|
From: <dav...@us...> - 2006-08-30 21:46:34
|
Revision: 1490
http://svn.sourceforge.net/frontierkernel/?rev=1490&view=rev
Author: davidgewirtz
Date: 2006-08-30 14:45:37 -0700 (Wed, 30 Aug 2006)
Log Message:
-----------
Updated SQLite code, updated for current trunk. Also updated to SQLite 3.3.7.
Modified Paths:
--------------
Frontier/branches/SQLite/Common/headers/kernelverbdefs.h
Frontier/branches/SQLite/Common/headers/kernelverbs.h
Frontier/branches/SQLite/Common/headers/langinternal.h
Frontier/branches/SQLite/Common/resources/Mac/kernelverbs.r
Frontier/branches/SQLite/Common/resources/Win32/WinLand.rc
Frontier/branches/SQLite/Common/resources/Win32/kernelverbs.rc
Frontier/branches/SQLite/Common/source/shell.c
Frontier/branches/SQLite/build_VC2K5/Frontier.vcproj
Added Paths:
-----------
Frontier/branches/SQLite/Common/headers/langsqlite.h
Frontier/branches/SQLite/Common/source/langsqlite.c
Frontier/branches/SQLite/Common/sqlite3/
Frontier/branches/SQLite/Common/sqlite3/alter.c
Frontier/branches/SQLite/Common/sqlite3/analyze.c
Frontier/branches/SQLite/Common/sqlite3/attach.c
Frontier/branches/SQLite/Common/sqlite3/auth.c
Frontier/branches/SQLite/Common/sqlite3/btree.c
Frontier/branches/SQLite/Common/sqlite3/btree.h
Frontier/branches/SQLite/Common/sqlite3/build.c
Frontier/branches/SQLite/Common/sqlite3/callback.c
Frontier/branches/SQLite/Common/sqlite3/complete.c
Frontier/branches/SQLite/Common/sqlite3/date.c
Frontier/branches/SQLite/Common/sqlite3/delete.c
Frontier/branches/SQLite/Common/sqlite3/expr.c
Frontier/branches/SQLite/Common/sqlite3/func.c
Frontier/branches/SQLite/Common/sqlite3/hash.c
Frontier/branches/SQLite/Common/sqlite3/hash.h
Frontier/branches/SQLite/Common/sqlite3/insert.c
Frontier/branches/SQLite/Common/sqlite3/keywordhash.h
Frontier/branches/SQLite/Common/sqlite3/legacy.c
Frontier/branches/SQLite/Common/sqlite3/loadext.c
Frontier/branches/SQLite/Common/sqlite3/main.c
Frontier/branches/SQLite/Common/sqlite3/opcodes.c
Frontier/branches/SQLite/Common/sqlite3/opcodes.h
Frontier/branches/SQLite/Common/sqlite3/os.c
Frontier/branches/SQLite/Common/sqlite3/os.h
Frontier/branches/SQLite/Common/sqlite3/os_common.h
Frontier/branches/SQLite/Common/sqlite3/os_os2.c
Frontier/branches/SQLite/Common/sqlite3/os_unix.c
Frontier/branches/SQLite/Common/sqlite3/os_win.c
Frontier/branches/SQLite/Common/sqlite3/pager.c
Frontier/branches/SQLite/Common/sqlite3/pager.h
Frontier/branches/SQLite/Common/sqlite3/parse.c
Frontier/branches/SQLite/Common/sqlite3/parse.h
Frontier/branches/SQLite/Common/sqlite3/pragma.c
Frontier/branches/SQLite/Common/sqlite3/prepare.c
Frontier/branches/SQLite/Common/sqlite3/printf.c
Frontier/branches/SQLite/Common/sqlite3/random.c
Frontier/branches/SQLite/Common/sqlite3/select.c
Frontier/branches/SQLite/Common/sqlite3/shell.c
Frontier/branches/SQLite/Common/sqlite3/sqlite3.def
Frontier/branches/SQLite/Common/sqlite3/sqlite3.h
Frontier/branches/SQLite/Common/sqlite3/sqlite3ext.h
Frontier/branches/SQLite/Common/sqlite3/sqliteInt.h
Frontier/branches/SQLite/Common/sqlite3/table.c
Frontier/branches/SQLite/Common/sqlite3/tclsqlite.c
Frontier/branches/SQLite/Common/sqlite3/tokenize.c
Frontier/branches/SQLite/Common/sqlite3/trigger.c
Frontier/branches/SQLite/Common/sqlite3/update.c
Frontier/branches/SQLite/Common/sqlite3/utf.c
Frontier/branches/SQLite/Common/sqlite3/util.c
Frontier/branches/SQLite/Common/sqlite3/vacuum.c
Frontier/branches/SQLite/Common/sqlite3/vdbe.c
Frontier/branches/SQLite/Common/sqlite3/vdbe.h
Frontier/branches/SQLite/Common/sqlite3/vdbeInt.h
Frontier/branches/SQLite/Common/sqlite3/vdbeapi.c
Frontier/branches/SQLite/Common/sqlite3/vdbeaux.c
Frontier/branches/SQLite/Common/sqlite3/vdbefifo.c
Frontier/branches/SQLite/Common/sqlite3/vdbemem.c
Frontier/branches/SQLite/Common/sqlite3/vtab.c
Frontier/branches/SQLite/Common/sqlite3/where.c
Modified: Frontier/branches/SQLite/Common/headers/kernelverbdefs.h
===================================================================
--- Frontier/branches/SQLite/Common/headers/kernelverbdefs.h 2006-08-30 19:38:37 UTC (rev 1489)
+++ Frontier/branches/SQLite/Common/headers/kernelverbdefs.h 2006-08-30 21:45:37 UTC (rev 1490)
@@ -51,4 +51,4 @@
#define idregexpverbs 1023 /*2003-04-22 AR: regular expression verbs*/
#define idmathverbs 1024 /*2004-12-29 SMD: extended math verbs*/
#define idcryptverbs 1025 /* 2006-03-07 creedon: crypt verbs */
-
+#define idsqliteverbs 1026 /* 2006-03-15 gewirtz sqlite verbs */
Modified: Frontier/branches/SQLite/Common/headers/kernelverbs.h
===================================================================
--- Frontier/branches/SQLite/Common/headers/kernelverbs.h 2006-08-30 19:38:37 UTC (rev 1489)
+++ Frontier/branches/SQLite/Common/headers/kernelverbs.h 2006-08-30 21:45:37 UTC (rev 1490)
@@ -56,3 +56,4 @@
extern boolean cryptinitverbs (void); /* langcrypt.c */
+extern boolean sqliteinitverbs (void); /* langsqlite.c */
\ No newline at end of file
Modified: Frontier/branches/SQLite/Common/headers/langinternal.h
===================================================================
--- Frontier/branches/SQLite/Common/headers/langinternal.h 2006-08-30 19:38:37 UTC (rev 1489)
+++ Frontier/branches/SQLite/Common/headers/langinternal.h 2006-08-30 21:45:37 UTC (rev 1490)
@@ -202,6 +202,8 @@
#define frnonexistantgroupnameerror 160
#define replaceitemerror 161 /* 2005-09-26 creedon */
#define cmdshellnotfounderror 162 /* 2006-03-10 aradke */
+#define sqliteopenerror 163 /* 2006-03-17 gewirtz */
+#define sqlitedberror 164 /* 2006-03-17 gewirtz */
#define langstacklist 137
Added: Frontier/branches/SQLite/Common/headers/langsqlite.h
===================================================================
--- Frontier/branches/SQLite/Common/headers/langsqlite.h (rev 0)
+++ Frontier/branches/SQLite/Common/headers/langsqlite.h 2006-08-30 21:45:37 UTC (rev 1490)
@@ -0,0 +1,61 @@
+
+/* $Id: langsqlite.h,v 1.1.2.1 2006/03/24 01:31:35 davidgewirtz Exp $ */
+
+/******************************************************************************
+
+ UserLand Frontier(tm) -- High performance Web content management,
+ object database, system-level and Internet scripting environment,
+ including source code editing and debugging.
+
+ Copyright (C) 1992-2004 UserLand Software, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************************************************************************/
+
+/* prototypes */
+
+extern boolean sqliteopenverb (hdltreenode, tyvaluerecord *, bigstring); /* 2006-03-15 gewirtz */
+
+extern boolean sqlitecloseverb (hdltreenode, tyvaluerecord *, bigstring); /* 2006-03-17 gewirtz */
+
+extern boolean sqlitecompilequeryverb (hdltreenode, tyvaluerecord *, bigstring); /* 2006-04-18 gewirtz */
+
+extern boolean sqliteclearqueryverb (hdltreenode, tyvaluerecord *, bigstring); /* 2006-04-18 gewirtz */
+
+extern boolean sqliteexecutequeryverb (hdltreenode, tyvaluerecord *, bigstring); /* 2006-04-18 gewirtz */
+
+extern boolean sqlitegetcolumncountverb (hdltreenode, tyvaluerecord *, bigstring); /* 2006-04-18 gewirtz */
+
+extern boolean sqlitegetcolumntypeverb (hdltreenode, tyvaluerecord *, bigstring); /* 2006-04-18 gewirtz */
+
+extern boolean sqlitegetcolumnintverb (hdltreenode, tyvaluerecord *, bigstring); /* 2006-04-18 gewirtz */
+
+extern boolean sqlitegetcolumndoubleverb (hdltreenode, tyvaluerecord *, bigstring); /* 2006-04-18 gewirtz */
+
+extern boolean sqlitegetcolumntextverb (hdltreenode, tyvaluerecord *, bigstring); /* 2006-04-18 gewirtz */
+
+extern boolean sqlitegetcolumnnameverb (hdltreenode, tyvaluerecord *, bigstring); /* 2006-04-18 gewirtz */
+
+extern boolean sqlitegetcolumnverb (hdltreenode, tyvaluerecord *, bigstring); /* 2006-04-20 gewirtz */
+
+extern boolean sqlitegeterrormessageverb (hdltreenode, tyvaluerecord *, bigstring); /* 2006-04-20 gewirtz */
+
+extern boolean sqliteinitverbs (void); /* 2006-03-15 gewirtz */
+
+/* boolean hmacmd5 (unsigned char *, int, unsigned char *, int, unsigned char *);*/ /* 2006-03-05 creedon */
+
+/* boolean hmacsha1 (unsigned char *, int, unsigned char *, int, unsigned char *);*/ /* 2006-03-12 creedon */
+
Modified: Frontier/branches/SQLite/Common/resources/Mac/kernelverbs.r
===================================================================
--- Frontier/branches/SQLite/Common/resources/Mac/kernelverbs.r 2006-08-30 19:38:37 UTC (rev 1489)
+++ Frontier/branches/SQLite/Common/resources/Mac/kernelverbs.r 2006-08-30 21:45:37 UTC (rev 1490)
@@ -1140,3 +1140,24 @@
}
};
+resource 'EFP#' (idsqliteverbs, "sqlite") { /* 2006-03-15 gewirtz sqlite verbs */
+ {
+ "sqlite", false, {
+
+ "open",
+ "compileQuery",
+ "clearQuery",
+ "executeQuery",
+ "getColumnCount",
+ "getColumnType",
+ "getColumnInt",
+ "getColumnDouble",
+ "getColumnText",
+ "getColumnName",
+ "getColumn",
+ "getErrorMessage",
+ "getClose"
+ }
+ }
+};
+
Modified: Frontier/branches/SQLite/Common/resources/Win32/WinLand.rc
===================================================================
--- Frontier/branches/SQLite/Common/resources/Win32/WinLand.rc 2006-08-30 19:38:37 UTC (rev 1489)
+++ Frontier/branches/SQLite/Common/resources/Win32/WinLand.rc 2006-08-30 21:45:37 UTC (rev 1490)
@@ -1533,6 +1533,8 @@
160 Lang_Errors DISCARDABLE BEGIN "Can't execute command because the replacement string contains a non-existant group name at character #^0.\0" END
161 Lang_Errors DISCARDABLE BEGIN "An item named \042^0\042 already exists.\0" END // Replace it or create a duplicate?" /* 2005-09-26 creedon */
162 Lang_Errors DISCARDABLE BEGIN "Can't run shell command because the shell \042^0\042 was not found.\0" END /* 2006-03-10 aradke */
+ 163 Lang_Errors DISCARDABLE BEGIN "Can't open database: ^0.\0" END /* 2006-03-17 gewirtz */
+ 164 Lang_Errors DISCARDABLE BEGIN "Database error: ^0.\0" END /* 2006-03-17 gewirtz */
1 Mac_Errors DISCARDABLE BEGIN "The \042^0\042 folder is full.\0" END
2 Mac_Errors DISCARDABLE BEGIN "The disk is full.\0" END
Modified: Frontier/branches/SQLite/Common/resources/Win32/kernelverbs.rc
===================================================================
--- Frontier/branches/SQLite/Common/resources/Win32/kernelverbs.rc 2006-08-30 19:38:37 UTC (rev 1489)
+++ Frontier/branches/SQLite/Common/resources/Win32/kernelverbs.rc 2006-08-30 21:45:37 UTC (rev 1490)
@@ -1077,3 +1077,24 @@
"hmacSHA1\0",
END
+1026 /* sqliteverbs */ EFP DISCARDABLE
+ BEGIN
+ 1, // Number of "blocks" in this resource
+ "sqlite\0", // Function Processor name
+ false, // Window required
+ 13, // Count of verbs
+ "open\0",
+ "compileQuery\0",
+ "clearQuery\0",
+ "executeQuery\0",
+ "getColumnCount\0",
+ "getColumnType\0",
+ "getColumnInt\0",
+ "getColumnDouble\0",
+ "getColumnText\0",
+ "getColumnName\0",
+ "getColumn\0",
+ "getErrorMessage\0",
+ "close\0"
+ END
+
Added: Frontier/branches/SQLite/Common/source/langsqlite.c
===================================================================
--- Frontier/branches/SQLite/Common/source/langsqlite.c (rev 0)
+++ Frontier/branches/SQLite/Common/source/langsqlite.c 2006-08-30 21:45:37 UTC (rev 1490)
@@ -0,0 +1,688 @@
+
+/* $Id: langsqlite.c,v 1.1.2.1 2006/03/24 01:32:31 davidgewirtz Exp $ */
+
+/******************************************************************************
+
+ UserLand Frontier(tm) -- High performance Web content management,
+ object database, system-level and Internet scripting environment,
+ including source code editing and debugging.
+
+ Copyright (C) 1992-2004 UserLand Software, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************************************************************************/
+
+#include "frontier.h"
+#include "standard.h"
+
+#include "frontierconfig.h"
+
+#include "error.h"
+#include "ops.h"
+#include "langinternal.h"
+#include "kernelverbs.h"
+#include "kernelverbdefs.h"
+#include "resources.h"
+#include "strings.h"
+#include "tablestructure.h"
+#include "lang.h"
+#include "langexternal.h"
+
+#include "langsqlite.h"
+#include <sqlite3.h>
+
+/* Building SQLite into Frontier
+
+The SQLite source distribution is compiled into the Frontier code as part of this
+module. A key goal in this implementation was to avoid touching any of the SQLite
+source files. SQLite is pretty complex in its coding, and I didn't want to take a
+chance that any changes to the original SQLite code would muck up the database
+functionality.
+
+To include the latest SQLite distribution (we're implementing SQLite 3 here),
+download the SQLite source code from http://www.sqlite.org/download.html.
+
+Move all the SQLite source files into the \Common\sqlite3 folder. If you need to
+include new files in the SQLite project, be sure that shell.c and tclsqlite.c are
+NOT included in the Frontier project.
+
+That's it. For further tips, see the Frontier Lab Notebook article at:
+
+http://manila.zatz.com/frontierkernel/stories/storyReader$29
+
+-- DG
+
+*/
+
+typedef enum tysqliteverbtoken { /* verbs that are processed by langsqlite.c */
+
+ openfunc,
+ compilequeryfunc,
+ clearqueryfunc,
+ executequeryfunc,
+ getcolumncountfunc,
+ getcolumntypefunc,
+ getcolumnintfunc,
+ getcolumndoublefunc,
+ getcolumntextfunc,
+ getcolumnnamefunc,
+ getcolumnfunc,
+ geterrormessagefunc,
+ closefunc,
+ ctsqliteverbs
+ } tysqliteverbtoken;
+
+
+static boolean sqlitefunctionvalue (short token, hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
+
+ /*
+ 2006-03-15 gewirtz: created, cribbed from langcrypt, itself cribbed from htmlfunctionvalue
+ */
+
+ hdltreenode hp1 = hparam1;
+ tyvaluerecord *v = vreturned;
+
+ setbooleanvalue (false, v); /* by default, sqlite functions return false */
+
+ switch (token) {
+
+ case openfunc: { /* 2006-03-14 gewirtz: open an SQLite db */
+
+ return (sqliteopenverb (hp1, v, bserror));
+ } /* openfunc */
+
+ case compilequeryfunc: { /* 2006-04-18 gewirtz: prepare an SQLite statement */
+
+ return (sqlitecompilequeryverb (hp1, v, bserror));
+ } /* compilequeryfunc */
+
+ case clearqueryfunc: { /* 2006-04-18 gewirtz: finalize an SQLite statement */
+
+ return (sqliteclearqueryverb (hp1, v, bserror));
+ } /* clearqueryfunc */
+
+ case executequeryfunc: { /* 2006-04-18 gewirtz: move the cursor one step after the query */
+
+ return (sqliteexecutequeryverb (hp1, v, bserror));
+ } /* executequeryfunc */
+
+ case getcolumncountfunc: { /* 2006-04-18 gewirtz: get the number of columns */
+
+ return (sqlitegetcolumncountverb (hp1, v, bserror));
+ } /* getcolumncountfunc */
+
+ case getcolumntypefunc: { /* 2006-04-18 gewirtz: get the type of the referenced column */
+ /* this version returns Frontier strings */
+ return (sqlitegetcolumntypeverb (hp1, v, bserror));
+ } /* getcolumntypefunc */
+
+ case getcolumnintfunc: { /* 2006-04-18 gewirtz: get an int value from the column */
+
+ return (sqlitegetcolumnintverb (hp1, v, bserror));
+ } /* getcolumnintfunc */
+
+ case getcolumndoublefunc: { /* 2006-04-18 gewirtz: get a double value from the column */
+
+ return (sqlitegetcolumndoubleverb (hp1, v, bserror));
+ } /* getcolumndoublefunc */
+
+ case getcolumntextfunc: { /* 2006-04-18 gewirtz: get a text value from the column */
+
+ return (sqlitegetcolumntextverb (hp1, v, bserror));
+ } /* getcolumntextfunc */
+
+ case getcolumnnamefunc: { /* 2006-04-18 gewirtz: get the field name of the column */
+
+ return (sqlitegetcolumnnameverb (hp1, v, bserror));
+ } /* getcolumnnamefunc */
+
+ case getcolumnfunc: { /* 2006-04-20 gewirtz: get the value of the column */
+
+ return (sqlitegetcolumnverb (hp1, v, bserror));
+ } /* getcolumnfunc */
+
+ case geterrormessagefunc: { /* 2006-04-20 gewirtz: get the SQLite error message */
+
+ return (sqlitegeterrormessageverb (hp1, v, bserror));
+ } /* geterrormessagefunc */
+
+ case closefunc: { /* 2006-03-15 gewirtz: close an SQLite db */
+
+ return (sqlitecloseverb (hp1, v, bserror));
+ } /* closefunc */
+
+ default:
+ getstringlist (langerrorlist, unimplementedverberror, bserror);
+
+ return (false);
+ } /* switch */
+ } /* sqlitefunctionvalue */
+
+
+boolean sqliteinitverbs (void) {
+
+ /* 2006-03-15 gewirtz: created, cribbed from cryptinitverbs */
+
+ return (loadfunctionprocessor (idsqliteverbs, &sqlitefunctionvalue));
+ } /* sqliteinitverbs */
+
+static void sqliteOpenError (const char *errmsg, bigstring bserror) {
+ bigstring bserrmsg;
+
+ copyctopstring (errmsg, bserrmsg); /* This creates a pstring at bserrmsg */
+ getstringlist (langerrorlist, sqliteopenerror, bserror);
+ parsedialogstring (bserror, bserrmsg, nil, nil, nil, bserror);
+
+ return;
+ } /*sqliteOpenError*/
+
+static void sqliteDatabaseError (const char *errmsg, bigstring bserror) {
+ bigstring bserrmsg;
+
+ copyctopstring (errmsg, bserrmsg); /* This creates a pstring at bserrmsg */
+ getstringlist (langerrorlist, sqlitedberror, bserror);
+ parsedialogstring (bserror, bserrmsg, nil, nil, nil, bserror);
+
+ return;
+ } /*sqliteDatabaseError*/
+
+static void sqliteScriptError (const char *errmsg, bigstring bserror) {
+ bigstring bserrmsg;
+
+ copyctopstring (errmsg, bserrmsg); /* This creates a pstring at bserrmsg */
+ getstringlist (langerrorlist, notfunctionerror, bserror);
+ parsedialogstring (bserror, bserrmsg, nil, nil, nil, bserror);
+
+ return;
+ } /*sqliteScriptError*/
+
+
+boolean sqliteopenverb (hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
+ Handle dbfile; /* path to database file */
+ sqlite3 *dbid; /* the SQLite database handle */
+ int returnCode; /* return code from SQLite call */
+
+ /*
+ sqlite.open(dbfile)
+
+ Action: opens a SQLite database
+ Params: a file path to the database file
+ Returns: a value that corresponds to the opened database ID
+ Usage: call in a try statement
+ Notes: do not pass the opened database ID across threads
+
+ SQLite docs: http://www.sqlite.org/capi3ref.html#sqlite3_open.
+ */
+
+ flnextparamislast = true; /* makes sure Frontier throws an error if more than one param is passed */
+
+ if (!gettextvalue (hparam1, 1, &dbfile)) /* get the param */
+ return (false);
+
+ pushcharhandle (0x00, dbfile); /* convert *dbfile to a string */
+
+ /* Process the SQLite sequence */
+ returnCode = sqlite3_open(*dbfile, &dbid);
+ if(returnCode) {
+ sqliteOpenError(sqlite3_errmsg(dbid), bserror); /* send database open error */
+ sqlite3_close(dbid);
+ return (false);
+ }
+
+ /* return the db address to the scripter */
+ return (setheapvalue ((Handle) dbid, longvaluetype, vreturned));
+
+} /* sqliteopenverb */
+
+boolean sqlitecloseverb (hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
+ sqlite3 *dbid; /* the SQLite database handle */
+ int returnCode; /* return code from SQLite call */
+
+ /*
+ sqlite.close(dbid)
+
+ Action: close an SQLite database
+ Params: a database id
+ Returns: an SQLite result code
+ Usage: check result code for success or failure
+ Notes: do not pass the opened database ID across threads.
+
+ SQLite docs: http://www.sqlite.org/capi3ref.html#sqlite3_close.
+ */
+
+ flnextparamislast = true; /* makes sure Frontier throws an error if more than one param is passed */
+
+ if (!getlongvalue (hparam1, 1, (long *) &dbid)) /* Get the long value, which becomes the db pointer */
+ return (false);
+
+ /* Process the SQLite sequence */
+ returnCode = sqlite3_close(dbid);
+
+ return setlongvalue (returnCode, vreturned);
+
+} /* sqlitecloseverb */
+
+boolean sqlitecompilequeryverb (hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
+ Handle query; /* the SQL query passed to the SQLite engine */
+ sqlite3 *dbid; /* the SQLite database handle */
+ sqlite3_stmt *queryid = 0; /* the compiled query */
+ int returnCode; /* return code from SQLite call */
+
+ /*
+ sqlite.compileQuery(dbid, query)
+
+ Action: compile an SQLite query
+ Params: a database id and a query string
+ Returns: a query id
+ Usage: call in a try statement
+ Notes: do not pass the opened database ID across threads.
+
+ SQLite docs: http://www.sqlite.org/capi3ref.html#sqlite3_prepare.
+
+ Code that is a good example of prepare in use:
+ http://souptonuts.sourceforge.net/code/eatblob.c.html
+ */
+
+ if (!getlongvalue (hparam1, 1, (long *) &dbid)) /* Get the long value, which becomes the db pointer */
+ return (false);
+
+ flnextparamislast = true; /* makes sure Frontier throws an error if more than one param is passed */
+
+ if (!getreadonlytextvalue (hparam1, 2, &query)) /* get the query param */
+ return (false);
+
+ /* Process the SQLite sequence */
+ returnCode = sqlite3_prepare(dbid, *query, gethandlesize(query), &queryid, 0);
+ if(returnCode != SQLITE_OK || queryid == NULL) {
+ sqliteDatabaseError(sqlite3_errmsg(dbid), bserror); /* send database error */
+ return (false);
+ }
+
+ return (setlongvalue ((long) queryid, vreturned)); /* return the db address to the scripter */
+
+} /* sqlitecompilequeryverb */
+
+boolean sqliteclearqueryverb (hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
+ sqlite3_stmt *queryid; /* query id */
+ int returnCode; /* return code from SQLite call */
+
+ /*
+ sqlite.clearQuery(queryid)
+
+ Action: clear an SQLite query
+ 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_finalize.
+ */
+
+ 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_finalize(queryid);
+
+ return setlongvalue (returnCode, vreturned);
+
+} /* sqliteclearqueryverb */
+
+boolean sqliteexecutequeryverb (hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
+ sqlite3_stmt *queryid; /* query id */
+ int returnCode; /* return code from SQLite call */
+
+ /*
+ sqlite.executeQuery(queryid)
+
+ Action: perform the query, moving the query cursor to the next row of results
+ 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_step.
+ */
+
+ 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 pline pointer */
+ return (false);
+
+ /* Process the SQLite sequence */
+ returnCode = sqlite3_step(queryid);
+
+ return setlongvalue (returnCode, vreturned);
+
+} /* sqliteexecutequeryverb */
+
+boolean sqlitegetcolumntypeverb (hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
+ long columnNumber; /* column number */
+ sqlite3_stmt *queryid; /* query id */
+ int returnCode; /* return code from SQLite call */
+
+ /*
+ sqlite.getColumnType(queryid, columnNumber)
+
+ Action: Retrieve the type of the specified column
+ Params: a query id and the number of the column (1 base)
+ Returns: an SQLite result code
+ Notes: do not pass the opened database ID across threads.
+
+ 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 */
+ return (false);
+
+ flnextparamislast = true; /* makes sure Frontier throws an error if more than one param is passed */
+
+ /* Enter the verb, convert the param to null-terminated string */
+ if (!getlongvalue (hparam1, 2, &columnNumber))
+ 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);
+
+ switch(returnCode) {
+
+ case SQLITE_INTEGER: {
+ return setostypevalue (langgettypeid (longvaluetype), vreturned);
+ }
+ case SQLITE_FLOAT: {
+ return setostypevalue (langgettypeid (doublevaluetype), vreturned);
+ }
+ case SQLITE_TEXT: {
+ return setostypevalue (langgettypeid (stringvaluetype), vreturned);
+ }
+ case SQLITE_BLOB: {
+ return setostypevalue (langgettypeid (binaryvaluetype), vreturned);
+ }
+ case SQLITE_NULL: {
+ return setostypevalue (langgettypeid (novaluetype), vreturned);
+ }
+ default: {
+ /* 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.");
+ return (false);
+ }
+ } /* switch */
+
+} /* sqlitegetcolumntypeverb */
+
+boolean sqlitegetcolumnnameverb (hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
+ long columnNumber; /* column number */
+ Handle returnH;
+ const char *column_name;
+ sqlite3_stmt *queryid;
+
+ /*
+ sqlite.getColumnName(queryid, columnNumber)
+
+ Action: Retrieve the name of the specified column
+ Params: a query id and the number of the column (1 base)
+ Returns: an SQLite result code
+ Notes: do not pass the opened database ID across threads.
+
+ SQLite docs: http://www.sqlite.org/capi3ref.html#sqlite3_column_name.
+ */
+
+ if (!getlongvalue (hparam1, 1, (long *) &queryid)) /* Get the long value, which becomes the pline pointer */
+ return (false);
+
+ flnextparamislast = true; /* makes sure Frontier throws an error if more than one param is passed */
+
+ /* Enter the verb, convert the param to null-terminated string */
+ if (!getlongvalue (hparam1, 2, &columnNumber))
+ 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);
+ return (setheapvalue (returnH, stringvaluetype, vreturned));
+
+} /* sqlitegetcolumnnameverb */
+
+boolean sqlitegetcolumncountverb (hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
+ sqlite3_stmt *queryid;
+ int returnCode; /* return code from SQLite call */
+
+ /*
+ sqlite.getColumnCount(queryid)
+
+ Action: Retrieve number of columns returned in a query
+ Params: a query id
+ Returns: the number of columns in the result set returned by the prepared SQL statement.
+ Notes: do not pass the opened database ID across threads.
+ returns 0 if pStmt is an SQL statement that does not return data (for example an UPDATE).
+
+ SQLite docs: http://www.sqlite.org/capi3ref.html#sqlite3_column_count.
+ */
+ 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 pline pointer */
+ return (false);
+
+ /* Process the SQLite sequence */
+ returnCode = sqlite3_column_count(queryid);
+
+ return setlongvalue (returnCode, vreturned);
+
+} /* sqlitegetcolumncountverb */
+
+boolean sqlitegetcolumnintverb (hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
+ long columnNumber;
+ sqlite3_stmt *queryid;
+ long returnCode; /* return code from SQLite call */
+
+ /*
+ sqlite.getColumnInt(queryid, columnNumber)
+
+ Action: Retrieve the value of the specified integer-type column
+ Params: a query id and the number of the column (1 base)
+ Returns: an SQLite result code
+ Notes: do not pass the opened database ID across threads.
+
+ SQLite docs: http://www.sqlite.org/capi3ref.html#sqlite3_column_int.
+ */
+
+ if (!getlongvalue (hparam1, 1, (long *) &queryid)) /* Get the long value, which becomes the pline pointer */
+ return (false);
+
+ flnextparamislast = true; /* makes sure Frontier throws an error if more than one param is passed */
+
+ /* Enter the verb, convert the param to null-terminated string */
+ if (!getlongvalue (hparam1, 2, &columnNumber))
+ 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);
+
+ return (setlongvalue ((long) returnCode, vreturned));
+
+} /* sqlitegetcolumnintverb */
+
+boolean sqlitegetcolumndoubleverb (hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
+ long columnNumber;
+ sqlite3_stmt *queryid;
+ double returnCode; /* return code from SQLite call */
+
+ /*
+ sqlite.getColumnDouble(queryid, columnNumber)
+
+ Action: Retrieve the value of the specified double-type column
+ Params: a query id and the number of the column (1 base)
+ Returns: an SQLite result code
+ Notes: do not pass the opened database ID across threads.
+
+ SQLite docs: http://www.sqlite.org/capi3ref.html#sqlite3_column_double.
+ */
+
+ if (!getlongvalue (hparam1, 1, (long *) &queryid)) /* Get the long value, which becomes the pline pointer */
+ return (false);
+
+ flnextparamislast = true; /* makes sure Frontier throws an error if more than one param is passed */
+
+ /* Enter the verb, convert the param to null-terminated string */
+ if (!getlongvalue (hparam1, 2, &columnNumber))
+ 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);
+
+ return (setlongvalue ((double) returnCode, vreturned));
+
+} /* sqlitegetcolumndoubleverb */
+
+boolean sqlitegetcolumntextverb (hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
+ long columnNumber;
+ sqlite3_stmt *queryid;
+ Handle returnH;
+ const unsigned char *column_text;
+
+ /*
+ sqlite.getColumnText(queryid, columnNumber)
+
+ Action: Retrieve the value of the specified text-type column
+ Params: a query id and the number of the column (1 base)
+ Returns: an SQLite result code
+ Notes: do not pass the opened database ID across threads.
+
+ SQLite docs: http://www.sqlite.org/capi3ref.html#sqlite3_column_text.
+ */
+
+ if (!getlongvalue (hparam1, 1, (long *) &queryid)) /* Get the long value, which becomes the pline pointer */
+ return (false);
+
+ flnextparamislast = true; /* makes sure Frontier throws an error if more than one param is passed */
+
+ /* Enter the verb, convert the param to null-terminated string */
+ if (!getlongvalue (hparam1, 2, &columnNumber))
+ 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);
+ return (setheapvalue (returnH, stringvaluetype, vreturned));
+
+} /* sqlitegetcolumntextverb */
+
+boolean sqlitegetcolumnverb (hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
+ long columnNumber; /* column number */
+ sqlite3_stmt *queryid; /* query id */
+ int returnCode; /* return code from SQLite call */
+ Handle returnH;
+ const unsigned char *column_text;
+
+ /*
+ sqlite.getColumn(queryid, columnNumber)
+
+ Action: Retrieve the value of the specified column element
+ Params: a query id and the number of the column (1 base)
+ 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 */
+ return (false);
+
+ flnextparamislast = true; /* makes sure Frontier throws an error if more than one param is passed */
+
+ /* Enter the verb, convert the param to null-terminated string */
+ if (!getlongvalue (hparam1, 2, &columnNumber))
+ 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);
+
+ switch(returnCode) {
+
+ case SQLITE_INTEGER: {
+ returnCode = sqlite3_column_int(queryid, (int) columnNumber);
+ return (setlongvalue ((long) returnCode, vreturned));
+ }
+ case SQLITE_FLOAT: {
+ returnCode = sqlite3_column_double(queryid, (int) columnNumber);
+ return (setlongvalue ((double) returnCode, 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);
+ return (setheapvalue (returnH, stringvaluetype, vreturned));
+ }
+ case SQLITE_BLOB: {
+ return (setlongvalue ((long) 0, vreturned));
+ }
+ case SQLITE_NULL: {
+ return (setlongvalue ((long) 0, vreturned));
+ }
+ default: {
+ /* 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.");
+ return (false);
+ }
+ } /* switch */
+
+} /* sqlitegetcolumntext */
+
+boolean sqlitegeterrormessageverb (hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
+ const char *sqliteError; /* pointer to the error message */
+ sqlite3 *db; /* the SQLite database handle */
+ Handle returnH = nil; /* The handle being returned back to Frontier */
+
+ /*
+ Frontier verb: sqlite.getErrorMessage(dbfile)
+
+ Returns the error message for the most recent SQLite API call.
+ Takes a database ID.
+ Returns a string containing the error message.
+ NOTE: do not pass the opened database ID across threads.
+
+ SQLite docs: http://www.sqlite.org/capi3ref.html#sqlite3_errmsg.
+ */
+
+ flnextparamislast = true; /* makes sure Frontier throws an error if more than one param is passed */
+
+ if (!getlongvalue (hparam1, 1, (long *) &db)) /* Get the long value, which becomes the db pointer */
+ return (false);
+
+ /* Process the SQLite sequence */
+ sqliteError = sqlite3_errmsg(db);
+
+ /* Exit the verb, converting errMsg back to Frontier handle */
+ newfilledhandle ((ptrvoid) sqliteError, strlen (sqliteError), &returnH);
+ return (setheapvalue (returnH, stringvaluetype, vreturned));
+
+} /* sqlitegeterrormessageverb */
\ No newline at end of file
Modified: Frontier/branches/SQLite/Common/source/shell.c
===================================================================
--- Frontier/branches/SQLite/Common/source/shell.c 2006-08-30 19:38:37 UTC (rev 1489)
+++ Frontier/branches/SQLite/Common/source/shell.c 2006-08-30 21:45:37 UTC (rev 1490)
@@ -1319,6 +1319,8 @@
htmlinitverbs ();
+ sqliteinitverbs (); /* 2006-03-15 gewirtz: langsqlite.c */
+
#ifdef flregexpverbs
regexpinitverbs (); /* 2003-04-23 AR: langregexp.c */
#endif
Added: Frontier/branches/SQLite/Common/sqlite3/alter.c
===================================================================
--- Frontier/branches/SQLite/Common/sqlite3/alter.c (rev 0)
+++ Frontier/branches/SQLite/Common/sqlite3/alter.c 2006-08-30 21:45:37 UTC (rev 1490)
@@ -0,0 +1,575 @@
+/*
+** 2005 February 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains C code routines that used to generate VDBE code
+** that implements the ALTER TABLE command.
+**
+** $Id: alter.c,v 1.21 2006/06/21 12:36:25 danielk1977 Exp $
+*/
+#include "sqliteInt.h"
+#include <ctype.h>
+
+/*
+** The code in this file only exists if we are not omitting the
+** ALTER TABLE logic from the build.
+*/
+#ifndef SQLITE_OMIT_ALTERTABLE
+
+
+/*
+** This function is used by SQL generated to implement the
+** ALTER TABLE command. The first argument is the text of a CREATE TABLE or
+** CREATE INDEX command. The second is a table name. The table name in
+** the CREATE TABLE or CREATE INDEX statement is replaced with the second
+** argument and the result returned. Examples:
+**
+** sqlite_rename_table('CREATE TABLE abc(a, b, c)', 'def')
+** -> 'CREATE TABLE def(a, b, c)'
+**
+** sqlite_rename_table('CREATE INDEX i ON abc(a)', 'def')
+** -> 'CREATE INDEX i ON def(a, b, c)'
+*/
+static void renameTableFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ unsigned char const *zSql = sqlite3_value_text(argv[0]);
+ unsigned char const *zTableName = sqlite3_value_text(argv[1]);
+
+ int token;
+ Token tname;
+ unsigned char const *zCsr = zSql;
+ int len = 0;
+ char *zRet;
+
+ /* The principle used to locate the table name in the CREATE TABLE
+ ** statement is that the table name is the first token that is immediatedly
+ ** followed by a left parenthesis - TK_LP.
+ */
+ if( zSql ){
+ do {
+ /* Store the token that zCsr points to in tname. */
+ tname.z = zCsr;
+ tname.n = len;
+
+ /* Advance zCsr to the next token. Store that token type in 'token',
+ ** and it's length in 'len' (to be used next iteration of this loop).
+ */
+ do {
+ zCsr += len;
+ len = sqlite3GetToken(zCsr, &token);
+ } while( token==TK_SPACE );
+ assert( len>0 );
+ } while( token!=TK_LP );
+
+ zRet = sqlite3MPrintf("%.*s%Q%s", tname.z - zSql, zSql,
+ zTableName, tname.z+tname.n);
+ sqlite3_result_text(context, zRet, -1, sqlite3FreeX);
+ }
+}
+
+#ifndef SQLITE_OMIT_TRIGGER
+/* This function is used by SQL generated to implement the ALTER TABLE
+** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER
+** statement. The second is a table name. The table name in the CREATE
+** TRIGGER statement is replaced with the second argument and the result
+** returned. This is analagous to renameTableFunc() above, except for CREATE
+** TRIGGER, not CREATE INDEX and CREATE TABLE.
+*/
+static void renameTriggerFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ unsigned char const *zSql = sqlite3_value_text(argv[0]);
+ unsigned char const *zTableName = sqlite3_value_text(argv[1]);
+
+ int token;
+ Token tname;
+ int dist = 3;
+ unsigned char const *zCsr = zSql;
+ int len = 0;
+ char *zRet;
+
+ /* The principle used to locate the table name in the CREATE TRIGGER
+ ** statement is that the table name is the first token that is immediatedly
+ ** preceded by either TK_ON or TK_DOT and immediatedly followed by one
+ ** of TK_WHEN, TK_BEGIN or TK_FOR.
+ */
+ if( zSql ){
+ do {
+ /* Store the token that zCsr points to in tname. */
+ tname.z = zCsr;
+ tname.n = len;
+
+ /* Advance zCsr to the next token. Store that token type in 'token',
+ ** and it's length in 'len' (to be used next iteration of this loop).
+ */
+ do {
+ zCsr += len;
+ len = sqlite3GetToken(zCsr, &token);
+ }while( token==TK_SPACE );
+ assert( len>0 );
+
+ /* Variable 'dist' stores the number of tokens read since the most
+ ** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN
+ ** token is read and 'dist' equals 2, the condition stated above
+ ** to be met.
+ **
+ ** Note that ON cannot be a database, table or column name, so
+ ** there is no need to worry about syntax like
+ ** "CREATE TRIGGER ... ON ON.ON BEGIN ..." etc.
+ */
+ dist++;
+ if( token==TK_DOT || token==TK_ON ){
+ dist = 0;
+ }
+ } while( dist!=2 || (token!=TK_WHEN && token!=TK_FOR && token!=TK_BEGIN) );
+
+ /* Variable tname now contains the token that is the old table-name
+ ** in the CREATE TRIGGER statement.
+ */
+ zRet = sqlite3MPrintf("%.*s%Q%s", tname.z - zSql, zSql,
+ zTableName, tname.z+tname.n);
+ sqlite3_result_text(context, zRet, -1, sqlite3FreeX);
+ }
+}
+#endif /* !SQLITE_OMIT_TRIGGER */
+
+/*
+** Register built-in functions used to help implement ALTER TABLE
+*/
+void sqlite3AlterFunctions(sqlite3 *db){
+ static const struct {
+ char *zName;
+ signed char nArg;
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value **);
+ } aFuncs[] = {
+ { "sqlite_rename_table", 2, renameTableFunc},
+#ifndef SQLITE_OMIT_TRIGGER
+ { "sqlite_rename_trigger", 2, renameTriggerFunc},
+#endif
+ };
+ int i;
+
+ for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
+ sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg,
+ SQLITE_UTF8, 0, aFuncs[i].xFunc, 0, 0);
+ }
+}
+
+/*
+** Generate the text of a WHERE expression which can be used to select all
+** temporary triggers on table pTab from the sqlite_temp_master table. If
+** table pTab has no temporary triggers, or is itself stored in the
+** temporary database, NULL is returned.
+*/
+static char *whereTempTriggers(Parse *pParse, Table *pTab){
+ Trigger *pTrig;
+ char *zWhere = 0;
+ char *tmp = 0;
+ const Schema *pTempSchema = pParse->db->aDb[1].pSchema; /* Temp db schema */
+
+ /* If the table is not located in the temp-db (in which case NULL is
+ ** returned, loop through the tables list of triggers. For each trigger
+ ** that is not part of the temp-db schema, add a clause to the WHERE
+ ** expression being built up in zWhere.
+ */
+ if( pTab->pSchema!=pTempSchema ){
+ for( pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext ){
+ if( pTrig->pSchema==pTempSchema ){
+ if( !zWhere ){
+ zWhere = sqlite3MPrintf("name=%Q", pTrig->name);
+ }else{
+ tmp = zWhere;
+ zWhere = sqlite3MPrintf("%s OR name=%Q", zWhere, pTrig->name);
+ sqliteFree(tmp);
+ }
+ }
+ }
+ }
+ return zWhere;
+}
+
+/*
+** Generate code to drop and reload the internal representation of table
+** pTab from the database, including triggers and temporary triggers.
+** Argument zName is the name of the table in the database schema at
+** the time the generated code is executed. This can be different from
+** pTab->zName if this function is being called to code part of an
+** "ALTER TABLE RENAME TO" statement.
+*/
+static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){
+ Vdbe *v;
+ char *zWhere;
+ int iDb; /* Index of database containing pTab */
+#ifndef SQLITE_OMIT_TRIGGER
+ Trigger *pTrig;
+#endif
+
+ v = sqlite3GetVdbe(pParse);
+ if( !v ) return;
+ iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
+ assert( iDb>=0 );
+
+#ifndef SQLITE_OMIT_TRIGGER
+ /* Drop any table triggers from the internal schema. */
+ for(pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext){
+ int iTrigDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
+ assert( iTrigDb==iDb || iTrigDb==1 );
+ sqlite3VdbeOp3(v, OP_DropTrigger, iTrigDb, 0, pTrig->name, 0);
+ }
+#endif
+
+ /* Drop the table and index from the internal schema */
+ sqlite3VdbeOp3(v, OP_DropTable, iDb, 0, pTab->zName, 0);
+
+ /* Reload the table, index and permanent trigger schemas. */
+ zWhere = sqlite3MPrintf("tbl_name=%Q", zName);
+ if( !zWhere ) return;
+ sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, zWhere, P3_DYNAMIC);
+
+#ifndef SQLITE_OMIT_TRIGGER
+ /* Now, if the table is not stored in the temp database, reload any temp
+ ** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined.
+ */
+ if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
+ sqlite3VdbeOp3(v, OP_ParseSchema, 1, 0, zWhere, P3_DYNAMIC);
+ }
+#endif
+}
+
+/*
+** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy"
+** command.
+*/
+void sqlite3AlterRenameTable(
+ Parse *pParse, /* Parser context. */
+ SrcList *pSrc, /* The table to rename. */
+ Token *pName /* The new table name. */
+){
+ int iDb; /* Database that contains the table */
+ char *zDb; /* Name of database iDb */
+ Table *pTab; /* Table being renamed */
+ char *zName = 0; /* NULL-terminated version of pName */
+ sqlite3 *db = pParse->db; /* Database connection */
+ Vdbe *v;
+#ifndef SQLITE_OMIT_TRIGGER
+ char *zWhere = 0; /* Where clause to locate temp triggers */
+#endif
+
+ if( sqlite3MallocFailed() ) goto exit_rename_table;
+ assert( pSrc->nSrc==1 );
+
+ pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
+ if( !pTab ) goto exit_rename_table;
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( IsVirtual(pTab) ){
+ sqlite3ErrorMsg(pParse, "virtual tables may not be altered");
+ goto exit_rename_table;
+ }
+#endif
+ iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
+ zDb = db->aDb[iDb].zName;
+
+ /* Get a NULL terminated version of the new table name. */
+ zName = sqlite3NameFromToken(pName);
+ if( !zName ) goto exit_rename_table;
+
+ /* Check that a table or index named 'zName' does not already exist
+ ** in database iDb. If so, this is an error.
+ */
+ if( sqlite3FindTable(db, zName, zDb) || sqlite3FindIndex(db, zName, zDb) ){
+ sqlite3ErrorMsg(pParse,
+ "there is already another table or index with this name: %s", zName);
+ goto exit_rename_table;
+ }
+
+ /* Make sure it is not a system table being altered, or a reserved name
+ ** that the table is being renamed to.
+ */
+ if( strlen(pTab->zName)>6 && 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7) ){
+ sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName);
+ goto exit_rename_table;
+ }
+ if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
+ goto exit_rename_table;
+ }
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ /* Invoke the authorization callback. */
+ if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){
+ goto exit_rename_table;
+ }
+#endif
+
+ /* Begin a transaction and code the VerifyCookie for database iDb.
+ ** Then modify the schema cookie (since the ALTER TABLE modifies the
+ ** schema).
+ */
+ v = sqlite3GetVdbe(pParse);
+ if( v==0 ){
+ goto exit_rename_table;
+ }
+ sqlite3BeginWriteOperation(pParse, 0, iDb);
+ sqlite3ChangeCookie(db, v, iDb);
+
+ /* Modify the sqlite_master table to use the new table name. */
+ sqlite3NestedParse(pParse,
+ "UPDATE %Q.%s SET "
+#ifdef SQLITE_OMIT_TRIGGER
+ "sql = sqlite_rename_table(sql, %Q), "
+#else
+ "sql = CASE "
+ "WHEN type = 'trigger' THEN sqlite_rename_trigger(sql, %Q)"
+ "ELSE sqlite_rename_table(sql, %Q) END, "
+#endif
+ "tbl_name = %Q, "
+ "name = CASE "
+ "WHEN type='table' THEN %Q "
+ "WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN "
+ "'sqlite_autoindex_' || %Q || substr(name, %d+18,10) "
+ "ELSE name END "
+ "WHERE tbl_name=%Q AND "
+ "(type='table' OR type='index' OR type='trigger');",
+ zDb, SCHEMA_TABLE(iDb), zName, zName, zName,
+#ifndef SQLITE_OMIT_TRIGGER
+ zName,
+#endif
+ zName, strlen(pTab->zName), pTab->zName
+ );
+
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+ /* If the sqlite_sequence table exists in this database, then update
+ ** it with the new table name.
+ */
+ if( sqlite3FindTable(db, "sqlite_sequence", zDb) ){
+ sqlite3NestedParse(pParse,
+ "UPDATE %Q.sqlite_sequence set name = %Q WHERE name = %Q",
+ zDb, zName, pTab->zName);
+ }
+#endif
+
+#ifndef SQLITE_OMIT_TRIGGER
+ /* If there are TEMP triggers on this table, modify the sqlite_temp_master
+ ** table. Don't do this if the table being ALTERed is itself located in
+ ** the temp database.
+ */
+ if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
+ sqlite3NestedParse(pParse,
+ "UPDATE sqlite_temp_master SET "
+ "sql = sqlite_rename_trigger(sql, %Q), "
+ "tbl_name = %Q "
+ "WHERE %s;", zName, zName, zWhere);
+ sqliteFree(zWhere);
+ }
+#endif
+
+ /* Drop and reload the internal table schema. */
+ reloadTableSchema(pParse, pTab, zName);
+
+exit_rename_table:
+ sqlite3SrcListDelete(pSrc);
+ sqliteFree(zName);
+}
+
+
+/*
+** This function is called after an "ALTER TABLE ... ADD" statement
+** has been parsed. Argument pColDef contains the text of the new
+** column definition.
+**
+** The Table structure pParse->pNewTable was extended to include
+** the new column during parsing.
+*/
+void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
+ Table *pNew; /* Copy of pParse->pNewTable */
+ Table *pTab; /* Table being altered */
+ int iDb; /* Database number */
+ const char *zDb; /* Database name */
+ const char *zTab; /* Table name */
+ char *zCol; /* Null-terminated column definition */
+ Column *pCol; /* The new column */
+ Expr *pDflt; /* Default value for the new column */
+
+ if( pParse->nErr ) return;
+ pNew = pParse->pNewTable;
+ assert( pNew );
+
+ iDb = sqlite3SchemaToIndex(pParse->db, pNew->pSchema);
+ zDb = pParse->db->aDb[iDb].zName;
+ zTab = pNew->zName;
+ pCol = &pNew->aCol[pNew->nCol-1];
+ pDflt = pCol->pDflt;
+ pTab = sqlite3FindTable(pParse->db, zTab, zDb);
+ assert( pTab );
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ /* Invoke the authorization callback. */
+ if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){
+ return;
+ }
+#endif
+
+ /* If the default value for the new column was specified with a
+ ** literal NULL, then set pDflt to 0. This simplifies checking
+ ** for an SQL NULL default below.
+ */
+ if( pDflt && pDflt->op==TK_NULL ){
+ pDflt = 0;
+ }
+
+ /* Check that the new column is not specified as PRIMARY KEY or UNIQUE.
+ ** If there is a NOT NULL constraint, then the default value for the
+ ** column must not be NULL.
+ */
+ if( pCol->isPrimKey ){
+ sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column");
+ return;
+ }
+ if( pNew->pIndex ){
+ sqlite3ErrorMsg(pParse, "Cannot add a UNIQUE column");
+ return;
+ }
+ if( pCol->notNull && !pDflt ){
+ sqlite3ErrorMsg(pParse,
+ "Cannot add a NOT NULL column with default value NULL");
+ return;
+ }
+
+ /* Ensure the default expression is something that sqlite3ValueFromExpr()
+ ** can handle (i.e. not CURRENT_TIME etc.)
+ */
+ if( pDflt ){
+ sqlite3_value *pVal;
+ if( sqlite3ValueFromExpr(pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal) ){
+ /* malloc() has failed */
+ return;
+ }
+ if( !pVal ){
+ sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default");
+ return;
+ }
+ sqlite3ValueFree(pVal);
+ }
+
+ /* Modify the CREATE TABLE statement. */
+ zCol = sqliteStrNDup((char*)pColDef->z, pColDef->n);
+ if( zCol ){
+ char *zEnd = &zCol[pColDef->n-1];
+ while( (zEnd>zCol && *zEnd==';') || isspace(*(unsigned char *)zEnd) ){
+ *zEnd-- = '\0';
+ }
+ sqlite3NestedParse(pParse,
+ "UPDATE %Q.%s SET "
+ "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d,length(sql)) "
+ "WHERE type = 'table' AND name = %Q",
+ zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1,
+ zTab
+ );
+ sqliteFree(zCol);
+ }
+
+ /* If the default value of the new column is NULL, then set the file
+ ** format to 2. If the default value of the new column is not NULL,
+ ** the file format becomes 3.
+ */
+ sqlite3MinimumFileFormat(pParse, iDb, pDflt ? 3 : 2);
+
+ /* Reload the schema of the modified table. */
+ reloadTableSchema(pParse, pTab, pTab->zName);
+}
+
+/*
+** This function is called by the parser after the table-name in
+** an "ALTER TABLE <table-name> ADD" statement is parsed. Argument
+** pSrc is the full-name of the table being altered.
+**
+** This routine makes a (partial) copy of the Table structure
+** for the table being altered and sets Parse.pNewTable to point
+** to it. Routines called by the parser as the column definition
+** is parsed (i.e. sqlite3AddColumn()) add the new Column data to
+** the copy. The copy of the Table structure is deleted by tokenize.c
+** after parsing is finished.
+**
+** Routine sqlite3AlterFinishAddColumn() will be called to complete
+** coding the "ALTER TABLE ... ADD" statement.
+*/
+void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
+ Table *pNew;
+ Table *pTab;
+ Vdbe *v;
+ int iDb;
+ int i;
+ int nAlloc;
+
+ /* Look up the table being altered. */
+ assert( pParse->pNewTable==0 );
+ if( sqlite3MallocFailed() ) goto exit_begin_add_column;
+ pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
+ if( !pTab ) goto exit_begin_add_column;
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( IsVirtual(pTab) ){
+ sqlite3ErrorMsg(pParse, "virtual tables may not be altered");
+ goto exit_begin_add_column;
+ }
+#endif
+
+ /* Make sure this is not an attempt to ALTER a view. */
+ if( pTab->pSelect ){
+ sqlite3ErrorMsg(pParse, "Cannot add a column to a view");
+ goto exit_begin_add_column;
+ }
+
+ assert( pTab->addColOffset>0 );
+ iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
+
+ /* Put a copy of the Table struct in Parse.pNewTable for the
+ ** sqlite3AddColumn() function and friends to modify.
+ */
+ pNew = (Table *)sqliteMalloc(sizeof(Table));
+ if( !pNew ) goto exit_begin_add_column;
+ pParse->pNewTable = pNew;
+ pNew->nRef = 1;
+ pNew->nCol = pTab->nCol;
+ assert( pNew->nCol>0 );
+ nAlloc = (((pNew->nCol-1)/8)*8)+8;
+ assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 );
+ pNew->aCol = (Column *)sqliteMalloc(sizeof(Column)*nAlloc);
+ pNew->zName = sqliteStrDup(pTab->zName);
+ if( !pNew->aCol || !pNew->zName ){
+ goto exit_begin_add_column;
+ }
+ memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol);
+ for(i=0; i<pNew->nCol; i++){
+ Column *pCol = &pNew->aCol[i];
+ pCol->zName = sqliteStrDup(pCol->zName);
+ pCol->zColl = 0;
+ pCol->zType = 0;
+ pCol->pDflt = 0;
+ }
+ pNew->pSchema = pParse->db->aDb[iDb].pSchema;
+ pNew->addColOffset = pTab->addColOffset;
+ pNew->nRef = 1;
+
+ /* Begin a transaction and increment the schema cookie. */
+ sqlite3BeginWriteOperation(pParse, 0, iDb);
+ v = sqlite3GetVdbe(pParse);
+ if( !v ) goto exit_begin_add_column;
+ sqlite3ChangeCookie(pParse->db, v, iDb);
+
+exit_begin_add_column:
+ sqlite3SrcListDelete(pSrc);
+ return;
+}
+#endif /* SQLITE_ALTER_TABLE */
Added: Frontier/branches/SQLite/Common/sqlite3/analyze.c
===================================================================
--- Frontier/branches/SQLite/Common/sqlite3/analyze.c (rev 0)
+++ Frontier/branches/SQLite/Common/sqlite3/analyze.c 2006-08-30 21:45:37 UTC (rev 1490)
@@ -0,0 +1,403 @@
+/*
+** 2005 July 8
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains code associated with the ANALYZE command.
+**
+** @(#) $Id: analyze.c,v 1.16 2006/01/10 17:58:23 danielk1977 Exp $
+*/
+#ifndef SQLITE_OMIT_ANALYZE
+#include "sqliteInt.h"
+
+/*
+** This routine generates code that opens the sqlite_stat1 table on cursor
+** iStatCur.
+**
+** If the sqlite_stat1 tables does not previously exist, it is created.
+** If it does previously exist, all entires associated with table zWhere
+** are removed. If zWhere==0 then all entries are removed.
+*/
+static void openStatTable(
+ Parse *pParse, /* Parsing context */
+ int iDb, /* The database we are looking in */
+ int iStatCur, /* Open the sqlite_stat1 table on this cursor */
+ const char *zWhere /* Delete entries associated with this table */
+){
+ sqlite3 *db = pParse->db;
+ Db *pDb;
+ int iRootPage;
+ Table *pStat;
+ Vdbe *v = sqlite3GetVdbe(pParse);
+
+ pDb = &db->aDb[iDb];
+ if( (pStat = sqlite3FindTable(db, "sqlite_stat1", pDb->zName))==0 ){
+ /* The sqlite_stat1 tables does not exist. Create it.
+ ** Note that a side-effect of the CREATE TABLE statement is to leave
+ ** the rootpage of the new table on the top of the stack. This is
+ ** important because the OpenWrite opcode below will be needing it. */
+ sqlite3NestedParse(pParse,
+ "CREATE TABLE %Q.sqlite_stat1(tbl,idx,stat)",
+ pDb->zName
+ );
+ iRootPage = 0; /* Cause rootpage to be taken from top of stack */
+ }else if( zWhere ){
+ /* The sqlite_stat1 table exists. Delete all entries associated with
+ ** the table zWhere. */
+ sqlite3NestedParse(pParse,
+ "DELETE FROM %Q.sqlite_stat1 WHERE tbl=%Q",
+ pDb->zName, zWhere
+ );
+ iRootPage = pStat->tnum;
+ }else{
+ /* The sqlite_stat1 table already exists. Delete all rows. */
+ iRootPage = pStat->tnum;
+ sqlite3VdbeAddOp(v, OP_Clear, pStat->tnum, iDb);
+ }
+
+ /* Open the sqlite_stat1 table for writing. Unless it was created
+ ** by this vdbe program, lock it for writing at the shared-cache level.
+ ** If this vdbe did create the sqlite_stat1 table, then it must have
+ ** already obtained a schema-lock, making the write-lock redundant.
+ */
+ if( iRootPage>0 ){
+ sqlite3TableLock(pParse, iDb, iRootPage, 1, "sqlite_stat1");
+ }
+ sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
+ sqlite3VdbeAddOp(v, OP_OpenWrite, iStatCur, iRootPage);
+ sqlite3VdbeAddOp(v, OP_SetNumColumns, iStatCur, 3);
+}
+
+/*
+** Generate code to do an analysis of all indices associated with
+** a single table.
+*/
+static void analyzeOneTable(
+ Parse *pParse, /* Parser context */
+ Table *pTab, /* Table whose indices are to be analyzed */
+ int iStatCur, /* Cursor that writes to the sqlite_stat1 table */
+ int iMem /* Available memory locations begin here */
+){
+ Index *pIdx; /* An index to being analyzed */
+ int iIdxCur; /* Cursor number for index being analyzed */
+ int nCol; /* Number of columns in the index */
+ Vdbe *v; /* The virtual machine being built up */
+ int i; /* Loop counter */
+ int topOfLoop; /* The top of the loop */
+ int endOfLoop; /* The end of the lo...
[truncated message content] |