|
From: <dav...@us...> - 2006-08-31 23:03:39
|
Revision: 1491
http://svn.sourceforge.net/frontierkernel/?rev=1491&view=rev
Author: davidgewirtz
Date: 2006-08-31 16:03:28 -0700 (Thu, 31 Aug 2006)
Log Message:
-----------
Lots of updates to the SQLite implementation.
Modified Paths:
--------------
Frontier/branches/SQLite/Common/headers/langsqlite.h
Frontier/branches/SQLite/Common/resources/Mac/kernelverbs.r
Frontier/branches/SQLite/Common/resources/Win32/kernelverbs.rc
Frontier/branches/SQLite/Common/source/langsqlite.c
Modified: Frontier/branches/SQLite/Common/headers/langsqlite.h
===================================================================
--- Frontier/branches/SQLite/Common/headers/langsqlite.h 2006-08-30 21:45:37 UTC (rev 1490)
+++ Frontier/branches/SQLite/Common/headers/langsqlite.h 2006-08-31 23:03:28 UTC (rev 1491)
@@ -35,8 +35,10 @@
extern boolean sqliteclearqueryverb (hdltreenode, tyvaluerecord *, bigstring); /* 2006-04-18 gewirtz */
-extern boolean sqliteexecutequeryverb (hdltreenode, tyvaluerecord *, bigstring); /* 2006-04-18 gewirtz */
+extern boolean sqliteresetqueryverb (hdltreenode, tyvaluerecord *, bigstring); /* 2006-08-31 gewirtz */
+extern boolean sqlitestepqueryverb (hdltreenode, tyvaluerecord *, bigstring); /* 2006-08-31 gewirtz */
+
extern boolean sqlitegetcolumncountverb (hdltreenode, tyvaluerecord *, bigstring); /* 2006-04-18 gewirtz */
extern boolean sqlitegetcolumntypeverb (hdltreenode, tyvaluerecord *, bigstring); /* 2006-04-18 gewirtz */
@@ -51,6 +53,8 @@
extern boolean sqlitegetcolumnverb (hdltreenode, tyvaluerecord *, bigstring); /* 2006-04-20 gewirtz */
+extern boolean sqlitegetrowverb (hdltreenode, tyvaluerecord *, bigstring); /* 2006-08-31 gewirtz */
+
extern boolean sqlitegeterrormessageverb (hdltreenode, tyvaluerecord *, bigstring); /* 2006-04-20 gewirtz */
extern boolean sqliteinitverbs (void); /* 2006-03-15 gewirtz */
@@ -59,3 +63,7 @@
/* boolean hmacsha1 (unsigned char *, int, unsigned char *, int, unsigned char *);*/ /* 2006-03-12 creedon */
+/* SQLITE MESSAGES */
+#define SQLITE_COLUMN_ERROR_0 "\xe9""SQLite column error. Frontier uses a base-1 index. Columns must be specified with 1 indicating the first column. This is different from the SQLite API, which requires that columns must be specified with 0 indicating the first column."
+#define SQLITE_COLUMN_ERROR_MAX "\x50""SQLite column error. An attempt was made to access a column that does not exist."
+#define SQLITE_COLUMN_ERROR_UNDEFINED "\x29""SQLite returned an undefined column type."
\ No newline at end of file
Modified: Frontier/branches/SQLite/Common/resources/Mac/kernelverbs.r
===================================================================
--- Frontier/branches/SQLite/Common/resources/Mac/kernelverbs.r 2006-08-30 21:45:37 UTC (rev 1490)
+++ Frontier/branches/SQLite/Common/resources/Mac/kernelverbs.r 2006-08-31 23:03:28 UTC (rev 1491)
@@ -1140,14 +1140,15 @@
}
};
-resource 'EFP#' (idsqliteverbs, "sqlite") { /* 2006-03-15 gewirtz sqlite verbs */
+resource 'EFP#' (idsqliteverbs, "sqlite") { /* 2006-08-31 gewirtz sqlite verbs */
{
"sqlite", false, {
"open",
"compileQuery",
"clearQuery",
- "executeQuery",
+ "resetQuery",
+ "stepQuery",
"getColumnCount",
"getColumnType",
"getColumnInt",
@@ -1155,6 +1156,7 @@
"getColumnText",
"getColumnName",
"getColumn",
+ "getRow",
"getErrorMessage",
"getClose"
}
Modified: Frontier/branches/SQLite/Common/resources/Win32/kernelverbs.rc
===================================================================
--- Frontier/branches/SQLite/Common/resources/Win32/kernelverbs.rc 2006-08-30 21:45:37 UTC (rev 1490)
+++ Frontier/branches/SQLite/Common/resources/Win32/kernelverbs.rc 2006-08-31 23:03:28 UTC (rev 1491)
@@ -1082,11 +1082,12 @@
1, // Number of "blocks" in this resource
"sqlite\0", // Function Processor name
false, // Window required
- 13, // Count of verbs
+ 15, // Count of verbs
"open\0",
"compileQuery\0",
"clearQuery\0",
- "executeQuery\0",
+ "resetQuery\0",
+ "stepQuery\0",
"getColumnCount\0",
"getColumnType\0",
"getColumnInt\0",
@@ -1094,6 +1095,7 @@
"getColumnText\0",
"getColumnName\0",
"getColumn\0",
+ "getRow\0",
"getErrorMessage\0",
"close\0"
END
Modified: Frontier/branches/SQLite/Common/source/langsqlite.c
===================================================================
--- Frontier/branches/SQLite/Common/source/langsqlite.c 2006-08-30 21:45:37 UTC (rev 1490)
+++ Frontier/branches/SQLite/Common/source/langsqlite.c 2006-08-31 23:03:28 UTC (rev 1491)
@@ -39,6 +39,8 @@
#include "strings.h"
#include "tablestructure.h"
#include "lang.h"
+#include "oplist.h"
+#include "langsystem7.h"
#include "langexternal.h"
#include "langsqlite.h"
@@ -72,7 +74,8 @@
openfunc,
compilequeryfunc,
clearqueryfunc,
- executequeryfunc,
+ resetqueryfunc,
+ stepqueryfunc,
getcolumncountfunc,
getcolumntypefunc,
getcolumnintfunc,
@@ -80,6 +83,7 @@
getcolumntextfunc,
getcolumnnamefunc,
getcolumnfunc,
+ getrowfunc,
geterrormessagefunc,
closefunc,
ctsqliteverbs
@@ -114,11 +118,16 @@
return (sqliteclearqueryverb (hp1, v, bserror));
} /* clearqueryfunc */
- case executequeryfunc: { /* 2006-04-18 gewirtz: move the cursor one step after the query */
+ case resetqueryfunc: { /* 2006-08-31 gewirtz: reset an SQLite query statement */
- return (sqliteexecutequeryverb (hp1, v, bserror));
- } /* executequeryfunc */
+ return (sqliteresetqueryverb (hp1, v, bserror));
+ } /* resetqueryfunc */
+ case stepqueryfunc: { /* 2006-08-31 gewirtz: move the cursor one step after the query */
+
+ return (sqlitestepqueryverb (hp1, v, bserror));
+ } /* stepqueryfunc */
+
case getcolumncountfunc: { /* 2006-04-18 gewirtz: get the number of columns */
return (sqlitegetcolumncountverb (hp1, v, bserror));
@@ -154,6 +163,11 @@
return (sqlitegetcolumnverb (hp1, v, bserror));
} /* getcolumnfunc */
+ case getrowfunc: { /* 2006-08-31 gewirtz: get the values in a row */
+
+ return (sqlitegetrowverb (hp1, v, bserror));
+ } /* getrowfunc */
+
case geterrormessagefunc: { /* 2006-04-20 gewirtz: get the SQLite error message */
return (sqlitegeterrormessageverb (hp1, v, bserror));
@@ -342,13 +356,40 @@
} /* sqliteclearqueryverb */
-boolean sqliteexecutequeryverb (hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
+boolean sqliteresetqueryverb (hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
sqlite3_stmt *queryid; /* query id */
int returnCode; /* return code from SQLite call */
/*
- sqlite.executeQuery(queryid)
+ sqlite.resetQuery(queryid)
+ Action: reset an SQLite query, so you can scan again from the beginning
+ Params: a query id
+ Returns: an SQLite result code
+ Notes: do not pass the opened database ID across threads.
+
+ SQLite docs: http://www.sqlite.org/capi3ref.html#sqlite3_reset.
+ */
+
+ flnextparamislast = true; /* makes sure Frontier throws an error if more than one param is passed */
+
+ if (!getlongvalue (hparam1, 1, (long *) &queryid)) /* Get the long value, which becomes the queryid pointer */
+ return (false);
+
+ /* Process the SQLite sequence */
+ returnCode = sqlite3_reset(queryid);
+
+ return setlongvalue (returnCode, vreturned);
+
+} /* sqliteresetqueryverb */
+
+boolean sqlitestepqueryverb (hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
+ sqlite3_stmt *queryid; /* query id */
+ int returnCode; /* return code from SQLite call */
+
+ /*
+ sqlite.stepQuery(queryid)
+
Action: perform the query, moving the query cursor to the next row of results
Params: a query id
Returns: an SQLite result code
@@ -367,12 +408,13 @@
return setlongvalue (returnCode, vreturned);
-} /* sqliteexecutequeryverb */
+} /* sqlitestepqueryverb */
boolean sqlitegetcolumntypeverb (hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
long columnNumber; /* column number */
sqlite3_stmt *queryid; /* query id */
int returnCode; /* return code from SQLite call */
+ int columnCount;
/*
sqlite.getColumnType(queryid, columnNumber)
@@ -394,6 +436,17 @@
if (!getlongvalue (hparam1, 2, &columnNumber))
return (false);
+ /* Validate the column number */
+ if (columnNumber < 1) {
+ langerrormessage (SQLITE_COLUMN_ERROR_0);
+ return (false);
+ }
+ columnCount = sqlite3_column_count(queryid);
+ if (columnNumber > columnCount) {
+ langerrormessage (SQLITE_COLUMN_ERROR_MAX);
+ return (false);
+ }
+
/* Process the SQLite sequence */
--columnNumber; /* Frontier uses base 1, but SQLite uses a base of 0 for its column numbering */
returnCode = sqlite3_column_type(queryid, (int) columnNumber);
@@ -419,7 +472,7 @@
/* SQLite spec says sqlite3_column_type only returns the above 5 types. But,
just in case it lied, we'll return an error type to help Frontier avoid
getting a case of return value indigestion. */
- langerrormessage ("\x29""SQLite returned an undefined column type.");
+ langerrormessage (SQLITE_COLUMN_ERROR_UNDEFINED);
return (false);
}
} /* switch */
@@ -431,6 +484,7 @@
Handle returnH;
const char *column_name;
sqlite3_stmt *queryid;
+ int columnCount;
/*
sqlite.getColumnName(queryid, columnNumber)
@@ -452,12 +506,25 @@
if (!getlongvalue (hparam1, 2, &columnNumber))
return (false);
+ /* Validate the column number */
+ if (columnNumber < 1) {
+ langerrormessage (SQLITE_COLUMN_ERROR_0);
+ return (false);
+ }
+ columnCount = sqlite3_column_count(queryid);
+ if (columnNumber > columnCount) {
+ langerrormessage (SQLITE_COLUMN_ERROR_MAX);
+ return (false);
+ }
+
/* Process the SQLite sequence */
--columnNumber; /* Frontier uses base 1, but SQLite uses a base of 0 for its column numbering */
column_name = sqlite3_column_name(queryid, (int) columnNumber);
/* Exit the verb, converting column_name back to Frontier handle */
- newfilledhandle ((ptrvoid) column_name, strlen (column_name), &returnH);
+ if (!newfilledhandle ((ptrvoid) column_name, strlen (column_name), &returnH))
+ return false; /* Allocation failed */
+
return (setheapvalue (returnH, stringvaluetype, vreturned));
} /* sqlitegetcolumnnameverb */
@@ -493,6 +560,7 @@
long columnNumber;
sqlite3_stmt *queryid;
long returnCode; /* return code from SQLite call */
+ int columnCount;
/*
sqlite.getColumnInt(queryid, columnNumber)
@@ -514,6 +582,17 @@
if (!getlongvalue (hparam1, 2, &columnNumber))
return (false);
+ /* Validate the column number */
+ if (columnNumber < 1) {
+ langerrormessage (SQLITE_COLUMN_ERROR_0);
+ return (false);
+ }
+ columnCount = sqlite3_column_count(queryid);
+ if (columnNumber > columnCount) {
+ langerrormessage (SQLITE_COLUMN_ERROR_MAX);
+ return (false);
+ }
+
/* Process the SQLite sequence */
--columnNumber; /* Frontier uses base 1, but SQLite uses a base of 0 for its column numbering */
returnCode = sqlite3_column_int(queryid, (int) columnNumber);
@@ -525,7 +604,8 @@
boolean sqlitegetcolumndoubleverb (hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
long columnNumber;
sqlite3_stmt *queryid;
- double returnCode; /* return code from SQLite call */
+ double returnDouble; /* double value returned from SQLite call */
+ int columnCount;
/*
sqlite.getColumnDouble(queryid, columnNumber)
@@ -547,11 +627,22 @@
if (!getlongvalue (hparam1, 2, &columnNumber))
return (false);
+ /* Validate the column number */
+ if (columnNumber < 1) {
+ langerrormessage (SQLITE_COLUMN_ERROR_0);
+ return (false);
+ }
+ columnCount = sqlite3_column_count(queryid);
+ if (columnNumber > columnCount) {
+ langerrormessage (SQLITE_COLUMN_ERROR_MAX);
+ return (false);
+ }
+
/* Process the SQLite sequence */
--columnNumber; /* Frontier uses base 1, but SQLite uses a base of 0 for its column numbering */
- returnCode = sqlite3_column_double(queryid, (int) columnNumber);
+ returnDouble = sqlite3_column_double(queryid, (int) columnNumber);
- return (setlongvalue ((double) returnCode, vreturned));
+ return (setdoublevalue (returnDouble, vreturned));
} /* sqlitegetcolumndoubleverb */
@@ -560,6 +651,7 @@
sqlite3_stmt *queryid;
Handle returnH;
const unsigned char *column_text;
+ int columnCount;
/*
sqlite.getColumnText(queryid, columnNumber)
@@ -581,12 +673,25 @@
if (!getlongvalue (hparam1, 2, &columnNumber))
return (false);
+ /* Validate the column number */
+ if (columnNumber < 1) {
+ langerrormessage (SQLITE_COLUMN_ERROR_0);
+ return (false);
+ }
+ columnCount = sqlite3_column_count(queryid);
+ if (columnNumber > columnCount) {
+ langerrormessage (SQLITE_COLUMN_ERROR_MAX);
+ return (false);
+ }
+
/* Process the SQLite sequence */
--columnNumber; /* Frontier uses base 1, but SQLite uses a base of 0 for its column numbering */
column_text = sqlite3_column_text(queryid, (int) columnNumber);
/* Exit the verb, converting column_name back to Frontier handle */
- newfilledhandle ((ptrvoid) column_text, strlen (column_text), &returnH);
+ if (!newfilledhandle ((ptrvoid) column_text, strlen (column_text), &returnH))
+ return false; /* Allocation failed */
+
return (setheapvalue (returnH, stringvaluetype, vreturned));
} /* sqlitegetcolumntextverb */
@@ -595,8 +700,11 @@
long columnNumber; /* column number */
sqlite3_stmt *queryid; /* query id */
int returnCode; /* return code from SQLite call */
+ double returnDouble; /* double value returned from SQLite call */
Handle returnH;
+ int columnCount;
const unsigned char *column_text;
+ /* const unsigned char *column_blob; */
/*
sqlite.getColumn(queryid, columnNumber)
@@ -606,8 +714,6 @@
Returns: an SQLite result code
Notes: do not pass the opened database ID across threads.
this implementation does not support blobs. If a blob column is requested, 0 is returned.
-
- SQLite docs: http://www.sqlite.org/capi3ref.html#sqlite3_column_type.
*/
if (!getlongvalue (hparam1, 1, (long *) &queryid)) /* Get the long value, which becomes the queryid pointer */
@@ -619,6 +725,17 @@
if (!getlongvalue (hparam1, 2, &columnNumber))
return (false);
+ /* Validate the column number */
+ if (columnNumber < 1) {
+ langerrormessage (SQLITE_COLUMN_ERROR_0);
+ return (false);
+ }
+ columnCount = sqlite3_column_count(queryid);
+ if (columnNumber > columnCount) {
+ langerrormessage (SQLITE_COLUMN_ERROR_MAX);
+ return (false);
+ }
+
/* Process the SQLite sequence */
--columnNumber; /* Frontier uses base 1, but SQLite uses a base of 0 for its column numbering */
returnCode = sqlite3_column_type(queryid, (int) columnNumber);
@@ -630,18 +747,31 @@
return (setlongvalue ((long) returnCode, vreturned));
}
case SQLITE_FLOAT: {
- returnCode = sqlite3_column_double(queryid, (int) columnNumber);
- return (setlongvalue ((double) returnCode, vreturned));
+ returnDouble = sqlite3_column_double(queryid, (int) columnNumber);
+ return (setdoublevalue (returnDouble, vreturned));
}
case SQLITE_TEXT: {
column_text = sqlite3_column_text(queryid, (int) columnNumber);
/* Exit the verb, converting column_name back to Frontier handle */
- newfilledhandle ((ptrvoid) column_text, strlen (column_text), &returnH);
+ if (!newfilledhandle ((ptrvoid) column_text, strlen (column_text), &returnH))
+ return false; /* Allocation failed */
return (setheapvalue (returnH, stringvaluetype, vreturned));
}
case SQLITE_BLOB: {
return (setlongvalue ((long) 0, vreturned));
+
+ /* The following code is ignored. Andre suggested returning actual binary
+ data to Frontier, but I'm concerned about reliability, moving that data
+ back and forth, so in this implementation, I'm explicitly making blob
+ data not supported -- DG */
+
+ // column_blob = sqlite3_column_blob(queryid, (int) columnNumber);
+
+ /* Exit the verb, converting column_name back to Frontier handle */
+ //if (!newfilledhandle ((ptrvoid) column_blob, strlen (column_blob), &returnH))
+ // return false; /* Allocation failed */
+ //return (setbinaryvalue (returnH, '\?\?\?\?', vreturned));
}
case SQLITE_NULL: {
return (setlongvalue ((long) 0, vreturned));
@@ -655,8 +785,106 @@
}
} /* switch */
-} /* sqlitegetcolumntext */
+} /* sqlitegetcolumn */
+boolean sqlitegetrowverb (hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
+ long columnNumber; /* column number */
+ int columnCount; /* number of columns */
+ sqlite3_stmt *queryid; /* query id */
+ int returnCode; /* return code from SQLite call */
+ double returnDouble; /* double value returned from SQLite call */
+ Handle returnH;
+ const unsigned char *column_text;
+ hdllistrecord hlist;
+ tyvaluerecord val;
+
+ /*
+ sqlite.getRow(queryid)
+
+ Action: Retrieve a row as a list
+ Params: a query id
+ Returns: an SQLite result code
+ Notes: do not pass the opened database ID across threads.
+ this implementation does not support blobs. If a blob column is requested, 0 is returned.
+ */
+
+ flnextparamislast = true; /* makes sure Frontier throws an error if more than one param is passed */
+
+ if (!getlongvalue (hparam1, 1, (long *) &queryid)) /* Get the long value, which becomes the queryid pointer */
+ return (false);
+
+ /* Process the SQLite sequence */
+ columnCount = sqlite3_column_count(queryid); /* first, figure out how many columns we've got */
+
+ if (columnCount == 0) {
+ langerrormessage ("\x2F""SQLite.getRow requires a minimum of one column.");
+ return (false);
+ }
+
+ if (!opnewlist (&hlist, false)) /* fail out if we can't create the list */
+ return (false);
+
+ for (columnNumber = 0 ; columnNumber < columnCount ; ++columnNumber) {
+
+ returnCode = sqlite3_column_type(queryid, (int) columnNumber);
+
+ switch(returnCode) {
+
+ case SQLITE_INTEGER: {
+ returnCode = sqlite3_column_int(queryid, (int) columnNumber);
+ if (!langpushlistlong (hlist, (long) returnCode))
+ goto error;
+ break;
+ }
+ case SQLITE_FLOAT: {
+ returnDouble = sqlite3_column_double(queryid, (int) columnNumber);
+ if (!setdoublevalue (returnDouble, &val))
+ goto error;
+ if (!langpushlistval (hlist, nil, &val))
+ goto error;
+ break;
+ }
+ case SQLITE_TEXT: {
+ column_text = sqlite3_column_text(queryid, (int) columnNumber);
+
+ /* Exit the verb, converting column_name back to Frontier handle */
+ if (!newfilledhandle ((ptrvoid) column_text, strlen (column_text), &returnH))
+ return false; /* Allocation failed */
+ if (!setheapvalue (returnH, stringvaluetype, &val)) /* convert handle to value */
+ goto error;
+ if (!langpushlistval (hlist, nil, &val))
+ goto error;
+ break;
+ }
+ case SQLITE_BLOB: {
+ if (!langpushlistlong (hlist, (long) 0))
+ goto error;
+ break;
+ }
+ case SQLITE_NULL: {
+ if (!langpushlistlong (hlist, (long) 0))
+ goto error;
+ break;
+ }
+ default: {
+ /* SQLite spec says sqlite3_column_type only returns the above 5 types. But,
+ just in case it lied, this time we return a 0, so the rest of the fields
+ can be read properly. */
+ if (!langpushlistlong (hlist, (long) 0))
+ goto error;
+ }
+ } /* switch */
+ } /* for */
+
+ return (setheapvalue ((Handle) hlist, listvaluetype, vreturned));
+
+ error: {
+ opdisposelist (hlist);
+ return (false);
+ }
+
+} /* sqlitegetrow */
+
boolean sqlitegeterrormessageverb (hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
const char *sqliteError; /* pointer to the error message */
sqlite3 *db; /* the SQLite database handle */
@@ -682,7 +910,9 @@
sqliteError = sqlite3_errmsg(db);
/* Exit the verb, converting errMsg back to Frontier handle */
- newfilledhandle ((ptrvoid) sqliteError, strlen (sqliteError), &returnH);
+ if(!newfilledhandle ((ptrvoid) sqliteError, strlen (sqliteError), &returnH))
+ return false; /* Allocation failed */
+
return (setheapvalue (returnH, stringvaluetype, vreturned));
} /* sqlitegeterrormessageverb */
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|