summaryrefslogtreecommitdiff
path: root/ext/pdo_sqlite/sqlite/src
diff options
context:
space:
mode:
Diffstat (limited to 'ext/pdo_sqlite/sqlite/src')
-rw-r--r--ext/pdo_sqlite/sqlite/src/alter.c334
-rw-r--r--ext/pdo_sqlite/sqlite/src/attach.c9
-rw-r--r--ext/pdo_sqlite/sqlite/src/auth.c5
-rw-r--r--ext/pdo_sqlite/sqlite/src/btree.c1665
-rw-r--r--ext/pdo_sqlite/sqlite/src/btree.h24
-rw-r--r--ext/pdo_sqlite/sqlite/src/build.c961
-rw-r--r--ext/pdo_sqlite/sqlite/src/date.c119
-rw-r--r--ext/pdo_sqlite/sqlite/src/delete.c90
-rw-r--r--ext/pdo_sqlite/sqlite/src/experimental.c38
-rw-r--r--ext/pdo_sqlite/sqlite/src/expr.c1086
-rw-r--r--ext/pdo_sqlite/sqlite/src/func.c100
-rw-r--r--ext/pdo_sqlite/sqlite/src/hash.c9
-rw-r--r--ext/pdo_sqlite/sqlite/src/insert.c213
-rw-r--r--ext/pdo_sqlite/sqlite/src/main.c104
-rw-r--r--ext/pdo_sqlite/sqlite/src/opcodes.c259
-rw-r--r--ext/pdo_sqlite/sqlite/src/opcodes.h257
-rw-r--r--ext/pdo_sqlite/sqlite/src/os.h31
-rw-r--r--ext/pdo_sqlite/sqlite/src/os_test.c8
-rw-r--r--ext/pdo_sqlite/sqlite/src/os_unix.c43
-rw-r--r--ext/pdo_sqlite/sqlite/src/os_win.c23
-rw-r--r--ext/pdo_sqlite/sqlite/src/pager.c772
-rw-r--r--ext/pdo_sqlite/sqlite/src/pager.h13
-rw-r--r--ext/pdo_sqlite/sqlite/src/parse.c3724
-rw-r--r--ext/pdo_sqlite/sqlite/src/parse.h155
-rw-r--r--ext/pdo_sqlite/sqlite/src/parse.y229
-rw-r--r--ext/pdo_sqlite/sqlite/src/pragma.c328
-rw-r--r--ext/pdo_sqlite/sqlite/src/printf.c24
-rw-r--r--ext/pdo_sqlite/sqlite/src/select.c673
-rw-r--r--ext/pdo_sqlite/sqlite/src/shell.c19
-rw-r--r--ext/pdo_sqlite/sqlite/src/sqlite.h.in104
-rw-r--r--ext/pdo_sqlite/sqlite/src/sqliteInt.h279
-rw-r--r--ext/pdo_sqlite/sqlite/src/tclsqlite.c550
-rw-r--r--ext/pdo_sqlite/sqlite/src/test1.c440
-rw-r--r--ext/pdo_sqlite/sqlite/src/test2.c31
-rw-r--r--ext/pdo_sqlite/sqlite/src/test3.c94
-rw-r--r--ext/pdo_sqlite/sqlite/src/test5.c3
-rw-r--r--ext/pdo_sqlite/sqlite/src/tokenize.c229
-rw-r--r--ext/pdo_sqlite/sqlite/src/trigger.c122
-rw-r--r--ext/pdo_sqlite/sqlite/src/update.c72
-rw-r--r--ext/pdo_sqlite/sqlite/src/utf.c12
-rw-r--r--ext/pdo_sqlite/sqlite/src/util.c81
-rw-r--r--ext/pdo_sqlite/sqlite/src/vacuum.c86
-rw-r--r--ext/pdo_sqlite/sqlite/src/vdbe.c457
-rw-r--r--ext/pdo_sqlite/sqlite/src/vdbe.h2
-rw-r--r--ext/pdo_sqlite/sqlite/src/vdbeInt.h10
-rw-r--r--ext/pdo_sqlite/sqlite/src/vdbeapi.c62
-rw-r--r--ext/pdo_sqlite/sqlite/src/vdbeaux.c153
-rw-r--r--ext/pdo_sqlite/sqlite/src/vdbemem.c21
-rw-r--r--ext/pdo_sqlite/sqlite/src/where.c816
49 files changed, 10182 insertions, 4757 deletions
diff --git a/ext/pdo_sqlite/sqlite/src/alter.c b/ext/pdo_sqlite/sqlite/src/alter.c
new file mode 100644
index 0000000000..199cdca383
--- /dev/null
+++ b/ext/pdo_sqlite/sqlite/src/alter.c
@@ -0,0 +1,334 @@
+/*
+** 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$
+*/
+#include "sqliteInt.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;
+ 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;
+ 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++){
+ sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg,
+ SQLITE_UTF8, 0, aFuncs[i].xFunc, 0, 0);
+ }
+}
+
+/*
+** 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 */
+ char *zWhere = 0; /* Where clause of schema elements to reparse */
+ sqlite3 *db = pParse->db; /* Database connection */
+ Vdbe *v;
+#ifndef SQLITE_OMIT_TRIGGER
+ char *zTempTrig = 0; /* Where clause to locate temp triggers */
+#endif
+
+ assert( pSrc->nSrc==1 );
+
+ pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
+ if( !pTab ) goto exit_rename_table;
+ iDb = pTab->iDb;
+ 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( iDb!=1 ){
+ Trigger *pTrig;
+ char *tmp = 0;
+ for( pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext ){
+ if( pTrig->iDb==1 ){
+ if( !zTempTrig ){
+ zTempTrig =
+ sqlite3MPrintf("type = 'trigger' AND (name=%Q", pTrig->name);
+ }else{
+ tmp = zTempTrig;
+ zTempTrig = sqlite3MPrintf("%s OR name=%Q", zTempTrig, pTrig->name);
+ sqliteFree(tmp);
+ }
+ }
+ }
+ if( zTempTrig ){
+ tmp = zTempTrig;
+ zTempTrig = sqlite3MPrintf("%s)", zTempTrig);
+ sqliteFree(tmp);
+ sqlite3NestedParse(pParse,
+ "UPDATE sqlite_temp_master SET "
+ "sql = sqlite_rename_trigger(sql, %Q), "
+ "tbl_name = %Q "
+ "WHERE %s;", zName, zName, zTempTrig);
+ }
+ }
+#endif
+
+ /* Drop the elements of the in-memory schema that refered to the table
+ ** renamed and load the new versions from the database.
+ */
+ if( pParse->nErr==0 ){
+#ifndef SQLITE_OMIT_TRIGGER
+ Trigger *pTrig;
+ for( pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext ){
+ assert( pTrig->iDb==iDb || pTrig->iDb==1 );
+ sqlite3VdbeOp3(v, OP_DropTrigger, pTrig->iDb, 0, pTrig->name, 0);
+ }
+#endif
+ sqlite3VdbeOp3(v, OP_DropTable, iDb, 0, pTab->zName, 0);
+ zWhere = sqlite3MPrintf("tbl_name=%Q", zName);
+ sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, zWhere, P3_DYNAMIC);
+#ifndef SQLITE_OMIT_TRIGGER
+ if( zTempTrig ){
+ sqlite3VdbeOp3(v, OP_ParseSchema, 1, 0, zTempTrig, P3_DYNAMIC);
+ }
+ }else{
+ sqliteFree(zTempTrig);
+#endif
+ }
+
+exit_rename_table:
+ sqlite3SrcListDelete(pSrc);
+ sqliteFree(zName);
+}
+#endif /* SQLITE_ALTER_TABLE */
diff --git a/ext/pdo_sqlite/sqlite/src/attach.c b/ext/pdo_sqlite/sqlite/src/attach.c
index 2f0899865c..79c325f4c1 100644
--- a/ext/pdo_sqlite/sqlite/src/attach.c
+++ b/ext/pdo_sqlite/sqlite/src/attach.c
@@ -38,6 +38,7 @@ void sqlite3Attach(
v = sqlite3GetVdbe(pParse);
if( !v ) return;
+ sqlite3VdbeAddOp(v, OP_Expire, 1, 0);
sqlite3VdbeAddOp(v, OP_Halt, 0, 0);
if( pParse->explain ) return;
db = pParse->db;
@@ -160,6 +161,7 @@ void sqlite3Detach(Parse *pParse, Token *pDbname){
v = sqlite3GetVdbe(pParse);
if( !v ) return;
+ sqlite3VdbeAddOp(v, OP_Expire, 0, 0);
sqlite3VdbeAddOp(v, OP_Halt, 0, 0);
if( pParse->explain ) return;
db = pParse->db;
@@ -251,11 +253,14 @@ int sqlite3FixSrcList(
pFix->zType, pFix->pName, pItem->zDatabase);
return 1;
}
+#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
+#endif
}
return 0;
}
+#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
int sqlite3FixSelect(
DbFixer *pFix, /* Context of the fixation */
Select *pSelect /* The SELECT statement to be fixed to one database */
@@ -309,6 +314,9 @@ int sqlite3FixExprList(
}
return 0;
}
+#endif
+
+#ifndef SQLITE_OMIT_TRIGGER
int sqlite3FixTriggerStep(
DbFixer *pFix, /* Context of the fixation */
TriggerStep *pStep /* The trigger step be fixed to one database */
@@ -327,3 +335,4 @@ int sqlite3FixTriggerStep(
}
return 0;
}
+#endif
diff --git a/ext/pdo_sqlite/sqlite/src/auth.c b/ext/pdo_sqlite/sqlite/src/auth.c
index b251eacfdf..d4b7a61bd3 100644
--- a/ext/pdo_sqlite/sqlite/src/auth.c
+++ b/ext/pdo_sqlite/sqlite/src/auth.c
@@ -76,6 +76,7 @@ int sqlite3_set_authorizer(
){
db->xAuth = xAuth;
db->pAuthArg = pArg;
+ sqlite3ExpirePreparedStatements(db);
return SQLITE_OK;
}
@@ -114,10 +115,10 @@ void sqlite3AuthRead(
if( db->xAuth==0 ) return;
assert( pExpr->op==TK_COLUMN );
- for(iSrc=0; iSrc<pTabList->nSrc; iSrc++){
+ for(iSrc=0; pTabList && iSrc<pTabList->nSrc; iSrc++){
if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break;
}
- if( iSrc>=0 && iSrc<pTabList->nSrc ){
+ if( iSrc>=0 && pTabList && iSrc<pTabList->nSrc ){
pTab = pTabList->a[iSrc].pTab;
}else if( (pStack = pParse->trigStack)!=0 ){
/* This must be an attempt to read the NEW or OLD pseudo-tables
diff --git a/ext/pdo_sqlite/sqlite/src/btree.c b/ext/pdo_sqlite/sqlite/src/btree.c
index fe8754e01d..b4ea019b6e 100644
--- a/ext/pdo_sqlite/sqlite/src/btree.c
+++ b/ext/pdo_sqlite/sqlite/src/btree.c
@@ -211,6 +211,11 @@
#include "os.h"
#include <assert.h>
+/*
+** This macro rounds values up so that if the value is an address it
+** is guaranteed to be an address that is aligned to an 8-byte boundary.
+*/
+#define FORCE_ALIGNMENT(X) (((X)+7)&~7)
/* The following value is the maximum cell size assuming a maximum page
** size give above.
@@ -299,7 +304,11 @@ struct Btree {
u8 minEmbedFrac; /* Minimum payload as % of total page size */
u8 minLeafFrac; /* Minimum leaf payload as % of total page size */
u8 pageSizeFixed; /* True if the page size can no longer be changed */
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ u8 autoVacuum; /* True if database supports auto-vacuum */
+#endif
u16 pageSize; /* Total number of bytes on a page */
+ u16 psAligned; /* pageSize rounded up to a multiple of 8 */
u16 usableSize; /* Number of usable bytes on each page */
int maxLocal; /* Maximum local payload in non-LEAFDATA tables */
int minLocal; /* Minimum local payload in non-LEAFDATA tables */
@@ -347,15 +356,26 @@ struct BtCursor {
CellInfo info; /* A parse of the cell we are pointing at */
u8 wrFlag; /* True if writable */
u8 isValid; /* TRUE if points to a valid entry */
- u8 status; /* Set to SQLITE_ABORT if cursors is invalidated */
};
/*
+** The TRACE macro will print high-level status information about the
+** btree operation when the global variable sqlite3_btree_trace is
+** enabled.
+*/
+#if SQLITE_TEST
+# define TRACE(X) if( sqlite3_btree_trace )\
+ { sqlite3DebugPrintf X; fflush(stdout); }
+#else
+# define TRACE(X)
+#endif
+int sqlite3_btree_trace=0; /* True to enable tracing */
+
+/*
** Forward declaration
*/
static int checkReadLocks(Btree*,Pgno,BtCursor*);
-
/*
** Read or write a two- and four-byte big-endian integer values.
*/
@@ -385,6 +405,136 @@ static void put4byte(unsigned char *p, u32 v){
#define getVarint32 sqlite3GetVarint32
#define putVarint sqlite3PutVarint
+/* The database page the PENDING_BYTE occupies. This page is never used.
+** TODO: This macro is very similary to PAGER_MJ_PGNO() in pager.c. They
+** should possibly be consolidated (presumably in pager.h).
+*/
+#define PENDING_BYTE_PAGE(pBt) ((PENDING_BYTE/(pBt)->pageSize)+1)
+
+#ifndef SQLITE_OMIT_AUTOVACUUM
+/*
+** These macros define the location of the pointer-map entry for a
+** database page. The first argument to each is the number of usable
+** bytes on each page of the database (often 1024). The second is the
+** page number to look up in the pointer map.
+**
+** PTRMAP_PAGENO returns the database page number of the pointer-map
+** page that stores the required pointer. PTRMAP_PTROFFSET returns
+** the offset of the requested map entry.
+**
+** If the pgno argument passed to PTRMAP_PAGENO is a pointer-map page,
+** then pgno is returned. So (pgno==PTRMAP_PAGENO(pgsz, pgno)) can be
+** used to test if pgno is a pointer-map page. PTRMAP_ISPAGE implements
+** this test.
+*/
+#define PTRMAP_PAGENO(pgsz, pgno) (((pgno-2)/(pgsz/5+1))*(pgsz/5+1)+2)
+#define PTRMAP_PTROFFSET(pgsz, pgno) (((pgno-2)%(pgsz/5+1)-1)*5)
+#define PTRMAP_ISPAGE(pgsz, pgno) (PTRMAP_PAGENO(pgsz,pgno)==pgno)
+
+/*
+** The pointer map is a lookup table that identifies the parent page for
+** each child page in the database file. The parent page is the page that
+** contains a pointer to the child. Every page in the database contains
+** 0 or 1 parent pages. (In this context 'database page' refers
+** to any page that is not part of the pointer map itself.) Each pointer map
+** entry consists of a single byte 'type' and a 4 byte parent page number.
+** The PTRMAP_XXX identifiers below are the valid types.
+**
+** The purpose of the pointer map is to facility moving pages from one
+** position in the file to another as part of autovacuum. When a page
+** is moved, the pointer in its parent must be updated to point to the
+** new location. The pointer map is used to locate the parent page quickly.
+**
+** PTRMAP_ROOTPAGE: The database page is a root-page. The page-number is not
+** used in this case.
+**
+** PTRMAP_FREEPAGE: The database page is an unused (free) page. The page-number
+** is not used in this case.
+**
+** PTRMAP_OVERFLOW1: The database page is the first page in a list of
+** overflow pages. The page number identifies the page that
+** contains the cell with a pointer to this overflow page.
+**
+** PTRMAP_OVERFLOW2: The database page is the second or later page in a list of
+** overflow pages. The page-number identifies the previous
+** page in the overflow page list.
+**
+** PTRMAP_BTREE: The database page is a non-root btree page. The page number
+** identifies the parent page in the btree.
+*/
+#define PTRMAP_ROOTPAGE 1
+#define PTRMAP_FREEPAGE 2
+#define PTRMAP_OVERFLOW1 3
+#define PTRMAP_OVERFLOW2 4
+#define PTRMAP_BTREE 5
+
+/*
+** Write an entry into the pointer map.
+**
+** This routine updates the pointer map entry for page number 'key'
+** so that it maps to type 'eType' and parent page number 'pgno'.
+** An error code is returned if something goes wrong, otherwise SQLITE_OK.
+*/
+static int ptrmapPut(Btree *pBt, Pgno key, u8 eType, Pgno parent){
+ u8 *pPtrmap; /* The pointer map page */
+ Pgno iPtrmap; /* The pointer map page number */
+ int offset; /* Offset in pointer map page */
+ int rc;
+
+ assert( pBt->autoVacuum );
+ if( key==0 ){
+ return SQLITE_CORRUPT;
+ }
+ iPtrmap = PTRMAP_PAGENO(pBt->usableSize, key);
+ rc = sqlite3pager_get(pBt->pPager, iPtrmap, (void **)&pPtrmap);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ offset = PTRMAP_PTROFFSET(pBt->usableSize, key);
+
+ if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){
+ TRACE(("PTRMAP_UPDATE: %d->(%d,%d)\n", key, eType, parent));
+ rc = sqlite3pager_write(pPtrmap);
+ if( rc==SQLITE_OK ){
+ pPtrmap[offset] = eType;
+ put4byte(&pPtrmap[offset+1], parent);
+ }
+ }
+
+ sqlite3pager_unref(pPtrmap);
+ return rc;
+}
+
+/*
+** Read an entry from the pointer map.
+**
+** This routine retrieves the pointer map entry for page 'key', writing
+** the type and parent page number to *pEType and *pPgno respectively.
+** An error code is returned if something goes wrong, otherwise SQLITE_OK.
+*/
+static int ptrmapGet(Btree *pBt, Pgno key, u8 *pEType, Pgno *pPgno){
+ int iPtrmap; /* Pointer map page index */
+ u8 *pPtrmap; /* Pointer map page data */
+ int offset; /* Offset of entry in pointer map */
+ int rc;
+
+ iPtrmap = PTRMAP_PAGENO(pBt->usableSize, key);
+ rc = sqlite3pager_get(pBt->pPager, iPtrmap, (void **)&pPtrmap);
+ if( rc!=0 ){
+ return rc;
+ }
+
+ offset = PTRMAP_PTROFFSET(pBt->usableSize, key);
+ if( pEType ) *pEType = pPtrmap[offset];
+ if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]);
+
+ sqlite3pager_unref(pPtrmap);
+ if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT;
+ return SQLITE_OK;
+}
+
+#endif /* SQLITE_OMIT_AUTOVACUUM */
+
/*
** Given a btree page and a cell index (0 means the first cell on
** the page, 1 means the second cell, and so forth) return a pointer
@@ -514,6 +664,36 @@ static int cellSizePtr(MemPage *pPage, u8 *pCell){
return info.nSize;
}
+#ifndef SQLITE_OMIT_AUTOVACUUM
+/*
+** If the cell pCell, part of page pPage contains a pointer
+** to an overflow page, insert an entry into the pointer-map
+** for the overflow page.
+*/
+static int ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell){
+ if( pCell ){
+ CellInfo info;
+ parseCellPtr(pPage, pCell, &info);
+ if( (info.nData+(pPage->intKey?0:info.nKey))>info.nLocal ){
+ Pgno ovfl = get4byte(&pCell[info.iOverflow]);
+ return ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno);
+ }
+ }
+ return SQLITE_OK;
+}
+/*
+** If the cell with index iCell on page pPage contains a pointer
+** to an overflow page, insert an entry into the pointer-map
+** for the overflow page.
+*/
+static int ptrmapPutOvfl(MemPage *pPage, int iCell){
+ u8 *pCell;
+ pCell = findOverflowCell(pPage, iCell);
+ return ptrmapPutOvflPtr(pPage, pCell);
+}
+#endif
+
+
/*
** Do sanity checking on a page. Throw an exception if anything is
** not right.
@@ -533,7 +713,7 @@ static void _pageIntegrity(MemPage *pPage){
used = sqliteMallocRaw( pPage->pBt->pageSize );
if( used==0 ) return;
usableSize = pPage->pBt->usableSize;
- assert( pPage->aData==&((unsigned char*)pPage)[-pPage->pBt->pageSize] );
+ assert( pPage->aData==&((unsigned char*)pPage)[-pPage->pBt->psAligned] );
hdr = pPage->hdrOffset;
assert( hdr==(pPage->pgno==1 ? 100 : 0) );
assert( pPage->pgno==sqlite3pager_pagenumber(pPage->aData) );
@@ -824,7 +1004,6 @@ static int initPage(
MemPage *pParent /* The parent. Might be NULL */
){
int pc; /* Address of a freeblock within pPage->aData[] */
- int i; /* Loop counter */
int hdr; /* Offset to beginning of page header */
u8 *data; /* Equal to pPage->aData */
Btree *pBt; /* The main btree structure */
@@ -837,7 +1016,7 @@ static int initPage(
assert( pBt!=0 );
assert( pParent==0 || pParent->pBt==pBt );
assert( pPage->pgno==sqlite3pager_pagenumber(pPage->aData) );
- assert( pPage->aData == &((unsigned char*)pPage)[-pBt->pageSize] );
+ assert( pPage->aData == &((unsigned char*)pPage)[-pBt->psAligned] );
if( pPage->pParent!=pParent && (pPage->pParent!=0 || pPage->isInit) ){
/* The parent page should never change unless the file is corrupt */
return SQLITE_CORRUPT; /* bkpt-CORRUPT */
@@ -868,17 +1047,12 @@ static int initPage(
/* Compute the total free space on the page */
pc = get2byte(&data[hdr+1]);
nFree = data[hdr+7] + top - (cellOffset + 2*pPage->nCell);
- i = 0;
while( pc>0 ){
int next, size;
if( pc>usableSize-4 ){
/* Free block is off the page */
return SQLITE_CORRUPT; /* bkpt-CORRUPT */
}
- if( i++>SQLITE_MAX_PAGE_SIZE/4 ){
- /* The free block list forms an infinite loop */
- return SQLITE_CORRUPT; /* bkpt-CORRUPT */
- }
next = get2byte(&data[pc]);
size = get2byte(&data[pc+2]);
if( next>0 && next<=pc+size+3 ){
@@ -910,7 +1084,7 @@ static void zeroPage(MemPage *pPage, int flags){
int first;
assert( sqlite3pager_pagenumber(data)==pPage->pgno );
- assert( &data[pBt->pageSize] == (unsigned char*)pPage );
+ assert( &data[pBt->psAligned] == (unsigned char*)pPage );
assert( sqlite3pager_iswriteable(data) );
memset(&data[hdr], 0, pBt->usableSize - hdr);
data[hdr] = flags;
@@ -939,7 +1113,7 @@ static int getPage(Btree *pBt, Pgno pgno, MemPage **ppPage){
MemPage *pPage;
rc = sqlite3pager_get(pBt->pPager, pgno, (void**)&aData);
if( rc ) return rc;
- pPage = (MemPage*)&aData[pBt->pageSize];
+ pPage = (MemPage*)&aData[pBt->psAligned];
pPage->aData = aData;
pPage->pBt = pBt;
pPage->pgno = pgno;
@@ -978,7 +1152,7 @@ static void releasePage(MemPage *pPage){
if( pPage ){
assert( pPage->aData );
assert( pPage->pBt );
- assert( &pPage->aData[pPage->pBt->pageSize]==(unsigned char*)pPage );
+ assert( &pPage->aData[pPage->pBt->psAligned]==(unsigned char*)pPage );
sqlite3pager_unref(pPage->aData);
}
}
@@ -989,7 +1163,7 @@ static void releasePage(MemPage *pPage){
** happens.
*/
static void pageDestructor(void *pData, int pageSize){
- MemPage *pPage = (MemPage*)&((char*)pData)[pageSize];
+ MemPage *pPage = (MemPage*)&((char*)pData)[FORCE_ALIGNMENT(pageSize)];
if( pPage->pParent ){
MemPage *pParent = pPage->pParent;
pPage->pParent = 0;
@@ -1007,7 +1181,7 @@ static void pageDestructor(void *pData, int pageSize){
** page to agree with the restored data.
*/
static void pageReinit(void *pData, int pageSize){
- MemPage *pPage = (MemPage*)&((char*)pData)[pageSize];
+ MemPage *pPage = (MemPage*)&((char*)pData)[FORCE_ALIGNMENT(pageSize)];
if( pPage->isInit ){
pPage->isInit = 0;
initPage(pPage, pPage->pParent);
@@ -1049,8 +1223,7 @@ int sqlite3BtreeOpen(
*ppBtree = 0;
return SQLITE_NOMEM;
}
- rc = sqlite3pager_open(&pBt->pPager, zFilename, EXTRA_SIZE,
- (flags & BTREE_OMIT_JOURNAL)==0);
+ rc = sqlite3pager_open(&pBt->pPager, zFilename, EXTRA_SIZE, flags);
if( rc!=SQLITE_OK ){
if( pBt->pPager ) sqlite3pager_close(pBt->pPager);
sqliteFree(pBt);
@@ -1069,6 +1242,21 @@ int sqlite3BtreeOpen(
pBt->maxEmbedFrac = 64; /* 25% */
pBt->minEmbedFrac = 32; /* 12.5% */
pBt->minLeafFrac = 32; /* 12.5% */
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ /* If the magic name ":memory:" will create an in-memory database, then
+ ** do not set the auto-vacuum flag, even if SQLITE_DEFAULT_AUTOVACUUM
+ ** is true. On the other hand, if SQLITE_OMIT_MEMORYDB has been defined,
+ ** then ":memory:" is just a regular file-name. Respect the auto-vacuum
+ ** default in this case.
+ */
+#ifndef SQLITE_OMIT_MEMORYDB
+ if( zFilename && strcmp(zFilename,":memory:") ){
+#else
+ if( zFilename ){
+#endif
+ pBt->autoVacuum = SQLITE_DEFAULT_AUTOVACUUM;
+ }
+#endif
nReserve = 0;
}else{
nReserve = zDbHeader[20];
@@ -1076,8 +1264,12 @@ int sqlite3BtreeOpen(
pBt->minEmbedFrac = zDbHeader[22];
pBt->minLeafFrac = zDbHeader[23];
pBt->pageSizeFixed = 1;
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ pBt->autoVacuum = (get4byte(&zDbHeader[36 + 4*4])?1:0);
+#endif
}
pBt->usableSize = pBt->pageSize - nReserve;
+ pBt->psAligned = FORCE_ALIGNMENT(pBt->pageSize);
sqlite3pager_set_pagesize(pBt->pPager, pBt->pageSize);
*ppBtree = pBt;
return SQLITE_OK;
@@ -1131,13 +1323,28 @@ int sqlite3BtreeSetCacheSize(Btree *pBt, int mxPage){
** is a very low but non-zero probability of damage. Level 3 reduces the
** probability of damage to near zero but with a write performance reduction.
*/
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
int sqlite3BtreeSetSafetyLevel(Btree *pBt, int level){
sqlite3pager_set_safety_level(pBt->pPager, level);
return SQLITE_OK;
}
+#endif
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM)
/*
** Change the default pages size and the number of reserved bytes per page.
+**
+** The page size must be a power of 2 between 512 and 65536. If the page
+** size supplied does not meet this constraint then the page size is not
+** changed.
+**
+** Page sizes are constrained to be a power of two so that the region
+** of the database file used for locking (beginning at PENDING_BYTE,
+** the first byte past the 1GB boundary, 0x40000000) needs to occur
+** at the beginning of a page.
+**
+** If parameter nReserve is less than zero, then the number of reserved
+** bytes per page is left unchanged.
*/
int sqlite3BtreeSetPageSize(Btree *pBt, int pageSize, int nReserve){
if( pBt->pageSizeFixed ){
@@ -1146,8 +1353,10 @@ int sqlite3BtreeSetPageSize(Btree *pBt, int pageSize, int nReserve){
if( nReserve<0 ){
nReserve = pBt->pageSize - pBt->usableSize;
}
- if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE ){
+ if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE &&
+ ((pageSize-1)&pageSize)==0 ){
pBt->pageSize = pageSize;
+ pBt->psAligned = FORCE_ALIGNMENT(pageSize);
sqlite3pager_set_pagesize(pBt->pPager, pageSize);
}
pBt->usableSize = pBt->pageSize - nReserve;
@@ -1163,6 +1372,38 @@ int sqlite3BtreeGetPageSize(Btree *pBt){
int sqlite3BtreeGetReserve(Btree *pBt){
return pBt->pageSize - pBt->usableSize;
}
+#endif /* !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) */
+
+/*
+** Change the 'auto-vacuum' property of the database. If the 'autoVacuum'
+** parameter is non-zero, then auto-vacuum mode is enabled. If zero, it
+** is disabled. The default value for the auto-vacuum property is
+** determined by the SQLITE_DEFAULT_AUTOVACUUM macro.
+*/
+int sqlite3BtreeSetAutoVacuum(Btree *pBt, int autoVacuum){
+#ifdef SQLITE_OMIT_AUTOVACUUM
+ return SQLITE_READONLY;
+#else
+ if( pBt->pageSizeFixed ){
+ return SQLITE_READONLY;
+ }
+ pBt->autoVacuum = (autoVacuum?1:0);
+ return SQLITE_OK;
+#endif
+}
+
+/*
+** Return the value of the 'auto-vacuum' property. If auto-vacuum is
+** enabled 1 is returned. Otherwise 0.
+*/
+int sqlite3BtreeGetAutoVacuum(Btree *pBt){
+#ifdef SQLITE_OMIT_AUTOVACUUM
+ return 0;
+#else
+ return pBt->autoVacuum;
+#endif
+}
+
/*
** Get a reference to pPage1 of the database file. This will
@@ -1199,9 +1440,13 @@ static int lockBtree(Btree *pBt){
if( pBt->usableSize<500 ){
goto page1_init_failed;
}
+ pBt->psAligned = FORCE_ALIGNMENT(pBt->pageSize);
pBt->maxEmbedFrac = page1[21];
pBt->minEmbedFrac = page1[22];
pBt->minLeafFrac = page1[23];
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ pBt->autoVacuum = (get4byte(&page1[36 + 4*4])?1:0);
+#endif
}
/* maxLocal is the maximum amount of payload to store locally for
@@ -1248,7 +1493,7 @@ static void unlockBtreeIfUnused(Btree *pBt){
if( pBt->inTrans==TRANS_NONE && pBt->pCursor==0 && pBt->pPage1!=0 ){
if( pBt->pPage1->aData==0 ){
MemPage *pPage = pBt->pPage1;
- pPage->aData = &((char*)pPage)[-pBt->pageSize];
+ pPage->aData = &((char*)pPage)[-pBt->psAligned];
pPage->pBt = pBt;
pPage->pgno = 1;
}
@@ -1284,6 +1529,11 @@ static int newDatabase(Btree *pBt){
memset(&data[24], 0, 100-24);
zeroPage(pP1, PTF_INTKEY|PTF_LEAF|PTF_LEAFDATA );
pBt->pageSizeFixed = 1;
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( pBt->autoVacuum ){
+ put4byte(&data[36 + 4*4], 1);
+ }
+#endif
return SQLITE_OK;
}
@@ -1348,6 +1598,304 @@ int sqlite3BtreeBeginTrans(Btree *pBt, int wrflag){
return rc;
}
+#ifndef SQLITE_OMIT_AUTOVACUUM
+
+/*
+** Set the pointer-map entries for all children of page pPage. Also, if
+** pPage contains cells that point to overflow pages, set the pointer
+** map entries for the overflow pages as well.
+*/
+static int setChildPtrmaps(MemPage *pPage){
+ int i; /* Counter variable */
+ int nCell; /* Number of cells in page pPage */
+ int rc = SQLITE_OK; /* Return code */
+ Btree *pBt = pPage->pBt;
+ int isInitOrig = pPage->isInit;
+ Pgno pgno = pPage->pgno;
+
+ initPage(pPage, 0);
+ nCell = pPage->nCell;
+
+ for(i=0; i<nCell; i++){
+ u8 *pCell = findCell(pPage, i);
+
+ rc = ptrmapPutOvflPtr(pPage, pCell);
+ if( rc!=SQLITE_OK ){
+ goto set_child_ptrmaps_out;
+ }
+
+ if( !pPage->leaf ){
+ Pgno childPgno = get4byte(pCell);
+ rc = ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno);
+ if( rc!=SQLITE_OK ) goto set_child_ptrmaps_out;
+ }
+ }
+
+ if( !pPage->leaf ){
+ Pgno childPgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
+ rc = ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno);
+ }
+
+set_child_ptrmaps_out:
+ pPage->isInit = isInitOrig;
+ return rc;
+}
+
+/*
+** Somewhere on pPage, which is guarenteed to be a btree page, not an overflow
+** page, is a pointer to page iFrom. Modify this pointer so that it points to
+** iTo. Parameter eType describes the type of pointer to be modified, as
+** follows:
+**
+** PTRMAP_BTREE: pPage is a btree-page. The pointer points at a child
+** page of pPage.
+**
+** PTRMAP_OVERFLOW1: pPage is a btree-page. The pointer points at an overflow
+** page pointed to by one of the cells on pPage.
+**
+** PTRMAP_OVERFLOW2: pPage is an overflow-page. The pointer points at the next
+** overflow page in the list.
+*/
+static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
+ if( eType==PTRMAP_OVERFLOW2 ){
+ /* The pointer is always the first 4 bytes of the page in this case. */
+ if( get4byte(pPage->aData)!=iFrom ){
+ return SQLITE_CORRUPT;
+ }
+ put4byte(pPage->aData, iTo);
+ }else{
+ int isInitOrig = pPage->isInit;
+ int i;
+ int nCell;
+
+ initPage(pPage, 0);
+ nCell = pPage->nCell;
+
+ for(i=0; i<nCell; i++){
+ u8 *pCell = findCell(pPage, i);
+ if( eType==PTRMAP_OVERFLOW1 ){
+ CellInfo info;
+ parseCellPtr(pPage, pCell, &info);
+ if( info.iOverflow ){
+ if( iFrom==get4byte(&pCell[info.iOverflow]) ){
+ put4byte(&pCell[info.iOverflow], iTo);
+ break;
+ }
+ }
+ }else{
+ if( get4byte(pCell)==iFrom ){
+ put4byte(pCell, iTo);
+ break;
+ }
+ }
+ }
+
+ if( i==nCell ){
+ if( eType!=PTRMAP_BTREE ||
+ get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){
+ return SQLITE_CORRUPT;
+ }
+ put4byte(&pPage->aData[pPage->hdrOffset+8], iTo);
+ }
+
+ pPage->isInit = isInitOrig;
+ }
+ return SQLITE_OK;
+}
+
+
+/*
+** Move the open database page pDbPage to location iFreePage in the
+** database. The pDbPage reference remains valid.
+*/
+static int relocatePage(
+ Btree *pBt, /* Btree */
+ MemPage *pDbPage, /* Open page to move */
+ u8 eType, /* Pointer map 'type' entry for pDbPage */
+ Pgno iPtrPage, /* Pointer map 'page-no' entry for pDbPage */
+ Pgno iFreePage /* The location to move pDbPage to */
+){
+ MemPage *pPtrPage; /* The page that contains a pointer to pDbPage */
+ Pgno iDbPage = pDbPage->pgno;
+ Pager *pPager = pBt->pPager;
+ int rc;
+
+ assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 ||
+ eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE );
+
+ /* Move page iDbPage from it's current location to page number iFreePage */
+ TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n",
+ iDbPage, iFreePage, iPtrPage, eType));
+ rc = sqlite3pager_movepage(pPager, pDbPage->aData, iFreePage);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ pDbPage->pgno = iFreePage;
+
+ /* If pDbPage was a btree-page, then it may have child pages and/or cells
+ ** that point to overflow pages. The pointer map entries for all these
+ ** pages need to be changed.
+ **
+ ** If pDbPage is an overflow page, then the first 4 bytes may store a
+ ** pointer to a subsequent overflow page. If this is the case, then
+ ** the pointer map needs to be updated for the subsequent overflow page.
+ */
+ if( eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ){
+ rc = setChildPtrmaps(pDbPage);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ }else{
+ Pgno nextOvfl = get4byte(pDbPage->aData);
+ if( nextOvfl!=0 ){
+ rc = ptrmapPut(pBt, nextOvfl, PTRMAP_OVERFLOW2, iFreePage);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ }
+ }
+
+ /* Fix the database pointer on page iPtrPage that pointed at iDbPage so
+ ** that it points at iFreePage. Also fix the pointer map entry for
+ ** iPtrPage.
+ */
+ if( eType!=PTRMAP_ROOTPAGE ){
+ rc = getPage(pBt, iPtrPage, &pPtrPage);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ rc = sqlite3pager_write(pPtrPage->aData);
+ if( rc!=SQLITE_OK ){
+ releasePage(pPtrPage);
+ return rc;
+ }
+ rc = modifyPagePointer(pPtrPage, iDbPage, iFreePage, eType);
+ releasePage(pPtrPage);
+ if( rc==SQLITE_OK ){
+ rc = ptrmapPut(pBt, iFreePage, eType, iPtrPage);
+ }
+ }
+ return rc;
+}
+
+/* Forward declaration required by autoVacuumCommit(). */
+static int allocatePage(Btree *, MemPage **, Pgno *, Pgno, u8);
+
+/*
+** This routine is called prior to sqlite3pager_commit when a transaction
+** is commited for an auto-vacuum database.
+*/
+static int autoVacuumCommit(Btree *pBt, Pgno *nTrunc){
+ Pager *pPager = pBt->pPager;
+ Pgno nFreeList; /* Number of pages remaining on the free-list. */
+ int nPtrMap; /* Number of pointer-map pages deallocated */
+ Pgno origSize; /* Pages in the database file */
+ Pgno finSize; /* Pages in the database file after truncation */
+ int rc; /* Return code */
+ u8 eType;
+ int pgsz = pBt->pageSize; /* Page size for this database */
+ Pgno iDbPage; /* The database page to move */
+ MemPage *pDbMemPage = 0; /* "" */
+ Pgno iPtrPage; /* The page that contains a pointer to iDbPage */
+ Pgno iFreePage; /* The free-list page to move iDbPage to */
+ MemPage *pFreeMemPage = 0; /* "" */
+
+#ifndef NDEBUG
+ int nRef = *sqlite3pager_stats(pPager);
+#endif
+
+ assert( pBt->autoVacuum );
+ if( PTRMAP_ISPAGE(pgsz, sqlite3pager_pagecount(pPager)) ){
+ return SQLITE_CORRUPT;
+ }
+
+ /* Figure out how many free-pages are in the database. If there are no
+ ** free pages, then auto-vacuum is a no-op.
+ */
+ nFreeList = get4byte(&pBt->pPage1->aData[36]);
+ if( nFreeList==0 ){
+ *nTrunc = 0;
+ return SQLITE_OK;
+ }
+
+ origSize = sqlite3pager_pagecount(pPager);
+ nPtrMap = (nFreeList-origSize+PTRMAP_PAGENO(pgsz, origSize)+pgsz/5)/(pgsz/5);
+ finSize = origSize - nFreeList - nPtrMap;
+ if( origSize>PENDING_BYTE_PAGE(pBt) && finSize<=PENDING_BYTE_PAGE(pBt) ){
+ finSize--;
+ if( PTRMAP_ISPAGE(pBt->usableSize, finSize) ){
+ finSize--;
+ }
+ }
+ TRACE(("AUTOVACUUM: Begin (db size %d->%d)\n", origSize, finSize));
+
+ /* Variable 'finSize' will be the size of the file in pages after
+ ** the auto-vacuum has completed (the current file size minus the number
+ ** of pages on the free list). Loop through the pages that lie beyond
+ ** this mark, and if they are not already on the free list, move them
+ ** to a free page earlier in the file (somewhere before finSize).
+ */
+ for( iDbPage=finSize+1; iDbPage<=origSize; iDbPage++ ){
+ /* If iDbPage is a pointer map page, or the pending-byte page, skip it. */
+ if( PTRMAP_ISPAGE(pgsz, iDbPage) || iDbPage==PENDING_BYTE_PAGE(pBt) ){
+ continue;
+ }
+
+ rc = ptrmapGet(pBt, iDbPage, &eType, &iPtrPage);
+ if( rc!=SQLITE_OK ) goto autovacuum_out;
+ assert( eType!=PTRMAP_ROOTPAGE );
+
+ /* If iDbPage is free, do not swap it. */
+ if( eType==PTRMAP_FREEPAGE ){
+ continue;
+ }
+ rc = getPage(pBt, iDbPage, &pDbMemPage);
+ if( rc!=SQLITE_OK ) goto autovacuum_out;
+
+ /* Find the next page in the free-list that is not already at the end
+ ** of the file. A page can be pulled off the free list using the
+ ** allocatePage() routine.
+ */
+ do{
+ if( pFreeMemPage ){
+ releasePage(pFreeMemPage);
+ pFreeMemPage = 0;
+ }
+ rc = allocatePage(pBt, &pFreeMemPage, &iFreePage, 0, 0);
+ if( rc!=SQLITE_OK ){
+ releasePage(pDbMemPage);
+ goto autovacuum_out;
+ }
+ assert( iFreePage<=origSize );
+ }while( iFreePage>finSize );
+ releasePage(pFreeMemPage);
+ pFreeMemPage = 0;
+
+ rc = relocatePage(pBt, pDbMemPage, eType, iPtrPage, iFreePage);
+ releasePage(pDbMemPage);
+ if( rc!=SQLITE_OK ) goto autovacuum_out;
+ }
+
+ /* The entire free-list has been swapped to the end of the file. So
+ ** truncate the database file to finSize pages and consider the
+ ** free-list empty.
+ */
+ rc = sqlite3pager_write(pBt->pPage1->aData);
+ if( rc!=SQLITE_OK ) goto autovacuum_out;
+ put4byte(&pBt->pPage1->aData[32], 0);
+ put4byte(&pBt->pPage1->aData[36], 0);
+ if( rc!=SQLITE_OK ) goto autovacuum_out;
+ *nTrunc = finSize;
+
+autovacuum_out:
+ assert( nRef==*sqlite3pager_stats(pPager) );
+ if( rc!=SQLITE_OK ){
+ sqlite3pager_rollback(pPager);
+ }
+ return rc;
+}
+#endif
+
/*
** Commit the transaction currently in progress.
**
@@ -1381,25 +1929,6 @@ static int countWriteCursors(Btree *pBt){
}
#endif
-#if 0
-/*
-** Invalidate all cursors
-*/
-static void invalidateCursors(Btree *pBt){
- BtCursor *pCur;
- for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
- MemPage *pPage = pCur->pPage;
- if( pPage /* && !pPage->isInit */ ){
- pageIntegrity(pPage);
- releasePage(pPage);
- pCur->pPage = 0;
- pCur->isValid = 0;
- pCur->status = SQLITE_ABORT;
- }
- }
-}
-#endif
-
#ifdef SQLITE_TEST
/*
** Print debugging information about all cursors to standard output.
@@ -1618,7 +2147,6 @@ int sqlite3BtreeCursor(
pCur->pPrev = 0;
pBt->pCursor = pCur;
pCur->isValid = 0;
- pCur->status = SQLITE_OK;
*ppCur = pCur;
return SQLITE_OK;
@@ -1845,9 +2373,7 @@ static int getPayload(
** the available payload.
*/
int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
- if( pCur->isValid==0 ){
- return pCur->status;
- }
+ assert( pCur->isValid );
assert( pCur->pPage!=0 );
assert( pCur->pPage->intKey==0 );
assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
@@ -1864,9 +2390,7 @@ int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
** the available payload.
*/
int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
- if( !pCur->isValid ){
- return pCur->status ? pCur->status : SQLITE_INTERNAL;
- }
+ assert( pCur->isValid );
assert( pCur->pPage!=0 );
assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
return getPayload(pCur, offset, amt, pBuf, 1);
@@ -2104,9 +2628,6 @@ static int moveToRightmost(BtCursor *pCur){
*/
int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
int rc;
- if( pCur->status ){
- return pCur->status;
- }
rc = moveToRoot(pCur);
if( rc ) return rc;
if( pCur->isValid==0 ){
@@ -2126,9 +2647,6 @@ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
*/
int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
int rc;
- if( pCur->status ){
- return pCur->status;
- }
rc = moveToRoot(pCur);
if( rc ) return rc;
if( pCur->isValid==0 ){
@@ -2171,10 +2689,6 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
*/
int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, i64 nKey, int *pRes){
int rc;
-
- if( pCur->status ){
- return pCur->status;
- }
rc = moveToRoot(pCur);
if( rc ) return rc;
assert( pCur->pPage );
@@ -2184,13 +2698,16 @@ int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, i64 nKey, int *pRes){
assert( pCur->pPage->nCell==0 );
return SQLITE_OK;
}
- for(;;){
+ for(;;){
int lwr, upr;
Pgno chldPg;
MemPage *pPage = pCur->pPage;
int c = -1; /* pRes return if table is empty must be -1 */
lwr = 0;
upr = pPage->nCell-1;
+ if( !pPage->intKey && pKey==0 ){
+ return SQLITE_CORRUPT;
+ }
pageIntegrity(pPage);
while( lwr<=upr ){
void *pCellKey;
@@ -2288,6 +2805,7 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
}
assert( pPage->isInit );
assert( pCur->idx<pPage->nCell );
+
pCur->idx++;
pCur->info.nSize = 0;
if( pCur->idx>=pPage->nCell ){
@@ -2337,6 +2855,7 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
*pRes = 1;
return SQLITE_OK;
}
+
pPage = pCur->pPage;
assert( pPage->isInit );
assert( pCur->idx>=0 );
@@ -2357,7 +2876,7 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
}
pCur->idx--;
pCur->info.nSize = 0;
- if( pPage->leafData ){
+ if( pPage->leafData && !pPage->leaf ){
rc = sqlite3BtreePrevious(pCur, pRes);
}else{
rc = SQLITE_OK;
@@ -2368,19 +2887,6 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
}
/*
-** The TRACE macro will print high-level status information about the
-** btree operation when the global variable sqlite3_btree_trace is
-** enabled.
-*/
-#if SQLITE_TEST
-# define TRACE(X) if( sqlite3_btree_trace )\
- { sqlite3DebugPrintf X; fflush(stdout); }
-#else
-# define TRACE(X)
-#endif
-int sqlite3_btree_trace=0; /* True to enable tracing */
-
-/*
** Allocate a new page from the database file.
**
** The new page is marked as dirty. (In other words, sqlite3pager_write()
@@ -2396,8 +2902,18 @@ int sqlite3_btree_trace=0; /* True to enable tracing */
** locate a page close to the page number "nearby". This can be used in an
** attempt to keep related pages close to each other in the database file,
** which in turn can make database access faster.
+**
+** If the "exact" parameter is not 0, and the page-number nearby exists
+** anywhere on the free-list, then it is guarenteed to be returned. This
+** is only used by auto-vacuum databases when allocating a new table.
*/
-static int allocatePage(Btree *pBt, MemPage **ppPage, Pgno *pPgno, Pgno nearby){
+static int allocatePage(
+ Btree *pBt,
+ MemPage **ppPage,
+ Pgno *pPgno,
+ Pgno nearby,
+ u8 exact
+){
MemPage *pPage1;
int rc;
int n; /* Number of pages on the freelist */
@@ -2407,72 +2923,200 @@ static int allocatePage(Btree *pBt, MemPage **ppPage, Pgno *pPgno, Pgno nearby){
n = get4byte(&pPage1->aData[36]);
if( n>0 ){
/* There are pages on the freelist. Reuse one of those pages. */
- MemPage *pTrunk;
+ MemPage *pTrunk = 0;
+ Pgno iTrunk;
+ MemPage *pPrevTrunk = 0;
+ u8 searchList = 0; /* If the free-list must be searched for 'nearby' */
+
+ /* If the 'exact' parameter was true and a query of the pointer-map
+ ** shows that the page 'nearby' is somewhere on the free-list, then
+ ** the entire-list will be searched for that page.
+ */
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( exact ){
+ u8 eType;
+ assert( nearby>0 );
+ assert( pBt->autoVacuum );
+ rc = ptrmapGet(pBt, nearby, &eType, 0);
+ if( rc ) return rc;
+ if( eType==PTRMAP_FREEPAGE ){
+ searchList = 1;
+ }
+ *pPgno = nearby;
+ }
+#endif
+
+ /* Decrement the free-list count by 1. Set iTrunk to the index of the
+ ** first free-list trunk page. iPrevTrunk is initially 1.
+ */
rc = sqlite3pager_write(pPage1->aData);
if( rc ) return rc;
put4byte(&pPage1->aData[36], n-1);
- rc = getPage(pBt, get4byte(&pPage1->aData[32]), &pTrunk);
- if( rc ) return rc;
- rc = sqlite3pager_write(pTrunk->aData);
- if( rc ){
- releasePage(pTrunk);
- return rc;
- }
- k = get4byte(&pTrunk->aData[4]);
- if( k==0 ){
- /* The trunk has no leaves. So extract the trunk page itself and
- ** use it as the newly allocated page */
- *pPgno = get4byte(&pPage1->aData[32]);
- memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4);
- *ppPage = pTrunk;
- TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1));
- }else if( k>pBt->usableSize/4 - 8 ){
- /* Value of k is out of range. Database corruption */
- return SQLITE_CORRUPT; /* bkpt-CORRUPT */
- }else{
- /* Extract a leaf from the trunk */
- int closest;
- unsigned char *aData = pTrunk->aData;
- if( nearby>0 ){
- int i, dist;
- closest = 0;
- dist = get4byte(&aData[8]) - nearby;
- if( dist<0 ) dist = -dist;
- for(i=1; i<k; i++){
- int d2 = get4byte(&aData[8+i*4]) - nearby;
- if( d2<0 ) d2 = -d2;
- if( d2<dist ) closest = i;
- }
+
+ /* The code within this loop is run only once if the 'searchList' variable
+ ** is not true. Otherwise, it runs once for each trunk-page on the
+ ** free-list until the page 'nearby' is located.
+ */
+ do {
+ pPrevTrunk = pTrunk;
+ if( pPrevTrunk ){
+ iTrunk = get4byte(&pPrevTrunk->aData[0]);
}else{
- closest = 0;
+ iTrunk = get4byte(&pPage1->aData[32]);
}
- *pPgno = get4byte(&aData[8+closest*4]);
- if( *pPgno>sqlite3pager_pagecount(pBt->pPager) ){
- /* Free page off the end of the file */
- return SQLITE_CORRUPT; /* bkpt-CORRUPT */
+ rc = getPage(pBt, iTrunk, &pTrunk);
+ if( rc ){
+ releasePage(pPrevTrunk);
+ return rc;
}
- TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d: %d more free pages\n",
- *pPgno, closest+1, k, pTrunk->pgno, n-1));
- if( closest<k-1 ){
- memcpy(&aData[8+closest*4], &aData[4+k*4], 4);
+
+ /* TODO: This should move to after the loop? */
+ rc = sqlite3pager_write(pTrunk->aData);
+ if( rc ){
+ releasePage(pTrunk);
+ releasePage(pPrevTrunk);
+ return rc;
}
- put4byte(&aData[4], k-1);
- rc = getPage(pBt, *pPgno, ppPage);
- releasePage(pTrunk);
- if( rc==SQLITE_OK ){
- sqlite3pager_dont_rollback((*ppPage)->aData);
- rc = sqlite3pager_write((*ppPage)->aData);
+
+ k = get4byte(&pTrunk->aData[4]);
+ if( k==0 && !searchList ){
+ /* The trunk has no leaves and the list is not being searched.
+ ** So extract the trunk page itself and use it as the newly
+ ** allocated page */
+ assert( pPrevTrunk==0 );
+ *pPgno = iTrunk;
+ memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4);
+ *ppPage = pTrunk;
+ pTrunk = 0;
+ TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1));
+ }else if( k>pBt->usableSize/4 - 8 ){
+ /* Value of k is out of range. Database corruption */
+ return SQLITE_CORRUPT; /* bkpt-CORRUPT */
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ }else if( searchList && nearby==iTrunk ){
+ /* The list is being searched and this trunk page is the page
+ ** to allocate, regardless of whether it has leaves.
+ */
+ assert( *pPgno==iTrunk );
+ *ppPage = pTrunk;
+ searchList = 0;
+ if( k==0 ){
+ if( !pPrevTrunk ){
+ memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4);
+ }else{
+ memcpy(&pPrevTrunk->aData[0], &pTrunk->aData[0], 4);
+ }
+ }else{
+ /* The trunk page is required by the caller but it contains
+ ** pointers to free-list leaves. The first leaf becomes a trunk
+ ** page in this case.
+ */
+ MemPage *pNewTrunk;
+ Pgno iNewTrunk = get4byte(&pTrunk->aData[8]);
+ rc = getPage(pBt, iNewTrunk, &pNewTrunk);
+ if( rc!=SQLITE_OK ){
+ releasePage(pTrunk);
+ releasePage(pPrevTrunk);
+ return rc;
+ }
+ rc = sqlite3pager_write(pNewTrunk->aData);
+ if( rc!=SQLITE_OK ){
+ releasePage(pNewTrunk);
+ releasePage(pTrunk);
+ releasePage(pPrevTrunk);
+ return rc;
+ }
+ memcpy(&pNewTrunk->aData[0], &pTrunk->aData[0], 4);
+ put4byte(&pNewTrunk->aData[4], k-1);
+ memcpy(&pNewTrunk->aData[8], &pTrunk->aData[12], (k-1)*4);
+ if( !pPrevTrunk ){
+ put4byte(&pPage1->aData[32], iNewTrunk);
+ }else{
+ put4byte(&pPrevTrunk->aData[0], iNewTrunk);
+ }
+ releasePage(pNewTrunk);
+ }
+ pTrunk = 0;
+ TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1));
+#endif
+ }else{
+ /* Extract a leaf from the trunk */
+ int closest;
+ Pgno iPage;
+ unsigned char *aData = pTrunk->aData;
+ if( nearby>0 ){
+ int i, dist;
+ closest = 0;
+ dist = get4byte(&aData[8]) - nearby;
+ if( dist<0 ) dist = -dist;
+ for(i=1; i<k; i++){
+ int d2 = get4byte(&aData[8+i*4]) - nearby;
+ if( d2<0 ) d2 = -d2;
+ if( d2<dist ){
+ closest = i;
+ dist = d2;
+ }
+ }
+ }else{
+ closest = 0;
+ }
+
+ iPage = get4byte(&aData[8+closest*4]);
+ if( !searchList || iPage==nearby ){
+ *pPgno = iPage;
+ if( *pPgno>sqlite3pager_pagecount(pBt->pPager) ){
+ /* Free page off the end of the file */
+ return SQLITE_CORRUPT; /* bkpt-CORRUPT */
+ }
+ TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d"
+ ": %d more free pages\n",
+ *pPgno, closest+1, k, pTrunk->pgno, n-1));
+ if( closest<k-1 ){
+ memcpy(&aData[8+closest*4], &aData[4+k*4], 4);
+ }
+ put4byte(&aData[4], k-1);
+ rc = getPage(pBt, *pPgno, ppPage);
+ if( rc==SQLITE_OK ){
+ sqlite3pager_dont_rollback((*ppPage)->aData);
+ rc = sqlite3pager_write((*ppPage)->aData);
+ if( rc!=SQLITE_OK ){
+ releasePage(*ppPage);
+ }
+ }
+ searchList = 0;
+ }
}
- }
+ releasePage(pPrevTrunk);
+ }while( searchList );
+ releasePage(pTrunk);
}else{
/* There are no pages on the freelist, so create a new page at the
** end of the file */
*pPgno = sqlite3pager_pagecount(pBt->pPager) + 1;
+
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt->usableSize, *pPgno) ){
+ /* If *pPgno refers to a pointer-map page, allocate two new pages
+ ** at the end of the file instead of one. The first allocated page
+ ** becomes a new pointer-map page, the second is used by the caller.
+ */
+ TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", *pPgno));
+ assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
+ (*pPgno)++;
+ }
+#endif
+
+ assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
rc = getPage(pBt, *pPgno, ppPage);
if( rc ) return rc;
rc = sqlite3pager_write((*ppPage)->aData);
+ if( rc!=SQLITE_OK ){
+ releasePage(*ppPage);
+ }
TRACE(("ALLOCATE: %d from end of file\n", *pPgno));
}
+
+ assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
return rc;
}
@@ -2498,6 +3142,16 @@ static int freePage(MemPage *pPage){
n = get4byte(&pPage1->aData[36]);
put4byte(&pPage1->aData[36], n+1);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ /* If the database supports auto-vacuum, write an entry in the pointer-map
+ ** to indicate that the page is free.
+ */
+ if( pBt->autoVacuum ){
+ rc = ptrmapPut(pBt, pPage->pgno, PTRMAP_FREEPAGE, 0);
+ if( rc ) return rc;
+ }
+#endif
+
if( n==0 ){
/* This is the first free page */
rc = sqlite3pager_write(pPage->aData);
@@ -2552,6 +3206,9 @@ static int clearCell(MemPage *pPage, unsigned char *pCell){
ovflPgno = get4byte(&pCell[info.iOverflow]);
while( ovflPgno!=0 ){
MemPage *pOvfl;
+ if( ovflPgno>sqlite3pager_pagecount(pBt->pPager) ){
+ return SQLITE_CORRUPT;
+ }
rc = getPage(pBt, ovflPgno, &pOvfl);
if( rc ) return rc;
ovflPgno = get4byte(pOvfl->aData);
@@ -2628,10 +3285,23 @@ static int fillInCell(
while( nPayload>0 ){
if( spaceLeft==0 ){
- rc = allocatePage(pBt, &pOvfl, &pgnoOvfl, pgnoOvfl);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ Pgno pgnoPtrmap = pgnoOvfl; /* Overflow page pointer-map entry page */
+#endif
+ rc = allocatePage(pBt, &pOvfl, &pgnoOvfl, pgnoOvfl, 0);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ /* If the database supports auto-vacuum, and the second or subsequent
+ ** overflow page is being allocated, add an entry to the pointer-map
+ ** for that page now. The entry for the first overflow page will be
+ ** added later, by the insertCell() routine.
+ */
+ if( pBt->autoVacuum && pgnoPtrmap!=0 && rc==SQLITE_OK ){
+ rc = ptrmapPut(pBt, pgnoOvfl, PTRMAP_OVERFLOW2, pgnoPtrmap);
+ }
+#endif
if( rc ){
releasePage(pToRelease);
- clearCell(pPage, pCell);
+ /* clearCell(pPage, pCell); */
return rc;
}
put4byte(pPrior, pgnoOvfl);
@@ -2665,15 +3335,15 @@ static int fillInCell(
** given in the second argument so that MemPage.pParent holds the
** pointer in the third argument.
*/
-static void reparentPage(Btree *pBt, Pgno pgno, MemPage *pNewParent, int idx){
+static int reparentPage(Btree *pBt, Pgno pgno, MemPage *pNewParent, int idx){
MemPage *pThis;
unsigned char *aData;
- if( pgno==0 ) return;
+ if( pgno==0 ) return SQLITE_OK;
assert( pBt->pPager!=0 );
aData = sqlite3pager_lookup(pBt->pPager, pgno);
if( aData ){
- pThis = (MemPage*)&aData[pBt->pageSize];
+ pThis = (MemPage*)&aData[pBt->psAligned];
assert( pThis->aData==aData );
if( pThis->isInit ){
if( pThis->pParent!=pNewParent ){
@@ -2685,8 +3355,17 @@ static void reparentPage(Btree *pBt, Pgno pgno, MemPage *pNewParent, int idx){
}
sqlite3pager_unref(aData);
}
+
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( pBt->autoVacuum ){
+ return ptrmapPut(pBt, pgno, PTRMAP_BTREE, pNewParent->pgno);
+ }
+#endif
+ return SQLITE_OK;
}
+
+
/*
** Change the pParent pointer of all children of pPage to point back
** to pPage.
@@ -2697,17 +3376,26 @@ static void reparentPage(Btree *pBt, Pgno pgno, MemPage *pNewParent, int idx){
** This routine gets called after you memcpy() one page into
** another.
*/
-static void reparentChildPages(MemPage *pPage){
+static int reparentChildPages(MemPage *pPage){
int i;
- Btree *pBt;
+ Btree *pBt = pPage->pBt;
+ int rc = SQLITE_OK;
+
+ if( pPage->leaf ) return SQLITE_OK;
- if( pPage->leaf ) return;
- pBt = pPage->pBt;
for(i=0; i<pPage->nCell; i++){
- reparentPage(pBt, get4byte(findCell(pPage,i)), pPage, i);
+ u8 *pCell = findCell(pPage, i);
+ if( !pPage->leaf ){
+ rc = reparentPage(pBt, get4byte(pCell), pPage, i);
+ if( rc!=SQLITE_OK ) return rc;
+ }
}
- reparentPage(pBt, get4byte(&pPage->aData[pPage->hdrOffset+8]), pPage, i);
- pPage->idxShift = 0;
+ if( !pPage->leaf ){
+ rc = reparentPage(pBt, get4byte(&pPage->aData[pPage->hdrOffset+8]),
+ pPage, i);
+ pPage->idxShift = 0;
+ }
+ return rc;
}
/*
@@ -2753,13 +3441,19 @@ static void dropCell(MemPage *pPage, int idx, int sz){
** in pTemp or the original pCell) and also record its index.
** Allocating a new entry in pPage->aCell[] implies that
** pPage->nOverflow is incremented.
+**
+** If nSkip is non-zero, then do not copy the first nSkip bytes of the
+** cell. The caller will overwrite them after this function returns. If
+** nSkip is non-zero, then pCell may not point to an invalid memory location
+** (but pCell+nSkip is always valid).
*/
-static void insertCell(
+static int insertCell(
MemPage *pPage, /* Page into which we are copying */
int i, /* New cell becomes the i-th cell of the page */
u8 *pCell, /* Content of the new cell */
int sz, /* Bytes of content in pCell */
- u8 *pTemp /* Temp storage space for pCell, if needed */
+ u8 *pTemp, /* Temp storage space for pCell, if needed */
+ u8 nSkip /* Do not write the first nSkip bytes of the cell */
){
int idx; /* Where to write new cell content in data[] */
int j; /* Loop counter */
@@ -2776,7 +3470,7 @@ static void insertCell(
assert( sqlite3pager_iswriteable(pPage->aData) );
if( pPage->nOverflow || sz+2>pPage->nFree ){
if( pTemp ){
- memcpy(pTemp, pCell, sz);
+ memcpy(pTemp+nSkip, pCell+nSkip, sz-nSkip);
pCell = pTemp;
}
j = pPage->nOverflow++;
@@ -2801,7 +3495,7 @@ static void insertCell(
assert( end <= get2byte(&data[hdr+5]) );
pPage->nCell++;
pPage->nFree -= 2;
- memcpy(&data[idx], pCell, sz);
+ memcpy(&data[idx+nSkip], pCell+nSkip, sz-nSkip);
for(j=end-2, ptr=&data[j]; j>ins; j-=2, ptr-=2){
ptr[0] = ptr[-2];
ptr[1] = ptr[-1];
@@ -2810,7 +3504,23 @@ static void insertCell(
put2byte(&data[hdr+3], pPage->nCell);
pPage->idxShift = 1;
pageIntegrity(pPage);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( pPage->pBt->autoVacuum ){
+ /* The cell may contain a pointer to an overflow page. If so, write
+ ** the entry for the overflow page into the pointer map.
+ */
+ CellInfo info;
+ parseCellPtr(pPage, pCell, &info);
+ if( (info.nData+(pPage->intKey?0:info.nKey))>info.nLocal ){
+ Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]);
+ int rc = ptrmapPut(pPage->pBt, pgnoOvfl, PTRMAP_OVERFLOW1, pPage->pgno);
+ if( rc!=SQLITE_OK ) return rc;
+ }
+ }
+#endif
}
+
+ return SQLITE_OK;
}
/*
@@ -2856,14 +3566,6 @@ static void assemblePage(
}
/*
-** GCC does not define the offsetof() macro so we'll have to do it
-** ourselves.
-*/
-#ifndef offsetof
-#define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD))
-#endif
-
-/*
** The following parameters determine how many adjacent pages get involved
** in a balancing operation. NN is the number of neighbors on either side
** of the page that participate in the balancing operation. NB is the
@@ -2879,7 +3581,110 @@ static void assemblePage(
#define NB (NN*2+1) /* Total pages involved in the balance */
/* Forward reference */
-static int balance(MemPage*);
+static int balance(MemPage*, int);
+
+#ifndef SQLITE_OMIT_QUICKBALANCE
+/*
+** This version of balance() handles the common special case where
+** a new entry is being inserted on the extreme right-end of the
+** tree, in other words, when the new entry will become the largest
+** entry in the tree.
+**
+** Instead of trying balance the 3 right-most leaf pages, just add
+** a new page to the right-hand side and put the one new entry in
+** that page. This leaves the right side of the tree somewhat
+** unbalanced. But odds are that we will be inserting new entries
+** at the end soon afterwards so the nearly empty page will quickly
+** fill up. On average.
+**
+** pPage is the leaf page which is the right-most page in the tree.
+** pParent is its parent. pPage must have a single overflow entry
+** which is also the right-most entry on the page.
+*/
+static int balance_quick(MemPage *pPage, MemPage *pParent){
+ int rc;
+ MemPage *pNew;
+ Pgno pgnoNew;
+ u8 *pCell;
+ int szCell;
+ CellInfo info;
+ Btree *pBt = pPage->pBt;
+ int parentIdx = pParent->nCell; /* pParent new divider cell index */
+ int parentSize; /* Size of new divider cell */
+ u8 parentCell[64]; /* Space for the new divider cell */
+
+ /* Allocate a new page. Insert the overflow cell from pPage
+ ** into it. Then remove the overflow cell from pPage.
+ */
+ rc = allocatePage(pBt, &pNew, &pgnoNew, 0, 0);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ pCell = pPage->aOvfl[0].pCell;
+ szCell = cellSizePtr(pPage, pCell);
+ zeroPage(pNew, pPage->aData[0]);
+ assemblePage(pNew, 1, &pCell, &szCell);
+ pPage->nOverflow = 0;
+
+ /* Set the parent of the newly allocated page to pParent. */
+ pNew->pParent = pParent;
+ sqlite3pager_ref(pParent->aData);
+
+ /* pPage is currently the right-child of pParent. Change this
+ ** so that the right-child is the new page allocated above and
+ ** pPage is the next-to-right child.
+ */
+ assert( pPage->nCell>0 );
+ parseCellPtr(pPage, findCell(pPage, pPage->nCell-1), &info);
+ rc = fillInCell(pParent, parentCell, 0, info.nKey, 0, 0, &parentSize);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ assert( parentSize<64 );
+ rc = insertCell(pParent, parentIdx, parentCell, parentSize, 0, 4);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ put4byte(findOverflowCell(pParent,parentIdx), pPage->pgno);
+ put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew);
+
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ /* If this is an auto-vacuum database, update the pointer map
+ ** with entries for the new page, and any pointer from the
+ ** cell on the page to an overflow page.
+ */
+ if( pBt->autoVacuum ){
+ rc = ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ rc = ptrmapPutOvfl(pNew, 0);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ }
+#endif
+
+ /* Release the reference to the new page and balance the parent page,
+ ** in case the divider cell inserted caused it to become overfull.
+ */
+ releasePage(pNew);
+ return balance(pParent, 0);
+}
+#endif /* SQLITE_OMIT_QUICKBALANCE */
+
+/*
+** The ISAUTOVACUUM macro is used within balance_nonroot() to determine
+** if the database supports auto-vacuum or not. Because it is used
+** within an expression that is an argument to another macro
+** (sqliteMallocRaw), it is not possible to use conditional compilation.
+** So, this macro is defined instead.
+*/
+#ifndef SQLITE_OMIT_AUTOVACUUM
+#define ISAUTOVACUUM (pBt->autoVacuum)
+#else
+#define ISAUTOVACUUM 0
+#endif
/*
** This routine redistributes Cells on pPage and up to NN*2 siblings
@@ -2941,6 +3746,9 @@ static int balance_nonroot(MemPage *pPage){
int *szCell; /* Local size of all cells in apCell[] */
u8 *aCopy[NB]; /* Space for holding data of apCopy[] */
u8 *aSpace; /* Space to hold copies of dividers cells */
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ u8 *aFrom = 0;
+#endif
/*
** Find the parent page.
@@ -2953,6 +3761,31 @@ static int balance_nonroot(MemPage *pPage){
assert( pParent );
TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno));
+#ifndef SQLITE_OMIT_QUICKBALANCE
+ /*
+ ** A special case: If a new entry has just been inserted into a
+ ** table (that is, a btree with integer keys and all data at the leaves)
+ ** an the new entry is the right-most entry in the tree (it has the
+ ** largest key) then use the special balance_quick() routine for
+ ** balancing. balance_quick() is much faster and results in a tighter
+ ** packing of data in the common case.
+ */
+ if( pPage->leaf &&
+ pPage->intKey &&
+ pPage->leafData &&
+ pPage->nOverflow==1 &&
+ pPage->aOvfl[0].idx==pPage->nCell &&
+ pPage->pParent->pgno!=1 &&
+ get4byte(&pParent->aData[pParent->hdrOffset+8])==pPage->pgno
+ ){
+ /*
+ ** TODO: Check the siblings to the left of pPage. It may be that
+ ** they are not full and no new page is required.
+ */
+ return balance_quick(pPage, pParent);
+ }
+#endif
+
/*
** Allocate space for memory structures
*/
@@ -2960,7 +3793,8 @@ static int balance_nonroot(MemPage *pPage){
apCell = sqliteMallocRaw(
(mxCellPerPage+2)*NB*(sizeof(u8*)+sizeof(int))
+ sizeof(MemPage)*NB
- + pBt->pageSize*(5+NB)
+ + pBt->psAligned*(5+NB)
+ + (ISAUTOVACUUM ? (mxCellPerPage+2)*NN*2 : 0)
);
if( apCell==0 ){
return SQLITE_NOMEM;
@@ -2968,9 +3802,14 @@ static int balance_nonroot(MemPage *pPage){
szCell = (int*)&apCell[(mxCellPerPage+2)*NB];
aCopy[0] = (u8*)&szCell[(mxCellPerPage+2)*NB];
for(i=1; i<NB; i++){
- aCopy[i] = &aCopy[i-1][pBt->pageSize+sizeof(MemPage)];
+ aCopy[i] = &aCopy[i-1][pBt->psAligned+sizeof(MemPage)];
}
- aSpace = &aCopy[NB-1][pBt->pageSize+sizeof(MemPage)];
+ aSpace = &aCopy[NB-1][pBt->psAligned+sizeof(MemPage)];
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( pBt->autoVacuum ){
+ aFrom = &aSpace[5*pBt->psAligned];
+ }
+#endif
/*
** Find the cell in the parent page whose left child points back
@@ -3041,10 +3880,10 @@ static int balance_nonroot(MemPage *pPage){
** process of being overwritten.
*/
for(i=0; i<nOld; i++){
- MemPage *p = apCopy[i] = (MemPage*)&aCopy[i][pBt->pageSize];
- p->aData = &((u8*)p)[-pBt->pageSize];
- memcpy(p->aData, apOld[i]->aData, pBt->pageSize + sizeof(MemPage));
- p->aData = &((u8*)p)[-pBt->pageSize];
+ MemPage *p = apCopy[i] = (MemPage*)&aCopy[i][pBt->psAligned];
+ p->aData = &((u8*)p)[-pBt->psAligned];
+ memcpy(p->aData, apOld[i]->aData, pBt->psAligned + sizeof(MemPage));
+ p->aData = &((u8*)p)[-pBt->psAligned];
}
/*
@@ -3072,6 +3911,18 @@ static int balance_nonroot(MemPage *pPage){
for(j=0; j<limit; j++){
apCell[nCell] = findOverflowCell(pOld, j);
szCell[nCell] = cellSizePtr(pOld, apCell[nCell]);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( pBt->autoVacuum ){
+ int a;
+ aFrom[nCell] = i;
+ for(a=0; a<pOld->nOverflow; a++){
+ if( pOld->aOvfl[a].pCell==apCell[nCell] ){
+ aFrom[nCell] = 0xFF;
+ break;
+ }
+ }
+ }
+#endif
nCell++;
}
if( i<nOld-1 ){
@@ -3088,9 +3939,14 @@ static int balance_nonroot(MemPage *pPage){
szCell[nCell] = sz;
pTemp = &aSpace[iSpace];
iSpace += sz;
- assert( iSpace<=pBt->pageSize*5 );
+ assert( iSpace<=pBt->psAligned*5 );
memcpy(pTemp, apDiv[i], sz);
apCell[nCell] = pTemp+leafCorrection;
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( pBt->autoVacuum ){
+ aFrom[nCell] = 0xFF;
+ }
+#endif
dropCell(pParent, nxDiv, sz);
szCell[nCell] -= leafCorrection;
assert( get4byte(pTemp)==pgnoOld[i] );
@@ -3179,9 +4035,10 @@ static int balance_nonroot(MemPage *pPage){
pNew = apNew[i] = apOld[i];
pgnoNew[i] = pgnoOld[i];
apOld[i] = 0;
- sqlite3pager_write(pNew->aData);
+ rc = sqlite3pager_write(pNew->aData);
+ if( rc ) goto balance_cleanup;
}else{
- rc = allocatePage(pBt, &pNew, &pgnoNew[i], pgnoNew[i-1]);
+ rc = allocatePage(pBt, &pNew, &pgnoNew[i], pgnoNew[i-1], 0);
if( rc ) goto balance_cleanup;
apNew[i] = pNew;
}
@@ -3243,19 +4100,42 @@ static int balance_nonroot(MemPage *pPage){
nNew>=4 ? pgnoNew[3] : 0, nNew>=4 ? szNew[3] : 0,
nNew>=5 ? pgnoNew[4] : 0, nNew>=5 ? szNew[4] : 0));
-
/*
** Evenly distribute the data in apCell[] across the new pages.
** Insert divider cells into pParent as necessary.
*/
j = 0;
for(i=0; i<nNew; i++){
+ /* Assemble the new sibling page. */
MemPage *pNew = apNew[i];
assert( pNew->pgno==pgnoNew[i] );
assemblePage(pNew, cntNew[i]-j, &apCell[j], &szCell[j]);
- j = cntNew[i];
assert( pNew->nCell>0 );
assert( pNew->nOverflow==0 );
+
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ /* If this is an auto-vacuum database, update the pointer map entries
+ ** that point to the siblings that were rearranged. These can be: left
+ ** children of cells, the right-child of the page, or overflow pages
+ ** pointed to by cells.
+ */
+ if( pBt->autoVacuum ){
+ for(k=j; k<cntNew[i]; k++){
+ if( aFrom[k]==0xFF || apCopy[aFrom[k]]->pgno!=pNew->pgno ){
+ rc = ptrmapPutOvfl(pNew, k-j);
+ if( rc!=SQLITE_OK ){
+ goto balance_cleanup;
+ }
+ }
+ }
+ }
+#endif
+
+ j = cntNew[i];
+
+ /* If the sibling page assembled above was not the right-most sibling,
+ ** insert a divider cell into the parent page.
+ */
if( i<nNew-1 && j<nCell ){
u8 *pCell;
u8 *pTemp;
@@ -3266,22 +4146,40 @@ static int balance_nonroot(MemPage *pPage){
memcpy(&pNew->aData[8], pCell, 4);
pTemp = 0;
}else if( leafData ){
+ /* If the tree is a leaf-data tree, and the siblings are leaves,
+ ** then there is no divider cell in apCell[]. Instead, the divider
+ ** cell consists of the integer key for the right-most cell of
+ ** the sibling-page assembled above only.
+ */
CellInfo info;
j--;
parseCellPtr(pNew, apCell[j], &info);
pCell = &aSpace[iSpace];
fillInCell(pParent, pCell, 0, info.nKey, 0, 0, &sz);
iSpace += sz;
- assert( iSpace<=pBt->pageSize*5 );
+ assert( iSpace<=pBt->psAligned*5 );
pTemp = 0;
}else{
pCell -= 4;
pTemp = &aSpace[iSpace];
iSpace += sz;
- assert( iSpace<=pBt->pageSize*5 );
+ assert( iSpace<=pBt->psAligned*5 );
}
- insertCell(pParent, nxDiv, pCell, sz, pTemp);
+ rc = insertCell(pParent, nxDiv, pCell, sz, pTemp, 4);
+ if( rc!=SQLITE_OK ) goto balance_cleanup;
put4byte(findOverflowCell(pParent,nxDiv), pNew->pgno);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ /* If this is an auto-vacuum database, and not a leaf-data tree,
+ ** then update the pointer map with an entry for the overflow page
+ ** that the cell just inserted points to (if any).
+ */
+ if( pBt->autoVacuum && !leafData ){
+ rc = ptrmapPutOvfl(pParent, nxDiv);
+ if( rc!=SQLITE_OK ){
+ goto balance_cleanup;
+ }
+ }
+#endif
j++;
nxDiv++;
}
@@ -3303,19 +4201,21 @@ static int balance_nonroot(MemPage *pPage){
** Reparent children of all cells.
*/
for(i=0; i<nNew; i++){
- reparentChildPages(apNew[i]);
+ rc = reparentChildPages(apNew[i]);
+ if( rc!=SQLITE_OK ) goto balance_cleanup;
}
- reparentChildPages(pParent);
+ rc = reparentChildPages(pParent);
+ if( rc!=SQLITE_OK ) goto balance_cleanup;
/*
** Balance the parent page. Note that the current page (pPage) might
- ** have been added to the freelist is it might no longer be initialized.
+ ** have been added to the freelist so it might no longer be initialized.
** But the parent page will always be initialized.
*/
assert( pParent->isInit );
/* assert( pPage->isInit ); // No! pPage might have been added to freelist */
/* pageIntegrity(pPage); // No! pPage might have been added to freelist */
- rc = balance(pParent);
+ rc = balance(pParent, 0);
/*
** Cleanup before returning.
@@ -3390,6 +4290,9 @@ static int balance_shallower(MemPage *pPage){
szCell[i] = cellSizePtr(pChild, apCell[i]);
}
assemblePage(pPage, pChild->nCell, apCell, szCell);
+ /* Copy the right-pointer of the child to the parent. */
+ put4byte(&pPage->aData[pPage->hdrOffset+8],
+ get4byte(&pChild->aData[pChild->hdrOffset+8]));
freePage(pChild);
TRACE(("BALANCE: child %d transfer to page 1\n", pChild->pgno));
}else{
@@ -3407,7 +4310,20 @@ static int balance_shallower(MemPage *pPage){
TRACE(("BALANCE: transfer child %d into root %d\n",
pChild->pgno, pPage->pgno));
}
- reparentChildPages(pPage);
+ rc = reparentChildPages(pPage);
+ assert( pPage->nOverflow==0 );
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( pBt->autoVacuum ){
+ int i;
+ for(i=0; i<pPage->nCell; i++){
+ rc = ptrmapPutOvfl(pPage, i);
+ if( rc!=SQLITE_OK ){
+ goto end_shallow_balance;
+ }
+ }
+ }
+#endif
+ if( rc!=SQLITE_OK ) goto end_shallow_balance;
releasePage(pChild);
}
end_shallow_balance:
@@ -3439,7 +4355,7 @@ static int balance_deeper(MemPage *pPage){
assert( pPage->pParent==0 );
assert( pPage->nOverflow>0 );
pBt = pPage->pBt;
- rc = allocatePage(pBt, &pChild, &pgnoChild, pPage->pgno);
+ rc = allocatePage(pBt, &pChild, &pgnoChild, pPage->pgno, 0);
if( rc ) return rc;
assert( sqlite3pager_iswriteable(pChild->aData) );
usableSize = pBt->usableSize;
@@ -3449,6 +4365,7 @@ static int balance_deeper(MemPage *pPage){
cdata = pChild->aData;
memcpy(cdata, &data[hdr], pPage->cellOffset+2*pPage->nCell-hdr);
memcpy(&cdata[brk], &data[brk], usableSize-brk);
+ assert( pChild->isInit==0 );
rc = initPage(pChild, pPage);
if( rc ) return rc;
memcpy(pChild->aOvfl, pPage->aOvfl, pPage->nOverflow*sizeof(pPage->aOvfl[0]));
@@ -3460,6 +4377,19 @@ static int balance_deeper(MemPage *pPage){
zeroPage(pPage, pChild->aData[0] & ~PTF_LEAF);
put4byte(&pPage->aData[pPage->hdrOffset+8], pgnoChild);
TRACE(("BALANCE: copy root %d into %d\n", pPage->pgno, pChild->pgno));
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( pBt->autoVacuum ){
+ int i;
+ rc = ptrmapPut(pBt, pChild->pgno, PTRMAP_BTREE, pPage->pgno);
+ if( rc ) return rc;
+ for(i=0; i<pChild->nCell; i++){
+ rc = ptrmapPutOvfl(pChild, i);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ }
+ }
+#endif
rc = balance_nonroot(pChild);
releasePage(pChild);
return rc;
@@ -3469,17 +4399,18 @@ static int balance_deeper(MemPage *pPage){
** Decide if the page pPage needs to be balanced. If balancing is
** required, call the appropriate balancing routine.
*/
-static int balance(MemPage *pPage){
+static int balance(MemPage *pPage, int insert){
int rc = SQLITE_OK;
if( pPage->pParent==0 ){
if( pPage->nOverflow>0 ){
rc = balance_deeper(pPage);
}
- if( pPage->nCell==0 ){
+ if( rc==SQLITE_OK && pPage->nCell==0 ){
rc = balance_shallower(pPage);
}
}else{
- if( pPage->nOverflow>0 || pPage->nFree>pPage->pBt->usableSize*2/3 ){
+ if( pPage->nOverflow>0 ||
+ (!insert && pPage->nFree>pPage->pBt->usableSize*2/3) ){
rc = balance_nonroot(pPage);
}
}
@@ -3535,9 +4466,6 @@ int sqlite3BtreeInsert(
unsigned char *oldCell;
unsigned char *newCell = 0;
- if( pCur->status ){
- return pCur->status; /* A rollback destroyed this cursor */
- }
if( pBt->inTrans!=TRANS_WRITE ){
/* Must start a transaction before doing an insert */
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
@@ -3584,11 +4512,14 @@ int sqlite3BtreeInsert(
}else{
assert( pPage->leaf );
}
- insertCell(pPage, pCur->idx, newCell, szNew, 0);
- rc = balance(pPage);
+ rc = insertCell(pPage, pCur->idx, newCell, szNew, 0, 0);
+ if( rc!=SQLITE_OK ) goto end_insert;
+ rc = balance(pPage, 1);
/* sqlite3BtreePageDump(pCur->pBt, pCur->pgnoRoot, 1); */
/* fflush(stdout); */
- moveToRoot(pCur);
+ if( rc==SQLITE_OK ){
+ moveToRoot(pCur);
+ }
end_insert:
sqliteFree(newCell);
return rc;
@@ -3606,9 +4537,6 @@ int sqlite3BtreeDelete(BtCursor *pCur){
Btree *pBt = pCur->pBt;
assert( pPage->isInit );
- if( pCur->status ){
- return pCur->status; /* A rollback destroyed this cursor */
- }
if( pBt->inTrans!=TRANS_WRITE ){
/* Must start a transaction before doing a delete */
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
@@ -3625,11 +4553,18 @@ int sqlite3BtreeDelete(BtCursor *pCur){
}
rc = sqlite3pager_write(pPage->aData);
if( rc ) return rc;
+
+ /* Locate the cell within it's page and leave pCell pointing to the
+ ** data. The clearCell() call frees any overflow pages associated with the
+ ** cell. The cell itself is still intact.
+ */
pCell = findCell(pPage, pCur->idx);
if( !pPage->leaf ){
pgnoChild = get4byte(pCell);
}
- clearCell(pPage, pCell);
+ rc = clearCell(pPage, pCell);
+ if( rc ) return rc;
+
if( !pPage->leaf ){
/*
** The entry we are about to delete is not a leaf so if we do not
@@ -3662,19 +4597,20 @@ int sqlite3BtreeDelete(BtCursor *pCur){
assert( MX_CELL_SIZE(pBt)>=szNext+4 );
tempCell = sqliteMallocRaw( MX_CELL_SIZE(pBt) );
if( tempCell==0 ) return SQLITE_NOMEM;
- insertCell(pPage, pCur->idx, pNext-4, szNext+4, tempCell);
+ rc = insertCell(pPage, pCur->idx, pNext-4, szNext+4, tempCell, 0);
+ if( rc!=SQLITE_OK ) return rc;
put4byte(findOverflowCell(pPage, pCur->idx), pgnoChild);
- rc = balance(pPage);
+ rc = balance(pPage, 0);
sqliteFree(tempCell);
if( rc ) return rc;
dropCell(leafCur.pPage, leafCur.idx, szNext);
- rc = balance(leafCur.pPage);
+ rc = balance(leafCur.pPage, 0);
releaseTempCursor(&leafCur);
}else{
TRACE(("DELETE: table=%d delete from leaf %d\n",
pCur->pgnoRoot, pPage->pgno));
dropCell(pPage, pCur->idx, cellSizePtr(pPage, pCell));
- rc = balance(pPage);
+ rc = balance(pPage, 0);
}
moveToRoot(pCur);
return rc;
@@ -3699,11 +4635,102 @@ int sqlite3BtreeCreateTable(Btree *pBt, int *piTable, int flags){
/* Must start a transaction first */
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
}
- if( pBt->readOnly ){
- return SQLITE_READONLY;
+ assert( !pBt->readOnly );
+
+ /* It is illegal to create a table if any cursors are open on the
+ ** database. This is because in auto-vacuum mode the backend may
+ ** need to move a database page to make room for the new root-page.
+ ** If an open cursor was using the page a problem would occur.
+ */
+ if( pBt->pCursor ){
+ return SQLITE_LOCKED;
}
- rc = allocatePage(pBt, &pRoot, &pgnoRoot, 1);
+
+#ifdef SQLITE_OMIT_AUTOVACUUM
+ rc = allocatePage(pBt, &pRoot, &pgnoRoot, 1, 0);
if( rc ) return rc;
+#else
+ if( pBt->autoVacuum ){
+ Pgno pgnoMove; /* Move a page here to make room for the root-page */
+ MemPage *pPageMove; /* The page to move to. */
+
+ /* Read the value of meta[3] from the database to determine where the
+ ** root page of the new table should go. meta[3] is the largest root-page
+ ** created so far, so the new root-page is (meta[3]+1).
+ */
+ rc = sqlite3BtreeGetMeta(pBt, 4, &pgnoRoot);
+ if( rc!=SQLITE_OK ) return rc;
+ pgnoRoot++;
+
+ /* The new root-page may not be allocated on a pointer-map page, or the
+ ** PENDING_BYTE page.
+ */
+ if( pgnoRoot==PTRMAP_PAGENO(pBt->usableSize, pgnoRoot) ||
+ pgnoRoot==PENDING_BYTE_PAGE(pBt) ){
+ pgnoRoot++;
+ }
+ assert( pgnoRoot>=3 );
+
+ /* Allocate a page. The page that currently resides at pgnoRoot will
+ ** be moved to the allocated page (unless the allocated page happens
+ ** to reside at pgnoRoot).
+ */
+ rc = allocatePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, 1);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+
+ if( pgnoMove!=pgnoRoot ){
+ u8 eType;
+ Pgno iPtrPage;
+
+ releasePage(pPageMove);
+ rc = getPage(pBt, pgnoRoot, &pRoot);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage);
+ assert( eType!=PTRMAP_ROOTPAGE );
+ assert( eType!=PTRMAP_FREEPAGE );
+ if( rc!=SQLITE_OK ){
+ releasePage(pRoot);
+ return rc;
+ }
+ rc = relocatePage(pBt, pRoot, eType, iPtrPage, pgnoMove);
+ releasePage(pRoot);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ rc = getPage(pBt, pgnoRoot, &pRoot);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ rc = sqlite3pager_write(pRoot->aData);
+ if( rc!=SQLITE_OK ){
+ releasePage(pRoot);
+ return rc;
+ }
+ }else{
+ pRoot = pPageMove;
+ }
+
+ /* Update the pointer-map and meta-data with the new root-page number. */
+ rc = ptrmapPut(pBt, pgnoRoot, PTRMAP_ROOTPAGE, 0);
+ if( rc ){
+ releasePage(pRoot);
+ return rc;
+ }
+ rc = sqlite3BtreeUpdateMeta(pBt, 4, pgnoRoot);
+ if( rc ){
+ releasePage(pRoot);
+ return rc;
+ }
+
+ }else{
+ rc = allocatePage(pBt, &pRoot, &pgnoRoot, 1, 0);
+ if( rc ) return rc;
+ }
+#endif
assert( sqlite3pager_iswriteable(pRoot->aData) );
zeroPage(pRoot, flags | PTF_LEAF);
sqlite3pager_unref(pRoot->aData);
@@ -3726,6 +4753,10 @@ static int clearDatabasePage(
unsigned char *pCell;
int i;
+ if( pgno>sqlite3pager_pagecount(pBt->pPager) ){
+ return SQLITE_CORRUPT;
+ }
+
rc = getAndInitPage(pBt, pgno, &pPage, pParent);
if( rc ) return rc;
rc = sqlite3pager_write(pPage->aData);
@@ -3787,29 +4818,119 @@ int sqlite3BtreeClearTable(Btree *pBt, int iTable){
**
** This routine will fail with SQLITE_LOCKED if there are any open
** cursors on the table.
+**
+** If AUTOVACUUM is enabled and the page at iTable is not the last
+** root page in the database file, then the last root page
+** in the database file is moved into the slot formerly occupied by
+** iTable and that last slot formerly occupied by the last root page
+** is added to the freelist instead of iTable. In this say, all
+** root pages are kept at the beginning of the database file, which
+** is necessary for AUTOVACUUM to work right. *piMoved is set to the
+** page number that used to be the last root page in the file before
+** the move. If no page gets moved, *piMoved is set to 0.
+** The last root page is recorded in meta[3] and the value of
+** meta[3] is updated by this procedure.
*/
-int sqlite3BtreeDropTable(Btree *pBt, int iTable){
+int sqlite3BtreeDropTable(Btree *pBt, int iTable, int *piMoved){
int rc;
- MemPage *pPage;
- BtCursor *pCur;
+ MemPage *pPage = 0;
+
if( pBt->inTrans!=TRANS_WRITE ){
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
}
- for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
- if( pCur->pgnoRoot==(Pgno)iTable ){
- return SQLITE_LOCKED; /* Cannot drop a table that has a cursor */
- }
+
+ /* It is illegal to drop a table if any cursors are open on the
+ ** database. This is because in auto-vacuum mode the backend may
+ ** need to move another root-page to fill a gap left by the deleted
+ ** root page. If an open cursor was using this page a problem would
+ ** occur.
+ */
+ if( pBt->pCursor ){
+ return SQLITE_LOCKED;
}
+
rc = getPage(pBt, (Pgno)iTable, &pPage);
if( rc ) return rc;
rc = sqlite3BtreeClearTable(pBt, iTable);
if( rc ) return rc;
+
+ *piMoved = 0;
+
if( iTable>1 ){
+#ifdef SQLITE_OMIT_AUTOVACUUM
rc = freePage(pPage);
+ releasePage(pPage);
+#else
+ if( pBt->autoVacuum ){
+ Pgno maxRootPgno;
+ rc = sqlite3BtreeGetMeta(pBt, 4, &maxRootPgno);
+ if( rc!=SQLITE_OK ){
+ releasePage(pPage);
+ return rc;
+ }
+
+ if( iTable==maxRootPgno ){
+ /* If the table being dropped is the table with the largest root-page
+ ** number in the database, put the root page on the free list.
+ */
+ rc = freePage(pPage);
+ releasePage(pPage);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ }else{
+ /* The table being dropped does not have the largest root-page
+ ** number in the database. So move the page that does into the
+ ** gap left by the deleted root-page.
+ */
+ MemPage *pMove;
+ releasePage(pPage);
+ rc = getPage(pBt, maxRootPgno, &pMove);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ rc = relocatePage(pBt, pMove, PTRMAP_ROOTPAGE, 0, iTable);
+ releasePage(pMove);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ rc = getPage(pBt, maxRootPgno, &pMove);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ rc = freePage(pMove);
+ releasePage(pMove);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ *piMoved = maxRootPgno;
+ }
+
+ /* Set the new 'max-root-page' value in the database header. This
+ ** is the old value less one, less one more if that happens to
+ ** be a root-page number, less one again if that is the
+ ** PENDING_BYTE_PAGE.
+ */
+ maxRootPgno--;
+ if( maxRootPgno==PENDING_BYTE_PAGE(pBt) ){
+ maxRootPgno--;
+ }
+ if( maxRootPgno==PTRMAP_PAGENO(pBt->usableSize, maxRootPgno) ){
+ maxRootPgno--;
+ }
+ assert( maxRootPgno!=PENDING_BYTE_PAGE(pBt) );
+
+ rc = sqlite3BtreeUpdateMeta(pBt, 4, maxRootPgno);
+ }else{
+ rc = freePage(pPage);
+ releasePage(pPage);
+ }
+#endif
}else{
+ /* If sqlite3BtreeDropTable was called on page 1. */
zeroPage(pPage, PTF_INTKEY|PTF_LEAF );
+ releasePage(pPage);
}
- releasePage(pPage);
return rc;
}
@@ -3834,9 +4955,12 @@ int sqlite3BtreeGetMeta(Btree *pBt, int idx, u32 *pMeta){
*pMeta = get4byte(&pP1[36 + idx*4]);
sqlite3pager_unref(pP1);
- /* The current implementation is unable to handle writes to an autovacuumed
- ** database. So make such a database readonly. */
+ /* If autovacuumed is disabled in this build but we are trying to
+ ** access an autovacuumed database, then make the database readonly.
+ */
+#ifdef SQLITE_OMIT_AUTOVACUUM
if( idx==4 && *pMeta>0 ) pBt->readOnly = 1;
+#endif
return SQLITE_OK;
}
@@ -3869,12 +4993,12 @@ int sqlite3BtreeFlags(BtCursor *pCur){
return pPage ? pPage->aData[pPage->hdrOffset] : 0;
}
+#ifdef SQLITE_DEBUG
/*
** Print a disassembly of the given page on standard output. This routine
** is used for debugging and testing only.
*/
-#ifdef SQLITE_TEST
-int sqlite3BtreePageDump(Btree *pBt, int pgno, int recursive){
+static int btreePageDump(Btree *pBt, int pgno, int recursive, MemPage *pParent){
int rc;
MemPage *pPage;
int i, j, c;
@@ -3890,7 +5014,7 @@ int sqlite3BtreePageDump(Btree *pBt, int pgno, int recursive){
rc = getPage(pBt, (Pgno)pgno, &pPage);
isInit = pPage->isInit;
if( pPage->isInit==0 ){
- initPage(pPage, 0);
+ initPage(pPage, pParent);
}
if( rc ){
return rc;
@@ -3960,16 +5084,19 @@ int sqlite3BtreePageDump(Btree *pBt, int pgno, int recursive){
if( recursive && !pPage->leaf ){
for(i=0; i<nCell; i++){
unsigned char *pCell = findCell(pPage, i);
- sqlite3BtreePageDump(pBt, get4byte(pCell), 1);
+ btreePageDump(pBt, get4byte(pCell), 1, pPage);
idx = get2byte(pCell);
}
- sqlite3BtreePageDump(pBt, get4byte(&data[hdr+8]), 1);
+ btreePageDump(pBt, get4byte(&data[hdr+8]), 1, pPage);
}
pPage->isInit = isInit;
sqlite3pager_unref(data);
fflush(stdout);
return SQLITE_OK;
}
+int sqlite3BtreePageDump(Btree *pBt, int pgno, int recursive){
+ return btreePageDump(pBt, pgno, recursive, 0);
+}
#endif
#ifdef SQLITE_TEST
@@ -4058,6 +5185,7 @@ struct IntegrityCk {
char *zErrMsg; /* An error message. NULL of no errors seen. */
};
+#ifndef SQLITE_OMIT_INTEGRITY_CHECK
/*
** Append a message to the error message string.
*/
@@ -4083,7 +5211,9 @@ static void checkAppendMsg(
}
sqliteFree(zMsg2);
}
+#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
+#ifndef SQLITE_OMIT_INTEGRITY_CHECK
/*
** Add 1 to the reference count for page iPage. If this is the second
** reference to the page, add an error message to pCheck->zErrMsg.
@@ -4105,6 +5235,37 @@ static int checkRef(IntegrityCk *pCheck, int iPage, char *zContext){
return (pCheck->anRef[iPage]++)>1;
}
+#ifndef SQLITE_OMIT_AUTOVACUUM
+/*
+** Check that the entry in the pointer-map for page iChild maps to
+** page iParent, pointer type ptrType. If not, append an error message
+** to pCheck.
+*/
+static void checkPtrmap(
+ IntegrityCk *pCheck, /* Integrity check context */
+ Pgno iChild, /* Child page number */
+ u8 eType, /* Expected pointer map type */
+ Pgno iParent, /* Expected pointer map parent page number */
+ char *zContext /* Context description (used for error msg) */
+){
+ int rc;
+ u8 ePtrmapType;
+ Pgno iPtrmapParent;
+
+ rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent);
+ if( rc!=SQLITE_OK ){
+ checkAppendMsg(pCheck, zContext, "Failed to read ptrmap key=%d", iChild);
+ return;
+ }
+
+ if( ePtrmapType!=eType || iPtrmapParent!=iParent ){
+ checkAppendMsg(pCheck, zContext,
+ "Bad ptr map entry key=%d expected=(%d,%d) got=(%d,%d)",
+ iChild, eType, iParent, ePtrmapType, iPtrmapParent);
+ }
+}
+#endif
+
/*
** Check the integrity of the freelist or of an overflow page list.
** Verify that the number of pages on the list is N.
@@ -4134,22 +5295,47 @@ static void checkList(
}
if( isFreeList ){
int n = get4byte(&pOvfl[4]);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( pCheck->pBt->autoVacuum ){
+ checkPtrmap(pCheck, iPage, PTRMAP_FREEPAGE, 0, zContext);
+ }
+#endif
if( n>pCheck->pBt->usableSize/4-8 ){
checkAppendMsg(pCheck, zContext,
"freelist leaf count too big on page %d", iPage);
N--;
}else{
for(i=0; i<n; i++){
- checkRef(pCheck, get4byte(&pOvfl[8+i*4]), zContext);
+ Pgno iFreePage = get4byte(&pOvfl[8+i*4]);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( pCheck->pBt->autoVacuum ){
+ checkPtrmap(pCheck, iFreePage, PTRMAP_FREEPAGE, 0, zContext);
+ }
+#endif
+ checkRef(pCheck, iFreePage, zContext);
}
N -= n;
}
}
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ else{
+ /* If this database supports auto-vacuum and iPage is not the last
+ ** page in this overflow list, check that the pointer-map entry for
+ ** the following page matches iPage.
+ */
+ if( pCheck->pBt->autoVacuum && N>0 ){
+ i = get4byte(pOvfl);
+ checkPtrmap(pCheck, i, PTRMAP_OVERFLOW2, iPage, zContext);
+ }
+ }
+#endif
iPage = get4byte(pOvfl);
sqlite3pager_unref(pOvfl);
}
}
+#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
+#ifndef SQLITE_OMIT_INTEGRITY_CHECK
/*
** Do various sanity checks on a single page of a tree. Return
** the tree depth. Root pages return 0. Parents of root pages
@@ -4189,6 +5375,8 @@ static int checkTreePage(
char zContext[100];
char *hit;
+ sprintf(zContext, "Page %d: ", iPage);
+
/* Check that the page exists
*/
cur.pBt = pBt = pCheck->pBt;
@@ -4225,13 +5413,24 @@ static int checkTreePage(
if( !pPage->intKey ) sz += info.nKey;
if( sz>info.nLocal ){
int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4);
- checkList(pCheck, 0, get4byte(&pCell[info.iOverflow]),nPage,zContext);
+ Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( pBt->autoVacuum ){
+ checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage, zContext);
+ }
+#endif
+ checkList(pCheck, 0, pgnoOvfl, nPage, zContext);
}
/* Check sanity of left child page.
*/
if( !pPage->leaf ){
pgno = get4byte(pCell);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( pBt->autoVacuum ){
+ checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext);
+ }
+#endif
d2 = checkTreePage(pCheck,pgno,pPage,zContext,0,0,0,0);
if( i>0 && d2!=depth ){
checkAppendMsg(pCheck, zContext, "Child page depth differs");
@@ -4242,6 +5441,11 @@ static int checkTreePage(
if( !pPage->leaf ){
pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
sprintf(zContext, "On page %d at right child: ", iPage);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( pBt->autoVacuum ){
+ checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, 0);
+ }
+#endif
checkTreePage(pCheck, pgno, pPage, zContext,0,0,0,0);
}
@@ -4258,13 +5462,23 @@ static int checkTreePage(
int pc = get2byte(&data[cellStart+i*2]);
int size = cellSizePtr(pPage, &data[pc]);
int j;
- for(j=pc+size-1; j>=pc; j--) hit[j]++;
+ if( (pc+size-1)>=usableSize || pc<0 ){
+ checkAppendMsg(pCheck, 0,
+ "Corruption detected in cell %d on page %d",i,iPage,0);
+ }else{
+ for(j=pc+size-1; j>=pc; j--) hit[j]++;
+ }
}
for(cnt=0, i=get2byte(&data[hdr+1]); i>0 && i<usableSize && cnt<10000;
cnt++){
int size = get2byte(&data[i+2]);
int j;
- for(j=i+size-1; j>=i; j--) hit[j]++;
+ if( (i+size-1)>=usableSize || i<0 ){
+ checkAppendMsg(pCheck, 0,
+ "Corruption detected in cell %d on page %d",i,iPage,0);
+ }else{
+ for(j=i+size-1; j>=i; j--) hit[j]++;
+ }
i = get2byte(&data[i]);
}
for(i=cnt=0; i<usableSize; i++){
@@ -4287,7 +5501,9 @@ static int checkTreePage(
releasePage(pPage);
return depth+1;
}
+#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
+#ifndef SQLITE_OMIT_INTEGRITY_CHECK
/*
** This routine does a complete check of the given BTree file. aRoot[] is
** an array of pages numbers were each page number is the root page of
@@ -4315,8 +5531,13 @@ char *sqlite3BtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){
return 0;
}
sCheck.anRef = sqliteMallocRaw( (sCheck.nPage+1)*sizeof(sCheck.anRef[0]) );
+ if( !sCheck.anRef ){
+ unlockBtreeIfUnused(pBt);
+ return sqlite3MPrintf("Unable to malloc %d bytes",
+ (sCheck.nPage+1)*sizeof(sCheck.anRef[0]));
+ }
for(i=0; i<=sCheck.nPage; i++){ sCheck.anRef[i] = 0; }
- i = PENDING_BYTE/pBt->pageSize + 1;
+ i = PENDING_BYTE_PAGE(pBt);
if( i<=sCheck.nPage ){
sCheck.anRef[i] = 1;
}
@@ -4331,15 +5552,34 @@ char *sqlite3BtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){
*/
for(i=0; i<nRoot; i++){
if( aRoot[i]==0 ) continue;
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( pBt->autoVacuum && aRoot[i]>1 ){
+ checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0, 0);
+ }
+#endif
checkTreePage(&sCheck, aRoot[i], 0, "List of tree roots: ", 0,0,0,0);
}
/* Make sure every page in the file is referenced
*/
for(i=1; i<=sCheck.nPage; i++){
+#ifdef SQLITE_OMIT_AUTOVACUUM
if( sCheck.anRef[i]==0 ){
checkAppendMsg(&sCheck, 0, "Page %d is never used", i);
}
+#else
+ /* If the database supports auto-vacuum, make sure no tables contain
+ ** references to pointer-map pages.
+ */
+ if( sCheck.anRef[i]==0 &&
+ (PTRMAP_PAGENO(pBt->usableSize, i)!=i || !pBt->autoVacuum) ){
+ checkAppendMsg(&sCheck, 0, "Page %d is never used", i);
+ }
+ if( sCheck.anRef[i]!=0 &&
+ (PTRMAP_PAGENO(pBt->usableSize, i)==i && pBt->autoVacuum) ){
+ checkAppendMsg(&sCheck, 0, "Pointer map page %d is referenced", i);
+ }
+#endif
}
/* Make sure this analysis did not leave any unref() pages
@@ -4357,6 +5597,7 @@ char *sqlite3BtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){
sqliteFree(sCheck.anRef);
return sCheck.zErrMsg;
}
+#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
/*
** Return the full pathname of the underlying database file.
@@ -4384,6 +5625,7 @@ const char *sqlite3BtreeGetJournalname(Btree *pBt){
return sqlite3pager_journalname(pBt->pPager);
}
+#ifndef SQLITE_OMIT_VACUUM
/*
** Copy the complete content of pBtFrom into pBtTo. A transaction
** must be active for both files.
@@ -4425,6 +5667,7 @@ int sqlite3BtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){
}
return rc;
}
+#endif /* SQLITE_OMIT_VACUUM */
/*
** Return non-zero if a transaction is active.
@@ -4456,7 +5699,15 @@ int sqlite3BtreeIsInStmt(Btree *pBt){
*/
int sqlite3BtreeSync(Btree *pBt, const char *zMaster){
if( pBt->inTrans==TRANS_WRITE ){
- return sqlite3pager_sync(pBt->pPager, zMaster);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ Pgno nTrunc = 0;
+ if( pBt->autoVacuum ){
+ int rc = autoVacuumCommit(pBt, &nTrunc);
+ if( rc!=SQLITE_OK ) return rc;
+ }
+ return sqlite3pager_sync(pBt->pPager, zMaster, nTrunc);
+#endif
+ return sqlite3pager_sync(pBt->pPager, zMaster, 0);
}
return SQLITE_OK;
}
diff --git a/ext/pdo_sqlite/sqlite/src/btree.h b/ext/pdo_sqlite/sqlite/src/btree.h
index 48524aefc1..d4ee97ef38 100644
--- a/ext/pdo_sqlite/sqlite/src/btree.h
+++ b/ext/pdo_sqlite/sqlite/src/btree.h
@@ -24,6 +24,14 @@
#define SQLITE_N_BTREE_META 10
/*
+** If defined as non-zero, auto-vacuum is enabled by default. Otherwise
+** it must be turned on for each database using "PRAGMA auto_vacuum = 1".
+*/
+#ifndef SQLITE_DEFAULT_AUTOVACUUM
+ #define SQLITE_DEFAULT_AUTOVACUUM 0
+#endif
+
+/*
** Forward declarations of structure
*/
typedef struct Btree Btree;
@@ -38,9 +46,13 @@ int sqlite3BtreeOpen(
/* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the
** following values.
+**
+** NOTE: These values must match the corresponding PAGER_ values in
+** pager.h.
*/
#define BTREE_OMIT_JOURNAL 1 /* Do not use journal. No argument */
-#define BTREE_MEMORY 2 /* In-memory DB. No argument */
+#define BTREE_NO_READLOCK 2 /* Omit readlocks on readonly files */
+#define BTREE_MEMORY 4 /* In-memory DB. No argument */
int sqlite3BtreeClose(Btree*);
int sqlite3BtreeSetBusyHandler(Btree*,BusyHandler*);
@@ -49,6 +61,8 @@ int sqlite3BtreeSetSafetyLevel(Btree*,int);
int sqlite3BtreeSetPageSize(Btree*,int,int);
int sqlite3BtreeGetPageSize(Btree*);
int sqlite3BtreeGetReserve(Btree*);
+int sqlite3BtreeSetAutoVacuum(Btree *, int);
+int sqlite3BtreeGetAutoVacuum(Btree *);
int sqlite3BtreeBeginTrans(Btree*,int);
int sqlite3BtreeCommit(Btree*);
int sqlite3BtreeRollback(Btree*);
@@ -72,7 +86,7 @@ int sqlite3BtreeCopyFile(Btree *, Btree *);
#define BTREE_ZERODATA 2 /* Table has keys only - no data */
#define BTREE_LEAFDATA 4 /* Data stored in leaves only. Implies INTKEY */
-int sqlite3BtreeDropTable(Btree*, int);
+int sqlite3BtreeDropTable(Btree*, int, int*);
int sqlite3BtreeClearTable(Btree*, int);
int sqlite3BtreeGetMeta(Btree*, int idx, u32 *pValue);
int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
@@ -117,8 +131,12 @@ struct Pager *sqlite3BtreePager(Btree*);
#ifdef SQLITE_TEST
int sqlite3BtreeCursorInfo(BtCursor*, int*, int);
void sqlite3BtreeCursorList(Btree*);
-int sqlite3BtreePageDump(Btree*, int, int recursive);
#endif
+#ifdef SQLITE_DEBUG
+int sqlite3BtreePageDump(Btree*, int, int recursive);
+#else
+#define sqlite3BtreePageDump(X,Y,Z) SQLITE_OK
+#endif
#endif /* _BTREE_H_ */
diff --git a/ext/pdo_sqlite/sqlite/src/build.c b/ext/pdo_sqlite/sqlite/src/build.c
index 3e5e08a541..1908a47118 100644
--- a/ext/pdo_sqlite/sqlite/src/build.c
+++ b/ext/pdo_sqlite/sqlite/src/build.c
@@ -21,7 +21,6 @@
** BEGIN TRANSACTION
** COMMIT
** ROLLBACK
-** PRAGMA
**
** $Id$
*/
@@ -30,9 +29,7 @@
/*
** This routine is called when a new SQL statement is beginning to
-** be parsed. Check to see if the schema for the database needs
-** to be read from the SQLITE_MASTER and SQLITE_TEMP_MASTER tables.
-** If it does, then read it.
+** be parsed. Initialize the pParse structure as needed.
*/
void sqlite3BeginParse(Parse *pParse, int explainFlag){
pParse->explain = explainFlag;
@@ -54,6 +51,13 @@ void sqlite3FinishCoding(Parse *pParse){
Vdbe *v;
if( sqlite3_malloc_failed ) return;
+ if( pParse->nested ) return;
+ if( !pParse->pVdbe ){
+ if( pParse->rc==SQLITE_OK && pParse->nErr ){
+ pParse->rc = SQLITE_ERROR;
+ }
+ return;
+ }
/* Begin by generating some termination code at the end of the
** vdbe program
@@ -85,7 +89,7 @@ void sqlite3FinishCoding(Parse *pParse){
** statement as its P3 argument. This does not change the functionality
** of the program.
**
- ** This is used to implement sqlite3_trace() functionality.
+ ** This is used to implement sqlite3_trace().
*/
sqlite3VdbeOp3(v, OP_Noop, 0, 0, pParse->zSql, pParse->zTail-pParse->zSql);
}
@@ -97,8 +101,8 @@ void sqlite3FinishCoding(Parse *pParse){
FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0;
sqlite3VdbeTrace(v, trace);
sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem+3,
- pParse->nTab+3, pParse->explain);
- pParse->rc = pParse->nErr ? SQLITE_ERROR : SQLITE_DONE;
+ pParse->nTab+3, pParse->nMaxDepth+1, pParse->explain);
+ pParse->rc = SQLITE_DONE;
pParse->colNamesSet = 0;
}else if( pParse->rc==SQLITE_OK ){
pParse->rc = SQLITE_ERROR;
@@ -106,13 +110,48 @@ void sqlite3FinishCoding(Parse *pParse){
pParse->nTab = 0;
pParse->nMem = 0;
pParse->nSet = 0;
- pParse->nAgg = 0;
pParse->nVar = 0;
pParse->cookieMask = 0;
pParse->cookieGoto = 0;
}
/*
+** Run the parser and code generator recursively in order to generate
+** code for the SQL statement given onto the end of the pParse context
+** currently under construction. When the parser is run recursively
+** this way, the final OP_Halt is not appended and other initialization
+** and finalization steps are omitted because those are handling by the
+** outermost parser.
+**
+** Not everything is nestable. This facility is designed to permit
+** INSERT, UPDATE, and DELETE operations against SQLITE_MASTER. Use
+** care if you decide to try to use this routine for some other purposes.
+*/
+void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
+ va_list ap;
+ char *zSql;
+ int rc;
+# define SAVE_SZ (sizeof(Parse) - offsetof(Parse,nVar))
+ char saveBuf[SAVE_SZ];
+
+ if( pParse->nErr ) return;
+ assert( pParse->nested<10 ); /* Nesting should only be of limited depth */
+ va_start(ap, zFormat);
+ zSql = sqlite3VMPrintf(zFormat, ap);
+ va_end(ap);
+ if( zSql==0 ){
+ return; /* A malloc must have failed */
+ }
+ pParse->nested++;
+ memcpy(saveBuf, &pParse->nVar, SAVE_SZ);
+ memset(&pParse->nVar, 0, SAVE_SZ);
+ rc = sqlite3RunParser(pParse, zSql, 0);
+ sqliteFree(zSql);
+ memcpy(&pParse->nVar, saveBuf, SAVE_SZ);
+ pParse->nested--;
+}
+
+/*
** Locate the in-memory structure that describes a particular database
** table given the name of that table and (optionally) the name of the
** database containing the table. Return NULL if not found.
@@ -279,8 +318,7 @@ void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){
sqlite3HashClear(&pDb->aFKey);
sqlite3HashClear(&pDb->idxHash);
for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
- Trigger *pTrigger = sqliteHashData(pElem);
- sqlite3DeleteTrigger(pTrigger);
+ sqlite3DeleteTrigger((Trigger*)sqliteHashData(pElem));
}
sqlite3HashClear(&temp2);
sqlite3HashInit(&pDb->tblHash, SQLITE_HASH_STRING, 0);
@@ -289,6 +327,7 @@ void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){
sqlite3DeleteTable(db, pTab);
}
sqlite3HashClear(&temp1);
+ pDb->pSeqTab = 0;
DbClearProperty(db, i, DB_SchemaLoaded);
if( iDb>0 ) return;
}
@@ -356,7 +395,7 @@ static void sqliteResetColumnNames(Table *pTable){
assert( pTable!=0 );
for(i=0, pCol=pTable->aCol; i<pTable->nCol; i++, pCol++){
sqliteFree(pCol->zName);
- sqliteFree(pCol->zDflt);
+ sqlite3ExprDelete(pCol->pDflt);
sqliteFree(pCol->zType);
}
sqliteFree(pTable->aCol);
@@ -393,6 +432,7 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
sqliteDeleteIndex(db, pIndex);
}
+#ifndef SQLITE_OMIT_FOREIGN_KEY
/* Delete all foreign keys associated with this table. The keys
** should have already been unlinked from the db->aFKey hash table
*/
@@ -403,6 +443,7 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey );
sqliteFree(pFKey);
}
+#endif
/* Delete the Table structure itself.
*/
@@ -428,6 +469,7 @@ void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){
pDb = &db->aDb[iDb];
p = sqlite3HashInsert(&pDb->tblHash, zTabName, strlen(zTabName)+1, 0);
if( p ){
+#ifndef SQLITE_OMIT_FOREIGN_KEY
for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){
int nTo = strlen(pF1->zTo) + 1;
pF2 = sqlite3HashFind(&pDb->aFKey, pF1->zTo, nTo);
@@ -440,6 +482,7 @@ void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){
}
}
}
+#endif
sqlite3DeleteTable(db, p);
}
db->flags |= SQLITE_InternChanges;
@@ -482,16 +525,23 @@ void sqlite3OpenMasterTable(Vdbe *v, int iDb){
** index of the named database in db->aDb[], or -1 if the named db
** does not exist.
*/
-int findDb(sqlite3 *db, Token *pName){
- int i;
- Db *pDb;
- for(pDb=db->aDb, i=0; i<db->nDb; i++, pDb++){
- if( pName->n==strlen(pDb->zName) &&
- 0==sqlite3StrNICmp(pDb->zName, pName->z, pName->n) ){
- return i;
+static int findDb(sqlite3 *db, Token *pName){
+ int i = -1; /* Database number */
+ int n; /* Number of characters in the name */
+ Db *pDb; /* A database whose name space is being searched */
+ char *zName; /* Name we are searching for */
+
+ zName = sqlite3NameFromToken(pName);
+ if( zName ){
+ n = strlen(zName);
+ for(i=(db->nDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){
+ if( n==strlen(pDb->zName) && 0==sqlite3StrICmp(pDb->zName, zName) ){
+ break;
+ }
}
+ sqliteFree(zName);
}
- return -1;
+ return i;
}
/* The table or view or trigger name is passed to this routine via tokens
@@ -544,7 +594,8 @@ int sqlite3TwoPartName(
** is reserved for internal use.
*/
int sqlite3CheckObjectName(Parse *pParse, const char *zName){
- if( !pParse->db->init.busy && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
+ if( !pParse->db->init.busy && pParse->nested==0
+ && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName);
return SQLITE_ERROR;
}
@@ -578,7 +629,7 @@ void sqlite3StartTable(
){
Table *pTable;
Index *pIdx;
- char *zName;
+ char *zName = 0; /* The name of the new table */
sqlite3 *db = pParse->db;
Vdbe *v;
int iDb; /* Database number to create the table in */
@@ -606,7 +657,6 @@ void sqlite3StartTable(
if( isTemp && iDb>1 ){
/* If creating a temp table, the name may not be qualified */
sqlite3ErrorMsg(pParse, "temporary table name must be unqualified");
- pParse->nErr++;
return;
}
if( isTemp ) iDb = 1;
@@ -615,8 +665,7 @@ void sqlite3StartTable(
zName = sqlite3NameFromToken(pName);
if( zName==0 ) return;
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
- sqliteFree(zName);
- return;
+ goto begin_table_error;
}
if( db->init.iDb==1 ) isTemp = 1;
#ifndef SQLITE_OMIT_AUTHORIZATION
@@ -625,8 +674,7 @@ void sqlite3StartTable(
int code;
char *zDb = db->aDb[iDb].zName;
if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
- sqliteFree(zName);
- return;
+ goto begin_table_error;
}
if( isView ){
if( isTemp ){
@@ -642,8 +690,7 @@ void sqlite3StartTable(
}
}
if( sqlite3AuthCheck(pParse, code, zName, 0, zDb) ){
- sqliteFree(zName);
- return;
+ goto begin_table_error;
}
}
#endif
@@ -652,25 +699,24 @@ void sqlite3StartTable(
** index or table name in the same database. Issue an error message if
** it does.
*/
- if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) return;
+ if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
+ goto begin_table_error;
+ }
pTable = sqlite3FindTable(db, zName, db->aDb[iDb].zName);
if( pTable ){
sqlite3ErrorMsg(pParse, "table %T already exists", pName);
- sqliteFree(zName);
- return;
+ goto begin_table_error;
}
if( (pIdx = sqlite3FindIndex(db, zName, 0))!=0 &&
( iDb==0 || !db->init.busy) ){
sqlite3ErrorMsg(pParse, "there is already an index named %s", zName);
- sqliteFree(zName);
- return;
+ goto begin_table_error;
}
pTable = sqliteMalloc( sizeof(Table) );
if( pTable==0 ){
pParse->rc = SQLITE_NOMEM;
pParse->nErr++;
- sqliteFree(zName);
- return;
+ goto begin_table_error;
}
pTable->zName = zName;
pTable->nCol = 0;
@@ -681,6 +727,16 @@ void sqlite3StartTable(
if( pParse->pNewTable ) sqlite3DeleteTable(db, pParse->pNewTable);
pParse->pNewTable = pTable;
+ /* If this is the magic sqlite_sequence table used by autoincrement,
+ ** then record a pointer to this table in the main database structure
+ ** so that INSERT can find the table easily.
+ */
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+ if( strcmp(zName, "sqlite_sequence")==0 ){
+ db->aDb[iDb].pSeqTab = pTable;
+ }
+#endif
+
/* Begin generating the code that will insert the table record into
** the SQLITE_MASTER table. Note in particular that we must go ahead
** and allocate the record number for the table entry now. Before any
@@ -690,25 +746,69 @@ void sqlite3StartTable(
** now.
*/
if( !db->init.busy && (v = sqlite3GetVdbe(pParse))!=0 ){
+ int lbl;
sqlite3BeginWriteOperation(pParse, 0, iDb);
- /* Every time a new table is created the file-format
- ** and encoding meta-values are set in the database, in
- ** case this is the first table created.
+
+ /* If the file format and encoding in the database have not been set,
+ ** set them now.
*/
+ sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 1); /* file_format */
+ lbl = sqlite3VdbeMakeLabel(v);
+ sqlite3VdbeAddOp(v, OP_If, 0, lbl);
sqlite3VdbeAddOp(v, OP_Integer, db->file_format, 0);
sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1);
sqlite3VdbeAddOp(v, OP_Integer, db->enc, 0);
sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 4);
+ sqlite3VdbeResolveLabel(v, lbl);
+ /* This just creates a place-holder record in the sqlite_master table.
+ ** The record created does not contain anything yet. It will be replaced
+ ** by the real entry in code generated at sqlite3EndTable().
+ **
+ ** The rowid for the new entry is left on the top of the stack.
+ ** The rowid value is needed by the code that sqlite3EndTable will
+ ** generate.
+ */
+#ifndef SQLITE_OMIT_VIEW
+ if( isView ){
+ sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
+ }else
+#endif
+ {
+ sqlite3VdbeAddOp(v, OP_CreateTable, iDb, 0);
+ }
sqlite3OpenMasterTable(v, iDb);
sqlite3VdbeAddOp(v, OP_NewRecno, 0, 0);
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0);
+ sqlite3VdbeAddOp(v, OP_Close, 0, 0);
+ sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
}
+
+ /* Normal (non-error) return. */
+ return;
+
+ /* If an error occurs, we jump here */
+begin_table_error:
+ sqliteFree(zName);
+ return;
}
/*
+** This macro is used to compare two strings in a case-insensitive manner.
+** It is slightly faster than calling sqlite3StrICmp() directly, but
+** produces larger code.
+**
+** WARNING: This macro is not compatible with the strcmp() family. It
+** returns true if the two strings are equal, otherwise false.
+*/
+#define STRICMP(x, y) (\
+sqlite3UpperToLower[*(unsigned char *)(x)]== \
+sqlite3UpperToLower[*(unsigned char *)(y)] \
+&& sqlite3StrICmp((x)+1,(y)+1)==0 )
+
+/*
** Add a new column to the table currently being constructed.
**
** The parser calls this routine once for each column declaration
@@ -725,7 +825,7 @@ void sqlite3AddColumn(Parse *pParse, Token *pName){
z = sqlite3NameFromToken(pName);
if( z==0 ) return;
for(i=0; i<p->nCol; i++){
- if( sqlite3StrICmp(z, p->aCol[i].zName)==0 ){
+ if( STRICMP(z, p->aCol[i].zName) ){
sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
sqliteFree(z);
return;
@@ -765,6 +865,55 @@ void sqlite3AddNotNull(Parse *pParse, int onError){
}
/*
+** Scan the column type name zType (length nType) and return the
+** associated affinity type.
+**
+** This routine does a case-independent search of zType for the
+** substrings in the following table. If one of the substrings is
+** found, the corresponding affinity is returned. If zType contains
+** more than one of the substrings, entries toward the top of
+** the table take priority. For example, if zType is 'BLOBINT',
+** SQLITE_AFF_INTEGER is returned.
+**
+** Substring | Affinity
+** --------------------------------
+** 'INT' | SQLITE_AFF_INTEGER
+** 'CHAR' | SQLITE_AFF_TEXT
+** 'CLOB' | SQLITE_AFF_TEXT
+** 'TEXT' | SQLITE_AFF_TEXT
+** 'BLOB' | SQLITE_AFF_NONE
+**
+** If none of the substrings in the above table are found,
+** SQLITE_AFF_NUMERIC is returned.
+*/
+static char sqlite3AffinityType(const char *zType, int nType){
+ u32 h = 0;
+ char aff = SQLITE_AFF_NUMERIC;
+ const unsigned char *zIn = zType;
+ const unsigned char *zEnd = (zIn+nType);
+
+ while( zIn!=zEnd ){
+ h = (h<<8) + sqlite3UpperToLower[*zIn];
+ zIn++;
+ if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */
+ aff = SQLITE_AFF_TEXT;
+ }else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){ /* CLOB */
+ aff = SQLITE_AFF_TEXT;
+ }else if( h==(('t'<<24)+('e'<<16)+('x'<<8)+'t') ){ /* TEXT */
+ aff = SQLITE_AFF_TEXT;
+ }else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b') /* BLOB */
+ && aff==SQLITE_AFF_NUMERIC ){
+ aff = SQLITE_AFF_NONE;
+ }else if( (h&0x00FFFFFF)==(('i'<<16)+('n'<<8)+'t') ){ /* INT */
+ aff = SQLITE_AFF_INTEGER;
+ break;
+ }
+ }
+
+ return aff;
+}
+
+/*
** This routine is called by the parser while in the middle of
** parsing a CREATE TABLE statement. The pFirst token is the first
** token in the sequence of tokens that describe the type of the
@@ -777,19 +926,21 @@ void sqlite3AddColumnType(Parse *pParse, Token *pFirst, Token *pLast){
Table *p;
int i, j;
int n;
- char *z, **pz;
+ char *z;
+ const unsigned char *zIn;
+
Column *pCol;
if( (p = pParse->pNewTable)==0 ) return;
i = p->nCol-1;
if( i<0 ) return;
pCol = &p->aCol[i];
- pz = &pCol->zType;
- n = pLast->n + (pLast->z - pFirst->z);
+ zIn = pFirst->z;
+ n = pLast->n + (pLast->z - zIn);
assert( pCol->zType==0 );
- z = pCol->zType = sqlite3MPrintf("%.*s", n, pFirst->z);
+ z = pCol->zType = sqliteMallocRaw(n+1);
if( z==0 ) return;
- for(i=j=0; z[i]; i++){
- int c = z[i];
+ for(i=j=0; i<n; i++){
+ int c = zIn[i];
if( isspace(c) ) continue;
z[j++] = c;
}
@@ -798,23 +949,28 @@ void sqlite3AddColumnType(Parse *pParse, Token *pFirst, Token *pLast){
}
/*
-** The given token is the default value for the last column added to
-** the table currently under construction. If "minusFlag" is true, it
-** means the value token was preceded by a minus sign.
+** The expression is the default value for the most recently added column
+** of the table currently under construction.
+**
+** Default value expressions must be constant. Raise an exception if this
+** is not the case.
**
** This routine is called by the parser while in the middle of
** parsing a CREATE TABLE statement.
*/
-void sqlite3AddDefaultValue(Parse *pParse, Token *pVal, int minusFlag){
+void sqlite3AddDefaultValue(Parse *pParse, Expr *pExpr){
Table *p;
- int i;
- char *z;
+ Column *pCol;
if( (p = pParse->pNewTable)==0 ) return;
- i = p->nCol-1;
- if( i<0 ) return;
- assert( p->aCol[i].zDflt==0 );
- z = p->aCol[i].zDflt = sqlite3MPrintf("%s%T", minusFlag ? "-" : "", pVal);
- sqlite3Dequote(z);
+ pCol = &(p->aCol[p->nCol-1]);
+ if( !sqlite3ExprIsConstant(pExpr) ){
+ sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
+ pCol->zName);
+ }else{
+ sqlite3ExprDelete(pCol->pDflt);
+ pCol->pDflt = sqlite3ExprDup(pExpr);
+ }
+ sqlite3ExprDelete(pExpr);
}
/*
@@ -827,9 +983,7 @@ void sqlite3AddDefaultValue(Parse *pParse, Token *pVal, int minusFlag){
** error.
**
** If the PRIMARY KEY is on a single column whose datatype is INTEGER,
-** then we will try to use that column as the row id. (Exception:
-** For backwards compatibility with older databases, do not do this
-** if the file format version number is less than 1.) Set the Table.iPKey
+** then we will try to use that column as the rowid. Set the Table.iPKey
** field of the table under construction to be the index of the
** INTEGER PRIMARY KEY column. Table.iPKey is set to -1 if there is
** no INTEGER PRIMARY KEY.
@@ -837,7 +991,12 @@ void sqlite3AddDefaultValue(Parse *pParse, Token *pVal, int minusFlag){
** If the key is not an INTEGER PRIMARY KEY, then create a unique
** index for the key. No index is created for INTEGER PRIMARY KEYs.
*/
-void sqlite3AddPrimaryKey(Parse *pParse, ExprList *pList, int onError){
+void sqlite3AddPrimaryKey(
+ Parse *pParse, /* Parsing context */
+ ExprList *pList, /* List of field names to be indexed */
+ int onError, /* What to do with a uniqueness conflict */
+ int autoInc /* True if the AUTOINCREMENT keyword is present */
+){
Table *pTab = pParse->pNewTable;
char *zType = 0;
int iCol = -1, i;
@@ -868,6 +1027,12 @@ void sqlite3AddPrimaryKey(Parse *pParse, ExprList *pList, int onError){
if( zType && sqlite3StrICmp(zType, "INTEGER")==0 ){
pTab->iPKey = iCol;
pTab->keyConf = onError;
+ pTab->autoInc = autoInc;
+ }else if( autoInc ){
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+ sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an "
+ "INTEGER PRIMARY KEY");
+#endif
}else{
sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, 0);
pList = 0;
@@ -980,6 +1145,7 @@ static void callCollNeeded(sqlite3 *db, const char *zName, int nName){
db->xCollNeeded(db->pCollNeededArg, db, (int)db->enc, zExternal);
sqliteFree(zExternal);
}
+#ifndef SQLITE_OMIT_UTF16
if( db->xCollNeeded16 ){
char const *zExternal;
sqlite3_value *pTmp = sqlite3GetTransientValue(db);
@@ -988,6 +1154,7 @@ static void callCollNeeded(sqlite3 *db, const char *zName, int nName){
if( !zExternal ) return;
db->xCollNeeded16(db->pCollNeededArg, db, (int)db->enc, zExternal);
}
+#endif
}
/*
@@ -1105,44 +1272,6 @@ CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName){
}
-
-/*
-** Scan the column type name zType (length nType) and return the
-** associated affinity type.
-*/
-char sqlite3AffinityType(const char *zType, int nType){
- int n, i;
- static const struct {
- const char *zSub; /* Keywords substring to search for */
- char nSub; /* length of zSub */
- char affinity; /* Affinity to return if it matches */
- } substrings[] = {
- {"INT", 3, SQLITE_AFF_INTEGER},
- {"CHAR", 4, SQLITE_AFF_TEXT},
- {"CLOB", 4, SQLITE_AFF_TEXT},
- {"TEXT", 4, SQLITE_AFF_TEXT},
- {"BLOB", 4, SQLITE_AFF_NONE},
- };
-
- if( nType==0 ){
- return SQLITE_AFF_NONE;
- }
- for(i=0; i<sizeof(substrings)/sizeof(substrings[0]); i++){
- int c1 = substrings[i].zSub[0];
- int c2 = tolower(c1);
- int limit = nType - substrings[i].nSub;
- const char *z = substrings[i].zSub;
- for(n=0; n<=limit; n++){
- int c = zType[n];
- if( (c==c1 || c==c2)
- && 0==sqlite3StrNICmp(&zType[n], z, substrings[i].nSub) ){
- return substrings[i].affinity;
- }
- }
- }
- return SQLITE_AFF_NUMERIC;
-}
-
/*
** Generate code that will increment the schema cookie.
**
@@ -1303,20 +1432,33 @@ void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){
if( !db->init.busy ){
int n;
Vdbe *v;
+ char *zType; /* "view" or "table" */
+ char *zType2; /* "VIEW" or "TABLE" */
+ char *zStmt; /* Text of the CREATE TABLE or CREATE VIEW statement */
v = sqlite3GetVdbe(pParse);
if( v==0 ) return;
+ sqlite3VdbeAddOp(v, OP_Close, 0, 0);
+
+ /* Create the rootpage for the new table and push it onto the stack.
+ ** A view has no rootpage, so just push a zero onto the stack for
+ ** views. Initialize zType at the same time.
+ */
if( p->pSelect==0 ){
/* A regular table */
- sqlite3VdbeAddOp(v, OP_CreateTable, p->iDb, 0);
+ /* sqlite3VdbeAddOp(v, OP_CreateTable, p->iDb, 0); */
+ zType = "table";
+ zType2 = "TABLE";
+#ifndef SQLITE_OMIT_VIEW
}else{
/* A view */
- sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
+ /* sqlite3VdbeAddOp(v, OP_Integer, 0, 0); */
+ zType = "view";
+ zType2 = "VIEW";
+#endif
}
- sqlite3VdbeAddOp(v, OP_Close, 0, 0);
-
/* If this is a CREATE TABLE xx AS SELECT ..., execute the SELECT
** statement to populate the new table. The root-page number for the
** new table is on the top of the vdbe stack.
@@ -1344,40 +1486,55 @@ void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){
sqlite3DeleteTable(0, pSelTab);
}
}
-
- sqlite3OpenMasterTable(v, p->iDb);
-
- sqlite3VdbeOp3(v, OP_String8, 0, 0, p->pSelect==0?"table":"view",P3_STATIC);
- sqlite3VdbeOp3(v, OP_String8, 0, 0, p->zName, 0);
- sqlite3VdbeOp3(v, OP_String8, 0, 0, p->zName, 0);
- sqlite3VdbeAddOp(v, OP_Pull, 3, 0);
+ /* Compute the complete text of the CREATE statement */
if( pSelect ){
- char *z = createTableStmt(p);
- n = z ? strlen(z) : 0;
- sqlite3VdbeAddOp(v, OP_String8, 0, 0);
- sqlite3VdbeChangeP3(v, -1, z, n);
- sqliteFree(z);
+ zStmt = createTableStmt(p);
}else{
- if( p->pSelect ){
- sqlite3VdbeOp3(v, OP_String8, 0, 0, "CREATE VIEW ", P3_STATIC);
- }else{
- sqlite3VdbeOp3(v, OP_String8, 0, 0, "CREATE TABLE ", P3_STATIC);
- }
- assert( pEnd!=0 );
n = Addr(pEnd->z) - Addr(pParse->sNameToken.z) + 1;
- sqlite3VdbeAddOp(v, OP_String8, 0, 0);
- sqlite3VdbeChangeP3(v, -1, pParse->sNameToken.z, n);
- sqlite3VdbeAddOp(v, OP_Concat, 0, 0);
+ zStmt = sqlite3MPrintf("CREATE %s %.*s", zType2, n, pParse->sNameToken.z);
}
- sqlite3VdbeOp3(v, OP_MakeRecord, 5, 0, "tttit", P3_STATIC);
- sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0);
+
+ /* A slot for the record has already been allocated in the
+ ** SQLITE_MASTER table. We just need to update that slot with all
+ ** the information we've collected. The rowid for the preallocated
+ ** slot is the 2nd item on the stack. The top of the stack is the
+ ** root page for the new table (or a 0 if this is a view).
+ */
+ sqlite3NestedParse(pParse,
+ "UPDATE %Q.%s "
+ "SET type='%s', name=%Q, tbl_name=%Q, rootpage=#0, sql=%Q "
+ "WHERE rowid=#1",
+ db->aDb[p->iDb].zName, SCHEMA_TABLE(p->iDb),
+ zType,
+ p->zName,
+ p->zName,
+ zStmt
+ );
+ sqliteFree(zStmt);
sqlite3ChangeCookie(db, v, p->iDb);
- sqlite3VdbeAddOp(v, OP_Close, 0, 0);
+
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+ /* Check to see if we need to create an sqlite_sequence table for
+ ** keeping track of autoincrement keys.
+ */
+ if( p->autoInc ){
+ Db *pDb = &db->aDb[p->iDb];
+ if( pDb->pSeqTab==0 ){
+ sqlite3NestedParse(pParse,
+ "CREATE TABLE %Q.sqlite_sequence(name,seq)",
+ pDb->zName
+ );
+ }
+ }
+#endif
+
+ /* Reparse everything to update our internal data structures */
sqlite3VdbeOp3(v, OP_ParseSchema, p->iDb, 0,
sqlite3MPrintf("tbl_name='%q'",p->zName), P3_DYNAMIC);
}
+
/* Add the table to the in-memory representation of the database.
*/
if( db->init.busy && pParse->nErr==0 ){
@@ -1389,17 +1546,20 @@ void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){
assert( p==pOld ); /* Malloc must have failed inside HashInsert() */
return;
}
+#ifndef SQLITE_OMIT_FOREIGN_KEY
for(pFKey=p->pFKey; pFKey; pFKey=pFKey->pNextFrom){
int nTo = strlen(pFKey->zTo) + 1;
pFKey->pNextTo = sqlite3HashFind(&pDb->aFKey, pFKey->zTo, nTo);
sqlite3HashInsert(&pDb->aFKey, pFKey->zTo, nTo, pFKey);
}
+#endif
pParse->pNewTable = 0;
db->nTable++;
db->flags |= SQLITE_InternChanges;
}
}
+#ifndef SQLITE_OMIT_VIEW
/*
** The parser calls this routine in order to create a new VIEW
*/
@@ -1461,17 +1621,19 @@ void sqlite3CreateView(
sqlite3EndTable(pParse, &sEnd, 0);
return;
}
+#endif /* SQLITE_OMIT_VIEW */
+#ifndef SQLITE_OMIT_VIEW
/*
** The Table structure pTable is really a VIEW. Fill in the names of
** the columns of the view in the pTable structure. Return the number
** of errors. If an error is seen leave an error message in pParse->zErrMsg.
*/
int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
- ExprList *pEList;
- Select *pSel;
- Table *pSelTab;
- int nErr = 0;
+ Table *pSelTab; /* A fake table from which we get the result set */
+ Select *pSel; /* Copy of the SELECT that implements the view */
+ int nErr = 0; /* Number of errors encountered */
+ int n; /* Temporarily holds the number of cursors assigned */
assert( pTable );
@@ -1496,23 +1658,19 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
}
/* If we get this far, it means we need to compute the table names.
+ ** Note that the call to sqlite3ResultSetOfSelect() will expand any
+ ** "*" elements in the results set of the view and will assign cursors
+ ** to the elements of the FROM clause. But we do not want these changes
+ ** to be permanent. So the computation is done on a copy of the SELECT
+ ** statement that defines the view.
*/
- assert( pTable->pSelect ); /* If nCol==0, then pTable must be a VIEW */
- pSel = pTable->pSelect;
-
- /* Note that the call to sqlite3ResultSetOfSelect() will expand any
- ** "*" elements in this list. But we will need to restore the list
- ** back to its original configuration afterwards, so we save a copy of
- ** the original in pEList.
- */
- pEList = pSel->pEList;
- pSel->pEList = sqlite3ExprListDup(pEList);
- if( pSel->pEList==0 ){
- pSel->pEList = pEList;
- return 1; /* Malloc failed */
- }
+ assert( pTable->pSelect );
+ pSel = sqlite3SelectDup(pTable->pSelect);
+ n = pParse->nTab;
+ sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
pTable->nCol = -1;
pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSel);
+ pParse->nTab = n;
if( pSelTab ){
assert( pTable->aCol==0 );
pTable->nCol = pSelTab->nCol;
@@ -1525,12 +1683,12 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
pTable->nCol = 0;
nErr++;
}
- sqlite3SelectUnbind(pSel);
- sqlite3ExprListDelete(pSel->pEList);
- pSel->pEList = pEList;
+ sqlite3SelectDelete(pSel);
return nErr;
}
+#endif /* SQLITE_OMIT_VIEW */
+#ifndef SQLITE_OMIT_VIEW
/*
** Clear the column names from every VIEW in database idx.
*/
@@ -1545,6 +1703,115 @@ static void sqliteViewResetAll(sqlite3 *db, int idx){
}
DbClearProperty(db, idx, DB_UnresetViews);
}
+#else
+# define sqliteViewResetAll(A,B)
+#endif /* SQLITE_OMIT_VIEW */
+
+/*
+** This function is called by the VDBE to adjust the internal schema
+** used by SQLite when the btree layer moves a table root page. The
+** root-page of a table or index in database iDb has changed from iFrom
+** to iTo.
+*/
+#ifndef SQLITE_OMIT_AUTOVACUUM
+void sqlite3RootPageMoved(Db *pDb, int iFrom, int iTo){
+ HashElem *pElem;
+
+ for(pElem=sqliteHashFirst(&pDb->tblHash); pElem; pElem=sqliteHashNext(pElem)){
+ Table *pTab = sqliteHashData(pElem);
+ if( pTab->tnum==iFrom ){
+ pTab->tnum = iTo;
+ return;
+ }
+ }
+ for(pElem=sqliteHashFirst(&pDb->idxHash); pElem; pElem=sqliteHashNext(pElem)){
+ Index *pIdx = sqliteHashData(pElem);
+ if( pIdx->tnum==iFrom ){
+ pIdx->tnum = iTo;
+ return;
+ }
+ }
+ assert(0);
+}
+#endif
+
+/*
+** Write code to erase the table with root-page iTable from database iDb.
+** Also write code to modify the sqlite_master table and internal schema
+** if a root-page of another table is moved by the btree-layer whilst
+** erasing iTable (this can happen with an auto-vacuum database).
+*/
+static void destroyRootPage(Parse *pParse, int iTable, int iDb){
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ sqlite3VdbeAddOp(v, OP_Destroy, iTable, iDb);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ /* OP_Destroy pushes an integer onto the stack. If this integer
+ ** is non-zero, then it is the root page number of a table moved to
+ ** location iTable. The following code modifies the sqlite_master table to
+ ** reflect this.
+ **
+ ** The "#0" in the SQL is a special constant that means whatever value
+ ** is on the top of the stack. See sqlite3RegisterExpr().
+ */
+ sqlite3NestedParse(pParse,
+ "UPDATE %Q.%s SET rootpage=%d WHERE #0 AND rootpage=#0",
+ pParse->db->aDb[iDb].zName, SCHEMA_TABLE(iDb), iTable);
+#endif
+}
+
+/*
+** Write VDBE code to erase table pTab and all associated indices on disk.
+** Code to update the sqlite_master tables and internal schema definitions
+** in case a root-page belonging to another table is moved by the btree layer
+** is also added (this can happen with an auto-vacuum database).
+*/
+static void destroyTable(Parse *pParse, Table *pTab){
+#ifdef SQLITE_OMIT_AUTOVACUUM
+ Index *pIdx;
+ destroyRootPage(pParse, pTab->tnum, pTab->iDb);
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ destroyRootPage(pParse, pIdx->tnum, pIdx->iDb);
+ }
+#else
+ /* If the database may be auto-vacuum capable (if SQLITE_OMIT_AUTOVACUUM
+ ** is not defined), then it is important to call OP_Destroy on the
+ ** table and index root-pages in order, starting with the numerically
+ ** largest root-page number. This guarantees that none of the root-pages
+ ** to be destroyed is relocated by an earlier OP_Destroy. i.e. if the
+ ** following were coded:
+ **
+ ** OP_Destroy 4 0
+ ** ...
+ ** OP_Destroy 5 0
+ **
+ ** and root page 5 happened to be the largest root-page number in the
+ ** database, then root page 5 would be moved to page 4 by the
+ ** "OP_Destroy 4 0" opcode. The subsequent "OP_Destroy 5 0" would hit
+ ** a free-list page.
+ */
+ int iTab = pTab->tnum;
+ int iDestroyed = 0;
+
+ while( 1 ){
+ Index *pIdx;
+ int iLargest = 0;
+
+ if( iDestroyed==0 || iTab<iDestroyed ){
+ iLargest = iTab;
+ }
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ int iIdx = pIdx->tnum;
+ assert( pIdx->iDb==pTab->iDb );
+ if( (iDestroyed==0 || (iIdx<iDestroyed)) && iIdx>iLargest ){
+ iLargest = iIdx;
+ }
+ }
+ if( iLargest==0 ) return;
+ destroyRootPage(pParse, iLargest, pTab->iDb);
+ iDestroyed = iLargest;
+ }
+#endif
+}
/*
** This routine is called to do the work of a DROP TABLE statement.
@@ -1553,7 +1820,6 @@ static void sqliteViewResetAll(sqlite3 *db, int idx){
void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){
Table *pTab;
Vdbe *v;
- int base;
sqlite3 *db = pParse->db;
int iDb;
@@ -1593,11 +1859,15 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){
}
}
#endif
- if( pTab->readOnly ){
+ if( pTab->readOnly || pTab==db->aDb[iDb].pSeqTab ){
sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName);
- pParse->nErr++;
goto exit_drop_table;
}
+
+#ifndef SQLITE_OMIT_VIEW
+ /* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used
+ ** on a table.
+ */
if( isView && pTab->pSelect==0 ){
sqlite3ErrorMsg(pParse, "use DROP TABLE to delete table %s", pTab->zName);
goto exit_drop_table;
@@ -1606,30 +1876,17 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){
sqlite3ErrorMsg(pParse, "use DROP VIEW to delete view %s", pTab->zName);
goto exit_drop_table;
}
+#endif
/* Generate code to remove the table from the master table
** on disk.
*/
v = sqlite3GetVdbe(pParse);
if( v ){
- static const VdbeOpList dropTable[] = {
- { OP_Rewind, 0, ADDR(13), 0},
- { OP_String8, 0, 0, 0}, /* 1 */
- { OP_MemStore, 1, 1, 0},
- { OP_MemLoad, 1, 0, 0}, /* 3 */
- { OP_Column, 0, 2, 0}, /* sqlite_master.tbl_name */
- { OP_Ne, 0, ADDR(12), 0},
- { OP_String8, 0, 0, "trigger"},
- { OP_Column, 0, 2, 0}, /* sqlite_master.type */
- { OP_Eq, 0, ADDR(12), 0},
- { OP_Delete, 0, 0, 0},
- { OP_Rewind, 0, ADDR(13), 0},
- { OP_Goto, 0, ADDR(3), 0},
- { OP_Next, 0, ADDR(3), 0}, /* 12 */
- };
- Index *pIdx;
Trigger *pTrigger;
- sqlite3BeginWriteOperation(pParse, 0, pTab->iDb);
+ int iDb = pTab->iDb;
+ Db *pDb = &db->aDb[iDb];
+ sqlite3BeginWriteOperation(pParse, 0, iDb);
/* Drop all triggers associated with the table being dropped. Code
** is generated to remove entries from sqlite_master and/or
@@ -1637,11 +1894,25 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){
*/
pTrigger = pTab->pTrigger;
while( pTrigger ){
- assert( pTrigger->iDb==pTab->iDb || pTrigger->iDb==1 );
+ assert( pTrigger->iDb==iDb || pTrigger->iDb==1 );
sqlite3DropTriggerPtr(pParse, pTrigger, 1);
pTrigger = pTrigger->pNext;
}
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+ /* Remove any entries of the sqlite_sequence table associated with
+ ** the table being dropped. This is done before the table is dropped
+ ** at the btree level, in case the sqlite_sequence table needs to
+ ** move as a result of the drop (can happen in auto-vacuum mode).
+ */
+ if( pTab->autoInc ){
+ sqlite3NestedParse(pParse,
+ "DELETE FROM %s.sqlite_sequence WHERE name=%Q",
+ pDb->zName, pTab->zName
+ );
+ }
+#endif
+
/* Drop all SQLITE_MASTER table and index entries that refer to the
** table. The program name loops through the master table and deletes
** every row that refers to a table of the same name as the one being
@@ -1649,18 +1920,18 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){
** created in the temp database that refers to a table in another
** database.
*/
- sqlite3OpenMasterTable(v, pTab->iDb);
- base = sqlite3VdbeAddOpList(v, ArraySize(dropTable), dropTable);
- sqlite3VdbeChangeP3(v, base+1, pTab->zName, 0);
- sqlite3ChangeCookie(db, v, pTab->iDb);
- sqlite3VdbeAddOp(v, OP_Close, 0, 0);
+ sqlite3NestedParse(pParse,
+ "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
+ pDb->zName, SCHEMA_TABLE(iDb), pTab->zName);
if( !isView ){
- sqlite3VdbeAddOp(v, OP_Destroy, pTab->tnum, pTab->iDb);
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- sqlite3VdbeAddOp(v, OP_Destroy, pIdx->tnum, pIdx->iDb);
- }
+ destroyTable(pParse, pTab);
}
- sqlite3VdbeOp3(v, OP_DropTable, pTab->iDb, 0, pTab->zName, 0);
+
+ /* Remove the table entry from SQLite's internal schema and modify
+ ** the schema cookie.
+ */
+ sqlite3VdbeOp3(v, OP_DropTable, iDb, 0, pTab->zName, 0);
+ sqlite3ChangeCookie(db, v, iDb);
}
sqliteViewResetAll(db, iDb);
@@ -1693,12 +1964,13 @@ void sqlite3CreateForeignKey(
ExprList *pToCol, /* Columns in the other table */
int flags /* Conflict resolution algorithms. */
){
+#ifndef SQLITE_OMIT_FOREIGN_KEY
+ FKey *pFKey = 0;
Table *p = pParse->pNewTable;
int nByte;
int i;
int nCol;
char *z;
- FKey *pFKey = 0;
assert( pTo!=0 );
if( p==0 || pParse->nErr ) goto fk_end;
@@ -1779,6 +2051,7 @@ void sqlite3CreateForeignKey(
fk_end:
sqliteFree(pFKey);
+#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
sqlite3ExprListDelete(pFromCol);
sqlite3ExprListDelete(pToCol);
}
@@ -1791,15 +2064,80 @@ fk_end:
** accordingly.
*/
void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){
+#ifndef SQLITE_OMIT_FOREIGN_KEY
Table *pTab;
FKey *pFKey;
if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return;
pFKey->isDeferred = isDeferred;
+#endif
+}
+
+/*
+** Generate code that will erase and refill index *pIdx. This is
+** used to initialize a newly created index or to recompute the
+** content of an index in response to a REINDEX command.
+**
+** if memRootPage is not negative, it means that the index is newly
+** created. The memory cell specified by memRootPage contains the
+** root page number of the index. If memRootPage is negative, then
+** the index already exists and must be cleared before being refilled and
+** the root page number of the index is taken from pIndex->tnum.
+*/
+static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
+ Table *pTab = pIndex->pTable; /* The table that is indexed */
+ int iTab = pParse->nTab; /* Btree cursor used for pTab */
+ int iIdx = pParse->nTab+1; /* Btree cursor used for pIndex */
+ int addr1; /* Address of top of loop */
+ int tnum; /* Root page of index */
+ Vdbe *v; /* Generate code into this virtual machine */
+ int isUnique; /* True for a unique index */
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0,
+ pParse->db->aDb[pIndex->iDb].zName ) ){
+ return;
+ }
+#endif
+
+ /* Ensure all the required collation sequences are available. This
+ ** routine will invoke the collation-needed callback if necessary (and
+ ** if one has been registered).
+ */
+ if( sqlite3CheckIndexCollSeq(pParse, pIndex) ){
+ return;
+ }
+
+ v = sqlite3GetVdbe(pParse);
+ if( v==0 ) return;
+ if( memRootPage>=0 ){
+ sqlite3VdbeAddOp(v, OP_MemLoad, memRootPage, 0);
+ tnum = 0;
+ }else{
+ tnum = pIndex->tnum;
+ sqlite3VdbeAddOp(v, OP_Clear, tnum, pIndex->iDb);
+ }
+ sqlite3VdbeAddOp(v, OP_Integer, pIndex->iDb, 0);
+ sqlite3VdbeOp3(v, OP_OpenWrite, iIdx, tnum,
+ (char*)&pIndex->keyInfo, P3_KEYINFO);
+ sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0);
+ sqlite3VdbeAddOp(v, OP_OpenRead, iTab, pTab->tnum);
+ sqlite3VdbeAddOp(v, OP_SetNumColumns, iTab, pTab->nCol);
+ addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iTab, 0);
+ sqlite3GenerateIndexKey(v, pIndex, iTab);
+ isUnique = pIndex->onError!=OE_None;
+ sqlite3VdbeAddOp(v, OP_IdxPut, iIdx, isUnique);
+ if( isUnique ){
+ sqlite3VdbeChangeP3(v, -1, "indexed columns are not unique", P3_STATIC);
+ }
+ sqlite3VdbeAddOp(v, OP_Next, iTab, addr1+1);
+ sqlite3VdbeChangeP2(v, addr1, sqlite3VdbeCurrentAddr(v));
+ sqlite3VdbeAddOp(v, OP_Close, iTab, 0);
+ sqlite3VdbeAddOp(v, OP_Close, iIdx, 0);
}
/*
-** Create a new index for an SQL table. pIndex is the name of the index
-** and pTable is the name of the table that is to be indexed. Both will
+** Create a new index for an SQL table. pName1.pName2 is the name of the index
+** and pTblList is the name of the table that is to be indexed. Both will
** be NULL for a primary key or an index that is created to satisfy a
** UNIQUE constraint. If pTable and pIndex are NULL, use pParse->pNewTable
** as the table to be indexed. pParse->pNewTable is a table that is
@@ -1810,16 +2148,16 @@ void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){
** to the table currently under construction.
*/
void sqlite3CreateIndex(
- Parse *pParse, /* All information about this parse */
- Token *pName1, /* First part of index name. May be NULL */
- Token *pName2, /* Second part of index name. May be NULL */
- SrcList *pTblName, /* Table to index. Use pParse->pNewTable if 0 */
+ Parse *pParse, /* All information about this parse */
+ Token *pName1, /* First part of index name. May be NULL */
+ Token *pName2, /* Second part of index name. May be NULL */
+ SrcList *pTblName, /* Table to index. Use pParse->pNewTable if 0 */
ExprList *pList, /* A list of columns to be indexed */
- int onError, /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
- Token *pStart, /* The CREATE token that begins a CREATE TABLE statement */
- Token *pEnd /* The ")" that closes the CREATE INDEX statement */
+ int onError, /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
+ Token *pStart, /* The CREATE token that begins a CREATE TABLE statement */
+ Token *pEnd /* The ")" that closes the CREATE INDEX statement */
){
- Table *pTab = 0; /* Table to be indexed */
+ Table *pTab = 0; /* Table to be indexed */
Index *pIndex = 0; /* The index to be created */
char *zName = 0;
int i, j;
@@ -1874,10 +2212,12 @@ void sqlite3CreateIndex(
sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
goto exit_create_index;
}
+#ifndef SQLITE_OMIT_VIEW
if( pTab->pSelect ){
sqlite3ErrorMsg(pParse, "views may not be indexed");
goto exit_create_index;
}
+#endif
isTemp = pTab->iDb==1;
/*
@@ -1913,7 +2253,7 @@ void sqlite3CreateIndex(
goto exit_create_index;
}
}
- }else if( pName==0 ){
+ }else{
char zBuf[30];
int n;
Index *pLoop;
@@ -2076,60 +2416,55 @@ void sqlite3CreateIndex(
** step can be skipped.
*/
else if( db->init.busy==0 ){
- int n;
Vdbe *v;
- int lbl1, lbl2;
+ char *zStmt;
+ int iMem = pParse->nMem++;
v = sqlite3GetVdbe(pParse);
if( v==0 ) goto exit_create_index;
- if( pTblName!=0 ){
- sqlite3BeginWriteOperation(pParse, 0, iDb);
- sqlite3OpenMasterTable(v, iDb);
- }
- sqlite3VdbeAddOp(v, OP_NewRecno, 0, 0);
- sqlite3VdbeOp3(v, OP_String8, 0, 0, "index", P3_STATIC);
- sqlite3VdbeOp3(v, OP_String8, 0, 0, pIndex->zName, 0);
- sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0);
+
+ /* Create the rootpage for the index
+ */
+ sqlite3BeginWriteOperation(pParse, 1, iDb);
sqlite3VdbeAddOp(v, OP_CreateIndex, iDb, 0);
- if( pTblName ){
- sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
- sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
- sqlite3VdbeOp3(v, OP_OpenWrite, 1, 0,
- (char*)&pIndex->keyInfo, P3_KEYINFO);
- }
- sqlite3VdbeAddOp(v, OP_String8, 0, 0);
+ sqlite3VdbeAddOp(v, OP_MemStore, iMem, 0);
+
+ /* Gather the complete text of the CREATE INDEX statement into
+ ** the zStmt variable
+ */
if( pStart && pEnd ){
- if( onError==OE_None ){
- sqlite3VdbeChangeP3(v, -1, "CREATE INDEX ", P3_STATIC);
- }else{
- sqlite3VdbeChangeP3(v, -1, "CREATE UNIQUE INDEX ", P3_STATIC);
- }
- sqlite3VdbeAddOp(v, OP_String8, 0, 0);
- n = Addr(pEnd->z) - Addr(pName->z) + 1;
- sqlite3VdbeChangeP3(v, -1, pName->z, n);
- sqlite3VdbeAddOp(v, OP_Concat, 0, 0);
+ /* A named index with an explicit CREATE INDEX statement */
+ zStmt = sqlite3MPrintf("CREATE%s INDEX %.*s",
+ onError==OE_None ? "" : " UNIQUE",
+ Addr(pEnd->z) - Addr(pName->z) + 1,
+ pName->z);
+ }else{
+ /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
+ /* zStmt = sqlite3MPrintf(""); */
+ zStmt = 0;
}
- sqlite3VdbeOp3(v, OP_MakeRecord, 5, 0, "tttit", P3_STATIC);
- sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0);
+
+ /* Add an entry in sqlite_master for this index
+ */
+ sqlite3NestedParse(pParse,
+ "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#0,%Q);",
+ db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
+ pIndex->zName,
+ pTab->zName,
+ zStmt
+ );
+ sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
+ sqliteFree(zStmt);
+
+ /* Fill the index with data and reparse the schema. Code an OP_Expire
+ ** to invalidate all pre-compiled statements.
+ */
if( pTblName ){
- sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0);
- sqlite3VdbeAddOp(v, OP_OpenRead, 2, pTab->tnum);
- /* VdbeComment((v, "%s", pTab->zName)); */
- sqlite3VdbeAddOp(v, OP_SetNumColumns, 2, pTab->nCol);
- lbl2 = sqlite3VdbeMakeLabel(v);
- sqlite3VdbeAddOp(v, OP_Rewind, 2, lbl2);
- lbl1 = sqlite3VdbeCurrentAddr(v);
- sqlite3GenerateIndexKey(v, pIndex, 2);
- sqlite3VdbeOp3(v, OP_IdxPut, 1, pIndex->onError!=OE_None,
- "indexed columns are not unique", P3_STATIC);
- sqlite3VdbeAddOp(v, OP_Next, 2, lbl1);
- sqlite3VdbeResolveLabel(v, lbl2);
- sqlite3VdbeAddOp(v, OP_Close, 2, 0);
- sqlite3VdbeAddOp(v, OP_Close, 1, 0);
+ sqlite3RefillIndex(pParse, pIndex, iMem);
sqlite3ChangeCookie(db, v, iDb);
- sqlite3VdbeAddOp(v, OP_Close, 0, 0);
sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0,
sqlite3MPrintf("name='%q'", pIndex->zName), P3_DYNAMIC);
+ sqlite3VdbeAddOp(v, OP_Expire, 0, 0);
}
}
@@ -2207,27 +2542,15 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName){
/* Generate code to remove the index and from the master table */
v = sqlite3GetVdbe(pParse);
if( v ){
- static const VdbeOpList dropIndex[] = {
- { OP_Rewind, 0, ADDR(9), 0},
- { OP_String8, 0, 0, 0}, /* 1 */
- { OP_MemStore, 1, 1, 0},
- { OP_MemLoad, 1, 0, 0}, /* 3 */
- { OP_Column, 0, 1, 0},
- { OP_Eq, 0, ADDR(8), 0},
- { OP_Next, 0, ADDR(3), 0},
- { OP_Goto, 0, ADDR(9), 0},
- { OP_Delete, 0, 0, 0}, /* 8 */
- };
- int base;
-
- sqlite3BeginWriteOperation(pParse, 0, pIndex->iDb);
- sqlite3OpenMasterTable(v, pIndex->iDb);
- base = sqlite3VdbeAddOpList(v, ArraySize(dropIndex), dropIndex);
- sqlite3VdbeChangeP3(v, base+1, pIndex->zName, 0);
- sqlite3ChangeCookie(db, v, pIndex->iDb);
- sqlite3VdbeAddOp(v, OP_Close, 0, 0);
- sqlite3VdbeAddOp(v, OP_Destroy, pIndex->tnum, pIndex->iDb);
- sqlite3VdbeOp3(v, OP_DropIndex, pIndex->iDb, 0, pIndex->zName, 0);
+ int iDb = pIndex->iDb;
+ sqlite3NestedParse(pParse,
+ "DELETE FROM %Q.%s WHERE name=%Q",
+ db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
+ pIndex->zName
+ );
+ sqlite3ChangeCookie(db, v, iDb);
+ destroyRootPage(pParse, pIndex->tnum, iDb);
+ sqlite3VdbeOp3(v, OP_DropIndex, iDb, 0, pIndex->zName, 0);
}
exit_drop_index:
@@ -2327,9 +2650,12 @@ SrcList *sqlite3SrcListAppend(SrcList *pList, Token *pTable, Token *pDatabase){
*/
void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
int i;
- for(i=0; i<pList->nSrc; i++){
- if( pList->a[i].iCursor<0 ){
- pList->a[i].iCursor = pParse->nTab++;
+ struct SrcList_item *pItem;
+ for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
+ if( pItem->iCursor>=0 ) break;
+ pItem->iCursor = pParse->nTab++;
+ if( pItem->pSelect ){
+ sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc);
}
}
}
@@ -2544,7 +2870,7 @@ void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){
if( v==0 ) return;
sqlite3CodeVerifySchema(pParse, iDb);
pParse->writeMask |= 1<<iDb;
- if( setStatement ){
+ if( setStatement && pParse->nested==0 ){
sqlite3VdbeAddOp(v, OP_Statement, iDb, 0);
}
if( iDb!=1 && pParse->db->aDb[1].pBt!=0 ){
@@ -2552,6 +2878,7 @@ void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){
}
}
+#ifndef SQLITE_OMIT_UTF16
/*
** Return the transient sqlite3_value object used for encoding conversions
** during SQL compilation.
@@ -2562,3 +2889,121 @@ sqlite3_value *sqlite3GetTransientValue(sqlite3 *db){
}
return db->pValue;
}
+#endif
+
+/*
+** Check to see if pIndex uses the collating sequence pColl. Return
+** true if it does and false if it does not.
+*/
+#ifndef SQLITE_OMIT_REINDEX
+static int collationMatch(CollSeq *pColl, Index *pIndex){
+ int n = pIndex->keyInfo.nField;
+ CollSeq **pp = pIndex->keyInfo.aColl;
+ while( n-- ){
+ if( *pp==pColl ) return 1;
+ pp++;
+ }
+ return 0;
+}
+#endif
+
+/*
+** Recompute all indices of pTab that use the collating sequence pColl.
+** If pColl==0 then recompute all indices of pTab.
+*/
+#ifndef SQLITE_OMIT_REINDEX
+void reindexTable(Parse *pParse, Table *pTab, CollSeq *pColl){
+ Index *pIndex; /* An index associated with pTab */
+
+ for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
+ if( pColl==0 || collationMatch(pColl,pIndex) ){
+ sqlite3BeginWriteOperation(pParse, 0, pTab->iDb);
+ sqlite3RefillIndex(pParse, pIndex, -1);
+ }
+ }
+}
+#endif
+
+/*
+** Recompute all indices of all tables in all databases where the
+** indices use the collating sequence pColl. If pColl==0 then recompute
+** all indices everywhere.
+*/
+#ifndef SQLITE_OMIT_REINDEX
+void reindexDatabases(Parse *pParse, CollSeq *pColl){
+ Db *pDb; /* A single database */
+ int iDb; /* The database index number */
+ sqlite3 *db = pParse->db; /* The database connection */
+ HashElem *k; /* For looping over tables in pDb */
+ Table *pTab; /* A table in the database */
+
+ for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){
+ if( pDb==0 ) continue;
+ for(k=sqliteHashFirst(&pDb->tblHash); k; k=sqliteHashNext(k)){
+ pTab = (Table*)sqliteHashData(k);
+ reindexTable(pParse, pTab, pColl);
+ }
+ }
+}
+#endif
+
+/*
+** Generate code for the REINDEX command.
+**
+** REINDEX -- 1
+** REINDEX <collation> -- 2
+** REINDEX ?<database>.?<tablename> -- 3
+** REINDEX ?<database>.?<indexname> -- 4
+**
+** Form 1 causes all indices in all attached databases to be rebuilt.
+** Form 2 rebuilds all indices in all databases that use the named
+** collating function. Forms 3 and 4 rebuild the named index or all
+** indices associated with the named table.
+*/
+#ifndef SQLITE_OMIT_REINDEX
+void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
+ CollSeq *pColl; /* Collating sequence to be reindexed, or NULL */
+ char *z; /* Name of a table or index */
+ const char *zDb; /* Name of the database */
+ Table *pTab; /* A table in the database */
+ Index *pIndex; /* An index associated with pTab */
+ int iDb; /* The database index number */
+ sqlite3 *db = pParse->db; /* The database connection */
+ Token *pObjName; /* Name of the table or index to be reindexed */
+
+ /* Read the database schema. If an error occurs, leave an error message
+ ** and code in pParse and return NULL. */
+ if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
+ return;
+ }
+
+ if( pName1==0 || pName1->z==0 ){
+ reindexDatabases(pParse, 0);
+ return;
+ }else if( pName2==0 || pName2->z==0 ){
+ pColl = sqlite3FindCollSeq(db, db->enc, pName1->z, pName1->n, 0);
+ if( pColl ){
+ reindexDatabases(pParse, pColl);
+ return;
+ }
+ }
+ iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName);
+ if( iDb<0 ) return;
+ z = sqlite3NameFromToken(pObjName);
+ zDb = db->aDb[iDb].zName;
+ pTab = sqlite3FindTable(db, z, zDb);
+ if( pTab ){
+ reindexTable(pParse, pTab, 0);
+ sqliteFree(z);
+ return;
+ }
+ pIndex = sqlite3FindIndex(db, z, zDb);
+ sqliteFree(z);
+ if( pIndex ){
+ sqlite3BeginWriteOperation(pParse, 0, iDb);
+ sqlite3RefillIndex(pParse, pIndex, -1);
+ return;
+ }
+ sqlite3ErrorMsg(pParse, "unable to identify the object to be reindexed");
+}
+#endif
diff --git a/ext/pdo_sqlite/sqlite/src/date.c b/ext/pdo_sqlite/sqlite/src/date.c
index 634e81d5ed..8780a51b6d 100644
--- a/ext/pdo_sqlite/sqlite/src/date.c
+++ b/ext/pdo_sqlite/sqlite/src/date.c
@@ -315,12 +315,10 @@ static int parseDateOrTime(const char *zDate, DateTime *p){
return 0;
}else if( sqlite3StrICmp(zDate,"now")==0){
double r;
- if( sqlite3OsCurrentTime(&r)==0 ){
- p->rJD = r;
- p->validJD = 1;
- return 0;
- }
- return 1;
+ sqlite3OsCurrentTime(&r);
+ p->rJD = r;
+ p->validJD = 1;
+ return 0;
}else if( sqlite3IsNumber(zDate, 0, SQLITE_UTF8) ){
p->rJD = sqlite3AtoF(zDate, 0);
p->validJD = 1;
@@ -862,9 +860,100 @@ static void strftimeFunc(
}
}
+/*
+** current_time()
+**
+** This function returns the same value as time('now').
+*/
+static void ctimeFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ sqlite3_value *pVal = sqlite3ValueNew();
+ if( pVal ){
+ sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC);
+ timeFunc(context, 1, &pVal);
+ sqlite3ValueFree(pVal);
+ }
+}
+/*
+** current_date()
+**
+** This function returns the same value as date('now').
+*/
+static void cdateFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ sqlite3_value *pVal = sqlite3ValueNew();
+ if( pVal ){
+ sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC);
+ dateFunc(context, 1, &pVal);
+ sqlite3ValueFree(pVal);
+ }
+}
+
+/*
+** current_timestamp()
+**
+** This function returns the same value as datetime('now').
+*/
+static void ctimestampFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ sqlite3_value *pVal = sqlite3ValueNew();
+ if( pVal ){
+ sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC);
+ datetimeFunc(context, 1, &pVal);
+ sqlite3ValueFree(pVal);
+ }
+}
#endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */
+#ifdef SQLITE_OMIT_DATETIME_FUNCS
+/*
+** If the library is compiled to omit the full-scale date and time
+** handling (to get a smaller binary), the following minimal version
+** of the functions current_time(), current_date() and current_timestamp()
+** are included instead. This is to support column declarations that
+** include "DEFAULT CURRENT_TIME" etc.
+**
+** This function uses the C-library functions time(), gmtime()
+** and strftime(). The format string to pass to strftime() is supplied
+** as the user-data for the function.
+*/
+static void currentTimeFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ time_t t;
+ char *zFormat = (char *)sqlite3_user_data(context);
+ char zBuf[20];
+
+ time(&t);
+#ifdef SQLITE_TEST
+ {
+ extern int sqlite3_current_time; /* See os_XXX.c */
+ if( sqlite3_current_time ){
+ t = sqlite3_current_time;
+ }
+ }
+#endif
+
+ sqlite3OsEnterMutex();
+ strftime(zBuf, 20, zFormat, gmtime(&t));
+ sqlite3OsLeaveMutex();
+
+ sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+}
+#endif
+
/*
** This function registered all of the above C functions as SQL
** functions. This should be the only routine in this file with
@@ -882,6 +971,9 @@ void sqlite3RegisterDateTimeFunctions(sqlite3 *db){
{ "time", -1, timeFunc },
{ "datetime", -1, datetimeFunc },
{ "strftime", -1, strftimeFunc },
+ { "current_time", 0, ctimeFunc },
+ { "current_timestamp", 0, ctimestampFunc },
+ { "current_date", 0, cdateFunc },
};
int i;
@@ -889,5 +981,20 @@ void sqlite3RegisterDateTimeFunctions(sqlite3 *db){
sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg,
SQLITE_UTF8, 0, aFuncs[i].xFunc, 0, 0);
}
+#else
+ static const struct {
+ char *zName;
+ char *zFormat;
+ } aFuncs[] = {
+ { "current_time", "%H:%M:%S" },
+ { "current_date", "%Y-%m-%d" },
+ { "current_timestamp", "%Y-%m-%d %H:%M:%S" }
+ };
+ int i;
+
+ for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
+ sqlite3_create_function(db, aFuncs[i].zName, 0, SQLITE_UTF8,
+ aFuncs[i].zFormat, currentTimeFunc, 0, 0);
+ }
#endif
}
diff --git a/ext/pdo_sqlite/sqlite/src/delete.c b/ext/pdo_sqlite/sqlite/src/delete.c
index 866da61d92..fa661977d7 100644
--- a/ext/pdo_sqlite/sqlite/src/delete.c
+++ b/ext/pdo_sqlite/sqlite/src/delete.c
@@ -10,7 +10,7 @@
**
*************************************************************************
** This file contains C code routines that are called by the parser
-** to handle DELETE FROM statements.
+** in order to generate code for DELETE FROM statements.
**
** $Id$
*/
@@ -38,14 +38,17 @@ Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
** writable return 0;
*/
int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
- if( pTab->readOnly ){
+ if( pTab->readOnly && (pParse->db->flags & SQLITE_WriteSchema)==0
+ && pParse->nested==0 ){
sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName);
return 1;
}
+#ifndef SQLITE_OMIT_VIEW
if( !viewOk && pTab->pSelect ){
sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName);
return 1;
}
+#endif
return 0;
}
@@ -65,7 +68,11 @@ void sqlite3OpenTableForReading(
/*
-** Process a DELETE FROM statement.
+** Generate code for a DELETE FROM statement.
+**
+** DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL;
+** \________/ \________________/
+** pTabList pWhere
*/
void sqlite3DeleteFrom(
Parse *pParse, /* The parser context */
@@ -81,13 +88,14 @@ void sqlite3DeleteFrom(
Index *pIdx; /* For looping over indices of the table */
int iCur; /* VDBE Cursor number for pTab */
sqlite3 *db; /* Main database structure */
- int isView; /* True if attempting to delete from a view */
AuthContext sContext; /* Authorization context */
+ int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */
+ NameContext sNC; /* Name context to resolve expressions in */
- int row_triggers_exist = 0; /* True if any triggers exist */
- int before_triggers; /* True if there are BEFORE triggers */
- int after_triggers; /* True if there are AFTER triggers */
- int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */
+#ifndef SQLITE_OMIT_TRIGGER
+ int isView; /* True if attempting to delete from a view */
+ int triggers_exist = 0; /* True if any triggers exist */
+#endif
sContext.pParse = 0;
if( pParse->nErr || sqlite3_malloc_failed ){
@@ -104,13 +112,23 @@ void sqlite3DeleteFrom(
*/
pTab = sqlite3SrcListLookup(pParse, pTabList);
if( pTab==0 ) goto delete_from_cleanup;
- before_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger,
- TK_DELETE, TK_BEFORE, TK_ROW, 0);
- after_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger,
- TK_DELETE, TK_AFTER, TK_ROW, 0);
- row_triggers_exist = before_triggers || after_triggers;
+
+ /* Figure out if we have any triggers and if the table being
+ ** deleted from is a view
+ */
+#ifndef SQLITE_OMIT_TRIGGER
+ triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0);
isView = pTab->pSelect!=0;
- if( sqlite3IsReadOnly(pParse, pTab, before_triggers) ){
+#else
+# define triggers_exist 0
+# define isView 0
+#endif
+#ifdef SQLITE_OMIT_VIEW
+# undef isView
+# define isView 0
+#endif
+
+ if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){
goto delete_from_cleanup;
}
assert( pTab->iDb<db->nDb );
@@ -127,15 +145,18 @@ void sqlite3DeleteFrom(
/* Allocate a cursor used to store the old.* data for a trigger.
*/
- if( row_triggers_exist ){
+ if( triggers_exist ){
oldIdx = pParse->nTab++;
}
- /* Resolve the column names in all the expressions.
+ /* Resolve the column names in the WHERE clause.
*/
assert( pTabList->nSrc==1 );
iCur = pTabList->a[0].iCursor = pParse->nTab++;
- if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0, pWhere, 0, 0) ){
+ memset(&sNC, 0, sizeof(sNC));
+ sNC.pParse = pParse;
+ sNC.pSrcList = pTabList;
+ if( sqlite3ExprResolveNames(&sNC, pWhere) ){
goto delete_from_cleanup;
}
@@ -151,8 +172,8 @@ void sqlite3DeleteFrom(
if( v==0 ){
goto delete_from_cleanup;
}
- sqlite3VdbeCountChanges(v);
- sqlite3BeginWriteOperation(pParse, row_triggers_exist, pTab->iDb);
+ if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
+ sqlite3BeginWriteOperation(pParse, triggers_exist, pTab->iDb);
/* If we are trying to delete from a view, construct that view into
** a temporary table.
@@ -174,7 +195,7 @@ void sqlite3DeleteFrom(
** It is easier just to erase the whole table. Note, however, that
** this means that the row change count will be incorrect.
*/
- if( pWhere==0 && !row_triggers_exist ){
+ if( pWhere==0 && !triggers_exist ){
if( db->flags & SQLITE_CountRows ){
/* If counting rows deleted, just count the total number of
** entries in the table. */
@@ -210,11 +231,12 @@ void sqlite3DeleteFrom(
/* Begin the database scan
*/
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 1, 0);
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0);
if( pWInfo==0 ) goto delete_from_cleanup;
- /* Remember the key of every item to be deleted.
+ /* Remember the rowid of every item to be deleted.
*/
+ sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0);
if( db->flags & SQLITE_CountRows ){
sqlite3VdbeAddOp(v, OP_AddImm, 1, 0);
@@ -226,7 +248,7 @@ void sqlite3DeleteFrom(
/* Open the pseudo-table used to store OLD if there are triggers.
*/
- if( row_triggers_exist ){
+ if( triggers_exist ){
sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
sqlite3VdbeAddOp(v, OP_SetNumColumns, oldIdx, pTab->nCol);
}
@@ -241,7 +263,7 @@ void sqlite3DeleteFrom(
/* This is the beginning of the delete loop when there are
** row triggers.
*/
- if( row_triggers_exist ){
+ if( triggers_exist ){
addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, end);
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
if( !isView ){
@@ -255,8 +277,8 @@ void sqlite3DeleteFrom(
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
}
- sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1,
- oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
+ (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_BEFORE, pTab,
+ -1, oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
addr);
}
@@ -271,25 +293,25 @@ void sqlite3DeleteFrom(
/* This is the beginning of the delete loop when there are no
** row triggers */
- if( !row_triggers_exist ){
+ if( !triggers_exist ){
addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, end);
}
/* Delete the row */
- sqlite3GenerateRowDelete(db, v, pTab, iCur, 1);
+ sqlite3GenerateRowDelete(db, v, pTab, iCur, pParse->nested==0);
}
/* If there are row triggers, close all cursors then invoke
** the AFTER triggers
*/
- if( row_triggers_exist ){
+ if( triggers_exist ){
if( !isView ){
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
}
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
}
- sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1,
+ (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_AFTER, pTab, -1,
oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
addr);
}
@@ -300,7 +322,7 @@ void sqlite3DeleteFrom(
sqlite3VdbeAddOp(v, OP_ListReset, 0, 0);
/* Close the cursors after the loop if there are no row triggers */
- if( !row_triggers_exist ){
+ if( !triggers_exist ){
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
}
@@ -309,9 +331,11 @@ void sqlite3DeleteFrom(
}
/*
- ** Return the number of rows that were deleted.
+ ** Return the number of rows that were deleted. If this routine is
+ ** generating code because of a call to sqlite3NestedParse(), do not
+ ** invoke the callback function.
*/
- if( db->flags & SQLITE_CountRows ){
+ if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, "rows deleted", P3_STATIC);
diff --git a/ext/pdo_sqlite/sqlite/src/experimental.c b/ext/pdo_sqlite/sqlite/src/experimental.c
new file mode 100644
index 0000000000..073f21835c
--- /dev/null
+++ b/ext/pdo_sqlite/sqlite/src/experimental.c
@@ -0,0 +1,38 @@
+
+/*
+** 2001 September 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 are called by the parser
+** to handle SELECT statements in SQLite.
+**
+** $Id$
+*/
+#include "sqliteInt.h"
+
+/*
+** Set all the parameters in the compiled SQL statement to NULL.
+*/
+int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
+ int i;
+ int rc = SQLITE_OK;
+ for(i=1; rc==SQLITE_OK && i<=sqlite3_bind_parameter_count(pStmt); i++){
+ rc = sqlite3_bind_null(pStmt, i);
+ }
+ return rc;
+}
+
+/*
+** Sleep for a little while. Return the amount of time slept.
+*/
+int sqlite3_sleep(int ms){
+ return sqlite3OsSleep(ms);
+}
+
diff --git a/ext/pdo_sqlite/sqlite/src/expr.c b/ext/pdo_sqlite/sqlite/src/expr.c
index 2da3645b9b..c4943b1f83 100644
--- a/ext/pdo_sqlite/sqlite/src/expr.c
+++ b/ext/pdo_sqlite/sqlite/src/expr.c
@@ -62,8 +62,8 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
}
/*
-** pExpr is the left operand of a comparison operator. aff2 is the
-** type affinity of the right operand. This routine returns the
+** pExpr is an operand of a comparison operator. aff2 is the
+** type affinity of the other operand. This routine returns the
** type affinity that should be used for the comparison operator.
*/
char sqlite3CompareAffinity(Expr *pExpr, char aff2){
@@ -179,7 +179,7 @@ static int codeCompare(
** for this node is obtained from sqliteMalloc(). The calling function
** is responsible for making sure the node eventually gets freed.
*/
-Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, Token *pToken){
+Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, const Token *pToken){
Expr *pNew;
pNew = sqliteMalloc( sizeof(Expr) );
if( pNew==0 ){
@@ -189,6 +189,7 @@ Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, Token *pToken){
pNew->op = op;
pNew->pLeft = pLeft;
pNew->pRight = pRight;
+ pNew->iAgg = -1;
if( pToken ){
assert( pToken->dyn==0 );
pNew->span = pNew->token = *pToken;
@@ -199,6 +200,42 @@ Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, Token *pToken){
}
/*
+** When doing a nested parse, you can include terms in an expression
+** that look like this: #0 #1 #2 ... These terms refer to elements
+** on the stack. "#0" (or just "#") means the top of the stack.
+** "#1" means the next down on the stack. And so forth. #-1 means
+** memory location 0. #-2 means memory location 1. And so forth.
+**
+** This routine is called by the parser to deal with on of those terms.
+** It immediately generates code to store the value in a memory location.
+** The returns an expression that will code to extract the value from
+** that memory location as needed.
+*/
+Expr *sqlite3RegisterExpr(Parse *pParse, Token *pToken){
+ Vdbe *v = pParse->pVdbe;
+ Expr *p;
+ int depth;
+ if( v==0 ) return 0;
+ if( pParse->nested==0 ){
+ sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", pToken);
+ return 0;
+ }
+ p = sqlite3Expr(TK_REGISTER, 0, 0, pToken);
+ if( p==0 ){
+ return 0; /* Malloc failed */
+ }
+ depth = atoi(&pToken->z[1]);
+ if( depth>=0 ){
+ p->iTable = pParse->nMem++;
+ sqlite3VdbeAddOp(v, OP_Dup, depth, 0);
+ sqlite3VdbeAddOp(v, OP_MemStore, p->iTable, 1);
+ }else{
+ p->iTable = -1-depth;
+ }
+ return p;
+}
+
+/*
** Join two expressions using an AND operator. If either expression is
** NULL, then just return the other expression.
*/
@@ -356,7 +393,7 @@ Expr *sqlite3ExprDup(Expr *p){
if( pNew==0 ) return 0;
memcpy(pNew, p, sizeof(*pNew));
if( p->token.z!=0 ){
- pNew->token.z = sqliteStrDup(p->token.z);
+ pNew->token.z = sqliteStrNDup(p->token.z, p->token.n);
pNew->token.dyn = 1;
}else{
assert( pNew->token.z==0 );
@@ -410,6 +447,15 @@ ExprList *sqlite3ExprListDup(ExprList *p){
}
return pNew;
}
+
+/*
+** If cursors, triggers, views and subqueries are all omitted from
+** the build, then none of the following routines, except for
+** sqlite3SelectDup(), can be called. sqlite3SelectDup() is sometimes
+** called with a NULL argument.
+*/
+#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) \
+ || !defined(SQLITE_OMIT_SUBQUERY)
SrcList *sqlite3SrcListDup(SrcList *p){
SrcList *pNew;
int i;
@@ -427,10 +473,14 @@ SrcList *sqlite3SrcListDup(SrcList *p){
pNewItem->zAlias = sqliteStrDup(pOldItem->zAlias);
pNewItem->jointype = pOldItem->jointype;
pNewItem->iCursor = pOldItem->iCursor;
- pNewItem->pTab = 0;
+ pNewItem->pTab = pOldItem->pTab;
+ if( pNewItem->pTab ){
+ pNewItem->pTab->isTransient = 0;
+ }
pNewItem->pSelect = sqlite3SelectDup(pOldItem->pSelect);
pNewItem->pOn = sqlite3ExprDup(pOldItem->pOn);
pNewItem->pUsing = sqlite3IdListDup(pOldItem->pUsing);
+ pNewItem->colUsed = pOldItem->colUsed;
}
return pNew;
}
@@ -465,14 +515,22 @@ Select *sqlite3SelectDup(Select *p){
pNew->pOrderBy = sqlite3ExprListDup(p->pOrderBy);
pNew->op = p->op;
pNew->pPrior = sqlite3SelectDup(p->pPrior);
- pNew->nLimit = p->nLimit;
- pNew->nOffset = p->nOffset;
- pNew->zSelect = 0;
+ pNew->pLimit = sqlite3ExprDup(p->pLimit);
+ pNew->pOffset = sqlite3ExprDup(p->pOffset);
pNew->iLimit = -1;
pNew->iOffset = -1;
pNew->ppOpenTemp = 0;
+ pNew->pFetch = 0;
+ pNew->isResolved = p->isResolved;
+ pNew->isAgg = p->isAgg;
return pNew;
}
+#else
+Select *sqlite3SelectDup(Select *p){
+ assert( p==0 );
+ return 0;
+}
+#endif
/*
@@ -525,44 +583,104 @@ void sqlite3ExprListDelete(ExprList *pList){
}
/*
-** Walk an expression tree. Return 1 if the expression is constant
-** and 0 if it involves variables.
+** Walk an expression tree. Call xFunc for each node visited.
**
-** For the purposes of this function, a double-quoted string (ex: "abc")
-** is considered a variable but a single-quoted string (ex: 'abc') is
-** a constant.
+** The return value from xFunc determines whether the tree walk continues.
+** 0 means continue walking the tree. 1 means do not walk children
+** of the current node but continue with siblings. 2 means abandon
+** the tree walk completely.
+**
+** The return value from this routine is 1 to abandon the tree walk
+** and 0 to continue.
*/
-int sqlite3ExprIsConstant(Expr *p){
- switch( p->op ){
+static int walkExprList(ExprList *, int (*)(void *, Expr*), void *);
+static int walkExprTree(Expr *pExpr, int (*xFunc)(void*,Expr*), void *pArg){
+ int rc;
+ if( pExpr==0 ) return 0;
+ rc = (*xFunc)(pArg, pExpr);
+ if( rc==0 ){
+ if( walkExprTree(pExpr->pLeft, xFunc, pArg) ) return 1;
+ if( walkExprTree(pExpr->pRight, xFunc, pArg) ) return 1;
+ if( walkExprList(pExpr->pList, xFunc, pArg) ) return 1;
+ }
+ return rc>1;
+}
+
+/*
+** Call walkExprTree() for every expression in list p.
+*/
+static int walkExprList(ExprList *p, int (*xFunc)(void *, Expr*), void *pArg){
+ int i;
+ struct ExprList_item *pItem;
+ if( !p ) return 0;
+ for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){
+ if( walkExprTree(pItem->pExpr, xFunc, pArg) ) return 1;
+ }
+ return 0;
+}
+
+/*
+** Call walkExprTree() for every expression in Select p, not including
+** expressions that are part of sub-selects in any FROM clause or the LIMIT
+** or OFFSET expressions..
+*/
+static int walkSelectExpr(Select *p, int (*xFunc)(void *, Expr*), void *pArg){
+ walkExprList(p->pEList, xFunc, pArg);
+ walkExprTree(p->pWhere, xFunc, pArg);
+ walkExprList(p->pGroupBy, xFunc, pArg);
+ walkExprTree(p->pHaving, xFunc, pArg);
+ walkExprList(p->pOrderBy, xFunc, pArg);
+ return 0;
+}
+
+
+/*
+** This routine is designed as an xFunc for walkExprTree().
+**
+** pArg is really a pointer to an integer. If we can tell by looking
+** at pExpr that the expression that contains pExpr is not a constant
+** expression, then set *pArg to 0 and return 2 to abandon the tree walk.
+** If pExpr does does not disqualify the expression from being a constant
+** then do nothing.
+**
+** After walking the whole tree, if no nodes are found that disqualify
+** the expression as constant, then we assume the whole expression
+** is constant. See sqlite3ExprIsConstant() for additional information.
+*/
+static int exprNodeIsConstant(void *pArg, Expr *pExpr){
+ switch( pExpr->op ){
case TK_ID:
case TK_COLUMN:
case TK_DOT:
+ case TK_AGG_FUNCTION:
case TK_FUNCTION:
+#ifndef SQLITE_OMIT_SUBQUERY
+ case TK_SELECT:
+ case TK_EXISTS:
+#endif
+ *((int*)pArg) = 0;
+ return 2;
+ default:
return 0;
- case TK_NULL:
- case TK_STRING:
- case TK_BLOB:
- case TK_INTEGER:
- case TK_FLOAT:
- case TK_VARIABLE:
- return 1;
- default: {
- if( p->pLeft && !sqlite3ExprIsConstant(p->pLeft) ) return 0;
- if( p->pRight && !sqlite3ExprIsConstant(p->pRight) ) return 0;
- if( p->pList ){
- int i;
- for(i=0; i<p->pList->nExpr; i++){
- if( !sqlite3ExprIsConstant(p->pList->a[i].pExpr) ) return 0;
- }
- }
- return p->pLeft!=0 || p->pRight!=0 || (p->pList && p->pList->nExpr>0);
- }
}
- return 0;
}
/*
-** If the given expression codes a constant integer that is small enough
+** Walk an expression tree. Return 1 if the expression is constant
+** and 0 if it involves variables.
+**
+** For the purposes of this function, a double-quoted string (ex: "abc")
+** is considered a variable but a single-quoted string (ex: 'abc') is
+** a constant.
+*/
+int sqlite3ExprIsConstant(Expr *p){
+ int isConst = 1;
+ walkExprTree(p, exprNodeIsConstant, &isConst);
+ return isConst;
+}
+
+/*
+** If the expression p codes a constant integer that is small enough
** to fit in a 32-bit integer, return 1 and put the value of the integer
** in *pValue. If the expression is not an integer or if it is too big
** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.
@@ -575,16 +693,6 @@ int sqlite3ExprIsInteger(Expr *p, int *pValue){
}
break;
}
- case TK_STRING: {
- const u8 *z = (u8*)p->token.z;
- int n = p->token.n;
- if( n>0 && z[0]=='-' ){ z++; n--; }
- while( n>0 && *z && isdigit(*z) ){ z++; n--; }
- if( n==0 && sqlite3GetInt32(p->token.z, pValue) ){
- return 1;
- }
- break;
- }
case TK_UPLUS: {
return sqlite3ExprIsInteger(p->pLeft, pValue);
}
@@ -641,8 +749,7 @@ static int lookupName(
Token *pDbToken, /* Name of the database containing table, or NULL */
Token *pTableToken, /* Name of table containing column, or NULL */
Token *pColumnToken, /* Name of the column. */
- SrcList *pSrcList, /* List of tables used to resolve column names */
- ExprList *pEList, /* List of expressions used to resolve "AS" */
+ NameContext *pNC, /* The name context used to resolve the name */
Expr *pExpr /* Make this EXPR node point to the selected column */
){
char *zDb = 0; /* Name of the database. The "X" in X.Y.Z */
@@ -652,6 +759,9 @@ static int lookupName(
int cnt = 0; /* Number of matching column names */
int cntTab = 0; /* Number of matching table names */
sqlite3 *db = pParse->db; /* The database */
+ struct SrcList_item *pItem; /* Use for looping over pSrcList items */
+ struct SrcList_item *pMatch = 0; /* The matching pSrcList item */
+ NameContext *pTopNC = pNC; /* First namecontext in the list */
assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */
zDb = sqlite3NameFromToken(pDbToken);
@@ -660,114 +770,132 @@ static int lookupName(
if( sqlite3_malloc_failed ){
return 1; /* Leak memory (zDb and zTab) if malloc fails */
}
- assert( zTab==0 || pEList==0 );
pExpr->iTable = -1;
- for(i=0; i<pSrcList->nSrc; i++){
- struct SrcList_item *pItem = &pSrcList->a[i];
- Table *pTab = pItem->pTab;
- Column *pCol;
-
- if( pTab==0 ) continue;
- assert( pTab->nCol>0 );
- if( zTab ){
- if( pItem->zAlias ){
- char *zTabName = pItem->zAlias;
- if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
- }else{
- char *zTabName = pTab->zName;
- if( zTabName==0 || sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
- if( zDb!=0 && sqlite3StrICmp(db->aDb[pTab->iDb].zName, zDb)!=0 ){
- continue;
+ while( pNC && cnt==0 ){
+ SrcList *pSrcList = pNC->pSrcList;
+ ExprList *pEList = pNC->pEList;
+
+ pNC->nRef++;
+ /* assert( zTab==0 || pEList==0 ); */
+ if( pSrcList ){
+ for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
+ Table *pTab = pItem->pTab;
+ Column *pCol;
+
+ if( pTab==0 ) continue;
+ assert( pTab->nCol>0 );
+ if( zTab ){
+ if( pItem->zAlias ){
+ char *zTabName = pItem->zAlias;
+ if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
+ }else{
+ char *zTabName = pTab->zName;
+ if( zTabName==0 || sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
+ if( zDb!=0 && sqlite3StrICmp(db->aDb[pTab->iDb].zName, zDb)!=0 ){
+ continue;
+ }
+ }
+ }
+ if( 0==(cntTab++) ){
+ pExpr->iTable = pItem->iCursor;
+ pExpr->iDb = pTab->iDb;
+ pMatch = pItem;
+ }
+ for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
+ if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
+ cnt++;
+ pExpr->iTable = pItem->iCursor;
+ pMatch = pItem;
+ pExpr->iDb = pTab->iDb;
+ /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
+ pExpr->iColumn = j==pTab->iPKey ? -1 : j;
+ pExpr->affinity = pTab->aCol[j].affinity;
+ pExpr->pColl = pTab->aCol[j].pColl;
+ break;
+ }
}
}
}
- if( 0==(cntTab++) ){
- pExpr->iTable = pItem->iCursor;
- pExpr->iDb = pTab->iDb;
- }
- for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
- if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
- cnt++;
- pExpr->iTable = pItem->iCursor;
- pExpr->iDb = pTab->iDb;
- /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
- pExpr->iColumn = j==pTab->iPKey ? -1 : j;
- pExpr->affinity = pTab->aCol[j].affinity;
- pExpr->pColl = pTab->aCol[j].pColl;
- break;
+
+#ifndef SQLITE_OMIT_TRIGGER
+ /* If we have not already resolved the name, then maybe
+ ** it is a new.* or old.* trigger argument reference
+ */
+ if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){
+ TriggerStack *pTriggerStack = pParse->trigStack;
+ Table *pTab = 0;
+ if( pTriggerStack->newIdx != -1 && sqlite3StrICmp("new", zTab) == 0 ){
+ pExpr->iTable = pTriggerStack->newIdx;
+ assert( pTriggerStack->pTab );
+ pTab = pTriggerStack->pTab;
+ }else if( pTriggerStack->oldIdx != -1 && sqlite3StrICmp("old", zTab)==0 ){
+ pExpr->iTable = pTriggerStack->oldIdx;
+ assert( pTriggerStack->pTab );
+ pTab = pTriggerStack->pTab;
}
- }
- }
- /* If we have not already resolved the name, then maybe
- ** it is a new.* or old.* trigger argument reference
- */
- if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){
- TriggerStack *pTriggerStack = pParse->trigStack;
- Table *pTab = 0;
- if( pTriggerStack->newIdx != -1 && sqlite3StrICmp("new", zTab) == 0 ){
- pExpr->iTable = pTriggerStack->newIdx;
- assert( pTriggerStack->pTab );
- pTab = pTriggerStack->pTab;
- }else if( pTriggerStack->oldIdx != -1 && sqlite3StrICmp("old", zTab) == 0 ){
- pExpr->iTable = pTriggerStack->oldIdx;
- assert( pTriggerStack->pTab );
- pTab = pTriggerStack->pTab;
- }
-
- if( pTab ){
- int j;
- Column *pCol = pTab->aCol;
-
- pExpr->iDb = pTab->iDb;
- cntTab++;
- for(j=0; j < pTab->nCol; j++, pCol++) {
- if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
- cnt++;
- pExpr->iColumn = j==pTab->iPKey ? -1 : j;
- pExpr->affinity = pTab->aCol[j].affinity;
- pExpr->pColl = pTab->aCol[j].pColl;
- break;
+ if( pTab ){
+ int j;
+ Column *pCol = pTab->aCol;
+
+ pExpr->iDb = pTab->iDb;
+ cntTab++;
+ for(j=0; j < pTab->nCol; j++, pCol++) {
+ if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
+ cnt++;
+ pExpr->iColumn = j==pTab->iPKey ? -1 : j;
+ pExpr->affinity = pTab->aCol[j].affinity;
+ pExpr->pColl = pTab->aCol[j].pColl;
+ break;
+ }
}
}
}
- }
+#endif /* !defined(SQLITE_OMIT_TRIGGER) */
- /*
- ** Perhaps the name is a reference to the ROWID
- */
- if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){
- cnt = 1;
- pExpr->iColumn = -1;
- pExpr->affinity = SQLITE_AFF_INTEGER;
- }
+ /*
+ ** Perhaps the name is a reference to the ROWID
+ */
+ if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){
+ cnt = 1;
+ pExpr->iColumn = -1;
+ pExpr->affinity = SQLITE_AFF_INTEGER;
+ }
- /*
- ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z
- ** might refer to an result-set alias. This happens, for example, when
- ** we are resolving names in the WHERE clause of the following command:
- **
- ** SELECT a+b AS x FROM table WHERE x<10;
- **
- ** In cases like this, replace pExpr with a copy of the expression that
- ** forms the result set entry ("a+b" in the example) and return immediately.
- ** Note that the expression in the result set should have already been
- ** resolved by the time the WHERE clause is resolved.
- */
- if( cnt==0 && pEList!=0 ){
- for(j=0; j<pEList->nExpr; j++){
- char *zAs = pEList->a[j].zName;
- if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
- assert( pExpr->pLeft==0 && pExpr->pRight==0 );
- pExpr->op = TK_AS;
- pExpr->iColumn = j;
- pExpr->pLeft = sqlite3ExprDup(pEList->a[j].pExpr);
- sqliteFree(zCol);
- assert( zTab==0 && zDb==0 );
- return 0;
- }
- }
+ /*
+ ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z
+ ** might refer to an result-set alias. This happens, for example, when
+ ** we are resolving names in the WHERE clause of the following command:
+ **
+ ** SELECT a+b AS x FROM table WHERE x<10;
+ **
+ ** In cases like this, replace pExpr with a copy of the expression that
+ ** forms the result set entry ("a+b" in the example) and return immediately.
+ ** Note that the expression in the result set should have already been
+ ** resolved by the time the WHERE clause is resolved.
+ */
+ if( cnt==0 && pEList!=0 && zTab==0 ){
+ for(j=0; j<pEList->nExpr; j++){
+ char *zAs = pEList->a[j].zName;
+ if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
+ assert( pExpr->pLeft==0 && pExpr->pRight==0 );
+ pExpr->op = TK_AS;
+ pExpr->iColumn = j;
+ pExpr->pLeft = sqlite3ExprDup(pEList->a[j].pExpr);
+ sqliteFree(zCol);
+ assert( zTab==0 && zDb==0 );
+ return 0;
+ }
+ }
+ }
+
+ /* Advance to the next name context. The loop will exit when either
+ ** we have a match (cnt>0) or when we run out of name contexts.
+ */
+ if( cnt==0 ){
+ pNC = pNC->pNext;
+ }
}
/*
@@ -799,6 +927,22 @@ static int lookupName(
}
sqlite3ErrorMsg(pParse, zErr, z);
sqliteFree(z);
+ pTopNC->nErr++;
+ }
+
+ /* If a column from a table in pSrcList is referenced, then record
+ ** this fact in the pSrcList.a[].colUsed bitmask. Column 0 causes
+ ** bit 0 to be set. Column 1 sets bit 1. And so forth. If the
+ ** column number is greater than the number of bits in the bitmask
+ ** then set the high-order bit of the bitmask.
+ */
+ if( pExpr->iColumn>=0 && pMatch!=0 ){
+ int n = pExpr->iColumn;
+ if( n>=sizeof(Bitmask)*8 ){
+ n = sizeof(Bitmask)*8-1;
+ }
+ assert( pMatch->iCursor==pExpr->iTable );
+ pMatch->colUsed |= 1<<n;
}
/* Clean up and return
@@ -811,53 +955,87 @@ static int lookupName(
sqlite3ExprDelete(pExpr->pRight);
pExpr->pRight = 0;
pExpr->op = TK_COLUMN;
- sqlite3AuthRead(pParse, pExpr, pSrcList);
+ if( cnt==1 ){
+ assert( pNC!=0 );
+ sqlite3AuthRead(pParse, pExpr, pNC->pSrcList);
+ }
return cnt!=1;
}
/*
-** This routine walks an expression tree and resolves references to
-** table columns. Nodes of the form ID.ID or ID resolve into an
-** index to the table in the table list and a column offset. The
-** Expr.opcode for such nodes is changed to TK_COLUMN. The Expr.iTable
-** value is changed to the index of the referenced table in pTabList
-** plus the "base" value. The base value will ultimately become the
-** VDBE cursor number for a cursor that is pointing into the referenced
-** table. The Expr.iColumn value is changed to the index of the column
-** of the referenced table. The Expr.iColumn value for the special
-** ROWID column is -1. Any INTEGER PRIMARY KEY column is tried as an
-** alias for ROWID.
-**
-** We also check for instances of the IN operator. IN comes in two
-** forms:
-**
-** expr IN (exprlist)
-** and
-** expr IN (SELECT ...)
+** pExpr is a node that defines a function of some kind. It might
+** be a syntactic function like "count(x)" or it might be a function
+** that implements an operator, like "a LIKE b".
**
-** The first form is handled by creating a set holding the list
-** of allowed values. The second form causes the SELECT to generate
-** a temporary table.
+** This routine makes *pzName point to the name of the function and
+** *pnName hold the number of characters in the function name.
+*/
+static void getFunctionName(Expr *pExpr, const char **pzName, int *pnName){
+ switch( pExpr->op ){
+ case TK_FUNCTION: {
+ *pzName = pExpr->token.z;
+ *pnName = pExpr->token.n;
+ break;
+ }
+ case TK_LIKE: {
+ *pzName = "like";
+ *pnName = 4;
+ break;
+ }
+ case TK_GLOB: {
+ *pzName = "glob";
+ *pnName = 4;
+ break;
+ }
+ case TK_CTIME: {
+ *pzName = "current_time";
+ *pnName = 12;
+ break;
+ }
+ case TK_CDATE: {
+ *pzName = "current_date";
+ *pnName = 12;
+ break;
+ }
+ case TK_CTIMESTAMP: {
+ *pzName = "current_timestamp";
+ *pnName = 17;
+ break;
+ }
+ }
+}
+
+/*
+** This routine is designed as an xFunc for walkExprTree().
**
-** This routine also looks for scalar SELECTs that are part of an expression.
-** If it finds any, it generates code to write the value of that select
-** into a memory cell.
+** Resolve symbolic names into TK_COLUMN operators for the current
+** node in the expression tree. Return 0 to continue the search down
+** the tree or 2 to abort the tree walk.
**
-** Unknown columns or tables provoke an error. The function returns
-** the number of errors seen and leaves an error message on pParse->zErrMsg.
+** This routine also does error checking and name resolution for
+** function names. The operator for aggregate functions is changed
+** to TK_AGG_FUNCTION.
*/
-int sqlite3ExprResolveIds(
- Parse *pParse, /* The parser context */
- SrcList *pSrcList, /* List of tables used to resolve column names */
- ExprList *pEList, /* List of expressions used to resolve "AS" */
- Expr *pExpr /* The expression to be analyzed. */
-){
- int i;
-
- if( pExpr==0 || pSrcList==0 ) return 0;
- for(i=0; i<pSrcList->nSrc; i++){
- assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab );
+static int nameResolverStep(void *pArg, Expr *pExpr){
+ NameContext *pNC = (NameContext*)pArg;
+ SrcList *pSrcList;
+ Parse *pParse;
+
+ if( pExpr==0 ) return 1;
+ assert( pNC!=0 );
+ pSrcList = pNC->pSrcList;
+ pParse = pNC->pParse;
+
+ if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return 1;
+ ExprSetProperty(pExpr, EP_Resolved);
+#ifndef NDEBUG
+ if( pSrcList ){
+ int i;
+ for(i=0; i<pSrcList->nSrc; i++){
+ assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab);
+ }
}
+#endif
switch( pExpr->op ){
/* Double-quoted strings (ex: "abc") are used as identifiers if
** possible. Otherwise they remain as strings. Single-quoted
@@ -867,13 +1045,11 @@ int sqlite3ExprResolveIds(
if( pExpr->token.z[0]=='\'' ) break;
/* Fall thru into the TK_ID case if this is a double-quoted string */
}
- /* A lone identifier is the name of a columnd.
+ /* A lone identifier is the name of a column.
*/
case TK_ID: {
- if( lookupName(pParse, 0, 0, &pExpr->token, pSrcList, pEList, pExpr) ){
- return 1;
- }
- break;
+ lookupName(pParse, 0, 0, &pExpr->token, pNC, pExpr);
+ return 1;
}
/* A table name and column name: ID.ID
@@ -885,6 +1061,7 @@ int sqlite3ExprResolveIds(
Token *pDb;
Expr *pRight;
+ /* if( pSrcList==0 ) break; */
pRight = pExpr->pRight;
if( pRight->op==TK_ID ){
pDb = 0;
@@ -896,22 +1073,171 @@ int sqlite3ExprResolveIds(
pTable = &pRight->pLeft->token;
pColumn = &pRight->pRight->token;
}
- if( lookupName(pParse, pDb, pTable, pColumn, pSrcList, 0, pExpr) ){
- return 1;
+ lookupName(pParse, pDb, pTable, pColumn, pNC, pExpr);
+ return 1;
+ }
+
+ /* Resolve function names
+ */
+ case TK_CTIME:
+ case TK_CTIMESTAMP:
+ case TK_CDATE:
+ case TK_GLOB:
+ case TK_LIKE:
+ case TK_FUNCTION: {
+ ExprList *pList = pExpr->pList; /* The argument list */
+ int n = pList ? pList->nExpr : 0; /* Number of arguments */
+ int no_such_func = 0; /* True if no such function exists */
+ int wrong_num_args = 0; /* True if wrong number of arguments */
+ int is_agg = 0; /* True if is an aggregate function */
+ int i;
+ int nId; /* Number of characters in function name */
+ const char *zId; /* The function name. */
+ FuncDef *pDef; /* Information about the function */
+ int enc = pParse->db->enc; /* The database encoding */
+
+ getFunctionName(pExpr, &zId, &nId);
+ pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
+ if( pDef==0 ){
+ pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0);
+ if( pDef==0 ){
+ no_such_func = 1;
+ }else{
+ wrong_num_args = 1;
+ }
+ }else{
+ is_agg = pDef->xFunc==0;
+ }
+ if( is_agg && !pNC->allowAgg ){
+ sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
+ pNC->nErr++;
+ is_agg = 0;
+ }else if( no_such_func ){
+ sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
+ pNC->nErr++;
+ }else if( wrong_num_args ){
+ sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
+ nId, zId);
+ pNC->nErr++;
+ }
+ if( is_agg ){
+ pExpr->op = TK_AGG_FUNCTION;
+ pNC->hasAgg = 1;
+ }
+ if( is_agg ) pNC->allowAgg = 0;
+ for(i=0; pNC->nErr==0 && i<n; i++){
+ walkExprTree(pList->a[i].pExpr, nameResolverStep, pNC);
+ }
+ if( is_agg ) pNC->allowAgg = 1;
+ /* FIX ME: Compute pExpr->affinity based on the expected return
+ ** type of the function
+ */
+ return is_agg;
+ }
+#ifndef SQLITE_OMIT_SUBQUERY
+ case TK_SELECT:
+ case TK_EXISTS:
+#endif
+ case TK_IN: {
+ if( pExpr->pSelect ){
+ int nRef = pNC->nRef;
+ sqlite3SelectResolve(pParse, pExpr->pSelect, pNC);
+ assert( pNC->nRef>=nRef );
+ if( nRef!=pNC->nRef ){
+ ExprSetProperty(pExpr, EP_VarSelect);
+ }
}
- break;
}
+ }
+ return 0;
+}
+/*
+** This routine walks an expression tree and resolves references to
+** table columns. Nodes of the form ID.ID or ID resolve into an
+** index to the table in the table list and a column offset. The
+** Expr.opcode for such nodes is changed to TK_COLUMN. The Expr.iTable
+** value is changed to the index of the referenced table in pTabList
+** plus the "base" value. The base value will ultimately become the
+** VDBE cursor number for a cursor that is pointing into the referenced
+** table. The Expr.iColumn value is changed to the index of the column
+** of the referenced table. The Expr.iColumn value for the special
+** ROWID column is -1. Any INTEGER PRIMARY KEY column is tried as an
+** alias for ROWID.
+**
+** Also resolve function names and check the functions for proper
+** usage. Make sure all function names are recognized and all functions
+** have the correct number of arguments. Leave an error message
+** in pParse->zErrMsg if anything is amiss. Return the number of errors.
+**
+** If the expression contains aggregate functions then set the EP_Agg
+** property on the expression.
+*/
+int sqlite3ExprResolveNames(
+ NameContext *pNC, /* Namespace to resolve expressions in. */
+ Expr *pExpr /* The expression to be analyzed. */
+){
+ if( pExpr==0 ) return 0;
+ walkExprTree(pExpr, nameResolverStep, pNC);
+ if( pNC->nErr>0 ){
+ ExprSetProperty(pExpr, EP_Error);
+ }
+ return ExprHasProperty(pExpr, EP_Error);
+}
+
+/*
+** A pointer instance of this structure is used to pass information
+** through walkExprTree into codeSubqueryStep().
+*/
+typedef struct QueryCoder QueryCoder;
+struct QueryCoder {
+ Parse *pParse; /* The parsing context */
+ NameContext *pNC; /* Namespace of first enclosing query */
+};
+
+
+/*
+** Generate code for subqueries and IN operators.
+**
+** IN operators comes in two forms:
+**
+** expr IN (exprlist)
+** and
+** expr IN (SELECT ...)
+**
+** The first form is handled by creating a set holding the list
+** of allowed values. The second form causes the SELECT to generate
+** a temporary table.
+*/
+#ifndef SQLITE_OMIT_SUBQUERY
+void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
+ int label = 0; /* Address after sub-select code */
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ if( v==0 ) return;
+
+ /* If this is not a variable (correlated) select, then execute
+ ** it only once. Unless this is part of a trigger program. In
+ ** that case re-execute every time (this could be optimized).
+ */
+ if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->trigStack ){
+ int mem = pParse->nMem++;
+ sqlite3VdbeAddOp(v, OP_MemLoad, mem, 0);
+ label = sqlite3VdbeMakeLabel(v);
+ sqlite3VdbeAddOp(v, OP_If, 0, label);
+ sqlite3VdbeAddOp(v, OP_Integer, 1, 0);
+ sqlite3VdbeAddOp(v, OP_MemStore, mem, 1);
+ }
+
+ if( pExpr->pSelect ){
+ sqlite3VdbeAddOp(v, OP_AggContextPush, 0, 0);
+ }
+
+ switch( pExpr->op ){
case TK_IN: {
char affinity;
- Vdbe *v = sqlite3GetVdbe(pParse);
KeyInfo keyInfo;
int addr; /* Address of OP_OpenTemp instruction */
- if( v==0 ) return 1;
- if( sqlite3ExprResolveIds(pParse, pSrcList, pEList, pExpr->pLeft) ){
- return 1;
- }
affinity = sqlite3ExprAffinity(pExpr->pLeft);
/* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
@@ -970,10 +1296,7 @@ int sqlite3ExprResolveIds(
if( !sqlite3ExprIsConstant(pE2) ){
sqlite3ErrorMsg(pParse,
"right-hand side of IN operator must be constant");
- return 1;
- }
- if( sqlite3ExprCheck(pParse, pE2, 0, 0) ){
- return 1;
+ return;
}
/* Evaluate the expression and insert it into the temp table */
@@ -984,183 +1307,43 @@ int sqlite3ExprResolveIds(
}
}
sqlite3VdbeChangeP3(v, addr, (void *)&keyInfo, P3_KEYINFO);
-
break;
}
+ case TK_EXISTS:
case TK_SELECT: {
/* This has to be a scalar SELECT. Generate code to put the
** value of this select in a memory cell and record the number
** of the memory cell in iColumn.
*/
- pExpr->iColumn = pParse->nMem++;
- if(sqlite3Select(pParse, pExpr->pSelect, SRT_Mem,pExpr->iColumn,0,0,0,0)){
- return 1;
- }
- break;
- }
-
- /* For all else, just recursively walk the tree */
- default: {
- if( pExpr->pLeft
- && sqlite3ExprResolveIds(pParse, pSrcList, pEList, pExpr->pLeft) ){
- return 1;
- }
- if( pExpr->pRight
- && sqlite3ExprResolveIds(pParse, pSrcList, pEList, pExpr->pRight) ){
- return 1;
- }
- if( pExpr->pList ){
- int i;
- ExprList *pList = pExpr->pList;
- for(i=0; i<pList->nExpr; i++){
- Expr *pArg = pList->a[i].pExpr;
- if( sqlite3ExprResolveIds(pParse, pSrcList, pEList, pArg) ){
- return 1;
- }
- }
- }
- }
- }
- return 0;
-}
-
-/*
-** pExpr is a node that defines a function of some kind. It might
-** be a syntactic function like "count(x)" or it might be a function
-** that implements an operator, like "a LIKE b".
-**
-** This routine makes *pzName point to the name of the function and
-** *pnName hold the number of characters in the function name.
-*/
-static void getFunctionName(Expr *pExpr, const char **pzName, int *pnName){
- switch( pExpr->op ){
- case TK_FUNCTION: {
- *pzName = pExpr->token.z;
- *pnName = pExpr->token.n;
- break;
- }
- case TK_LIKE: {
- *pzName = "like";
- *pnName = 4;
- break;
- }
- case TK_GLOB: {
- *pzName = "glob";
- *pnName = 4;
- break;
- }
- default: {
- *pzName = "can't happen";
- *pnName = 12;
- break;
- }
- }
-}
-
-/*
-** Error check the functions in an expression. Make sure all
-** function names are recognized and all functions have the correct
-** number of arguments. Leave an error message in pParse->zErrMsg
-** if anything is amiss. Return the number of errors.
-**
-** if pIsAgg is not null and this expression is an aggregate function
-** (like count(*) or max(value)) then write a 1 into *pIsAgg.
-*/
-int sqlite3ExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg){
- int nErr = 0;
- if( pExpr==0 ) return 0;
- switch( pExpr->op ){
- case TK_GLOB:
- case TK_LIKE:
- case TK_FUNCTION: {
- int n = pExpr->pList ? pExpr->pList->nExpr : 0; /* Number of arguments */
- int no_such_func = 0; /* True if no such function exists */
- int wrong_num_args = 0; /* True if wrong number of arguments */
- int is_agg = 0; /* True if is an aggregate function */
- int i;
- int nId; /* Number of characters in function name */
- const char *zId; /* The function name. */
- FuncDef *pDef;
- int enc = pParse->db->enc;
+ int sop;
+ Select *pSel;
- getFunctionName(pExpr, &zId, &nId);
- pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
- if( pDef==0 ){
- pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0);
- if( pDef==0 ){
- no_such_func = 1;
- }else{
- wrong_num_args = 1;
- }
+ pExpr->iColumn = pParse->nMem++;
+ pSel = pExpr->pSelect;
+ if( pExpr->op==TK_SELECT ){
+ sop = SRT_Mem;
}else{
- is_agg = pDef->xFunc==0;
- }
- if( is_agg && !allowAgg ){
- sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId, zId);
- nErr++;
- is_agg = 0;
- }else if( no_such_func ){
- sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
- nErr++;
- }else if( wrong_num_args ){
- sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
- nId, zId);
- nErr++;
- }
- if( is_agg ){
- pExpr->op = TK_AGG_FUNCTION;
- if( pIsAgg ) *pIsAgg = 1;
- }
- for(i=0; nErr==0 && i<n; i++){
- nErr = sqlite3ExprCheck(pParse, pExpr->pList->a[i].pExpr,
- allowAgg && !is_agg, pIsAgg);
- }
- /* FIX ME: Compute pExpr->affinity based on the expected return
- ** type of the function
- */
- }
- default: {
- if( pExpr->pLeft ){
- nErr = sqlite3ExprCheck(pParse, pExpr->pLeft, allowAgg, pIsAgg);
- }
- if( nErr==0 && pExpr->pRight ){
- nErr = sqlite3ExprCheck(pParse, pExpr->pRight, allowAgg, pIsAgg);
- }
- if( nErr==0 && pExpr->pList ){
- int n = pExpr->pList->nExpr;
- int i;
- for(i=0; nErr==0 && i<n; i++){
- Expr *pE2 = pExpr->pList->a[i].pExpr;
- nErr = sqlite3ExprCheck(pParse, pE2, allowAgg, pIsAgg);
- }
+ static const Token one = { "1", 0, 1 };
+ sop = SRT_Exists;
+ sqlite3ExprListDelete(pSel->pEList);
+ pSel->pEList = sqlite3ExprListAppend(0,
+ sqlite3Expr(TK_INTEGER, 0, 0, &one), 0);
}
+ sqlite3Select(pParse, pSel, sop, pExpr->iColumn, 0, 0, 0, 0);
break;
}
}
- return nErr;
-}
-/*
-** Call sqlite3ExprResolveIds() followed by sqlite3ExprCheck().
-**
-** This routine is provided as a convenience since it is very common
-** to call ResolveIds() and Check() back to back.
-*/
-int sqlite3ExprResolveAndCheck(
- Parse *pParse, /* The parser context */
- SrcList *pSrcList, /* List of tables used to resolve column names */
- ExprList *pEList, /* List of expressions used to resolve "AS" */
- Expr *pExpr, /* The expression to be analyzed. */
- int allowAgg, /* True to allow aggregate expressions */
- int *pIsAgg /* Set to TRUE if aggregates are found */
-){
- if( pExpr==0 ) return 0;
- if( sqlite3ExprResolveIds(pParse,pSrcList,pEList,pExpr) ){
- return 1;
+ if( pExpr->pSelect ){
+ sqlite3VdbeAddOp(v, OP_AggContextPop, 0, 0);
+ }
+ if( label<0 ){
+ sqlite3VdbeResolveLabel(v, label);
}
- return sqlite3ExprCheck(pParse, pExpr, allowAgg, pIsAgg);
+ return;
}
+#endif /* SQLITE_OMIT_SUBQUERY */
/*
** Generate an instruction that will put the integer describe by
@@ -1190,12 +1373,16 @@ static void codeInteger(Vdbe *v, const char *z, int n){
void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
Vdbe *v = pParse->pVdbe;
int op;
- if( v==0 || pExpr==0 ) return;
+ if( v==0 ) return;
+ if( pExpr==0 ){
+ sqlite3VdbeAddOp(v, OP_String8, 0, 0); /* Empty expression evals to NULL */
+ return;
+ }
op = pExpr->op;
switch( op ){
case TK_COLUMN: {
- if( pParse->useAgg ){
- sqlite3VdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg);
+ if( !pParse->fillAgg && pExpr->iAgg>=0 ){
+ sqlite3VdbeAddOp(v, OP_AggGet, pExpr->iAggCtx, pExpr->iAgg);
}else if( pExpr->iColumn>=0 ){
sqlite3VdbeAddOp(v, OP_Column, pExpr->iTable, pExpr->iColumn);
#ifndef NDEBUG
@@ -1220,12 +1407,14 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
sqlite3VdbeDequoteP3(v, -1);
break;
}
+#ifndef SQLITE_OMIT_BLOB_LITERAL
case TK_BLOB: {
assert( TK_BLOB==OP_HexBlob );
sqlite3VdbeOp3(v, op, 0, 0, pExpr->token.z+1, pExpr->token.n-1);
sqlite3VdbeDequoteP3(v, -1);
break;
}
+#endif
case TK_NULL: {
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
break;
@@ -1237,6 +1426,10 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
}
break;
}
+ case TK_REGISTER: {
+ sqlite3VdbeAddOp(v, OP_MemLoad, pExpr->iTable, 0);
+ break;
+ }
case TK_LT:
case TK_LE:
case TK_GT:
@@ -1323,6 +1516,9 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
sqlite3VdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg);
break;
}
+ case TK_CDATE:
+ case TK_CTIME:
+ case TK_CTIMESTAMP:
case TK_GLOB:
case TK_LIKE:
case TK_FUNCTION: {
@@ -1354,7 +1550,10 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
sqlite3VdbeOp3(v, OP_Function, nExpr, p2, (char*)pDef, P3_FUNCDEF);
break;
}
+#ifndef SQLITE_OMIT_SUBQUERY
+ case TK_EXISTS:
case TK_SELECT: {
+ sqlite3CodeSubselect(pParse, pExpr);
sqlite3VdbeAddOp(v, OP_MemLoad, pExpr->iColumn, 0);
VdbeComment((v, "# load subquery result"));
break;
@@ -1362,6 +1561,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
case TK_IN: {
int addr;
char affinity;
+ sqlite3CodeSubselect(pParse, pExpr);
/* Figure out the affinity to use to create a key from the results
** of the expression. affinityStr stores a static string suitable for
@@ -1386,6 +1586,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
break;
}
+#endif
case TK_BETWEEN: {
Expr *pLeft = pExpr->pLeft;
struct ExprList_item *pLItem = pExpr->pList->a;
@@ -1452,6 +1653,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
sqlite3VdbeResolveLabel(v, expr_end_label);
break;
}
+#ifndef SQLITE_OMIT_TRIGGER
case TK_RAISE: {
if( !pParse->trigStack ){
sqlite3ErrorMsg(pParse,
@@ -1472,10 +1674,38 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
VdbeComment((v, "# raise(IGNORE)"));
}
}
+#endif
break;
}
}
+#ifndef SQLITE_OMIT_TRIGGER
+/*
+** Generate code that evalutes the given expression and leaves the result
+** on the stack. See also sqlite3ExprCode().
+**
+** This routine might also cache the result and modify the pExpr tree
+** so that it will make use of the cached result on subsequent evaluations
+** rather than evaluate the whole expression again. Trivial expressions are
+** not cached. If the expression is cached, its result is stored in a
+** memory location.
+*/
+void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr){
+ Vdbe *v = pParse->pVdbe;
+ int iMem;
+ int addr1, addr2;
+ if( v==0 ) return;
+ addr1 = sqlite3VdbeCurrentAddr(v);
+ sqlite3ExprCode(pParse, pExpr);
+ addr2 = sqlite3VdbeCurrentAddr(v);
+ if( addr2>addr1+1 || sqlite3VdbeGetOp(v, addr1)->opcode==OP_Function ){
+ iMem = pExpr->iTable = pParse->nMem++;
+ sqlite3VdbeAddOp(v, OP_MemStore, iMem, 0);
+ pExpr->op = TK_REGISTER;
+ }
+}
+#endif
+
/*
** Generate code that pushes the value of every element of the given
** expression list onto the stack.
@@ -1737,6 +1967,8 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){
/*
** Add a new element to the pParse->aAgg[] array and return its index.
+** The new element is initialized to zero. The calling function is
+** expected to fill it in.
*/
static int appendAggInfo(Parse *pParse){
if( (pParse->nAgg & 0x7)==0 ){
@@ -1752,80 +1984,91 @@ static int appendAggInfo(Parse *pParse){
}
/*
-** Analyze the given expression looking for aggregate functions and
-** for variables that need to be added to the pParse->aAgg[] array.
-** Make additional entries to the pParse->aAgg[] array as necessary.
+** This is an xFunc for walkExprTree() used to implement
+** sqlite3ExprAnalyzeAggregates(). See sqlite3ExprAnalyzeAggregates
+** for additional information.
**
-** This routine should only be called after the expression has been
-** analyzed by sqlite3ExprResolveIds() and sqlite3ExprCheck().
-**
-** If errors are seen, leave an error message in zErrMsg and return
-** the number of errors.
+** This routine analyzes the aggregate function at pExpr.
*/
-int sqlite3ExprAnalyzeAggregates(Parse *pParse, Expr *pExpr){
+static int analyzeAggregate(void *pArg, Expr *pExpr){
int i;
AggExpr *aAgg;
- int nErr = 0;
+ NameContext *pNC = (NameContext *)pArg;
+ Parse *pParse = pNC->pParse;
+ SrcList *pSrcList = pNC->pSrcList;
- if( pExpr==0 ) return 0;
switch( pExpr->op ){
case TK_COLUMN: {
- aAgg = pParse->aAgg;
- for(i=0; i<pParse->nAgg; i++){
- if( aAgg[i].isAgg ) continue;
- if( aAgg[i].pExpr->iTable==pExpr->iTable
- && aAgg[i].pExpr->iColumn==pExpr->iColumn ){
- break;
+ for(i=0; pSrcList && i<pSrcList->nSrc; i++){
+ if( pExpr->iTable==pSrcList->a[i].iCursor ){
+ aAgg = pParse->aAgg;
+ for(i=0; i<pParse->nAgg; i++){
+ if( aAgg[i].isAgg ) continue;
+ if( aAgg[i].pExpr->iTable==pExpr->iTable
+ && aAgg[i].pExpr->iColumn==pExpr->iColumn ){
+ break;
+ }
+ }
+ if( i>=pParse->nAgg ){
+ i = appendAggInfo(pParse);
+ if( i<0 ) return 1;
+ pParse->aAgg[i].isAgg = 0;
+ pParse->aAgg[i].pExpr = pExpr;
+ }
+ pExpr->iAgg = i;
+ pExpr->iAggCtx = pNC->nDepth;
+ return 1;
}
}
- if( i>=pParse->nAgg ){
- i = appendAggInfo(pParse);
- if( i<0 ) return 1;
- pParse->aAgg[i].isAgg = 0;
- pParse->aAgg[i].pExpr = pExpr;
- }
- pExpr->iAgg = i;
- break;
+ return 1;
}
case TK_AGG_FUNCTION: {
- aAgg = pParse->aAgg;
- for(i=0; i<pParse->nAgg; i++){
- if( !aAgg[i].isAgg ) continue;
- if( sqlite3ExprCompare(aAgg[i].pExpr, pExpr) ){
- break;
+ if( pNC->nDepth==0 ){
+ aAgg = pParse->aAgg;
+ for(i=0; i<pParse->nAgg; i++){
+ if( !aAgg[i].isAgg ) continue;
+ if( sqlite3ExprCompare(aAgg[i].pExpr, pExpr) ){
+ break;
+ }
}
- }
- if( i>=pParse->nAgg ){
- u8 enc = pParse->db->enc;
- i = appendAggInfo(pParse);
- if( i<0 ) return 1;
- pParse->aAgg[i].isAgg = 1;
- pParse->aAgg[i].pExpr = pExpr;
- pParse->aAgg[i].pFunc = sqlite3FindFunction(pParse->db,
- pExpr->token.z, pExpr->token.n,
- pExpr->pList ? pExpr->pList->nExpr : 0, enc, 0);
- }
- pExpr->iAgg = i;
- break;
- }
- default: {
- if( pExpr->pLeft ){
- nErr = sqlite3ExprAnalyzeAggregates(pParse, pExpr->pLeft);
- }
- if( nErr==0 && pExpr->pRight ){
- nErr = sqlite3ExprAnalyzeAggregates(pParse, pExpr->pRight);
- }
- if( nErr==0 && pExpr->pList ){
- int n = pExpr->pList->nExpr;
- int i;
- for(i=0; nErr==0 && i<n; i++){
- nErr = sqlite3ExprAnalyzeAggregates(pParse, pExpr->pList->a[i].pExpr);
+ if( i>=pParse->nAgg ){
+ u8 enc = pParse->db->enc;
+ i = appendAggInfo(pParse);
+ if( i<0 ) return 1;
+ pParse->aAgg[i].isAgg = 1;
+ pParse->aAgg[i].pExpr = pExpr;
+ pParse->aAgg[i].pFunc = sqlite3FindFunction(pParse->db,
+ pExpr->token.z, pExpr->token.n,
+ pExpr->pList ? pExpr->pList->nExpr : 0, enc, 0);
}
+ pExpr->iAgg = i;
+ return 1;
}
- break;
}
}
- return nErr;
+ if( pExpr->pSelect ){
+ pNC->nDepth++;
+ walkSelectExpr(pExpr->pSelect, analyzeAggregate, pNC);
+ pNC->nDepth--;
+ }
+ return 0;
+}
+
+/*
+** Analyze the given expression looking for aggregate functions and
+** for variables that need to be added to the pParse->aAgg[] array.
+** Make additional entries to the pParse->aAgg[] array as necessary.
+**
+** This routine should only be called after the expression has been
+** analyzed by sqlite3ExprResolveNames().
+**
+** If errors are seen, leave an error message in zErrMsg and return
+** the number of errors.
+*/
+int sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
+ int nErr = pNC->pParse->nErr;
+ walkExprTree(pExpr, analyzeAggregate, pNC);
+ return pNC->pParse->nErr - nErr;
}
/*
@@ -1917,7 +2160,10 @@ FuncDef *sqlite3FindFunction(
pBest->iPrefEnc = enc;
memcpy(pBest->zName, zName, nName);
pBest->zName[nName] = 0;
- sqlite3HashInsert(&db->aFunc, pBest->zName, nName, (void*)pBest);
+ if( pBest==sqlite3HashInsert(&db->aFunc,pBest->zName,nName,(void*)pBest) ){
+ sqliteFree(pBest);
+ return 0;
+ }
}
if( pBest && (pBest->xStep || pBest->xFunc || createFlag) ){
diff --git a/ext/pdo_sqlite/sqlite/src/func.c b/ext/pdo_sqlite/sqlite/src/func.c
index f61bdae3fd..49ceed39ea 100644
--- a/ext/pdo_sqlite/sqlite/src/func.c
+++ b/ext/pdo_sqlite/sqlite/src/func.c
@@ -18,11 +18,11 @@
**
** $Id$
*/
+#include "sqliteInt.h"
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
-#include "sqliteInt.h"
#include "vdbeInt.h"
#include "os.h"
@@ -347,10 +347,11 @@ static const struct compareInfo likeInfo = { '%', '_', 0, 1 };
**
** abc[*]xyz Matches "abc*xyz" only
*/
-int patternCompare(
+static int patternCompare(
const u8 *zPattern, /* The glob pattern */
const u8 *zString, /* The string to compare against the glob */
- const struct compareInfo *pInfo /* Information about how to do the compare */
+ const struct compareInfo *pInfo, /* Information about how to do the compare */
+ const int esc /* The escape character */
){
register int c;
int invert;
@@ -360,9 +361,10 @@ int patternCompare(
u8 matchAll = pInfo->matchAll;
u8 matchSet = pInfo->matchSet;
u8 noCase = pInfo->noCase;
+ int prevEscape = 0; /* True if the previous character was 'escape' */
while( (c = *zPattern)!=0 ){
- if( c==matchAll ){
+ if( !prevEscape && c==matchAll ){
while( (c=zPattern[1]) == matchAll || c == matchOne ){
if( c==matchOne ){
if( *zString==0 ) return 0;
@@ -370,9 +372,15 @@ int patternCompare(
}
zPattern++;
}
+ if( c && esc && sqlite3ReadUtf8(&zPattern[1])==esc ){
+ u8 const *zTemp = &zPattern[1];
+ sqliteNextChar(zTemp);
+ c = *zTemp;
+ }
if( c==0 ) return 1;
if( c==matchSet ){
- while( *zString && patternCompare(&zPattern[1],zString,pInfo)==0 ){
+ assert( esc==0 ); /* This is GLOB, not LIKE */
+ while( *zString && patternCompare(&zPattern[1],zString,pInfo,esc)==0 ){
sqliteNextChar(zString);
}
return *zString!=0;
@@ -386,17 +394,18 @@ int patternCompare(
while( c2 != 0 && c2 != c ){ c2 = *++zString; }
}
if( c2==0 ) return 0;
- if( patternCompare(&zPattern[1],zString,pInfo) ) return 1;
+ if( patternCompare(&zPattern[1],zString,pInfo,esc) ) return 1;
sqliteNextChar(zString);
}
return 0;
}
- }else if( c==matchOne ){
+ }else if( !prevEscape && c==matchOne ){
if( *zString==0 ) return 0;
sqliteNextChar(zString);
zPattern++;
}else if( c==matchSet ){
int prior_c = 0;
+ assert( esc==0 ); /* This only occurs for GLOB, not LIKE */
seen = 0;
invert = 0;
c = sqliteCharVal(zString);
@@ -424,6 +433,9 @@ int patternCompare(
if( c2==0 || (seen ^ invert)==0 ) return 0;
sqliteNextChar(zString);
zPattern++;
+ }else if( esc && !prevEscape && sqlite3ReadUtf8(zPattern)==esc){
+ prevEscape = 1;
+ sqliteNextChar(zPattern);
}else{
if( noCase ){
if( sqlite3UpperToLower[c] != sqlite3UpperToLower[*zString] ) return 0;
@@ -432,6 +444,7 @@ int patternCompare(
}
zPattern++;
zString++;
+ prevEscape = 0;
}
}
return *zString==0;
@@ -457,8 +470,21 @@ static void likeFunc(
){
const unsigned char *zA = sqlite3_value_text(argv[0]);
const unsigned char *zB = sqlite3_value_text(argv[1]);
+ int escape = 0;
+ if( argc==3 ){
+ /* The escape character string must consist of a single UTF-8 character.
+ ** Otherwise, return an error.
+ */
+ const unsigned char *zEsc = sqlite3_value_text(argv[2]);
+ if( sqlite3utf8CharLen(zEsc, -1)!=1 ){
+ sqlite3_result_error(context,
+ "ESCAPE expression must be a single character", -1);
+ return;
+ }
+ escape = sqlite3ReadUtf8(zEsc);
+ }
if( zA && zB ){
- sqlite3_result_int(context, patternCompare(zA, zB, &likeInfo));
+ sqlite3_result_int(context, patternCompare(zA, zB, &likeInfo, escape));
}
}
@@ -469,13 +495,13 @@ static void likeFunc(
**
** A GLOB B
**
-** is implemented as glob(A,B).
+** is implemented as glob(B,A).
*/
static void globFunc(sqlite3_context *context, int arg, sqlite3_value **argv){
const unsigned char *zA = sqlite3_value_text(argv[0]);
const unsigned char *zB = sqlite3_value_text(argv[1]);
if( zA && zB ){
- sqlite3_result_int(context, patternCompare(zA, zB, &globInfo));
+ sqlite3_result_int(context, patternCompare(zA, zB, &globInfo, 0));
}
}
@@ -507,6 +533,7 @@ static void versionFunc(
sqlite3_result_text(context, sqlite3_version, -1, SQLITE_STATIC);
}
+
/*
** EXPERIMENTAL - This is not an official function. The interface may
** change. This function may disappear. Do not write code that depends
@@ -704,10 +731,12 @@ static void test_destructor(
memcpy(zVal, sqlite3ValueText(argv[0], db->enc), len);
if( db->enc==SQLITE_UTF8 ){
sqlite3_result_text(pCtx, zVal, -1, destructor);
+#ifndef SQLITE_OMIT_UTF16
}else if( db->enc==SQLITE_UTF16LE ){
sqlite3_result_text16le(pCtx, zVal, -1, destructor);
}else{
sqlite3_result_text16be(pCtx, zVal, -1, destructor);
+#endif /* SQLITE_OMIT_UTF16 */
}
}
static void test_destructor_count(
@@ -762,6 +791,20 @@ static void test_auxdata(
}
#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
+/*
+** A function to test error reporting from user functions. This function
+** returns a copy of it's first argument as an error.
+*/
+static void test_error(
+ sqlite3_context *pCtx,
+ int nArg,
+ sqlite3_value **argv
+){
+ sqlite3_result_error(pCtx, sqlite3_value_text(argv[0]), 0);
+}
+#endif /* SQLITE_TEST */
+
/*
** An instance of the following structure holds the context of a
** sum() or avg() aggregate computation.
@@ -808,33 +851,6 @@ struct StdDevCtx {
int cnt; /* Number of terms counted */
};
-#if 0 /* Omit because math library is required */
-/*
-** Routines used to compute the standard deviation as an aggregate.
-*/
-static void stdDevStep(sqlite3_context *context, int argc, const char **argv){
- StdDevCtx *p;
- double x;
- if( argc<1 ) return;
- p = sqlite3_aggregate_context(context, sizeof(*p));
- if( p && argv[0] ){
- x = sqlite3AtoF(argv[0], 0);
- p->sum += x;
- p->sum2 += x*x;
- p->cnt++;
- }
-}
-static void stdDevFinalize(sqlite3_context *context){
- double rN = sqlite3_aggregate_count(context);
- StdDevCtx *p = sqlite3_aggregate_context(context, sizeof(*p));
- if( p && p->cnt>1 ){
- double rCnt = cnt;
- sqlite3_set_result_double(context,
- sqrt((p->sum2 - p->sum*p->sum/rCnt)/(rCnt-1.0)));
- }
-}
-#endif
-
/*
** The following structure keeps track of state information for the
** count() aggregate function.
@@ -933,7 +949,9 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
{ "typeof", 1, 0, SQLITE_UTF8, 0, typeofFunc },
{ "length", 1, 0, SQLITE_UTF8, 0, lengthFunc },
{ "substr", 3, 0, SQLITE_UTF8, 0, substrFunc },
+#ifndef SQLITE_OMIT_UTF16
{ "substr", 3, 0, SQLITE_UTF16LE, 0, sqlite3utf16Substr },
+#endif
{ "abs", 1, 0, SQLITE_UTF8, 0, absFunc },
{ "round", 1, 0, SQLITE_UTF8, 0, roundFunc },
{ "round", 2, 0, SQLITE_UTF8, 0, roundFunc },
@@ -945,6 +963,7 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
{ "ifnull", 2, 0, SQLITE_UTF8, 1, ifnullFunc },
{ "random", -1, 0, SQLITE_UTF8, 0, randomFunc },
{ "like", 2, 0, SQLITE_UTF8, 0, likeFunc },
+ { "like", 3, 0, SQLITE_UTF8, 0, likeFunc },
{ "glob", 2, 0, SQLITE_UTF8, 0, globFunc },
{ "nullif", 2, 0, SQLITE_UTF8, 1, nullifFunc },
{ "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc},
@@ -960,6 +979,7 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
{ "test_destructor", 1, 1, SQLITE_UTF8, 0, test_destructor},
{ "test_destructor_count", 0, 0, SQLITE_UTF8, 0, test_destructor_count},
{ "test_auxdata", -1, 0, SQLITE_UTF8, 0, test_auxdata},
+ { "test_error", 1, 0, SQLITE_UTF8, 0, test_error},
#endif
};
static const struct {
@@ -976,9 +996,6 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
{ "avg", 1, 0, 0, sumStep, avgFinalize },
{ "count", 0, 0, 0, countStep, countFinalize },
{ "count", 1, 0, 0, countStep, countFinalize },
-#if 0
- { "stddev", 1, 0, stdDevStep, stdDevFinalize },
-#endif
};
int i;
@@ -998,6 +1015,9 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
}
}
}
+#ifndef SQLITE_OMIT_ALTERTABLE
+ sqlite3AlterFunctions(db);
+#endif
for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){
void *pArg = 0;
switch( aAggs[i].argType ){
diff --git a/ext/pdo_sqlite/sqlite/src/hash.c b/ext/pdo_sqlite/sqlite/src/hash.c
index 23e2e19748..e01aae7163 100644
--- a/ext/pdo_sqlite/sqlite/src/hash.c
+++ b/ext/pdo_sqlite/sqlite/src/hash.c
@@ -98,7 +98,14 @@ static int ptrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
** Hash and comparison functions when the mode is SQLITE_HASH_STRING
*/
static int strHash(const void *pKey, int nKey){
- return sqlite3HashNoCase((const char*)pKey, nKey);
+ const char *z = (const char *)pKey;
+ int h = 0;
+ if( nKey<=0 ) nKey = strlen(z);
+ while( nKey > 0 ){
+ h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++];
+ nKey--;
+ }
+ return h & 0x7fffffff;
}
static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){
if( n1!=n2 ) return 1;
diff --git a/ext/pdo_sqlite/sqlite/src/insert.c b/ext/pdo_sqlite/sqlite/src/insert.c
index 65cbdc8ff1..c9485fe247 100644
--- a/ext/pdo_sqlite/sqlite/src/insert.c
+++ b/ext/pdo_sqlite/sqlite/src/insert.c
@@ -94,6 +94,27 @@ void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){
sqlite3VdbeChangeP3(v, -1, pTab->zColAff, 0);
}
+/*
+** Return non-zero if SELECT statement p opens the table with rootpage
+** iTab in database iDb. This is used to see if a statement of the form
+** "INSERT INTO <iDb, iTab> SELECT ..." can run without using temporary
+** table for the results of the SELECT.
+**
+** No checking is done for sub-selects that are part of expressions.
+*/
+static int selectReadsTable(Select *p, int iDb, int iTab){
+ int i;
+ struct SrcList_item *pItem;
+ if( p->pSrc==0 ) return 0;
+ for(i=0, pItem=p->pSrc->a; i<p->pSrc->nSrc; i++, pItem++){
+ if( pItem->pSelect ){
+ if( selectReadsTable(p, iDb, iTab) ) return 1;
+ }else{
+ if( pItem->pTab->iDb==iDb && pItem->pTab->tnum==iTab ) return 1;
+ }
+ }
+ return 0;
+}
/*
** This routine is call to handle SQL of the following forms:
@@ -182,18 +203,24 @@ void sqlite3Insert(
sqlite3 *db; /* The main database structure */
int keyColumn = -1; /* Column that is the INTEGER PRIMARY KEY */
int endOfLoop; /* Label for the end of the insertion loop */
- int useTempTable; /* Store SELECT results in intermediate table */
+ int useTempTable = 0; /* Store SELECT results in intermediate table */
int srcTab = 0; /* Data comes from this temporary cursor if >=0 */
int iSelectLoop = 0; /* Address of code that implements the SELECT */
int iCleanup = 0; /* Address of the cleanup code */
int iInsertBlock = 0; /* Address of the subroutine used to insert data */
int iCntMem = 0; /* Memory cell used for the row counter */
- int isView; /* True if attempting to insert into a view */
+ int newIdx = -1; /* Cursor for the NEW table */
+ Db *pDb; /* The database containing table being inserted into */
+ int counterMem = 0; /* Memory cell holding AUTOINCREMENT counter */
- int row_triggers_exist = 0; /* True if there are FOR EACH ROW triggers */
- int before_triggers; /* True if there are BEFORE triggers */
- int after_triggers; /* True if there are AFTER triggers */
- int newIdx = -1; /* Cursor for the NEW table */
+#ifndef SQLITE_OMIT_TRIGGER
+ int isView; /* True if attempting to insert into a view */
+ int triggers_exist = 0; /* True if there are FOR EACH ROW triggers */
+#endif
+
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+ int counterRowid; /* Memory cell holding rowid of autoinc counter */
+#endif
if( pParse->nErr || sqlite3_malloc_failed ) goto insert_cleanup;
db = pParse->db;
@@ -208,22 +235,32 @@ void sqlite3Insert(
goto insert_cleanup;
}
assert( pTab->iDb<db->nDb );
- zDb = db->aDb[pTab->iDb].zName;
+ pDb = &db->aDb[pTab->iDb];
+ zDb = pDb->zName;
if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){
goto insert_cleanup;
}
+ /* Figure out if we have any triggers and if the table being
+ ** inserted into is a view
+ */
+#ifndef SQLITE_OMIT_TRIGGER
+ triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0);
+ isView = pTab->pSelect!=0;
+#else
+# define triggers_exist 0
+# define isView 0
+#endif
+#ifdef SQLITE_OMIT_VIEW
+# undef isView
+# define isView 0
+#endif
+
/* Ensure that:
* (a) the table is not read-only,
* (b) that if it is a view then ON INSERT triggers exist
*/
- before_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, TK_INSERT,
- TK_BEFORE, TK_ROW, 0);
- after_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, TK_INSERT,
- TK_AFTER, TK_ROW, 0);
- row_triggers_exist = before_triggers || after_triggers;
- isView = pTab->pSelect!=0;
- if( sqlite3IsReadOnly(pParse, pTab, before_triggers) ){
+ if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){
goto insert_cleanup;
}
if( pTab==0 ) goto insert_cleanup;
@@ -245,14 +282,42 @@ void sqlite3Insert(
*/
v = sqlite3GetVdbe(pParse);
if( v==0 ) goto insert_cleanup;
- sqlite3VdbeCountChanges(v);
- sqlite3BeginWriteOperation(pParse, pSelect || row_triggers_exist, pTab->iDb);
+ if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
+ sqlite3BeginWriteOperation(pParse, pSelect || triggers_exist, pTab->iDb);
/* if there are row triggers, allocate a temp table for new.* references. */
- if( row_triggers_exist ){
+ if( triggers_exist ){
newIdx = pParse->nTab++;
}
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+ /* If this is an AUTOINCREMENT table, look up the sequence number in the
+ ** sqlite_sequence table and store it in memory cell counterMem. Also
+ ** remember the rowid of the sqlite_sequence table entry in memory cell
+ ** counterRowid.
+ */
+ if( pTab->autoInc ){
+ int iCur = pParse->nTab;
+ int base = sqlite3VdbeCurrentAddr(v);
+ counterRowid = pParse->nMem++;
+ counterMem = pParse->nMem++;
+ sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0);
+ sqlite3VdbeAddOp(v, OP_OpenRead, iCur, pDb->pSeqTab->tnum);
+ sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, 2);
+ sqlite3VdbeAddOp(v, OP_Rewind, iCur, base+13);
+ sqlite3VdbeAddOp(v, OP_Column, iCur, 0);
+ sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0);
+ sqlite3VdbeAddOp(v, OP_Ne, 28417, base+12);
+ sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
+ sqlite3VdbeAddOp(v, OP_MemStore, counterRowid, 1);
+ sqlite3VdbeAddOp(v, OP_Column, iCur, 1);
+ sqlite3VdbeAddOp(v, OP_MemStore, counterMem, 1);
+ sqlite3VdbeAddOp(v, OP_Goto, 0, base+13);
+ sqlite3VdbeAddOp(v, OP_Next, iCur, base+4);
+ sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
+ }
+#endif /* SQLITE_OMIT_AUTOINCREMENT */
+
/* Figure out how many columns of data are supplied. If the data
** is coming from a SELECT statement, then this step also generates
** all the code to implement the SELECT statement and invoke a subroutine
@@ -268,8 +333,11 @@ void sqlite3Insert(
iInitCode = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);
iSelectLoop = sqlite3VdbeCurrentAddr(v);
iInsertBlock = sqlite3VdbeMakeLabel(v);
- rc = sqlite3Select(pParse, pSelect, SRT_Subroutine, iInsertBlock, 0,0,0,0);
+
+ /* Resolve the expressions in the SELECT statement and execute it. */
+ rc = sqlite3Select(pParse, pSelect, SRT_Subroutine, iInsertBlock,0,0,0,0);
if( rc || pParse->nErr || sqlite3_malloc_failed ) goto insert_cleanup;
+
iCleanup = sqlite3VdbeMakeLabel(v);
sqlite3VdbeAddOp(v, OP_Goto, 0, iCleanup);
assert( pSelect->pEList );
@@ -283,20 +351,8 @@ void sqlite3Insert(
** of the tables being read by the SELECT statement. Also use a
** temp table in the case of row triggers.
*/
- if( row_triggers_exist ){
+ if( triggers_exist || selectReadsTable(pSelect, pTab->iDb, pTab->tnum) ){
useTempTable = 1;
- }else{
- int addr = 0;
- useTempTable = 0;
- while( useTempTable==0 ){
- VdbeOp *pOp;
- addr = sqlite3VdbeFindOp(v, addr, OP_OpenRead, pTab->tnum);
- if( addr==0 ) break;
- pOp = sqlite3VdbeGetOp(v, addr-2);
- if( pOp->opcode==OP_Integer && pOp->p1==pTab->iDb ){
- useTempTable = 1;
- }
- }
}
if( useTempTable ){
@@ -328,15 +384,16 @@ void sqlite3Insert(
/* This is the case if the data for the INSERT is coming from a VALUES
** clause
*/
- SrcList dummy;
+ NameContext sNC;
+ memset(&sNC, 0, sizeof(sNC));
+ sNC.pParse = pParse;
assert( pList!=0 );
srcTab = -1;
useTempTable = 0;
assert( pList );
nColumn = pList->nExpr;
- dummy.nSrc = 0;
for(i=0; i<nColumn; i++){
- if( sqlite3ExprResolveAndCheck(pParse,&dummy,0,pList->a[i].pExpr,0,0) ){
+ if( sqlite3ExprResolveNames(&sNC, pList->a[i].pExpr) ){
goto insert_cleanup;
}
}
@@ -404,7 +461,7 @@ void sqlite3Insert(
/* Open the temp table for FOR EACH ROW triggers
*/
- if( row_triggers_exist ){
+ if( triggers_exist ){
sqlite3VdbeAddOp(v, OP_OpenPseudo, newIdx, 0);
sqlite3VdbeAddOp(v, OP_SetNumColumns, newIdx, pTab->nCol);
}
@@ -418,7 +475,7 @@ void sqlite3Insert(
}
/* Open tables and indices if there are no row triggers */
- if( !row_triggers_exist ){
+ if( !triggers_exist ){
base = pParse->nTab;
sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite);
}
@@ -440,7 +497,7 @@ void sqlite3Insert(
/* Run the BEFORE and INSTEAD OF triggers, if there are any
*/
endOfLoop = sqlite3VdbeMakeLabel(v);
- if( before_triggers ){
+ if( triggers_exist & TRIGGER_BEFORE ){
/* build the NEW.* reference row. Note that if there is an INTEGER
** PRIMARY KEY into which a NULL is being inserted, that NULL will be
@@ -452,9 +509,8 @@ void sqlite3Insert(
sqlite3VdbeAddOp(v, OP_Integer, -1, 0);
}else if( useTempTable ){
sqlite3VdbeAddOp(v, OP_Column, srcTab, keyColumn);
- }else if( pSelect ){
- sqlite3VdbeAddOp(v, OP_Dup, nColumn - keyColumn - 1, 1);
}else{
+ assert( pSelect==0 ); /* Otherwise useTempTable is true */
sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr);
sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3);
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
@@ -473,13 +529,12 @@ void sqlite3Insert(
}
}
if( pColumn && j>=pColumn->nId ){
- sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->aCol[i].zDflt, P3_STATIC);
+ sqlite3ExprCode(pParse, pTab->aCol[i].pDflt);
}else if( useTempTable ){
sqlite3VdbeAddOp(v, OP_Column, srcTab, j);
- }else if( pSelect ){
- sqlite3VdbeAddOp(v, OP_Dup, nColumn-j-1, 1);
}else{
- sqlite3ExprCode(pParse, pList->a[j].pExpr);
+ assert( pSelect==0 ); /* Otherwise useTempTable is true */
+ sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr);
}
}
sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
@@ -495,7 +550,7 @@ void sqlite3Insert(
sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0);
/* Fire BEFORE or INSTEAD OF triggers */
- if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TK_BEFORE, pTab,
+ if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_BEFORE, pTab,
newIdx, -1, onError, endOfLoop) ){
goto insert_cleanup;
}
@@ -504,7 +559,7 @@ void sqlite3Insert(
/* If any triggers exists, the opening of tables and indices is deferred
** until now.
*/
- if( row_triggers_exist && !isView ){
+ if( triggers_exist && !isView ){
base = pParse->nTab;
sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite);
}
@@ -528,11 +583,16 @@ void sqlite3Insert(
*/
sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3);
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
- sqlite3VdbeAddOp(v, OP_NewRecno, base, 0);
+ sqlite3VdbeAddOp(v, OP_NewRecno, base, counterMem);
sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
}else{
- sqlite3VdbeAddOp(v, OP_NewRecno, base, 0);
+ sqlite3VdbeAddOp(v, OP_NewRecno, base, counterMem);
+ }
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+ if( pTab->autoInc ){
+ sqlite3VdbeAddOp(v, OP_MemMax, counterMem, 0);
}
+#endif /* SQLITE_OMIT_AUTOINCREMENT */
/* Push onto the stack, data for all columns of the new entry, beginning
** with the first column.
@@ -554,7 +614,7 @@ void sqlite3Insert(
}
}
if( pColumn && j>=pColumn->nId ){
- sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->aCol[i].zDflt, P3_STATIC);
+ sqlite3ExprCode(pParse, pTab->aCol[i].pDflt);
}else if( useTempTable ){
sqlite3VdbeAddOp(v, OP_Column, srcTab, j);
}else if( pSelect ){
@@ -570,7 +630,7 @@ void sqlite3Insert(
sqlite3GenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0,
0, onError, endOfLoop);
sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0,
- after_triggers ? newIdx : -1);
+ (triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1);
}
/* Update the count of rows that are inserted
@@ -579,7 +639,7 @@ void sqlite3Insert(
sqlite3VdbeAddOp(v, OP_MemIncr, iCntMem, 0);
}
- if( row_triggers_exist ){
+ if( triggers_exist ){
/* Close all tables opened */
if( !isView ){
sqlite3VdbeAddOp(v, OP_Close, base, 0);
@@ -589,8 +649,8 @@ void sqlite3Insert(
}
/* Code AFTER triggers */
- if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TK_AFTER, pTab, newIdx, -1,
- onError, endOfLoop) ){
+ if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_AFTER, pTab,
+ newIdx, -1, onError, endOfLoop) ){
goto insert_cleanup;
}
}
@@ -608,7 +668,7 @@ void sqlite3Insert(
sqlite3VdbeResolveLabel(v, iCleanup);
}
- if( !row_triggers_exist ){
+ if( !triggers_exist ){
/* Close all tables opened */
sqlite3VdbeAddOp(v, OP_Close, base, 0);
for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
@@ -616,10 +676,35 @@ void sqlite3Insert(
}
}
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+ /* Update the sqlite_sequence table by storing the content of the
+ ** counter value in memory counterMem back into the sqlite_sequence
+ ** table.
+ */
+ if( pTab->autoInc ){
+ int iCur = pParse->nTab;
+ int base = sqlite3VdbeCurrentAddr(v);
+ sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0);
+ sqlite3VdbeAddOp(v, OP_OpenWrite, iCur, pDb->pSeqTab->tnum);
+ sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, 2);
+ sqlite3VdbeAddOp(v, OP_MemLoad, counterRowid, 0);
+ sqlite3VdbeAddOp(v, OP_NotNull, -1, base+7);
+ sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
+ sqlite3VdbeAddOp(v, OP_NewRecno, iCur, 0);
+ sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0);
+ sqlite3VdbeAddOp(v, OP_MemLoad, counterMem, 0);
+ sqlite3VdbeAddOp(v, OP_MakeRecord, 2, 0);
+ sqlite3VdbeAddOp(v, OP_PutIntKey, iCur, 0);
+ sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
+ }
+#endif
+
/*
- ** Return the number of rows inserted.
+ ** Return the number of rows inserted. If this routine is
+ ** generating code because of a call to sqlite3NestedParse(), do not
+ ** invoke the callback function.
*/
- if( db->flags & SQLITE_CountRows ){
+ if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){
sqlite3VdbeAddOp(v, OP_MemLoad, iCntMem, 0);
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
sqlite3VdbeSetNumCols(v, 1);
@@ -753,11 +838,13 @@ void sqlite3GenerateConstraintChecks(
}else if( onError==OE_Default ){
onError = OE_Abort;
}
- if( onError==OE_Replace && pTab->aCol[i].zDflt==0 ){
+ if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){
onError = OE_Abort;
}
sqlite3VdbeAddOp(v, OP_Dup, nCol-1-i, 1);
addr = sqlite3VdbeAddOp(v, OP_NotNull, 1, 0);
+ assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
+ || onError==OE_Ignore || onError==OE_Replace );
switch( onError ){
case OE_Rollback:
case OE_Abort:
@@ -775,11 +862,10 @@ void sqlite3GenerateConstraintChecks(
break;
}
case OE_Replace: {
- sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->aCol[i].zDflt, P3_STATIC);
+ sqlite3ExprCode(pParse, pTab->aCol[i].pDflt);
sqlite3VdbeAddOp(v, OP_Push, nCol-i, 0);
break;
}
- default: assert(0);
}
sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v));
}
@@ -885,6 +971,8 @@ void sqlite3GenerateConstraintChecks(
jumpInst2 = sqlite3VdbeAddOp(v, OP_IsUnique, base+iCur+1, 0);
/* Generate code that executes if the new index entry is not unique */
+ assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
+ || onError==OE_Ignore || onError==OE_Replace );
switch( onError ){
case OE_Rollback:
case OE_Abort:
@@ -929,7 +1017,6 @@ void sqlite3GenerateConstraintChecks(
seenReplace = 1;
break;
}
- default: assert(0);
}
contAddr = sqlite3VdbeCurrentAddr(v);
assert( contAddr<(1<<24) );
@@ -975,12 +1062,18 @@ void sqlite3CompleteInsertion(
}
sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
sqlite3TableAffinityStr(v, pTab);
+#ifndef SQLITE_OMIT_TRIGGER
if( newIdx>=0 ){
sqlite3VdbeAddOp(v, OP_Dup, 1, 0);
sqlite3VdbeAddOp(v, OP_Dup, 1, 0);
sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0);
}
- pik_flags = (OPFLAG_NCHANGE|(isUpdate?0:OPFLAG_LASTROWID));
+#endif
+ if( pParse->nested ){
+ pik_flags = 0;
+ }else{
+ pik_flags = (OPFLAG_NCHANGE|(isUpdate?0:OPFLAG_LASTROWID));
+ }
sqlite3VdbeAddOp(v, OP_PutIntKey, base, pik_flags);
if( isUpdate && recnoChng ){
diff --git a/ext/pdo_sqlite/sqlite/src/main.c b/ext/pdo_sqlite/sqlite/src/main.c
index 0ae7e1b263..1d6dec3a3c 100644
--- a/ext/pdo_sqlite/sqlite/src/main.c
+++ b/ext/pdo_sqlite/sqlite/src/main.c
@@ -202,7 +202,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
** meta[2] Size of the page cache.
** meta[3] Use freelist if 0. Autovacuum if greater than zero.
** meta[4] Db text encoding. 1:UTF-8 3:UTF-16 LE 4:UTF-16 BE
- ** meta[5]
+ ** meta[5] The user cookie. Used by the application.
** meta[6]
** meta[7]
** meta[8]
@@ -257,12 +257,23 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
/* This happens if the database was initially empty */
db->file_format = 1;
}
+
+ if( db->file_format==2 ){
+ /* File format 2 is treated exactly as file format 1. New
+ ** databases are created with file format 1.
+ */
+ db->file_format = 1;
+ }
}
/*
- ** file_format==1 Version 3.0.0.
+ ** file_format==1 Version 3.0.0.
+ ** file_format==2 Version 3.1.3.
+ **
+ ** Version 3.0 can only use files with file_format==1. Version 3.1.3
+ ** can read and write files with file_format==1 or file_format==2.
*/
- if( meta[1]>1 ){
+ if( meta[1]>2 ){
sqlite3BtreeCloseCursor(curMain);
sqlite3SetString(pzErrMsg, "unsupported file format", (char*)0);
return SQLITE_ERROR;
@@ -279,7 +290,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
}else{
char *zSql;
zSql = sqlite3MPrintf(
- "SELECT name, rootpage, sql, %s FROM '%q'.%s",
+ "SELECT name, rootpage, sql, '%s' FROM '%q'.%s",
zDbNum, db->aDb[iDb].zName, zMasterName);
sqlite3SafetyOff(db);
rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
@@ -373,12 +384,13 @@ int sqlite3ReadSchema(Parse *pParse){
const char rcsid3[] = "@(#) \044Id: SQLite version " SQLITE_VERSION " $";
const char sqlite3_version[] = SQLITE_VERSION;
const char *sqlite3_libversion(void){ return sqlite3_version; }
+int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; }
/*
** This is the default collating function named "BINARY" which is always
** available.
*/
-static int binaryCollatingFunc(
+static int binCollFunc(
void *NotUsed,
int nKey1, const void *pKey1,
int nKey2, const void *pKey2
@@ -553,7 +565,7 @@ const char *sqlite3ErrStr(int rc){
case SQLITE_NOLFS: z = "kernel lacks large file support"; break;
case SQLITE_AUTH: z = "authorization denied"; break;
case SQLITE_FORMAT: z = "auxiliary database format error"; break;
- case SQLITE_RANGE: z = "bind index out of range"; break;
+ case SQLITE_RANGE: z = "bind or column index out of range"; break;
case SQLITE_NOTADB: z = "file is encrypted or is not a database";break;
default: z = "unknown error"; break;
}
@@ -706,6 +718,7 @@ int sqlite3_create_function(
return SQLITE_ERROR;
}
+#ifndef SQLITE_OMIT_UTF16
/* If SQLITE_UTF16 is specified as the encoding type, transform this
** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the
** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally.
@@ -725,6 +738,25 @@ int sqlite3_create_function(
if( rc!=SQLITE_OK ) return rc;
enc = SQLITE_UTF16BE;
}
+#else
+ enc = SQLITE_UTF8;
+#endif
+
+ /* Check if an existing function is being overridden or deleted. If so,
+ ** and there are active VMs, then return SQLITE_BUSY. If a function
+ ** is being overridden/deleted but there are no active VMs, allow the
+ ** operation to continue but invalidate all precompiled statements.
+ */
+ p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 0);
+ if( p && p->iPrefEnc==enc && p->nArg==nArg ){
+ if( db->activeVdbeCnt ){
+ sqlite3Error(db, SQLITE_BUSY,
+ "Unable to delete/modify user-function due to active statements");
+ return SQLITE_BUSY;
+ }else{
+ sqlite3ExpirePreparedStatements(db);
+ }
+ }
p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 1);
if( p==0 ) return SQLITE_NOMEM;
@@ -734,6 +766,7 @@ int sqlite3_create_function(
p->pUserData = pUserData;
return SQLITE_OK;
}
+#ifndef SQLITE_OMIT_UTF16
int sqlite3_create_function16(
sqlite3 *db,
const void *zFunctionName,
@@ -762,6 +795,7 @@ int sqlite3_create_function16(
pUserData, xFunc, xStep, xFinal);
return rc;
}
+#endif
/*
** Register a trace function. The pArg from the previously registered trace
@@ -835,13 +869,14 @@ int sqlite3BtreeFactory(
if( omitJournal ){
btree_flags |= BTREE_OMIT_JOURNAL;
}
+ if( db->flags & SQLITE_NoReadlock ){
+ btree_flags |= BTREE_NO_READLOCK;
+ }
if( zFilename==0 ){
-#ifndef TEMP_STORE
-# define TEMP_STORE 1
-#endif
#if TEMP_STORE==0
/* Do nothing */
#endif
+#ifndef SQLITE_OMIT_MEMORYDB
#if TEMP_STORE==1
if( db->temp_store==2 ) zFilename = ":memory:";
#endif
@@ -851,6 +886,7 @@ int sqlite3BtreeFactory(
#if TEMP_STORE==3
zFilename = ":memory:";
#endif
+#endif /* SQLITE_OMIT_MEMORYDB */
}
rc = sqlite3BtreeOpen(zFilename, ppBtree, btree_flags);
@@ -880,6 +916,7 @@ const char *sqlite3_errmsg(sqlite3 *db){
return z;
}
+#ifndef SQLITE_OMIT_UTF16
/*
** Return UTF-16 encoded English language explanation of the most recent
** error.
@@ -919,6 +956,7 @@ const void *sqlite3_errmsg16(sqlite3 *db){
}
return z;
}
+#endif /* SQLITE_OMIT_UTF16 */
/*
** Return the most recent error code generated by an SQLite routine.
@@ -1005,6 +1043,7 @@ int sqlite3_prepare(
if( pzTail ) *pzTail = sParse.zTail;
rc = sParse.rc;
+#ifndef SQLITE_OMIT_EXPLAIN
if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){
sqlite3VdbeSetNumCols(sParse.pVdbe, 5);
sqlite3VdbeSetColName(sParse.pVdbe, 0, "addr", P3_STATIC);
@@ -1013,6 +1052,7 @@ int sqlite3_prepare(
sqlite3VdbeSetColName(sParse.pVdbe, 3, "p2", P3_STATIC);
sqlite3VdbeSetColName(sParse.pVdbe, 4, "p3", P3_STATIC);
}
+#endif
prepare_out:
if( sqlite3SafetyOff(db) ){
@@ -1033,6 +1073,7 @@ prepare_out:
return rc;
}
+#ifndef SQLITE_OMIT_UTF16
/*
** Compile the UTF-16 encoded SQL statement zSql into a statement handle.
*/
@@ -1076,6 +1117,7 @@ int sqlite3_prepare16(
return rc;
}
+#endif /* SQLITE_OMIT_UTF16 */
/*
** This routine does the work of opening a database on behalf of
@@ -1091,7 +1133,6 @@ static int openDatabase(
){
sqlite3 *db;
int rc, i;
- char *zErrMsg = 0;
/* Allocate the sqlite data structure */
db = sqliteMalloc( sizeof(sqlite3) );
@@ -1102,7 +1143,7 @@ static int openDatabase(
db->aDb = db->aDbStatic;
db->enc = SQLITE_UTF8;
db->autoCommit = 1;
- /* db->flags |= SQLITE_ShortColNames; */
+ db->flags |= SQLITE_ShortColNames;
sqlite3HashInit(&db->aFunc, SQLITE_HASH_STRING, 0);
sqlite3HashInit(&db->aCollSeq, SQLITE_HASH_STRING, 0);
for(i=0; i<db->nDb; i++){
@@ -1116,11 +1157,9 @@ static int openDatabase(
** and UTF-16, so add a version for each to avoid any unnecessary
** conversions. The only error that can occur here is a malloc() failure.
*/
- sqlite3_create_collation(db, "BINARY", SQLITE_UTF8, 0,binaryCollatingFunc);
- sqlite3_create_collation(db, "BINARY", SQLITE_UTF16LE, 0,binaryCollatingFunc);
- sqlite3_create_collation(db, "BINARY", SQLITE_UTF16BE, 0,binaryCollatingFunc);
- db->pDfltColl = sqlite3FindCollSeq(db, db->enc, "BINARY", 6, 0);
- if( !db->pDfltColl ){
+ if( sqlite3_create_collation(db, "BINARY", SQLITE_UTF8, 0,binCollFunc) ||
+ sqlite3_create_collation(db, "BINARY", SQLITE_UTF16, 0,binCollFunc) ||
+ !(db->pDfltColl = sqlite3FindCollSeq(db, db->enc, "BINARY", 6, 0)) ){
rc = db->errCode;
assert( rc!=SQLITE_OK );
db->magic = SQLITE_MAGIC_CLOSED;
@@ -1150,14 +1189,8 @@ static int openDatabase(
** is accessed.
*/
sqlite3RegisterBuiltinFunctions(db);
- if( rc==SQLITE_OK ){
- sqlite3Error(db, SQLITE_OK, 0);
- db->magic = SQLITE_MAGIC_OPEN;
- }else{
- sqlite3Error(db, rc, "%s", zErrMsg, 0);
- if( zErrMsg ) sqliteFree(zErrMsg);
- db->magic = SQLITE_MAGIC_CLOSED;
- }
+ sqlite3Error(db, SQLITE_OK, 0);
+ db->magic = SQLITE_MAGIC_OPEN;
opendb_out:
if( sqlite3_errcode(db)==SQLITE_OK && sqlite3_malloc_failed ){
@@ -1177,6 +1210,7 @@ int sqlite3_open(
return openDatabase(zFilename, ppDb);
}
+#ifndef SQLITE_OMIT_UTF16
/*
** Open a new database handle.
*/
@@ -1205,6 +1239,7 @@ int sqlite3_open16(
return rc;
}
+#endif /* SQLITE_OMIT_UTF16 */
/*
** The following routine destroys a virtual machine that is created by
@@ -1239,7 +1274,7 @@ int sqlite3_reset(sqlite3_stmt *pStmt){
rc = SQLITE_OK;
}else{
rc = sqlite3VdbeReset((Vdbe*)pStmt);
- sqlite3VdbeMakeReady((Vdbe*)pStmt, -1, 0, 0, 0);
+ sqlite3VdbeMakeReady((Vdbe*)pStmt, -1, 0, 0, 0, 0);
}
return rc;
}
@@ -1276,6 +1311,21 @@ int sqlite3_create_collation(
);
return SQLITE_ERROR;
}
+
+ /* Check if this call is removing or replacing an existing collation
+ ** sequence. If so, and there are active VMs, return busy. If there
+ ** are no active VMs, invalidate any pre-compiled statements.
+ */
+ pColl = sqlite3FindCollSeq(db, (u8)enc, zName, strlen(zName), 0);
+ if( pColl && pColl->xCmp ){
+ if( db->activeVdbeCnt ){
+ sqlite3Error(db, SQLITE_BUSY,
+ "Unable to delete/modify collation sequence due to active statements");
+ return SQLITE_BUSY;
+ }
+ sqlite3ExpirePreparedStatements(db);
+ }
+
pColl = sqlite3FindCollSeq(db, (u8)enc, zName, strlen(zName), 1);
if( 0==pColl ){
rc = SQLITE_NOMEM;
@@ -1288,6 +1338,7 @@ int sqlite3_create_collation(
return rc;
}
+#ifndef SQLITE_OMIT_UTF16
/*
** Register a new collation sequence with the database handle db.
*/
@@ -1308,6 +1359,7 @@ int sqlite3_create_collation16(
zName8 = sqlite3ValueText(pTmp, SQLITE_UTF8);
return sqlite3_create_collation(db, zName8, enc, pCtx, xCompare);
}
+#endif /* SQLITE_OMIT_UTF16 */
/*
** Register a collation sequence factory callback with the database handle
@@ -1327,6 +1379,7 @@ int sqlite3_collation_needed(
return SQLITE_OK;
}
+#ifndef SQLITE_OMIT_UTF16
/*
** Register a collation sequence factory callback with the database handle
** db. Replace any previously installed collation sequence factory.
@@ -1344,3 +1397,4 @@ int sqlite3_collation_needed16(
db->pCollNeededArg = pCollNeededArg;
return SQLITE_OK;
}
+#endif /* SQLITE_OMIT_UTF16 */
diff --git a/ext/pdo_sqlite/sqlite/src/opcodes.c b/ext/pdo_sqlite/sqlite/src/opcodes.c
index b6f012198d..734d1a5409 100644
--- a/ext/pdo_sqlite/sqlite/src/opcodes.c
+++ b/ext/pdo_sqlite/sqlite/src/opcodes.c
@@ -1,128 +1,137 @@
/* Automatically generated. Do not edit */
-/* See the mkopcodec.h script for details. */
+/* See the mkopcodec.awk script for details. */
+#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
const char *const sqlite3OpcodeNames[] = { "?",
- "ContextPop",
- "IntegrityCk",
- "DropTrigger",
- "DropIndex",
- "Recno",
- "KeyAsData",
- "Delete",
- "MoveGt",
- "VerifyCookie",
- "Push",
- "Dup",
- "Blob",
- "IdxGT",
- "IdxRecno",
- "RowKey",
- "PutStrKey",
- "IsUnique",
- "SetNumColumns",
- "IdxIsNull",
- "NullRow",
- "OpenPseudo",
- "OpenWrite",
- "OpenRead",
- "Transaction",
- "AutoCommit",
- "Pop",
- "Halt",
- "Vacuum",
- "ListRead",
- "RowData",
- "NotExists",
- "MoveLe",
- "SetCookie",
- "Variable",
- "AggNext",
- "AggReset",
- "Sort",
- "IdxDelete",
- "ResetCount",
- "OpenTemp",
- "IdxColumn",
- "Integer",
- "AggSet",
- "CreateIndex",
- "IdxPut",
- "MoveLt",
- "Return",
- "MemLoad",
- "SortNext",
- "IdxLT",
- "Rewind",
- "AddImm",
- "AggFunc",
- "AggInit",
- "MemIncr",
- "ListReset",
- "Clear",
- "Or",
- "And",
- "Not",
- "PutIntKey",
- "If",
- "Callback",
- "IsNull",
- "NotNull",
- "Ne",
- "Eq",
- "Gt",
- "Le",
- "Lt",
- "Ge",
- "BitAnd",
- "BitOr",
- "ShiftLeft",
- "ShiftRight",
- "Add",
- "Subtract",
- "Multiply",
- "Divide",
- "Remainder",
- "Concat",
- "Negative",
- "SortReset",
- "BitNot",
- "String8",
- "SortPut",
- "Last",
- "NotFound",
- "MakeRecord",
- "String",
- "Goto",
- "AggFocus",
- "DropTable",
- "Column",
- "Noop",
- "AggGet",
- "CreateTable",
- "NewRecno",
- "Found",
- "Distinct",
- "Close",
- "Statement",
- "IfNot",
- "Pull",
- "MemStore",
- "Next",
- "Prev",
- "MoveGe",
- "MustBeInt",
- "ForceInt",
- "CollSeq",
- "Gosub",
- "ContextPush",
- "ListRewind",
- "ListWrite",
- "ParseSchema",
- "Destroy",
- "IdxGE",
- "FullKey",
- "ReadCookie",
- "AbsValue",
- "Real",
- "HexBlob",
- "Function",
+ /* 1 */ "MemLoad",
+ /* 2 */ "Column",
+ /* 3 */ "SetCookie",
+ /* 4 */ "IfMemPos",
+ /* 5 */ "MoveGt",
+ /* 6 */ "AggFocus",
+ /* 7 */ "RowKey",
+ /* 8 */ "IdxRecno",
+ /* 9 */ "AggNext",
+ /* 10 */ "OpenWrite",
+ /* 11 */ "If",
+ /* 12 */ "PutStrKey",
+ /* 13 */ "Pop",
+ /* 14 */ "SortPut",
+ /* 15 */ "AggContextPush",
+ /* 16 */ "CollSeq",
+ /* 17 */ "OpenRead",
+ /* 18 */ "Expire",
+ /* 19 */ "SortReset",
+ /* 20 */ "AutoCommit",
+ /* 21 */ "Sort",
+ /* 22 */ "ListRewind",
+ /* 23 */ "IntegrityCk",
+ /* 24 */ "Function",
+ /* 25 */ "Noop",
+ /* 26 */ "Return",
+ /* 27 */ "Variable",
+ /* 28 */ "String",
+ /* 29 */ "ParseSchema",
+ /* 30 */ "PutIntKey",
+ /* 31 */ "AggFunc",
+ /* 32 */ "Close",
+ /* 33 */ "ListWrite",
+ /* 34 */ "CreateIndex",
+ /* 35 */ "IsUnique",
+ /* 36 */ "IdxIsNull",
+ /* 37 */ "NotFound",
+ /* 38 */ "MustBeInt",
+ /* 39 */ "Halt",
+ /* 40 */ "IdxLT",
+ /* 41 */ "AddImm",
+ /* 42 */ "Statement",
+ /* 43 */ "RowData",
+ /* 44 */ "MemMax",
+ /* 45 */ "Push",
+ /* 46 */ "KeyAsData",
+ /* 47 */ "NotExists",
+ /* 48 */ "OpenTemp",
+ /* 49 */ "MemIncr",
+ /* 50 */ "Gosub",
+ /* 51 */ "AggSet",
+ /* 52 */ "Integer",
+ /* 53 */ "SortNext",
+ /* 54 */ "Prev",
+ /* 55 */ "CreateTable",
+ /* 56 */ "Last",
+ /* 57 */ "ResetCount",
+ /* 58 */ "Callback",
+ /* 59 */ "ContextPush",
+ /* 60 */ "DropTrigger",
+ /* 61 */ "DropIndex",
+ /* 62 */ "FullKey",
+ /* 63 */ "IdxGE",
+ /* 64 */ "Or",
+ /* 65 */ "And",
+ /* 66 */ "Not",
+ /* 67 */ "IdxDelete",
+ /* 68 */ "Vacuum",
+ /* 69 */ "MoveLe",
+ /* 70 */ "IsNull",
+ /* 71 */ "NotNull",
+ /* 72 */ "Ne",
+ /* 73 */ "Eq",
+ /* 74 */ "Gt",
+ /* 75 */ "Le",
+ /* 76 */ "Lt",
+ /* 77 */ "Ge",
+ /* 78 */ "IfNot",
+ /* 79 */ "BitAnd",
+ /* 80 */ "BitOr",
+ /* 81 */ "ShiftLeft",
+ /* 82 */ "ShiftRight",
+ /* 83 */ "Add",
+ /* 84 */ "Subtract",
+ /* 85 */ "Multiply",
+ /* 86 */ "Divide",
+ /* 87 */ "Remainder",
+ /* 88 */ "Concat",
+ /* 89 */ "Negative",
+ /* 90 */ "DropTable",
+ /* 91 */ "BitNot",
+ /* 92 */ "String8",
+ /* 93 */ "MakeRecord",
+ /* 94 */ "Delete",
+ /* 95 */ "AggContextPop",
+ /* 96 */ "ListRead",
+ /* 97 */ "ListReset",
+ /* 98 */ "Dup",
+ /* 99 */ "Goto",
+ /* 100 */ "Clear",
+ /* 101 */ "IdxGT",
+ /* 102 */ "MoveLt",
+ /* 103 */ "VerifyCookie",
+ /* 104 */ "Pull",
+ /* 105 */ "SetNumColumns",
+ /* 106 */ "AbsValue",
+ /* 107 */ "Transaction",
+ /* 108 */ "AggGet",
+ /* 109 */ "ContextPop",
+ /* 110 */ "Next",
+ /* 111 */ "AggInit",
+ /* 112 */ "Distinct",
+ /* 113 */ "NewRecno",
+ /* 114 */ "AggReset",
+ /* 115 */ "Destroy",
+ /* 116 */ "ReadCookie",
+ /* 117 */ "ForceInt",
+ /* 118 */ "Recno",
+ /* 119 */ "OpenPseudo",
+ /* 120 */ "Blob",
+ /* 121 */ "MemStore",
+ /* 122 */ "Rewind",
+ /* 123 */ "MoveGe",
+ /* 124 */ "IdxPut",
+ /* 125 */ "Found",
+ /* 126 */ "NullRow",
+ /* 127 */ "NotUsed_127",
+ /* 128 */ "NotUsed_128",
+ /* 129 */ "NotUsed_129",
+ /* 130 */ "Real",
+ /* 131 */ "HexBlob",
};
+#endif
diff --git a/ext/pdo_sqlite/sqlite/src/opcodes.h b/ext/pdo_sqlite/sqlite/src/opcodes.h
index 7b792c5a11..8be3dc7ea1 100644
--- a/ext/pdo_sqlite/sqlite/src/opcodes.h
+++ b/ext/pdo_sqlite/sqlite/src/opcodes.h
@@ -1,126 +1,135 @@
/* Automatically generated. Do not edit */
/* See the mkopcodeh.awk script for details */
-#define OP_ContextPop 1
-#define OP_IntegrityCk 2
-#define OP_DropTrigger 3
-#define OP_DropIndex 4
-#define OP_Recno 5
-#define OP_KeyAsData 6
-#define OP_Delete 7
-#define OP_MoveGt 8
-#define OP_VerifyCookie 9
-#define OP_Push 10
-#define OP_Dup 11
-#define OP_Blob 12
-#define OP_IdxGT 13
-#define OP_IdxRecno 14
-#define OP_RowKey 15
-#define OP_PutStrKey 16
-#define OP_IsUnique 17
-#define OP_SetNumColumns 18
-#define OP_Eq 67
-#define OP_IdxIsNull 19
-#define OP_NullRow 20
-#define OP_OpenPseudo 21
-#define OP_OpenWrite 22
-#define OP_OpenRead 23
-#define OP_Transaction 24
-#define OP_AutoCommit 25
-#define OP_Negative 82
-#define OP_Pop 26
-#define OP_Halt 27
-#define OP_Vacuum 28
-#define OP_ListRead 29
-#define OP_RowData 30
-#define OP_NotExists 31
-#define OP_MoveLe 32
-#define OP_SetCookie 33
-#define OP_Variable 34
-#define OP_AggNext 35
-#define OP_AggReset 36
-#define OP_Sort 37
-#define OP_IdxDelete 38
-#define OP_ResetCount 39
-#define OP_OpenTemp 40
-#define OP_IdxColumn 41
-#define OP_NotNull 65
-#define OP_Ge 71
-#define OP_Remainder 80
-#define OP_Divide 79
-#define OP_Integer 42
-#define OP_AggSet 43
-#define OP_CreateIndex 44
-#define OP_IdxPut 45
-#define OP_MoveLt 46
-#define OP_And 59
-#define OP_ShiftLeft 74
-#define OP_Real 122
-#define OP_Return 47
-#define OP_MemLoad 48
-#define OP_SortNext 49
-#define OP_IdxLT 50
-#define OP_Rewind 51
-#define OP_Gt 68
-#define OP_AddImm 52
-#define OP_Subtract 77
-#define OP_AggFunc 53
-#define OP_AggInit 54
-#define OP_MemIncr 55
-#define OP_ListReset 56
-#define OP_Clear 57
-#define OP_PutIntKey 61
-#define OP_IsNull 64
-#define OP_If 62
-#define OP_Callback 63
-#define OP_SortReset 83
-#define OP_SortPut 86
-#define OP_Last 87
-#define OP_NotFound 88
-#define OP_MakeRecord 89
-#define OP_BitAnd 72
-#define OP_Add 76
-#define OP_HexBlob 123
-#define OP_String 90
-#define OP_Goto 91
-#define OP_AggFocus 92
-#define OP_DropTable 93
-#define OP_Column 94
-#define OP_Noop 95
-#define OP_Not 60
-#define OP_Le 69
-#define OP_BitOr 73
-#define OP_Multiply 78
-#define OP_String8 85
-#define OP_AggGet 96
-#define OP_CreateTable 97
-#define OP_NewRecno 98
-#define OP_Found 99
-#define OP_Distinct 100
-#define OP_Close 101
-#define OP_Statement 102
-#define OP_IfNot 103
-#define OP_Pull 104
-#define OP_MemStore 105
-#define OP_Next 106
-#define OP_Prev 107
-#define OP_MoveGe 108
-#define OP_Lt 70
-#define OP_Ne 66
-#define OP_MustBeInt 109
-#define OP_ForceInt 110
-#define OP_ShiftRight 75
-#define OP_CollSeq 111
-#define OP_Gosub 112
-#define OP_ContextPush 113
-#define OP_ListRewind 114
-#define OP_ListWrite 115
-#define OP_ParseSchema 116
-#define OP_Destroy 117
-#define OP_IdxGE 118
-#define OP_FullKey 119
-#define OP_ReadCookie 120
-#define OP_BitNot 84
-#define OP_AbsValue 121
-#define OP_Or 58
-#define OP_Function 124
-#define OP_Concat 81
+#define OP_MemLoad 1
+#define OP_HexBlob 131 /* same as TK_BLOB */
+#define OP_Column 2
+#define OP_SetCookie 3
+#define OP_IfMemPos 4
+#define OP_Real 130 /* same as TK_FLOAT */
+#define OP_MoveGt 5
+#define OP_Ge 77 /* same as TK_GE */
+#define OP_AggFocus 6
+#define OP_RowKey 7
+#define OP_IdxRecno 8
+#define OP_AggNext 9
+#define OP_Eq 73 /* same as TK_EQ */
+#define OP_OpenWrite 10
+#define OP_NotNull 71 /* same as TK_NOTNULL */
+#define OP_If 11
+#define OP_PutStrKey 12
+#define OP_String8 92 /* same as TK_STRING */
+#define OP_Pop 13
+#define OP_SortPut 14
+#define OP_AggContextPush 15
+#define OP_CollSeq 16
+#define OP_OpenRead 17
+#define OP_Expire 18
+#define OP_SortReset 19
+#define OP_AutoCommit 20
+#define OP_Gt 74 /* same as TK_GT */
+#define OP_Sort 21
+#define OP_ListRewind 22
+#define OP_IntegrityCk 23
+#define OP_Function 24
+#define OP_Subtract 84 /* same as TK_MINUS */
+#define OP_And 65 /* same as TK_AND */
+#define OP_Noop 25
+#define OP_Return 26
+#define OP_Remainder 87 /* same as TK_REM */
+#define OP_Multiply 85 /* same as TK_STAR */
+#define OP_Variable 27
+#define OP_String 28
+#define OP_ParseSchema 29
+#define OP_PutIntKey 30
+#define OP_AggFunc 31
+#define OP_Close 32
+#define OP_ListWrite 33
+#define OP_CreateIndex 34
+#define OP_IsUnique 35
+#define OP_IdxIsNull 36
+#define OP_NotFound 37
+#define OP_MustBeInt 38
+#define OP_Halt 39
+#define OP_IdxLT 40
+#define OP_AddImm 41
+#define OP_Statement 42
+#define OP_RowData 43
+#define OP_MemMax 44
+#define OP_Push 45
+#define OP_Or 64 /* same as TK_OR */
+#define OP_KeyAsData 46
+#define OP_NotExists 47
+#define OP_OpenTemp 48
+#define OP_MemIncr 49
+#define OP_Gosub 50
+#define OP_Divide 86 /* same as TK_SLASH */
+#define OP_AggSet 51
+#define OP_Integer 52
+#define OP_SortNext 53
+#define OP_Prev 54
+#define OP_Concat 88 /* same as TK_CONCAT */
+#define OP_BitAnd 79 /* same as TK_BITAND */
+#define OP_CreateTable 55
+#define OP_Last 56
+#define OP_IsNull 70 /* same as TK_ISNULL */
+#define OP_ShiftRight 82 /* same as TK_RSHIFT */
+#define OP_ResetCount 57
+#define OP_Callback 58
+#define OP_ContextPush 59
+#define OP_DropTrigger 60
+#define OP_DropIndex 61
+#define OP_FullKey 62
+#define OP_IdxGE 63
+#define OP_IdxDelete 67
+#define OP_Vacuum 68
+#define OP_MoveLe 69
+#define OP_IfNot 78
+#define OP_DropTable 90
+#define OP_MakeRecord 93
+#define OP_Delete 94
+#define OP_AggContextPop 95
+#define OP_ListRead 96
+#define OP_ListReset 97
+#define OP_ShiftLeft 81 /* same as TK_LSHIFT */
+#define OP_Dup 98
+#define OP_Goto 99
+#define OP_Clear 100
+#define OP_IdxGT 101
+#define OP_MoveLt 102
+#define OP_Le 75 /* same as TK_LE */
+#define OP_VerifyCookie 103
+#define OP_Pull 104
+#define OP_Not 66 /* same as TK_NOT */
+#define OP_SetNumColumns 105
+#define OP_AbsValue 106
+#define OP_Transaction 107
+#define OP_Negative 89 /* same as TK_UMINUS */
+#define OP_Ne 72 /* same as TK_NE */
+#define OP_AggGet 108
+#define OP_ContextPop 109
+#define OP_BitOr 80 /* same as TK_BITOR */
+#define OP_Next 110
+#define OP_AggInit 111
+#define OP_Distinct 112
+#define OP_NewRecno 113
+#define OP_Lt 76 /* same as TK_LT */
+#define OP_AggReset 114
+#define OP_Destroy 115
+#define OP_ReadCookie 116
+#define OP_ForceInt 117
+#define OP_Recno 118
+#define OP_OpenPseudo 119
+#define OP_Blob 120
+#define OP_Add 83 /* same as TK_PLUS */
+#define OP_MemStore 121
+#define OP_Rewind 122
+#define OP_MoveGe 123
+#define OP_IdxPut 124
+#define OP_BitNot 91 /* same as TK_BITNOT */
+#define OP_Found 125
+#define OP_NullRow 126
+
+/* The following opcode values are never used */
+#define OP_NotUsed_127 127
+#define OP_NotUsed_128 128
+#define OP_NotUsed_129 129
diff --git a/ext/pdo_sqlite/sqlite/src/os.h b/ext/pdo_sqlite/sqlite/src/os.h
index fc478baa93..d39d62d809 100644
--- a/ext/pdo_sqlite/sqlite/src/os.h
+++ b/ext/pdo_sqlite/sqlite/src/os.h
@@ -25,30 +25,17 @@
*/
#if !defined(OS_UNIX) && !defined(OS_TEST)
# ifndef OS_WIN
-# ifndef OS_MAC
-# if defined(__MACOS__)
-# define OS_MAC 1
-# define OS_WIN 0
-# define OS_UNIX 0
-# elif defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
-# define OS_MAC 0
-# define OS_WIN 1
-# define OS_UNIX 0
-# else
-# define OS_MAC 0
-# define OS_WIN 0
-# define OS_UNIX 1
-# endif
-# else
-# define OS_WIN 0
-# define OS_UNIX 0
+# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
+# define OS_WIN 1
+# define OS_UNIX 0
+# else
+# define OS_WIN 0
+# define OS_UNIX 1
# endif
# else
-# define OS_MAC 0
# define OS_UNIX 0
# endif
#else
-# define OS_MAC 0
# ifndef OS_WIN
# define OS_WIN 0
# endif
@@ -66,9 +53,6 @@
#if OS_WIN
# include "os_win.h"
#endif
-#if OS_MAC
-# include "os_mac.h"
-#endif
/*
** Temporary files are named starting with this prefix followed by 16 random
@@ -162,7 +146,7 @@
**
*/
#define PENDING_BYTE 0x40000000 /* First byte past the 1GB boundary */
-/* #define PENDING_BYTE 0x5400 // Page 20 - for testing */
+/* #define PENDING_BYTE 0x5400 // Page 22 - for testing */
#define RESERVED_BYTE (PENDING_BYTE+1)
#define SHARED_FIRST (PENDING_BYTE+2)
#define SHARED_SIZE 510
@@ -176,6 +160,7 @@ int sqlite3OsOpenReadOnly(const char*, OsFile*);
int sqlite3OsOpenDirectory(const char*, OsFile*);
int sqlite3OsSyncDirectory(const char*);
int sqlite3OsTempFileName(char*);
+int sqlite3OsIsDirWritable(char*);
int sqlite3OsClose(OsFile*);
int sqlite3OsRead(OsFile*, void*, int amt);
int sqlite3OsWrite(OsFile*, const void*, int amt);
diff --git a/ext/pdo_sqlite/sqlite/src/os_test.c b/ext/pdo_sqlite/sqlite/src/os_test.c
index 0e292bc428..8199f5b183 100644
--- a/ext/pdo_sqlite/sqlite/src/os_test.c
+++ b/ext/pdo_sqlite/sqlite/src/os_test.c
@@ -239,10 +239,12 @@ printf("Writing block %d of %s\n", i, pFile->zName);
if( BLOCK_OFFSET(i+1)>nMax ){
len = nMax-BLOCK_OFFSET(i);
}
- if( trash ){
- sqlite3Randomness(len, p);
+ if( len>0 ){
+ if( trash ){
+ sqlite3Randomness(len, p);
+ }
+ rc = sqlite3RealWrite(&pFile->fd, p, len);
}
- rc = sqlite3RealWrite(&pFile->fd, p, len);
}
sqliteFree(p);
}
diff --git a/ext/pdo_sqlite/sqlite/src/os_unix.c b/ext/pdo_sqlite/sqlite/src/os_unix.c
index 94fca70199..0e270c0bb6 100644
--- a/ext/pdo_sqlite/sqlite/src/os_unix.c
+++ b/ext/pdo_sqlite/sqlite/src/os_unix.c
@@ -574,7 +574,7 @@ int sqlite3OsOpenDirectory(
** name of a directory, then that directory will be used to store
** temporary files.
*/
-const char *sqlite3_temp_directory = 0;
+char *sqlite3_temp_directory = 0;
/*
** Create a temporary file name in zBuf. zBuf must be big enough to
@@ -616,6 +616,22 @@ int sqlite3OsTempFileName(char *zBuf){
return SQLITE_OK;
}
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
+/*
+** Check that a given pathname is a directory and is writable
+**
+*/
+int sqlite3OsIsDirWritable(char *zBuf){
+ struct stat buf;
+ if( zBuf==0 ) return 0;
+ if( zBuf[0]==0 ) return 0;
+ if( stat(zBuf, &buf) ) return 0;
+ if( !S_ISDIR(buf.st_mode) ) return 0;
+ if( access(zBuf, 07) ) return 0;
+ return 1;
+}
+#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
+
/*
** Read data from a file into a buffer. Return SQLITE_OK if all
** bytes were read successfully and SQLITE_IOERR if anything goes
@@ -645,6 +661,7 @@ int sqlite3OsRead(OsFile *id, void *pBuf, int amt){
int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){
int wrote = 0;
assert( id->isOpen );
+ assert( amt>0 );
SimulateIOError(SQLITE_IOERR);
SimulateDiskfullError;
TIMER_START;
@@ -675,8 +692,17 @@ int sqlite3OsSeek(OsFile *id, i64 offset){
** The fsync() system call does not work as advertised on many
** unix systems. The following procedure is an attempt to make
** it work better.
+**
+** The SQLITE_NO_SYNC macro disables all fsync()s. This is useful
+** for testing when we want to run through the test suite quickly.
+** You are strongly advised *not* to deploy with SQLITE_NO_SYNC
+** enabled, however, since with SQLITE_NO_SYNC enabled, an OS crash
+** or power failure will likely corrupt the database file.
*/
static int full_fsync(int fd){
+#ifdef SQLITE_NO_SYNC
+ return SQLITE_OK;
+#else
int rc;
#ifdef F_FULLFSYNC
rc = fcntl(fd, F_FULLFSYNC, 0);
@@ -685,6 +711,7 @@ static int full_fsync(int fd){
rc = fsync(fd);
#endif
return rc;
+#endif
}
/*
@@ -1157,10 +1184,16 @@ int sqlite3OsRandomSeed(char *zBuf){
memset(zBuf, 0, 256);
#if !defined(SQLITE_TEST)
{
- int pid;
- time((time_t*)zBuf);
- pid = getpid();
- memcpy(&zBuf[sizeof(time_t)], &pid, sizeof(pid));
+ int pid, fd;
+ fd = open("/dev/urandom", O_RDONLY);
+ if( fd<0 ){
+ time((time_t*)zBuf);
+ pid = getpid();
+ memcpy(&zBuf[sizeof(time_t)], &pid, sizeof(pid));
+ }else{
+ read(fd, zBuf, 256);
+ close(fd);
+ }
}
#endif
return SQLITE_OK;
diff --git a/ext/pdo_sqlite/sqlite/src/os_win.c b/ext/pdo_sqlite/sqlite/src/os_win.c
index f6e3e3ea83..2614ed08a6 100644
--- a/ext/pdo_sqlite/sqlite/src/os_win.c
+++ b/ext/pdo_sqlite/sqlite/src/os_win.c
@@ -202,7 +202,7 @@ int sqlite3OsOpenDirectory(
** name of a directory, then that directory will be used to store
** temporary files.
*/
-const char *sqlite3_temp_directory = 0;
+char *sqlite3_temp_directory = 0;
/*
** Create a temporary file name in zBuf. zBuf must be big enough to
@@ -275,12 +275,13 @@ int sqlite3OsRead(OsFile *id, void *pBuf, int amt){
** or some other error code on failure.
*/
int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){
- int rc;
+ int rc = 0;
DWORD wrote;
assert( id->isOpen );
SimulateIOError(SQLITE_IOERR);
SimulateDiskfullError;
TRACE3("WRITE %d lock=%d\n", id->h, id->locktype);
+ assert( amt>0 );
while( amt>0 && (rc = WriteFile(id->h, pBuf, amt, &wrote, 0))!=0 && wrote>0 ){
amt -= wrote;
pBuf = &((char*)pBuf)[wrote];
@@ -409,6 +410,24 @@ static int unlockReadLock(OsFile *id){
return res;
}
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
+/*
+** Check that a given pathname is a directory and is writable
+**
+*/
+int sqlite3OsIsDirWritable(char *zBuf){
+ int fileAttr;
+ if(! zBuf ) return 0;
+ if(! isNT() && strlen(zBuf) > MAX_PATH ) return 0;
+ fileAttr = GetFileAttributesA(zBuf);
+ if( fileAttr == 0xffffffff ) return 0;
+ if( (fileAttr & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY ){
+ return 0;
+ }
+ return 1;
+}
+#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
+
/*
** Lock the file with the lock specified by parameter locktype - one
** of the following:
diff --git a/ext/pdo_sqlite/sqlite/src/pager.c b/ext/pdo_sqlite/sqlite/src/pager.c
index a374562bc7..47d895240c 100644
--- a/ext/pdo_sqlite/sqlite/src/pager.c
+++ b/ext/pdo_sqlite/sqlite/src/pager.c
@@ -34,13 +34,32 @@
#define TRACE2(X,Y) sqlite3DebugPrintf(X,Y)
#define TRACE3(X,Y,Z) sqlite3DebugPrintf(X,Y,Z)
#define TRACE4(X,Y,Z,W) sqlite3DebugPrintf(X,Y,Z,W)
+#define TRACE5(X,Y,Z,W,V) sqlite3DebugPrintf(X,Y,Z,W,V)
#else
#define TRACE1(X)
#define TRACE2(X,Y)
#define TRACE3(X,Y,Z)
#define TRACE4(X,Y,Z,W)
+#define TRACE5(X,Y,Z,W,V)
#endif
+/*
+** The following two macros are used within the TRACEX() macros above
+** to print out file-descriptors. They are required so that tracing
+** can be turned on when using both the regular os_unix.c and os_test.c
+** backends.
+**
+** PAGERID() takes a pointer to a Pager struct as it's argument. The
+** associated file-descriptor is returned. FILEHANDLEID() takes an OsFile
+** struct as it's argument.
+*/
+#ifdef OS_TEST
+#define PAGERID(p) (p->fd->fd.h)
+#define FILEHANDLEID(fd) (fd->fd.h)
+#else
+#define PAGERID(p) (p->fd.h)
+#define FILEHANDLEID(fd) (fd.h)
+#endif
/*
** The page cache as a whole is always in one of the following
@@ -111,6 +130,12 @@
#endif
/*
+** This macro rounds values up so that if the value is an address it
+** is guaranteed to be an address that is aligned to an 8-byte boundary.
+*/
+#define FORCE_ALIGNMENT(X) (((X)+7)&~7)
+
+/*
** Each in-memory image of a page begins with the following header.
** This header is only visible to this pager module. The client
** code that calls pager sees only the data that follows the header.
@@ -143,7 +168,10 @@ struct PgHdr {
u8 alwaysRollback; /* Disable dont_rollback() for this page */
short int nRef; /* Number of users of this page */
PgHdr *pDirty; /* Dirty pages sorted by PgHdr.pgno */
- /* pPager->pageSize bytes of page data follow this header */
+#ifdef SQLITE_CHECK_PAGES
+ u32 pageHash;
+#endif
+ /* pPager->psAligned bytes of page data follow this header */
/* Pager.nExtra bytes of local data follow the page data */
};
@@ -179,9 +207,9 @@ struct PgHistory {
*/
#define PGHDR_TO_DATA(P) ((void*)(&(P)[1]))
#define DATA_TO_PGHDR(D) (&((PgHdr*)(D))[-1])
-#define PGHDR_TO_EXTRA(G,P) ((void*)&((char*)(&(G)[1]))[(P)->pageSize])
+#define PGHDR_TO_EXTRA(G,P) ((void*)&((char*)(&(G)[1]))[(P)->psAligned])
#define PGHDR_TO_HIST(P,PGR) \
- ((PgHistory*)&((char*)(&(P)[1]))[(PGR)->pageSize+(PGR)->nExtra])
+ ((PgHistory*)&((char*)(&(P)[1]))[(PGR)->psAligned+(PGR)->nExtra])
/*
** How big to make the hash table used for locating in-memory pages
@@ -214,15 +242,18 @@ struct Pager {
void (*xDestructor)(void*,int); /* Call this routine when freeing pages */
void (*xReiniter)(void*,int); /* Call this routine when reloading pages */
int pageSize; /* Number of bytes in a page */
+ int psAligned; /* pageSize rounded up to a multiple of 8 */
int nPage; /* Total number of in-memory pages */
int nRef; /* Number of in-memory pages with PgHdr.nRef>0 */
int mxPage; /* Maximum number of pages to hold in cache */
int nHit, nMiss, nOvfl; /* Cache hits, missing, and LRU overflows */
+ int nRead,nWrite; /* Database pages read/written */
void (*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
void *pCodecArg; /* First argument to xCodec() */
u8 journalOpen; /* True if journal file descriptors is valid */
u8 journalStarted; /* True if header of journal is synced */
u8 useJournal; /* Use a rollback journal on this file */
+ u8 noReadlock; /* Do not bother to obtain readlocks */
u8 stmtOpen; /* True if the statement subjournal is open */
u8 stmtInUse; /* True we are in a statement subtransaction */
u8 stmtAutoopen; /* Open stmt journal when main journal is opened*/
@@ -301,6 +332,21 @@ static const unsigned char aJournalMagic[] = {
*/
#define JOURNAL_HDR_SZ(pPager) (pPager->sectorSize)
+/*
+** The macro MEMDB is true if we are dealing with an in-memory database.
+** We do this as a macro so that if the SQLITE_OMIT_MEMORYDB macro is set,
+** the value of MEMDB will be a constant and the compiler will optimize
+** out code that would never execute.
+*/
+#ifdef SQLITE_OMIT_MEMORYDB
+# define MEMDB 0
+#else
+# define MEMDB pPager->memDb
+#endif
+
+/*
+** The default size of a disk sector
+*/
#define PAGER_SECTOR_SIZE 512
/*
@@ -310,12 +356,18 @@ static const unsigned char aJournalMagic[] = {
** is devoted to storing a master journal name - there are no more pages to
** roll back. See comments for function writeMasterJournal() for details.
*/
-#define PAGER_MJ_PGNO(x) (PENDING_BYTE/((x)->pageSize))
+/* #define PAGER_MJ_PGNO(x) (PENDING_BYTE/((x)->pageSize)) */
+#define PAGER_MJ_PGNO(x) ((PENDING_BYTE/((x)->pageSize))+1)
+
+/*
+** The maximum legal page number is (2^31 - 1).
+*/
+#define PAGER_MAX_PGNO 2147483647
/*
** Enable reference count tracking (for debugging) here:
*/
-#ifdef SQLITE_TEST
+#ifdef SQLITE_DEBUG
int pager3_refinfo_enable = 0;
static void pager_refinfo(PgHdr *p){
static int cnt = 0;
@@ -402,6 +454,36 @@ static int pager_errcode(Pager *pPager){
return rc;
}
+#ifdef SQLITE_CHECK_PAGES
+/*
+** Return a 32-bit hash of the page data for pPage.
+*/
+static u32 pager_pagehash(PgHdr *pPage){
+ u32 hash = 0;
+ int i;
+ unsigned char *pData = (unsigned char *)PGHDR_TO_DATA(pPage);
+ for(i=0; i<pPage->pPager->pageSize; i++){
+ hash = (hash+i)^pData[i];
+ }
+ return hash;
+}
+
+/*
+** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES
+** is defined, and NDEBUG is not defined, an assert() statement checks
+** that the page is either dirty or still matches the calculated page-hash.
+*/
+#define CHECK_PAGE(x) checkPage(x)
+static void checkPage(PgHdr *pPg){
+ Pager *pPager = pPg->pPager;
+ assert( !pPg->pageHash || pPager->errMask || MEMDB || pPg->dirty ||
+ pPg->pageHash==pager_pagehash(pPg) );
+}
+
+#else
+#define CHECK_PAGE(x)
+#endif
+
/*
** When this is called the journal file for pager pPager must be open.
** The master journal file name is read from the end of the file and
@@ -463,8 +545,9 @@ static int readMasterJournal(OsFile *pJrnl, char **pzMaster){
*/
sqliteFree(*pzMaster);
*pzMaster = 0;
+ }else{
+ (*pzMaster)[len] = '\0';
}
- (*pzMaster)[len] = '\0';
return SQLITE_OK;
}
@@ -772,7 +855,7 @@ static void pager_reset(Pager *pPager){
static int pager_unwritelock(Pager *pPager){
PgHdr *pPg;
int rc;
- assert( !pPager->memDb );
+ assert( !MEMDB );
if( pPager->state<PAGER_RESERVED ){
return SQLITE_OK;
}
@@ -791,6 +874,9 @@ static int pager_unwritelock(Pager *pPager){
pPg->inJournal = 0;
pPg->dirty = 0;
pPg->needSync = 0;
+#ifdef SQLITE_CHECK_PAGES
+ pPg->pageHash = pager_pagehash(pPg);
+#endif
}
pPager->dirtyCache = 0;
pPager->nRec = 0;
@@ -886,18 +972,20 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){
*/
pPg = pager_lookup(pPager, pgno);
assert( pPager->state>=PAGER_EXCLUSIVE || pPg );
- TRACE3("PLAYBACK %d page %d\n", pPager->fd.h, pgno);
+ TRACE3("PLAYBACK %d page %d\n", PAGERID(pPager), pgno);
if( pPager->state>=PAGER_EXCLUSIVE ){
sqlite3OsSeek(&pPager->fd, (pgno-1)*(i64)pPager->pageSize);
rc = sqlite3OsWrite(&pPager->fd, aData, pPager->pageSize);
}
if( pPg ){
- /* No page should ever be rolled back that is in use, except for page
- ** 1 which is held in use in order to keep the lock on the database
- ** active.
+ /* No page should ever be explicitly rolled back that is in use, except
+ ** for page 1 which is held in use in order to keep the lock on the
+ ** database active. However such a page may be rolled back as a result
+ ** of an internal error resulting in an automatic call to
+ ** sqlite3pager_rollback().
*/
void *pData;
- assert( pPg->nRef==0 || pPg->pgno==1 );
+ /* assert( pPg->nRef==0 || pPg->pgno==1 ); */
pData = PGHDR_TO_DATA(pPg);
memcpy(pData, aData, pPager->pageSize);
if( pPager->xDestructor ){ /*** FIX ME: Should this be xReinit? ***/
@@ -906,6 +994,9 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){
if( pPager->state>=PAGER_EXCLUSIVE ){
pPg->dirty = 0;
pPg->needSync = 0;
+#ifdef SQLITE_CHECK_PAGES
+ pPg->pageHash = pager_pagehash(pPg);
+#endif
}
CODEC(pPager, pData, pPg->pgno, 3);
}
@@ -963,6 +1054,7 @@ static int pager_delmaster(const char *zMaster){
** so, return without deleting the master journal file.
*/
OsFile journal;
+ int c;
memset(&journal, 0, sizeof(journal));
rc = sqlite3OsOpenReadOnly(zJournal, &journal);
@@ -976,7 +1068,9 @@ static int pager_delmaster(const char *zMaster){
goto delmaster_out;
}
- if( zMasterPtr && !strcmp(zMasterPtr, zMaster) ){
+ c = zMasterPtr!=0 && strcmp(zMasterPtr, zMaster)==0;
+ sqliteFree(zMasterPtr);
+ if( c ){
/* We have a match. Do not delete the master journal file. */
goto delmaster_out;
}
@@ -1015,7 +1109,7 @@ static int pager_reload_cache(Pager *pPager){
if( (int)pPg->pgno <= pPager->origDbSize ){
sqlite3OsSeek(&pPager->fd, pPager->pageSize*(i64)(pPg->pgno-1));
rc = sqlite3OsRead(&pPager->fd, zBuf, pPager->pageSize);
- TRACE3("REFETCH %d page %d\n", pPager->fd.h, pPg->pgno);
+ TRACE3("REFETCH %d page %d\n", PAGERID(pPager), pPg->pgno);
if( rc ) break;
CODEC(pPager, zBuf, pPg->pgno, 2);
}else{
@@ -1031,6 +1125,9 @@ static int pager_reload_cache(Pager *pPager){
}
pPg->needSync = 0;
pPg->dirty = 0;
+#ifdef SQLITE_CHECK_PAGES
+ pPg->pageHash = pager_pagehash(pPg);
+#endif
}
return rc;
}
@@ -1040,6 +1137,7 @@ static int pager_reload_cache(Pager *pPager){
** indicated.
*/
static int pager_truncate(Pager *pPager, int nPage){
+ assert( pPager->state>=PAGER_EXCLUSIVE );
return sqlite3OsTruncate(&pPager->fd, pPager->pageSize*(i64)nPage);
}
@@ -1159,7 +1257,8 @@ static int pager_playback(Pager *pPager){
/* If this is the first header read from the journal, truncate the
** database file back to it's original size.
*/
- if( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){
+ if( pPager->state>=PAGER_EXCLUSIVE &&
+ pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){
assert( pPager->origDbSize==0 || pPager->origDbSize==mxPg );
rc = pager_truncate(pPager, mxPg);
if( rc!=SQLITE_OK ){
@@ -1200,11 +1299,10 @@ end_playback:
}
if( zMaster ){
/* If there was a master journal and this routine will return true,
- ** see if it is possible to delete the master journal. If errors
- ** occur during this process, ignore them.
+ ** see if it is possible to delete the master journal.
*/
if( rc==SQLITE_OK ){
- pager_delmaster(zMaster);
+ rc = pager_delmaster(zMaster);
}
sqliteFree(zMaster);
}
@@ -1258,10 +1356,11 @@ static int pager_stmt_playback(Pager *pPager){
hdrOff = szJ;
}
-
/* Truncate the database back to its original size.
*/
- rc = pager_truncate(pPager, pPager->stmtSize);
+ if( pPager->state>=PAGER_EXCLUSIVE ){
+ rc = pager_truncate(pPager, pPager->stmtSize);
+ }
pPager->dbSize = pPager->stmtSize;
/* Figure out how many records are in the statement journal.
@@ -1384,11 +1483,13 @@ void sqlite3pager_set_cachesize(Pager *pPager, int mxPage){
** Numeric values associated with these states are OFF==1, NORMAL=2,
** and FULL=3.
*/
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
void sqlite3pager_set_safety_level(Pager *pPager, int level){
pPager->noSync = level==1 || pPager->tempFile;
pPager->fullSync = level==3 && !pPager->tempFile;
if( pPager->noSync ) pPager->needSync = 0;
}
+#endif
/*
** Open a temporary file. Write the name of the file into zName
@@ -1428,7 +1529,7 @@ int sqlite3pager_open(
Pager **ppPager, /* Return the Pager structure here */
const char *zFilename, /* Name of the database file to open */
int nExtra, /* Extra bytes append to each in-memory page */
- int useJournal /* TRUE to use a rollback journal on this file */
+ int flags /* flags controlling this file */
){
Pager *pPager;
char *zFullPathname = 0;
@@ -1439,6 +1540,8 @@ int sqlite3pager_open(
int tempFile = 0;
int memDb = 0;
int readOnly = 0;
+ int useJournal = (flags & PAGER_OMIT_JOURNAL)==0;
+ int noReadlock = (flags & PAGER_NO_READLOCK)!=0;
char zTemp[SQLITE_TEMPNAME_SIZE];
*ppPager = 0;
@@ -1447,11 +1550,14 @@ int sqlite3pager_open(
return SQLITE_NOMEM;
}
if( zFilename && zFilename[0] ){
+#ifndef SQLITE_OMIT_MEMORYDB
if( strcmp(zFilename,":memory:")==0 ){
memDb = 1;
zFullPathname = sqliteStrDup("");
rc = SQLITE_OK;
- }else{
+ }else
+#endif
+ {
zFullPathname = sqlite3OsFullPathname(zFilename);
if( zFullPathname ){
rc = sqlite3OsOpenReadWrite(zFullPathname, &fd, &readOnly);
@@ -1481,7 +1587,7 @@ int sqlite3pager_open(
sqliteFree(zFullPathname);
return SQLITE_NOMEM;
}
- TRACE3("OPEN %d %s\n", fd.h, zFullPathname);
+ TRACE3("OPEN %d %s\n", FILEHANDLEID(fd), zFullPathname);
pPager->zFilename = (char*)&pPager[1];
pPager->zDirectory = &pPager->zFilename[nameLen+1];
pPager->zJournal = &pPager->zDirectory[nameLen+1];
@@ -1498,11 +1604,13 @@ int sqlite3pager_open(
#endif
pPager->journalOpen = 0;
pPager->useJournal = useJournal && !memDb;
+ pPager->noReadlock = noReadlock && readOnly;
pPager->stmtOpen = 0;
pPager->stmtInUse = 0;
pPager->nRef = 0;
pPager->dbSize = memDb-1;
pPager->pageSize = SQLITE_DEFAULT_PAGE_SIZE;
+ pPager->psAligned = FORCE_ALIGNMENT(pPager->pageSize);
pPager->stmtSize = 0;
pPager->stmtJSize = 0;
pPager->nPage = 0;
@@ -1518,7 +1626,7 @@ int sqlite3pager_open(
pPager->pFirst = 0;
pPager->pFirstSynced = 0;
pPager->pLast = 0;
- pPager->nExtra = nExtra;
+ pPager->nExtra = FORCE_ALIGNMENT(nExtra);
pPager->sectorSize = PAGER_SECTOR_SIZE;
pPager->pBusyHandler = 0;
memset(pPager->aHash, 0, sizeof(pPager->aHash));
@@ -1564,6 +1672,7 @@ void sqlite3pager_set_reiniter(Pager *pPager, void (*xReinit)(void*,int)){
void sqlite3pager_set_pagesize(Pager *pPager, int pageSize){
assert( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE );
pPager->pageSize = pageSize;
+ pPager->psAligned = FORCE_ALIGNMENT(pageSize);
}
/*
@@ -1572,7 +1681,7 @@ void sqlite3pager_set_pagesize(Pager *pPager, int pageSize){
*/
void sqlite3pager_read_fileheader(Pager *pPager, int N, unsigned char *pDest){
memset(pDest, 0, N);
- if( pPager->memDb==0 ){
+ if( MEMDB==0 ){
sqlite3OsSeek(&pPager->fd, 0);
sqlite3OsRead(&pPager->fd, pDest, N);
}
@@ -1593,7 +1702,7 @@ int sqlite3pager_pagecount(Pager *pPager){
return 0;
}
n /= pPager->pageSize;
- if( !pPager->memDb && n==PENDING_BYTE/pPager->pageSize ){
+ if( !MEMDB && n==PENDING_BYTE/pPager->pageSize ){
n++;
}
if( pPager->state!=PAGER_UNLOCK ){
@@ -1609,6 +1718,33 @@ static int syncJournal(Pager*);
/*
+** Unlink pPg from it's hash chain. Also set the page number to 0 to indicate
+** that the page is not part of any hash chain. This is required because the
+** sqlite3pager_movepage() routine can leave a page in the
+** pNextFree/pPrevFree list that is not a part of any hash-chain.
+*/
+static void unlinkHashChain(Pager *pPager, PgHdr *pPg){
+ if( pPg->pgno==0 ){
+ /* If the page number is zero, then this page is not in any hash chain. */
+ return;
+ }
+ if( pPg->pNextHash ){
+ pPg->pNextHash->pPrevHash = pPg->pPrevHash;
+ }
+ if( pPg->pPrevHash ){
+ assert( pPager->aHash[pager_hash(pPg->pgno)]!=pPg );
+ pPg->pPrevHash->pNextHash = pPg->pNextHash;
+ }else{
+ int h = pager_hash(pPg->pgno);
+ assert( pPager->aHash[h]==pPg );
+ pPager->aHash[h] = pPg->pNextHash;
+ }
+
+ pPg->pgno = 0;
+ pPg->pNextHash = pPg->pPrevHash = 0;
+}
+
+/*
** Unlink a page from the free list (the list of all pages where nRef==0)
** and from its hash collision chain.
*/
@@ -1638,19 +1774,10 @@ static void unlinkPage(PgHdr *pPg){
pPg->pNextFree = pPg->pPrevFree = 0;
/* Unlink from the pgno hash table */
- if( pPg->pNextHash ){
- pPg->pNextHash->pPrevHash = pPg->pPrevHash;
- }
- if( pPg->pPrevHash ){
- pPg->pPrevHash->pNextHash = pPg->pNextHash;
- }else{
- int h = pager_hash(pPg->pgno);
- assert( pPager->aHash[h]==pPg );
- pPager->aHash[h] = pPg->pNextHash;
- }
- pPg->pNextHash = pPg->pPrevHash = 0;
+ unlinkHashChain(pPager, pPg);
}
+#ifndef SQLITE_OMIT_MEMORYDB
/*
** This routine is used to truncate an in-memory database. Delete
** all pages whose pgno is larger than pPager->dbSize and is unreferenced.
@@ -1676,6 +1803,40 @@ static void memoryTruncate(Pager *pPager){
}
}
}
+#else
+#define memoryTruncate(p)
+#endif
+
+/*
+** Try to obtain a lock on a file. Invoke the busy callback if the lock
+** is currently not available. Repeate until the busy callback returns
+** false or until the lock succeeds.
+**
+** Return SQLITE_OK on success and an error code if we cannot obtain
+** the lock.
+*/
+static int pager_wait_on_lock(Pager *pPager, int locktype){
+ int rc;
+ assert( PAGER_SHARED==SHARED_LOCK );
+ assert( PAGER_RESERVED==RESERVED_LOCK );
+ assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK );
+ if( pPager->state>=locktype ){
+ rc = SQLITE_OK;
+ }else{
+ int busy = 1;
+ do {
+ rc = sqlite3OsLock(&pPager->fd, locktype);
+ }while( rc==SQLITE_BUSY &&
+ pPager->pBusyHandler &&
+ pPager->pBusyHandler->xFunc &&
+ pPager->pBusyHandler->xFunc(pPager->pBusyHandler->pArg, busy++)
+ );
+ if( rc==SQLITE_OK ){
+ pPager->state = locktype;
+ }
+ }
+ return rc;
+}
/*
** Truncate the file to the number of pages specified.
@@ -1690,7 +1851,7 @@ int sqlite3pager_truncate(Pager *pPager, Pgno nPage){
if( nPage>=(unsigned)pPager->dbSize ){
return SQLITE_OK;
}
- if( pPager->memDb ){
+ if( MEMDB ){
pPager->dbSize = nPage;
memoryTruncate(pPager);
return SQLITE_OK;
@@ -1699,6 +1860,13 @@ int sqlite3pager_truncate(Pager *pPager, Pgno nPage){
if( rc!=SQLITE_OK ){
return rc;
}
+
+ /* Get an exclusive lock on the database before truncating. */
+ rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+
rc = pager_truncate(pPager, nPage);
if( rc==SQLITE_OK ){
pPager->dbSize = nPage;
@@ -1721,15 +1889,27 @@ int sqlite3pager_close(Pager *pPager){
case PAGER_RESERVED:
case PAGER_SYNCED:
case PAGER_EXCLUSIVE: {
+ /* We ignore any IO errors that occur during the rollback
+ ** operation. So disable IO error simulation so that testing
+ ** works more easily.
+ */
+#if defined(SQLITE_TEST) && (defined(OS_UNIX) || defined(OS_WIN))
+ extern int sqlite3_io_error_pending;
+ int ioerr_cnt = sqlite3_io_error_pending;
+ sqlite3_io_error_pending = -1;
+#endif
sqlite3pager_rollback(pPager);
- if( !pPager->memDb ){
+#if defined(SQLITE_TEST) && (defined(OS_UNIX) || defined(OS_WIN))
+ sqlite3_io_error_pending = ioerr_cnt;
+#endif
+ if( !MEMDB ){
sqlite3OsUnlock(&pPager->fd, NO_LOCK);
}
assert( pPager->journalOpen==0 );
break;
}
case PAGER_SHARED: {
- if( !pPager->memDb ){
+ if( !MEMDB ){
sqlite3OsUnlock(&pPager->fd, NO_LOCK);
}
break;
@@ -1741,7 +1921,7 @@ int sqlite3pager_close(Pager *pPager){
}
for(pPg=pPager->pAll; pPg; pPg=pNext){
#ifndef NDEBUG
- if( pPager->memDb ){
+ if( MEMDB ){
PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
assert( !pPg->alwaysRollback );
assert( !pHist->pOrig );
@@ -1751,7 +1931,7 @@ int sqlite3pager_close(Pager *pPager){
pNext = pPg->pNextAll;
sqliteFree(pPg);
}
- TRACE2("CLOSE %d\n", pPager->fd.h);
+ TRACE2("CLOSE %d\n", PAGERID(pPager));
sqlite3OsClose(&pPager->fd);
assert( pPager->journalOpen==0 );
/* Temp files are automatically deleted by the OS
@@ -1759,12 +1939,7 @@ int sqlite3pager_close(Pager *pPager){
** sqlite3OsDelete(pPager->zFilename);
** }
*/
- if( pPager->zFilename!=(char*)&pPager[1] ){
- assert( 0 ); /* Cannot happen */
- sqliteFree(pPager->zFilename);
- sqliteFree(pPager->zJournal);
- sqliteFree(pPager->zDirectory);
- }
+
sqliteFree(pPager);
return SQLITE_OK;
}
@@ -1809,7 +1984,7 @@ static void _page_ref(PgHdr *pPg){
pPg->nRef++;
REFINFO(pPg);
}
-#ifdef SQLITE_TEST
+#ifdef SQLITE_DEBUG
static void page_ref(PgHdr *pPg){
if( pPg->nRef==0 ){
_page_ref(pPg);
@@ -1882,7 +2057,7 @@ static int syncJournal(Pager *pPager){
** it as a candidate for rollback.
*/
if( pPager->fullSync ){
- TRACE2("SYNC journal of %d\n", pPager->fd.h);
+ TRACE2("SYNC journal of %d\n", PAGERID(pPager));
rc = sqlite3OsSync(&pPager->jfd);
if( rc!=0 ) return rc;
}
@@ -1892,7 +2067,7 @@ static int syncJournal(Pager *pPager){
sqlite3OsSeek(&pPager->jfd, pPager->journalOff);
}
- TRACE2("SYNC journal of %d\n", pPager->fd.h);
+ TRACE2("SYNC journal of %d\n", PAGERID(pPager));
rc = sqlite3OsSync(&pPager->jfd);
if( rc!=0 ) return rc;
pPager->journalStarted = 1;
@@ -1924,37 +2099,6 @@ static int syncJournal(Pager *pPager){
}
/*
-** Try to obtain a lock on a file. Invoke the busy callback if the lock
-** is currently not available. Repeate until the busy callback returns
-** false or until the lock succeeds.
-**
-** Return SQLITE_OK on success and an error code if we cannot obtain
-** the lock.
-*/
-static int pager_wait_on_lock(Pager *pPager, int locktype){
- int rc;
- assert( PAGER_SHARED==SHARED_LOCK );
- assert( PAGER_RESERVED==RESERVED_LOCK );
- assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK );
- if( pPager->state>=locktype ){
- rc = SQLITE_OK;
- }else{
- int busy = 1;
- do {
- rc = sqlite3OsLock(&pPager->fd, locktype);
- }while( rc==SQLITE_BUSY &&
- pPager->pBusyHandler &&
- pPager->pBusyHandler->xFunc &&
- pPager->pBusyHandler->xFunc(pPager->pBusyHandler->pArg, busy++)
- );
- if( rc==SQLITE_OK ){
- pPager->state = locktype;
- }
- }
- return rc;
-}
-
-/*
** Given a list of pages (connected by the PgHdr.pDirty pointer) write
** every one of those pages out to the database file and mark them all
** as clean.
@@ -1990,12 +2134,28 @@ static int pager_write_pagelist(PgHdr *pList){
while( pList ){
assert( pList->dirty );
sqlite3OsSeek(&pPager->fd, (pList->pgno-1)*(i64)pPager->pageSize);
- CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6);
- TRACE3("STORE %d page %d\n", pPager->fd.h, pList->pgno);
- rc = sqlite3OsWrite(&pPager->fd, PGHDR_TO_DATA(pList), pPager->pageSize);
- CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 0);
+ /* If there are dirty pages in the page cache with page numbers greater
+ ** than Pager.dbSize, this means sqlite3pager_truncate() was called to
+ ** make the file smaller (presumably by auto-vacuum code). Do not write
+ ** any such pages to the file.
+ */
+ if( pList->pgno<=pPager->dbSize ){
+ CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6);
+ TRACE3("STORE %d page %d\n", PAGERID(pPager), pList->pgno);
+ rc = sqlite3OsWrite(&pPager->fd, PGHDR_TO_DATA(pList), pPager->pageSize);
+ CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 0);
+ pPager->nWrite++;
+ }
+#ifndef NDEBUG
+ else{
+ TRACE3("NOSTORE %d page %d\n", PAGERID(pPager), pList->pgno);
+ }
+#endif
if( rc ) return rc;
pList->dirty = 0;
+#ifdef SQLITE_CHECK_PAGES
+ pList->pageHash = pager_pagehash(pList);
+#endif
pList = pList->pDirty;
}
return SQLITE_OK;
@@ -2043,12 +2203,18 @@ static PgHdr *pager_get_all_dirty_pages(Pager *pPager){
*/
int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
PgHdr *pPg;
- int rc;
+ int rc, n;
+
+ /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page
+ ** number greater than this, or zero, is requested.
+ */
+ if( pgno>PAGER_MAX_PGNO || pgno==0 ){
+ return SQLITE_CORRUPT;
+ }
/* Make sure we have not hit any critical errors.
*/
assert( pPager!=0 );
- assert( pgno!=0 );
*ppPage = 0;
if( pPager->errMask & ~(PAGER_ERR_FULL) ){
return pager_errcode(pPager);
@@ -2057,10 +2223,12 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
/* If this is the first page accessed, then get a SHARED lock
** on the database file.
*/
- if( pPager->nRef==0 && !pPager->memDb ){
- rc = pager_wait_on_lock(pPager, SHARED_LOCK);
- if( rc!=SQLITE_OK ){
- return rc;
+ if( pPager->nRef==0 && !MEMDB ){
+ if( !pPager->noReadlock ){
+ rc = pager_wait_on_lock(pPager, SHARED_LOCK);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
}
/* If a journal file exists, and there is no RESERVED lock on the
@@ -2123,7 +2291,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
}else{
/* Search for page in cache */
pPg = pager_lookup(pPager, pgno);
- if( pPager->memDb && pPager->state==PAGER_UNLOCK ){
+ if( MEMDB && pPager->state==PAGER_UNLOCK ){
pPager->state = PAGER_SHARED;
}
}
@@ -2131,20 +2299,20 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
/* The requested page is not in the page cache. */
int h;
pPager->nMiss++;
- if( pPager->nPage<pPager->mxPage || pPager->pFirst==0 || pPager->memDb ){
+ if( pPager->nPage<pPager->mxPage || pPager->pFirst==0 || MEMDB ){
/* Create a new page */
- pPg = sqliteMallocRaw( sizeof(*pPg) + pPager->pageSize
+ pPg = sqliteMallocRaw( sizeof(*pPg) + pPager->psAligned
+ sizeof(u32) + pPager->nExtra
- + pPager->memDb*sizeof(PgHistory) );
+ + MEMDB*sizeof(PgHistory) );
if( pPg==0 ){
- if( !pPager->memDb ){
+ if( !MEMDB ){
pager_unwritelock(pPager);
}
pPager->errMask |= PAGER_ERR_MEM;
return SQLITE_NOMEM;
}
memset(pPg, 0, sizeof(*pPg));
- if( pPager->memDb ){
+ if( MEMDB ){
memset(PGHDR_TO_HIST(pPg, pPager), 0, sizeof(PgHistory));
}
pPg->pPager = pPager;
@@ -2247,20 +2415,20 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
if( pPager->nExtra>0 ){
memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra);
}
- sqlite3pager_pagecount(pPager);
+ n = sqlite3pager_pagecount(pPager);
if( pPager->errMask!=0 ){
sqlite3pager_unref(PGHDR_TO_DATA(pPg));
rc = pager_errcode(pPager);
return rc;
}
- if( pPager->dbSize<(int)pgno ){
+ if( n<(int)pgno ){
memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize);
}else{
int rc;
- assert( pPager->memDb==0 );
+ assert( MEMDB==0 );
sqlite3OsSeek(&pPager->fd, (pgno-1)*(i64)pPager->pageSize);
rc = sqlite3OsRead(&pPager->fd, PGHDR_TO_DATA(pPg), pPager->pageSize);
- TRACE3("FETCH %d page %d\n", pPager->fd.h, pPg->pgno);
+ TRACE3("FETCH %d page %d\n", PAGERID(pPager), pPg->pgno);
CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3);
if( rc!=SQLITE_OK ){
i64 fileSize;
@@ -2271,8 +2439,13 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
}else{
memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize);
}
+ }else{
+ pPager->nRead++;
}
}
+#ifdef SQLITE_CHECK_PAGES
+ pPg->pageHash = pager_pagehash(pPg);
+#endif
}else{
/* The requested page is in the page cache. */
pPager->nHit++;
@@ -2325,6 +2498,8 @@ int sqlite3pager_unref(void *pData){
pPg->nRef--;
REFINFO(pPg);
+ CHECK_PAGE(pPg);
+
/* When the number of references to a page reach 0, call the
** destructor and add the page to the freelist.
*/
@@ -2351,7 +2526,7 @@ int sqlite3pager_unref(void *pData){
*/
pPager->nRef--;
assert( pPager->nRef>=0 );
- if( pPager->nRef==0 && !pPager->memDb ){
+ if( pPager->nRef==0 && !MEMDB ){
pager_reset(pPager);
}
}
@@ -2367,7 +2542,7 @@ int sqlite3pager_unref(void *pData){
*/
static int pager_open_journal(Pager *pPager){
int rc;
- assert( !pPager->memDb );
+ assert( !MEMDB );
assert( pPager->state>=PAGER_RESERVED );
assert( pPager->journalOpen==0 );
assert( pPager->useJournal );
@@ -2452,7 +2627,7 @@ int sqlite3pager_begin(void *pData, int exFlag){
assert( pPager->state!=PAGER_UNLOCK );
if( pPager->state==PAGER_SHARED ){
assert( pPager->aInJournal==0 );
- if( pPager->memDb ){
+ if( MEMDB ){
pPager->state = PAGER_EXCLUSIVE;
pPager->origDbSize = pPager->dbSize;
}else{
@@ -2471,7 +2646,7 @@ int sqlite3pager_begin(void *pData, int exFlag){
return rc;
}
pPager->dirtyCache = 0;
- TRACE2("TRANSACTION %d\n", pPager->fd.h);
+ TRACE2("TRANSACTION %d\n", PAGERID(pPager));
if( pPager->useJournal && !pPager->tempFile ){
rc = pager_open_journal(pPager);
}
@@ -2513,128 +2688,130 @@ int sqlite3pager_write(void *pData){
assert( !pPager->setMaster );
+ CHECK_PAGE(pPg);
+
/* Mark the page as dirty. If the page has already been written
** to the journal then we can return right away.
*/
pPg->dirty = 1;
if( pPg->inJournal && (pPg->inStmt || pPager->stmtInUse==0) ){
pPager->dirtyCache = 1;
- return SQLITE_OK;
- }
-
- /* If we get this far, it means that the page needs to be
- ** written to the transaction journal or the ckeckpoint journal
- ** or both.
- **
- ** First check to see that the transaction journal exists and
- ** create it if it does not.
- */
- assert( pPager->state!=PAGER_UNLOCK );
- rc = sqlite3pager_begin(pData, 0);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- assert( pPager->state>=PAGER_RESERVED );
- if( !pPager->journalOpen && pPager->useJournal ){
- rc = pager_open_journal(pPager);
- if( rc!=SQLITE_OK ) return rc;
- }
- assert( pPager->journalOpen || !pPager->useJournal );
- pPager->dirtyCache = 1;
+ }else{
- /* The transaction journal now exists and we have a RESERVED or an
- ** EXCLUSIVE lock on the main database file. Write the current page to
- ** the transaction journal if it is not there already.
- */
- if( !pPg->inJournal && (pPager->useJournal || pPager->memDb) ){
- if( (int)pPg->pgno <= pPager->origDbSize ){
- int szPg;
- u32 saved;
- if( pPager->memDb ){
+ /* If we get this far, it means that the page needs to be
+ ** written to the transaction journal or the ckeckpoint journal
+ ** or both.
+ **
+ ** First check to see that the transaction journal exists and
+ ** create it if it does not.
+ */
+ assert( pPager->state!=PAGER_UNLOCK );
+ rc = sqlite3pager_begin(pData, 0);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ assert( pPager->state>=PAGER_RESERVED );
+ if( !pPager->journalOpen && pPager->useJournal ){
+ rc = pager_open_journal(pPager);
+ if( rc!=SQLITE_OK ) return rc;
+ }
+ assert( pPager->journalOpen || !pPager->useJournal );
+ pPager->dirtyCache = 1;
+
+ /* The transaction journal now exists and we have a RESERVED or an
+ ** EXCLUSIVE lock on the main database file. Write the current page to
+ ** the transaction journal if it is not there already.
+ */
+ if( !pPg->inJournal && (pPager->useJournal || MEMDB) ){
+ if( (int)pPg->pgno <= pPager->origDbSize ){
+ int szPg;
+ u32 saved;
+ if( MEMDB ){
+ PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
+ TRACE3("JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
+ assert( pHist->pOrig==0 );
+ pHist->pOrig = sqliteMallocRaw( pPager->pageSize );
+ if( pHist->pOrig ){
+ memcpy(pHist->pOrig, PGHDR_TO_DATA(pPg), pPager->pageSize);
+ }
+ }else{
+ u32 cksum;
+ CODEC(pPager, pData, pPg->pgno, 7);
+ cksum = pager_cksum(pPager, pPg->pgno, pData);
+ saved = *(u32*)PGHDR_TO_EXTRA(pPg, pPager);
+ store32bits(cksum, pPg, pPager->pageSize);
+ szPg = pPager->pageSize+8;
+ store32bits(pPg->pgno, pPg, -4);
+ rc = sqlite3OsWrite(&pPager->jfd, &((char*)pData)[-4], szPg);
+ pPager->journalOff += szPg;
+ TRACE4("JOURNAL %d page %d needSync=%d\n",
+ PAGERID(pPager), pPg->pgno, pPg->needSync);
+ CODEC(pPager, pData, pPg->pgno, 0);
+ *(u32*)PGHDR_TO_EXTRA(pPg, pPager) = saved;
+ if( rc!=SQLITE_OK ){
+ sqlite3pager_rollback(pPager);
+ pPager->errMask |= PAGER_ERR_FULL;
+ return rc;
+ }
+ pPager->nRec++;
+ assert( pPager->aInJournal!=0 );
+ pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7);
+ pPg->needSync = !pPager->noSync;
+ if( pPager->stmtInUse ){
+ pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
+ page_add_to_stmt_list(pPg);
+ }
+ }
+ }else{
+ pPg->needSync = !pPager->journalStarted && !pPager->noSync;
+ TRACE4("APPEND %d page %d needSync=%d\n",
+ PAGERID(pPager), pPg->pgno, pPg->needSync);
+ }
+ if( pPg->needSync ){
+ pPager->needSync = 1;
+ }
+ pPg->inJournal = 1;
+ }
+
+ /* If the statement journal is open and the page is not in it,
+ ** then write the current page to the statement journal. Note that
+ ** the statement journal format differs from the standard journal format
+ ** in that it omits the checksums and the header.
+ */
+ if( pPager->stmtInUse && !pPg->inStmt && (int)pPg->pgno<=pPager->stmtSize ){
+ assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize );
+ if( MEMDB ){
PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
- TRACE3("JOURNAL %d page %d\n", pPager->fd.h, pPg->pgno);
- assert( pHist->pOrig==0 );
- pHist->pOrig = sqliteMallocRaw( pPager->pageSize );
- if( pHist->pOrig ){
- memcpy(pHist->pOrig, PGHDR_TO_DATA(pPg), pPager->pageSize);
+ assert( pHist->pStmt==0 );
+ pHist->pStmt = sqliteMallocRaw( pPager->pageSize );
+ if( pHist->pStmt ){
+ memcpy(pHist->pStmt, PGHDR_TO_DATA(pPg), pPager->pageSize);
}
+ TRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
}else{
- u32 cksum;
- CODEC(pPager, pData, pPg->pgno, 7);
- cksum = pager_cksum(pPager, pPg->pgno, pData);
- saved = *(u32*)PGHDR_TO_EXTRA(pPg, pPager);
- store32bits(cksum, pPg, pPager->pageSize);
- szPg = pPager->pageSize+8;
store32bits(pPg->pgno, pPg, -4);
- rc = sqlite3OsWrite(&pPager->jfd, &((char*)pData)[-4], szPg);
- pPager->journalOff += szPg;
- TRACE4("JOURNAL %d page %d needSync=%d\n",
- pPager->fd.h, pPg->pgno, pPg->needSync);
+ CODEC(pPager, pData, pPg->pgno, 7);
+ rc = sqlite3OsWrite(&pPager->stfd,((char*)pData)-4, pPager->pageSize+4);
+ TRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
CODEC(pPager, pData, pPg->pgno, 0);
- *(u32*)PGHDR_TO_EXTRA(pPg, pPager) = saved;
if( rc!=SQLITE_OK ){
sqlite3pager_rollback(pPager);
pPager->errMask |= PAGER_ERR_FULL;
return rc;
}
- pPager->nRec++;
- assert( pPager->aInJournal!=0 );
- pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7);
- pPg->needSync = !pPager->noSync;
- if( pPager->stmtInUse ){
- pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
- page_add_to_stmt_list(pPg);
- }
+ pPager->stmtNRec++;
+ assert( pPager->aInStmt!=0 );
+ pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
}
- }else{
- pPg->needSync = !pPager->journalStarted && !pPager->noSync;
- TRACE4("APPEND %d page %d needSync=%d\n",
- pPager->fd.h, pPg->pgno, pPg->needSync);
- }
- if( pPg->needSync ){
- pPager->needSync = 1;
- }
- pPg->inJournal = 1;
- }
-
- /* If the statement journal is open and the page is not in it,
- ** then write the current page to the statement journal. Note that
- ** the statement journal format differs from the standard journal format
- ** in that it omits the checksums and the header.
- */
- if( pPager->stmtInUse && !pPg->inStmt && (int)pPg->pgno<=pPager->stmtSize ){
- assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize );
- if( pPager->memDb ){
- PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
- assert( pHist->pStmt==0 );
- pHist->pStmt = sqliteMallocRaw( pPager->pageSize );
- if( pHist->pStmt ){
- memcpy(pHist->pStmt, PGHDR_TO_DATA(pPg), pPager->pageSize);
- }
- TRACE3("STMT-JOURNAL %d page %d\n", pPager->fd.h, pPg->pgno);
- }else{
- store32bits(pPg->pgno, pPg, -4);
- CODEC(pPager, pData, pPg->pgno, 7);
- rc = sqlite3OsWrite(&pPager->stfd, ((char*)pData)-4, pPager->pageSize+4);
- TRACE3("STMT-JOURNAL %d page %d\n", pPager->fd.h, pPg->pgno);
- CODEC(pPager, pData, pPg->pgno, 0);
- if( rc!=SQLITE_OK ){
- sqlite3pager_rollback(pPager);
- pPager->errMask |= PAGER_ERR_FULL;
- return rc;
- }
- pPager->stmtNRec++;
- assert( pPager->aInStmt!=0 );
- pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
+ page_add_to_stmt_list(pPg);
}
- page_add_to_stmt_list(pPg);
}
/* Update the database size and return.
*/
if( pPager->dbSize<(int)pPg->pgno ){
pPager->dbSize = pPg->pgno;
- if( !pPager->memDb && pPager->dbSize==PENDING_BYTE/pPager->pageSize ){
+ if( !MEMDB && pPager->dbSize==PENDING_BYTE/pPager->pageSize ){
pPager->dbSize++;
}
}
@@ -2651,6 +2828,7 @@ int sqlite3pager_iswriteable(void *pData){
return pPg->dirty;
}
+#ifndef SQLITE_OMIT_VACUUM
/*
** Replace the content of a single page with the information in the third
** argument.
@@ -2669,6 +2847,7 @@ int sqlite3pager_overwrite(Pager *pPager, Pgno pgno, void *pData){
}
return rc;
}
+#endif
/*
** A call to this routine tells the pager that it is not necessary to
@@ -2697,7 +2876,7 @@ int sqlite3pager_overwrite(Pager *pPager, Pgno pgno, void *pData){
void sqlite3pager_dont_write(Pager *pPager, Pgno pgno){
PgHdr *pPg;
- if( pPager->memDb ) return;
+ if( MEMDB ) return;
pPg = pager_lookup(pPager, pgno);
pPg->alwaysRollback = 1;
@@ -2712,8 +2891,11 @@ void sqlite3pager_dont_write(Pager *pPager, Pgno pgno){
** corruption during the next transaction.
*/
}else{
- TRACE3("DONT_WRITE page %d of %d\n", pgno, pPager->fd.h);
+ TRACE3("DONT_WRITE page %d of %d\n", pgno, PAGERID(pPager));
pPg->dirty = 0;
+#ifdef SQLITE_CHECK_PAGES
+ pPg->pageHash = pager_pagehash(pPg);
+#endif
}
}
}
@@ -2729,7 +2911,7 @@ void sqlite3pager_dont_rollback(void *pData){
Pager *pPager = pPg->pPager;
if( pPager->state!=PAGER_EXCLUSIVE || pPager->journalOpen==0 ) return;
- if( pPg->alwaysRollback || pPager->alwaysRollback || pPager->memDb ) return;
+ if( pPg->alwaysRollback || pPager->alwaysRollback || MEMDB ) return;
if( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ){
assert( pPager->aInJournal!=0 );
pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7);
@@ -2738,7 +2920,7 @@ void sqlite3pager_dont_rollback(void *pData){
pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
page_add_to_stmt_list(pPg);
}
- TRACE3("DONT_ROLLBACK page %d of %d\n", pPg->pgno, pPager->fd.h);
+ TRACE3("DONT_ROLLBACK page %d of %d\n", pPg->pgno, PAGERID(pPager));
}
if( pPager->stmtInUse && !pPg->inStmt && (int)pPg->pgno<=pPager->stmtSize ){
assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize );
@@ -2749,6 +2931,7 @@ void sqlite3pager_dont_rollback(void *pData){
}
+#ifndef SQLITE_OMIT_MEMORYDB
/*
** Clear a PgHistory block
*/
@@ -2758,6 +2941,9 @@ static void clearHistory(PgHistory *pHist){
pHist->pOrig = 0;
pHist->pStmt = 0;
}
+#else
+#define clearHistory(x)
+#endif
/*
** Commit all changes to the database and release the write lock.
@@ -2784,8 +2970,8 @@ int sqlite3pager_commit(Pager *pPager){
if( pPager->state<PAGER_RESERVED ){
return SQLITE_ERROR;
}
- TRACE2("COMMIT %d\n", pPager->fd.h);
- if( pPager->memDb ){
+ TRACE2("COMMIT %d\n", PAGERID(pPager));
+ if( MEMDB ){
pPg = pager_get_all_dirty_pages(pPager);
while( pPg ){
clearHistory(PGHDR_TO_HIST(pPg, pPager));
@@ -2816,7 +3002,7 @@ int sqlite3pager_commit(Pager *pPager){
return rc;
}
assert( pPager->journalOpen );
- rc = sqlite3pager_sync(pPager, 0);
+ rc = sqlite3pager_sync(pPager, 0, 0);
if( rc!=SQLITE_OK ){
goto commit_abort;
}
@@ -2845,8 +3031,8 @@ commit_abort:
*/
int sqlite3pager_rollback(Pager *pPager){
int rc;
- TRACE2("ROLLBACK %d\n", pPager->fd.h);
- if( pPager->memDb ){
+ TRACE2("ROLLBACK %d\n", PAGERID(pPager));
+ if( MEMDB ){
PgHdr *p;
for(p=pPager->pAll; p; p=p->pNextAll){
PgHistory *pHist;
@@ -2860,9 +3046,9 @@ int sqlite3pager_rollback(Pager *pPager){
pHist = PGHDR_TO_HIST(p, pPager);
if( pHist->pOrig ){
memcpy(PGHDR_TO_DATA(p), pHist->pOrig, pPager->pageSize);
- TRACE3("ROLLBACK-PAGE %d of %d\n", p->pgno, pPager->fd.h);
+ TRACE3("ROLLBACK-PAGE %d of %d\n", p->pgno, PAGERID(pPager));
}else{
- TRACE3("PAGE %d is clean on %d\n", p->pgno, pPager->fd.h);
+ TRACE3("PAGE %d is clean on %d\n", p->pgno, PAGERID(pPager));
}
clearHistory(pHist);
p->dirty = 0;
@@ -2896,13 +3082,11 @@ int sqlite3pager_rollback(Pager *pPager){
return pager_errcode(pPager);
}
if( pPager->state==PAGER_RESERVED ){
- int rc2, rc3;
+ int rc2;
rc = pager_reload_cache(pPager);
- rc2 = pager_truncate(pPager, pPager->origDbSize);
- rc3 = pager_unwritelock(pPager);
+ rc2 = pager_unwritelock(pPager);
if( rc==SQLITE_OK ){
rc = rc2;
- if( rc3 ) rc = rc3;
}
}else{
rc = pager_playback(pPager);
@@ -2927,7 +3111,7 @@ int sqlite3pager_isreadonly(Pager *pPager){
** This routine is used for testing and analysis only.
*/
int *sqlite3pager_stats(Pager *pPager){
- static int a[9];
+ static int a[11];
a[0] = pPager->nRef;
a[1] = pPager->nPage;
a[2] = pPager->mxPage;
@@ -2937,6 +3121,8 @@ int *sqlite3pager_stats(Pager *pPager){
a[6] = pPager->nHit;
a[7] = pPager->nMiss;
a[8] = pPager->nOvfl;
+ a[9] = pPager->nRead;
+ a[10] = pPager->nWrite;
return a;
}
@@ -2952,8 +3138,8 @@ int sqlite3pager_stmt_begin(Pager *pPager){
char zTemp[SQLITE_TEMPNAME_SIZE];
assert( !pPager->stmtInUse );
assert( pPager->dbSize>=0 );
- TRACE2("STMT-BEGIN %d\n", pPager->fd.h);
- if( pPager->memDb ){
+ TRACE2("STMT-BEGIN %d\n", PAGERID(pPager));
+ if( MEMDB ){
pPager->stmtInUse = 1;
pPager->stmtSize = pPager->dbSize;
return SQLITE_OK;
@@ -3000,8 +3186,8 @@ stmt_begin_failed:
int sqlite3pager_stmt_commit(Pager *pPager){
if( pPager->stmtInUse ){
PgHdr *pPg, *pNext;
- TRACE2("STMT-COMMIT %d\n", pPager->fd.h);
- if( !pPager->memDb ){
+ TRACE2("STMT-COMMIT %d\n", PAGERID(pPager));
+ if( !MEMDB ){
sqlite3OsSeek(&pPager->stfd, 0);
/* sqlite3OsTruncate(&pPager->stfd, 0); */
sqliteFree( pPager->aInStmt );
@@ -3012,7 +3198,7 @@ int sqlite3pager_stmt_commit(Pager *pPager){
assert( pPg->inStmt );
pPg->inStmt = 0;
pPg->pPrevStmt = pPg->pNextStmt = 0;
- if( pPager->memDb ){
+ if( MEMDB ){
PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
sqliteFree(pHist->pStmt);
pHist->pStmt = 0;
@@ -3032,8 +3218,8 @@ int sqlite3pager_stmt_commit(Pager *pPager){
int sqlite3pager_stmt_rollback(Pager *pPager){
int rc;
if( pPager->stmtInUse ){
- TRACE2("STMT-ROLLBACK %d\n", pPager->fd.h);
- if( pPager->memDb ){
+ TRACE2("STMT-ROLLBACK %d\n", PAGERID(pPager));
+ if( MEMDB ){
PgHdr *pPg;
for(pPg=pPager->pStmt; pPg; pPg=pPg->pNextStmt){
PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
@@ -3132,14 +3318,20 @@ static int pager_incr_changecounter(Pager *pPager){
**
** Note that if zMaster==NULL, this does not overwrite a previous value
** passed to an sqlite3pager_sync() call.
+**
+** If parameter nTrunc is non-zero, then the pager file is truncated to
+** nTrunc pages (this is used by auto-vacuum databases).
*/
-int sqlite3pager_sync(Pager *pPager, const char *zMaster){
+int sqlite3pager_sync(Pager *pPager, const char *zMaster, Pgno nTrunc){
int rc = SQLITE_OK;
+ TRACE4("DATABASE SYNC: File=%s zMaster=%s nTrunc=%d\n",
+ pPager->zFilename, zMaster, nTrunc);
+
/* If this is an in-memory db, or no pages have been written to, or this
** function has already been called, it is a no-op.
*/
- if( pPager->state!=PAGER_SYNCED && !pPager->memDb && pPager->dirtyCache ){
+ if( pPager->state!=PAGER_SYNCED && !MEMDB && pPager->dirtyCache ){
PgHdr *pPg;
assert( pPager->journalOpen );
@@ -3152,12 +3344,38 @@ int sqlite3pager_sync(Pager *pPager, const char *zMaster){
if( !pPager->setMaster ){
rc = pager_incr_changecounter(pPager);
if( rc!=SQLITE_OK ) goto sync_exit;
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( nTrunc!=0 ){
+ /* If this transaction has made the database smaller, then all pages
+ ** being discarded by the truncation must be written to the journal
+ ** file.
+ */
+ Pgno i;
+ void *pPage;
+ for( i=nTrunc+1; i<=pPager->origDbSize; i++ ){
+ if( !(pPager->aInJournal[i/8] & (1<<(i&7))) ){
+ rc = sqlite3pager_get(pPager, i, &pPage);
+ if( rc!=SQLITE_OK ) goto sync_exit;
+ rc = sqlite3pager_write(pPage);
+ sqlite3pager_unref(pPage);
+ if( rc!=SQLITE_OK ) goto sync_exit;
+ }
+ }
+ }
+#endif
rc = writeMasterJournal(pPager, zMaster);
if( rc!=SQLITE_OK ) goto sync_exit;
rc = syncJournal(pPager);
if( rc!=SQLITE_OK ) goto sync_exit;
}
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( nTrunc!=0 ){
+ rc = sqlite3pager_truncate(pPager, nTrunc);
+ if( rc!=SQLITE_OK ) goto sync_exit;
+ }
+#endif
+
/* Write all dirty pages to the database file */
pPg = pager_get_all_dirty_pages(pPager);
rc = pager_write_pagelist(pPg);
@@ -3175,6 +3393,102 @@ sync_exit:
return rc;
}
+#ifndef SQLITE_OMIT_AUTOVACUUM
+/*
+** Move the page identified by pData to location pgno in the file.
+**
+** There must be no references to the current page pgno. If current page
+** pgno is not already in the rollback journal, it is not written there by
+** by this routine. The same applies to the page pData refers to on entry to
+** this routine.
+**
+** References to the page refered to by pData remain valid. Updating any
+** meta-data associated with page pData (i.e. data stored in the nExtra bytes
+** allocated along with the page) is the responsibility of the caller.
+**
+** A transaction must be active when this routine is called, however it is
+** illegal to call this routine if a statment transaction is active.
+*/
+int sqlite3pager_movepage(Pager *pPager, void *pData, Pgno pgno){
+ PgHdr *pPg = DATA_TO_PGHDR(pData);
+ PgHdr *pPgOld;
+ int h;
+ Pgno needSyncPgno = 0;
+
+ assert( !pPager->stmtInUse );
+ assert( pPg->nRef>0 );
+
+ TRACE5("MOVE %d page %d (needSync=%d) moves to %d\n",
+ PAGERID(pPager), pPg->pgno, pPg->needSync, pgno);
+
+ if( pPg->needSync ){
+ needSyncPgno = pPg->pgno;
+ assert( pPg->inJournal );
+ assert( pPg->dirty );
+ assert( pPager->needSync );
+ }
+
+ /* Unlink pPg from it's hash-chain */
+ unlinkHashChain(pPager, pPg);
+
+ /* If the cache contains a page with page-number pgno, remove it
+ ** from it's hash chain. Also, if the PgHdr.needSync was set for
+ ** page pgno before the 'move' operation, it needs to be retained
+ ** for the page moved there.
+ */
+ pPgOld = pager_lookup(pPager, pgno);
+ if( pPgOld ){
+ assert( pPgOld->nRef==0 );
+ unlinkHashChain(pPager, pPgOld);
+ pPgOld->dirty = 0;
+ if( pPgOld->needSync ){
+ assert( pPgOld->inJournal );
+ pPg->inJournal = 1;
+ pPg->needSync = 1;
+ assert( pPager->needSync );
+ }
+ }
+
+ /* Change the page number for pPg and insert it into the new hash-chain. */
+ pPg->pgno = pgno;
+ h = pager_hash(pgno);
+ if( pPager->aHash[h] ){
+ assert( pPager->aHash[h]->pPrevHash==0 );
+ pPager->aHash[h]->pPrevHash = pPg;
+ }
+ pPg->pNextHash = pPager->aHash[h];
+ pPager->aHash[h] = pPg;
+ pPg->pPrevHash = 0;
+
+ pPg->dirty = 1;
+ pPager->dirtyCache = 1;
+
+ if( needSyncPgno ){
+ /* If needSyncPgno is non-zero, then the journal file needs to be
+ ** sync()ed before any data is written to database file page needSyncPgno.
+ ** Currently, no such page exists in the page-cache and the
+ ** Pager.aInJournal bit has been set. This needs to be remedied by loading
+ ** the page into the pager-cache and setting the PgHdr.needSync flag.
+ **
+ ** The sqlite3pager_get() call may cause the journal to sync. So make
+ ** sure the Pager.needSync flag is set too.
+ */
+ int rc;
+ void *pNeedSync;
+ assert( pPager->needSync );
+ rc = sqlite3pager_get(pPager, needSyncPgno, &pNeedSync);
+ if( rc!=SQLITE_OK ) return rc;
+ pPager->needSync = 1;
+ DATA_TO_PGHDR(pNeedSync)->needSync = 1;
+ DATA_TO_PGHDR(pNeedSync)->inJournal = 1;
+ DATA_TO_PGHDR(pNeedSync)->dirty = 1;
+ sqlite3pager_unref(pNeedSync);
+ }
+
+ return SQLITE_OK;
+}
+#endif
+
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
/*
** Return the current state of the file lock for the given pager.
@@ -3190,7 +3504,7 @@ int sqlite3pager_lockstate(Pager *pPager){
}
#endif
-#ifdef SQLITE_TEST
+#ifdef SQLITE_DEBUG
/*
** Print a listing of all referenced pages and their ref count.
*/
diff --git a/ext/pdo_sqlite/sqlite/src/pager.h b/ext/pdo_sqlite/sqlite/src/pager.h
index 0231e27a93..a592b1944b 100644
--- a/ext/pdo_sqlite/sqlite/src/pager.h
+++ b/ext/pdo_sqlite/sqlite/src/pager.h
@@ -50,13 +50,21 @@ typedef unsigned int Pgno;
*/
typedef struct Pager Pager;
+/*
+** Allowed values for the flags parameter to sqlite3pager_open().
+**
+** NOTE: This values must match the corresponding BTREE_ values in btree.h.
+*/
+#define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */
+#define PAGER_NO_READLOCK 0x0002 /* Omit readlocks on readonly files */
+
/*
** See source code comments for a detailed description of the following
** routines:
*/
int sqlite3pager_open(Pager **ppPager, const char *zFilename,
- int nExtra, int useJournal);
+ int nExtra, int flags);
void sqlite3pager_set_busyhandler(Pager*, BusyHandler *pBusyHandler);
void sqlite3pager_set_destructor(Pager*, void(*)(void*,int));
void sqlite3pager_set_reiniter(Pager*, void(*)(void*,int));
@@ -76,7 +84,7 @@ int sqlite3pager_pagecount(Pager*);
int sqlite3pager_truncate(Pager*,Pgno);
int sqlite3pager_begin(void*, int exFlag);
int sqlite3pager_commit(Pager*);
-int sqlite3pager_sync(Pager*,const char *zMaster);
+int sqlite3pager_sync(Pager*,const char *zMaster, Pgno);
int sqlite3pager_rollback(Pager*);
int sqlite3pager_isreadonly(Pager*);
int sqlite3pager_stmt_begin(Pager*);
@@ -91,6 +99,7 @@ const char *sqlite3pager_dirname(Pager*);
const char *sqlite3pager_journalname(Pager*);
int sqlite3pager_rename(Pager*, const char *zNewName);
void sqlite3pager_set_codec(Pager*,void(*)(void*,void*,Pgno,int),void*);
+int sqlite3pager_movepage(Pager*,void*,Pgno);
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
int sqlite3pager_lockstate(Pager*);
diff --git a/ext/pdo_sqlite/sqlite/src/parse.c b/ext/pdo_sqlite/sqlite/src/parse.c
index 1856c3ea97..bec7a0a433 100644
--- a/ext/pdo_sqlite/sqlite/src/parse.c
+++ b/ext/pdo_sqlite/sqlite/src/parse.c
@@ -1,10 +1,10 @@
-/* Driver template for the LEMON parser generator.
+/* Driver template for the LEMON parser generator.
** The author disclaims copyright to this source code.
*/
/* First off, code is include which follows the "include" declaration
** in the input file. */
#include <stdio.h>
-#line 33 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 33 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
#include "sqliteInt.h"
#include "parse.h"
@@ -14,8 +14,8 @@
** LIMIT clause of a SELECT statement.
*/
struct LimitVal {
- int limit; /* The LIMIT value. -1 if there is no limit */
- int offset; /* The OFFSET. 0 if there is none */
+ Expr *pLimit; /* The LIMIT expression. NULL if there is no limit */
+ Expr *pOffset; /* The OFFSET expression. NULL if there is none */
};
/*
@@ -43,7 +43,7 @@ struct TrigEvent { int a; IdList * b; };
*/
struct AttachKey { int type; Token key; };
-#line 48 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 48 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
/* Next is all token values, in a form suitable for use by makeheaders.
** This section will be null unless lemon is run with the -m switch.
*/
@@ -93,35 +93,35 @@ struct AttachKey { int type; Token key; };
** defined, then do no error processing.
*/
#define YYCODETYPE unsigned char
-#define YYNOCODE 225
+#define YYNOCODE 239
#define YYACTIONTYPE unsigned short int
#define sqlite3ParserTOKENTYPE Token
typedef union {
sqlite3ParserTOKENTYPE yy0;
- struct {int value; int mask;} yy47;
- TriggerStep* yy91;
- Token yy98;
- Select* yy107;
- struct TrigEvent yy146;
- ExprList* yy210;
- Expr* yy258;
- SrcList* yy259;
+ struct AttachKey yy40;
+ int yy60;
+ struct TrigEvent yy62;
+ struct {int value; int mask;} yy243;
+ struct LikeOp yy258;
+ ExprList* yy266;
IdList* yy272;
- int yy284;
- struct AttachKey yy292;
- struct LikeOp yy342;
- struct LimitVal yy404;
- int yy449;
+ Select* yy331;
+ struct LimitVal yy348;
+ Token yy406;
+ SrcList* yy427;
+ Expr* yy454;
+ TriggerStep* yy455;
+ int yy477;
} YYMINORTYPE;
#define YYSTACKDEPTH 100
#define sqlite3ParserARG_SDECL Parse *pParse;
#define sqlite3ParserARG_PDECL ,Parse *pParse
#define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse
#define sqlite3ParserARG_STORE yypParser->pParse = pParse
-#define YYNSTATE 537
-#define YYNRULE 292
-#define YYERRORSYMBOL 130
-#define YYERRSYMDT yy449
+#define YYNSTATE 564
+#define YYNRULE 305
+#define YYERRORSYMBOL 141
+#define YYERRSYMDT yy477
#define YYFALLBACK 1
#define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
@@ -175,430 +175,481 @@ typedef union {
** yy_default[] Default action for each state.
*/
static const YYACTIONTYPE yy_action[] = {
- /* 0 */ 257, 325, 255, 138, 140, 142, 144, 146, 148, 150,
- /* 10 */ 152, 154, 156, 89, 87, 88, 159, 12, 4, 6,
- /* 20 */ 158, 537, 38, 24, 830, 1, 536, 3, 329, 488,
- /* 30 */ 534, 535, 319, 50, 124, 112, 160, 169, 174, 179,
- /* 40 */ 168, 173, 134, 136, 128, 130, 126, 132, 138, 140,
- /* 50 */ 142, 144, 146, 148, 150, 152, 154, 156, 26, 73,
- /* 60 */ 384, 256, 39, 58, 64, 66, 299, 330, 612, 611,
- /* 70 */ 351, 30, 92, 332, 326, 159, 13, 14, 353, 158,
- /* 80 */ 5, 355, 361, 366, 499, 146, 148, 150, 152, 154,
- /* 90 */ 156, 12, 369, 124, 112, 160, 169, 174, 179, 168,
- /* 100 */ 173, 134, 136, 128, 130, 126, 132, 138, 140, 142,
- /* 110 */ 144, 146, 148, 150, 152, 154, 156, 128, 130, 126,
- /* 120 */ 132, 138, 140, 142, 144, 146, 148, 150, 152, 154,
- /* 130 */ 156, 659, 353, 244, 62, 355, 361, 366, 79, 12,
- /* 140 */ 63, 98, 96, 289, 159, 280, 369, 349, 158, 181,
- /* 150 */ 13, 14, 27, 12, 546, 383, 32, 10, 368, 273,
- /* 160 */ 515, 765, 124, 112, 160, 169, 174, 179, 168, 173,
- /* 170 */ 134, 136, 128, 130, 126, 132, 138, 140, 142, 144,
- /* 180 */ 146, 148, 150, 152, 154, 156, 810, 349, 47, 73,
- /* 190 */ 222, 763, 223, 114, 246, 31, 32, 48, 13, 14,
- /* 200 */ 74, 274, 252, 166, 175, 180, 275, 304, 49, 8,
- /* 210 */ 255, 45, 13, 14, 159, 290, 350, 382, 158, 245,
- /* 220 */ 441, 46, 378, 183, 247, 185, 186, 15, 16, 17,
- /* 230 */ 73, 205, 124, 112, 160, 169, 174, 179, 168, 173,
- /* 240 */ 134, 136, 128, 130, 126, 132, 138, 140, 142, 144,
- /* 250 */ 146, 148, 150, 152, 154, 156, 542, 306, 438, 159,
- /* 260 */ 98, 96, 332, 158, 272, 475, 447, 437, 12, 256,
- /* 270 */ 288, 12, 304, 339, 287, 50, 77, 124, 112, 160,
- /* 280 */ 169, 174, 179, 168, 173, 134, 136, 128, 130, 126,
- /* 290 */ 132, 138, 140, 142, 144, 146, 148, 150, 152, 154,
- /* 300 */ 156, 547, 36, 335, 39, 58, 64, 66, 299, 330,
- /* 310 */ 35, 334, 291, 545, 114, 332, 114, 329, 12, 625,
- /* 320 */ 353, 187, 306, 355, 361, 366, 422, 13, 14, 159,
- /* 330 */ 13, 14, 184, 158, 369, 636, 188, 259, 188, 764,
- /* 340 */ 91, 87, 88, 100, 87, 88, 219, 124, 112, 160,
- /* 350 */ 169, 174, 179, 168, 173, 134, 136, 128, 130, 126,
- /* 360 */ 132, 138, 140, 142, 144, 146, 148, 150, 152, 154,
- /* 370 */ 156, 297, 282, 114, 292, 51, 237, 13, 14, 150,
- /* 380 */ 152, 154, 156, 114, 12, 225, 53, 225, 159, 166,
- /* 390 */ 175, 180, 158, 380, 303, 111, 433, 658, 69, 92,
- /* 400 */ 379, 183, 92, 185, 186, 111, 124, 112, 160, 169,
- /* 410 */ 174, 179, 168, 173, 134, 136, 128, 130, 126, 132,
- /* 420 */ 138, 140, 142, 144, 146, 148, 150, 152, 154, 156,
- /* 430 */ 103, 230, 561, 159, 773, 12, 286, 158, 631, 534,
- /* 440 */ 535, 105, 815, 13, 14, 166, 175, 180, 203, 808,
- /* 450 */ 215, 124, 112, 160, 169, 174, 179, 168, 173, 134,
- /* 460 */ 136, 128, 130, 126, 132, 138, 140, 142, 144, 146,
- /* 470 */ 148, 150, 152, 154, 156, 2, 3, 183, 159, 185,
- /* 480 */ 186, 813, 158, 43, 44, 569, 33, 633, 41, 348,
- /* 490 */ 340, 413, 415, 414, 13, 14, 124, 112, 160, 169,
- /* 500 */ 174, 179, 168, 173, 134, 136, 128, 130, 126, 132,
- /* 510 */ 138, 140, 142, 144, 146, 148, 150, 152, 154, 156,
- /* 520 */ 249, 336, 697, 159, 337, 338, 183, 158, 185, 186,
- /* 530 */ 56, 57, 183, 11, 185, 186, 183, 416, 185, 186,
- /* 540 */ 402, 124, 112, 160, 169, 174, 179, 168, 173, 134,
- /* 550 */ 136, 128, 130, 126, 132, 138, 140, 142, 144, 146,
- /* 560 */ 148, 150, 152, 154, 156, 342, 87, 88, 159, 345,
- /* 570 */ 87, 88, 158, 98, 96, 183, 404, 185, 186, 240,
- /* 580 */ 9, 183, 92, 185, 186, 802, 124, 177, 160, 169,
- /* 590 */ 174, 179, 168, 173, 134, 136, 128, 130, 126, 132,
- /* 600 */ 138, 140, 142, 144, 146, 148, 150, 152, 154, 156,
- /* 610 */ 787, 341, 257, 159, 255, 255, 183, 158, 185, 186,
- /* 620 */ 94, 95, 480, 518, 92, 307, 314, 316, 92, 548,
- /* 630 */ 325, 171, 112, 160, 169, 174, 179, 168, 173, 134,
- /* 640 */ 136, 128, 130, 126, 132, 138, 140, 142, 144, 146,
- /* 650 */ 148, 150, 152, 154, 156, 255, 25, 486, 159, 482,
- /* 660 */ 170, 358, 158, 19, 241, 242, 252, 266, 513, 267,
- /* 670 */ 259, 553, 72, 256, 256, 402, 68, 244, 160, 169,
- /* 680 */ 174, 179, 168, 173, 134, 136, 128, 130, 126, 132,
- /* 690 */ 138, 140, 142, 144, 146, 148, 150, 152, 154, 156,
- /* 700 */ 207, 255, 72, 326, 780, 260, 68, 267, 514, 47,
- /* 710 */ 189, 428, 388, 385, 256, 325, 259, 21, 48, 162,
- /* 720 */ 395, 12, 114, 161, 516, 517, 195, 193, 294, 49,
- /* 730 */ 207, 484, 209, 312, 191, 70, 71, 387, 246, 113,
- /* 740 */ 189, 164, 165, 73, 198, 114, 363, 396, 114, 391,
- /* 750 */ 73, 277, 529, 313, 436, 182, 195, 193, 72, 467,
- /* 760 */ 256, 623, 68, 245, 191, 70, 71, 188, 163, 113,
- /* 770 */ 188, 119, 120, 121, 122, 197, 114, 803, 691, 72,
- /* 780 */ 13, 14, 92, 68, 73, 73, 207, 77, 326, 73,
- /* 790 */ 199, 807, 99, 436, 452, 293, 189, 223, 474, 325,
- /* 800 */ 309, 119, 120, 121, 122, 197, 423, 207, 221, 460,
- /* 810 */ 434, 419, 195, 193, 418, 90, 224, 189, 77, 225,
- /* 820 */ 191, 70, 71, 73, 442, 113, 420, 114, 325, 444,
- /* 830 */ 372, 468, 114, 195, 193, 283, 325, 311, 310, 402,
- /* 840 */ 470, 191, 70, 71, 114, 7, 113, 41, 460, 474,
- /* 850 */ 18, 20, 22, 386, 296, 114, 457, 119, 120, 121,
- /* 860 */ 122, 197, 766, 446, 521, 554, 123, 430, 444, 23,
- /* 870 */ 531, 114, 326, 114, 114, 481, 114, 125, 119, 120,
- /* 880 */ 121, 122, 197, 510, 72, 441, 114, 238, 68, 114,
- /* 890 */ 508, 506, 114, 127, 114, 129, 131, 114, 133, 411,
- /* 900 */ 412, 322, 114, 114, 114, 114, 407, 114, 135, 326,
- /* 910 */ 660, 137, 207, 114, 139, 114, 141, 451, 114, 143,
- /* 920 */ 114, 114, 189, 114, 145, 147, 149, 151, 114, 153,
- /* 930 */ 489, 493, 437, 114, 114, 155, 479, 157, 195, 193,
- /* 940 */ 167, 77, 176, 178, 114, 190, 191, 70, 71, 114,
- /* 950 */ 192, 113, 114, 114, 114, 194, 196, 114, 691, 114,
- /* 960 */ 269, 320, 343, 321, 344, 269, 204, 114, 359, 284,
- /* 970 */ 321, 206, 114, 555, 216, 218, 220, 114, 364, 234,
- /* 980 */ 321, 239, 660, 119, 120, 121, 122, 197, 373, 271,
- /* 990 */ 321, 281, 114, 114, 367, 227, 227, 269, 431, 408,
- /* 1000 */ 321, 503, 439, 44, 465, 473, 267, 471, 114, 77,
- /* 1010 */ 402, 402, 402, 402, 455, 459, 265, 457, 402, 402,
- /* 1020 */ 823, 417, 504, 507, 556, 471, 28, 29, 560, 37,
- /* 1030 */ 472, 73, 34, 55, 40, 41, 42, 54, 59, 67,
- /* 1040 */ 570, 571, 52, 75, 60, 78, 483, 485, 487, 491,
- /* 1050 */ 61, 65, 76, 464, 495, 501, 101, 527, 77, 238,
- /* 1060 */ 233, 235, 85, 93, 86, 80, 97, 238, 102, 81,
- /* 1070 */ 104, 82, 108, 107, 109, 110, 83, 115, 497, 84,
- /* 1080 */ 117, 116, 156, 172, 637, 217, 638, 118, 202, 226,
- /* 1090 */ 639, 208, 106, 211, 227, 210, 213, 214, 212, 229,
- /* 1100 */ 228, 231, 236, 223, 200, 243, 201, 251, 248, 250,
- /* 1110 */ 254, 253, 232, 258, 261, 270, 264, 263, 262, 268,
- /* 1120 */ 276, 278, 285, 295, 318, 279, 300, 303, 301, 305,
- /* 1130 */ 333, 346, 298, 323, 327, 356, 357, 362, 370, 302,
- /* 1140 */ 371, 53, 374, 394, 399, 354, 331, 375, 401, 409,
- /* 1150 */ 308, 347, 315, 324, 406, 317, 405, 328, 795, 390,
- /* 1160 */ 389, 392, 397, 410, 421, 800, 360, 381, 365, 393,
- /* 1170 */ 398, 352, 376, 403, 801, 377, 400, 425, 426, 424,
- /* 1180 */ 427, 429, 771, 432, 772, 435, 440, 698, 443, 794,
- /* 1190 */ 445, 438, 809, 449, 699, 450, 453, 448, 454, 456,
- /* 1200 */ 811, 458, 461, 462, 463, 469, 812, 814, 476, 630,
- /* 1210 */ 478, 632, 779, 821, 490, 477, 690, 492, 494, 496,
- /* 1220 */ 498, 693, 500, 505, 696, 509, 781, 511, 782, 783,
- /* 1230 */ 466, 784, 785, 502, 512, 786, 520, 822, 519, 530,
- /* 1240 */ 524, 824, 523, 825, 525, 528, 533, 828, 518, 518,
- /* 1250 */ 518, 518, 518, 518, 522, 518, 526, 518, 518, 532,
+ /* 0 */ 263, 261, 261, 154, 124, 126, 128, 130, 132, 134,
+ /* 10 */ 136, 138, 140, 142, 350, 567, 145, 641, 261, 369,
+ /* 20 */ 144, 114, 116, 112, 118, 7, 124, 126, 128, 130,
+ /* 30 */ 132, 134, 136, 138, 140, 142, 136, 138, 140, 142,
+ /* 40 */ 110, 94, 146, 157, 162, 167, 156, 161, 120, 122,
+ /* 50 */ 114, 116, 112, 118, 9, 124, 126, 128, 130, 132,
+ /* 60 */ 134, 136, 138, 140, 142, 574, 223, 262, 262, 124,
+ /* 70 */ 126, 128, 130, 132, 134, 136, 138, 140, 142, 13,
+ /* 80 */ 96, 145, 13, 2, 262, 144, 4, 78, 371, 92,
+ /* 90 */ 10, 373, 380, 385, 132, 134, 136, 138, 140, 142,
+ /* 100 */ 75, 3, 562, 388, 296, 110, 94, 146, 157, 162,
+ /* 110 */ 167, 156, 161, 120, 122, 114, 116, 112, 118, 77,
+ /* 120 */ 124, 126, 128, 130, 132, 134, 136, 138, 140, 142,
+ /* 130 */ 145, 65, 573, 13, 144, 11, 371, 66, 292, 373,
+ /* 140 */ 380, 385, 870, 1, 563, 14, 15, 4, 14, 15,
+ /* 150 */ 172, 388, 51, 665, 110, 94, 146, 157, 162, 167,
+ /* 160 */ 156, 161, 120, 122, 114, 116, 112, 118, 72, 124,
+ /* 170 */ 126, 128, 130, 132, 134, 136, 138, 140, 142, 51,
+ /* 180 */ 37, 341, 40, 59, 67, 69, 305, 336, 107, 106,
+ /* 190 */ 108, 847, 572, 34, 338, 96, 366, 349, 13, 14,
+ /* 200 */ 15, 371, 12, 145, 373, 380, 385, 144, 564, 40,
+ /* 210 */ 59, 67, 69, 305, 336, 75, 388, 3, 562, 190,
+ /* 220 */ 345, 338, 44, 45, 95, 460, 802, 110, 94, 146,
+ /* 230 */ 157, 162, 167, 156, 161, 120, 122, 114, 116, 112,
+ /* 240 */ 118, 575, 124, 126, 128, 130, 132, 134, 136, 138,
+ /* 250 */ 140, 142, 20, 48, 800, 364, 362, 101, 102, 367,
+ /* 260 */ 499, 295, 49, 596, 14, 15, 191, 32, 33, 27,
+ /* 270 */ 148, 403, 96, 50, 147, 534, 46, 145, 494, 466,
+ /* 280 */ 456, 144, 580, 279, 36, 340, 47, 399, 309, 81,
+ /* 290 */ 368, 401, 75, 335, 398, 505, 176, 501, 150, 151,
+ /* 300 */ 197, 110, 94, 146, 157, 162, 167, 156, 161, 120,
+ /* 310 */ 122, 114, 116, 112, 118, 77, 124, 126, 128, 130,
+ /* 320 */ 132, 134, 136, 138, 140, 142, 149, 280, 258, 169,
+ /* 330 */ 96, 39, 281, 13, 298, 367, 96, 175, 22, 335,
+ /* 340 */ 28, 145, 188, 402, 33, 144, 217, 6, 5, 171,
+ /* 350 */ 75, 173, 174, 25, 176, 581, 75, 57, 58, 507,
+ /* 360 */ 235, 351, 356, 357, 265, 110, 94, 146, 157, 162,
+ /* 370 */ 167, 156, 161, 120, 122, 114, 116, 112, 118, 503,
+ /* 380 */ 124, 126, 128, 130, 132, 134, 136, 138, 140, 142,
+ /* 390 */ 457, 77, 243, 294, 48, 227, 236, 293, 297, 14,
+ /* 400 */ 15, 288, 96, 49, 217, 152, 222, 163, 168, 278,
+ /* 410 */ 24, 13, 687, 13, 50, 145, 518, 201, 152, 144,
+ /* 420 */ 163, 168, 75, 358, 582, 171, 176, 173, 174, 263,
+ /* 430 */ 171, 261, 173, 174, 354, 356, 357, 588, 211, 110,
+ /* 440 */ 94, 146, 157, 162, 167, 156, 161, 120, 122, 114,
+ /* 450 */ 116, 112, 118, 654, 124, 126, 128, 130, 132, 134,
+ /* 460 */ 136, 138, 140, 142, 303, 13, 688, 96, 250, 817,
+ /* 470 */ 96, 16, 17, 18, 246, 81, 216, 14, 15, 14,
+ /* 480 */ 15, 145, 13, 406, 435, 144, 13, 75, 487, 387,
+ /* 490 */ 75, 493, 248, 258, 235, 660, 358, 262, 310, 852,
+ /* 500 */ 171, 26, 173, 174, 253, 110, 94, 146, 157, 162,
+ /* 510 */ 167, 156, 161, 120, 122, 114, 116, 112, 118, 397,
+ /* 520 */ 124, 126, 128, 130, 132, 134, 136, 138, 140, 142,
+ /* 530 */ 229, 14, 15, 489, 250, 152, 252, 163, 168, 171,
+ /* 540 */ 839, 173, 174, 360, 361, 96, 145, 533, 14, 15,
+ /* 550 */ 144, 866, 14, 15, 801, 442, 312, 275, 255, 453,
+ /* 560 */ 850, 338, 251, 535, 536, 75, 662, 247, 13, 493,
+ /* 570 */ 110, 94, 146, 157, 162, 167, 156, 161, 120, 122,
+ /* 580 */ 114, 116, 112, 118, 845, 124, 126, 128, 130, 132,
+ /* 590 */ 134, 136, 138, 140, 142, 726, 96, 171, 96, 173,
+ /* 600 */ 174, 171, 252, 173, 174, 152, 583, 163, 168, 42,
+ /* 610 */ 720, 525, 96, 145, 441, 271, 75, 144, 75, 170,
+ /* 620 */ 302, 640, 91, 31, 358, 313, 320, 322, 251, 432,
+ /* 630 */ 434, 433, 75, 844, 14, 15, 176, 110, 94, 146,
+ /* 640 */ 157, 162, 167, 156, 161, 120, 122, 114, 116, 112,
+ /* 650 */ 118, 77, 124, 126, 128, 130, 132, 134, 136, 138,
+ /* 660 */ 140, 142, 171, 96, 173, 174, 331, 52, 171, 96,
+ /* 670 */ 173, 174, 96, 195, 213, 207, 29, 348, 145, 54,
+ /* 680 */ 310, 318, 144, 75, 455, 342, 217, 93, 83, 75,
+ /* 690 */ 30, 452, 75, 109, 587, 286, 111, 171, 265, 173,
+ /* 700 */ 174, 319, 110, 94, 146, 157, 162, 167, 156, 161,
+ /* 710 */ 120, 122, 114, 116, 112, 118, 77, 124, 126, 128,
+ /* 720 */ 130, 132, 134, 136, 138, 140, 142, 244, 96, 187,
+ /* 730 */ 96, 96, 810, 331, 214, 266, 215, 35, 312, 96,
+ /* 740 */ 96, 479, 328, 145, 623, 38, 327, 144, 75, 455,
+ /* 750 */ 75, 75, 113, 689, 115, 117, 315, 461, 426, 75,
+ /* 760 */ 75, 77, 463, 119, 121, 407, 325, 110, 165, 146,
+ /* 770 */ 157, 162, 167, 156, 161, 120, 122, 114, 116, 112,
+ /* 780 */ 118, 77, 124, 126, 128, 130, 132, 134, 136, 138,
+ /* 790 */ 140, 142, 42, 96, 96, 96, 96, 824, 273, 159,
+ /* 800 */ 415, 96, 410, 272, 96, 273, 479, 41, 145, 332,
+ /* 810 */ 537, 43, 144, 75, 75, 75, 75, 123, 125, 127,
+ /* 820 */ 129, 75, 465, 64, 75, 131, 53, 463, 133, 158,
+ /* 830 */ 317, 316, 265, 94, 146, 157, 162, 167, 156, 161,
+ /* 840 */ 120, 122, 114, 116, 112, 118, 219, 124, 126, 128,
+ /* 850 */ 130, 132, 134, 136, 138, 140, 142, 96, 689, 96,
+ /* 860 */ 96, 532, 96, 331, 299, 96, 215, 96, 96, 283,
+ /* 870 */ 96, 261, 219, 96, 145, 96, 840, 75, 144, 75,
+ /* 880 */ 75, 135, 75, 137, 139, 75, 141, 75, 75, 143,
+ /* 890 */ 75, 153, 155, 75, 164, 75, 376, 166, 56, 178,
+ /* 900 */ 146, 157, 162, 167, 156, 161, 120, 122, 114, 116,
+ /* 910 */ 112, 118, 652, 124, 126, 128, 130, 132, 134, 136,
+ /* 920 */ 138, 140, 142, 76, 96, 96, 96, 71, 438, 364,
+ /* 930 */ 362, 437, 96, 96, 96, 96, 331, 262, 233, 332,
+ /* 940 */ 96, 55, 331, 439, 75, 75, 75, 331, 180, 182,
+ /* 950 */ 184, 199, 75, 75, 75, 75, 196, 198, 208, 210,
+ /* 960 */ 75, 107, 106, 108, 212, 720, 326, 177, 327, 382,
+ /* 970 */ 430, 431, 107, 106, 108, 391, 548, 61, 96, 96,
+ /* 980 */ 449, 471, 458, 45, 183, 181, 300, 96, 476, 352,
+ /* 990 */ 96, 353, 179, 73, 74, 343, 346, 95, 75, 75,
+ /* 1000 */ 290, 96, 224, 240, 345, 275, 42, 75, 95, 76,
+ /* 1010 */ 75, 245, 332, 71, 277, 383, 275, 327, 332, 96,
+ /* 1020 */ 75, 75, 404, 332, 287, 386, 96, 392, 421, 327,
+ /* 1030 */ 101, 102, 103, 104, 105, 185, 189, 199, 96, 75,
+ /* 1040 */ 96, 101, 102, 427, 414, 60, 75, 107, 106, 108,
+ /* 1050 */ 474, 470, 486, 177, 77, 450, 421, 327, 75, 484,
+ /* 1060 */ 75, 273, 478, 436, 491, 492, 423, 490, 421, 421,
+ /* 1070 */ 183, 181, 421, 421, 483, 421, 77, 421, 179, 73,
+ /* 1080 */ 74, 476, 244, 95, 77, 81, 526, 860, 490, 421,
+ /* 1090 */ 689, 522, 62, 64, 500, 70, 597, 63, 523, 68,
+ /* 1100 */ 598, 76, 81, 79, 81, 71, 502, 504, 84, 80,
+ /* 1110 */ 506, 510, 244, 514, 239, 520, 101, 102, 103, 104,
+ /* 1120 */ 105, 185, 189, 77, 546, 241, 82, 558, 86, 199,
+ /* 1130 */ 85, 225, 90, 87, 97, 88, 99, 142, 89, 107,
+ /* 1140 */ 106, 108, 160, 98, 516, 177, 100, 218, 666, 667,
+ /* 1150 */ 668, 186, 209, 193, 192, 194, 200, 204, 203, 202,
+ /* 1160 */ 206, 205, 183, 181, 219, 220, 221, 226, 228, 232,
+ /* 1170 */ 179, 73, 74, 230, 233, 95, 234, 231, 237, 242,
+ /* 1180 */ 238, 215, 260, 249, 257, 276, 267, 254, 256, 259,
+ /* 1190 */ 264, 269, 270, 76, 274, 282, 301, 71, 219, 268,
+ /* 1200 */ 285, 291, 284, 306, 324, 307, 311, 308, 101, 102,
+ /* 1210 */ 103, 104, 105, 185, 189, 803, 355, 329, 375, 304,
+ /* 1220 */ 314, 199, 321, 337, 330, 365, 334, 372, 309, 333,
+ /* 1230 */ 323, 107, 106, 108, 344, 339, 347, 177, 374, 378,
+ /* 1240 */ 400, 359, 370, 377, 381, 379, 384, 389, 363, 390,
+ /* 1250 */ 393, 394, 396, 54, 183, 181, 289, 408, 395, 409,
+ /* 1260 */ 411, 413, 179, 73, 74, 412, 416, 95, 417, 420,
+ /* 1270 */ 428, 422, 832, 429, 443, 440, 444, 837, 838, 76,
+ /* 1280 */ 446, 445, 448, 71, 451, 808, 809, 459, 454, 447,
+ /* 1290 */ 418, 727, 728, 831, 464, 462, 846, 457, 469, 419,
+ /* 1300 */ 101, 102, 103, 104, 105, 185, 189, 199, 467, 468,
+ /* 1310 */ 472, 473, 475, 424, 848, 477, 480, 107, 106, 108,
+ /* 1320 */ 425, 482, 488, 177, 485, 849, 481, 495, 496, 851,
+ /* 1330 */ 659, 661, 816, 858, 497, 509, 511, 719, 513, 515,
+ /* 1340 */ 183, 181, 722, 517, 725, 519, 521, 524, 179, 73,
+ /* 1350 */ 74, 818, 528, 95, 530, 819, 820, 531, 538, 821,
+ /* 1360 */ 8, 822, 539, 823, 549, 19, 21, 23, 405, 541,
+ /* 1370 */ 542, 544, 543, 859, 547, 861, 862, 865, 545, 540,
+ /* 1380 */ 551, 867, 557, 555, 552, 550, 101, 102, 103, 104,
+ /* 1390 */ 105, 185, 189, 554, 560, 559, 561, 868, 529, 545,
+ /* 1400 */ 460, 545, 545, 545, 545, 527, 545, 553, 545, 545,
+ /* 1410 */ 545, 545, 556, 545, 545, 545, 545, 545, 545, 545,
+ /* 1420 */ 545, 545, 545, 545, 545, 545, 545, 545, 545, 545,
+ /* 1430 */ 545, 545, 545, 545, 545, 545, 545, 545, 545, 545,
+ /* 1440 */ 545, 545, 545, 545, 545, 545, 545, 545, 545, 545,
+ /* 1450 */ 545, 545, 545, 508, 512, 456, 545, 545, 545, 498,
+ /* 1460 */ 545, 545, 545, 545, 81,
};
static const YYCODETYPE yy_lookahead[] = {
- /* 0 */ 24, 139, 26, 72, 73, 74, 75, 76, 77, 78,
- /* 10 */ 79, 80, 81, 154, 155, 156, 40, 26, 135, 136,
- /* 20 */ 44, 0, 158, 140, 131, 132, 133, 134, 164, 146,
- /* 30 */ 9, 10, 170, 60, 58, 59, 60, 61, 62, 63,
+ /* 0 */ 24, 26, 26, 78, 79, 80, 81, 82, 83, 84,
+ /* 10 */ 85, 86, 87, 88, 22, 9, 40, 23, 26, 25,
+ /* 20 */ 44, 74, 75, 76, 77, 9, 79, 80, 81, 82,
+ /* 30 */ 83, 84, 85, 86, 87, 88, 85, 86, 87, 88,
/* 40 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
- /* 50 */ 74, 75, 76, 77, 78, 79, 80, 81, 22, 176,
- /* 60 */ 24, 85, 89, 90, 91, 92, 93, 94, 23, 23,
- /* 70 */ 25, 25, 213, 100, 212, 40, 85, 86, 87, 44,
- /* 80 */ 9, 90, 91, 92, 201, 76, 77, 78, 79, 80,
- /* 90 */ 81, 26, 101, 58, 59, 60, 61, 62, 63, 64,
- /* 100 */ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
- /* 110 */ 75, 76, 77, 78, 79, 80, 81, 68, 69, 70,
- /* 120 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
- /* 130 */ 81, 23, 87, 25, 29, 90, 91, 92, 179, 26,
- /* 140 */ 35, 76, 77, 23, 40, 186, 101, 139, 44, 22,
- /* 150 */ 85, 86, 144, 26, 9, 147, 148, 12, 159, 146,
- /* 160 */ 95, 126, 58, 59, 60, 61, 62, 63, 64, 65,
- /* 170 */ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
- /* 180 */ 76, 77, 78, 79, 80, 81, 17, 139, 18, 176,
- /* 190 */ 23, 17, 25, 139, 86, 147, 148, 27, 85, 86,
- /* 200 */ 146, 188, 189, 204, 205, 206, 193, 45, 38, 137,
- /* 210 */ 26, 41, 85, 86, 40, 161, 168, 169, 44, 111,
- /* 220 */ 51, 51, 60, 103, 111, 105, 106, 13, 14, 15,
- /* 230 */ 176, 127, 58, 59, 60, 61, 62, 63, 64, 65,
- /* 240 */ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
- /* 250 */ 76, 77, 78, 79, 80, 81, 9, 95, 58, 40,
- /* 260 */ 76, 77, 100, 44, 22, 96, 97, 98, 26, 85,
- /* 270 */ 104, 26, 45, 89, 108, 60, 107, 58, 59, 60,
- /* 280 */ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
- /* 290 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
- /* 300 */ 81, 9, 87, 88, 89, 90, 91, 92, 93, 94,
- /* 310 */ 157, 158, 23, 9, 139, 100, 139, 164, 26, 119,
- /* 320 */ 87, 23, 95, 90, 91, 92, 21, 85, 86, 40,
- /* 330 */ 85, 86, 104, 44, 101, 107, 161, 152, 161, 17,
- /* 340 */ 154, 155, 156, 154, 155, 156, 127, 58, 59, 60,
- /* 350 */ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
- /* 360 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
- /* 370 */ 81, 23, 187, 139, 199, 89, 199, 85, 86, 78,
- /* 380 */ 79, 80, 81, 139, 26, 210, 100, 210, 40, 204,
- /* 390 */ 205, 206, 44, 164, 165, 161, 91, 23, 22, 213,
- /* 400 */ 171, 103, 213, 105, 106, 161, 58, 59, 60, 61,
- /* 410 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
- /* 420 */ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
- /* 430 */ 196, 197, 9, 40, 129, 26, 78, 44, 9, 9,
- /* 440 */ 10, 197, 9, 85, 86, 204, 205, 206, 126, 11,
- /* 450 */ 128, 58, 59, 60, 61, 62, 63, 64, 65, 66,
- /* 460 */ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
- /* 470 */ 77, 78, 79, 80, 81, 133, 134, 103, 40, 105,
- /* 480 */ 106, 9, 44, 173, 174, 109, 149, 9, 95, 152,
- /* 490 */ 153, 96, 97, 98, 85, 86, 58, 59, 60, 61,
- /* 500 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
- /* 510 */ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
- /* 520 */ 111, 152, 9, 40, 155, 156, 103, 44, 105, 106,
- /* 530 */ 13, 14, 103, 139, 105, 106, 103, 47, 105, 106,
- /* 540 */ 139, 58, 59, 60, 61, 62, 63, 64, 65, 66,
- /* 550 */ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
- /* 560 */ 77, 78, 79, 80, 81, 154, 155, 156, 40, 154,
- /* 570 */ 155, 156, 44, 76, 77, 103, 175, 105, 106, 25,
- /* 580 */ 138, 103, 213, 105, 106, 95, 58, 59, 60, 61,
- /* 590 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
- /* 600 */ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
- /* 610 */ 9, 22, 24, 40, 26, 26, 103, 44, 105, 106,
- /* 620 */ 121, 122, 20, 22, 213, 96, 97, 98, 213, 9,
- /* 630 */ 139, 60, 59, 60, 61, 62, 63, 64, 65, 66,
+ /* 50 */ 74, 75, 76, 77, 148, 79, 80, 81, 82, 83,
+ /* 60 */ 84, 85, 86, 87, 88, 9, 25, 92, 92, 79,
+ /* 70 */ 80, 81, 82, 83, 84, 85, 86, 87, 88, 26,
+ /* 80 */ 150, 40, 26, 144, 92, 44, 147, 157, 94, 48,
+ /* 90 */ 149, 97, 98, 99, 83, 84, 85, 86, 87, 88,
+ /* 100 */ 170, 9, 10, 109, 174, 64, 65, 66, 67, 68,
+ /* 110 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 189,
+ /* 120 */ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
+ /* 130 */ 40, 29, 9, 26, 44, 12, 94, 35, 85, 97,
+ /* 140 */ 98, 99, 142, 143, 144, 92, 93, 147, 92, 93,
+ /* 150 */ 112, 109, 66, 115, 64, 65, 66, 67, 68, 69,
+ /* 160 */ 70, 71, 72, 73, 74, 75, 76, 77, 22, 79,
+ /* 170 */ 80, 81, 82, 83, 84, 85, 86, 87, 88, 66,
+ /* 180 */ 94, 95, 96, 97, 98, 99, 100, 101, 60, 61,
+ /* 190 */ 62, 17, 9, 160, 108, 150, 163, 164, 26, 92,
+ /* 200 */ 93, 94, 150, 40, 97, 98, 99, 44, 0, 96,
+ /* 210 */ 97, 98, 99, 100, 101, 170, 109, 9, 10, 174,
+ /* 220 */ 92, 108, 186, 187, 96, 51, 136, 64, 65, 66,
+ /* 230 */ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ /* 240 */ 77, 9, 79, 80, 81, 82, 83, 84, 85, 86,
+ /* 250 */ 87, 88, 149, 18, 17, 83, 84, 129, 130, 150,
+ /* 260 */ 20, 23, 27, 117, 92, 93, 221, 158, 159, 22,
+ /* 270 */ 40, 24, 150, 38, 44, 103, 41, 40, 104, 105,
+ /* 280 */ 106, 44, 9, 157, 168, 169, 51, 177, 178, 115,
+ /* 290 */ 181, 182, 170, 177, 184, 55, 174, 57, 68, 69,
+ /* 300 */ 137, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+ /* 310 */ 73, 74, 75, 76, 77, 189, 79, 80, 81, 82,
+ /* 320 */ 83, 84, 85, 86, 87, 88, 96, 201, 202, 22,
+ /* 330 */ 150, 169, 206, 26, 212, 150, 150, 23, 149, 177,
+ /* 340 */ 155, 40, 23, 158, 159, 44, 224, 145, 146, 111,
+ /* 350 */ 170, 113, 114, 151, 174, 9, 170, 13, 14, 157,
+ /* 360 */ 174, 165, 166, 167, 163, 64, 65, 66, 67, 68,
+ /* 370 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 139,
+ /* 380 */ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
+ /* 390 */ 64, 189, 212, 112, 18, 209, 210, 116, 23, 92,
+ /* 400 */ 93, 200, 150, 27, 224, 217, 218, 219, 220, 22,
+ /* 410 */ 149, 26, 23, 26, 38, 40, 214, 41, 217, 44,
+ /* 420 */ 219, 220, 170, 227, 9, 111, 174, 113, 114, 24,
+ /* 430 */ 111, 26, 113, 114, 165, 166, 167, 9, 137, 64,
+ /* 440 */ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+ /* 450 */ 75, 76, 77, 127, 79, 80, 81, 82, 83, 84,
+ /* 460 */ 85, 86, 87, 88, 23, 26, 23, 150, 25, 9,
+ /* 470 */ 150, 13, 14, 15, 25, 115, 224, 92, 93, 92,
+ /* 480 */ 93, 40, 26, 153, 47, 44, 26, 170, 128, 171,
+ /* 490 */ 170, 174, 201, 202, 174, 9, 227, 92, 45, 9,
+ /* 500 */ 111, 152, 113, 114, 119, 64, 65, 66, 67, 68,
+ /* 510 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 66,
+ /* 520 */ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
+ /* 530 */ 210, 92, 93, 216, 25, 217, 93, 219, 220, 111,
+ /* 540 */ 103, 113, 114, 129, 130, 150, 40, 150, 92, 93,
+ /* 550 */ 44, 9, 92, 93, 17, 225, 103, 150, 119, 229,
+ /* 560 */ 9, 108, 119, 166, 167, 170, 9, 118, 26, 174,
+ /* 570 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ /* 580 */ 74, 75, 76, 77, 11, 79, 80, 81, 82, 83,
+ /* 590 */ 84, 85, 86, 87, 88, 9, 150, 111, 150, 113,
+ /* 600 */ 114, 111, 93, 113, 114, 217, 9, 219, 220, 103,
+ /* 610 */ 9, 216, 150, 40, 21, 208, 170, 44, 170, 157,
+ /* 620 */ 174, 23, 174, 25, 227, 104, 105, 106, 119, 104,
+ /* 630 */ 105, 106, 170, 11, 92, 93, 174, 64, 65, 66,
/* 640 */ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
- /* 650 */ 77, 78, 79, 80, 81, 26, 141, 55, 40, 57,
- /* 660 */ 89, 170, 44, 138, 110, 188, 189, 23, 67, 25,
- /* 670 */ 152, 9, 22, 85, 85, 139, 26, 25, 60, 61,
- /* 680 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
- /* 690 */ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
- /* 700 */ 50, 26, 22, 212, 9, 187, 26, 25, 139, 18,
- /* 710 */ 60, 175, 20, 146, 85, 139, 152, 138, 27, 40,
- /* 720 */ 146, 26, 139, 44, 155, 156, 76, 77, 78, 38,
- /* 730 */ 50, 129, 41, 32, 84, 85, 86, 142, 86, 89,
- /* 740 */ 60, 62, 63, 176, 161, 139, 170, 55, 139, 57,
- /* 750 */ 176, 187, 123, 52, 146, 146, 76, 77, 22, 146,
- /* 760 */ 85, 9, 26, 111, 84, 85, 86, 161, 89, 89,
- /* 770 */ 161, 121, 122, 123, 124, 125, 139, 95, 9, 22,
- /* 780 */ 85, 86, 213, 26, 176, 176, 50, 107, 212, 176,
- /* 790 */ 207, 11, 25, 146, 25, 23, 60, 25, 161, 139,
- /* 800 */ 99, 121, 122, 123, 124, 125, 211, 50, 199, 201,
- /* 810 */ 215, 28, 76, 77, 31, 48, 210, 60, 107, 210,
- /* 820 */ 84, 85, 86, 176, 216, 89, 43, 139, 139, 221,
- /* 830 */ 170, 120, 139, 76, 77, 78, 139, 88, 89, 139,
- /* 840 */ 203, 84, 85, 86, 139, 11, 89, 95, 201, 161,
- /* 850 */ 16, 17, 18, 19, 161, 139, 139, 121, 122, 123,
- /* 860 */ 124, 125, 126, 216, 30, 9, 161, 170, 221, 138,
- /* 870 */ 36, 139, 212, 139, 139, 175, 139, 161, 121, 122,
- /* 880 */ 123, 124, 125, 49, 22, 51, 139, 118, 26, 139,
- /* 890 */ 56, 203, 139, 161, 139, 161, 161, 139, 161, 53,
- /* 900 */ 54, 212, 139, 139, 139, 139, 126, 139, 161, 212,
- /* 910 */ 24, 161, 50, 139, 161, 139, 161, 200, 139, 161,
- /* 920 */ 139, 139, 60, 139, 161, 161, 161, 161, 139, 161,
- /* 930 */ 96, 97, 98, 139, 139, 161, 102, 161, 76, 77,
- /* 940 */ 161, 107, 161, 161, 139, 161, 84, 85, 86, 139,
- /* 950 */ 161, 89, 139, 139, 139, 161, 161, 139, 9, 139,
- /* 960 */ 139, 23, 23, 25, 25, 139, 161, 139, 23, 139,
- /* 970 */ 25, 161, 139, 9, 161, 161, 161, 139, 23, 161,
- /* 980 */ 25, 161, 95, 121, 122, 123, 124, 125, 23, 161,
- /* 990 */ 25, 161, 139, 139, 161, 109, 109, 139, 23, 161,
- /* 1000 */ 25, 146, 173, 174, 23, 23, 25, 25, 139, 107,
- /* 1010 */ 139, 139, 139, 139, 161, 161, 195, 139, 139, 139,
- /* 1020 */ 9, 195, 120, 23, 9, 25, 145, 23, 9, 139,
- /* 1030 */ 161, 176, 150, 42, 159, 95, 33, 167, 46, 22,
- /* 1040 */ 109, 109, 159, 177, 160, 178, 175, 175, 175, 175,
- /* 1050 */ 159, 159, 176, 195, 175, 175, 113, 46, 107, 118,
- /* 1060 */ 116, 115, 185, 214, 117, 180, 214, 118, 114, 181,
- /* 1070 */ 25, 182, 94, 160, 26, 151, 183, 109, 200, 184,
- /* 1080 */ 109, 139, 81, 89, 107, 126, 107, 139, 17, 139,
- /* 1090 */ 107, 22, 198, 174, 109, 23, 139, 23, 25, 143,
- /* 1100 */ 139, 198, 114, 25, 208, 190, 209, 111, 139, 139,
- /* 1110 */ 143, 139, 160, 139, 191, 95, 22, 112, 192, 139,
- /* 1120 */ 23, 191, 109, 23, 22, 192, 139, 165, 162, 139,
- /* 1130 */ 167, 23, 159, 198, 198, 46, 22, 22, 46, 163,
- /* 1140 */ 22, 100, 93, 24, 217, 139, 151, 139, 95, 39,
- /* 1150 */ 166, 152, 166, 160, 220, 166, 219, 160, 11, 143,
- /* 1160 */ 139, 139, 139, 37, 47, 95, 159, 169, 159, 143,
- /* 1170 */ 143, 169, 162, 143, 95, 163, 218, 139, 143, 129,
- /* 1180 */ 95, 22, 9, 159, 129, 11, 172, 119, 17, 9,
- /* 1190 */ 9, 58, 17, 139, 119, 99, 139, 172, 67, 181,
- /* 1200 */ 9, 67, 119, 139, 22, 22, 9, 9, 110, 9,
- /* 1210 */ 181, 9, 9, 9, 110, 139, 9, 181, 172, 99,
- /* 1220 */ 181, 9, 119, 22, 9, 139, 9, 139, 9, 9,
- /* 1230 */ 202, 9, 9, 202, 143, 9, 23, 9, 139, 34,
- /* 1240 */ 24, 9, 152, 9, 139, 152, 139, 9, 224, 224,
- /* 1250 */ 224, 224, 224, 224, 222, 224, 223, 224, 224, 222,
+ /* 650 */ 77, 189, 79, 80, 81, 82, 83, 84, 85, 86,
+ /* 660 */ 87, 88, 111, 150, 113, 114, 150, 96, 111, 150,
+ /* 670 */ 113, 114, 150, 136, 212, 138, 156, 162, 40, 108,
+ /* 680 */ 45, 32, 44, 170, 157, 170, 224, 174, 192, 170,
+ /* 690 */ 23, 98, 170, 174, 9, 199, 174, 111, 163, 113,
+ /* 700 */ 114, 52, 64, 65, 66, 67, 68, 69, 70, 71,
+ /* 710 */ 72, 73, 74, 75, 76, 77, 189, 79, 80, 81,
+ /* 720 */ 82, 83, 84, 85, 86, 87, 88, 126, 150, 157,
+ /* 730 */ 150, 150, 139, 150, 23, 200, 25, 161, 103, 150,
+ /* 740 */ 150, 214, 226, 40, 23, 150, 25, 44, 170, 157,
+ /* 750 */ 170, 170, 174, 24, 174, 174, 107, 230, 136, 170,
+ /* 760 */ 170, 189, 235, 174, 174, 20, 183, 64, 65, 66,
+ /* 770 */ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ /* 780 */ 77, 189, 79, 80, 81, 82, 83, 84, 85, 86,
+ /* 790 */ 87, 88, 103, 150, 150, 150, 150, 9, 25, 66,
+ /* 800 */ 55, 150, 57, 23, 150, 25, 214, 171, 40, 226,
+ /* 810 */ 22, 33, 44, 170, 170, 170, 170, 174, 174, 174,
+ /* 820 */ 174, 170, 230, 102, 170, 174, 171, 235, 174, 96,
+ /* 830 */ 95, 96, 163, 65, 66, 67, 68, 69, 70, 71,
+ /* 840 */ 72, 73, 74, 75, 76, 77, 117, 79, 80, 81,
+ /* 850 */ 82, 83, 84, 85, 86, 87, 88, 150, 103, 150,
+ /* 860 */ 150, 73, 150, 150, 23, 150, 25, 150, 150, 200,
+ /* 870 */ 150, 26, 117, 150, 40, 150, 103, 170, 44, 170,
+ /* 880 */ 170, 174, 170, 174, 174, 170, 174, 170, 170, 174,
+ /* 890 */ 170, 174, 174, 170, 174, 170, 183, 174, 42, 174,
+ /* 900 */ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
+ /* 910 */ 76, 77, 9, 79, 80, 81, 82, 83, 84, 85,
+ /* 920 */ 86, 87, 88, 22, 150, 150, 150, 26, 28, 83,
+ /* 930 */ 84, 31, 150, 150, 150, 150, 150, 92, 26, 226,
+ /* 940 */ 150, 180, 150, 43, 170, 170, 170, 150, 174, 174,
+ /* 950 */ 174, 50, 170, 170, 170, 170, 174, 174, 174, 174,
+ /* 960 */ 170, 60, 61, 62, 174, 9, 23, 66, 25, 183,
+ /* 970 */ 53, 54, 60, 61, 62, 183, 131, 172, 150, 150,
+ /* 980 */ 183, 25, 186, 187, 83, 84, 85, 150, 150, 23,
+ /* 990 */ 150, 25, 91, 92, 93, 83, 84, 96, 170, 170,
+ /* 1000 */ 150, 150, 174, 174, 92, 150, 103, 170, 96, 22,
+ /* 1010 */ 170, 174, 226, 26, 174, 23, 150, 25, 226, 150,
+ /* 1020 */ 170, 170, 157, 226, 174, 174, 150, 23, 150, 25,
+ /* 1030 */ 129, 130, 131, 132, 133, 134, 135, 50, 150, 170,
+ /* 1040 */ 150, 129, 130, 174, 157, 46, 170, 60, 61, 62,
+ /* 1050 */ 174, 213, 157, 66, 189, 23, 150, 25, 170, 23,
+ /* 1060 */ 170, 25, 174, 208, 174, 23, 188, 25, 150, 150,
+ /* 1070 */ 83, 84, 150, 150, 208, 150, 189, 150, 91, 92,
+ /* 1080 */ 93, 150, 126, 96, 189, 115, 23, 9, 25, 150,
+ /* 1090 */ 9, 157, 171, 102, 188, 22, 117, 173, 128, 171,
+ /* 1100 */ 117, 22, 115, 190, 115, 26, 188, 188, 193, 189,
+ /* 1110 */ 188, 188, 126, 188, 124, 188, 129, 130, 131, 132,
+ /* 1120 */ 133, 134, 135, 189, 46, 123, 191, 188, 195, 50,
+ /* 1130 */ 194, 121, 125, 196, 117, 197, 117, 88, 198, 60,
+ /* 1140 */ 61, 62, 96, 150, 213, 66, 150, 150, 115, 115,
+ /* 1150 */ 115, 22, 136, 223, 222, 17, 22, 25, 187, 23,
+ /* 1160 */ 23, 150, 83, 84, 117, 150, 154, 122, 25, 101,
+ /* 1170 */ 91, 92, 93, 211, 26, 96, 162, 172, 211, 122,
+ /* 1180 */ 172, 25, 154, 203, 119, 103, 204, 150, 150, 150,
+ /* 1190 */ 150, 120, 22, 22, 150, 23, 23, 26, 117, 205,
+ /* 1200 */ 205, 117, 204, 150, 22, 175, 150, 176, 129, 130,
+ /* 1210 */ 131, 132, 133, 134, 135, 136, 23, 211, 22, 171,
+ /* 1220 */ 179, 50, 179, 162, 172, 163, 172, 150, 178, 211,
+ /* 1230 */ 179, 60, 61, 62, 170, 180, 170, 66, 46, 23,
+ /* 1240 */ 182, 228, 182, 173, 22, 171, 171, 46, 228, 22,
+ /* 1250 */ 100, 150, 176, 108, 83, 84, 85, 150, 175, 154,
+ /* 1260 */ 150, 24, 91, 92, 93, 154, 150, 96, 154, 103,
+ /* 1270 */ 39, 154, 11, 37, 139, 47, 150, 103, 103, 22,
+ /* 1280 */ 103, 154, 22, 26, 171, 9, 139, 185, 11, 150,
+ /* 1290 */ 231, 127, 127, 9, 9, 17, 17, 64, 107, 232,
+ /* 1300 */ 129, 130, 131, 132, 133, 134, 135, 50, 185, 150,
+ /* 1310 */ 150, 73, 194, 233, 9, 73, 127, 60, 61, 62,
+ /* 1320 */ 234, 22, 22, 66, 215, 9, 150, 118, 150, 9,
+ /* 1330 */ 9, 9, 9, 9, 194, 118, 194, 9, 185, 107,
+ /* 1340 */ 83, 84, 9, 194, 9, 127, 215, 22, 91, 92,
+ /* 1350 */ 93, 9, 150, 96, 150, 9, 9, 154, 150, 9,
+ /* 1360 */ 11, 9, 23, 9, 34, 16, 17, 18, 19, 236,
+ /* 1370 */ 163, 150, 24, 9, 163, 9, 9, 9, 237, 30,
+ /* 1380 */ 236, 9, 20, 154, 150, 36, 129, 130, 131, 132,
+ /* 1390 */ 133, 134, 135, 150, 140, 59, 150, 9, 49, 238,
+ /* 1400 */ 51, 238, 238, 238, 238, 56, 238, 58, 238, 238,
+ /* 1410 */ 238, 238, 63, 238, 238, 238, 238, 238, 238, 238,
+ /* 1420 */ 238, 238, 238, 238, 238, 238, 238, 238, 238, 238,
+ /* 1430 */ 238, 238, 238, 238, 238, 238, 238, 238, 238, 238,
+ /* 1440 */ 238, 238, 238, 238, 238, 238, 238, 238, 238, 238,
+ /* 1450 */ 238, 238, 238, 104, 105, 106, 238, 238, 238, 110,
+ /* 1460 */ 238, 238, 238, 238, 115,
};
-#define YY_SHIFT_USE_DFLT (-70)
+#define YY_SHIFT_USE_DFLT (-76)
static const short yy_shift_ofst[] = {
- /* 0 */ 430, 21, -70, 834, 71, -70, 247, 214, 145, 304,
- /* 10 */ 292, 620, -70, -70, -70, -70, -70, -70, 145, 662,
- /* 20 */ 145, 856, 145, 964, 36, 1015, 245, 46, 1004, 1019,
- /* 30 */ -9, -70, 675, -70, 215, -70, 245, -27, -70, 940,
- /* 40 */ -70, 1003, 170, -70, -70, -70, -70, -70, -70, -70,
- /* 50 */ 286, 940, -70, 991, -70, 517, -70, -70, 992, 105,
- /* 60 */ 940, -70, -70, -70, 940, -70, 1017, 862, 376, 650,
- /* 70 */ 931, 932, 680, -70, 120, 951, -70, 166, -70, 554,
- /* 80 */ 941, 946, 944, 943, 947, -70, 497, -70, -70, 767,
- /* 90 */ 497, -70, 499, -70, -70, -70, 499, -70, -70, 497,
- /* 100 */ -70, 954, 862, 1045, 862, 978, 105, -70, 1048, -70,
- /* 110 */ -70, 483, 862, -70, 968, 245, 971, 245, -70, -70,
- /* 120 */ -70, -70, -70, 618, 862, 573, 862, -69, 862, -69,
- /* 130 */ 862, -69, 862, -69, 862, 49, 862, 49, 862, 9,
- /* 140 */ 862, 9, 862, 9, 862, 9, 862, 301, 862, 301,
- /* 150 */ 862, 1001, 862, 1001, 862, 1001, 862, -70, -70, -70,
- /* 160 */ 679, -70, -70, -70, -70, -70, 862, 49, -70, 571,
- /* 170 */ -70, 994, -70, -70, -70, 862, 528, 862, 49, -70,
- /* 180 */ 127, 680, 298, 228, 977, 979, 983, -70, 483, 862,
- /* 190 */ 618, 862, -70, 862, -70, 862, -70, 736, 35, 959,
- /* 200 */ 322, 1071, -70, 862, 104, 862, 483, 1069, 691, 1072,
- /* 210 */ -70, 1073, 245, 1074, -70, 862, 174, 862, 219, 862,
- /* 220 */ 483, 167, -70, 862, -70, -70, 985, 245, -70, -70,
- /* 230 */ 978, 105, -70, 862, 483, 988, 862, 1078, 862, 483,
- /* 240 */ -70, -70, 652, -70, -70, -70, 113, -70, 409, -70,
- /* 250 */ 996, -70, 242, 985, 588, -70, -70, 245, -70, -70,
- /* 260 */ 1020, 1005, -70, 1094, 245, 644, -70, 245, -70, -70,
- /* 270 */ 862, 483, 951, 374, 108, 1097, 588, 1020, 1005, -70,
- /* 280 */ 757, -24, -70, -70, 1013, 358, -70, -70, -70, -70,
- /* 290 */ 289, -70, 772, -70, 1100, -70, 348, 940, -70, 245,
- /* 300 */ 1102, -70, 227, -70, 245, -70, 529, 701, -70, 749,
- /* 310 */ -70, -70, -70, -70, 701, -70, 701, -70, 245, 938,
- /* 320 */ -70, 245, 978, 105, -70, -70, 978, 105, -70, -70,
- /* 330 */ 1048, -70, 991, -70, -70, 184, -70, -70, -70, -70,
- /* 340 */ 589, 497, 939, -70, 497, 1108, -70, -70, -70, -70,
- /* 350 */ 45, 233, -70, 245, -70, 1089, 1114, 245, 945, 940,
- /* 360 */ -70, 1115, 245, 955, 940, -70, 862, 393, -70, 1092,
- /* 370 */ 1118, 245, 965, 1049, 245, 1102, -70, 162, 1041, -70,
- /* 380 */ -70, -70, -70, -70, 951, 423, 305, 692, 245, 985,
- /* 390 */ -70, 245, 886, 1119, 951, 429, 245, 985, 783, 395,
- /* 400 */ 1053, 245, 985, -70, 1110, 780, 1147, 862, 438, 1126,
- /* 410 */ 846, -70, -70, 1070, 1079, 490, 245, 682, -70, -70,
- /* 420 */ 1117, -70, -70, 1050, 245, 887, 1085, 245, 1159, 245,
- /* 430 */ 975, 752, 1173, 1055, 1174, 169, 433, 200, 170, -70,
- /* 440 */ 1068, 1075, 1171, 1180, 1181, 169, 1175, 1133, 245, 1096,
- /* 450 */ 245, 769, 245, 1131, 862, 483, 1191, 1134, 862, 483,
- /* 460 */ 1083, 245, 1182, 245, 981, -70, 711, 472, 1183, 862,
- /* 470 */ 982, 862, 483, 1197, 483, 1098, 245, 949, 1198, 602,
- /* 480 */ 245, 1200, 245, 1202, 245, 1203, 245, 1204, 478, 1104,
- /* 490 */ 245, 949, 1207, 1133, 245, 1120, 245, 769, 1212, 1103,
- /* 500 */ 245, 1182, 902, 513, 1201, 862, 1000, 1215, 695, 1217,
- /* 510 */ 245, 985, 601, 65, 1219, 1220, 1222, 1223, 245, 1213,
- /* 520 */ 1226, 1205, 675, 1216, 245, 1011, 1228, 629, 1232, 1234,
- /* 530 */ -70, 1205, 245, 1238, -70, -70, -70,
+ /* 0 */ 92, 208, -76, -76, 1349, 6, 16, -76, 458, 123,
+ /* 10 */ 183, 56, 232, -76, -76, -76, -76, -76, -76, 123,
+ /* 20 */ 273, 123, 346, 123, 415, 247, 597, 456, 598, 667,
+ /* 30 */ 685, 107, -76, -25, -76, 86, -76, 456, 113, -76,
+ /* 40 */ 689, -76, 778, 235, -76, -76, -76, -76, -76, -76,
+ /* 50 */ -76, 571, 689, -76, 856, -76, 344, -76, -76, 999,
+ /* 60 */ 102, 689, 991, -76, -76, -76, -76, 689, -76, 1073,
+ /* 70 */ 1257, 146, 901, 979, 983, -76, 987, -76, 238, 989,
+ /* 80 */ -76, 281, -76, 449, 986, 1002, 990, 1010, 1007, -76,
+ /* 90 */ 1257, 41, 1257, 638, 1257, -76, 1017, 456, 1019, 456,
+ /* 100 */ -76, -76, -76, -76, -76, -76, -76, -76, -76, 834,
+ /* 110 */ 1257, 768, 1257, -10, 1257, -10, 1257, -10, 1257, -10,
+ /* 120 */ 1257, -53, 1257, -53, 1257, 11, 1257, 11, 1257, 11,
+ /* 130 */ 1257, 11, 1257, -49, 1257, -49, 1257, 1049, 1257, 1049,
+ /* 140 */ 1257, 1049, 1257, -76, -76, -76, 230, -76, -76, -76,
+ /* 150 */ -76, -76, 1257, -75, 1257, -10, -76, 733, -76, 1046,
+ /* 160 */ -76, -76, -76, 1257, 703, 1257, -53, -76, 307, 987,
+ /* 170 */ 314, 38, 1033, 1034, 1035, -76, 638, 1257, 834, 1257,
+ /* 180 */ -76, 1257, -76, 1257, -76, 1129, 989, 319, -76, 1079,
+ /* 190 */ 90, 1016, 537, 1138, -76, 1257, 163, 1257, 638, 1134,
+ /* 200 */ 376, 1136, -76, 1132, 456, 1137, -76, 1257, 237, 1257,
+ /* 210 */ 301, 1257, 638, 711, -76, 1257, -76, -76, 1047, 456,
+ /* 220 */ -76, -76, -76, 1257, 638, 1045, 1257, 1143, 1257, 1068,
+ /* 230 */ 102, -76, 1148, -76, -76, 638, 1068, 102, -76, 1257,
+ /* 240 */ 638, 1057, 1257, 1156, 1257, 638, -76, -76, 509, -76,
+ /* 250 */ -76, -76, 385, -76, 439, -76, 1065, -76, 387, 1047,
+ /* 260 */ 405, -76, -76, 456, -76, -76, 1082, 1071, -76, 1170,
+ /* 270 */ 456, 780, -76, 456, -76, -76, 1257, 638, 989, 389,
+ /* 280 */ 443, 1172, 405, 1082, 1071, -76, 1171, -24, -76, -76,
+ /* 290 */ 1084, 53, -76, -76, -76, -76, 375, -76, 841, -76,
+ /* 300 */ 1173, -76, 441, 689, -76, 456, 1182, -76, 635, -76,
+ /* 310 */ 456, -76, 521, 649, -76, 735, -76, -76, -76, -76,
+ /* 320 */ 649, -76, 649, -76, 456, 943, -76, 456, 1068, 102,
+ /* 330 */ -76, -76, 1068, 102, -76, -76, 1148, -76, 856, -76,
+ /* 340 */ -76, 912, -76, 128, -76, -76, 128, -76, -76, -8,
+ /* 350 */ 846, 966, -76, 846, 1193, -76, -76, -76, 414, -76,
+ /* 360 */ -76, -76, 414, -76, -76, -76, -76, -76, -6, 42,
+ /* 370 */ -76, 456, -76, 1192, 1196, 456, 721, 1216, 689, -76,
+ /* 380 */ 1222, 456, 992, 689, -76, 1257, 506, -76, 1201, 1227,
+ /* 390 */ 456, 1004, 1150, 456, 1182, -76, 453, 1145, -76, -76,
+ /* 400 */ -76, -76, -76, 989, 428, 593, 745, 456, 1047, -76,
+ /* 410 */ 456, 729, 1237, 989, 486, 456, 1047, 900, 525, 1166,
+ /* 420 */ 456, 1047, -76, 1231, 622, 1261, 1257, 573, 1236, 917,
+ /* 430 */ -76, -76, 1174, 1175, 437, 456, 773, -76, -76, 1228,
+ /* 440 */ -76, -76, 1135, 456, 755, 1177, 456, 1260, 456, 1032,
+ /* 450 */ 903, 1276, 1147, 1277, 174, 490, 326, 235, -76, 1164,
+ /* 460 */ 1165, 1278, 1284, 1285, 174, 1279, 1233, 456, 1191, 456,
+ /* 470 */ 956, 456, 1238, 1257, 638, 1305, 1242, 1257, 638, 1189,
+ /* 480 */ 456, 1299, 456, 1036, -76, 360, 551, 1300, 1257, 1042,
+ /* 490 */ 1257, 638, 1316, 638, 1209, 456, 601, 1320, 240, 456,
+ /* 500 */ 1321, 456, 1322, 456, 1323, 456, 1324, 557, 1217, 456,
+ /* 510 */ 601, 1328, 1233, 456, 1232, 456, 956, 1333, 1218, 456,
+ /* 520 */ 1299, 970, 586, 1325, 1257, 1063, 1335, 460, 1342, 456,
+ /* 530 */ 1047, 788, 172, 1346, 1347, 1350, 1352, 456, 1339, 1354,
+ /* 540 */ 1330, -25, 1348, 456, 1078, 1364, 845, 1366, 1367, -76,
+ /* 550 */ 1330, 456, 1368, 542, 1081, 1372, 1362, 456, 1336, 1254,
+ /* 560 */ 456, 1388, -76, -76,
};
-#define YY_REDUCE_USE_DFLT (-142)
+#define YY_REDUCE_USE_DFLT (-95)
static const short yy_reduce_ofst[] = {
- /* 0 */ -107, 342, -142, -117, -142, -142, -142, 72, 442, -142,
- /* 10 */ 394, -142, -142, -142, -142, -142, -142, -142, 525, -142,
- /* 20 */ 579, -142, 731, -142, 515, -142, 8, 881, -142, -142,
- /* 30 */ 48, -142, 337, 882, 153, -142, 890, -136, -142, 875,
- /* 40 */ -142, -142, 310, -142, -142, -142, -142, -142, -142, -142,
- /* 50 */ -142, 883, -142, 870, -142, -142, -142, -142, -142, 884,
- /* 60 */ 891, -142, -142, -142, 892, -142, -142, 693, -142, 175,
- /* 70 */ -142, -142, 54, -142, 866, 876, -142, 867, -41, 885,
- /* 80 */ 888, 889, 893, 895, 877, -142, -141, -142, -142, -142,
- /* 90 */ 186, -142, 849, -142, -142, -142, 852, -142, -142, 189,
- /* 100 */ -142, -142, 234, -142, 244, 894, 913, -142, 924, -142,
- /* 110 */ -142, 241, 705, -142, -142, 942, -142, 948, -142, -142,
- /* 120 */ -142, -142, -142, 241, 716, 241, 732, 241, 734, 241,
- /* 130 */ 735, 241, 737, 241, 747, 241, 750, 241, 753, 241,
- /* 140 */ 755, 241, 758, 241, 763, 241, 764, 241, 765, 241,
- /* 150 */ 766, 241, 768, 241, 774, 241, 776, 241, -142, -142,
- /* 160 */ -142, -142, -142, -142, -142, -142, 779, 241, -142, -142,
- /* 170 */ -142, -142, -142, -142, -142, 781, 241, 782, 241, -142,
- /* 180 */ 950, 609, 866, -142, -142, -142, -142, -142, 241, 784,
- /* 190 */ 241, 789, 241, 794, 241, 795, 241, 583, 241, 896,
- /* 200 */ 897, -142, -142, 805, 241, 810, 241, -142, 919, -142,
- /* 210 */ -142, -142, 957, -142, -142, 813, 241, 814, 241, 815,
- /* 220 */ 241, -142, -142, 606, -142, -142, 956, 961, -142, -142,
- /* 230 */ 903, 952, -142, 818, 241, -142, 177, -142, 820, 241,
- /* 240 */ -142, 477, 915, -142, -142, -142, 969, -142, 970, -142,
- /* 250 */ -142, -142, 972, 967, 518, -142, -142, 974, -142, -142,
- /* 260 */ 923, 926, -142, -142, 821, -142, -142, 980, -142, -142,
- /* 270 */ 828, 241, 13, 866, 915, -142, 564, 930, 933, -142,
- /* 280 */ 830, 185, -142, -142, -142, 942, -142, -142, -142, -142,
- /* 290 */ 241, -142, -142, -142, -142, -142, 241, 973, -142, 987,
- /* 300 */ 966, 976, 962, -142, 990, -142, -142, 984, -142, -142,
- /* 310 */ -142, -142, -142, -142, 986, -142, 989, -142, -138, -142,
- /* 320 */ -142, 689, 935, 993, -142, -142, 936, 997, -142, -142,
- /* 330 */ 995, -142, 963, -142, -142, 369, -142, -142, -142, -142,
- /* 340 */ 999, 411, -142, -142, 415, -142, -142, -142, -142, -142,
- /* 350 */ 998, 1002, -142, 1006, -142, -142, -142, 491, -142, 1007,
- /* 360 */ -142, -142, 576, -142, 1009, -142, 833, -1, -142, -142,
- /* 370 */ -142, 660, -142, -142, 1008, 1010, 1012, 229, -142, -142,
- /* 380 */ -142, -142, -142, -142, 567, 866, 595, -142, 1021, 1016,
- /* 390 */ -142, 1022, 1026, -142, 574, 866, 1023, 1027, 927, 958,
- /* 400 */ -142, 401, 1030, -142, 937, 934, -142, 838, 241, -142,
- /* 410 */ -142, -142, -142, -142, -142, -142, 826, -142, -142, -142,
- /* 420 */ -142, -142, -142, -142, 1038, 1035, -142, 536, -142, 697,
- /* 430 */ -142, 1024, -142, -142, -142, 608, 866, 1014, 829, -142,
- /* 440 */ -142, -142, -142, -142, -142, 647, -142, 1025, 1054, -142,
- /* 450 */ 717, 1018, 1057, -142, 853, 241, -142, -142, 854, 241,
- /* 460 */ -142, 1064, 1028, 858, -142, -142, 613, 866, -142, 637,
- /* 470 */ -142, 869, 241, -142, 241, -142, 1076, 1029, -142, -142,
- /* 480 */ 700, -142, 871, -142, 872, -142, 873, -142, 866, -142,
- /* 490 */ 874, 1036, -142, 1046, 879, -142, 878, 1039, -142, -142,
- /* 500 */ 880, 1031, 855, 866, -142, 688, -142, -142, 1086, -142,
- /* 510 */ 1088, 1091, -142, 569, -142, -142, -142, -142, 1099, -142,
- /* 520 */ -142, 1032, 1090, -142, 1105, 1033, -142, 1093, -142, -142,
- /* 530 */ -142, 1037, 1107, -142, -142, -142, -142,
+ /* 0 */ 0, -61, -95, -95, 202, -95, -95, -95, -94, -59,
+ /* 10 */ -95, 52, -95, -95, -95, -95, -95, -95, -95, 103,
+ /* 20 */ -95, 189, -95, 261, -95, 349, -95, 185, 520, -95,
+ /* 30 */ -95, 109, -95, 33, 576, 116, -95, 595, 162, -95,
+ /* 40 */ 636, -95, -95, 36, -95, -95, -95, -95, -95, -95,
+ /* 50 */ -95, -95, 655, -95, 761, -95, -95, -95, -95, -95,
+ /* 60 */ 805, 921, 924, -95, -95, -95, -95, 928, -95, -95,
+ /* 70 */ 446, -95, 122, -95, -95, -95, -70, -95, 913, 920,
+ /* 80 */ -95, 935, 496, 915, 936, 933, 937, 938, 940, -95,
+ /* 90 */ 448, 388, 513, 388, 519, -95, -95, 993, -95, 996,
+ /* 100 */ -95, -95, -95, -95, -95, -95, -95, -95, -95, 388,
+ /* 110 */ 522, 388, 578, 388, 580, 388, 581, 388, 589, 388,
+ /* 120 */ 590, 388, 643, 388, 644, 388, 645, 388, 646, 388,
+ /* 130 */ 651, 388, 654, 388, 707, 388, 709, 388, 710, 388,
+ /* 140 */ 712, 388, 715, 388, -95, -95, -95, -95, -95, -95,
+ /* 150 */ -95, -95, 717, 188, 718, 388, -95, -95, -95, -95,
+ /* 160 */ -95, -95, -95, 720, 388, 723, 388, -95, 997, 462,
+ /* 170 */ 913, -95, -95, -95, -95, -95, 388, 725, 388, 774,
+ /* 180 */ 388, 775, 388, 776, 388, -95, 572, 913, -95, 45,
+ /* 190 */ 388, 932, 930, -95, -95, 782, 388, 783, 388, -95,
+ /* 200 */ 971, -95, -95, -95, 1011, -95, -95, 784, 388, 785,
+ /* 210 */ 388, 790, 388, -95, -95, 252, -95, -95, 1012, 1015,
+ /* 220 */ -95, -95, -95, 828, 388, -95, 186, -95, 320, 962,
+ /* 230 */ 1005, -95, 1014, -95, -95, 388, 967, 1008, -95, 829,
+ /* 240 */ 388, -95, 180, -95, 837, 388, -95, 291, 980, -95,
+ /* 250 */ -95, -95, 1037, -95, 1038, -95, -95, -95, 1039, 1028,
+ /* 260 */ 535, -95, -95, 1040, -95, -95, 982, 994, -95, -95,
+ /* 270 */ 407, -95, -95, 1044, -95, -95, 840, 388, 126, 913,
+ /* 280 */ 980, -95, 669, 998, 995, -95, 850, 201, -95, -95,
+ /* 290 */ -95, 993, -95, -95, -95, -95, 388, -95, -95, -95,
+ /* 300 */ -95, -95, 388, 1048, -95, 1053, 1030, 1031, 1050, -95,
+ /* 310 */ 1056, -95, -95, 1041, -95, -95, -95, -95, -95, -95,
+ /* 320 */ 1043, -95, 1051, -95, 583, -95, -95, 516, 1006, 1052,
+ /* 330 */ -95, -95, 1018, 1054, -95, -95, 1061, -95, 1055, -95,
+ /* 340 */ -95, 515, -95, 1064, -95, -95, 1066, -95, -95, 1062,
+ /* 350 */ 196, -95, -95, 269, -95, -95, -95, -95, 1013, -95,
+ /* 360 */ -95, -95, 1020, -95, -95, -95, -95, -95, 1058, 1060,
+ /* 370 */ -95, 1077, -95, -95, -95, 713, 1070, -95, 1074, -95,
+ /* 380 */ -95, 786, -95, 1075, -95, 851, 318, -95, -95, -95,
+ /* 390 */ 792, -95, -95, 1101, 1083, 1076, 110, -95, -95, -95,
+ /* 400 */ -95, -95, -95, 865, 913, 330, -95, 1107, 1105, -95,
+ /* 410 */ 1110, 1111, -95, 887, 913, 1116, 1114, 1059, 1067, -95,
+ /* 420 */ 878, 1117, -95, 1080, 1086, -95, 869, 388, -95, -95,
+ /* 430 */ -95, -95, -95, -95, -95, 855, -95, -95, -95, -95,
+ /* 440 */ -95, -95, -95, 1126, 1127, -95, 1139, -95, 797, -95,
+ /* 450 */ 1113, -95, -95, -95, 527, 913, 1102, 796, -95, -95,
+ /* 460 */ -95, -95, -95, -95, 592, -95, 1123, 1159, -95, 838,
+ /* 470 */ 1118, 1160, -95, 876, 388, -95, -95, 888, 388, -95,
+ /* 480 */ 1176, 1109, 866, -95, -95, 895, 913, -95, 317, -95,
+ /* 490 */ 890, 388, -95, 388, -95, 1178, 1140, -95, -95, 906,
+ /* 500 */ -95, 918, -95, 919, -95, 922, -95, 913, -95, 923,
+ /* 510 */ 1142, -95, 1153, 925, -95, 931, 1149, -95, -95, 927,
+ /* 520 */ 1131, 934, 913, -95, 395, -95, -95, 1202, -95, 1204,
+ /* 530 */ 1203, -95, 397, -95, -95, -95, -95, 1208, -95, -95,
+ /* 540 */ 1133, 1207, -95, 1221, 1141, -95, 1211, -95, -95, -95,
+ /* 550 */ 1144, 1234, -95, 1243, 1229, -95, -95, 939, -95, -95,
+ /* 560 */ 1246, -95, -95, -95,
};
static const YYACTIONTYPE yy_default[] = {
- /* 0 */ 544, 544, 538, 829, 829, 540, 829, 549, 829, 829,
- /* 10 */ 829, 829, 569, 570, 571, 550, 551, 552, 829, 829,
- /* 20 */ 829, 829, 829, 829, 829, 829, 829, 829, 829, 829,
- /* 30 */ 829, 562, 572, 581, 564, 580, 829, 829, 582, 623,
- /* 40 */ 588, 829, 829, 624, 627, 628, 629, 818, 819, 820,
- /* 50 */ 829, 623, 589, 608, 606, 829, 609, 610, 829, 679,
- /* 60 */ 623, 590, 677, 678, 623, 591, 829, 829, 708, 770,
- /* 70 */ 714, 709, 829, 634, 829, 829, 635, 643, 645, 652,
- /* 80 */ 691, 682, 684, 672, 686, 640, 793, 578, 579, 687,
- /* 90 */ 793, 688, 829, 788, 790, 791, 829, 789, 792, 793,
- /* 100 */ 689, 829, 829, 673, 829, 680, 679, 674, 829, 566,
- /* 110 */ 681, 676, 829, 707, 829, 829, 710, 829, 711, 712,
- /* 120 */ 713, 715, 716, 719, 829, 720, 829, 721, 829, 722,
- /* 130 */ 829, 723, 829, 724, 829, 725, 829, 726, 829, 727,
- /* 140 */ 829, 728, 829, 729, 829, 730, 829, 731, 829, 732,
- /* 150 */ 829, 733, 829, 734, 829, 735, 829, 736, 737, 738,
- /* 160 */ 829, 739, 740, 745, 753, 756, 829, 741, 742, 829,
- /* 170 */ 743, 829, 746, 744, 752, 829, 829, 829, 754, 755,
- /* 180 */ 829, 770, 829, 829, 829, 829, 829, 758, 769, 829,
- /* 190 */ 747, 829, 748, 829, 749, 829, 750, 829, 829, 829,
- /* 200 */ 829, 829, 760, 829, 829, 829, 761, 829, 829, 829,
- /* 210 */ 816, 829, 829, 829, 817, 829, 829, 829, 829, 829,
- /* 220 */ 762, 829, 757, 770, 767, 768, 660, 829, 661, 759,
- /* 230 */ 680, 679, 675, 829, 685, 829, 770, 683, 829, 692,
- /* 240 */ 644, 655, 653, 654, 663, 664, 829, 665, 829, 666,
- /* 250 */ 829, 667, 829, 660, 651, 567, 568, 829, 649, 650,
- /* 260 */ 669, 671, 656, 829, 829, 829, 670, 829, 704, 705,
- /* 270 */ 829, 668, 655, 829, 829, 829, 651, 669, 671, 657,
- /* 280 */ 829, 651, 646, 647, 829, 829, 648, 641, 642, 751,
- /* 290 */ 829, 706, 829, 717, 829, 718, 829, 623, 592, 829,
- /* 300 */ 774, 596, 593, 597, 829, 598, 829, 829, 599, 829,
- /* 310 */ 602, 603, 604, 605, 829, 600, 829, 601, 829, 829,
- /* 320 */ 775, 829, 680, 679, 776, 778, 680, 679, 777, 594,
- /* 330 */ 829, 595, 608, 607, 583, 793, 584, 585, 586, 587,
- /* 340 */ 573, 793, 829, 574, 793, 829, 575, 577, 576, 565,
- /* 350 */ 829, 829, 613, 829, 616, 829, 829, 829, 829, 623,
- /* 360 */ 617, 829, 829, 829, 623, 618, 829, 623, 619, 829,
- /* 370 */ 829, 829, 829, 829, 829, 774, 596, 621, 829, 620,
- /* 380 */ 622, 614, 615, 563, 829, 829, 559, 829, 829, 660,
- /* 390 */ 557, 829, 829, 829, 829, 829, 829, 660, 799, 829,
- /* 400 */ 829, 829, 660, 662, 804, 829, 829, 829, 829, 829,
- /* 410 */ 829, 805, 806, 829, 829, 829, 829, 829, 796, 797,
- /* 420 */ 829, 798, 558, 829, 829, 829, 829, 829, 829, 829,
- /* 430 */ 829, 829, 829, 829, 829, 829, 829, 829, 829, 626,
- /* 440 */ 829, 829, 829, 829, 829, 829, 829, 625, 829, 829,
- /* 450 */ 829, 829, 829, 829, 829, 694, 829, 829, 829, 695,
- /* 460 */ 829, 829, 702, 829, 829, 703, 829, 829, 829, 829,
- /* 470 */ 829, 829, 700, 829, 701, 829, 829, 829, 829, 829,
- /* 480 */ 829, 829, 829, 829, 829, 829, 829, 829, 829, 829,
- /* 490 */ 829, 829, 829, 625, 829, 829, 829, 829, 829, 829,
- /* 500 */ 829, 702, 829, 829, 829, 829, 829, 829, 829, 829,
- /* 510 */ 829, 660, 829, 793, 829, 829, 829, 829, 829, 829,
- /* 520 */ 829, 827, 829, 829, 829, 829, 829, 829, 829, 829,
- /* 530 */ 826, 827, 829, 829, 541, 543, 539,
+ /* 0 */ 570, 570, 565, 568, 869, 869, 869, 569, 576, 869,
+ /* 10 */ 869, 869, 869, 596, 597, 598, 577, 578, 579, 869,
+ /* 20 */ 869, 869, 869, 869, 869, 869, 869, 869, 869, 869,
+ /* 30 */ 869, 869, 589, 599, 608, 591, 607, 869, 869, 609,
+ /* 40 */ 652, 615, 869, 869, 653, 656, 657, 658, 855, 856,
+ /* 50 */ 857, 869, 652, 616, 637, 635, 869, 638, 639, 869,
+ /* 60 */ 708, 652, 623, 617, 624, 706, 707, 652, 618, 869,
+ /* 70 */ 869, 738, 807, 744, 739, 735, 869, 663, 869, 869,
+ /* 80 */ 664, 672, 674, 681, 720, 711, 713, 701, 715, 669,
+ /* 90 */ 869, 716, 869, 717, 869, 737, 869, 869, 740, 869,
+ /* 100 */ 741, 742, 743, 745, 746, 747, 750, 751, 752, 753,
+ /* 110 */ 869, 754, 869, 755, 869, 756, 869, 757, 869, 758,
+ /* 120 */ 869, 759, 869, 760, 869, 761, 869, 762, 869, 763,
+ /* 130 */ 869, 764, 869, 765, 869, 766, 869, 767, 869, 768,
+ /* 140 */ 869, 769, 869, 770, 771, 772, 869, 773, 774, 781,
+ /* 150 */ 788, 791, 869, 776, 869, 775, 778, 869, 779, 869,
+ /* 160 */ 782, 780, 787, 869, 869, 869, 789, 790, 869, 807,
+ /* 170 */ 869, 869, 869, 869, 869, 794, 806, 869, 783, 869,
+ /* 180 */ 784, 869, 785, 869, 786, 869, 869, 869, 796, 869,
+ /* 190 */ 869, 869, 869, 869, 797, 869, 869, 869, 798, 869,
+ /* 200 */ 869, 869, 853, 869, 869, 869, 854, 869, 869, 869,
+ /* 210 */ 869, 869, 799, 869, 792, 807, 804, 805, 689, 869,
+ /* 220 */ 690, 795, 777, 869, 718, 869, 869, 702, 869, 709,
+ /* 230 */ 708, 703, 869, 593, 710, 705, 709, 708, 704, 869,
+ /* 240 */ 714, 869, 807, 712, 869, 721, 673, 684, 682, 683,
+ /* 250 */ 692, 693, 869, 694, 869, 695, 869, 696, 869, 689,
+ /* 260 */ 680, 594, 595, 869, 678, 679, 698, 700, 685, 869,
+ /* 270 */ 869, 869, 699, 869, 733, 734, 869, 697, 684, 869,
+ /* 280 */ 869, 869, 680, 698, 700, 686, 869, 680, 675, 676,
+ /* 290 */ 869, 869, 677, 670, 671, 793, 869, 736, 869, 748,
+ /* 300 */ 869, 749, 869, 652, 619, 869, 811, 625, 620, 626,
+ /* 310 */ 869, 627, 869, 869, 628, 869, 631, 632, 633, 634,
+ /* 320 */ 869, 629, 869, 630, 869, 869, 812, 869, 709, 708,
+ /* 330 */ 813, 815, 709, 708, 814, 621, 869, 622, 637, 636,
+ /* 340 */ 610, 869, 611, 869, 612, 744, 869, 613, 614, 600,
+ /* 350 */ 830, 869, 601, 830, 869, 602, 605, 606, 869, 825,
+ /* 360 */ 827, 828, 869, 826, 829, 604, 603, 592, 869, 869,
+ /* 370 */ 642, 869, 645, 869, 869, 869, 869, 869, 652, 646,
+ /* 380 */ 869, 869, 869, 652, 647, 869, 652, 648, 869, 869,
+ /* 390 */ 869, 869, 869, 869, 811, 625, 650, 869, 649, 651,
+ /* 400 */ 643, 644, 590, 869, 869, 586, 869, 869, 689, 584,
+ /* 410 */ 869, 869, 869, 869, 869, 869, 689, 836, 869, 869,
+ /* 420 */ 869, 689, 691, 841, 869, 869, 869, 869, 869, 869,
+ /* 430 */ 842, 843, 869, 869, 869, 869, 869, 833, 834, 869,
+ /* 440 */ 835, 585, 869, 869, 869, 869, 869, 869, 869, 869,
+ /* 450 */ 869, 869, 869, 869, 869, 869, 869, 869, 655, 869,
+ /* 460 */ 869, 869, 869, 869, 869, 869, 654, 869, 869, 869,
+ /* 470 */ 869, 869, 869, 869, 723, 869, 869, 869, 724, 869,
+ /* 480 */ 869, 731, 869, 869, 732, 869, 869, 869, 869, 869,
+ /* 490 */ 869, 729, 869, 730, 869, 869, 869, 869, 869, 869,
+ /* 500 */ 869, 869, 869, 869, 869, 869, 869, 869, 869, 869,
+ /* 510 */ 869, 869, 654, 869, 869, 869, 869, 869, 869, 869,
+ /* 520 */ 731, 869, 869, 869, 869, 869, 869, 869, 869, 869,
+ /* 530 */ 689, 869, 830, 869, 869, 869, 869, 869, 869, 869,
+ /* 540 */ 864, 869, 869, 869, 869, 869, 869, 869, 869, 863,
+ /* 550 */ 864, 869, 869, 869, 869, 869, 869, 869, 869, 869,
+ /* 560 */ 869, 869, 571, 566,
};
#define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))
@@ -672,6 +723,12 @@ static const YYCODETYPE yyFallback[] = {
26, /* TRIGGER => ID */
26, /* VACUUM => ID */
26, /* VIEW => ID */
+ 26, /* REINDEX => ID */
+ 26, /* RENAME => ID */
+ 26, /* CDATE => ID */
+ 26, /* CTIME => ID */
+ 26, /* CTIMESTAMP => ID */
+ 26, /* ALTER => ID */
0, /* OR => nothing */
0, /* AND => nothing */
0, /* NOT => nothing */
@@ -686,6 +743,7 @@ static const YYCODETYPE yyFallback[] = {
0, /* LE => nothing */
0, /* LT => nothing */
0, /* GE => nothing */
+ 0, /* ESCAPE => nothing */
0, /* BITAND => nothing */
0, /* BITOR => nothing */
0, /* LSHIFT => nothing */
@@ -709,6 +767,7 @@ static const YYCODETYPE yyFallback[] = {
0, /* CHECK => nothing */
0, /* REFERENCES => nothing */
0, /* COLLATE => nothing */
+ 0, /* AUTOINCR => nothing */
0, /* ON => nothing */
0, /* DELETE => nothing */
0, /* UPDATE => nothing */
@@ -738,12 +797,15 @@ static const YYCODETYPE yyFallback[] = {
0, /* INTEGER => nothing */
0, /* FLOAT => nothing */
0, /* BLOB => nothing */
+ 0, /* REGISTER => nothing */
0, /* VARIABLE => nothing */
+ 0, /* EXISTS => nothing */
0, /* CASE => nothing */
0, /* WHEN => nothing */
0, /* THEN => nothing */
0, /* ELSE => nothing */
0, /* INDEX => nothing */
+ 0, /* TO => nothing */
};
#endif /* YYFALLBACK */
@@ -828,16 +890,18 @@ static const char *const yyTokenName[] = {
"LIKE", "MATCH", "KEY", "OF",
"OFFSET", "PRAGMA", "RAISE", "REPLACE",
"RESTRICT", "ROW", "STATEMENT", "TRIGGER",
- "VACUUM", "VIEW", "OR", "AND",
- "NOT", "IS", "BETWEEN", "IN",
- "ISNULL", "NOTNULL", "NE", "EQ",
- "GT", "LE", "LT", "GE",
- "BITAND", "BITOR", "LSHIFT", "RSHIFT",
- "PLUS", "MINUS", "STAR", "SLASH",
- "REM", "CONCAT", "UMINUS", "UPLUS",
- "BITNOT", "STRING", "JOIN_KW", "CONSTRAINT",
- "DEFAULT", "NULL", "PRIMARY", "UNIQUE",
- "CHECK", "REFERENCES", "COLLATE", "ON",
+ "VACUUM", "VIEW", "REINDEX", "RENAME",
+ "CDATE", "CTIME", "CTIMESTAMP", "ALTER",
+ "OR", "AND", "NOT", "IS",
+ "BETWEEN", "IN", "ISNULL", "NOTNULL",
+ "NE", "EQ", "GT", "LE",
+ "LT", "GE", "ESCAPE", "BITAND",
+ "BITOR", "LSHIFT", "RSHIFT", "PLUS",
+ "MINUS", "STAR", "SLASH", "REM",
+ "CONCAT", "UMINUS", "UPLUS", "BITNOT",
+ "STRING", "JOIN_KW", "CONSTRAINT", "DEFAULT",
+ "NULL", "PRIMARY", "UNIQUE", "CHECK",
+ "REFERENCES", "COLLATE", "AUTOINCR", "ON",
"DELETE", "UPDATE", "INSERT", "SET",
"DEFERRABLE", "FOREIGN", "DROP", "UNION",
"ALL", "INTERSECT", "EXCEPT", "SELECT",
@@ -845,31 +909,33 @@ static const char *const yyTokenName[] = {
"USING", "ORDER", "BY", "GROUP",
"HAVING", "LIMIT", "WHERE", "INTO",
"VALUES", "INTEGER", "FLOAT", "BLOB",
- "VARIABLE", "CASE", "WHEN", "THEN",
- "ELSE", "INDEX", "error", "input",
- "cmdlist", "ecmd", "explain", "cmdx",
- "cmd", "transtype", "trans_opt", "nm",
- "create_table", "create_table_args", "temp", "dbnm",
- "columnlist", "conslist_opt", "select", "column",
- "columnid", "type", "carglist", "id",
- "ids", "typename", "signed", "plus_num",
- "minus_num", "carg", "ccons", "onconf",
- "sortorder", "expr", "idxlist_opt", "refargs",
- "defer_subclause", "refarg", "refact", "init_deferred_pred_opt",
- "conslist", "tcons", "idxlist", "defer_subclause_opt",
- "orconf", "resolvetype", "raisetype", "fullname",
- "oneselect", "multiselect_op", "distinct", "selcollist",
- "from", "where_opt", "groupby_opt", "having_opt",
- "orderby_opt", "limit_opt", "sclp", "as",
- "seltablist", "stl_prefix", "joinop", "on_opt",
- "using_opt", "seltablist_paren", "joinop2", "inscollist",
- "sortlist", "sortitem", "collate", "exprlist",
- "setlist", "insert_cmd", "inscollist_opt", "itemlist",
- "likeop", "between_op", "in_op", "case_operand",
- "case_exprlist", "case_else", "expritem", "uniqueflag",
- "idxitem", "plus_opt", "number", "trigger_decl",
- "trigger_cmd_list", "trigger_time", "trigger_event", "foreach_clause",
- "when_clause", "trigger_cmd", "database_kw_opt", "key_opt",
+ "REGISTER", "VARIABLE", "EXISTS", "CASE",
+ "WHEN", "THEN", "ELSE", "INDEX",
+ "TO", "error", "input", "cmdlist",
+ "ecmd", "cmdx", "cmd", "explain",
+ "transtype", "trans_opt", "nm", "create_table",
+ "create_table_args", "temp", "dbnm", "columnlist",
+ "conslist_opt", "select", "column", "columnid",
+ "type", "carglist", "id", "ids",
+ "typename", "signed", "plus_num", "minus_num",
+ "carg", "ccons", "term", "onconf",
+ "sortorder", "autoinc", "expr", "idxlist_opt",
+ "refargs", "defer_subclause", "refarg", "refact",
+ "init_deferred_pred_opt", "conslist", "tcons", "idxlist",
+ "defer_subclause_opt", "orconf", "resolvetype", "raisetype",
+ "fullname", "oneselect", "multiselect_op", "distinct",
+ "selcollist", "from", "where_opt", "groupby_opt",
+ "having_opt", "orderby_opt", "limit_opt", "sclp",
+ "as", "seltablist", "stl_prefix", "joinop",
+ "on_opt", "using_opt", "seltablist_paren", "joinop2",
+ "inscollist", "sortlist", "sortitem", "collate",
+ "exprlist", "setlist", "insert_cmd", "inscollist_opt",
+ "itemlist", "likeop", "escape", "between_op",
+ "in_op", "case_operand", "case_exprlist", "case_else",
+ "expritem", "uniqueflag", "idxitem", "plus_opt",
+ "number", "trigger_decl", "trigger_cmd_list", "trigger_time",
+ "trigger_event", "foreach_clause", "when_clause", "trigger_cmd",
+ "database_kw_opt", "key_opt",
};
#endif /* NDEBUG */
@@ -880,11 +946,11 @@ static const char *const yyRuleName[] = {
/* 0 */ "input ::= cmdlist",
/* 1 */ "cmdlist ::= cmdlist ecmd",
/* 2 */ "cmdlist ::= ecmd",
- /* 3 */ "ecmd ::= explain cmdx SEMI",
+ /* 3 */ "cmdx ::= cmd",
/* 4 */ "ecmd ::= SEMI",
- /* 5 */ "cmdx ::= cmd",
- /* 6 */ "explain ::= EXPLAIN",
- /* 7 */ "explain ::=",
+ /* 5 */ "ecmd ::= explain cmdx SEMI",
+ /* 6 */ "explain ::=",
+ /* 7 */ "explain ::= EXPLAIN",
/* 8 */ "cmd ::= BEGIN transtype trans_opt",
/* 9 */ "trans_opt ::=",
/* 10 */ "trans_opt ::= TRANSACTION",
@@ -924,251 +990,264 @@ static const char *const yyRuleName[] = {
/* 44 */ "carglist ::=",
/* 45 */ "carg ::= CONSTRAINT nm ccons",
/* 46 */ "carg ::= ccons",
- /* 47 */ "carg ::= DEFAULT ids",
- /* 48 */ "carg ::= DEFAULT plus_num",
- /* 49 */ "carg ::= DEFAULT minus_num",
- /* 50 */ "carg ::= DEFAULT NULL",
+ /* 47 */ "carg ::= DEFAULT term",
+ /* 48 */ "carg ::= DEFAULT PLUS term",
+ /* 49 */ "carg ::= DEFAULT MINUS term",
+ /* 50 */ "carg ::= DEFAULT id",
/* 51 */ "ccons ::= NULL onconf",
/* 52 */ "ccons ::= NOT NULL onconf",
- /* 53 */ "ccons ::= PRIMARY KEY sortorder onconf",
+ /* 53 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc",
/* 54 */ "ccons ::= UNIQUE onconf",
/* 55 */ "ccons ::= CHECK LP expr RP onconf",
/* 56 */ "ccons ::= REFERENCES nm idxlist_opt refargs",
/* 57 */ "ccons ::= defer_subclause",
/* 58 */ "ccons ::= COLLATE id",
- /* 59 */ "refargs ::=",
- /* 60 */ "refargs ::= refargs refarg",
- /* 61 */ "refarg ::= MATCH nm",
- /* 62 */ "refarg ::= ON DELETE refact",
- /* 63 */ "refarg ::= ON UPDATE refact",
- /* 64 */ "refarg ::= ON INSERT refact",
- /* 65 */ "refact ::= SET NULL",
- /* 66 */ "refact ::= SET DEFAULT",
- /* 67 */ "refact ::= CASCADE",
- /* 68 */ "refact ::= RESTRICT",
- /* 69 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt",
- /* 70 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt",
- /* 71 */ "init_deferred_pred_opt ::=",
- /* 72 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
- /* 73 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
- /* 74 */ "conslist_opt ::=",
- /* 75 */ "conslist_opt ::= COMMA conslist",
- /* 76 */ "conslist ::= conslist COMMA tcons",
- /* 77 */ "conslist ::= conslist tcons",
- /* 78 */ "conslist ::= tcons",
- /* 79 */ "tcons ::= CONSTRAINT nm",
- /* 80 */ "tcons ::= PRIMARY KEY LP idxlist RP onconf",
- /* 81 */ "tcons ::= UNIQUE LP idxlist RP onconf",
- /* 82 */ "tcons ::= CHECK expr onconf",
- /* 83 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt",
- /* 84 */ "defer_subclause_opt ::=",
- /* 85 */ "defer_subclause_opt ::= defer_subclause",
- /* 86 */ "onconf ::=",
- /* 87 */ "onconf ::= ON CONFLICT resolvetype",
- /* 88 */ "orconf ::=",
- /* 89 */ "orconf ::= OR resolvetype",
- /* 90 */ "resolvetype ::= raisetype",
- /* 91 */ "resolvetype ::= IGNORE",
- /* 92 */ "resolvetype ::= REPLACE",
- /* 93 */ "cmd ::= DROP TABLE fullname",
- /* 94 */ "cmd ::= CREATE temp VIEW nm dbnm AS select",
- /* 95 */ "cmd ::= DROP VIEW fullname",
- /* 96 */ "cmd ::= select",
- /* 97 */ "select ::= oneselect",
- /* 98 */ "select ::= select multiselect_op oneselect",
- /* 99 */ "multiselect_op ::= UNION",
- /* 100 */ "multiselect_op ::= UNION ALL",
- /* 101 */ "multiselect_op ::= INTERSECT",
- /* 102 */ "multiselect_op ::= EXCEPT",
- /* 103 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
- /* 104 */ "distinct ::= DISTINCT",
- /* 105 */ "distinct ::= ALL",
- /* 106 */ "distinct ::=",
- /* 107 */ "sclp ::= selcollist COMMA",
- /* 108 */ "sclp ::=",
- /* 109 */ "selcollist ::= sclp expr as",
- /* 110 */ "selcollist ::= sclp STAR",
- /* 111 */ "selcollist ::= sclp nm DOT STAR",
- /* 112 */ "as ::= AS nm",
- /* 113 */ "as ::= ids",
- /* 114 */ "as ::=",
- /* 115 */ "from ::=",
- /* 116 */ "from ::= FROM seltablist",
- /* 117 */ "stl_prefix ::= seltablist joinop",
- /* 118 */ "stl_prefix ::=",
- /* 119 */ "seltablist ::= stl_prefix nm dbnm as on_opt using_opt",
- /* 120 */ "seltablist ::= stl_prefix LP seltablist_paren RP as on_opt using_opt",
- /* 121 */ "seltablist_paren ::= select",
- /* 122 */ "seltablist_paren ::= seltablist",
- /* 123 */ "dbnm ::=",
- /* 124 */ "dbnm ::= DOT nm",
- /* 125 */ "fullname ::= nm dbnm",
- /* 126 */ "joinop ::= COMMA",
- /* 127 */ "joinop ::= JOIN",
- /* 128 */ "joinop ::= JOIN_KW JOIN",
- /* 129 */ "joinop ::= JOIN_KW nm JOIN",
- /* 130 */ "joinop ::= JOIN_KW nm nm JOIN",
- /* 131 */ "on_opt ::= ON expr",
- /* 132 */ "on_opt ::=",
- /* 133 */ "using_opt ::= USING LP inscollist RP",
- /* 134 */ "using_opt ::=",
- /* 135 */ "orderby_opt ::=",
- /* 136 */ "orderby_opt ::= ORDER BY sortlist",
- /* 137 */ "sortlist ::= sortlist COMMA sortitem collate sortorder",
- /* 138 */ "sortlist ::= sortitem collate sortorder",
- /* 139 */ "sortitem ::= expr",
- /* 140 */ "sortorder ::= ASC",
- /* 141 */ "sortorder ::= DESC",
- /* 142 */ "sortorder ::=",
- /* 143 */ "collate ::=",
- /* 144 */ "collate ::= COLLATE id",
- /* 145 */ "groupby_opt ::=",
- /* 146 */ "groupby_opt ::= GROUP BY exprlist",
- /* 147 */ "having_opt ::=",
- /* 148 */ "having_opt ::= HAVING expr",
- /* 149 */ "limit_opt ::=",
- /* 150 */ "limit_opt ::= LIMIT signed",
- /* 151 */ "limit_opt ::= LIMIT signed OFFSET signed",
- /* 152 */ "limit_opt ::= LIMIT signed COMMA signed",
- /* 153 */ "cmd ::= DELETE FROM fullname where_opt",
- /* 154 */ "where_opt ::=",
- /* 155 */ "where_opt ::= WHERE expr",
- /* 156 */ "cmd ::= UPDATE orconf fullname SET setlist where_opt",
- /* 157 */ "setlist ::= setlist COMMA nm EQ expr",
- /* 158 */ "setlist ::= nm EQ expr",
- /* 159 */ "cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP",
- /* 160 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select",
- /* 161 */ "insert_cmd ::= INSERT orconf",
- /* 162 */ "insert_cmd ::= REPLACE",
- /* 163 */ "itemlist ::= itemlist COMMA expr",
- /* 164 */ "itemlist ::= expr",
- /* 165 */ "inscollist_opt ::=",
- /* 166 */ "inscollist_opt ::= LP inscollist RP",
- /* 167 */ "inscollist ::= inscollist COMMA nm",
- /* 168 */ "inscollist ::= nm",
- /* 169 */ "expr ::= LP expr RP",
- /* 170 */ "expr ::= NULL",
- /* 171 */ "expr ::= ID",
- /* 172 */ "expr ::= JOIN_KW",
- /* 173 */ "expr ::= nm DOT nm",
- /* 174 */ "expr ::= nm DOT nm DOT nm",
- /* 175 */ "expr ::= INTEGER",
- /* 176 */ "expr ::= FLOAT",
- /* 177 */ "expr ::= STRING",
- /* 178 */ "expr ::= BLOB",
- /* 179 */ "expr ::= VARIABLE",
- /* 180 */ "expr ::= ID LP exprlist RP",
- /* 181 */ "expr ::= ID LP STAR RP",
- /* 182 */ "expr ::= expr AND expr",
- /* 183 */ "expr ::= expr OR expr",
- /* 184 */ "expr ::= expr LT expr",
- /* 185 */ "expr ::= expr GT expr",
- /* 186 */ "expr ::= expr LE expr",
- /* 187 */ "expr ::= expr GE expr",
- /* 188 */ "expr ::= expr NE expr",
- /* 189 */ "expr ::= expr EQ expr",
- /* 190 */ "expr ::= expr BITAND expr",
- /* 191 */ "expr ::= expr BITOR expr",
- /* 192 */ "expr ::= expr LSHIFT expr",
- /* 193 */ "expr ::= expr RSHIFT expr",
- /* 194 */ "expr ::= expr PLUS expr",
- /* 195 */ "expr ::= expr MINUS expr",
- /* 196 */ "expr ::= expr STAR expr",
- /* 197 */ "expr ::= expr SLASH expr",
- /* 198 */ "expr ::= expr REM expr",
- /* 199 */ "expr ::= expr CONCAT expr",
- /* 200 */ "likeop ::= LIKE",
- /* 201 */ "likeop ::= GLOB",
- /* 202 */ "likeop ::= NOT LIKE",
- /* 203 */ "likeop ::= NOT GLOB",
- /* 204 */ "expr ::= expr likeop expr",
- /* 205 */ "expr ::= expr ISNULL",
- /* 206 */ "expr ::= expr IS NULL",
- /* 207 */ "expr ::= expr NOTNULL",
- /* 208 */ "expr ::= expr NOT NULL",
- /* 209 */ "expr ::= expr IS NOT NULL",
- /* 210 */ "expr ::= NOT expr",
- /* 211 */ "expr ::= BITNOT expr",
- /* 212 */ "expr ::= MINUS expr",
- /* 213 */ "expr ::= PLUS expr",
- /* 214 */ "expr ::= LP select RP",
- /* 215 */ "between_op ::= BETWEEN",
- /* 216 */ "between_op ::= NOT BETWEEN",
- /* 217 */ "expr ::= expr between_op expr AND expr",
- /* 218 */ "in_op ::= IN",
- /* 219 */ "in_op ::= NOT IN",
- /* 220 */ "expr ::= expr in_op LP exprlist RP",
- /* 221 */ "expr ::= expr in_op LP select RP",
- /* 222 */ "expr ::= expr in_op nm dbnm",
- /* 223 */ "expr ::= CASE case_operand case_exprlist case_else END",
- /* 224 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
- /* 225 */ "case_exprlist ::= WHEN expr THEN expr",
- /* 226 */ "case_else ::= ELSE expr",
- /* 227 */ "case_else ::=",
- /* 228 */ "case_operand ::= expr",
- /* 229 */ "case_operand ::=",
- /* 230 */ "exprlist ::= exprlist COMMA expritem",
- /* 231 */ "exprlist ::= expritem",
- /* 232 */ "expritem ::= expr",
- /* 233 */ "expritem ::=",
- /* 234 */ "cmd ::= CREATE uniqueflag INDEX nm dbnm ON fullname LP idxlist RP onconf",
- /* 235 */ "uniqueflag ::= UNIQUE",
- /* 236 */ "uniqueflag ::=",
- /* 237 */ "idxlist_opt ::=",
- /* 238 */ "idxlist_opt ::= LP idxlist RP",
- /* 239 */ "idxlist ::= idxlist COMMA idxitem collate sortorder",
- /* 240 */ "idxlist ::= idxitem collate sortorder",
- /* 241 */ "idxitem ::= nm",
- /* 242 */ "cmd ::= DROP INDEX fullname",
- /* 243 */ "cmd ::= VACUUM",
- /* 244 */ "cmd ::= VACUUM nm",
- /* 245 */ "cmd ::= PRAGMA nm dbnm EQ nm",
- /* 246 */ "cmd ::= PRAGMA nm dbnm EQ ON",
- /* 247 */ "cmd ::= PRAGMA nm dbnm EQ plus_num",
- /* 248 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
- /* 249 */ "cmd ::= PRAGMA nm dbnm LP nm RP",
- /* 250 */ "cmd ::= PRAGMA nm dbnm",
- /* 251 */ "plus_num ::= plus_opt number",
- /* 252 */ "minus_num ::= MINUS number",
- /* 253 */ "number ::= INTEGER",
- /* 254 */ "number ::= FLOAT",
- /* 255 */ "plus_opt ::= PLUS",
- /* 256 */ "plus_opt ::=",
- /* 257 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END",
- /* 258 */ "trigger_decl ::= temp TRIGGER nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
- /* 259 */ "trigger_time ::= BEFORE",
- /* 260 */ "trigger_time ::= AFTER",
- /* 261 */ "trigger_time ::= INSTEAD OF",
- /* 262 */ "trigger_time ::=",
- /* 263 */ "trigger_event ::= DELETE",
- /* 264 */ "trigger_event ::= INSERT",
- /* 265 */ "trigger_event ::= UPDATE",
- /* 266 */ "trigger_event ::= UPDATE OF inscollist",
- /* 267 */ "foreach_clause ::=",
- /* 268 */ "foreach_clause ::= FOR EACH ROW",
- /* 269 */ "foreach_clause ::= FOR EACH STATEMENT",
- /* 270 */ "when_clause ::=",
- /* 271 */ "when_clause ::= WHEN expr",
- /* 272 */ "trigger_cmd_list ::= trigger_cmd SEMI trigger_cmd_list",
- /* 273 */ "trigger_cmd_list ::=",
- /* 274 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt",
- /* 275 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP",
- /* 276 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select",
- /* 277 */ "trigger_cmd ::= DELETE FROM nm where_opt",
- /* 278 */ "trigger_cmd ::= select",
- /* 279 */ "expr ::= RAISE LP IGNORE RP",
- /* 280 */ "expr ::= RAISE LP raisetype COMMA nm RP",
- /* 281 */ "raisetype ::= ROLLBACK",
- /* 282 */ "raisetype ::= ABORT",
- /* 283 */ "raisetype ::= FAIL",
- /* 284 */ "cmd ::= DROP TRIGGER fullname",
- /* 285 */ "cmd ::= ATTACH database_kw_opt ids AS nm key_opt",
- /* 286 */ "key_opt ::=",
- /* 287 */ "key_opt ::= KEY ids",
- /* 288 */ "key_opt ::= KEY BLOB",
- /* 289 */ "database_kw_opt ::= DATABASE",
- /* 290 */ "database_kw_opt ::=",
- /* 291 */ "cmd ::= DETACH database_kw_opt nm",
+ /* 59 */ "autoinc ::=",
+ /* 60 */ "autoinc ::= AUTOINCR",
+ /* 61 */ "refargs ::=",
+ /* 62 */ "refargs ::= refargs refarg",
+ /* 63 */ "refarg ::= MATCH nm",
+ /* 64 */ "refarg ::= ON DELETE refact",
+ /* 65 */ "refarg ::= ON UPDATE refact",
+ /* 66 */ "refarg ::= ON INSERT refact",
+ /* 67 */ "refact ::= SET NULL",
+ /* 68 */ "refact ::= SET DEFAULT",
+ /* 69 */ "refact ::= CASCADE",
+ /* 70 */ "refact ::= RESTRICT",
+ /* 71 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt",
+ /* 72 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt",
+ /* 73 */ "init_deferred_pred_opt ::=",
+ /* 74 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
+ /* 75 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
+ /* 76 */ "conslist_opt ::=",
+ /* 77 */ "conslist_opt ::= COMMA conslist",
+ /* 78 */ "conslist ::= conslist COMMA tcons",
+ /* 79 */ "conslist ::= conslist tcons",
+ /* 80 */ "conslist ::= tcons",
+ /* 81 */ "tcons ::= CONSTRAINT nm",
+ /* 82 */ "tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf",
+ /* 83 */ "tcons ::= UNIQUE LP idxlist RP onconf",
+ /* 84 */ "tcons ::= CHECK expr onconf",
+ /* 85 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt",
+ /* 86 */ "defer_subclause_opt ::=",
+ /* 87 */ "defer_subclause_opt ::= defer_subclause",
+ /* 88 */ "onconf ::=",
+ /* 89 */ "onconf ::= ON CONFLICT resolvetype",
+ /* 90 */ "orconf ::=",
+ /* 91 */ "orconf ::= OR resolvetype",
+ /* 92 */ "resolvetype ::= raisetype",
+ /* 93 */ "resolvetype ::= IGNORE",
+ /* 94 */ "resolvetype ::= REPLACE",
+ /* 95 */ "cmd ::= DROP TABLE fullname",
+ /* 96 */ "cmd ::= CREATE temp VIEW nm dbnm AS select",
+ /* 97 */ "cmd ::= DROP VIEW fullname",
+ /* 98 */ "cmd ::= select",
+ /* 99 */ "select ::= oneselect",
+ /* 100 */ "select ::= select multiselect_op oneselect",
+ /* 101 */ "multiselect_op ::= UNION",
+ /* 102 */ "multiselect_op ::= UNION ALL",
+ /* 103 */ "multiselect_op ::= INTERSECT",
+ /* 104 */ "multiselect_op ::= EXCEPT",
+ /* 105 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
+ /* 106 */ "distinct ::= DISTINCT",
+ /* 107 */ "distinct ::= ALL",
+ /* 108 */ "distinct ::=",
+ /* 109 */ "sclp ::= selcollist COMMA",
+ /* 110 */ "sclp ::=",
+ /* 111 */ "selcollist ::= sclp expr as",
+ /* 112 */ "selcollist ::= sclp STAR",
+ /* 113 */ "selcollist ::= sclp nm DOT STAR",
+ /* 114 */ "as ::= AS nm",
+ /* 115 */ "as ::= ids",
+ /* 116 */ "as ::=",
+ /* 117 */ "from ::=",
+ /* 118 */ "from ::= FROM seltablist",
+ /* 119 */ "stl_prefix ::= seltablist joinop",
+ /* 120 */ "stl_prefix ::=",
+ /* 121 */ "seltablist ::= stl_prefix nm dbnm as on_opt using_opt",
+ /* 122 */ "seltablist ::= stl_prefix LP seltablist_paren RP as on_opt using_opt",
+ /* 123 */ "seltablist_paren ::= select",
+ /* 124 */ "seltablist_paren ::= seltablist",
+ /* 125 */ "dbnm ::=",
+ /* 126 */ "dbnm ::= DOT nm",
+ /* 127 */ "fullname ::= nm dbnm",
+ /* 128 */ "joinop ::= COMMA",
+ /* 129 */ "joinop ::= JOIN",
+ /* 130 */ "joinop ::= JOIN_KW JOIN",
+ /* 131 */ "joinop ::= JOIN_KW nm JOIN",
+ /* 132 */ "joinop ::= JOIN_KW nm nm JOIN",
+ /* 133 */ "on_opt ::= ON expr",
+ /* 134 */ "on_opt ::=",
+ /* 135 */ "using_opt ::= USING LP inscollist RP",
+ /* 136 */ "using_opt ::=",
+ /* 137 */ "orderby_opt ::=",
+ /* 138 */ "orderby_opt ::= ORDER BY sortlist",
+ /* 139 */ "sortlist ::= sortlist COMMA sortitem collate sortorder",
+ /* 140 */ "sortlist ::= sortitem collate sortorder",
+ /* 141 */ "sortitem ::= expr",
+ /* 142 */ "sortorder ::= ASC",
+ /* 143 */ "sortorder ::= DESC",
+ /* 144 */ "sortorder ::=",
+ /* 145 */ "collate ::=",
+ /* 146 */ "collate ::= COLLATE id",
+ /* 147 */ "groupby_opt ::=",
+ /* 148 */ "groupby_opt ::= GROUP BY exprlist",
+ /* 149 */ "having_opt ::=",
+ /* 150 */ "having_opt ::= HAVING expr",
+ /* 151 */ "limit_opt ::=",
+ /* 152 */ "limit_opt ::= LIMIT expr",
+ /* 153 */ "limit_opt ::= LIMIT expr OFFSET expr",
+ /* 154 */ "limit_opt ::= LIMIT expr COMMA expr",
+ /* 155 */ "cmd ::= DELETE FROM fullname where_opt",
+ /* 156 */ "where_opt ::=",
+ /* 157 */ "where_opt ::= WHERE expr",
+ /* 158 */ "cmd ::= UPDATE orconf fullname SET setlist where_opt",
+ /* 159 */ "setlist ::= setlist COMMA nm EQ expr",
+ /* 160 */ "setlist ::= nm EQ expr",
+ /* 161 */ "cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP",
+ /* 162 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select",
+ /* 163 */ "insert_cmd ::= INSERT orconf",
+ /* 164 */ "insert_cmd ::= REPLACE",
+ /* 165 */ "itemlist ::= itemlist COMMA expr",
+ /* 166 */ "itemlist ::= expr",
+ /* 167 */ "inscollist_opt ::=",
+ /* 168 */ "inscollist_opt ::= LP inscollist RP",
+ /* 169 */ "inscollist ::= inscollist COMMA nm",
+ /* 170 */ "inscollist ::= nm",
+ /* 171 */ "expr ::= term",
+ /* 172 */ "expr ::= LP expr RP",
+ /* 173 */ "term ::= NULL",
+ /* 174 */ "expr ::= ID",
+ /* 175 */ "expr ::= JOIN_KW",
+ /* 176 */ "expr ::= nm DOT nm",
+ /* 177 */ "expr ::= nm DOT nm DOT nm",
+ /* 178 */ "term ::= INTEGER",
+ /* 179 */ "term ::= FLOAT",
+ /* 180 */ "term ::= STRING",
+ /* 181 */ "expr ::= BLOB",
+ /* 182 */ "expr ::= REGISTER",
+ /* 183 */ "expr ::= VARIABLE",
+ /* 184 */ "expr ::= ID LP exprlist RP",
+ /* 185 */ "expr ::= ID LP STAR RP",
+ /* 186 */ "term ::= CTIME",
+ /* 187 */ "term ::= CDATE",
+ /* 188 */ "term ::= CTIMESTAMP",
+ /* 189 */ "expr ::= expr AND expr",
+ /* 190 */ "expr ::= expr OR expr",
+ /* 191 */ "expr ::= expr LT expr",
+ /* 192 */ "expr ::= expr GT expr",
+ /* 193 */ "expr ::= expr LE expr",
+ /* 194 */ "expr ::= expr GE expr",
+ /* 195 */ "expr ::= expr NE expr",
+ /* 196 */ "expr ::= expr EQ expr",
+ /* 197 */ "expr ::= expr BITAND expr",
+ /* 198 */ "expr ::= expr BITOR expr",
+ /* 199 */ "expr ::= expr LSHIFT expr",
+ /* 200 */ "expr ::= expr RSHIFT expr",
+ /* 201 */ "expr ::= expr PLUS expr",
+ /* 202 */ "expr ::= expr MINUS expr",
+ /* 203 */ "expr ::= expr STAR expr",
+ /* 204 */ "expr ::= expr SLASH expr",
+ /* 205 */ "expr ::= expr REM expr",
+ /* 206 */ "expr ::= expr CONCAT expr",
+ /* 207 */ "likeop ::= LIKE",
+ /* 208 */ "likeop ::= GLOB",
+ /* 209 */ "likeop ::= NOT LIKE",
+ /* 210 */ "likeop ::= NOT GLOB",
+ /* 211 */ "escape ::= ESCAPE expr",
+ /* 212 */ "escape ::=",
+ /* 213 */ "expr ::= expr likeop expr escape",
+ /* 214 */ "expr ::= expr ISNULL",
+ /* 215 */ "expr ::= expr IS NULL",
+ /* 216 */ "expr ::= expr NOTNULL",
+ /* 217 */ "expr ::= expr NOT NULL",
+ /* 218 */ "expr ::= expr IS NOT NULL",
+ /* 219 */ "expr ::= NOT expr",
+ /* 220 */ "expr ::= BITNOT expr",
+ /* 221 */ "expr ::= MINUS expr",
+ /* 222 */ "expr ::= PLUS expr",
+ /* 223 */ "between_op ::= BETWEEN",
+ /* 224 */ "between_op ::= NOT BETWEEN",
+ /* 225 */ "expr ::= expr between_op expr AND expr",
+ /* 226 */ "in_op ::= IN",
+ /* 227 */ "in_op ::= NOT IN",
+ /* 228 */ "expr ::= expr in_op LP exprlist RP",
+ /* 229 */ "expr ::= LP select RP",
+ /* 230 */ "expr ::= expr in_op LP select RP",
+ /* 231 */ "expr ::= expr in_op nm dbnm",
+ /* 232 */ "expr ::= EXISTS LP select RP",
+ /* 233 */ "expr ::= CASE case_operand case_exprlist case_else END",
+ /* 234 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
+ /* 235 */ "case_exprlist ::= WHEN expr THEN expr",
+ /* 236 */ "case_else ::= ELSE expr",
+ /* 237 */ "case_else ::=",
+ /* 238 */ "case_operand ::= expr",
+ /* 239 */ "case_operand ::=",
+ /* 240 */ "exprlist ::= exprlist COMMA expritem",
+ /* 241 */ "exprlist ::= expritem",
+ /* 242 */ "expritem ::= expr",
+ /* 243 */ "expritem ::=",
+ /* 244 */ "cmd ::= CREATE uniqueflag INDEX nm dbnm ON nm LP idxlist RP onconf",
+ /* 245 */ "uniqueflag ::= UNIQUE",
+ /* 246 */ "uniqueflag ::=",
+ /* 247 */ "idxlist_opt ::=",
+ /* 248 */ "idxlist_opt ::= LP idxlist RP",
+ /* 249 */ "idxlist ::= idxlist COMMA idxitem collate sortorder",
+ /* 250 */ "idxlist ::= idxitem collate sortorder",
+ /* 251 */ "idxitem ::= nm",
+ /* 252 */ "cmd ::= DROP INDEX fullname",
+ /* 253 */ "cmd ::= VACUUM",
+ /* 254 */ "cmd ::= VACUUM nm",
+ /* 255 */ "cmd ::= PRAGMA nm dbnm EQ nm",
+ /* 256 */ "cmd ::= PRAGMA nm dbnm EQ ON",
+ /* 257 */ "cmd ::= PRAGMA nm dbnm EQ plus_num",
+ /* 258 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
+ /* 259 */ "cmd ::= PRAGMA nm dbnm LP nm RP",
+ /* 260 */ "cmd ::= PRAGMA nm dbnm",
+ /* 261 */ "plus_num ::= plus_opt number",
+ /* 262 */ "minus_num ::= MINUS number",
+ /* 263 */ "number ::= INTEGER",
+ /* 264 */ "number ::= FLOAT",
+ /* 265 */ "plus_opt ::= PLUS",
+ /* 266 */ "plus_opt ::=",
+ /* 267 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END",
+ /* 268 */ "trigger_decl ::= temp TRIGGER nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
+ /* 269 */ "trigger_time ::= BEFORE",
+ /* 270 */ "trigger_time ::= AFTER",
+ /* 271 */ "trigger_time ::= INSTEAD OF",
+ /* 272 */ "trigger_time ::=",
+ /* 273 */ "trigger_event ::= DELETE",
+ /* 274 */ "trigger_event ::= INSERT",
+ /* 275 */ "trigger_event ::= UPDATE",
+ /* 276 */ "trigger_event ::= UPDATE OF inscollist",
+ /* 277 */ "foreach_clause ::=",
+ /* 278 */ "foreach_clause ::= FOR EACH ROW",
+ /* 279 */ "foreach_clause ::= FOR EACH STATEMENT",
+ /* 280 */ "when_clause ::=",
+ /* 281 */ "when_clause ::= WHEN expr",
+ /* 282 */ "trigger_cmd_list ::= trigger_cmd SEMI trigger_cmd_list",
+ /* 283 */ "trigger_cmd_list ::=",
+ /* 284 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt",
+ /* 285 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP",
+ /* 286 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select",
+ /* 287 */ "trigger_cmd ::= DELETE FROM nm where_opt",
+ /* 288 */ "trigger_cmd ::= select",
+ /* 289 */ "expr ::= RAISE LP IGNORE RP",
+ /* 290 */ "expr ::= RAISE LP raisetype COMMA nm RP",
+ /* 291 */ "raisetype ::= ROLLBACK",
+ /* 292 */ "raisetype ::= ABORT",
+ /* 293 */ "raisetype ::= FAIL",
+ /* 294 */ "cmd ::= DROP TRIGGER fullname",
+ /* 295 */ "cmd ::= ATTACH database_kw_opt ids AS nm key_opt",
+ /* 296 */ "key_opt ::=",
+ /* 297 */ "key_opt ::= KEY ids",
+ /* 298 */ "key_opt ::= KEY BLOB",
+ /* 299 */ "database_kw_opt ::= DATABASE",
+ /* 300 */ "database_kw_opt ::=",
+ /* 301 */ "cmd ::= DETACH database_kw_opt nm",
+ /* 302 */ "cmd ::= REINDEX",
+ /* 303 */ "cmd ::= REINDEX nm dbnm",
+ /* 304 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
};
#endif /* NDEBUG */
@@ -1226,63 +1305,72 @@ static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){
** which appear on the RHS of the rule, but which are not used
** inside the C code.
*/
- case 146:
- case 176:
- case 193:
-#line 303 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3SelectDelete((yypminor->yy107));}
-#line 1236 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
- break;
- case 161:
- case 181:
- case 183:
- case 191:
- case 197:
- case 210:
-#line 552 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3ExprDelete((yypminor->yy258));}
-#line 1246 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 157:
+ case 189:
+ case 206:
+#line 325 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3SelectDelete((yypminor->yy331));}
+#line 1315 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 162:
case 170:
- case 179:
- case 182:
- case 184:
- case 186:
+ case 174:
+ case 194:
case 196:
- case 199:
- case 200:
- case 203:
- case 208:
-#line 744 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3ExprListDelete((yypminor->yy210));}
-#line 1261 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 204:
+ case 210:
+ case 224:
+#line 584 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3ExprDelete((yypminor->yy454));}
+#line 1326 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 175:
- case 180:
- case 188:
- case 189:
-#line 428 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3SrcListDelete((yypminor->yy259));}
-#line 1269 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
- break;
+ case 183:
case 192:
case 195:
+ case 197:
+ case 199:
+ case 209:
+ case 212:
+ case 213:
+ case 216:
+ case 222:
+#line 796 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3ExprListDelete((yypminor->yy266));}
+#line 1341 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
+ case 188:
+ case 193:
+ case 201:
case 202:
-#line 446 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 454 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3SrcListDelete((yypminor->yy427));}
+#line 1349 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
+ case 198:
+#line 516 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+ sqlite3ExprDelete((yypminor->yy348).pLimit);
+ sqlite3ExprDelete((yypminor->yy348).pOffset);
+}
+#line 1357 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
+ case 205:
+ case 208:
+ case 215:
+#line 472 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{sqlite3IdListDelete((yypminor->yy272));}
-#line 1276 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 1364 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 216:
- case 221:
-#line 833 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3DeleteTriggerStep((yypminor->yy91));}
-#line 1282 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 230:
+ case 235:
+#line 889 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3DeleteTriggerStep((yypminor->yy455));}
+#line 1370 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 218:
-#line 817 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3IdListDelete((yypminor->yy146).b);}
-#line 1287 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 232:
+#line 873 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3IdListDelete((yypminor->yy62).b);}
+#line 1375 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
default: break; /* If no destructor action specified: do nothing */
}
@@ -1458,298 +1546,311 @@ static const struct {
YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
unsigned char nrhs; /* Number of right-hand side symbols in the rule */
} yyRuleInfo[] = {
- { 131, 1 },
- { 132, 2 },
- { 132, 1 },
- { 133, 3 },
- { 133, 1 },
- { 135, 1 },
- { 134, 1 },
- { 134, 0 },
- { 136, 3 },
- { 138, 0 },
- { 138, 1 },
- { 138, 2 },
- { 137, 0 },
- { 137, 1 },
- { 137, 1 },
- { 137, 1 },
- { 136, 2 },
- { 136, 2 },
- { 136, 2 },
- { 136, 2 },
- { 140, 5 },
{ 142, 1 },
- { 142, 0 },
- { 141, 4 },
- { 141, 2 },
- { 144, 3 },
+ { 143, 2 },
+ { 143, 1 },
+ { 145, 1 },
{ 144, 1 },
- { 147, 3 },
- { 148, 1 },
- { 151, 1 },
- { 152, 1 },
- { 152, 1 },
- { 139, 1 },
- { 139, 1 },
- { 139, 1 },
+ { 144, 3 },
+ { 147, 0 },
+ { 147, 1 },
+ { 146, 3 },
{ 149, 0 },
{ 149, 1 },
- { 149, 4 },
- { 149, 6 },
+ { 149, 2 },
+ { 148, 0 },
+ { 148, 1 },
+ { 148, 1 },
+ { 148, 1 },
+ { 146, 2 },
+ { 146, 2 },
+ { 146, 2 },
+ { 146, 2 },
+ { 151, 5 },
{ 153, 1 },
- { 153, 2 },
- { 154, 1 },
- { 154, 1 },
- { 150, 2 },
- { 150, 0 },
- { 157, 3 },
- { 157, 1 },
- { 157, 2 },
- { 157, 2 },
- { 157, 2 },
- { 157, 2 },
- { 158, 2 },
+ { 153, 0 },
+ { 152, 4 },
+ { 152, 2 },
+ { 155, 3 },
+ { 155, 1 },
{ 158, 3 },
- { 158, 4 },
- { 158, 2 },
- { 158, 5 },
- { 158, 4 },
- { 158, 1 },
- { 158, 2 },
- { 163, 0 },
- { 163, 2 },
- { 165, 2 },
- { 165, 3 },
- { 165, 3 },
- { 165, 3 },
- { 166, 2 },
- { 166, 2 },
- { 166, 1 },
- { 166, 1 },
- { 164, 3 },
+ { 159, 1 },
+ { 162, 1 },
+ { 163, 1 },
+ { 163, 1 },
+ { 150, 1 },
+ { 150, 1 },
+ { 150, 1 },
+ { 160, 0 },
+ { 160, 1 },
+ { 160, 4 },
+ { 160, 6 },
+ { 164, 1 },
{ 164, 2 },
- { 167, 0 },
- { 167, 2 },
- { 167, 2 },
- { 145, 0 },
- { 145, 2 },
+ { 165, 1 },
+ { 165, 1 },
+ { 161, 2 },
+ { 161, 0 },
{ 168, 3 },
- { 168, 2 },
{ 168, 1 },
+ { 168, 2 },
+ { 168, 3 },
+ { 168, 3 },
+ { 168, 2 },
{ 169, 2 },
- { 169, 6 },
- { 169, 5 },
{ 169, 3 },
- { 169, 10 },
- { 171, 0 },
- { 171, 1 },
- { 159, 0 },
- { 159, 3 },
- { 172, 0 },
- { 172, 2 },
- { 173, 1 },
- { 173, 1 },
+ { 169, 5 },
+ { 169, 2 },
+ { 169, 5 },
+ { 169, 4 },
+ { 169, 1 },
+ { 169, 2 },
+ { 173, 0 },
{ 173, 1 },
- { 136, 3 },
- { 136, 7 },
- { 136, 3 },
- { 136, 1 },
- { 146, 1 },
- { 146, 3 },
- { 177, 1 },
- { 177, 2 },
- { 177, 1 },
- { 177, 1 },
- { 176, 9 },
- { 178, 1 },
- { 178, 1 },
- { 178, 0 },
- { 186, 2 },
- { 186, 0 },
- { 179, 3 },
+ { 176, 0 },
+ { 176, 2 },
+ { 178, 2 },
+ { 178, 3 },
+ { 178, 3 },
+ { 178, 3 },
{ 179, 2 },
- { 179, 4 },
- { 187, 2 },
- { 187, 1 },
- { 187, 0 },
+ { 179, 2 },
+ { 179, 1 },
+ { 179, 1 },
+ { 177, 3 },
+ { 177, 2 },
{ 180, 0 },
{ 180, 2 },
- { 189, 2 },
- { 189, 0 },
- { 188, 6 },
- { 188, 7 },
- { 193, 1 },
- { 193, 1 },
- { 143, 0 },
- { 143, 2 },
- { 175, 2 },
- { 190, 1 },
+ { 180, 2 },
+ { 156, 0 },
+ { 156, 2 },
+ { 181, 3 },
+ { 181, 2 },
+ { 181, 1 },
+ { 182, 2 },
+ { 182, 7 },
+ { 182, 5 },
+ { 182, 3 },
+ { 182, 10 },
+ { 184, 0 },
+ { 184, 1 },
+ { 171, 0 },
+ { 171, 3 },
+ { 185, 0 },
+ { 185, 2 },
+ { 186, 1 },
+ { 186, 1 },
+ { 186, 1 },
+ { 146, 3 },
+ { 146, 7 },
+ { 146, 3 },
+ { 146, 1 },
+ { 157, 1 },
+ { 157, 3 },
{ 190, 1 },
{ 190, 2 },
- { 190, 3 },
- { 190, 4 },
- { 191, 2 },
+ { 190, 1 },
+ { 190, 1 },
+ { 189, 9 },
+ { 191, 1 },
+ { 191, 1 },
{ 191, 0 },
+ { 199, 2 },
+ { 199, 0 },
+ { 192, 3 },
+ { 192, 2 },
{ 192, 4 },
- { 192, 0 },
- { 184, 0 },
- { 184, 3 },
- { 196, 5 },
- { 196, 3 },
- { 197, 1 },
- { 160, 1 },
- { 160, 1 },
- { 160, 0 },
- { 198, 0 },
- { 198, 2 },
- { 182, 0 },
- { 182, 3 },
- { 183, 0 },
- { 183, 2 },
- { 185, 0 },
- { 185, 2 },
- { 185, 4 },
- { 185, 4 },
- { 136, 4 },
- { 181, 0 },
- { 181, 2 },
- { 136, 6 },
- { 200, 5 },
- { 200, 3 },
- { 136, 8 },
- { 136, 5 },
- { 201, 2 },
- { 201, 1 },
- { 203, 3 },
- { 203, 1 },
+ { 200, 2 },
+ { 200, 1 },
+ { 200, 0 },
+ { 193, 0 },
+ { 193, 2 },
+ { 202, 2 },
{ 202, 0 },
- { 202, 3 },
- { 195, 3 },
- { 195, 1 },
- { 161, 3 },
- { 161, 1 },
- { 161, 1 },
- { 161, 1 },
- { 161, 3 },
- { 161, 5 },
- { 161, 1 },
- { 161, 1 },
- { 161, 1 },
- { 161, 1 },
- { 161, 1 },
- { 161, 4 },
- { 161, 4 },
- { 161, 3 },
- { 161, 3 },
- { 161, 3 },
- { 161, 3 },
- { 161, 3 },
- { 161, 3 },
- { 161, 3 },
- { 161, 3 },
- { 161, 3 },
- { 161, 3 },
- { 161, 3 },
- { 161, 3 },
- { 161, 3 },
- { 161, 3 },
- { 161, 3 },
- { 161, 3 },
- { 161, 3 },
- { 161, 3 },
- { 204, 1 },
- { 204, 1 },
- { 204, 2 },
- { 204, 2 },
- { 161, 3 },
- { 161, 2 },
- { 161, 3 },
- { 161, 2 },
- { 161, 3 },
- { 161, 4 },
- { 161, 2 },
- { 161, 2 },
- { 161, 2 },
- { 161, 2 },
- { 161, 3 },
- { 205, 1 },
- { 205, 2 },
- { 161, 5 },
+ { 201, 6 },
+ { 201, 7 },
{ 206, 1 },
- { 206, 2 },
- { 161, 5 },
- { 161, 5 },
- { 161, 4 },
- { 161, 5 },
- { 208, 5 },
- { 208, 4 },
- { 209, 2 },
- { 209, 0 },
- { 207, 1 },
- { 207, 0 },
- { 199, 3 },
- { 199, 1 },
+ { 206, 1 },
+ { 154, 0 },
+ { 154, 2 },
+ { 188, 2 },
+ { 203, 1 },
+ { 203, 1 },
+ { 203, 2 },
+ { 203, 3 },
+ { 203, 4 },
+ { 204, 2 },
+ { 204, 0 },
+ { 205, 4 },
+ { 205, 0 },
+ { 197, 0 },
+ { 197, 3 },
+ { 209, 5 },
+ { 209, 3 },
{ 210, 1 },
- { 210, 0 },
- { 136, 11 },
- { 211, 1 },
+ { 172, 1 },
+ { 172, 1 },
+ { 172, 0 },
{ 211, 0 },
- { 162, 0 },
- { 162, 3 },
- { 170, 5 },
- { 170, 3 },
- { 212, 1 },
- { 136, 3 },
- { 136, 1 },
- { 136, 2 },
- { 136, 5 },
- { 136, 5 },
- { 136, 5 },
- { 136, 5 },
- { 136, 6 },
- { 136, 3 },
- { 155, 2 },
- { 156, 2 },
- { 214, 1 },
+ { 211, 2 },
+ { 195, 0 },
+ { 195, 3 },
+ { 196, 0 },
+ { 196, 2 },
+ { 198, 0 },
+ { 198, 2 },
+ { 198, 4 },
+ { 198, 4 },
+ { 146, 4 },
+ { 194, 0 },
+ { 194, 2 },
+ { 146, 6 },
+ { 213, 5 },
+ { 213, 3 },
+ { 146, 8 },
+ { 146, 5 },
+ { 214, 2 },
{ 214, 1 },
- { 213, 1 },
- { 213, 0 },
- { 136, 5 },
- { 215, 10 },
- { 217, 1 },
- { 217, 1 },
- { 217, 2 },
- { 217, 0 },
- { 218, 1 },
- { 218, 1 },
- { 218, 1 },
- { 218, 3 },
- { 219, 0 },
- { 219, 3 },
- { 219, 3 },
- { 220, 0 },
- { 220, 2 },
{ 216, 3 },
- { 216, 0 },
- { 221, 6 },
- { 221, 8 },
- { 221, 5 },
- { 221, 4 },
- { 221, 1 },
- { 161, 4 },
- { 161, 6 },
+ { 216, 1 },
+ { 215, 0 },
+ { 215, 3 },
+ { 208, 3 },
+ { 208, 1 },
{ 174, 1 },
+ { 174, 3 },
+ { 170, 1 },
{ 174, 1 },
{ 174, 1 },
- { 136, 3 },
- { 136, 6 },
- { 223, 0 },
- { 223, 2 },
+ { 174, 3 },
+ { 174, 5 },
+ { 170, 1 },
+ { 170, 1 },
+ { 170, 1 },
+ { 174, 1 },
+ { 174, 1 },
+ { 174, 1 },
+ { 174, 4 },
+ { 174, 4 },
+ { 170, 1 },
+ { 170, 1 },
+ { 170, 1 },
+ { 174, 3 },
+ { 174, 3 },
+ { 174, 3 },
+ { 174, 3 },
+ { 174, 3 },
+ { 174, 3 },
+ { 174, 3 },
+ { 174, 3 },
+ { 174, 3 },
+ { 174, 3 },
+ { 174, 3 },
+ { 174, 3 },
+ { 174, 3 },
+ { 174, 3 },
+ { 174, 3 },
+ { 174, 3 },
+ { 174, 3 },
+ { 174, 3 },
+ { 217, 1 },
+ { 217, 1 },
+ { 217, 2 },
+ { 217, 2 },
+ { 218, 2 },
+ { 218, 0 },
+ { 174, 4 },
+ { 174, 2 },
+ { 174, 3 },
+ { 174, 2 },
+ { 174, 3 },
+ { 174, 4 },
+ { 174, 2 },
+ { 174, 2 },
+ { 174, 2 },
+ { 174, 2 },
+ { 219, 1 },
+ { 219, 2 },
+ { 174, 5 },
+ { 220, 1 },
+ { 220, 2 },
+ { 174, 5 },
+ { 174, 3 },
+ { 174, 5 },
+ { 174, 4 },
+ { 174, 4 },
+ { 174, 5 },
+ { 222, 5 },
+ { 222, 4 },
{ 223, 2 },
- { 222, 1 },
- { 222, 0 },
- { 136, 3 },
+ { 223, 0 },
+ { 221, 1 },
+ { 221, 0 },
+ { 212, 3 },
+ { 212, 1 },
+ { 224, 1 },
+ { 224, 0 },
+ { 146, 11 },
+ { 225, 1 },
+ { 225, 0 },
+ { 175, 0 },
+ { 175, 3 },
+ { 183, 5 },
+ { 183, 3 },
+ { 226, 1 },
+ { 146, 3 },
+ { 146, 1 },
+ { 146, 2 },
+ { 146, 5 },
+ { 146, 5 },
+ { 146, 5 },
+ { 146, 5 },
+ { 146, 6 },
+ { 146, 3 },
+ { 166, 2 },
+ { 167, 2 },
+ { 228, 1 },
+ { 228, 1 },
+ { 227, 1 },
+ { 227, 0 },
+ { 146, 5 },
+ { 229, 10 },
+ { 231, 1 },
+ { 231, 1 },
+ { 231, 2 },
+ { 231, 0 },
+ { 232, 1 },
+ { 232, 1 },
+ { 232, 1 },
+ { 232, 3 },
+ { 233, 0 },
+ { 233, 3 },
+ { 233, 3 },
+ { 234, 0 },
+ { 234, 2 },
+ { 230, 3 },
+ { 230, 0 },
+ { 235, 6 },
+ { 235, 8 },
+ { 235, 5 },
+ { 235, 4 },
+ { 235, 1 },
+ { 174, 4 },
+ { 174, 6 },
+ { 187, 1 },
+ { 187, 1 },
+ { 187, 1 },
+ { 146, 3 },
+ { 146, 6 },
+ { 237, 0 },
+ { 237, 2 },
+ { 237, 2 },
+ { 236, 1 },
+ { 236, 0 },
+ { 146, 3 },
+ { 146, 1 },
+ { 146, 3 },
+ { 146, 6 },
};
static void yy_accept(yyParser*); /* Forward Declaration */
@@ -1786,99 +1887,101 @@ static void yy_reduce(
** #line <lineno> <thisfile>
** break;
*/
- case 5:
-#line 86 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 3:
+#line 84 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{ sqlite3FinishCoding(pParse); }
-#line 1794 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 1895 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 6:
-#line 87 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ sqlite3BeginParse(pParse, 1); }
-#line 1799 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 87 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ sqlite3BeginParse(pParse, 0); }
+#line 1900 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 7:
-#line 88 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ sqlite3BeginParse(pParse, 0); }
-#line 1804 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 89 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ sqlite3BeginParse(pParse, 1); }
+#line 1905 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 8:
-#line 93 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy284);}
-#line 1809 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 95 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy60);}
+#line 1910 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 12:
-#line 98 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = TK_DEFERRED;}
-#line 1814 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 100 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = TK_DEFERRED;}
+#line 1915 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 13:
case 14:
case 15:
- case 99:
case 101:
- case 102:
-#line 99 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = yymsp[0].major;}
-#line 1824 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 103:
+ case 104:
+#line 101 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = yymsp[0].major;}
+#line 1925 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 16:
case 17:
-#line 102 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 104 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{sqlite3CommitTransaction(pParse);}
-#line 1830 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 1931 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 18:
-#line 104 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 106 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{sqlite3RollbackTransaction(pParse);}
-#line 1835 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 1936 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 20:
-#line 109 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 111 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- sqlite3StartTable(pParse,&yymsp[-4].minor.yy0,&yymsp[-1].minor.yy98,&yymsp[0].minor.yy98,yymsp[-3].minor.yy284,0);
+ sqlite3StartTable(pParse,&yymsp[-4].minor.yy0,&yymsp[-1].minor.yy406,&yymsp[0].minor.yy406,yymsp[-3].minor.yy60,0);
}
-#line 1842 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 1943 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 21:
- case 72:
- case 104:
- case 216:
- case 219:
-#line 113 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = 1;}
-#line 1851 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 60:
+ case 74:
+ case 106:
+ case 224:
+ case 227:
+#line 115 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = 1;}
+#line 1953 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 22:
- case 71:
+ case 59:
case 73:
- case 84:
- case 105:
- case 106:
- case 215:
- case 218:
-#line 114 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = 0;}
-#line 1863 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 75:
+ case 86:
+ case 107:
+ case 108:
+ case 223:
+ case 226:
+#line 116 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = 0;}
+#line 1966 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 23:
-#line 115 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 117 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
sqlite3EndTable(pParse,&yymsp[0].minor.yy0,0);
}
-#line 1870 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 1973 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 24:
-#line 118 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 120 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- sqlite3EndTable(pParse,0,yymsp[0].minor.yy107);
- sqlite3SelectDelete(yymsp[0].minor.yy107);
+ sqlite3EndTable(pParse,0,yymsp[0].minor.yy331);
+ sqlite3SelectDelete(yymsp[0].minor.yy331);
}
-#line 1878 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 1981 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 28:
-#line 130 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddColumn(pParse,&yymsp[0].minor.yy98);}
-#line 1883 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 132 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3AddColumn(pParse,&yymsp[0].minor.yy406);}
+#line 1986 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 29:
case 30:
@@ -1886,600 +1989,619 @@ static void yy_reduce(
case 32:
case 33:
case 34:
- case 253:
- case 254:
-#line 136 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy98 = yymsp[0].minor.yy0;}
-#line 1895 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 263:
+ case 264:
+#line 138 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy406 = yymsp[0].minor.yy0;}
+#line 1998 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 36:
-#line 185 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy98,&yymsp[0].minor.yy98);}
-#line 1900 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 193 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy406,&yymsp[0].minor.yy406);}
+#line 2003 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 37:
-#line 186 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddColumnType(pParse,&yymsp[-3].minor.yy98,&yymsp[0].minor.yy0);}
-#line 1905 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 194 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3AddColumnType(pParse,&yymsp[-3].minor.yy406,&yymsp[0].minor.yy0);}
+#line 2008 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 38:
-#line 188 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddColumnType(pParse,&yymsp[-5].minor.yy98,&yymsp[0].minor.yy0);}
-#line 1910 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 196 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3AddColumnType(pParse,&yymsp[-5].minor.yy406,&yymsp[0].minor.yy0);}
+#line 2013 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 39:
- case 112:
- case 113:
- case 124:
- case 144:
- case 241:
+ case 114:
+ case 115:
+ case 126:
+ case 146:
case 251:
- case 252:
-#line 190 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy98 = yymsp[0].minor.yy98;}
-#line 1922 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 261:
+ case 262:
+#line 198 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy406 = yymsp[0].minor.yy406;}
+#line 2025 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 40:
-#line 191 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy98.z=yymsp[-1].minor.yy98.z; yygotominor.yy98.n=yymsp[0].minor.yy98.n+(yymsp[0].minor.yy98.z-yymsp[-1].minor.yy98.z);}
-#line 1927 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 199 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy406.z=yymsp[-1].minor.yy406.z; yygotominor.yy406.n=yymsp[0].minor.yy406.n+(yymsp[0].minor.yy406.z-yymsp[-1].minor.yy406.z);}
+#line 2030 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 41:
-#line 193 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = atoi(yymsp[0].minor.yy98.z); }
-#line 1932 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 201 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = atoi(yymsp[0].minor.yy406.z); }
+#line 2035 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 42:
-#line 194 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = -atoi(yymsp[0].minor.yy98.z); }
-#line 1937 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 202 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = -atoi(yymsp[0].minor.yy406.z); }
+#line 2040 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 47:
case 48:
-#line 199 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy98,0);}
-#line 1943 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 207 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy454);}
+#line 2046 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 49:
-#line 201 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy98,1);}
-#line 1948 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 209 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+ Expr *p = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy454, 0, 0);
+ sqlite3AddDefaultValue(pParse,p);
+}
+#line 2054 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
+ case 50:
+#line 213 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+ Expr *p = sqlite3Expr(TK_STRING, 0, 0, &yymsp[0].minor.yy406);
+ sqlite3AddDefaultValue(pParse,p);
+}
+#line 2062 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 52:
-#line 208 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddNotNull(pParse, yymsp[0].minor.yy284);}
-#line 1953 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 222 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3AddNotNull(pParse, yymsp[0].minor.yy60);}
+#line 2067 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 53:
-#line 209 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddPrimaryKey(pParse,0,yymsp[0].minor.yy284);}
-#line 1958 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 224 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy60,yymsp[0].minor.yy60);}
+#line 2072 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 54:
-#line 210 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy284,0,0);}
-#line 1963 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 225 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy60,0,0);}
+#line 2077 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 56:
-#line 213 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy98,yymsp[-1].minor.yy210,yymsp[0].minor.yy284);}
-#line 1968 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 228 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy406,yymsp[-1].minor.yy266,yymsp[0].minor.yy60);}
+#line 2082 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 57:
-#line 214 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy284);}
-#line 1973 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 229 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy60);}
+#line 2087 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 58:
-#line 215 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddCollateType(pParse, yymsp[0].minor.yy98.z, yymsp[0].minor.yy98.n);}
-#line 1978 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
- break;
- case 59:
-#line 223 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = OE_Restrict * 0x010101; }
-#line 1983 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
- break;
- case 60:
-#line 224 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = (yymsp[-1].minor.yy284 & yymsp[0].minor.yy47.mask) | yymsp[0].minor.yy47.value; }
-#line 1988 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 230 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3AddCollateType(pParse, yymsp[0].minor.yy406.z, yymsp[0].minor.yy406.n);}
+#line 2092 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 61:
-#line 226 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy47.value = 0; yygotominor.yy47.mask = 0x000000; }
-#line 1993 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 243 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = OE_Restrict * 0x010101; }
+#line 2097 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 62:
-#line 227 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy47.value = yymsp[0].minor.yy284; yygotominor.yy47.mask = 0x0000ff; }
-#line 1998 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 244 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = (yymsp[-1].minor.yy60 & yymsp[0].minor.yy243.mask) | yymsp[0].minor.yy243.value; }
+#line 2102 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 63:
-#line 228 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy47.value = yymsp[0].minor.yy284<<8; yygotominor.yy47.mask = 0x00ff00; }
-#line 2003 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 246 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy243.value = 0; yygotominor.yy243.mask = 0x000000; }
+#line 2107 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 64:
-#line 229 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy47.value = yymsp[0].minor.yy284<<16; yygotominor.yy47.mask = 0xff0000; }
-#line 2008 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 247 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy243.value = yymsp[0].minor.yy60; yygotominor.yy243.mask = 0x0000ff; }
+#line 2112 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 65:
-#line 231 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = OE_SetNull; }
-#line 2013 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 248 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy243.value = yymsp[0].minor.yy60<<8; yygotominor.yy243.mask = 0x00ff00; }
+#line 2117 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 66:
-#line 232 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = OE_SetDflt; }
-#line 2018 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 249 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy243.value = yymsp[0].minor.yy60<<16; yygotominor.yy243.mask = 0xff0000; }
+#line 2122 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 67:
-#line 233 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = OE_Cascade; }
-#line 2023 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 251 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = OE_SetNull; }
+#line 2127 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 68:
-#line 234 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = OE_Restrict; }
-#line 2028 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 252 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = OE_SetDflt; }
+#line 2132 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 69:
+#line 253 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = OE_Cascade; }
+#line 2137 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
case 70:
- case 85:
+#line 254 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = OE_Restrict; }
+#line 2142 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
+ case 71:
+ case 72:
case 87:
case 89:
- case 90:
- case 161:
-#line 236 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = yymsp[0].minor.yy284;}
-#line 2039 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
- break;
- case 80:
-#line 253 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3AddPrimaryKey(pParse,yymsp[-2].minor.yy210,yymsp[0].minor.yy284);}
-#line 2044 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 91:
+ case 92:
+ case 163:
+#line 256 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = yymsp[0].minor.yy60;}
+#line 2153 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 81:
-#line 255 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy210,yymsp[0].minor.yy284,0,0);}
-#line 2049 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 82:
+#line 273 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy266,yymsp[0].minor.yy60,yymsp[-2].minor.yy60);}
+#line 2158 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 83:
-#line 258 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 275 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy266,yymsp[0].minor.yy60,0,0);}
+#line 2163 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
+ case 85:
+#line 278 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy210, &yymsp[-3].minor.yy98, yymsp[-2].minor.yy210, yymsp[-1].minor.yy284);
- sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy284);
+ sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy266, &yymsp[-3].minor.yy406, yymsp[-2].minor.yy266, yymsp[-1].minor.yy60);
+ sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy60);
}
-#line 2057 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2171 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 86:
case 88:
-#line 272 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = OE_Default;}
-#line 2063 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
- break;
- case 91:
-#line 277 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = OE_Ignore;}
-#line 2068 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
- break;
- case 92:
- case 162:
-#line 278 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = OE_Replace;}
-#line 2074 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 90:
+#line 292 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = OE_Default;}
+#line 2177 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 93:
-#line 282 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{
- sqlite3DropTable(pParse, yymsp[0].minor.yy259, 0);
-}
-#line 2081 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 297 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = OE_Ignore;}
+#line 2182 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 94:
-#line 288 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{
- sqlite3CreateView(pParse, &yymsp[-6].minor.yy0, &yymsp[-3].minor.yy98, &yymsp[-2].minor.yy98, yymsp[0].minor.yy107, yymsp[-5].minor.yy284);
-}
-#line 2088 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 164:
+#line 298 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = OE_Replace;}
+#line 2188 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 95:
-#line 291 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 302 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- sqlite3DropTable(pParse, yymsp[0].minor.yy259, 1);
+ sqlite3DropTable(pParse, yymsp[0].minor.yy427, 0);
}
-#line 2095 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2195 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 96:
-#line 297 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 309 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- sqlite3Select(pParse, yymsp[0].minor.yy107, SRT_Callback, 0, 0, 0, 0, 0);
- sqlite3SelectDelete(yymsp[0].minor.yy107);
+ sqlite3CreateView(pParse, &yymsp[-6].minor.yy0, &yymsp[-3].minor.yy406, &yymsp[-2].minor.yy406, yymsp[0].minor.yy331, yymsp[-5].minor.yy60);
}
-#line 2103 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2202 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 97:
- case 121:
-#line 307 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy107 = yymsp[0].minor.yy107;}
-#line 2109 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 312 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+ sqlite3DropTable(pParse, yymsp[0].minor.yy427, 1);
+}
+#line 2209 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 98:
-#line 308 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 319 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- if( yymsp[0].minor.yy107 ){
- yymsp[0].minor.yy107->op = yymsp[-1].minor.yy284;
- yymsp[0].minor.yy107->pPrior = yymsp[-2].minor.yy107;
- }
- yygotominor.yy107 = yymsp[0].minor.yy107;
+ sqlite3Select(pParse, yymsp[0].minor.yy331, SRT_Callback, 0, 0, 0, 0, 0);
+ sqlite3SelectDelete(yymsp[0].minor.yy331);
}
-#line 2120 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2217 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 100:
-#line 317 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = TK_ALL;}
-#line 2125 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 99:
+ case 123:
+#line 329 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy331 = yymsp[0].minor.yy331;}
+#line 2223 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 103:
-#line 321 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 100:
+#line 331 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- yygotominor.yy107 = sqlite3SelectNew(yymsp[-6].minor.yy210,yymsp[-5].minor.yy259,yymsp[-4].minor.yy258,yymsp[-3].minor.yy210,yymsp[-2].minor.yy258,yymsp[-1].minor.yy210,yymsp[-7].minor.yy284,yymsp[0].minor.yy404.limit,yymsp[0].minor.yy404.offset);
+ if( yymsp[0].minor.yy331 ){
+ yymsp[0].minor.yy331->op = yymsp[-1].minor.yy60;
+ yymsp[0].minor.yy331->pPrior = yymsp[-2].minor.yy331;
+ }
+ yygotominor.yy331 = yymsp[0].minor.yy331;
}
-#line 2132 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2234 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 107:
- case 238:
-#line 342 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy210 = yymsp[-1].minor.yy210;}
-#line 2138 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 102:
+#line 340 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = TK_ALL;}
+#line 2239 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 108:
- case 135:
- case 145:
- case 237:
-#line 343 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy210 = 0;}
-#line 2146 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 105:
+#line 345 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+ yygotominor.yy331 = sqlite3SelectNew(yymsp[-6].minor.yy266,yymsp[-5].minor.yy427,yymsp[-4].minor.yy454,yymsp[-3].minor.yy266,yymsp[-2].minor.yy454,yymsp[-1].minor.yy266,yymsp[-7].minor.yy60,yymsp[0].minor.yy348.pLimit,yymsp[0].minor.yy348.pOffset);
+}
+#line 2246 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 109:
-#line 344 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 248:
+#line 366 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy266 = yymsp[-1].minor.yy266;}
+#line 2252 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
+ case 110:
+ case 137:
+ case 147:
+ case 247:
+#line 367 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy266 = 0;}
+#line 2260 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
+ case 111:
+#line 368 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- yygotominor.yy210 = sqlite3ExprListAppend(yymsp[-2].minor.yy210,yymsp[-1].minor.yy258,yymsp[0].minor.yy98.n?&yymsp[0].minor.yy98:0);
+ yygotominor.yy266 = sqlite3ExprListAppend(yymsp[-2].minor.yy266,yymsp[-1].minor.yy454,yymsp[0].minor.yy406.n?&yymsp[0].minor.yy406:0);
}
-#line 2153 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2267 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 110:
-#line 347 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 112:
+#line 371 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- yygotominor.yy210 = sqlite3ExprListAppend(yymsp[-1].minor.yy210, sqlite3Expr(TK_ALL, 0, 0, 0), 0);
+ yygotominor.yy266 = sqlite3ExprListAppend(yymsp[-1].minor.yy266, sqlite3Expr(TK_ALL, 0, 0, 0), 0);
}
-#line 2160 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2274 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 111:
-#line 350 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 113:
+#line 374 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
Expr *pRight = sqlite3Expr(TK_ALL, 0, 0, 0);
- Expr *pLeft = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy98);
- yygotominor.yy210 = sqlite3ExprListAppend(yymsp[-3].minor.yy210, sqlite3Expr(TK_DOT, pLeft, pRight, 0), 0);
+ Expr *pLeft = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy406);
+ yygotominor.yy266 = sqlite3ExprListAppend(yymsp[-3].minor.yy266, sqlite3Expr(TK_DOT, pLeft, pRight, 0), 0);
}
-#line 2169 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
- break;
- case 114:
-#line 362 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy98.n = 0;}
-#line 2174 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
- break;
- case 115:
-#line 374 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy259 = sqliteMalloc(sizeof(*yygotominor.yy259));}
-#line 2179 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2283 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 116:
-#line 375 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy259 = yymsp[0].minor.yy259;}
-#line 2184 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 386 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy406.n = 0;}
+#line 2288 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 117:
-#line 380 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{
- yygotominor.yy259 = yymsp[-1].minor.yy259;
- if( yygotominor.yy259 && yygotominor.yy259->nSrc>0 ) yygotominor.yy259->a[yygotominor.yy259->nSrc-1].jointype = yymsp[0].minor.yy284;
-}
-#line 2192 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 398 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy427 = sqliteMalloc(sizeof(*yygotominor.yy427));}
+#line 2293 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 118:
-#line 384 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy259 = 0;}
-#line 2197 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 399 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy427 = yymsp[0].minor.yy427;}
+#line 2298 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 119:
-#line 385 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 404 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- yygotominor.yy259 = sqlite3SrcListAppend(yymsp[-5].minor.yy259,&yymsp[-4].minor.yy98,&yymsp[-3].minor.yy98);
- if( yymsp[-2].minor.yy98.n ) sqlite3SrcListAddAlias(yygotominor.yy259,&yymsp[-2].minor.yy98);
- if( yymsp[-1].minor.yy258 ){
- if( yygotominor.yy259 && yygotominor.yy259->nSrc>1 ){ yygotominor.yy259->a[yygotominor.yy259->nSrc-2].pOn = yymsp[-1].minor.yy258; }
- else { sqlite3ExprDelete(yymsp[-1].minor.yy258); }
- }
- if( yymsp[0].minor.yy272 ){
- if( yygotominor.yy259 && yygotominor.yy259->nSrc>1 ){ yygotominor.yy259->a[yygotominor.yy259->nSrc-2].pUsing = yymsp[0].minor.yy272; }
- else { sqlite3IdListDelete(yymsp[0].minor.yy272); }
- }
+ yygotominor.yy427 = yymsp[-1].minor.yy427;
+ if( yygotominor.yy427 && yygotominor.yy427->nSrc>0 ) yygotominor.yy427->a[yygotominor.yy427->nSrc-1].jointype = yymsp[0].minor.yy60;
}
-#line 2213 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2306 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 120:
-#line 398 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 408 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy427 = 0;}
+#line 2311 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
+ case 121:
+#line 409 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- yygotominor.yy259 = sqlite3SrcListAppend(yymsp[-6].minor.yy259,0,0);
- yygotominor.yy259->a[yygotominor.yy259->nSrc-1].pSelect = yymsp[-4].minor.yy107;
- if( yymsp[-2].minor.yy98.n ) sqlite3SrcListAddAlias(yygotominor.yy259,&yymsp[-2].minor.yy98);
- if( yymsp[-1].minor.yy258 ){
- if( yygotominor.yy259 && yygotominor.yy259->nSrc>1 ){ yygotominor.yy259->a[yygotominor.yy259->nSrc-2].pOn = yymsp[-1].minor.yy258; }
- else { sqlite3ExprDelete(yymsp[-1].minor.yy258); }
+ yygotominor.yy427 = sqlite3SrcListAppend(yymsp[-5].minor.yy427,&yymsp[-4].minor.yy406,&yymsp[-3].minor.yy406);
+ if( yymsp[-2].minor.yy406.n ) sqlite3SrcListAddAlias(yygotominor.yy427,&yymsp[-2].minor.yy406);
+ if( yymsp[-1].minor.yy454 ){
+ if( yygotominor.yy427 && yygotominor.yy427->nSrc>1 ){ yygotominor.yy427->a[yygotominor.yy427->nSrc-2].pOn = yymsp[-1].minor.yy454; }
+ else { sqlite3ExprDelete(yymsp[-1].minor.yy454); }
}
if( yymsp[0].minor.yy272 ){
- if( yygotominor.yy259 && yygotominor.yy259->nSrc>1 ){ yygotominor.yy259->a[yygotominor.yy259->nSrc-2].pUsing = yymsp[0].minor.yy272; }
+ if( yygotominor.yy427 && yygotominor.yy427->nSrc>1 ){ yygotominor.yy427->a[yygotominor.yy427->nSrc-2].pUsing = yymsp[0].minor.yy272; }
else { sqlite3IdListDelete(yymsp[0].minor.yy272); }
}
}
-#line 2230 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2327 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 122:
-#line 419 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 423 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- yygotominor.yy107 = sqlite3SelectNew(0,yymsp[0].minor.yy259,0,0,0,0,0,-1,0);
-}
-#line 2237 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ yygotominor.yy427 = sqlite3SrcListAppend(yymsp[-6].minor.yy427,0,0);
+ yygotominor.yy427->a[yygotominor.yy427->nSrc-1].pSelect = yymsp[-4].minor.yy331;
+ if( yymsp[-2].minor.yy406.n ) sqlite3SrcListAddAlias(yygotominor.yy427,&yymsp[-2].minor.yy406);
+ if( yymsp[-1].minor.yy454 ){
+ if( yygotominor.yy427 && yygotominor.yy427->nSrc>1 ){ yygotominor.yy427->a[yygotominor.yy427->nSrc-2].pOn = yymsp[-1].minor.yy454; }
+ else { sqlite3ExprDelete(yymsp[-1].minor.yy454); }
+ }
+ if( yymsp[0].minor.yy272 ){
+ if( yygotominor.yy427 && yygotominor.yy427->nSrc>1 ){ yygotominor.yy427->a[yygotominor.yy427->nSrc-2].pUsing = yymsp[0].minor.yy272; }
+ else { sqlite3IdListDelete(yymsp[0].minor.yy272); }
+ }
+ }
+#line 2344 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 123:
-#line 424 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy98.z=0; yygotominor.yy98.n=0;}
-#line 2242 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 124:
+#line 444 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+ yygotominor.yy331 = sqlite3SelectNew(0,yymsp[0].minor.yy427,0,0,0,0,0,0,0);
+ }
+#line 2351 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 125:
-#line 429 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy259 = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy98,&yymsp[0].minor.yy98);}
-#line 2247 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 450 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy406.z=0; yygotominor.yy406.n=0;}
+#line 2356 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 126:
case 127:
-#line 433 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = JT_INNER; }
-#line 2253 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 455 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy427 = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy406,&yymsp[0].minor.yy406);}
+#line 2361 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 128:
-#line 435 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
-#line 2258 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
- break;
case 129:
-#line 436 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy98,0); }
-#line 2263 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 459 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = JT_INNER; }
+#line 2367 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 130:
-#line 438 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy98,&yymsp[-1].minor.yy98); }
-#line 2268 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 461 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
+#line 2372 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 131:
- case 139:
- case 148:
- case 155:
- case 226:
- case 228:
- case 232:
-#line 442 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy258 = yymsp[0].minor.yy258;}
-#line 2279 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 462 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy406,0); }
+#line 2377 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 132:
- case 147:
- case 154:
- case 227:
- case 229:
- case 233:
-#line 443 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy258 = 0;}
-#line 2289 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 464 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy406,&yymsp[-1].minor.yy406); }
+#line 2382 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 133:
- case 166:
-#line 447 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy272 = yymsp[-1].minor.yy272;}
-#line 2295 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 141:
+ case 150:
+ case 157:
+ case 171:
+ case 211:
+ case 236:
+ case 238:
+ case 242:
+#line 468 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy454 = yymsp[0].minor.yy454;}
+#line 2395 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 134:
- case 165:
-#line 448 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy272 = 0;}
-#line 2301 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 149:
+ case 156:
+ case 212:
+ case 237:
+ case 239:
+ case 243:
+#line 469 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy454 = 0;}
+#line 2406 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
+ case 135:
+ case 168:
+#line 473 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy272 = yymsp[-1].minor.yy272;}
+#line 2412 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 136:
- case 146:
-#line 459 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy210 = yymsp[0].minor.yy210;}
-#line 2307 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 167:
+#line 474 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy272 = 0;}
+#line 2418 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 137:
-#line 460 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 138:
+ case 148:
+#line 485 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy266 = yymsp[0].minor.yy266;}
+#line 2424 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
+ case 139:
+#line 486 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- yygotominor.yy210 = sqlite3ExprListAppend(yymsp[-4].minor.yy210,yymsp[-2].minor.yy258,yymsp[-1].minor.yy98.n>0?&yymsp[-1].minor.yy98:0);
- if( yygotominor.yy210 ) yygotominor.yy210->a[yygotominor.yy210->nExpr-1].sortOrder = yymsp[0].minor.yy284;
+ yygotominor.yy266 = sqlite3ExprListAppend(yymsp[-4].minor.yy266,yymsp[-2].minor.yy454,yymsp[-1].minor.yy406.n>0?&yymsp[-1].minor.yy406:0);
+ if( yygotominor.yy266 ) yygotominor.yy266->a[yygotominor.yy266->nExpr-1].sortOrder = yymsp[0].minor.yy60;
}
-#line 2315 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2432 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 138:
-#line 464 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 140:
+#line 490 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- yygotominor.yy210 = sqlite3ExprListAppend(0,yymsp[-2].minor.yy258,yymsp[-1].minor.yy98.n>0?&yymsp[-1].minor.yy98:0);
- if( yygotominor.yy210 && yygotominor.yy210->a ) yygotominor.yy210->a[0].sortOrder = yymsp[0].minor.yy284;
+ yygotominor.yy266 = sqlite3ExprListAppend(0,yymsp[-2].minor.yy454,yymsp[-1].minor.yy406.n>0?&yymsp[-1].minor.yy406:0);
+ if( yygotominor.yy266 && yygotominor.yy266->a ) yygotominor.yy266->a[0].sortOrder = yymsp[0].minor.yy60;
}
-#line 2323 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2440 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 140:
case 142:
-#line 473 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = SQLITE_SO_ASC;}
-#line 2329 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
- break;
- case 141:
-#line 474 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = SQLITE_SO_DESC;}
-#line 2334 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 144:
+#line 499 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = SQLITE_SO_ASC;}
+#line 2446 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 143:
-#line 476 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy98.z = 0; yygotominor.yy98.n = 0;}
-#line 2339 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 500 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = SQLITE_SO_DESC;}
+#line 2451 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 149:
-#line 490 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy404.limit = -1; yygotominor.yy404.offset = 0;}
-#line 2344 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
- break;
- case 150:
-#line 491 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy404.limit = yymsp[0].minor.yy284; yygotominor.yy404.offset = 0;}
-#line 2349 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 145:
+#line 502 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy406.z = 0; yygotominor.yy406.n = 0;}
+#line 2456 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 151:
-#line 493 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy404.limit = yymsp[-2].minor.yy284; yygotominor.yy404.offset = yymsp[0].minor.yy284;}
-#line 2354 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 520 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy348.pLimit = 0; yygotominor.yy348.pOffset = 0;}
+#line 2461 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 152:
-#line 495 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy404.limit = yymsp[0].minor.yy284; yygotominor.yy404.offset = yymsp[-2].minor.yy284;}
-#line 2359 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 521 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy348.pLimit = yymsp[0].minor.yy454; yygotominor.yy348.pOffset = 0;}
+#line 2466 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 153:
-#line 499 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy259,yymsp[0].minor.yy258);}
-#line 2364 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 523 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy348.pLimit = yymsp[-2].minor.yy454; yygotominor.yy348.pOffset = yymsp[0].minor.yy454;}
+#line 2471 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 156:
-#line 513 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3Update(pParse,yymsp[-3].minor.yy259,yymsp[-1].minor.yy210,yymsp[0].minor.yy258,yymsp[-4].minor.yy284);}
-#line 2369 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 154:
+#line 525 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy348.pOffset = yymsp[-2].minor.yy454; yygotominor.yy348.pLimit = yymsp[0].minor.yy454;}
+#line 2476 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 157:
-#line 516 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy210 = sqlite3ExprListAppend(yymsp[-4].minor.yy210,yymsp[0].minor.yy258,&yymsp[-2].minor.yy98);}
-#line 2374 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 155:
+#line 529 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy427,yymsp[0].minor.yy454);}
+#line 2481 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 158:
-#line 517 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy210 = sqlite3ExprListAppend(0,yymsp[0].minor.yy258,&yymsp[-2].minor.yy98);}
-#line 2379 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 543 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3Update(pParse,yymsp[-3].minor.yy427,yymsp[-1].minor.yy266,yymsp[0].minor.yy454,yymsp[-4].minor.yy60);}
+#line 2486 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 159:
-#line 523 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3Insert(pParse, yymsp[-5].minor.yy259, yymsp[-1].minor.yy210, 0, yymsp[-4].minor.yy272, yymsp[-7].minor.yy284);}
-#line 2384 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 546 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy266 = sqlite3ExprListAppend(yymsp[-4].minor.yy266,yymsp[0].minor.yy454,&yymsp[-2].minor.yy406);}
+#line 2491 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 160:
-#line 525 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3Insert(pParse, yymsp[-2].minor.yy259, 0, yymsp[0].minor.yy107, yymsp[-1].minor.yy272, yymsp[-4].minor.yy284);}
-#line 2389 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 547 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy266 = sqlite3ExprListAppend(0,yymsp[0].minor.yy454,&yymsp[-2].minor.yy406);}
+#line 2496 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 163:
- case 230:
-#line 535 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy210 = sqlite3ExprListAppend(yymsp[-2].minor.yy210,yymsp[0].minor.yy258,0);}
-#line 2395 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 161:
+#line 553 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3Insert(pParse, yymsp[-5].minor.yy427, yymsp[-1].minor.yy266, 0, yymsp[-4].minor.yy272, yymsp[-7].minor.yy60);}
+#line 2501 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 164:
- case 231:
-#line 536 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy210 = sqlite3ExprListAppend(0,yymsp[0].minor.yy258,0);}
-#line 2401 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 162:
+#line 555 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3Insert(pParse, yymsp[-2].minor.yy427, 0, yymsp[0].minor.yy331, yymsp[-1].minor.yy272, yymsp[-4].minor.yy60);}
+#line 2506 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 167:
-#line 545 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy272 = sqlite3IdListAppend(yymsp[-2].minor.yy272,&yymsp[0].minor.yy98);}
-#line 2406 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 165:
+ case 240:
+#line 565 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy266 = sqlite3ExprListAppend(yymsp[-2].minor.yy266,yymsp[0].minor.yy454,0);}
+#line 2512 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 168:
-#line 546 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy272 = sqlite3IdListAppend(0,&yymsp[0].minor.yy98);}
-#line 2411 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 166:
+ case 241:
+#line 566 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy266 = sqlite3ExprListAppend(0,yymsp[0].minor.yy454,0);}
+#line 2518 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 169:
-#line 554 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy258 = yymsp[-1].minor.yy258; sqlite3ExprSpan(yygotominor.yy258,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); }
-#line 2416 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 575 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy272 = sqlite3IdListAppend(yymsp[-2].minor.yy272,&yymsp[0].minor.yy406);}
+#line 2523 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 170:
- case 175:
- case 176:
- case 177:
- case 178:
-#line 555 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy258 = sqlite3Expr(yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);}
-#line 2425 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 576 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy272 = sqlite3IdListAppend(0,&yymsp[0].minor.yy406);}
+#line 2528 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 171:
case 172:
-#line 556 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy258 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy0);}
-#line 2431 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 587 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy454 = yymsp[-1].minor.yy454; sqlite3ExprSpan(yygotominor.yy454,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); }
+#line 2533 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 173:
-#line 558 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 178:
+ case 179:
+ case 180:
+ case 181:
+#line 588 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy454 = sqlite3Expr(yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);}
+#line 2542 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
+ case 174:
+ case 175:
+#line 589 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy454 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy0);}
+#line 2548 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
+ case 176:
+#line 591 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy98);
- Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy98);
- yygotominor.yy258 = sqlite3Expr(TK_DOT, temp1, temp2, 0);
+ Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy406);
+ Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy406);
+ yygotominor.yy454 = sqlite3Expr(TK_DOT, temp1, temp2, 0);
}
-#line 2440 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2557 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 174:
-#line 563 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 177:
+#line 596 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-4].minor.yy98);
- Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy98);
- Expr *temp3 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy98);
+ Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-4].minor.yy406);
+ Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy406);
+ Expr *temp3 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy406);
Expr *temp4 = sqlite3Expr(TK_DOT, temp2, temp3, 0);
- yygotominor.yy258 = sqlite3Expr(TK_DOT, temp1, temp4, 0);
+ yygotominor.yy454 = sqlite3Expr(TK_DOT, temp1, temp4, 0);
}
-#line 2451 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2568 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 179:
-#line 574 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 182:
+#line 607 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy454 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);}
+#line 2573 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
+ case 183:
+#line 608 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
Token *pToken = &yymsp[0].minor.yy0;
- Expr *pExpr = yygotominor.yy258 = sqlite3Expr(TK_VARIABLE, 0, 0, pToken);
+ Expr *pExpr = yygotominor.yy454 = sqlite3Expr(TK_VARIABLE, 0, 0, pToken);
sqlite3ExprAssignVarNumber(pParse, pExpr);
}
-#line 2460 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2582 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 180:
-#line 579 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 184:
+#line 613 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- yygotominor.yy258 = sqlite3ExprFunction(yymsp[-1].minor.yy210, &yymsp[-3].minor.yy0);
- sqlite3ExprSpan(yygotominor.yy258,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
+ yygotominor.yy454 = sqlite3ExprFunction(yymsp[-1].minor.yy266, &yymsp[-3].minor.yy0);
+ sqlite3ExprSpan(yygotominor.yy454,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
}
-#line 2468 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2590 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 181:
-#line 583 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 185:
+#line 617 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- yygotominor.yy258 = sqlite3ExprFunction(0, &yymsp[-3].minor.yy0);
- sqlite3ExprSpan(yygotominor.yy258,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
+ yygotominor.yy454 = sqlite3ExprFunction(0, &yymsp[-3].minor.yy0);
+ sqlite3ExprSpan(yygotominor.yy454,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
}
-#line 2476 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2598 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 182:
- case 183:
- case 184:
- case 185:
case 186:
case 187:
case 188:
+#line 621 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy454 = sqlite3Expr(yymsp[0].major,0,0,0);}
+#line 2605 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
case 189:
case 190:
case 191:
@@ -2491,435 +2613,473 @@ static void yy_reduce(
case 197:
case 198:
case 199:
-#line 587 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy258 = sqlite3Expr(yymsp[-1].major, yymsp[-2].minor.yy258, yymsp[0].minor.yy258, 0);}
-#line 2498 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
- break;
case 200:
-#line 606 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy342.opcode = TK_LIKE; yygotominor.yy342.not = 0;}
-#line 2503 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
- break;
case 201:
-#line 607 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy342.opcode = TK_GLOB; yygotominor.yy342.not = 0;}
-#line 2508 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
- break;
case 202:
-#line 608 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy342.opcode = TK_LIKE; yygotominor.yy342.not = 1;}
-#line 2513 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
- break;
case 203:
-#line 609 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy342.opcode = TK_GLOB; yygotominor.yy342.not = 1;}
-#line 2518 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
- break;
case 204:
-#line 610 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{
- ExprList *pList = sqlite3ExprListAppend(0, yymsp[0].minor.yy258, 0);
- pList = sqlite3ExprListAppend(pList, yymsp[-2].minor.yy258, 0);
- yygotominor.yy258 = sqlite3ExprFunction(pList, 0);
- if( yygotominor.yy258 ) yygotominor.yy258->op = yymsp[-1].minor.yy342.opcode;
- if( yymsp[-1].minor.yy342.not ) yygotominor.yy258 = sqlite3Expr(TK_NOT, yygotominor.yy258, 0, 0);
- sqlite3ExprSpan(yygotominor.yy258, &yymsp[-2].minor.yy258->span, &yymsp[0].minor.yy258->span);
-}
-#line 2530 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
- break;
case 205:
-#line 618 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{
- yygotominor.yy258 = sqlite3Expr(TK_ISNULL, yymsp[-1].minor.yy258, 0, 0);
- sqlite3ExprSpan(yygotominor.yy258,&yymsp[-1].minor.yy258->span,&yymsp[0].minor.yy0);
-}
-#line 2538 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
- break;
case 206:
-#line 622 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{
- yygotominor.yy258 = sqlite3Expr(TK_ISNULL, yymsp[-2].minor.yy258, 0, 0);
- sqlite3ExprSpan(yygotominor.yy258,&yymsp[-2].minor.yy258->span,&yymsp[0].minor.yy0);
-}
-#line 2546 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 624 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy454 = sqlite3Expr(yymsp[-1].major, yymsp[-2].minor.yy454, yymsp[0].minor.yy454, 0);}
+#line 2627 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 207:
-#line 626 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{
- yygotominor.yy258 = sqlite3Expr(TK_NOTNULL, yymsp[-1].minor.yy258, 0, 0);
- sqlite3ExprSpan(yygotominor.yy258,&yymsp[-1].minor.yy258->span,&yymsp[0].minor.yy0);
-}
-#line 2554 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 643 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy258.opcode = TK_LIKE; yygotominor.yy258.not = 0;}
+#line 2632 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 208:
-#line 630 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{
- yygotominor.yy258 = sqlite3Expr(TK_NOTNULL, yymsp[-2].minor.yy258, 0, 0);
- sqlite3ExprSpan(yygotominor.yy258,&yymsp[-2].minor.yy258->span,&yymsp[0].minor.yy0);
-}
-#line 2562 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 644 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy258.opcode = TK_GLOB; yygotominor.yy258.not = 0;}
+#line 2637 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 209:
-#line 634 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{
- yygotominor.yy258 = sqlite3Expr(TK_NOTNULL, yymsp[-3].minor.yy258, 0, 0);
- sqlite3ExprSpan(yygotominor.yy258,&yymsp[-3].minor.yy258->span,&yymsp[0].minor.yy0);
-}
-#line 2570 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 645 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy258.opcode = TK_LIKE; yygotominor.yy258.not = 1;}
+#line 2642 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 210:
- case 211:
-#line 638 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 646 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy258.opcode = TK_GLOB; yygotominor.yy258.not = 1;}
+#line 2647 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
+ case 213:
+#line 650 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- yygotominor.yy258 = sqlite3Expr(yymsp[-1].major, yymsp[0].minor.yy258, 0, 0);
- sqlite3ExprSpan(yygotominor.yy258,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy258->span);
+ ExprList *pList = sqlite3ExprListAppend(0, yymsp[-1].minor.yy454, 0);
+ pList = sqlite3ExprListAppend(pList, yymsp[-3].minor.yy454, 0);
+ if( yymsp[0].minor.yy454 ){
+ pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy454, 0);
+ }
+ yygotominor.yy454 = sqlite3ExprFunction(pList, 0);
+ if( yygotominor.yy454 ) yygotominor.yy454->op = yymsp[-2].minor.yy258.opcode;
+ if( yymsp[-2].minor.yy258.not ) yygotominor.yy454 = sqlite3Expr(TK_NOT, yygotominor.yy454, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy454, &yymsp[-3].minor.yy454->span, &yymsp[-1].minor.yy454->span);
}
-#line 2579 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2662 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 212:
-#line 646 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 214:
+#line 662 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- yygotominor.yy258 = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy258, 0, 0);
- sqlite3ExprSpan(yygotominor.yy258,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy258->span);
+ yygotominor.yy454 = sqlite3Expr(TK_ISNULL, yymsp[-1].minor.yy454, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy454,&yymsp[-1].minor.yy454->span,&yymsp[0].minor.yy0);
}
-#line 2587 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2670 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 213:
-#line 650 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 215:
+#line 666 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- yygotominor.yy258 = sqlite3Expr(TK_UPLUS, yymsp[0].minor.yy258, 0, 0);
- sqlite3ExprSpan(yygotominor.yy258,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy258->span);
+ yygotominor.yy454 = sqlite3Expr(TK_ISNULL, yymsp[-2].minor.yy454, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy454,&yymsp[-2].minor.yy454->span,&yymsp[0].minor.yy0);
}
-#line 2595 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2678 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 214:
-#line 654 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 216:
+#line 670 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- yygotominor.yy258 = sqlite3Expr(TK_SELECT, 0, 0, 0);
- if( yygotominor.yy258 ) yygotominor.yy258->pSelect = yymsp[-1].minor.yy107;
- sqlite3ExprSpan(yygotominor.yy258,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
+ yygotominor.yy454 = sqlite3Expr(TK_NOTNULL, yymsp[-1].minor.yy454, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy454,&yymsp[-1].minor.yy454->span,&yymsp[0].minor.yy0);
}
-#line 2604 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2686 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 217:
-#line 662 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 674 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+ yygotominor.yy454 = sqlite3Expr(TK_NOTNULL, yymsp[-2].minor.yy454, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy454,&yymsp[-2].minor.yy454->span,&yymsp[0].minor.yy0);
+}
+#line 2694 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
+ case 218:
+#line 678 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- ExprList *pList = sqlite3ExprListAppend(0, yymsp[-2].minor.yy258, 0);
- pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy258, 0);
- yygotominor.yy258 = sqlite3Expr(TK_BETWEEN, yymsp[-4].minor.yy258, 0, 0);
- if( yygotominor.yy258 ) yygotominor.yy258->pList = pList;
- if( yymsp[-3].minor.yy284 ) yygotominor.yy258 = sqlite3Expr(TK_NOT, yygotominor.yy258, 0, 0);
- sqlite3ExprSpan(yygotominor.yy258,&yymsp[-4].minor.yy258->span,&yymsp[0].minor.yy258->span);
+ yygotominor.yy454 = sqlite3Expr(TK_NOTNULL, yymsp[-3].minor.yy454, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy454,&yymsp[-3].minor.yy454->span,&yymsp[0].minor.yy0);
}
-#line 2616 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2702 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
+ case 219:
case 220:
-#line 673 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 682 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- yygotominor.yy258 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy258, 0, 0);
- if( yygotominor.yy258 ) yygotominor.yy258->pList = yymsp[-1].minor.yy210;
- if( yymsp[-3].minor.yy284 ) yygotominor.yy258 = sqlite3Expr(TK_NOT, yygotominor.yy258, 0, 0);
- sqlite3ExprSpan(yygotominor.yy258,&yymsp[-4].minor.yy258->span,&yymsp[0].minor.yy0);
+ yygotominor.yy454 = sqlite3Expr(yymsp[-1].major, yymsp[0].minor.yy454, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy454,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy454->span);
}
-#line 2626 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2711 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 221:
-#line 679 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 690 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- yygotominor.yy258 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy258, 0, 0);
- if( yygotominor.yy258 ) yygotominor.yy258->pSelect = yymsp[-1].minor.yy107;
- if( yymsp[-3].minor.yy284 ) yygotominor.yy258 = sqlite3Expr(TK_NOT, yygotominor.yy258, 0, 0);
- sqlite3ExprSpan(yygotominor.yy258,&yymsp[-4].minor.yy258->span,&yymsp[0].minor.yy0);
+ yygotominor.yy454 = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy454, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy454,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy454->span);
}
-#line 2636 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2719 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 222:
-#line 685 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 694 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- SrcList *pSrc = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy98,&yymsp[0].minor.yy98);
- yygotominor.yy258 = sqlite3Expr(TK_IN, yymsp[-3].minor.yy258, 0, 0);
- if( yygotominor.yy258 ) yygotominor.yy258->pSelect = sqlite3SelectNew(0,pSrc,0,0,0,0,0,-1,0);
- if( yymsp[-2].minor.yy284 ) yygotominor.yy258 = sqlite3Expr(TK_NOT, yygotominor.yy258, 0, 0);
- sqlite3ExprSpan(yygotominor.yy258,&yymsp[-3].minor.yy258->span,yymsp[0].minor.yy98.z?&yymsp[0].minor.yy98:&yymsp[-1].minor.yy98);
+ yygotominor.yy454 = sqlite3Expr(TK_UPLUS, yymsp[0].minor.yy454, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy454,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy454->span);
}
-#line 2647 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2727 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 223:
-#line 695 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 225:
+#line 701 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- yygotominor.yy258 = sqlite3Expr(TK_CASE, yymsp[-3].minor.yy258, yymsp[-1].minor.yy258, 0);
- if( yygotominor.yy258 ) yygotominor.yy258->pList = yymsp[-2].minor.yy210;
- sqlite3ExprSpan(yygotominor.yy258, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0);
+ ExprList *pList = sqlite3ExprListAppend(0, yymsp[-2].minor.yy454, 0);
+ pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy454, 0);
+ yygotominor.yy454 = sqlite3Expr(TK_BETWEEN, yymsp[-4].minor.yy454, 0, 0);
+ if( yygotominor.yy454 ) yygotominor.yy454->pList = pList;
+ if( yymsp[-3].minor.yy60 ) yygotominor.yy454 = sqlite3Expr(TK_NOT, yygotominor.yy454, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy454,&yymsp[-4].minor.yy454->span,&yymsp[0].minor.yy454->span);
}
-#line 2656 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2739 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 224:
-#line 702 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 228:
+#line 713 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- yygotominor.yy210 = sqlite3ExprListAppend(yymsp[-4].minor.yy210, yymsp[-2].minor.yy258, 0);
- yygotominor.yy210 = sqlite3ExprListAppend(yygotominor.yy210, yymsp[0].minor.yy258, 0);
-}
-#line 2664 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ yygotominor.yy454 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy454, 0, 0);
+ if( yygotominor.yy454 ) yygotominor.yy454->pList = yymsp[-1].minor.yy266;
+ if( yymsp[-3].minor.yy60 ) yygotominor.yy454 = sqlite3Expr(TK_NOT, yygotominor.yy454, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy454,&yymsp[-4].minor.yy454->span,&yymsp[0].minor.yy0);
+ }
+#line 2749 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 225:
-#line 706 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 229:
+#line 719 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+ yygotominor.yy454 = sqlite3Expr(TK_SELECT, 0, 0, 0);
+ if( yygotominor.yy454 ) yygotominor.yy454->pSelect = yymsp[-1].minor.yy331;
+ sqlite3ExprSpan(yygotominor.yy454,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
+ }
+#line 2758 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
+ case 230:
+#line 724 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+ yygotominor.yy454 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy454, 0, 0);
+ if( yygotominor.yy454 ) yygotominor.yy454->pSelect = yymsp[-1].minor.yy331;
+ if( yymsp[-3].minor.yy60 ) yygotominor.yy454 = sqlite3Expr(TK_NOT, yygotominor.yy454, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy454,&yymsp[-4].minor.yy454->span,&yymsp[0].minor.yy0);
+ }
+#line 2768 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
+ case 231:
+#line 730 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- yygotominor.yy210 = sqlite3ExprListAppend(0, yymsp[-2].minor.yy258, 0);
- yygotominor.yy210 = sqlite3ExprListAppend(yygotominor.yy210, yymsp[0].minor.yy258, 0);
+ SrcList *pSrc = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy406,&yymsp[0].minor.yy406);
+ yygotominor.yy454 = sqlite3Expr(TK_IN, yymsp[-3].minor.yy454, 0, 0);
+ if( yygotominor.yy454 ) yygotominor.yy454->pSelect = sqlite3SelectNew(0,pSrc,0,0,0,0,0,0,0);
+ if( yymsp[-2].minor.yy60 ) yygotominor.yy454 = sqlite3Expr(TK_NOT, yygotominor.yy454, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy454,&yymsp[-3].minor.yy454->span,yymsp[0].minor.yy406.z?&yymsp[0].minor.yy406:&yymsp[-1].minor.yy406);
+ }
+#line 2779 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
+ case 232:
+#line 737 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+ Expr *p = yygotominor.yy454 = sqlite3Expr(TK_EXISTS, 0, 0, 0);
+ if( p ){
+ p->pSelect = yymsp[-1].minor.yy331;
+ sqlite3ExprSpan(p,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
+ }
+ }
+#line 2790 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
+ case 233:
+#line 747 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+ yygotominor.yy454 = sqlite3Expr(TK_CASE, yymsp[-3].minor.yy454, yymsp[-1].minor.yy454, 0);
+ if( yygotominor.yy454 ) yygotominor.yy454->pList = yymsp[-2].minor.yy266;
+ sqlite3ExprSpan(yygotominor.yy454, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0);
}
-#line 2672 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2799 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 234:
-#line 731 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 754 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- if( yymsp[-9].minor.yy284!=OE_None ) yymsp[-9].minor.yy284 = yymsp[0].minor.yy284;
- if( yymsp[-9].minor.yy284==OE_Default) yymsp[-9].minor.yy284 = OE_Abort;
- sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy98, &yymsp[-6].minor.yy98, yymsp[-4].minor.yy259, yymsp[-2].minor.yy210, yymsp[-9].minor.yy284, &yymsp[-10].minor.yy0, &yymsp[-1].minor.yy0);
+ yygotominor.yy266 = sqlite3ExprListAppend(yymsp[-4].minor.yy266, yymsp[-2].minor.yy454, 0);
+ yygotominor.yy266 = sqlite3ExprListAppend(yygotominor.yy266, yymsp[0].minor.yy454, 0);
}
-#line 2681 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2807 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
case 235:
- case 282:
-#line 738 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = OE_Abort;}
-#line 2687 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 758 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+ yygotominor.yy266 = sqlite3ExprListAppend(0, yymsp[-2].minor.yy454, 0);
+ yygotominor.yy266 = sqlite3ExprListAppend(yygotominor.yy266, yymsp[0].minor.yy454, 0);
+}
+#line 2815 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 236:
-#line 739 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = OE_None;}
-#line 2692 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 244:
+#line 783 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+ if( yymsp[-9].minor.yy60!=OE_None ) yymsp[-9].minor.yy60 = yymsp[0].minor.yy60;
+ if( yymsp[-9].minor.yy60==OE_Default) yymsp[-9].minor.yy60 = OE_Abort;
+ sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy406, &yymsp[-6].minor.yy406, sqlite3SrcListAppend(0,&yymsp[-4].minor.yy406,0),yymsp[-2].minor.yy266,yymsp[-9].minor.yy60, &yymsp[-10].minor.yy0, &yymsp[-1].minor.yy0);
+}
+#line 2824 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 239:
-#line 749 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 245:
+ case 292:
+#line 790 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = OE_Abort;}
+#line 2830 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
+ case 246:
+#line 791 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = OE_None;}
+#line 2835 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
+ case 249:
+#line 801 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
Expr *p = 0;
- if( yymsp[-1].minor.yy98.n>0 ){
+ if( yymsp[-1].minor.yy406.n>0 ){
p = sqlite3Expr(TK_COLUMN, 0, 0, 0);
- if( p ) p->pColl = sqlite3LocateCollSeq(pParse, yymsp[-1].minor.yy98.z, yymsp[-1].minor.yy98.n);
+ if( p ) p->pColl = sqlite3LocateCollSeq(pParse, yymsp[-1].minor.yy406.z, yymsp[-1].minor.yy406.n);
}
- yygotominor.yy210 = sqlite3ExprListAppend(yymsp[-4].minor.yy210, p, &yymsp[-2].minor.yy98);
+ yygotominor.yy266 = sqlite3ExprListAppend(yymsp[-4].minor.yy266, p, &yymsp[-2].minor.yy406);
}
-#line 2704 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2847 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 240:
-#line 757 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 250:
+#line 809 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
Expr *p = 0;
- if( yymsp[-1].minor.yy98.n>0 ){
+ if( yymsp[-1].minor.yy406.n>0 ){
p = sqlite3Expr(TK_COLUMN, 0, 0, 0);
- if( p ) p->pColl = sqlite3LocateCollSeq(pParse, yymsp[-1].minor.yy98.z, yymsp[-1].minor.yy98.n);
+ if( p ) p->pColl = sqlite3LocateCollSeq(pParse, yymsp[-1].minor.yy406.z, yymsp[-1].minor.yy406.n);
}
- yygotominor.yy210 = sqlite3ExprListAppend(0, p, &yymsp[-2].minor.yy98);
+ yygotominor.yy266 = sqlite3ExprListAppend(0, p, &yymsp[-2].minor.yy406);
}
-#line 2716 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2859 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 242:
-#line 770 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3DropIndex(pParse, yymsp[0].minor.yy259);}
-#line 2721 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 252:
+#line 822 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3DropIndex(pParse, yymsp[0].minor.yy427);}
+#line 2864 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 243:
- case 244:
-#line 774 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 253:
+ case 254:
+#line 826 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{sqlite3Vacuum(pParse,0);}
-#line 2727 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2870 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 245:
- case 247:
-#line 779 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3Pragma(pParse,&yymsp[-3].minor.yy98,&yymsp[-2].minor.yy98,&yymsp[0].minor.yy98,0);}
-#line 2733 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 255:
+ case 257:
+#line 832 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3Pragma(pParse,&yymsp[-3].minor.yy406,&yymsp[-2].minor.yy406,&yymsp[0].minor.yy406,0);}
+#line 2876 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 246:
-#line 780 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3Pragma(pParse,&yymsp[-3].minor.yy98,&yymsp[-2].minor.yy98,&yymsp[0].minor.yy0,0);}
-#line 2738 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 256:
+#line 833 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3Pragma(pParse,&yymsp[-3].minor.yy406,&yymsp[-2].minor.yy406,&yymsp[0].minor.yy0,0);}
+#line 2881 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 248:
-#line 782 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 258:
+#line 835 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- sqlite3Pragma(pParse,&yymsp[-3].minor.yy98,&yymsp[-2].minor.yy98,&yymsp[0].minor.yy98,1);
+ sqlite3Pragma(pParse,&yymsp[-3].minor.yy406,&yymsp[-2].minor.yy406,&yymsp[0].minor.yy406,1);
}
-#line 2745 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2888 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 249:
-#line 785 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3Pragma(pParse,&yymsp[-4].minor.yy98,&yymsp[-3].minor.yy98,&yymsp[-1].minor.yy98,0);}
-#line 2750 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 259:
+#line 838 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3Pragma(pParse,&yymsp[-4].minor.yy406,&yymsp[-3].minor.yy406,&yymsp[-1].minor.yy406,0);}
+#line 2893 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 250:
-#line 786 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{sqlite3Pragma(pParse,&yymsp[-1].minor.yy98,&yymsp[0].minor.yy98,0,0);}
-#line 2755 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 260:
+#line 839 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3Pragma(pParse,&yymsp[-1].minor.yy406,&yymsp[0].minor.yy406,0,0);}
+#line 2898 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 257:
-#line 796 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 267:
+#line 852 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
Token all;
- all.z = yymsp[-3].minor.yy98.z;
- all.n = (yymsp[0].minor.yy0.z - yymsp[-3].minor.yy98.z) + yymsp[0].minor.yy0.n;
- sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy91, &all);
+ all.z = yymsp[-3].minor.yy406.z;
+ all.n = (yymsp[0].minor.yy0.z - yymsp[-3].minor.yy406.z) + yymsp[0].minor.yy0.n;
+ sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy455, &all);
}
-#line 2765 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2908 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 258:
-#line 805 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 268:
+#line 861 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy98, &yymsp[-6].minor.yy98, yymsp[-5].minor.yy284, yymsp[-4].minor.yy146.a, yymsp[-4].minor.yy146.b, yymsp[-2].minor.yy259, yymsp[-1].minor.yy284, yymsp[0].minor.yy258, yymsp[-9].minor.yy284);
- yygotominor.yy98 = (yymsp[-6].minor.yy98.n==0?yymsp[-7].minor.yy98:yymsp[-6].minor.yy98);
+ sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy406, &yymsp[-6].minor.yy406, yymsp[-5].minor.yy60, yymsp[-4].minor.yy62.a, yymsp[-4].minor.yy62.b, yymsp[-2].minor.yy427, yymsp[-1].minor.yy60, yymsp[0].minor.yy454, yymsp[-9].minor.yy60);
+ yygotominor.yy406 = (yymsp[-6].minor.yy406.n==0?yymsp[-7].minor.yy406:yymsp[-6].minor.yy406);
}
-#line 2773 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2916 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 259:
- case 262:
-#line 811 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = TK_BEFORE; }
-#line 2779 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 269:
+ case 272:
+#line 867 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = TK_BEFORE; }
+#line 2922 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 260:
-#line 812 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = TK_AFTER; }
-#line 2784 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 270:
+#line 868 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = TK_AFTER; }
+#line 2927 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 261:
-#line 813 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = TK_INSTEAD;}
-#line 2789 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 271:
+#line 869 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = TK_INSTEAD;}
+#line 2932 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 263:
- case 264:
- case 265:
-#line 818 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy146.a = yymsp[0].major; yygotominor.yy146.b = 0;}
-#line 2796 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 273:
+ case 274:
+ case 275:
+#line 874 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy62.a = yymsp[0].major; yygotominor.yy62.b = 0;}
+#line 2939 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 266:
-#line 821 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy146.a = TK_UPDATE; yygotominor.yy146.b = yymsp[0].minor.yy272;}
-#line 2801 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 276:
+#line 877 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy62.a = TK_UPDATE; yygotominor.yy62.b = yymsp[0].minor.yy272;}
+#line 2944 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 267:
- case 268:
-#line 824 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = TK_ROW; }
-#line 2807 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 277:
+ case 278:
+#line 880 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = TK_ROW; }
+#line 2950 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 269:
-#line 826 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy284 = TK_STATEMENT; }
-#line 2812 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 279:
+#line 882 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy60 = TK_STATEMENT; }
+#line 2955 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 270:
-#line 829 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy258 = 0; }
-#line 2817 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 280:
+#line 885 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy454 = 0; }
+#line 2960 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 271:
-#line 830 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy258 = yymsp[0].minor.yy258; }
-#line 2822 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 281:
+#line 886 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy454 = yymsp[0].minor.yy454; }
+#line 2965 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 272:
-#line 834 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 282:
+#line 890 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- yymsp[-2].minor.yy91->pNext = yymsp[0].minor.yy91;
- yygotominor.yy91 = yymsp[-2].minor.yy91;
+ yymsp[-2].minor.yy455->pNext = yymsp[0].minor.yy455;
+ yygotominor.yy455 = yymsp[-2].minor.yy455;
}
-#line 2830 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 2973 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 273:
-#line 838 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy91 = 0; }
-#line 2835 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 283:
+#line 894 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy455 = 0; }
+#line 2978 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 274:
-#line 844 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy91 = sqlite3TriggerUpdateStep(&yymsp[-3].minor.yy98, yymsp[-1].minor.yy210, yymsp[0].minor.yy258, yymsp[-4].minor.yy284); }
-#line 2840 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 284:
+#line 900 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy455 = sqlite3TriggerUpdateStep(&yymsp[-3].minor.yy406, yymsp[-1].minor.yy266, yymsp[0].minor.yy454, yymsp[-4].minor.yy60); }
+#line 2983 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 275:
-#line 849 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy91 = sqlite3TriggerInsertStep(&yymsp[-5].minor.yy98, yymsp[-4].minor.yy272, yymsp[-1].minor.yy210, 0, yymsp[-7].minor.yy284);}
-#line 2845 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 285:
+#line 905 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy455 = sqlite3TriggerInsertStep(&yymsp[-5].minor.yy406, yymsp[-4].minor.yy272, yymsp[-1].minor.yy266, 0, yymsp[-7].minor.yy60);}
+#line 2988 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 276:
-#line 852 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy91 = sqlite3TriggerInsertStep(&yymsp[-2].minor.yy98, yymsp[-1].minor.yy272, 0, yymsp[0].minor.yy107, yymsp[-4].minor.yy284);}
-#line 2850 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 286:
+#line 908 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy455 = sqlite3TriggerInsertStep(&yymsp[-2].minor.yy406, yymsp[-1].minor.yy272, 0, yymsp[0].minor.yy331, yymsp[-4].minor.yy60);}
+#line 2993 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 277:
-#line 856 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy91 = sqlite3TriggerDeleteStep(&yymsp[-1].minor.yy98, yymsp[0].minor.yy258);}
-#line 2855 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 287:
+#line 912 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy455 = sqlite3TriggerDeleteStep(&yymsp[-1].minor.yy406, yymsp[0].minor.yy454);}
+#line 2998 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 278:
-#line 859 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy91 = sqlite3TriggerSelectStep(yymsp[0].minor.yy107); }
-#line 2860 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 288:
+#line 915 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy455 = sqlite3TriggerSelectStep(yymsp[0].minor.yy331); }
+#line 3003 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 279:
-#line 862 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 289:
+#line 918 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- yygotominor.yy258 = sqlite3Expr(TK_RAISE, 0, 0, 0);
- yygotominor.yy258->iColumn = OE_Ignore;
- sqlite3ExprSpan(yygotominor.yy258, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0);
+ yygotominor.yy454 = sqlite3Expr(TK_RAISE, 0, 0, 0);
+ yygotominor.yy454->iColumn = OE_Ignore;
+ sqlite3ExprSpan(yygotominor.yy454, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0);
}
-#line 2869 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 3012 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 280:
-#line 867 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 290:
+#line 923 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- yygotominor.yy258 = sqlite3Expr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy98);
- yygotominor.yy258->iColumn = yymsp[-3].minor.yy284;
- sqlite3ExprSpan(yygotominor.yy258, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
+ yygotominor.yy454 = sqlite3Expr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy406);
+ yygotominor.yy454->iColumn = yymsp[-3].minor.yy60;
+ sqlite3ExprSpan(yygotominor.yy454, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
}
-#line 2878 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 3021 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 281:
-#line 873 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = OE_Rollback;}
-#line 2883 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 291:
+#line 931 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = OE_Rollback;}
+#line 3026 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 283:
-#line 875 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{yygotominor.yy284 = OE_Fail;}
-#line 2888 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 293:
+#line 933 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{yygotominor.yy60 = OE_Fail;}
+#line 3031 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 284:
-#line 879 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 294:
+#line 938 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- sqlite3DropTrigger(pParse,yymsp[0].minor.yy259);
+ sqlite3DropTrigger(pParse,yymsp[0].minor.yy427);
}
-#line 2895 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 3038 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 285:
-#line 884 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 295:
+#line 944 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- sqlite3Attach(pParse, &yymsp[-3].minor.yy98, &yymsp[-1].minor.yy98, yymsp[0].minor.yy292.type, &yymsp[0].minor.yy292.key);
+ sqlite3Attach(pParse, &yymsp[-3].minor.yy406, &yymsp[-1].minor.yy406, yymsp[0].minor.yy40.type, &yymsp[0].minor.yy40.key);
}
-#line 2902 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 3045 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 286:
-#line 888 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy292.type = 0; }
-#line 2907 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 296:
+#line 948 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy40.type = 0; }
+#line 3050 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 287:
-#line 889 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy292.type=1; yygotominor.yy292.key = yymsp[0].minor.yy98; }
-#line 2912 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 297:
+#line 949 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy40.type=1; yygotominor.yy40.key = yymsp[0].minor.yy406; }
+#line 3055 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 288:
-#line 890 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
-{ yygotominor.yy292.type=2; yygotominor.yy292.key = yymsp[0].minor.yy0; }
-#line 2917 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+ case 298:
+#line 950 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{ yygotominor.yy40.type=2; yygotominor.yy40.key = yymsp[0].minor.yy0; }
+#line 3060 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
- case 291:
-#line 896 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+ case 301:
+#line 956 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{
+ sqlite3Detach(pParse, &yymsp[0].minor.yy406);
+}
+#line 3067 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
+ case 302:
+#line 962 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3Reindex(pParse, 0, 0);}
+#line 3072 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
+ case 303:
+#line 963 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
+{sqlite3Reindex(pParse, &yymsp[-1].minor.yy406, &yymsp[0].minor.yy406);}
+#line 3077 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
+ break;
+ case 304:
+#line 968 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
{
- sqlite3Detach(pParse, &yymsp[0].minor.yy98);
+ sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy427,&yymsp[0].minor.yy406);
}
-#line 2924 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 3084 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
break;
};
yygoto = yyRuleInfo[yyruleno].lhs;
@@ -2961,7 +3121,7 @@ static void yy_syntax_error(
){
sqlite3ParserARG_FETCH;
#define TOKEN (yyminor.yy0)
-#line 23 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.y"
+#line 23 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.y"
if( pParse->zErrMsg==0 ){
if( TOKEN.z[0] ){
@@ -2970,7 +3130,7 @@ static void yy_syntax_error(
sqlite3ErrorMsg(pParse, "incomplete SQL statement");
}
}
-#line 2976 "/home/wez/play/php/pecl/pdo_sqlite/sqlite/src/parse.c"
+#line 3136 "/home/wez/php5-HEAD/ext/pdo_sqlite/sqlite/src/parse.c"
sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */
}
diff --git a/ext/pdo_sqlite/sqlite/src/parse.h b/ext/pdo_sqlite/sqlite/src/parse.h
index 547319ed70..e50789a834 100644
--- a/ext/pdo_sqlite/sqlite/src/parse.h
+++ b/ext/pdo_sqlite/sqlite/src/parse.h
@@ -55,75 +55,86 @@
#define TK_TRIGGER 55
#define TK_VACUUM 56
#define TK_VIEW 57
-#define TK_OR 58
-#define TK_AND 59
-#define TK_NOT 60
-#define TK_IS 61
-#define TK_BETWEEN 62
-#define TK_IN 63
-#define TK_ISNULL 64
-#define TK_NOTNULL 65
-#define TK_NE 66
-#define TK_EQ 67
-#define TK_GT 68
-#define TK_LE 69
-#define TK_LT 70
-#define TK_GE 71
-#define TK_BITAND 72
-#define TK_BITOR 73
-#define TK_LSHIFT 74
-#define TK_RSHIFT 75
-#define TK_PLUS 76
-#define TK_MINUS 77
-#define TK_STAR 78
-#define TK_SLASH 79
-#define TK_REM 80
-#define TK_CONCAT 81
-#define TK_UMINUS 82
-#define TK_UPLUS 83
-#define TK_BITNOT 84
-#define TK_STRING 85
-#define TK_JOIN_KW 86
-#define TK_CONSTRAINT 87
-#define TK_DEFAULT 88
-#define TK_NULL 89
-#define TK_PRIMARY 90
-#define TK_UNIQUE 91
-#define TK_CHECK 92
-#define TK_REFERENCES 93
-#define TK_COLLATE 94
-#define TK_ON 95
-#define TK_DELETE 96
-#define TK_UPDATE 97
-#define TK_INSERT 98
-#define TK_SET 99
-#define TK_DEFERRABLE 100
-#define TK_FOREIGN 101
-#define TK_DROP 102
-#define TK_UNION 103
-#define TK_ALL 104
-#define TK_INTERSECT 105
-#define TK_EXCEPT 106
-#define TK_SELECT 107
-#define TK_DISTINCT 108
-#define TK_DOT 109
-#define TK_FROM 110
-#define TK_JOIN 111
-#define TK_USING 112
-#define TK_ORDER 113
-#define TK_BY 114
-#define TK_GROUP 115
-#define TK_HAVING 116
-#define TK_LIMIT 117
-#define TK_WHERE 118
-#define TK_INTO 119
-#define TK_VALUES 120
-#define TK_INTEGER 121
-#define TK_FLOAT 122
-#define TK_BLOB 123
-#define TK_VARIABLE 124
-#define TK_CASE 125
-#define TK_WHEN 126
-#define TK_THEN 127
-#define TK_ELSE 128
-#define TK_INDEX 129
+#define TK_REINDEX 58
+#define TK_RENAME 59
+#define TK_CDATE 60
+#define TK_CTIME 61
+#define TK_CTIMESTAMP 62
+#define TK_ALTER 63
+#define TK_OR 64
+#define TK_AND 65
+#define TK_NOT 66
+#define TK_IS 67
+#define TK_BETWEEN 68
+#define TK_IN 69
+#define TK_ISNULL 70
+#define TK_NOTNULL 71
+#define TK_NE 72
+#define TK_EQ 73
+#define TK_GT 74
+#define TK_LE 75
+#define TK_LT 76
+#define TK_GE 77
+#define TK_ESCAPE 78
+#define TK_BITAND 79
+#define TK_BITOR 80
+#define TK_LSHIFT 81
+#define TK_RSHIFT 82
+#define TK_PLUS 83
+#define TK_MINUS 84
+#define TK_STAR 85
+#define TK_SLASH 86
+#define TK_REM 87
+#define TK_CONCAT 88
+#define TK_UMINUS 89
+#define TK_UPLUS 90
+#define TK_BITNOT 91
+#define TK_STRING 92
+#define TK_JOIN_KW 93
+#define TK_CONSTRAINT 94
+#define TK_DEFAULT 95
+#define TK_NULL 96
+#define TK_PRIMARY 97
+#define TK_UNIQUE 98
+#define TK_CHECK 99
+#define TK_REFERENCES 100
+#define TK_COLLATE 101
+#define TK_AUTOINCR 102
+#define TK_ON 103
+#define TK_DELETE 104
+#define TK_UPDATE 105
+#define TK_INSERT 106
+#define TK_SET 107
+#define TK_DEFERRABLE 108
+#define TK_FOREIGN 109
+#define TK_DROP 110
+#define TK_UNION 111
+#define TK_ALL 112
+#define TK_INTERSECT 113
+#define TK_EXCEPT 114
+#define TK_SELECT 115
+#define TK_DISTINCT 116
+#define TK_DOT 117
+#define TK_FROM 118
+#define TK_JOIN 119
+#define TK_USING 120
+#define TK_ORDER 121
+#define TK_BY 122
+#define TK_GROUP 123
+#define TK_HAVING 124
+#define TK_LIMIT 125
+#define TK_WHERE 126
+#define TK_INTO 127
+#define TK_VALUES 128
+#define TK_INTEGER 129
+#define TK_FLOAT 130
+#define TK_BLOB 131
+#define TK_REGISTER 132
+#define TK_VARIABLE 133
+#define TK_EXISTS 134
+#define TK_CASE 135
+#define TK_WHEN 136
+#define TK_THEN 137
+#define TK_ELSE 138
+#define TK_INDEX 139
+#define TK_TO 140
diff --git a/ext/pdo_sqlite/sqlite/src/parse.y b/ext/pdo_sqlite/sqlite/src/parse.y
index 59dd563a6c..66398ac4f1 100644
--- a/ext/pdo_sqlite/sqlite/src/parse.y
+++ b/ext/pdo_sqlite/sqlite/src/parse.y
@@ -39,8 +39,8 @@
** LIMIT clause of a SELECT statement.
*/
struct LimitVal {
- int limit; /* The LIMIT value. -1 if there is no limit */
- int offset; /* The OFFSET. 0 if there is none */
+ Expr *pLimit; /* The LIMIT expression. NULL if there is no limit */
+ Expr *pOffset; /* The OFFSET expression. NULL if there is none */
};
/*
@@ -81,11 +81,13 @@ struct AttachKey { int type; Token key; };
input ::= cmdlist.
cmdlist ::= cmdlist ecmd.
cmdlist ::= ecmd.
-ecmd ::= explain cmdx SEMI.
-ecmd ::= SEMI.
cmdx ::= cmd. { sqlite3FinishCoding(pParse); }
-explain ::= EXPLAIN. { sqlite3BeginParse(pParse, 1); }
+ecmd ::= SEMI.
+ecmd ::= explain cmdx SEMI.
explain ::= . { sqlite3BeginParse(pParse, 0); }
+%ifndef SQLITE_OMIT_EXPLAIN
+explain ::= EXPLAIN. { sqlite3BeginParse(pParse, 1); }
+%endif
///////////////////// Begin and end transactions. ////////////////////////////
//
@@ -144,7 +146,12 @@ id(A) ::= ID(X). {A = X;}
DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR
GLOB IGNORE IMMEDIATE INITIALLY INSTEAD LIKE MATCH KEY
OF OFFSET PRAGMA RAISE REPLACE RESTRICT ROW STATEMENT
- TEMP TRIGGER VACUUM VIEW.
+ TEMP TRIGGER VACUUM VIEW
+%ifdef SQLITE_OMIT_COMPOUND_SELECT
+ EXCEPT INTERSECT UNION
+%endif
+ REINDEX RENAME CDATE CTIME CTIMESTAMP ALTER
+ .
// Define operator precedence early so that this is the first occurance
// of the operator tokens in the grammer. Keeping the operators together
@@ -162,6 +169,7 @@ id(A) ::= ID(X). {A = X;}
%right NOT.
%left IS LIKE GLOB BETWEEN IN ISNULL NOTNULL NE EQ.
%left GT LE LT GE.
+%right ESCAPE.
%left BITAND BITOR LSHIFT RSHIFT.
%left PLUS MINUS.
%left STAR SLASH REM.
@@ -196,17 +204,24 @@ carglist ::= carglist carg.
carglist ::= .
carg ::= CONSTRAINT nm ccons.
carg ::= ccons.
-carg ::= DEFAULT ids(X). {sqlite3AddDefaultValue(pParse,&X,0);}
-carg ::= DEFAULT plus_num(X). {sqlite3AddDefaultValue(pParse,&X,0);}
-carg ::= DEFAULT minus_num(X). {sqlite3AddDefaultValue(pParse,&X,1);}
-carg ::= DEFAULT NULL.
+carg ::= DEFAULT term(X). {sqlite3AddDefaultValue(pParse,X);}
+carg ::= DEFAULT PLUS term(X). {sqlite3AddDefaultValue(pParse,X);}
+carg ::= DEFAULT MINUS term(X). {
+ Expr *p = sqlite3Expr(TK_UMINUS, X, 0, 0);
+ sqlite3AddDefaultValue(pParse,p);
+}
+carg ::= DEFAULT id(X). {
+ Expr *p = sqlite3Expr(TK_STRING, 0, 0, &X);
+ sqlite3AddDefaultValue(pParse,p);
+}
// In addition to the type name, we also care about the primary key and
// UNIQUE constraints.
//
ccons ::= NULL onconf.
ccons ::= NOT NULL onconf(R). {sqlite3AddNotNull(pParse, R);}
-ccons ::= PRIMARY KEY sortorder onconf(R). {sqlite3AddPrimaryKey(pParse,0,R);}
+ccons ::= PRIMARY KEY sortorder onconf(R) autoinc(I).
+ {sqlite3AddPrimaryKey(pParse,0,R,I);}
ccons ::= UNIQUE onconf(R). {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0);}
ccons ::= CHECK LP expr RP onconf.
ccons ::= REFERENCES nm(T) idxlist_opt(TA) refargs(R).
@@ -214,6 +229,11 @@ ccons ::= REFERENCES nm(T) idxlist_opt(TA) refargs(R).
ccons ::= defer_subclause(D). {sqlite3DeferForeignKey(pParse,D);}
ccons ::= COLLATE id(C). {sqlite3AddCollateType(pParse, C.z, C.n);}
+// The optional AUTOINCREMENT keyword
+%type autoinc {int}
+autoinc(X) ::= . {X = 0;}
+autoinc(X) ::= AUTOINCR. {X = 1;}
+
// The next group of rules parses the arguments to a REFERENCES clause
// that determine if the referential integrity checking is deferred or
// or immediate and which determine what action to take if a ref-integ
@@ -249,8 +269,8 @@ conslist ::= conslist COMMA tcons.
conslist ::= conslist tcons.
conslist ::= tcons.
tcons ::= CONSTRAINT nm.
-tcons ::= PRIMARY KEY LP idxlist(X) RP onconf(R).
- {sqlite3AddPrimaryKey(pParse,X,R);}
+tcons ::= PRIMARY KEY LP idxlist(X) autoinc(I) RP onconf(R).
+ {sqlite3AddPrimaryKey(pParse,X,R,I);}
tcons ::= UNIQUE LP idxlist(X) RP onconf(R).
{sqlite3CreateIndex(pParse,0,0,0,X,R,0,0);}
tcons ::= CHECK expr onconf.
@@ -285,12 +305,14 @@ cmd ::= DROP TABLE fullname(X). {
///////////////////// The CREATE VIEW statement /////////////////////////////
//
+%ifndef SQLITE_OMIT_VIEW
cmd ::= CREATE(X) temp(T) VIEW nm(Y) dbnm(Z) AS select(S). {
sqlite3CreateView(pParse, &X, &Y, &Z, S, T);
}
cmd ::= DROP VIEW fullname(X). {
sqlite3DropTable(pParse, X, 1);
}
+%endif // SQLITE_OMIT_VIEW
//////////////////////// The SELECT statement /////////////////////////////////
//
@@ -305,6 +327,7 @@ cmd ::= select(X). {
%destructor oneselect {sqlite3SelectDelete($$);}
select(A) ::= oneselect(X). {A = X;}
+%ifndef SQLITE_OMIT_COMPOUND_SELECT
select(A) ::= select(X) multiselect_op(Y) oneselect(Z). {
if( Z ){
Z->op = Y;
@@ -317,9 +340,10 @@ multiselect_op(A) ::= UNION(OP). {A = @OP;}
multiselect_op(A) ::= UNION ALL. {A = TK_ALL;}
multiselect_op(A) ::= INTERSECT(OP). {A = @OP;}
multiselect_op(A) ::= EXCEPT(OP). {A = @OP;}
+%endif // SQLITE_OMIT_COMPOUND_SELECT
oneselect(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y)
groupby_opt(P) having_opt(Q) orderby_opt(Z) limit_opt(L). {
- A = sqlite3SelectNew(W,X,Y,P,Q,Z,D,L.limit,L.offset);
+ A = sqlite3SelectNew(W,X,Y,P,Q,Z,D,L.pLimit,L.pOffset);
}
// The "distinct" nonterminal is true (1) if the DISTINCT keyword is
@@ -394,31 +418,33 @@ seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) as(Z) on_opt(N) using_opt(U). {
else { sqlite3IdListDelete(U); }
}
}
-seltablist(A) ::= stl_prefix(X) LP seltablist_paren(S) RP
- as(Z) on_opt(N) using_opt(U). {
- A = sqlite3SrcListAppend(X,0,0);
- A->a[A->nSrc-1].pSelect = S;
- if( Z.n ) sqlite3SrcListAddAlias(A,&Z);
- if( N ){
- if( A && A->nSrc>1 ){ A->a[A->nSrc-2].pOn = N; }
- else { sqlite3ExprDelete(N); }
+%ifndef SQLITE_OMIT_SUBQUERY
+ seltablist(A) ::= stl_prefix(X) LP seltablist_paren(S) RP
+ as(Z) on_opt(N) using_opt(U). {
+ A = sqlite3SrcListAppend(X,0,0);
+ A->a[A->nSrc-1].pSelect = S;
+ if( Z.n ) sqlite3SrcListAddAlias(A,&Z);
+ if( N ){
+ if( A && A->nSrc>1 ){ A->a[A->nSrc-2].pOn = N; }
+ else { sqlite3ExprDelete(N); }
+ }
+ if( U ){
+ if( A && A->nSrc>1 ){ A->a[A->nSrc-2].pUsing = U; }
+ else { sqlite3IdListDelete(U); }
+ }
}
- if( U ){
- if( A && A->nSrc>1 ){ A->a[A->nSrc-2].pUsing = U; }
- else { sqlite3IdListDelete(U); }
+
+ // A seltablist_paren nonterminal represents anything in a FROM that
+ // is contained inside parentheses. This can be either a subquery or
+ // a grouping of table and subqueries.
+ //
+ %type seltablist_paren {Select*}
+ %destructor seltablist_paren {sqlite3SelectDelete($$);}
+ seltablist_paren(A) ::= select(S). {A = S;}
+ seltablist_paren(A) ::= seltablist(F). {
+ A = sqlite3SelectNew(0,F,0,0,0,0,0,0,0);
}
-}
-
-// A seltablist_paren nonterminal represents anything in a FROM that
-// is contained inside parentheses. This can be either a subquery or
-// a grouping of table and subqueries.
-//
-%type seltablist_paren {Select*}
-%destructor seltablist_paren {sqlite3SelectDelete($$);}
-seltablist_paren(A) ::= select(S). {A = S;}
-seltablist_paren(A) ::= seltablist(F). {
- A = sqlite3SelectNew(0,F,0,0,0,0,0,-1,0);
-}
+%endif // SQLITE_OMIT_SUBQUERY
%type dbnm {Token}
dbnm(A) ::= . {A.z=0; A.n=0;}
@@ -487,12 +513,16 @@ having_opt(A) ::= . {A = 0;}
having_opt(A) ::= HAVING expr(X). {A = X;}
%type limit_opt {struct LimitVal}
-limit_opt(A) ::= . {A.limit = -1; A.offset = 0;}
-limit_opt(A) ::= LIMIT signed(X). {A.limit = X; A.offset = 0;}
-limit_opt(A) ::= LIMIT signed(X) OFFSET signed(Y).
- {A.limit = X; A.offset = Y;}
-limit_opt(A) ::= LIMIT signed(X) COMMA signed(Y).
- {A.limit = Y; A.offset = X;}
+%destructor limit_opt {
+ sqlite3ExprDelete($$.pLimit);
+ sqlite3ExprDelete($$.pOffset);
+}
+limit_opt(A) ::= . {A.pLimit = 0; A.pOffset = 0;}
+limit_opt(A) ::= LIMIT expr(X). {A.pLimit = X; A.pOffset = 0;}
+limit_opt(A) ::= LIMIT expr(X) OFFSET expr(Y).
+ {A.pLimit = X; A.pOffset = Y;}
+limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y).
+ {A.pOffset = X; A.pLimit = Y;}
/////////////////////////// The DELETE statement /////////////////////////////
//
@@ -550,9 +580,12 @@ inscollist(A) ::= nm(Y). {A = sqlite3IdListAppend(0,&Y);}
%type expr {Expr*}
%destructor expr {sqlite3ExprDelete($$);}
+%type term {Expr*}
+%destructor term {sqlite3ExprDelete($$);}
+expr(A) ::= term(X). {A = X;}
expr(A) ::= LP(B) expr(X) RP(E). {A = X; sqlite3ExprSpan(A,&B,&E); }
-expr(A) ::= NULL(X). {A = sqlite3Expr(@X, 0, 0, &X);}
+term(A) ::= NULL(X). {A = sqlite3Expr(@X, 0, 0, &X);}
expr(A) ::= ID(X). {A = sqlite3Expr(TK_ID, 0, 0, &X);}
expr(A) ::= JOIN_KW(X). {A = sqlite3Expr(TK_ID, 0, 0, &X);}
expr(A) ::= nm(X) DOT nm(Y). {
@@ -567,10 +600,11 @@ expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). {
Expr *temp4 = sqlite3Expr(TK_DOT, temp2, temp3, 0);
A = sqlite3Expr(TK_DOT, temp1, temp4, 0);
}
-expr(A) ::= INTEGER(X). {A = sqlite3Expr(@X, 0, 0, &X);}
-expr(A) ::= FLOAT(X). {A = sqlite3Expr(@X, 0, 0, &X);}
-expr(A) ::= STRING(X). {A = sqlite3Expr(@X, 0, 0, &X);}
+term(A) ::= INTEGER(X). {A = sqlite3Expr(@X, 0, 0, &X);}
+term(A) ::= FLOAT(X). {A = sqlite3Expr(@X, 0, 0, &X);}
+term(A) ::= STRING(X). {A = sqlite3Expr(@X, 0, 0, &X);}
expr(A) ::= BLOB(X). {A = sqlite3Expr(@X, 0, 0, &X);}
+expr(A) ::= REGISTER(X). {A = sqlite3RegisterExpr(pParse, &X);}
expr(A) ::= VARIABLE(X). {
Token *pToken = &X;
Expr *pExpr = A = sqlite3Expr(TK_VARIABLE, 0, 0, pToken);
@@ -584,6 +618,9 @@ expr(A) ::= ID(X) LP STAR RP(E). {
A = sqlite3ExprFunction(0, &X);
sqlite3ExprSpan(A,&X,&E);
}
+term(A) ::= CTIME(OP). {A = sqlite3Expr(@OP,0,0,0);}
+term(A) ::= CDATE(OP). {A = sqlite3Expr(@OP,0,0,0);}
+term(A) ::= CTIMESTAMP(OP). {A = sqlite3Expr(@OP,0,0,0);}
expr(A) ::= expr(X) AND(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);}
expr(A) ::= expr(X) OR(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);}
expr(A) ::= expr(X) LT(OP) expr(Y). {A = sqlite3Expr(@OP, X, Y, 0);}
@@ -607,14 +644,21 @@ likeop(A) ::= LIKE. {A.opcode = TK_LIKE; A.not = 0;}
likeop(A) ::= GLOB. {A.opcode = TK_GLOB; A.not = 0;}
likeop(A) ::= NOT LIKE. {A.opcode = TK_LIKE; A.not = 1;}
likeop(A) ::= NOT GLOB. {A.opcode = TK_GLOB; A.not = 1;}
-expr(A) ::= expr(X) likeop(OP) expr(Y). [LIKE] {
+%type escape {Expr*}
+escape(X) ::= ESCAPE expr(A). [ESCAPE] {X = A;}
+escape(X) ::= . [ESCAPE] {X = 0;}
+expr(A) ::= expr(X) likeop(OP) expr(Y) escape(E). [LIKE] {
ExprList *pList = sqlite3ExprListAppend(0, Y, 0);
pList = sqlite3ExprListAppend(pList, X, 0);
+ if( E ){
+ pList = sqlite3ExprListAppend(pList, E, 0);
+ }
A = sqlite3ExprFunction(pList, 0);
if( A ) A->op = OP.opcode;
if( OP.not ) A = sqlite3Expr(TK_NOT, A, 0, 0);
sqlite3ExprSpan(A, &X->span, &Y->span);
}
+
expr(A) ::= expr(X) ISNULL(E). {
A = sqlite3Expr(TK_ISNULL, X, 0, 0);
sqlite3ExprSpan(A,&X->span,&E);
@@ -651,11 +695,6 @@ expr(A) ::= PLUS(B) expr(X). [UPLUS] {
A = sqlite3Expr(TK_UPLUS, X, 0, 0);
sqlite3ExprSpan(A,&B,&X->span);
}
-expr(A) ::= LP(B) select(X) RP(E). {
- A = sqlite3Expr(TK_SELECT, 0, 0, 0);
- if( A ) A->pSelect = X;
- sqlite3ExprSpan(A,&B,&E);
-}
%type between_op {int}
between_op(A) ::= BETWEEN. {A = 0;}
between_op(A) ::= NOT BETWEEN. {A = 1;}
@@ -667,29 +706,42 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
if( N ) A = sqlite3Expr(TK_NOT, A, 0, 0);
sqlite3ExprSpan(A,&W->span,&Y->span);
}
-%type in_op {int}
-in_op(A) ::= IN. {A = 0;}
-in_op(A) ::= NOT IN. {A = 1;}
-expr(A) ::= expr(X) in_op(N) LP exprlist(Y) RP(E). [IN] {
- A = sqlite3Expr(TK_IN, X, 0, 0);
- if( A ) A->pList = Y;
- if( N ) A = sqlite3Expr(TK_NOT, A, 0, 0);
- sqlite3ExprSpan(A,&X->span,&E);
-}
-expr(A) ::= expr(X) in_op(N) LP select(Y) RP(E). [IN] {
- A = sqlite3Expr(TK_IN, X, 0, 0);
- if( A ) A->pSelect = Y;
- if( N ) A = sqlite3Expr(TK_NOT, A, 0, 0);
- sqlite3ExprSpan(A,&X->span,&E);
-}
-expr(A) ::= expr(X) in_op(N) nm(Y) dbnm(Z). [IN] {
- SrcList *pSrc = sqlite3SrcListAppend(0,&Y,&Z);
- A = sqlite3Expr(TK_IN, X, 0, 0);
- if( A ) A->pSelect = sqlite3SelectNew(0,pSrc,0,0,0,0,0,-1,0);
- if( N ) A = sqlite3Expr(TK_NOT, A, 0, 0);
- sqlite3ExprSpan(A,&X->span,Z.z?&Z:&Y);
-}
-
+%ifndef SQLITE_OMIT_SUBQUERY
+ %type in_op {int}
+ in_op(A) ::= IN. {A = 0;}
+ in_op(A) ::= NOT IN. {A = 1;}
+ expr(A) ::= expr(X) in_op(N) LP exprlist(Y) RP(E). [IN] {
+ A = sqlite3Expr(TK_IN, X, 0, 0);
+ if( A ) A->pList = Y;
+ if( N ) A = sqlite3Expr(TK_NOT, A, 0, 0);
+ sqlite3ExprSpan(A,&X->span,&E);
+ }
+ expr(A) ::= LP(B) select(X) RP(E). {
+ A = sqlite3Expr(TK_SELECT, 0, 0, 0);
+ if( A ) A->pSelect = X;
+ sqlite3ExprSpan(A,&B,&E);
+ }
+ expr(A) ::= expr(X) in_op(N) LP select(Y) RP(E). [IN] {
+ A = sqlite3Expr(TK_IN, X, 0, 0);
+ if( A ) A->pSelect = Y;
+ if( N ) A = sqlite3Expr(TK_NOT, A, 0, 0);
+ sqlite3ExprSpan(A,&X->span,&E);
+ }
+ expr(A) ::= expr(X) in_op(N) nm(Y) dbnm(Z). [IN] {
+ SrcList *pSrc = sqlite3SrcListAppend(0,&Y,&Z);
+ A = sqlite3Expr(TK_IN, X, 0, 0);
+ if( A ) A->pSelect = sqlite3SelectNew(0,pSrc,0,0,0,0,0,0,0);
+ if( N ) A = sqlite3Expr(TK_NOT, A, 0, 0);
+ sqlite3ExprSpan(A,&X->span,Z.z?&Z:&Y);
+ }
+ expr(A) ::= EXISTS(B) LP select(Y) RP(E). {
+ Expr *p = A = sqlite3Expr(TK_EXISTS, 0, 0, 0);
+ if( p ){
+ p->pSelect = Y;
+ sqlite3ExprSpan(p,&B,&E);
+ }
+ }
+%endif // SQLITE_OMIT_SUBQUERY
/* CASE expressions */
expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). {
@@ -728,10 +780,10 @@ expritem(A) ::= . {A = 0;}
///////////////////////////// The CREATE INDEX command ///////////////////////
//
cmd ::= CREATE(S) uniqueflag(U) INDEX nm(X) dbnm(D)
- ON fullname(Y) LP idxlist(Z) RP(E) onconf(R). {
+ ON nm(Y) LP idxlist(Z) RP(E) onconf(R). {
if( U!=OE_None ) U = R;
if( U==OE_Default) U = OE_Abort;
- sqlite3CreateIndex(pParse, &X, &D, Y, Z, U, &S, &E);
+ sqlite3CreateIndex(pParse, &X, &D, sqlite3SrcListAppend(0,&Y,0),Z,U, &S, &E);
}
%type uniqueflag {int}
@@ -776,6 +828,7 @@ cmd ::= VACUUM nm. {sqlite3Vacuum(pParse,0);}
///////////////////////////// The PRAGMA command /////////////////////////////
//
+%ifndef SQLITE_OMIT_PRAGMA
cmd ::= PRAGMA nm(X) dbnm(Z) EQ nm(Y). {sqlite3Pragma(pParse,&X,&Z,&Y,0);}
cmd ::= PRAGMA nm(X) dbnm(Z) EQ ON(Y). {sqlite3Pragma(pParse,&X,&Z,&Y,0);}
cmd ::= PRAGMA nm(X) dbnm(Z) EQ plus_num(Y). {sqlite3Pragma(pParse,&X,&Z,&Y,0);}
@@ -784,6 +837,7 @@ cmd ::= PRAGMA nm(X) dbnm(Z) EQ minus_num(Y). {
}
cmd ::= PRAGMA nm(X) dbnm(Z) LP nm(Y) RP. {sqlite3Pragma(pParse,&X,&Z,&Y,0);}
cmd ::= PRAGMA nm(X) dbnm(Z). {sqlite3Pragma(pParse,&X,&Z,0,0);}
+%endif // SQLITE_OMIT_PRAGMA
plus_num(A) ::= plus_opt number(X). {A = X;}
minus_num(A) ::= MINUS number(X). {A = X;}
number(A) ::= INTEGER(X). {A = X;}
@@ -793,6 +847,8 @@ plus_opt ::= .
//////////////////////////// The CREATE TRIGGER command /////////////////////
+%ifndef SQLITE_OMIT_TRIGGER
+
cmd ::= CREATE trigger_decl(A) BEGIN trigger_cmd_list(S) END(Z). {
Token all;
all.z = A.z;
@@ -869,6 +925,8 @@ expr(A) ::= RAISE(X) LP raisetype(T) COMMA nm(Z) RP(Y). {
A->iColumn = T;
sqlite3ExprSpan(A, &X, &Y);
}
+%endif // !SQLITE_OMIT_TRIGGER
+
%type raisetype {int}
raisetype(A) ::= ROLLBACK. {A = OE_Rollback;}
raisetype(A) ::= ABORT. {A = OE_Abort;}
@@ -876,9 +934,11 @@ raisetype(A) ::= FAIL. {A = OE_Fail;}
//////////////////////// DROP TRIGGER statement //////////////////////////////
+%ifndef SQLITE_OMIT_TRIGGER
cmd ::= DROP TRIGGER fullname(X). {
sqlite3DropTrigger(pParse,X);
}
+%endif // !SQLITE_OMIT_TRIGGER
//////////////////////// ATTACH DATABASE file AS name /////////////////////////
cmd ::= ATTACH database_kw_opt ids(F) AS nm(D) key_opt(K). {
@@ -896,3 +956,16 @@ database_kw_opt ::= .
cmd ::= DETACH database_kw_opt nm(D). {
sqlite3Detach(pParse, &D);
}
+
+////////////////////////// REINDEX collation //////////////////////////////////
+%ifndef SQLITE_OMIT_REINDEX
+cmd ::= REINDEX. {sqlite3Reindex(pParse, 0, 0);}
+cmd ::= REINDEX nm(X) dbnm(Y). {sqlite3Reindex(pParse, &X, &Y);}
+%endif
+
+//////////////////////// ALTER TABLE table ... ////////////////////////////////
+%ifndef SQLITE_OMIT_ALTERTABLE
+cmd ::= ALTER TABLE fullname(X) RENAME TO nm(Z). {
+ sqlite3AlterRenameTable(pParse,X,&Z);
+}
+%endif
diff --git a/ext/pdo_sqlite/sqlite/src/pragma.c b/ext/pdo_sqlite/sqlite/src/pragma.c
index 94a218632a..3c09a4b196 100644
--- a/ext/pdo_sqlite/sqlite/src/pragma.c
+++ b/ext/pdo_sqlite/sqlite/src/pragma.c
@@ -14,30 +14,19 @@
** $Id$
*/
#include "sqliteInt.h"
+#include "os.h"
#include <ctype.h>
+/* Ignore this whole file if pragmas are disabled
+*/
+#ifndef SQLITE_OMIT_PRAGMA
+
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
# include "pager.h"
# include "btree.h"
#endif
/*
-** Interpret the given string as a boolean value.
-*/
-static int getBoolean(const u8 *z){
- static const u8 *azTrue[] = { "yes", "on", "true" };
- int i;
- if( z[0]==0 ) return 0;
- if( sqlite3IsNumber(z, 0, SQLITE_UTF8) ){
- return atoi(z);
- }
- for(i=0; i<sizeof(azTrue)/sizeof(azTrue[0]); i++){
- if( sqlite3StrICmp(z,azTrue[i])==0 ) return 1;
- }
- return 0;
-}
-
-/*
** Interpret the given string as a safety level. Return 0 for OFF,
** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or
** unrecognized string argument.
@@ -47,31 +36,34 @@ static int getBoolean(const u8 *z){
** to support legacy SQL code. The safety level used to be boolean
** and older scripts may have used numbers 0 for OFF and 1 for ON.
*/
-static int getSafetyLevel(u8 *z){
- static const struct {
- const u8 *zWord;
- int val;
- } aKey[] = {
- { "no", 0 },
- { "off", 0 },
- { "false", 0 },
- { "yes", 1 },
- { "on", 1 },
- { "true", 1 },
- { "full", 2 },
- };
- int i;
- if( z[0]==0 ) return 1;
- if( sqlite3IsNumber(z, 0, SQLITE_UTF8) ){
+static int getSafetyLevel(const u8 *z){
+ /* 123456789 123456789 */
+ static const char zText[] = "onoffalseyestruefull";
+ static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16};
+ static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 4};
+ static const u8 iValue[] = {1, 0, 0, 0, 1, 1, 2};
+ int i, n;
+ if( isdigit(*z) ){
return atoi(z);
}
- for(i=0; i<sizeof(aKey)/sizeof(aKey[0]); i++){
- if( sqlite3StrICmp(z,aKey[i].zWord)==0 ) return aKey[i].val;
+ n = strlen(z);
+ for(i=0; i<sizeof(iLength); i++){
+ if( iLength[i]==n && sqlite3StrNICmp(&zText[iOffset[i]],z,n)==0 ){
+ return iValue[i];
+ }
}
return 1;
}
/*
+** Interpret the given string as a boolean value.
+*/
+static int getBoolean(const u8 *z){
+ return getSafetyLevel(z)&1;
+}
+
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
+/*
** Interpret the given string as a temp db location. Return 1 for file
** backed temporary databases, 2 for the Red-Black tree in memory database
** and 0 to use the compile-time default.
@@ -89,14 +81,11 @@ static int getTempStore(const char *z){
}
/*
-** If the TEMP database is open, close it and mark the database schema
-** as needing reloading. This must be done when using the TEMP_STORE
-** or DEFAULT_TEMP_STORE pragmas.
+** Invalidate temp storage, either when the temp storage is changed
+** from default, or when 'file' and the temp_store_directory has changed
*/
-static int changeTempStorage(Parse *pParse, const char *zStorageType){
- int ts = getTempStore(zStorageType);
+static int invalidateTempStorage(Parse *pParse){
sqlite3 *db = pParse->db;
- if( db->temp_store==ts ) return SQLITE_OK;
if( db->aDb[1].pBt!=0 ){
if( db->flags & SQLITE_InTrans ){
sqlite3ErrorMsg(pParse, "temporary storage cannot be changed "
@@ -107,9 +96,25 @@ static int changeTempStorage(Parse *pParse, const char *zStorageType){
db->aDb[1].pBt = 0;
sqlite3ResetInternalSchema(db, 0);
}
+ return SQLITE_OK;
+}
+
+/*
+** If the TEMP database is open, close it and mark the database schema
+** as needing reloading. This must be done when using the TEMP_STORE
+** or DEFAULT_TEMP_STORE pragmas.
+*/
+static int changeTempStorage(Parse *pParse, const char *zStorageType){
+ int ts = getTempStore(zStorageType);
+ sqlite3 *db = pParse->db;
+ if( db->temp_store==ts ) return SQLITE_OK;
+ if( invalidateTempStorage( pParse ) != SQLITE_OK ){
+ return SQLITE_ERROR;
+ }
db->temp_store = ts;
return SQLITE_OK;
}
+#endif
/*
** Generate code to return a single integer value.
@@ -130,35 +135,42 @@ static void returnSingleInt(Parse *pParse, const char *zLabel, int value){
** Also, implement the pragma.
*/
static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
- static const struct {
+ static const struct sPragmaType {
const char *zName; /* Name of the pragma */
int mask; /* Mask for the db->flags value */
} aPragma[] = {
{ "vdbe_trace", SQLITE_VdbeTrace },
{ "sql_trace", SQLITE_SqlTrace },
{ "vdbe_listing", SQLITE_VdbeListing },
-#if 1 /* FIX ME: Remove the following pragmas */
{ "full_column_names", SQLITE_FullColNames },
{ "short_column_names", SQLITE_ShortColNames },
{ "count_changes", SQLITE_CountRows },
{ "empty_result_callbacks", SQLITE_NullCallback },
-#endif
+ /* The following is VERY experimental */
+ { "writable_schema", SQLITE_WriteSchema },
+ { "omit_readlock", SQLITE_NoReadlock },
};
int i;
- for(i=0; i<sizeof(aPragma)/sizeof(aPragma[0]); i++){
- if( sqlite3StrICmp(zLeft, aPragma[i].zName)==0 ){
+ const struct sPragmaType *p;
+ for(i=0, p=aPragma; i<sizeof(aPragma)/sizeof(aPragma[0]); i++, p++){
+ if( sqlite3StrICmp(zLeft, p->zName)==0 ){
sqlite3 *db = pParse->db;
Vdbe *v;
- if( zRight==0 ){
- v = sqlite3GetVdbe(pParse);
- if( v ){
- returnSingleInt(pParse,
- aPragma[i].zName, (db->flags&aPragma[i].mask)!=0);
+ v = sqlite3GetVdbe(pParse);
+ if( v ){
+ if( zRight==0 ){
+ returnSingleInt(pParse, p->zName, (db->flags & p->mask)!=0 );
+ }else{
+ if( getBoolean(zRight) ){
+ db->flags |= p->mask;
+ }else{
+ db->flags &= ~p->mask;
+ }
}
- }else if( getBoolean(zRight) ){
- db->flags |= aPragma[i].mask;
- }else{
- db->flags &= ~aPragma[i].mask;
+ /* If one of these pragmas is executed, any prepared statements
+ ** need to be recompiled.
+ */
+ sqlite3VdbeAddOp(v, OP_Expire, 0, 0);
}
return 1;
}
@@ -217,6 +229,7 @@ void sqlite3Pragma(
goto pragma_out;
}
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
/*
** PRAGMA [database.]default_cache_size
** PRAGMA [database.]default_cache_size=N
@@ -281,11 +294,32 @@ void sqlite3Pragma(
int size = pBt ? sqlite3BtreeGetPageSize(pBt) : 0;
returnSingleInt(pParse, "page_size", size);
}else{
- sqlite3BtreeSetPageSize(pBt, atoi(zRight), sqlite3BtreeGetReserve(pBt));
+ sqlite3BtreeSetPageSize(pBt, atoi(zRight), -1);
}
}else
+#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
/*
+ ** PRAGMA [database.]auto_vacuum
+ ** PRAGMA [database.]auto_vacuum=N
+ **
+ ** Get or set the (boolean) value of the database 'auto-vacuum' parameter.
+ */
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( sqlite3StrICmp(zLeft,"auto_vacuum")==0 ){
+ Btree *pBt = pDb->pBt;
+ if( !zRight ){
+ int auto_vacuum =
+ pBt ? sqlite3BtreeGetAutoVacuum(pBt) : SQLITE_DEFAULT_AUTOVACUUM;
+ returnSingleInt(pParse, "auto_vacuum", auto_vacuum);
+ }else{
+ sqlite3BtreeSetAutoVacuum(pBt, getBoolean(zRight));
+ }
+ }else
+#endif
+
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
+ /*
** PRAGMA [database.]cache_size
** PRAGMA [database.]cache_size=N
**
@@ -331,6 +365,45 @@ void sqlite3Pragma(
}else
/*
+ ** PRAGMA temp_store_directory
+ ** PRAGMA temp_store_directory = ""|"directory_name"
+ **
+ ** Return or set the local value of the temp_store_directory flag. Changing
+ ** the value sets a specific directory to be used for temporary files.
+ ** Setting to a null string reverts to the default temporary directory search.
+ ** If temporary directory is changed, then invalidateTempStorage.
+ **
+ */
+ if( sqlite3StrICmp(zLeft, "temp_store_directory")==0 ){
+ if( !zRight ){
+ if( sqlite3_temp_directory ){
+ sqlite3VdbeSetNumCols(v, 1);
+ sqlite3VdbeSetColName(v, 0, "temp_store_directory", P3_STATIC);
+ sqlite3VdbeOp3(v, OP_String8, 0, 0, sqlite3_temp_directory, 0);
+ sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
+ }
+ }else{
+ if( zRight[0] && !sqlite3OsIsDirWritable(zRight) ){
+ sqlite3ErrorMsg(pParse, "not a writable directory");
+ goto pragma_out;
+ }
+ if( TEMP_STORE==0
+ || (TEMP_STORE==1 && db->temp_store<=1)
+ || (TEMP_STORE==2 && db->temp_store==1)
+ ){
+ invalidateTempStorage(pParse);
+ }
+ sqliteFree(sqlite3_temp_directory);
+ if( zRight[0] ){
+ sqlite3_temp_directory = zRight;
+ zRight = 0;
+ }else{
+ sqlite3_temp_directory = 0;
+ }
+ }
+ }else
+
+ /*
** PRAGMA [database.]synchronous
** PRAGMA [database.]synchronous=OFF|ON|NORMAL|FULL
**
@@ -353,22 +426,14 @@ void sqlite3Pragma(
}
}
}else
-
-#if 0 /* Used once during development. No longer needed */
- if( sqlite3StrICmp(zLeft, "trigger_overhead_test")==0 ){
- if( getBoolean(zRight) ){
- sqlite3_always_code_trigger_setup = 1;
- }else{
- sqlite3_always_code_trigger_setup = 0;
- }
- }else
-#endif
+#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
if( flagPragma(pParse, zLeft, zRight) ){
/* The flagPragma() subroutine also generates any necessary code
** there is nothing more to do here */
}else
+#ifndef SQLITE_OMIT_SCHEMA_PRAGMAS
/*
** PRAGMA table_info(<table>)
**
@@ -401,8 +466,7 @@ void sqlite3Pragma(
sqlite3VdbeOp3(v, OP_String8, 0, 0,
pTab->aCol[i].zType ? pTab->aCol[i].zType : "numeric", 0);
sqlite3VdbeAddOp(v, OP_Integer, pTab->aCol[i].notNull, 0);
- sqlite3VdbeOp3(v, OP_String8, 0, 0,
- pTab->aCol[i].zDflt, P3_STATIC);
+ sqlite3ExprCode(pParse, pTab->aCol[i].pDflt);
sqlite3VdbeAddOp(v, OP_Integer, pTab->aCol[i].isPrimKey, 0);
sqlite3VdbeAddOp(v, OP_Callback, 6, 0);
}
@@ -458,6 +522,40 @@ void sqlite3Pragma(
}
}else
+ if( sqlite3StrICmp(zLeft, "database_list")==0 ){
+ int i;
+ if( sqlite3ReadSchema(pParse) ) goto pragma_out;
+ sqlite3VdbeSetNumCols(v, 3);
+ sqlite3VdbeSetColName(v, 0, "seq", P3_STATIC);
+ sqlite3VdbeSetColName(v, 1, "name", P3_STATIC);
+ sqlite3VdbeSetColName(v, 2, "file", P3_STATIC);
+ for(i=0; i<db->nDb; i++){
+ if( db->aDb[i].pBt==0 ) continue;
+ assert( db->aDb[i].zName!=0 );
+ sqlite3VdbeAddOp(v, OP_Integer, i, 0);
+ sqlite3VdbeOp3(v, OP_String8, 0, 0, db->aDb[i].zName, 0);
+ sqlite3VdbeOp3(v, OP_String8, 0, 0,
+ sqlite3BtreeGetFilename(db->aDb[i].pBt), 0);
+ sqlite3VdbeAddOp(v, OP_Callback, 3, 0);
+ }
+ }else
+
+ if( sqlite3StrICmp(zLeft, "collation_list")==0 ){
+ int i = 0;
+ HashElem *p;
+ sqlite3VdbeSetNumCols(v, 2);
+ sqlite3VdbeSetColName(v, 0, "seq", P3_STATIC);
+ sqlite3VdbeSetColName(v, 1, "name", P3_STATIC);
+ for(p=sqliteHashFirst(&db->aCollSeq); p; p=sqliteHashNext(p)){
+ CollSeq *pColl = (CollSeq *)sqliteHashData(p);
+ sqlite3VdbeAddOp(v, OP_Integer, i++, 0);
+ sqlite3VdbeOp3(v, OP_String8, 0, 0, pColl->zName, 0);
+ sqlite3VdbeAddOp(v, OP_Callback, 2, 0);
+ }
+ }else
+#endif /* SQLITE_OMIT_SCHEMA_PRAGMAS */
+
+#ifndef SQLITE_OMIT_FOREIGN_KEY
if( sqlite3StrICmp(zLeft, "foreign_key_list")==0 && zRight ){
FKey *pFK;
Table *pTab;
@@ -491,24 +589,7 @@ void sqlite3Pragma(
}
}
}else
-
- if( sqlite3StrICmp(zLeft, "database_list")==0 ){
- int i;
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
- sqlite3VdbeSetNumCols(v, 3);
- sqlite3VdbeSetColName(v, 0, "seq", P3_STATIC);
- sqlite3VdbeSetColName(v, 1, "name", P3_STATIC);
- sqlite3VdbeSetColName(v, 2, "file", P3_STATIC);
- for(i=0; i<db->nDb; i++){
- if( db->aDb[i].pBt==0 ) continue;
- assert( db->aDb[i].zName!=0 );
- sqlite3VdbeAddOp(v, OP_Integer, i, 0);
- sqlite3VdbeOp3(v, OP_String8, 0, 0, db->aDb[i].zName, 0);
- sqlite3VdbeOp3(v, OP_String8, 0, 0,
- sqlite3BtreeGetFilename(db->aDb[i].pBt), 0);
- sqlite3VdbeAddOp(v, OP_Callback, 3, 0);
- }
- }else
+#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
#ifndef NDEBUG
if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
@@ -521,6 +602,7 @@ void sqlite3Pragma(
}else
#endif
+#ifndef SQLITE_OMIT_INTEGRITY_CHECK
if( sqlite3StrICmp(zLeft, "integrity_check")==0 ){
int i, j, addr;
@@ -645,6 +727,9 @@ void sqlite3Pragma(
addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode);
sqlite3VdbeChangeP2(v, addr+2, addr+ArraySize(endCode));
}else
+#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
+
+#ifndef SQLITE_OMIT_UTF16
/*
** PRAGMA encoding
** PRAGMA encoding = "utf-8"|"utf-16"|"utf-16le"|"utf-16be"
@@ -715,6 +800,69 @@ void sqlite3Pragma(
}
}
}else
+#endif /* SQLITE_OMIT_UTF16 */
+
+#ifndef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
+ /*
+ ** PRAGMA [database.]schema_version
+ ** PRAGMA [database.]schema_version = <integer>
+ **
+ ** PRAGMA [database.]user_version
+ ** PRAGMA [database.]user_version = <integer>
+ **
+ ** The pragma's schema_version and user_version are used to set or get
+ ** the value of the schema-version and user-version, respectively. Both
+ ** the schema-version and the user-version are 32-bit signed integers
+ ** stored in the database header.
+ **
+ ** The schema-cookie is usually only manipulated internally by SQLite. It
+ ** is incremented by SQLite whenever the database schema is modified (by
+ ** creating or dropping a table or index). The schema version is used by
+ ** SQLite each time a query is executed to ensure that the internal cache
+ ** of the schema used when compiling the SQL query matches the schema of
+ ** the database against which the compiled query is actually executed.
+ ** Subverting this mechanism by using "PRAGMA schema_version" to modify
+ ** the schema-version is potentially dangerous and may lead to program
+ ** crashes or database corruption. Use with caution!
+ **
+ ** The user-version is not used internally by SQLite. It may be used by
+ ** applications for any purpose.
+ */
+ if( sqlite3StrICmp(zLeft, "schema_version")==0 ||
+ sqlite3StrICmp(zLeft, "user_version")==0 ){
+
+ int iCookie; /* Cookie index. 0 for schema-cookie, 6 for user-cookie. */
+ if( zLeft[0]=='s' || zLeft[0]=='S' ){
+ iCookie = 0;
+ }else{
+ iCookie = 5;
+ }
+
+ if( zRight ){
+ /* Write the specified cookie value */
+ static const VdbeOpList setCookie[] = {
+ { OP_Transaction, 0, 1, 0}, /* 0 */
+ { OP_Integer, 0, 0, 0}, /* 1 */
+ { OP_SetCookie, 0, 0, 0}, /* 2 */
+ };
+ int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie);
+ sqlite3VdbeChangeP1(v, addr, iDb);
+ sqlite3VdbeChangeP1(v, addr+1, atoi(zRight));
+ sqlite3VdbeChangeP1(v, addr+2, iDb);
+ sqlite3VdbeChangeP2(v, addr+2, iCookie);
+ }else{
+ /* Read the specified cookie value */
+ static const VdbeOpList readCookie[] = {
+ { OP_ReadCookie, 0, 0, 0}, /* 0 */
+ { OP_Callback, 1, 0, 0}
+ };
+ int addr = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie);
+ sqlite3VdbeChangeP1(v, addr, iDb);
+ sqlite3VdbeChangeP2(v, addr, iCookie);
+ sqlite3VdbeSetNumCols(v, 1);
+ }
+ }
+#endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
/*
@@ -748,7 +896,17 @@ void sqlite3Pragma(
#endif
{}
+
+ if( v ){
+ /* Code an OP_Expire at the end of each PRAGMA program to cause
+ ** the VDBE implementing the pragma to expire. Most (all?) pragmas
+ ** are only valid for a single execution.
+ */
+ sqlite3VdbeAddOp(v, OP_Expire, 1, 0);
+ }
pragma_out:
sqliteFree(zLeft);
sqliteFree(zRight);
}
+
+#endif /* SQLITE_OMIT_PRAGMA */
diff --git a/ext/pdo_sqlite/sqlite/src/printf.c b/ext/pdo_sqlite/sqlite/src/printf.c
index 43e1286372..6e700771b4 100644
--- a/ext/pdo_sqlite/sqlite/src/printf.c
+++ b/ext/pdo_sqlite/sqlite/src/printf.c
@@ -99,6 +99,7 @@ typedef struct et_info { /* Information about each format field */
*/
#define FLAG_SIGNED 1 /* True if the value to convert is signed */
#define FLAG_INTERN 2 /* True if for internal use only */
+#define FLAG_STRING 4 /* Allow infinity precision */
/*
@@ -109,10 +110,10 @@ static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
static const char aPrefix[] = "-x0\000X0";
static const et_info fmtinfo[] = {
{ 'd', 10, 1, etRADIX, 0, 0 },
- { 's', 0, 0, etSTRING, 0, 0 },
- { 'z', 0, 2, etDYNSTRING, 0, 0 },
- { 'q', 0, 0, etSQLESCAPE, 0, 0 },
- { 'Q', 0, 0, etSQLESCAPE2, 0, 0 },
+ { 's', 0, 4, etSTRING, 0, 0 },
+ { 'z', 0, 6, etDYNSTRING, 0, 0 },
+ { 'q', 0, 4, etSQLESCAPE, 0, 0 },
+ { 'Q', 0, 4, etSQLESCAPE2, 0, 0 },
{ 'c', 0, 0, etCHARX, 0, 0 },
{ 'o', 8, 0, etRADIX, 0, 2 },
{ 'u', 10, 0, etRADIX, 0, 0 },
@@ -296,8 +297,6 @@ static int vxprintf(
c = *++fmt;
}
}
- /* Limit the precision to prevent overflowing buf[] during conversion */
- if( precision>etBUFSIZE-40 ) precision = etBUFSIZE-40;
}else{
precision = -1;
}
@@ -328,6 +327,11 @@ static int vxprintf(
}
zExtra = 0;
+ /* Limit the precision to prevent overflowing buf[] during conversion */
+ if( precision>etBUFSIZE-40 && (infop->flags & FLAG_STRING)==0 ){
+ precision = etBUFSIZE-40;
+ }
+
/*
** At this point, variables are initialized as follows:
**
@@ -563,13 +567,15 @@ static int vxprintf(
case etSQLESCAPE2:
{
int i, j, n, c, isnull;
+ int needQuote;
char *arg = va_arg(ap,char*);
isnull = arg==0;
if( isnull ) arg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
for(i=n=0; (c=arg[i])!=0; i++){
if( c=='\'' ) n++;
}
- n += i + 1 + ((!isnull && xtype==etSQLESCAPE2) ? 2 : 0);
+ needQuote = !isnull && xtype==etSQLESCAPE2;
+ n += i + 1 + needQuote*2;
if( n>etBUFSIZE ){
bufpt = zExtra = sqliteMalloc( n );
if( bufpt==0 ) return -1;
@@ -577,12 +583,12 @@ static int vxprintf(
bufpt = buf;
}
j = 0;
- if( !isnull && xtype==etSQLESCAPE2 ) bufpt[j++] = '\'';
+ if( needQuote ) bufpt[j++] = '\'';
for(i=0; (c=arg[i])!=0; i++){
bufpt[j++] = c;
if( c=='\'' ) bufpt[j++] = c;
}
- if( !isnull && xtype==etSQLESCAPE2 ) bufpt[j++] = '\'';
+ if( needQuote ) bufpt[j++] = '\'';
bufpt[j] = 0;
length = j;
if( precision>=0 && precision<length ) length = precision;
diff --git a/ext/pdo_sqlite/sqlite/src/select.c b/ext/pdo_sqlite/sqlite/src/select.c
index 8bee789773..646134df2e 100644
--- a/ext/pdo_sqlite/sqlite/src/select.c
+++ b/ext/pdo_sqlite/sqlite/src/select.c
@@ -29,11 +29,12 @@ Select *sqlite3SelectNew(
Expr *pHaving, /* the HAVING clause */
ExprList *pOrderBy, /* the ORDER BY clause */
int isDistinct, /* true if the DISTINCT keyword is present */
- int nLimit, /* LIMIT value. -1 means not used */
- int nOffset /* OFFSET value. 0 means no offset */
+ Expr *pLimit, /* LIMIT value. NULL means not used */
+ Expr *pOffset /* OFFSET value. NULL means no offset */
){
Select *pNew;
pNew = sqliteMalloc( sizeof(*pNew) );
+ assert( !pOffset || pLimit ); /* Can't have OFFSET without LIMIT. */
if( pNew==0 ){
sqlite3ExprListDelete(pEList);
sqlite3SrcListDelete(pSrc);
@@ -41,6 +42,8 @@ Select *sqlite3SelectNew(
sqlite3ExprListDelete(pGroupBy);
sqlite3ExprDelete(pHaving);
sqlite3ExprListDelete(pOrderBy);
+ sqlite3ExprDelete(pLimit);
+ sqlite3ExprDelete(pOffset);
}else{
if( pEList==0 ){
pEList = sqlite3ExprListAppend(0, sqlite3Expr(TK_ALL,0,0,0), 0);
@@ -53,8 +56,8 @@ Select *sqlite3SelectNew(
pNew->pOrderBy = pOrderBy;
pNew->isDistinct = isDistinct;
pNew->op = TK_SELECT;
- pNew->nLimit = nLimit;
- pNew->nOffset = nOffset;
+ pNew->pLimit = pLimit;
+ pNew->pOffset = pOffset;
pNew->iLimit = -1;
pNew->iOffset = -1;
}
@@ -160,7 +163,9 @@ static void setToken(Token *p, const char *z){
static void addWhereTerm(
const char *zCol, /* Name of the column */
const Table *pTab1, /* First table */
+ const char *zAlias1, /* Alias for first table. May be NULL */
const Table *pTab2, /* Second table */
+ const char *zAlias2, /* Alias for second table. May be NULL */
Expr **ppExpr /* Add the equality term to this expression */
){
Token dummy;
@@ -171,9 +176,15 @@ static void addWhereTerm(
setToken(&dummy, zCol);
pE1a = sqlite3Expr(TK_ID, 0, 0, &dummy);
pE2a = sqlite3Expr(TK_ID, 0, 0, &dummy);
- setToken(&dummy, pTab1->zName);
+ if( zAlias1==0 ){
+ zAlias1 = pTab1->zName;
+ }
+ setToken(&dummy, zAlias1);
pE1b = sqlite3Expr(TK_ID, 0, 0, &dummy);
- setToken(&dummy, pTab2->zName);
+ if( zAlias2==0 ){
+ zAlias2 = pTab2->zName;
+ }
+ setToken(&dummy, zAlias2);
pE2b = sqlite3Expr(TK_ID, 0, 0, &dummy);
pE1c = sqlite3Expr(TK_DOT, pE1b, pE1a, 0);
pE2c = sqlite3Expr(TK_DOT, pE2b, pE2a, 0);
@@ -241,7 +252,8 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
for(j=0; j<pLeftTab->nCol; j++){
char *zName = pLeftTab->aCol[j].zName;
if( columnIndex(pRightTab, zName)>=0 ){
- addWhereTerm(zName, pLeftTab, pRightTab, &p->pWhere);
+ addWhereTerm(zName, pLeftTab, pLeft->zAlias,
+ pRightTab, pRight->zAlias, &p->pWhere);
}
}
}
@@ -279,7 +291,8 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
"not present in both tables", zName);
return 1;
}
- addWhereTerm(zName, pLeftTab, pRightTab, &p->pWhere);
+ addWhereTerm(zName, pLeftTab, pLeft->zAlias,
+ pRightTab, pRight->zAlias, &p->pWhere);
}
}
}
@@ -298,21 +311,12 @@ void sqlite3SelectDelete(Select *p){
sqlite3ExprDelete(p->pHaving);
sqlite3ExprListDelete(p->pOrderBy);
sqlite3SelectDelete(p->pPrior);
- sqliteFree(p->zSelect);
+ sqlite3ExprDelete(p->pLimit);
+ sqlite3ExprDelete(p->pOffset);
sqliteFree(p);
}
/*
-** Delete the aggregate information from the parse structure.
-*/
-static void sqliteAggregateInfoReset(Parse *pParse){
- sqliteFree(pParse->aAgg);
- pParse->aAgg = 0;
- pParse->nAgg = 0;
- pParse->useAgg = 0;
-}
-
-/*
** Insert code into "v" that will push the record on the top of the
** stack into the sorter.
*/
@@ -336,9 +340,10 @@ static void codeLimiter(
int nPop /* Number of times to pop stack when jumping */
){
if( p->iOffset>=0 ){
- int addr = sqlite3VdbeCurrentAddr(v) + 2;
+ int addr = sqlite3VdbeCurrentAddr(v) + 3;
if( nPop>0 ) addr++;
- sqlite3VdbeAddOp(v, OP_MemIncr, p->iOffset, addr);
+ sqlite3VdbeAddOp(v, OP_MemIncr, p->iOffset, 0);
+ sqlite3VdbeAddOp(v, OP_IfMemPos, p->iOffset, addr);
if( nPop>0 ){
sqlite3VdbeAddOp(v, OP_Pop, nPop, 0);
}
@@ -425,6 +430,7 @@ static int selectInnerLoop(
}
switch( eDest ){
+#ifndef SQLITE_OMIT_COMPOUND_SELECT
/* In this mode, write each query result to the key of the temporary
** table iParm.
*/
@@ -436,6 +442,20 @@ static int selectInnerLoop(
break;
}
+ /* Construct a record from the query result, but instead of
+ ** saving that record, use it as a key to delete elements from
+ ** the temporary table iParm.
+ */
+ case SRT_Except: {
+ int addr;
+ addr = sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT);
+ sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC);
+ sqlite3VdbeAddOp(v, OP_NotFound, iParm, addr+3);
+ sqlite3VdbeAddOp(v, OP_Delete, iParm, 0);
+ break;
+ }
+#endif
+
/* Store the result as data using a unique key.
*/
case SRT_Table:
@@ -451,19 +471,7 @@ static int selectInnerLoop(
break;
}
- /* Construct a record from the query result, but instead of
- ** saving that record, use it as a key to delete elements from
- ** the temporary table iParm.
- */
- case SRT_Except: {
- int addr;
- addr = sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT);
- sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC);
- sqlite3VdbeAddOp(v, OP_NotFound, iParm, addr+3);
- sqlite3VdbeAddOp(v, OP_Delete, iParm, 0);
- break;
- }
-
+#ifndef SQLITE_OMIT_SUBQUERY
/* If we are creating a set for an "expr IN (SELECT ...)" construct,
** then there should be a single item on the stack. Write this
** item into the set table with bogus data.
@@ -493,6 +501,7 @@ static int selectInnerLoop(
** store the results in the appropriate memory cell and break out
** of the scan loop.
*/
+ case SRT_Exists:
case SRT_Mem: {
assert( nColumn==1 );
if( pOrderBy ){
@@ -503,6 +512,7 @@ static int selectInnerLoop(
}
break;
}
+#endif /* #ifndef SQLITE_OMIT_SUBQUERY */
/* Send the data to the callback function.
*/
@@ -531,6 +541,7 @@ static int selectInnerLoop(
break;
}
+#if !defined(SQLITE_OMIT_TRIGGER)
/* Discard the results. This is used for SELECT statements inside
** the body of a TRIGGER. The purpose of such selects is to call
** user-defined functions that have side effects. We do not care
@@ -541,6 +552,7 @@ static int selectInnerLoop(
sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0);
break;
}
+#endif
}
return 0;
}
@@ -596,6 +608,7 @@ static void generateSortTail(
sqlite3VdbeAddOp(v, OP_PutIntKey, iParm, 0);
break;
}
+#ifndef SQLITE_OMIT_SUBQUERY
case SRT_Set: {
assert( nColumn==1 );
sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3);
@@ -606,12 +619,14 @@ static void generateSortTail(
sqlite3VdbeAddOp(v, OP_PutStrKey, (iParm&0x0000FFFF), 0);
break;
}
+ case SRT_Exists:
case SRT_Mem: {
assert( nColumn==1 );
sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1);
sqlite3VdbeAddOp(v, OP_Goto, 0, end1);
break;
}
+#endif
case SRT_Callback:
case SRT_Subroutine: {
int i;
@@ -650,18 +665,31 @@ static void generateSortTail(
** The declaration type for an expression is either TEXT, NUMERIC or ANY.
** The declaration type for a ROWID field is INTEGER.
*/
-static const char *columnType(Parse *pParse, SrcList *pTabList, Expr *pExpr){
+static const char *columnType(NameContext *pNC, Expr *pExpr){
char const *zType;
int j;
- if( pExpr==0 || pTabList==0 ) return 0;
+ if( pExpr==0 || pNC->pSrcList==0 ) return 0;
+
+ /* The TK_AS operator can only occur in ORDER BY, GROUP BY, HAVING,
+ ** and LIMIT clauses. But pExpr originates in the result set of a
+ ** SELECT. So pExpr can never contain an AS operator.
+ */
+ assert( pExpr->op!=TK_AS );
switch( pExpr->op ){
case TK_COLUMN: {
- Table *pTab;
+ Table *pTab = 0;
int iCol = pExpr->iColumn;
- for(j=0; j<pTabList->nSrc && pTabList->a[j].iCursor!=pExpr->iTable; j++){}
- assert( j<pTabList->nSrc );
- pTab = pTabList->a[j].pTab;
+ while( pNC && !pTab ){
+ SrcList *pTabList = pNC->pSrcList;
+ for(j=0;j<pTabList->nSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++);
+ if( j<pTabList->nSrc ){
+ pTab = pTabList->a[j].pTab;
+ }else{
+ pNC = pNC->pNext;
+ }
+ }
+ assert( pTab );
if( iCol<0 ) iCol = pTab->iPKey;
assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
if( iCol<0 ){
@@ -671,14 +699,16 @@ static const char *columnType(Parse *pParse, SrcList *pTabList, Expr *pExpr){
}
break;
}
- case TK_AS:
- zType = columnType(pParse, pTabList, pExpr->pLeft);
- break;
+#ifndef SQLITE_OMIT_SUBQUERY
case TK_SELECT: {
+ NameContext sNC;
Select *pS = pExpr->pSelect;
- zType = columnType(pParse, pS->pSrc, pS->pEList->a[0].pExpr);
+ sNC.pSrcList = pExpr->pSelect->pSrc;
+ sNC.pNext = pNC;
+ zType = columnType(&sNC, pS->pEList->a[0].pExpr);
break;
}
+#endif
default:
zType = 0;
}
@@ -697,9 +727,11 @@ static void generateColumnTypes(
){
Vdbe *v = pParse->pVdbe;
int i;
+ NameContext sNC;
+ sNC.pSrcList = pTabList;
for(i=0; i<pEList->nExpr; i++){
Expr *p = pEList->a[i].pExpr;
- const char *zType = columnType(pParse, pTabList, p);
+ const char *zType = columnType(&sNC, p);
if( zType==0 ) continue;
/* The vdbe must make it's own copy of the column-type, in case the
** schema is reset before this virtual machine is deleted.
@@ -723,10 +755,12 @@ static void generateColumnNames(
sqlite3 *db = pParse->db;
int fullNames, shortNames;
+#ifndef SQLITE_OMIT_EXPLAIN
/* If this is an EXPLAIN, skip this step */
if( pParse->explain ){
return;
}
+#endif
assert( v!=0 );
if( pParse->colNamesSet || v==0 || sqlite3_malloc_failed ) return;
@@ -753,7 +787,7 @@ static void generateColumnNames(
if( iCol<0 ) iCol = pTab->iPKey;
assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
if( iCol<0 ){
- zCol = "_ROWID_";
+ zCol = "rowid";
}else{
zCol = pTab->aCol[iCol].zName;
}
@@ -768,7 +802,7 @@ static void generateColumnNames(
sqlite3SetString(&zName, zTab, ".", zCol, 0);
sqlite3VdbeSetColName(v, i, zName, P3_DYNAMIC);
}else{
- sqlite3VdbeSetColName(v, i, zCol, 0);
+ sqlite3VdbeSetColName(v, i, zCol, strlen(zCol));
}
}else if( p->span.z && p->span.z[0] ){
sqlite3VdbeSetColName(v, i, p->span.z, p->span.n);
@@ -783,6 +817,7 @@ static void generateColumnNames(
generateColumnTypes(pParse, pTabList, pEList);
}
+#ifndef SQLITE_OMIT_COMPOUND_SELECT
/*
** Name of the connection operator, used for error messages.
*/
@@ -796,11 +831,12 @@ static const char *selectOpName(int id){
}
return z;
}
+#endif /* SQLITE_OMIT_COMPOUND_SELECT */
/*
** Forward declaration
*/
-static int fillInColumnList(Parse*, Select*);
+static int prepSelectStmt(Parse*, Select*);
/*
** Given a SELECT statement, generate a Table structure that describes
@@ -812,7 +848,10 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
ExprList *pEList;
Column *aCol, *pCol;
- if( fillInColumnList(pParse, pSelect) ){
+ if( prepSelectStmt(pParse, pSelect) ){
+ return 0;
+ }
+ if( sqlite3SelectResolve(pParse, pSelect, 0) ){
return 0;
}
pTab = sqliteMalloc( sizeof(Table) );
@@ -825,38 +864,55 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
assert( pTab->nCol>0 );
pTab->aCol = aCol = sqliteMalloc( sizeof(pTab->aCol[0])*pTab->nCol );
for(i=0, pCol=aCol; i<pTab->nCol; i++, pCol++){
- Expr *pR;
+ Expr *p, *pR;
char *zType;
char *zName;
- Expr *p = pEList->a[i].pExpr;
+ char *zBasename;
+ int cnt;
+ NameContext sNC;
+
+ /* Get an appropriate name for the column
+ */
+ p = pEList->a[i].pExpr;
assert( p->pRight==0 || p->pRight->token.z==0 || p->pRight->token.z[0]!=0 );
if( (zName = pEList->a[i].zName)!=0 ){
+ /* If the column contains an "AS <name>" phrase, use <name> as the name */
zName = sqliteStrDup(zName);
}else if( p->op==TK_DOT
- && (pR=p->pRight)!=0 && pR->token.z && pR->token.z[0] ){
- int cnt;
+ && (pR=p->pRight)!=0 && pR->token.z && pR->token.z[0] ){
+ /* For columns of the from A.B use B as the name */
zName = sqlite3MPrintf("%T", &pR->token);
- for(j=cnt=0; j<i; j++){
- if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){
- sqliteFree(zName);
- zName = sqlite3MPrintf("%T_%d", &pR->token, ++cnt);
- j = -1;
- }
- }
}else if( p->span.z && p->span.z[0] ){
+ /* Use the original text of the column expression as its name */
zName = sqlite3MPrintf("%T", &p->span);
}else{
+ /* If all else fails, make up a name */
zName = sqlite3MPrintf("column%d", i+1);
}
sqlite3Dequote(zName);
+
+ /* Make sure the column name is unique. If the name is not unique,
+ ** append a integer to the name so that it becomes unique.
+ */
+ zBasename = zName;
+ for(j=cnt=0; j<i; j++){
+ if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){
+ zName = sqlite3MPrintf("%s:%d", zBasename, ++cnt);
+ j = -1;
+ }
+ }
+ if( zBasename!=zName ){
+ sqliteFree(zBasename);
+ }
pCol->zName = zName;
- zType = sqliteStrDup(columnType(pParse, pSelect->pSrc ,p));
+ /* Get the typename, type affinity, and collating sequence for the
+ ** column.
+ */
+ sNC.pSrcList = pSelect->pSrc;
+ zType = sqliteStrDup(columnType(&sNC, p));
pCol->zType = zType;
- pCol->affinity = SQLITE_AFF_NUMERIC;
- if( zType ){
- pCol->affinity = sqlite3AffinityType(zType, strlen(zType));
- }
+ pCol->affinity = sqlite3ExprAffinity(p);
pCol->pColl = sqlite3ExprCollSeq(pParse, p);
if( !pCol->pColl ){
pCol->pColl = pParse->db->pDfltColl;
@@ -867,20 +923,24 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
}
/*
-** For the given SELECT statement, do three things.
+** Prepare a SELECT statement for processing by doing the following
+** things:
+**
+** (1) Make sure VDBE cursor numbers have been assigned to every
+** element of the FROM clause.
**
-** (1) Fill in the pTabList->a[].pTab fields in the SrcList that
-** defines the set of tables that should be scanned. For views,
+** (2) Fill in the pTabList->a[].pTab fields in the SrcList that
+** defines FROM clause. When views appear in the FROM clause,
** fill pTabList->a[].pSelect with a copy of the SELECT statement
** that implements the view. A copy is made of the view's SELECT
** statement so that we can freely modify or delete that statement
** without worrying about messing up the presistent representation
** of the view.
**
-** (2) Add terms to the WHERE clause to accomodate the NATURAL keyword
+** (3) Add terms to the WHERE clause to accomodate the NATURAL keyword
** on joins and the ON and USING clause of joins.
**
-** (3) Scan the list of columns in the result set (pEList) looking
+** (4) Scan the list of columns in the result set (pEList) looking
** for instances of the "*" operator or the TABLE.* operator.
** If found, expand each "*" to be every column in every table
** and TABLE.* to be every column in TABLE.
@@ -888,7 +948,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
** Return 0 on success. If there are problems, leave an error message
** in pParse and return non-zero.
*/
-static int fillInColumnList(Parse *pParse, Select *p){
+static int prepSelectStmt(Parse *pParse, Select *p){
int i, j, k, rc;
SrcList *pTabList;
ExprList *pEList;
@@ -899,14 +959,24 @@ static int fillInColumnList(Parse *pParse, Select *p){
pTabList = p->pSrc;
pEList = p->pEList;
- /* Look up every table in the table list.
+ /* Make sure cursor numbers have been assigned to all entries in
+ ** the FROM clause of the SELECT statement.
+ */
+ sqlite3SrcListAssignCursors(pParse, p->pSrc);
+
+ /* Look up every table named in the FROM clause of the select. If
+ ** an entry of the FROM clause is a subquery instead of a table or view,
+ ** then create a transient table structure to describe the subquery.
*/
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
- if( pFrom->pTab ){
- /* This routine has run before! No need to continue */
+ if( pFrom->pTab!=0 ){
+ /* This statement has already been prepared. There is no need
+ ** to go further. */
+ assert( i==0 );
return 0;
}
if( pFrom->zName==0 ){
+#ifndef SQLITE_OMIT_SUBQUERY
/* A sub-query in the FROM clause of a SELECT */
assert( pFrom->pSelect!=0 );
if( pFrom->zAlias==0 ){
@@ -923,6 +993,7 @@ static int fillInColumnList(Parse *pParse, Select *p){
** pTab is not pointing to a persistent table structure that defines
** part of the schema. */
pTab->isTransient = 1;
+#endif
}else{
/* An ordinary table or view name in the FROM clause */
pFrom->pTab = pTab =
@@ -930,6 +1001,7 @@ static int fillInColumnList(Parse *pParse, Select *p){
if( pTab==0 ){
return 1;
}
+#ifndef SQLITE_OMIT_VIEW
if( pTab->pSelect ){
/* We reach here if the named table is a really a view */
if( sqlite3ViewGetColumnNames(pParse, pTab) ){
@@ -944,6 +1016,7 @@ static int fillInColumnList(Parse *pParse, Select *p){
pFrom->pSelect = sqlite3SelectDup(pTab->pSelect);
}
}
+#endif
}
}
@@ -1042,7 +1115,7 @@ static int fillInColumnList(Parse *pParse, Select *p){
pExpr = pRight;
pExpr->span = pExpr->token;
}
- pNew = sqlite3ExprListAppend(pNew, pExpr, 0);
+ pNew = sqlite3ExprListAppend(pNew, pExpr, &pRight->token);
}
}
if( !tableSeen ){
@@ -1075,6 +1148,7 @@ static int fillInColumnList(Parse *pParse, Select *p){
** will be left pointing to a deallocated Table structure after the
** DROP and a coredump will occur the next time the VIEW is used.
*/
+#if 0
void sqlite3SelectUnbind(Select *p){
int i;
SrcList *pSrc = p->pSrc;
@@ -1093,7 +1167,9 @@ void sqlite3SelectUnbind(Select *p){
}
}
}
+#endif
+#ifndef SQLITE_OMIT_COMPOUND_SELECT
/*
** This routine associates entries in an ORDER BY expression list with
** columns in a result. For each ORDER BY expression, the opcode of
@@ -1122,7 +1198,7 @@ static int matchOrderbyToColumn(
if( mustComplete ){
for(i=0; i<pOrderBy->nExpr; i++){ pOrderBy->a[i].done = 0; }
}
- if( fillInColumnList(pParse, pSelect) ){
+ if( prepSelectStmt(pParse, pSelect) ){
return 1;
}
if( pSelect->pPrior ){
@@ -1165,6 +1241,7 @@ static int matchOrderbyToColumn(
pE->op = TK_COLUMN;
pE->iColumn = iCol;
pE->iTable = iTable;
+ pE->iAgg = -1;
pOrderBy->a[i].done = 1;
}
if( iCol<0 && mustComplete ){
@@ -1176,6 +1253,7 @@ static int matchOrderbyToColumn(
}
return nErr;
}
+#endif /* #ifndef SQLITE_OMIT_COMPOUND_SELECT */
/*
** Get a VDBE for the given parser context. Create a new one if necessary.
@@ -1191,12 +1269,12 @@ Vdbe *sqlite3GetVdbe(Parse *pParse){
/*
** Compute the iLimit and iOffset fields of the SELECT based on the
-** nLimit and nOffset fields. nLimit and nOffset hold the integers
+** pLimit and pOffset expressions. nLimit and nOffset hold the expressions
** that appear in the original SQL statement after the LIMIT and OFFSET
-** keywords. Or that hold -1 and 0 if those keywords are omitted.
-** iLimit and iOffset are the integer memory register numbers for
-** counters used to compute the limit and offset. If there is no
-** limit and/or offset, then iLimit and iOffset are negative.
+** keywords. Or NULL if those keywords are omitted. iLimit and iOffset
+** are the integer memory register numbers for counters used to compute
+** the limit and offset. If there is no limit and/or offset, then
+** iLimit and iOffset are negative.
**
** This routine changes the values if iLimit and iOffset only if
** a limit or offset is defined by nLimit and nOffset. iLimit and
@@ -1209,28 +1287,29 @@ Vdbe *sqlite3GetVdbe(Parse *pParse){
*/
static void computeLimitRegisters(Parse *pParse, Select *p){
/*
- ** If the comparison is p->nLimit>0 then "LIMIT 0" shows
- ** all rows. It is the same as no limit. If the comparision is
- ** p->nLimit>=0 then "LIMIT 0" show no rows at all.
** "LIMIT -1" always shows all rows. There is some
** contraversy about what the correct behavior should be.
** The current implementation interprets "LIMIT 0" to mean
** no rows.
*/
- if( p->nLimit>=0 ){
+ if( p->pLimit ){
int iMem = pParse->nMem++;
Vdbe *v = sqlite3GetVdbe(pParse);
if( v==0 ) return;
- sqlite3VdbeAddOp(v, OP_Integer, -p->nLimit, 0);
+ sqlite3ExprCode(pParse, p->pLimit);
+ sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
+ sqlite3VdbeAddOp(v, OP_Negative, 0, 0);
sqlite3VdbeAddOp(v, OP_MemStore, iMem, 1);
VdbeComment((v, "# LIMIT counter"));
p->iLimit = iMem;
}
- if( p->nOffset>0 ){
+ if( p->pOffset ){
int iMem = pParse->nMem++;
Vdbe *v = sqlite3GetVdbe(pParse);
if( v==0 ) return;
- sqlite3VdbeAddOp(v, OP_Integer, -p->nOffset, 0);
+ sqlite3ExprCode(pParse, p->pOffset);
+ sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
+ sqlite3VdbeAddOp(v, OP_Negative, 0, 0);
sqlite3VdbeAddOp(v, OP_MemStore, iMem, 1);
VdbeComment((v, "# OFFSET counter"));
p->iOffset = iMem;
@@ -1260,7 +1339,7 @@ static int openTempIndex(Parse *pParse, Select *p, int iTab, int keyAsData){
Vdbe *v = pParse->pVdbe;
int addr;
- if( fillInColumnList(pParse, p) ){
+ if( prepSelectStmt(pParse, p) ){
return 0;
}
nColumn = p->pEList->nExpr;
@@ -1282,6 +1361,7 @@ static int openTempIndex(Parse *pParse, Select *p, int iTab, int keyAsData){
return addr;
}
+#ifndef SQLITE_OMIT_COMPOUND_SELECT
/*
** Add the address "addr" to the set of all OpenTemp opcode addresses
** that are being accumulated in p->ppOpenTemp.
@@ -1294,7 +1374,9 @@ static int multiSelectOpenTempAddr(Select *p, int addr){
pList->a[pList->nId-1].idx = addr;
return SQLITE_OK;
}
+#endif /* SQLITE_OMIT_COMPOUND_SELECT */
+#ifndef SQLITE_OMIT_COMPOUND_SELECT
/*
** Return the appropriate collating sequence for the iCol-th column of
** the result set for the compound-select statement "p". Return NULL if
@@ -1315,7 +1397,9 @@ static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){
}
return pRet;
}
+#endif /* SQLITE_OMIT_COMPOUND_SELECT */
+#ifndef SQLITE_OMIT_COMPOUND_SELECT
/*
** This routine is called to process a query that is really the union
** or intersection of two or more separate queries.
@@ -1375,7 +1459,7 @@ static int multiSelect(
rc = 1;
goto multi_select_end;
}
- if( pPrior->nLimit>=0 || pPrior->nOffset>0 ){
+ if( pPrior->pLimit ){
sqlite3ErrorMsg(pParse,"LIMIT clause should come after %s not before",
selectOpName(p->op));
rc = 1;
@@ -1416,8 +1500,9 @@ static int multiSelect(
switch( p->op ){
case TK_ALL: {
if( p->pOrderBy==0 ){
- pPrior->nLimit = p->nLimit;
- pPrior->nOffset = p->nOffset;
+ assert( !pPrior->pLimit );
+ pPrior->pLimit = p->pLimit;
+ pPrior->pOffset = p->pOffset;
rc = sqlite3Select(pParse, pPrior, eDest, iParm, 0, 0, 0, aff);
if( rc ){
goto multi_select_end;
@@ -1425,8 +1510,8 @@ static int multiSelect(
p->pPrior = 0;
p->iLimit = pPrior->iLimit;
p->iOffset = pPrior->iOffset;
- p->nLimit = -1;
- p->nOffset = 0;
+ p->pLimit = 0;
+ p->pOffset = 0;
rc = sqlite3Select(pParse, p, eDest, iParm, 0, 0, 0, aff);
p->pPrior = pPrior;
if( rc ){
@@ -1441,12 +1526,12 @@ static int multiSelect(
int unionTab; /* Cursor number of the temporary table holding result */
int op = 0; /* One of the SRT_ operations to apply to self */
int priorOp; /* The SRT_ operation to apply to prior selects */
- int nLimit, nOffset; /* Saved values of p->nLimit and p->nOffset */
- ExprList *pOrderBy; /* The ORDER BY clause for the right SELECT */
+ Expr *pLimit, *pOffset; /* Saved values of p->nLimit and p->nOffset */
+ ExprList *pOrderBy; /* The ORDER BY clause for the right SELECT */
int addr;
priorOp = p->op==TK_ALL ? SRT_Table : SRT_Union;
- if( eDest==priorOp && p->pOrderBy==0 && p->nLimit<0 && p->nOffset==0 ){
+ if( eDest==priorOp && p->pOrderBy==0 && !p->pLimit && !p->pOffset ){
/* We can reuse a temporary table generated by a SELECT to our
** right.
*/
@@ -1476,6 +1561,7 @@ static int multiSelect(
/* Code the SELECT statements to our left
*/
+ assert( !pPrior->pOrderBy );
rc = sqlite3Select(pParse, pPrior, priorOp, unionTab, 0, 0, 0, aff);
if( rc ){
goto multi_select_end;
@@ -1491,15 +1577,18 @@ static int multiSelect(
p->pPrior = 0;
pOrderBy = p->pOrderBy;
p->pOrderBy = 0;
- nLimit = p->nLimit;
- p->nLimit = -1;
- nOffset = p->nOffset;
- p->nOffset = 0;
+ pLimit = p->pLimit;
+ p->pLimit = 0;
+ pOffset = p->pOffset;
+ p->pOffset = 0;
rc = sqlite3Select(pParse, p, op, unionTab, 0, 0, 0, aff);
p->pPrior = pPrior;
p->pOrderBy = pOrderBy;
- p->nLimit = nLimit;
- p->nOffset = nOffset;
+ sqlite3ExprDelete(p->pLimit);
+ p->pLimit = pLimit;
+ p->pOffset = pOffset;
+ p->iLimit = -1;
+ p->iOffset = -1;
if( rc ){
goto multi_select_end;
}
@@ -1536,7 +1625,7 @@ static int multiSelect(
case TK_INTERSECT: {
int tab1, tab2;
int iCont, iBreak, iStart;
- int nLimit, nOffset;
+ Expr *pLimit, *pOffset;
int addr;
/* INTERSECT is different from the others since it requires
@@ -1578,14 +1667,15 @@ static int multiSelect(
assert( nAddr<sizeof(aAddr)/sizeof(aAddr[0]) );
aAddr[nAddr++] = sqlite3VdbeAddOp(v, OP_SetNumColumns, tab2, 0);
p->pPrior = 0;
- nLimit = p->nLimit;
- p->nLimit = -1;
- nOffset = p->nOffset;
- p->nOffset = 0;
+ pLimit = p->pLimit;
+ p->pLimit = 0;
+ pOffset = p->pOffset;
+ p->pOffset = 0;
rc = sqlite3Select(pParse, p, SRT_Union, tab2, 0, 0, 0, aff);
p->pPrior = pPrior;
- p->nLimit = nLimit;
- p->nOffset = nOffset;
+ sqlite3ExprDelete(p->pLimit);
+ p->pLimit = pLimit;
+ p->pOffset = pOffset;
if( rc ){
goto multi_select_end;
}
@@ -1681,7 +1771,7 @@ static int multiSelect(
Expr *pExpr = pOrderByTerm->pExpr;
char *zName = pOrderByTerm->zName;
assert( pExpr->op==TK_COLUMN && pExpr->iColumn<nCol );
- assert( !pExpr->pColl );
+ /* assert( !pExpr->pColl ); */
if( zName ){
pExpr->pColl = sqlite3LocateCollSeq(pParse, zName, -1);
}else{
@@ -1704,7 +1794,9 @@ multi_select_end:
p->ppOpenTemp = 0;
return rc;
}
+#endif /* SQLITE_OMIT_COMPOUND_SELECT */
+#ifndef SQLITE_OMIT_VIEW
/*
** Scan through the expression pExpr. Replace every reference to
** a column in table number iTable with a copy of the iColumn-th
@@ -1719,6 +1811,7 @@ multi_select_end:
** of the subquery rather the result set of the subquery.
*/
static void substExprList(ExprList*,int,ExprList*); /* Forward Decl */
+static void substSelect(Select *, int, ExprList *); /* Forward Decl */
static void substExpr(Expr *pExpr, int iTable, ExprList *pEList){
if( pExpr==0 ) return;
if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){
@@ -1742,22 +1835,34 @@ static void substExpr(Expr *pExpr, int iTable, ExprList *pEList){
pExpr->iAgg = pNew->iAgg;
sqlite3TokenCopy(&pExpr->token, &pNew->token);
sqlite3TokenCopy(&pExpr->span, &pNew->span);
+ pExpr->pSelect = sqlite3SelectDup(pNew->pSelect);
+ pExpr->flags = pNew->flags;
}
}else{
substExpr(pExpr->pLeft, iTable, pEList);
substExpr(pExpr->pRight, iTable, pEList);
+ substSelect(pExpr->pSelect, iTable, pEList);
substExprList(pExpr->pList, iTable, pEList);
}
}
-static void
-substExprList(ExprList *pList, int iTable, ExprList *pEList){
+static void substExprList(ExprList *pList, int iTable, ExprList *pEList){
int i;
if( pList==0 ) return;
for(i=0; i<pList->nExpr; i++){
substExpr(pList->a[i].pExpr, iTable, pEList);
}
}
+static void substSelect(Select *p, int iTable, ExprList *pEList){
+ if( !p ) return;
+ substExprList(p->pEList, iTable, pEList);
+ substExprList(p->pGroupBy, iTable, pEList);
+ substExprList(p->pOrderBy, iTable, pEList);
+ substExpr(p->pHaving, iTable, pEList);
+ substExpr(p->pWhere, iTable, pEList);
+}
+#endif /* !defined(SQLITE_OMIT_VIEW) */
+#ifndef SQLITE_OMIT_VIEW
/*
** This routine attempts to flatten subqueries in order to speed
** execution. It returns 1 if it makes changes and 0 if no flattening
@@ -1855,11 +1960,13 @@ static int flattenSubquery(
if( subqueryIsAgg && pSrc->nSrc>1 ) return 0;
pSubSrc = pSub->pSrc;
assert( pSubSrc );
+ if( (pSub->pLimit && p->pLimit) || pSub->pOffset ||
+ (pSub->pLimit && isAgg) ) return 0;
if( pSubSrc->nSrc==0 ) return 0;
- if( (pSub->isDistinct || pSub->nLimit>=0) && (pSrc->nSrc>1 || isAgg) ){
+ if( pSub->isDistinct && (pSrc->nSrc>1 || isAgg) ){
return 0;
}
- if( (p->isDistinct || p->nLimit>=0) && subqueryIsAgg ) return 0;
+ if( p->isDistinct && subqueryIsAgg ) return 0;
if( p->pOrderBy && pSub->pOrderBy ) return 0;
/* Restriction 3: If the subquery is a join, make sure the subquery is
@@ -1991,17 +2098,13 @@ static int flattenSubquery(
*/
p->isDistinct = p->isDistinct || pSub->isDistinct;
- /* Transfer the limit expression from the subquery to the outer
- ** query.
+ /*
+ ** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y;
*/
- if( pSub->nLimit>=0 ){
- if( p->nLimit<0 ){
- p->nLimit = pSub->nLimit;
- }else if( p->nLimit+p->nOffset > pSub->nLimit+pSub->nOffset ){
- p->nLimit = pSub->nLimit + pSub->nOffset - p->nOffset;
- }
+ if( pSub->pLimit ){
+ p->pLimit = pSub->pLimit;
+ pSub->pLimit = 0;
}
- p->nOffset += pSub->nOffset;
/* Finially, delete what is left of the subquery and return
** success.
@@ -2009,6 +2112,7 @@ static int flattenSubquery(
sqlite3SelectDelete(pSub);
return 1;
}
+#endif /* SQLITE_OMIT_VIEW */
/*
** Analyze the SELECT statement passed in as an argument to see if it
@@ -2042,7 +2146,6 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
ExprList *pEList, *pList, eList;
struct ExprList_item eListItem;
SrcList *pSrc;
-
/* Check to see if this query is a simple min() or max() query. Return
** zero if it is not.
@@ -2115,17 +2218,25 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
if( pIdx==0 ){
sqlite3VdbeAddOp(v, seekOp, base, 0);
}else{
+ /* Even though the cursor used to open the index here is closed
+ ** as soon as a single value has been read from it, allocate it
+ ** using (pParse->nTab++) to prevent the cursor id from being
+ ** reused. This is important for statements of the form
+ ** "INSERT INTO x SELECT max() FROM x".
+ */
+ int iIdx;
+ iIdx = pParse->nTab++;
sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
- sqlite3VdbeOp3(v, OP_OpenRead, base+1, pIdx->tnum,
+ sqlite3VdbeOp3(v, OP_OpenRead, iIdx, pIdx->tnum,
(char*)&pIdx->keyInfo, P3_KEYINFO);
if( seekOp==OP_Rewind ){
sqlite3VdbeAddOp(v, OP_String, 0, 0);
sqlite3VdbeAddOp(v, OP_MakeRecord, 1, 0);
seekOp = OP_MoveGt;
}
- sqlite3VdbeAddOp(v, seekOp, base+1, 0);
- sqlite3VdbeAddOp(v, OP_IdxRecno, base+1, 0);
- sqlite3VdbeAddOp(v, OP_Close, base+1, 0);
+ sqlite3VdbeAddOp(v, seekOp, iIdx, 0);
+ sqlite3VdbeAddOp(v, OP_IdxRecno, iIdx, 0);
+ sqlite3VdbeAddOp(v, OP_Close, iIdx, 0);
sqlite3VdbeAddOp(v, OP_MoveGe, base, 0);
}
eList.nExpr = 1;
@@ -2148,42 +2259,194 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
** corresponding entry in the result set.
*/
static int processOrderGroupBy(
- Parse *pParse, /* Parsing context */
+ NameContext *pNC, /* Name context of the SELECT statement. */
ExprList *pOrderBy, /* The ORDER BY or GROUP BY clause to be processed */
- SrcList *pTabList, /* The FROM clause */
- ExprList *pEList, /* The result set */
- int isAgg, /* True if aggregate functions are involved */
const char *zType /* Either "ORDER" or "GROUP", as appropriate */
){
int i;
+ ExprList *pEList = pNC->pEList; /* The result set of the SELECT */
+ Parse *pParse = pNC->pParse; /* The result set of the SELECT */
+ assert( pEList );
+
if( pOrderBy==0 ) return 0;
for(i=0; i<pOrderBy->nExpr; i++){
int iCol;
Expr *pE = pOrderBy->a[i].pExpr;
- if( sqlite3ExprIsInteger(pE, &iCol) && iCol>0 && iCol<=pEList->nExpr ){
- sqlite3ExprDelete(pE);
- pE = pOrderBy->a[i].pExpr = sqlite3ExprDup(pEList->a[iCol-1].pExpr);
- }
- if( sqlite3ExprResolveAndCheck(pParse, pTabList, pEList, pE, isAgg, 0) ){
- return 1;
- }
- if( sqlite3ExprIsConstant(pE) ){
- if( sqlite3ExprIsInteger(pE, &iCol)==0 ){
- sqlite3ErrorMsg(pParse,
- "%s BY terms must not be non-integer constants", zType);
- return 1;
- }else if( iCol<=0 || iCol>pEList->nExpr ){
+ if( sqlite3ExprIsInteger(pE, &iCol) ){
+ if( iCol>0 && iCol<=pEList->nExpr ){
+ sqlite3ExprDelete(pE);
+ pE = pOrderBy->a[i].pExpr = sqlite3ExprDup(pEList->a[iCol-1].pExpr);
+ }else{
sqlite3ErrorMsg(pParse,
"%s BY column number %d out of range - should be "
"between 1 and %d", zType, iCol, pEList->nExpr);
return 1;
}
}
+ if( sqlite3ExprResolveNames(pNC, pE) ){
+ return 1;
+ }
+ if( sqlite3ExprIsConstant(pE) ){
+ sqlite3ErrorMsg(pParse,
+ "%s BY terms must not be non-integer constants", zType);
+ return 1;
+ }
}
return 0;
}
/*
+** This routine resolves any names used in the result set of the
+** supplied SELECT statement. If the SELECT statement being resolved
+** is a sub-select, then pOuterNC is a pointer to the NameContext
+** of the parent SELECT.
+*/
+int sqlite3SelectResolve(
+ Parse *pParse, /* The parser context */
+ Select *p, /* The SELECT statement being coded. */
+ NameContext *pOuterNC /* The outer name context. May be NULL. */
+){
+ ExprList *pEList; /* Result set. */
+ int i; /* For-loop variable used in multiple places */
+ NameContext sNC; /* Local name-context */
+
+ /* If this routine has run before, return immediately. */
+ if( p->isResolved ){
+ assert( !pOuterNC );
+ return SQLITE_OK;
+ }
+ p->isResolved = 1;
+
+ /* If there have already been errors, do nothing. */
+ if( pParse->nErr>0 ){
+ return SQLITE_ERROR;
+ }
+
+ /* Prepare the select statement. This call will allocate all cursors
+ ** required to handle the tables and subqueries in the FROM clause.
+ */
+ if( prepSelectStmt(pParse, p) ){
+ return SQLITE_ERROR;
+ }
+
+ /* Resolve the expressions in the LIMIT and OFFSET clauses. These
+ ** are not allowed to refer to any names, so pass an empty NameContext.
+ */
+ sNC.pParse = pParse;
+ sNC.hasAgg = 0;
+ sNC.nErr = 0;
+ sNC.nRef = 0;
+ sNC.pEList = 0;
+ sNC.allowAgg = 0;
+ sNC.pSrcList = 0;
+ sNC.pNext = 0;
+ if( sqlite3ExprResolveNames(&sNC, p->pLimit) ||
+ sqlite3ExprResolveNames(&sNC, p->pOffset) ){
+ return SQLITE_ERROR;
+ }
+
+ /* Set up the local name-context to pass to ExprResolveNames() to
+ ** resolve the expression-list.
+ */
+ sNC.allowAgg = 1;
+ sNC.pSrcList = p->pSrc;
+ sNC.pNext = pOuterNC;
+
+ /* NameContext.nDepth stores the depth of recursion for this query. For
+ ** an outer query (e.g. SELECT * FROM sqlite_master) this is 1. For
+ ** a subquery it is 2. For a subquery of a subquery, 3. And so on.
+ ** Parse.nMaxDepth is the maximum depth for any subquery resolved so
+ ** far. This is used to determine the number of aggregate contexts
+ ** required at runtime.
+ */
+ sNC.nDepth = (pOuterNC?pOuterNC->nDepth+1:1);
+ if( sNC.nDepth>pParse->nMaxDepth ){
+ pParse->nMaxDepth = sNC.nDepth;
+ }
+
+ /* Resolve names in the result set. */
+ pEList = p->pEList;
+ if( !pEList ) return SQLITE_ERROR;
+ for(i=0; i<pEList->nExpr; i++){
+ Expr *pX = pEList->a[i].pExpr;
+ if( sqlite3ExprResolveNames(&sNC, pX) ){
+ return SQLITE_ERROR;
+ }
+ }
+
+ /* If there are no aggregate functions in the result-set, and no GROUP BY
+ ** expression, do not allow aggregates in any of the other expressions.
+ */
+ assert( !p->isAgg );
+ if( p->pGroupBy || sNC.hasAgg ){
+ p->isAgg = 1;
+ }else{
+ sNC.allowAgg = 0;
+ }
+
+ /* If a HAVING clause is present, then there must be a GROUP BY clause.
+ */
+ if( p->pHaving && !p->pGroupBy ){
+ sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
+ return SQLITE_ERROR;
+ }
+
+ /* Add the expression list to the name-context before parsing the
+ ** other expressions in the SELECT statement. This is so that
+ ** expressions in the WHERE clause (etc.) can refer to expressions by
+ ** aliases in the result set.
+ **
+ ** Minor point: If this is the case, then the expression will be
+ ** re-evaluated for each reference to it.
+ */
+ sNC.pEList = p->pEList;
+ if( sqlite3ExprResolveNames(&sNC, p->pWhere) ||
+ sqlite3ExprResolveNames(&sNC, p->pHaving) ||
+ processOrderGroupBy(&sNC, p->pOrderBy, "ORDER") ||
+ processOrderGroupBy(&sNC, p->pGroupBy, "GROUP")
+ ){
+ return SQLITE_ERROR;
+ }
+
+ return SQLITE_OK;
+}
+
+/*
+** An instance of the following struct is used by sqlite3Select()
+** to save aggregate related information from the Parse object
+** at the start of each call and to restore it at the end. See
+** saveAggregateInfo() and restoreAggregateInfo().
+*/
+struct AggregateInfo {
+ int nAgg;
+ AggExpr *aAgg;
+};
+typedef struct AggregateInfo AggregateInfo;
+
+/*
+** Copy aggregate related information from the Parse structure
+** into the AggregateInfo structure. Zero the aggregate related
+** values in the Parse struct.
+*/
+static void saveAggregateInfo(Parse *pParse, AggregateInfo *pInfo){
+ pInfo->aAgg = pParse->aAgg;
+ pInfo->nAgg = pParse->nAgg;
+ pParse->aAgg = 0;
+ pParse->nAgg = 0;
+}
+
+/*
+** Copy aggregate related information from the AggregateInfo struct
+** back into the Parse structure. The aggregate related information
+** currently stored in the Parse structure is deleted.
+*/
+static void restoreAggregateInfo(Parse *pParse, AggregateInfo *pInfo){
+ sqliteFree(pParse->aAgg);
+ pParse->aAgg = pInfo->aAgg;
+ pParse->nAgg = pInfo->nAgg;
+}
+
+/*
** Generate code for the given SELECT statement.
**
** The results are distributed in various ways depending on the
@@ -2248,7 +2511,7 @@ int sqlite3Select(
int i;
WhereInfo *pWInfo;
Vdbe *v;
- int isAgg = 0; /* True for select lists like "count(*)" */
+ int isAgg; /* True for select lists like "count(*)" */
ExprList *pEList; /* List of columns to extract. */
SrcList *pTabList; /* List of tables to select from */
Expr *pWhere; /* The WHERE clause. May be NULL */
@@ -2258,28 +2521,39 @@ int sqlite3Select(
int isDistinct; /* True if the DISTINCT keyword is present */
int distinct; /* Table to use for the distinct set */
int rc = 1; /* Value to return from this function */
+ AggregateInfo sAggInfo;
if( sqlite3_malloc_failed || pParse->nErr || p==0 ) return 1;
if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
+#ifndef SQLITE_OMIT_COMPOUND_SELECT
/* If there is are a sequence of queries, do the earlier ones first.
*/
if( p->pPrior ){
return multiSelect(pParse, p, eDest, iParm, aff);
}
+#endif
+
+ saveAggregateInfo(pParse, &sAggInfo);
+ pOrderBy = p->pOrderBy;
+ if( eDest==SRT_Union || eDest==SRT_Except || eDest==SRT_Discard ){
+ p->pOrderBy = 0;
+ }
+ if( sqlite3SelectResolve(pParse, p, 0) ){
+ goto select_end;
+ }
+ p->pOrderBy = pOrderBy;
/* Make local copies of the parameters for this query.
*/
pTabList = p->pSrc;
pWhere = p->pWhere;
- pOrderBy = p->pOrderBy;
pGroupBy = p->pGroupBy;
pHaving = p->pHaving;
+ isAgg = p->isAgg;
isDistinct = p->isDistinct;
-
- /* Allocate VDBE cursors for each table in the FROM clause
- */
- sqlite3SrcListAssignCursors(pParse, pTabList);
+ pEList = p->pEList;
+ if( pEList==0 ) goto select_end;
/*
** Do not even attempt to generate any code if we have already seen
@@ -2287,25 +2561,17 @@ int sqlite3Select(
*/
if( pParse->nErr>0 ) goto select_end;
- /* Expand any "*" terms in the result set. (For example the "*" in
- ** "SELECT * FROM t1") The fillInColumnlist() routine also does some
- ** other housekeeping - see the header comment for details.
- */
- if( fillInColumnList(pParse, p) ){
- goto select_end;
- }
- pWhere = p->pWhere;
- pEList = p->pEList;
- if( pEList==0 ) goto select_end;
-
/* If writing to memory or generating a set
** only a single column may be output.
*/
+ assert( eDest!=SRT_Exists || pEList->nExpr==1 );
+#ifndef SQLITE_OMIT_SUBQUERY
if( (eDest==SRT_Mem || eDest==SRT_Set) && pEList->nExpr>1 ){
sqlite3ErrorMsg(pParse, "only a single result allowed for "
"a SELECT that is part of an expression");
goto select_end;
}
+#endif
/* ORDER BY is ignored for some destinations.
*/
@@ -2319,35 +2585,6 @@ int sqlite3Select(
break;
}
- /* At this point, we should have allocated all the cursors that we
- ** need to handle subquerys and temporary tables.
- **
- ** Resolve the column names and do a semantics check on all the expressions.
- */
- for(i=0; i<pEList->nExpr; i++){
- if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0, pEList->a[i].pExpr,
- 1, &isAgg) ){
- goto select_end;
- }
- }
- if( sqlite3ExprResolveAndCheck(pParse, pTabList, pEList, pWhere, 0, 0) ){
- goto select_end;
- }
- if( pHaving ){
- if( pGroupBy==0 ){
- sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
- goto select_end;
- }
- if( sqlite3ExprResolveAndCheck(pParse, pTabList, pEList,pHaving,1,&isAgg) ){
- goto select_end;
- }
- }
- if( processOrderGroupBy(pParse, pOrderBy, pTabList, pEList, isAgg, "ORDER")
- || processOrderGroupBy(pParse, pGroupBy, pTabList, pEList, isAgg, "GROUP")
- ){
- goto select_end;
- }
-
/* Begin generating code.
*/
v = sqlite3GetVdbe(pParse);
@@ -2362,6 +2599,7 @@ int sqlite3Select(
/* Generate code for all sub-queries in the FROM clause
*/
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
for(i=0; i<pTabList->nSrc; i++){
const char *zSavedAuthContext = 0;
int needRestoreContext;
@@ -2388,6 +2626,7 @@ int sqlite3Select(
pHaving = p->pHaving;
isDistinct = p->isDistinct;
}
+#endif
/* Check for the special case of a min() or max() function by itself
** in the result set.
@@ -2400,11 +2639,13 @@ int sqlite3Select(
/* Check to see if this is a subquery that can be "flattened" into its parent.
** If flattening is a possiblity, do so and return immediately.
*/
+#ifndef SQLITE_OMIT_VIEW
if( pParent && pParentAgg &&
flattenSubquery(pParse, pParent, parentTab, *pParentAgg, isAgg) ){
if( isAgg ) *pParentAgg = 1;
- return rc;
+ goto select_end;
}
+#endif
/* If there is an ORDER BY clause, resolve any collation sequences
** names that have been explicitly specified.
@@ -2434,28 +2675,32 @@ int sqlite3Select(
/* Do an analysis of aggregate expressions.
*/
- sqliteAggregateInfoReset(pParse);
if( isAgg || pGroupBy ){
+ NameContext sNC;
+ memset(&sNC, 0, sizeof(sNC));
+ sNC.pParse = pParse;
+ sNC.pSrcList = pTabList;
+
assert( pParse->nAgg==0 );
isAgg = 1;
for(i=0; i<pEList->nExpr; i++){
- if( sqlite3ExprAnalyzeAggregates(pParse, pEList->a[i].pExpr) ){
+ if( sqlite3ExprAnalyzeAggregates(&sNC, pEList->a[i].pExpr) ){
goto select_end;
}
}
if( pGroupBy ){
for(i=0; i<pGroupBy->nExpr; i++){
- if( sqlite3ExprAnalyzeAggregates(pParse, pGroupBy->a[i].pExpr) ){
+ if( sqlite3ExprAnalyzeAggregates(&sNC, pGroupBy->a[i].pExpr) ){
goto select_end;
}
}
}
- if( pHaving && sqlite3ExprAnalyzeAggregates(pParse, pHaving) ){
+ if( pHaving && sqlite3ExprAnalyzeAggregates(&sNC, pHaving) ){
goto select_end;
}
if( pOrderBy ){
for(i=0; i<pOrderBy->nExpr; i++){
- if( sqlite3ExprAnalyzeAggregates(pParse, pOrderBy->a[i].pExpr) ){
+ if( sqlite3ExprAnalyzeAggregates(&sNC, pOrderBy->a[i].pExpr) ){
goto select_end;
}
}
@@ -2490,10 +2735,10 @@ int sqlite3Select(
}
}
- /* Initialize the memory cell to NULL
+ /* Initialize the memory cell to NULL for SRT_Mem or 0 for SRT_Exists
*/
- if( eDest==SRT_Mem ){
- sqlite3VdbeAddOp(v, OP_String8, 0, 0);
+ if( eDest==SRT_Mem || eDest==SRT_Exists ){
+ sqlite3VdbeAddOp(v, eDest==SRT_Mem ? OP_String8 : OP_Integer, 0, 0);
sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1);
}
@@ -2508,8 +2753,8 @@ int sqlite3Select(
/* Begin the database scan
*/
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0,
- pGroupBy ? 0 : &pOrderBy);
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,
+ pGroupBy ? 0 : &pOrderBy, p->pFetch);
if( pWInfo==0 ) goto select_end;
/* Use the standard inner loop if we are not dealing with
@@ -2527,8 +2772,9 @@ int sqlite3Select(
*/
else{
AggExpr *pAgg;
+ int lbl1 = 0;
+ pParse->fillAgg = 1;
if( pGroupBy ){
- int lbl1;
for(i=0; i<pGroupBy->nExpr; i++){
sqlite3ExprCode(pParse, pGroupBy->a[i].pExpr);
}
@@ -2537,11 +2783,14 @@ int sqlite3Select(
sqlite3VdbeAddOp(v, OP_MakeRecord, pGroupBy->nExpr, 0);
lbl1 = sqlite3VdbeMakeLabel(v);
sqlite3VdbeAddOp(v, OP_AggFocus, 0, lbl1);
- for(i=0, pAgg=pParse->aAgg; i<pParse->nAgg; i++, pAgg++){
- if( pAgg->isAgg ) continue;
- sqlite3ExprCode(pParse, pAgg->pExpr);
- sqlite3VdbeAddOp(v, OP_AggSet, 0, i);
- }
+ }
+ for(i=0, pAgg=pParse->aAgg; i<pParse->nAgg; i++, pAgg++){
+ if( pAgg->isAgg ) continue;
+ sqlite3ExprCode(pParse, pAgg->pExpr);
+ sqlite3VdbeAddOp(v, OP_AggSet, 0, i);
+ }
+ pParse->fillAgg = 0;
+ if( lbl1<0 ){
sqlite3VdbeResolveLabel(v, lbl1);
}
for(i=0, pAgg=pParse->aAgg; i<pParse->nAgg; i++, pAgg++){
@@ -2581,7 +2830,6 @@ int sqlite3Select(
int endagg = sqlite3VdbeMakeLabel(v);
int startagg;
startagg = sqlite3VdbeAddOp(v, OP_AggNext, 0, endagg);
- pParse->useAgg = 1;
if( pHaving ){
sqlite3ExprIfFalse(pParse, pHaving, startagg, 1);
}
@@ -2592,7 +2840,6 @@ int sqlite3Select(
sqlite3VdbeAddOp(v, OP_Goto, 0, startagg);
sqlite3VdbeResolveLabel(v, endagg);
sqlite3VdbeAddOp(v, OP_Noop, 0, 0);
- pParse->useAgg = 0;
}
/* If there is an ORDER BY clause, then we need to sort the results
@@ -2602,6 +2849,7 @@ int sqlite3Select(
generateSortTail(pParse, p, v, pEList->nExpr, eDest, iParm);
}
+#ifndef SQLITE_OMIT_SUBQUERY
/* If this was a subquery, we have now converted the subquery into a
** temporary table. So delete the subquery structure from the parent
** to prevent this subquery from being evaluated again and to force the
@@ -2613,6 +2861,7 @@ int sqlite3Select(
sqlite3SelectDelete(p);
pParent->pSrc->a[parentTab].pSelect = 0;
}
+#endif
/* The SELECT was successfully coded. Set the return code to 0
** to indicate no errors.
@@ -2623,6 +2872,6 @@ int sqlite3Select(
** successful coding of the SELECT.
*/
select_end:
- sqliteAggregateInfoReset(pParse);
+ restoreAggregateInfo(pParse, &sAggInfo);
return rc;
}
diff --git a/ext/pdo_sqlite/sqlite/src/shell.c b/ext/pdo_sqlite/sqlite/src/shell.c
index bdd13cc931..2b369a210e 100644
--- a/ext/pdo_sqlite/sqlite/src/shell.c
+++ b/ext/pdo_sqlite/sqlite/src/shell.c
@@ -196,7 +196,9 @@ static char *one_input_line(const char *zPrior, FILE *in){
zPrompt = mainPrompt;
}
zResult = readline(zPrompt);
+#if defined(HAVE_READLINE) && HAVE_READLINE==1
if( zResult ) add_history(zResult);
+#endif
return zResult;
}
@@ -360,6 +362,7 @@ static void output_csv(struct callback_data *p, const char *z, int bSep){
}
}
+#ifdef SIGINT
/*
** This routine runs when the user presses Ctrl-C
*/
@@ -367,6 +370,7 @@ static void interrupt_handler(int NotUsed){
seenInterrupt = 1;
if( db ) sqlite3_interrupt(db);
}
+#endif
/*
** This is the callback routine that the SQLite library
@@ -652,7 +656,11 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
zType = azArg[1];
zSql = azArg[2];
- fprintf(p->out, "%s;\n", zSql);
+ if( strcasecmp(zTable,"sqlite_sequence")!=0 ){
+ fprintf(p->out, "%s;\n", zSql);
+ }else{
+ fprintf(p->out, "DELETE FROM sqlite_sequence;\n");
+ }
if( strcmp(zType, "table")==0 ){
sqlite3_stmt *pTableInfo = 0;
@@ -746,7 +754,7 @@ static char zHelp[] =
".help Show this message\n"
".import FILE TABLE Import data from FILE into TABLE\n"
".indices TABLE Show names of all indices on TABLE\n"
- ".mode MODE ?TABLE? Set output mode where MODE is on of:\n"
+ ".mode MODE ?TABLE? Set output mode where MODE is one of:\n"
" csv Comma-separated values\n"
" column Left-aligned columns. (See .width)\n"
" html HTML <table> code\n"
@@ -882,6 +890,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
data.colWidth[0] = 3;
data.colWidth[1] = 15;
data.colWidth[2] = 58;
+ data.cnt = 0;
sqlite3_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg);
if( zErrMsg ){
fprintf(stderr,"Error: %s\n", zErrMsg);
@@ -1677,7 +1686,11 @@ int main(int argc, char **argv){
if( i<argc ){
data.zDbFilename = argv[i++];
}else{
+#ifndef SQLITE_OMIT_MEMORYDB
data.zDbFilename = ":memory:";
+#else
+ data.zDbFilename = 0;
+#endif
}
if( i<argc ){
zFirstCmd = argv[i++];
@@ -1770,7 +1783,9 @@ int main(int argc, char **argv){
if( zHome && (zHistory = malloc(strlen(zHome)+20))!=0 ){
sprintf(zHistory,"%s/.sqlite_history", zHome);
}
+#if defined(HAVE_READLINE) && HAVE_READLINE==1
if( zHistory ) read_history(zHistory);
+#endif
process_input(&data, 0);
if( zHistory ){
stifle_history(100);
diff --git a/ext/pdo_sqlite/sqlite/src/sqlite.h.in b/ext/pdo_sqlite/sqlite/src/sqlite.h.in
index 2dd97ed8cd..daffc25c62 100644
--- a/ext/pdo_sqlite/sqlite/src/sqlite.h.in
+++ b/ext/pdo_sqlite/sqlite/src/sqlite.h.in
@@ -30,9 +30,25 @@ extern "C" {
*/
#ifdef SQLITE_VERSION
# undef SQLITE_VERSION
-#else
-# define SQLITE_VERSION "--VERS--"
#endif
+#define SQLITE_VERSION "--VERS--"
+
+/*
+** The format of the version string is "X.Y.Z<trailing string>", where
+** X is the major version number, Y is the minor version number and Z
+** is the release number. The trailing string is often "alpha" or "beta".
+** For example "3.1.1beta".
+**
+** The SQLITE_VERSION_NUMBER is an integer with the value
+** (X*100000 + Y*1000 + Z). For example, for version "3.1.1beta",
+** SQLITE_VERSION_NUMBER is set to 3001001. To detect if they are using
+** version 3.1.1 or greater at compile time, programs may use the test
+** (SQLITE_VERSION_NUMBER>=3001001).
+*/
+#ifdef SQLITE_VERSION_NUMBER
+# undef SQLITE_VERSION_NUMBER
+#endif
+#define SQLITE_VERSION_NUMBER --VERSION-NUMBER--
/*
** The version string is also compiled into the library so that a program
@@ -45,6 +61,12 @@ extern const char sqlite3_version[];
const char *sqlite3_libversion(void);
/*
+** Return the value of the SQLITE_VERSION_NUMBER macro when the
+** library was compiled.
+*/
+int sqlite3_libversion_number(void);
+
+/*
** Each open sqlite database is represented by an instance of the
** following opaque structure.
*/
@@ -309,7 +331,7 @@ int sqlite3_busy_timeout(sqlite3*, int ms);
** pass the result data pointer to sqlite3_free_table() in order to
** release the memory that was malloc-ed. Because of the way the
** malloc() happens, the calling function must not try to call
-** malloc() directly. Only sqlite3_free_table() is able to release
+** free() directly. Only sqlite3_free_table() is able to release
** the memory properly and safely.
**
** The return value of this routine is the same as from sqlite3_exec().
@@ -428,6 +450,8 @@ int sqlite3_set_authorizer(
#define SQLITE_UPDATE 23 /* Table Name Column Name */
#define SQLITE_ATTACH 24 /* Filename NULL */
#define SQLITE_DETACH 25 /* Database Name NULL */
+#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */
+#define SQLITE_REINDEX 27 /* Index Name NULL */
/*
@@ -448,8 +472,8 @@ void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
/*
** This routine configures a callback function - the progress callback - that
** is invoked periodically during long running calls to sqlite3_exec(),
-** sqlite3_step() and sqlite3_get_table(). An example use for this API is to keep
-** a GUI updated during a large query.
+** sqlite3_step() and sqlite3_get_table(). An example use for this API is to
+** keep a GUI updated during a large query.
**
** The progress callback is invoked once for every N virtual machine opcodes,
** where N is the second argument to this function. The progress callback
@@ -606,14 +630,19 @@ typedef struct Mem sqlite3_value;
/*
** In the SQL strings input to sqlite3_prepare() and sqlite3_prepare16(),
-** one or more literals can be replace by a wildcard "?" or ":N:" where
-** N is an integer. These value of these wildcard literals can be set
-** using the routines listed below.
+** one or more literals can be replace by parameters "?" or ":AAA" or
+** "$VVV" where AAA is an identifer and VVV is a variable name according
+** to the syntax rules of the TCL programming language.
+** The value of these parameters (also called "host parameter names") can
+** be set using the routines listed below.
**
** In every case, the first parameter is a pointer to the sqlite3_stmt
** structure returned from sqlite3_prepare(). The second parameter is the
-** index of the wildcard. The first "?" has an index of 1. ":N:" wildcards
-** use the index N.
+** index of the parameter. The first parameter as an index of 1. For
+** named parameters (":AAA" or "$VVV") you can use
+** sqlite3_bind_parameter_index() to get the correct index value given
+** the parameters name. If the same named parameter occurs more than
+** once, it is assigned the same index each time.
**
** The fifth parameter to sqlite3_bind_blob(), sqlite3_bind_text(), and
** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or
@@ -624,8 +653,8 @@ typedef struct Mem sqlite3_value;
** own private copy of the data.
**
** The sqlite3_bind_* routine must be called before sqlite3_step() after
-** an sqlite3_prepare() or sqlite3_reset(). Unbound wildcards are interpreted
-** as NULL.
+** an sqlite3_prepare() or sqlite3_reset(). Unbound parameterss are
+** interpreted as NULL.
*/
int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
int sqlite3_bind_double(sqlite3_stmt*, int, double);
@@ -637,16 +666,16 @@ int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
/*
-** Return the number of wildcards in a compiled SQL statement. This
+** Return the number of parameters in a compiled SQL statement. This
** routine was added to support DBD::SQLite.
*/
int sqlite3_bind_parameter_count(sqlite3_stmt*);
/*
-** Return the name of the i-th parameter. Ordinary wildcards "?" are
-** nameless and a NULL is returned. For wildcards of the form :N or
-** $vvvv the complete text of the wildcard is returned.
-** NULL is returned if the index is out of range.
+** Return the name of the i-th parameter. Ordinary parameters "?" are
+** nameless and a NULL is returned. For parameters of the form :AAA or
+** $VVV the complete text of the parameter name is returned, including
+** the initial ":" or "$". NULL is returned if the index is out of range.
*/
const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
@@ -658,6 +687,13 @@ const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName);
/*
+** Set all the parameters in the compiled SQL statement to NULL.
+**
+******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
+*/
+int sqlite3_clear_bindings(sqlite3_stmt*);
+
+/*
** Return the number of columns in the result set returned by the compiled
** SQL statement. This routine returns 0 if pStmt is an SQL statement
** that does not return data (for example an UPDATE).
@@ -1148,17 +1184,41 @@ int sqlite3_rekey(
);
/*
-** If the following global variable is made to point to a constant
+** Sleep for a little while. The second parameter is the number of
+** miliseconds to sleep for.
+**
+** If the operating system does not support sleep requests with
+** milisecond time resolution, then the time will be rounded up to
+** the nearest second. The number of miliseconds of sleep actually
+** requested from the operating system is returned.
+**
+******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
+*/
+int sqlite3_sleep(int);
+
+/*
+** Return TRUE (non-zero) of the statement supplied as an argument needs
+** to be recompiled. A statement needs to be recompiled whenever the
+** execution environment changes in a way that would alter the program
+** that sqlite3_prepare() generates. For example, if new functions or
+** collating sequences are registered or if an authorizer function is
+** added or changed.
+**
+******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
+*/
+int sqlite3_expired(sqlite3_stmt*);
+
+/*
+** If the following global variable is made to point to a
** string which is the name of a directory, then all temporary files
** created by SQLite will be placed in that directory. If this variable
** is NULL pointer, then SQLite does a search for an appropriate temporary
** file directory.
**
-** This variable should only be changed when there are no open databases.
-** Once sqlite3_open() has been called, this variable should not be changed
-** until all database connections are closed.
+** Once sqlite3_open() has been called, changing this variable will invalidate the
+** current temporary database, if any.
*/
-extern const char *sqlite3_temp_directory;
+extern char *sqlite3_temp_directory;
#ifdef __cplusplus
} /* End of the 'extern "C"' block */
diff --git a/ext/pdo_sqlite/sqlite/src/sqliteInt.h b/ext/pdo_sqlite/sqlite/src/sqliteInt.h
index b4fa474ba9..a9dde13186 100644
--- a/ext/pdo_sqlite/sqlite/src/sqliteInt.h
+++ b/ext/pdo_sqlite/sqlite/src/sqliteInt.h
@@ -47,13 +47,25 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
+#include <stddef.h>
/*
** The maximum number of in-memory pages to use for the main database
-** table and for temporary tables.
+** table and for temporary tables. Internally, the MAX_PAGES and
+** TEMP_PAGES macros are used. To override the default values at
+** compilation time, the SQLITE_DEFAULT_CACHE_SIZE and
+** SQLITE_DEFAULT_TEMP_CACHE_SIZE macros should be set.
*/
-#define MAX_PAGES 2000
-#define TEMP_PAGES 500
+#ifdef SQLITE_DEFAULT_CACHE_SIZE
+# define MAX_PAGES SQLITE_DEFAULT_CACHE_SIZE
+#else
+# define MAX_PAGES 2000
+#endif
+#ifdef SQLITE_DEFAULT_TEMP_CACHE_SIZE
+# define TEMP_PAGES SQLITE_DEFAULT_TEMP_CACHE_SIZE
+#else
+# define TEMP_PAGES 500
+#endif
/*
** If the following macro is set to 1, then NULL values are considered
@@ -102,10 +114,28 @@
** a minimum.
*/
/* #define SQLITE_OMIT_AUTHORIZATION 1 */
-/* #define SQLITE_OMIT_INMEMORYDB 1 */
+/* #define SQLITE_OMIT_MEMORYDB 1 */
/* #define SQLITE_OMIT_VACUUM 1 */
/* #define SQLITE_OMIT_DATETIME_FUNCS 1 */
/* #define SQLITE_OMIT_PROGRESS_CALLBACK 1 */
+/* #define SQLITE_OMIT_AUTOVACUUM */
+/* #define SQLITE_OMIT_ALTERTABLE */
+
+/*
+** Provide a default value for TEMP_STORE in case it is not specified
+** on the command-line
+*/
+#ifndef TEMP_STORE
+# define TEMP_STORE 1
+#endif
+
+/*
+** GCC does not define the offsetof() macro so we'll have to do it
+** ourselves.
+*/
+#ifndef offsetof
+#define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD))
+#endif
/*
** Integers of known sizes. These typedefs might change for architectures
@@ -213,7 +243,7 @@ struct BusyHandler {
** each malloc() and free(). This output can be analyzed
** by an AWK script to determine if there are any leaks.
*/
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_MEMDEBUG
# define sqliteMalloc(X) sqlite3Malloc_(X,1,__FILE__,__LINE__)
# define sqliteMallocRaw(X) sqlite3Malloc_(X,0,__FILE__,__LINE__)
# define sqliteFree(X) sqlite3Free_(X,__FILE__,__LINE__)
@@ -239,10 +269,11 @@ extern int sqlite3_malloc_failed;
** The following global variables are used for testing and debugging
** only. They only work if SQLITE_DEBUG is defined.
*/
-#ifdef SQLITE_DEBUG
-extern int sqlite3_nMalloc; /* Number of sqliteMalloc() calls */
-extern int sqlite3_nFree; /* Number of sqliteFree() calls */
-extern int sqlite3_iMallocFail; /* Fail sqliteMalloc() after this many calls */
+#ifdef SQLITE_MEMDEBUG
+extern int sqlite3_nMalloc; /* Number of sqliteMalloc() calls */
+extern int sqlite3_nFree; /* Number of sqliteFree() calls */
+extern int sqlite3_iMallocFail; /* Fail sqliteMalloc() after this many calls */
+extern int sqlite3_iMallocReset; /* Set iMallocFail to this when it reaches 0 */
#endif
/*
@@ -296,6 +327,8 @@ typedef struct AuthContext AuthContext;
typedef struct KeyClass KeyClass;
typedef struct CollSeq CollSeq;
typedef struct KeyInfo KeyInfo;
+typedef struct NameContext NameContext;
+typedef struct Fetch Fetch;
/*
** Each database file to be accessed by the system is an instance
@@ -316,7 +349,8 @@ struct Db {
u8 inTrans; /* 0: not writable. 1: Transaction. 2: Checkpoint */
u8 safety_level; /* How aggressive at synching data to disk */
int cache_size; /* Number of pages to use in the cache */
- void *pAux; /* Auxiliary data. Usually NULL */
+ Table *pSeqTab; /* The sqlite_sequence table used by AUTOINCREMENT */
+ void *pAux; /* Auxiliary data. Usually NULL */
void (*xFreeAux)(void*); /* Routine to free pAux */
};
@@ -408,7 +442,6 @@ struct sqlite3 {
void *pProgressArg; /* Argument to the progress callback */
int nProgressOps; /* Number of opcodes for progress callback */
#endif
-
int errCode; /* Most recent error code (SQLITE_*) */
u8 enc; /* Text encoding for this database. */
u8 autoCommit; /* The auto-commit flag. */
@@ -417,9 +450,8 @@ struct sqlite3 {
void *pCollNeededArg;
sqlite3_value *pValue; /* Value used for transient conversions */
sqlite3_value *pErr; /* Most recent error message */
-
char *zErrMsg; /* Most recent error message (UTF-8 encoded) */
- char *zErrMsg16; /* Most recent error message (UTF-8 encoded) */
+ char *zErrMsg16; /* Most recent error message (UTF-16 encoded) */
};
/*
@@ -443,6 +475,9 @@ struct sqlite3 {
/* result set is empty */
#define SQLITE_SqlTrace 0x00000200 /* Debug print SQL as it executes */
#define SQLITE_VdbeListing 0x00000400 /* Debug listings of VDBE programs */
+#define SQLITE_WriteSchema 0x00000800 /* OK to update SQLITE_MASTER */
+#define SQLITE_NoReadlock 0x00001000 /* Readlocks are omitted when
+ ** accessing read-only databases */
/*
** Possible values for the sqlite.magic field.
@@ -478,7 +513,7 @@ struct FuncDef {
*/
struct Column {
char *zName; /* Name of this column */
- char *zDflt; /* Default value of this column */
+ Expr *pDflt; /* Default value of this column */
char *zType; /* Data type for this column */
CollSeq *pColl; /* Collating sequence. If NULL, use the default */
u8 notNull; /* True if there is a NOT NULL constraint */
@@ -572,6 +607,7 @@ struct Table {
u8 isTransient; /* True if automatically deleted when VDBE finishes */
u8 hasPrimKey; /* True if there exists a primary key */
u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
+ u8 autoInc; /* True if the integer primary key is autoincrement */
Trigger *pTrigger; /* List of SQL triggers on this table */
FKey *pFKey; /* Linked list of all foreign keys in this table */
char *zColAff; /* String defining the affinity of each column */
@@ -759,6 +795,12 @@ struct Token {
** marker (a question mark character '?' in the original SQL) then the
** Expr.iTable holds the index number for that variable.
**
+** If the expression is a subquery then Expr.iColumn holds an integer
+** register number containing the result of the subquery. If the
+** subquery gives a constant result, then iTable is -1. If the subquery
+** gives a different answer at different times during statement processing
+** then iTable is the address of a subroutine that computes the subquery.
+**
** The Expr.pSelect field points to a SELECT statement. The SELECT might
** be the right operand of an IN operator. Or, if a scalar SELECT appears
** in an expression the opcode is TK_SELECT and Expr.pSelect is the only
@@ -777,8 +819,9 @@ struct Expr {
Token span; /* Complete text of the expression */
int iTable, iColumn; /* When op==TK_COLUMN, then this expr node means the
** iColumn-th field of the iTable-th table. */
- int iAgg; /* When op==TK_COLUMN and pParse->useAgg==TRUE, pull
+ int iAgg; /* When op==TK_COLUMN and pParse->fillAgg==FALSE, pull
** result from the iAgg-th element of the aggregator */
+ int iAggCtx; /* The value to pass as P1 of OP_AggGet. */
Select *pSelect; /* When the expression is a sub-select. Also the
** right side of "<expr> IN (<select>)" */
};
@@ -787,6 +830,11 @@ struct Expr {
** The following are the meanings of bits in the Expr.flags field.
*/
#define EP_FromJoin 0x0001 /* Originated in ON or USING clause of a join */
+#define EP_Agg 0x0002 /* Contains one or more aggregate functions */
+#define EP_Resolved 0x0004 /* IDs have been resolved to COLUMNs */
+#define EP_Error 0x0008 /* Expression contains one or more errors */
+#define EP_Not 0x0010 /* Operator preceeded by NOT */
+#define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */
/*
** These macros can be used to test, set, or clear bits in the
@@ -842,6 +890,11 @@ struct IdList {
};
/*
+** The bitmask datatype defined below is used for various optimizations.
+*/
+typedef unsigned int Bitmask;
+
+/*
** The following structure describes the FROM clause of a SELECT statement.
** Each table or subquery in the FROM clause is a separate element of
** the SrcList.a[] array.
@@ -865,6 +918,7 @@ struct SrcList {
int iCursor; /* The VDBE cursor number used to access this table */
Expr *pOn; /* The ON clause of a join */
IdList *pUsing; /* The USING clause of a join */
+ Bitmask colUsed; /* Bit N (1<<N) set if column N or pTab is used */
} a[1]; /* One entry for each identifier on the list */
};
@@ -886,9 +940,10 @@ struct SrcList {
*/
struct WhereLevel {
int iMem; /* Memory cell used by this level */
- Index *pIdx; /* Index used */
- int iCur; /* Cursor number used for this index */
- int score; /* How well this indexed scored */
+ Index *pIdx; /* Index used. NULL if no index */
+ int iTabCur; /* The VDBE cursor used to access the table */
+ int iIdxCur; /* The VDBE cursor used to acesss pIdx */
+ int score; /* How well this index scored */
int brk; /* Jump here to break out of the loop */
int cont; /* Jump here to continue with the next loop cycle */
int op, p1, p2; /* Opcode used to terminate the loop */
@@ -908,6 +963,7 @@ struct WhereLevel {
struct WhereInfo {
Parse *pParse;
SrcList *pTabList; /* List of tables in the join */
+ int iTop; /* The very beginning of the WHERE loop */
int iContinue; /* Jump here to continue with next record */
int iBreak; /* Jump here to break out of the loop */
int nLevel; /* Number of nested loop */
@@ -915,17 +971,42 @@ struct WhereInfo {
};
/*
+** A NameContext defines a context in which to resolve table and column
+** names. The context consists of a list of tables (the pSrcList) field and
+** a list of named expression (pEList). The named expression list may
+** be NULL. The pSrc corresponds to the FROM clause of a SELECT or
+** to the table being operated on by INSERT, UPDATE, or DELETE. The
+** pEList corresponds to the result set of a SELECT and is NULL for
+** other statements.
+**
+** NameContexts can be nested. When resolving names, the inner-most
+** context is searched first. If no match is found, the next outer
+** context is checked. If there is still no match, the next context
+** is checked. This process continues until either a match is found
+** or all contexts are check. When a match is found, the nRef member of
+** the context containing the match is incremented.
+**
+** Each subquery gets a new NameContext. The pNext field points to the
+** NameContext in the parent query. Thus the process of scanning the
+** NameContext list corresponds to searching through successively outer
+** subqueries looking for a match.
+*/
+struct NameContext {
+ Parse *pParse; /* The parser */
+ SrcList *pSrcList; /* One or more tables used to resolve names */
+ ExprList *pEList; /* Optional list of named expressions */
+ int nRef; /* Number of names resolved by this context */
+ int nErr; /* Number of errors encountered while resolving names */
+ u8 allowAgg; /* Aggregate functions allowed here */
+ u8 hasAgg;
+ int nDepth; /* Depth of subquery recursion. 1 for no recursion */
+ NameContext *pNext; /* Next outer name context. NULL for outermost */
+};
+
+/*
** An instance of the following structure contains all information
** needed to generate code for a single SELECT statement.
**
-** The zSelect field is used when the Select structure must be persistent.
-** Normally, the expression tree points to tokens in the original input
-** string that encodes the select. But if the Select structure must live
-** longer than its input string (for example when it is used to describe
-** a VIEW) we have to make a copy of the input string so that the nodes
-** of the expression tree will have something to point to. zSelect is used
-** to hold that copy.
-**
** nLimit is set to -1 if there is no LIMIT clause. nOffset is set to 0.
** If there is a LIMIT clause, the parser sets nLimit to the value of the
** limit and nOffset to the value of the offset (or 0 if there is not
@@ -942,10 +1023,13 @@ struct Select {
Expr *pHaving; /* The HAVING clause */
ExprList *pOrderBy; /* The ORDER BY clause */
Select *pPrior; /* Prior select in a compound select statement */
- int nLimit, nOffset; /* LIMIT and OFFSET values. -1 means not used */
+ Expr *pLimit; /* LIMIT expression. NULL means not used. */
+ Expr *pOffset; /* OFFSET expression. NULL means not used. */
int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
- char *zSelect; /* Complete text of the SELECT command */
IdList **ppOpenTemp; /* OP_OpenTemp addresses used by multi-selects */
+ Fetch *pFetch; /* If this stmt is part of a FETCH command */
+ u8 isResolved; /* True once sqlite3SelectResolve() has run. */
+ u8 isAgg; /* True if this is an aggregate query */
};
/*
@@ -961,6 +1045,7 @@ struct Select {
#define SRT_Discard 9 /* Do not save the results anywhere */
#define SRT_Sorter 10 /* Store results in the sorter */
#define SRT_Subroutine 11 /* Call a subroutine to handle results */
+#define SRT_Exists 12 /* Put 0 or 1 in a memory cell */
/*
** When a SELECT uses aggregate functions (like "count(*)" or "avg(f1)")
@@ -991,41 +1076,51 @@ struct AggExpr {
** An SQL parser context. A copy of this structure is passed through
** the parser and down into all the parser action routine in order to
** carry around information that is global to the entire parse.
+**
+** The structure is divided into two parts. When the parser and code
+** generate call themselves recursively, the first part of the structure
+** is constant but the second part is reset at the beginning and end of
+** each recursion.
*/
struct Parse {
sqlite3 *db; /* The main database structure */
int rc; /* Return code from execution */
char *zErrMsg; /* An error message */
- Token sErrToken; /* The token at which the error occurred */
- Token sNameToken; /* Token with unqualified schema object name */
- Token sLastToken; /* The last token parsed */
- const char *zSql; /* All SQL text */
- const char *zTail; /* All SQL text past the last semicolon parsed */
- Table *pNewTable; /* A table being constructed by CREATE TABLE */
Vdbe *pVdbe; /* An engine for executing database bytecode */
u8 colNamesSet; /* TRUE after OP_ColumnName has been issued to pVdbe */
- u8 explain; /* True if the EXPLAIN flag is found on the query */
u8 nameClash; /* A permanent table name clashes with temp table name */
- u8 useAgg; /* If true, extract field values from the aggregator
- ** while generating expressions. Normally false */
u8 checkSchema; /* Causes schema cookie check after an error */
+ u8 nested; /* Number of nested calls to the parser/code generator */
int nErr; /* Number of errors seen */
int nTab; /* Number of previously allocated VDBE cursors */
int nMem; /* Number of memory cells used so far */
int nSet; /* Number of sets used so far */
- int nAgg; /* Number of aggregate expressions */
+ u32 cookieMask; /* Bitmask of schema verified databases */
+ int cookieValue[MAX_ATTACHED+2]; /* Values of cookies to verify */
+ int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */
+ u32 writeMask; /* Start a write transaction on these databases */
+ u8 fillAgg; /* If true, ignore the Expr.iAgg field. Normally false */
+
+ /* Above is constant between recursions. Below is reset before and after
+ ** each recursion */
+
int nVar; /* Number of '?' variables seen in the SQL so far */
int nVarExpr; /* Number of used slots in apVarExpr[] */
int nVarExprAlloc; /* Number of allocated slots in apVarExpr[] */
Expr **apVarExpr; /* Pointers to :aaa and $aaaa wildcard expressions */
- AggExpr *aAgg; /* An array of aggregate expressions */
- const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
+ u8 explain; /* True if the EXPLAIN flag is found on the query */
+ Token sErrToken; /* The token at which the error occurred */
+ Token sNameToken; /* Token with unqualified schema object name */
+ Token sLastToken; /* The last token parsed */
+ const char *zSql; /* All SQL text */
+ const char *zTail; /* All SQL text past the last semicolon parsed */
+ Table *pNewTable; /* A table being constructed by CREATE TABLE */
Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */
TriggerStack *trigStack; /* Trigger actions being coded */
- u32 cookieMask; /* Bitmask of schema verified databases */
- int cookieValue[MAX_ATTACHED+2]; /* Values of cookies to verify */
- int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */
- u32 writeMask; /* Start a write transaction on these databases */
+ const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
+ int nAgg; /* Number of aggregate expressions */
+ AggExpr *aAgg; /* An array of aggregate expressions */
+ int nMaxDepth; /* Maximum depth of subquery recursion */
};
/*
@@ -1064,7 +1159,7 @@ struct Trigger {
u8 iDb; /* Database containing this trigger */
u8 iTabDb; /* Database containing Trigger.table */
u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT */
- u8 tr_tm; /* One of TK_BEFORE, TK_AFTER */
+ u8 tr_tm; /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
Expr *pWhen; /* The WHEN clause of the expresion (may be NULL) */
IdList *pColumns; /* If this is an UPDATE OF <column-list> trigger,
the <column-list> is stored here */
@@ -1076,6 +1171,16 @@ struct Trigger {
};
/*
+** A trigger is either a BEFORE or an AFTER trigger. The following constants
+** determine which.
+**
+** If there are multiple triggers, you might of some BEFORE and some AFTER.
+** In that cases, the constants below can be ORed together.
+*/
+#define TRIGGER_BEFORE 1
+#define TRIGGER_AFTER 2
+
+/*
* An instance of struct TriggerStep is used to store a single SQL statement
* that is a part of a trigger-program.
*
@@ -1188,7 +1293,6 @@ typedef struct {
char **pzErrMsg; /* Error message stored here */
} InitData;
-
/*
* This global flag is set for performance testing of triggers. When it is set
* SQLite will perform the overhead of building new and old trigger references
@@ -1206,7 +1310,7 @@ int sqlite3IsNumber(const char*, int*, u8);
int sqlite3Compare(const char *, const char *);
int sqlite3SortCompare(const char *, const char *);
void sqlite3RealToSortable(double r, char *);
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_MEMDEBUG
void *sqlite3Malloc_(int,int,char*,int);
void sqlite3Free_(void*,char*,int);
void *sqlite3Realloc_(void*,int,char*,int);
@@ -1233,7 +1337,8 @@ void sqlite3Dequote(char*);
int sqlite3KeywordCode(const char*, int);
int sqlite3RunParser(Parse*, const char*, char **);
void sqlite3FinishCoding(Parse*);
-Expr *sqlite3Expr(int, Expr*, Expr*, Token*);
+Expr *sqlite3Expr(int, Expr*, Expr*, const Token*);
+Expr *sqlite3RegisterExpr(Parse*,Token*);
Expr *sqlite3ExprAnd(Expr*, Expr*);
void sqlite3ExprSpan(Expr*,Token*,Token*);
Expr *sqlite3ExprFunction(ExprList*, Token*);
@@ -1253,13 +1358,19 @@ void sqlite3OpenMasterTable(Vdbe *v, int);
void sqlite3StartTable(Parse*,Token*,Token*,Token*,int,int);
void sqlite3AddColumn(Parse*,Token*);
void sqlite3AddNotNull(Parse*, int);
-void sqlite3AddPrimaryKey(Parse*, ExprList*, int);
+void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int);
void sqlite3AddColumnType(Parse*,Token*,Token*);
-void sqlite3AddDefaultValue(Parse*,Token*,int);
+void sqlite3AddDefaultValue(Parse*,Expr*);
void sqlite3AddCollateType(Parse*, const char*, int);
void sqlite3EndTable(Parse*,Token*,Select*);
-void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int);
-int sqlite3ViewGetColumnNames(Parse*,Table*);
+
+#ifndef SQLITE_OMIT_VIEW
+ void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int);
+ int sqlite3ViewGetColumnNames(Parse*,Table*);
+#else
+# define sqlite3ViewGetColumnNames(A,B) 0
+#endif
+
void sqlite3DropTable(Parse*, SrcList*, int);
void sqlite3DeleteTable(sqlite3*, Table*);
void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int);
@@ -1277,35 +1388,36 @@ void sqlite3AddKeyType(Vdbe*, ExprList*);
void sqlite3AddIdxKeyType(Vdbe*, Index*);
int sqlite3Select(Parse*, Select*, int, int, Select*, int, int*, char *aff);
Select *sqlite3SelectNew(ExprList*,SrcList*,Expr*,ExprList*,Expr*,ExprList*,
- int,int,int);
+ int,Expr*,Expr*);
void sqlite3SelectDelete(Select*);
void sqlite3SelectUnbind(Select*);
Table *sqlite3SrcListLookup(Parse*, SrcList*);
int sqlite3IsReadOnly(Parse*, Table*, int);
void sqlite3OpenTableForReading(Vdbe*, int iCur, Table*);
+void sqlite3OpenTable(Vdbe*, int iCur, Table*, int);
void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
-WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, int, ExprList**);
+WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, Fetch*);
void sqlite3WhereEnd(WhereInfo*);
void sqlite3ExprCode(Parse*, Expr*);
+void sqlite3ExprCodeAndCache(Parse*, Expr*);
int sqlite3ExprCodeExprList(Parse*, ExprList*);
void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
+void sqlite3NextedParse(Parse*, const char*, ...);
Table *sqlite3FindTable(sqlite3*,const char*, const char*);
Table *sqlite3LocateTable(Parse*,const char*, const char*);
Index *sqlite3FindIndex(sqlite3*,const char*, const char*);
void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*);
void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
-void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
void sqlite3Vacuum(Parse*, Token*);
int sqlite3RunVacuum(char**, sqlite3*);
char *sqlite3NameFromToken(Token*);
int sqlite3ExprCheck(Parse*, Expr*, int, int*);
int sqlite3ExprCompare(Expr*, Expr*);
int sqliteFuncId(Token*);
-int sqlite3ExprResolveIds(Parse*, SrcList*, ExprList*, Expr*);
-int sqlite3ExprResolveAndCheck(Parse*,SrcList*,ExprList*,Expr*,int,int*);
-int sqlite3ExprAnalyzeAggregates(Parse*, Expr*);
+int sqlite3ExprResolveNames(NameContext *, Expr *);
+int sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
Vdbe *sqlite3GetVdbe(Parse*);
void sqlite3Randomness(int, void*);
void sqlite3RollbackAll(sqlite3*);
@@ -1336,21 +1448,32 @@ int sqlite3SafetyOn(sqlite3*);
int sqlite3SafetyOff(sqlite3*);
int sqlite3SafetyCheck(sqlite3*);
void sqlite3ChangeCookie(sqlite3*, Vdbe*, int);
-void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
- int,Expr*,int);
-void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*);
-void sqlite3DropTrigger(Parse*, SrcList*);
-void sqlite3DropTriggerPtr(Parse*, Trigger*, int);
-int sqlite3TriggersExist(Parse* , Trigger* , int , int , int, ExprList*);
-int sqlite3CodeRowTrigger(Parse*, int, ExprList*, int, Table *, int, int,
- int, int);
-void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);
-void sqlite3DeleteTriggerStep(TriggerStep*);
-TriggerStep *sqlite3TriggerSelectStep(Select*);
-TriggerStep *sqlite3TriggerInsertStep(Token*, IdList*, ExprList*, Select*, int);
-TriggerStep *sqlite3TriggerUpdateStep(Token*, ExprList*, Expr*, int);
-TriggerStep *sqlite3TriggerDeleteStep(Token*, Expr*);
-void sqlite3DeleteTrigger(Trigger*);
+
+#ifndef SQLITE_OMIT_TRIGGER
+ void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
+ int,Expr*,int);
+ void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*);
+ void sqlite3DropTrigger(Parse*, SrcList*);
+ void sqlite3DropTriggerPtr(Parse*, Trigger*, int);
+ int sqlite3TriggersExist(Parse*, Table*, int, ExprList*);
+ int sqlite3CodeRowTrigger(Parse*, int, ExprList*, int, Table *, int, int,
+ int, int);
+ void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);
+ void sqlite3DeleteTriggerStep(TriggerStep*);
+ TriggerStep *sqlite3TriggerSelectStep(Select*);
+ TriggerStep *sqlite3TriggerInsertStep(Token*, IdList*, ExprList*,Select*,int);
+ TriggerStep *sqlite3TriggerUpdateStep(Token*, ExprList*, Expr*, int);
+ TriggerStep *sqlite3TriggerDeleteStep(Token*, Expr*);
+ void sqlite3DeleteTrigger(Trigger*);
+ void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
+#else
+# define sqlite3TriggersExist(A,B,C,D,E,F) 0
+# define sqlite3DeleteTrigger(A)
+# define sqlite3DropTriggerPtr(A,B,C)
+# define sqlite3UnlinkAndDeleteTrigger(A,B,C)
+# define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I) 0
+#endif
+
int sqlite3JoinType(Parse*, Token*, Token*, Token*);
void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int);
void sqlite3DeferForeignKey(Parse*, int);
@@ -1386,7 +1509,6 @@ int sqlite3PutVarint(unsigned char *, u64);
int sqlite3GetVarint(const unsigned char *, u64 *);
int sqlite3GetVarint32(const unsigned char *, u32 *);
int sqlite3VarintLen(u64 v);
-char sqlite3AffinityType(const char *, int);
void sqlite3IndexAffinityStr(Vdbe *, Index *);
void sqlite3TableAffinityStr(Vdbe *, Table *);
char sqlite3CompareAffinity(Expr *pExpr, char aff2);
@@ -1415,5 +1537,14 @@ void sqlite3ValueFree(sqlite3_value*);
sqlite3_value *sqlite3ValueNew();
sqlite3_value *sqlite3GetTransientValue(sqlite3*db);
extern const unsigned char sqlite3UpperToLower[];
+void sqlite3RootPageMoved(Db*, int, int);
+void sqlite3Reindex(Parse*, Token*, Token*);
+void sqlite3AlterFunctions(sqlite3*);
+void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
+int sqlite3GetToken(const unsigned char *, int *);
+void sqlite3NestedParse(Parse*, const char*, ...);
+void sqlite3ExpirePreparedStatements(sqlite3*);
+void sqlite3CodeSubselect(Parse *, Expr *);
+int sqlite3SelectResolve(Parse *, Select *, NameContext *);
#endif
diff --git a/ext/pdo_sqlite/sqlite/src/tclsqlite.c b/ext/pdo_sqlite/sqlite/src/tclsqlite.c
index 5e37945b70..7f1aba3c7e 100644
--- a/ext/pdo_sqlite/sqlite/src/tclsqlite.c
+++ b/ext/pdo_sqlite/sqlite/src/tclsqlite.c
@@ -22,6 +22,9 @@
#include <string.h>
#include <assert.h>
+#define NUM_PREPARED_STMTS 10
+#define MAX_PREPARED_STMTS 100
+
/*
** If TCL uses UTF-8 and SQLite is configured to use iso8859, then we
** have to do a translation when going between the two. Set the
@@ -55,6 +58,19 @@ struct SqlCollate {
};
/*
+** Prepared statements are cached for faster execution. Each prepared
+** statement is described by an instance of the following structure.
+*/
+typedef struct SqlPreparedStmt SqlPreparedStmt;
+struct SqlPreparedStmt {
+ SqlPreparedStmt *pNext; /* Next in linked list */
+ SqlPreparedStmt *pPrev; /* Previous on the list */
+ sqlite3_stmt *pStmt; /* The prepared statement */
+ int nSql; /* chars in zSql[] */
+ char zSql[1]; /* Text of the SQL statement */
+};
+
+/*
** There is one instance of this structure for each SQLite database
** that has been opened by the SQLite TCL interface.
*/
@@ -71,14 +87,35 @@ struct SqliteDb {
SqlCollate *pCollate; /* List of SQL collation functions */
int rc; /* Return code of most recent sqlite3_exec() */
Tcl_Obj *pCollateNeeded; /* Collation needed script */
+ SqlPreparedStmt *stmtList; /* List of prepared statements*/
+ SqlPreparedStmt *stmtLast; /* Last statement in the list */
+ int maxStmt; /* The next maximum number of stmtList */
+ int nStmt; /* Number of statements in stmtList */
};
/*
+** Finalize and free a list of prepared statements
+*/
+static void flushStmtCache( SqliteDb *pDb ){
+ SqlPreparedStmt *pPreStmt;
+
+ while( pDb->stmtList ){
+ sqlite3_finalize( pDb->stmtList->pStmt );
+ pPreStmt = pDb->stmtList;
+ pDb->stmtList = pDb->stmtList->pNext;
+ Tcl_Free( (char*)pPreStmt );
+ }
+ pDb->nStmt = 0;
+ pDb->stmtLast = 0;
+}
+
+/*
** TCL calls this procedure when an sqlite3 database command is
** deleted.
*/
static void DbDeleteCmd(void *db){
SqliteDb *pDb = (SqliteDb*)db;
+ flushStmtCache(pDb);
sqlite3_close(pDb->db);
while( pDb->pFunc ){
SqlFunc *pFunc = pDb->pFunc;
@@ -215,7 +252,7 @@ static int tclSqlCollate(
** This routine is called to evaluate an SQL function implemented
** using TCL script.
*/
-static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
SqlFunc *p = sqlite3_user_data(context);
Tcl_DString cmd;
int i;
@@ -287,6 +324,8 @@ static int auth_callback(
case SQLITE_UPDATE : zCode="SQLITE_UPDATE"; break;
case SQLITE_ATTACH : zCode="SQLITE_ATTACH"; break;
case SQLITE_DETACH : zCode="SQLITE_DETACH"; break;
+ case SQLITE_ALTER_TABLE : zCode="SQLITE_ALTER_TABLE"; break;
+ case SQLITE_REINDEX : zCode="SQLITE_REINDEX"; break;
default : zCode="????"; break;
}
Tcl_DStringInit(&str);
@@ -333,6 +372,54 @@ static Tcl_Obj *dbTextToObj(char const *zText){
}
/*
+** This routine reads a line of text from FILE in, stores
+** the text in memory obtained from malloc() and returns a pointer
+** to the text. NULL is returned at end of file, or if malloc()
+** fails.
+**
+** The interface is like "readline" but no command-line editing
+** is done.
+**
+** copied from shell.c from '.import' command
+*/
+static char *local_getline(char *zPrompt, FILE *in){
+ char *zLine;
+ int nLine;
+ int n;
+ int eol;
+
+ nLine = 100;
+ zLine = malloc( nLine );
+ if( zLine==0 ) return 0;
+ n = 0;
+ eol = 0;
+ while( !eol ){
+ if( n+100>nLine ){
+ nLine = nLine*2 + 100;
+ zLine = realloc(zLine, nLine);
+ if( zLine==0 ) return 0;
+ }
+ if( fgets(&zLine[n], nLine - n, in)==0 ){
+ if( n==0 ){
+ free(zLine);
+ return 0;
+ }
+ zLine[n] = 0;
+ eol = 1;
+ break;
+ }
+ while( zLine[n] ){ n++; }
+ if( n>0 && zLine[n-1]=='\n' ){
+ n--;
+ zLine[n] = 0;
+ eol = 1;
+ }
+ }
+ zLine = realloc( zLine, n+1 );
+ return zLine;
+}
+
+/*
** The "sqlite" command below creates a new Tcl command for each
** connection it opens to an SQLite database. This routine is invoked
** whenever one of those connection-specific commands is executed
@@ -350,22 +437,25 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
int choice;
int rc = TCL_OK;
static const char *DB_strs[] = {
- "authorizer", "busy", "changes",
- "close", "collate", "collation_needed",
- "commit_hook", "complete", "errorcode",
- "eval", "function", "last_insert_rowid",
- "onecolumn", "progress", "rekey",
- "timeout", "total_changes", "trace",
+ "authorizer", "busy", "cache",
+ "changes", "close", "collate",
+ "collation_needed", "commit_hook", "complete",
+ "copy", "errorcode", "eval",
+ "function", "last_insert_rowid", "onecolumn",
+ "progress", "rekey", "timeout",
+ "total_changes", "trace", "version",
0
};
enum DB_enum {
- DB_AUTHORIZER, DB_BUSY, DB_CHANGES,
- DB_CLOSE, DB_COLLATE, DB_COLLATION_NEEDED,
- DB_COMMIT_HOOK, DB_COMPLETE, DB_ERRORCODE,
- DB_EVAL, DB_FUNCTION, DB_LAST_INSERT_ROWID,
- DB_ONECOLUMN, DB_PROGRESS, DB_REKEY,
- DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE,
+ DB_AUTHORIZER, DB_BUSY, DB_CACHE,
+ DB_CHANGES, DB_CLOSE, DB_COLLATE,
+ DB_COLLATION_NEEDED, DB_COMMIT_HOOK, DB_COMPLETE,
+ DB_COPY, DB_ERRORCODE, DB_EVAL,
+ DB_FUNCTION, DB_LAST_INSERT_ROWID,DB_ONECOLUMN,
+ DB_PROGRESS, DB_REKEY, DB_TIMEOUT,
+ DB_TOTAL_CHANGES, DB_TRACE, DB_VERSION
};
+ /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */
if( objc<2 ){
Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
@@ -467,6 +557,55 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
break;
}
+ /* $db cache flush
+ ** $db cache size n
+ **
+ ** Flush the prepared statement cache, or set the maximum number of
+ ** cached statements.
+ */
+ case DB_CACHE: {
+ char *subCmd;
+ int n;
+
+ if( objc<=2 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "cache option ?arg?");
+ return TCL_ERROR;
+ }
+ subCmd = Tcl_GetStringFromObj( objv[2], 0 );
+ if( *subCmd=='f' && strcmp(subCmd,"flush")==0 ){
+ if( objc!=3 ){
+ Tcl_WrongNumArgs(interp, 2, objv, "flush");
+ return TCL_ERROR;
+ }else{
+ flushStmtCache( pDb );
+ }
+ }else if( *subCmd=='s' && strcmp(subCmd,"size")==0 ){
+ if( objc!=4 ){
+ Tcl_WrongNumArgs(interp, 2, objv, "size n");
+ return TCL_ERROR;
+ }else{
+ if( TCL_ERROR==Tcl_GetIntFromObj(interp, objv[3], &n) ){
+ Tcl_AppendResult( interp, "cannot convert \"",
+ Tcl_GetStringFromObj(objv[3],0), "\" to integer", 0);
+ return TCL_ERROR;
+ }else{
+ if( n<0 ){
+ flushStmtCache( pDb );
+ n = 0;
+ }else if( n>MAX_PREPARED_STMTS ){
+ n = MAX_PREPARED_STMTS;
+ }
+ pDb->maxStmt = n;
+ }
+ }
+ }else{
+ Tcl_AppendResult( interp, "bad option \"",
+ Tcl_GetStringFromObj(objv[0],0), "\": must be flush or size", 0);
+ return TCL_ERROR;
+ }
+ break;
+ }
+
/* $db changes
**
** Return the number of rows that were modified, inserted, or deleted by
@@ -557,6 +696,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
strcpy(pCollate->zScript, zScript);
if( sqlite3_create_collation(pDb->db, zName, SQLITE_UTF8,
pCollate, tclSqlCollate) ){
+ Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE);
return TCL_ERROR;
}
break;
@@ -636,6 +776,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
int nParm; /* Number of entries used in apParm[] */
Tcl_Obj *aParm[10]; /* Static space for apParm[] in the common case */
Tcl_Obj *pRet; /* Value to be returned */
+ SqlPreparedStmt *pPreStmt; /* Pointer to a prepared statement */
+ int rc2;
if( choice==DB_ONECOLUMN ){
if( objc!=3 ){
@@ -665,29 +807,78 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
Tcl_IncrRefCount(objv[2]);
zSql = Tcl_GetStringFromObj(objv[2], 0);
while( rc==TCL_OK && zSql[0] ){
- int i; /* Loop counter */
- int nVar; /* Number of wildcards in the SQL */
- int nCol; /* Number of columns in the result set */
+ int i; /* Loop counter */
+ int nVar; /* Number of bind parameters in the pStmt */
+ int nCol; /* Number of columns in the result set */
Tcl_Obj **apColName = 0; /* Array of column names */
+ int len; /* String length of zSql */
- /* Compile a single SQL statement */
- if( SQLITE_OK!=sqlite3_prepare(pDb->db, zSql, -1, &pStmt, &zLeft) ){
- Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db)));
- rc = TCL_ERROR;
- break;
+ /* Try to find a SQL statement that has already been compiled and
+ ** which matches the next sequence of SQL.
+ */
+ pStmt = 0;
+ pPreStmt = pDb->stmtList;
+ len = strlen(zSql);
+ if( pPreStmt && sqlite3_expired(pPreStmt->pStmt) ){
+ flushStmtCache(pDb);
+ pPreStmt = 0;
+ }
+ for(; pPreStmt; pPreStmt=pPreStmt->pNext){
+ int n = pPreStmt->nSql;
+ if( len>=n
+ && memcmp(pPreStmt->zSql, zSql, n)==0
+ && (zSql[n]==0 || zSql[n-1]==';')
+ ){
+ pStmt = pPreStmt->pStmt;
+ zLeft = &zSql[pPreStmt->nSql];
+
+ /* When a prepared statement is found, unlink it from the
+ ** cache list. It will later be added back to the beginning
+ ** of the cache list in order to implement LRU replacement.
+ */
+ if( pPreStmt->pPrev ){
+ pPreStmt->pPrev->pNext = pPreStmt->pNext;
+ }else{
+ pDb->stmtList = pPreStmt->pNext;
+ }
+ if( pPreStmt->pNext ){
+ pPreStmt->pNext->pPrev = pPreStmt->pPrev;
+ }else{
+ pDb->stmtLast = pPreStmt->pPrev;
+ }
+ pDb->nStmt--;
+ break;
+ }
}
+
+ /* If no prepared statement was found. Compile the SQL text
+ */
if( pStmt==0 ){
- if( SQLITE_OK!=sqlite3_errcode(pDb->db) ){
+ if( SQLITE_OK!=sqlite3_prepare(pDb->db, zSql, -1, &pStmt, &zLeft) ){
Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db)));
rc = TCL_ERROR;
break;
- }else{
- zSql = zLeft;
- continue;
}
+ if( pStmt==0 ){
+ if( SQLITE_OK!=sqlite3_errcode(pDb->db) ){
+ /* A compile-time error in the statement
+ */
+ Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db)));
+ rc = TCL_ERROR;
+ break;
+ }else{
+ /* The statement was a no-op. Continue to the next statement
+ ** in the SQL string.
+ */
+ zSql = zLeft;
+ continue;
+ }
+ }
+ assert( pPreStmt==0 );
}
- /* Bind values to wildcards that begin with $ or : */
+ /* Bind values to parameters that begin with $ or :
+ */
nVar = sqlite3_bind_parameter_count(pStmt);
nParm = 0;
if( nVar>sizeof(aParm)/sizeof(aParm[0]) ){
@@ -697,7 +888,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
}
for(i=1; i<=nVar; i++){
const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
- if( zVar[0]=='$' || zVar[0]==':' ){
+ if( zVar!=0 && (zVar[0]=='$' || zVar[0]==':') ){
Tcl_Obj *pVar = Tcl_GetVar2Ex(interp, &zVar[1], 0, 0);
if( pVar ){
int n;
@@ -723,6 +914,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
Tcl_IncrRefCount(pVar);
apParm[nParm++] = pVar;
}
+ }else{
+ sqlite3_bind_null( pStmt, i );
}
}
}
@@ -827,19 +1020,75 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
Tcl_Free((char*)apParm);
}
- /* Finalize the statement. If the result code is SQLITE_SCHEMA, then
- ** try again to execute the same statement
+ /* Reset the statement. If the result code is SQLITE_SCHEMA, then
+ ** flush the statement cache and try the statement again.
*/
- if( SQLITE_SCHEMA==sqlite3_finalize(pStmt) ){
+ rc2 = sqlite3_reset(pStmt);
+ if( SQLITE_SCHEMA==rc2 ){
+ /* After a schema change, flush the cache and try to run the
+ ** statement again
+ */
+ flushStmtCache( pDb );
+ sqlite3_finalize(pStmt);
+ if( pPreStmt ) Tcl_Free((char*)pPreStmt);
continue;
- }
-
- if( SQLITE_OK!=sqlite3_errcode(pDb->db) ){
+ }else if( SQLITE_OK!=rc2 ){
+ /* If a run-time error occurs, report the error and stop reading
+ ** the SQL
+ */
Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db)));
+ sqlite3_finalize(pStmt);
rc = TCL_ERROR;
+ if( pPreStmt ) Tcl_Free((char*)pPreStmt);
break;
+ }else if( pDb->maxStmt<=0 ){
+ /* If the cache is turned off, deallocated the statement */
+ if( pPreStmt ) Tcl_Free((char*)pPreStmt);
+ sqlite3_finalize(pStmt);
+ }else{
+ /* Everything worked and the cache is operational.
+ ** Create a new SqlPreparedStmt structure if we need one.
+ ** (If we already have one we can just reuse it.)
+ */
+ if( pPreStmt==0 ){
+ len = zLeft - zSql;
+ pPreStmt = (SqlPreparedStmt*)Tcl_Alloc( sizeof(*pPreStmt) + len );
+ if( pPreStmt==0 ) return TCL_ERROR;
+ pPreStmt->pStmt = pStmt;
+ pPreStmt->nSql = len;
+ memcpy(pPreStmt->zSql, zSql, len);
+ pPreStmt->zSql[len] = 0;
+ }
+
+ /* Add the prepared statement to the beginning of the cache list
+ */
+ pPreStmt->pNext = pDb->stmtList;
+ pPreStmt->pPrev = 0;
+ if( pDb->stmtList ){
+ pDb->stmtList->pPrev = pPreStmt;
+ }
+ pDb->stmtList = pPreStmt;
+ if( pDb->stmtLast==0 ){
+ assert( pDb->nStmt==0 );
+ pDb->stmtLast = pPreStmt;
+ }else{
+ assert( pDb->nStmt>0 );
+ }
+ pDb->nStmt++;
+
+ /* If we have too many statement in cache, remove the surplus from the
+ ** end of the cache list.
+ */
+ while( pDb->nStmt>pDb->maxStmt ){
+ sqlite3_finalize(pDb->stmtLast->pStmt);
+ pDb->stmtLast = pDb->stmtLast->pPrev;
+ Tcl_Free((char*)pDb->stmtLast->pNext);
+ pDb->stmtLast->pNext = 0;
+ pDb->nStmt--;
+ }
}
+ /* Proceed to the next statement */
zSql = zLeft;
}
Tcl_DecrRefCount(objv[2]);
@@ -879,7 +1128,13 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
strcpy(pFunc->zScript, zScript);
rc = sqlite3_create_function(pDb->db, zName, -1, SQLITE_UTF8,
pFunc, tclSqlFunc, 0, 0);
- if( rc!=SQLITE_OK ) rc = TCL_ERROR;
+ if( rc!=SQLITE_OK ){
+ rc = TCL_ERROR;
+ Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE);
+ }else{
+ /* Must flush any cached statements */
+ flushStmtCache( pDb );
+ }
break;
}
@@ -1040,6 +1295,202 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
break;
}
+ /* $db copy conflict-algorithm table filename ?SEPARATOR? ?NULLINDICATOR?
+ **
+ ** Copy data into table from filename, optionally using SEPARATOR
+ ** as column separators. If a column contains a null string, or the
+ ** value of NULLINDICATOR, a NULL is inserted for the column.
+ ** conflict-algorithm is one of the sqlite conflict algorithms:
+ ** rollback, abort, fail, ignore, replace
+ ** On success, return the number of lines processed, not necessarily same
+ ** as 'db changes' due to conflict-algorithm selected.
+ **
+ ** This code is basically an implementation/enhancement of
+ ** the sqlite3 shell.c ".import" command.
+ **
+ ** This command usage is equivalent to the sqlite2.x COPY statement,
+ ** which imports file data into a table using the PostgreSQL COPY file format:
+ ** $db copy $conflit_algo $table_name $filename \t \\N
+ */
+ case DB_COPY: {
+ char *zTable; /* Insert data into this table */
+ char *zFile; /* The file from which to extract data */
+ char *zConflict; /* The conflict algorithm to use */
+ sqlite3_stmt *pStmt; /* A statement */
+ int rc; /* Result code */
+ int nCol; /* Number of columns in the table */
+ int nByte; /* Number of bytes in an SQL string */
+ int i, j; /* Loop counters */
+ int nSep; /* Number of bytes in zSep[] */
+ int nNull; /* Number of bytes in zNull[] */
+ char *zSql; /* An SQL statement */
+ char *zLine; /* A single line of input from the file */
+ char **azCol; /* zLine[] broken up into columns */
+ char *zCommit; /* How to commit changes */
+ FILE *in; /* The input file */
+ int lineno = 0; /* Line number of input file */
+ char zLineNum[80]; /* Line number print buffer */
+ Tcl_Obj *pResult; /* interp result */
+
+ char *zSep;
+ char *zNull;
+ if( objc<5 || objc>7 ){
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "CONFLICT-ALGORITHM TABLE FILENAME ?SEPARATOR? ?NULLINDICATOR?");
+ return TCL_ERROR;
+ }
+ if( objc>=6 ){
+ zSep = Tcl_GetStringFromObj(objv[5], 0);
+ }else{
+ zSep = "\t";
+ }
+ if( objc>=7 ){
+ zNull = Tcl_GetStringFromObj(objv[6], 0);
+ }else{
+ zNull = "";
+ }
+ zConflict = Tcl_GetStringFromObj(objv[2], 0);
+ zTable = Tcl_GetStringFromObj(objv[3], 0);
+ zFile = Tcl_GetStringFromObj(objv[4], 0);
+ nSep = strlen(zSep);
+ nNull = strlen(zNull);
+ if( nSep==0 ){
+ Tcl_AppendResult(interp, "Error: non-null separator required for copy", 0);
+ return TCL_ERROR;
+ }
+ if(sqlite3StrICmp(zConflict, "rollback") != 0 &&
+ sqlite3StrICmp(zConflict, "abort" ) != 0 &&
+ sqlite3StrICmp(zConflict, "fail" ) != 0 &&
+ sqlite3StrICmp(zConflict, "ignore" ) != 0 &&
+ sqlite3StrICmp(zConflict, "replace" ) != 0 ) {
+ Tcl_AppendResult(interp, "Error: \"", zConflict,
+ "\", conflict-algorithm must be one of: rollback, "
+ "abort, fail, ignore, or replace", 0);
+ return TCL_ERROR;
+ }
+ zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable);
+ if( zSql==0 ){
+ Tcl_AppendResult(interp, "Error: no such table: ", zTable, 0);
+ return TCL_ERROR;
+ }
+ nByte = strlen(zSql);
+ rc = sqlite3_prepare(pDb->db, zSql, 0, &pStmt, 0);
+ sqlite3_free(zSql);
+ if( rc ){
+ Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), 0);
+ nCol = 0;
+ }else{
+ nCol = sqlite3_column_count(pStmt);
+ }
+ sqlite3_finalize(pStmt);
+ if( nCol==0 ) {
+ return TCL_ERROR;
+ }
+ zSql = malloc( nByte + 50 + nCol*2 );
+ if( zSql==0 ) {
+ Tcl_AppendResult(interp, "Error: can't malloc()", 0);
+ return TCL_ERROR;
+ }
+ sqlite3_snprintf(nByte+50, zSql, "INSERT OR %q INTO '%q' VALUES(?",
+ zConflict, zTable);
+ j = strlen(zSql);
+ for(i=1; i<nCol; i++){
+ zSql[j++] = ',';
+ zSql[j++] = '?';
+ }
+ zSql[j++] = ')';
+ zSql[j] = 0;
+ rc = sqlite3_prepare(pDb->db, zSql, 0, &pStmt, 0);
+ free(zSql);
+ if( rc ){
+ Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), 0);
+ sqlite3_finalize(pStmt);
+ return TCL_ERROR;
+ }
+ in = fopen(zFile, "rb");
+ if( in==0 ){
+ Tcl_AppendResult(interp, "Error: cannot open file: ", zFile, NULL);
+ sqlite3_finalize(pStmt);
+ return TCL_ERROR;
+ }
+ azCol = malloc( sizeof(azCol[0])*(nCol+1) );
+ if( azCol==0 ) {
+ Tcl_AppendResult(interp, "Error: can't malloc()", 0);
+ return TCL_ERROR;
+ }
+ sqlite3_exec(pDb->db, "BEGIN", 0, 0, 0);
+ zCommit = "COMMIT";
+ while( (zLine = local_getline(0, in))!=0 ){
+ char *z;
+ i = 0;
+ lineno++;
+ azCol[0] = zLine;
+ for(i=0, z=zLine; *z; z++){
+ if( *z==zSep[0] && strncmp(z, zSep, nSep)==0 ){
+ *z = 0;
+ i++;
+ if( i<nCol ){
+ azCol[i] = &z[nSep];
+ z += nSep-1;
+ }
+ }
+ }
+ if( i+1!=nCol ){
+ char *zErr;
+ zErr = malloc(200 + strlen(zFile));
+ sprintf(zErr,"Error: %s line %d: expected %d columns of data but found %d",
+ zFile, lineno, nCol, i+1);
+ Tcl_AppendResult(interp, zErr, 0);
+ free(zErr);
+ zCommit = "ROLLBACK";
+ break;
+ }
+ for(i=0; i<nCol; i++){
+ /* check for null data, if so, bind as null */
+ if ((nNull>0 && strcmp(azCol[i], zNull)==0) || strlen(azCol[i])==0) {
+ sqlite3_bind_null(pStmt, i+1);
+ }else{
+ sqlite3_bind_text(pStmt, i+1, azCol[i], -1, SQLITE_STATIC);
+ }
+ }
+ sqlite3_step(pStmt);
+ rc = sqlite3_reset(pStmt);
+ free(zLine);
+ if( rc!=SQLITE_OK ){
+ Tcl_AppendResult(interp,"Error: ", sqlite3_errmsg(pDb->db), 0);
+ zCommit = "ROLLBACK";
+ break;
+ }
+ }
+ free(azCol);
+ fclose(in);
+ sqlite3_finalize(pStmt);
+ sqlite3_exec(pDb->db, zCommit, 0, 0, 0);
+
+ if( zCommit[0] == 'C' ){
+ /* success, set result as number of lines processed */
+ pResult = Tcl_GetObjResult(interp);
+ Tcl_SetIntObj(pResult, lineno);
+ rc = TCL_OK;
+ }else{
+ /* failure, append lineno where failed */
+ sprintf(zLineNum,"%d",lineno);
+ Tcl_AppendResult(interp,", failed while processing line: ",zLineNum,0);
+ rc = TCL_ERROR;
+ }
+ break;
+ }
+
+ /* $db version
+ **
+ ** Return the version string for this database.
+ */
+ case DB_VERSION: {
+ Tcl_SetResult(interp, (char *)sqlite3_libversion(), TCL_STATIC);
+ break;
+ }
+
+
} /* End of the SWITCH statement */
return rc;
}
@@ -1146,6 +1597,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
free(zErrMsg);
return TCL_ERROR;
}
+ p->maxStmt = NUM_PREPARED_STMTS;
zArg = Tcl_GetStringFromObj(objv[1], 0);
Tcl_CreateObjCommand(interp, zArg, DbObjCmd, (char*)p, DbDeleteCmd);
@@ -1163,12 +1615,12 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
#ifdef SQLITE_TEST
{
extern void Md5_Register(sqlite3*);
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_MEMDEBUG
int mallocfail = sqlite3_iMallocFail;
sqlite3_iMallocFail = 0;
#endif
Md5_Register(p->db);
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_MEMDEBUG
sqlite3_iMallocFail = mallocfail;
#endif
}
@@ -1199,20 +1651,20 @@ int Sqlite3_Init(Tcl_Interp *interp){
Tcl_InitStubs(interp, "8.4", 0);
Tcl_CreateObjCommand(interp, "sqlite3", (Tcl_ObjCmdProc*)DbMain, 0, 0);
Tcl_PkgProvide(interp, "sqlite3", "3.0");
+ Tcl_CreateObjCommand(interp, "sqlite", (Tcl_ObjCmdProc*)DbMain, 0, 0);
+ Tcl_PkgProvide(interp, "sqlite", "3.0");
return TCL_OK;
}
-int Tclsqlite3_Init(Tcl_Interp *interp){
- Tcl_InitStubs(interp, "8.4", 0);
- Tcl_CreateObjCommand(interp, "sqlite3", (Tcl_ObjCmdProc*)DbMain, 0, 0);
- Tcl_PkgProvide(interp, "sqlite3", "3.0");
- return TCL_OK;
-}
-int Sqlite3_SafeInit(Tcl_Interp *interp){
- return TCL_OK;
-}
-int Tclsqlite3_SafeInit(Tcl_Interp *interp){
- return TCL_OK;
-}
+int Tclsqlite3_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
+int Sqlite3_SafeInit(Tcl_Interp *interp){ return TCL_OK; }
+int Tclsqlite3_SafeInit(Tcl_Interp *interp){ return TCL_OK; }
+
+#ifndef SQLITE_3_SUFFIX_ONLY
+int Sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
+int Tclsqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
+int Sqlite_SafeInit(Tcl_Interp *interp){ return TCL_OK; }
+int Tclsqlite_SafeInit(Tcl_Interp *interp){ return TCL_OK; }
+#endif
#ifdef TCLSH
/*****************************************************************************
@@ -1285,7 +1737,7 @@ int TCLSH_MAIN(int argc, char **argv){
int i;
Tcl_SetVar(interp,"argv0",argv[1],TCL_GLOBAL_ONLY);
Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY);
- for(i=2; i<argc; i++){
+ for(i=3-TCLSH; i<argc; i++){
Tcl_SetVar(interp, "argv", argv[i],
TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE);
}
diff --git a/ext/pdo_sqlite/sqlite/src/test1.c b/ext/pdo_sqlite/sqlite/src/test1.c
index ba4e440eba..7a96c378b5 100644
--- a/ext/pdo_sqlite/sqlite/src/test1.c
+++ b/ext/pdo_sqlite/sqlite/src/test1.c
@@ -478,21 +478,22 @@ static int test_create_function(
){
int rc;
sqlite3 *db;
- sqlite3_value *pVal;
extern void Md5_Register(sqlite3*);
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " FILENAME\"", 0);
+ " DB\"", 0);
return TCL_ERROR;
}
if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_ANY, 0,
ifnullFunc, 0, 0);
+#ifndef SQLITE_OMIT_UTF16
/* Use the sqlite3_create_function16() API here. Mainly for fun, but also
** because it is not tested anywhere else. */
if( rc==SQLITE_OK ){
+ sqlite3_value *pVal;
pVal = sqlite3ValueNew();
sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC);
rc = sqlite3_create_function16(db,
@@ -500,7 +501,10 @@ static int test_create_function(
1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0);
sqlite3ValueFree(pVal);
}
+#endif
+
if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
+ Tcl_SetResult(interp, (char *)errorName(rc), 0);
return TCL_OK;
}
@@ -743,12 +747,17 @@ static int sqlite3_mprintf_stronly(
}
/*
-** Usage: sqlite_malloc_fail N
+** Usage: sqlite_malloc_fail N ?REPEAT-INTERVAL?
+**
+** Rig sqliteMalloc() to fail on the N-th call and every REPEAT-INTERVAL call
+** after that. If REPEAT-INTERVAL is 0 or is omitted, then only a single
+** malloc will fail. If REPEAT-INTERVAL is 1 then all mallocs after the
+** first failure will continue to fail on every call. If REPEAT-INTERVAL is
+** 2 then every other malloc will fail. And so forth.
**
-** Rig sqliteMalloc() to fail on the N-th call. Turn off this mechanism
-** and reset the sqlite3_malloc_failed variable is N==0.
+** Turn off this mechanism and reset the sqlite3_malloc_failed variable is N==0.
*/
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_MEMDEBUG
static int sqlite_malloc_fail(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
@@ -756,12 +765,19 @@ static int sqlite_malloc_fail(
char **argv /* Text of each argument */
){
int n;
- if( argc!=2 ){
+ int rep;
+ if( argc!=2 && argc!=3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
+ if( argc==3 ){
+ if( Tcl_GetInt(interp, argv[2], &rep) ) return TCL_ERROR;
+ }else{
+ rep = 0;
+ }
sqlite3_iMallocFail = n;
+ sqlite3_iMallocReset = rep;
sqlite3_malloc_failed = 0;
return TCL_OK;
}
@@ -772,7 +788,7 @@ static int sqlite_malloc_fail(
**
** Return the number of prior calls to sqliteMalloc() and sqliteFree().
*/
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_MEMDEBUG
static int sqlite_malloc_stat(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
@@ -892,10 +908,12 @@ static int test_finalize(
if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
- db = StmtToDb(pStmt);
+ if( pStmt ){
+ db = StmtToDb(pStmt);
+ }
rc = sqlite3_finalize(pStmt);
Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
- if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
+ if( db && sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
return TCL_OK;
}
@@ -922,7 +940,9 @@ static int test_reset(
if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
rc = sqlite3_reset(pStmt);
- if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
+ if( pStmt &&
+ sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
+ Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
if( rc ){
return TCL_ERROR;
}
@@ -930,6 +950,28 @@ static int test_reset(
}
/*
+** Usage: sqlite3_expired STMT
+**
+** Return TRUE if a recompilation of the statement is recommended.
+*/
+static int test_expired(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ sqlite3_stmt *pStmt;
+ if( objc!=2 ){
+ Tcl_AppendResult(interp, "wrong # args: should be \"",
+ Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
+ return TCL_ERROR;
+ }
+ if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(sqlite3_expired(pStmt)));
+ return TCL_OK;
+}
+
+/*
** Usage: sqlite3_changes DB
**
** Return the number of changes made to the database by the last SQL
@@ -1005,7 +1047,7 @@ static int test_bind(
return TCL_OK;
}
-
+#ifndef SQLITE_OMIT_UTF16
/*
** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be>
**
@@ -1148,6 +1190,7 @@ bad_args:
Tcl_WrongNumArgs(interp, 1, objv, "DB");
return TCL_ERROR;
}
+#endif /* SQLITE_OMIT_UTF16 */
/*
** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be>
@@ -1174,6 +1217,7 @@ bad_args:
** for a UTF-16LE test_function(), and UTF-16LE for an implementation that
** prefers UTF-16BE.
*/
+#ifndef SQLITE_OMIT_UTF16
static void test_function_utf8(
sqlite3_context *pCtx,
int nArg,
@@ -1243,12 +1287,14 @@ static void test_function_utf16be(
-1, SQLITE_TRANSIENT);
sqlite3ValueFree(pVal);
}
+#endif /* SQLITE_OMIT_UTF16 */
static int test_function(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
+#ifndef SQLITE_OMIT_UTF16
sqlite3 *db;
int val;
@@ -1275,6 +1321,7 @@ static int test_function(
bad_args:
Tcl_AppendResult(interp, "wrong # args: should be \"",
Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
+#endif /* SQLITE_OMIT_UTF16 */
return TCL_ERROR;
}
@@ -1553,6 +1600,7 @@ static int test_bind_text16(
int objc,
Tcl_Obj *CONST objv[]
){
+#ifndef SQLITE_OMIT_UTF16
sqlite3_stmt *pStmt;
int idx;
int bytes;
@@ -1576,6 +1624,7 @@ static int test_bind_text16(
return TCL_ERROR;
}
+#endif /* SQLITE_OMIT_UTF16 */
return TCL_OK;
}
@@ -1696,6 +1745,29 @@ static int test_bind_parameter_index(
}
/*
+** Usage: sqlite3_clear_bindings STMT
+**
+*/
+#if 0
+static int test_clear_bindings(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ sqlite3_stmt *pStmt;
+
+ if( objc!=2 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "STMT");
+ return TCL_ERROR;
+ }
+ if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt)));
+ return TCL_OK;
+}
+#endif
+
+/*
** Usage: sqlite3_errcode DB
**
** Return the string representation of the most recent sqlite3_* API
@@ -1760,6 +1832,7 @@ static int test_errmsg16(
int objc,
Tcl_Obj *CONST objv[]
){
+#ifndef SQLITE_OMIT_UTF16
sqlite3 *db;
const void *zErr;
int bytes;
@@ -1774,6 +1847,7 @@ static int test_errmsg16(
zErr = sqlite3_errmsg16(db);
bytes = sqlite3utf16ByteLen(zErr, -1);
Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes));
+#endif /* SQLITE_OMIT_UTF16 */
return TCL_OK;
}
@@ -1844,6 +1918,7 @@ static int test_prepare16(
int objc,
Tcl_Obj *CONST objv[]
){
+#ifndef SQLITE_OMIT_UTF16
sqlite3 *db;
const void *zSql;
const void *zTail = 0;
@@ -1883,6 +1958,7 @@ static int test_prepare16(
if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
}
Tcl_AppendResult(interp, zBuf, 0);
+#endif /* SQLITE_OMIT_UTF16 */
return TCL_OK;
}
@@ -1923,6 +1999,7 @@ static int test_open16(
int objc,
Tcl_Obj *CONST objv[]
){
+#ifndef SQLITE_OMIT_UTF16
const void *zFilename;
sqlite3 *db;
int rc;
@@ -1939,6 +2016,7 @@ static int test_open16(
if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR;
Tcl_AppendResult(interp, zBuf, 0);
+#endif /* SQLITE_OMIT_UTF16 */
return TCL_OK;
}
@@ -1954,6 +2032,7 @@ static int test_complete16(
int objc,
Tcl_Obj *CONST objv[]
){
+#ifndef SQLITE_OMIT_UTF16
char *zBuf;
if( objc!=2 ){
@@ -1963,6 +2042,7 @@ static int test_complete16(
zBuf = Tcl_GetByteArrayFromObj(objv[1], 0);
Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_complete16(zBuf)));
+#endif /* SQLITE_OMIT_UTF16 */
return TCL_OK;
}
@@ -2227,6 +2307,7 @@ static int test_stmt_utf16(
int objc,
Tcl_Obj *CONST objv[]
){
+#ifndef SQLITE_OMIT_UTF16
sqlite3_stmt *pStmt;
int col;
Tcl_Obj *pRet;
@@ -2247,6 +2328,7 @@ static int test_stmt_utf16(
pRet = Tcl_NewByteArrayObj(zName16, sqlite3utf16ByteLen(zName16, -1)+2);
Tcl_SetObjResult(interp, pRet);
}
+#endif /* SQLITE_OMIT_UTF16 */
return TCL_OK;
}
@@ -2443,6 +2525,133 @@ static int test_sqlite3OsTempFileName(
}
/*
+** Usage: sqlite_set_magic DB MAGIC-NUMBER
+**
+** Set the db->magic value. This is used to test error recovery logic.
+*/
+static int sqlite_set_magic(
+ void * clientData,
+ Tcl_Interp *interp,
+ int argc,
+ char **argv
+){
+ sqlite3 *db;
+ if( argc!=3 ){
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " DB MAGIC", 0);
+ return TCL_ERROR;
+ }
+ if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
+ if( strcmp(argv[2], "SQLITE_MAGIC_OPEN")==0 ){
+ db->magic = SQLITE_MAGIC_OPEN;
+ }else if( strcmp(argv[2], "SQLITE_MAGIC_CLOSED")==0 ){
+ db->magic = SQLITE_MAGIC_CLOSED;
+ }else if( strcmp(argv[2], "SQLITE_MAGIC_BUSY")==0 ){
+ db->magic = SQLITE_MAGIC_BUSY;
+ }else if( strcmp(argv[2], "SQLITE_MAGIC_ERROR")==0 ){
+ db->magic = SQLITE_MAGIC_ERROR;
+ }else if( Tcl_GetInt(interp, argv[2], &db->magic) ){
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+** Usage: sqlite3_interrupt DB
+**
+** Trigger an interrupt on DB
+*/
+static int test_interrupt(
+ void * clientData,
+ Tcl_Interp *interp,
+ int argc,
+ char **argv
+){
+ sqlite3 *db;
+ if( argc!=2 ){
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0);
+ return TCL_ERROR;
+ }
+ if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
+ sqlite3_interrupt(db);
+ return TCL_OK;
+}
+
+/*
+** Usage: sqlite3_sleep ms
+**
+** Sleep for the specified number of ms.
+*/
+#if 0
+static int test_sleep(
+ void * clientData,
+ Tcl_Interp *interp,
+ int argc,
+ char **argv
+){
+ sqlite3 *db;
+ if( argc!=2 ){
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " ms", 0);
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_sleep(atoi(argv[1]))));
+ return TCL_OK;
+}
+#endif
+
+/*
+** Usage: sqlite_delete_function DB function-name
+**
+** Delete the user function 'function-name' from database handle DB. It
+** is assumed that the user function was created as UTF8, any number of
+** arguments (the way the TCL interface does it).
+*/
+static int delete_function(
+ void * clientData,
+ Tcl_Interp *interp,
+ int argc,
+ char **argv
+){
+ int rc;
+ sqlite3 *db;
+ if( argc!=3 ){
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " DB function-name", 0);
+ return TCL_ERROR;
+ }
+ if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
+ rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 0, 0, 0);
+ Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
+ return TCL_OK;
+}
+
+/*
+** Usage: sqlite_delete_collation DB collation-name
+**
+** Delete the collation sequence 'collation-name' from database handle
+** DB. It is assumed that the collation sequence was created as UTF8 (the
+** way the TCL interface does it).
+*/
+static int delete_collation(
+ void * clientData,
+ Tcl_Interp *interp,
+ int argc,
+ char **argv
+){
+ int rc;
+ sqlite3 *db;
+ if( argc!=3 ){
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " DB function-name", 0);
+ return TCL_ERROR;
+ }
+ if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
+ rc = sqlite3_create_collation(db, argv[2], SQLITE_UTF8, 0, 0);
+ Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
+ return TCL_OK;
+}
+
+/*
** Usage: tcl_variable_type VARIABLENAME
**
** Return the name of the internal representation for the
@@ -2468,12 +2677,188 @@ static int tcl_variable_type(
}
/*
+** This routine sets entries in the global ::sqlite_options() array variable
+** according to the compile-time configuration of the database. Test
+** procedures use this to determine when tests should be omitted.
+*/
+static void set_options(Tcl_Interp *interp){
+#ifdef SQLITE_32BIT_ROWID
+ Tcl_SetVar2(interp, "sqlite_options", "rowid32", "1", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "rowid32", "0", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_ALTERTABLE
+ Tcl_SetVar2(interp, "sqlite_options", "altertable", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "altertable", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_AUTHORIZATION
+ Tcl_SetVar2(interp, "sqlite_options", "auth", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "auth", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_AUTOINCREMENT
+ Tcl_SetVar2(interp, "sqlite_options", "autoinc", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "autoinc", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_AUTOVACUUM
+ Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "1", TCL_GLOBAL_ONLY);
+#endif /* SQLITE_OMIT_AUTOVACUUM */
+#if !defined(SQLITE_DEFAULT_AUTOVACUUM) || SQLITE_DEFAULT_AUTOVACUUM==0
+ Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","0",TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","1",TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_BLOB_LITERAL
+ Tcl_SetVar2(interp, "sqlite_options", "bloblit", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "bloblit", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_COMPOUND_SELECT
+ Tcl_SetVar2(interp, "sqlite_options", "compound", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "compound", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_CONFLICT_CLAUSE
+ Tcl_SetVar2(interp, "sqlite_options", "conflict", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "conflict", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_DATETIME_FUNCS
+ Tcl_SetVar2(interp, "sqlite_options", "datetime", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "datetime", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_EXPLAIN
+ Tcl_SetVar2(interp, "sqlite_options", "explain", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "explain", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_FLOATING_POINT
+ Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_FOREIGN_KEY
+ Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_INTEGRITY_CHECK
+ Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "integrityck", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_MEMORYDB
+ Tcl_SetVar2(interp, "sqlite_options", "memorydb", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "memorydb", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_PAGER_PRAGMAS
+ Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_PRAGMA
+ Tcl_SetVar2(interp, "sqlite_options", "pragma", "0", TCL_GLOBAL_ONLY);
+ Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "pragma", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
+ Tcl_SetVar2(interp, "sqlite_options", "progress", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "progress", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_REINDEX
+ Tcl_SetVar2(interp, "sqlite_options", "reindex", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "reindex", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
+ Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
+ Tcl_SetVar2(interp, "sqlite_options", "schema_version", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "schema_version", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_SUBQUERY
+ Tcl_SetVar2(interp, "sqlite_options", "subquery", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "subquery", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_TCL_VARIABLE
+ Tcl_SetVar2(interp, "sqlite_options", "tclvar", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "tclvar", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#if defined(THREADSAFE) && THREADSAFE
+ Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "1", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "0", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_TRIGGER
+ Tcl_SetVar2(interp, "sqlite_options", "trigger", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "trigger", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_UTF16
+ Tcl_SetVar2(interp, "sqlite_options", "utf16", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "utf16", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_VACUUM
+ Tcl_SetVar2(interp, "sqlite_options", "vacuum", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "vacuum", "1", TCL_GLOBAL_ONLY);
+#endif
+
+#ifdef SQLITE_OMIT_VIEW
+ Tcl_SetVar2(interp, "sqlite_options", "view", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "view", "1", TCL_GLOBAL_ONLY);
+#endif
+}
+
+/*
** Register commands with the TCL interpreter.
*/
int Sqlitetest1_Init(Tcl_Interp *interp){
extern int sqlite3_search_count;
extern int sqlite3_interrupt_count;
extern int sqlite3_open_file_count;
+ extern int sqlite3_sort_count;
extern int sqlite3_current_time;
static struct {
char *zName;
@@ -2494,7 +2879,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate },
{ "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func },
{ "sqlite_abort", (Tcl_CmdProc*)sqlite_abort },
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_MEMDEBUG
{ "sqlite_malloc_fail", (Tcl_CmdProc*)sqlite_malloc_fail },
{ "sqlite_malloc_stat", (Tcl_CmdProc*)sqlite_malloc_stat },
#endif
@@ -2502,6 +2887,13 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "breakpoint", (Tcl_CmdProc*)test_breakpoint },
{ "sqlite3_key", (Tcl_CmdProc*)test_key },
{ "sqlite3_rekey", (Tcl_CmdProc*)test_rekey },
+ { "sqlite_set_magic", (Tcl_CmdProc*)sqlite_set_magic },
+ { "sqlite3_interrupt", (Tcl_CmdProc*)test_interrupt },
+#if 0
+ { "sqlite3_sleep", (Tcl_CmdProc*)test_sleep },
+#endif
+ { "sqlite_delete_function", (Tcl_CmdProc*)delete_function },
+ { "sqlite_delete_collation", (Tcl_CmdProc*)delete_collation }
};
static struct {
char *zName;
@@ -2518,6 +2910,9 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_bind_parameter_count", test_bind_parameter_count, 0},
{ "sqlite3_bind_parameter_name", test_bind_parameter_name, 0},
{ "sqlite3_bind_parameter_index", test_bind_parameter_index, 0},
+#if 0
+ { "sqlite3_clear_bindings", test_clear_bindings, 0},
+#endif
{ "sqlite3_errcode", test_errcode ,0 },
{ "sqlite3_errmsg", test_errmsg ,0 },
{ "sqlite3_errmsg16", test_errmsg16 ,0 },
@@ -2529,6 +2924,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_prepare16", test_prepare16 ,0 },
{ "sqlite3_finalize", test_finalize ,0 },
{ "sqlite3_reset", test_reset ,0 },
+ { "sqlite3_expired", test_expired ,0 },
{ "sqlite3_changes", test_changes ,0 },
{ "sqlite3_step", test_step ,0 },
@@ -2539,15 +2935,17 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_column_blob", test_column_blob ,0 },
{ "sqlite3_column_double", test_column_double ,0 },
{ "sqlite3_column_int64", test_column_int64 ,0 },
- { "sqlite3_column_int", test_stmt_int, sqlite3_column_int },
- { "sqlite3_column_bytes", test_stmt_int, sqlite3_column_bytes },
- { "sqlite3_column_bytes16", test_stmt_int, sqlite3_column_bytes16 },
{ "sqlite3_column_text", test_stmt_utf8, sqlite3_column_text },
{ "sqlite3_column_decltype", test_stmt_utf8, sqlite3_column_decltype },
{ "sqlite3_column_name", test_stmt_utf8, sqlite3_column_name },
+ { "sqlite3_column_int", test_stmt_int, sqlite3_column_int },
+ { "sqlite3_column_bytes", test_stmt_int, sqlite3_column_bytes },
+#ifndef SQLITE_OMIT_UTF16
+ { "sqlite3_column_bytes16", test_stmt_int, sqlite3_column_bytes16 },
{ "sqlite3_column_text16", test_stmt_utf16, sqlite3_column_text16 },
{ "sqlite3_column_decltype16", test_stmt_utf16, sqlite3_column_decltype16},
{ "sqlite3_column_name16", test_stmt_utf16, sqlite3_column_name16 },
+#endif
/* Functions from os.h */
{ "sqlite3OsOpenReadWrite",test_sqlite3OsOpenReadWrite, 0 },
@@ -2557,16 +2955,19 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
/* Custom test interfaces */
{ "sqlite3OsUnlock", test_sqlite3OsUnlock, 0 },
+#ifndef SQLITE_OMIT_UTF16
{ "add_test_collate", test_collate, 0 },
{ "add_test_collate_needed", test_collate_needed, 0 },
{ "add_test_function", test_function, 0 },
+#endif
{ "sqlite3_crashparams", sqlite3_crashparams, 0 },
{ "sqlite3_test_errstr", test_errstr, 0 },
{ "tcl_variable_type", tcl_variable_type, 0 },
-
};
+ static int bitmask_size = sizeof(Bitmask)*8;
int i;
extern int sqlite3_os_trace;
+
for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
@@ -2577,6 +2978,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
}
Tcl_LinkVar(interp, "sqlite_search_count",
(char*)&sqlite3_search_count, TCL_LINK_INT);
+ Tcl_LinkVar(interp, "sqlite_sort_count",
+ (char*)&sqlite3_sort_count, TCL_LINK_INT);
Tcl_LinkVar(interp, "sqlite_interrupt_count",
(char*)&sqlite3_interrupt_count, TCL_LINK_INT);
Tcl_LinkVar(interp, "sqlite_open_file_count",
@@ -2589,5 +2992,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
(char*)&sqlite_static_bind_value, TCL_LINK_STRING);
Tcl_LinkVar(interp, "sqlite_temp_directory",
(char*)&sqlite3_temp_directory, TCL_LINK_STRING);
+ Tcl_LinkVar(interp, "bitmask_size",
+ (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
+ set_options(interp);
return TCL_OK;
}
diff --git a/ext/pdo_sqlite/sqlite/src/test2.c b/ext/pdo_sqlite/sqlite/src/test2.c
index a3706c1a78..2f8cdf4846 100644
--- a/ext/pdo_sqlite/sqlite/src/test2.c
+++ b/ext/pdo_sqlite/sqlite/src/test2.c
@@ -81,7 +81,7 @@ static int pager_open(
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[2], &nPage) ) return TCL_ERROR;
- rc = sqlite3pager_open(&pPager, argv[1], 0, 1);
+ rc = sqlite3pager_open(&pPager, argv[1], 0, 0);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
@@ -377,6 +377,34 @@ static int page_lookup(
}
/*
+** Usage: pager_truncate ID PGNO
+*/
+static int pager_truncate(
+ void *NotUsed,
+ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
+ int argc, /* Number of arguments */
+ const char **argv /* Text of each argument */
+){
+ Pager *pPager;
+ int rc;
+ int pgno;
+ if( argc!=3 ){
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " ID PGNO\"", 0);
+ return TCL_ERROR;
+ }
+ pPager = sqlite3TextToPtr(argv[1]);
+ if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
+ rc = sqlite3pager_truncate(pPager, pgno);
+ if( rc!=SQLITE_OK ){
+ Tcl_AppendResult(interp, errorName(rc), 0);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+
+/*
** Usage: page_unref PAGE
**
** Drop a pointer to a page.
@@ -553,6 +581,7 @@ int Sqlitetest2_Init(Tcl_Interp *interp){
{ "page_read", (Tcl_CmdProc*)page_read },
{ "page_write", (Tcl_CmdProc*)page_write },
{ "page_number", (Tcl_CmdProc*)page_number },
+ { "pager_truncate", (Tcl_CmdProc*)pager_truncate },
{ "fake_big_file", (Tcl_CmdProc*)fake_big_file },
};
int i;
diff --git a/ext/pdo_sqlite/sqlite/src/test3.c b/ext/pdo_sqlite/sqlite/src/test3.c
index 8824029f89..a3edd8740c 100644
--- a/ext/pdo_sqlite/sqlite/src/test3.c
+++ b/ext/pdo_sqlite/sqlite/src/test3.c
@@ -44,6 +44,7 @@ static char *errorName(int rc){
case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break;
case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break;
case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break;
+ case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break;
default: zName = "SQLITE_Unknown"; break;
}
return zName;
@@ -315,6 +316,7 @@ static int btree_drop_table(
Btree *pBt;
int iTable;
int rc;
+ int notUsed1;
if( argc!=3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID TABLENUM\"", 0);
@@ -322,7 +324,7 @@ static int btree_drop_table(
}
pBt = sqlite3TextToPtr(argv[1]);
if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
- rc = sqlite3BtreeDropTable(pBt, iTable);
+ rc = sqlite3BtreeDropTable(pBt, iTable, &notUsed1);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
@@ -512,10 +514,10 @@ static int btree_pager_stats(
}
pBt = sqlite3TextToPtr(argv[1]);
a = sqlite3pager_stats(sqlite3BtreePager(pBt));
- for(i=0; i<9; i++){
+ for(i=0; i<11; i++){
static char *zName[] = {
"ref", "page", "max", "size", "state", "err",
- "hit", "miss", "ovfl",
+ "hit", "miss", "ovfl", "read", "write"
};
char zBuf[100];
Tcl_AppendElement(interp, zName[i]);
@@ -544,7 +546,9 @@ static int btree_pager_ref_dump(
return TCL_ERROR;
}
pBt = sqlite3TextToPtr(argv[1]);
+#ifdef SQLITE_DEBUG
sqlite3pager_refdump(sqlite3BtreePager(pBt));
+#endif
return TCL_OK;
}
@@ -562,10 +566,10 @@ static int btree_integrity_check(
const char **argv /* Text of each argument */
){
Btree *pBt;
- char *zResult;
int nRoot;
int *aRoot;
int i;
+ char *zResult;
if( argc<3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
@@ -578,7 +582,11 @@ static int btree_integrity_check(
for(i=0; i<argc-2; i++){
if( Tcl_GetInt(interp, argv[i+2], &aRoot[i]) ) return TCL_ERROR;
}
+#ifndef SQLITE_OMIT_INTEGRITY_CHECK
zResult = sqlite3BtreeIntegrityCheck(pBt, aRoot, nRoot);
+#else
+ zResult = 0;
+#endif
if( zResult ){
Tcl_AppendResult(interp, zResult, 0);
sqliteFree(zResult);
@@ -1014,7 +1022,7 @@ static int btree_key(
}
/*
-** Usage: btree_data ID
+** Usage: btree_data ID ?N?
**
** Return the data for the entry at which the cursor is pointing.
*/
@@ -1029,13 +1037,17 @@ static int btree_data(
u32 n;
char *zBuf;
- if( argc!=2 ){
+ if( argc!=2 && argc!=3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID\"", 0);
return TCL_ERROR;
}
pCur = sqlite3TextToPtr(argv[1]);
- sqlite3BtreeDataSize(pCur, &n);
+ if( argc==2 ){
+ sqlite3BtreeDataSize(pCur, &n);
+ }else{
+ n = atoi(argv[2]);
+ }
zBuf = malloc( n+1 );
rc = sqlite3BtreeData(pCur, 0, n, zBuf);
if( rc ){
@@ -1315,6 +1327,72 @@ static int btree_varint_test(
}
/*
+** usage: btree_from_db DB-HANDLE
+**
+** This command returns the btree handle for the main database associated
+** with the database-handle passed as the argument. Example usage:
+**
+** sqlite3 db test.db
+** set bt [btree_from_db db]
+*/
+static int btree_from_db(
+ void *NotUsed,
+ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
+ int argc, /* Number of arguments */
+ const char **argv /* Text of each argument */
+){
+ char zBuf[100];
+ Tcl_CmdInfo info;
+ sqlite3 *db;
+ Btree *pBt;
+
+ if( argc!=2 ){
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " DB-HANDLE\"", 0);
+ return TCL_ERROR;
+ }
+
+ if( 1!=Tcl_GetCommandInfo(interp, argv[1], &info) ){
+ Tcl_AppendResult(interp, "No such db-handle: \"", argv[1], "\"", 0);
+ return TCL_ERROR;
+ }
+ db = *((sqlite3 **)info.objClientData);
+ assert( db );
+
+ pBt = db->aDb[0].pBt;
+ sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", pBt);
+ Tcl_SetResult(interp, zBuf, TCL_VOLATILE);
+ return TCL_OK;
+}
+
+
+/*
+** usage: btree_set_cache_size ID NCACHE
+**
+** Set the size of the cache used by btree $ID.
+*/
+static int btree_set_cache_size(
+ void *NotUsed,
+ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
+ int argc, /* Number of arguments */
+ const char **argv /* Text of each argument */
+){
+ int nCache;
+ Btree *pBt;
+
+ if( argc!=3 ){
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " BT NCACHE\"", 0);
+ return TCL_ERROR;
+ }
+ pBt = sqlite3TextToPtr(argv[1]);
+ if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR;
+ sqlite3BtreeSetCacheSize(pBt, nCache);
+ return TCL_OK;
+}
+
+
+/*
** Register commands with the TCL interpreter.
*/
int Sqlitetest3_Init(Tcl_Interp *interp){
@@ -1360,6 +1438,8 @@ int Sqlitetest3_Init(Tcl_Interp *interp){
{ "btree_begin_statement", (Tcl_CmdProc*)btree_begin_statement },
{ "btree_commit_statement", (Tcl_CmdProc*)btree_commit_statement },
{ "btree_rollback_statement", (Tcl_CmdProc*)btree_rollback_statement },
+ { "btree_from_db", (Tcl_CmdProc*)btree_from_db },
+ { "btree_set_cache_size", (Tcl_CmdProc*)btree_set_cache_size },
};
int i;
diff --git a/ext/pdo_sqlite/sqlite/src/test5.c b/ext/pdo_sqlite/sqlite/src/test5.c
index 4de7269642..28f546f608 100644
--- a/ext/pdo_sqlite/sqlite/src/test5.c
+++ b/ext/pdo_sqlite/sqlite/src/test5.c
@@ -190,7 +190,9 @@ static int test_translate_selftest(
int objc,
Tcl_Obj *CONST objv[]
){
+#ifndef SQLITE_OMIT_UTF16
sqlite3utfSelfTest();
+#endif
return SQLITE_OK;
}
@@ -214,4 +216,3 @@ int Sqlitetest5_Init(Tcl_Interp *interp){
}
return SQLITE_OK;
}
-
diff --git a/ext/pdo_sqlite/sqlite/src/tokenize.c b/ext/pdo_sqlite/sqlite/src/tokenize.c
index 061e5b9a45..fb1f6674df 100644
--- a/ext/pdo_sqlite/sqlite/src/tokenize.c
+++ b/ext/pdo_sqlite/sqlite/src/tokenize.c
@@ -23,106 +23,18 @@
#include <stdlib.h>
/*
-** This function looks up an identifier to determine if it is a
-** keyword. If it is a keyword, the token code of that keyword is
+** The sqlite3KeywordCode function looks up an identifier to determine if
+** it is a keyword. If it is a keyword, the token code of that keyword is
** returned. If the input is not a keyword, TK_ID is returned.
**
** The implementation of this routine was generated by a program,
-** mkkeywordhash.c, located in the tool subdirectory of the distribution.
-** The output of the mkkeywordhash.c program was manually cut and pasted
-** into this file. When the set of keywords for SQLite changes, you
-** must modify the mkkeywordhash.c program (to add or remove keywords from
-** the data tables) then rerun that program to regenerate this function.
+** mkkeywordhash.h, located in the tool subdirectory of the distribution.
+** The output of the mkkeywordhash.c program is written into a file
+** named keywordhash.h and then included into this source file by
+** the #include below.
*/
-int sqlite3KeywordCode(const char *z, int n){
- static const char zText[519] =
- "ABORTAFTERALLANDASCATTACHBEFOREBEGINBETWEENBYCASCADECASECHECK"
- "COLLATECOMMITCONFLICTCONSTRAINTCREATECROSSDATABASEDEFAULTDEFERRABLE"
- "DEFERREDDELETEDESCDETACHDISTINCTDROPEACHELSEENDEXCEPTEXCLUSIVE"
- "EXPLAINFAILFOREIGNFROMFULLGLOBGROUPHAVINGIGNOREIMMEDIATEINDEX"
- "INITIALLYINNERINSERTINSTEADINTERSECTINTOISNULLJOINKEYLEFTLIKE"
- "LIMITMATCHNATURALNOTNULLNULLOFFSETONORDEROUTERPRAGMAPRIMARYRAISE"
- "REFERENCESREPLACERESTRICTRIGHTROLLBACKROWSELECTSETSTATEMENTTABLE"
- "TEMPORARYTHENTRANSACTIONTRIGGERUNIONUNIQUEUPDATEUSINGVACUUMVALUES"
- "VIEWWHENWHERE";
- static const unsigned char aHash[154] = {
- 0, 75, 82, 0, 0, 97, 80, 0, 83, 0, 0, 0, 0,
- 0, 0, 6, 0, 95, 4, 0, 0, 0, 0, 0, 0, 0,
- 0, 96, 86, 8, 0, 26, 13, 7, 19, 15, 0, 0, 32,
- 25, 0, 21, 31, 41, 0, 0, 0, 34, 27, 0, 0, 30,
- 0, 0, 0, 9, 0, 10, 0, 0, 0, 0, 51, 0, 44,
- 43, 0, 45, 40, 0, 29, 39, 35, 0, 0, 20, 0, 59,
- 0, 16, 0, 17, 0, 18, 0, 55, 42, 72, 0, 33, 0,
- 0, 61, 66, 56, 0, 0, 0, 0, 0, 0, 0, 54, 0,
- 0, 0, 0, 0, 74, 50, 76, 64, 52, 0, 0, 0, 0,
- 68, 84, 0, 47, 0, 58, 60, 92, 0, 0, 48, 0, 93,
- 0, 63, 71, 98, 0, 0, 0, 0, 0, 67, 0, 0, 0,
- 0, 87, 0, 0, 0, 0, 0, 90, 88, 0, 94,
- };
- static const unsigned char aNext[98] = {
- 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 12, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0,
- 0, 0, 0, 14, 3, 24, 0, 0, 0, 1, 22, 0, 0,
- 36, 23, 28, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0,
- 0, 49, 37, 0, 0, 0, 38, 0, 53, 0, 57, 62, 0,
- 0, 0, 0, 0, 0, 70, 46, 0, 65, 0, 0, 0, 0,
- 69, 73, 0, 77, 0, 0, 0, 0, 0, 0, 81, 85, 0,
- 91, 79, 78, 0, 0, 89, 0,
- };
- static const unsigned char aLen[98] = {
- 5, 5, 3, 3, 2, 3, 6, 6, 5, 7, 2, 7, 4,
- 5, 7, 6, 8, 10, 6, 5, 8, 7, 10, 8, 6, 4,
- 6, 8, 4, 4, 4, 3, 6, 9, 7, 4, 3, 7, 4,
- 4, 4, 5, 6, 6, 9, 2, 5, 9, 5, 6, 7, 9,
- 4, 2, 6, 4, 3, 4, 4, 5, 5, 7, 3, 7, 4,
- 2, 6, 2, 2, 5, 5, 6, 7, 5, 10, 7, 8, 5,
- 8, 3, 6, 3, 9, 5, 4, 9, 4, 11, 7, 5, 6,
- 6, 5, 6, 6, 4, 4, 5,
- };
- static const unsigned short int aOffset[98] = {
- 0, 5, 10, 13, 16, 16, 19, 25, 31, 36, 43, 45, 52,
- 56, 61, 68, 74, 82, 92, 98, 103, 111, 118, 128, 136, 142,
- 146, 152, 160, 164, 168, 172, 175, 181, 190, 197, 201, 201, 208,
- 212, 216, 220, 225, 231, 237, 246, 246, 251, 260, 265, 271, 278,
- 287, 291, 291, 297, 301, 304, 308, 312, 317, 322, 329, 329, 336,
- 340, 340, 346, 348, 348, 353, 358, 364, 371, 376, 386, 393, 401,
- 406, 414, 417, 423, 426, 435, 440, 440, 449, 453, 464, 471, 476,
- 482, 488, 493, 499, 505, 509, 513,
- };
- static const unsigned char aCode[98] = {
- TK_ABORT, TK_AFTER, TK_ALL, TK_AND, TK_AS,
- TK_ASC, TK_ATTACH, TK_BEFORE, TK_BEGIN, TK_BETWEEN,
- TK_BY, TK_CASCADE, TK_CASE, TK_CHECK, TK_COLLATE,
- TK_COMMIT, TK_CONFLICT, TK_CONSTRAINT, TK_CREATE, TK_JOIN_KW,
- TK_DATABASE, TK_DEFAULT, TK_DEFERRABLE, TK_DEFERRED, TK_DELETE,
- TK_DESC, TK_DETACH, TK_DISTINCT, TK_DROP, TK_EACH,
- TK_ELSE, TK_END, TK_EXCEPT, TK_EXCLUSIVE, TK_EXPLAIN,
- TK_FAIL, TK_FOR, TK_FOREIGN, TK_FROM, TK_JOIN_KW,
- TK_GLOB, TK_GROUP, TK_HAVING, TK_IGNORE, TK_IMMEDIATE,
- TK_IN, TK_INDEX, TK_INITIALLY, TK_JOIN_KW, TK_INSERT,
- TK_INSTEAD, TK_INTERSECT, TK_INTO, TK_IS, TK_ISNULL,
- TK_JOIN, TK_KEY, TK_JOIN_KW, TK_LIKE, TK_LIMIT,
- TK_MATCH, TK_JOIN_KW, TK_NOT, TK_NOTNULL, TK_NULL,
- TK_OF, TK_OFFSET, TK_ON, TK_OR, TK_ORDER,
- TK_JOIN_KW, TK_PRAGMA, TK_PRIMARY, TK_RAISE, TK_REFERENCES,
- TK_REPLACE, TK_RESTRICT, TK_JOIN_KW, TK_ROLLBACK, TK_ROW,
- TK_SELECT, TK_SET, TK_STATEMENT, TK_TABLE, TK_TEMP,
- TK_TEMP, TK_THEN, TK_TRANSACTION,TK_TRIGGER, TK_UNION,
- TK_UNIQUE, TK_UPDATE, TK_USING, TK_VACUUM, TK_VALUES,
- TK_VIEW, TK_WHEN, TK_WHERE,
- };
- int h, i;
- if( n<2 ) return TK_ID;
- h = (sqlite3UpperToLower[((unsigned char*)z)[0]]*5 +
- sqlite3UpperToLower[((unsigned char*)z)[n-1]]*3 +
- n) % 154;
- for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){
- if( aLen[i]==n && sqlite3StrNICmp(&zText[aOffset[i]],z,n)==0 ){
- return aCode[i];
- }
- }
- return TK_ID;
-}
+#include "keywordhash.h"
+
/*
** If X is a character that can be used in an identifier and
@@ -137,9 +49,15 @@ int sqlite3KeywordCode(const char *z, int n){
** with the high-order bit set. The latter rule means that
** any sequence of UTF-8 characters or characters taken from
** an extended ISO8859 character set can form an identifier.
+**
+** Ticket #1066. the SQL standard does not allow '$' in the
+** middle of identfiers. But many SQL implementations do.
+** SQLite will allow '$' in identifiers for compatibility.
+** But the feature is undocumented.
*/
static const char isIdChar[] = {
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */
@@ -147,13 +65,13 @@ static const char isIdChar[] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */
};
-#define IdChar(C) (((c=C)&0x80)!=0 || (c>0x2f && isIdChar[c-0x30]))
+#define IdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && isIdChar[c-0x20]))
/*
** Return the length of the token that begins at z[0].
** Store the token type in *tokenType before returning.
*/
-static int sqliteGetToken(const unsigned char *z, int *tokenType){
+static int getToken(const unsigned char *z, int *tokenType){
int i, c;
switch( *z ){
case ' ': case '\t': case '\n': case '\f': case '\r': {
@@ -265,6 +183,11 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){
*tokenType = TK_BITNOT;
return 1;
}
+ case '#': {
+ for(i=1; isdigit(z[i]) || (i==1 && z[1]=='-'); i++){}
+ *tokenType = TK_REGISTER;
+ return i;
+ }
case '\'': case '"': {
int delim = z[0];
for(i=1; (c=z[i])!=0; i++){
@@ -288,6 +211,7 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){
case '5': case '6': case '7': case '8': case '9': {
*tokenType = TK_INTEGER;
for(i=1; isdigit(z[i]); i++){}
+#ifndef SQLITE_OMIT_FLOATING_POINT
if( z[i]=='.' && isdigit(z[i+1]) ){
i += 2;
while( isdigit(z[i]) ){ i++; }
@@ -302,6 +226,7 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){
while( isdigit(z[i]) ){ i++; }
*tokenType = TK_FLOAT;
}
+#endif
return i;
}
case '[': {
@@ -319,6 +244,7 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){
*tokenType = i>1 ? TK_VARIABLE : TK_ILLEGAL;
return i;
}
+#ifndef SQLITE_OMIT_TCL_VARIABLE
case '$': {
*tokenType = TK_VARIABLE;
if( z[1]=='{' ){
@@ -355,7 +281,9 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){
if( n==0 ) *tokenType = TK_ILLEGAL;
}
return i;
- }
+ }
+#endif
+#ifndef SQLITE_OMIT_BLOB_LITERAL
case 'x': case 'X': {
if( (c=z[1])=='\'' || c=='"' ){
int delim = c;
@@ -375,18 +303,22 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){
}
/* Otherwise fall through to the next case */
}
+#endif
default: {
if( !IdChar(*z) ){
break;
}
for(i=1; IdChar(z[i]); i++){}
- *tokenType = sqlite3KeywordCode((char*)z, i);
+ *tokenType = keywordCode((char*)z, i);
return i;
}
}
*tokenType = TK_ILLEGAL;
return 1;
}
+int sqlite3GetToken(const unsigned char *z, int *tokenType){
+ return getToken(z, tokenType);
+}
/*
** Run the parser on the given SQL string. The parser structure is
@@ -426,7 +358,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
assert( i>=0 );
pParse->sLastToken.z = &zSql[i];
assert( pParse->sLastToken.dyn==0 );
- pParse->sLastToken.n = sqliteGetToken((unsigned char*)&zSql[i], &tokenType);
+ pParse->sLastToken.n = getToken((unsigned char*)&zSql[i],&tokenType);
i += pParse->sLastToken.n;
switch( tokenType ){
case TK_SPACE:
@@ -486,7 +418,7 @@ abort_parse:
pParse->zErrMsg = 0;
if( !nErr ) nErr++;
}
- if( pParse->pVdbe && pParse->nErr>0 ){
+ if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){
sqlite3VdbeDelete(pParse->pVdbe);
pParse->pVdbe = 0;
}
@@ -503,14 +435,14 @@ abort_parse:
** Token types used by the sqlite3_complete() routine. See the header
** comments on that procedure for additional information.
*/
-#define tkEXPLAIN 0
-#define tkCREATE 1
-#define tkTEMP 2
-#define tkTRIGGER 3
-#define tkEND 4
-#define tkSEMI 5
-#define tkWS 6
-#define tkOTHER 7
+#define tkSEMI 0
+#define tkWS 1
+#define tkOTHER 2
+#define tkEXPLAIN 3
+#define tkCREATE 4
+#define tkTEMP 5
+#define tkTRIGGER 6
+#define tkEND 7
/*
** Return TRUE if the given SQL string ends in a semicolon.
@@ -525,16 +457,16 @@ abort_parse:
** returns 1 if it ends in the START state and 0 if it ends
** in any other state.
**
-** (1) EXPLAIN The keyword EXPLAIN has been seen at the beginning of
+** (1) NORMAL We are in the middle of statement which ends with a single
+** semicolon.
+**
+** (2) EXPLAIN The keyword EXPLAIN has been seen at the beginning of
** a statement.
**
-** (2) CREATE The keyword CREATE has been seen at the beginning of a
+** (3) CREATE The keyword CREATE has been seen at the beginning of a
** statement, possibly preceeded by EXPLAIN and/or followed by
** TEMP or TEMPORARY
**
-** (3) NORMAL We are in the middle of statement which ends with a single
-** semicolon.
-**
** (4) TRIGGER We are in the middle of a trigger definition that must be
** ended by a semicolon, the keyword END, and another semicolon.
**
@@ -547,36 +479,51 @@ abort_parse:
** Transitions between states above are determined by tokens extracted
** from the input. The following tokens are significant:
**
-** (0) tkEXPLAIN The "explain" keyword.
-** (1) tkCREATE The "create" keyword.
-** (2) tkTEMP The "temp" or "temporary" keyword.
-** (3) tkTRIGGER The "trigger" keyword.
-** (4) tkEND The "end" keyword.
-** (5) tkSEMI A semicolon.
-** (6) tkWS Whitespace
-** (7) tkOTHER Any other SQL token.
+** (0) tkSEMI A semicolon.
+** (1) tkWS Whitespace
+** (2) tkOTHER Any other SQL token.
+** (3) tkEXPLAIN The "explain" keyword.
+** (4) tkCREATE The "create" keyword.
+** (5) tkTEMP The "temp" or "temporary" keyword.
+** (6) tkTRIGGER The "trigger" keyword.
+** (7) tkEND The "end" keyword.
**
** Whitespace never causes a state transition and is always ignored.
+**
+** If we compile with SQLITE_OMIT_TRIGGER, all of the computation needed
+** to recognize the end of a trigger can be omitted. All we have to do
+** is look for a semicolon that is not part of an string or comment.
*/
int sqlite3_complete(const char *zSql){
u8 state = 0; /* Current state, using numbers defined in header comment */
u8 token; /* Value of the next token */
- /* The following matrix defines the transition from one state to another
- ** according to what token is seen. trans[state][token] returns the
- ** next state.
+#ifndef SQLITE_OMIT_TRIGGER
+ /* A complex statement machine used to detect the end of a CREATE TRIGGER
+ ** statement. This is the normal case.
*/
static const u8 trans[7][8] = {
/* Token: */
- /* State: ** EXPLAIN CREATE TEMP TRIGGER END SEMI WS OTHER */
- /* 0 START: */ { 1, 2, 3, 3, 3, 0, 0, 3, },
- /* 1 EXPLAIN: */ { 3, 2, 3, 3, 3, 0, 1, 3, },
- /* 2 CREATE: */ { 3, 3, 2, 4, 3, 0, 2, 3, },
- /* 3 NORMAL: */ { 3, 3, 3, 3, 3, 0, 3, 3, },
- /* 4 TRIGGER: */ { 4, 4, 4, 4, 4, 5, 4, 4, },
- /* 5 SEMI: */ { 4, 4, 4, 4, 6, 5, 5, 4, },
- /* 6 END: */ { 4, 4, 4, 4, 4, 0, 6, 4, },
+ /* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */
+ /* 0 START: */ { 0, 0, 1, 2, 3, 1, 1, 1, },
+ /* 1 NORMAL: */ { 0, 1, 1, 1, 1, 1, 1, 1, },
+ /* 2 EXPLAIN: */ { 0, 2, 1, 1, 3, 1, 1, 1, },
+ /* 3 CREATE: */ { 0, 3, 1, 1, 1, 3, 4, 1, },
+ /* 4 TRIGGER: */ { 5, 4, 4, 4, 4, 4, 4, 4, },
+ /* 5 SEMI: */ { 5, 5, 4, 4, 4, 4, 4, 6, },
+ /* 6 END: */ { 0, 6, 4, 4, 4, 4, 4, 4, },
+ };
+#else
+ /* If triggers are not suppored by this compile then the statement machine
+ ** used to detect the end of a statement is much simplier
+ */
+ static const u8 trans[2][3] = {
+ /* Token: */
+ /* State: ** SEMI WS OTHER */
+ /* 0 START: */ { 0, 0, 1, },
+ /* 1 NORMAL: */ { 0, 1, 1, },
};
+#endif /* SQLITE_OMIT_TRIGGER */
while( *zSql ){
switch( *zSql ){
@@ -636,6 +583,9 @@ int sqlite3_complete(const char *zSql){
/* Keywords and unquoted identifiers */
int nId;
for(nId=1; IdChar(zSql[nId]); nId++){}
+#ifdef SQLITE_OMIT_TRIGGER
+ token = tkOTHER;
+#else
switch( *zSql ){
case 'c': case 'C': {
if( nId==6 && sqlite3StrNICmp(zSql, "create", 6)==0 ){
@@ -660,9 +610,13 @@ int sqlite3_complete(const char *zSql){
case 'e': case 'E': {
if( nId==3 && sqlite3StrNICmp(zSql, "end", 3)==0 ){
token = tkEND;
- }else if( nId==7 && sqlite3StrNICmp(zSql, "explain", 7)==0 ){
+ }else
+#ifndef SQLITE_OMIT_EXPLAIN
+ if( nId==7 && sqlite3StrNICmp(zSql, "explain", 7)==0 ){
token = tkEXPLAIN;
- }else{
+ }else
+#endif
+ {
token = tkOTHER;
}
break;
@@ -672,6 +626,7 @@ int sqlite3_complete(const char *zSql){
break;
}
}
+#endif /* SQLITE_OMIT_TRIGGER */
zSql += nId-1;
}else{
/* Operators and special symbols */
@@ -686,6 +641,7 @@ int sqlite3_complete(const char *zSql){
return state==0;
}
+#ifndef SQLITE_OMIT_UTF16
/*
** This routine is the same as the sqlite3_complete() routine described
** above, except that the parameter is required to be UTF-16 encoded, not
@@ -705,3 +661,4 @@ int sqlite3_complete16(const void *zSql){
sqlite3ValueFree(pVal);
return rc;
}
+#endif /* SQLITE_OMIT_UTF16 */
diff --git a/ext/pdo_sqlite/sqlite/src/trigger.c b/ext/pdo_sqlite/sqlite/src/trigger.c
index bbb526f802..eccc810e9b 100644
--- a/ext/pdo_sqlite/sqlite/src/trigger.c
+++ b/ext/pdo_sqlite/sqlite/src/trigger.c
@@ -12,6 +12,7 @@
*/
#include "sqliteInt.h"
+#ifndef SQLITE_OMIT_TRIGGER
/*
** Delete a linked list of TriggerStep structures.
*/
@@ -110,9 +111,7 @@ void sqlite3BeginTrigger(
}
/* Do not create a trigger on a system table */
- if( (iDb!=1 && sqlite3StrICmp(pTab->zName, MASTER_NAME)==0) ||
- (iDb==1 && sqlite3StrICmp(pTab->zName, TEMP_MASTER_NAME)==0)
- ){
+ if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
sqlite3ErrorMsg(pParse, "cannot create trigger on system table");
pParse->nErr++;
goto trigger_cleanup;
@@ -166,7 +165,7 @@ void sqlite3BeginTrigger(
pTrigger->iDb = iDb;
pTrigger->iTabDb = pTab->iDb;
pTrigger->op = op;
- pTrigger->tr_tm = tr_tm;
+ pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER;
pTrigger->pWhen = sqlite3ExprDup(pWhen);
pTrigger->pColumns = sqlite3IdListDup(pColumns);
pTrigger->foreach = foreach;
@@ -190,20 +189,20 @@ void sqlite3FinishTrigger(
TriggerStep *pStepList, /* The triggered program */
Token *pAll /* Token that describes the complete CREATE TRIGGER */
){
- Trigger *nt = 0; /* The trigger whose construction is finishing up */
+ Trigger *pTrig = 0; /* The trigger whose construction is finishing up */
sqlite3 *db = pParse->db; /* The database */
DbFixer sFix;
if( pParse->nErr || pParse->pNewTrigger==0 ) goto triggerfinish_cleanup;
- nt = pParse->pNewTrigger;
+ pTrig = pParse->pNewTrigger;
pParse->pNewTrigger = 0;
- nt->step_list = pStepList;
+ pTrig->step_list = pStepList;
while( pStepList ){
- pStepList->pTrig = nt;
+ pStepList->pTrig = pTrig;
pStepList = pStepList->pNext;
}
- if( sqlite3FixInit(&sFix, pParse, nt->iDb, "trigger", &nt->nameToken)
- && sqlite3FixTriggerStep(&sFix, nt->step_list) ){
+ if( sqlite3FixInit(&sFix, pParse, pTrig->iDb, "trigger", &pTrig->nameToken)
+ && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){
goto triggerfinish_cleanup;
}
@@ -229,35 +228,32 @@ void sqlite3FinishTrigger(
/* Make an entry in the sqlite_master table */
v = sqlite3GetVdbe(pParse);
if( v==0 ) goto triggerfinish_cleanup;
- sqlite3BeginWriteOperation(pParse, 0, nt->iDb);
- sqlite3OpenMasterTable(v, nt->iDb);
+ sqlite3BeginWriteOperation(pParse, 0, pTrig->iDb);
+ sqlite3OpenMasterTable(v, pTrig->iDb);
addr = sqlite3VdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
- sqlite3VdbeChangeP3(v, addr+2, nt->name, 0);
- sqlite3VdbeChangeP3(v, addr+3, nt->table, 0);
+ sqlite3VdbeChangeP3(v, addr+2, pTrig->name, 0);
+ sqlite3VdbeChangeP3(v, addr+3, pTrig->table, 0);
sqlite3VdbeChangeP3(v, addr+6, pAll->z, pAll->n);
- if( nt->iDb!=0 ){
- sqlite3ChangeCookie(db, v, nt->iDb);
- }
+ sqlite3ChangeCookie(db, v, pTrig->iDb);
sqlite3VdbeAddOp(v, OP_Close, 0, 0);
- sqlite3VdbeOp3(v, OP_ParseSchema, nt->iDb, 0,
- sqlite3MPrintf("type='trigger' AND name='%q'", nt->name), P3_DYNAMIC);
+ sqlite3VdbeOp3(v, OP_ParseSchema, pTrig->iDb, 0,
+ sqlite3MPrintf("type='trigger' AND name='%q'", pTrig->name), P3_DYNAMIC);
}
if( db->init.busy ){
Table *pTab;
- sqlite3HashInsert(&db->aDb[nt->iDb].trigHash,
- nt->name, strlen(nt->name)+1, nt);
- pTab = sqlite3LocateTable(pParse, nt->table, db->aDb[nt->iTabDb].zName);
+ sqlite3HashInsert(&db->aDb[pTrig->iDb].trigHash,
+ pTrig->name, strlen(pTrig->name)+1, pTrig);
+ pTab = sqlite3LocateTable(pParse,pTrig->table,db->aDb[pTrig->iTabDb].zName);
assert( pTab!=0 );
- nt->pNext = pTab->pTrigger;
- pTab->pTrigger = nt;
- nt = 0;
+ pTrig->pNext = pTab->pTrigger;
+ pTab->pTrigger = pTrig;
+ pTrig = 0;
}
triggerfinish_cleanup:
- sqlite3DeleteTrigger(nt);
- sqlite3DeleteTrigger(pParse->pNewTrigger);
- pParse->pNewTrigger = 0;
+ sqlite3DeleteTrigger(pTrig);
+ assert( !pParse->pNewTrigger );
sqlite3DeleteTriggerStep(pStepList);
}
@@ -555,52 +551,38 @@ static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){
return 0;
}
-/* A global variable that is TRUE if we should always set up temp tables for
- * for triggers, even if there are no triggers to code. This is used to test
- * how much overhead the triggers algorithm is causing.
- *
- * This flag can be set or cleared using the "trigger_overhead_test" pragma.
- * The pragma is not documented since it is not really part of the interface
- * to SQLite, just the test procedure.
-*/
-int sqlite3_always_code_trigger_setup = 0;
-
/*
- * Returns true if a trigger matching op, tr_tm and foreach that is NOT already
- * on the Parse objects trigger-stack (to prevent recursive trigger firing) is
- * found in the list specified as pTrigger.
- */
+** Return a bit vector to indicate what kind of triggers exist for operation
+** "op" on table pTab. If pChanges is not NULL then it is a list of columns
+** that are being updated. Triggers only match if the ON clause of the
+** trigger definition overlaps the set of columns being updated.
+**
+** The returned bit vector is some combination of TRIGGER_BEFORE and
+** TRIGGER_AFTER.
+*/
int sqlite3TriggersExist(
Parse *pParse, /* Used to check for recursive triggers */
- Trigger *pTrigger, /* A list of triggers associated with a table */
+ Table *pTab, /* The table the contains the triggers */
int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
- int tr_tm, /* one of TK_BEFORE, TK_AFTER */
- int foreach, /* one of TK_ROW or TK_STATEMENT */
ExprList *pChanges /* Columns that change in an UPDATE statement */
){
- Trigger * pTriggerCursor;
+ Trigger *pTrigger = pTab->pTrigger;
+ int mask = 0;
- if( sqlite3_always_code_trigger_setup ){
- return 1;
- }
-
- pTriggerCursor = pTrigger;
- while( pTriggerCursor ){
- if( pTriggerCursor->op == op &&
- pTriggerCursor->tr_tm == tr_tm &&
- pTriggerCursor->foreach == foreach &&
- checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){
- TriggerStack * ss;
+ while( pTrigger ){
+ if( pTrigger->op==op && checkColumnOverLap(pTrigger->pColumns, pChanges) ){
+ TriggerStack *ss;
ss = pParse->trigStack;
- while( ss && ss->pTrigger != pTrigger ){
+ while( ss && ss->pTrigger!=pTab->pTrigger ){
ss = ss->pNext;
}
- if( !ss )return 1;
+ if( ss==0 ){
+ mask |= pTrigger->tr_tm;
+ }
}
- pTriggerCursor = pTriggerCursor->pNext;
+ pTrigger = pTrigger->pNext;
}
-
- return 0;
+ return mask;
}
/*
@@ -658,6 +640,7 @@ static int codeTriggerProgram(
Select * ss = sqlite3SelectDup(pTriggerStep->pSelect);
assert(ss);
assert(ss->pSrc);
+ sqlite3SelectResolve(pParse, ss, 0);
sqlite3Select(pParse, ss, SRT_Discard, 0, 0, 0, 0, 0);
sqlite3SelectDelete(ss);
break;
@@ -726,7 +709,7 @@ int sqlite3CodeRowTrigger(
Parse *pParse, /* Parse context */
int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
- int tr_tm, /* One of TK_BEFORE, TK_AFTER */
+ int tr_tm, /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
Table *pTab, /* The table to code triggers from */
int newIdx, /* The indice of the "new" row to access */
int oldIdx, /* The indice of the "old" row to access */
@@ -738,7 +721,7 @@ int sqlite3CodeRowTrigger(
TriggerStack trigStackEntry;
assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
- assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER );
+ assert(tr_tm == TRIGGER_BEFORE || tr_tm == TRIGGER_AFTER );
assert(newIdx != -1 || oldIdx != -1);
@@ -747,8 +730,7 @@ int sqlite3CodeRowTrigger(
int fire_this = 0;
/* determine whether we should code this trigger */
- if( pTrigger->op == op && pTrigger->tr_tm == tr_tm &&
- pTrigger->foreach == TK_ROW ){
+ if( pTrigger->op == op && pTrigger->tr_tm == tr_tm ){
fire_this = 1;
for(pStack=pParse->trigStack; pStack; pStack=pStack->pNext){
if( pStack->pTrigger==pTrigger ){
@@ -763,11 +745,12 @@ int sqlite3CodeRowTrigger(
if( fire_this ){
int endTrigger;
- SrcList dummyTablist;
Expr * whenExpr;
AuthContext sContext;
+ NameContext sNC;
- dummyTablist.nSrc = 0;
+ memset(&sNC, 0, sizeof(sNC));
+ sNC.pParse = pParse;
/* Push an entry on to the trigger stack */
trigStackEntry.pTrigger = pTrigger;
@@ -782,7 +765,7 @@ int sqlite3CodeRowTrigger(
/* code the WHEN clause */
endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe);
whenExpr = sqlite3ExprDup(pTrigger->pWhen);
- if( sqlite3ExprResolveIds(pParse, &dummyTablist, 0, whenExpr) ){
+ if( sqlite3ExprResolveNames(&sNC, whenExpr) ){
pParse->trigStack = trigStackEntry.pNext;
sqlite3ExprDelete(whenExpr);
return 1;
@@ -802,3 +785,4 @@ int sqlite3CodeRowTrigger(
}
return 0;
}
+#endif /* !defined(SQLITE_OMIT_TRIGGER) */
diff --git a/ext/pdo_sqlite/sqlite/src/update.c b/ext/pdo_sqlite/sqlite/src/update.c
index 08c7987c6f..29ac02a646 100644
--- a/ext/pdo_sqlite/sqlite/src/update.c
+++ b/ext/pdo_sqlite/sqlite/src/update.c
@@ -48,12 +48,13 @@ void sqlite3Update(
int chngRecno; /* True if the record number is being changed */
Expr *pRecnoExpr = 0; /* Expression defining the new record number */
int openAll = 0; /* True if all indices need to be opened */
- int isView; /* Trying to update a view */
AuthContext sContext; /* The authorization context */
+ NameContext sNC; /* The name-context to resolve expressions in */
- int before_triggers; /* True if there are any BEFORE triggers */
- int after_triggers; /* True if there are any AFTER triggers */
- int row_triggers_exist = 0; /* True if any row triggers exist */
+#ifndef SQLITE_OMIT_TRIGGER
+ int isView; /* Trying to update a view */
+ int triggers_exist = 0; /* True if any row triggers exist */
+#endif
int newIdx = -1; /* index of trigger "new" temp table */
int oldIdx = -1; /* index of trigger "old" temp table */
@@ -67,13 +68,23 @@ void sqlite3Update(
*/
pTab = sqlite3SrcListLookup(pParse, pTabList);
if( pTab==0 ) goto update_cleanup;
- before_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger,
- TK_UPDATE, TK_BEFORE, TK_ROW, pChanges);
- after_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger,
- TK_UPDATE, TK_AFTER, TK_ROW, pChanges);
- row_triggers_exist = before_triggers || after_triggers;
+
+ /* Figure out if we have any triggers and if the table being
+ ** updated is a view
+ */
+#ifndef SQLITE_OMIT_TRIGGER
+ triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges);
isView = pTab->pSelect!=0;
- if( sqlite3IsReadOnly(pParse, pTab, before_triggers) ){
+#else
+# define triggers_exist 0
+# define isView 0
+#endif
+#ifdef SQLITE_OMIT_VIEW
+# undef isView
+# define isView 0
+#endif
+
+ if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){
goto update_cleanup;
}
if( isView ){
@@ -88,7 +99,7 @@ void sqlite3Update(
/* If there are FOR EACH ROW triggers, allocate cursors for the
** special OLD and NEW tables
*/
- if( row_triggers_exist ){
+ if( triggers_exist ){
newIdx = pParse->nTab++;
oldIdx = pParse->nTab++;
}
@@ -103,6 +114,11 @@ void sqlite3Update(
pParse->nTab++;
}
+ /* Initialize the name-context */
+ memset(&sNC, 0, sizeof(sNC));
+ sNC.pParse = pParse;
+ sNC.pSrcList = pTabList;
+
/* Resolve the column names in all the expressions of the
** of the UPDATE statement. Also find the column index
** for each column to be updated in the pChanges array. For each
@@ -111,8 +127,7 @@ void sqlite3Update(
*/
chngRecno = 0;
for(i=0; i<pChanges->nExpr; i++){
- if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0,
- pChanges->a[i].pExpr, 0, 0) ){
+ if( sqlite3ExprResolveNames(&sNC, pChanges->a[i].pExpr) ){
goto update_cleanup;
}
for(j=0; j<pTab->nCol; j++){
@@ -188,7 +203,7 @@ void sqlite3Update(
/* Resolve the column names in all the expressions in the
** WHERE clause.
*/
- if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0, pWhere, 0, 0) ){
+ if( sqlite3ExprResolveNames(&sNC, pWhere) ){
goto update_cleanup;
}
@@ -202,7 +217,7 @@ void sqlite3Update(
*/
v = sqlite3GetVdbe(pParse);
if( v==0 ) goto update_cleanup;
- sqlite3VdbeCountChanges(v);
+ if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
sqlite3BeginWriteOperation(pParse, 1, pTab->iDb);
/* If we are trying to update a view, construct that view into
@@ -217,11 +232,12 @@ void sqlite3Update(
/* Begin the database scan
*/
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 1, 0);
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0);
if( pWInfo==0 ) goto update_cleanup;
/* Remember the index of every item to be updated.
*/
+ sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0);
/* End the database scan loop.
@@ -234,7 +250,7 @@ void sqlite3Update(
sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
}
- if( row_triggers_exist ){
+ if( triggers_exist ){
/* Create pseudo-tables for NEW and OLD
*/
sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
@@ -266,11 +282,11 @@ void sqlite3Update(
/* Generate the NEW table
*/
if( chngRecno ){
- sqlite3ExprCode(pParse, pRecnoExpr);
+ sqlite3ExprCodeAndCache(pParse, pRecnoExpr);
}else{
sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
}
- for(i=0; i<pTab->nCol; i++){ /* TODO: Factor out this loop as common code */
+ for(i=0; i<pTab->nCol; i++){
if( i==pTab->iPKey ){
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
continue;
@@ -279,7 +295,7 @@ void sqlite3Update(
if( j<0 ){
sqlite3VdbeAddOp(v, OP_Column, iCur, i);
}else{
- sqlite3ExprCode(pParse, pChanges->a[j].pExpr);
+ sqlite3ExprCodeAndCache(pParse, pChanges->a[j].pExpr);
}
}
sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
@@ -294,7 +310,7 @@ void sqlite3Update(
/* Fire the BEFORE and INSTEAD OF triggers
*/
- if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE, pTab,
+ if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TRIGGER_BEFORE, pTab,
newIdx, oldIdx, onError, addr) ){
goto update_cleanup;
}
@@ -336,7 +352,7 @@ void sqlite3Update(
** Also, the old data is needed to delete the old index entires.
** So make the cursor point at the old record.
*/
- if( !row_triggers_exist ){
+ if( !triggers_exist ){
sqlite3VdbeAddOp(v, OP_ListRewind, 0, 0);
addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, 0);
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
@@ -396,7 +412,7 @@ void sqlite3Update(
/* If there are triggers, close all the cursors after each iteration
** through the loop. The fire the after triggers.
*/
- if( row_triggers_exist ){
+ if( triggers_exist ){
if( !isView ){
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
if( openAll || aIdxUsed[i] )
@@ -404,7 +420,7 @@ void sqlite3Update(
}
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
}
- if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER, pTab,
+ if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TRIGGER_AFTER, pTab,
newIdx, oldIdx, onError, addr) ){
goto update_cleanup;
}
@@ -418,7 +434,7 @@ void sqlite3Update(
sqlite3VdbeAddOp(v, OP_ListReset, 0, 0);
/* Close all tables if there were no FOR EACH ROW triggers */
- if( !row_triggers_exist ){
+ if( !triggers_exist ){
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
if( openAll || aIdxUsed[i] ){
sqlite3VdbeAddOp(v, OP_Close, iCur+i+1, 0);
@@ -431,9 +447,11 @@ void sqlite3Update(
}
/*
- ** Return the number of rows that were changed.
+ ** Return the number of rows that were changed. If this routine is
+ ** generating code because of a call to sqlite3NestedParse(), do not
+ ** invoke the callback function.
*/
- if( db->flags & SQLITE_CountRows && !pParse->trigStack ){
+ if( db->flags & SQLITE_CountRows && !pParse->trigStack && pParse->nested==0 ){
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, "rows updated", P3_STATIC);
diff --git a/ext/pdo_sqlite/sqlite/src/utf.c b/ext/pdo_sqlite/sqlite/src/utf.c
index 58b1a972d7..a96b36c6db 100644
--- a/ext/pdo_sqlite/sqlite/src/utf.c
+++ b/ext/pdo_sqlite/sqlite/src/utf.c
@@ -58,8 +58,8 @@
** sqlite3utf8LikeCompare() - Do a LIKE match given two UTF8 char* strings.
**
*/
-#include <assert.h>
#include "sqliteInt.h"
+#include <assert.h>
#include "vdbeInt.h"
/*
@@ -232,6 +232,7 @@ int sqlite3ReadUtf8(const unsigned char *z){
*/
/* #define TRANSLATE_TRACE 1 */
+#ifndef SQLITE_OMIT_UTF16
/*
** This routine transforms the internal text encoding used by pMem to
** desiredEnc. It is an error if the string is already of the desired
@@ -251,7 +252,7 @@ int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
assert( pMem->enc!=0 );
assert( pMem->n>=0 );
-#ifdef TRANSLATE_TRACE
+#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
{
char zBuf[100];
sqlite3VdbeMemPrettyPrint(pMem, zBuf, 100);
@@ -367,7 +368,7 @@ int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
pMem->z = zOut;
translate_out:
-#ifdef TRANSLATE_TRACE
+#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
{
char zBuf[100];
sqlite3VdbeMemPrettyPrint(pMem, zBuf, 100);
@@ -423,6 +424,7 @@ int sqlite3VdbeMemHandleBom(Mem *pMem){
}
return rc;
}
+#endif /* SQLITE_OMIT_UTF16 */
/*
** pZ is a UTF-8 encoded unicode string. If nByte is less than zero,
@@ -447,6 +449,7 @@ int sqlite3utf8CharLen(const char *z, int nByte){
return r;
}
+#ifndef SQLITE_OMIT_UTF16
/*
** pZ is a UTF-16 encoded unicode string. If nChar is less than zero,
** return the number of bytes up to (but not including), the first pair
@@ -563,4 +566,5 @@ void sqlite3utfSelfTest(){
assert( (z-zBuf)==n );
}
}
-#endif
+#endif /* SQLITE_TEST */
+#endif /* SQLITE_OMIT_UTF16 */
diff --git a/ext/pdo_sqlite/sqlite/src/util.c b/ext/pdo_sqlite/sqlite/src/util.c
index 74ec89795f..bcbfe2493e 100644
--- a/ext/pdo_sqlite/sqlite/src/util.c
+++ b/ext/pdo_sqlite/sqlite/src/util.c
@@ -20,18 +20,18 @@
#include <stdarg.h>
#include <ctype.h>
-#if SQLITE_DEBUG>2 && defined(__GLIBC__)
+#if SQLITE_MEMDEBUG>2 && defined(__GLIBC__)
#include <execinfo.h>
void print_stack_trace(){
void *bt[30];
int i;
int n = backtrace(bt, 30);
- sqlite3DebugPrintf("STACK: ");
+ fprintf(stderr, "STACK: ");
for(i=0; i<n;i++){
- sqlite3DebugPrintf("%p ", bt[i]);
+ fprintf(stderr, "%p ", bt[i]);
}
- sqlite3DebugPrintf("\n");
+ fprintf(stderr, "\n");
}
#else
#define print_stack_trace()
@@ -44,19 +44,23 @@ void print_stack_trace(){
int sqlite3_malloc_failed = 0;
/*
-** If SQLITE_DEBUG is defined, then use versions of malloc() and
+** If SQLITE_MEMDEBUG is defined, then use versions of malloc() and
** free() that track memory usage and check for buffer overruns.
*/
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_MEMDEBUG
/*
** For keeping track of the number of mallocs and frees. This
-** is used to check for memory leaks.
+** is used to check for memory leaks. The iMallocFail and iMallocReset
+** values are used to simulate malloc() failures during testing in
+** order to verify that the library correctly handles an out-of-memory
+** condition.
*/
int sqlite3_nMalloc; /* Number of sqliteMalloc() calls */
int sqlite3_nFree; /* Number of sqliteFree() calls */
int sqlite3_iMallocFail; /* Fail sqliteMalloc() after this many calls */
-#if SQLITE_DEBUG>1
+int sqlite3_iMallocReset = -1; /* When iMallocFail reaches 0, set to this */
+#if SQLITE_MEMDEBUG>1
static int memcnt = 0;
#endif
@@ -77,11 +81,11 @@ void *sqlite3Malloc_(int n, int bZero, char *zFile, int line){
sqlite3_iMallocFail--;
if( sqlite3_iMallocFail==0 ){
sqlite3_malloc_failed++;
-#if SQLITE_DEBUG>1
+#if SQLITE_MEMDEBUG>1
fprintf(stderr,"**** failed to allocate %d bytes at %s:%d\n",
n, zFile,line);
#endif
- sqlite3_iMallocFail--;
+ sqlite3_iMallocFail = sqlite3_iMallocReset;
return 0;
}
}
@@ -89,7 +93,7 @@ void *sqlite3Malloc_(int n, int bZero, char *zFile, int line){
k = (n+sizeof(int)-1)/sizeof(int);
pi = malloc( (N_GUARD*2+1+k)*sizeof(int));
if( pi==0 ){
- sqlite3_malloc_failed++;
+ if( n>0 ) sqlite3_malloc_failed++;
return 0;
}
sqlite3_nMalloc++;
@@ -98,7 +102,7 @@ void *sqlite3Malloc_(int n, int bZero, char *zFile, int line){
for(i=0; i<N_GUARD; i++) pi[k+1+N_GUARD+i] = 0xdead3344;
p = &pi[N_GUARD+1];
memset(p, bZero==0, n);
-#if SQLITE_DEBUG>1
+#if SQLITE_MEMDEBUG>1
print_stack_trace();
fprintf(stderr,"%06d malloc %d bytes at 0x%x from %s:%d\n",
++memcnt, n, (int)p, zFile,line);
@@ -152,7 +156,7 @@ void sqlite3Free_(void *p, char *zFile, int line){
}
}
memset(pi, 0xff, (k+N_GUARD*2+1)*sizeof(int));
-#if SQLITE_DEBUG>1
+#if SQLITE_MEMDEBUG>1
fprintf(stderr,"%06d free %d bytes at 0x%x from %s:%d\n",
++memcnt, n, (int)p, zFile,line);
#endif
@@ -193,7 +197,7 @@ void *sqlite3Realloc_(void *oldP, int n, char *zFile, int line){
k = (n + sizeof(int) - 1)/sizeof(int);
pi = malloc( (k+N_GUARD*2+1)*sizeof(int) );
if( pi==0 ){
- sqlite3_malloc_failed++;
+ if( n>0 ) sqlite3_malloc_failed++;
return 0;
}
for(i=0; i<N_GUARD; i++) pi[i] = 0xdead1122;
@@ -206,7 +210,7 @@ void *sqlite3Realloc_(void *oldP, int n, char *zFile, int line){
}
memset(oldPi, 0xab, (oldK+N_GUARD+2)*sizeof(int));
free(oldPi);
-#if SQLITE_DEBUG>1
+#if SQLITE_MEMDEBUG>1
print_stack_trace();
fprintf(stderr,"%06d realloc %d to %d bytes at 0x%x to 0x%x at %s:%d\n",
++memcnt, oldN, n, (int)oldP, (int)p, zFile, line);
@@ -241,13 +245,13 @@ char *sqlite3StrNDup_(const char *z, int n, char *zFile, int line){
void sqlite3FreeX(void *p){
sqliteFree(p);
}
-#endif /* SQLITE_DEBUG */
+#endif /* SQLITE_MEMDEBUG */
/*
** The following versions of malloc() and free() are for use in a
** normal build.
*/
-#if !defined(SQLITE_DEBUG)
+#if !defined(SQLITE_MEMDEBUG)
/*
** Allocate new memory and set it to zero. Return NULL if
@@ -300,7 +304,7 @@ void *sqlite3Realloc(void *p, int n){
}
p2 = realloc(p, n);
if( p2==0 ){
- sqlite3_malloc_failed++;
+ if( n>0 ) sqlite3_malloc_failed++;
}
return p2;
}
@@ -325,7 +329,7 @@ char *sqlite3StrNDup(const char *z, int n){
}
return zNew;
}
-#endif /* !defined(SQLITE_DEBUG) */
+#endif /* !defined(SQLITE_MEMDEBUG) */
/*
** Create a string from the 2nd and subsequent arguments (up to the
@@ -489,20 +493,6 @@ const unsigned char sqlite3UpperToLower[] = {
#define UpperToLower sqlite3UpperToLower
/*
-** This function computes a hash on the name of a keyword.
-** Case is not significant.
-*/
-int sqlite3HashNoCase(const char *z, int n){
- int h = 0;
- if( n<=0 ) n = strlen(z);
- while( n > 0 ){
- h = (h<<3) ^ h ^ UpperToLower[(unsigned char)*z++];
- n--;
- }
- return h & 0x7fffffff;
-}
-
-/*
** Some systems have stricmp(). Others have strcasecmp(). Because
** there is no consistency, we will define our own.
*/
@@ -796,7 +786,7 @@ int sqlite3SafetyCheck(sqlite3 *db){
int sqlite3PutVarint(unsigned char *p, u64 v){
int i, j, n;
u8 buf[10];
- if( v & 0xff00000000000000 ){
+ if( v & (((u64)0xff000000)<<32) ){
p[8] = v;
v >>= 8;
for(i=7; i>=0; i--){
@@ -868,6 +858,7 @@ int sqlite3GetVarint32(const unsigned char *p, u32 *v){
u32 x;
int n;
unsigned char c;
+#if 0
if( ((c = p[0]) & 0x80)==0 ){
*v = c;
return 1;
@@ -878,6 +869,18 @@ int sqlite3GetVarint32(const unsigned char *p, u32 *v){
return 2;
}
x = (x<<7) | (c & 0x7f);
+#else
+ if( ((signed char*)p)[0]>=0 ){
+ *v = p[0];
+ return 1;
+ }
+ x = p[0] & 0x7f;
+ if( ((signed char*)p)[1]>=0 ){
+ *v = (x<<7) | p[1];
+ return 2;
+ }
+ x = (x<<7) | (p[1] & 0x7f);
+#endif
n = 2;
do{
x = (x<<7) | ((c = p[n++])&0x7f);
@@ -899,6 +902,8 @@ int sqlite3VarintLen(u64 v){
return i;
}
+#if (!defined(SQLITE_OMIT_BLOB_LITERAL) && !defined(SQLITE_HAS_CODEC)) \
+ || defined(SQLITE_TEST)
/*
** Translate a single byte of Hex into an integer.
*/
@@ -907,13 +912,14 @@ static int hexToInt(int h){
return h - '0';
}else if( h>='a' && h<='f' ){
return h - 'a' + 10;
- }else if( h>='A' && h<='F' ){
- return h - 'A' + 10;
}else{
- return 0;
+ assert( h>='A' && h<='F' );
+ return h - 'A' + 10;
}
}
+#endif /* (!SQLITE_OMIT_BLOB_LITERAL && !SQLITE_HAS_CODEC) || SQLITE_TEST */
+#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
/*
** Convert a BLOB literal of the form "x'hhhhhh'" into its binary
** value. Return a pointer to its binary value. Space to hold the
@@ -932,6 +938,7 @@ void *sqlite3HexToBlob(const char *z){
}
return zBlob;
}
+#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */
#if defined(SQLITE_TEST)
/*
diff --git a/ext/pdo_sqlite/sqlite/src/vacuum.c b/ext/pdo_sqlite/sqlite/src/vacuum.c
index 371a855770..ed418b0ff6 100644
--- a/ext/pdo_sqlite/sqlite/src/vacuum.c
+++ b/ext/pdo_sqlite/sqlite/src/vacuum.c
@@ -19,7 +19,7 @@
#include "sqliteInt.h"
#include "os.h"
-#if !defined(SQLITE_OMIT_VACUUM) || SQLITE_OMIT_VACUUM
+#ifndef SQLITE_OMIT_VACUUM
/*
** Generate a random name of 20 character in length.
*/
@@ -93,11 +93,10 @@ void sqlite3Vacuum(Parse *pParse, Token *pTableName){
*/
int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
int rc = SQLITE_OK; /* Return code from service routines */
-#if !defined(SQLITE_OMIT_VACUUM) || SQLITE_OMIT_VACUUM
+#ifndef SQLITE_OMIT_VACUUM
const char *zFilename; /* full pathname of the database file */
int nFilename; /* number of characters in zFilename[] */
char *zTemp = 0; /* a temporary file in same directory as zFilename */
- int i; /* Loop counter */
Btree *pMain; /* The database being vacuumed */
Btree *pTemp;
char *zSql = 0;
@@ -129,11 +128,19 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
goto end_of_vacuum;
}
strcpy(zTemp, zFilename);
- i = 0;
+
+ /* The randomName() procedure in the following loop uses an excellent
+ ** source of randomness to generate a name from a space of 1.3e+31
+ ** possibilities. So unless the directory already contains on the order
+ ** of 1.3e+31 files, the probability that the following loop will
+ ** run more than once or twice is vanishingly small. We are certain
+ ** enough that this loop will always terminate (and terminate quickly)
+ ** that we don't even bother to set a maximum loop count.
+ */
do {
zTemp[nFilename] = '-';
randomName((unsigned char*)&zTemp[nFilename+1]);
- } while( i<10 && sqlite3OsFileExists(zTemp) );
+ } while( sqlite3OsFileExists(zTemp) );
/* Attach the temporary database as 'vacuum_db'. The synchronous pragma
** can be set to 'off' for this file, as it is not recovered if a crash
@@ -159,6 +166,10 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
assert( sqlite3BtreeGetPageSize(pTemp)==sqlite3BtreeGetPageSize(pMain) );
execSql(db, "PRAGMA vacuum_db.synchronous=OFF");
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ sqlite3BtreeSetAutoVacuum(pTemp, sqlite3BtreeGetAutoVacuum(pMain));
+#endif
+
/* Begin a transaction */
rc = execSql(db, "BEGIN;");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
@@ -168,14 +179,17 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
*/
rc = execExecSql(db,
"SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14,100000000) "
- " FROM sqlite_master WHERE type='table' "
- "UNION ALL "
- "SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14,100000000) "
- " FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %' "
- "UNION ALL "
+ " FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'");
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
+ rc = execExecSql(db,
+ "SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14,100000000)"
+ " FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %' ");
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
+ rc = execExecSql(db,
"SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21,100000000) "
- " FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'"
- "UNION ALL "
+ " FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'");
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
+ rc = execExecSql(db,
"SELECT 'CREATE VIEW vacuum_db.' || substr(sql,13,100000000) "
" FROM sqlite_master WHERE type='view'"
);
@@ -189,9 +203,24 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
"SELECT 'INSERT INTO vacuum_db.' || quote(name) "
"|| ' SELECT * FROM ' || quote(name) || ';'"
"FROM sqlite_master "
- "WHERE type = 'table';"
+ "WHERE type = 'table' AND name!='sqlite_sequence';"
+ );
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
+
+ /* Copy over the sequence table
+ */
+ rc = execExecSql(db,
+ "SELECT 'DELETE FROM vacuum_db.' || quote(name) || ';' "
+ "FROM vacuum_db.sqlite_master WHERE name='sqlite_sequence' "
);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
+ rc = execExecSql(db,
+ "SELECT 'INSERT INTO vacuum_db.' || quote(name) "
+ "|| ' SELECT * FROM ' || quote(name) || ';' "
+ "FROM vacuum_db.sqlite_master WHERE name=='sqlite_sequence';"
+ );
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
+
/* Copy the triggers from the main database to the temporary database.
** This was deferred before in case the triggers interfered with copying
@@ -215,22 +244,31 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
*/
if( sqlite3BtreeIsInTrans(pTemp) ){
u32 meta;
+ int i;
+
+ /* This array determines which meta meta values are preserved in the
+ ** vacuum. Even entries are the meta value number and odd entries
+ ** are an increment to apply to the meta value after the vacuum.
+ ** The increment is used to increase the schema cookie so that other
+ ** connections to the same database will know to reread the schema.
+ */
+ static const unsigned char aCopy[] = {
+ 1, 1, /* Add one to the old schema cookie */
+ 3, 0, /* Preserve the default page cache size */
+ 5, 0, /* Preserve the default text encoding */
+ 6, 0, /* Preserve the user version */
+ };
assert( 0==sqlite3BtreeIsInTrans(pMain) );
rc = sqlite3BtreeBeginTrans(pMain, 1);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
- /* Copy Btree meta values 3 and 4. These correspond to SQL layer meta
- ** values 2 and 3, the default values of a couple of pragmas.
- */
- rc = sqlite3BtreeGetMeta(pMain, 3, &meta);
- if( rc!=SQLITE_OK ) goto end_of_vacuum;
- rc = sqlite3BtreeUpdateMeta(pTemp, 3, meta);
- if( rc!=SQLITE_OK ) goto end_of_vacuum;
- rc = sqlite3BtreeGetMeta(pMain, 4, &meta);
- if( rc!=SQLITE_OK ) goto end_of_vacuum;
- rc = sqlite3BtreeUpdateMeta(pTemp, 4, meta);
- if( rc!=SQLITE_OK ) goto end_of_vacuum;
+ /* Copy Btree meta values */
+ for(i=0; i<sizeof(aCopy)/sizeof(aCopy[0]); i+=2){
+ rc = sqlite3BtreeGetMeta(pMain, aCopy[i], &meta);
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
+ rc = sqlite3BtreeUpdateMeta(pTemp, aCopy[i], meta+aCopy[i+1]);
+ }
rc = sqlite3BtreeCopyFile(pMain, pTemp);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
diff --git a/ext/pdo_sqlite/sqlite/src/vdbe.c b/ext/pdo_sqlite/sqlite/src/vdbe.c
index 58f8c73109..485788820c 100644
--- a/ext/pdo_sqlite/sqlite/src/vdbe.c
+++ b/ext/pdo_sqlite/sqlite/src/vdbe.c
@@ -70,6 +70,15 @@ int sqlite3_search_count = 0;
int sqlite3_interrupt_count = 0;
/*
+** The next global variable is incremented each type the OP_Sort opcode
+** is executed. The test procedures use this information to make sure that
+** sorting is occurring or not occuring at appropriate times. This variable
+** has no function other than to help verify the correct operation of the
+** library.
+*/
+int sqlite3_sort_count = 0;
+
+/*
** Release the memory associated with the given stack level. This
** leaves the Mem.flags field in an inconsistent state.
*/
@@ -294,7 +303,7 @@ static void applyAffinity(Mem *pRec, char affinity, u8 enc){
}
}
-#ifndef NDEBUG
+#ifdef SQLITE_DEBUG
/*
** Write a nice string representation of the contents of cell pMem
** into buffer zBuf, length nBuf.
@@ -371,7 +380,7 @@ void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf, int nBuf){
#ifdef VDBE_PROFILE
/*
** The following routine only works on pentium-class processors.
-** It uses the RDTSC opcode to read cycle count value out of the
+** It uses the RDTSC opcode to read the cycle count value out of the
** processor and returns that value. This can be used for high-res
** profiling.
*/
@@ -468,9 +477,9 @@ int sqlite3VdbeExec(
#endif
pOp = &p->aOp[pc];
- /* Only allow tracing if NDEBUG is not defined.
+ /* Only allow tracing if SQLITE_DEBUG is defined.
*/
-#ifndef NDEBUG
+#ifdef SQLITE_DEBUG
if( p->trace ){
if( pc==0 ){
printf("VDBE Execution Trace:\n");
@@ -478,8 +487,6 @@ int sqlite3VdbeExec(
}
sqlite3VdbePrintOp(p->trace, pc, pOp);
}
-#endif
-#ifdef SQLITE_TEST
if( p->trace==0 && pc==0 && sqlite3OsFileExists("vdbe_sqltrace") ){
sqlite3VdbePrintSql(p);
}
@@ -618,11 +625,10 @@ case OP_Halt: {
sqlite3SetString(&p->zErrMsg, pOp->p3, (char*)0);
}
rc = sqlite3VdbeHalt(p);
+ assert( rc==SQLITE_BUSY || rc==SQLITE_OK );
if( rc==SQLITE_BUSY ){
p->rc = SQLITE_BUSY;
return SQLITE_BUSY;
- }else if( rc!=SQLITE_OK ){
- p->rc = rc;
}
return p->rc ? SQLITE_ERROR : SQLITE_DONE;
}
@@ -632,6 +638,9 @@ case OP_Halt: {
** The integer value P1 is pushed onto the stack. If P3 is not zero
** then it is assumed to be a string representation of the same integer.
** If P1 is zero and P3 is not zero, then the value is derived from P3.
+**
+** If the value cannot be represented as a 32-bits then its value
+** will be in P3.
*/
case OP_Integer: {
pTos++;
@@ -671,6 +680,7 @@ case OP_Real: { /* same as TK_FLOAT */
** into an OP_String before it is executed for the first time.
*/
case OP_String8: { /* same as TK_STRING */
+#ifndef SQLITE_OMIT_UTF16
pOp->opcode = OP_String;
if( db->enc!=SQLITE_UTF8 && pOp->p3 ){
@@ -687,6 +697,7 @@ case OP_String8: { /* same as TK_STRING */
pOp->p3 = pTos->z;
break;
}
+#endif
/* Otherwise fall through to the next case, OP_String */
}
@@ -701,11 +712,16 @@ case OP_String: {
if( pOp->p3 ){
pTos->flags = MEM_Str|MEM_Static|MEM_Term;
pTos->z = pOp->p3;
+#ifndef SQLITE_OMIT_UTF16
if( db->enc==SQLITE_UTF8 ){
pTos->n = strlen(pTos->z);
}else{
pTos->n = sqlite3utf16ByteLen(pTos->z, -1);
}
+#else
+ assert( db->enc==SQLITE_UTF8 );
+ pTos->n = strlen(pTos->z);
+#endif
pTos->enc = db->enc;
}else{
pTos->flags = MEM_Null;
@@ -713,6 +729,7 @@ case OP_String: {
break;
}
+#ifndef SQLITE_OMIT_BLOB_LITERAL
/* Opcode: HexBlob * * P3
**
** P3 is an UTF-8 SQL hex encoding of a blob. The blob is pushed onto the
@@ -750,13 +767,14 @@ case OP_HexBlob: { /* same as TK_BLOB */
** by the compiler. Instead, the compiler layer specifies
** an OP_HexBlob opcode, with the hex string representation of
** the blob as P3. This opcode is transformed to an OP_Blob
-** before execution (within the sqlite3_prepare() function).
+** the first time it is executed.
*/
case OP_Blob: {
pTos++;
sqlite3VdbeMemSetStr(pTos, pOp->p3, pOp->p1, 0, 0);
break;
}
+#endif /* SQLITE_OMIT_BLOB_LITERAL */
/* Opcode: Variable P1 * *
**
@@ -1084,7 +1102,7 @@ divide_by_zero:
** P3 is a pointer to a CollSeq struct. If the next call to a user function
** or aggregate calls sqlite3GetFuncCollSeq(), this collation sequence will
** be returned. This is used by the built-in min(), max() and nullif()
-** built-in functions.
+** functions.
**
** The interface used by the implementation of the aforementioned functions
** to retrieve the collation sequence set by this opcode is not available
@@ -1140,7 +1158,6 @@ case OP_Function: {
ctx.s.z = 0;
ctx.s.xDel = 0;
ctx.isError = 0;
- ctx.isStep = 0;
if( ctx.pFunc->needCollSeq ){
assert( pOp>p->aOp );
assert( pOp[-1].p3type==P3_COLLSEQ );
@@ -1643,25 +1660,30 @@ case OP_NotNull: { /* same as TK_NOTNULL */
** opcode must be called to set the number of fields in the table.
**
** This opcode sets the number of columns for cursor P1 to P2.
+**
+** If OP_KeyAsData is to be applied to cursor P1, it must be executed
+** before this op-code.
*/
case OP_SetNumColumns: {
+ Cursor *pC;
assert( (pOp->p1)<p->nCursor );
assert( p->apCsr[pOp->p1]!=0 );
- p->apCsr[pOp->p1]->nField = pOp->p2;
+ pC = p->apCsr[pOp->p1];
+ pC->nField = pOp->p2;
+ if( (!pC->keyAsData && pC->zeroData) || (pC->keyAsData && pC->intKey) ){
+ rc = SQLITE_CORRUPT;
+ goto abort_due_to_error;
+ }
break;
}
-/* Opcode: IdxColumn P1 * *
-**
-** P1 is a cursor opened on an index. Push the first field from the
-** current index key onto the stack.
-*/
/* Opcode: Column P1 P2 *
**
** Interpret the data that cursor P1 points to as a structure built using
** the MakeRecord instruction. (See the MakeRecord opcode for additional
** information about the format of the data.) Push onto the stack the value
-** of the P2-th column contained in the data.
+** of the P2-th column contained in the data. If there are less that (P2+1)
+** values in the record, push a NULL onto the stack.
**
** If the KeyAsData opcode has previously executed on this cursor, then the
** field might be extracted from the key rather than the data.
@@ -1673,7 +1695,6 @@ case OP_SetNumColumns: {
** stack. The column value is not copied. The number of columns in the
** record is stored on the stack just above the record itself.
*/
-case OP_IdxColumn:
case OP_Column: {
u32 payloadSize; /* Number of bytes in the record */
int p1 = pOp->p1; /* P1 value of the opcode */
@@ -1727,7 +1748,8 @@ case OP_Column: {
pCrsr = 0;
}else if( (pC = p->apCsr[p1])->pCursor!=0 ){
/* The record is stored in a B-Tree */
- sqlite3VdbeCursorMoveto(pC);
+ rc = sqlite3VdbeCursorMoveto(pC);
+ if( rc ) goto abort_due_to_error;
zRec = 0;
pCrsr = pC->pCursor;
if( pC->nullRow ){
@@ -1743,6 +1765,7 @@ case OP_Column: {
sqlite3BtreeDataSize(pCrsr, &payloadSize);
}
nField = pC->nField;
+#ifndef SQLITE_OMIT_TRIGGER
}else if( pC->pseudoTable ){
/* The record is the sole entry of a pseudo-table */
payloadSize = pC->nData;
@@ -1751,6 +1774,7 @@ case OP_Column: {
assert( payloadSize==0 || zRec!=0 );
nField = pC->nField;
pCrsr = 0;
+#endif
}else{
zRec = 0;
payloadSize = 0;
@@ -1816,7 +1840,7 @@ case OP_Column: {
if( !zRec && avail<szHdr ){
rc = sqlite3VdbeMemFromBtree(pCrsr, 0, szHdr, pC->keyAsData, &sMem);
if( rc!=SQLITE_OK ){
- goto abort_due_to_error;
+ goto op_column_out;
}
zData = sMem.z;
}
@@ -1827,6 +1851,7 @@ case OP_Column: {
** of the record to the start of the data for the i-th column
*/
offset = szHdr;
+ assert( offset>0 );
i = 0;
while( idx<szHdr && i<nField && offset<=payloadSize ){
aOffset[i] = offset;
@@ -1837,15 +1862,23 @@ case OP_Column: {
Release(&sMem);
sMem.flags = MEM_Null;
+ /* If i is less that nField, then there are less fields in this
+ ** record than SetNumColumns indicated there are columns in the
+ ** table. Set the offset for any extra columns not present in
+ ** the record to 0. This tells code below to push a NULL onto the
+ ** stack instead of deserializing a value from the record.
+ */
+ while( i<nField ){
+ aOffset[i++] = 0;
+ }
+
/* The header should end at the start of data and the data should
** end at last byte of the record. If this is not the case then
** we are dealing with a malformed record.
*/
if( idx!=szHdr || offset!=payloadSize ){
- sqliteFree(aType);
- if( pC ) pC->aType = 0;
rc = SQLITE_CORRUPT;
- break;
+ goto op_column_out;
}
/* Remember all aType and aColumn information if we have a cursor
@@ -1858,20 +1891,28 @@ case OP_Column: {
}
}
- /* Get the column information.
+ /* Get the column information. If aOffset[p2] is non-zero, then
+ ** deserialize the value from the record. If aOffset[p2] is zero,
+ ** then there are not enough fields in the record to satisfy the
+ ** request. The value is NULL in this case.
*/
- if( rc!=SQLITE_OK ){
- goto abort_due_to_error;
- }
- if( zRec ){
- zData = &zRec[aOffset[p2]];
+ if( aOffset[p2] ){
+ assert( rc==SQLITE_OK );
+ if( zRec ){
+ zData = &zRec[aOffset[p2]];
+ }else{
+ len = sqlite3VdbeSerialTypeLen(aType[p2]);
+ rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len,pC->keyAsData,&sMem);
+ if( rc!=SQLITE_OK ){
+ goto op_column_out;
+ }
+ zData = sMem.z;
+ }
+ sqlite3VdbeSerialGet(zData, aType[p2], pTos);
+ pTos->enc = db->enc;
}else{
- len = sqlite3VdbeSerialTypeLen(aType[p2]);
- sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, pC->keyAsData, &sMem);
- zData = sMem.z;
+ pTos->flags = MEM_Null;
}
- sqlite3VdbeSerialGet(zData, aType[p2], pTos);
- pTos->enc = db->enc;
/* If we dynamically allocated space to hold the data (in the
** sqlite3VdbeMemFromBtree() call above) then transfer control of that
@@ -1891,14 +1932,15 @@ case OP_Column: {
** can abandon sMem */
rc = sqlite3VdbeMemMakeWriteable(pTos);
+op_column_out:
/* Release the aType[] memory if we are not dealing with cursor */
- if( !pC ){
+ if( !pC || !pC->aType ){
sqliteFree(aType);
}
break;
}
-/* Opcode MakeRecord P1 P2 P3
+/* Opcode: MakeRecord P1 P2 P3
**
** Convert the top abs(P1) entries of the stack into a single entry
** suitable for use as a data record in a database table or as a key
@@ -1923,12 +1965,11 @@ case OP_Column: {
** field of the index key (i.e. the first character of P3 corresponds to the
** lowest element on the stack).
**
-** Character Column affinity
-** ------------------------------
-** 'n' NUMERIC
-** 'i' INTEGER
-** 't' TEXT
-** 'o' NONE
+** The mapping from character to affinity is as follows:
+** 'n' = NUMERIC.
+** 'i' = INTEGER.
+** 't' = TEXT.
+** 'o' = NONE.
**
** If P3 is NULL then all index fields have the affinity NONE.
*/
@@ -2034,15 +2075,7 @@ case OP_MakeRecord: {
if( addRowid ){
zCsr += sqlite3VdbeSerialPut(zCsr, pRowid);
}
-
- /* If zCsr has not been advanced exactly nByte bytes, then one
- ** of the sqlite3PutVarint() or sqlite3VdbeSerialPut() calls above
- ** failed. This indicates a corrupted memory cell or code bug.
- */
- if( zCsr!=(zNewRecord+nByte) ){
- rc = SQLITE_INTERNAL;
- goto abort_due_to_error;
- }
+ assert( zCsr==(zNewRecord+nByte) );
/* Pop entries off the stack if required. Push the new record on. */
if( !leaveOnStack ){
@@ -2448,6 +2481,7 @@ case OP_OpenTemp: {
break;
}
+#ifndef SQLITE_OMIT_TRIGGER
/* Opcode: OpenPseudo P1 * *
**
** Open a new cursor that points to a fake table that contains a single
@@ -2469,6 +2503,7 @@ case OP_OpenPseudo: {
pCx->pIncrKey = &pCx->bogusIncrKey;
break;
}
+#endif
/* Opcode: Close P1 * *
**
@@ -2542,7 +2577,6 @@ case OP_MoveGt: {
*pC->pIncrKey = oc==OP_MoveGt || oc==OP_MoveLe;
if( pC->intKey ){
i64 iKey;
- assert( !pOp->p3 );
Integerify(pTos);
iKey = intToKey(pTos->i);
if( pOp->p2==0 && pOp->opcode==OP_MoveGe ){
@@ -2552,12 +2586,18 @@ case OP_MoveGt: {
pTos--;
break;
}
- sqlite3BtreeMoveto(pC->pCursor, 0, (u64)iKey, &res);
+ rc = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)iKey, &res);
+ if( rc!=SQLITE_OK ){
+ goto abort_due_to_error;
+ }
pC->lastRecno = pTos->i;
pC->recnoIsValid = res==0;
}else{
Stringify(pTos, db->enc);
- sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
+ rc = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
+ if( rc!=SQLITE_OK ){
+ goto abort_due_to_error;
+ }
pC->recnoIsValid = 0;
}
pC->deferredMoveto = 0;
@@ -2566,7 +2606,8 @@ case OP_MoveGt: {
sqlite3_search_count++;
if( oc==OP_MoveGe || oc==OP_MoveGt ){
if( res<0 ){
- sqlite3BtreeNext(pC->pCursor, &res);
+ rc = sqlite3BtreeNext(pC->pCursor, &res);
+ if( rc!=SQLITE_OK ) goto abort_due_to_error;
pC->recnoIsValid = 0;
}else{
res = 0;
@@ -2574,7 +2615,8 @@ case OP_MoveGt: {
}else{
assert( oc==OP_MoveLt || oc==OP_MoveLe );
if( res>=0 ){
- sqlite3BtreePrevious(pC->pCursor, &res);
+ rc = sqlite3BtreePrevious(pC->pCursor, &res);
+ if( rc!=SQLITE_OK ) goto abort_due_to_error;
pC->recnoIsValid = 0;
}else{
/* res might be negative because the table is empty. Check to
@@ -2782,17 +2824,17 @@ case OP_NotExists: {
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
- int res, rx;
+ int res;
u64 iKey;
assert( pTos->flags & MEM_Int );
assert( p->apCsr[i]->intKey );
iKey = intToKey(pTos->i);
- rx = sqlite3BtreeMoveto(pCrsr, 0, iKey, &res);
+ rc = sqlite3BtreeMoveto(pCrsr, 0, iKey, &res);
pC->lastRecno = pTos->i;
pC->recnoIsValid = res==0;
pC->nullRow = 0;
pC->cacheValid = 0;
- if( rx!=SQLITE_OK || res!=0 ){
+ if( res!=0 ){
pc = pOp->p2 - 1;
pC->recnoIsValid = 0;
}
@@ -2802,12 +2844,19 @@ case OP_NotExists: {
break;
}
-/* Opcode: NewRecno P1 * *
+/* Opcode: NewRecno P1 P2 *
**
** Get a new integer record number used as the key to a table.
** The record number is not previously used as a key in the database
** table that cursor P1 points to. The new record number is pushed
** onto the stack.
+**
+** If P2>0 then P2 is a memory cell that holds the largest previously
+** generated record number. No new record numbers are allowed to be less
+** than this value. When this value reaches its maximum, a SQLITE_FULL
+** error is generated. The P2 memory cell is updated with the generated
+** record number. This P2 mechanism is used to help implement the
+** AUTOINCREMENT feature.
*/
case OP_NewRecno: {
int i = pOp->p1;
@@ -2852,8 +2901,24 @@ case OP_NewRecno: {
int res, rx=SQLITE_OK, cnt;
i64 x;
cnt = 0;
+ if( (sqlite3BtreeFlags(pC->pCursor)&(BTREE_INTKEY|BTREE_ZERODATA)) !=
+ BTREE_INTKEY ){
+ rc = SQLITE_CORRUPT;
+ goto abort_due_to_error;
+ }
assert( (sqlite3BtreeFlags(pC->pCursor) & BTREE_INTKEY)!=0 );
assert( (sqlite3BtreeFlags(pC->pCursor) & BTREE_ZERODATA)==0 );
+
+#ifdef SQLITE_32BIT_ROWID
+# define MAX_ROWID 0x7fffffff
+#else
+ /* Some compilers complain about constants of the form 0x7fffffffffffffff.
+ ** Others complain about 0x7ffffffffffffffffLL. The following macro seems
+ ** to provide the constant while making all compilers happy.
+ */
+# define MAX_ROWID ( (((u64)0x7fffffff)<<32) | (u64)0xffffffff )
+#endif
+
if( !pC->useRandomRowid ){
if( pC->nextRowidValid ){
v = pC->nextRowid;
@@ -2864,14 +2929,33 @@ case OP_NewRecno: {
}else{
sqlite3BtreeKeySize(pC->pCursor, &v);
v = keyToInt(v);
- if( v==0x7fffffffffffffff ){
+ if( v==MAX_ROWID ){
pC->useRandomRowid = 1;
}else{
v++;
}
}
}
- if( v<0x7fffffffffffffff ){
+
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+ if( pOp->p2 ){
+ Mem *pMem;
+ assert( pOp->p2>0 && pOp->p2<p->nMem ); /* P2 is a valid memory cell */
+ pMem = &p->aMem[pOp->p2];
+ Integerify(pMem);
+ assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P2) holds an integer */
+ if( pMem->i==MAX_ROWID || pC->useRandomRowid ){
+ rc = SQLITE_FULL;
+ goto abort_due_to_error;
+ }
+ if( v<pMem->i+1 ){
+ v = pMem->i + 1;
+ }
+ pMem->i = v;
+ }
+#endif
+
+ if( v<MAX_ROWID ){
pC->nextRowidValid = 1;
pC->nextRowid = v+1;
}else{
@@ -2879,6 +2963,7 @@ case OP_NewRecno: {
}
}
if( pC->useRandomRowid ){
+ assert( pOp->p2==0 ); /* SQLITE_FULL must have occurred prior to this */
v = db->priorNewRowid;
cnt = 0;
do{
@@ -2979,6 +3064,7 @@ case OP_PutStrKey: {
}else{
assert( pTos->flags & (MEM_Blob|MEM_Str) );
}
+#ifndef SQLITE_OMIT_TRIGGER
if( pC->pseudoTable ){
/* PutStrKey does not work for pseudo-tables.
** The following assert makes sure we are not trying to use
@@ -3000,8 +3086,12 @@ case OP_PutStrKey: {
}
pC->nullRow = 0;
}else{
+#endif
rc = sqlite3BtreeInsert(pC->pCursor, zKey, nKey, pTos->z, pTos->n);
+#ifndef SQLITE_OMIT_TRIGGER
}
+#endif
+
pC->recnoIsValid = 0;
pC->deferredMoveto = 0;
pC->cacheValid = 0;
@@ -3031,7 +3121,8 @@ case OP_Delete: {
pC = p->apCsr[i];
assert( pC!=0 );
if( pC->pCursor!=0 ){
- sqlite3VdbeCursorMoveto(pC);
+ rc = sqlite3VdbeCursorMoveto(pC);
+ if( rc ) goto abort_due_to_error;
rc = sqlite3BtreeDelete(pC->pCursor);
pC->nextRowidValid = 0;
pC->cacheValid = 0;
@@ -3104,7 +3195,8 @@ case OP_RowData: {
pTos->flags = MEM_Null;
}else if( pC->pCursor!=0 ){
BtCursor *pCrsr = pC->pCursor;
- sqlite3VdbeCursorMoveto(pC);
+ rc = sqlite3VdbeCursorMoveto(pC);
+ if( rc ) goto abort_due_to_error;
if( pC->nullRow ){
pTos->flags = MEM_Null;
break;
@@ -3132,10 +3224,12 @@ case OP_RowData: {
}else{
sqlite3BtreeData(pCrsr, 0, n, pTos->z);
}
+#ifndef SQLITE_OMIT_TRIGGER
}else if( pC->pseudoTable ){
pTos->n = pC->nData;
pTos->z = pC->pData;
pTos->flags = MEM_Blob|MEM_Ephem;
+#endif
}else{
pTos->flags = MEM_Null;
}
@@ -3157,7 +3251,8 @@ case OP_Recno: {
assert( i>=0 && i<p->nCursor );
pC = p->apCsr[i];
assert( pC!=0 );
- sqlite3VdbeCursorMoveto(pC);
+ rc = sqlite3VdbeCursorMoveto(pC);
+ if( rc ) goto abort_due_to_error;
pTos++;
if( pC->recnoIsValid ){
v = pC->lastRecno;
@@ -3176,6 +3271,7 @@ case OP_Recno: {
break;
}
+#ifndef SQLITE_OMIT_COMPOUND_SELECT
/* Opcode: FullKey P1 * *
**
** Extract the complete key from the record that cursor P1 is currently
@@ -3202,7 +3298,8 @@ case OP_FullKey: {
i64 amt;
char *z;
- sqlite3VdbeCursorMoveto(pC);
+ rc = sqlite3VdbeCursorMoveto(pC);
+ if( rc ) goto abort_due_to_error;
assert( pC->intKey==0 );
sqlite3BtreeKeySize(pCrsr, &amt);
if( amt<=0 ){
@@ -3224,6 +3321,7 @@ case OP_FullKey: {
}
break;
}
+#endif
/* Opcode: NullRow P1 * *
**
@@ -3441,7 +3539,7 @@ case OP_IdxDelete: {
/* Opcode: IdxRecno P1 * *
**
** Push onto the stack an integer which is the varint located at the
-** end of the index key pointed to by cursor P1. These integer should be
+** end of the index key pointed to by cursor P1. This integer should be
** the record number of the table entry to which this index entry points.
**
** See also: Recno, MakeIdxKey.
@@ -3596,10 +3694,33 @@ case OP_IdxIsNull: {
** P2==1 then the table to be clear is in the auxiliary database file
** that is used to store tables create using CREATE TEMPORARY TABLE.
**
+** If AUTOVACUUM is enabled then it is possible that another root page
+** might be moved into the newly deleted root page in order to keep all
+** root pages contiguous at the beginning of the database. The former
+** value of the root page that moved - its value before the move occurred -
+** is pushed onto the stack. If no page movement was required (because
+** the table being dropped was already the last one in the database) then
+** a zero is pushed onto the stack. If AUTOVACUUM is disabled
+** then a zero is pushed onto the stack.
+**
** See also: Clear
*/
case OP_Destroy: {
- rc = sqlite3BtreeDropTable(db->aDb[pOp->p2].pBt, pOp->p1);
+ int iMoved;
+ if( db->activeVdbeCnt>1 ){
+ rc = SQLITE_LOCKED;
+ }else{
+ assert( db->activeVdbeCnt==1 );
+ rc = sqlite3BtreeDropTable(db->aDb[pOp->p2].pBt, pOp->p1, &iMoved);
+ pTos++;
+ pTos->flags = MEM_Int;
+ pTos->i = iMoved;
+ #ifndef SQLITE_OMIT_AUTOVACUUM
+ if( rc==SQLITE_OK && iMoved!=0 ){
+ sqlite3RootPageMoved(&db->aDb[pOp->p2], iMoved, pOp->p1);
+ }
+ #endif
+ }
break;
}
@@ -3735,6 +3856,7 @@ case OP_DropTrigger: {
}
+#ifndef SQLITE_OMIT_INTEGRITY_CHECK
/* Opcode: IntegrityCk * P2 *
**
** Do an analysis of the currently open database. Push onto the
@@ -3786,6 +3908,7 @@ case OP_IntegrityCk: {
sqliteFree(aRoot);
break;
}
+#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
/* Opcode: ListWrite * * *
**
@@ -3871,6 +3994,32 @@ case OP_ListReset: {
break;
}
+#ifndef SQLITE_OMIT_SUBQUERY
+/* Opcode: AggContextPush * * *
+**
+** Save the state of the current aggregator. It is restored an
+** AggContextPop opcode.
+**
+*/
+case OP_AggContextPush: {
+ p->pAgg++;
+ assert( p->pAgg<&p->apAgg[p->nAgg] );
+ break;
+}
+
+/* Opcode: AggContextPop * * *
+**
+** Restore the aggregator to the state it was in when AggContextPush
+** was last called. Any data in the current aggregator is deleted.
+*/
+case OP_AggContextPop: {
+ p->pAgg--;
+ assert( p->pAgg>=p->apAgg );
+ break;
+}
+#endif
+
+#ifndef SQLITE_OMIT_TRIGGER
/* Opcode: ContextPush * * *
**
** Save the current Vdbe context such that it can be restored by a ContextPop
@@ -3911,12 +4060,13 @@ case OP_ContextPop: {
p->pList = pContext->pList;
break;
}
+#endif /* #ifndef SQLITE_OMIT_TRIGGER */
/* Opcode: SortPut * * *
**
** The TOS is the key and the NOS is the data. Pop both from the stack
** and put them on the sorter. The key and data should have been
-** made using SortMakeKey and SortMakeRec, respectively.
+** made using the MakeRecord opcode.
*/
case OP_SortPut: {
Mem *pNos = &pTos[-1];
@@ -3947,6 +4097,7 @@ case OP_Sort: {
KeyInfo *pKeyInfo = (KeyInfo*)pOp->p3;
Sorter *pElem;
Sorter *apSorter[NSORT];
+ sqlite3_sort_count++;
pKeyInfo->enc = p->db->enc;
for(i=0; i<NSORT; i++){
apSorter[i] = 0;
@@ -4048,10 +4199,34 @@ case OP_MemLoad: {
break;
}
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+/* Opcode: MemMax P1 * *
+**
+** Set the value of memory cell P1 to the maximum of its current value
+** and the value on the top of the stack. The stack is unchanged.
+**
+** This instruction throws an error if the memory cell is not initially
+** an integer.
+*/
+case OP_MemMax: {
+ int i = pOp->p1;
+ Mem *pMem;
+ assert( pTos>=p->aStack );
+ assert( i>=0 && i<p->nMem );
+ pMem = &p->aMem[i];
+ Integerify(pMem);
+ Integerify(pTos);
+ if( pMem->i<pTos->i){
+ pMem->i = pTos->i;
+ }
+ break;
+}
+#endif /* SQLITE_OMIT_AUTOINCREMENT */
+
/* Opcode: MemIncr P1 P2 *
**
** Increment the integer valued memory cell P1 by 1. If P2 is not zero
-** and the result after the increment is greater than zero, then jump
+** and the result after the increment is exactly 1, then jump
** to P2.
**
** This instruction throws an error if the memory cell is not initially
@@ -4064,7 +4239,24 @@ case OP_MemIncr: {
pMem = &p->aMem[i];
assert( pMem->flags==MEM_Int );
pMem->i++;
- if( pOp->p2>0 && pMem->i>0 ){
+ if( pOp->p2>0 && pMem->i==1 ){
+ pc = pOp->p2 - 1;
+ }
+ break;
+}
+
+/* Opcode: IfMemPos P1 P2 *
+**
+** If the value of memory cell P1 is 1 or greater, jump to P2. This
+** opcode assumes that memory cell P1 holds an integer value.
+*/
+case OP_IfMemPos: {
+ int i = pOp->p1;
+ Mem *pMem;
+ assert( i>=0 && i<p->nMem );
+ pMem = &p->aMem[i];
+ assert( pMem->flags==MEM_Int );
+ if( pMem->i>0 ){
pc = pOp->p2 - 1;
}
break;
@@ -4072,8 +4264,8 @@ case OP_MemIncr: {
/* Opcode: AggReset P1 P2 P3
**
-** Reset the aggregator so that it no longer contains any data.
-** Future aggregator elements will contain P2 values each and be sorted
+** Reset the current aggregator context so that it no longer contains any
+** data. Future aggregator elements will contain P2 values each and be sorted
** using the KeyInfo structure pointed to by P3.
**
** If P1 is non-zero, then only a single aggregator row is available (i.e.
@@ -4083,18 +4275,18 @@ case OP_MemIncr: {
case OP_AggReset: {
assert( !pOp->p3 || pOp->p3type==P3_KEYINFO );
if( pOp->p1 ){
- rc = sqlite3VdbeAggReset(0, &p->agg, (KeyInfo *)pOp->p3);
- p->agg.nMem = pOp->p2; /* Agg.nMem is used by AggInsert() */
- rc = AggInsert(&p->agg, 0, 0);
+ rc = sqlite3VdbeAggReset(0, p->pAgg, (KeyInfo *)pOp->p3);
+ p->pAgg->nMem = pOp->p2; /* Agg.nMem is used by AggInsert() */
+ rc = AggInsert(p->pAgg, 0, 0);
}else{
- rc = sqlite3VdbeAggReset(db, &p->agg, (KeyInfo *)pOp->p3);
- p->agg.nMem = pOp->p2;
+ rc = sqlite3VdbeAggReset(db, p->pAgg, (KeyInfo *)pOp->p3);
+ p->pAgg->nMem = pOp->p2;
}
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
- p->agg.apFunc = sqliteMalloc( p->agg.nMem*sizeof(p->agg.apFunc[0]) );
- if( p->agg.apFunc==0 ) goto no_mem;
+ p->pAgg->apFunc = sqliteMalloc( p->pAgg->nMem*sizeof(p->pAgg->apFunc[0]) );
+ if( p->pAgg->apFunc==0 ) goto no_mem;
break;
}
@@ -4106,8 +4298,8 @@ case OP_AggReset: {
*/
case OP_AggInit: {
int i = pOp->p2;
- assert( i>=0 && i<p->agg.nMem );
- p->agg.apFunc[i] = (FuncDef*)pOp->p3;
+ assert( i>=0 && i<p->pAgg->nMem );
+ p->pAgg->apFunc[i] = (FuncDef*)pOp->p3;
break;
}
@@ -4142,14 +4334,13 @@ case OP_AggFunc: {
storeTypeInfo(pRec, db->enc);
}
i = pTos->i;
- assert( i>=0 && i<p->agg.nMem );
+ assert( i>=0 && i<p->pAgg->nMem );
ctx.pFunc = (FuncDef*)pOp->p3;
- pMem = &p->agg.pCurrent->aMem[i];
+ pMem = &p->pAgg->pCurrent->aMem[i];
ctx.s.z = pMem->zShort; /* Space used for small aggregate contexts */
ctx.pAgg = pMem->z;
ctx.cnt = ++pMem->i;
ctx.isError = 0;
- ctx.isStep = 1;
ctx.pColl = 0;
if( ctx.pFunc->needCollSeq ){
assert( pOp>p->aOp );
@@ -4189,18 +4380,18 @@ case OP_AggFocus: {
Stringify(pTos, db->enc);
zKey = pTos->z;
nKey = pTos->n;
- assert( p->agg.pBtree );
- assert( p->agg.pCsr );
- rc = sqlite3BtreeMoveto(p->agg.pCsr, zKey, nKey, &res);
+ assert( p->pAgg->pBtree );
+ assert( p->pAgg->pCsr );
+ rc = sqlite3BtreeMoveto(p->pAgg->pCsr, zKey, nKey, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
if( res==0 ){
- rc = sqlite3BtreeData(p->agg.pCsr, 0, sizeof(AggElem*),
- (char *)&p->agg.pCurrent);
+ rc = sqlite3BtreeData(p->pAgg->pCsr, 0, sizeof(AggElem*),
+ (char *)&p->pAgg->pCurrent);
pc = pOp->p2 - 1;
}else{
- rc = AggInsert(&p->agg, zKey, nKey);
+ rc = AggInsert(p->pAgg, zKey, nKey);
}
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
@@ -4218,27 +4409,48 @@ case OP_AggFocus: {
case OP_AggSet: {
AggElem *pFocus;
int i = pOp->p2;
- pFocus = p->agg.pCurrent;
+ pFocus = p->pAgg->pCurrent;
assert( pTos>=p->aStack );
if( pFocus==0 ) goto no_mem;
- assert( i>=0 && i<p->agg.nMem );
+ assert( i>=0 && i<p->pAgg->nMem );
rc = sqlite3VdbeMemMove(&pFocus->aMem[i], pTos);
pTos--;
break;
}
-/* Opcode: AggGet * P2 *
+/* Opcode: AggGet P1 P2 *
**
** Push a new entry onto the stack which is a copy of the P2-th field
** of the current aggregate. Strings are not duplicated so
** string values will be ephemeral.
+**
+** If P1 is zero, then the value is pulled out of the current aggregate
+** in the current aggregate context. If P1 is greater than zero, then
+** the value is taken from the P1th outer aggregate context. (i.e. if
+** P1==1 then read from the aggregate context that will be restored
+** by the next OP_AggContextPop opcode).
*/
case OP_AggGet: {
AggElem *pFocus;
int i = pOp->p2;
- pFocus = p->agg.pCurrent;
- if( pFocus==0 ) goto no_mem;
- assert( i>=0 && i<p->agg.nMem );
+ Agg *pAgg = &p->pAgg[-pOp->p1];
+ assert( pAgg>=p->apAgg );
+ pFocus = pAgg->pCurrent;
+ if( pFocus==0 ){
+ int res;
+ if( sqlite3_malloc_failed ) goto no_mem;
+ rc = sqlite3BtreeFirst(pAgg->pCsr, &res);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ if( res!=0 ){
+ rc = AggInsert(pAgg, "", 1);
+ pFocus = pAgg->pCurrent;
+ }else{
+ rc = sqlite3BtreeData(pAgg->pCsr, 0, 4, (char *)&pFocus);
+ }
+ }
+ assert( i>=0 && i<pAgg->nMem );
pTos++;
sqlite3VdbeMemShallowCopy(pTos, &pFocus->aMem[i], MEM_Ephem);
if( pTos->flags&MEM_Str ){
@@ -4263,16 +4475,16 @@ case OP_AggNext: {
int res;
assert( rc==SQLITE_OK );
CHECK_FOR_INTERRUPT;
- if( p->agg.searching==0 ){
- p->agg.searching = 1;
- if( p->agg.pCsr ){
- rc = sqlite3BtreeFirst(p->agg.pCsr, &res);
+ if( p->pAgg->searching==0 ){
+ p->pAgg->searching = 1;
+ if( p->pAgg->pCsr ){
+ rc = sqlite3BtreeFirst(p->pAgg->pCsr, &res);
}else{
res = 0;
}
}else{
- if( p->agg.pCsr ){
- rc = sqlite3BtreeNext(p->agg.pCsr, &res);
+ if( p->pAgg->pCsr ){
+ rc = sqlite3BtreeNext(p->pAgg->pCsr, &res);
}else{
res = 1;
}
@@ -4285,21 +4497,20 @@ case OP_AggNext: {
sqlite3_context ctx;
Mem *aMem;
- if( p->agg.pCsr ){
- rc = sqlite3BtreeData(p->agg.pCsr, 0, sizeof(AggElem*),
- (char *)&p->agg.pCurrent);
+ if( p->pAgg->pCsr ){
+ rc = sqlite3BtreeData(p->pAgg->pCsr, 0, sizeof(AggElem*),
+ (char *)&p->pAgg->pCurrent);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
}
- aMem = p->agg.pCurrent->aMem;
- for(i=0; i<p->agg.nMem; i++){
- FuncDef *pFunc = p->agg.apFunc[i];
+ aMem = p->pAgg->pCurrent->aMem;
+ for(i=0; i<p->pAgg->nMem; i++){
+ FuncDef *pFunc = p->pAgg->apFunc[i];
Mem *pMem = &aMem[i];
if( pFunc==0 || pFunc->xFinalize==0 ) continue;
ctx.s.flags = MEM_Null;
ctx.s.z = pMem->zShort;
ctx.pAgg = (void*)pMem->z;
ctx.cnt = pMem->i;
- ctx.isStep = 0;
ctx.pFunc = pFunc;
pFunc->xFinalize(&ctx);
pMem->z = ctx.pAgg;
@@ -4328,6 +4539,25 @@ case OP_Vacuum: {
break;
}
+/* Opcode: Expire P1 * *
+**
+** Cause precompiled statements to become expired. An expired statement
+** fails with an error code of SQLITE_SCHEMA if it is ever executed
+** (via sqlite3_step()).
+**
+** If P1 is 0, then all SQL statements become expired. If P1 is non-zero,
+** then only the currently executing statement is affected.
+*/
+case OP_Expire: {
+ if( !pOp->p1 ){
+ sqlite3ExpirePreparedStatements(db);
+ }else{
+ p->expired = 1;
+ }
+ break;
+}
+
+
/* An other opcode is illegal...
*/
default: {
@@ -4371,6 +4601,8 @@ default: {
sqlite3SetString(&p->zErrMsg, "jump destination out of range", (char*)0);
rc = SQLITE_INTERNAL;
}
+#ifdef SQLITE_DEBUG
+ /* Code for tracing the vdbe stack. */
if( p->trace && pTos>=p->aStack ){
int i;
fprintf(p->trace, "Stack:");
@@ -4393,7 +4625,8 @@ default: {
if( rc!=0 ) fprintf(p->trace," rc=%d",rc);
fprintf(p->trace,"\n");
}
-#endif
+#endif /* SQLITE_DEBUG */
+#endif /* NDEBUG */
} /* The end of the for(;;) loop the loops through opcodes */
/* If we reach this point, it means that execution is finished.
diff --git a/ext/pdo_sqlite/sqlite/src/vdbe.h b/ext/pdo_sqlite/sqlite/src/vdbe.h
index 490417a422..e1b83986f2 100644
--- a/ext/pdo_sqlite/sqlite/src/vdbe.h
+++ b/ext/pdo_sqlite/sqlite/src/vdbe.h
@@ -110,7 +110,7 @@ int sqlite3VdbeFindOp(Vdbe*, int, int, int);
VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
int sqlite3VdbeMakeLabel(Vdbe*);
void sqlite3VdbeDelete(Vdbe*);
-void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int);
+void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int,int);
int sqlite3VdbeFinalize(Vdbe*);
void sqlite3VdbeResolveLabel(Vdbe*, int);
int sqlite3VdbeCurrentAddr(Vdbe*);
diff --git a/ext/pdo_sqlite/sqlite/src/vdbeInt.h b/ext/pdo_sqlite/sqlite/src/vdbeInt.h
index a929cb95e1..42682d1e25 100644
--- a/ext/pdo_sqlite/sqlite/src/vdbeInt.h
+++ b/ext/pdo_sqlite/sqlite/src/vdbeInt.h
@@ -220,7 +220,6 @@ struct sqlite3_context {
Mem s; /* The return value is stored here */
void *pAgg; /* Aggregate context */
u8 isError; /* Set to true for an error */
- u8 isStep; /* Current in the step function */
int cnt; /* Number of times that the step function has been called */
CollSeq *pColl;
};
@@ -322,7 +321,9 @@ struct Vdbe {
int magic; /* Magic number for sanity checking */
int nMem; /* Number of memory locations currently allocated */
Mem *aMem; /* The memory locations */
- Agg agg; /* Aggregate information */
+ int nAgg; /* Number of elements in apAgg */
+ Agg *apAgg; /* Array of aggregate contexts */
+ Agg *pAgg; /* Current aggregate context */
int nCallback; /* Number of callbacks invoked so far */
Keylist *pList; /* A list of ROWIDs */
int contextStackTop; /* Index of top element in the context stack */
@@ -343,6 +344,7 @@ struct Vdbe {
u8 explain; /* True if EXPLAIN present on SQL command */
u8 changeCntOn; /* True to update the change-counter */
u8 aborted; /* True if ROLLBACK in another VM causes an abort */
+ u8 expired; /* True if the VM needs to be recompiled */
int nChange; /* Number of db changes made since last reset */
};
@@ -363,10 +365,12 @@ int sqlite3VdbeAggReset(sqlite3*, Agg *, KeyInfo *);
void sqlite3VdbeKeylistFree(Keylist*);
void sqliteVdbePopStack(Vdbe*,int);
int sqlite3VdbeCursorMoveto(Cursor*);
-#if !defined(NDEBUG) || defined(VDBE_PROFILE)
+#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
void sqlite3VdbePrintOp(FILE*, int, Op*);
#endif
+#ifdef SQLITE_DEBUG
void sqlite3VdbePrintSql(Vdbe*);
+#endif
int sqlite3VdbeSerialTypeLen(u32);
u32 sqlite3VdbeSerialType(Mem*);
int sqlite3VdbeSerialPut(unsigned char*, Mem*);
diff --git a/ext/pdo_sqlite/sqlite/src/vdbeapi.c b/ext/pdo_sqlite/sqlite/src/vdbeapi.c
index f6047f6fbe..ca1612875a 100644
--- a/ext/pdo_sqlite/sqlite/src/vdbeapi.c
+++ b/ext/pdo_sqlite/sqlite/src/vdbeapi.c
@@ -16,6 +16,21 @@
#include "sqliteInt.h"
#include "vdbeInt.h"
+/*
+** Return TRUE (non-zero) of the statement supplied as an argument needs
+** to be recompiled. A statement needs to be recompiled whenever the
+** execution environment changes in a way that would alter the program
+** that sqlite3_prepare() generates. For example, if new functions or
+** collating sequences are registered or if an authorizer function is
+** added or changed.
+**
+***** EXPERIMENTAL ******
+*/
+int sqlite3_expired(sqlite3_stmt *pStmt){
+ Vdbe *p = (Vdbe*)pStmt;
+ return p==0 || p->expired;
+}
+
/**************************** sqlite3_value_ *******************************
** The following routines extract information from a Mem or sqlite3_value
** structure.
@@ -46,6 +61,7 @@ sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){
const unsigned char *sqlite3_value_text(sqlite3_value *pVal){
return (const char *)sqlite3ValueText(pVal, SQLITE_UTF8);
}
+#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_value_text16(sqlite3_value* pVal){
return sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
}
@@ -55,6 +71,7 @@ const void *sqlite3_value_text16be(sqlite3_value *pVal){
const void *sqlite3_value_text16le(sqlite3_value *pVal){
return sqlite3ValueText(pVal, SQLITE_UTF16LE);
}
+#endif /* SQLITE_OMIT_UTF16 */
int sqlite3_value_type(sqlite3_value* pVal){
return pVal->type;
}
@@ -100,6 +117,7 @@ void sqlite3_result_text(
){
sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, xDel);
}
+#ifndef SQLITE_OMIT_UTF16
void sqlite3_result_text16(
sqlite3_context *pCtx,
const void *z,
@@ -124,6 +142,7 @@ void sqlite3_result_text16le(
){
sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16LE, xDel);
}
+#endif /* SQLITE_OMIT_UTF16 */
void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){
sqlite3VdbeMemCopy(&pCtx->s, pValue);
}
@@ -144,6 +163,12 @@ int sqlite3_step(sqlite3_stmt *pStmt){
if( p->aborted ){
return SQLITE_ABORT;
}
+ if( p->pc<=0 && p->expired ){
+ if( p->rc==SQLITE_OK ){
+ p->rc = SQLITE_SCHEMA;
+ }
+ return SQLITE_ERROR;
+ }
db = p->db;
if( sqlite3SafetyOn(db) ){
p->rc = SQLITE_MISUSE;
@@ -177,9 +202,12 @@ int sqlite3_step(sqlite3_stmt *pStmt){
db->activeVdbeCnt++;
p->pc = 0;
}
+#ifndef SQLITE_OMIT_EXPLAIN
if( p->explain ){
rc = sqlite3VdbeList(p);
- }else{
+ }else
+#endif /* SQLITE_OMIT_EXPLAIN */
+ {
rc = sqlite3VdbeExec(p);
}
@@ -343,9 +371,11 @@ sqlite_int64 sqlite3_column_int64(sqlite3_stmt *pStmt, int i){
const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int i){
return sqlite3_value_text( columnMem(pStmt,i) );
}
+#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){
return sqlite3_value_text16( columnMem(pStmt,i) );
}
+#endif /* SQLITE_OMIT_UTF16 */
int sqlite3_column_type(sqlite3_stmt *pStmt, int i){
return sqlite3_value_type( columnMem(pStmt,i) );
}
@@ -384,14 +414,6 @@ const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){
}
/*
-** Return the name of the 'i'th column of the result set of SQL statement
-** pStmt, encoded as UTF-16.
-*/
-const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){
- return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, 0);
-}
-
-/*
** Return the column declaration type (if applicable) of the 'i'th column
** of the result set of SQL statement pStmt, encoded as UTF-8.
*/
@@ -399,6 +421,15 @@ const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){
return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, 1);
}
+#ifndef SQLITE_OMIT_UTF16
+/*
+** Return the name of the 'i'th column of the result set of SQL statement
+** pStmt, encoded as UTF-16.
+*/
+const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){
+ return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, 0);
+}
+
/*
** Return the column declaration type (if applicable) of the 'i'th column
** of the result set of SQL statement pStmt, encoded as UTF-16.
@@ -406,6 +437,7 @@ const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){
const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){
return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, 1);
}
+#endif /* SQLITE_OMIT_UTF16 */
/******************************* sqlite3_bind_ ***************************
**
@@ -513,6 +545,7 @@ int sqlite3_bind_text(
){
return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8);
}
+#ifndef SQLITE_OMIT_UTF16
int sqlite3_bind_text16(
sqlite3_stmt *pStmt,
int i,
@@ -522,6 +555,7 @@ int sqlite3_bind_text16(
){
return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE);
}
+#endif /* SQLITE_OMIT_UTF16 */
/*
** Return the number of wildcards that can be potentially bound to.
@@ -578,10 +612,12 @@ int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){
return 0;
}
createVarMap(p);
- for(i=0; i<p->nVar; i++){
- const char *z = p->azVar[i];
- if( z && strcmp(z,zName)==0 ){
- return i+1;
+ if( zName ){
+ for(i=0; i<p->nVar; i++){
+ const char *z = p->azVar[i];
+ if( z && strcmp(z,zName)==0 ){
+ return i+1;
+ }
}
}
return 0;
diff --git a/ext/pdo_sqlite/sqlite/src/vdbeaux.c b/ext/pdo_sqlite/sqlite/src/vdbeaux.c
index fa9751daab..6d77d725f4 100644
--- a/ext/pdo_sqlite/sqlite/src/vdbeaux.c
+++ b/ext/pdo_sqlite/sqlite/src/vdbeaux.c
@@ -103,7 +103,7 @@ int sqlite3VdbeAddOp(Vdbe *p, int op, int p1, int p2){
pOp->p2 = p2;
pOp->p3 = 0;
pOp->p3type = P3_NOTUSED;
-#ifndef NDEBUG
+#ifdef SQLITE_DEBUG
if( sqlite3_vdbe_addop_trace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]);
#endif
return i;
@@ -212,7 +212,7 @@ int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){
pOut->p2 = p2<0 ? addr + ADDR(p2) : p2;
pOut->p3 = pIn->p3;
pOut->p3type = pIn->p3 ? P3_STATIC : P3_NOTUSED;
-#ifndef NDEBUG
+#ifdef SQLITE_DEBUG
if( sqlite3_vdbe_addop_trace ){
sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]);
}
@@ -375,6 +375,8 @@ VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
return &p->aOp[addr];
}
+#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \
+ || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
/*
** Compute a string that describes the P3 parameter for an opcode.
** Use zTemp for any required temporary buffer space.
@@ -444,9 +446,10 @@ static char *displayP3(Op *pOp, char *zTemp, int nTemp){
}
return zP3;
}
+#endif
-#if !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
+#if defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
/*
** Print a single opcode. This routine is used for debugging only.
*/
@@ -473,6 +476,7 @@ static void releaseMemArray(Mem *p, int N){
}
}
+#ifndef SQLITE_OMIT_EXPLAIN
/*
** Give a listing of the program in the virtual machine.
**
@@ -488,6 +492,9 @@ int sqlite3VdbeList(
int rc = SQLITE_OK;
assert( p->explain );
+ if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE;
+ assert( db->magic==SQLITE_MAGIC_BUSY );
+ assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY );
/* Even though this opcode does not put dynamic strings onto the
** the stack, they may become dynamic if the user calls
@@ -498,17 +505,14 @@ int sqlite3VdbeList(
}
p->resOnStack = 0;
+
i = p->pc++;
if( i>=p->nOp ){
p->rc = SQLITE_OK;
rc = SQLITE_DONE;
}else if( db->flags & SQLITE_Interrupt ){
db->flags &= ~SQLITE_Interrupt;
- if( db->magic!=SQLITE_MAGIC_BUSY ){
- p->rc = SQLITE_MISUSE;
- }else{
- p->rc = SQLITE_INTERRUPT;
- }
+ p->rc = SQLITE_INTERRUPT;
rc = SQLITE_ERROR;
sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(p->rc), (char*)0);
}else{
@@ -549,6 +553,7 @@ int sqlite3VdbeList(
}
return rc;
}
+#endif /* SQLITE_OMIT_EXPLAIN */
/*
** Print the SQL that was used to generate a VDBE program.
@@ -581,6 +586,7 @@ void sqlite3VdbeMakeReady(
int nVar, /* Number of '?' see in the SQL statement */
int nMem, /* Number of memory cells to allocate */
int nCursor, /* Number of cursors to allocate */
+ int nAgg, /* Number of aggregate contexts required */
int isExplain /* True if the EXPLAIN keywords is present */
){
int n;
@@ -610,6 +616,7 @@ void sqlite3VdbeMakeReady(
+ nVar*sizeof(char*) /* azVar */
+ nMem*sizeof(Mem) /* aMem */
+ nCursor*sizeof(Cursor*) /* apCsr */
+ + nAgg*sizeof(Agg) /* Aggregate contexts */
);
if( !sqlite3_malloc_failed ){
p->aMem = &p->aStack[n];
@@ -620,15 +627,20 @@ void sqlite3VdbeMakeReady(
p->apArg = (Mem**)&p->aVar[nVar];
p->azVar = (char**)&p->apArg[n];
p->apCsr = (Cursor**)&p->azVar[nVar];
+ if( nAgg>0 ){
+ p->nAgg = nAgg;
+ p->apAgg = (Agg*)&p->apCsr[nCursor];
+ }
p->nCursor = nCursor;
for(n=0; n<nVar; n++){
p->aVar[n].flags = MEM_Null;
}
- for(n=0; n<nMem; n++){
- p->aMem[n].flags = MEM_Null;
- }
}
}
+ p->pAgg = p->apAgg;
+ for(n=0; n<p->nMem; n++){
+ p->aMem[n].flags = MEM_Null;
+ }
#ifdef SQLITE_DEBUG
if( (p->db->flags & SQLITE_VdbeListing)!=0
@@ -684,7 +696,7 @@ void sqlite3VdbeSorterReset(Vdbe *p){
** Free all resources allociated with AggElem pElem, an element of
** aggregate pAgg.
*/
-void freeAggElem(AggElem *pElem, Agg *pAgg){
+static void freeAggElem(AggElem *pElem, Agg *pAgg){
int i;
for(i=0; i<pAgg->nMem; i++){
Mem *pMem = &pElem->aMem[i];
@@ -694,9 +706,8 @@ void freeAggElem(AggElem *pElem, Agg *pAgg){
ctx.s.flags = MEM_Null;
ctx.pAgg = pMem->z;
ctx.cnt = pMem->i;
- ctx.isStep = 0;
ctx.isError = 0;
- (*pAgg->apFunc[i]->xFinalize)(&ctx);
+ (*ctx.pFunc->xFinalize)(&ctx);
pMem->z = ctx.pAgg;
if( pMem->z!=0 && pMem->z!=pMem->zShort ){
sqliteFree(pMem->z);
@@ -729,8 +740,10 @@ void freeAggElem(AggElem *pElem, Agg *pAgg){
*/
int sqlite3VdbeAggReset(sqlite3 *db, Agg *pAgg, KeyInfo *pKeyInfo){
int rc = 0;
- BtCursor *pCsr = pAgg->pCsr;
+ BtCursor *pCsr;
+ if( !pAgg ) return SQLITE_OK;
+ pCsr = pAgg->pCsr;
assert( (pCsr && pAgg->nTab>0) || (!pCsr && pAgg->nTab==0)
|| sqlite3_malloc_failed );
@@ -748,7 +761,7 @@ int sqlite3VdbeAggReset(sqlite3 *db, Agg *pAgg, KeyInfo *pKeyInfo){
while( res==0 && rc==SQLITE_OK ){
AggElem *pElem;
rc = sqlite3BtreeData(pCsr, 0, sizeof(AggElem*), (char *)&pElem);
- if( res!=SQLITE_OK ){
+ if( rc!=SQLITE_OK ){
return rc;
}
assert( pAgg->apFunc!=0 );
@@ -779,7 +792,11 @@ int sqlite3VdbeAggReset(sqlite3 *db, Agg *pAgg, KeyInfo *pKeyInfo){
if( db ){
if( !pAgg->pBtree ){
assert( pAgg->nTab==0 );
+#ifndef SQLITE_OMIT_MEMORYDB
rc = sqlite3BtreeFactory(db, ":memory:", 0, TEMP_PAGES, &pAgg->pBtree);
+#else
+ rc = sqlite3BtreeFactory(db, 0, 0, TEMP_PAGES, &pAgg->pBtree);
+#endif
if( rc!=SQLITE_OK ) return rc;
sqlite3BtreeBeginTrans(pAgg->pBtree, 1);
rc = sqlite3BtreeCreateTable(pAgg->pBtree, &pAgg->nTab, 0);
@@ -878,7 +895,9 @@ static void Cleanup(Vdbe *p){
sqliteFree(p->contextStack);
}
sqlite3VdbeSorterReset(p);
- sqlite3VdbeAggReset(0, &p->agg, 0);
+ for(i=0; i<p->nAgg; i++){
+ sqlite3VdbeAggReset(0, &p->apAgg[i], 0);
+ }
p->contextStack = 0;
p->contextStackDepth = 0;
p->contextStackTop = 0;
@@ -1026,7 +1045,7 @@ static int vdbeCommit(sqlite3 *db){
** master journal file. If an error occurs at this point close
** and delete the master journal file. All the individual journal files
** still have 'null' as the master journal pointer, so they will roll
- ** back independantly if a failure occurs.
+ ** back independently if a failure occurs.
*/
for(i=0; i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
@@ -1050,18 +1069,12 @@ static int vdbeCommit(sqlite3 *db){
*/
zMainFile = sqlite3BtreeGetDirname(db->aDb[0].pBt);
rc = sqlite3OsOpenDirectory(zMainFile, &master);
- if( rc!=SQLITE_OK ){
+ if( rc!=SQLITE_OK || (rc = sqlite3OsSync(&master))!=SQLITE_OK ){
sqlite3OsClose(&master);
sqlite3OsDelete(zMaster);
sqliteFree(zMaster);
return rc;
}
- rc = sqlite3OsSync(&master);
- if( rc!=SQLITE_OK ){
- sqlite3OsClose(&master);
- sqliteFree(zMaster);
- return rc;
- }
/* Sync all the db files involved in the transaction. The same call
** sets the master journal pointer in each individual journal. If
@@ -1103,8 +1116,6 @@ static int vdbeCommit(sqlite3 *db){
** master journal exists now or if it will exist after the operating
** system crash that may follow the fsync() failure.
*/
- assert(0);
- sqliteFree(zMaster);
return rc;
}
@@ -1193,7 +1204,9 @@ int sqlite3VdbeHalt(Vdbe *p){
}
closeAllCursors(p);
checkActiveVdbeCnt(db);
- if( db->autoCommit && db->activeVdbeCnt==1 ){
+ if( p->pc<0 ){
+ /* No commit or rollback needed if the program never started */
+ }else if( db->autoCommit && db->activeVdbeCnt==1 ){
if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){
/* The auto-commit flag is true, there are no other active queries
** using this handle and the vdbe program was successful or hit an
@@ -1236,7 +1249,7 @@ int sqlite3VdbeHalt(Vdbe *p){
}
/* If this was an INSERT, UPDATE or DELETE, set the change counter. */
- if( p->changeCntOn ){
+ if( p->changeCntOn && p->pc>=0 ){
if( !xFunc || xFunc==sqlite3BtreeCommitStmt ){
sqlite3VdbeSetChanges(db, p->nChange);
}else{
@@ -1285,17 +1298,27 @@ int sqlite3VdbeReset(Vdbe *p){
*/
sqlite3VdbeHalt(p);
- /* Transfer the error code and error message from the VDBE into the
- ** main database structure.
+ /* If the VDBE has be run even partially, then transfer the error code
+ ** and error message from the VDBE into the main database structure. But
+ ** if the VDBE has just been set to run but has not actually executed any
+ ** instructions yet, leave the main database error information unchanged.
*/
- if( p->zErrMsg ){
- sqlite3Error(p->db, p->rc, "%s", p->zErrMsg);
- sqliteFree(p->zErrMsg);
- p->zErrMsg = 0;
- }else if( p->rc ){
+ if( p->pc>=0 ){
+ if( p->zErrMsg ){
+ sqlite3Error(p->db, p->rc, "%s", p->zErrMsg);
+ sqliteFree(p->zErrMsg);
+ p->zErrMsg = 0;
+ }else if( p->rc ){
+ sqlite3Error(p->db, p->rc, 0);
+ }else{
+ sqlite3Error(p->db, SQLITE_OK, 0);
+ }
+ }else if( p->rc && p->expired ){
+ /* The expired flag was set on the VDBE before the first call
+ ** to sqlite3_step(). For consistency (since sqlite3_step() was
+ ** called), set the database error in this case as well.
+ */
sqlite3Error(p->db, p->rc, 0);
- }else{
- sqlite3Error(p->db, SQLITE_OK, 0);
}
/* Reclaim all memory used by the VDBE
@@ -1329,6 +1352,9 @@ int sqlite3VdbeReset(Vdbe *p){
#endif
p->magic = VDBE_MAGIC_INIT;
p->aborted = 0;
+ if( p->rc==SQLITE_SCHEMA ){
+ sqlite3ResetInternalSchema(p->db, 0);
+ }
return p->rc;
}
@@ -1338,18 +1364,13 @@ int sqlite3VdbeReset(Vdbe *p){
*/
int sqlite3VdbeFinalize(Vdbe *p){
int rc = SQLITE_OK;
- sqlite3 *db = p->db;
if( p->magic==VDBE_MAGIC_RUN || p->magic==VDBE_MAGIC_HALT ){
rc = sqlite3VdbeReset(p);
}else if( p->magic!=VDBE_MAGIC_INIT ){
- /* sqlite3Error(p->db, SQLITE_MISUSE, 0); */
return SQLITE_MISUSE;
}
sqlite3VdbeDelete(p);
- if( rc==SQLITE_SCHEMA ){
- sqlite3ResetInternalSchema(db, 0);
- }
return rc;
}
@@ -1418,19 +1439,22 @@ void sqlite3VdbeDelete(Vdbe *p){
*/
int sqlite3VdbeCursorMoveto(Cursor *p){
if( p->deferredMoveto ){
- int res;
+ int res, rc;
extern int sqlite3_search_count;
assert( p->intKey );
if( p->intKey ){
- sqlite3BtreeMoveto(p->pCursor, 0, p->movetoTarget, &res);
+ rc = sqlite3BtreeMoveto(p->pCursor, 0, p->movetoTarget, &res);
}else{
- sqlite3BtreeMoveto(p->pCursor,(char*)&p->movetoTarget,sizeof(i64),&res);
+ rc = sqlite3BtreeMoveto(p->pCursor,(char*)&p->movetoTarget,
+ sizeof(i64),&res);
}
+ if( rc ) return rc;
*p->pIncrKey = 0;
p->lastRecno = keyToInt(p->movetoTarget);
p->recnoIsValid = res==0;
if( res<0 ){
- sqlite3BtreeNext(p->pCursor, &res);
+ rc = sqlite3BtreeNext(p->pCursor, &res);
+ if( rc ) return rc;
}
sqlite3_search_count++;
p->deferredMoveto = 0;
@@ -1487,13 +1511,15 @@ u32 sqlite3VdbeSerialType(Mem *pMem){
return 0;
}
if( flags&MEM_Int ){
- /* Figure out whether to use 1, 2, 4 or 8 bytes. */
+ /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */
+# define MAX_6BYTE ((((i64)0x00010000)<<32)-1)
i64 i = pMem->i;
- if( i>=-127 && i<=127 ) return 1;
- if( i>=-32767 && i<=32767 ) return 2;
- if( i>=-8388607 && i<=8388607 ) return 3;
- if( i>=-2147483647 && i<=2147483647 ) return 4;
- if( i>=-140737488355328L && i<=140737488355328L ) return 5;
+ u64 u = i<0 ? -i : i;
+ if( u<=127 ) return 1;
+ if( u<=32767 ) return 2;
+ if( u<=8388607 ) return 3;
+ if( u<=2147483647 ) return 4;
+ if( u<=MAX_6BYTE ) return 5;
return 6;
}
if( flags&MEM_Real ){
@@ -1801,6 +1827,23 @@ void sqlite3VdbeSetChanges(sqlite3 *db, int nChange){
** Set a flag in the vdbe to update the change counter when it is finalised
** or reset.
*/
-void sqlite3VdbeCountChanges(Vdbe *p){
- p->changeCntOn = 1;
+void sqlite3VdbeCountChanges(Vdbe *v){
+ v->changeCntOn = 1;
+}
+
+/*
+** Mark every prepared statement associated with a database connection
+** as expired.
+**
+** An expired statement means that recompilation of the statement is
+** recommend. Statements expire when things happen that make their
+** programs obsolete. Removing user-defined functions or collating
+** sequences, or changing an authorization function are the types of
+** things that make prepared statements obsolete.
+*/
+void sqlite3ExpirePreparedStatements(sqlite3 *db){
+ Vdbe *p;
+ for(p = db->pVdbe; p; p=p->pNext){
+ p->expired = 1;
+ }
}
diff --git a/ext/pdo_sqlite/sqlite/src/vdbemem.c b/ext/pdo_sqlite/sqlite/src/vdbemem.c
index c6cd94e634..23da9ced9e 100644
--- a/ext/pdo_sqlite/sqlite/src/vdbemem.c
+++ b/ext/pdo_sqlite/sqlite/src/vdbemem.c
@@ -34,10 +34,21 @@
** between formats.
*/
int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
+ int rc;
if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){
return SQLITE_OK;
}
- return sqlite3VdbeMemTranslate(pMem, desiredEnc);
+#ifdef SQLITE_OMIT_UTF16
+ return SQLITE_ERROR;
+#else
+ rc = sqlite3VdbeMemTranslate(pMem, desiredEnc);
+ if( rc==SQLITE_NOMEM ){
+ sqlite3VdbeMemRelease(pMem);
+ pMem->flags = MEM_Null;
+ pMem->z = 0;
+ }
+ return rc;
+#endif
}
/*
@@ -390,6 +401,8 @@ int sqlite3VdbeMemSetStr(
pMem->type = enc==0 ? SQLITE_BLOB : SQLITE_TEXT;
pMem->n = n;
+ assert( enc==0 || enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE
+ || enc==SQLITE_UTF16BE );
switch( enc ){
case 0:
pMem->flags |= MEM_Blob;
@@ -403,6 +416,7 @@ int sqlite3VdbeMemSetStr(
}
break;
+#ifndef SQLITE_OMIT_UTF16
case SQLITE_UTF16LE:
case SQLITE_UTF16BE:
pMem->flags |= MEM_Str;
@@ -413,10 +427,7 @@ int sqlite3VdbeMemSetStr(
if( sqlite3VdbeMemHandleBom(pMem) ){
return SQLITE_NOMEM;
}
- break;
-
- default:
- assert(0);
+#endif /* SQLITE_OMIT_UTF16 */
}
if( pMem->flags&MEM_Ephem ){
return sqlite3VdbeMemMakeWriteable(pMem);
diff --git a/ext/pdo_sqlite/sqlite/src/where.c b/ext/pdo_sqlite/sqlite/src/where.c
index 08c174e934..b2489a4706 100644
--- a/ext/pdo_sqlite/sqlite/src/where.c
+++ b/ext/pdo_sqlite/sqlite/src/where.c
@@ -10,7 +10,11 @@
**
*************************************************************************
** This module contains C code that generates VDBE code used to process
-** the WHERE clause of SQL statements.
+** the WHERE clause of SQL statements. This module is reponsible for
+** generating the code that loops through a table looking for applicable
+** rows. Indices are selected and used to speed the search when doing
+** so is applicable. Because this module is responsible for selecting
+** indices, you might also think of this module as the "query optimizer".
**
** $Id$
*/
@@ -20,6 +24,43 @@
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause. Each WHERE
** clause subexpression is separated from the others by an AND operator.
+**
+** The idxLeft and idxRight fields are the VDBE cursor numbers for the
+** table that contains the column that appears on the left-hand and
+** right-hand side of ExprInfo.p. If either side of ExprInfo.p is
+** something other than a simple column reference, then idxLeft or
+** idxRight are -1.
+**
+** It is the VDBE cursor number is the value stored in Expr.iTable
+** when Expr.op==TK_COLUMN and the value stored in SrcList.a[].iCursor.
+**
+** prereqLeft, prereqRight, and prereqAll record sets of cursor numbers,
+** but they do so indirectly. A single ExprMaskSet structure translates
+** cursor number into bits and the translated bit is stored in the prereq
+** fields. The translation is used in order to maximize the number of
+** bits that will fit in a Bitmask. The VDBE cursor numbers might be
+** spread out over the non-negative integers. For example, the cursor
+** numbers might be 3, 8, 9, 10, 20, 23, 41, and 45. The ExprMaskSet
+** translates these sparse cursor numbers into consecutive integers
+** beginning with 0 in order to make the best possible use of the available
+** bits in the Bitmask. So, in the example above, the cursor numbers
+** would be mapped into integers 0 through 7.
+**
+** prereqLeft tells us every VDBE cursor that is referenced on the
+** left-hand side of ExprInfo.p. prereqRight does the same for the
+** right-hand side of the expression. The following identity always
+** holds:
+**
+** prereqAll = prereqLeft | prereqRight
+**
+** The ExprInfo.indexable field is true if the ExprInfo.p expression
+** is of a form that might control an index. Indexable expressions
+** look like this:
+**
+** <column> <op> <expr>
+**
+** Where <column> is a simple column name and <op> is on of the operators
+** that allowedOp() recognizes.
*/
typedef struct ExprInfo ExprInfo;
struct ExprInfo {
@@ -29,24 +70,41 @@ struct ExprInfo {
** p->pLeft is not the column of any table */
short int idxRight; /* p->pRight is a column in this table number. -1 if
** p->pRight is not the column of any table */
- unsigned prereqLeft; /* Bitmask of tables referenced by p->pLeft */
- unsigned prereqRight; /* Bitmask of tables referenced by p->pRight */
- unsigned prereqAll; /* Bitmask of tables referenced by p */
+ Bitmask prereqLeft; /* Bitmask of tables referenced by p->pLeft */
+ Bitmask prereqRight; /* Bitmask of tables referenced by p->pRight */
+ Bitmask prereqAll; /* Bitmask of tables referenced by p */
};
/*
** An instance of the following structure keeps track of a mapping
-** between VDBE cursor numbers and bitmasks. The VDBE cursor numbers
-** are small integers contained in SrcList_item.iCursor and Expr.iTable
-** fields. For any given WHERE clause, we want to track which cursors
-** are being used, so we assign a single bit in a 32-bit word to track
-** that cursor. Then a 32-bit integer is able to show the set of all
-** cursors being used.
+** between VDBE cursor numbers and bits of the bitmasks in ExprInfo.
+**
+** The VDBE cursor numbers are small integers contained in
+** SrcList_item.iCursor and Expr.iTable fields. For any given WHERE
+** clause, the cursor numbers might not begin with 0 and they might
+** contain gaps in the numbering sequence. But we want to make maximum
+** use of the bits in our bitmasks. This structure provides a mapping
+** from the sparse cursor numbers into consecutive integers beginning
+** with 0.
+**
+** If ExprMaskSet.ix[A]==B it means that The A-th bit of a Bitmask
+** corresponds VDBE cursor number B. The A-th bit of a bitmask is 1<<A.
+**
+** For example, if the WHERE clause expression used these VDBE
+** cursors: 4, 5, 8, 29, 57, 73. Then the ExprMaskSet structure
+** would map those cursor numbers into bits 0 through 5.
+**
+** Note that the mapping is not necessarily ordered. In the example
+** above, the mapping might go like this: 4->3, 5->1, 8->2, 29->0,
+** 57->5, 73->4. Or one of 719 other combinations might be used. It
+** does not really matter. What is important is that sparse cursor
+** numbers all get mapped into bit numbers that begin with 0 and contain
+** no gaps.
*/
typedef struct ExprMaskSet ExprMaskSet;
struct ExprMaskSet {
- int n; /* Number of assigned cursor values */
- int ix[31]; /* Cursor assigned to each bit */
+ int n; /* Number of assigned cursor values */
+ int ix[sizeof(Bitmask)*8]; /* Cursor assigned to each bit */
};
/*
@@ -55,13 +113,21 @@ struct ExprMaskSet {
#define ARRAYSIZE(X) (sizeof(X)/sizeof(X[0]))
/*
-** This routine is used to divide the WHERE expression into subexpressions
-** separated by the AND operator.
+** This routine identifies subexpressions in the WHERE clause where
+** each subexpression is separate by the AND operator. aSlot is
+** filled with pointers to the subexpressions. For example:
+**
+** WHERE a=='hello' AND coalesce(b,11)<10 AND (c+12!=d OR c==22)
+** \________/ \_______________/ \________________/
+** slot[0] slot[1] slot[2]
+**
+** The original WHERE clause in pExpr is unaltered. All this routine
+** does is make aSlot[] entries point to substructure within pExpr.
**
-** aSlot[] is an array of subexpressions structures.
-** There are nSlot spaces left in this array. This routine attempts to
-** split pExpr into subexpressions and fills aSlot[] with those subexpressions.
-** The return value is the number of slots filled.
+** aSlot[] is an array of subexpressions structures. There are nSlot
+** spaces left in this array. This routine finds as many AND-separated
+** subexpressions as it can and puts pointers to those subexpressions
+** into aSlot[] entries. The return value is the number of slots filled.
*/
static int exprSplit(int nSlot, ExprInfo *aSlot, Expr *pExpr){
int cnt = 0;
@@ -86,23 +152,29 @@ static int exprSplit(int nSlot, ExprInfo *aSlot, Expr *pExpr){
#define initMaskSet(P) memset(P, 0, sizeof(*P))
/*
-** Return the bitmask for the given cursor. Assign a new bitmask
-** if this is the first time the cursor has been seen.
+** Return the bitmask for the given cursor number. Return 0 if
+** iCursor is not in the set.
*/
-static int getMask(ExprMaskSet *pMaskSet, int iCursor){
+static Bitmask getMask(ExprMaskSet *pMaskSet, int iCursor){
int i;
for(i=0; i<pMaskSet->n; i++){
- if( pMaskSet->ix[i]==iCursor ) return 1<<i;
- }
- if( i==pMaskSet->n && i<ARRAYSIZE(pMaskSet->ix) ){
- pMaskSet->n++;
- pMaskSet->ix[i] = iCursor;
- return 1<<i;
+ if( pMaskSet->ix[i]==iCursor ){
+ return ((Bitmask)1)<<i;
+ }
}
return 0;
}
/*
+** Create a new mask for cursor iCursor.
+*/
+static void createMask(ExprMaskSet *pMaskSet, int iCursor){
+ if( pMaskSet->n<ARRAYSIZE(pMaskSet->ix) ){
+ pMaskSet->ix[pMaskSet->n++] = iCursor;
+ }
+}
+
+/*
** Destroy an expression mask set
*/
#define freeMaskSet(P) /* NO-OP */
@@ -113,30 +185,39 @@ static int getMask(ExprMaskSet *pMaskSet, int iCursor){
** tree.
**
** In order for this routine to work, the calling function must have
-** previously invoked sqlite3ExprResolveIds() on the expression. See
+** previously invoked sqlite3ExprResolveNames() on the expression. See
** the header comment on that routine for additional information.
-** The sqlite3ExprResolveIds() routines looks for column names and
+** The sqlite3ExprResolveNames() routines looks for column names and
** sets their opcodes to TK_COLUMN and their Expr.iTable fields to
** the VDBE cursor number of the table.
*/
-static int exprTableUsage(ExprMaskSet *pMaskSet, Expr *p){
- unsigned int mask = 0;
+static Bitmask exprListTableUsage(ExprMaskSet *, ExprList *);
+static Bitmask exprTableUsage(ExprMaskSet *pMaskSet, Expr *p){
+ Bitmask mask = 0;
if( p==0 ) return 0;
if( p->op==TK_COLUMN ){
mask = getMask(pMaskSet, p->iTable);
- if( mask==0 ) mask = -1;
return mask;
}
- if( p->pRight ){
- mask = exprTableUsage(pMaskSet, p->pRight);
+ mask = exprTableUsage(pMaskSet, p->pRight);
+ mask |= exprTableUsage(pMaskSet, p->pLeft);
+ mask |= exprListTableUsage(pMaskSet, p->pList);
+ if( p->pSelect ){
+ Select *pS = p->pSelect;
+ mask |= exprListTableUsage(pMaskSet, pS->pEList);
+ mask |= exprListTableUsage(pMaskSet, pS->pGroupBy);
+ mask |= exprListTableUsage(pMaskSet, pS->pOrderBy);
+ mask |= exprTableUsage(pMaskSet, pS->pWhere);
+ mask |= exprTableUsage(pMaskSet, pS->pHaving);
}
- if( p->pLeft ){
- mask |= exprTableUsage(pMaskSet, p->pLeft);
- }
- if( p->pList ){
- int i;
- for(i=0; i<p->pList->nExpr; i++){
- mask |= exprTableUsage(pMaskSet, p->pList->a[i].pExpr);
+ return mask;
+}
+static Bitmask exprListTableUsage(ExprMaskSet *pMaskSet, ExprList *pList){
+ int i;
+ Bitmask mask = 0;
+ if( pList ){
+ for(i=0; i<pList->nExpr; i++){
+ mask |= exprTableUsage(pMaskSet, pList->a[i].pExpr);
}
}
return mask;
@@ -144,7 +225,7 @@ static int exprTableUsage(ExprMaskSet *pMaskSet, Expr *p){
/*
** Return TRUE if the given operator is one of the operators that is
-** allowed for an indexable WHERE clause. The allowed operators are
+** allowed for an indexable WHERE clause term. The allowed operators are
** "=", "<", ">", "<=", ">=", and "IN".
*/
static int allowedOp(int op){
@@ -153,7 +234,7 @@ static int allowedOp(int op){
}
/*
-** Swap two integers.
+** Swap two objects of type T.
*/
#define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;}
@@ -168,8 +249,9 @@ static int allowedOp(int op){
*/
static int tableOrder(SrcList *pList, int iCur){
int i;
- for(i=0; i<pList->nSrc; i++){
- if( pList->a[i].iCursor==iCur ) return i;
+ struct SrcList_item *pItem;
+ for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
+ if( pItem->iCursor==iCur ) return i;
}
return -1;
}
@@ -228,98 +310,123 @@ static void exprAnalyze(SrcList *pSrc, ExprMaskSet *pMaskSet, ExprInfo *pInfo){
}
/*
+** This routine decides if pIdx can be used to satisfy the ORDER BY
+** clause. If it can, it returns 1. If pIdx cannot satisfy the
+** ORDER BY clause, this routine returns 0.
+**
** pOrderBy is an ORDER BY clause from a SELECT statement. pTab is the
** left-most table in the FROM clause of that same SELECT statement and
-** the table has a cursor number of "base".
-**
-** This routine attempts to find an index for pTab that generates the
-** correct record sequence for the given ORDER BY clause. The return value
-** is a pointer to an index that does the job. NULL is returned if the
-** table has no index that will generate the correct sort order.
+** the table has a cursor number of "base". pIdx is an index on pTab.
**
-** If there are two or more indices that generate the correct sort order
-** and pPreferredIdx is one of those indices, then return pPreferredIdx.
+** nEqCol is the number of columns of pIdx that are used as equality
+** constraints. Any of these columns may be missing from the ORDER BY
+** clause and the match can still be a success.
**
-** nEqCol is the number of columns of pPreferredIdx that are used as
-** equality constraints. Any index returned must have exactly this same
-** set of columns. The ORDER BY clause only matches index columns beyond the
-** the first nEqCol columns.
+** If the index is UNIQUE, then the ORDER BY clause is allowed to have
+** additional terms past the end of the index and the match will still
+** be a success.
**
-** All terms of the ORDER BY clause must be either ASC or DESC. The
-** *pbRev value is set to 1 if the ORDER BY clause is all DESC and it is
-** set to 0 if the ORDER BY clause is all ASC.
+** All terms of the ORDER BY that match against the index must be either
+** ASC or DESC. (Terms of the ORDER BY clause past the end of a UNIQUE
+** index do not need to satisfy this constraint.) The *pbRev value is
+** set to 1 if the ORDER BY clause is all DESC and it is set to 0 if
+** the ORDER BY clause is all ASC.
*/
-static Index *findSortingIndex(
- Parse *pParse,
+static int isSortingIndex(
+ Parse *pParse, /* Parsing context */
+ Index *pIdx, /* The index we are testing */
Table *pTab, /* The table to be sorted */
int base, /* Cursor number for pTab */
ExprList *pOrderBy, /* The ORDER BY clause */
- Index *pPreferredIdx, /* Use this index, if possible and not NULL */
- int nEqCol, /* Number of index columns used with == constraints */
+ int nEqCol, /* Number of index columns with == constraints */
int *pbRev /* Set to 1 if ORDER BY is DESC */
){
- int i, j;
- Index *pMatch;
- Index *pIdx;
- int sortOrder;
+ int i, j; /* Loop counters */
+ int sortOrder; /* Which direction we are sorting */
+ int nTerm; /* Number of ORDER BY terms */
+ struct ExprList_item *pTerm; /* A term of the ORDER BY clause */
sqlite3 *db = pParse->db;
assert( pOrderBy!=0 );
- assert( pOrderBy->nExpr>0 );
- sortOrder = pOrderBy->a[0].sortOrder;
- for(i=0; i<pOrderBy->nExpr; i++){
- Expr *p;
- if( pOrderBy->a[i].sortOrder!=sortOrder ){
- /* Indices can only be used if all ORDER BY terms are either
- ** DESC or ASC. Indices cannot be used on a mixture. */
- return 0;
- }
- p = pOrderBy->a[i].pExpr;
- if( p->op!=TK_COLUMN || p->iTable!=base ){
+ nTerm = pOrderBy->nExpr;
+ assert( nTerm>0 );
+
+ /* Match terms of the ORDER BY clause against columns of
+ ** the index.
+ */
+ for(i=j=0, pTerm=pOrderBy->a; j<nTerm && i<pIdx->nColumn; i++){
+ Expr *pExpr; /* The expression of the ORDER BY pTerm */
+ CollSeq *pColl; /* The collating sequence of pExpr */
+
+ pExpr = pTerm->pExpr;
+ if( pExpr->op!=TK_COLUMN || pExpr->iTable!=base ){
/* Can not use an index sort on anything that is not a column in the
** left-most table of the FROM clause */
return 0;
}
- }
-
- /* If we get this far, it means the ORDER BY clause consists only of
- ** ascending columns in the left-most table of the FROM clause. Now
- ** check for a matching index.
- */
- pMatch = 0;
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- int nExpr = pOrderBy->nExpr;
- if( pIdx->nColumn < nEqCol || pIdx->nColumn < nExpr ) continue;
- for(i=j=0; i<nEqCol; i++){
- CollSeq *pColl = sqlite3ExprCollSeq(pParse, pOrderBy->a[j].pExpr);
- if( !pColl ) pColl = db->pDfltColl;
- if( pPreferredIdx->aiColumn[i]!=pIdx->aiColumn[i] ) break;
- if( pPreferredIdx->keyInfo.aColl[i]!=pIdx->keyInfo.aColl[i] ) break;
- if( j<nExpr &&
- pOrderBy->a[j].pExpr->iColumn==pIdx->aiColumn[i] &&
- pColl==pIdx->keyInfo.aColl[i]
- ){
- j++;
+ pColl = sqlite3ExprCollSeq(pParse, pExpr);
+ if( !pColl ) pColl = db->pDfltColl;
+ if( pExpr->iColumn!=pIdx->aiColumn[i] || pColl!=pIdx->keyInfo.aColl[i] ){
+ /* Term j of the ORDER BY clause does not match column i of the index */
+ if( i<nEqCol ){
+ /* If an index column that is constrained by == fails to match an
+ ** ORDER BY term, that is OK. Just ignore that column of the index
+ */
+ continue;
+ }else{
+ /* If an index column fails to match and is not constrained by ==
+ ** then the index cannot satisfy the ORDER BY constraint.
+ */
+ return 0;
}
}
- if( i<nEqCol ) continue;
- for(i=0; i+j<nExpr; i++){
- CollSeq *pColl = sqlite3ExprCollSeq(pParse, pOrderBy->a[i+j].pExpr);
- if( !pColl ) pColl = db->pDfltColl;
- if( pOrderBy->a[i+j].pExpr->iColumn!=pIdx->aiColumn[i+nEqCol] ||
- pColl!=pIdx->keyInfo.aColl[i+nEqCol] ) break;
- }
- if( i+j>=nExpr ){
- pMatch = pIdx;
- if( pIdx==pPreferredIdx ) break;
+ if( i>nEqCol ){
+ if( pTerm->sortOrder!=sortOrder ){
+ /* Indices can only be used if all ORDER BY terms past the
+ ** equality constraints are all either DESC or ASC. */
+ return 0;
+ }
+ }else{
+ sortOrder = pTerm->sortOrder;
}
+ j++;
+ pTerm++;
}
- if( pMatch && pbRev ){
+
+ /* The index can be used for sorting if all terms of the ORDER BY clause
+ ** or covered or if we ran out of index columns and the it is a UNIQUE
+ ** index.
+ */
+ if( j>=nTerm || (i>=pIdx->nColumn && pIdx->onError!=OE_None) ){
*pbRev = sortOrder==SQLITE_SO_DESC;
+ return 1;
+ }
+ return 0;
+}
+
+/*
+** Check table to see if the ORDER BY clause in pOrderBy can be satisfied
+** by sorting in order of ROWID. Return true if so and set *pbRev to be
+** true for reverse ROWID and false for forward ROWID order.
+*/
+static int sortableByRowid(
+ int base, /* Cursor number for table to be sorted */
+ ExprList *pOrderBy, /* The ORDER BY clause */
+ int *pbRev /* Set to 1 if ORDER BY is DESC */
+){
+ Expr *p;
+
+ assert( pOrderBy!=0 );
+ assert( pOrderBy->nExpr>0 );
+ p = pOrderBy->a[0].pExpr;
+ if( p->op==TK_COLUMN && p->iTable==base && p->iColumn==-1 ){
+ *pbRev = pOrderBy->a[0].sortOrder;
+ return 1;
}
- return pMatch;
+ return 0;
}
+
/*
** Disable a term in the WHERE clause. Except, do not disable the term
** if it controls a LEFT OUTER JOIN and it did not originate in the ON
@@ -331,7 +438,7 @@ static Index *findSortingIndex(
** (2) SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x AND t2.z='ok'
** (3) SELECT * FROM t1, t2 WHERE t1.a=t2.x AND t2.z='ok'
**
-** The t2.z='ok' is disabled in the in (2) because it did not originate
+** The t2.z='ok' is disabled in the in (2) because it originates
** in the ON clause. The term is disabled in (3) because it is not part
** of a LEFT OUTER JOIN. In (1), the term is not disabled.
**
@@ -382,22 +489,33 @@ static void codeEqualityTerm(
if( pX->op!=TK_IN ){
assert( pX->op==TK_EQ );
sqlite3ExprCode(pParse, pX->pRight);
+#ifndef SQLITE_OMIT_SUBQUERY
}else{
- int iTab = pX->iTable;
+ int iTab;
Vdbe *v = pParse->pVdbe;
+
+ sqlite3CodeSubselect(pParse, pX);
+ iTab = pX->iTable;
sqlite3VdbeAddOp(v, OP_Rewind, iTab, brk);
sqlite3VdbeAddOp(v, OP_KeyAsData, iTab, 1);
- pLevel->inP2 = sqlite3VdbeAddOp(v, OP_IdxColumn, iTab, 0);
+ VdbeComment((v, "# %.*s", pX->span.n, pX->span.z));
+ pLevel->inP2 = sqlite3VdbeAddOp(v, OP_Column, iTab, 0);
pLevel->inOp = OP_Next;
pLevel->inP1 = iTab;
+#endif
}
disableTerm(pLevel, &pTerm->p);
}
+/*
+** The number of bits in a Bitmask
+*/
+#define BMS (sizeof(Bitmask)*8-1)
+
/*
** Generate the beginning of the loop used for WHERE clause processing.
-** The return value is a pointer to an (opaque) structure that contains
+** The return value is a pointer to an opaque structure that contains
** information needed to terminate the loop. Later, the calling routine
** should invoke sqlite3WhereEnd() with the return value of this function
** in order to complete the WHERE clause processing.
@@ -426,6 +544,11 @@ static void codeEqualityTerm(
** And so forth. This routine generates code to open those VDBE cursors
** and sqlite3WhereEnd() generates the code to close them.
**
+** The code that sqlite3WhereBegin() generates leaves the cursors named
+** in pTabList pointing at their appropriate entries. The [...] code
+** can use OP_Column and OP_Recno opcodes on these cursors to extract
+** data from the various tables of the loop.
+**
** If the WHERE clause is empty, the foreach loops must each scan their
** entire tables. Thus a three-way join is an O(N^3) operation. But if
** the tables have indices and there are terms in the WHERE clause that
@@ -473,30 +596,35 @@ static void codeEqualityTerm(
** output order, then the *ppOrderBy is unchanged.
*/
WhereInfo *sqlite3WhereBegin(
- Parse *pParse, /* The parser context */
- SrcList *pTabList, /* A list of all tables to be scanned */
- Expr *pWhere, /* The WHERE clause */
- int pushKey, /* If TRUE, leave the table key on the stack */
- ExprList **ppOrderBy /* An ORDER BY clause, or NULL */
+ Parse *pParse, /* The parser context */
+ SrcList *pTabList, /* A list of all tables to be scanned */
+ Expr *pWhere, /* The WHERE clause */
+ ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */
+ Fetch *pFetch /* Initial location of cursors. NULL otherwise */
){
int i; /* Loop counter */
WhereInfo *pWInfo; /* Will become the return value of this function */
Vdbe *v = pParse->pVdbe; /* The virtual database engine */
int brk, cont = 0; /* Addresses used during code generation */
int nExpr; /* Number of subexpressions in the WHERE clause */
- int loopMask; /* One bit set for each outer loop */
- int haveKey = 0; /* True if KEY is on the stack */
+ Bitmask loopMask; /* One bit set for each outer loop */
ExprInfo *pTerm; /* A single term in the WHERE clause; ptr to aExpr[] */
ExprMaskSet maskSet; /* The expression mask set */
- int iDirectEq[32]; /* Term of the form ROWID==X for the N-th table */
- int iDirectLt[32]; /* Term of the form ROWID<X or ROWID<=X */
- int iDirectGt[32]; /* Term of the form ROWID>X or ROWID>=X */
+ int iDirectEq[BMS]; /* Term of the form ROWID==X for the N-th table */
+ int iDirectLt[BMS]; /* Term of the form ROWID<X or ROWID<=X */
+ int iDirectGt[BMS]; /* Term of the form ROWID>X or ROWID>=X */
ExprInfo aExpr[101]; /* The WHERE clause is divided into these terms */
+ struct SrcList_item *pTabItem; /* A single entry from pTabList */
+ WhereLevel *pLevel; /* A single level in the pWInfo list */
- /* pushKey is only allowed if there is a single table (as in an INSERT or
- ** UPDATE statement)
+ /* The number of terms in the FROM clause is limited by the number of
+ ** bits in a Bitmask
*/
- assert( pushKey==0 || pTabList->nSrc==1 );
+ if( pTabList->nSrc>sizeof(Bitmask)*8 ){
+ sqlite3ErrorMsg(pParse, "at most %d tables in a join",
+ sizeof(Bitmask)*8);
+ return 0;
+ }
/* Split the WHERE clause into separate subexpressions where each
** subexpression is separated by an AND operator. If the aExpr[]
@@ -511,7 +639,7 @@ WhereInfo *sqlite3WhereBegin(
"than %d terms allowed", (int)ARRAYSIZE(aExpr)-1);
return 0;
}
-
+
/* Allocate and initialize the WhereInfo structure that will become the
** return value.
*/
@@ -534,28 +662,11 @@ WhereInfo *sqlite3WhereBegin(
/* Analyze all of the subexpressions.
*/
+ for(i=0; i<pTabList->nSrc; i++){
+ createMask(&maskSet, pTabList->a[i].iCursor);
+ }
for(pTerm=aExpr, i=0; i<nExpr; i++, pTerm++){
- TriggerStack *pStack;
exprAnalyze(pTabList, &maskSet, pTerm);
-
- /* If we are executing a trigger body, remove all references to
- ** new.* and old.* tables from the prerequisite masks.
- */
- if( (pStack = pParse->trigStack)!=0 ){
- int x;
- if( (x=pStack->newIdx) >= 0 ){
- int mask = ~getMask(&maskSet, x);
- pTerm->prereqRight &= mask;
- pTerm->prereqLeft &= mask;
- pTerm->prereqAll &= mask;
- }
- if( (x=pStack->oldIdx) >= 0 ){
- int mask = ~getMask(&maskSet, x);
- pTerm->prereqRight &= mask;
- pTerm->prereqLeft &= mask;
- pTerm->prereqAll &= mask;
- }
- }
}
/* Figure out what index to use (if any) for each nested loop.
@@ -575,15 +686,17 @@ WhereInfo *sqlite3WhereBegin(
** to the limit of 32 bits in an integer bitmask.
*/
loopMask = 0;
- for(i=0; i<pTabList->nSrc && i<ARRAYSIZE(iDirectEq); i++){
+ pTabItem = pTabList->a;
+ pLevel = pWInfo->a;
+ for(i=0; i<pTabList->nSrc && i<ARRAYSIZE(iDirectEq); i++,pTabItem++,pLevel++){
int j;
- WhereLevel *pLevel = &pWInfo->a[i];
- int iCur = pTabList->a[i].iCursor; /* The cursor for this table */
- int mask = getMask(&maskSet, iCur); /* Cursor mask for this table */
- Table *pTab = pTabList->a[i].pTab;
+ int iCur = pTabItem->iCursor; /* The cursor for this table */
+ Bitmask mask = getMask(&maskSet, iCur); /* Cursor mask for this table */
+ Table *pTab = pTabItem->pTab;
Index *pIdx;
Index *pBestIdx = 0;
int bestScore = 0;
+ int bestRev = 0;
/* Check to see if there is an expression that uses only the
** ROWID field of this table. For terms of the form ROWID==expr
@@ -593,7 +706,7 @@ WhereInfo *sqlite3WhereBegin(
**
** (Added:) Treat ROWID IN expr like ROWID=expr.
*/
- pLevel->iCur = -1;
+ pLevel->iIdxCur = -1;
iDirectEq[i] = -1;
iDirectLt[i] = -1;
iDirectGt[i] = -1;
@@ -611,6 +724,12 @@ WhereInfo *sqlite3WhereBegin(
}
}
}
+
+ /* If we found a term that tests ROWID with == or IN, that term
+ ** will be used to locate the rows in the database table. There
+ ** is not need to continue into the code below that looks for
+ ** an index. We will always use the ROWID over an index.
+ */
if( iDirectEq[i]>=0 ){
loopMask |= mask;
pLevel->pIdx = 0;
@@ -621,19 +740,28 @@ WhereInfo *sqlite3WhereBegin(
** the "best" index. pBestIdx is left set to NULL if no indices
** are usable.
**
- ** The best index is determined as follows. For each of the
+ ** The best index is the one with the highest score. The score
+ ** for the index is determined as follows. For each of the
** left-most terms that is fixed by an equality operator, add
- ** 8 to the score. The right-most term of the index may be
- ** constrained by an inequality. Add 1 if for an "x<..." constraint
- ** and add 2 for an "x>..." constraint. Chose the index that
- ** gives the best score.
+ ** 32 to the score. The right-most term of the index may be
+ ** constrained by an inequality. Add 4 if for an "x<..." constraint
+ ** and add 8 for an "x>..." constraint. If both constraints
+ ** are present, add 12.
+ **
+ ** If the left-most term of the index uses an IN operator
+ ** (ex: "x IN (...)") then add 16 to the score.
+ **
+ ** If an index can be used for sorting, add 2 to the score.
+ ** If an index contains all the terms of a table that are ever
+ ** used by any expression in the SQL statement, then add 1 to
+ ** the score.
**
** This scoring system is designed so that the score can later be
- ** used to determine how the index is used. If the score&7 is 0
- ** then all constraints are equalities. If score&1 is not 0 then
+ ** used to determine how the index is used. If the score&0x1c is 0
+ ** then all constraints are equalities. If score&0x4 is not 0 then
** there is an inequality used as a termination key. (ex: "x<...")
- ** If score&2 is not 0 then there is an inequality used as the
- ** start key. (ex: "x>..."). A score or 4 is the special case
+ ** If score&0x8 is not 0 then there is an inequality used as the
+ ** start key. (ex: "x>..."). A score or 0x10 is the special case
** of an IN operator constraint. (ex: "x IN ...").
**
** The IN operator (as in "<expr> IN (...)") is treated the same as
@@ -643,13 +771,16 @@ WhereInfo *sqlite3WhereBegin(
** other columns of the index.
*/
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- int eqMask = 0; /* Index columns covered by an x=... term */
- int ltMask = 0; /* Index columns covered by an x<... term */
- int gtMask = 0; /* Index columns covered by an x>... term */
- int inMask = 0; /* Index columns covered by an x IN .. term */
- int nEq, m, score;
+ Bitmask eqMask = 0; /* Index columns covered by an x=... term */
+ Bitmask ltMask = 0; /* Index columns covered by an x<... term */
+ Bitmask gtMask = 0; /* Index columns covered by an x>... term */
+ Bitmask inMask = 0; /* Index columns covered by an x IN .. term */
+ Bitmask m;
+ int nEq, score, bRev = 0;
- if( pIdx->nColumn>32 ) continue; /* Ignore indices too many columns */
+ if( pIdx->nColumn>sizeof(eqMask)*8 ){
+ continue; /* Ignore indices with too many columns to analyze */
+ }
for(pTerm=aExpr, j=0; j<nExpr; j++, pTerm++){
Expr *pX = pTerm->p;
CollSeq *pColl = sqlite3ExprCollSeq(pParse, pX->pLeft);
@@ -676,17 +807,17 @@ WhereInfo *sqlite3WhereBegin(
break;
}
case TK_EQ: {
- eqMask |= 1<<k;
+ eqMask |= ((Bitmask)1)<<k;
break;
}
case TK_LE:
case TK_LT: {
- ltMask |= 1<<k;
+ ltMask |= ((Bitmask)1)<<k;
break;
}
case TK_GE:
case TK_GT: {
- gtMask |= 1<<k;
+ gtMask |= ((Bitmask)1)<<k;
break;
}
default: {
@@ -705,25 +836,58 @@ WhereInfo *sqlite3WhereBegin(
** on the left of the index with == constraints.
*/
for(nEq=0; nEq<pIdx->nColumn; nEq++){
- m = (1<<(nEq+1))-1;
+ m = (((Bitmask)1)<<(nEq+1))-1;
if( (m & eqMask)!=m ) break;
}
- score = nEq*8; /* Base score is 8 times number of == constraints */
- m = 1<<nEq;
- if( m & ltMask ) score++; /* Increase score for a < constraint */
- if( m & gtMask ) score+=2; /* Increase score for a > constraint */
- if( score==0 && inMask ) score = 4; /* Default score for IN constraint */
+
+ /* Begin assemblying the score
+ */
+ score = nEq*32; /* Base score is 32 times number of == constraints */
+ m = ((Bitmask)1)<<nEq;
+ if( m & ltMask ) score+=4; /* Increase score for a < constraint */
+ if( m & gtMask ) score+=8; /* Increase score for a > constraint */
+ if( score==0 && inMask ) score = 16; /* Default score for IN constraint */
+
+ /* Give bonus points if this index can be used for sorting
+ */
+ if( i==0 && score!=16 && ppOrderBy && *ppOrderBy ){
+ int base = pTabList->a[0].iCursor;
+ if( isSortingIndex(pParse, pIdx, pTab, base, *ppOrderBy, nEq, &bRev) ){
+ score += 2;
+ }
+ }
+
+ /* Check to see if we can get away with using just the index without
+ ** ever reading the table. If that is the case, then add one bonus
+ ** point to the score.
+ */
+ if( score && pTabItem->colUsed < (((Bitmask)1)<<(BMS-1)) ){
+ for(m=0, j=0; j<pIdx->nColumn; j++){
+ int x = pIdx->aiColumn[j];
+ if( x<BMS-1 ){
+ m |= ((Bitmask)1)<<x;
+ }
+ }
+ if( (pTabItem->colUsed & m)==pTabItem->colUsed ){
+ score++;
+ }
+ }
+
+ /* If the score for this index is the best we have seen so far, then
+ ** save it
+ */
if( score>bestScore ){
pBestIdx = pIdx;
bestScore = score;
+ bestRev = bRev;
}
}
pLevel->pIdx = pBestIdx;
pLevel->score = bestScore;
- pLevel->bRev = 0;
+ pLevel->bRev = bestRev;
loopMask |= mask;
if( pBestIdx ){
- pLevel->iCur = pParse->nTab++;
+ pLevel->iIdxCur = pParse->nTab++;
}
}
@@ -731,65 +895,88 @@ WhereInfo *sqlite3WhereBegin(
** use of an index on the first table.
*/
if( ppOrderBy && *ppOrderBy && pTabList->nSrc>0 ){
- Index *pSortIdx;
- Index *pIdx;
- Table *pTab;
- int bRev = 0;
-
- pTab = pTabList->a[0].pTab;
- pIdx = pWInfo->a[0].pIdx;
- if( pIdx && pWInfo->a[0].score==4 ){
- /* If there is already an IN index on the left-most table,
- ** it will not give the correct sort order.
- ** So, pretend that no suitable index is found.
- */
- pSortIdx = 0;
- }else if( iDirectEq[0]>=0 || iDirectLt[0]>=0 || iDirectGt[0]>=0 ){
- /* If the left-most column is accessed using its ROWID, then do
- ** not try to sort by index.
- */
- pSortIdx = 0;
- }else{
- int nEqCol = (pWInfo->a[0].score+4)/8;
- pSortIdx = findSortingIndex(pParse, pTab, pTabList->a[0].iCursor,
- *ppOrderBy, pIdx, nEqCol, &bRev);
- }
- if( pSortIdx && (pIdx==0 || pIdx==pSortIdx) ){
- if( pIdx==0 ){
- pWInfo->a[0].pIdx = pSortIdx;
- pWInfo->a[0].iCur = pParse->nTab++;
- }
- pWInfo->a[0].bRev = bRev;
- *ppOrderBy = 0;
- }
+ Index *pIdx; /* Index derived from the WHERE clause */
+ Table *pTab; /* Left-most table in the FROM clause */
+ int bRev = 0; /* True to reverse the output order */
+ int iCur; /* Btree-cursor that will be used by pTab */
+ WhereLevel *pLevel0 = &pWInfo->a[0];
+
+ pTab = pTabList->a[0].pTab;
+ pIdx = pLevel0->pIdx;
+ iCur = pTabList->a[0].iCursor;
+ if( pIdx==0 && sortableByRowid(iCur, *ppOrderBy, &bRev) ){
+ /* The ORDER BY clause specifies ROWID order, which is what we
+ ** were going to be doing anyway...
+ */
+ *ppOrderBy = 0;
+ pLevel0->bRev = bRev;
+ }else if( pLevel0->score==16 ){
+ /* If there is already an IN index on the left-most table,
+ ** it will not give the correct sort order.
+ ** So, pretend that no suitable index is found.
+ */
+ }else if( iDirectEq[0]>=0 || iDirectLt[0]>=0 || iDirectGt[0]>=0 ){
+ /* If the left-most column is accessed using its ROWID, then do
+ ** not try to sort by index. But do delete the ORDER BY clause
+ ** if it is redundant.
+ */
+ }else if( (pLevel0->score&2)!=0 ){
+ /* The index that was selected for searching will cause rows to
+ ** appear in sorted order.
+ */
+ *ppOrderBy = 0;
+ }
}
- /* Open all tables in the pTabList and all indices used by those tables.
+ /* Open all tables in the pTabList and any indices selected for
+ ** searching those tables.
*/
sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
- for(i=0; i<pTabList->nSrc; i++){
+ pLevel = pWInfo->a;
+ for(i=0, pTabItem=pTabList->a; i<pTabList->nSrc; i++, pTabItem++, pLevel++){
Table *pTab;
Index *pIx;
+ int iIdxCur = pLevel->iIdxCur;
- pTab = pTabList->a[i].pTab;
+ pTab = pTabItem->pTab;
if( pTab->isTransient || pTab->pSelect ) continue;
- sqlite3OpenTableForReading(v, pTabList->a[i].iCursor, pTab);
- sqlite3CodeVerifySchema(pParse, pTab->iDb);
- if( (pIx = pWInfo->a[i].pIdx)!=0 ){
+ if( (pLevel->score & 1)==0 ){
+ sqlite3OpenTableForReading(v, pTabItem->iCursor, pTab);
+ }
+ pLevel->iTabCur = pTabItem->iCursor;
+ if( (pIx = pLevel->pIdx)!=0 ){
sqlite3VdbeAddOp(v, OP_Integer, pIx->iDb, 0);
- sqlite3VdbeOp3(v, OP_OpenRead, pWInfo->a[i].iCur, pIx->tnum,
+ sqlite3VdbeOp3(v, OP_OpenRead, iIdxCur, pIx->tnum,
(char*)&pIx->keyInfo, P3_KEYINFO);
}
+ if( (pLevel->score & 1)!=0 ){
+ sqlite3VdbeAddOp(v, OP_KeyAsData, iIdxCur, 1);
+ sqlite3VdbeAddOp(v, OP_SetNumColumns, iIdxCur, pIx->nColumn+1);
+ }
+ sqlite3CodeVerifySchema(pParse, pTab->iDb);
}
+ pWInfo->iTop = sqlite3VdbeCurrentAddr(v);
/* Generate the code to do the search
*/
loopMask = 0;
- for(i=0; i<pTabList->nSrc; i++){
+ pLevel = pWInfo->a;
+ pTabItem = pTabList->a;
+ for(i=0; i<pTabList->nSrc; i++, pTabItem++, pLevel++){
int j, k;
- int iCur = pTabList->a[i].iCursor;
- Index *pIdx;
- WhereLevel *pLevel = &pWInfo->a[i];
+ int iCur = pTabItem->iCursor; /* The VDBE cursor for the table */
+ Index *pIdx; /* The index we will be using */
+ int iIdxCur; /* The VDBE cursor for the index */
+ int omitTable; /* True if we use the index only */
+
+ pIdx = pLevel->pIdx;
+ iIdxCur = pLevel->iIdxCur;
+ pLevel->inOp = OP_Noop;
+
+ /* Check to see if it is appropriate to omit the use of the table
+ ** here and use its index instead.
+ */
+ omitTable = (pLevel->score&1)!=0;
/* If this is the right table of a LEFT OUTER JOIN, allocate and
** initialize a memory cell that records if this table matches any
@@ -803,8 +990,6 @@ WhereInfo *sqlite3WhereBegin(
VdbeComment((v, "# init LEFT JOIN no-match flag"));
}
- pIdx = pLevel->pIdx;
- pLevel->inOp = OP_Noop;
if( i<ARRAYSIZE(iDirectEq) && (k = iDirectEq[i])>=0 ){
/* Case 1: We can directly reference a single row using an
** equality comparison against the ROWID field. Or
@@ -815,19 +1000,20 @@ WhereInfo *sqlite3WhereBegin(
pTerm = &aExpr[k];
assert( pTerm->p!=0 );
assert( pTerm->idxLeft==iCur );
+ assert( omitTable==0 );
brk = pLevel->brk = sqlite3VdbeMakeLabel(v);
codeEqualityTerm(pParse, pTerm, brk, pLevel);
cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
sqlite3VdbeAddOp(v, OP_MustBeInt, 1, brk);
- haveKey = 0;
sqlite3VdbeAddOp(v, OP_NotExists, iCur, brk);
+ VdbeComment((v, "pk"));
pLevel->op = OP_Noop;
- }else if( pIdx!=0 && pLevel->score>0 && pLevel->score%4==0 ){
+ }else if( pIdx!=0 && pLevel->score>3 && (pLevel->score&0x0c)==0 ){
/* Case 2: There is an index and all terms of the WHERE clause that
- ** refer to the index use the "==" or "IN" operators.
+ ** refer to the index using the "==" or "IN" operators.
*/
int start;
- int nColumn = (pLevel->score+4)/8;
+ int nColumn = (pLevel->score+16)/32;
brk = pLevel->brk = sqlite3VdbeMakeLabel(v);
/* For each column of the index, find the term of the WHERE clause that
@@ -840,6 +1026,7 @@ WhereInfo *sqlite3WhereBegin(
if( pTerm->idxLeft==iCur
&& (pTerm->prereqRight & loopMask)==pTerm->prereqRight
&& pX->pLeft->iColumn==pIdx->aiColumn[j]
+ && (pX->op==TK_EQ || pX->op==TK_IN)
){
char idxaff = pIdx->pTable->aCol[pX->pLeft->iColumn].affinity;
if( sqlite3IndexAffinityOk(pX, idxaff) ){
@@ -861,36 +1048,40 @@ WhereInfo *sqlite3WhereBegin(
** iteration of the scan to see if the scan has finished. */
if( pLevel->bRev ){
/* Scan in reverse order */
- sqlite3VdbeAddOp(v, OP_MoveLe, pLevel->iCur, brk);
+ sqlite3VdbeAddOp(v, OP_MoveLe, iIdxCur, brk);
start = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
- sqlite3VdbeAddOp(v, OP_IdxLT, pLevel->iCur, brk);
+ sqlite3VdbeAddOp(v, OP_IdxLT, iIdxCur, brk);
pLevel->op = OP_Prev;
}else{
/* Scan in the forward order */
- sqlite3VdbeAddOp(v, OP_MoveGe, pLevel->iCur, brk);
+ sqlite3VdbeAddOp(v, OP_MoveGe, iIdxCur, brk);
start = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
- sqlite3VdbeOp3(v, OP_IdxGE, pLevel->iCur, brk, "+", P3_STATIC);
+ sqlite3VdbeOp3(v, OP_IdxGE, iIdxCur, brk, "+", P3_STATIC);
pLevel->op = OP_Next;
}
- sqlite3VdbeAddOp(v, OP_RowKey, pLevel->iCur, 0);
+ sqlite3VdbeAddOp(v, OP_RowKey, iIdxCur, 0);
sqlite3VdbeAddOp(v, OP_IdxIsNull, nColumn, cont);
- sqlite3VdbeAddOp(v, OP_IdxRecno, pLevel->iCur, 0);
- if( i==pTabList->nSrc-1 && pushKey ){
- haveKey = 1;
- }else{
+ if( !omitTable ){
+ sqlite3VdbeAddOp(v, OP_IdxRecno, iIdxCur, 0);
sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
- haveKey = 0;
}
- pLevel->p1 = pLevel->iCur;
+ pLevel->p1 = iIdxCur;
pLevel->p2 = start;
}else if( i<ARRAYSIZE(iDirectLt) && (iDirectLt[i]>=0 || iDirectGt[i]>=0) ){
/* Case 3: We have an inequality comparison against the ROWID field.
*/
int testOp = OP_Noop;
int start;
+ int bRev = pLevel->bRev;
+ assert( omitTable==0 );
brk = pLevel->brk = sqlite3VdbeMakeLabel(v);
cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
+ if( bRev ){
+ int t = iDirectGt[i];
+ iDirectGt[i] = iDirectLt[i];
+ iDirectLt[i] = t;
+ }
if( iDirectGt[i]>=0 ){
Expr *pX;
k = iDirectGt[i];
@@ -900,11 +1091,12 @@ WhereInfo *sqlite3WhereBegin(
assert( pX!=0 );
assert( pTerm->idxLeft==iCur );
sqlite3ExprCode(pParse, pX->pRight);
- sqlite3VdbeAddOp(v, OP_ForceInt, pX->op==TK_LT || pX->op==TK_GT, brk);
- sqlite3VdbeAddOp(v, OP_MoveGe, iCur, brk);
+ sqlite3VdbeAddOp(v, OP_ForceInt, pX->op==TK_LE || pX->op==TK_GT, brk);
+ sqlite3VdbeAddOp(v, bRev ? OP_MoveLt : OP_MoveGe, iCur, brk);
+ VdbeComment((v, "pk"));
disableTerm(pLevel, &pTerm->p);
}else{
- sqlite3VdbeAddOp(v, OP_Rewind, iCur, brk);
+ sqlite3VdbeAddOp(v, bRev ? OP_Last : OP_Rewind, iCur, brk);
}
if( iDirectLt[i]>=0 ){
Expr *pX;
@@ -918,14 +1110,14 @@ WhereInfo *sqlite3WhereBegin(
pLevel->iMem = pParse->nMem++;
sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
if( pX->op==TK_LT || pX->op==TK_GT ){
- testOp = OP_Ge;
+ testOp = bRev ? OP_Le : OP_Ge;
}else{
- testOp = OP_Gt;
+ testOp = bRev ? OP_Lt : OP_Gt;
}
disableTerm(pLevel, &pTerm->p);
}
start = sqlite3VdbeCurrentAddr(v);
- pLevel->op = OP_Next;
+ pLevel->op = bRev ? OP_Prev : OP_Next;
pLevel->p1 = iCur;
pLevel->p2 = start;
if( testOp!=OP_Noop ){
@@ -933,21 +1125,27 @@ WhereInfo *sqlite3WhereBegin(
sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
sqlite3VdbeAddOp(v, testOp, 0, brk);
}
- haveKey = 0;
}else if( pIdx==0 ){
/* Case 4: There is no usable index. We must do a complete
** scan of the entire database table.
*/
int start;
+ int opRewind;
+ assert( omitTable==0 );
brk = pLevel->brk = sqlite3VdbeMakeLabel(v);
cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
- sqlite3VdbeAddOp(v, OP_Rewind, iCur, brk);
+ if( pLevel->bRev ){
+ opRewind = OP_Last;
+ pLevel->op = OP_Prev;
+ }else{
+ opRewind = OP_Rewind;
+ pLevel->op = OP_Next;
+ }
+ sqlite3VdbeAddOp(v, opRewind, iCur, brk);
start = sqlite3VdbeCurrentAddr(v);
- pLevel->op = OP_Next;
pLevel->p1 = iCur;
pLevel->p2 = start;
- haveKey = 0;
}else{
/* Case 5: The WHERE clause term that refers to the right-most
** column of the index is an inequality. For example, if
@@ -961,7 +1159,7 @@ WhereInfo *sqlite3WhereBegin(
** to force the output order to conform to an ORDER BY.
*/
int score = pLevel->score;
- int nEqColumn = score/8;
+ int nEqColumn = score/32;
int start;
int leFlag=0, geFlag=0;
int testOp;
@@ -1005,7 +1203,7 @@ WhereInfo *sqlite3WhereBegin(
** 2002-Dec-04: On a reverse-order scan, the so-called "termination"
** key computed here really ends up being the start key.
*/
- if( (score & 1)!=0 ){
+ if( (score & 4)!=0 ){
for(pTerm=aExpr, k=0; k<nExpr; k++, pTerm++){
Expr *pX = pTerm->p;
if( pX==0 ) continue;
@@ -1026,17 +1224,17 @@ WhereInfo *sqlite3WhereBegin(
leFlag = 1;
}
if( testOp!=OP_Noop ){
- int nCol = nEqColumn + (score & 1);
+ int nCol = nEqColumn + ((score & 4)!=0);
pLevel->iMem = pParse->nMem++;
buildIndexProbe(v, nCol, brk, pIdx);
if( pLevel->bRev ){
int op = leFlag ? OP_MoveLe : OP_MoveLt;
- sqlite3VdbeAddOp(v, op, pLevel->iCur, brk);
+ sqlite3VdbeAddOp(v, op, iIdxCur, brk);
}else{
sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
}
}else if( pLevel->bRev ){
- sqlite3VdbeAddOp(v, OP_Last, pLevel->iCur, brk);
+ sqlite3VdbeAddOp(v, OP_Last, iIdxCur, brk);
}
/* Generate the start key. This is the key that defines the lower
@@ -1048,7 +1246,7 @@ WhereInfo *sqlite3WhereBegin(
** 2002-Dec-04: In the case of a reverse-order search, the so-called
** "start" key really ends up being used as the termination key.
*/
- if( (score & 2)!=0 ){
+ if( (score & 8)!=0 ){
for(pTerm=aExpr, k=0; k<nExpr; k++, pTerm++){
Expr *pX = pTerm->p;
if( pX==0 ) continue;
@@ -1066,8 +1264,8 @@ WhereInfo *sqlite3WhereBegin(
}else{
geFlag = 1;
}
- if( nEqColumn>0 || (score&2)!=0 ){
- int nCol = nEqColumn + ((score&2)!=0);
+ if( nEqColumn>0 || (score&8)!=0 ){
+ int nCol = nEqColumn + ((score&8)!=0);
buildIndexProbe(v, nCol, brk, pIdx);
if( pLevel->bRev ){
pLevel->iMem = pParse->nMem++;
@@ -1075,12 +1273,12 @@ WhereInfo *sqlite3WhereBegin(
testOp = OP_IdxLT;
}else{
int op = geFlag ? OP_MoveGe : OP_MoveGt;
- sqlite3VdbeAddOp(v, op, pLevel->iCur, brk);
+ sqlite3VdbeAddOp(v, op, iIdxCur, brk);
}
}else if( pLevel->bRev ){
testOp = OP_Noop;
}else{
- sqlite3VdbeAddOp(v, OP_Rewind, pLevel->iCur, brk);
+ sqlite3VdbeAddOp(v, OP_Rewind, iIdxCur, brk);
}
/* Generate the the top of the loop. If there is a termination
@@ -1090,25 +1288,22 @@ WhereInfo *sqlite3WhereBegin(
start = sqlite3VdbeCurrentAddr(v);
if( testOp!=OP_Noop ){
sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
- sqlite3VdbeAddOp(v, testOp, pLevel->iCur, brk);
+ sqlite3VdbeAddOp(v, testOp, iIdxCur, brk);
if( (leFlag && !pLevel->bRev) || (!geFlag && pLevel->bRev) ){
sqlite3VdbeChangeP3(v, -1, "+", P3_STATIC);
}
}
- sqlite3VdbeAddOp(v, OP_RowKey, pLevel->iCur, 0);
- sqlite3VdbeAddOp(v, OP_IdxIsNull, nEqColumn + (score & 1), cont);
- sqlite3VdbeAddOp(v, OP_IdxRecno, pLevel->iCur, 0);
- if( i==pTabList->nSrc-1 && pushKey ){
- haveKey = 1;
- }else{
+ sqlite3VdbeAddOp(v, OP_RowKey, iIdxCur, 0);
+ sqlite3VdbeAddOp(v, OP_IdxIsNull, nEqColumn + ((score&4)!=0), cont);
+ if( !omitTable ){
+ sqlite3VdbeAddOp(v, OP_IdxRecno, iIdxCur, 0);
sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
- haveKey = 0;
}
/* Record the instruction used to terminate the loop.
*/
pLevel->op = pLevel->bRev ? OP_Prev : OP_Next;
- pLevel->p1 = pLevel->iCur;
+ pLevel->p1 = iIdxCur;
pLevel->p2 = start;
}
loopMask |= getMask(&maskSet, iCur);
@@ -1122,10 +1317,6 @@ WhereInfo *sqlite3WhereBegin(
if( pLevel->iLeftJoin && !ExprHasProperty(pTerm->p,EP_FromJoin) ){
continue;
}
- if( haveKey ){
- haveKey = 0;
- sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
- }
sqlite3ExprIfFalse(pParse, pTerm->p, cont, 1);
pTerm->p = 0;
}
@@ -1142,23 +1333,12 @@ WhereInfo *sqlite3WhereBegin(
for(pTerm=aExpr, j=0; j<nExpr; j++, pTerm++){
if( pTerm->p==0 ) continue;
if( (pTerm->prereqAll & loopMask)!=pTerm->prereqAll ) continue;
- if( haveKey ){
- /* Cannot happen. "haveKey" can only be true if pushKey is true
- ** an pushKey can only be true for DELETE and UPDATE and there are
- ** no outer joins with DELETE and UPDATE.
- */
- haveKey = 0;
- sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
- }
sqlite3ExprIfFalse(pParse, pTerm->p, cont, 1);
pTerm->p = 0;
}
}
}
pWInfo->iContinue = cont;
- if( pushKey && !haveKey ){
- sqlite3VdbeAddOp(v, OP_Recno, pTabList->a[0].iCursor, 0);
- }
freeMaskSet(&maskSet);
return pWInfo;
}
@@ -1172,7 +1352,10 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
int i;
WhereLevel *pLevel;
SrcList *pTabList = pWInfo->pTabList;
+ struct SrcList_item *pTabItem;
+ /* Generate loop termination code.
+ */
for(i=pTabList->nSrc-1; i>=0; i--){
pLevel = &pWInfo->a[i];
sqlite3VdbeResolveLabel(v, pLevel->cont);
@@ -1186,25 +1369,74 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
if( pLevel->iLeftJoin ){
int addr;
addr = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iLeftJoin, 0);
- sqlite3VdbeAddOp(v, OP_NotNull, 1, addr+4 + (pLevel->iCur>=0));
+ sqlite3VdbeAddOp(v, OP_NotNull, 1, addr+4 + (pLevel->iIdxCur>=0));
sqlite3VdbeAddOp(v, OP_NullRow, pTabList->a[i].iCursor, 0);
- if( pLevel->iCur>=0 ){
- sqlite3VdbeAddOp(v, OP_NullRow, pLevel->iCur, 0);
+ if( pLevel->iIdxCur>=0 ){
+ sqlite3VdbeAddOp(v, OP_NullRow, pLevel->iIdxCur, 0);
}
sqlite3VdbeAddOp(v, OP_Goto, 0, pLevel->top);
}
}
+
+ /* The "break" point is here, just past the end of the outer loop.
+ ** Set it.
+ */
sqlite3VdbeResolveLabel(v, pWInfo->iBreak);
- for(i=0; i<pTabList->nSrc; i++){
- Table *pTab = pTabList->a[i].pTab;
+
+ /* Close all of the cursors that were opend by sqlite3WhereBegin.
+ */
+ pLevel = pWInfo->a;
+ pTabItem = pTabList->a;
+ for(i=0; i<pTabList->nSrc; i++, pTabItem++, pLevel++){
+ Table *pTab = pTabItem->pTab;
assert( pTab!=0 );
if( pTab->isTransient || pTab->pSelect ) continue;
- pLevel = &pWInfo->a[i];
- sqlite3VdbeAddOp(v, OP_Close, pTabList->a[i].iCursor, 0);
+ if( (pLevel->score & 1)==0 ){
+ sqlite3VdbeAddOp(v, OP_Close, pTabItem->iCursor, 0);
+ }
if( pLevel->pIdx!=0 ){
- sqlite3VdbeAddOp(v, OP_Close, pLevel->iCur, 0);
+ sqlite3VdbeAddOp(v, OP_Close, pLevel->iIdxCur, 0);
+ }
+
+ /* Make cursor substitutions for cases where we want to use
+ ** just the index and never reference the table.
+ **
+ ** Calls to the code generator in between sqlite3WhereBegin and
+ ** sqlite3WhereEnd will have created code that references the table
+ ** directly. This loop scans all that code looking for opcodes
+ ** that reference the table and converts them into opcodes that
+ ** reference the index.
+ */
+ if( pLevel->score & 1 ){
+ int i, j, last;
+ VdbeOp *pOp;
+ Index *pIdx = pLevel->pIdx;
+
+ assert( pIdx!=0 );
+ pOp = sqlite3VdbeGetOp(v, pWInfo->iTop);
+ last = sqlite3VdbeCurrentAddr(v);
+ for(i=pWInfo->iTop; i<last; i++, pOp++){
+ if( pOp->p1!=pLevel->iTabCur ) continue;
+ if( pOp->opcode==OP_Column ){
+ pOp->p1 = pLevel->iIdxCur;
+ for(j=0; j<pIdx->nColumn; j++){
+ if( pOp->p2==pIdx->aiColumn[j] ){
+ pOp->p2 = j;
+ break;
+ }
+ }
+ }else if( pOp->opcode==OP_Recno ){
+ pOp->p1 = pLevel->iIdxCur;
+ pOp->opcode = OP_IdxRecno;
+ }else if( pOp->opcode==OP_NullRow ){
+ pOp->opcode = OP_Noop;
+ }
+ }
}
}
+
+ /* Final cleanup
+ */
sqliteFree(pWInfo);
return;
}