diff options
Diffstat (limited to 'ext/pdo_sqlite/sqlite/src')
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, ¬Used1); 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; } |