diff --git a/mozilla/db/sqlite3/README.MOZILLA b/mozilla/db/sqlite3/README.MOZILLA index 3310737614d..61cc6287e1b 100644 --- a/mozilla/db/sqlite3/README.MOZILLA +++ b/mozilla/db/sqlite3/README.MOZILLA @@ -1,15 +1,11 @@ -This is sqlite 3.2.7. +This is sqlite 3.3.3 See http://www.sqlite.org/ for more info. We have a mozilla-specific Makefile.in in src/ (normally no Makefile.in there) that we use to build. -There's also a hand-written config.h in src; the only thing -sqlite wants there is SQLITE_PTR_SZ, which we define to be -PR_BYTES_PER_WORD. - We only imported the bits that we actually need for the build -- basically, the contents of the src directory, plus autogenerated files (see below). Note that we don't use all the files in the src dir; @@ -23,5 +19,5 @@ sqlite3 windows source .zip, or autoconfiscate and build a tarball and copy them out. Yes, this sucks, but it's better than having to build the parser and all that goop as part of our build. --- Vlad Vukicevic 10/2004 +-- Vlad Vukicevic 02/2006 diff --git a/mozilla/db/sqlite3/sqlite3-param-indexes.patch b/mozilla/db/sqlite3/sqlite3-param-indexes.patch new file mode 100644 index 00000000000..4ea5fa7a620 --- /dev/null +++ b/mozilla/db/sqlite3/sqlite3-param-indexes.patch @@ -0,0 +1,80 @@ +diff -ru orig/sqlite333/sqlite3.h sqlite333/sqlite3.h +--- orig/sqlite333/sqlite3.h 2006-01-31 08:23:57.000000000 -0800 ++++ sqlite333/sqlite3.h 2006-02-08 12:12:42.156250000 -0800 +@@ -1377,6 +1377,20 @@ + # undef double + #endif + ++/* ++** Given a wildcard parameter name, return the set of indexes of the ++** variables with that name. If there are no variables with the given ++** name, return 0. Otherwise, return the number of indexes returned ++** in *pIndexes. The array should be freed with ++** sqlite3_free_parameter_indexes. ++*/ ++int sqlite3_bind_parameter_indexes( ++ sqlite3_stmt *pStmt, ++ const char *zName, ++ int **pIndexes ++); ++void sqlite3_free_parameter_indexes(int *pIndexes); ++ + #ifdef __cplusplus + } /* End of the 'extern "C"' block */ + #endif +Only in sqlite333: sqlite3.h~ +diff -ru orig/sqlite333/vdbeapi.c sqlite333/vdbeapi.c +--- orig/sqlite333/vdbeapi.c 2006-01-31 08:23:57.000000000 -0800 ++++ sqlite333/vdbeapi.c 2006-02-08 12:13:46.562500000 -0800 +@@ -764,6 +764,50 @@ + } + + /* ++** Given a wildcard parameter name, return the set of indexes of the ++** variables with that name. If there are no variables with the given ++** name, return 0. Otherwise, return the number of indexes returned ++** in *pIndexes. The array should be freed with ++** sqlite3_free_parameter_indexes. ++*/ ++int sqlite3_bind_parameter_indexes( ++ sqlite3_stmt *pStmt, ++ const char *zName, ++ int **pIndexes ++){ ++ Vdbe *p = (Vdbe*)pStmt; ++ int i, j, nVars, *indexes; ++ if( p==0 ){ ++ return 0; ++ } ++ createVarMap(p); ++ if( !zName ) ++ return 0; ++ /* first count */ ++ nVars = 0; ++ for(i=0; inVar; i++){ ++ const char *z = p->azVar[i]; ++ if( z && strcmp(z,zName)==0 ){ ++ nVars++; ++ } ++ } ++ indexes = sqliteMalloc( sizeof(int) * nVars ); ++ j = 0; ++ for(i=0; inVar; i++){ ++ const char *z = p->azVar[i]; ++ if( z && strcmp(z,zName)==0 ) ++ indexes[j++] = i+1; ++ } ++ *pIndexes = indexes; ++ return nVars; ++} ++ ++void sqlite3_free_parameter_indexes(int *pIndexes) ++{ ++ sqliteFree( pIndexes ); ++} ++ ++/* + ** Transfer all bindings from the first statement over to the second. + ** If the two statements contain a different number of bindings, then + ** an SQLITE_ERROR is returned. +Only in sqlite333: vdbeapi.c~ diff --git a/mozilla/db/sqlite3/src/Makefile.in b/mozilla/db/sqlite3/src/Makefile.in index d2825a33f5a..b53481f5f47 100644 --- a/mozilla/db/sqlite3/src/Makefile.in +++ b/mozilla/db/sqlite3/src/Makefile.in @@ -69,6 +69,7 @@ CSRCS = \ legacy.c \ main.c \ opcodes.c \ + os.c \ os_unix.c \ os_win.c \ os_os2.c \ diff --git a/mozilla/db/sqlite3/src/alter.c b/mozilla/db/sqlite3/src/alter.c index d71fd303934..f6d4af52889 100644 --- a/mozilla/db/sqlite3/src/alter.c +++ b/mozilla/db/sqlite3/src/alter.c @@ -12,7 +12,7 @@ ** This file contains C code routines that used to generate VDBE code ** that implements the ALTER TABLE command. ** -** $Id: alter.c,v 1.4 2005-12-13 19:49:35 vladimir%pobox.com Exp $ +** $Id: alter.c,v 1.5 2006-02-08 21:10:09 vladimir%pobox.com Exp $ */ #include "sqliteInt.h" #include @@ -47,7 +47,7 @@ static void renameTableFunc( int token; Token tname; - char const *zCsr = zSql; + unsigned char const *zCsr = zSql; int len = 0; char *zRet; @@ -96,7 +96,7 @@ static void renameTriggerFunc( int token; Token tname; int dist = 3; - char const *zCsr = zSql; + unsigned char const *zCsr = zSql; int len = 0; char *zRet; @@ -162,7 +162,7 @@ void sqlite3AlterFunctions(sqlite3 *db){ int i; for(i=0; iiDb!=1 ){ + const Schema *pTempSchema = pParse->db->aDb[1].pSchema; /* Temp db schema */ + + /* If the table is not located in the temp-db (in which case NULL is + ** returned, loop through the tables list of triggers. For each trigger + ** that is not part of the temp-db schema, add a clause to the WHERE + ** expression being built up in zWhere. + */ + if( pTab->pSchema!=pTempSchema ){ for( pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext ){ - if( pTrig->iDb==1 ){ + if( pTrig->pSchema==pTempSchema ){ if( !zWhere ){ zWhere = sqlite3MPrintf("name=%Q", pTrig->name); }else{ @@ -204,20 +211,22 @@ static char *whereTempTriggers(Parse *pParse, Table *pTab){ static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){ Vdbe *v; char *zWhere; - int iDb; + int iDb; /* Index of database containing pTab */ #ifndef SQLITE_OMIT_TRIGGER Trigger *pTrig; #endif v = sqlite3GetVdbe(pParse); if( !v ) return; - iDb = pTab->iDb; + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + assert( iDb>=0 ); #ifndef SQLITE_OMIT_TRIGGER /* Drop any table triggers from the internal schema. */ for(pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext){ - assert( pTrig->iDb==iDb || pTrig->iDb==1 ); - sqlite3VdbeOp3(v, OP_DropTrigger, pTrig->iDb, 0, pTrig->name, 0); + int iTrigDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); + assert( iTrigDb==iDb || iTrigDb==1 ); + sqlite3VdbeOp3(v, OP_DropTrigger, iTrigDb, 0, pTrig->name, 0); } #endif @@ -233,7 +242,7 @@ static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){ /* Now, if the table is not stored in the temp database, reload any temp ** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined. */ - if( (zWhere=whereTempTriggers(pParse, pTab)) ){ + if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){ sqlite3VdbeOp3(v, OP_ParseSchema, 1, 0, zWhere, P3_DYNAMIC); } #endif @@ -258,12 +267,12 @@ void sqlite3AlterRenameTable( char *zWhere = 0; /* Where clause to locate temp triggers */ #endif - if( sqlite3_malloc_failed ) goto exit_rename_table; + if( sqlite3MallocFailed() ) goto exit_rename_table; assert( pSrc->nSrc==1 ); pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase); if( !pTab ) goto exit_rename_table; - iDb = pTab->iDb; + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); zDb = db->aDb[iDb].zName; /* Get a NULL terminated version of the new table name. */ @@ -349,7 +358,7 @@ void sqlite3AlterRenameTable( ** table. Don't do this if the table being ALTERed is itself located in ** the temp database. */ - if( (zWhere=whereTempTriggers(pParse, pTab)) ){ + if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){ sqlite3NestedParse(pParse, "UPDATE sqlite_temp_master SET " "sql = sqlite_rename_trigger(sql, %Q), " @@ -385,13 +394,12 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ char *zCol; /* Null-terminated column definition */ Column *pCol; /* The new column */ Expr *pDflt; /* Default value for the new column */ - Vdbe *v; if( pParse->nErr ) return; pNew = pParse->pNewTable; assert( pNew ); - iDb = pNew->iDb; + iDb = sqlite3SchemaToIndex(pParse->db, pNew->pSchema); zDb = pParse->db->aDb[iDb].zName; zTab = pNew->zName; pCol = &pNew->aCol[pNew->nCol-1]; @@ -399,6 +407,13 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ pTab = sqlite3FindTable(pParse->db, zTab, zDb); assert( pTab ); +#ifndef SQLITE_OMIT_AUTHORIZATION + /* Invoke the authorization callback. */ + if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ + return; + } +#endif + /* If the default value for the new column was specified with a ** literal NULL, then set pDflt to 0. This simplifies checking ** for an SQL NULL default below. @@ -442,7 +457,7 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ } /* Modify the CREATE TABLE statement. */ - zCol = sqliteStrNDup(pColDef->z, pColDef->n); + zCol = sqliteStrNDup((char*)pColDef->z, pColDef->n); if( zCol ){ char *zEnd = &zCol[pColDef->n-1]; while( (zEnd>zCol && *zEnd==';') || isspace(*(unsigned char *)zEnd) ){ @@ -462,22 +477,12 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ ** format to 2. If the default value of the new column is not NULL, ** the file format becomes 3. */ - if( (v=sqlite3GetVdbe(pParse)) ){ - int f = (pDflt?3:2); - - /* Only set the file format to $f if it is currently less than $f. */ - sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 1); - sqlite3VdbeAddOp(v, OP_Integer, f, 0); - sqlite3VdbeAddOp(v, OP_Ge, 0, sqlite3VdbeCurrentAddr(v)+3); - sqlite3VdbeAddOp(v, OP_Integer, f, 0); - sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1); - } + sqlite3MinimumFileFormat(pParse, iDb, pDflt ? 3 : 2); /* Reload the schema of the modified table. */ reloadTableSchema(pParse, pTab, pTab->zName); } - /* ** This function is called by the parser after the table-name in ** an "ALTER TABLE ADD" statement is parsed. Argument @@ -501,10 +506,9 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ int i; int nAlloc; - /* Look up the table being altered. */ assert( pParse->pNewTable==0 ); - if( sqlite3_malloc_failed ) goto exit_begin_add_column; + if( sqlite3MallocFailed() ) goto exit_begin_add_column; pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase); if( !pTab ) goto exit_begin_add_column; @@ -515,7 +519,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ } assert( pTab->addColOffset>0 ); - iDb = pTab->iDb; + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); /* Put a copy of the Table struct in Parse.pNewTable for the ** sqlite3AddColumn() function and friends to modify. @@ -540,7 +544,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ pCol->zType = 0; pCol->pDflt = 0; } - pNew->iDb = iDb; + pNew->pSchema = pParse->db->aDb[iDb].pSchema; pNew->addColOffset = pTab->addColOffset; pNew->nRef = 1; diff --git a/mozilla/db/sqlite3/src/analyze.c b/mozilla/db/sqlite3/src/analyze.c index 09ada04e91c..6d1e3bebd2b 100644 --- a/mozilla/db/sqlite3/src/analyze.c +++ b/mozilla/db/sqlite3/src/analyze.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code associated with the ANALYZE command. ** -** @(#) $Id: analyze.c,v 1.1 2005-12-13 19:49:35 vladimir%pobox.com Exp $ +** @(#) $Id: analyze.c,v 1.2 2006-02-08 21:10:09 vladimir%pobox.com Exp $ */ #ifndef SQLITE_OMIT_ANALYZE #include "sqliteInt.h" @@ -61,8 +61,14 @@ static void openStatTable( sqlite3VdbeAddOp(v, OP_Clear, pStat->tnum, iDb); } - /* Open the sqlite_stat1 table for writing. + /* Open the sqlite_stat1 table for writing. Unless it was created + ** by this vdbe program, lock it for writing at the shared-cache level. + ** If this vdbe did create the sqlite_stat1 table, then it must have + ** already obtained a schema-lock, making the write-lock redundant. */ + if( iRootPage>0 ){ + sqlite3TableLock(pParse, iDb, iRootPage, 1, "sqlite_stat1"); + } sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); sqlite3VdbeAddOp(v, OP_OpenWrite, iStatCur, iRootPage); sqlite3VdbeAddOp(v, OP_SetNumColumns, iStatCur, 3); @@ -86,6 +92,7 @@ static void analyzeOneTable( int topOfLoop; /* The top of the loop */ int endOfLoop; /* The end of the loop */ int addr; /* The address of an instruction */ + int iDb; /* Index of database containing pTab */ v = sqlite3GetVdbe(pParse); if( pTab==0 || pTab->pIndex==0 ){ @@ -93,21 +100,29 @@ static void analyzeOneTable( return; } + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + assert( iDb>=0 ); #ifndef SQLITE_OMIT_AUTHORIZATION if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0, - pParse->db->aDb[pTab->iDb].zName ) ){ + pParse->db->aDb[iDb].zName ) ){ return; } #endif + /* Establish a read-lock on the table at the shared-cache level. */ + sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); + iIdxCur = pParse->nTab; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); + /* Open a cursor to the index to be analyzed */ - sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0); + assert( iDb==sqlite3SchemaToIndex(pParse->db, pIdx->pSchema) ); + sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); VdbeComment((v, "# %s", pIdx->zName)); sqlite3VdbeOp3(v, OP_OpenRead, iIdxCur, pIdx->tnum, - (char*)&pIdx->keyInfo, P3_KEYINFO); + (char *)pKey, P3_KEYINFO_HANDOFF); nCol = pIdx->nColumn; if( iMem+nCol*2>=pParse->nMem ){ pParse->nMem = iMem+nCol*2+1; @@ -139,7 +154,7 @@ static void analyzeOneTable( endOfLoop = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_Rewind, iIdxCur, endOfLoop); topOfLoop = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp(v, OP_MemIncr, iMem, 0); + sqlite3VdbeAddOp(v, OP_MemIncr, 1, iMem); for(i=0; idb; + Schema *pSchema = db->aDb[iDb].pSchema; /* Schema of database iDb */ HashElem *k; int iStatCur; int iMem; @@ -222,7 +239,7 @@ static void analyzeDatabase(Parse *pParse, int iDb){ iStatCur = pParse->nTab++; openStatTable(pParse, iDb, iStatCur, 0); iMem = pParse->nMem; - for(k=sqliteHashFirst(&db->aDb[iDb].tblHash); k; k=sqliteHashNext(k)){ + for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){ Table *pTab = (Table*)sqliteHashData(k); analyzeOneTable(pParse, pTab, iStatCur, iMem); } @@ -238,7 +255,7 @@ static void analyzeTable(Parse *pParse, Table *pTab){ int iStatCur; assert( pTab!=0 ); - iDb = pTab->iDb; + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); sqlite3BeginWriteOperation(pParse, 0, iDb); iStatCur = pParse->nTab++; openStatTable(pParse, iDb, iStatCur, pTab->zName); @@ -360,7 +377,7 @@ void sqlite3AnalysisLoad(sqlite3 *db, int iDb){ char *zSql; /* Clear any prior statistics */ - for(i=sqliteHashFirst(&db->aDb[iDb].idxHash); i; i=sqliteHashNext(i)){ + for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ Index *pIdx = sqliteHashData(i); sqlite3DefaultRowEst(pIdx); } diff --git a/mozilla/db/sqlite3/src/attach.c b/mozilla/db/sqlite3/src/attach.c index f548aa5eb39..c66b212d160 100644 --- a/mozilla/db/sqlite3/src/attach.c +++ b/mozilla/db/sqlite3/src/attach.c @@ -11,201 +11,342 @@ ************************************************************************* ** This file contains code used to implement the ATTACH and DETACH commands. ** -** $Id: attach.c,v 1.34 2005/08/20 03:03:04 drh Exp $ +** $Id: attach.c,v 1.49 2006/01/24 12:09:18 danielk1977 Exp $ */ #include "sqliteInt.h" /* -** This routine is called by the parser to process an ATTACH statement: +** Resolve an expression that was part of an ATTACH or DETACH statement. This +** is slightly different from resolving a normal SQL expression, because simple +** identifiers are treated as strings, not possible column names or aliases. ** -** ATTACH DATABASE filename AS dbname +** i.e. if the parser sees: ** -** The pFilename and pDbname arguments are the tokens that define the -** filename and dbname in the ATTACH statement. +** ATTACH DATABASE abc AS def +** +** it treats the two expressions as literal strings 'abc' and 'def' instead of +** looking for columns of the same name. +** +** This only applies to the root node of pExpr, so the statement: +** +** ATTACH DATABASE abc||def AS 'db2' +** +** will fail because neither abc or def can be resolved. */ -void sqlite3Attach( - Parse *pParse, /* The parser context */ - Token *pFilename, /* Name of database file */ - Token *pDbname, /* Name of the database to use internally */ - int keyType, /* 0: no key. 1: TEXT, 2: BLOB */ - Token *pKey /* Text of the key for keytype 1 and 2 */ +static int resolveAttachExpr(NameContext *pName, Expr *pExpr) +{ + int rc = SQLITE_OK; + if( pExpr ){ + if( pExpr->op!=TK_ID ){ + rc = sqlite3ExprResolveNames(pName, pExpr); + }else{ + pExpr->op = TK_STRING; + } + } + return rc; +} + +/* +** An SQL user-function registered to do the work of an ATTACH statement. The +** three arguments to the function come directly from an attach statement: +** +** ATTACH DATABASE x AS y KEY z +** +** SELECT sqlite_attach(x, y, z) +** +** If the optional "KEY z" syntax is omitted, an SQL NULL is passed as the +** third argument. +*/ +static void attachFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv ){ + int i; + int rc = 0; + sqlite3 *db = sqlite3_user_data(context); + const char *zName; + const char *zFile; Db *aNew; - int rc, i; - char *zFile = 0; - char *zName = 0; - sqlite3 *db; - Vdbe *v; + char zErr[128]; + char *zErrDyn = 0; - 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; + zFile = (const char *)sqlite3_value_text(argv[0]); + zName = (const char *)sqlite3_value_text(argv[1]); + + /* Check for the following errors: + ** + ** * Too many attached databases, + ** * Transaction currently open + ** * Specified database name already being used. + */ if( db->nDb>=MAX_ATTACHED+2 ){ - sqlite3ErrorMsg(pParse, "too many attached databases - max %d", - MAX_ATTACHED); - pParse->rc = SQLITE_ERROR; - return; + sqlite3_snprintf( + 127, zErr, "too many attached databases - max %d", MAX_ATTACHED + ); + goto attach_error; } - if( !db->autoCommit ){ - sqlite3ErrorMsg(pParse, "cannot ATTACH database within transaction"); - pParse->rc = SQLITE_ERROR; - return; - } - - zFile = sqlite3NameFromToken(pFilename); - if( zFile==0 ){ - goto attach_end; - } -#ifndef SQLITE_OMIT_AUTHORIZATION - if( sqlite3AuthCheck(pParse, SQLITE_ATTACH, zFile, 0, 0)!=SQLITE_OK ){ - goto attach_end; - } -#endif /* SQLITE_OMIT_AUTHORIZATION */ - - zName = sqlite3NameFromToken(pDbname); - if( zName==0 ){ - goto attach_end; + strcpy(zErr, "cannot ATTACH database within transaction"); + goto attach_error; } for(i=0; inDb; i++){ char *z = db->aDb[i].zName; if( z && sqlite3StrICmp(z, zName)==0 ){ - sqlite3ErrorMsg(pParse, "database %s is already in use", zName); - pParse->rc = SQLITE_ERROR; - goto attach_end; + sqlite3_snprintf(127, zErr, "database %s is already in use", zName); + goto attach_error; } } + /* Allocate the new entry in the db->aDb[] array and initialise the schema + ** hash tables. + */ if( db->aDb==db->aDbStatic ){ aNew = sqliteMalloc( sizeof(db->aDb[0])*3 ); if( aNew==0 ){ - goto attach_end; + return; } memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); }else{ aNew = sqliteRealloc(db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); if( aNew==0 ){ - goto attach_end; + return; } } db->aDb = aNew; aNew = &db->aDb[db->nDb++]; memset(aNew, 0, sizeof(*aNew)); - sqlite3HashInit(&aNew->tblHash, SQLITE_HASH_STRING, 0); - sqlite3HashInit(&aNew->idxHash, SQLITE_HASH_STRING, 0); - sqlite3HashInit(&aNew->trigHash, SQLITE_HASH_STRING, 0); - sqlite3HashInit(&aNew->aFKey, SQLITE_HASH_STRING, 1); - aNew->zName = zName; - zName = 0; - aNew->safety_level = 3; + + /* Open the database file. If the btree is successfully opened, use + ** it to obtain the database schema. At this point the schema may + ** or may not be initialised. + */ rc = sqlite3BtreeFactory(db, zFile, 0, MAX_PAGES, &aNew->pBt); - if( rc ){ - sqlite3ErrorMsg(pParse, "unable to open database: %s", zFile); + if( rc==SQLITE_OK ){ + aNew->pSchema = sqlite3SchemaGet(aNew->pBt); + if( !aNew->pSchema ){ + rc = SQLITE_NOMEM; + }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){ + strcpy(zErr, + "attached databases must use the same text encoding as main database"); + goto attach_error; + } } + aNew->zName = sqliteStrDup(zName); + aNew->safety_level = 3; + #if SQLITE_HAS_CODEC { extern int sqlite3CodecAttach(sqlite3*, int, void*, int); - char *zKey; + extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); int nKey; - if( keyType==0 ){ - /* No key specified. Use the key from the main database */ - extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); - sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey); - }else if( keyType==1 ){ - /* Key specified as text */ - zKey = sqlite3NameFromToken(pKey); - nKey = strlen(zKey); - }else{ - /* Key specified as a BLOB */ - char *zTemp; - assert( keyType==2 ); - pKey->z++; - pKey->n--; - zTemp = sqlite3NameFromToken(pKey); - zKey = sqlite3HexToBlob(zTemp); - sqliteFree(zTemp); - } - sqlite3CodecAttach(db, db->nDb-1, zKey, nKey); - if( keyType ){ - sqliteFree(zKey); + char *zKey; + int t = sqlite3_value_type(argv[2]); + switch( t ){ + case SQLITE_INTEGER: + case SQLITE_FLOAT: + zErrDyn = sqliteStrDup("Invalid key value"); + rc = SQLITE_ERROR; + break; + + case SQLITE_TEXT: + case SQLITE_BLOB: + nKey = sqlite3_value_bytes(argv[2]); + zKey = (char *)sqlite3_value_blob(argv[2]); + sqlite3CodecAttach(db, db->nDb-1, zKey, nKey); + break; + + case SQLITE_NULL: + /* No key specified. Use the key from the main database */ + sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey); + sqlite3CodecAttach(db, db->nDb-1, zKey, nKey); + break; } } #endif - db->flags &= ~SQLITE_Initialized; - if( pParse->nErr==0 && rc==SQLITE_OK ){ - rc = sqlite3ReadSchema(pParse); + + /* If the file was opened successfully, read the schema for the new database. + ** If this fails, or if opening the file failed, then close the file and + ** remove the entry from the db->aDb[] array. i.e. put everything back the way + ** we found it. + */ + if( rc==SQLITE_OK ){ + sqlite3SafetyOn(db); + rc = sqlite3Init(db, &zErrDyn); + sqlite3SafetyOff(db); } if( rc ){ - int i = db->nDb - 1; - assert( i>=2 ); - if( db->aDb[i].pBt ){ - sqlite3BtreeClose(db->aDb[i].pBt); - db->aDb[i].pBt = 0; + int iDb = db->nDb - 1; + assert( iDb>=2 ); + if( db->aDb[iDb].pBt ){ + sqlite3BtreeClose(db->aDb[iDb].pBt); + db->aDb[iDb].pBt = 0; + db->aDb[iDb].pSchema = 0; } sqlite3ResetInternalSchema(db, 0); - assert( pParse->nErr>0 ); /* Always set by sqlite3ReadSchema() */ - if( pParse->rc==SQLITE_OK ){ - pParse->rc = SQLITE_ERROR; - } + db->nDb = iDb; + sqlite3_snprintf(127, zErr, "unable to open database: %s", zFile); + goto attach_error; } + + return; -attach_end: - sqliteFree(zFile); - sqliteFree(zName); +attach_error: + /* Return an error if we get here */ + if( zErrDyn ){ + sqlite3_result_error(context, zErrDyn, -1); + sqliteFree(zErrDyn); + }else{ + zErr[sizeof(zErr)-1] = 0; + sqlite3_result_error(context, zErr, -1); + } } /* -** This routine is called by the parser to process a DETACH statement: +** An SQL user-function registered to do the work of an DETACH statement. The +** three arguments to the function come directly from a detach statement: ** -** DETACH DATABASE dbname +** DETACH DATABASE x ** -** The pDbname argument is the name of the database in the DETACH statement. +** SELECT sqlite_detach(x) */ -void sqlite3Detach(Parse *pParse, Token *pDbname){ +static void detachFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const char *zName = (const char *)sqlite3_value_text(argv[0]); + sqlite3 *db = sqlite3_user_data(context); int i; - sqlite3 *db; - Vdbe *v; Db *pDb = 0; - char *zName; + char zErr[128]; - 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; - zName = sqlite3NameFromToken(pDbname); - if( zName==0 ) return; + assert(zName); for(i=0; inDb; i++){ pDb = &db->aDb[i]; if( pDb->pBt==0 ) continue; if( sqlite3StrICmp(pDb->zName, zName)==0 ) break; } + if( i>=db->nDb ){ - sqlite3ErrorMsg(pParse, "no such database: %z", zName); - return; + sqlite3_snprintf(sizeof(zErr), zErr, "no such database: %s", zName); + goto detach_error; } if( i<2 ){ - sqlite3ErrorMsg(pParse, "cannot detach database %z", zName); - return; + sqlite3_snprintf(sizeof(zErr), zErr, "cannot detach database %s", zName); + goto detach_error; } - sqliteFree(zName); if( !db->autoCommit ){ - sqlite3ErrorMsg(pParse, "cannot DETACH database within transaction"); - pParse->rc = SQLITE_ERROR; - return; + strcpy(zErr, "cannot DETACH database within transaction"); + goto detach_error; } -#ifndef SQLITE_OMIT_AUTHORIZATION - if( sqlite3AuthCheck(pParse,SQLITE_DETACH,db->aDb[i].zName,0,0)!=SQLITE_OK ){ - return; - } -#endif /* SQLITE_OMIT_AUTHORIZATION */ + sqlite3BtreeClose(pDb->pBt); pDb->pBt = 0; + pDb->pSchema = 0; sqlite3ResetInternalSchema(db, 0); + return; + +detach_error: + sqlite3_result_error(context, zErr, -1); +} + +/* +** This procedure generates VDBE code for a single invocation of either the +** sqlite_detach() or sqlite_attach() SQL user functions. +*/ +static void codeAttach( + Parse *pParse, /* The parser context */ + int type, /* Either SQLITE_ATTACH or SQLITE_DETACH */ + const char *zFunc, /* Either "sqlite_attach" or "sqlite_detach */ + int nFunc, /* Number of args to pass to zFunc */ + Expr *pAuthArg, /* Expression to pass to authorization callback */ + Expr *pFilename, /* Name of database file */ + Expr *pDbname, /* Name of the database to use internally */ + Expr *pKey /* Database key for encryption extension */ +){ + int rc; + NameContext sName; + Vdbe *v; + FuncDef *pFunc; + sqlite3* db = pParse->db; + +#ifndef SQLITE_OMIT_AUTHORIZATION + assert( sqlite3MallocFailed() || pAuthArg ); + if( pAuthArg ){ + char *zAuthArg = sqlite3NameFromToken(&pAuthArg->span); + if( !zAuthArg ){ + goto attach_end; + } + rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0); + sqliteFree(zAuthArg); + if(rc!=SQLITE_OK ){ + goto attach_end; + } + } +#endif /* SQLITE_OMIT_AUTHORIZATION */ + + memset(&sName, 0, sizeof(NameContext)); + sName.pParse = pParse; + + if( + SQLITE_OK!=(rc = resolveAttachExpr(&sName, pFilename)) || + SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) || + SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey)) + ){ + pParse->nErr++; + goto attach_end; + } + + v = sqlite3GetVdbe(pParse); + sqlite3ExprCode(pParse, pFilename); + sqlite3ExprCode(pParse, pDbname); + sqlite3ExprCode(pParse, pKey); + + assert( v || sqlite3MallocFailed() ); + if( v ){ + sqlite3VdbeAddOp(v, OP_Function, 0, nFunc); + pFunc = sqlite3FindFunction(db, zFunc, strlen(zFunc), nFunc, SQLITE_UTF8,0); + sqlite3VdbeChangeP3(v, -1, (char *)pFunc, P3_FUNCDEF); + + /* Code an OP_Expire. For an ATTACH statement, set P1 to true (expire this + ** statement only). For DETACH, set it to false (expire all existing + ** statements). + */ + sqlite3VdbeAddOp(v, OP_Expire, (type==SQLITE_ATTACH), 0); + } + +attach_end: + sqlite3ExprDelete(pFilename); + sqlite3ExprDelete(pDbname); + sqlite3ExprDelete(pKey); +} + +/* +** Called by the parser to compile a DETACH statement. +** +** DETACH pDbname +*/ +void sqlite3Detach(Parse *pParse, Expr *pDbname){ + codeAttach(pParse, SQLITE_DETACH, "sqlite_detach", 1, pDbname, 0, 0, pDbname); +} + +/* +** Called by the parser to compile an ATTACH statement. +** +** ATTACH p AS pDbname KEY pKey +*/ +void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){ + codeAttach(pParse, SQLITE_ATTACH, "sqlite_attach", 3, p, p, pDbname, pKey); +} + +/* +** Register the functions sqlite_attach and sqlite_detach. +*/ +void sqlite3AttachFunctions(sqlite3 *db){ + static const int enc = SQLITE_UTF8; + sqlite3CreateFunc(db, "sqlite_attach", 3, enc, db, attachFunc, 0, 0); + sqlite3CreateFunc(db, "sqlite_detach", 1, enc, db, detachFunc, 0, 0); } /* diff --git a/mozilla/db/sqlite3/src/auth.c b/mozilla/db/sqlite3/src/auth.c index 7627ee140aa..964ae66a635 100644 --- a/mozilla/db/sqlite3/src/auth.c +++ b/mozilla/db/sqlite3/src/auth.c @@ -14,7 +14,7 @@ ** systems that do not need this facility may omit it by recompiling ** the library with -DSQLITE_OMIT_AUTHORIZATION=1 ** -** $Id: auth.c,v 1.22 2005/07/29 15:36:15 drh Exp $ +** $Id: auth.c,v 1.24 2006/01/13 13:55:45 drh Exp $ */ #include "sqliteInt.h" @@ -112,10 +112,17 @@ void sqlite3AuthRead( int iSrc; /* Index in pTabList->a[] of table being read */ const char *zDBase; /* Name of database being accessed */ TriggerStack *pStack; /* The stack of current triggers */ + int iDb; /* The index of the database the expression refers to */ if( db->xAuth==0 ) return; if( pExpr->op==TK_AS ) return; assert( pExpr->op==TK_COLUMN ); + iDb = sqlite3SchemaToIndex(pParse->db, pExpr->pSchema); + if( iDb<0 ){ + /* An attempt to read a column out of a subquery or other + ** temporary table. */ + return; + } for(iSrc=0; pTabList && iSrcnSrc; iSrc++){ if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break; } @@ -140,14 +147,14 @@ void sqlite3AuthRead( }else{ zCol = "ROWID"; } - assert( pExpr->iDbnDb ); - zDBase = db->aDb[pExpr->iDb].zName; + assert( iDb>=0 && iDbnDb ); + zDBase = db->aDb[iDb].zName; rc = db->xAuth(db->pAuthArg, SQLITE_READ, pTab->zName, zCol, zDBase, pParse->zAuthContext); if( rc==SQLITE_IGNORE ){ pExpr->op = TK_NULL; }else if( rc==SQLITE_DENY ){ - if( db->nDb>2 || pExpr->iDb!=0 ){ + if( db->nDb>2 || iDb!=0 ){ sqlite3ErrorMsg(pParse, "access to %s.%s.%s is prohibited", zDBase, pTab->zName, zCol); }else{ diff --git a/mozilla/db/sqlite3/src/btree.c b/mozilla/db/sqlite3/src/btree.c index 7b9cde7cf40..f0e749302f1 100644 --- a/mozilla/db/sqlite3/src/btree.c +++ b/mozilla/db/sqlite3/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.269 2005/09/17 15:20:27 drh Exp $ +** $Id: btree.c,v 1.311 2006/01/24 16:37:58 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -230,6 +230,7 @@ /* Forward declarations */ typedef struct MemPage MemPage; +typedef struct BtLock BtLock; /* ** This is a magic string that appears at the beginning of every @@ -285,10 +286,10 @@ struct MemPage { u16 nFree; /* Number of free bytes on the page */ u16 nCell; /* Number of cells on this page, local and ovfl */ struct _OvflCell { /* Cells that will not fit on aData[] */ - u8 *pCell; /* Pointers to the body of the overflow cell */ - u16 idx; /* Insert this cell before idx-th non-overflow cell */ + u8 *pCell; /* Pointers to the body of the overflow cell */ + u16 idx; /* Insert this cell before idx-th non-overflow cell */ } aOvfl[5]; - struct Btree *pBt; /* Pointer back to BTree structure */ + BtShared *pBt; /* Pointer back to BTree structure */ u8 *aData; /* Pointer back to the start of the page */ Pgno pgno; /* Page number for this page */ MemPage *pParent; /* The parent of this page. NULL for root */ @@ -301,14 +302,32 @@ struct MemPage { */ #define EXTRA_SIZE sizeof(MemPage) +/* Btree handle */ +struct Btree { + sqlite3 *pSqlite; + BtShared *pBt; + u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */ +}; + +/* +** Btree.inTrans may take one of the following values. +** +** If the shared-data extension is enabled, there may be multiple users +** of the Btree structure. At most one of these may open a write transaction, +** but any number may have active read transactions. Variable Btree.pDb +** points to the handle that owns any current write-transaction. +*/ +#define TRANS_NONE 0 +#define TRANS_READ 1 +#define TRANS_WRITE 2 + /* ** Everything we need to know about an open database */ -struct Btree { +struct BtShared { Pager *pPager; /* The page cache */ BtCursor *pCursor; /* A list of all open cursors */ MemPage *pPage1; /* First page of the database */ - u8 inTrans; /* True if a transaction is in progress */ u8 inStmt; /* True if we are in a statement subtransaction */ u8 readOnly; /* True if the underlying file is readonly */ u8 maxEmbedFrac; /* Maximum payload as % of total page size */ @@ -325,15 +344,16 @@ struct Btree { int maxLeaf; /* Maximum local payload in a LEAFDATA table */ int minLeaf; /* Minimum local payload in a LEAFDATA table */ BusyHandler *pBusyHandler; /* Callback for when there is lock contention */ + u8 inTransaction; /* Transaction state */ + int nRef; /* Number of references to this structure */ + int nTransaction; /* Number of open transactions (read + write) */ + void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */ + void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */ +#ifndef SQLITE_OMIT_SHARED_CACHE + BtLock *pLock; /* List of locks held on this shared-btree struct */ + BtShared *pNext; /* Next in ThreadData.pBtree linked list */ +#endif }; -typedef Btree Bt; - -/* -** Btree.inTrans may take one of the following values. -*/ -#define TRANS_NONE 0 -#define TRANS_READ 1 -#define TRANS_WRITE 2 /* ** An instance of the following structure is used to hold information @@ -357,7 +377,7 @@ struct CellInfo { ** MemPage.aCell[] of the entry. */ struct BtCursor { - Btree *pBt; /* The Btree to which this cursor belongs */ + Btree *pBtree; /* The Btree to which this cursor belongs */ BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */ int (*xCompare)(void*,int,const void*,int,const void*); /* Key comp func */ void *pArg; /* First arg to xCompare() */ @@ -366,9 +386,38 @@ struct BtCursor { int idx; /* Index of the entry in pPage->aCell[] */ 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 eState; /* One of the CURSOR_XXX constants (see below) */ +#ifndef SQLITE_OMIT_SHARED_CACHE + void *pKey; + i64 nKey; + int skip; /* (skip<0) -> Prev() is a no-op. (skip>0) -> Next() is */ +#endif }; +/* +** Potential values for BtCursor.eState. The first two values (VALID and +** INVALID) may occur in any build. The third (REQUIRESEEK) may only occur +** if sqlite was compiled without the OMIT_SHARED_CACHE symbol defined. +** +** CURSOR_VALID: +** Cursor points to a valid entry. getPayload() etc. may be called. +** +** CURSOR_INVALID: +** Cursor does not point to a valid entry. This can happen (for example) +** because the table is empty or because BtreeCursorFirst() has not been +** called. +** +** CURSOR_REQUIRESEEK: +** The table that this cursor was opened on still exists, but has been +** modified since the cursor was last used. The cursor position is saved +** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in +** this state, restoreOrClearCursorPosition() can be called to attempt to seek +** the cursor to the saved position. +*/ +#define CURSOR_INVALID 0 +#define CURSOR_VALID 1 +#define CURSOR_REQUIRESEEK 2 + /* ** The TRACE macro will print high-level status information about the ** btree operation when the global variable sqlite3_btree_trace is @@ -385,7 +434,7 @@ int sqlite3_btree_trace=0; /* True to enable tracing */ /* ** Forward declaration */ -static int checkReadLocks(Btree*,Pgno,BtCursor*); +static int checkReadLocks(BtShared*,Pgno,BtCursor*); /* ** Read or write a two- and four-byte big-endian integer values. @@ -413,7 +462,8 @@ static void put4byte(unsigned char *p, u32 v){ ** file. */ #define getVarint sqlite3GetVarint -#define getVarint32 sqlite3GetVarint32 +/* #define getVarint32 sqlite3GetVarint32 */ +#define getVarint32(A,B) ((*B=*(A))<=0x7f?1:sqlite3GetVarint32(A,B)) #define putVarint sqlite3PutVarint /* The database page the PENDING_BYTE occupies. This page is never used. @@ -422,6 +472,274 @@ static void put4byte(unsigned char *p, u32 v){ */ #define PENDING_BYTE_PAGE(pBt) ((PENDING_BYTE/(pBt)->pageSize)+1) +/* +** A linked list of the following structures is stored at BtShared.pLock. +** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor +** is opened on the table with root page BtShared.iTable. Locks are removed +** from this list when a transaction is committed or rolled back, or when +** a btree handle is closed. +*/ +struct BtLock { + Btree *pBtree; /* Btree handle holding this lock */ + Pgno iTable; /* Root page of table */ + u8 eLock; /* READ_LOCK or WRITE_LOCK */ + BtLock *pNext; /* Next in BtShared.pLock list */ +}; + +/* Candidate values for BtLock.eLock */ +#define READ_LOCK 1 +#define WRITE_LOCK 2 + +#ifdef SQLITE_OMIT_SHARED_CACHE + /* + ** The functions queryTableLock(), lockTable() and unlockAllTables() + ** manipulate entries in the BtShared.pLock linked list used to store + ** shared-cache table level locks. If the library is compiled with the + ** shared-cache feature disabled, then there is only ever one user + ** of each BtShared structure and so this locking is not necessary. + ** So define the lock related functions as no-ops. + */ + #define queryTableLock(a,b,c) SQLITE_OK + #define lockTable(a,b,c) SQLITE_OK + #define unlockAllTables(a) + #define restoreOrClearCursorPosition(a,b) SQLITE_OK + #define saveAllCursors(a,b,c) SQLITE_OK + +#else + +static void releasePage(MemPage *pPage); + +/* +** Save the current cursor position in the variables BtCursor.nKey +** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK. +*/ +static int saveCursorPosition(BtCursor *pCur){ + int rc; + + assert( CURSOR_VALID==pCur->eState ); + assert( 0==pCur->pKey ); + + rc = sqlite3BtreeKeySize(pCur, &pCur->nKey); + + /* If this is an intKey table, then the above call to BtreeKeySize() + ** stores the integer key in pCur->nKey. In this case this value is + ** all that is required. Otherwise, if pCur is not open on an intKey + ** table, then malloc space for and store the pCur->nKey bytes of key + ** data. + */ + if( rc==SQLITE_OK && 0==pCur->pPage->intKey){ + void *pKey = sqliteMalloc(pCur->nKey); + if( pKey ){ + rc = sqlite3BtreeKey(pCur, 0, pCur->nKey, pKey); + if( rc==SQLITE_OK ){ + pCur->pKey = pKey; + }else{ + sqliteFree(pKey); + } + }else{ + rc = SQLITE_NOMEM; + } + } + assert( !pCur->pPage->intKey || !pCur->pKey ); + + if( rc==SQLITE_OK ){ + releasePage(pCur->pPage); + pCur->pPage = 0; + pCur->eState = CURSOR_REQUIRESEEK; + } + + return rc; +} + +/* +** Save the positions of all cursors except pExcept open on the table +** with root-page iRoot. Usually, this is called just before cursor +** pExcept is used to modify the table (BtreeDelete() or BtreeInsert()). +*/ +static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){ + BtCursor *p; + if( sqlite3ThreadDataReadOnly()->useSharedData ){ + for(p=pBt->pCursor; p; p=p->pNext){ + if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) && + p->eState==CURSOR_VALID ){ + int rc = saveCursorPosition(p); + if( SQLITE_OK!=rc ){ + return rc; + } + } + } + } + return SQLITE_OK; +} + +/* +** Restore the cursor to the position it was in (or as close to as possible) +** when saveCursorPosition() was called. Note that this call deletes the +** saved position info stored by saveCursorPosition(), so there can be +** at most one effective restoreOrClearCursorPosition() call after each +** saveCursorPosition(). +** +** If the second argument argument - doSeek - is false, then instead of +** returning the cursor to it's saved position, any saved position is deleted +** and the cursor state set to CURSOR_INVALID. +*/ +static int restoreOrClearCursorPositionX(BtCursor *pCur, int doSeek){ + int rc = SQLITE_OK; + assert( sqlite3ThreadDataReadOnly()->useSharedData ); + assert( pCur->eState==CURSOR_REQUIRESEEK ); + pCur->eState = CURSOR_INVALID; + if( doSeek ){ + rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, &pCur->skip); + } + if( rc==SQLITE_OK ){ + sqliteFree(pCur->pKey); + pCur->pKey = 0; + assert( CURSOR_VALID==pCur->eState || CURSOR_INVALID==pCur->eState ); + } + return rc; +} + +#define restoreOrClearCursorPosition(p,x) \ + (p->eState==CURSOR_REQUIRESEEK?restoreOrClearCursorPositionX(p,x):SQLITE_OK) + +/* +** Query to see if btree handle p may obtain a lock of type eLock +** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return +** SQLITE_OK if the lock may be obtained (by calling lockTable()), or +** SQLITE_LOCKED if not. +*/ +static int queryTableLock(Btree *p, Pgno iTab, u8 eLock){ + BtShared *pBt = p->pBt; + BtLock *pIter; + + /* This is a no-op if the shared-cache is not enabled */ + if( 0==sqlite3ThreadDataReadOnly()->useSharedData ){ + return SQLITE_OK; + } + + /* This (along with lockTable()) is where the ReadUncommitted flag is + ** dealt with. If the caller is querying for a read-lock and the flag is + ** set, it is unconditionally granted - even if there are write-locks + ** on the table. If a write-lock is requested, the ReadUncommitted flag + ** is not considered. + ** + ** In function lockTable(), if a read-lock is demanded and the + ** ReadUncommitted flag is set, no entry is added to the locks list + ** (BtShared.pLock). + ** + ** To summarize: If the ReadUncommitted flag is set, then read cursors do + ** not create or respect table locks. The locking procedure for a + ** write-cursor does not change. + */ + if( + !p->pSqlite || + 0==(p->pSqlite->flags&SQLITE_ReadUncommitted) || + eLock==WRITE_LOCK || + iTab==MASTER_ROOT + ){ + for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){ + if( pIter->pBtree!=p && pIter->iTable==iTab && + (pIter->eLock!=eLock || eLock!=READ_LOCK) ){ + return SQLITE_LOCKED; + } + } + } + return SQLITE_OK; +} + +/* +** Add a lock on the table with root-page iTable to the shared-btree used +** by Btree handle p. Parameter eLock must be either READ_LOCK or +** WRITE_LOCK. +** +** SQLITE_OK is returned if the lock is added successfully. SQLITE_BUSY and +** SQLITE_NOMEM may also be returned. +*/ +static int lockTable(Btree *p, Pgno iTable, u8 eLock){ + BtShared *pBt = p->pBt; + BtLock *pLock = 0; + BtLock *pIter; + + /* This is a no-op if the shared-cache is not enabled */ + if( 0==sqlite3ThreadDataReadOnly()->useSharedData ){ + return SQLITE_OK; + } + + assert( SQLITE_OK==queryTableLock(p, iTable, eLock) ); + + /* If the read-uncommitted flag is set and a read-lock is requested, + ** return early without adding an entry to the BtShared.pLock list. See + ** comment in function queryTableLock() for more info on handling + ** the ReadUncommitted flag. + */ + if( + (p->pSqlite) && + (p->pSqlite->flags&SQLITE_ReadUncommitted) && + (eLock==READ_LOCK) && + iTable!=MASTER_ROOT + ){ + return SQLITE_OK; + } + + /* First search the list for an existing lock on this table. */ + for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){ + if( pIter->iTable==iTable && pIter->pBtree==p ){ + pLock = pIter; + break; + } + } + + /* If the above search did not find a BtLock struct associating Btree p + ** with table iTable, allocate one and link it into the list. + */ + if( !pLock ){ + pLock = (BtLock *)sqliteMalloc(sizeof(BtLock)); + if( !pLock ){ + return SQLITE_NOMEM; + } + pLock->iTable = iTable; + pLock->pBtree = p; + pLock->pNext = pBt->pLock; + pBt->pLock = pLock; + } + + /* Set the BtLock.eLock variable to the maximum of the current lock + ** and the requested lock. This means if a write-lock was already held + ** and a read-lock requested, we don't incorrectly downgrade the lock. + */ + assert( WRITE_LOCK>READ_LOCK ); + if( eLock>pLock->eLock ){ + pLock->eLock = eLock; + } + + return SQLITE_OK; +} + +/* +** Release all the table locks (locks obtained via calls to the lockTable() +** procedure) held by Btree handle p. +*/ +static void unlockAllTables(Btree *p){ + BtLock **ppIter = &p->pBt->pLock; + + /* If the shared-cache extension is not enabled, there should be no + ** locks in the BtShared.pLock list, making this procedure a no-op. Assert + ** that this is the case. + */ + assert( sqlite3ThreadDataReadOnly()->useSharedData || 0==*ppIter ); + + while( *ppIter ){ + BtLock *pLock = *ppIter; + if( pLock->pBtree==p ){ + *ppIter = pLock->pNext; + sqliteFree(pLock); + }else{ + ppIter = &pLock->pNext; + } + } +} +#endif /* SQLITE_OMIT_SHARED_CACHE */ + #ifndef SQLITE_OMIT_AUTOVACUUM /* ** These macros define the location of the pointer-map entry for a @@ -486,7 +804,7 @@ static void put4byte(unsigned char *p, u32 v){ ** 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){ +static int ptrmapPut(BtShared *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 */ @@ -523,7 +841,7 @@ static int ptrmapPut(Btree *pBt, Pgno key, u8 eType, Pgno parent){ ** 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){ +static int ptrmapGet(BtShared *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 */ @@ -604,12 +922,16 @@ static void parseCellPtr( }else{ nPayload = 0; } - n += getVarint(&pCell[n], (u64 *)&pInfo->nKey); - pInfo->nHeader = n; pInfo->nData = nPayload; - if( !pPage->intKey ){ - nPayload += pInfo->nKey; + if( pPage->intKey ){ + n += getVarint(&pCell[n], (u64 *)&pInfo->nKey); + }else{ + u32 x; + n += getVarint32(&pCell[n], &x); + pInfo->nKey = x; + nPayload += x; } + pInfo->nHeader = n; if( nPayload<=pPage->maxLocal ){ /* This is the (easy) common case where the entire payload fits ** on the local page. No overflow is required. @@ -790,10 +1112,20 @@ static void _pageIntegrity(MemPage *pPage){ # define pageIntegrity(X) #endif +/* A bunch of assert() statements to check the transaction state variables +** of handle p (type Btree*) are internally consistent. +*/ +#define btreeIntegrity(p) \ + assert( p->inTrans!=TRANS_NONE || p->pBt->nTransactionpBt->nRef ); \ + assert( p->pBt->nTransaction<=p->pBt->nRef ); \ + assert( p->pBt->inTransaction!=TRANS_NONE || p->pBt->nTransaction==0 ); \ + assert( p->pBt->inTransaction>=p->inTrans ); + /* ** Defragment the page given. All Cells are moved to the -** beginning of the page and all free space is collected -** into one big FreeBlk at the end of the page. +** end of the page and all free space is collected into one +** big FreeBlk that occurs in between the header and cell +** pointer array and the cell content area. */ static int defragmentPage(MemPage *pPage){ int i; /* Loop counter */ @@ -977,7 +1309,7 @@ static void freeSpace(MemPage *pPage, int start, int size){ ** and initialize fields of the MemPage structure accordingly. */ static void decodeFlags(MemPage *pPage, int flagByte){ - Btree *pBt; /* A copy of pPage->pBt */ + BtShared *pBt; /* A copy of pPage->pBt */ assert( pPage->hdrOffset==(pPage->pgno==1 ? 100 : 0) ); pPage->intKey = (flagByte & (PTF_INTKEY|PTF_LEAFDATA))!=0; @@ -1017,7 +1349,7 @@ static int initPage( int pc; /* Address of a freeblock within pPage->aData[] */ int hdr; /* Offset to beginning of page header */ u8 *data; /* Equal to pPage->aData */ - Btree *pBt; /* The main btree structure */ + BtShared *pBt; /* The main btree structure */ int usableSize; /* Amount of usable space on each page */ int cellOffset; /* Offset from start of page to first cell pointer */ int nFree; /* Number of unused bytes on the page */ @@ -1090,7 +1422,7 @@ static int initPage( */ static void zeroPage(MemPage *pPage, int flags){ unsigned char *data = pPage->aData; - Btree *pBt = pPage->pBt; + BtShared *pBt = pPage->pBt; int hdr = pPage->hdrOffset; int first; @@ -1118,7 +1450,7 @@ static void zeroPage(MemPage *pPage, int flags){ ** Get a page from the pager. Initialize the MemPage.pBt and ** MemPage.aData elements if needed. */ -static int getPage(Btree *pBt, Pgno pgno, MemPage **ppPage){ +static int getPage(BtShared *pBt, Pgno pgno, MemPage **ppPage){ int rc; unsigned char *aData; MemPage *pPage; @@ -1139,7 +1471,7 @@ static int getPage(Btree *pBt, Pgno pgno, MemPage **ppPage){ ** getPage() and initPage(). */ static int getAndInitPage( - Btree *pBt, /* The database file */ + BtShared *pBt, /* The database file */ Pgno pgno, /* Number of the page to get */ MemPage **ppPage, /* Write the page pointer here */ MemPage *pParent /* Parent of the page */ @@ -1212,13 +1544,61 @@ static void pageReinit(void *pData, int pageSize){ */ int sqlite3BtreeOpen( const char *zFilename, /* Name of the file containing the BTree database */ + sqlite3 *pSqlite, /* Associated database handle */ Btree **ppBtree, /* Pointer to new Btree object written here */ int flags /* Options */ ){ - Btree *pBt; + BtShared *pBt; /* Shared part of btree structure */ + Btree *p; /* Handle to return */ int rc; int nReserve; unsigned char zDbHeader[100]; +#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) + const ThreadData *pTsdro; +#endif + + /* Set the variable isMemdb to true for an in-memory database, or + ** false for a file-based database. This symbol is only required if + ** either of the shared-data or autovacuum features are compiled + ** into the library. + */ +#if !defined(SQLITE_OMIT_SHARED_CACHE) || !defined(SQLITE_OMIT_AUTOVACUUM) + #ifdef SQLITE_OMIT_MEMORYDB + const int isMemdb = !zFilename; + #else + const int isMemdb = !zFilename || (strcmp(zFilename, ":memory:")?0:1); + #endif +#endif + + p = sqliteMalloc(sizeof(Btree)); + if( !p ){ + return SQLITE_NOMEM; + } + p->inTrans = TRANS_NONE; + p->pSqlite = pSqlite; + + /* Try to find an existing Btree structure opened on zFilename. */ +#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) + pTsdro = sqlite3ThreadDataReadOnly(); + if( pTsdro->useSharedData && zFilename && !isMemdb ){ + char *zFullPathname = sqlite3OsFullPathname(zFilename); + if( !zFullPathname ){ + sqliteFree(p); + return SQLITE_NOMEM; + } + for(pBt=pTsdro->pBtree; pBt; pBt=pBt->pNext){ + assert( pBt->nRef>0 ); + if( 0==strcmp(zFullPathname, sqlite3pager_filename(pBt->pPager)) ){ + p->pBt = pBt; + *ppBtree = p; + pBt->nRef++; + sqliteFree(zFullPathname); + return SQLITE_OK; + } + } + sqliteFree(zFullPathname); + } +#endif /* ** The following asserts make sure that structures used by the btree are @@ -1234,15 +1614,19 @@ int sqlite3BtreeOpen( pBt = sqliteMalloc( sizeof(*pBt) ); if( pBt==0 ){ *ppBtree = 0; + sqliteFree(p); return SQLITE_NOMEM; } rc = sqlite3pager_open(&pBt->pPager, zFilename, EXTRA_SIZE, flags); if( rc!=SQLITE_OK ){ if( pBt->pPager ) sqlite3pager_close(pBt->pPager); sqliteFree(pBt); + sqliteFree(p); *ppBtree = 0; return rc; } + p->pBt = pBt; + sqlite3pager_set_destructor(pBt->pPager, pageDestructor); sqlite3pager_set_reiniter(pBt->pPager, pageReinit); pBt->pCursor = 0; @@ -1263,11 +1647,7 @@ int sqlite3BtreeOpen( ** 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 + if( zFilename && !isMemdb ){ pBt->autoVacuum = SQLITE_DEFAULT_AUTOVACUUM; } #endif @@ -1285,18 +1665,87 @@ int sqlite3BtreeOpen( pBt->usableSize = pBt->pageSize - nReserve; assert( (pBt->pageSize & 7)==0 ); /* 8-byte alignment of pageSize */ sqlite3pager_set_pagesize(pBt->pPager, pBt->pageSize); - *ppBtree = pBt; + +#ifndef SQLITE_OMIT_SHARED_CACHE + /* Add the new btree to the linked list starting at ThreadData.pBtree. + ** There is no chance that a malloc() may fail inside of the + ** sqlite3ThreadData() call, as the ThreadData structure must have already + ** been allocated for pTsdro->useSharedData to be non-zero. + */ + if( pTsdro->useSharedData && zFilename && !isMemdb ){ + pBt->pNext = pTsdro->pBtree; + sqlite3ThreadData()->pBtree = pBt; + } +#endif + pBt->nRef = 1; + *ppBtree = p; return SQLITE_OK; } /* ** Close an open database and invalidate all cursors. */ -int sqlite3BtreeClose(Btree *pBt){ - while( pBt->pCursor ){ - sqlite3BtreeCloseCursor(pBt->pCursor); +int sqlite3BtreeClose(Btree *p){ + BtShared *pBt = p->pBt; + BtCursor *pCur; + +#ifndef SQLITE_OMIT_SHARED_CACHE + ThreadData *pTsd; +#endif + + /* Close all cursors opened via this handle. */ + pCur = pBt->pCursor; + while( pCur ){ + BtCursor *pTmp = pCur; + pCur = pCur->pNext; + if( pTmp->pBtree==p ){ + sqlite3BtreeCloseCursor(pTmp); + } } + + /* Rollback any active transaction and free the handle structure. + ** The call to sqlite3BtreeRollback() drops any table-locks held by + ** this handle. + */ + sqlite3BtreeRollback(p); + sqliteFree(p); + +#ifndef SQLITE_OMIT_SHARED_CACHE + /* If there are still other outstanding references to the shared-btree + ** structure, return now. The remainder of this procedure cleans + ** up the shared-btree. + */ + assert( pBt->nRef>0 ); + pBt->nRef--; + if( pBt->nRef ){ + return SQLITE_OK; + } + + /* Remove the shared-btree from the thread wide list. Call + ** ThreadDataReadOnly() and then cast away the const property of the + ** pointer to avoid allocating thread data if it is not really required. + */ + pTsd = (ThreadData *)sqlite3ThreadDataReadOnly(); + if( pTsd->pBtree==pBt ){ + assert( pTsd==sqlite3ThreadData() ); + pTsd->pBtree = pBt->pNext; + }else{ + BtShared *pPrev; + for(pPrev=pTsd->pBtree; pPrev && pPrev->pNext!=pBt; pPrev=pPrev->pNext); + if( pPrev ){ + assert( pTsd==sqlite3ThreadData() ); + pPrev->pNext = pBt->pNext; + } + } +#endif + + /* Close the pager and free the shared-btree structure */ + assert( !pBt->pCursor ); sqlite3pager_close(pBt->pPager); + if( pBt->xFreeSchema && pBt->pSchema ){ + pBt->xFreeSchema(pBt->pSchema); + } + sqliteFree(pBt->pSchema); sqliteFree(pBt); return SQLITE_OK; } @@ -1304,7 +1753,8 @@ int sqlite3BtreeClose(Btree *pBt){ /* ** Change the busy handler callback function. */ -int sqlite3BtreeSetBusyHandler(Btree *pBt, BusyHandler *pHandler){ +int sqlite3BtreeSetBusyHandler(Btree *p, BusyHandler *pHandler){ + BtShared *pBt = p->pBt; pBt->pBusyHandler = pHandler; sqlite3pager_set_busyhandler(pBt->pPager, pHandler); return SQLITE_OK; @@ -1325,7 +1775,8 @@ int sqlite3BtreeSetBusyHandler(Btree *pBt, BusyHandler *pHandler){ ** Synchronous is on by default so database corruption is not ** normally a worry. */ -int sqlite3BtreeSetCacheSize(Btree *pBt, int mxPage){ +int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){ + BtShared *pBt = p->pBt; sqlite3pager_set_cachesize(pBt->pPager, mxPage); return SQLITE_OK; } @@ -1339,7 +1790,8 @@ int sqlite3BtreeSetCacheSize(Btree *pBt, int mxPage){ ** probability of damage to near zero but with a write performance reduction. */ #ifndef SQLITE_OMIT_PAGER_PRAGMAS -int sqlite3BtreeSetSafetyLevel(Btree *pBt, int level){ +int sqlite3BtreeSetSafetyLevel(Btree *p, int level){ + BtShared *pBt = p->pBt; sqlite3pager_set_safety_level(pBt->pPager, level); return SQLITE_OK; } @@ -1349,7 +1801,8 @@ int sqlite3BtreeSetSafetyLevel(Btree *pBt, int level){ ** Return TRUE if the given btree is set to safety level 1. In other ** words, return TRUE if no sync() occurs on the disk files. */ -int sqlite3BtreeSyncDisabled(Btree *pBt){ +int sqlite3BtreeSyncDisabled(Btree *p){ + BtShared *pBt = p->pBt; assert( pBt && pBt->pPager ); return sqlite3pager_nosync(pBt->pPager); } @@ -1370,7 +1823,8 @@ int sqlite3BtreeSyncDisabled(Btree *pBt){ ** 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){ +int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve){ + BtShared *pBt = p->pBt; if( pBt->pageSizeFixed ){ return SQLITE_READONLY; } @@ -1380,6 +1834,7 @@ int sqlite3BtreeSetPageSize(Btree *pBt, int pageSize, int nReserve){ if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE && ((pageSize-1)&pageSize)==0 ){ assert( (pageSize & 7)==0 ); + assert( !pBt->pPage1 && !pBt->pCursor ); pBt->pageSize = sqlite3pager_set_pagesize(pBt->pPager, pageSize); } pBt->usableSize = pBt->pageSize - nReserve; @@ -1389,11 +1844,11 @@ int sqlite3BtreeSetPageSize(Btree *pBt, int pageSize, int nReserve){ /* ** Return the currently defined page size */ -int sqlite3BtreeGetPageSize(Btree *pBt){ - return pBt->pageSize; +int sqlite3BtreeGetPageSize(Btree *p){ + return p->pBt->pageSize; } -int sqlite3BtreeGetReserve(Btree *pBt){ - return pBt->pageSize - pBt->usableSize; +int sqlite3BtreeGetReserve(Btree *p){ + return p->pBt->pageSize - p->pBt->usableSize; } #endif /* !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) */ @@ -1403,7 +1858,8 @@ int sqlite3BtreeGetReserve(Btree *pBt){ ** is disabled. The default value for the auto-vacuum property is ** determined by the SQLITE_DEFAULT_AUTOVACUUM macro. */ -int sqlite3BtreeSetAutoVacuum(Btree *pBt, int autoVacuum){ +int sqlite3BtreeSetAutoVacuum(Btree *p, int autoVacuum){ + BtShared *pBt = p->pBt;; #ifdef SQLITE_OMIT_AUTOVACUUM return SQLITE_READONLY; #else @@ -1419,11 +1875,11 @@ int sqlite3BtreeSetAutoVacuum(Btree *pBt, int autoVacuum){ ** Return the value of the 'auto-vacuum' property. If auto-vacuum is ** enabled 1 is returned. Otherwise 0. */ -int sqlite3BtreeGetAutoVacuum(Btree *pBt){ +int sqlite3BtreeGetAutoVacuum(Btree *p){ #ifdef SQLITE_OMIT_AUTOVACUUM return 0; #else - return pBt->autoVacuum; + return p->pBt->autoVacuum; #endif } @@ -1438,7 +1894,7 @@ int sqlite3BtreeGetAutoVacuum(Btree *pBt){ ** is returned if we run out of memory. SQLITE_PROTOCOL is returned ** if there is a locking protocol violation. */ -static int lockBtree(Btree *pBt){ +static int lockBtree(BtShared *pBt){ int rc, pageSize; MemPage *pPage1; if( pBt->pPage1 ) return SQLITE_OK; @@ -1510,11 +1966,18 @@ page1_init_failed: ** This routine works like lockBtree() except that it also invokes the ** busy callback if there is lock contention. */ -static int lockBtreeWithRetry(Btree *pBt){ +static int lockBtreeWithRetry(Btree *pRef){ int rc = SQLITE_OK; - if( pBt->inTrans==TRANS_NONE ){ - rc = sqlite3BtreeBeginTrans(pBt, 0); - pBt->inTrans = TRANS_NONE; + if( pRef->inTrans==TRANS_NONE ){ + u8 inTransaction = pRef->pBt->inTransaction; + btreeIntegrity(pRef); + rc = sqlite3BtreeBeginTrans(pRef, 0); + pRef->pBt->inTransaction = inTransaction; + pRef->inTrans = TRANS_NONE; + if( rc==SQLITE_OK ){ + pRef->pBt->nTransaction--; + } + btreeIntegrity(pRef); } return rc; } @@ -1530,11 +1993,11 @@ static int lockBtreeWithRetry(Btree *pBt){ ** ** If there is a transaction in progress, this routine is a no-op. */ -static void unlockBtreeIfUnused(Btree *pBt){ - if( pBt->inTrans==TRANS_NONE && pBt->pCursor==0 && pBt->pPage1!=0 ){ +static void unlockBtreeIfUnused(BtShared *pBt){ + if( pBt->inTransaction==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 = &((u8*)pPage)[-pBt->pageSize]; pPage->pBt = pBt; pPage->pgno = 1; } @@ -1548,7 +2011,7 @@ static void unlockBtreeIfUnused(Btree *pBt){ ** Create a new database by initializing the first page of the ** file. */ -static int newDatabase(Btree *pBt){ +static int newDatabase(BtShared *pBt){ MemPage *pP1; unsigned char *data; int rc; @@ -1613,14 +2076,17 @@ static int newDatabase(Btree *pBt){ ** when A already has a read lock, we encourage A to give up and let B ** proceed. */ -int sqlite3BtreeBeginTrans(Btree *pBt, int wrflag){ +int sqlite3BtreeBeginTrans(Btree *p, int wrflag){ + BtShared *pBt = p->pBt; int rc = SQLITE_OK; + btreeIntegrity(p); + /* If the btree is already in a write-transaction, or it ** is already in a read-transaction and a read-transaction ** is requested, this is a no-op. */ - if( pBt->inTrans==TRANS_WRITE || (pBt->inTrans==TRANS_READ && !wrflag) ){ + if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){ return SQLITE_OK; } @@ -1629,6 +2095,14 @@ int sqlite3BtreeBeginTrans(Btree *pBt, int wrflag){ return SQLITE_READONLY; } + /* If another database handle has already opened a write transaction + ** on this shared-btree structure and a second write transaction is + ** requested, return SQLITE_BUSY. + */ + if( pBt->inTransaction==TRANS_WRITE && wrflag ){ + return SQLITE_BUSY; + } + do { if( pBt->pPage1==0 ){ rc = lockBtree(pBt); @@ -1642,13 +2116,24 @@ int sqlite3BtreeBeginTrans(Btree *pBt, int wrflag){ } if( rc==SQLITE_OK ){ - pBt->inTrans = (wrflag?TRANS_WRITE:TRANS_READ); if( wrflag ) pBt->inStmt = 0; }else{ unlockBtreeIfUnused(pBt); } - }while( rc==SQLITE_BUSY && pBt->inTrans==TRANS_NONE && + }while( rc==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE && sqlite3InvokeBusyHandler(pBt->pBusyHandler) ); + + if( rc==SQLITE_OK ){ + if( p->inTrans==TRANS_NONE ){ + pBt->nTransaction++; + } + p->inTrans = (wrflag?TRANS_WRITE:TRANS_READ); + if( p->inTrans>pBt->inTransaction ){ + pBt->inTransaction = p->inTrans; + } + } + + btreeIntegrity(p); return rc; } @@ -1663,7 +2148,7 @@ 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; + BtShared *pBt = pPage->pBt; int isInitOrig = pPage->isInit; Pgno pgno = pPage->pgno; @@ -1763,7 +2248,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ ** database. The pDbPage reference remains valid. */ static int relocatePage( - Btree *pBt, /* Btree */ + BtShared *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 */ @@ -1833,19 +2318,19 @@ static int relocatePage( } /* Forward declaration required by autoVacuumCommit(). */ -static int allocatePage(Btree *, MemPage **, Pgno *, Pgno, u8); +static int allocatePage(BtShared *, 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){ +static int autoVacuumCommit(BtShared *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 */ + 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 */ @@ -1928,6 +2413,12 @@ static int autoVacuumCommit(Btree *pBt, Pgno *nTrunc){ releasePage(pFreeMemPage); pFreeMemPage = 0; + /* Relocate the page into the body of the file. Note that although the + ** page has moved within the database file, the pDbMemPage pointer + ** remains valid. This means that this function can run without + ** invalidating cursors open on the btree. This is important in + ** shared-cache mode. + */ rc = relocatePage(pBt, pDbMemPage, eType, iPtrPage, iFreePage); releasePage(pDbMemPage); if( rc!=SQLITE_OK ) goto autovacuum_out; @@ -1959,15 +2450,47 @@ autovacuum_out: ** This will release the write lock on the database file. If there ** are no active cursors, it also releases the read lock. */ -int sqlite3BtreeCommit(Btree *pBt){ - int rc = SQLITE_OK; - if( pBt->inTrans==TRANS_WRITE ){ +int sqlite3BtreeCommit(Btree *p){ + BtShared *pBt = p->pBt; + + btreeIntegrity(p); + + /* If the handle has a write-transaction open, commit the shared-btrees + ** transaction and set the shared state to TRANS_READ. + */ + if( p->inTrans==TRANS_WRITE ){ + int rc; + assert( pBt->inTransaction==TRANS_WRITE ); + assert( pBt->nTransaction>0 ); rc = sqlite3pager_commit(pBt->pPager); + if( rc!=SQLITE_OK ){ + return rc; + } + pBt->inTransaction = TRANS_READ; + pBt->inStmt = 0; } - pBt->inTrans = TRANS_NONE; - pBt->inStmt = 0; + unlockAllTables(p); + + /* If the handle has any kind of transaction open, decrement the transaction + ** count of the shared btree. If the transaction count reaches 0, set + ** the shared state to TRANS_NONE. The unlockBtreeIfUnused() call below + ** will unlock the pager. + */ + if( p->inTrans!=TRANS_NONE ){ + pBt->nTransaction--; + if( 0==pBt->nTransaction ){ + pBt->inTransaction = TRANS_NONE; + } + } + + /* Set the handles current transaction state to TRANS_NONE and unlock + ** the pager if this call closed the only read or write transaction. + */ + p->inTrans = TRANS_NONE; unlockBtreeIfUnused(pBt); - return rc; + + btreeIntegrity(p); + return SQLITE_OK; } #ifndef NDEBUG @@ -1976,29 +2499,30 @@ int sqlite3BtreeCommit(Btree *pBt){ ** in assert() expressions, so it is only compiled if NDEBUG is not ** defined. */ -static int countWriteCursors(Btree *pBt){ +static int countWriteCursors(BtShared *pBt){ BtCursor *pCur; int r = 0; for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ - if( pCur->wrFlag ) r++; + if( pCur->wrFlag ) r++; } return r; } #endif -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) /* ** Print debugging information about all cursors to standard output. */ -void sqlite3BtreeCursorList(Btree *pBt){ +void sqlite3BtreeCursorList(Btree *p){ BtCursor *pCur; + BtShared *pBt = p->pBt; for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ MemPage *pPage = pCur->pPage; char *zMode = pCur->wrFlag ? "rw" : "ro"; sqlite3DebugPrintf("CURSOR %p rooted at %4d(%s) currently at %d.%d%s\n", pCur, pCur->pgnoRoot, zMode, pPage ? pPage->pgno : 0, pCur->idx, - pCur->isValid ? "" : " eof" + (pCur->eState==CURSOR_VALID) ? "" : " eof" ); } } @@ -2013,11 +2537,41 @@ void sqlite3BtreeCursorList(Btree *pBt){ ** This will release the write lock on the database file. If there ** are no active cursors, it also releases the read lock. */ -int sqlite3BtreeRollback(Btree *pBt){ - int rc = SQLITE_OK; +int sqlite3BtreeRollback(Btree *p){ + int rc; + BtShared *pBt = p->pBt; MemPage *pPage1; - if( pBt->inTrans==TRANS_WRITE ){ - rc = sqlite3pager_rollback(pBt->pPager); + + rc = saveAllCursors(pBt, 0, 0); +#ifndef SQLITE_OMIT_SHARED_CACHE + if( rc!=SQLITE_OK ){ + /* This is a horrible situation. An IO or malloc() error occured whilst + ** trying to save cursor positions. If this is an automatic rollback (as + ** the result of a constraint, malloc() failure or IO error) then + ** the cache may be internally inconsistent (not contain valid trees) so + ** we cannot simply return the error to the caller. Instead, abort + ** all queries that may be using any of the cursors that failed to save. + */ + while( pBt->pCursor ){ + sqlite3 *db = pBt->pCursor->pBtree->pSqlite; + if( db ){ + sqlite3AbortOtherActiveVdbes(db, 0); + } + } + } +#endif + btreeIntegrity(p); + unlockAllTables(p); + + if( p->inTrans==TRANS_WRITE ){ + int rc2; + + assert( TRANS_WRITE==pBt->inTransaction ); + rc2 = sqlite3pager_rollback(pBt->pPager); + if( rc2!=SQLITE_OK ){ + rc = rc2; + } + /* The rollback may have destroyed the pPage1->aData value. So ** call getPage() on page 1 again to make sure pPage1->aData is ** set correctly. */ @@ -2025,10 +2579,22 @@ int sqlite3BtreeRollback(Btree *pBt){ releasePage(pPage1); } assert( countWriteCursors(pBt)==0 ); + pBt->inTransaction = TRANS_READ; } - pBt->inTrans = TRANS_NONE; + + if( p->inTrans!=TRANS_NONE ){ + assert( pBt->nTransaction>0 ); + pBt->nTransaction--; + if( 0==pBt->nTransaction ){ + pBt->inTransaction = TRANS_NONE; + } + } + + p->inTrans = TRANS_NONE; pBt->inStmt = 0; unlockBtreeIfUnused(pBt); + + btreeIntegrity(p); return rc; } @@ -2047,11 +2613,13 @@ int sqlite3BtreeRollback(Btree *pBt){ ** error occurs within the statement, the effect of that one statement ** can be rolled back without having to rollback the entire transaction. */ -int sqlite3BtreeBeginStmt(Btree *pBt){ +int sqlite3BtreeBeginStmt(Btree *p){ int rc; - if( (pBt->inTrans!=TRANS_WRITE) || pBt->inStmt ){ + BtShared *pBt = p->pBt; + if( (p->inTrans!=TRANS_WRITE) || pBt->inStmt ){ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } + assert( pBt->inTransaction==TRANS_WRITE ); rc = pBt->readOnly ? SQLITE_OK : sqlite3pager_stmt_begin(pBt->pPager); pBt->inStmt = 1; return rc; @@ -2062,8 +2630,9 @@ int sqlite3BtreeBeginStmt(Btree *pBt){ ** Commit the statment subtransaction currently in progress. If no ** subtransaction is active, this is a no-op. */ -int sqlite3BtreeCommitStmt(Btree *pBt){ +int sqlite3BtreeCommitStmt(Btree *p){ int rc; + BtShared *pBt = p->pBt; if( pBt->inStmt && !pBt->readOnly ){ rc = sqlite3pager_stmt_commit(pBt->pPager); }else{ @@ -2081,12 +2650,16 @@ int sqlite3BtreeCommitStmt(Btree *pBt){ ** to use a cursor that was open at the beginning of this operation ** will result in an error. */ -int sqlite3BtreeRollbackStmt(Btree *pBt){ - int rc; - if( pBt->inStmt==0 || pBt->readOnly ) return SQLITE_OK; - rc = sqlite3pager_stmt_rollback(pBt->pPager); - assert( countWriteCursors(pBt)==0 ); - pBt->inStmt = 0; +int sqlite3BtreeRollbackStmt(Btree *p){ + int rc = SQLITE_OK; + BtShared *pBt = p->pBt; + sqlite3MallocDisallow(); + if( pBt->inStmt && !pBt->readOnly ){ + rc = sqlite3pager_stmt_rollback(pBt->pPager); + assert( countWriteCursors(pBt)==0 ); + pBt->inStmt = 0; + } + sqlite3MallocAllow(); return rc; } @@ -2150,7 +2723,7 @@ static int dfltCompare( ** always ignored for INTKEY tables. */ int sqlite3BtreeCursor( - Btree *pBt, /* The btree */ + Btree *p, /* The btree */ int iTable, /* Root page of table to open */ int wrFlag, /* 1 to write. 0 read-only */ int (*xCmp)(void*,int,const void*,int,const void*), /* Key Comparison func */ @@ -2159,6 +2732,7 @@ int sqlite3BtreeCursor( ){ int rc; BtCursor *pCur; + BtShared *pBt = p->pBt; *ppCur = 0; if( wrFlag ){ @@ -2169,19 +2743,19 @@ int sqlite3BtreeCursor( return SQLITE_LOCKED; } } + if( pBt->pPage1==0 ){ - rc = lockBtreeWithRetry(pBt); + rc = lockBtreeWithRetry(p); if( rc!=SQLITE_OK ){ return rc; } } - pCur = sqliteMallocRaw( sizeof(*pCur) ); + pCur = sqliteMalloc( sizeof(*pCur) ); if( pCur==0 ){ rc = SQLITE_NOMEM; goto create_cursor_exception; } pCur->pgnoRoot = (Pgno)iTable; - pCur->pPage = 0; /* For exit-handler, in case getAndInitPage() fails. */ if( iTable==1 && sqlite3pager_pagecount(pBt->pPager)==0 ){ rc = SQLITE_EMPTY; goto create_cursor_exception; @@ -2190,22 +2764,24 @@ int sqlite3BtreeCursor( if( rc!=SQLITE_OK ){ goto create_cursor_exception; } + + /* Now that no other errors can occur, finish filling in the BtCursor + ** variables, link the cursor into the BtShared list and set *ppCur (the + ** output argument to this function). + */ pCur->xCompare = xCmp ? xCmp : dfltCompare; pCur->pArg = pArg; - pCur->pBt = pBt; + pCur->pBtree = p; pCur->wrFlag = wrFlag; - pCur->idx = 0; - memset(&pCur->info, 0, sizeof(pCur->info)); pCur->pNext = pBt->pCursor; if( pCur->pNext ){ pCur->pNext->pPrev = pCur; } - pCur->pPrev = 0; pBt->pCursor = pCur; - pCur->isValid = 0; + pCur->eState = CURSOR_INVALID; *ppCur = pCur; - return SQLITE_OK; + return SQLITE_OK; create_cursor_exception: if( pCur ){ releasePage(pCur->pPage); @@ -2234,7 +2810,8 @@ void sqlite3BtreeSetCompare( ** when the last cursor is closed. */ int sqlite3BtreeCloseCursor(BtCursor *pCur){ - Btree *pBt = pCur->pBt; + BtShared *pBt = pCur->pBtree->pBt; + restoreOrClearCursorPosition(pCur, 0); if( pCur->pPrev ){ pCur->pPrev->pNext = pCur->pNext; }else{ @@ -2301,13 +2878,17 @@ static void getCellInfo(BtCursor *pCur){ ** itself, not the number of bytes in the key. */ int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ - if( !pCur->isValid ){ - *pSize = 0; - }else{ - getCellInfo(pCur); - *pSize = pCur->info.nKey; + int rc = restoreOrClearCursorPosition(pCur, 1); + if( rc==SQLITE_OK ){ + assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); + if( pCur->eState==CURSOR_INVALID ){ + *pSize = 0; + }else{ + getCellInfo(pCur); + *pSize = pCur->info.nKey; + } } - return SQLITE_OK; + return rc; } /* @@ -2318,14 +2899,18 @@ int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ ** the database is empty) then *pSize is set to 0. */ int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){ - if( !pCur->isValid ){ - /* Not pointing at a valid entry - set *pSize to 0. */ - *pSize = 0; - }else{ - getCellInfo(pCur); - *pSize = pCur->info.nData; + int rc = restoreOrClearCursorPosition(pCur, 1); + if( rc==SQLITE_OK ){ + assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); + if( pCur->eState==CURSOR_INVALID ){ + /* Not pointing at a valid entry - set *pSize to 0. */ + *pSize = 0; + }else{ + getCellInfo(pCur); + *pSize = pCur->info.nData; + } } - return SQLITE_OK; + return rc; } /* @@ -2348,19 +2933,18 @@ static int getPayload( Pgno nextPage; int rc; MemPage *pPage; - Btree *pBt; + BtShared *pBt; int ovflSize; u32 nKey; assert( pCur!=0 && pCur->pPage!=0 ); - assert( pCur->isValid ); - pBt = pCur->pBt; + assert( pCur->eState==CURSOR_VALID ); + pBt = pCur->pBtree->pBt; pPage = pCur->pPage; pageIntegrity(pPage); assert( pCur->idx>=0 && pCur->idxnCell ); getCellInfo(pCur); - aPayload = pCur->info.pCell; - aPayload += pCur->info.nHeader; + aPayload = pCur->info.pCell + pCur->info.nHeader; if( pPage->intKey ){ nKey = 0; }else{ @@ -2429,14 +3013,18 @@ static int getPayload( ** the available payload. */ int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ - assert( pCur->isValid ); - assert( pCur->pPage!=0 ); - if( pCur->pPage->intKey ){ - return SQLITE_CORRUPT_BKPT; + int rc = restoreOrClearCursorPosition(pCur, 1); + if( rc==SQLITE_OK ){ + assert( pCur->eState==CURSOR_VALID ); + assert( pCur->pPage!=0 ); + if( pCur->pPage->intKey ){ + return SQLITE_CORRUPT_BKPT; + } + assert( pCur->pPage->intKey==0 ); + assert( pCur->idx>=0 && pCur->idxpPage->nCell ); + rc = getPayload(pCur, offset, amt, (unsigned char*)pBuf, 0); } - assert( pCur->pPage->intKey==0 ); - assert( pCur->idx>=0 && pCur->idxpPage->nCell ); - return getPayload(pCur, offset, amt, (unsigned char*)pBuf, 0); + return rc; } /* @@ -2449,10 +3037,14 @@ int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ ** the available payload. */ int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ - assert( pCur->isValid ); - assert( pCur->pPage!=0 ); - assert( pCur->idx>=0 && pCur->idxpPage->nCell ); - return getPayload(pCur, offset, amt, pBuf, 1); + int rc = restoreOrClearCursorPosition(pCur, 1); + if( rc==SQLITE_OK ){ + assert( pCur->eState==CURSOR_VALID ); + assert( pCur->pPage!=0 ); + assert( pCur->idx>=0 && pCur->idxpPage->nCell ); + rc = getPayload(pCur, offset, amt, pBuf, 1); + } + return rc; } /* @@ -2485,7 +3077,7 @@ static const unsigned char *fetchPayload( int nLocal; assert( pCur!=0 && pCur->pPage!=0 ); - assert( pCur->isValid ); + assert( pCur->eState==CURSOR_VALID ); pPage = pCur->pPage; pageIntegrity(pPage); assert( pCur->idx>=0 && pCur->idxnCell ); @@ -2523,10 +3115,16 @@ static const unsigned char *fetchPayload( ** in the common case where no overflow pages are used. */ const void *sqlite3BtreeKeyFetch(BtCursor *pCur, int *pAmt){ - return (const void*)fetchPayload(pCur, pAmt, 0); + if( pCur->eState==CURSOR_VALID ){ + return (const void*)fetchPayload(pCur, pAmt, 0); + } + return 0; } const void *sqlite3BtreeDataFetch(BtCursor *pCur, int *pAmt){ - return (const void*)fetchPayload(pCur, pAmt, 1); + if( pCur->eState==CURSOR_VALID ){ + return (const void*)fetchPayload(pCur, pAmt, 1); + } + return 0; } @@ -2538,9 +3136,9 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){ int rc; MemPage *pNewPage; MemPage *pOldPage; - Btree *pBt = pCur->pBt; + BtShared *pBt = pCur->pBtree->pBt; - assert( pCur->isValid ); + assert( pCur->eState==CURSOR_VALID ); rc = getAndInitPage(pBt, newPgno, &pNewPage, pCur->pPage); if( rc ) return rc; pageIntegrity(pNewPage); @@ -2587,7 +3185,7 @@ static void moveToParent(BtCursor *pCur){ MemPage *pPage; int idxParent; - assert( pCur->isValid ); + assert( pCur->eState==CURSOR_VALID ); pPage = pCur->pPage; assert( pPage!=0 ); assert( !isRootPage(pPage) ); @@ -2609,17 +3207,24 @@ static void moveToParent(BtCursor *pCur){ */ static int moveToRoot(BtCursor *pCur){ MemPage *pRoot; - int rc; - Btree *pBt = pCur->pBt; + int rc = SQLITE_OK; + BtShared *pBt = pCur->pBtree->pBt; - rc = getAndInitPage(pBt, pCur->pgnoRoot, &pRoot, 0); - if( rc ){ - pCur->isValid = 0; - return rc; + restoreOrClearCursorPosition(pCur, 0); + pRoot = pCur->pPage; + if( pRoot && pRoot->pgno==pCur->pgnoRoot ){ + assert( pRoot->isInit ); + }else{ + if( + SQLITE_OK!=(rc = getAndInitPage(pBt, pCur->pgnoRoot, &pRoot, 0)) + ){ + pCur->eState = CURSOR_INVALID; + return rc; + } + releasePage(pCur->pPage); + pageIntegrity(pRoot); + pCur->pPage = pRoot; } - releasePage(pCur->pPage); - pageIntegrity(pRoot); - pCur->pPage = pRoot; pCur->idx = 0; pCur->info.nSize = 0; if( pRoot->nCell==0 && !pRoot->leaf ){ @@ -2627,23 +3232,26 @@ static int moveToRoot(BtCursor *pCur){ assert( pRoot->pgno==1 ); subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]); assert( subpage>0 ); - pCur->isValid = 1; + pCur->eState = CURSOR_VALID; rc = moveToChild(pCur, subpage); } - pCur->isValid = pCur->pPage->nCell>0; + pCur->eState = ((pCur->pPage->nCell>0)?CURSOR_VALID:CURSOR_INVALID); return rc; } /* ** Move the cursor down to the left-most leaf entry beneath the ** entry to which it is currently pointing. +** +** The left-most leaf is the one with the smallest key - the first +** in ascending order. */ static int moveToLeftmost(BtCursor *pCur){ Pgno pgno; int rc; MemPage *pPage; - assert( pCur->isValid ); + assert( pCur->eState==CURSOR_VALID ); while( !(pPage = pCur->pPage)->leaf ){ assert( pCur->idx>=0 && pCur->idxnCell ); pgno = get4byte(findCell(pPage, pCur->idx)); @@ -2659,13 +3267,16 @@ static int moveToLeftmost(BtCursor *pCur){ ** between moveToLeftmost() and moveToRightmost(). moveToLeftmost() ** finds the left-most entry beneath the *entry* whereas moveToRightmost() ** finds the right-most entry beneath the *page*. +** +** The right-most entry is the one with the largest key - the last +** key in ascending order. */ static int moveToRightmost(BtCursor *pCur){ Pgno pgno; int rc; MemPage *pPage; - assert( pCur->isValid ); + assert( pCur->eState==CURSOR_VALID ); while( !(pPage = pCur->pPage)->leaf ){ pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); pCur->idx = pPage->nCell; @@ -2685,7 +3296,7 @@ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){ int rc; rc = moveToRoot(pCur); if( rc ) return rc; - if( pCur->isValid==0 ){ + if( pCur->eState==CURSOR_INVALID ){ assert( pCur->pPage->nCell==0 ); *pRes = 1; return SQLITE_OK; @@ -2704,12 +3315,12 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ int rc; rc = moveToRoot(pCur); if( rc ) return rc; - if( pCur->isValid==0 ){ + if( CURSOR_INVALID==pCur->eState ){ assert( pCur->pPage->nCell==0 ); *pRes = 1; return SQLITE_OK; } - assert( pCur->isValid ); + assert( pCur->eState==CURSOR_VALID ); *pRes = 0; rc = moveToRightmost(pCur); return rc; @@ -2720,7 +3331,7 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ ** ** For INTKEY tables, only the nKey parameter is used. pKey is ** ignored. For other tables, nKey is the number of bytes of data -** in nKey. The comparison function specified when the cursor was +** in pKey. The comparison function specified when the cursor was ** created is used to compare keys. ** ** If an exact match is not found, then the cursor is always @@ -2744,11 +3355,13 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ */ int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, i64 nKey, int *pRes){ int rc; + int tryRightmost; rc = moveToRoot(pCur); if( rc ) return rc; assert( pCur->pPage ); assert( pCur->pPage->isInit ); - if( pCur->isValid==0 ){ + tryRightmost = pCur->pPage->intKey; + if( pCur->eState==CURSOR_INVALID ){ *pRes = -1; assert( pCur->pPage->nCell==0 ); return SQLITE_OK; @@ -2769,18 +3382,29 @@ int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, i64 nKey, int *pRes){ i64 nCellKey; pCur->idx = (lwr+upr)/2; pCur->info.nSize = 0; - sqlite3BtreeKeySize(pCur, &nCellKey); if( pPage->intKey ){ + u8 *pCell; + if( tryRightmost ){ + pCur->idx = upr; + } + pCell = findCell(pPage, pCur->idx) + pPage->childPtrSize; + if( pPage->hasData ){ + u32 dummy; + pCell += getVarint32(pCell, &dummy); + } + getVarint(pCell, (u64 *)&nCellKey); if( nCellKeynKey ){ c = +1; + tryRightmost = 0; }else{ c = 0; } }else{ int available; pCellKey = (void *)fetchPayload(pCur, &available, 0); + nCellKey = pCur->info.nKey; if( available>=nCellKey ){ c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey); }else{ @@ -2840,7 +3464,11 @@ int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, i64 nKey, int *pRes){ ** the first entry. TRUE is also returned if the table is empty. */ int sqlite3BtreeEof(BtCursor *pCur){ - return pCur->isValid==0; + /* TODO: What if the cursor is in CURSOR_REQUIRESEEK but all table entries + ** have been deleted? This API will need to change to return an error code + ** as well as the boolean result value. + */ + return (CURSOR_VALID!=pCur->eState); } /* @@ -2851,10 +3479,24 @@ int sqlite3BtreeEof(BtCursor *pCur){ */ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ int rc; - MemPage *pPage = pCur->pPage; + MemPage *pPage; + +#ifndef SQLITE_OMIT_SHARED_CACHE + rc = restoreOrClearCursorPosition(pCur, 1); + if( rc!=SQLITE_OK ){ + return rc; + } + if( pCur->skip>0 ){ + pCur->skip = 0; + *pRes = 0; + return SQLITE_OK; + } + pCur->skip = 0; +#endif assert( pRes!=0 ); - if( pCur->isValid==0 ){ + pPage = pCur->pPage; + if( CURSOR_INVALID==pCur->eState ){ *pRes = 1; return SQLITE_OK; } @@ -2874,7 +3516,7 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ do{ if( isRootPage(pPage) ){ *pRes = 1; - pCur->isValid = 0; + pCur->eState = CURSOR_INVALID; return SQLITE_OK; } moveToParent(pCur); @@ -2906,7 +3548,21 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ int rc; Pgno pgno; MemPage *pPage; - if( pCur->isValid==0 ){ + +#ifndef SQLITE_OMIT_SHARED_CACHE + rc = restoreOrClearCursorPosition(pCur, 1); + if( rc!=SQLITE_OK ){ + return rc; + } + if( pCur->skip<0 ){ + pCur->skip = 0; + *pRes = 0; + return SQLITE_OK; + } + pCur->skip = 0; +#endif + + if( CURSOR_INVALID==pCur->eState ){ *pRes = 1; return SQLITE_OK; } @@ -2922,7 +3578,7 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ }else{ while( pCur->idx==0 ){ if( isRootPage(pPage) ){ - pCur->isValid = 0; + pCur->eState = CURSOR_INVALID; *pRes = 1; return SQLITE_OK; } @@ -2963,7 +3619,7 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ ** is only used by auto-vacuum databases when allocating a new table. */ static int allocatePage( - Btree *pBt, + BtShared *pBt, MemPage **ppPage, Pgno *pPgno, Pgno nearby, @@ -3181,7 +3837,7 @@ static int allocatePage( ** sqlite3pager_unref() is NOT called for pPage. */ static int freePage(MemPage *pPage){ - Btree *pBt = pPage->pBt; + BtShared *pBt = pPage->pBt; MemPage *pPage1 = pBt->pPage1; int rc, n, k; @@ -3249,7 +3905,7 @@ static int freePage(MemPage *pPage){ ** Free any overflow pages associated with the given Cell. */ static int clearCell(MemPage *pPage, unsigned char *pCell){ - Btree *pBt = pPage->pBt; + BtShared *pBt = pPage->pBt; CellInfo info; Pgno ovflPgno; int rc; @@ -3301,7 +3957,7 @@ static int fillInCell( MemPage *pToRelease = 0; unsigned char *pPrior; unsigned char *pPayload; - Btree *pBt = pPage->pBt; + BtShared *pBt = pPage->pBt; Pgno pgnoOvfl = 0; int nHeader; CellInfo info; @@ -3390,7 +4046,7 @@ static int fillInCell( ** given in the second argument so that MemPage.pParent holds the ** pointer in the third argument. */ -static int reparentPage(Btree *pBt, Pgno pgno, MemPage *pNewParent, int idx){ +static int reparentPage(BtShared *pBt, Pgno pgno, MemPage *pNewParent, int idx){ MemPage *pThis; unsigned char *aData; @@ -3433,7 +4089,7 @@ static int reparentPage(Btree *pBt, Pgno pgno, MemPage *pNewParent, int idx){ */ static int reparentChildPages(MemPage *pPage){ int i; - Btree *pBt = pPage->pBt; + BtShared *pBt = pPage->pBt; int rc = SQLITE_OK; if( pPage->leaf ) return SQLITE_OK; @@ -3666,7 +4322,7 @@ static int balance_quick(MemPage *pPage, MemPage *pParent){ u8 *pCell; int szCell; CellInfo info; - Btree *pBt = pPage->pBt; + BtShared *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 */ @@ -3775,7 +4431,7 @@ static int balance_quick(MemPage *pPage, MemPage *pParent){ */ static int balance_nonroot(MemPage *pPage){ MemPage *pParent; /* The parent of pPage */ - Btree *pBt; /* The whole database */ + BtShared *pBt; /* The whole database */ int nCell = 0; /* Number of cells in apCell[] */ int nMaxCells = 0; /* Allocated size of apCell, szCell, aFrom. */ int nOld; /* Number of pages in apOld[] */ @@ -3796,7 +4452,6 @@ static int balance_nonroot(MemPage *pPage){ MemPage *apCopy[NB]; /* Private copies of apOld[] pages */ MemPage *apNew[NB+2]; /* pPage and up to NB siblings after balancing */ Pgno pgnoNew[NB+2]; /* Page numbers for each page in apNew[] */ - int idxDiv[NB]; /* Indices of divider cells in pParent */ u8 *apDiv[NB]; /* Divider cells in pParent */ int cntNew[NB+2]; /* Index in aCell[] of cell after i-th page */ int szNew[NB+2]; /* Combined size of cells place on i-th page */ @@ -3815,8 +4470,10 @@ static int balance_nonroot(MemPage *pPage){ assert( sqlite3pager_iswriteable(pPage->aData) ); pBt = pPage->pBt; pParent = pPage->pParent; - sqlite3pager_write(pParent->aData); assert( pParent ); + if( SQLITE_OK!=(rc = sqlite3pager_write(pParent->aData)) ){ + return rc; + } TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno)); #ifndef SQLITE_OMIT_QUICKBALANCE @@ -3888,7 +4545,6 @@ static int balance_nonroot(MemPage *pPage){ nDiv = 0; for(i=0, k=nxDiv; inCell ){ - idxDiv[i] = k; apDiv[i] = findCell(pParent, k); nDiv++; assert( !pParent->leaf ); @@ -4326,7 +4982,7 @@ static int balance_shallower(MemPage *pPage){ MemPage *pChild; /* The only child page of pPage */ Pgno pgnoChild; /* Page number for pChild */ int rc = SQLITE_OK; /* Return code from subprocedures */ - Btree *pBt; /* The main BTree structure */ + BtShared *pBt; /* The main BTree structure */ int mxCellPerPage; /* Maximum number of cells per page */ u8 **apCell; /* All cells from pages being balanced */ int *szCell; /* Local size of all cells */ @@ -4428,7 +5084,7 @@ static int balance_deeper(MemPage *pPage){ int rc; /* Return value from subprocedures */ MemPage *pChild; /* Pointer to a new child page */ Pgno pgnoChild; /* Page number of the new child page */ - Btree *pBt; /* The BTree */ + BtShared *pBt; /* The BTree */ int usableSize; /* Total usable size of a page */ u8 *data; /* Content of the parent page */ u8 *cdata; /* Content of the child page */ @@ -4517,10 +5173,12 @@ static int balance(MemPage *pPage, int insert){ ** a page entirely and we do not want to leave any cursors ** pointing to non-existant pages or cells. */ -static int checkReadLocks(Btree *pBt, Pgno pgnoRoot, BtCursor *pExclude){ +static int checkReadLocks(BtShared *pBt, Pgno pgnoRoot, BtCursor *pExclude){ BtCursor *p; for(p=pBt->pCursor; p; p=p->pNext){ + u32 flags = (p->pBtree->pSqlite ? p->pBtree->pSqlite->flags : 0); if( p->pgnoRoot!=pgnoRoot || p==pExclude ) continue; + if( p->wrFlag==0 && flags&SQLITE_ReadUncommitted ) continue; if( p->wrFlag==0 ) return SQLITE_LOCKED; if( p->pPage->pgno!=p->pgnoRoot ){ moveToRoot(p); @@ -4547,11 +5205,11 @@ int sqlite3BtreeInsert( int loc; int szNew; MemPage *pPage; - Btree *pBt = pCur->pBt; + BtShared *pBt = pCur->pBtree->pBt; unsigned char *oldCell; unsigned char *newCell = 0; - if( pBt->inTrans!=TRANS_WRITE ){ + if( pBt->inTransaction!=TRANS_WRITE ){ /* Must start a transaction before doing an insert */ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } @@ -4562,8 +5220,16 @@ int sqlite3BtreeInsert( if( checkReadLocks(pBt, pCur->pgnoRoot, pCur) ){ return SQLITE_LOCKED; /* The table pCur points to has a read lock */ } - rc = sqlite3BtreeMoveto(pCur, pKey, nKey, &loc); - if( rc ) return rc; + + /* Save the positions of any other cursors open on this table */ + restoreOrClearCursorPosition(pCur, 0); + if( + SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) || + SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, &loc)) + ){ + return rc; + } + pPage = pCur->pPage; assert( pPage->intKey || nKey>=0 ); assert( pPage->leaf || !pPage->leafData ); @@ -4579,7 +5245,7 @@ int sqlite3BtreeInsert( if( rc ) goto end_insert; assert( szNew==cellSizePtr(pPage, newCell) ); assert( szNew<=MX_CELL_SIZE(pBt) ); - if( loc==0 && pCur->isValid ){ + if( loc==0 && CURSOR_VALID==pCur->eState ){ int szOld; assert( pCur->idx>=0 && pCur->idxnCell ); oldCell = findCell(pPage, pCur->idx); @@ -4619,10 +5285,10 @@ int sqlite3BtreeDelete(BtCursor *pCur){ unsigned char *pCell; int rc; Pgno pgnoChild = 0; - Btree *pBt = pCur->pBt; + BtShared *pBt = pCur->pBtree->pBt; assert( pPage->isInit ); - if( pBt->inTrans!=TRANS_WRITE ){ + if( pBt->inTransaction!=TRANS_WRITE ){ /* Must start a transaction before doing a delete */ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } @@ -4636,8 +5302,19 @@ int sqlite3BtreeDelete(BtCursor *pCur){ if( checkReadLocks(pBt, pCur->pgnoRoot, pCur) ){ return SQLITE_LOCKED; /* The table pCur points to has a read lock */ } - rc = sqlite3pager_write(pPage->aData); - if( rc ) return rc; + + /* Restore the current cursor position (a no-op if the cursor is not in + ** CURSOR_REQUIRESEEK state) and save the positions of any other cursors + ** open on the same table. Then call sqlite3pager_write() on the page + ** that the entry will be deleted from. + */ + if( + (rc = restoreOrClearCursorPosition(pCur, 1))!=0 || + (rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur))!=0 || + (rc = sqlite3pager_write(pPage->aData))!=0 + ){ + 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 @@ -4660,7 +5337,9 @@ int sqlite3BtreeDelete(BtCursor *pCur){ */ BtCursor leafCur; unsigned char *pNext; - int szNext; + int szNext; /* The compiler warning is wrong: szNext is always + ** initialized before use. Adding an extra initialization + ** to silence the compiler slows down the code. */ int notUsed; unsigned char *tempCell = 0; assert( !pPage->leafData ); @@ -4722,11 +5401,12 @@ int sqlite3BtreeDelete(BtCursor *pCur){ ** BTREE_INTKEY|BTREE_LEAFDATA Used for SQL tables with rowid keys ** BTREE_ZERODATA Used for SQL indices */ -int sqlite3BtreeCreateTable(Btree *pBt, int *piTable, int flags){ +int sqlite3BtreeCreateTable(Btree *p, int *piTable, int flags){ + BtShared *pBt = p->pBt; MemPage *pRoot; Pgno pgnoRoot; int rc; - if( pBt->inTrans!=TRANS_WRITE ){ + if( pBt->inTransaction!=TRANS_WRITE ){ /* Must start a transaction first */ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } @@ -4753,7 +5433,7 @@ int sqlite3BtreeCreateTable(Btree *pBt, int *piTable, int flags){ ** 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); + rc = sqlite3BtreeGetMeta(p, 4, &pgnoRoot); if( rc!=SQLITE_OK ) return rc; pgnoRoot++; @@ -4820,7 +5500,7 @@ int sqlite3BtreeCreateTable(Btree *pBt, int *piTable, int flags){ releasePage(pRoot); return rc; } - rc = sqlite3BtreeUpdateMeta(pBt, 4, pgnoRoot); + rc = sqlite3BtreeUpdateMeta(p, 4, pgnoRoot); if( rc ){ releasePage(pRoot); return rc; @@ -4843,7 +5523,7 @@ int sqlite3BtreeCreateTable(Btree *pBt, int *piTable, int flags){ ** the page to the freelist. */ static int clearDatabasePage( - Btree *pBt, /* The BTree that contains the table */ + BtShared *pBt, /* The BTree that contains the table */ Pgno pgno, /* Page number to clear */ MemPage *pParent, /* Parent page. NULL for the root */ int freePageFlag /* Deallocate page if true */ @@ -4894,23 +5574,35 @@ cleardatabasepage_out: ** read cursors on the table. Open write cursors are moved to the ** root of the table. */ -int sqlite3BtreeClearTable(Btree *pBt, int iTable){ +int sqlite3BtreeClearTable(Btree *p, int iTable){ int rc; BtCursor *pCur; - if( pBt->inTrans!=TRANS_WRITE ){ + BtShared *pBt = p->pBt; + sqlite3 *db = p->pSqlite; + if( p->inTrans!=TRANS_WRITE ){ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } - for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ - if( pCur->pgnoRoot==(Pgno)iTable ){ - if( pCur->wrFlag==0 ) return SQLITE_LOCKED; - moveToRoot(pCur); + + /* If this connection is not in read-uncommitted mode and currently has + ** a read-cursor open on the table being cleared, return SQLITE_LOCKED. + */ + if( 0==db || 0==(db->flags&SQLITE_ReadUncommitted) ){ + for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ + if( pCur->pBtree==p && pCur->pgnoRoot==(Pgno)iTable ){ + if( 0==pCur->wrFlag ){ + return SQLITE_LOCKED; + } + moveToRoot(pCur); + } } } - rc = clearDatabasePage(pBt, (Pgno)iTable, 0, 0); - if( rc ){ - sqlite3BtreeRollback(pBt); + + /* Save the position of all cursors open on this table */ + if( SQLITE_OK!=(rc = saveAllCursors(pBt, iTable, 0)) ){ + return rc; } - return rc; + + return clearDatabasePage(pBt, (Pgno)iTable, 0, 0); } /* @@ -4933,11 +5625,12 @@ int sqlite3BtreeClearTable(Btree *pBt, int iTable){ ** 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 *piMoved){ +int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){ int rc; MemPage *pPage = 0; + BtShared *pBt = p->pBt; - if( pBt->inTrans!=TRANS_WRITE ){ + if( p->inTrans!=TRANS_WRITE ){ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } @@ -4953,7 +5646,7 @@ int sqlite3BtreeDropTable(Btree *pBt, int iTable, int *piMoved){ rc = getPage(pBt, (Pgno)iTable, &pPage); if( rc ) return rc; - rc = sqlite3BtreeClearTable(pBt, iTable); + rc = sqlite3BtreeClearTable(p, iTable); if( rc ){ releasePage(pPage); return rc; @@ -4968,7 +5661,7 @@ int sqlite3BtreeDropTable(Btree *pBt, int iTable, int *piMoved){ #else if( pBt->autoVacuum ){ Pgno maxRootPgno; - rc = sqlite3BtreeGetMeta(pBt, 4, &maxRootPgno); + rc = sqlite3BtreeGetMeta(p, 4, &maxRootPgno); if( rc!=SQLITE_OK ){ releasePage(pPage); return rc; @@ -5025,7 +5718,7 @@ int sqlite3BtreeDropTable(Btree *pBt, int iTable, int *piMoved){ } assert( maxRootPgno!=PENDING_BYTE_PAGE(pBt) ); - rc = sqlite3BtreeUpdateMeta(pBt, 4, maxRootPgno); + rc = sqlite3BtreeUpdateMeta(p, 4, maxRootPgno); }else{ rc = freePage(pPage); releasePage(pPage); @@ -5050,9 +5743,20 @@ int sqlite3BtreeDropTable(Btree *pBt, int iTable, int *piMoved){ ** layer (and the SetCookie and ReadCookie opcodes) the number of ** free pages is not visible. So Cookie[0] is the same as Meta[1]. */ -int sqlite3BtreeGetMeta(Btree *pBt, int idx, u32 *pMeta){ +int sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){ int rc; unsigned char *pP1; + BtShared *pBt = p->pBt; + + /* Reading a meta-data value requires a read-lock on page 1 (and hence + ** the sqlite_master table. We grab this lock regardless of whether or + ** not the SQLITE_ReadUncommitted flag is set (the table rooted at page + ** 1 is treated as a special case by queryTableLock() and lockTable()). + */ + rc = queryTableLock(p, 1, READ_LOCK); + if( rc!=SQLITE_OK ){ + return rc; + } assert( idx>=0 && idx<=15 ); rc = sqlite3pager_get(pBt->pPager, 1, (void**)&pP1); @@ -5067,18 +5771,21 @@ int sqlite3BtreeGetMeta(Btree *pBt, int idx, u32 *pMeta){ if( idx==4 && *pMeta>0 ) pBt->readOnly = 1; #endif - return SQLITE_OK; + /* Grab the read-lock on page 1. */ + rc = lockTable(p, 1, READ_LOCK); + return rc; } /* ** Write meta-information back into the database. Meta[0] is ** read-only and may not be written. */ -int sqlite3BtreeUpdateMeta(Btree *pBt, int idx, u32 iMeta){ +int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){ + BtShared *pBt = p->pBt; unsigned char *pP1; int rc; assert( idx>=1 && idx<=15 ); - if( pBt->inTrans!=TRANS_WRITE ){ + if( p->inTrans!=TRANS_WRITE ){ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } assert( pBt->pPage1!=0 ); @@ -5094,6 +5801,9 @@ int sqlite3BtreeUpdateMeta(Btree *pBt, int idx, u32 iMeta){ ** is currently pointing to. */ int sqlite3BtreeFlags(BtCursor *pCur){ + /* TODO: What about CURSOR_REQUIRESEEK state? Probably need to call + ** restoreOrClearCursorPosition() here. + */ MemPage *pPage = pCur->pPage; return pPage ? pPage->aData[pPage->hdrOffset] : 0; } @@ -5103,7 +5813,7 @@ int sqlite3BtreeFlags(BtCursor *pCur){ ** Print a disassembly of the given page on standard output. This routine ** is used for debugging and testing only. */ -static int btreePageDump(Btree *pBt, int pgno, int recursive, MemPage *pParent){ +static int btreePageDump(BtShared *pBt, int pgno, int recursive, MemPage *pParent){ int rc; MemPage *pPage; int i, j, c; @@ -5199,12 +5909,12 @@ static int btreePageDump(Btree *pBt, int pgno, int recursive, MemPage *pParent){ fflush(stdout); return SQLITE_OK; } -int sqlite3BtreePageDump(Btree *pBt, int pgno, int recursive){ - return btreePageDump(pBt, pgno, recursive, 0); +int sqlite3BtreePageDump(Btree *p, int pgno, int recursive){ + return btreePageDump(p->pBt, pgno, recursive, 0); } #endif -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) /* ** Fill aResult[] with information about the entry and page that the ** cursor is pointing to. @@ -5227,6 +5937,11 @@ int sqlite3BtreeCursorInfo(BtCursor *pCur, int *aResult, int upCnt){ MemPage *pPage = pCur->pPage; BtCursor tmpCur; + int rc = restoreOrClearCursorPosition(pCur, 1); + if( rc!=SQLITE_OK ){ + return rc; + } + pageIntegrity(pPage); assert( pPage->isInit ); getTempCursor(pCur, &tmpCur); @@ -5273,8 +5988,8 @@ int sqlite3BtreeCursorInfo(BtCursor *pCur, int *aResult, int upCnt){ ** Return the pager associated with a BTree. This routine is used for ** testing and debugging only. */ -Pager *sqlite3BtreePager(Btree *pBt){ - return pBt->pPager; +Pager *sqlite3BtreePager(Btree *p){ + return p->pBt->pPager; } /* @@ -5283,7 +5998,7 @@ Pager *sqlite3BtreePager(Btree *pBt){ */ typedef struct IntegrityCk IntegrityCk; struct IntegrityCk { - Btree *pBt; /* The tree being checked out */ + BtShared *pBt; /* The tree being checked out */ Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */ int nPage; /* Number of pages in the database */ int *anRef; /* Number of times each page is referenced */ @@ -5474,8 +6189,7 @@ static int checkTreePage( int hdr, cellStart; int nCell; u8 *data; - BtCursor cur; - Btree *pBt; + BtShared *pBt; int usableSize; char zContext[100]; char *hit; @@ -5484,7 +6198,7 @@ static int checkTreePage( /* Check that the page exists */ - cur.pBt = pBt = pCheck->pBt; + pBt = pCheck->pBt; usableSize = pBt->usableSize; if( iPage==0 ) return 0; if( checkRef(pCheck, iPage, zParentContext) ) return 0; @@ -5502,7 +6216,6 @@ static int checkTreePage( /* Check out all the cells. */ depth = 0; - cur.pPage = pPage; for(i=0; inCell; i++){ u8 *pCell; int sz; @@ -5618,13 +6331,14 @@ static int checkTreePage( ** and a pointer to that error message is returned. The calling function ** is responsible for freeing the error message when it is done. */ -char *sqlite3BtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){ +char *sqlite3BtreeIntegrityCheck(Btree *p, int *aRoot, int nRoot){ int i; int nRef; IntegrityCk sCheck; + BtShared *pBt = p->pBt; nRef = *sqlite3pager_stats(pBt->pPager); - if( lockBtreeWithRetry(pBt)!=SQLITE_OK ){ + if( lockBtreeWithRetry(p)!=SQLITE_OK ){ return sqliteStrDup("Unable to acquire a read lock on the database"); } sCheck.pBt = pBt; @@ -5706,17 +6420,17 @@ char *sqlite3BtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){ /* ** Return the full pathname of the underlying database file. */ -const char *sqlite3BtreeGetFilename(Btree *pBt){ - assert( pBt->pPager!=0 ); - return sqlite3pager_filename(pBt->pPager); +const char *sqlite3BtreeGetFilename(Btree *p){ + assert( p->pBt->pPager!=0 ); + return sqlite3pager_filename(p->pBt->pPager); } /* ** Return the pathname of the directory that contains the database file. */ -const char *sqlite3BtreeGetDirname(Btree *pBt){ - assert( pBt->pPager!=0 ); - return sqlite3pager_dirname(pBt->pPager); +const char *sqlite3BtreeGetDirname(Btree *p){ + assert( p->pBt->pPager!=0 ); + return sqlite3pager_dirname(p->pBt->pPager); } /* @@ -5724,9 +6438,9 @@ const char *sqlite3BtreeGetDirname(Btree *pBt){ ** value of this routine is the same regardless of whether the journal file ** has been created or not. */ -const char *sqlite3BtreeGetJournalname(Btree *pBt){ - assert( pBt->pPager!=0 ); - return sqlite3pager_journalname(pBt->pPager); +const char *sqlite3BtreeGetJournalname(Btree *p){ + assert( p->pBt->pPager!=0 ); + return sqlite3pager_journalname(p->pBt->pPager); } #ifndef SQLITE_OMIT_VACUUM @@ -5737,11 +6451,14 @@ const char *sqlite3BtreeGetJournalname(Btree *pBt){ ** The size of file pBtFrom may be reduced by this operation. ** If anything goes wrong, the transaction on pBtFrom is rolled back. */ -int sqlite3BtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){ +int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){ int rc = SQLITE_OK; Pgno i, nPage, nToPage, iSkip; - if( pBtTo->inTrans!=TRANS_WRITE || pBtFrom->inTrans!=TRANS_WRITE ){ + BtShared *pBtTo = pTo->pBt; + BtShared *pBtFrom = pFrom->pBt; + + if( pTo->inTrans!=TRANS_WRITE || pFrom->inTrans!=TRANS_WRITE ){ return SQLITE_ERROR; } if( pBtTo->pCursor ) return SQLITE_BUSY; @@ -5770,7 +6487,7 @@ int sqlite3BtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){ rc = sqlite3pager_truncate(pBtTo->pPager, nPage); } if( rc ){ - sqlite3BtreeRollback(pBtTo); + sqlite3BtreeRollback(pTo); } return rc; } @@ -5779,15 +6496,15 @@ int sqlite3BtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){ /* ** Return non-zero if a transaction is active. */ -int sqlite3BtreeIsInTrans(Btree *pBt){ - return (pBt && (pBt->inTrans==TRANS_WRITE)); +int sqlite3BtreeIsInTrans(Btree *p){ + return (p && (p->inTrans==TRANS_WRITE)); } /* ** Return non-zero if a statement transaction is active. */ -int sqlite3BtreeIsInStmt(Btree *pBt){ - return (pBt && pBt->inStmt); +int sqlite3BtreeIsInStmt(Btree *p){ + return (p->pBt && p->pBt->inStmt); } /* @@ -5804,8 +6521,9 @@ int sqlite3BtreeIsInStmt(Btree *pBt){ ** Once this is routine has returned, the only thing required to commit ** the write-transaction for this database file is to delete the journal. */ -int sqlite3BtreeSync(Btree *pBt, const char *zMaster){ - if( pBt->inTrans==TRANS_WRITE ){ +int sqlite3BtreeSync(Btree *p, const char *zMaster){ + if( p->inTrans==TRANS_WRITE ){ + BtShared *pBt = p->pBt; #ifndef SQLITE_OMIT_AUTOVACUUM Pgno nTrunc = 0; if( pBt->autoVacuum ){ @@ -5819,15 +6537,75 @@ int sqlite3BtreeSync(Btree *pBt, const char *zMaster){ return SQLITE_OK; } -#ifndef SQLITE_OMIT_GLOBALRECOVER /* -** Reset the btree and underlying pager after a malloc() failure. Any -** transaction that was active when malloc() failed is rolled back. +** This function returns a pointer to a blob of memory associated with +** a single shared-btree. The memory is used by client code for it's own +** purposes (for example, to store a high-level schema associated with +** the shared-btree). The btree layer manages reference counting issues. +** +** The first time this is called on a shared-btree, nBytes bytes of memory +** are allocated, zeroed, and returned to the caller. For each subsequent +** call the nBytes parameter is ignored and a pointer to the same blob +** of memory returned. +** +** Just before the shared-btree is closed, the function passed as the +** xFree argument when the memory allocation was made is invoked on the +** blob of allocated memory. This function should not call sqliteFree() +** on the memory, the btree layer does that. */ -int sqlite3BtreeReset(Btree *pBt){ - if( pBt->pCursor ) return SQLITE_BUSY; - pBt->inTrans = TRANS_NONE; - unlockBtreeIfUnused(pBt); - return sqlite3pager_reset(pBt->pPager); +void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){ + BtShared *pBt = p->pBt; + if( !pBt->pSchema ){ + pBt->pSchema = sqliteMalloc(nBytes); + pBt->xFreeSchema = xFree; + } + return pBt->pSchema; +} + +/* +** Return true if another user of the same shared btree as the argument +** handle holds an exclusive lock on the sqlite_master table. +*/ +int sqlite3BtreeSchemaLocked(Btree *p){ + return (queryTableLock(p, MASTER_ROOT, READ_LOCK)!=SQLITE_OK); +} + +int sqlite3BtreeLockTable(Btree *p, int iTab, u8 isWriteLock){ + int rc = SQLITE_OK; +#ifndef SQLITE_OMIT_SHARED_CACHE + u8 lockType = (isWriteLock?WRITE_LOCK:READ_LOCK); + rc = queryTableLock(p, iTab, lockType); + if( rc==SQLITE_OK ){ + rc = lockTable(p, iTab, lockType); + } +#endif + return rc; +} + +/* +** The following debugging interface has to be in this file (rather +** than in, for example, test1.c) so that it can get access to +** the definition of BtShared. +*/ +#if defined(SQLITE_DEBUG) && defined(TCLSH) +#include +int sqlite3_shared_cache_report( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + const ThreadData *pTd = sqlite3ThreadDataReadOnly(); + if( pTd->useSharedData ){ + BtShared *pBt; + Tcl_Obj *pRet = Tcl_NewObj(); + for(pBt=pTd->pBtree; pBt; pBt=pBt->pNext){ + const char *zFile = sqlite3pager_filename(pBt->pPager); + Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(zFile, -1)); + Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(pBt->nRef)); + } + Tcl_SetObjResult(interp, pRet); + } + return TCL_OK; } #endif diff --git a/mozilla/db/sqlite3/src/btree.h b/mozilla/db/sqlite3/src/btree.h index acc29710f36..70bdbd467ce 100644 --- a/mozilla/db/sqlite3/src/btree.h +++ b/mozilla/db/sqlite3/src/btree.h @@ -13,7 +13,7 @@ ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** -** @(#) $Id: btree.h,v 1.64 2005/08/27 16:36:49 drh Exp $ +** @(#) $Id: btree.h,v 1.69 2006/01/07 13:21:04 danielk1977 Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ @@ -36,10 +36,12 @@ */ typedef struct Btree Btree; typedef struct BtCursor BtCursor; +typedef struct BtShared BtShared; int sqlite3BtreeOpen( const char *zFilename, /* Name of database file to open */ + sqlite3 *db, /* Associated database connection */ Btree **, /* Return open Btree* here */ int flags /* Flags */ ); @@ -74,7 +76,9 @@ int sqlite3BtreeCreateTable(Btree*, int*, int flags); int sqlite3BtreeIsInTrans(Btree*); int sqlite3BtreeIsInStmt(Btree*); int sqlite3BtreeSync(Btree*, const char *zMaster); -int sqlite3BtreeReset(Btree *); +void *sqlite3BtreeSchema(Btree *, int, void(*)(void *)); +int sqlite3BtreeSchemaLocked(Btree *); +int sqlite3BtreeLockTable(Btree *, int, u8); const char *sqlite3BtreeGetFilename(Btree *); const char *sqlite3BtreeGetDirname(Btree *); diff --git a/mozilla/db/sqlite3/src/build.c b/mozilla/db/sqlite3/src/build.c index 9857a8e15b4..a25381250f1 100644 --- a/mozilla/db/sqlite3/src/build.c +++ b/mozilla/db/sqlite3/src/build.c @@ -22,7 +22,7 @@ ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.351 2005/09/20 17:42:23 drh Exp $ +** $Id: build.c,v 1.383 2006/01/24 12:09:19 danielk1977 Exp $ */ #include "sqliteInt.h" #include @@ -36,6 +36,86 @@ void sqlite3BeginParse(Parse *pParse, int explainFlag){ pParse->nVar = 0; } +#ifndef SQLITE_OMIT_SHARED_CACHE +/* +** The TableLock structure is only used by the sqlite3TableLock() and +** codeTableLocks() functions. +*/ +struct TableLock { + int iDb; + int iTab; + u8 isWriteLock; + const char *zName; +}; + +/* +** Have the compiled statement lock the table with rootpage iTab in database +** iDb at the shared-cache level when executed. The isWriteLock argument +** is zero for a read-lock, or non-zero for a write-lock. +** +** The zName parameter should point to the unqualified table name. This is +** used to provide a more informative error message should the lock fail. +*/ +void sqlite3TableLock( + Parse *pParse, + int iDb, + int iTab, + u8 isWriteLock, + const char *zName +){ + int i; + int nBytes; + TableLock *p; + + if( 0==sqlite3ThreadDataReadOnly()->useSharedData || iDb<0 ){ + return; + } + + for(i=0; inTableLock; i++){ + p = &pParse->aTableLock[i]; + if( p->iDb==iDb && p->iTab==iTab ){ + p->isWriteLock = (p->isWriteLock || isWriteLock); + return; + } + } + + nBytes = sizeof(TableLock) * (pParse->nTableLock+1); + sqliteReallocOrFree((void **)&pParse->aTableLock, nBytes); + if( pParse->aTableLock ){ + p = &pParse->aTableLock[pParse->nTableLock++]; + p->iDb = iDb; + p->iTab = iTab; + p->isWriteLock = isWriteLock; + p->zName = zName; + } +} + +/* +** Code an OP_TableLock instruction for each table locked by the +** statement (configured by calls to sqlite3TableLock()). +*/ +static void codeTableLocks(Parse *pParse){ + int i; + Vdbe *pVdbe; + assert( sqlite3ThreadDataReadOnly()->useSharedData || pParse->nTableLock==0 ); + + if( 0==(pVdbe = sqlite3GetVdbe(pParse)) ){ + return; + } + + for(i=0; inTableLock; i++){ + TableLock *p = &pParse->aTableLock[i]; + int p1 = p->iDb; + if( p->isWriteLock ){ + p1 = -1*(p1+1); + } + sqlite3VdbeOp3(pVdbe, OP_TableLock, p1, p->iTab, p->zName, P3_STATIC); + } +} +#else + #define codeTableLocks(x) +#endif + /* ** This routine is called after a single SQL statement has been ** parsed and a VDBE program to execute that statement has been @@ -50,7 +130,7 @@ void sqlite3FinishCoding(Parse *pParse){ sqlite3 *db; Vdbe *v; - if( sqlite3_malloc_failed ) return; + if( sqlite3MallocFailed() ) return; if( pParse->nested ) return; if( !pParse->pVdbe ){ if( pParse->rc==SQLITE_OK && pParse->nErr ){ @@ -82,6 +162,12 @@ void sqlite3FinishCoding(Parse *pParse){ sqlite3VdbeAddOp(v, OP_Transaction, iDb, (mask & pParse->writeMask)!=0); sqlite3VdbeAddOp(v, OP_VerifyCookie, iDb, pParse->cookieValue[iDb]); } + + /* Once all the cookies have been verified and transactions opened, + ** obtain the required table-locks. This is a no-op unless the + ** shared-cache feature is enabled. + */ + codeTableLocks(pParse); sqlite3VdbeAddOp(v, OP_Goto, 0, pParse->cookieGoto); } @@ -168,11 +254,10 @@ Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){ Table *p = 0; int i; assert( zName!=0 ); - assert( (db->flags & SQLITE_Initialized) || db->init.busy ); for(i=OMIT_TEMPDB; inDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue; - p = sqlite3HashFind(&db->aDb[j].tblHash, zName, strlen(zName)+1); + p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName, strlen(zName)+1); if( p ) break; } return p; @@ -224,11 +309,14 @@ Table *sqlite3LocateTable(Parse *pParse, const char *zName, const char *zDbase){ Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){ Index *p = 0; int i; - assert( (db->flags & SQLITE_Initialized) || db->init.busy ); for(i=OMIT_TEMPDB; inDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ + Schema *pSchema = db->aDb[j].pSchema; if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue; - p = sqlite3HashFind(&db->aDb[j].idxHash, zName, strlen(zName)+1); + assert( pSchema || (j==1 && !db->aDb[1].pBt) ); + if( pSchema ){ + p = sqlite3HashFind(&pSchema->idxHash, zName, strlen(zName)+1); + } if( p ) break; } return p; @@ -252,10 +340,9 @@ static void freeIndex(Index *p){ */ static void sqliteDeleteIndex(sqlite3 *db, Index *p){ Index *pOld; + const char *zName = p->zName; - assert( db!=0 && p->zName!=0 ); - pOld = sqlite3HashInsert(&db->aDb[p->iDb].idxHash, p->zName, - strlen(p->zName)+1, 0); + pOld = sqlite3HashInsert(&p->pSchema->idxHash, zName, strlen( zName)+1, 0); assert( pOld==0 || pOld==p ); freeIndex(p); } @@ -269,9 +356,10 @@ static void sqliteDeleteIndex(sqlite3 *db, Index *p){ void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){ Index *pIndex; int len; + Hash *pHash = &db->aDb[iDb].pSchema->idxHash; len = strlen(zIdxName); - pIndex = sqlite3HashInsert(&db->aDb[iDb].idxHash, zIdxName, len+1, 0); + pIndex = sqlite3HashInsert(pHash, zIdxName, len+1, 0); if( pIndex ){ if( pIndex->pTable->pIndex==pIndex ){ pIndex->pTable->pIndex = pIndex->pNext; @@ -299,39 +387,21 @@ void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){ ** single file indicated. */ void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){ - HashElem *pElem; - Hash temp1; - Hash temp2; int i, j; assert( iDb>=0 && iDbnDb ); - db->flags &= ~SQLITE_Initialized; for(i=iDb; inDb; i++){ Db *pDb = &db->aDb[i]; - temp1 = pDb->tblHash; - temp2 = pDb->trigHash; - sqlite3HashInit(&pDb->trigHash, SQLITE_HASH_STRING, 0); - sqlite3HashClear(&pDb->aFKey); - sqlite3HashClear(&pDb->idxHash); - for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){ - sqlite3DeleteTrigger((Trigger*)sqliteHashData(pElem)); + if( pDb->pSchema ){ + sqlite3SchemaFree(pDb->pSchema); } - sqlite3HashClear(&temp2); - sqlite3HashInit(&pDb->tblHash, SQLITE_HASH_STRING, 0); - for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){ - Table *pTab = sqliteHashData(pElem); - sqlite3DeleteTable(db, pTab); - } - sqlite3HashClear(&temp1); - pDb->pSeqTab = 0; - DbClearProperty(db, i, DB_SchemaLoaded); if( iDb>0 ) return; } assert( iDb==0 ); db->flags &= ~SQLITE_InternChanges; /* If one or more of the auxiliary database files has been closed, - ** then remove then from the auxiliary database list. We take the + ** then remove them from the auxiliary database list. We take the ** opportunity to do this here since we have just deleted all of the ** schema hash tables and therefore do not have to make any changes ** to any of those tables. @@ -394,6 +464,7 @@ static void sqliteResetColumnNames(Table *pTable){ sqliteFree(pCol->zName); sqlite3ExprDelete(pCol->pDflt); sqliteFree(pCol->zType); + sqliteFree(pCol->zColl); } sqliteFree(pTable->aCol); } @@ -420,6 +491,8 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ Index *pIndex, *pNext; FKey *pFKey, *pNextFKey; + db = 0; + if( pTable==0 ) return; /* Do not delete the table until the reference count reaches zero. */ @@ -433,7 +506,7 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ */ for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ pNext = pIndex->pNext; - assert( pIndex->iDb==pTable->iDb || (pTable->iDb==0 && pIndex->iDb==1) ); + assert( pIndex->pSchema==pTable->pSchema ); sqliteDeleteIndex(db, pIndex); } @@ -443,8 +516,7 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ */ for(pFKey=pTable->pFKey; pFKey; pFKey=pNextFKey){ pNextFKey = pFKey->pNextFrom; - assert( pTable->iDbnDb ); - assert( sqlite3HashFind(&db->aDb[pTable->iDb].aFKey, + assert( sqlite3HashFind(&pTable->pSchema->aFKey, pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey ); sqliteFree(pFKey); } @@ -456,6 +528,9 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ sqliteFree(pTable->zName); sqliteFree(pTable->zColAff); sqlite3SelectDelete(pTable->pSelect); +#ifndef SQLITE_OMIT_CHECK + sqlite3ExprDelete(pTable->pCheck); +#endif sqliteFree(pTable); } @@ -472,14 +547,14 @@ void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){ assert( iDb>=0 && iDbnDb ); assert( zTabName && zTabName[0] ); pDb = &db->aDb[iDb]; - p = sqlite3HashInsert(&pDb->tblHash, zTabName, strlen(zTabName)+1, 0); + p = sqlite3HashInsert(&pDb->pSchema->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); + pF2 = sqlite3HashFind(&pDb->pSchema->aFKey, pF1->zTo, nTo); if( pF2==pF1 ){ - sqlite3HashInsert(&pDb->aFKey, pF1->zTo, nTo, pF1->pNextTo); + sqlite3HashInsert(&pDb->pSchema->aFKey, pF1->zTo, nTo, pF1->pNextTo); }else{ while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; } if( pF2 ){ @@ -506,7 +581,7 @@ void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){ char *sqlite3NameFromToken(Token *pName){ char *zName; if( pName ){ - zName = sqliteStrNDup(pName->z, pName->n); + zName = sqliteStrNDup((char*)pName->z, pName->n); sqlite3Dequote(zName); }else{ zName = 0; @@ -518,7 +593,9 @@ char *sqlite3NameFromToken(Token *pName){ ** Open the sqlite_master table stored in database number iDb for ** writing. The table is opened using cursor 0. */ -void sqlite3OpenMasterTable(Vdbe *v, int iDb){ +void sqlite3OpenMasterTable(Parse *p, int iDb){ + Vdbe *v = sqlite3GetVdbe(p); + sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb)); sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); sqlite3VdbeAddOp(v, OP_OpenWrite, 0, MASTER_ROOT); sqlite3VdbeAddOp(v, OP_SetNumColumns, 0, 5); /* sqlite_master has 5 columns */ @@ -632,7 +709,8 @@ void sqlite3StartTable( Token *pName1, /* First part of the name of the table or view */ Token *pName2, /* Second part of the name of the table or view */ int isTemp, /* True if this is a TEMP table */ - int isView /* True if this is a VIEW */ + int isView, /* True if this is a VIEW */ + int noErr /* Do nothing if table already exists */ ){ Table *pTable; char *zName = 0; /* The name of the new table */ @@ -710,7 +788,9 @@ void sqlite3StartTable( } pTable = sqlite3FindTable(db, zName, db->aDb[iDb].zName); if( pTable ){ - sqlite3ErrorMsg(pParse, "table %T already exists", pName); + if( !noErr ){ + sqlite3ErrorMsg(pParse, "table %T already exists", pName); + } goto begin_table_error; } if( sqlite3FindIndex(db, zName, 0)!=0 && (iDb==0 || !db->init.busy) ){ @@ -728,7 +808,7 @@ void sqlite3StartTable( pTable->aCol = 0; pTable->iPKey = -1; pTable->pIndex = 0; - pTable->iDb = iDb; + pTable->pSchema = db->aDb[iDb].pSchema; pTable->nRef = 1; if( pParse->pNewTable ) sqlite3DeleteTable(db, pParse->pNewTable); pParse->pNewTable = pTable; @@ -739,7 +819,7 @@ void sqlite3StartTable( */ #ifndef SQLITE_OMIT_AUTOINCREMENT if( !pParse->nested && strcmp(zName, "sqlite_sequence")==0 ){ - db->aDb[iDb].pSeqTab = pTable; + pTable->pSchema->pSeqTab = pTable; } #endif @@ -753,6 +833,7 @@ void sqlite3StartTable( */ if( !db->init.busy && (v = sqlite3GetVdbe(pParse))!=0 ){ int lbl; + int fileFormat; sqlite3BeginWriteOperation(pParse, 0, iDb); /* If the file format and encoding in the database have not been set, @@ -761,9 +842,11 @@ void sqlite3StartTable( 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); + fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ? + 1 : SQLITE_DEFAULT_FILE_FORMAT; + sqlite3VdbeAddOp(v, OP_Integer, fileFormat, 0); sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1); - sqlite3VdbeAddOp(v, OP_Integer, db->enc, 0); + sqlite3VdbeAddOp(v, OP_Integer, ENC(db), 0); sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 4); sqlite3VdbeResolveLabel(v, lbl); @@ -783,7 +866,7 @@ void sqlite3StartTable( { sqlite3VdbeAddOp(v, OP_CreateTable, iDb, 0); } - sqlite3OpenMasterTable(v, iDb); + sqlite3OpenMasterTable(pParse, iDb); sqlite3VdbeAddOp(v, OP_NewRowid, 0, 0); sqlite3VdbeAddOp(v, OP_Dup, 0, 0); sqlite3VdbeAddOp(v, OP_Null, 0, 0); @@ -855,7 +938,6 @@ void sqlite3AddColumn(Parse *pParse, Token *pName){ ** be called next to set pCol->affinity correctly. */ pCol->affinity = SQLITE_AFF_NONE; - pCol->pColl = pParse->db->pDfltColl; p->nCol++; } @@ -891,6 +973,9 @@ void sqlite3AddNotNull(Parse *pParse, int onError){ ** 'CLOB' | SQLITE_AFF_TEXT ** 'TEXT' | SQLITE_AFF_TEXT ** 'BLOB' | SQLITE_AFF_NONE +** 'REAL' | SQLITE_AFF_REAL +** 'FLOA' | SQLITE_AFF_REAL +** 'DOUB' | SQLITE_AFF_REAL ** ** If none of the substrings in the above table are found, ** SQLITE_AFF_NUMERIC is returned. @@ -911,10 +996,21 @@ char sqlite3AffinityType(const Token *pType){ }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_NUMERIC || aff==SQLITE_AFF_REAL) ){ aff = SQLITE_AFF_NONE; +#ifndef SQLITE_OMIT_FLOATING_POINT + }else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l') /* REAL */ + && aff==SQLITE_AFF_NUMERIC ){ + aff = SQLITE_AFF_REAL; + }else if( h==(('f'<<24)+('l'<<16)+('o'<<8)+'a') /* FLOA */ + && aff==SQLITE_AFF_NUMERIC ){ + aff = SQLITE_AFF_REAL; + }else if( h==(('d'<<24)+('o'<<16)+('u'<<8)+'b') /* DOUB */ + && aff==SQLITE_AFF_NUMERIC ){ + aff = SQLITE_AFF_REAL; +#endif }else if( (h&0x00FFFFFF)==(('i'<<16)+('n'<<8)+'t') ){ /* INT */ - aff = SQLITE_AFF_INTEGER; + aff = SQLITE_AFF_INTEGER; break; } } @@ -993,7 +1089,8 @@ 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 */ + int autoInc, /* True if the AUTOINCREMENT keyword is present */ + int sortOrder /* SQLITE_SO_ASC or SQLITE_SO_DESC */ ){ Table *pTab = pParse->pNewTable; char *zType = 0; @@ -1024,7 +1121,8 @@ void sqlite3AddPrimaryKey( if( iCol>=0 && iColnCol ){ zType = pTab->aCol[iCol].zType; } - if( zType && sqlite3StrICmp(zType, "INTEGER")==0 ){ + if( zType && sqlite3StrICmp(zType, "INTEGER")==0 + && sortOrder==SQLITE_SO_ASC ){ pTab->iPKey = iCol; pTab->keyConf = onError; pTab->autoInc = autoInc; @@ -1034,7 +1132,7 @@ void sqlite3AddPrimaryKey( "INTEGER PRIMARY KEY"); #endif }else{ - sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, 0); + sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, 0, sortOrder, 0); pList = 0; } @@ -1043,47 +1141,51 @@ primary_key_exit: return; } +/* +** Add a new CHECK constraint to the table currently under construction. +*/ +void sqlite3AddCheckConstraint( + Parse *pParse, /* Parsing context */ + Expr *pCheckExpr /* The check expression */ +){ +#ifndef SQLITE_OMIT_CHECK + Table *pTab = pParse->pNewTable; + if( pTab ){ + /* The CHECK expression must be duplicated so that tokens refer + ** to malloced space and not the (ephemeral) text of the CREATE TABLE + ** statement */ + pTab->pCheck = sqlite3ExprAnd(pTab->pCheck, sqlite3ExprDup(pCheckExpr)); + } +#endif + sqlite3ExprDelete(pCheckExpr); +} + /* ** Set the collation function of the most recently parsed table column ** to the CollSeq given. */ void sqlite3AddCollateType(Parse *pParse, const char *zType, int nType){ Table *p; - Index *pIdx; - CollSeq *pColl; int i; if( (p = pParse->pNewTable)==0 ) return; i = p->nCol-1; - pColl = sqlite3LocateCollSeq(pParse, zType, nType); - p->aCol[i].pColl = pColl; - - /* If the column is declared as " PRIMARY KEY COLLATE ", - ** then an index may have been created on this column before the - ** collation type was added. Correct this if it is the case. - */ - for(pIdx = p->pIndex; pIdx; pIdx=pIdx->pNext){ - assert( pIdx->nColumn==1 ); - if( pIdx->aiColumn[0]==i ) pIdx->keyInfo.aColl[0] = pColl; - } -} - -/* -** Call sqlite3CheckCollSeq() for all collating sequences in an index, -** in order to verify that all the necessary collating sequences are -** loaded. -*/ -int sqlite3CheckIndexCollSeq(Parse *pParse, Index *pIdx){ - if( pIdx ){ - int i; - for(i=0; inColumn; i++){ - if( sqlite3CheckCollSeq(pParse, pIdx->keyInfo.aColl[i]) ){ - return SQLITE_ERROR; + if( sqlite3LocateCollSeq(pParse, zType, nType) ){ + Index *pIdx; + p->aCol[i].zColl = sqliteStrNDup(zType, nType); + + /* If the column is declared as " PRIMARY KEY COLLATE ", + ** then an index may have been created on this column before the + ** collation type was added. Correct this if it is the case. + */ + for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){ + assert( pIdx->nColumn==1 ); + if( pIdx->aiColumn[0]==i ){ + pIdx->azColl[0] = p->aCol[i].zColl; } } } - return SQLITE_OK; } /* @@ -1102,10 +1204,11 @@ int sqlite3CheckIndexCollSeq(Parse *pParse, Index *pIdx){ */ CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName){ sqlite3 *db = pParse->db; - u8 enc = db->enc; + u8 enc = ENC(db); u8 initbusy = db->init.busy; + CollSeq *pColl; - CollSeq *pColl = sqlite3FindCollSeq(db, enc, zName, nName, initbusy); + pColl = sqlite3FindCollSeq(db, enc, zName, nName, initbusy); if( !initbusy && (!pColl || !pColl->xCmp) ){ pColl = sqlite3GetCollSeq(db, pColl, zName, nName); if( !pColl ){ @@ -1138,7 +1241,7 @@ CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName){ ** 1 chance in 2^32. So we're safe enough. */ void sqlite3ChangeCookie(sqlite3 *db, Vdbe *v, int iDb){ - sqlite3VdbeAddOp(v, OP_Integer, db->aDb[iDb].schema_cookie+1, 0); + sqlite3VdbeAddOp(v, OP_Integer, db->aDb[iDb].pSchema->schema_cookie+1, 0); sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 0); } @@ -1186,7 +1289,7 @@ static void identPut(char *z, int *pIdx, char *zSignedIdent){ ** table. Memory to hold the text of the statement is obtained ** from sqliteMalloc() and must be freed by the calling function. */ -static char *createTableStmt(Table *p){ +static char *createTableStmt(Table *p, int isTemp){ int i, k, n; char *zStmt; char *zSep, *zSep2, *zEnd, *z; @@ -1212,7 +1315,7 @@ static char *createTableStmt(Table *p){ n += 35 + 6*p->nCol; zStmt = sqliteMallocRaw( n ); if( zStmt==0 ) return 0; - strcpy(zStmt, !OMIT_TEMPDB&&p->iDb==1 ? "CREATE TEMP TABLE ":"CREATE TABLE "); + strcpy(zStmt, !OMIT_TEMPDB&&isTemp ? "CREATE TEMP TABLE ":"CREATE TABLE "); k = strlen(zStmt); identPut(zStmt, &k, p->zName); zStmt[k++] = '('; @@ -1259,13 +1362,40 @@ void sqlite3EndTable( ){ Table *p; sqlite3 *db = pParse->db; + int iDb; - if( (pEnd==0 && pSelect==0) || pParse->nErr || sqlite3_malloc_failed ) return; + if( (pEnd==0 && pSelect==0) || pParse->nErr || sqlite3MallocFailed() ) { + return; + } p = pParse->pNewTable; if( p==0 ) return; assert( !db->init.busy || !pSelect ); + iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema); + +#ifndef SQLITE_OMIT_CHECK + /* Resolve names in all CHECK constraint expressions. + */ + if( p->pCheck ){ + SrcList sSrc; /* Fake SrcList for pParse->pNewTable */ + NameContext sNC; /* Name context for pParse->pNewTable */ + + memset(&sNC, 0, sizeof(sNC)); + memset(&sSrc, 0, sizeof(sSrc)); + sSrc.nSrc = 1; + sSrc.a[0].zName = p->zName; + sSrc.a[0].pTab = p; + sSrc.a[0].iCursor = -1; + sNC.pParse = pParse; + sNC.pSrcList = &sSrc; + sNC.isCheck = 1; + if( sqlite3ExprResolveNames(&sNC, p->pCheck) ){ + return; + } + } +#endif /* !defined(SQLITE_OMIT_CHECK) */ + /* If the db->init.busy is 1 it means we are reading the SQL off the ** "sqlite_master" or "sqlite_temp_master" table on the disk. ** So do not write to the disk again. Extract the root page number @@ -1318,11 +1448,16 @@ void sqlite3EndTable( ** Once the SELECT has been coded by sqlite3Select(), it is in a ** suitable state to query for the column names and types to be used ** by the new table. + ** + ** A shared-cache write-lock is not required to write to the new table, + ** as a schema-lock must have already been obtained to create it. Since + ** a schema-lock excludes all other database users, the write-lock would + ** be redundant. */ if( pSelect ){ Table *pSelTab; sqlite3VdbeAddOp(v, OP_Dup, 0, 0); - sqlite3VdbeAddOp(v, OP_Integer, p->iDb, 0); + sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); sqlite3VdbeAddOp(v, OP_OpenWrite, 1, 0); pParse->nTab = 2; sqlite3Select(pParse, pSelect, SRT_Table, 1, 0, 0, 0, 0); @@ -1341,7 +1476,7 @@ void sqlite3EndTable( /* Compute the complete text of the CREATE statement */ if( pSelect ){ - zStmt = createTableStmt(p); + zStmt = createTableStmt(p, p->pSchema==pParse->db->aDb[1].pSchema); }else{ n = pEnd->z - pParse->sNameToken.z + 1; zStmt = sqlite3MPrintf("CREATE %s %.*s", zType2, n, pParse->sNameToken.z); @@ -1357,22 +1492,22 @@ void sqlite3EndTable( "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), + db->aDb[iDb].zName, SCHEMA_TABLE(iDb), zType, p->zName, p->zName, zStmt ); sqliteFree(zStmt); - sqlite3ChangeCookie(db, v, p->iDb); + sqlite3ChangeCookie(db, v, iDb); #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 ){ + Db *pDb = &db->aDb[iDb]; + if( pDb->pSchema->pSeqTab==0 ){ sqlite3NestedParse(pParse, "CREATE TABLE %Q.sqlite_sequence(name,seq)", pDb->zName @@ -1382,7 +1517,7 @@ void sqlite3EndTable( #endif /* Reparse everything to update our internal data structures */ - sqlite3VdbeOp3(v, OP_ParseSchema, p->iDb, 0, + sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, sqlite3MPrintf("tbl_name='%q'",p->zName), P3_DYNAMIC); } @@ -1392,8 +1527,8 @@ void sqlite3EndTable( if( db->init.busy && pParse->nErr==0 ){ Table *pOld; FKey *pFKey; - Db *pDb = &db->aDb[p->iDb]; - pOld = sqlite3HashInsert(&pDb->tblHash, p->zName, strlen(p->zName)+1, p); + Schema *pSchema = p->pSchema; + pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, strlen(p->zName)+1,p); if( pOld ){ assert( p==pOld ); /* Malloc must have failed inside HashInsert() */ return; @@ -1401,8 +1536,8 @@ void sqlite3EndTable( #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); + pFKey->pNextTo = sqlite3HashFind(&pSchema->aFKey, pFKey->zTo, nTo); + sqlite3HashInsert(&pSchema->aFKey, pFKey->zTo, nTo, pFKey); } #endif pParse->pNewTable = 0; @@ -1411,9 +1546,14 @@ void sqlite3EndTable( #ifndef SQLITE_OMIT_ALTERTABLE if( !p->pSelect ){ + const char *zName = (const char *)pParse->sNameToken.z; + int nName; assert( !pSelect && pCons && pEnd ); - if( pCons->z==0 ) pCons = pEnd; - p->addColOffset = 13 + (pCons->z - pParse->sNameToken.z); + if( pCons->z==0 ){ + pCons = pEnd; + } + nName = (const char *)pCons->z - zName; + p->addColOffset = 13 + sqlite3utf8CharLen(zName, nName); } #endif } @@ -1437,20 +1577,22 @@ void sqlite3CreateView( Token sEnd; DbFixer sFix; Token *pName; + int iDb; if( pParse->nVar>0 ){ sqlite3ErrorMsg(pParse, "parameters are not allowed in views"); sqlite3SelectDelete(pSelect); return; } - sqlite3StartTable(pParse, pBegin, pName1, pName2, isTemp, 1); + sqlite3StartTable(pParse, pBegin, pName1, pName2, isTemp, 1, 0); p = pParse->pNewTable; if( p==0 || pParse->nErr ){ sqlite3SelectDelete(pSelect); return; } sqlite3TwoPartName(pParse, pName1, pName2, &pName); - if( sqlite3FixInit(&sFix, pParse, p->iDb, "view", pName) + iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema); + if( sqlite3FixInit(&sFix, pParse, iDb, "view", pName) && sqlite3FixSelect(&sFix, pSelect) ){ sqlite3SelectDelete(pSelect); @@ -1464,6 +1606,9 @@ void sqlite3CreateView( */ p->pSelect = sqlite3SelectDup(pSelect); sqlite3SelectDelete(pSelect); + if( sqlite3MallocFailed() ){ + return; + } if( !pParse->db->init.busy ){ sqlite3ViewGetColumnNames(pParse, p); } @@ -1534,24 +1679,28 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ */ 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; - pTable->aCol = pSelTab->aCol; - pSelTab->nCol = 0; - pSelTab->aCol = 0; - sqlite3DeleteTable(0, pSelTab); - DbSetProperty(pParse->db, pTable->iDb, DB_UnresetViews); - }else{ - pTable->nCol = 0; + if( pSel ){ + 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; + pTable->aCol = pSelTab->aCol; + pSelTab->nCol = 0; + pSelTab->aCol = 0; + sqlite3DeleteTable(0, pSelTab); + pTable->pSchema->flags |= DB_UnresetViews; + }else{ + pTable->nCol = 0; + nErr++; + } + sqlite3SelectDelete(pSel); + } else { nErr++; } - sqlite3SelectDelete(pSel); return nErr; } #endif /* SQLITE_OMIT_VIEW */ @@ -1563,7 +1712,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ static void sqliteViewResetAll(sqlite3 *db, int idx){ HashElem *i; if( !DbHasProperty(db, idx, DB_UnresetViews) ) return; - for(i=sqliteHashFirst(&db->aDb[idx].tblHash); i; i=sqliteHashNext(i)){ + for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){ Table *pTab = sqliteHashData(i); if( pTab->pSelect ){ sqliteResetColumnNames(pTab); @@ -1584,15 +1733,18 @@ static void sqliteViewResetAll(sqlite3 *db, int idx){ #ifndef SQLITE_OMIT_AUTOVACUUM void sqlite3RootPageMoved(Db *pDb, int iFrom, int iTo){ HashElem *pElem; - - for(pElem=sqliteHashFirst(&pDb->tblHash); pElem; pElem=sqliteHashNext(pElem)){ + Hash *pHash; + + pHash = &pDb->pSchema->tblHash; + for(pElem=sqliteHashFirst(pHash); 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)){ + pHash = &pDb->pSchema->idxHash; + for(pElem=sqliteHashFirst(pHash); pElem; pElem=sqliteHashNext(pElem)){ Index *pIdx = sqliteHashData(pElem); if( pIdx->tnum==iFrom ){ pIdx->tnum = iTo; @@ -1636,9 +1788,10 @@ static void destroyRootPage(Parse *pParse, int iTable, int iDb){ static void destroyTable(Parse *pParse, Table *pTab){ #ifdef SQLITE_OMIT_AUTOVACUUM Index *pIdx; - destroyRootPage(pParse, pTab->tnum, pTab->iDb); + int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + destroyRootPage(pParse, pTab->tnum, iDb); for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - destroyRootPage(pParse, pIdx->tnum, pIdx->iDb); + destroyRootPage(pParse, pIdx->tnum, iDb); } #else /* If the database may be auto-vacuum capable (if SQLITE_OMIT_AUTOVACUUM @@ -1669,14 +1822,18 @@ static void destroyTable(Parse *pParse, Table *pTab){ } for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ int iIdx = pIdx->tnum; - assert( pIdx->iDb==pTab->iDb ); + assert( pIdx->pSchema==pTab->pSchema ); if( (iDestroyed==0 || (iIdxiLargest ){ iLargest = iIdx; } } - if( iLargest==0 ) return; - destroyRootPage(pParse, iLargest, pTab->iDb); - iDestroyed = iLargest; + if( iLargest==0 ){ + return; + }else{ + int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + destroyRootPage(pParse, iLargest, iDb); + iDestroyed = iLargest; + } } #endif } @@ -1685,24 +1842,31 @@ static void destroyTable(Parse *pParse, Table *pTab){ ** This routine is called to do the work of a DROP TABLE statement. ** pName is the name of the table to be dropped. */ -void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){ +void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){ Table *pTab; Vdbe *v; sqlite3 *db = pParse->db; int iDb; - if( pParse->nErr || sqlite3_malloc_failed ) goto exit_drop_table; + if( pParse->nErr || sqlite3MallocFailed() ){ + goto exit_drop_table; + } assert( pName->nSrc==1 ); pTab = sqlite3LocateTable(pParse, pName->a[0].zName, pName->a[0].zDatabase); - if( pTab==0 ) goto exit_drop_table; - iDb = pTab->iDb; + if( pTab==0 ){ + if( noErr ){ + sqlite3ErrorClear(pParse); + } + goto exit_drop_table; + } + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); assert( iDb>=0 && iDbnDb ); #ifndef SQLITE_OMIT_AUTHORIZATION { int code; - const char *zTab = SCHEMA_TABLE(pTab->iDb); - const char *zDb = db->aDb[pTab->iDb].zName; + const char *zTab = SCHEMA_TABLE(iDb); + const char *zDb = db->aDb[iDb].zName; if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){ goto exit_drop_table; } @@ -1727,7 +1891,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){ } } #endif - if( pTab->readOnly || pTab==db->aDb[iDb].pSeqTab ){ + if( pTab->readOnly || pTab==db->aDb[iDb].pSchema->pSeqTab ){ sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName); goto exit_drop_table; } @@ -1752,7 +1916,6 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){ v = sqlite3GetVdbe(pParse); if( v ){ Trigger *pTrigger; - int iDb = pTab->iDb; Db *pDb = &db->aDb[iDb]; sqlite3BeginWriteOperation(pParse, 0, iDb); @@ -1762,7 +1925,8 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){ */ pTrigger = pTab->pTrigger; while( pTrigger ){ - assert( pTrigger->iDb==iDb || pTrigger->iDb==1 ); + assert( pTrigger->pSchema==pTab->pSchema || + pTrigger->pSchema==db->aDb[1].pSchema ); sqlite3DropTriggerPtr(pParse, pTrigger, 1); pTrigger = pTrigger->pNext; } @@ -1958,21 +2122,18 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ int addr1; /* Address of top of loop */ int tnum; /* Root page of index */ Vdbe *v; /* Generate code into this virtual machine */ + KeyInfo *pKey; /* KeyInfo for index */ + int iDb = sqlite3SchemaToIndex(pParse->db, pIndex->pSchema); #ifndef SQLITE_OMIT_AUTHORIZATION if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0, - pParse->db->aDb[pIndex->iDb].zName ) ){ + pParse->db->aDb[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; - } + /* Require a write-lock on the table to perform this operation */ + sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName); v = sqlite3GetVdbe(pParse); if( v==0 ) return; @@ -1981,12 +2142,12 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ tnum = 0; }else{ tnum = pIndex->tnum; - sqlite3VdbeAddOp(v, OP_Clear, tnum, pIndex->iDb); + sqlite3VdbeAddOp(v, OP_Clear, tnum, iDb); } - sqlite3VdbeAddOp(v, OP_Integer, pIndex->iDb, 0); - sqlite3VdbeOp3(v, OP_OpenWrite, iIdx, tnum, - (char*)&pIndex->keyInfo, P3_KEYINFO); - sqlite3OpenTableForReading(v, iTab, pTab); + sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); + pKey = sqlite3IndexKeyinfo(pParse, pIndex); + sqlite3VdbeOp3(v, OP_OpenWrite, iIdx, tnum, (char *)pKey, P3_KEYINFO_HANDOFF); + sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iTab, 0); sqlite3GenerateIndexKey(v, pIndex, iTab); if( pIndex->onError!=OE_None ){ @@ -2027,20 +2188,30 @@ void sqlite3CreateIndex( 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 */ + Token *pEnd, /* The ")" that closes the CREATE INDEX statement */ + int sortOrder, /* Sort order of primary key when pList==NULL */ + int ifNotExist /* Omit error if index already exists */ ){ - Table *pTab = 0; /* Table to be indexed */ - Index *pIndex = 0; /* The index to be created */ - char *zName = 0; + Table *pTab = 0; /* Table to be indexed */ + Index *pIndex = 0; /* The index to be created */ + char *zName = 0; /* Name of the index */ + int nName; /* Number of characters in zName */ int i, j; - Token nullId; /* Fake token for an empty ID list */ - DbFixer sFix; /* For assigning database names to pTable */ + Token nullId; /* Fake token for an empty ID list */ + DbFixer sFix; /* For assigning database names to pTable */ + int sortOrderMask; /* 1 to honor DESC in index. 0 to ignore. */ sqlite3 *db = pParse->db; + Db *pDb; /* The specific table containing the indexed database */ + int iDb; /* Index of the database that is being written */ + Token *pName = 0; /* Unqualified name of the index to create */ + struct ExprList_item *pListItem; /* For looping over pList */ + int nCol; + int nExtra = 0; + char *zExtra; - int iDb; /* Index of the database that is being written */ - Token *pName = 0; /* Unqualified name of the index to create */ - - if( pParse->nErr || sqlite3_malloc_failed ) goto exit_create_index; + if( pParse->nErr || sqlite3MallocFailed() ){ + goto exit_create_index; + } /* ** Find the table that is to be indexed. Return early if not found. @@ -2060,7 +2231,7 @@ void sqlite3CreateIndex( ** is a temp table. If so, set the database to 1. */ pTab = sqlite3SrcListLookup(pParse, pTblName); - if( pName2 && pName2->n==0 && pTab && pTab->iDb==1 ){ + if( pName2 && pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){ iDb = 1; } #endif @@ -2075,12 +2246,14 @@ void sqlite3CreateIndex( pTab = sqlite3LocateTable(pParse, pTblName->a[0].zName, pTblName->a[0].zDatabase); if( !pTab ) goto exit_create_index; - assert( iDb==pTab->iDb ); + assert( db->aDb[iDb].pSchema==pTab->pSchema ); }else{ assert( pName==0 ); - pTab = pParse->pNewTable; - iDb = pTab->iDb; + pTab = pParse->pNewTable; + if( !pTab ) goto exit_create_index; + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); } + pDb = &db->aDb[iDb]; if( pTab==0 || pParse->nErr ) goto exit_create_index; if( pTab->readOnly ){ @@ -2116,8 +2289,10 @@ void sqlite3CreateIndex( } if( !db->init.busy ){ if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto exit_create_index; - if( sqlite3FindIndex(db, zName, db->aDb[iDb].zName)!=0 ){ - sqlite3ErrorMsg(pParse, "index %s already exists", zName); + if( sqlite3FindIndex(db, zName, pDb->zName)!=0 ){ + if( !ifNotExist ){ + sqlite3ErrorMsg(pParse, "index %s already exists", zName); + } goto exit_create_index; } if( sqlite3FindTable(db, zName, 0)!=0 ){ @@ -2140,7 +2315,7 @@ void sqlite3CreateIndex( */ #ifndef SQLITE_OMIT_AUTHORIZATION { - const char *zDb = db->aDb[iDb].zName; + const char *zDb = pDb->zName; if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iDb), 0, zDb) ){ goto exit_create_index; } @@ -2157,56 +2332,96 @@ void sqlite3CreateIndex( ** So create a fake list to simulate this. */ if( pList==0 ){ - nullId.z = pTab->aCol[pTab->nCol-1].zName; - nullId.n = strlen(nullId.z); + nullId.z = (u8*)pTab->aCol[pTab->nCol-1].zName; + nullId.n = strlen((char*)nullId.z); pList = sqlite3ExprListAppend(0, 0, &nullId); if( pList==0 ) goto exit_create_index; + pList->a[0].sortOrder = sortOrder; + } + + /* Figure out how many bytes of space are required to store explicitly + ** specified collation sequence names. + */ + for(i=0; inExpr; i++){ + Expr *pExpr = pList->a[i].pExpr; + if( pExpr ){ + nExtra += (1 + strlen(pExpr->pColl->zName)); + } } /* ** Allocate the index structure. */ - pIndex = sqliteMalloc( sizeof(Index) + strlen(zName) + 1 + sizeof(int) + - (sizeof(int)*2 + sizeof(CollSeq*))*pList->nExpr ); - if( sqlite3_malloc_failed ) goto exit_create_index; - pIndex->aiColumn = (int*)&pIndex->keyInfo.aColl[pList->nExpr]; - pIndex->aiRowEst = (unsigned*)&pIndex->aiColumn[pList->nExpr]; - pIndex->zName = (char*)&pIndex->aiRowEst[pList->nExpr+1]; + nName = strlen(zName); + nCol = pList->nExpr; + pIndex = sqliteMalloc( + sizeof(Index) + /* Index structure */ + sizeof(int)*nCol + /* Index.aiColumn */ + sizeof(int)*(nCol+1) + /* Index.aiRowEst */ + sizeof(char *)*nCol + /* Index.azColl */ + sizeof(u8)*nCol + /* Index.aSortOrder */ + nName + 1 + /* Index.zName */ + nExtra /* Collation sequence names */ + ); + if( sqlite3MallocFailed() ) goto exit_create_index; + pIndex->aiColumn = (int *)(&pIndex[1]); + pIndex->aiRowEst = (unsigned *)(&pIndex->aiColumn[nCol]); + pIndex->azColl = (char **)(&pIndex->aiRowEst[nCol+1]); + pIndex->aSortOrder = (u8 *)(&pIndex->azColl[nCol]); + pIndex->zName = (char *)(&pIndex->aSortOrder[nCol]); + zExtra = (char *)(&pIndex->zName[nName+1]); strcpy(pIndex->zName, zName); pIndex->pTable = pTab; pIndex->nColumn = pList->nExpr; pIndex->onError = onError; pIndex->autoIndex = pName==0; - pIndex->iDb = iDb; + pIndex->pSchema = db->aDb[iDb].pSchema; + + /* Check to see if we should honor DESC requests on index columns + */ + if( pDb->pSchema->file_format>=4 ){ + sortOrderMask = -1; /* Honor DESC */ + }else{ + sortOrderMask = 0; /* Ignore DESC */ + } /* Scan the names of the columns of the table to be indexed and ** load the column indices into the Index structure. Report an error ** if any column is not found. */ - for(i=0; inExpr; i++){ - for(j=0; jnCol; j++){ - if( sqlite3StrICmp(pList->a[i].zName, pTab->aCol[j].zName)==0 ) break; + for(i=0, pListItem=pList->a; inExpr; i++, pListItem++){ + const char *zColName = pListItem->zName; + Column *pTabCol; + int requestedSortOrder; + char *zColl; /* Collation sequence */ + + for(j=0, pTabCol=pTab->aCol; jnCol; j++, pTabCol++){ + if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break; } if( j>=pTab->nCol ){ sqlite3ErrorMsg(pParse, "table %s has no column named %s", - pTab->zName, pList->a[i].zName); + pTab->zName, zColName); goto exit_create_index; } pIndex->aiColumn[i] = j; - if( pList->a[i].pExpr ){ - assert( pList->a[i].pExpr->pColl ); - pIndex->keyInfo.aColl[i] = pList->a[i].pExpr->pColl; + if( pListItem->pExpr ){ + assert( pListItem->pExpr->pColl ); + zColl = zExtra; + strcpy(zExtra, pListItem->pExpr->pColl->zName); + zExtra += (strlen(zColl) + 1); }else{ - pIndex->keyInfo.aColl[i] = pTab->aCol[j].pColl; + zColl = pTab->aCol[j].zColl; + if( !zColl ){ + zColl = db->pDfltColl->zName; + } } - assert( pIndex->keyInfo.aColl[i] ); - if( !db->init.busy && - sqlite3CheckCollSeq(pParse, pIndex->keyInfo.aColl[i]) - ){ + if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl, -1) ){ goto exit_create_index; } + pIndex->azColl[i] = zColl; + requestedSortOrder = pListItem->sortOrder & sortOrderMask; + pIndex->aSortOrder[i] = requestedSortOrder; } - pIndex->keyInfo.nField = pList->nExpr; sqlite3DefaultRowEst(pIndex); if( pTab==pParse->pNewTable ){ @@ -2232,8 +2447,11 @@ void sqlite3CreateIndex( if( pIdx->nColumn!=pIndex->nColumn ) continue; for(k=0; knColumn; k++){ + const char *z1 = pIdx->azColl[k]; + const char *z2 = pIndex->azColl[k]; if( pIdx->aiColumn[k]!=pIndex->aiColumn[k] ) break; - if( pIdx->keyInfo.aColl[k]!=pIndex->keyInfo.aColl[k] ) break; + if( pIdx->aSortOrder[k]!=pIndex->aSortOrder[k] ) break; + if( z1!=z2 && sqlite3StrICmp(z1, z2) ) break; } if( k==pIdx->nColumn ){ if( pIdx->onError!=pIndex->onError ){ @@ -2262,7 +2480,7 @@ void sqlite3CreateIndex( */ if( db->init.busy ){ Index *p; - p = sqlite3HashInsert(&db->aDb[pIndex->iDb].idxHash, + p = sqlite3HashInsert(&pIndex->pSchema->idxHash, pIndex->zName, strlen(pIndex->zName)+1, pIndex); if( p ){ assert( p==pIndex ); /* Malloc must have failed */ @@ -2297,6 +2515,7 @@ void sqlite3CreateIndex( v = sqlite3GetVdbe(pParse); if( v==0 ) goto exit_create_index; + /* Create the rootpage for the index */ sqlite3BeginWriteOperation(pParse, 1, iDb); @@ -2374,6 +2593,22 @@ exit_create_index: return; } +/* +** Generate code to make sure the file format number is at least minFormat. +** The generated code will increase the file format number if necessary. +*/ +void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){ + Vdbe *v; + v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 1); + sqlite3VdbeAddOp(v, OP_Integer, minFormat, 0); + sqlite3VdbeAddOp(v, OP_Ge, 0, sqlite3VdbeCurrentAddr(v)+3); + sqlite3VdbeAddOp(v, OP_Integer, minFormat, 0); + sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1); + } +} + /* ** Fill the Index.aiRowEst[] array with default information - information ** to be used when we have not run the ANALYZE command. @@ -2409,12 +2644,13 @@ void sqlite3DefaultRowEst(Index *pIdx){ ** This routine will drop an existing named index. This routine ** implements the DROP INDEX statement. */ -void sqlite3DropIndex(Parse *pParse, SrcList *pName){ +void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){ Index *pIndex; Vdbe *v; sqlite3 *db = pParse->db; + int iDb; - if( pParse->nErr || sqlite3_malloc_failed ){ + if( pParse->nErr || sqlite3MallocFailed() ){ goto exit_drop_index; } assert( pName->nSrc==1 ); @@ -2423,7 +2659,9 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName){ } pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase); if( pIndex==0 ){ - sqlite3ErrorMsg(pParse, "no such index: %S", pName, 0); + if( !ifExists ){ + sqlite3ErrorMsg(pParse, "no such index: %S", pName, 0); + } pParse->checkSchema = 1; goto exit_drop_index; } @@ -2432,16 +2670,17 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName){ "or PRIMARY KEY constraint cannot be dropped", 0); goto exit_drop_index; } + iDb = sqlite3SchemaToIndex(db, pIndex->pSchema); #ifndef SQLITE_OMIT_AUTHORIZATION { int code = SQLITE_DROP_INDEX; Table *pTab = pIndex->pTable; - const char *zDb = db->aDb[pIndex->iDb].zName; - const char *zTab = SCHEMA_TABLE(pIndex->iDb); + const char *zDb = db->aDb[iDb].zName; + const char *zTab = SCHEMA_TABLE(iDb); if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ goto exit_drop_index; } - if( !OMIT_TEMPDB && pIndex->iDb ) code = SQLITE_DROP_TEMP_INDEX; + if( !OMIT_TEMPDB && iDb ) code = SQLITE_DROP_TEMP_INDEX; if( sqlite3AuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){ goto exit_drop_index; } @@ -2451,7 +2690,6 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName){ /* Generate code to remove the index and from the master table */ v = sqlite3GetVdbe(pParse); if( v ){ - int iDb = pIndex->iDb; sqlite3NestedParse(pParse, "DELETE FROM %Q.%s WHERE name=%Q", db->aDb[iDb].zName, SCHEMA_TABLE(iDb), @@ -2621,11 +2859,14 @@ SrcList *sqlite3SrcListAppend(SrcList *pList, Token *pTable, Token *pDatabase){ void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){ int i; struct SrcList_item *pItem; - for(i=0, pItem=pList->a; inSrc; i++, pItem++){ - if( pItem->iCursor>=0 ) break; - pItem->iCursor = pParse->nTab++; - if( pItem->pSelect ){ - sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc); + assert(pList || sqlite3MallocFailed() ); + if( pList ){ + for(i=0, pItem=pList->a; inSrc; i++, pItem++){ + if( pItem->iCursor>=0 ) break; + pItem->iCursor = pParse->nTab++; + if( pItem->pSelect ){ + sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc); + } } } } @@ -2667,7 +2908,7 @@ void sqlite3BeginTransaction(Parse *pParse, int type){ int i; if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; - if( pParse->nErr || sqlite3_malloc_failed ) return; + if( pParse->nErr || sqlite3MallocFailed() ) return; if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ) return; v = sqlite3GetVdbe(pParse); @@ -2688,7 +2929,7 @@ void sqlite3CommitTransaction(Parse *pParse){ Vdbe *v; if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; - if( pParse->nErr || sqlite3_malloc_failed ) return; + if( pParse->nErr || sqlite3MallocFailed() ) return; if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ) return; v = sqlite3GetVdbe(pParse); @@ -2705,7 +2946,7 @@ void sqlite3RollbackTransaction(Parse *pParse){ Vdbe *v; if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; - if( pParse->nErr || sqlite3_malloc_failed ) return; + if( pParse->nErr || sqlite3MallocFailed() ) return; if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ) return; v = sqlite3GetVdbe(pParse); @@ -2737,6 +2978,7 @@ static int sqlite3OpenTempDatabase(Parse *pParse){ return 1; } } + assert( db->aDb[1].pSchema ); } return 0; } @@ -2781,7 +3023,7 @@ void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ mask = 1<cookieMask & mask)==0 ){ pParse->cookieMask |= mask; - pParse->cookieValue[iDb] = db->aDb[iDb].schema_cookie; + pParse->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie; if( !OMIT_TEMPDB && iDb==1 ){ sqlite3OpenTempDatabase(pParse); } @@ -2825,12 +3067,13 @@ void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){ ** 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++; +static int collationMatch(const char *zColl, Index *pIndex){ + int i; + for(i=0; inColumn; i++){ + const char *z = pIndex->azColl[i]; + if( z==zColl || (z && zColl && 0==sqlite3StrICmp(z, zColl)) ){ + return 1; + } } return 0; } @@ -2841,12 +3084,13 @@ static int collationMatch(CollSeq *pColl, Index *pIndex){ ** If pColl==0 then recompute all indices of pTab. */ #ifndef SQLITE_OMIT_REINDEX -static void reindexTable(Parse *pParse, Table *pTab, CollSeq *pColl){ +static void reindexTable(Parse *pParse, Table *pTab, char const *zColl){ 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); + if( zColl==0 || collationMatch(zColl, pIndex) ){ + int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3RefillIndex(pParse, pIndex, -1); } } @@ -2859,7 +3103,7 @@ static void reindexTable(Parse *pParse, Table *pTab, CollSeq *pColl){ ** all indices everywhere. */ #ifndef SQLITE_OMIT_REINDEX -static void reindexDatabases(Parse *pParse, CollSeq *pColl){ +static void reindexDatabases(Parse *pParse, char const *zColl){ Db *pDb; /* A single database */ int iDb; /* The database index number */ sqlite3 *db = pParse->db; /* The database connection */ @@ -2868,9 +3112,9 @@ static void reindexDatabases(Parse *pParse, CollSeq *pColl){ for(iDb=0, pDb=db->aDb; iDbnDb; iDb++, pDb++){ if( pDb==0 ) continue; - for(k=sqliteHashFirst(&pDb->tblHash); k; k=sqliteHashNext(k)){ + for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){ pTab = (Table*)sqliteHashData(k); - reindexTable(pParse, pTab, pColl); + reindexTable(pParse, pTab, zColl); } } } @@ -2910,9 +3154,14 @@ void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){ reindexDatabases(pParse, 0); return; }else if( pName2==0 || pName2->z==0 ){ - pColl = sqlite3FindCollSeq(db, db->enc, pName1->z, pName1->n, 0); + assert( pName1->z ); + pColl = sqlite3FindCollSeq(db, ENC(db), (char*)pName1->z, pName1->n, 0); if( pColl ){ - reindexDatabases(pParse, pColl); + char *zColl = sqliteStrNDup((const char *)pName1->z, pName1->n); + if( zColl ){ + reindexDatabases(pParse, zColl); + sqliteFree(zColl); + } return; } } @@ -2936,3 +3185,38 @@ void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){ sqlite3ErrorMsg(pParse, "unable to identify the object to be reindexed"); } #endif + +/* +** Return a dynamicly allocated KeyInfo structure that can be used +** with OP_OpenRead or OP_OpenWrite to access database index pIdx. +** +** If successful, a pointer to the new structure is returned. In this case +** the caller is responsible for calling sqliteFree() on the returned +** pointer. If an error occurs (out of memory or missing collation +** sequence), NULL is returned and the state of pParse updated to reflect +** the error. +*/ +KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){ + int i; + int nCol = pIdx->nColumn; + int nBytes = sizeof(KeyInfo) + (nCol-1)*sizeof(CollSeq*) + nCol; + KeyInfo *pKey = (KeyInfo *)sqliteMalloc(nBytes); + + if( pKey ){ + pKey->aSortOrder = (u8 *)&(pKey->aColl[nCol]); + assert( &pKey->aSortOrder[nCol]==&(((u8 *)pKey)[nBytes]) ); + for(i=0; iazColl[i]; + assert( zColl ); + pKey->aColl[i] = sqlite3LocateCollSeq(pParse, zColl, -1); + pKey->aSortOrder[i] = pIdx->aSortOrder[i]; + } + pKey->nField = nCol; + } + + if( pParse->nErr ){ + sqliteFree(pKey); + pKey = 0; + } + return pKey; +} diff --git a/mozilla/db/sqlite3/src/callback.c b/mozilla/db/sqlite3/src/callback.c index 70c44e488e4..8ea849b67d9 100644 --- a/mozilla/db/sqlite3/src/callback.c +++ b/mozilla/db/sqlite3/src/callback.c @@ -13,7 +13,7 @@ ** This file contains functions used to access the internal hash tables ** of user defined functions and collation sequences. ** -** $Id: callback.c,v 1.2 2005-12-13 19:49:35 vladimir%pobox.com Exp $ +** $Id: callback.c,v 1.3 2006-02-08 21:10:10 vladimir%pobox.com Exp $ */ #include "sqliteInt.h" @@ -29,17 +29,19 @@ static void callCollNeeded(sqlite3 *db, const char *zName, int nName){ if( db->xCollNeeded ){ char *zExternal = sqliteStrNDup(zName, nName); if( !zExternal ) return; - db->xCollNeeded(db->pCollNeededArg, db, (int)db->enc, zExternal); + db->xCollNeeded(db->pCollNeededArg, db, (int)ENC(db), zExternal); sqliteFree(zExternal); } #ifndef SQLITE_OMIT_UTF16 if( db->xCollNeeded16 ){ char const *zExternal; - sqlite3_value *pTmp = sqlite3GetTransientValue(db); - sqlite3ValueSetStr(pTmp, -1, zName, SQLITE_UTF8, SQLITE_STATIC); + sqlite3_value *pTmp = sqlite3ValueNew(); + sqlite3ValueSetStr(pTmp, nName, zName, SQLITE_UTF8, SQLITE_STATIC); zExternal = sqlite3ValueText(pTmp, SQLITE_UTF16NATIVE); - if( !zExternal ) return; - db->xCollNeeded16(db->pCollNeededArg, db, (int)db->enc, zExternal); + if( zExternal ){ + db->xCollNeeded16(db->pCollNeededArg, db, (int)ENC(db), zExternal); + } + sqlite3ValueFree(pTmp); } #endif } @@ -90,14 +92,14 @@ CollSeq *sqlite3GetCollSeq( p = pColl; if( !p ){ - p = sqlite3FindCollSeq(db, db->enc, zName, nName, 0); + p = sqlite3FindCollSeq(db, ENC(db), zName, nName, 0); } if( !p || !p->xCmp ){ /* No collation sequence of this type for this encoding is registered. ** Call the collation factory to see if it can supply us with one. */ callCollNeeded(db, zName, nName); - p = sqlite3FindCollSeq(db, db->enc, zName, nName, 0); + p = sqlite3FindCollSeq(db, ENC(db), zName, nName, 0); } if( p && !p->xCmp && synthCollSeq(db, p) ){ p = 0; @@ -128,6 +130,7 @@ int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){ pParse->nErr++; return SQLITE_ERROR; } + assert( p==pColl ); } return SQLITE_OK; } @@ -175,7 +178,8 @@ static CollSeq *findCollSeqEntry( ** return the pColl pointer to be deleted (because it wasn't added ** to the hash table). */ - assert( !pDel || (sqlite3_malloc_failed && pDel==pColl) ); + assert( !pDel || + (sqlite3MallocFailed() && pDel==pColl) ); sqliteFree(pDel); } } @@ -197,7 +201,12 @@ CollSeq *sqlite3FindCollSeq( int nName, int create ){ - CollSeq *pColl = findCollSeqEntry(db, zName, nName, create); + CollSeq *pColl; + if( zName ){ + pColl = findCollSeqEntry(db, zName, nName, create); + }else{ + pColl = db->pDfltColl; + } assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE ); if( pColl ) pColl += enc-1; @@ -286,7 +295,7 @@ FuncDef *sqlite3FindFunction( ** new entry to the hash table and return it. */ if( createFlag && bestmatch<6 && - (pBest = sqliteMalloc(sizeof(*pBest)+nName)) ){ + (pBest = sqliteMalloc(sizeof(*pBest)+nName))!=0 ){ pBest->nArg = nArg; pBest->pNext = pFirst; pBest->iPrefEnc = enc; diff --git a/mozilla/db/sqlite3/src/complete.c b/mozilla/db/sqlite3/src/complete.c index 24dd9ab73bc..d98263f715e 100644 --- a/mozilla/db/sqlite3/src/complete.c +++ b/mozilla/db/sqlite3/src/complete.c @@ -16,7 +16,7 @@ ** separating it out, the code will be automatically omitted from ** static links that do not use it. ** -** $Id: complete.c,v 1.1 2005-12-13 19:49:35 vladimir%pobox.com Exp $ +** $Id: complete.c,v 1.2 2006-02-08 21:10:10 vladimir%pobox.com Exp $ */ #include "sqliteInt.h" #ifndef SQLITE_OMIT_COMPLETE @@ -257,7 +257,7 @@ int sqlite3_complete16(const void *zSql){ rc = sqlite3_complete(zSql8); } sqlite3ValueFree(pVal); - return rc; + return sqlite3ApiExit(0, rc); } #endif /* SQLITE_OMIT_UTF16 */ #endif /* SQLITE_OMIT_COMPLETE */ diff --git a/mozilla/db/sqlite3/src/date.c b/mozilla/db/sqlite3/src/date.c index 35c0bf64a83..4a09a4f8df5 100644 --- a/mozilla/db/sqlite3/src/date.c +++ b/mozilla/db/sqlite3/src/date.c @@ -16,7 +16,7 @@ ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: date.c,v 1.45 2005/06/25 18:42:14 drh Exp $ +** $Id: date.c,v 1.53 2006/01/24 12:09:19 danielk1977 Exp $ ** ** NOTES: ** @@ -105,18 +105,20 @@ static int getDigits(const char *zDate, ...){ val = 0; while( N-- ){ if( !isdigit(*(u8*)zDate) ){ - return cnt; + goto end_getDigits; } val = val*10 + *zDate - '0'; zDate++; } if( valmax || (nextC!=0 && nextC!=*zDate) ){ - return cnt; + goto end_getDigits; } *pVal = val; zDate++; cnt++; }while( nextC ); + va_end(ap); +end_getDigits: return cnt; } @@ -236,7 +238,7 @@ static void computeJD(DateTime *p){ if( p->validHMS ){ p->rJD += (p->h*3600.0 + p->m*60.0 + p->s)/86400.0; if( p->validTZ ){ - p->rJD += p->tz*60/86400.0; + p->rJD -= p->tz*60/86400.0; p->validHMS = 0; p->validTZ = 0; } @@ -639,10 +641,10 @@ static int isDate(int argc, sqlite3_value **argv, DateTime *p){ int i; if( argc==0 ) return 1; if( SQLITE_NULL==sqlite3_value_type(argv[0]) || - parseDateOrTime(sqlite3_value_text(argv[0]), p) ) return 1; + parseDateOrTime((char*)sqlite3_value_text(argv[0]), p) ) return 1; for(i=1; iiDb, 0); + Vdbe *v = sqlite3GetVdbe(p); + assert( opcode==OP_OpenWrite || opcode==OP_OpenRead ); + sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite), pTab->zName); + sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); VdbeComment((v, "# %s", pTab->zName)); - sqlite3VdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum); + sqlite3VdbeAddOp(v, opcode, iCur, pTab->tnum); sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, pTab->nCol); } @@ -95,6 +100,7 @@ void sqlite3DeleteFrom( AuthContext sContext; /* Authorization context */ int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */ NameContext sNC; /* Name context to resolve expressions in */ + int iDb; #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to delete from a view */ @@ -102,7 +108,7 @@ void sqlite3DeleteFrom( #endif sContext.pParse = 0; - if( pParse->nErr || sqlite3_malloc_failed ){ + if( pParse->nErr || sqlite3MallocFailed() ){ goto delete_from_cleanup; } db = pParse->db; @@ -134,8 +140,9 @@ void sqlite3DeleteFrom( if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){ goto delete_from_cleanup; } - assert( pTab->iDbnDb ); - zDb = db->aDb[pTab->iDb].zName; + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + assert( iDbnDb ); + zDb = db->aDb[iDb].zName; if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){ goto delete_from_cleanup; } @@ -176,7 +183,7 @@ void sqlite3DeleteFrom( goto delete_from_cleanup; } if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); - sqlite3BeginWriteOperation(pParse, triggers_exist, pTab->iDb); + sqlite3BeginWriteOperation(pParse, triggers_exist, iDb); /* If we are trying to delete from a view, realize that view into ** a ephemeral table. @@ -203,20 +210,24 @@ void sqlite3DeleteFrom( /* If counting rows deleted, just count the total number of ** entries in the table. */ int endOfLoop = sqlite3VdbeMakeLabel(v); - int addr; + int addr2; if( !isView ){ - sqlite3OpenTableForReading(v, iCur, pTab); + sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead); } sqlite3VdbeAddOp(v, OP_Rewind, iCur, sqlite3VdbeCurrentAddr(v)+2); - addr = sqlite3VdbeAddOp(v, OP_AddImm, 1, 0); - sqlite3VdbeAddOp(v, OP_Next, iCur, addr); + addr2 = sqlite3VdbeAddOp(v, OP_AddImm, 1, 0); + sqlite3VdbeAddOp(v, OP_Next, iCur, addr2); sqlite3VdbeResolveLabel(v, endOfLoop); sqlite3VdbeAddOp(v, OP_Close, iCur, 0); } if( !isView ){ - sqlite3VdbeAddOp(v, OP_Clear, pTab->tnum, pTab->iDb); + sqlite3VdbeAddOp(v, OP_Clear, pTab->tnum, iDb); + if( !pParse->nested ){ + sqlite3VdbeChangeP3(v, -1, pTab->zName, P3_STATIC); + } for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - sqlite3VdbeAddOp(v, OP_Clear, pIdx->tnum, pIdx->iDb); + assert( pIdx->pSchema==pTab->pSchema ); + sqlite3VdbeAddOp(v, OP_Clear, pIdx->tnum, iDb); } } } @@ -225,13 +236,6 @@ void sqlite3DeleteFrom( ** the table and pick which records to delete. */ else{ - /* Ensure all required collation sequences are available. */ - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - if( sqlite3CheckIndexCollSeq(pParse, pIdx) ){ - goto delete_from_cleanup; - } - } - /* Begin the database scan */ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0); @@ -269,7 +273,7 @@ void sqlite3DeleteFrom( addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, end); if( !isView ){ sqlite3VdbeAddOp(v, OP_Dup, 0, 0); - sqlite3OpenTableForReading(v, iCur, pTab); + sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead); } sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0); sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0); @@ -380,6 +384,9 @@ void sqlite3GenerateRowDelete( addr = sqlite3VdbeAddOp(v, OP_NotExists, iCur, 0); sqlite3GenerateRowIndexDelete(db, v, pTab, iCur, 0); sqlite3VdbeAddOp(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0)); + if( count ){ + sqlite3VdbeChangeP3(v, -1, pTab->zName, P3_STATIC); + } sqlite3VdbeJumpHere(v, addr); } diff --git a/mozilla/db/sqlite3/src/experimental.c b/mozilla/db/sqlite3/src/experimental.c index 94062de3bb9..907fc6eff19 100644 --- a/mozilla/db/sqlite3/src/experimental.c +++ b/mozilla/db/sqlite3/src/experimental.c @@ -12,9 +12,10 @@ ** This file contains C code routines that are not a part of the official ** SQLite API. These routines are unsupported. ** -** $Id: experimental.c,v 1.1 2005-06-10 01:27:31 vladimir%pobox.com Exp $ +** $Id: experimental.c,v 1.2 2006-02-08 21:10:10 vladimir%pobox.com Exp $ */ #include "sqliteInt.h" +#include "os.h" /* ** Set all the parameters in the compiled SQL statement to NULL. diff --git a/mozilla/db/sqlite3/src/expr.c b/mozilla/db/sqlite3/src/expr.c index c415e7ab555..9a1e046334f 100644 --- a/mozilla/db/sqlite3/src/expr.c +++ b/mozilla/db/sqlite3/src/expr.c @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.230 2005/09/23 21:11:54 drh Exp $ +** $Id: expr.c,v 1.253 2006/01/30 14:36:59 drh Exp $ */ #include "sqliteInt.h" #include @@ -75,12 +75,10 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ char sqlite3CompareAffinity(Expr *pExpr, char aff2){ char aff1 = sqlite3ExprAffinity(pExpr); if( aff1 && aff2 ){ - /* Both sides of the comparison are columns. If one has numeric or - ** integer affinity, use that. Otherwise use no affinity. + /* Both sides of the comparison are columns. If one has numeric + ** affinity, use that. Otherwise use no affinity. */ - if( aff1==SQLITE_AFF_INTEGER || aff2==SQLITE_AFF_INTEGER ){ - return SQLITE_AFF_INTEGER; - }else if( aff1==SQLITE_AFF_NUMERIC || aff2==SQLITE_AFF_NUMERIC ){ + if( sqlite3IsNumericAffinity(aff1) || sqlite3IsNumericAffinity(aff2) ){ return SQLITE_AFF_NUMERIC; }else{ return SQLITE_AFF_NONE; @@ -89,7 +87,6 @@ char sqlite3CompareAffinity(Expr *pExpr, char aff2){ /* Neither side of the comparison is a column. Compare the ** results directly. */ - /* return SQLITE_AFF_NUMERIC; // Ticket #805 */ return SQLITE_AFF_NONE; }else{ /* One side is a column, the other is not. Use the columns affinity. */ @@ -129,11 +126,14 @@ static char comparisonAffinity(Expr *pExpr){ */ int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){ char aff = comparisonAffinity(pExpr); - return - (aff==SQLITE_AFF_NONE) || - (aff==SQLITE_AFF_NUMERIC && idx_affinity==SQLITE_AFF_INTEGER) || - (aff==SQLITE_AFF_INTEGER && idx_affinity==SQLITE_AFF_NUMERIC) || - (aff==idx_affinity); + switch( aff ){ + case SQLITE_AFF_NONE: + return 1; + case SQLITE_AFF_TEXT: + return idx_affinity==SQLITE_AFF_TEXT; + default: + return sqlite3IsNumericAffinity(idx_affinity); + } } /* @@ -235,7 +235,7 @@ Expr *sqlite3RegisterExpr(Parse *pParse, Token *pToken){ if( p==0 ){ return 0; /* Malloc failed */ } - depth = atoi(&pToken->z[1]); + depth = atoi((char*)&pToken->z[1]); p->iTable = pParse->nMem++; sqlite3VdbeAddOp(v, OP_Dup, depth, 0); sqlite3VdbeAddOp(v, OP_MemStore, p->iTable, 1); @@ -263,7 +263,7 @@ Expr *sqlite3ExprAnd(Expr *pLeft, Expr *pRight){ void sqlite3ExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){ assert( pRight!=0 ); assert( pLeft!=0 ); - if( !sqlite3_malloc_failed && pRight->z && pLeft->z ){ + if( !sqlite3MallocFailed() && pRight->z && pLeft->z ){ assert( pLeft->dyn==0 || pLeft->z[pLeft->n]==0 ); if( pLeft->dyn==0 && pRight->dyn==0 ){ pExpr->span.z = pLeft->z; @@ -280,6 +280,7 @@ void sqlite3ExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){ */ Expr *sqlite3ExprFunction(ExprList *pList, Token *pToken){ Expr *pNew; + assert( pToken ); pNew = sqliteMalloc( sizeof(Expr) ); if( pNew==0 ){ sqlite3ExprListDelete(pList); /* Avoid leaking memory when malloc fails */ @@ -287,12 +288,8 @@ Expr *sqlite3ExprFunction(ExprList *pList, Token *pToken){ } pNew->op = TK_FUNCTION; pNew->pList = pList; - if( pToken ){ - assert( pToken->dyn==0 ); - pNew->token = *pToken; - }else{ - pNew->token.z = 0; - } + assert( pToken->dyn==0 ); + pNew->token = *pToken; pNew->span = pNew->token; return pNew; } @@ -327,7 +324,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ /* Wildcard of the form "?nnn". Convert "nnn" to an integer and ** use it as the variable number */ int i; - pExpr->iTable = i = atoi(&pToken->z[1]); + pExpr->iTable = i = atoi((char*)&pToken->z[1]); if( i<1 || i>SQLITE_MAX_VARIABLE_NUMBER ){ sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d", SQLITE_MAX_VARIABLE_NUMBER); @@ -355,10 +352,10 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ pExpr->iTable = ++pParse->nVar; if( pParse->nVarExpr>=pParse->nVarExprAlloc-1 ){ pParse->nVarExprAlloc += pParse->nVarExprAlloc + 10; - sqlite3ReallocOrFree((void**)&pParse->apVarExpr, + sqliteReallocOrFree((void**)&pParse->apVarExpr, pParse->nVarExprAlloc*sizeof(pParse->apVarExpr[0]) ); } - if( !sqlite3_malloc_failed ){ + if( !sqlite3MallocFailed() ){ assert( pParse->apVarExpr!=0 ); pParse->apVarExpr[pParse->nVarExpr++] = pExpr; } @@ -415,7 +412,7 @@ Expr *sqlite3ExprDup(Expr *p){ if( pNew==0 ) return 0; memcpy(pNew, p, sizeof(*pNew)); if( p->token.z!=0 ){ - pNew->token.z = sqliteStrNDup(p->token.z, p->token.n); + pNew->token.z = (u8*)sqliteStrNDup((char*)p->token.z, p->token.n); pNew->token.dyn = 1; }else{ assert( pNew->token.z==0 ); @@ -432,7 +429,7 @@ void sqlite3TokenCopy(Token *pTo, Token *pFrom){ if( pTo->dyn ) sqliteFree((char*)pTo->z); if( pFrom->z ){ pTo->n = pFrom->n; - pTo->z = sqliteStrNDup(pFrom->z, pFrom->n); + pTo->z = (u8*)sqliteStrNDup((char*)pFrom->z, pFrom->n); pTo->dyn = 1; }else{ pTo->z = 0; @@ -462,7 +459,8 @@ ExprList *sqlite3ExprListDup(ExprList *p){ sqlite3TokenCopy(&pNewExpr->span, &pOldExpr->span); } assert( pNewExpr==0 || pNewExpr->span.z!=0 - || pOldExpr->span.z==0 || sqlite3_malloc_failed ); + || pOldExpr->span.z==0 + || sqlite3MallocFailed() ); pItem->zName = sqliteStrDup(pOldItem->zName); pItem->sortOrder = pOldItem->sortOrder; pItem->isAgg = pOldItem->isAgg; @@ -752,7 +750,7 @@ int sqlite3ExprIsConstantOrFunction(Expr *p){ int sqlite3ExprIsInteger(Expr *p, int *pValue){ switch( p->op ){ case TK_INTEGER: { - if( sqlite3GetInt32(p->token.z, pValue) ){ + if( sqlite3GetInt32((char*)p->token.z, pValue) ){ return 1; } break; @@ -809,7 +807,7 @@ int sqlite3IsRowid(const char *z){ ** in pParse and return non-zero. Return zero on success. */ static int lookupName( - Parse *pParse, /* The parsing context */ + Parse *pParse, /* The parsing context */ 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. */ @@ -831,19 +829,19 @@ static int lookupName( zDb = sqlite3NameFromToken(pDbToken); zTab = sqlite3NameFromToken(pTableToken); zCol = sqlite3NameFromToken(pColumnToken); - if( sqlite3_malloc_failed ){ + if( sqlite3MallocFailed() ){ goto lookupname_end; } pExpr->iTable = -1; while( pNC && cnt==0 ){ + ExprList *pEList; SrcList *pSrcList = pNC->pSrcList; - ExprList *pEList = pNC->pEList; - /* assert( zTab==0 || pEList==0 ); */ if( pSrcList ){ for(i=0, pItem=pSrcList->a; inSrc; i++, pItem++){ Table *pTab = pItem->pTab; + int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); Column *pCol; if( pTab==0 ) continue; @@ -855,27 +853,28 @@ static int lookupName( }else{ char *zTabName = pTab->zName; if( zTabName==0 || sqlite3StrICmp(zTabName, zTab)!=0 ) continue; - if( zDb!=0 && sqlite3StrICmp(db->aDb[pTab->iDb].zName, zDb)!=0 ){ + if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){ continue; } } } if( 0==(cntTab++) ){ pExpr->iTable = pItem->iCursor; - pExpr->iDb = pTab->iDb; + pExpr->pSchema = pTab->pSchema; pMatch = pItem; } for(j=0, pCol=pTab->aCol; jnCol; j++, pCol++){ if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ + const char *zColl = pTab->aCol[j].zColl; IdList *pUsing; cnt++; pExpr->iTable = pItem->iCursor; pMatch = pItem; - pExpr->iDb = pTab->iDb; + pExpr->pSchema = pTab->pSchema; /* 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; + pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0); if( pItem->jointype & JT_NATURAL ){ /* If this match occurred in the left table of a natural join, ** then skip the right table to avoid a duplicate match */ @@ -919,17 +918,18 @@ static int lookupName( } if( pTab ){ - int j; + int iCol; Column *pCol = pTab->aCol; - pExpr->iDb = pTab->iDb; + pExpr->pSchema = pTab->pSchema; cntTab++; - for(j=0; j < pTab->nCol; j++, pCol++) { + for(iCol=0; iCol < pTab->nCol; iCol++, pCol++) { if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ + const char *zColl = pTab->aCol[iCol].zColl; cnt++; - pExpr->iColumn = j==pTab->iPKey ? -1 : j; - pExpr->affinity = pTab->aCol[j].affinity; - pExpr->pColl = pTab->aCol[j].pColl; + pExpr->iColumn = iCol==pTab->iPKey ? -1 : iCol; + pExpr->affinity = pTab->aCol[iCol].affinity; + pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0); pExpr->pTab = pTab; break; } @@ -959,7 +959,7 @@ static int lookupName( ** 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 ){ + if( cnt==0 && (pEList = pNC->pEList)!=0 && zTab==0 ){ for(j=0; jnExpr; j++){ char *zAs = pEList->a[j].zName; if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ @@ -1006,9 +1006,9 @@ static int lookupName( char *zErr; zErr = cnt==0 ? "no such column: %s" : "ambiguous column name: %s"; if( zDb ){ - sqlite3SetString(&z, zDb, ".", zTab, ".", zCol, 0); + sqlite3SetString(&z, zDb, ".", zTab, ".", zCol, (char*)0); }else if( zTab ){ - sqlite3SetString(&z, zTab, ".", zCol, 0); + sqlite3SetString(&z, zTab, ".", zCol, (char*)0); }else{ z = sqliteStrDup(zCol); } @@ -1077,20 +1077,19 @@ lookupname_end_2: */ 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 ){ + if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){ + SrcList *pSrcList = pNC->pSrcList; int i; - for(i=0; inSrc; i++){ + for(i=0; ipSrcList->nSrc; i++){ assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursornTab); } } @@ -1149,9 +1148,9 @@ static int nameResolverStep(void *pArg, Expr *pExpr){ 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 */ + int enc = ENC(pParse->db); /* The database encoding */ - zId = pExpr->token.z; + zId = (char*)pExpr->token.z; nId = pExpr->token.n; pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); if( pDef==0 ){ @@ -1197,13 +1196,27 @@ static int nameResolverStep(void *pArg, Expr *pExpr){ case TK_IN: { if( pExpr->pSelect ){ int nRef = pNC->nRef; +#ifndef SQLITE_OMIT_CHECK + if( pNC->isCheck ){ + sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints"); + } +#endif sqlite3SelectResolve(pParse, pExpr->pSelect, pNC); assert( pNC->nRef>=nRef ); if( nRef!=pNC->nRef ){ ExprSetProperty(pExpr, EP_VarSelect); } } + break; } +#ifndef SQLITE_OMIT_CHECK + case TK_VARIABLE: { + if( pNC->isCheck ){ + sqlite3ErrorMsg(pParse,"parameters prohibited in CHECK constraints"); + } + break; + } +#endif } return 0; } @@ -1261,17 +1274,16 @@ struct QueryCoder { /* -** Generate code for subqueries and IN operators. +** Generate code for scalar subqueries used as an expression +** and IN operators. Examples: ** -** IN operators comes in two forms: +** (SELECT a FROM b) -- subquery +** EXISTS (SELECT a FROM b) -- EXISTS subquery +** x IN (4,5,11) -- IN operator with list on right-hand side +** x IN (SELECT a FROM b) -- IN operator with subquery on the right ** -** 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. +** The pExpr parameter describes the expression that contains the IN +** operator or subquery. */ #ifndef SQLITE_OMIT_SUBQUERY void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ @@ -1293,7 +1305,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ int mem = pParse->nMem++; sqlite3VdbeAddOp(v, OP_MemLoad, mem, 0); testAddr = sqlite3VdbeAddOp(v, OP_If, 0, 0); - assert( testAddr>0 || sqlite3_malloc_failed ); + assert( testAddr>0 || sqlite3MallocFailed() ); sqlite3VdbeAddOp(v, OP_MemInt, 1, mem); } @@ -1367,9 +1379,9 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ */ if( testAddr>0 && !sqlite3ExprIsConstant(pE2) ){ VdbeOp *aOp = sqlite3VdbeGetOp(v, testAddr-1); - int i; - for(i=0; i<3; i++){ - aOp[i].opcode = OP_Noop; + int j; + for(j=0; j<3; j++){ + aOp[j].opcode = OP_Noop; } testAddr = 0; } @@ -1390,21 +1402,25 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ ** value of this select in a memory cell and record the number ** of the memory cell in iColumn. */ - int sop; + static const Token one = { (u8*)"1", 0, 1 }; Select *pSel; + int iMem; + int sop; - pExpr->iColumn = pParse->nMem++; + pExpr->iColumn = iMem = pParse->nMem++; pSel = pExpr->pSelect; if( pExpr->op==TK_SELECT ){ sop = SRT_Mem; + sqlite3VdbeAddOp(v, OP_MemNull, iMem, 0); + VdbeComment((v, "# Init subquery result")); }else{ - static const Token one = { "1", 0, 1 }; sop = SRT_Exists; - sqlite3ExprListDelete(pSel->pEList); - pSel->pEList = sqlite3ExprListAppend(0, - sqlite3Expr(TK_INTEGER, 0, 0, &one), 0); + sqlite3VdbeAddOp(v, OP_MemInt, 0, iMem); + VdbeComment((v, "# Init EXISTS result")); } - sqlite3Select(pParse, pSel, sop, pExpr->iColumn, 0, 0, 0, 0); + sqlite3ExprDelete(pSel->pLimit); + pSel->pLimit = sqlite3Expr(TK_INTEGER, 0, 0, &one); + sqlite3Select(pParse, pSel, sop, iMem, 0, 0, 0, 0); break; } } @@ -1444,6 +1460,8 @@ static void codeInteger(Vdbe *v, const char *z, int n){ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ Vdbe *v = pParse->pVdbe; int op; + int stackChng = 1; /* Amount of change to stack depth */ + if( v==0 ) return; if( pExpr==0 ){ sqlite3VdbeAddOp(v, OP_Null, 0, 0); @@ -1465,16 +1483,27 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ /* Otherwise, fall thru into the TK_COLUMN case */ } case TK_COLUMN: { - if( pExpr->iColumn>=0 ){ - sqlite3VdbeAddOp(v, OP_Column, pExpr->iTable, pExpr->iColumn); - sqlite3ColumnDefault(v, pExpr->pTab, pExpr->iColumn); + if( pExpr->iTable<0 ){ + /* This only happens when coding check constraints */ + assert( pParse->ckOffset>0 ); + sqlite3VdbeAddOp(v, OP_Dup, pParse->ckOffset-pExpr->iColumn-1, 1); + }else if( pExpr->iColumn>=0 ){ + Table *pTab = pExpr->pTab; + int iCol = pExpr->iColumn; + sqlite3VdbeAddOp(v, OP_Column, pExpr->iTable, iCol); + sqlite3ColumnDefault(v, pTab, iCol); +#ifndef SQLITE_OMIT_FLOATING_POINT + if( pTab && pTab->aCol[iCol].affinity==SQLITE_AFF_REAL ){ + sqlite3VdbeAddOp(v, OP_RealAffinity, 0, 0); + } +#endif }else{ sqlite3VdbeAddOp(v, OP_Rowid, pExpr->iTable, 0); } break; } case TK_INTEGER: { - codeInteger(v, pExpr->token.z, pExpr->token.n); + codeInteger(v, (char*)pExpr->token.z, pExpr->token.n); break; } case TK_FLOAT: @@ -1482,7 +1511,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ assert( TK_FLOAT==OP_Real ); assert( TK_STRING==OP_String8 ); sqlite3DequoteExpr(pExpr); - sqlite3VdbeOp3(v, op, 0, 0, pExpr->token.z, pExpr->token.n); + sqlite3VdbeOp3(v, op, 0, 0, (char*)pExpr->token.z, pExpr->token.n); break; } case TK_NULL: { @@ -1495,7 +1524,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ const char *z; assert( TK_BLOB==OP_HexBlob ); n = pExpr->token.n - 3; - z = pExpr->token.z + 2; + z = (char*)pExpr->token.z + 2; assert( n>=0 ); if( n==0 ){ z = ""; @@ -1507,7 +1536,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ case TK_VARIABLE: { sqlite3VdbeAddOp(v, OP_Variable, pExpr->iTable, 0); if( pExpr->token.n>1 ){ - sqlite3VdbeChangeP3(v, -1, pExpr->token.z, pExpr->token.n); + sqlite3VdbeChangeP3(v, -1, (char*)pExpr->token.z, pExpr->token.n); } break; } @@ -1518,16 +1547,17 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ #ifndef SQLITE_OMIT_CAST case TK_CAST: { /* Expressions of the form: CAST(pLeft AS token) */ - int aff, op; + int aff, to_op; sqlite3ExprCode(pParse, pExpr->pLeft); aff = sqlite3AffinityType(&pExpr->token); - switch( aff ){ - case SQLITE_AFF_INTEGER: op = OP_ToInt; break; - case SQLITE_AFF_NUMERIC: op = OP_ToNumeric; break; - case SQLITE_AFF_TEXT: op = OP_ToText; break; - case SQLITE_AFF_NONE: op = OP_ToBlob; break; - } - sqlite3VdbeAddOp(v, op, 0, 0); + to_op = aff - SQLITE_AFF_TEXT + OP_ToText; + assert( to_op==OP_ToText || aff!=SQLITE_AFF_TEXT ); + assert( to_op==OP_ToBlob || aff!=SQLITE_AFF_NONE ); + assert( to_op==OP_ToNumeric || aff!=SQLITE_AFF_NUMERIC ); + assert( to_op==OP_ToInt || aff!=SQLITE_AFF_INTEGER ); + assert( to_op==OP_ToReal || aff!=SQLITE_AFF_REAL ); + sqlite3VdbeAddOp(v, to_op, 0, 0); + stackChng = 0; break; } #endif /* SQLITE_OMIT_CAST */ @@ -1546,6 +1576,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ sqlite3ExprCode(pParse, pExpr->pLeft); sqlite3ExprCode(pParse, pExpr->pRight); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, 0, 0); + stackChng = -1; break; } case TK_AND: @@ -1574,6 +1605,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ sqlite3ExprCode(pParse, pExpr->pLeft); sqlite3ExprCode(pParse, pExpr->pRight); sqlite3VdbeAddOp(v, op, 0, 0); + stackChng = -1; break; } case TK_UMINUS: { @@ -1581,8 +1613,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ assert( pLeft ); if( pLeft->op==TK_FLOAT || pLeft->op==TK_INTEGER ){ Token *p = &pLeft->token; - char *z = sqliteMalloc( p->n + 2 ); - sprintf(z, "-%.*s", p->n, p->z); + char *z = sqlite3MPrintf("-%.*s", p->n, p->z); if( pLeft->op==TK_FLOAT ){ sqlite3VdbeOp3(v, OP_Real, 0, 0, z, p->n+1); }else{ @@ -1599,6 +1630,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ assert( TK_NOT==OP_Not ); sqlite3ExprCode(pParse, pExpr->pLeft); sqlite3VdbeAddOp(v, op, 0, 0); + stackChng = 0; break; } case TK_ISNULL: @@ -1611,11 +1643,17 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ dest = sqlite3VdbeCurrentAddr(v) + 2; sqlite3VdbeAddOp(v, op, 1, dest); sqlite3VdbeAddOp(v, OP_AddImm, -1, 0); + stackChng = 0; break; } case TK_AGG_FUNCTION: { AggInfo *pInfo = pExpr->pAggInfo; - sqlite3VdbeAddOp(v, OP_MemLoad, pInfo->aFunc[pExpr->iAgg].iMem, 0); + if( pInfo==0 ){ + sqlite3ErrorMsg(pParse, "misuse of aggregate: %T", + &pExpr->span); + }else{ + sqlite3VdbeAddOp(v, OP_MemLoad, pInfo->aFunc[pExpr->iAgg].iMem, 0); + } break; } case TK_CONST_FUNC: @@ -1627,9 +1665,9 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ const char *zId; int constMask = 0; int i; - u8 enc = pParse->db->enc; + u8 enc = ENC(pParse->db); CollSeq *pColl = 0; - zId = pExpr->token.z; + zId = (char*)pExpr->token.z; nId = pExpr->token.n; pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0); assert( pDef!=0 ); @@ -1647,6 +1685,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ sqlite3VdbeOp3(v, OP_CollSeq, 0, 0, (char *)pColl, P3_COLLSEQ); } sqlite3VdbeOp3(v, OP_Function, constMask, nExpr, (char*)pDef, P3_FUNCDEF); + stackChng = 1-nExpr; break; } #ifndef SQLITE_OMIT_SUBQUERY @@ -1660,6 +1699,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ case TK_IN: { int addr; char affinity; + int ckOffset = pParse->ckOffset; sqlite3CodeSubselect(pParse, pExpr); /* Figure out the affinity to use to create a key from the results @@ -1669,6 +1709,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ affinity = comparisonAffinity(pExpr); sqlite3VdbeAddOp(v, OP_Integer, 1, 0); + pParse->ckOffset = ckOffset+1; /* Code the from " IN (...)". The temporary table ** pExpr->iTable contains the values that make up the (...) set. @@ -1705,6 +1746,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ case TK_UPLUS: case TK_AS: { sqlite3ExprCode(pParse, pExpr->pLeft); + stackChng = 0; break; } case TK_CASE: { @@ -1763,16 +1805,22 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ pExpr->iColumn == OE_Fail ); sqlite3DequoteExpr(pExpr); sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn, - pExpr->token.z, pExpr->token.n); + (char*)pExpr->token.z, pExpr->token.n); } else { assert( pExpr->iColumn == OE_Ignore ); sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, pParse->trigStack->ignoreJump); VdbeComment((v, "# raise(IGNORE)")); } + stackChng = 0; + break; } #endif - break; + } + + if( pParse->ckOffset ){ + pParse->ckOffset += stackChng; + assert( pParse->ckOffset ); } } @@ -1840,6 +1888,7 @@ int sqlite3ExprCodeExprList( void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ Vdbe *v = pParse->pVdbe; int op = 0; + int ckOffset = pParse->ckOffset; if( v==0 || pExpr==0 ) return; op = pExpr->op; switch( op ){ @@ -1914,6 +1963,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ break; } } + pParse->ckOffset = ckOffset; } /* @@ -1927,6 +1977,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ Vdbe *v = pParse->pVdbe; int op = 0; + int ckOffset = pParse->ckOffset; if( v==0 || pExpr==0 ) return; /* The value of pExpr->op and op are related as follows: @@ -2023,6 +2074,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ break; } } + pParse->ckOffset = ckOffset; } /* @@ -2031,10 +2083,8 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ */ int sqlite3ExprCompare(Expr *pA, Expr *pB){ int i; - if( pA==0 ){ - return pB==0; - }else if( pB==0 ){ - return 0; + if( pA==0||pB==0 ){ + return pB==pA; } if( pA->op!=pB->op ) return 0; if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 0; @@ -2056,7 +2106,9 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){ if( pA->token.z ){ if( pB->token.z==0 ) return 0; if( pB->token.n!=pA->token.n ) return 0; - if( sqlite3StrNICmp(pA->token.z, pB->token.z, pB->token.n)!=0 ) return 0; + if( sqlite3StrNICmp((char*)pA->token.z,(char*)pB->token.z,pB->token.n)!=0 ){ + return 0; + } } return 1; } @@ -2180,14 +2232,14 @@ static int analyzeAggregate(void *pArg, Expr *pExpr){ if( i>=pAggInfo->nFunc ){ /* pExpr is original. Make a new entry in pAggInfo->aFunc[] */ - u8 enc = pParse->db->enc; + u8 enc = ENC(pParse->db); i = addAggInfoFunc(pAggInfo); if( i>=0 ){ pItem = &pAggInfo->aFunc[i]; pItem->pExpr = pExpr; pItem->iMem = pParse->nMem++; pItem->pFunc = sqlite3FindFunction(pParse->db, - pExpr->token.z, pExpr->token.n, + (char*)pExpr->token.z, pExpr->token.n, pExpr->pList ? pExpr->pList->nExpr : 0, enc, 0); if( pExpr->flags & EP_Distinct ){ pItem->iDistinct = pParse->nTab++; diff --git a/mozilla/db/sqlite3/src/func.c b/mozilla/db/sqlite3/src/func.c index ed9133c3509..35caa6dcff5 100644 --- a/mozilla/db/sqlite3/src/func.c +++ b/mozilla/db/sqlite3/src/func.c @@ -16,11 +16,11 @@ ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: func.c,v 1.110 2005/09/08 20:37:43 drh Exp $ +** $Id: func.c,v 1.117 2006/01/17 13:21:40 danielk1977 Exp $ */ #include "sqliteInt.h" #include -#include +/* #include */ #include #include #include "vdbeInt.h" @@ -101,7 +101,7 @@ static void lengthFunc( break; } case SQLITE_TEXT: { - const char *z = sqlite3_value_text(argv[0]); + const unsigned char *z = sqlite3_value_text(argv[0]); for(len=0; *z; z++){ if( (0xc0&*z)!=0x80 ) len++; } sqlite3_result_int(context, len); break; @@ -146,8 +146,8 @@ static void substrFunc( int argc, sqlite3_value **argv ){ - const char *z; - const char *z2; + const unsigned char *z; + const unsigned char *z2; int i; int p1, p2, len; @@ -178,7 +178,7 @@ static void substrFunc( } while( z[i] && (z[i]&0xc0)==0x80 ){ i++; p2++; } if( p2<0 ) p2 = 0; - sqlite3_result_text(context, &z[p1], p2, SQLITE_TRANSIENT); + sqlite3_result_text(context, (char*)&z[p1], p2, SQLITE_TRANSIENT); } /* @@ -210,11 +210,11 @@ static void upperFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ if( argc<1 || SQLITE_NULL==sqlite3_value_type(argv[0]) ) return; z = sqliteMalloc(sqlite3_value_bytes(argv[0])+1); if( z==0 ) return; - strcpy(z, sqlite3_value_text(argv[0])); + strcpy((char*)z, (char*)sqlite3_value_text(argv[0])); for(i=0; z[i]; i++){ z[i] = toupper(z[i]); } - sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT); + sqlite3_result_text(context, (char*)z, -1, SQLITE_TRANSIENT); sqliteFree(z); } static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ @@ -223,11 +223,11 @@ static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ if( argc<1 || SQLITE_NULL==sqlite3_value_type(argv[0]) ) return; z = sqliteMalloc(sqlite3_value_bytes(argv[0])+1); if( z==0 ) return; - strcpy(z, sqlite3_value_text(argv[0])); + strcpy((char*)z, (char*)sqlite3_value_text(argv[0])); for(i=0; z[i]; i++){ z[i] = tolower(z[i]); } - sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT); + sqlite3_result_text(context, (char*)z, -1, SQLITE_TRANSIENT); sqliteFree(z); } @@ -495,7 +495,7 @@ static void likeFunc( ** Otherwise, return an error. */ const unsigned char *zEsc = sqlite3_value_text(argv[2]); - if( sqlite3utf8CharLen(zEsc, -1)!=1 ){ + if( sqlite3utf8CharLen((char*)zEsc, -1)!=1 ){ sqlite3_result_error(context, "ESCAPE expression must be a single character", -1); return; @@ -592,7 +592,7 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ } case SQLITE_TEXT: { int i,j,n; - const char *zArg = sqlite3_value_text(argv[0]); + const unsigned char *zArg = sqlite3_value_text(argv[0]); char *z; for(i=n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; } @@ -692,7 +692,7 @@ static void randStr(sqlite3_context *context, int argc, sqlite3_value **argv){ zBuf[i] = zSrc[zBuf[i]%(sizeof(zSrc)-1)]; } zBuf[n] = 0; - sqlite3_result_text(context, zBuf, n, SQLITE_TRANSIENT); + sqlite3_result_text(context, (char*)zBuf, n, SQLITE_TRANSIENT); } #endif /* SQLITE_TEST */ @@ -728,17 +728,17 @@ static void test_destructor( test_destructor_count_var++; assert( nArg==1 ); if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; - len = sqlite3ValueBytes(argv[0], db->enc); + len = sqlite3ValueBytes(argv[0], ENC(db)); zVal = sqliteMalloc(len+3); zVal[len] = 0; zVal[len-1] = 0; assert( zVal ); zVal++; - memcpy(zVal, sqlite3ValueText(argv[0], db->enc), len); - if( db->enc==SQLITE_UTF8 ){ + memcpy(zVal, sqlite3ValueText(argv[0], ENC(db)), len); + if( ENC(db)==SQLITE_UTF8 ){ sqlite3_result_text(pCtx, zVal, -1, destructor); #ifndef SQLITE_OMIT_UTF16 - }else if( db->enc==SQLITE_UTF16LE ){ + }else if( ENC(db)==SQLITE_UTF16LE ){ sqlite3_result_text16le(pCtx, zVal, -1, destructor); }else{ sqlite3_result_text16be(pCtx, zVal, -1, destructor); @@ -776,7 +776,7 @@ static void test_auxdata( char *zRet = sqliteMalloc(nArg*2); if( !zRet ) return; for(i=0; isum/(double)p->cnt); } } +static void totalFinalize(sqlite3_context *context){ + SumCtx *p; + p = sqlite3_aggregate_context(context, 0); + sqlite3_result_double(context, p ? p->sum : 0.0); +} /* ** An instance of the following structure holds the context of a @@ -1000,6 +1011,7 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ { "min", 1, 0, 1, minmaxStep, minMaxFinalize }, { "max", 1, 2, 1, minmaxStep, minMaxFinalize }, { "sum", 1, 0, 0, sumStep, sumFinalize }, + { "total", 1, 0, 0, sumStep, totalFinalize }, { "avg", 1, 0, 0, sumStep, avgFinalize }, { "count", 0, 0, 0, countStep, countFinalize }, { "count", 1, 0, 0, countStep, countFinalize }, @@ -1012,7 +1024,7 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ case 1: pArg = db; break; case 2: pArg = (void *)(-1); break; } - sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg, + sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg, aFuncs[i].eTextRep, pArg, aFuncs[i].xFunc, 0, 0); if( aFuncs[i].needCollSeq ){ FuncDef *pFunc = sqlite3FindFunction(db, aFuncs[i].zName, @@ -1024,6 +1036,9 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ } #ifndef SQLITE_OMIT_ALTERTABLE sqlite3AlterFunctions(db); +#endif +#ifndef SQLITE_OMIT_PARSER + sqlite3AttachFunctions(db); #endif for(i=0; ipList->nExpr!=2 ){ return 0; } - pDef = sqlite3FindFunction(db, pExpr->token.z, pExpr->token.n, 2, + pDef = sqlite3FindFunction(db, (char*)pExpr->token.z, pExpr->token.n, 2, SQLITE_UTF8, 0); if( pDef==0 || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){ return 0; diff --git a/mozilla/db/sqlite3/src/hash.c b/mozilla/db/sqlite3/src/hash.c index b7b2138da9d..2ef86a84f36 100644 --- a/mozilla/db/sqlite3/src/hash.c +++ b/mozilla/db/sqlite3/src/hash.c @@ -12,7 +12,7 @@ ** This is the implementation of generic hash-tables ** used in SQLite. ** -** $Id: hash.c,v 1.16 2005/01/31 12:56:44 danielk1977 Exp $ +** $Id: hash.c,v 1.17 2005/10/03 15:11:09 drh Exp $ */ #include "sqliteInt.h" #include @@ -294,6 +294,11 @@ static void removeElementGivenHash( } sqliteFree( elem ); pH->count--; + if( pH->count<=0 ){ + assert( pH->first==0 ); + assert( pH->count==0 ); + sqlite3HashClear(pH); + } } /* Attempt to locate an element of the hash table pH with a key diff --git a/mozilla/db/sqlite3/src/insert.c b/mozilla/db/sqlite3/src/insert.c index e19aa7da174..7899610e250 100644 --- a/mozilla/db/sqlite3/src/insert.c +++ b/mozilla/db/sqlite3/src/insert.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: insert.c,v 1.143 2005/09/20 17:42:23 drh Exp $ +** $Id: insert.c,v 1.160 2006/01/24 12:09:19 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -23,10 +23,11 @@ ** ** Character Column affinity ** ------------------------------ -** 'n' NUMERIC -** 'i' INTEGER -** 't' TEXT -** 'o' NONE +** 'a' TEXT +** 'b' NONE +** 'c' NUMERIC +** 'd' INTEGER +** 'e' REAL */ void sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){ if( !pIdx->zColAff ){ @@ -61,10 +62,11 @@ void sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){ ** ** Character Column affinity ** ------------------------------ -** 'n' NUMERIC -** 'i' INTEGER -** 't' TEXT -** 'o' NONE +** 'a' TEXT +** 'b' NONE +** 'c' NUMERIC +** 'd' INTEGER +** 'e' REAL */ void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){ /* The first time a column affinity string for a particular table @@ -102,15 +104,15 @@ void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){ ** ** No checking is done for sub-selects that are part of expressions. */ -static int selectReadsTable(Select *p, int iDb, int iTab){ +static int selectReadsTable(Select *p, Schema *pSchema, int iTab){ int i; struct SrcList_item *pItem; if( p->pSrc==0 ) return 0; for(i=0, pItem=p->pSrc->a; ipSrc->nSrc; i++, pItem++){ if( pItem->pSelect ){ - if( selectReadsTable(pItem->pSelect, iDb, iTab) ) return 1; + if( selectReadsTable(pItem->pSelect, pSchema, iTab) ) return 1; }else{ - if( pItem->pTab->iDb==iDb && pItem->pTab->tnum==iTab ) return 1; + if( pItem->pTab->pSchema==pSchema && pItem->pTab->tnum==iTab ) return 1; } } return 0; @@ -212,6 +214,7 @@ void sqlite3Insert( 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 iDb; #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to insert into a view */ @@ -219,10 +222,12 @@ void sqlite3Insert( #endif #ifndef SQLITE_OMIT_AUTOINCREMENT - int counterRowid; /* Memory cell holding rowid of autoinc counter */ + int counterRowid = 0; /* Memory cell holding rowid of autoinc counter */ #endif - if( pParse->nErr || sqlite3_malloc_failed ) goto insert_cleanup; + if( pParse->nErr || sqlite3MallocFailed() ){ + goto insert_cleanup; + } db = pParse->db; /* Locate the table into which we will be inserting new information. @@ -234,8 +239,9 @@ void sqlite3Insert( if( pTab==0 ){ goto insert_cleanup; } - assert( pTab->iDbnDb ); - pDb = &db->aDb[pTab->iDb]; + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + assert( iDbnDb ); + pDb = &db->aDb[iDb]; zDb = pDb->zName; if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){ goto insert_cleanup; @@ -271,19 +277,12 @@ void sqlite3Insert( goto insert_cleanup; } - /* Ensure all required collation sequences are available. */ - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - if( sqlite3CheckIndexCollSeq(pParse, pIdx) ){ - goto insert_cleanup; - } - } - /* Allocate a VDBE */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto insert_cleanup; if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); - sqlite3BeginWriteOperation(pParse, pSelect || triggers_exist, pTab->iDb); + sqlite3BeginWriteOperation(pParse, pSelect || triggers_exist, iDb); /* if there are row triggers, allocate a temp table for new.* references. */ if( triggers_exist ){ @@ -298,22 +297,20 @@ void sqlite3Insert( */ if( pTab->autoInc ){ int iCur = pParse->nTab; - int base = sqlite3VdbeCurrentAddr(v); + int addr = 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); + sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenRead); + sqlite3VdbeAddOp(v, OP_Rewind, iCur, addr+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_Ne, 0x100, addr+12); sqlite3VdbeAddOp(v, OP_Rowid, 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_Goto, 0, addr+13); + sqlite3VdbeAddOp(v, OP_Next, iCur, addr+4); sqlite3VdbeAddOp(v, OP_Close, iCur, 0); } #endif /* SQLITE_OMIT_AUTOINCREMENT */ @@ -336,7 +333,9 @@ void sqlite3Insert( /* 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; + if( rc || pParse->nErr || sqlite3MallocFailed() ){ + goto insert_cleanup; + } iCleanup = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_Goto, 0, iCleanup); @@ -351,7 +350,7 @@ void sqlite3Insert( ** of the tables being read by the SELECT statement. Also use a ** temp table in the case of row triggers. */ - if( triggers_exist || selectReadsTable(pSelect, pTab->iDb, pTab->tnum) ){ + if( triggers_exist || selectReadsTable(pSelect,pTab->pSchema,pTab->tnum) ){ useTempTable = 1; } @@ -362,7 +361,6 @@ void sqlite3Insert( srcTab = pParse->nTab++; sqlite3VdbeResolveLabel(v, iInsertBlock); sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); - sqlite3TableAffinityStr(v, pTab); sqlite3VdbeAddOp(v, OP_NewRowid, srcTab, 0); sqlite3VdbeAddOp(v, OP_Pull, 1, 0); sqlite3VdbeAddOp(v, OP_Insert, srcTab, 0); @@ -635,7 +633,7 @@ void sqlite3Insert( /* Update the count of rows that are inserted */ if( (db->flags & SQLITE_CountRows)!=0 ){ - sqlite3VdbeAddOp(v, OP_MemIncr, iCntMem, 0); + sqlite3VdbeAddOp(v, OP_MemIncr, 1, iCntMem); } if( triggers_exist ){ @@ -682,12 +680,10 @@ void sqlite3Insert( */ 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); + int addr = sqlite3VdbeCurrentAddr(v); + sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); sqlite3VdbeAddOp(v, OP_MemLoad, counterRowid, 0); - sqlite3VdbeAddOp(v, OP_NotNull, -1, base+7); + sqlite3VdbeAddOp(v, OP_NotNull, -1, addr+7); sqlite3VdbeAddOp(v, OP_Pop, 1, 0); sqlite3VdbeAddOp(v, OP_NewRowid, iCur, 0); sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0); @@ -870,7 +866,18 @@ void sqlite3GenerateConstraintChecks( /* Test all CHECK constraints */ - /**** TBD ****/ +#ifndef SQLITE_OMIT_CHECK + if( pTab->pCheck && (pParse->db->flags & SQLITE_IgnoreChecks)==0 ){ + int allOk = sqlite3VdbeMakeLabel(v); + assert( pParse->ckOffset==0 ); + pParse->ckOffset = nCol; + sqlite3ExprIfTrue(pParse, pTab->pCheck, allOk, 1); + assert( pParse->ckOffset==nCol ); + pParse->ckOffset = 0; + sqlite3VdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, OE_Abort); + sqlite3VdbeResolveLabel(v, allOk); + } +#endif /* !defined(SQLITE_OMIT_CHECK) */ /* If we have an INTEGER PRIMARY KEY, make sure the primary key ** of the new record does not previously exist. Except, if this @@ -1067,9 +1074,13 @@ void sqlite3CompleteInsertion( if( pParse->nested ){ pik_flags = 0; }else{ - pik_flags = (OPFLAG_NCHANGE|(isUpdate?0:OPFLAG_LASTROWID)); + pik_flags = OPFLAG_NCHANGE; + pik_flags |= (isUpdate?OPFLAG_ISUPDATE:OPFLAG_LASTROWID); } sqlite3VdbeAddOp(v, OP_Insert, base, pik_flags); + if( !pParse->nested ){ + sqlite3VdbeChangeP3(v, -1, pTab->zName, P3_STATIC); + } if( isUpdate && rowidChng ){ sqlite3VdbeAddOp(v, OP_Pop, 1, 0); @@ -1088,18 +1099,17 @@ void sqlite3OpenTableAndIndices( int op /* OP_OpenRead or OP_OpenWrite */ ){ int i; + int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); Index *pIdx; Vdbe *v = sqlite3GetVdbe(pParse); assert( v!=0 ); - sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0); - VdbeComment((v, "# %s", pTab->zName)); - sqlite3VdbeAddOp(v, op, base, pTab->tnum); - sqlite3VdbeAddOp(v, OP_SetNumColumns, base, pTab->nCol); + sqlite3OpenTable(pParse, base, iDb, pTab, op); for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ - sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0); + KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); + assert( pIdx->pSchema==pTab->pSchema ); + sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); VdbeComment((v, "# %s", pIdx->zName)); - sqlite3VdbeOp3(v, op, i+base, pIdx->tnum, - (char*)&pIdx->keyInfo, P3_KEYINFO); + sqlite3VdbeOp3(v, op, i+base, pIdx->tnum, (char*)pKey, P3_KEYINFO_HANDOFF); } if( pParse->nTab<=base+i ){ pParse->nTab = base+i; diff --git a/mozilla/db/sqlite3/src/keywordhash.h b/mozilla/db/sqlite3/src/keywordhash.h index 9beb5fbd2e1..c5ce4abfc25 100644 --- a/mozilla/db/sqlite3/src/keywordhash.h +++ b/mozilla/db/sqlite3/src/keywordhash.h @@ -1,28 +1,28 @@ -/* Hash score: 158 */ +/* Hash score: 159 */ static int keywordCode(const char *z, int n){ - static const char zText[535] = + static const char zText[537] = "ABORTABLEFTEMPORARYADDATABASELECTHENDEFAULTRANSACTIONATURALTER" "AISEACHECKEYAFTEREFERENCESCAPELSEXCEPTRIGGEREGEXPLAINITIALLYANALYZE" "XCLUSIVEXISTSTATEMENTANDEFERRABLEATTACHAVINGLOBEFOREIGNOREINDEX" "AUTOINCREMENTBEGINNERENAMEBETWEENOTNULLIKEBYCASCADEFERREDELETE" "CASECASTCOLLATECOLUMNCOMMITCONFLICTCONSTRAINTERSECTCREATECROSS" "CURRENT_DATECURRENT_TIMESTAMPLANDESCDETACHDISTINCTDROPRAGMATCH" - "FAILIMITFROMFULLGROUPDATEIMMEDIATEINSERTINSTEADINTOFFSETISNULL" + "FAILIMITFROMFULLGROUPDATEIFIMMEDIATEINSERTINSTEADINTOFFSETISNULL" "JOINORDEREPLACEOUTERESTRICTPRIMARYQUERYRIGHTROLLBACKROWHENUNION" "UNIQUEUSINGVACUUMVALUESVIEWHERE"; static const unsigned char aHash[127] = { - 91, 80, 106, 90, 0, 4, 0, 0, 113, 0, 83, 0, 0, - 94, 44, 76, 92, 0, 105, 108, 96, 0, 0, 10, 0, 0, - 112, 0, 109, 102, 0, 28, 48, 0, 41, 0, 0, 65, 71, - 0, 63, 19, 0, 104, 36, 103, 0, 107, 74, 0, 0, 33, - 0, 61, 37, 0, 8, 0, 114, 38, 12, 0, 77, 40, 25, + 92, 80, 107, 91, 0, 4, 0, 0, 114, 0, 83, 0, 0, + 95, 44, 76, 93, 0, 106, 109, 97, 90, 0, 10, 0, 0, + 113, 0, 110, 103, 0, 28, 48, 0, 41, 0, 0, 65, 71, + 0, 63, 19, 0, 105, 36, 104, 0, 108, 74, 0, 0, 33, + 0, 61, 37, 0, 8, 0, 115, 38, 12, 0, 77, 40, 25, 66, 0, 0, 31, 81, 53, 30, 50, 20, 88, 0, 34, 0, 75, 26, 0, 72, 0, 0, 0, 64, 47, 67, 22, 87, 29, - 69, 86, 0, 1, 0, 9, 100, 58, 18, 0, 111, 82, 98, - 54, 6, 85, 0, 0, 49, 93, 0, 101, 0, 70, 0, 0, - 15, 0, 115, 51, 56, 0, 2, 55, 0, 110, + 69, 86, 0, 1, 0, 9, 101, 58, 18, 0, 112, 82, 99, + 54, 6, 85, 0, 0, 49, 94, 0, 102, 0, 70, 0, 0, + 15, 0, 116, 51, 56, 0, 2, 55, 0, 111, }; - static const unsigned char aNext[115] = { + static const unsigned char aNext[116] = { 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 5, 13, 0, 7, 0, 0, 0, @@ -30,32 +30,32 @@ static int keywordCode(const char *z, int n){ 0, 0, 16, 0, 23, 52, 0, 0, 0, 0, 45, 0, 59, 0, 0, 0, 0, 0, 0, 0, 0, 73, 42, 0, 24, 60, 21, 0, 79, 0, 0, 68, 0, 0, 84, 46, 0, 0, 0, - 0, 0, 0, 0, 39, 95, 97, 0, 0, 99, 0, 32, 0, - 14, 27, 78, 0, 57, 89, 0, 35, 0, 62, 0, + 0, 0, 0, 0, 0, 39, 96, 98, 0, 0, 100, 0, 32, + 0, 14, 27, 78, 0, 57, 89, 0, 35, 0, 62, 0, }; - static const unsigned char aLen[115] = { + static const unsigned char aLen[116] = { 5, 5, 4, 4, 9, 2, 3, 8, 2, 6, 4, 3, 7, 11, 2, 7, 5, 5, 4, 5, 3, 5, 10, 6, 4, 6, 7, 6, 7, 9, 3, 7, 9, 6, 9, 3, 10, 6, 6, 4, 6, 3, 7, 6, 7, 5, 13, 2, 2, 5, 5, 6, 7, 3, 7, 4, 4, 2, 7, 3, 8, 6, 4, 4, 7, 6, 6, 8, 10, 9, 6, 5, 12, 12, 17, 4, 4, 6, - 8, 2, 4, 6, 5, 4, 5, 4, 4, 5, 6, 9, 6, - 7, 4, 2, 6, 3, 6, 4, 5, 7, 5, 8, 7, 5, - 5, 8, 3, 4, 5, 6, 5, 6, 6, 4, 5, + 8, 2, 4, 6, 5, 4, 5, 4, 4, 5, 6, 2, 9, + 6, 7, 4, 2, 6, 3, 6, 4, 5, 7, 5, 8, 7, + 5, 5, 8, 3, 4, 5, 6, 5, 6, 6, 4, 5, }; - static const unsigned short int aOffset[115] = { + static const unsigned short int aOffset[116] = { 0, 4, 7, 10, 10, 14, 19, 21, 26, 27, 32, 34, 36, 42, 51, 52, 57, 61, 65, 67, 71, 74, 78, 86, 91, 94, 99, 105, 108, 113, 118, 122, 128, 136, 141, 150, 152, 162, 167, 172, 175, 177, 177, 181, 185, 187, 192, 194, 196, 205, 208, 212, 218, 224, 224, 227, 230, 234, 236, 237, 241, 248, 254, 258, 262, 269, 275, 281, 289, 296, 305, 311, 316, 328, 328, 344, 348, 352, - 358, 359, 366, 369, 373, 378, 381, 386, 390, 394, 397, 403, 412, - 418, 425, 428, 428, 431, 434, 440, 444, 448, 455, 459, 467, 474, - 479, 484, 492, 494, 498, 503, 509, 514, 520, 526, 529, + 358, 359, 366, 369, 373, 378, 381, 386, 390, 394, 397, 403, 405, + 414, 420, 427, 430, 430, 433, 436, 442, 446, 450, 457, 461, 469, + 476, 481, 486, 494, 496, 500, 505, 511, 516, 522, 528, 531, }; - static const unsigned char aCode[115] = { + static const unsigned char aCode[116] = { TK_ABORT, TK_TABLE, TK_JOIN_KW, TK_TEMP, TK_TEMP, TK_OR, TK_ADD, TK_DATABASE, TK_AS, TK_SELECT, TK_THEN, TK_END, TK_DEFAULT, TK_TRANSACTION,TK_ON, @@ -73,12 +73,13 @@ static int keywordCode(const char *z, int n){ TK_CREATE, TK_JOIN_KW, TK_CTIME_KW, TK_CTIME_KW, TK_CTIME_KW, TK_PLAN, TK_DESC, TK_DETACH, TK_DISTINCT, TK_IS, TK_DROP, TK_PRAGMA, TK_MATCH, TK_FAIL, TK_LIMIT, - TK_FROM, TK_JOIN_KW, TK_GROUP, TK_UPDATE, TK_IMMEDIATE, - TK_INSERT, TK_INSTEAD, TK_INTO, TK_OF, TK_OFFSET, - TK_SET, TK_ISNULL, TK_JOIN, TK_ORDER, TK_REPLACE, - TK_JOIN_KW, TK_RESTRICT, TK_PRIMARY, TK_QUERY, TK_JOIN_KW, - TK_ROLLBACK, TK_ROW, TK_WHEN, TK_UNION, TK_UNIQUE, - TK_USING, TK_VACUUM, TK_VALUES, TK_VIEW, TK_WHERE, + TK_FROM, TK_JOIN_KW, TK_GROUP, TK_UPDATE, TK_IF, + TK_IMMEDIATE, TK_INSERT, TK_INSTEAD, TK_INTO, TK_OF, + TK_OFFSET, TK_SET, TK_ISNULL, TK_JOIN, TK_ORDER, + TK_REPLACE, TK_JOIN_KW, TK_RESTRICT, TK_PRIMARY, TK_QUERY, + TK_JOIN_KW, TK_ROLLBACK, TK_ROW, TK_WHEN, TK_UNION, + TK_UNIQUE, TK_USING, TK_VACUUM, TK_VALUES, TK_VIEW, + TK_WHERE, }; int h, i; if( n<2 ) return TK_ID; @@ -92,6 +93,6 @@ static int keywordCode(const char *z, int n){ } return TK_ID; } -int sqlite3KeywordCode(const char *z, int n){ - return keywordCode(z, n); +int sqlite3KeywordCode(const unsigned char *z, int n){ + return keywordCode((char*)z, n); } diff --git a/mozilla/db/sqlite3/src/legacy.c b/mozilla/db/sqlite3/src/legacy.c index a44af16ec31..12749c1deba 100644 --- a/mozilla/db/sqlite3/src/legacy.c +++ b/mozilla/db/sqlite3/src/legacy.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: legacy.c,v 1.7 2004/09/06 17:34:13 drh Exp $ +** $Id: legacy.c,v 1.13 2006/01/23 13:14:55 drh Exp $ */ #include "sqliteInt.h" @@ -68,9 +68,8 @@ int sqlite3_exec( nCallback = 0; nCol = sqlite3_column_count(pStmt); - azCols = sqliteMalloc(2*nCol*sizeof(const char *)); - if( nCol && !azCols ){ - rc = SQLITE_NOMEM; + azCols = sqliteMalloc(2*nCol*sizeof(const char *) + 1); + if( azCols==0 ){ goto exec_out; } @@ -122,9 +121,7 @@ exec_out: if( pStmt ) sqlite3_finalize(pStmt); if( azCols ) sqliteFree(azCols); - if( sqlite3_malloc_failed ){ - rc = SQLITE_NOMEM; - } + rc = sqlite3ApiExit(0, rc); if( rc!=SQLITE_OK && rc==sqlite3_errcode(db) && pzErrMsg ){ *pzErrMsg = malloc(1+strlen(sqlite3_errmsg(db))); if( *pzErrMsg ){ diff --git a/mozilla/db/sqlite3/src/main.c b/mozilla/db/sqlite3/src/main.c index d3928fd4f71..7daadf6936f 100644 --- a/mozilla/db/sqlite3/src/main.c +++ b/mozilla/db/sqlite3/src/main.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.302 2005/09/17 15:20:27 drh Exp $ +** $Id: main.c,v 1.331 2006/01/24 16:37:58 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -26,28 +26,6 @@ */ const int sqlite3one = 1; -#ifndef SQLITE_OMIT_GLOBALRECOVER -/* -** Linked list of all open database handles. This is used by the -** sqlite3_global_recover() function. Entries are added to the list -** by openDatabase() and removed by sqlite3_close(). -*/ -static sqlite3 *pDbList = 0; -#endif - -#ifndef SQLITE_OMIT_UTF16 -/* -** Return the transient sqlite3_value object used for encoding conversions -** during SQL compilation. -*/ -sqlite3_value *sqlite3GetTransientValue(sqlite3 *db){ - if( !db->pValue ){ - db->pValue = sqlite3ValueNew(); - } - return db->pValue; -} -#endif - /* ** The version of the library */ @@ -158,6 +136,9 @@ int sqlite3_close(sqlite3 *db){ if( pDb->pBt ){ sqlite3BtreeClose(pDb->pBt); pDb->pBt = 0; + if( j!=1 ){ + pDb->pSchema = 0; + } } } sqlite3ResetInternalSchema(db, 0); @@ -179,33 +160,21 @@ int sqlite3_close(sqlite3 *db){ sqlite3HashClear(&db->aFunc); sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */ - if( db->pValue ){ - sqlite3ValueFree(db->pValue); - } if( db->pErr ){ sqlite3ValueFree(db->pErr); } -#ifndef SQLITE_OMIT_GLOBALRECOVER - { - sqlite3 *pPrev; - sqlite3OsEnterMutex(); - pPrev = pDbList; - while( pPrev && pPrev->pNext!=db ){ - pPrev = pPrev->pNext; - } - if( pPrev ){ - pPrev->pNext = db->pNext; - }else{ - assert( pDbList==db ); - pDbList = db->pNext; - } - sqlite3OsLeaveMutex(); - } -#endif - db->magic = SQLITE_MAGIC_ERROR; + + /* The temp-database schema is allocated differently from the other schema + ** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()). + ** So it needs to be freed here. Todo: Why not roll the temp schema into + ** the same sqliteMalloc() as the one that allocates the database + ** structure? + */ + sqliteFree(db->aDb[1].pSchema); sqliteFree(db); + sqlite3ReleaseThreadData(); return SQLITE_OK; } @@ -214,13 +183,24 @@ int sqlite3_close(sqlite3 *db){ */ void sqlite3RollbackAll(sqlite3 *db){ int i; + int inTrans = 0; for(i=0; inDb; i++){ if( db->aDb[i].pBt ){ + if( sqlite3BtreeIsInTrans(db->aDb[i].pBt) ){ + inTrans = 1; + } sqlite3BtreeRollback(db->aDb[i].pBt); db->aDb[i].inTrans = 0; } } - sqlite3ResetInternalSchema(db, 0); + if( db->flags&SQLITE_InternChanges ){ + sqlite3ResetInternalSchema(db, 0); + } + + /* If one has been configured, invoke the rollback-hook callback */ + if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){ + db->xRollbackCallback(db->pRollbackArg); + } } /* @@ -402,9 +382,12 @@ void sqlite3_interrupt(sqlite3 *db){ void sqlite3_free(char *p){ free(p); } /* -** Create new user functions. +** This function is exactly the same as sqlite3_create_function(), except +** that it is designed to be called by internal code. The difference is +** that if a malloc() fails in sqlite3_create_function(), an error code +** is returned and the mallocFailed flag cleared. */ -int sqlite3_create_function( +int sqlite3CreateFunc( sqlite3 *db, const char *zFunctionName, int nArg, @@ -441,10 +424,10 @@ int sqlite3_create_function( enc = SQLITE_UTF16NATIVE; }else if( enc==SQLITE_ANY ){ int rc; - rc = sqlite3_create_function(db, zFunctionName, nArg, SQLITE_UTF8, + rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8, pUserData, xFunc, xStep, xFinal); if( rc!=SQLITE_OK ) return rc; - rc = sqlite3_create_function(db, zFunctionName, nArg, SQLITE_UTF16LE, + rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE, pUserData, xFunc, xStep, xFinal); if( rc!=SQLITE_OK ) return rc; enc = SQLITE_UTF16BE; @@ -463,6 +446,7 @@ int sqlite3_create_function( if( db->activeVdbeCnt ){ sqlite3Error(db, SQLITE_BUSY, "Unable to delete/modify user-function due to active statements"); + assert( !sqlite3MallocFailed() ); return SQLITE_BUSY; }else{ sqlite3ExpirePreparedStatements(db); @@ -470,42 +454,56 @@ int sqlite3_create_function( } p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 1); - if( p==0 ) return SQLITE_NOMEM; - p->flags = 0; - p->xFunc = xFunc; - p->xStep = xStep; - p->xFinalize = xFinal; - p->pUserData = pUserData; + if( p ){ + p->flags = 0; + p->xFunc = xFunc; + p->xStep = xStep; + p->xFinalize = xFinal; + p->pUserData = pUserData; + } return SQLITE_OK; } + +/* +** Create new user functions. +*/ +int sqlite3_create_function( + sqlite3 *db, + const char *zFunctionName, + int nArg, + int enc, + void *p, + void (*xFunc)(sqlite3_context*,int,sqlite3_value **), + void (*xStep)(sqlite3_context*,int,sqlite3_value **), + void (*xFinal)(sqlite3_context*) +){ + int rc; + assert( !sqlite3MallocFailed() ); + rc = sqlite3CreateFunc(db, zFunctionName, nArg, enc, p, xFunc, xStep, xFinal); + + return sqlite3ApiExit(db, rc); +} + #ifndef SQLITE_OMIT_UTF16 int sqlite3_create_function16( sqlite3 *db, const void *zFunctionName, int nArg, int eTextRep, - void *pUserData, + void *p, void (*xFunc)(sqlite3_context*,int,sqlite3_value**), void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*) ){ int rc; - char const *zFunc8; - sqlite3_value *pTmp; + char *zFunc8; + assert( !sqlite3MallocFailed() ); - if( sqlite3SafetyCheck(db) ){ - return SQLITE_MISUSE; - } - pTmp = sqlite3GetTransientValue(db); - sqlite3ValueSetStr(pTmp, -1, zFunctionName, SQLITE_UTF16NATIVE,SQLITE_STATIC); - zFunc8 = sqlite3ValueText(pTmp, SQLITE_UTF8); + zFunc8 = sqlite3utf16to8(zFunctionName, -1); + rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xFunc, xStep, xFinal); + sqliteFree(zFunc8); - if( !zFunc8 ){ - return SQLITE_NOMEM; - } - rc = sqlite3_create_function(db, zFunc8, nArg, eTextRep, - pUserData, xFunc, xStep, xFinal); - return rc; + return sqlite3ApiExit(db, rc); } #endif @@ -547,7 +545,7 @@ void *sqlite3_profile( /*** EXPERIMENTAL *** ** ** Register a function to be invoked when a transaction comments. -** If either function returns non-zero, then the commit becomes a +** If the invoked function returns non-zero, then the commit becomes a ** rollback. */ void *sqlite3_commit_hook( @@ -561,6 +559,35 @@ void *sqlite3_commit_hook( return pOld; } +/* +** Register a callback to be invoked each time a row is updated, +** inserted or deleted using this database connection. +*/ +void *sqlite3_update_hook( + sqlite3 *db, /* Attach the hook to this database */ + void (*xCallback)(void*,int,char const *,char const *,sqlite_int64), + void *pArg /* Argument to the function */ +){ + void *pRet = db->pUpdateArg; + db->xUpdateCallback = xCallback; + db->pUpdateArg = pArg; + return pRet; +} + +/* +** Register a callback to be invoked each time a transaction is rolled +** back by this database connection. +*/ +void *sqlite3_rollback_hook( + sqlite3 *db, /* Attach the hook to this database */ + void (*xCallback)(void*), /* Callback function */ + void *pArg /* Argument to the function */ +){ + void *pRet = db->pRollbackArg; + db->xRollbackCallback = xCallback; + db->pRollbackArg = pArg; + return pRet; +} /* ** This routine is called to create a connection to a database BTree @@ -621,7 +648,7 @@ int sqlite3BtreeFactory( #endif /* SQLITE_OMIT_MEMORYDB */ } - rc = sqlite3BtreeOpen(zFilename, ppBtree, btree_flags); + rc = sqlite3BtreeOpen(zFilename, (sqlite3 *)db, ppBtree, btree_flags); if( rc==SQLITE_OK ){ sqlite3BtreeSetBusyHandler(*ppBtree, (void*)&db->busyHandler); sqlite3BtreeSetCacheSize(*ppBtree, nCache); @@ -635,13 +662,13 @@ int sqlite3BtreeFactory( */ const char *sqlite3_errmsg(sqlite3 *db){ const char *z; - if( sqlite3_malloc_failed ){ + if( !db || sqlite3MallocFailed() ){ return sqlite3ErrStr(SQLITE_NOMEM); } if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){ return sqlite3ErrStr(SQLITE_MISUSE); } - z = sqlite3_value_text(db->pErr); + z = (char*)sqlite3_value_text(db->pErr); if( z==0 ){ z = sqlite3ErrStr(db->errCode); } @@ -674,7 +701,7 @@ const void *sqlite3_errmsg16(sqlite3 *db){ }; const void *z; - if( sqlite3_malloc_failed ){ + if( sqlite3MallocFailed() ){ return (void *)(&outOfMemBe[SQLITE_UTF16NATIVE==SQLITE_UTF16LE?1:0]); } if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){ @@ -686,15 +713,17 @@ const void *sqlite3_errmsg16(sqlite3 *db){ SQLITE_UTF8, SQLITE_STATIC); z = sqlite3_value_text16(db->pErr); } + sqlite3ApiExit(0, 0); return z; } #endif /* SQLITE_OMIT_UTF16 */ /* -** Return the most recent error code generated by an SQLite routine. +** Return the most recent error code generated by an SQLite routine. If NULL is +** passed to this function, we assume a malloc() failed during sqlite3_open(). */ int sqlite3_errcode(sqlite3 *db){ - if( sqlite3_malloc_failed ){ + if( !db || sqlite3MallocFailed() ){ return SQLITE_NOMEM; } if( sqlite3SafetyCheck(db) ){ @@ -703,6 +732,60 @@ int sqlite3_errcode(sqlite3 *db){ return db->errCode; } +static int createCollation( + sqlite3* db, + const char *zName, + int enc, + void* pCtx, + int(*xCompare)(void*,int,const void*,int,const void*) +){ + CollSeq *pColl; + + if( sqlite3SafetyCheck(db) ){ + return SQLITE_MISUSE; + } + + /* 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. + */ + if( enc==SQLITE_UTF16 ){ + enc = SQLITE_UTF16NATIVE; + } + + if( enc!=SQLITE_UTF8 && enc!=SQLITE_UTF16LE && enc!=SQLITE_UTF16BE ){ + sqlite3Error(db, SQLITE_ERROR, + "Param 3 to sqlite3_create_collation() must be one of " + "SQLITE_UTF8, SQLITE_UTF16, SQLITE_UTF16LE or SQLITE_UTF16BE" + ); + 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( pColl ){ + pColl->xCmp = xCompare; + pColl->pUser = pCtx; + pColl->enc = enc; + } + sqlite3Error(db, SQLITE_OK, 0); + return SQLITE_OK; +} + + /* ** This routine does the work of opening a database on behalf of ** sqlite3_open() and sqlite3_open16(). The database filename "zFilename" @@ -713,9 +796,11 @@ static int openDatabase( sqlite3 **ppDb /* OUT: Returned database handle */ ){ sqlite3 *db; - int rc, i; + int rc; CollSeq *pColl; + assert( !sqlite3MallocFailed() ); + /* Allocate the sqlite data structure */ db = sqliteMalloc( sizeof(sqlite3) ); if( db==0 ) goto opendb_out; @@ -723,33 +808,26 @@ static int openDatabase( db->magic = SQLITE_MAGIC_BUSY; db->nDb = 2; db->aDb = db->aDbStatic; - db->enc = SQLITE_UTF8; db->autoCommit = 1; db->flags |= SQLITE_ShortColNames; sqlite3HashInit(&db->aFunc, SQLITE_HASH_STRING, 0); sqlite3HashInit(&db->aCollSeq, SQLITE_HASH_STRING, 0); - for(i=0; inDb; i++){ - sqlite3HashInit(&db->aDb[i].tblHash, SQLITE_HASH_STRING, 0); - sqlite3HashInit(&db->aDb[i].idxHash, SQLITE_HASH_STRING, 0); - sqlite3HashInit(&db->aDb[i].trigHash, SQLITE_HASH_STRING, 0); - sqlite3HashInit(&db->aDb[i].aFKey, SQLITE_HASH_STRING, 1); - } - + /* Add the default collation sequence BINARY. BINARY works for both UTF-8 ** 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. */ - 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 ); + if( createCollation(db, "BINARY", SQLITE_UTF8, 0,binCollFunc) || + createCollation(db, "BINARY", SQLITE_UTF16, 0,binCollFunc) || + (db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0))==0 + ){ + assert( sqlite3MallocFailed() ); db->magic = SQLITE_MAGIC_CLOSED; goto opendb_out; } /* Also add a UTF-8 case-insensitive collation sequence. */ - sqlite3_create_collation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc); + createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc); /* Set flags on the built-in collating sequences */ db->pDfltColl->type = SQLITE_COLL_BINARY; @@ -765,6 +843,14 @@ static int openDatabase( db->magic = SQLITE_MAGIC_CLOSED; goto opendb_out; } +#ifndef SQLITE_OMIT_PARSER + db->aDb[0].pSchema = sqlite3SchemaGet(db->aDb[0].pBt); + db->aDb[1].pSchema = sqlite3SchemaGet(0); +#endif + + if( db->aDb[0].pSchema ){ + ENC(db) = SQLITE_UTF8; + } /* The default safety_level for the main database is 'full'; for the temp ** database it is 'NONE'. This matches the pager layer defaults. @@ -776,29 +862,23 @@ static int openDatabase( db->aDb[1].safety_level = 1; #endif - /* Register all built-in functions, but do not attempt to read the ** database schema yet. This is delayed until the first time the database ** is accessed. */ - sqlite3RegisterBuiltinFunctions(db); - sqlite3Error(db, SQLITE_OK, 0); + if( !sqlite3MallocFailed() ){ + sqlite3RegisterBuiltinFunctions(db); + sqlite3Error(db, SQLITE_OK, 0); + } db->magic = SQLITE_MAGIC_OPEN; opendb_out: - if( sqlite3_errcode(db)==SQLITE_OK && sqlite3_malloc_failed ){ - sqlite3Error(db, SQLITE_NOMEM, 0); + if( SQLITE_NOMEM==(rc = sqlite3_errcode(db)) ){ + sqlite3_close(db); + db = 0; } *ppDb = db; -#ifndef SQLITE_OMIT_GLOBALRECOVER - if( db ){ - sqlite3OsEnterMutex(); - db->pNext = pDbList; - pDbList = db; - sqlite3OsLeaveMutex(); - } -#endif - return sqlite3_errcode(db); + return sqlite3ApiExit(0, rc); } /* @@ -820,9 +900,10 @@ int sqlite3_open16( sqlite3 **ppDb ){ char const *zFilename8; /* zFilename encoded in UTF-8 instead of UTF-16 */ - int rc = SQLITE_NOMEM; + int rc = SQLITE_OK; sqlite3_value *pVal; + assert( zFilename ); assert( ppDb ); *ppDb = 0; pVal = sqlite3ValueNew(); @@ -831,14 +912,16 @@ int sqlite3_open16( if( zFilename8 ){ rc = openDatabase(zFilename8, ppDb); if( rc==SQLITE_OK && *ppDb ){ - sqlite3_exec(*ppDb, "PRAGMA encoding = 'UTF-16'", 0, 0, 0); + rc = sqlite3_exec(*ppDb, "PRAGMA encoding = 'UTF-16'", 0, 0, 0); + if( rc!=SQLITE_OK ){ + sqlite3_close(*ppDb); + *ppDb = 0; + } } } - if( pVal ){ - sqlite3ValueFree(pVal); - } + sqlite3ValueFree(pVal); - return rc; + return sqlite3ApiExit(0, rc); } #endif /* SQLITE_OMIT_UTF16 */ @@ -890,53 +973,10 @@ int sqlite3_create_collation( void* pCtx, int(*xCompare)(void*,int,const void*,int,const void*) ){ - CollSeq *pColl; - int rc = SQLITE_OK; - - if( sqlite3SafetyCheck(db) ){ - return SQLITE_MISUSE; - } - - /* 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. - */ - if( enc==SQLITE_UTF16 ){ - enc = SQLITE_UTF16NATIVE; - } - - if( enc!=SQLITE_UTF8 && enc!=SQLITE_UTF16LE && enc!=SQLITE_UTF16BE ){ - sqlite3Error(db, SQLITE_ERROR, - "Param 3 to sqlite3_create_collation() must be one of " - "SQLITE_UTF8, SQLITE_UTF16, SQLITE_UTF16LE or SQLITE_UTF16BE" - ); - 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; - }else{ - pColl->xCmp = xCompare; - pColl->pUser = pCtx; - pColl->enc = enc; - } - sqlite3Error(db, rc, 0); - return rc; + int rc; + assert( !sqlite3MallocFailed() ); + rc = createCollation(db, zName, enc, pCtx, xCompare); + return sqlite3ApiExit(db, rc); } #ifndef SQLITE_OMIT_UTF16 @@ -950,15 +990,15 @@ int sqlite3_create_collation16( void* pCtx, int(*xCompare)(void*,int,const void*,int,const void*) ){ - char const *zName8; - sqlite3_value *pTmp; - if( sqlite3SafetyCheck(db) ){ - return SQLITE_MISUSE; + int rc = SQLITE_OK; + char *zName8; + assert( !sqlite3MallocFailed() ); + zName8 = sqlite3utf16to8(zName, -1); + if( zName8 ){ + rc = createCollation(db, zName8, enc, pCtx, xCompare); + sqliteFree(zName8); } - pTmp = sqlite3GetTransientValue(db); - sqlite3ValueSetStr(pTmp, -1, zName, SQLITE_UTF16NATIVE, SQLITE_STATIC); - zName8 = sqlite3ValueText(pTmp, SQLITE_UTF8); - return sqlite3_create_collation(db, zName8, enc, pCtx, xCompare); + return sqlite3ApiExit(db, rc); } #endif /* SQLITE_OMIT_UTF16 */ @@ -1002,37 +1042,11 @@ int sqlite3_collation_needed16( #ifndef SQLITE_OMIT_GLOBALRECOVER /* -** This function is called to recover from a malloc failure that occured -** within SQLite. -** -** This function is *not* threadsafe. Calling this from within a threaded -** application when threads other than the caller have used SQLite is -** dangerous and will almost certainly result in malfunctions. +** This function is now an anachronism. It used to be used to recover from a +** malloc() failure, but SQLite now does this automatically. */ int sqlite3_global_recover(){ - int rc = SQLITE_OK; - - if( sqlite3_malloc_failed ){ - sqlite3 *db; - int i; - sqlite3_malloc_failed = 0; - for(db=pDbList; db; db=db->pNext ){ - sqlite3ExpirePreparedStatements(db); - for(i=0; inDb; i++){ - Btree *pBt = db->aDb[i].pBt; - if( pBt && (rc=sqlite3BtreeReset(pBt)) ){ - goto recover_out; - } - } - db->autoCommit = 1; - } - } - -recover_out: - if( rc!=SQLITE_OK ){ - sqlite3_malloc_failed = 1; - } - return rc; + return SQLITE_OK; } #endif @@ -1058,3 +1072,44 @@ int sqlite3Corrupt(void){ return SQLITE_CORRUPT; } #endif + + +#ifndef SQLITE_OMIT_SHARED_CACHE +/* +** Enable or disable the shared pager and schema features for the +** current thread. +** +** This routine should only be called when there are no open +** database connections. +*/ +int sqlite3_enable_shared_cache(int enable){ + ThreadData *pTd = sqlite3ThreadData(); + if( pTd ){ + /* It is only legal to call sqlite3_enable_shared_cache() when there + ** are no currently open b-trees that were opened by the calling thread. + ** This condition is only easy to detect if the shared-cache were + ** previously enabled (and is being disabled). + */ + if( pTd->pBtree && !enable ){ + assert( pTd->useSharedData ); + return SQLITE_MISUSE; + } + + pTd->useSharedData = enable; + sqlite3ReleaseThreadData(); + } + return sqlite3ApiExit(0, SQLITE_OK); +} +#endif + +/* +** This is a convenience routine that makes sure that all thread-specific +** data for this thread has been deallocated. +*/ +void sqlite3_thread_cleanup(void){ + ThreadData *pTd = sqlite3OsThreadSpecificData(0); + if( pTd ){ + memset(pTd, 0, sizeof(*pTd)); + sqlite3OsThreadSpecificData(-1); + } +} diff --git a/mozilla/db/sqlite3/src/opcodes.c b/mozilla/db/sqlite3/src/opcodes.c index 189cdfe0417..9f1bdbaaea6 100644 --- a/mozilla/db/sqlite3/src/opcodes.c +++ b/mozilla/db/sqlite3/src/opcodes.c @@ -11,111 +11,111 @@ const char *const sqlite3OpcodeNames[] = { "?", /* 7 */ "RowKey", /* 8 */ "OpenWrite", /* 9 */ "If", - /* 10 */ "ToInt", - /* 11 */ "Pop", - /* 12 */ "CollSeq", - /* 13 */ "OpenRead", - /* 14 */ "Expire", - /* 15 */ "AutoCommit", - /* 16 */ "IntegrityCk", + /* 10 */ "Pop", + /* 11 */ "CollSeq", + /* 12 */ "OpenRead", + /* 13 */ "Expire", + /* 14 */ "AutoCommit", + /* 15 */ "IntegrityCk", + /* 16 */ "Not", /* 17 */ "Sort", /* 18 */ "Function", /* 19 */ "Noop", /* 20 */ "Return", /* 21 */ "NewRowid", - /* 22 */ "Variable", - /* 23 */ "String", - /* 24 */ "ParseSchema", - /* 25 */ "Close", - /* 26 */ "CreateIndex", - /* 27 */ "IsUnique", - /* 28 */ "IdxIsNull", - /* 29 */ "NotFound", - /* 30 */ "Int64", - /* 31 */ "MustBeInt", - /* 32 */ "Halt", - /* 33 */ "Rowid", - /* 34 */ "IdxLT", - /* 35 */ "AddImm", - /* 36 */ "Statement", - /* 37 */ "RowData", - /* 38 */ "MemMax", - /* 39 */ "Push", - /* 40 */ "NotExists", - /* 41 */ "MemIncr", - /* 42 */ "Gosub", - /* 43 */ "Integer", - /* 44 */ "ToNumeric", - /* 45 */ "MemInt", - /* 46 */ "Prev", - /* 47 */ "CreateTable", - /* 48 */ "Last", - /* 49 */ "IdxRowid", - /* 50 */ "MakeIdxRec", - /* 51 */ "ResetCount", - /* 52 */ "FifoWrite", - /* 53 */ "Callback", - /* 54 */ "ContextPush", - /* 55 */ "DropTrigger", - /* 56 */ "DropIndex", - /* 57 */ "IdxGE", - /* 58 */ "IdxDelete", - /* 59 */ "Vacuum", - /* 60 */ "MoveLe", - /* 61 */ "IfNot", - /* 62 */ "DropTable", - /* 63 */ "MakeRecord", - /* 64 */ "ToBlob", - /* 65 */ "Delete", - /* 66 */ "AggFinal", - /* 67 */ "Or", - /* 68 */ "And", - /* 69 */ "Not", - /* 70 */ "Dup", - /* 71 */ "Goto", - /* 72 */ "FifoRead", - /* 73 */ "IsNull", - /* 74 */ "NotNull", - /* 75 */ "Ne", - /* 76 */ "Eq", - /* 77 */ "Gt", - /* 78 */ "Le", - /* 79 */ "Lt", - /* 80 */ "Ge", - /* 81 */ "Clear", - /* 82 */ "BitAnd", - /* 83 */ "BitOr", - /* 84 */ "ShiftLeft", - /* 85 */ "ShiftRight", - /* 86 */ "Add", - /* 87 */ "Subtract", - /* 88 */ "Multiply", - /* 89 */ "Divide", - /* 90 */ "Remainder", - /* 91 */ "Concat", - /* 92 */ "Negative", - /* 93 */ "IdxGT", - /* 94 */ "BitNot", - /* 95 */ "String8", + /* 22 */ "IfMemNeg", + /* 23 */ "Variable", + /* 24 */ "String", + /* 25 */ "RealAffinity", + /* 26 */ "ParseSchema", + /* 27 */ "Close", + /* 28 */ "CreateIndex", + /* 29 */ "IsUnique", + /* 30 */ "IdxIsNull", + /* 31 */ "NotFound", + /* 32 */ "Int64", + /* 33 */ "MustBeInt", + /* 34 */ "Halt", + /* 35 */ "Rowid", + /* 36 */ "IdxLT", + /* 37 */ "AddImm", + /* 38 */ "Statement", + /* 39 */ "RowData", + /* 40 */ "MemMax", + /* 41 */ "Push", + /* 42 */ "NotExists", + /* 43 */ "MemIncr", + /* 44 */ "Gosub", + /* 45 */ "Integer", + /* 46 */ "MemInt", + /* 47 */ "Prev", + /* 48 */ "CreateTable", + /* 49 */ "Last", + /* 50 */ "IdxRowid", + /* 51 */ "MakeIdxRec", + /* 52 */ "ResetCount", + /* 53 */ "FifoWrite", + /* 54 */ "Callback", + /* 55 */ "ContextPush", + /* 56 */ "DropTrigger", + /* 57 */ "DropIndex", + /* 58 */ "IdxGE", + /* 59 */ "Or", + /* 60 */ "And", + /* 61 */ "IdxDelete", + /* 62 */ "Vacuum", + /* 63 */ "MoveLe", + /* 64 */ "IsNull", + /* 65 */ "NotNull", + /* 66 */ "Ne", + /* 67 */ "Eq", + /* 68 */ "Gt", + /* 69 */ "Le", + /* 70 */ "Lt", + /* 71 */ "Ge", + /* 72 */ "IfNot", + /* 73 */ "BitAnd", + /* 74 */ "BitOr", + /* 75 */ "ShiftLeft", + /* 76 */ "ShiftRight", + /* 77 */ "Add", + /* 78 */ "Subtract", + /* 79 */ "Multiply", + /* 80 */ "Divide", + /* 81 */ "Remainder", + /* 82 */ "Concat", + /* 83 */ "Negative", + /* 84 */ "DropTable", + /* 85 */ "BitNot", + /* 86 */ "String8", + /* 87 */ "MakeRecord", + /* 88 */ "Delete", + /* 89 */ "AggFinal", + /* 90 */ "Dup", + /* 91 */ "Goto", + /* 92 */ "TableLock", + /* 93 */ "FifoRead", + /* 94 */ "Clear", + /* 95 */ "IdxGT", /* 96 */ "MoveLt", /* 97 */ "VerifyCookie", /* 98 */ "AggStep", /* 99 */ "Pull", - /* 100 */ "ToText", - /* 101 */ "SetNumColumns", - /* 102 */ "AbsValue", - /* 103 */ "Transaction", - /* 104 */ "ContextPop", - /* 105 */ "Next", - /* 106 */ "IdxInsert", - /* 107 */ "Distinct", - /* 108 */ "Insert", - /* 109 */ "Destroy", - /* 110 */ "ReadCookie", - /* 111 */ "ForceInt", - /* 112 */ "LoadAnalysis", - /* 113 */ "OpenVirtual", - /* 114 */ "Explain", + /* 100 */ "SetNumColumns", + /* 101 */ "AbsValue", + /* 102 */ "Transaction", + /* 103 */ "ContextPop", + /* 104 */ "Next", + /* 105 */ "IdxInsert", + /* 106 */ "Distinct", + /* 107 */ "Insert", + /* 108 */ "Destroy", + /* 109 */ "ReadCookie", + /* 110 */ "ForceInt", + /* 111 */ "LoadAnalysis", + /* 112 */ "OpenVirtual", + /* 113 */ "Explain", + /* 114 */ "IfMemZero", /* 115 */ "OpenPseudo", /* 116 */ "Null", /* 117 */ "Blob", @@ -125,16 +125,23 @@ const char *const sqlite3OpcodeNames[] = { "?", /* 121 */ "MemMove", /* 122 */ "MemNull", /* 123 */ "Found", - /* 124 */ "NullRow", - /* 125 */ "NotUsed_125", - /* 126 */ "NotUsed_126", + /* 124 */ "Real", + /* 125 */ "HexBlob", + /* 126 */ "NullRow", /* 127 */ "NotUsed_127", /* 128 */ "NotUsed_128", /* 129 */ "NotUsed_129", /* 130 */ "NotUsed_130", /* 131 */ "NotUsed_131", /* 132 */ "NotUsed_132", - /* 133 */ "Real", - /* 134 */ "HexBlob", + /* 133 */ "NotUsed_133", + /* 134 */ "NotUsed_134", + /* 135 */ "NotUsed_135", + /* 136 */ "NotUsed_136", + /* 137 */ "ToText", + /* 138 */ "ToBlob", + /* 139 */ "ToNumeric", + /* 140 */ "ToInt", + /* 141 */ "ToReal", }; #endif diff --git a/mozilla/db/sqlite3/src/opcodes.h b/mozilla/db/sqlite3/src/opcodes.h index 4db3ec16399..e768d603503 100644 --- a/mozilla/db/sqlite3/src/opcodes.h +++ b/mozilla/db/sqlite3/src/opcodes.h @@ -1,149 +1,159 @@ /* Automatically generated. Do not edit */ /* See the mkopcodeh.awk script for details */ #define OP_MemLoad 1 -#define OP_HexBlob 134 /* same as TK_BLOB */ +#define OP_HexBlob 125 /* same as TK_BLOB */ #define OP_Column 2 #define OP_SetCookie 3 #define OP_IfMemPos 4 -#define OP_Real 133 /* same as TK_FLOAT */ +#define OP_Real 124 /* same as TK_FLOAT */ #define OP_Sequence 5 #define OP_MoveGt 6 -#define OP_Ge 80 /* same as TK_GE */ +#define OP_Ge 71 /* same as TK_GE */ #define OP_RowKey 7 -#define OP_Eq 76 /* same as TK_EQ */ +#define OP_Eq 67 /* same as TK_EQ */ #define OP_OpenWrite 8 -#define OP_NotNull 74 /* same as TK_NOTNULL */ +#define OP_NotNull 65 /* same as TK_NOTNULL */ #define OP_If 9 -#define OP_ToInt 10 -#define OP_String8 95 /* same as TK_STRING */ -#define OP_Pop 11 -#define OP_CollSeq 12 -#define OP_OpenRead 13 -#define OP_Expire 14 -#define OP_AutoCommit 15 -#define OP_Gt 77 /* same as TK_GT */ -#define OP_IntegrityCk 16 +#define OP_ToInt 140 /* same as TK_TO_INT */ +#define OP_String8 86 /* same as TK_STRING */ +#define OP_Pop 10 +#define OP_CollSeq 11 +#define OP_OpenRead 12 +#define OP_Expire 13 +#define OP_AutoCommit 14 +#define OP_Gt 68 /* same as TK_GT */ +#define OP_IntegrityCk 15 #define OP_Sort 17 #define OP_Function 18 -#define OP_And 68 /* same as TK_AND */ -#define OP_Subtract 87 /* same as TK_MINUS */ +#define OP_And 60 /* same as TK_AND */ +#define OP_Subtract 78 /* same as TK_MINUS */ #define OP_Noop 19 #define OP_Return 20 -#define OP_Remainder 90 /* same as TK_REM */ +#define OP_Remainder 81 /* same as TK_REM */ #define OP_NewRowid 21 -#define OP_Multiply 88 /* same as TK_STAR */ -#define OP_Variable 22 -#define OP_String 23 -#define OP_ParseSchema 24 -#define OP_Close 25 -#define OP_CreateIndex 26 -#define OP_IsUnique 27 -#define OP_IdxIsNull 28 -#define OP_NotFound 29 -#define OP_Int64 30 -#define OP_MustBeInt 31 -#define OP_Halt 32 -#define OP_Rowid 33 -#define OP_IdxLT 34 -#define OP_AddImm 35 -#define OP_Statement 36 -#define OP_RowData 37 -#define OP_MemMax 38 -#define OP_Push 39 -#define OP_Or 67 /* same as TK_OR */ -#define OP_NotExists 40 -#define OP_MemIncr 41 -#define OP_Gosub 42 -#define OP_Divide 89 /* same as TK_SLASH */ -#define OP_Integer 43 -#define OP_ToNumeric 44 -#define OP_MemInt 45 -#define OP_Prev 46 -#define OP_Concat 91 /* same as TK_CONCAT */ -#define OP_BitAnd 82 /* same as TK_BITAND */ -#define OP_CreateTable 47 -#define OP_Last 48 -#define OP_IsNull 73 /* same as TK_ISNULL */ -#define OP_IdxRowid 49 -#define OP_MakeIdxRec 50 -#define OP_ShiftRight 85 /* same as TK_RSHIFT */ -#define OP_ResetCount 51 -#define OP_FifoWrite 52 -#define OP_Callback 53 -#define OP_ContextPush 54 -#define OP_DropTrigger 55 -#define OP_DropIndex 56 -#define OP_IdxGE 57 -#define OP_IdxDelete 58 -#define OP_Vacuum 59 -#define OP_MoveLe 60 -#define OP_IfNot 61 -#define OP_DropTable 62 -#define OP_MakeRecord 63 -#define OP_ToBlob 64 -#define OP_Delete 65 -#define OP_AggFinal 66 -#define OP_ShiftLeft 84 /* same as TK_LSHIFT */ -#define OP_Dup 70 -#define OP_Goto 71 -#define OP_FifoRead 72 -#define OP_Clear 81 -#define OP_IdxGT 93 +#define OP_Multiply 79 /* same as TK_STAR */ +#define OP_IfMemNeg 22 +#define OP_Variable 23 +#define OP_String 24 +#define OP_RealAffinity 25 +#define OP_ParseSchema 26 +#define OP_Close 27 +#define OP_CreateIndex 28 +#define OP_IsUnique 29 +#define OP_IdxIsNull 30 +#define OP_NotFound 31 +#define OP_Int64 32 +#define OP_MustBeInt 33 +#define OP_Halt 34 +#define OP_Rowid 35 +#define OP_IdxLT 36 +#define OP_AddImm 37 +#define OP_Statement 38 +#define OP_RowData 39 +#define OP_MemMax 40 +#define OP_Push 41 +#define OP_Or 59 /* same as TK_OR */ +#define OP_NotExists 42 +#define OP_MemIncr 43 +#define OP_Gosub 44 +#define OP_Divide 80 /* same as TK_SLASH */ +#define OP_Integer 45 +#define OP_ToNumeric 139 /* same as TK_TO_NUMERIC*/ +#define OP_MemInt 46 +#define OP_Prev 47 +#define OP_Concat 82 /* same as TK_CONCAT */ +#define OP_BitAnd 73 /* same as TK_BITAND */ +#define OP_CreateTable 48 +#define OP_Last 49 +#define OP_IsNull 64 /* same as TK_ISNULL */ +#define OP_IdxRowid 50 +#define OP_MakeIdxRec 51 +#define OP_ShiftRight 76 /* same as TK_RSHIFT */ +#define OP_ResetCount 52 +#define OP_FifoWrite 53 +#define OP_Callback 54 +#define OP_ContextPush 55 +#define OP_DropTrigger 56 +#define OP_DropIndex 57 +#define OP_IdxGE 58 +#define OP_IdxDelete 61 +#define OP_Vacuum 62 +#define OP_MoveLe 63 +#define OP_IfNot 72 +#define OP_DropTable 84 +#define OP_MakeRecord 87 +#define OP_ToBlob 138 /* same as TK_TO_BLOB */ +#define OP_Delete 88 +#define OP_AggFinal 89 +#define OP_ShiftLeft 75 /* same as TK_LSHIFT */ +#define OP_Dup 90 +#define OP_Goto 91 +#define OP_TableLock 92 +#define OP_FifoRead 93 +#define OP_Clear 94 +#define OP_IdxGT 95 #define OP_MoveLt 96 -#define OP_Le 78 /* same as TK_LE */ +#define OP_Le 69 /* same as TK_LE */ #define OP_VerifyCookie 97 #define OP_AggStep 98 #define OP_Pull 99 -#define OP_ToText 100 -#define OP_Not 69 /* same as TK_NOT */ -#define OP_SetNumColumns 101 -#define OP_AbsValue 102 -#define OP_Transaction 103 -#define OP_Negative 92 /* same as TK_UMINUS */ -#define OP_Ne 75 /* same as TK_NE */ -#define OP_ContextPop 104 -#define OP_BitOr 83 /* same as TK_BITOR */ -#define OP_Next 105 -#define OP_IdxInsert 106 -#define OP_Distinct 107 -#define OP_Lt 79 /* same as TK_LT */ -#define OP_Insert 108 -#define OP_Destroy 109 -#define OP_ReadCookie 110 -#define OP_ForceInt 111 -#define OP_LoadAnalysis 112 -#define OP_OpenVirtual 113 -#define OP_Explain 114 +#define OP_ToText 137 /* same as TK_TO_TEXT */ +#define OP_Not 16 /* same as TK_NOT */ +#define OP_ToReal 141 /* same as TK_TO_REAL */ +#define OP_SetNumColumns 100 +#define OP_AbsValue 101 +#define OP_Transaction 102 +#define OP_Negative 83 /* same as TK_UMINUS */ +#define OP_Ne 66 /* same as TK_NE */ +#define OP_ContextPop 103 +#define OP_BitOr 74 /* same as TK_BITOR */ +#define OP_Next 104 +#define OP_IdxInsert 105 +#define OP_Distinct 106 +#define OP_Lt 70 /* same as TK_LT */ +#define OP_Insert 107 +#define OP_Destroy 108 +#define OP_ReadCookie 109 +#define OP_ForceInt 110 +#define OP_LoadAnalysis 111 +#define OP_OpenVirtual 112 +#define OP_Explain 113 +#define OP_IfMemZero 114 #define OP_OpenPseudo 115 #define OP_Null 116 #define OP_Blob 117 -#define OP_Add 86 /* same as TK_PLUS */ +#define OP_Add 77 /* same as TK_PLUS */ #define OP_MemStore 118 #define OP_Rewind 119 #define OP_MoveGe 120 -#define OP_BitNot 94 /* same as TK_BITNOT */ +#define OP_BitNot 85 /* same as TK_BITNOT */ #define OP_MemMove 121 #define OP_MemNull 122 #define OP_Found 123 -#define OP_NullRow 124 +#define OP_NullRow 126 /* The following opcode values are never used */ -#define OP_NotUsed_125 125 -#define OP_NotUsed_126 126 #define OP_NotUsed_127 127 #define OP_NotUsed_128 128 #define OP_NotUsed_129 129 #define OP_NotUsed_130 130 #define OP_NotUsed_131 131 #define OP_NotUsed_132 132 +#define OP_NotUsed_133 133 +#define OP_NotUsed_134 134 +#define OP_NotUsed_135 135 +#define OP_NotUsed_136 136 -#define NOPUSH_MASK_0 65368 -#define NOPUSH_MASK_1 47898 -#define NOPUSH_MASK_2 22493 -#define NOPUSH_MASK_3 32761 -#define NOPUSH_MASK_4 65215 -#define NOPUSH_MASK_5 30719 -#define NOPUSH_MASK_6 40895 -#define NOPUSH_MASK_7 6603 -#define NOPUSH_MASK_8 0 -#define NOPUSH_MASK_9 0 +/* Opcodes that are guaranteed to never push a value onto the stack +** contain a 1 their corresponding position of the following mask +** set. See the opcodeNoPush() function in vdbeaux.c */ +#define NOPUSH_MASK_0 0x7f58 +#define NOPUSH_MASK_1 0xee5b +#define NOPUSH_MASK_2 0x9f76 +#define NOPUSH_MASK_3 0xfff2 +#define NOPUSH_MASK_4 0xffff +#define NOPUSH_MASK_5 0xdb3b +#define NOPUSH_MASK_6 0xcfdf +#define NOPUSH_MASK_7 0x49cd +#define NOPUSH_MASK_8 0x3e00 +#define NOPUSH_MASK_9 0x0000 diff --git a/mozilla/db/sqlite3/src/os.c b/mozilla/db/sqlite3/src/os.c new file mode 100644 index 00000000000..ec482fe0e7c --- /dev/null +++ b/mozilla/db/sqlite3/src/os.c @@ -0,0 +1,92 @@ +/* +** 2005 November 29 +** +** 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 OS interface code that is common to all +** architectures. +*/ +#define _SQLITE_OS_C_ 1 +#include "sqliteInt.h" +#include "os.h" + +/* +** The following routines are convenience wrappers around methods +** of the OsFile object. This is mostly just syntactic sugar. All +** of this would be completely automatic if SQLite were coded using +** C++ instead of plain old C. +*/ +int sqlite3OsClose(OsFile **pId){ + OsFile *id; + if( pId!=0 && (id = *pId)!=0 ){ + return id->pMethod->xClose(pId); + }else{ + return SQLITE_OK; + } +} +int sqlite3OsOpenDirectory(OsFile *id, const char *zName){ + return id->pMethod->xOpenDirectory(id, zName); +} +int sqlite3OsRead(OsFile *id, void *pBuf, int amt){ + return id->pMethod->xRead(id, pBuf, amt); +} +int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){ + return id->pMethod->xWrite(id, pBuf, amt); +} +int sqlite3OsSeek(OsFile *id, i64 offset){ + return id->pMethod->xSeek(id, offset); +} +int sqlite3OsTruncate(OsFile *id, i64 size){ + return id->pMethod->xTruncate(id, size); +} +int sqlite3OsSync(OsFile *id, int fullsync){ + return id->pMethod->xSync(id, fullsync); +} +void sqlite3OsSetFullSync(OsFile *id, int value){ + id->pMethod->xSetFullSync(id, value); +} +#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) +/* This method is currently only used while interactively debugging the +** pager. More specificly, it can only be used when sqlite3DebugPrintf() is +** included in the build. */ +int sqlite3OsFileHandle(OsFile *id){ + return id->pMethod->xFileHandle(id); +} +#endif +int sqlite3OsFileSize(OsFile *id, i64 *pSize){ + return id->pMethod->xFileSize(id, pSize); +} +int sqlite3OsLock(OsFile *id, int lockType){ + return id->pMethod->xLock(id, lockType); +} +int sqlite3OsUnlock(OsFile *id, int lockType){ + return id->pMethod->xUnlock(id, lockType); +} +int sqlite3OsLockState(OsFile *id){ + return id->pMethod->xLockState(id); +} +int sqlite3OsCheckReservedLock(OsFile *id){ + return id->pMethod->xCheckReservedLock(id); +} + +#ifdef SQLITE_ENABLE_REDEF_IO +/* +** A function to return a pointer to the virtual function table. +** This routine really does not accomplish very much since the +** virtual function table is a global variable and anybody who +** can call this function can just as easily access the variable +** for themselves. Nevertheless, we include this routine for +** backwards compatibility with an earlier redefinable I/O +** interface design. +*/ +struct sqlite3OsVtbl *sqlite3_os_switch(void){ + return &sqlite3Os; +} +#endif diff --git a/mozilla/db/sqlite3/src/os.h b/mozilla/db/sqlite3/src/os.h index 0ae73b81676..6fa78bac3a6 100644 --- a/mozilla/db/sqlite3/src/os.h +++ b/mozilla/db/sqlite3/src/os.h @@ -18,12 +18,10 @@ #define _SQLITE_OS_H_ /* -** Figure out if we are dealing with Unix, Windows or MacOS. -** -** N.B. MacOS means Mac Classic (or Carbon). Treat Darwin (OS X) as Unix. -** The MacOS build is designed to use CodeWarrior (tested with v8) +** Figure out if we are dealing with Unix, Windows, or some other +** operating system. */ -#if !defined(OS_UNIX) && !defined(OS_TEST) && !defined(OS_OTHER) +#if !defined(OS_UNIX) && !defined(OS_OTHER) # define OS_OTHER 0 # ifndef OS_WIN # if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__) @@ -49,28 +47,15 @@ # endif #endif -/* -** Invoke the appropriate operating-system specific header file. -*/ -#if OS_TEST -# include "os_test.h" -#endif -#if OS_UNIX -# include "os_unix.h" -#endif -#if OS_WIN -# include "os_win.h" -#endif -#if OS_OS2 -# include "os_os2.h" -#endif -/* os_other.c and os_other.h are not delivered with SQLite. These files -** are place-holders that can be filled in by third-party developers to -** implement backends to their on proprietary operating systems. +/* +** Define the maximum size of a temporary filename */ -#if OS_OTHER -# include "os_other.h" +#if OS_WIN +# include +# define SQLITE_TEMPNAME_SIZE (MAX_PATH+50) +#else +# define SQLITE_TEMPNAME_SIZE 200 #endif /* If the SET_FULLSYNC macro is not defined above, then make it @@ -93,6 +78,104 @@ # define TEMP_FILE_PREFIX "sqlite_" #endif +/* +** Define the interfaces for Unix and for Windows. +*/ +#if OS_UNIX +#define sqlite3OsOpenReadWrite sqlite3UnixOpenReadWrite +#define sqlite3OsOpenExclusive sqlite3UnixOpenExclusive +#define sqlite3OsOpenReadOnly sqlite3UnixOpenReadOnly +#define sqlite3OsDelete sqlite3UnixDelete +#define sqlite3OsFileExists sqlite3UnixFileExists +#define sqlite3OsFullPathname sqlite3UnixFullPathname +#define sqlite3OsIsDirWritable sqlite3UnixIsDirWritable +#define sqlite3OsSyncDirectory sqlite3UnixSyncDirectory +#define sqlite3OsTempFileName sqlite3UnixTempFileName +#define sqlite3OsRandomSeed sqlite3UnixRandomSeed +#define sqlite3OsSleep sqlite3UnixSleep +#define sqlite3OsCurrentTime sqlite3UnixCurrentTime +#define sqlite3OsEnterMutex sqlite3UnixEnterMutex +#define sqlite3OsLeaveMutex sqlite3UnixLeaveMutex +#define sqlite3OsInMutex sqlite3UnixInMutex +#define sqlite3OsThreadSpecificData sqlite3UnixThreadSpecificData +#define sqlite3OsMalloc sqlite3GenericMalloc +#define sqlite3OsRealloc sqlite3GenericRealloc +#define sqlite3OsFree sqlite3GenericFree +#define sqlite3OsAllocationSize sqlite3GenericAllocationSize +#endif +#if OS_WIN +#define sqlite3OsOpenReadWrite sqlite3WinOpenReadWrite +#define sqlite3OsOpenExclusive sqlite3WinOpenExclusive +#define sqlite3OsOpenReadOnly sqlite3WinOpenReadOnly +#define sqlite3OsDelete sqlite3WinDelete +#define sqlite3OsFileExists sqlite3WinFileExists +#define sqlite3OsFullPathname sqlite3WinFullPathname +#define sqlite3OsIsDirWritable sqlite3WinIsDirWritable +#define sqlite3OsSyncDirectory sqlite3WinSyncDirectory +#define sqlite3OsTempFileName sqlite3WinTempFileName +#define sqlite3OsRandomSeed sqlite3WinRandomSeed +#define sqlite3OsSleep sqlite3WinSleep +#define sqlite3OsCurrentTime sqlite3WinCurrentTime +#define sqlite3OsEnterMutex sqlite3WinEnterMutex +#define sqlite3OsLeaveMutex sqlite3WinLeaveMutex +#define sqlite3OsInMutex sqlite3WinInMutex +#define sqlite3OsThreadSpecificData sqlite3WinThreadSpecificData +#define sqlite3OsMalloc sqlite3GenericMalloc +#define sqlite3OsRealloc sqlite3GenericRealloc +#define sqlite3OsFree sqlite3GenericFree +#define sqlite3OsAllocationSize sqlite3GenericAllocationSize +#endif + +/* +** If using an alternative OS interface, then we must have an "os_other.h" +** header file available for that interface. Presumably the "os_other.h" +** header file contains #defines similar to those above. +*/ +#if OS_OTHER +# include "os_other.h" +#endif + + + +/* +** Forward declarations +*/ +typedef struct OsFile OsFile; +typedef struct IoMethod IoMethod; + +/* +** An instance of the following structure contains pointers to all +** methods on an OsFile object. +*/ +struct IoMethod { + int (*xClose)(OsFile**); + int (*xOpenDirectory)(OsFile*, const char*); + int (*xRead)(OsFile*, void*, int amt); + int (*xWrite)(OsFile*, const void*, int amt); + int (*xSeek)(OsFile*, i64 offset); + int (*xTruncate)(OsFile*, i64 size); + int (*xSync)(OsFile*, int); + void (*xSetFullSync)(OsFile *id, int setting); + int (*xFileHandle)(OsFile *id); + int (*xFileSize)(OsFile*, i64 *pSize); + int (*xLock)(OsFile*, int); + int (*xUnlock)(OsFile*, int); + int (*xLockState)(OsFile *id); + int (*xCheckReservedLock)(OsFile *id); +}; + +/* +** The OsFile object describes an open disk file in an OS-dependent way. +** The version of OsFile defined here is a generic version. Each OS +** implementation defines its own subclass of this structure that contains +** additional information needed to handle file I/O. But the pMethod +** entry (pointing to the virtual function table) always occurs first +** so that we can always find the appropriate methods. +*/ +struct OsFile { + IoMethod const *pMethod; +}; + /* ** The following values may be passed as the second argument to ** sqlite3OsLock(). The various locks exhibit the following semantics: @@ -147,8 +230,10 @@ ** a random byte is selected for a shared lock. The pool of bytes for ** shared locks begins at SHARED_FIRST. ** -** These #defines are available in os.h so that Unix can use the same -** byte ranges for locking. This leaves open the possiblity of having +** These #defines are available in sqlite_aux.h so that adaptors for +** connecting SQLite to other operating systems can use the same byte +** ranges for locking. In particular, the same locking strategy and +** byte ranges are used for Unix. This leaves open the possiblity of having ** clients on win95, winNT, and unix all talking to the same shared file ** and all locking correctly. To do so would require that samba (or whatever ** tool is being used for file sharing) implements locks correctly between @@ -182,36 +267,181 @@ extern unsigned int sqlite3_pending_byte; #define SHARED_FIRST (PENDING_BYTE+2) #define SHARED_SIZE 510 - -int sqlite3OsDelete(const char*); -int sqlite3OsFileExists(const char*); -int sqlite3OsOpenReadWrite(const char*, OsFile*, int*); -int sqlite3OsOpenExclusive(const char*, OsFile*, int); -int sqlite3OsOpenReadOnly(const char*, OsFile*); -int sqlite3OsOpenDirectory(const char*, OsFile*); -int sqlite3OsSyncDirectory(const char*); -int sqlite3OsTempFileName(char*); -int sqlite3OsIsDirWritable(char*); -int sqlite3OsClose(OsFile*); +/* +** Prototypes for operating system interface routines. +*/ +int sqlite3OsClose(OsFile**); +int sqlite3OsOpenDirectory(OsFile*, const char*); int sqlite3OsRead(OsFile*, void*, int amt); int sqlite3OsWrite(OsFile*, const void*, int amt); int sqlite3OsSeek(OsFile*, i64 offset); -int sqlite3OsSync(OsFile*, int); int sqlite3OsTruncate(OsFile*, i64 size); +int sqlite3OsSync(OsFile*, int); +void sqlite3OsSetFullSync(OsFile *id, int setting); +int sqlite3OsFileHandle(OsFile *id); int sqlite3OsFileSize(OsFile*, i64 *pSize); -char *sqlite3OsFullPathname(const char*); int sqlite3OsLock(OsFile*, int); int sqlite3OsUnlock(OsFile*, int); +int sqlite3OsLockState(OsFile *id); int sqlite3OsCheckReservedLock(OsFile *id); - - -/* The interface for file I/O is above. Other miscellaneous functions -** are below */ - +int sqlite3OsOpenReadWrite(const char*, OsFile**, int*); +int sqlite3OsOpenExclusive(const char*, OsFile**, int); +int sqlite3OsOpenReadOnly(const char*, OsFile**); +int sqlite3OsDelete(const char*); +int sqlite3OsFileExists(const char*); +char *sqlite3OsFullPathname(const char*); +int sqlite3OsIsDirWritable(char*); +int sqlite3OsSyncDirectory(const char*); +int sqlite3OsTempFileName(char*); int sqlite3OsRandomSeed(char*); int sqlite3OsSleep(int ms); int sqlite3OsCurrentTime(double*); void sqlite3OsEnterMutex(void); void sqlite3OsLeaveMutex(void); +int sqlite3OsInMutex(int); +ThreadData *sqlite3OsThreadSpecificData(int); +void *sqlite3OsMalloc(int); +void *sqlite3OsRealloc(void *, int); +void sqlite3OsFree(void *); +int sqlite3OsAllocationSize(void *); + +/* +** If the SQLITE_ENABLE_REDEF_IO macro is defined, then the OS-layer +** interface routines are not called directly but are invoked using +** pointers to functions. This allows the implementation of various +** OS-layer interface routines to be modified at run-time. There are +** obscure but legitimate reasons for wanting to do this. But for +** most users, a direct call to the underlying interface is preferable +** so the the redefinable I/O interface is turned off by default. +*/ +#ifdef SQLITE_ENABLE_REDEF_IO + +/* +** When redefinable I/O is enabled, a single global instance of the +** following structure holds pointers to the routines that SQLite +** uses to talk with the underlying operating system. Modify this +** structure (before using any SQLite API!) to accomodate perculiar +** operating system interfaces or behaviors. +*/ +struct sqlite3OsVtbl { + int (*xOpenReadWrite)(const char*, OsFile**, int*); + int (*xOpenExclusive)(const char*, OsFile**, int); + int (*xOpenReadOnly)(const char*, OsFile**); + + int (*xDelete)(const char*); + int (*xFileExists)(const char*); + char *(*xFullPathname)(const char*); + int (*xIsDirWritable)(char*); + int (*xSyncDirectory)(const char*); + int (*xTempFileName)(char*); + + int (*xRandomSeed)(char*); + int (*xSleep)(int ms); + int (*xCurrentTime)(double*); + + void (*xEnterMutex)(void); + void (*xLeaveMutex)(void); + int (*xInMutex)(int); + ThreadData *(*xThreadSpecificData)(int); + + void *(*xMalloc)(int); + void *(*xRealloc)(void *, int); + void (*xFree)(void *); + int (*xAllocationSize)(void *); +}; + +/* Macro used to comment out routines that do not exists when there is +** no disk I/O +*/ +#ifdef SQLITE_OMIT_DISKIO +# define IF_DISKIO(X) 0 +#else +# define IF_DISKIO(X) X +#endif + +#ifdef _SQLITE_OS_C_ + /* + ** The os.c file implements the global virtual function table. + */ + struct sqlite3OsVtbl sqlite3Os = { + IF_DISKIO( sqlite3OsOpenReadWrite ), + IF_DISKIO( sqlite3OsOpenExclusive ), + IF_DISKIO( sqlite3OsOpenReadOnly ), + IF_DISKIO( sqlite3OsDelete ), + IF_DISKIO( sqlite3OsFileExists ), + IF_DISKIO( sqlite3OsFullPathname ), + IF_DISKIO( sqlite3OsIsDirWritable ), + IF_DISKIO( sqlite3OsSyncDirectory ), + IF_DISKIO( sqlite3OsTempFileName ), + sqlite3OsRandomSeed, + sqlite3OsSleep, + sqlite3OsCurrentTime, + sqlite3OsEnterMutex, + sqlite3OsLeaveMutex, + sqlite3OsInMutex, + sqlite3OsThreadSpecificData, + sqlite3OsMalloc, + sqlite3OsRealloc, + sqlite3OsFree, + sqlite3OsAllocationSize + }; +#else + /* + ** Files other than os.c just reference the global virtual function table. + */ + extern struct sqlite3OsVtbl sqlite3Os; +#endif /* _SQLITE_OS_C_ */ + + +/* This additional API routine is available with redefinable I/O */ +struct sqlite3OsVtbl *sqlite3_os_switch(void); + + +/* +** Redefine the OS interface to go through the virtual function table +** rather than calling routines directly. +*/ +#undef sqlite3OsOpenReadWrite +#undef sqlite3OsOpenExclusive +#undef sqlite3OsOpenReadOnly +#undef sqlite3OsDelete +#undef sqlite3OsFileExists +#undef sqlite3OsFullPathname +#undef sqlite3OsIsDirWritable +#undef sqlite3OsSyncDirectory +#undef sqlite3OsTempFileName +#undef sqlite3OsRandomSeed +#undef sqlite3OsSleep +#undef sqlite3OsCurrentTime +#undef sqlite3OsEnterMutex +#undef sqlite3OsLeaveMutex +#undef sqlite3OsInMutex +#undef sqlite3OsThreadSpecificData +#undef sqlite3OsMalloc +#undef sqlite3OsRealloc +#undef sqlite3OsFree +#undef sqlite3OsAllocationSize +#define sqlite3OsOpenReadWrite sqlite3Os.xOpenReadWrite +#define sqlite3OsOpenExclusive sqlite3Os.xOpenExclusive +#define sqlite3OsOpenReadOnly sqlite3Os.xOpenReadOnly +#define sqlite3OsDelete sqlite3Os.xDelete +#define sqlite3OsFileExists sqlite3Os.xFileExists +#define sqlite3OsFullPathname sqlite3Os.xFullPathname +#define sqlite3OsIsDirWritable sqlite3Os.xIsDirWritable +#define sqlite3OsSyncDirectory sqlite3Os.xSyncDirectory +#define sqlite3OsTempFileName sqlite3Os.xTempFileName +#define sqlite3OsRandomSeed sqlite3Os.xRandomSeed +#define sqlite3OsSleep sqlite3Os.xSleep +#define sqlite3OsCurrentTime sqlite3Os.xCurrentTime +#define sqlite3OsEnterMutex sqlite3Os.xEnterMutex +#define sqlite3OsLeaveMutex sqlite3Os.xLeaveMutex +#define sqlite3OsInMutex sqlite3Os.xInMutex +#define sqlite3OsThreadSpecificData sqlite3Os.xThreadSpecificData +#define sqlite3OsMalloc sqlite3Os.xMalloc +#define sqlite3OsRealloc sqlite3Os.xRealloc +#define sqlite3OsFree sqlite3Os.xFree +#define sqlite3OsAllocationSize sqlite3Os.xAllocationSize + +#endif /* SQLITE_ENABLE_REDEF_IO */ #endif /* _SQLITE_OS_H_ */ diff --git a/mozilla/db/sqlite3/src/os_common.h b/mozilla/db/sqlite3/src/os_common.h index b19ff059067..b83a02b7c46 100644 --- a/mozilla/db/sqlite3/src/os_common.h +++ b/mozilla/db/sqlite3/src/os_common.h @@ -88,6 +88,7 @@ static unsigned int elapse; ** is used for testing the I/O recovery logic. */ #ifdef SQLITE_TEST +int sqlite3_io_error_hit = 0; int sqlite3_io_error_pending = 0; int sqlite3_diskfull_pending = 0; int sqlite3_diskfull = 0; @@ -95,7 +96,7 @@ int sqlite3_diskfull = 0; if( sqlite3_io_error_pending ) \ if( sqlite3_io_error_pending-- == 1 ){ local_ioerr(); return A; } static void local_ioerr(){ - sqlite3_io_error_pending = 0; /* Really just a place to set a breakpoint */ + sqlite3_io_error_hit = 1; /* Really just a place to set a breakpoint */ } #define SimulateDiskfullError \ if( sqlite3_diskfull_pending ){ \ @@ -121,3 +122,67 @@ int sqlite3_open_file_count = 0; #else #define OpenCounter(X) #endif + +/* +** sqlite3GenericMalloc +** sqlite3GenericRealloc +** sqlite3GenericOsFree +** sqlite3GenericAllocationSize +** +** Implementation of the os level dynamic memory allocation interface in terms +** of the standard malloc(), realloc() and free() found in many operating +** systems. No rocket science here. +** +** There are two versions of these four functions here. The version +** implemented here is only used if memory-management or memory-debugging is +** enabled. This version allocates an extra 8-bytes at the beginning of each +** block and stores the size of the allocation there. +** +** If neither memory-management or debugging is enabled, the second +** set of implementations is used instead. +*/ +#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) || defined (SQLITE_MEMDEBUG) +void *sqlite3GenericMalloc(int n){ + char *p = (char *)malloc(n+8); + assert(n>0); + assert(sizeof(int)<=8); + if( p ){ + *(int *)p = n; + p += 8; + } + return (void *)p; +} +void *sqlite3GenericRealloc(void *p, int n){ + char *p2 = ((char *)p - 8); + assert(n>0); + p2 = realloc(p2, n+8); + if( p2 ){ + *(int *)p2 = n; + p2 += 8; + } + return (void *)p2; +} +void sqlite3GenericFree(void *p){ + assert(p); + free((void *)((char *)p - 8)); +} +int sqlite3GenericAllocationSize(void *p){ + return p ? *(int *)((char *)p - 8) : 0; +} +#else +void *sqlite3GenericMalloc(int n){ + char *p = (char *)malloc(n); + return (void *)p; +} +void *sqlite3GenericRealloc(void *p, int n){ + assert(n>0); + p = realloc(p, n); + return p; +} +void sqlite3GenericFree(void *p){ + assert(p); + free(p); +} +/* Never actually used, but needed for the linker */ +int sqlite3GenericAllocationSize(void *p){ return 0; } +#endif diff --git a/mozilla/db/sqlite3/src/os_unix.c b/mozilla/db/sqlite3/src/os_unix.c index f4e09b5364b..074f07399a7 100644 --- a/mozilla/db/sqlite3/src/os_unix.c +++ b/mozilla/db/sqlite3/src/os_unix.c @@ -16,15 +16,100 @@ #include "os.h" #if OS_UNIX /* This file is used on unix only */ +/* +** These #defines should enable >2GB file support on Posix if the +** underlying operating system supports it. If the OS lacks +** large file support, these should be no-ops. +** +** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch +** on the compiler command line. This is necessary if you are compiling +** on a recent machine (ex: RedHat 7.2) but you want your code to work +** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2 +** without this option, LFS is enable. But LFS does not exist in the kernel +** in RedHat 6.0, so the code won't work. Hence, for maximum binary +** portability you should omit LFS. +*/ +#ifndef SQLITE_DISABLE_LFS +# define _LARGE_FILE 1 +# ifndef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 +# endif +# define _LARGEFILE_SOURCE 1 +#endif +/* +** standard include files. +*/ +#include +#include +#include +#include #include #include #include -#include + +/* +** If we are to be thread-safe, include the pthreads header and define +** the SQLITE_UNIX_THREADS macro. +*/ +#if defined(THREADSAFE) && THREADSAFE +# include +# define SQLITE_UNIX_THREADS 1 +#endif + +/* +** Default permissions when creating a new file +*/ +#ifndef SQLITE_DEFAULT_FILE_PERMISSIONS +# define SQLITE_DEFAULT_FILE_PERMISSIONS 0644 +#endif + + + +/* +** The unixFile structure is subclass of OsFile specific for the unix +** protability layer. +*/ +typedef struct unixFile unixFile; +struct unixFile { + IoMethod const *pMethod; /* Always the first entry */ + struct openCnt *pOpen; /* Info about all open fd's on this inode */ + struct lockInfo *pLock; /* Info about locks on this inode */ + int h; /* The file descriptor */ + unsigned char locktype; /* The type of lock held on this fd */ + unsigned char isOpen; /* True if needs to be closed */ + unsigned char fullSync; /* Use F_FULLSYNC if available */ + int dirfd; /* File descriptor for the directory */ +#ifdef SQLITE_UNIX_THREADS + pthread_t tid; /* The thread that "owns" this OsFile */ +#endif +}; + +/* +** Provide the ability to override some OS-layer functions during +** testing. This is used to simulate OS crashes to verify that +** commits are atomic even in the event of an OS crash. +*/ +#ifdef SQLITE_CRASH_TEST + extern int sqlite3CrashTestEnable; + extern int sqlite3CrashOpenReadWrite(const char*, OsFile**, int*); + extern int sqlite3CrashOpenExclusive(const char*, OsFile**, int); + extern int sqlite3CrashOpenReadOnly(const char*, OsFile**, int); +# define CRASH_TEST_OVERRIDE(X,A,B,C) \ + if(sqlite3CrashTestEnable){ return X(A,B,C); } +#else +# define CRASH_TEST_OVERRIDE(X,A,B,C) /* no-op */ +#endif + + +/* +** Include code that is common to all os_*.c files +*/ +#include "os_common.h" /* ** Do not include any of the File I/O interface procedures if the -** SQLITE_OMIT_DISKIO macro is defined (indicating that there database +** SQLITE_OMIT_DISKIO macro is defined (indicating that the database ** will be in-memory only) */ #ifndef SQLITE_OMIT_DISKIO @@ -51,17 +136,12 @@ ** The DJGPP compiler environment looks mostly like Unix, but it ** lacks the fcntl() system call. So redefine fcntl() to be something ** that always succeeds. This means that locking does not occur under -** DJGPP. But its DOS - what did you expect? +** DJGPP. But it's DOS - what did you expect? */ #ifdef __DJGPP__ # define fcntl(A,B,C) 0 #endif -/* -** Include code that is common to all os_*.c files -*/ -#include "os_common.h" - /* ** The threadid macro resolves to the thread-id or to 0. Used for ** testing and debugging only. @@ -80,10 +160,18 @@ ** means that sqlite3* database handles cannot be moved from one thread ** to another. This logic makes sure a user does not try to do that ** by mistake. +** +** Version 3.3.1 (2006-01-15): OsFiles can be moved from one thread to +** another as long as we are running on a system that supports threads +** overriding each others locks (which now the most common behavior) +** or if no locks are held. But the OsFile.pLock field needs to be +** recomputed because its key includes the thread-id. See the +** transferOwnership() function below for additional information */ -#ifdef SQLITE_UNIX_THREADS -# define SET_THREADID(X) X->tid = pthread_self() -# define CHECK_THREADID(X) (!pthread_equal(X->tid, pthread_self())) +#if defined(SQLITE_UNIX_THREADS) +# define SET_THREADID(X) (X)->tid = pthread_self() +# define CHECK_THREADID(X) (threadsOverrideEachOthersLocks==0 && \ + !pthread_equal((X)->tid, pthread_self())) #else # define SET_THREADID(X) # define CHECK_THREADID(X) 0 @@ -195,14 +283,14 @@ ** ** If threads cannot override each others locks, then we set the ** lockKey.tid field to the thread ID. If threads can override -** each others locks then tid is always set to zero. tid is also -** set to zero if we compile without threading support. +** each others locks then tid is always set to zero. tid is omitted +** if we compile without threading support. */ struct lockKey { dev_t dev; /* Device number */ ino_t ino; /* Inode number */ #ifdef SQLITE_UNIX_THREADS - pthread_t tid; /* Thread ID or zero if threads cannot override each other */ + pthread_t tid; /* Thread ID or zero if threads can override each other */ #endif }; @@ -248,8 +336,9 @@ struct openCnt { }; /* -** These hash table maps inodes and process IDs into lockInfo and openCnt -** structures. Access to these hash tables must be protected by a mutex. +** These hash tables map inodes and file descriptors (really, lockKey and +** openKey structures) into lockInfo and openCnt structures. Access to +** these hash tables must be protected by a mutex. */ static Hash lockHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 }; static Hash openHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 }; @@ -263,8 +352,16 @@ static Hash openHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 }; ** 0: No. Threads cannot override each others locks. ** 1: Yes. Threads can override each others locks. ** -1: We don't know yet. +** +** This variable normally has file scope only. But during testing, we make +** it a global so that the test code can change its value in order to verify +** that the right stuff happens in either case. */ +#ifdef SQLITE_TEST +int threadsOverrideEachOthersLocks = -1; +#else static int threadsOverrideEachOthersLocks = -1; +#endif /* ** This structure holds information passed into individual test @@ -283,7 +380,7 @@ struct threadTestData { ** This routine is used for troubleshooting locks on multithreaded ** platforms. Enable by compiling with the -DSQLITE_LOCK_TRACE ** command-line option on the compiler. This code is normally -** turnned off. +** turned off. */ static int lockTrace(int fd, int op, struct flock *p){ char *zOpName, *zType; @@ -353,7 +450,7 @@ static void *threadLockingTest(void *pArg){ ** can override each others locks then sets the ** threadsOverrideEachOthersLocks variable appropriately. */ -static void testThreadLockingBehavior(fd_orig){ +static void testThreadLockingBehavior(int fd_orig){ int fd; struct threadTestData d[2]; pthread_t t[2]; @@ -381,6 +478,7 @@ static void testThreadLockingBehavior(fd_orig){ ** Release a lockInfo structure previously allocated by findLockInfo(). */ static void releaseLockInfo(struct lockInfo *pLock){ + assert( sqlite3OsInMutex(1) ); pLock->nRef--; if( pLock->nRef==0 ){ sqlite3HashInsert(&lockHash, &pLock->key, sizeof(pLock->key), 0); @@ -392,18 +490,19 @@ static void releaseLockInfo(struct lockInfo *pLock){ ** Release a openCnt structure previously allocated by findLockInfo(). */ static void releaseOpenCnt(struct openCnt *pOpen){ + assert( sqlite3OsInMutex(1) ); pOpen->nRef--; if( pOpen->nRef==0 ){ sqlite3HashInsert(&openHash, &pOpen->key, sizeof(pOpen->key), 0); - sqliteFree(pOpen->aPending); + free(pOpen->aPending); sqliteFree(pOpen); } } /* ** Given a file descriptor, locate lockInfo and openCnt structures that -** describes that file descriptor. Create a new ones if necessary. The -** return values might be unset if an error occurs. +** describes that file descriptor. Create new ones if necessary. The +** return values might be uninitialized if an error occurs. ** ** Return the number of errors. */ @@ -420,6 +519,8 @@ static int findLockInfo( struct openCnt *pOpen; rc = fstat(fd, &statbuf); if( rc!=0 ) return 1; + + assert( sqlite3OsInMutex(1) ); memset(&key1, 0, sizeof(key1)); key1.dev = statbuf.st_dev; key1.ino = statbuf.st_ino; @@ -436,7 +537,10 @@ static int findLockInfo( if( pLock==0 ){ struct lockInfo *pOld; pLock = sqliteMallocRaw( sizeof(*pLock) ); - if( pLock==0 ) return 1; + if( pLock==0 ){ + rc = 1; + goto exit_findlockinfo; + } pLock->key = key1; pLock->nRef = 1; pLock->cnt = 0; @@ -445,43 +549,113 @@ static int findLockInfo( if( pOld!=0 ){ assert( pOld==pLock ); sqliteFree(pLock); - return 1; + rc = 1; + goto exit_findlockinfo; } }else{ pLock->nRef++; } *ppLock = pLock; - pOpen = (struct openCnt*)sqlite3HashFind(&openHash, &key2, sizeof(key2)); - if( pOpen==0 ){ - struct openCnt *pOld; - pOpen = sqliteMallocRaw( sizeof(*pOpen) ); + if( ppOpen!=0 ){ + pOpen = (struct openCnt*)sqlite3HashFind(&openHash, &key2, sizeof(key2)); if( pOpen==0 ){ - releaseLockInfo(pLock); - return 1; + struct openCnt *pOld; + pOpen = sqliteMallocRaw( sizeof(*pOpen) ); + if( pOpen==0 ){ + releaseLockInfo(pLock); + rc = 1; + goto exit_findlockinfo; + } + pOpen->key = key2; + pOpen->nRef = 1; + pOpen->nLock = 0; + pOpen->nPending = 0; + pOpen->aPending = 0; + pOld = sqlite3HashInsert(&openHash, &pOpen->key, sizeof(key2), pOpen); + if( pOld!=0 ){ + assert( pOld==pOpen ); + sqliteFree(pOpen); + releaseLockInfo(pLock); + rc = 1; + goto exit_findlockinfo; + } + }else{ + pOpen->nRef++; } - pOpen->key = key2; - pOpen->nRef = 1; - pOpen->nLock = 0; - pOpen->nPending = 0; - pOpen->aPending = 0; - pOld = sqlite3HashInsert(&openHash, &pOpen->key, sizeof(key2), pOpen); - if( pOld!=0 ){ - assert( pOld==pOpen ); - sqliteFree(pOpen); - releaseLockInfo(pLock); - return 1; - } - }else{ - pOpen->nRef++; + *ppOpen = pOpen; } - *ppOpen = pOpen; - return 0; + +exit_findlockinfo: + return rc; } +#ifdef SQLITE_DEBUG +/* +** Helper function for printing out trace information from debugging +** binaries. This returns the string represetation of the supplied +** integer lock-type. +*/ +static const char *locktypeName(int locktype){ + switch( locktype ){ + case NO_LOCK: return "NONE"; + case SHARED_LOCK: return "SHARED"; + case RESERVED_LOCK: return "RESERVED"; + case PENDING_LOCK: return "PENDING"; + case EXCLUSIVE_LOCK: return "EXCLUSIVE"; + } + return "ERROR"; +} +#endif + +/* +** If we are currently in a different thread than the thread that the +** unixFile argument belongs to, then transfer ownership of the unixFile +** over to the current thread. +** +** A unixFile is only owned by a thread on systems where one thread is +** unable to override locks created by a different thread. RedHat9 is +** an example of such a system. +** +** Ownership transfer is only allowed if the unixFile is currently unlocked. +** If the unixFile is locked and an ownership is wrong, then return +** SQLITE_MISUSE. SQLITE_OK is returned if everything works. +*/ +#ifdef SQLITE_UNIX_THREADS +static int transferOwnership(unixFile *pFile){ + int rc; + pthread_t hSelf; + if( threadsOverrideEachOthersLocks ){ + /* Ownership transfers not needed on this system */ + return SQLITE_OK; + } + hSelf = pthread_self(); + if( pthread_equal(pFile->tid, hSelf) ){ + /* We are still in the same thread */ + TRACE1("No-transfer, same thread\n"); + return SQLITE_OK; + } + if( pFile->locktype!=NO_LOCK ){ + /* We cannot change ownership while we are holding a lock! */ + return SQLITE_MISUSE; + } + TRACE4("Transfer ownership of %d from %d to %d\n", pFile->h,pFile->tid,hSelf); + pFile->tid = hSelf; + releaseLockInfo(pFile->pLock); + rc = findLockInfo(pFile->h, &pFile->pLock, 0); + TRACE5("LOCK %d is now %s(%s,%d)\n", pFile->h, + locktypeName(pFile->locktype), + locktypeName(pFile->pLock->locktype), pFile->pLock->cnt); + return rc; +} +#else + /* On single-threaded builds, ownership transfer is a no-op */ +# define transferOwnership(X) SQLITE_OK +#endif + /* ** Delete the named file */ -int sqlite3OsDelete(const char *zFilename){ +int sqlite3UnixDelete(const char *zFilename){ unlink(zFilename); return SQLITE_OK; } @@ -489,10 +663,13 @@ int sqlite3OsDelete(const char *zFilename){ /* ** Return TRUE if the named file exists. */ -int sqlite3OsFileExists(const char *zFilename){ +int sqlite3UnixFileExists(const char *zFilename){ return access(zFilename, 0)==0; } +/* Forward declaration */ +static int allocateUnixFile(unixFile *pInit, OsFile **pId); + /* ** Attempt to open a file for both reading and writing. If that ** fails, try opening it read-only. If the file does not exist, @@ -506,25 +683,26 @@ int sqlite3OsFileExists(const char *zFilename){ ** On failure, the function returns SQLITE_CANTOPEN and leaves ** *id and *pReadonly unchanged. */ -int sqlite3OsOpenReadWrite( +int sqlite3UnixOpenReadWrite( const char *zFilename, - OsFile *id, + OsFile **pId, int *pReadonly ){ int rc; - assert( !id->isOpen ); - id->dirfd = -1; - SET_THREADID(id); - id->h = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY, + unixFile f; + + CRASH_TEST_OVERRIDE(sqlite3CrashOpenReadWrite, zFilename, pId, pReadonly); + assert( 0==*pId ); + f.h = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY, SQLITE_DEFAULT_FILE_PERMISSIONS); - if( id->h<0 ){ + if( f.h<0 ){ #ifdef EISDIR if( errno==EISDIR ){ return SQLITE_CANTOPEN; } #endif - id->h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); - if( id->h<0 ){ + f.h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); + if( f.h<0 ){ return SQLITE_CANTOPEN; } *pReadonly = 1; @@ -532,17 +710,14 @@ int sqlite3OsOpenReadWrite( *pReadonly = 0; } sqlite3OsEnterMutex(); - rc = findLockInfo(id->h, &id->pLock, &id->pOpen); + rc = findLockInfo(f.h, &f.pLock, &f.pOpen); sqlite3OsLeaveMutex(); if( rc ){ - close(id->h); + close(f.h); return SQLITE_NOMEM; } - id->locktype = 0; - id->isOpen = 1; - TRACE3("OPEN %-3d %s\n", id->h, zFilename); - OpenCounter(+1); - return SQLITE_OK; + TRACE3("OPEN %-3d %s\n", f.h, zFilename); + return allocateUnixFile(&f, pId); } @@ -560,36 +735,34 @@ int sqlite3OsOpenReadWrite( ** ** On failure, return SQLITE_CANTOPEN. */ -int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ +int sqlite3UnixOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ int rc; - assert( !id->isOpen ); + unixFile f; + + CRASH_TEST_OVERRIDE(sqlite3CrashOpenExclusive, zFilename, pId, delFlag); + assert( 0==*pId ); if( access(zFilename, 0)==0 ){ return SQLITE_CANTOPEN; } - SET_THREADID(id); - id->dirfd = -1; - id->h = open(zFilename, + f.h = open(zFilename, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY, SQLITE_DEFAULT_FILE_PERMISSIONS); - if( id->h<0 ){ + if( f.h<0 ){ return SQLITE_CANTOPEN; } sqlite3OsEnterMutex(); - rc = findLockInfo(id->h, &id->pLock, &id->pOpen); + rc = findLockInfo(f.h, &f.pLock, &f.pOpen); sqlite3OsLeaveMutex(); if( rc ){ - close(id->h); + close(f.h); unlink(zFilename); return SQLITE_NOMEM; } - id->locktype = 0; - id->isOpen = 1; if( delFlag ){ unlink(zFilename); } - TRACE3("OPEN-EX %-3d %s\n", id->h, zFilename); - OpenCounter(+1); - return SQLITE_OK; + TRACE3("OPEN-EX %-3d %s\n", f.h, zFilename); + return allocateUnixFile(&f, pId); } /* @@ -599,27 +772,25 @@ int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ ** ** On failure, return SQLITE_CANTOPEN. */ -int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){ +int sqlite3UnixOpenReadOnly(const char *zFilename, OsFile **pId){ int rc; - assert( !id->isOpen ); - SET_THREADID(id); - id->dirfd = -1; - id->h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); - if( id->h<0 ){ + unixFile f; + + CRASH_TEST_OVERRIDE(sqlite3CrashOpenReadOnly, zFilename, pId, 0); + assert( 0==*pId ); + f.h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); + if( f.h<0 ){ return SQLITE_CANTOPEN; } sqlite3OsEnterMutex(); - rc = findLockInfo(id->h, &id->pLock, &id->pOpen); + rc = findLockInfo(f.h, &f.pLock, &f.pOpen); sqlite3OsLeaveMutex(); if( rc ){ - close(id->h); + close(f.h); return SQLITE_NOMEM; } - id->locktype = 0; - id->isOpen = 1; - TRACE3("OPEN-RO %-3d %s\n", id->h, zFilename); - OpenCounter(+1); - return SQLITE_OK; + TRACE3("OPEN-RO %-3d %s\n", f.h, zFilename); + return allocateUnixFile(&f, pId); } /* @@ -631,29 +802,30 @@ int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){ ** This routine is only meaningful for Unix. It is a no-op under ** windows since windows does not support hard links. ** -** On success, a handle for a previously open file is at *id is +** On success, a handle for a previously open file at *id is ** updated with the new directory file descriptor and SQLITE_OK is ** returned. ** ** On failure, the function returns SQLITE_CANTOPEN and leaves ** *id unchanged. */ -int sqlite3OsOpenDirectory( - const char *zDirname, - OsFile *id +static int unixOpenDirectory( + OsFile *id, + const char *zDirname ){ - if( !id->isOpen ){ + unixFile *pFile = (unixFile*)id; + if( pFile==0 ){ /* Do not open the directory if the corresponding file is not already ** open. */ return SQLITE_CANTOPEN; } - SET_THREADID(id); - assert( id->dirfd<0 ); - id->dirfd = open(zDirname, O_RDONLY|O_BINARY, 0); - if( id->dirfd<0 ){ + SET_THREADID(pFile); + assert( pFile->dirfd<0 ); + pFile->dirfd = open(zDirname, O_RDONLY|O_BINARY, 0); + if( pFile->dirfd<0 ){ return SQLITE_CANTOPEN; } - TRACE3("OPENDIR %-3d %s\n", id->dirfd, zDirname); + TRACE3("OPENDIR %-3d %s\n", pFile->dirfd, zDirname); return SQLITE_OK; } @@ -661,6 +833,8 @@ int sqlite3OsOpenDirectory( ** If the following global variable points to a string which is the ** name of a directory, then that directory will be used to store ** temporary files. +** +** See also the "PRAGMA temp_store_directory" SQL command. */ char *sqlite3_temp_directory = 0; @@ -668,7 +842,7 @@ char *sqlite3_temp_directory = 0; ** Create a temporary file name in zBuf. zBuf must be big enough to ** hold at least SQLITE_TEMPNAME_SIZE characters. */ -int sqlite3OsTempFileName(char *zBuf){ +int sqlite3UnixTempFileName(char *zBuf){ static const char *azDirs[] = { 0, "/var/tmp", @@ -704,35 +878,36 @@ 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){ +int sqlite3UnixIsDirWritable(char *zBuf){ +#ifndef SQLITE_OMIT_PAGER_PRAGMAS 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; +#endif /* SQLITE_OMIT_PAGER_PRAGMAS */ 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 ** wrong. */ -int sqlite3OsRead(OsFile *id, void *pBuf, int amt){ +static int unixRead(OsFile *id, void *pBuf, int amt){ int got; - assert( id->isOpen ); + assert( id ); SimulateIOError(SQLITE_IOERR); TIMER_START; - got = read(id->h, pBuf, amt); + got = read(((unixFile*)id)->h, pBuf, amt); TIMER_END; - TRACE5("READ %-3d %5d %7d %d\n", id->h, got, last_page, TIMER_ELAPSED); + TRACE5("READ %-3d %5d %7d %d\n", ((unixFile*)id)->h, got, + last_page, TIMER_ELAPSED); SEEK(0); /* if( got<0 ) got = 0; */ if( got==amt ){ @@ -746,19 +921,20 @@ int sqlite3OsRead(OsFile *id, void *pBuf, int amt){ ** Write data from a buffer into a file. Return SQLITE_OK on success ** or some other error code on failure. */ -int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){ +static int unixWrite(OsFile *id, const void *pBuf, int amt){ int wrote = 0; - assert( id->isOpen ); + assert( id ); assert( amt>0 ); SimulateIOError(SQLITE_IOERR); SimulateDiskfullError; TIMER_START; - while( amt>0 && (wrote = write(id->h, pBuf, amt))>0 ){ + while( amt>0 && (wrote = write(((unixFile*)id)->h, pBuf, amt))>0 ){ amt -= wrote; pBuf = &((char*)pBuf)[wrote]; } TIMER_END; - TRACE5("WRITE %-3d %5d %7d %d\n", id->h, wrote, last_page, TIMER_ELAPSED); + TRACE5("WRITE %-3d %5d %7d %d\n", ((unixFile*)id)->h, wrote, + last_page, TIMER_ELAPSED); SEEK(0); if( amt>0 ){ return SQLITE_FULL; @@ -769,13 +945,13 @@ int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){ /* ** Move the read/write pointer in a file. */ -int sqlite3OsSeek(OsFile *id, i64 offset){ - assert( id->isOpen ); +static int unixSeek(OsFile *id, i64 offset){ + assert( id ); SEEK(offset/1024 + 1); #ifdef SQLITE_TEST if( offset ) SimulateDiskfullError #endif - lseek(id->h, offset, SEEK_SET); + lseek(((unixFile*)id)->h, offset, SEEK_SET); return SQLITE_OK; } @@ -788,6 +964,14 @@ int sqlite3_sync_count = 0; int sqlite3_fullsync_count = 0; #endif +/* +** Use the fdatasync() API only if the HAVE_FDATASYNC macro is defined. +** Otherwise use fsync() in its place. +*/ +#ifndef HAVE_FDATASYNC +# define fdatasync fsync +#endif + /* ** The fsync() system call does not work as advertised on many @@ -829,12 +1013,9 @@ static int full_fsync(int fd, int fullSync, int dataOnly){ if( rc ) rc = fsync(fd); #else /* if !defined(F_FULLSYNC) */ -#if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO>0 if( dataOnly ){ rc = fdatasync(fd); - }else -#endif /* _POSIX_SYNCHRONIZED_IO > 0 */ - { + }else{ rc = fsync(fd); } #endif /* defined(F_FULLFSYNC) */ @@ -858,18 +1039,23 @@ static int full_fsync(int fd, int fullSync, int dataOnly){ ** the directory entry for the journal was never created) and the transaction ** will not roll back - possibly leading to database corruption. */ -int sqlite3OsSync(OsFile *id, int dataOnly){ - assert( id->isOpen ); +static int unixSync(OsFile *id, int dataOnly){ + unixFile *pFile = (unixFile*)id; + assert( pFile ); SimulateIOError(SQLITE_IOERR); - TRACE2("SYNC %-3d\n", id->h); - if( full_fsync(id->h, id->fullSync, dataOnly) ){ + TRACE2("SYNC %-3d\n", pFile->h); + if( full_fsync(pFile->h, pFile->fullSync, dataOnly) ){ return SQLITE_IOERR; } - if( id->dirfd>=0 ){ - TRACE2("DIRSYNC %-3d\n", id->dirfd); - full_fsync(id->dirfd, id->fullSync, 0); - close(id->dirfd); /* Only need to sync once, so close the directory */ - id->dirfd = -1; /* when we are done. */ + if( pFile->dirfd>=0 ){ + TRACE2("DIRSYNC %-3d\n", pFile->dirfd); +#ifndef SQLITE_DISABLE_DIRSYNC + if( full_fsync(pFile->dirfd, pFile->fullSync, 0) ){ + return SQLITE_IOERR; + } +#endif + close(pFile->dirfd); /* Only need to sync once, so close the directory */ + pFile->dirfd = -1; /* when we are done. */ } return SQLITE_OK; } @@ -882,7 +1068,10 @@ int sqlite3OsSync(OsFile *id, int dataOnly){ ** before making changes to individual journals on a multi-database commit. ** The F_FULLFSYNC option is not needed here. */ -int sqlite3OsSyncDirectory(const char *zDirname){ +int sqlite3UnixSyncDirectory(const char *zDirname){ +#ifdef SQLITE_DISABLE_DIRSYNC + return SQLITE_OK; +#else int fd; int r; SimulateIOError(SQLITE_IOERR); @@ -894,25 +1083,26 @@ int sqlite3OsSyncDirectory(const char *zDirname){ r = fsync(fd); close(fd); return ((r==0)?SQLITE_OK:SQLITE_IOERR); +#endif } /* ** Truncate an open file to a specified size */ -int sqlite3OsTruncate(OsFile *id, i64 nByte){ - assert( id->isOpen ); +static int unixTruncate(OsFile *id, i64 nByte){ + assert( id ); SimulateIOError(SQLITE_IOERR); - return ftruncate(id->h, nByte)==0 ? SQLITE_OK : SQLITE_IOERR; + return ftruncate(((unixFile*)id)->h, nByte)==0 ? SQLITE_OK : SQLITE_IOERR; } /* ** Determine the current size of a file in bytes */ -int sqlite3OsFileSize(OsFile *id, i64 *pSize){ +static int unixFileSize(OsFile *id, i64 *pSize){ struct stat buf; - assert( id->isOpen ); + assert( id ); SimulateIOError(SQLITE_IOERR); - if( fstat(id->h, &buf)!=0 ){ + if( fstat(((unixFile*)id)->h, &buf)!=0 ){ return SQLITE_IOERR; } *pSize = buf.st_size; @@ -925,15 +1115,15 @@ int sqlite3OsFileSize(OsFile *id, i64 *pSize){ ** non-zero. If the file is unlocked or holds only SHARED locks, then ** return zero. */ -int sqlite3OsCheckReservedLock(OsFile *id){ +static int unixCheckReservedLock(OsFile *id){ int r = 0; + unixFile *pFile = (unixFile*)id; - assert( id->isOpen ); - if( CHECK_THREADID(id) ) return SQLITE_MISUSE; - sqlite3OsEnterMutex(); /* Needed because id->pLock is shared across threads */ + assert( pFile ); + sqlite3OsEnterMutex(); /* Because pFile->pLock is shared across threads */ /* Check if a thread in this process holds such a lock */ - if( id->pLock->locktype>SHARED_LOCK ){ + if( pFile->pLock->locktype>SHARED_LOCK ){ r = 1; } @@ -945,36 +1135,18 @@ int sqlite3OsCheckReservedLock(OsFile *id){ lock.l_start = RESERVED_BYTE; lock.l_len = 1; lock.l_type = F_WRLCK; - fcntl(id->h, F_GETLK, &lock); + fcntl(pFile->h, F_GETLK, &lock); if( lock.l_type!=F_UNLCK ){ r = 1; } } sqlite3OsLeaveMutex(); - TRACE3("TEST WR-LOCK %d %d\n", id->h, r); + TRACE3("TEST WR-LOCK %d %d\n", pFile->h, r); return r; } -#ifdef SQLITE_DEBUG -/* -** Helper function for printing out trace information from debugging -** binaries. This returns the string represetation of the supplied -** integer lock-type. -*/ -static const char * locktypeName(int locktype){ - switch( locktype ){ - case NO_LOCK: return "NONE"; - case SHARED_LOCK: return "SHARED"; - case RESERVED_LOCK: return "RESERVED"; - case PENDING_LOCK: return "PENDING"; - case EXCLUSIVE_LOCK: return "EXCLUSIVE"; - } - return "ERROR"; -} -#endif - /* ** Lock the file with the lock specified by parameter locktype - one ** of the following: @@ -999,7 +1171,7 @@ static const char * locktypeName(int locktype){ ** This routine will only increase a lock. Use the sqlite3OsUnlock() ** routine to lower a locking level. */ -int sqlite3OsLock(OsFile *id, int locktype){ +static int unixLock(OsFile *id, int locktype){ /* The following describes the implementation of the various locks and ** lock transitions in terms of the POSIX advisory shared and exclusive ** lock primitives (called read-locks and write-locks below, to avoid @@ -1039,39 +1211,49 @@ int sqlite3OsLock(OsFile *id, int locktype){ ** even if the locking primitive used is always a write-lock. */ int rc = SQLITE_OK; - struct lockInfo *pLock = id->pLock; + unixFile *pFile = (unixFile*)id; + struct lockInfo *pLock = pFile->pLock; struct flock lock; int s; - assert( id->isOpen ); - TRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", id->h, locktypeName(locktype), - locktypeName(id->locktype), locktypeName(pLock->locktype), pLock->cnt - ,getpid() ); - if( CHECK_THREADID(id) ) return SQLITE_MISUSE; + assert( pFile ); + TRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", pFile->h, + locktypeName(locktype), locktypeName(pFile->locktype), + locktypeName(pLock->locktype), pLock->cnt , getpid()); /* If there is already a lock of this type or more restrictive on the ** OsFile, do nothing. Don't use the end_lock: exit path, as ** sqlite3OsEnterMutex() hasn't been called yet. */ - if( id->locktype>=locktype ){ - TRACE3("LOCK %d %s ok (already held)\n", id->h, locktypeName(locktype)); + if( pFile->locktype>=locktype ){ + TRACE3("LOCK %d %s ok (already held)\n", pFile->h, + locktypeName(locktype)); return SQLITE_OK; } /* Make sure the locking sequence is correct */ - assert( id->locktype!=NO_LOCK || locktype==SHARED_LOCK ); + assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); assert( locktype!=PENDING_LOCK ); - assert( locktype!=RESERVED_LOCK || id->locktype==SHARED_LOCK ); + assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); - /* This mutex is needed because id->pLock is shared across threads + /* This mutex is needed because pFile->pLock is shared across threads */ sqlite3OsEnterMutex(); + /* Make sure the current thread owns the pFile. + */ + rc = transferOwnership(pFile); + if( rc!=SQLITE_OK ){ + sqlite3OsLeaveMutex(); + return rc; + } + pLock = pFile->pLock; + /* If some thread using this PID has a lock via a different OsFile* ** handle that precludes the requested lock, return BUSY. */ - if( (id->locktype!=pLock->locktype && + if( (pFile->locktype!=pLock->locktype && (pLock->locktype>=PENDING_LOCK || locktype>SHARED_LOCK)) ){ rc = SQLITE_BUSY; @@ -1085,11 +1267,11 @@ int sqlite3OsLock(OsFile *id, int locktype){ if( locktype==SHARED_LOCK && (pLock->locktype==SHARED_LOCK || pLock->locktype==RESERVED_LOCK) ){ assert( locktype==SHARED_LOCK ); - assert( id->locktype==0 ); + assert( pFile->locktype==0 ); assert( pLock->cnt>0 ); - id->locktype = SHARED_LOCK; + pFile->locktype = SHARED_LOCK; pLock->cnt++; - id->pOpen->nLock++; + pFile->pOpen->nLock++; goto end_lock; } @@ -1102,11 +1284,11 @@ int sqlite3OsLock(OsFile *id, int locktype){ ** be released. */ if( locktype==SHARED_LOCK - || (locktype==EXCLUSIVE_LOCK && id->locktypelocktypeh, F_SETLK, &lock); + s = fcntl(pFile->h, F_SETLK, &lock); if( s ){ rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; goto end_lock; @@ -1124,21 +1306,21 @@ int sqlite3OsLock(OsFile *id, int locktype){ /* Now get the read-lock */ lock.l_start = SHARED_FIRST; lock.l_len = SHARED_SIZE; - s = fcntl(id->h, F_SETLK, &lock); + s = fcntl(pFile->h, F_SETLK, &lock); /* Drop the temporary PENDING lock */ lock.l_start = PENDING_BYTE; lock.l_len = 1L; lock.l_type = F_UNLCK; - if( fcntl(id->h, F_SETLK, &lock)!=0 ){ + if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){ rc = SQLITE_IOERR; /* This should never happen */ goto end_lock; } if( s ){ rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; }else{ - id->locktype = SHARED_LOCK; - id->pOpen->nLock++; + pFile->locktype = SHARED_LOCK; + pFile->pOpen->nLock++; pLock->cnt = 1; } }else if( locktype==EXCLUSIVE_LOCK && pLock->cnt>1 ){ @@ -1150,7 +1332,7 @@ int sqlite3OsLock(OsFile *id, int locktype){ ** assumed that there is a SHARED or greater lock on the file ** already. */ - assert( 0!=id->locktype ); + assert( 0!=pFile->locktype ); lock.l_type = F_WRLCK; switch( locktype ){ case RESERVED_LOCK: @@ -1163,63 +1345,62 @@ int sqlite3OsLock(OsFile *id, int locktype){ default: assert(0); } - s = fcntl(id->h, F_SETLK, &lock); + s = fcntl(pFile->h, F_SETLK, &lock); if( s ){ rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; } } if( rc==SQLITE_OK ){ - id->locktype = locktype; + pFile->locktype = locktype; pLock->locktype = locktype; }else if( locktype==EXCLUSIVE_LOCK ){ - id->locktype = PENDING_LOCK; + pFile->locktype = PENDING_LOCK; pLock->locktype = PENDING_LOCK; } end_lock: sqlite3OsLeaveMutex(); - TRACE4("LOCK %d %s %s\n", id->h, locktypeName(locktype), + TRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype), rc==SQLITE_OK ? "ok" : "failed"); return rc; } /* -** Lower the locking level on file descriptor id to locktype. locktype +** Lower the locking level on file descriptor pFile to locktype. locktype ** must be either NO_LOCK or SHARED_LOCK. ** ** If the locking level of the file descriptor is already at or below ** the requested locking level, this routine is a no-op. -** -** It is not possible for this routine to fail if the second argument -** is NO_LOCK. If the second argument is SHARED_LOCK, this routine -** might return SQLITE_IOERR instead of SQLITE_OK. */ -int sqlite3OsUnlock(OsFile *id, int locktype){ +static int unixUnlock(OsFile *id, int locktype){ struct lockInfo *pLock; struct flock lock; int rc = SQLITE_OK; + unixFile *pFile = (unixFile*)id; - assert( id->isOpen ); - TRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", id->h, locktype, id->locktype, - id->pLock->locktype, id->pLock->cnt, getpid()); - if( CHECK_THREADID(id) ) return SQLITE_MISUSE; + assert( pFile ); + TRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype, + pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid()); assert( locktype<=SHARED_LOCK ); - if( id->locktype<=locktype ){ + if( pFile->locktype<=locktype ){ return SQLITE_OK; } + if( CHECK_THREADID(pFile) ){ + return SQLITE_MISUSE; + } sqlite3OsEnterMutex(); - pLock = id->pLock; + pLock = pFile->pLock; assert( pLock->cnt!=0 ); - if( id->locktype>SHARED_LOCK ){ - assert( pLock->locktype==id->locktype ); + if( pFile->locktype>SHARED_LOCK ){ + assert( pLock->locktype==pFile->locktype ); if( locktype==SHARED_LOCK ){ lock.l_type = F_RDLCK; lock.l_whence = SEEK_SET; lock.l_start = SHARED_FIRST; lock.l_len = SHARED_SIZE; - if( fcntl(id->h, F_SETLK, &lock)!=0 ){ + if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){ /* This should never happen */ rc = SQLITE_IOERR; } @@ -1228,7 +1409,7 @@ int sqlite3OsUnlock(OsFile *id, int locktype){ lock.l_whence = SEEK_SET; lock.l_start = PENDING_BYTE; lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE ); - if( fcntl(id->h, F_SETLK, &lock)==0 ){ + if( fcntl(pFile->h, F_SETLK, &lock)==0 ){ pLock->locktype = SHARED_LOCK; }else{ rc = SQLITE_IOERR; /* This should never happen */ @@ -1246,7 +1427,7 @@ int sqlite3OsUnlock(OsFile *id, int locktype){ lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = lock.l_len = 0L; - if( fcntl(id->h, F_SETLK, &lock)==0 ){ + if( fcntl(pFile->h, F_SETLK, &lock)==0 ){ pLock->locktype = NO_LOCK; }else{ rc = SQLITE_IOERR; /* This should never happen */ @@ -1257,7 +1438,7 @@ int sqlite3OsUnlock(OsFile *id, int locktype){ ** count reaches zero, close any other file descriptors whose close ** was deferred because of outstanding locks. */ - pOpen = id->pOpen; + pOpen = pFile->pOpen; pOpen->nLock--; assert( pOpen->nLock>=0 ); if( pOpen->nLock==0 && pOpen->nPending>0 ){ @@ -1265,26 +1446,28 @@ int sqlite3OsUnlock(OsFile *id, int locktype){ for(i=0; inPending; i++){ close(pOpen->aPending[i]); } - sqliteFree(pOpen->aPending); + free(pOpen->aPending); pOpen->nPending = 0; pOpen->aPending = 0; } } sqlite3OsLeaveMutex(); - id->locktype = locktype; + pFile->locktype = locktype; return rc; } /* ** Close a file. */ -int sqlite3OsClose(OsFile *id){ - if( !id->isOpen ) return SQLITE_OK; - if( CHECK_THREADID(id) ) return SQLITE_MISUSE; - sqlite3OsUnlock(id, NO_LOCK); +static int unixClose(OsFile **pId){ + unixFile *id = (unixFile*)*pId; + + if( !id ) return SQLITE_OK; + unixUnlock(*pId, NO_LOCK); if( id->dirfd>=0 ) close(id->dirfd); id->dirfd = -1; sqlite3OsEnterMutex(); + if( id->pOpen->nLock ){ /* If there are outstanding locks, do not actually close the file just ** yet because that would clear those locks. Instead, add the file @@ -1293,7 +1476,7 @@ int sqlite3OsClose(OsFile *id){ */ int *aNew; struct openCnt *pOpen = id->pOpen; - aNew = sqliteRealloc( pOpen->aPending, (pOpen->nPending+1)*sizeof(int) ); + aNew = realloc( pOpen->aPending, (pOpen->nPending+1)*sizeof(int) ); if( aNew==0 ){ /* If a malloc fails, just leak the file descriptor */ }else{ @@ -1307,10 +1490,13 @@ int sqlite3OsClose(OsFile *id){ } releaseLockInfo(id->pLock); releaseOpenCnt(id->pOpen); + sqlite3OsLeaveMutex(); id->isOpen = 0; TRACE2("CLOSE %-3d\n", id->h); OpenCounter(-1); + sqliteFree(id); + *pId = 0; return SQLITE_OK; } @@ -1320,7 +1506,7 @@ int sqlite3OsClose(OsFile *id){ ** The calling function is responsible for freeing this space once it ** is no longer needed. */ -char *sqlite3OsFullPathname(const char *zRelative){ +char *sqlite3UnixFullPathname(const char *zRelative){ char *zFull = 0; if( zRelative[0]=='/' ){ sqlite3SetString(&zFull, zRelative, (char*)0); @@ -1337,6 +1523,78 @@ char *sqlite3OsFullPathname(const char *zRelative){ return zFull; } +/* +** Change the value of the fullsync flag in the given file descriptor. +*/ +static void unixSetFullSync(OsFile *id, int v){ + ((unixFile*)id)->fullSync = v; +} + +/* +** Return the underlying file handle for an OsFile +*/ +static int unixFileHandle(OsFile *id){ + return ((unixFile*)id)->h; +} + +/* +** Return an integer that indices the type of lock currently held +** by this handle. (Used for testing and analysis only.) +*/ +static int unixLockState(OsFile *id){ + return ((unixFile*)id)->locktype; +} + +/* +** This vector defines all the methods that can operate on an OsFile +** for unix. +*/ +static const IoMethod sqlite3UnixIoMethod = { + unixClose, + unixOpenDirectory, + unixRead, + unixWrite, + unixSeek, + unixTruncate, + unixSync, + unixSetFullSync, + unixFileHandle, + unixFileSize, + unixLock, + unixUnlock, + unixLockState, + unixCheckReservedLock, +}; + +/* +** Allocate memory for a unixFile. Initialize the new unixFile +** to the value given in pInit and return a pointer to the new +** OsFile. If we run out of memory, close the file and return NULL. +*/ +static int allocateUnixFile(unixFile *pInit, OsFile **pId){ + unixFile *pNew; + pInit->dirfd = -1; + pInit->fullSync = 0; + pInit->locktype = 0; + SET_THREADID(pInit); + pNew = sqliteMalloc( sizeof(unixFile) ); + if( pNew==0 ){ + close(pInit->h); + sqlite3OsEnterMutex(); + releaseLockInfo(pInit->pLock); + releaseOpenCnt(pInit->pOpen); + sqlite3OsLeaveMutex(); + *pId = 0; + return SQLITE_NOMEM; + }else{ + *pNew = *pInit; + pNew->pMethod = &sqlite3UnixIoMethod; + *pId = (OsFile*)pNew; + OpenCounter(+1); + return SQLITE_OK; + } +} + #endif /* SQLITE_OMIT_DISKIO */ /*************************************************************************** @@ -1350,7 +1608,7 @@ char *sqlite3OsFullPathname(const char *zRelative){ ** is written into the buffer zBuf[256]. The calling function must ** supply a sufficiently large buffer. */ -int sqlite3OsRandomSeed(char *zBuf){ +int sqlite3UnixRandomSeed(char *zBuf){ /* We have to initialize zBuf to prevent valgrind from reporting ** errors. The reports issued by valgrind are incorrect - we would ** prefer that the randomness be increased by making use of the @@ -1360,7 +1618,7 @@ int sqlite3OsRandomSeed(char *zBuf){ ** in the random seed. ** ** When testing, initializing zBuf[] to zero is all we do. That means - ** that we always use the same random number sequence.* This makes the + ** that we always use the same random number sequence. This makes the ** tests repeatable. */ memset(zBuf, 0, 256); @@ -1369,7 +1627,9 @@ int sqlite3OsRandomSeed(char *zBuf){ int pid, fd; fd = open("/dev/urandom", O_RDONLY); if( fd<0 ){ - time((time_t*)zBuf); + time_t t; + time(&t); + memcpy(zBuf, &t, sizeof(t)); pid = getpid(); memcpy(&zBuf[sizeof(time_t)], &pid, sizeof(pid)); }else{ @@ -1383,8 +1643,9 @@ int sqlite3OsRandomSeed(char *zBuf){ /* ** Sleep for a little while. Return the amount of time slept. +** The argument is the number of milliseconds we want to sleep. */ -int sqlite3OsSleep(int ms){ +int sqlite3UnixSleep(int ms){ #if defined(HAVE_USLEEP) && HAVE_USLEEP usleep(ms*1000); return ms; @@ -1399,7 +1660,9 @@ int sqlite3OsSleep(int ms){ */ static int inMutex = 0; #ifdef SQLITE_UNIX_THREADS -static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_t mutexOwner; +static pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER; #endif /* @@ -1409,19 +1672,152 @@ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; ** ** SQLite uses only a single Mutex. There is not much critical ** code and what little there is executes quickly and without blocking. +** +** As of version 3.3.2, this mutex must be recursive. */ -void sqlite3OsEnterMutex(){ +void sqlite3UnixEnterMutex(){ #ifdef SQLITE_UNIX_THREADS - pthread_mutex_lock(&mutex); + pthread_mutex_lock(&mutex1); + if( inMutex==0 ){ + pthread_mutex_lock(&mutex2); + mutexOwner = pthread_self(); + } + pthread_mutex_unlock(&mutex1); #endif - assert( !inMutex ); - inMutex = 1; + inMutex++; } -void sqlite3OsLeaveMutex(){ - assert( inMutex ); - inMutex = 0; +void sqlite3UnixLeaveMutex(){ + assert( inMutex>0 ); #ifdef SQLITE_UNIX_THREADS - pthread_mutex_unlock(&mutex); + assert( pthread_equal(mutexOwner, pthread_self()) ); + pthread_mutex_lock(&mutex1); + inMutex--; + if( inMutex==0 ){ + pthread_mutex_unlock(&mutex2); + } + pthread_mutex_unlock(&mutex1); +#else + inMutex--; +#endif +} + +/* +** Return TRUE if the mutex is currently held. +** +** If the thisThreadOnly parameter is true, return true only if the +** calling thread holds the mutex. If the parameter is false, return +** true if any thread holds the mutex. +*/ +int sqlite3UnixInMutex(int thisThreadOnly){ +#ifdef SQLITE_UNIX_THREADS + return inMutex>0 && + (thisThreadOnly==0 || pthread_equal(mutexOwner, pthread_self())); +#else + return inMutex>0; +#endif +} + +/* +** Remember the number of thread-specific-data blocks allocated. +** Use this to verify that we are not leaking thread-specific-data. +** Ticket #1601 +*/ +#ifdef SQLITE_TEST +int sqlite3_tsd_count = 0; +# ifdef SQLITE_UNIX_THREADS + static pthread_mutex_t tsd_counter_mutex = PTHREAD_MUTEX_INITIALIZER; +# define TSD_COUNTER(N) \ + pthread_mutex_lock(&tsd_counter_mutex); \ + sqlite3_tsd_count += N; \ + pthread_mutex_unlock(&tsd_counter_mutex); +# else +# define TSD_COUNTER(N) sqlite3_tsd_count += N +# endif +#else +# define TSD_COUNTER(N) /* no-op */ +#endif + +/* +** If called with allocateFlag>0, then return a pointer to thread +** specific data for the current thread. Allocate and zero the +** thread-specific data if it does not already exist. +** +** If called with allocateFlag==0, then check the current thread +** specific data. Return it if it exists. If it does not exist, +** then return NULL. +** +** If called with allocateFlag<0, check to see if the thread specific +** data is allocated and is all zero. If it is then deallocate it. +** Return a pointer to the thread specific data or NULL if it is +** unallocated or gets deallocated. +*/ +ThreadData *sqlite3UnixThreadSpecificData(int allocateFlag){ + static const ThreadData zeroData = {0}; /* Initializer to silence warnings + ** from broken compilers */ +#ifdef SQLITE_UNIX_THREADS + static pthread_key_t key; + static int keyInit = 0; + ThreadData *pTsd; + + if( !keyInit ){ + sqlite3OsEnterMutex(); + if( !keyInit ){ + int rc; + rc = pthread_key_create(&key, 0); + if( rc ){ + sqlite3OsLeaveMutex(); + return 0; + } + keyInit = 1; + } + sqlite3OsLeaveMutex(); + } + + pTsd = pthread_getspecific(key); + if( allocateFlag>0 ){ + if( pTsd==0 ){ + if( !sqlite3TestMallocFail() ){ + pTsd = sqlite3OsMalloc(sizeof(zeroData)); + } +#ifdef SQLITE_MEMDEBUG + sqlite3_isFail = 0; +#endif + if( pTsd ){ + *pTsd = zeroData; + pthread_setspecific(key, pTsd); + TSD_COUNTER(+1); + } + } + }else if( pTsd!=0 && allocateFlag<0 + && memcmp(pTsd, &zeroData, sizeof(ThreadData))==0 ){ + sqlite3OsFree(pTsd); + pthread_setspecific(key, 0); + TSD_COUNTER(-1); + pTsd = 0; + } + return pTsd; +#else + static ThreadData *pTsd = 0; + if( allocateFlag>0 ){ + if( pTsd==0 ){ + if( !sqlite3TestMallocFail() ){ + pTsd = sqlite3OsMalloc( sizeof(zeroData) ); + } +#ifdef SQLITE_MEMDEBUG + sqlite3_isFail = 0; +#endif + if( pTsd ){ + *pTsd = zeroData; + TSD_COUNTER(+1); + } + } + }else if( pTsd!=0 && allocateFlag<0 + && memcmp(pTsd, &zeroData, sizeof(ThreadData))==0 ){ + sqlite3OsFree(pTsd); + TSD_COUNTER(-1); + pTsd = 0; + } + return pTsd; #endif } @@ -1438,7 +1834,7 @@ int sqlite3_current_time = 0; ** current time and date as a Julian Day number into *prNow and ** return 0. Return 1 if the time and date cannot be found. */ -int sqlite3OsCurrentTime(double *prNow){ +int sqlite3UnixCurrentTime(double *prNow){ #ifdef NO_GETTOD time_t t; time(&t); diff --git a/mozilla/db/sqlite3/src/os_win.c b/mozilla/db/sqlite3/src/os_win.c index ad874ae6335..944d6e29d1e 100644 --- a/mozilla/db/sqlite3/src/os_win.c +++ b/mozilla/db/sqlite3/src/os_win.c @@ -34,6 +34,49 @@ */ #include "os_common.h" +/* +** Determine if we are dealing with WindowsCE - which has a much +** reduced API. +*/ +#if defined(_WIN32_WCE) +# define OS_WINCE 1 +#else +# define OS_WINCE 0 +#endif + +/* +** WinCE lacks native support for file locking so we have to fake it +** with some code of our own. +*/ +#if OS_WINCE +typedef struct winceLock { + int nReaders; /* Number of reader locks obtained */ + BOOL bPending; /* Indicates a pending lock has been obtained */ + BOOL bReserved; /* Indicates a reserved lock has been obtained */ + BOOL bExclusive; /* Indicates an exclusive lock has been obtained */ +} winceLock; +#endif + +/* +** The winFile structure is a subclass of OsFile specific to the win32 +** portability layer. +*/ +typedef struct winFile winFile; +struct winFile { + IoMethod const *pMethod;/* Must be first */ + HANDLE h; /* Handle for accessing the file */ + unsigned char locktype; /* Type of lock currently held on this file */ + short sharedLockByte; /* Randomly chosen byte used as a shared lock */ +#if OS_WINCE + WCHAR *zDeleteOnClose; /* Name of file to delete when closing */ + HANDLE hMutex; /* Mutex used to control access to shared lock */ + HANDLE hShared; /* Shared memory segment used for locking */ + winceLock local; /* Locks obtained by this instance of winFile */ + winceLock *shared; /* Global shared lock memory for the file */ +#endif +}; + + /* ** Do not include any of the File I/O interface procedures if the ** SQLITE_OMIT_DISKIO macro is defined (indicating that there database @@ -56,8 +99,8 @@ int sqlite3_os_type = 0; /* -** Return true (non-zero) if we are running under WinNT, Win2K or WinXP. -** Return false (zero) for Win95, Win98, or WinME. +** Return true (non-zero) if we are running under WinNT, Win2K, WinXP, +** or WinCE. Return false (zero) for Win95, Win98, or WinME. ** ** Here is an interesting observation: Win95, Win98, and WinME lack ** the LockFileEx() API. But we can still statically link against that @@ -66,15 +109,19 @@ int sqlite3_os_type = 0; ** WinNT/2K/XP so that we will know whether or not we can safely call ** the LockFileEx() API. */ -static int isNT(void){ - if( sqlite3_os_type==0 ){ - OSVERSIONINFO sInfo; - sInfo.dwOSVersionInfoSize = sizeof(sInfo); - GetVersionEx(&sInfo); - sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; +#if OS_WINCE +# define isNT() (1) +#else + static int isNT(void){ + if( sqlite3_os_type==0 ){ + OSVERSIONINFO sInfo; + sInfo.dwOSVersionInfoSize = sizeof(sInfo); + GetVersionEx(&sInfo); + sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; + } + return sqlite3_os_type==2; } - return sqlite3_os_type==2; -} +#endif /* OS_WINCE */ /* ** Convert a UTF-8 string to UTF-32. Space to hold the returned string @@ -122,17 +169,326 @@ static char *unicodeToUtf8(const WCHAR *zWideFilename){ return zFilename; } +#if OS_WINCE +/************************************************************************* +** This section contains code for WinCE only. +*/ +/* +** WindowsCE does not have a localtime() function. So create a +** substitute. +*/ +#include +struct tm *__cdecl localtime(const time_t *t) +{ + static struct tm y; + FILETIME uTm, lTm; + SYSTEMTIME pTm; + i64 t64; + t64 = *t; + t64 = (t64 + 11644473600)*10000000; + uTm.dwLowDateTime = t64 & 0xFFFFFFFF; + uTm.dwHighDateTime= t64 >> 32; + FileTimeToLocalFileTime(&uTm,&lTm); + FileTimeToSystemTime(&lTm,&pTm); + y.tm_year = pTm.wYear - 1900; + y.tm_mon = pTm.wMonth - 1; + y.tm_wday = pTm.wDayOfWeek; + y.tm_mday = pTm.wDay; + y.tm_hour = pTm.wHour; + y.tm_min = pTm.wMinute; + y.tm_sec = pTm.wSecond; + return &y; +} + +/* This will never be called, but defined to make the code compile */ +#define GetTempPathA(a,b) + +#define LockFile(a,b,c,d,e) winceLockFile(&a, b, c, d, e) +#define UnlockFile(a,b,c,d,e) winceUnlockFile(&a, b, c, d, e) +#define LockFileEx(a,b,c,d,e,f) winceLockFileEx(&a, b, c, d, e, f) + +#define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-offsetof(winFile,h)] + +/* +** Acquire a lock on the handle h +*/ +static void winceMutexAcquire(HANDLE h){ + DWORD dwErr; + do { + dwErr = WaitForSingleObject(h, INFINITE); + } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED); +} +/* +** Release a lock acquired by winceMutexAcquire() +*/ +#define winceMutexRelease(h) ReleaseMutex(h) + +/* +** Create the mutex and shared memory used for locking in the file +** descriptor pFile +*/ +static BOOL winceCreateLock(const char *zFilename, winFile *pFile){ + WCHAR *zTok; + WCHAR *zName = utf8ToUnicode(zFilename); + BOOL bInit = TRUE; + + /* Initialize the local lockdata */ + ZeroMemory(&pFile->local, sizeof(pFile->local)); + + /* Replace the backslashes from the filename and lowercase it + ** to derive a mutex name. */ + zTok = CharLowerW(zName); + for (;*zTok;zTok++){ + if (*zTok == '\\') *zTok = '_'; + } + + /* Create/open the named mutex */ + pFile->hMutex = CreateMutexW(NULL, FALSE, zName); + if (!pFile->hMutex){ + sqliteFree(zName); + return FALSE; + } + + /* Acquire the mutex before continuing */ + winceMutexAcquire(pFile->hMutex); + + /* Since the names of named mutexes, semaphores, file mappings etc are + ** case-sensitive, take advantage of that by uppercasing the mutex name + ** and using that as the shared filemapping name. + */ + CharUpperW(zName); + pFile->hShared = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, + PAGE_READWRITE, 0, sizeof(winceLock), + zName); + + /* Set a flag that indicates we're the first to create the memory so it + ** must be zero-initialized */ + if (GetLastError() == ERROR_ALREADY_EXISTS){ + bInit = FALSE; + } + + sqliteFree(zName); + + /* If we succeeded in making the shared memory handle, map it. */ + if (pFile->hShared){ + pFile->shared = (winceLock*)MapViewOfFile(pFile->hShared, + FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock)); + /* If mapping failed, close the shared memory handle and erase it */ + if (!pFile->shared){ + CloseHandle(pFile->hShared); + pFile->hShared = NULL; + } + } + + /* If shared memory could not be created, then close the mutex and fail */ + if (pFile->hShared == NULL){ + winceMutexRelease(pFile->hMutex); + CloseHandle(pFile->hMutex); + pFile->hMutex = NULL; + return FALSE; + } + + /* Initialize the shared memory if we're supposed to */ + if (bInit) { + ZeroMemory(pFile->shared, sizeof(winceLock)); + } + + winceMutexRelease(pFile->hMutex); + return TRUE; +} + +/* +** Destroy the part of winFile that deals with wince locks +*/ +static void winceDestroyLock(winFile *pFile){ + if (pFile->hMutex){ + /* Acquire the mutex */ + winceMutexAcquire(pFile->hMutex); + + /* The following blocks should probably assert in debug mode, but they + are to cleanup in case any locks remained open */ + if (pFile->local.nReaders){ + pFile->shared->nReaders --; + } + if (pFile->local.bReserved){ + pFile->shared->bReserved = FALSE; + } + if (pFile->local.bPending){ + pFile->shared->bPending = FALSE; + } + if (pFile->local.bExclusive){ + pFile->shared->bExclusive = FALSE; + } + + /* De-reference and close our copy of the shared memory handle */ + UnmapViewOfFile(pFile->shared); + CloseHandle(pFile->hShared); + + /* Done with the mutex */ + winceMutexRelease(pFile->hMutex); + CloseHandle(pFile->hMutex); + pFile->hMutex = NULL; + } +} + +/* +** An implementation of the LockFile() API of windows for wince +*/ +static BOOL winceLockFile( + HANDLE *phFile, + DWORD dwFileOffsetLow, + DWORD dwFileOffsetHigh, + DWORD nNumberOfBytesToLockLow, + DWORD nNumberOfBytesToLockHigh +){ + winFile *pFile = HANDLE_TO_WINFILE(phFile); + BOOL bReturn = FALSE; + + if (!pFile->hMutex) return TRUE; + winceMutexAcquire(pFile->hMutex); + + /* Wanting an exclusive lock? */ + if (dwFileOffsetLow == SHARED_FIRST + && nNumberOfBytesToLockLow == SHARED_SIZE){ + if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){ + pFile->shared->bExclusive = TRUE; + pFile->local.bExclusive = TRUE; + bReturn = TRUE; + } + } + + /* Want a read-only lock? */ + else if ((dwFileOffsetLow >= SHARED_FIRST && + dwFileOffsetLow < SHARED_FIRST + SHARED_SIZE) && + nNumberOfBytesToLockLow == 1){ + if (pFile->shared->bExclusive == 0){ + pFile->local.nReaders ++; + if (pFile->local.nReaders == 1){ + pFile->shared->nReaders ++; + } + bReturn = TRUE; + } + } + + /* Want a pending lock? */ + else if (dwFileOffsetLow == PENDING_BYTE && nNumberOfBytesToLockLow == 1){ + /* If no pending lock has been acquired, then acquire it */ + if (pFile->shared->bPending == 0) { + pFile->shared->bPending = TRUE; + pFile->local.bPending = TRUE; + bReturn = TRUE; + } + } + /* Want a reserved lock? */ + else if (dwFileOffsetLow == RESERVED_BYTE && nNumberOfBytesToLockLow == 1){ + if (pFile->shared->bReserved == 0) { + pFile->shared->bReserved = TRUE; + pFile->local.bReserved = TRUE; + bReturn = TRUE; + } + } + + winceMutexRelease(pFile->hMutex); + return bReturn; +} + +/* +** An implementation of the UnlockFile API of windows for wince +*/ +static BOOL winceUnlockFile( + HANDLE *phFile, + DWORD dwFileOffsetLow, + DWORD dwFileOffsetHigh, + DWORD nNumberOfBytesToUnlockLow, + DWORD nNumberOfBytesToUnlockHigh +){ + winFile *pFile = HANDLE_TO_WINFILE(phFile); + BOOL bReturn = FALSE; + + if (!pFile->hMutex) return TRUE; + winceMutexAcquire(pFile->hMutex); + + /* Releasing a reader lock or an exclusive lock */ + if (dwFileOffsetLow >= SHARED_FIRST && + dwFileOffsetLow < SHARED_FIRST + SHARED_SIZE){ + /* Did we have an exclusive lock? */ + if (pFile->local.bExclusive){ + pFile->local.bExclusive = FALSE; + pFile->shared->bExclusive = FALSE; + bReturn = TRUE; + } + + /* Did we just have a reader lock? */ + else if (pFile->local.nReaders){ + pFile->local.nReaders --; + if (pFile->local.nReaders == 0) + { + pFile->shared->nReaders --; + } + bReturn = TRUE; + } + } + + /* Releasing a pending lock */ + else if (dwFileOffsetLow == PENDING_BYTE && nNumberOfBytesToUnlockLow == 1){ + if (pFile->local.bPending){ + pFile->local.bPending = FALSE; + pFile->shared->bPending = FALSE; + bReturn = TRUE; + } + } + /* Releasing a reserved lock */ + else if (dwFileOffsetLow == RESERVED_BYTE && nNumberOfBytesToUnlockLow == 1){ + if (pFile->local.bReserved) { + pFile->local.bReserved = FALSE; + pFile->shared->bReserved = FALSE; + bReturn = TRUE; + } + } + + winceMutexRelease(pFile->hMutex); + return bReturn; +} + +/* +** An implementation of the LockFileEx() API of windows for wince +*/ +static BOOL winceLockFileEx( + HANDLE *phFile, + DWORD dwFlags, + DWORD dwReserved, + DWORD nNumberOfBytesToLockLow, + DWORD nNumberOfBytesToLockHigh, + LPOVERLAPPED lpOverlapped +){ + /* If the caller wants a shared read lock, forward this call + ** to winceLockFile */ + if (lpOverlapped->Offset == SHARED_FIRST && + dwFlags == 1 && + nNumberOfBytesToLockLow == SHARED_SIZE){ + return winceLockFile(phFile, SHARED_FIRST, 0, 1, 0); + } + return FALSE; +} +/* +** End of the special code for wince +*****************************************************************************/ +#endif /* OS_WINCE */ /* ** Delete the named file */ -int sqlite3OsDelete(const char *zFilename){ +int sqlite3WinDelete(const char *zFilename){ WCHAR *zWide = utf8ToUnicode(zFilename); if( zWide ){ DeleteFileW(zWide); sqliteFree(zWide); }else{ +#if OS_WINCE + return SQLITE_NOMEM; +#else DeleteFileA(zFilename); +#endif } TRACE2("DELETE \"%s\"\n", zFilename); return SQLITE_OK; @@ -141,18 +497,25 @@ int sqlite3OsDelete(const char *zFilename){ /* ** Return TRUE if the named file exists. */ -int sqlite3OsFileExists(const char *zFilename){ +int sqlite3WinFileExists(const char *zFilename){ int exists = 0; WCHAR *zWide = utf8ToUnicode(zFilename); if( zWide ){ exists = GetFileAttributesW(zWide) != 0xffffffff; sqliteFree(zWide); }else{ +#if OS_WINCE + return SQLITE_NOMEM; +#else exists = GetFileAttributesA(zFilename) != 0xffffffff; +#endif } return exists; } +/* Forward declaration */ +static int allocateWinFile(winFile *pInit, OsFile **pId); + /* ** Attempt to open a file for both reading and writing. If that ** fails, try opening it read-only. If the file does not exist, @@ -166,14 +529,15 @@ int sqlite3OsFileExists(const char *zFilename){ ** On failure, the function returns SQLITE_CANTOPEN and leaves ** *id and *pReadonly unchanged. */ -int sqlite3OsOpenReadWrite( +int sqlite3WinOpenReadWrite( const char *zFilename, - OsFile *id, + OsFile **pId, int *pReadonly ){ + winFile f; HANDLE h; WCHAR *zWide = utf8ToUnicode(zFilename); - assert( !id->isOpen ); + assert( *pId==0 ); if( zWide ){ h = CreateFileW(zWide, GENERIC_READ | GENERIC_WRITE, @@ -200,8 +564,18 @@ int sqlite3OsOpenReadWrite( }else{ *pReadonly = 0; } +#if OS_WINCE + if (!winceCreateLock(zFilename, &f)){ + CloseHandle(h); + sqliteFree(zWide); + return SQLITE_CANTOPEN; + } +#endif sqliteFree(zWide); }else{ +#if OS_WINCE + return SQLITE_NOMEM; +#else h = CreateFileA(zFilename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, @@ -226,14 +600,14 @@ int sqlite3OsOpenReadWrite( }else{ *pReadonly = 0; } +#endif /* OS_WINCE */ } - id->h = h; - id->locktype = NO_LOCK; - id->sharedLockByte = 0; - id->isOpen = 1; - OpenCounter(+1); + f.h = h; +#if OS_WINCE + f.zDeleteOnClose = 0; +#endif TRACE3("OPEN R/W %d \"%s\"\n", h, zFilename); - return SQLITE_OK; + return allocateWinFile(&f, pId); } @@ -251,17 +625,18 @@ int sqlite3OsOpenReadWrite( ** ** On failure, return SQLITE_CANTOPEN. */ -int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ +int sqlite3WinOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ + winFile f; HANDLE h; int fileflags; WCHAR *zWide = utf8ToUnicode(zFilename); - assert( !id->isOpen ); + assert( *pId == 0 ); + fileflags = FILE_FLAG_RANDOM_ACCESS; +#if !OS_WINCE if( delFlag ){ - fileflags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_RANDOM_ACCESS - | FILE_FLAG_DELETE_ON_CLOSE; - }else{ - fileflags = FILE_FLAG_RANDOM_ACCESS; + fileflags |= FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE; } +#endif if( zWide ){ h = CreateFileW(zWide, GENERIC_READ | GENERIC_WRITE, @@ -273,6 +648,9 @@ int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ ); sqliteFree(zWide); }else{ +#if OS_WINCE + return SQLITE_NOMEM; +#else h = CreateFileA(zFilename, GENERIC_READ | GENERIC_WRITE, 0, @@ -281,17 +659,18 @@ int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ fileflags, NULL ); +#endif /* OS_WINCE */ } if( h==INVALID_HANDLE_VALUE ){ return SQLITE_CANTOPEN; } - id->h = h; - id->locktype = NO_LOCK; - id->sharedLockByte = 0; - id->isOpen = 1; - OpenCounter(+1); + f.h = h; +#if OS_WINCE + f.zDeleteOnClose = delFlag ? utf8ToUnicode(zFilename) : 0; + f.hMutex = NULL; +#endif TRACE3("OPEN EX %d \"%s\"\n", h, zFilename); - return SQLITE_OK; + return allocateWinFile(&f, pId); } /* @@ -301,10 +680,11 @@ int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ ** ** On failure, return SQLITE_CANTOPEN. */ -int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){ +int sqlite3WinOpenReadOnly(const char *zFilename, OsFile **pId){ + winFile f; HANDLE h; WCHAR *zWide = utf8ToUnicode(zFilename); - assert( !id->isOpen ); + assert( *pId==0 ); if( zWide ){ h = CreateFileW(zWide, GENERIC_READ, @@ -316,6 +696,9 @@ int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){ ); sqliteFree(zWide); }else{ +#if OS_WINCE + return SQLITE_NOMEM; +#else h = CreateFileA(zFilename, GENERIC_READ, 0, @@ -324,17 +707,18 @@ int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); +#endif } if( h==INVALID_HANDLE_VALUE ){ return SQLITE_CANTOPEN; } - id->h = h; - id->locktype = NO_LOCK; - id->sharedLockByte = 0; - id->isOpen = 1; - OpenCounter(+1); + f.h = h; +#if OS_WINCE + f.zDeleteOnClose = 0; + f.hMutex = NULL; +#endif TRACE3("OPEN RO %d \"%s\"\n", h, zFilename); - return SQLITE_OK; + return allocateWinFile(&f, pId); } /* @@ -353,9 +737,9 @@ int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){ ** On failure, the function returns SQLITE_CANTOPEN and leaves ** *id unchanged. */ -int sqlite3OsOpenDirectory( - const char *zDirname, - OsFile *id +static int winOpenDirectory( + OsFile *id, + const char *zDirname ){ return SQLITE_OK; } @@ -371,7 +755,7 @@ char *sqlite3_temp_directory = 0; ** Create a temporary file name in zBuf. zBuf must be big enough to ** hold at least SQLITE_TEMPNAME_SIZE characters. */ -int sqlite3OsTempFileName(char *zBuf){ +int sqlite3WinTempFileName(char *zBuf){ static char zChars[] = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -413,12 +797,21 @@ int sqlite3OsTempFileName(char *zBuf){ /* ** Close a file. */ -int sqlite3OsClose(OsFile *id){ - if( id->isOpen ){ - TRACE2("CLOSE %d\n", id->h); - CloseHandle(id->h); +static int winClose(OsFile **pId){ + winFile *pFile; + if( pId && (pFile = (winFile*)*pId)!=0 ){ + TRACE2("CLOSE %d\n", pFile->h); + CloseHandle(pFile->h); +#if OS_WINCE + winceDestroyLock(pFile); + if( pFile->zDeleteOnClose ){ + DeleteFileW(pFile->zDeleteOnClose); + sqliteFree(pFile->zDeleteOnClose); + } +#endif OpenCounter(-1); - id->isOpen = 0; + sqliteFree(pFile); + *pId = 0; } return SQLITE_OK; } @@ -428,12 +821,12 @@ int sqlite3OsClose(OsFile *id){ ** bytes were read successfully and SQLITE_IOERR if anything goes ** wrong. */ -int sqlite3OsRead(OsFile *id, void *pBuf, int amt){ +static int winRead(OsFile *id, void *pBuf, int amt){ DWORD got; - assert( id->isOpen ); + assert( id!=0 ); SimulateIOError(SQLITE_IOERR); - TRACE3("READ %d lock=%d\n", id->h, id->locktype); - if( !ReadFile(id->h, pBuf, amt, &got, 0) ){ + TRACE3("READ %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype); + if( !ReadFile(((winFile*)id)->h, pBuf, amt, &got, 0) ){ got = 0; } if( got==(DWORD)amt ){ @@ -447,15 +840,16 @@ int sqlite3OsRead(OsFile *id, void *pBuf, int amt){ ** Write data from a buffer into a file. Return SQLITE_OK on success ** or some other error code on failure. */ -int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){ +static int winWrite(OsFile *id, const void *pBuf, int amt){ int rc = 0; DWORD wrote; - assert( id->isOpen ); + assert( id!=0 ); SimulateIOError(SQLITE_IOERR); SimulateDiskfullError; - TRACE3("WRITE %d lock=%d\n", id->h, id->locktype); + TRACE3("WRITE %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype); assert( amt>0 ); - while( amt>0 && (rc = WriteFile(id->h, pBuf, amt, &wrote, 0))!=0 && wrote>0 ){ + while( amt>0 && (rc = WriteFile(((winFile*)id)->h, pBuf, amt, &wrote, 0))!=0 + && wrote>0 ){ amt -= wrote; pBuf = &((char*)pBuf)[wrote]; } @@ -475,17 +869,17 @@ int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){ /* ** Move the read/write pointer in a file. */ -int sqlite3OsSeek(OsFile *id, i64 offset){ +static int winSeek(OsFile *id, i64 offset){ LONG upperBits = offset>>32; LONG lowerBits = offset & 0xffffffff; DWORD rc; - assert( id->isOpen ); + assert( id!=0 ); #ifdef SQLITE_TEST if( offset ) SimulateDiskfullError #endif SEEK(offset/1024 + 1); - rc = SetFilePointer(id->h, lowerBits, &upperBits, FILE_BEGIN); - TRACE3("SEEK %d %lld\n", id->h, offset); + rc = SetFilePointer(((winFile*)id)->h, lowerBits, &upperBits, FILE_BEGIN); + TRACE3("SEEK %d %lld\n", ((winFile*)id)->h, offset); if( rc==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR ){ return SQLITE_FULL; } @@ -495,10 +889,10 @@ int sqlite3OsSeek(OsFile *id, i64 offset){ /* ** Make sure all writes to a particular file are committed to disk. */ -int sqlite3OsSync(OsFile *id, int dataOnly){ - assert( id->isOpen ); - TRACE3("SYNC %d lock=%d\n", id->h, id->locktype); - if( FlushFileBuffers(id->h) ){ +static int winSync(OsFile *id, int dataOnly){ + assert( id!=0 ); + TRACE3("SYNC %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype); + if( FlushFileBuffers(((winFile*)id)->h) ){ return SQLITE_OK; }else{ return SQLITE_IOERR; @@ -509,7 +903,7 @@ int sqlite3OsSync(OsFile *id, int dataOnly){ ** Sync the directory zDirname. This is a no-op on operating systems other ** than UNIX. */ -int sqlite3OsSyncDirectory(const char *zDirname){ +int sqlite3WinSyncDirectory(const char *zDirname){ SimulateIOError(SQLITE_IOERR); return SQLITE_OK; } @@ -517,34 +911,41 @@ int sqlite3OsSyncDirectory(const char *zDirname){ /* ** Truncate an open file to a specified size */ -int sqlite3OsTruncate(OsFile *id, i64 nByte){ +static int winTruncate(OsFile *id, i64 nByte){ LONG upperBits = nByte>>32; - assert( id->isOpen ); - TRACE3("TRUNCATE %d %lld\n", id->h, nByte); + assert( id!=0 ); + TRACE3("TRUNCATE %d %lld\n", ((winFile*)id)->h, nByte); SimulateIOError(SQLITE_IOERR); - SetFilePointer(id->h, nByte, &upperBits, FILE_BEGIN); - SetEndOfFile(id->h); + SetFilePointer(((winFile*)id)->h, nByte, &upperBits, FILE_BEGIN); + SetEndOfFile(((winFile*)id)->h); return SQLITE_OK; } /* ** Determine the current size of a file in bytes */ -int sqlite3OsFileSize(OsFile *id, i64 *pSize){ +static int winFileSize(OsFile *id, i64 *pSize){ DWORD upperBits, lowerBits; - assert( id->isOpen ); + assert( id!=0 ); SimulateIOError(SQLITE_IOERR); - lowerBits = GetFileSize(id->h, &upperBits); + lowerBits = GetFileSize(((winFile*)id)->h, &upperBits); *pSize = (((i64)upperBits)<<32) + lowerBits; return SQLITE_OK; } +/* +** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems. +*/ +#ifndef LOCKFILE_FAIL_IMMEDIATELY +# define LOCKFILE_FAIL_IMMEDIATELY 1 +#endif + /* ** Acquire a reader lock. ** Different API routines are called depending on whether or not this ** is Win95 or WinNT. */ -static int getReadLock(OsFile *id){ +static int getReadLock(winFile *id){ int res; if( isNT() ){ OVERLAPPED ovlp; @@ -564,12 +965,12 @@ static int getReadLock(OsFile *id){ /* ** Undo a readlock */ -static int unlockReadLock(OsFile *id){ +static int unlockReadLock(winFile *pFile){ int res; if( isNT() ){ - res = UnlockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0); + res = UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); }else{ - res = UnlockFile(id->h, SHARED_FIRST + id->sharedLockByte, 0, 1, 0); + res = UnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0); } return res; } @@ -579,7 +980,7 @@ static int unlockReadLock(OsFile *id){ ** Check that a given pathname is a directory and is writable ** */ -int sqlite3OsIsDirWritable(char *zDirname){ +int sqlite3WinIsDirWritable(char *zDirname){ int fileAttr; WCHAR *zWide; if( zDirname==0 ) return 0; @@ -589,7 +990,11 @@ int sqlite3OsIsDirWritable(char *zDirname){ fileAttr = GetFileAttributesW(zWide); sqliteFree(zWide); }else{ +#if OS_WINCE + return 0; +#else fileAttr = GetFileAttributesA(zDirname); +#endif } if( fileAttr == 0xffffffff ) return 0; if( (fileAttr & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY ){ @@ -620,45 +1025,46 @@ int sqlite3OsIsDirWritable(char *zDirname){ ** RESERVED -> (PENDING) -> EXCLUSIVE ** PENDING -> EXCLUSIVE ** -** This routine will only increase a lock. The sqlite3OsUnlock() routine +** This routine will only increase a lock. The winUnlock() routine ** erases all locks at once and returns us immediately to locking level 0. ** It is not possible to lower the locking level one step at a time. You ** must go straight to locking level 0. */ -int sqlite3OsLock(OsFile *id, int locktype){ +static int winLock(OsFile *id, int locktype){ int rc = SQLITE_OK; /* Return code from subroutines */ int res = 1; /* Result of a windows lock call */ int newLocktype; /* Set id->locktype to this value before exiting */ int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */ + winFile *pFile = (winFile*)id; - assert( id->isOpen ); + assert( pFile!=0 ); TRACE5("LOCK %d %d was %d(%d)\n", - id->h, locktype, id->locktype, id->sharedLockByte); + pFile->h, locktype, pFile->locktype, pFile->sharedLockByte); /* If there is already a lock of this type or more restrictive on the ** OsFile, do nothing. Don't use the end_lock: exit path, as ** sqlite3OsEnterMutex() hasn't been called yet. */ - if( id->locktype>=locktype ){ + if( pFile->locktype>=locktype ){ return SQLITE_OK; } /* Make sure the locking sequence is correct */ - assert( id->locktype!=NO_LOCK || locktype==SHARED_LOCK ); + assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); assert( locktype!=PENDING_LOCK ); - assert( locktype!=RESERVED_LOCK || id->locktype==SHARED_LOCK ); + assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of ** the PENDING_LOCK byte is temporary. */ - newLocktype = id->locktype; - if( id->locktype==NO_LOCK - || (locktype==EXCLUSIVE_LOCK && id->locktype==RESERVED_LOCK) + newLocktype = pFile->locktype; + if( pFile->locktype==NO_LOCK + || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK) ){ int cnt = 3; - while( cnt-->0 && (res = LockFile(id->h, PENDING_BYTE, 0, 1, 0))==0 ){ + while( cnt-->0 && (res = LockFile(pFile->h, PENDING_BYTE, 0, 1, 0))==0 ){ /* Try 3 times to get the pending lock. The pending lock might be ** held by another reader process who will release it momentarily. */ @@ -671,8 +1077,8 @@ int sqlite3OsLock(OsFile *id, int locktype){ /* Acquire a shared lock */ if( locktype==SHARED_LOCK && res ){ - assert( id->locktype==NO_LOCK ); - res = getReadLock(id); + assert( pFile->locktype==NO_LOCK ); + res = getReadLock(pFile); if( res ){ newLocktype = SHARED_LOCK; } @@ -681,8 +1087,8 @@ int sqlite3OsLock(OsFile *id, int locktype){ /* Acquire a RESERVED lock */ if( locktype==RESERVED_LOCK && res ){ - assert( id->locktype==SHARED_LOCK ); - res = LockFile(id->h, RESERVED_BYTE, 0, 1, 0); + assert( pFile->locktype==SHARED_LOCK ); + res = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); if( res ){ newLocktype = RESERVED_LOCK; } @@ -698,10 +1104,10 @@ int sqlite3OsLock(OsFile *id, int locktype){ /* Acquire an EXCLUSIVE lock */ if( locktype==EXCLUSIVE_LOCK && res ){ - assert( id->locktype>=SHARED_LOCK ); - res = unlockReadLock(id); + assert( pFile->locktype>=SHARED_LOCK ); + res = unlockReadLock(pFile); TRACE2("unreadlock = %d\n", res); - res = LockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0); + res = LockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); if( res ){ newLocktype = EXCLUSIVE_LOCK; }else{ @@ -713,7 +1119,7 @@ int sqlite3OsLock(OsFile *id, int locktype){ ** release it now. */ if( gotPendingLock && locktype==SHARED_LOCK ){ - UnlockFile(id->h, PENDING_BYTE, 0, 1, 0); + UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0); } /* Update the state of the lock has held in the file descriptor then @@ -722,11 +1128,11 @@ int sqlite3OsLock(OsFile *id, int locktype){ if( res ){ rc = SQLITE_OK; }else{ - TRACE4("LOCK FAILED %d trying for %d but got %d\n", id->h, + TRACE4("LOCK FAILED %d trying for %d but got %d\n", pFile->h, locktype, newLocktype); rc = SQLITE_BUSY; } - id->locktype = newLocktype; + pFile->locktype = newLocktype; return rc; } @@ -735,19 +1141,20 @@ int sqlite3OsLock(OsFile *id, int locktype){ ** file by this or any other process. If such a lock is held, return ** non-zero, otherwise zero. */ -int sqlite3OsCheckReservedLock(OsFile *id){ +static int winCheckReservedLock(OsFile *id){ int rc; - assert( id->isOpen ); - if( id->locktype>=RESERVED_LOCK ){ + winFile *pFile = (winFile*)id; + assert( pFile!=0 ); + if( pFile->locktype>=RESERVED_LOCK ){ rc = 1; - TRACE3("TEST WR-LOCK %d %d (local)\n", id->h, rc); + TRACE3("TEST WR-LOCK %d %d (local)\n", pFile->h, rc); }else{ - rc = LockFile(id->h, RESERVED_BYTE, 0, 1, 0); + rc = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); if( rc ){ - UnlockFile(id->h, RESERVED_BYTE, 0, 1, 0); + UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); } rc = !rc; - TRACE3("TEST WR-LOCK %d %d (remote)\n", id->h, rc); + TRACE3("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc); } return rc; } @@ -763,32 +1170,33 @@ int sqlite3OsCheckReservedLock(OsFile *id){ ** is NO_LOCK. If the second argument is SHARED_LOCK then this routine ** might return SQLITE_IOERR; */ -int sqlite3OsUnlock(OsFile *id, int locktype){ +static int winUnlock(OsFile *id, int locktype){ int type; int rc = SQLITE_OK; - assert( id->isOpen ); + winFile *pFile = (winFile*)id; + assert( pFile!=0 ); assert( locktype<=SHARED_LOCK ); - TRACE5("UNLOCK %d to %d was %d(%d)\n", id->h, locktype, - id->locktype, id->sharedLockByte); - type = id->locktype; + TRACE5("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype, + pFile->locktype, pFile->sharedLockByte); + type = pFile->locktype; if( type>=EXCLUSIVE_LOCK ){ - UnlockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0); - if( locktype==SHARED_LOCK && !getReadLock(id) ){ + UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); + if( locktype==SHARED_LOCK && !getReadLock(pFile) ){ /* This should never happen. We should always be able to ** reacquire the read lock */ rc = SQLITE_IOERR; } } if( type>=RESERVED_LOCK ){ - UnlockFile(id->h, RESERVED_BYTE, 0, 1, 0); + UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); } if( locktype==NO_LOCK && type>=SHARED_LOCK ){ - unlockReadLock(id); + unlockReadLock(pFile); } if( type>=PENDING_LOCK ){ - UnlockFile(id->h, PENDING_BYTE, 0, 1, 0); + UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0); } - id->locktype = locktype; + pFile->locktype = locktype; return rc; } @@ -798,17 +1206,21 @@ int sqlite3OsUnlock(OsFile *id, int locktype){ ** The calling function is responsible for freeing this space once it ** is no longer needed. */ -char *sqlite3OsFullPathname(const char *zRelative){ - char *zNotUsed; +char *sqlite3WinFullPathname(const char *zRelative){ char *zFull; - WCHAR *zWide; +#if defined(__CYGWIN__) int nByte; -#ifdef __CYGWIN__ nByte = strlen(zRelative) + MAX_PATH + 1001; zFull = sqliteMalloc( nByte ); if( zFull==0 ) return 0; if( cygwin_conv_to_full_win32_path(zRelative, zFull) ) return 0; +#elif OS_WINCE + /* WinCE has no concept of a relative pathname, or so I am told. */ + zFull = sqliteStrDup(zRelative); #else + char *zNotUsed; + WCHAR *zWide; + int nByte; zWide = utf8ToUnicode(zRelative); if( zWide ){ WCHAR *zTemp, *zNotUsedW; @@ -829,6 +1241,76 @@ char *sqlite3OsFullPathname(const char *zRelative){ return zFull; } +/* +** The fullSync option is meaningless on windows. This is a no-op. +*/ +static void winSetFullSync(OsFile *id, int v){ + return; +} + +/* +** Return the underlying file handle for an OsFile +*/ +static int winFileHandle(OsFile *id){ + return (int)((winFile*)id)->h; +} + +/* +** Return an integer that indices the type of lock currently held +** by this handle. (Used for testing and analysis only.) +*/ +static int winLockState(OsFile *id){ + return ((winFile*)id)->locktype; +} + +/* +** This vector defines all the methods that can operate on an OsFile +** for win32. +*/ +static const IoMethod sqlite3WinIoMethod = { + winClose, + winOpenDirectory, + winRead, + winWrite, + winSeek, + winTruncate, + winSync, + winSetFullSync, + winFileHandle, + winFileSize, + winLock, + winUnlock, + winLockState, + winCheckReservedLock, +}; + +/* +** Allocate memory for an OsFile. Initialize the new OsFile +** to the value given in pInit and return a pointer to the new +** OsFile. If we run out of memory, close the file and return NULL. +*/ +static int allocateWinFile(winFile *pInit, OsFile **pId){ + winFile *pNew; + pNew = sqliteMalloc( sizeof(*pNew) ); + if( pNew==0 ){ + CloseHandle(pInit->h); +#if OS_WINCE + sqliteFree(pInit->zDeleteOnClose); +#endif + *pId = 0; + return SQLITE_NOMEM; + }else{ + *pNew = *pInit; + pNew->pMethod = &sqlite3WinIoMethod; + pNew->locktype = NO_LOCK; + pNew->sharedLockByte = 0; + *pId = (OsFile*)pNew; + OpenCounter(+1); + return SQLITE_OK; + } +} + + #endif /* SQLITE_OMIT_DISKIO */ /*************************************************************************** ** Everything above deals with file I/O. Everything that follows deals @@ -840,7 +1322,7 @@ char *sqlite3OsFullPathname(const char *zRelative){ ** is written into the buffer zBuf[256]. The calling function must ** supply a sufficiently large buffer. */ -int sqlite3OsRandomSeed(char *zBuf){ +int sqlite3WinRandomSeed(char *zBuf){ /* We have to initialize zBuf to prevent valgrind from reporting ** errors. The reports issued by valgrind are incorrect - we would ** prefer that the randomness be increased by making use of the @@ -861,7 +1343,7 @@ int sqlite3OsRandomSeed(char *zBuf){ /* ** Sleep for a little while. Return the amount of time slept. */ -int sqlite3OsSleep(int ms){ +int sqlite3WinSleep(int ms){ Sleep(ms); return ms; } @@ -871,18 +1353,22 @@ int sqlite3OsSleep(int ms){ */ static int inMutex = 0; #ifdef SQLITE_W32_THREADS + static DWORD mutexOwner; static CRITICAL_SECTION cs; #endif /* -** The following pair of routine implement mutual exclusion for +** The following pair of routines implement mutual exclusion for ** multi-threaded processes. Only a single thread is allowed to ** executed code that is surrounded by EnterMutex() and LeaveMutex(). ** ** SQLite uses only a single Mutex. There is not much critical ** code and what little there is executes quickly and without blocking. +** +** Version 3.3.1 and earlier used a simple mutex. Beginning with +** version 3.3.2, a recursive mutex is required. */ -void sqlite3OsEnterMutex(){ +void sqlite3WinEnterMutex(){ #ifdef SQLITE_W32_THREADS static int isInit = 0; while( !isInit ){ @@ -895,18 +1381,35 @@ void sqlite3OsEnterMutex(){ } } EnterCriticalSection(&cs); + mutexOwner = GetCurrentThreadId(); #endif - assert( !inMutex ); - inMutex = 1; + inMutex++; } -void sqlite3OsLeaveMutex(){ +void sqlite3WinLeaveMutex(){ assert( inMutex ); - inMutex = 0; + inMutex--; #ifdef SQLITE_W32_THREADS + assert( mutexOwner==GetCurrentThreadId() ); LeaveCriticalSection(&cs); #endif } +/* +** Return TRUE if the mutex is currently held. +** +** If the thisThreadOnly parameter is true, return true if and only if the +** calling thread holds the mutex. If the parameter is false, return +** true if any thread holds the mutex. +*/ +int sqlite3WinInMutex(int thisThreadOnly){ +#ifdef SQLITE_W32_THREADS + return inMutex>0 && (thisThreadOnly==0 || mutexOwner==GetCurrentThreadId()); +#else + return inMutex>0; +#endif +} + + /* ** The following variable, if set to a non-zero value, becomes the result ** returned from sqlite3OsCurrentTime(). This is used for testing. @@ -920,13 +1423,19 @@ int sqlite3_current_time = 0; ** current time and date as a Julian Day number into *prNow and ** return 0. Return 1 if the time and date cannot be found. */ -int sqlite3OsCurrentTime(double *prNow){ +int sqlite3WinCurrentTime(double *prNow){ FILETIME ft; /* FILETIME structure is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5). */ double now; +#if OS_WINCE + SYSTEMTIME time; + GetSystemTime(&time); + SystemTimeToFileTime(&time,&ft); +#else GetSystemTimeAsFileTime( &ft ); +#endif now = ((double)ft.dwHighDateTime) * 4294967296.0; *prNow = (now + ft.dwLowDateTime)/864000000000.0 + 2305813.5; #ifdef SQLITE_TEST @@ -937,4 +1446,71 @@ int sqlite3OsCurrentTime(double *prNow){ return 0; } +/* +** Remember the number of thread-specific-data blocks allocated. +** Use this to verify that we are not leaking thread-specific-data. +** Ticket #1601 +*/ +#ifdef SQLITE_TEST +int sqlite3_tsd_count = 0; +# define TSD_COUNTER_INCR InterlockedIncrement(&sqlite3_tsd_count) +# define TSD_COUNTER_DECR InterlockedDecrement(&sqlite3_tsd_count) +#else +# define TSD_COUNTER_INCR /* no-op */ +# define TSD_COUNTER_DECR /* no-op */ +#endif + + + +/* +** If called with allocateFlag>1, then return a pointer to thread +** specific data for the current thread. Allocate and zero the +** thread-specific data if it does not already exist necessary. +** +** If called with allocateFlag==0, then check the current thread +** specific data. Return it if it exists. If it does not exist, +** then return NULL. +** +** If called with allocateFlag<0, check to see if the thread specific +** data is allocated and is all zero. If it is then deallocate it. +** Return a pointer to the thread specific data or NULL if it is +** unallocated or gets deallocated. +*/ +ThreadData *sqlite3WinThreadSpecificData(int allocateFlag){ + static int key; + static int keyInit = 0; + static const ThreadData zeroData; + ThreadData *pTsd; + + if( !keyInit ){ + sqlite3OsEnterMutex(); + if( !keyInit ){ + key = TlsAlloc(); + if( key==0xffffffff ){ + sqlite3OsLeaveMutex(); + return 0; + } + keyInit = 1; + } + sqlite3OsLeaveMutex(); + } + pTsd = TlsGetValue(key); + if( allocateFlag>0 ){ + if( !pTsd ){ + pTsd = sqlite3OsMalloc( sizeof(zeroData) ); + if( pTsd ){ + *pTsd = zeroData; + TlsSetValue(key, pTsd); + TSD_COUNTER_INCR; + } + } + }else if( pTsd!=0 && allocateFlag<0 + && memcmp(pTsd, &zeroData, sizeof(ThreadData))==0 ){ + sqlite3OsFree(pTsd); + TlsSetValue(key, 0); + TSD_COUNTER_DECR; + pTsd = 0; + } + return pTsd; +} #endif /* OS_WIN */ diff --git a/mozilla/db/sqlite3/src/pager.c b/mozilla/db/sqlite3/src/pager.c index 74b55aa1cf5..e01ed62cfbb 100644 --- a/mozilla/db/sqlite3/src/pager.c +++ b/mozilla/db/sqlite3/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.215 2005/09/17 15:20:27 drh Exp $ +** @(#) $Id: pager.c,v 1.257 2006/01/30 22:48:44 drh Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -46,21 +46,14 @@ /* ** 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. +** to print out file-descriptors. ** ** 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 +#define PAGERID(p) FILEHANDLEID(&(p)->fd) +#define FILEHANDLEID(fd) (sqlite3OsFileHandle(&fd)) /* ** The page cache as a whole is always in one of the following @@ -232,6 +225,14 @@ struct PgHistory { /* ** A open page cache is an instance of the following structure. +** +** Pager.errCode may be set to SQLITE_IOERR, SQLITE_CORRUPT, SQLITE_PROTOCOL +** or SQLITE_FULL. Once one of the first three errors occurs, it persists +** and is returned as the result of every major pager API call. The +** SQLITE_FULL return code is slightly different. It persists only until the +** next successful rollback is performed on the pager cache. Also, +** SQLITE_FULL does not affect the sqlite3pager_get() and sqlite3pager_lookup() +** APIs, they may still be used successfully. */ struct Pager { u8 journalOpen; /* True if journal file descriptors is valid */ @@ -244,7 +245,7 @@ struct Pager { u8 noSync; /* Do not sync the journal if true */ u8 fullSync; /* Do extra syncs of the journal for robustness */ u8 state; /* PAGER_UNLOCK, _SHARED, _RESERVED, etc. */ - u8 errMask; /* One of several kinds of errors */ + u8 errCode; /* One of several kinds of errors */ u8 tempFile; /* zFilename is a temporary file */ u8 readOnly; /* True for a read-only database */ u8 needSync; /* True if an fsync() is needed on the journal */ @@ -269,8 +270,8 @@ struct Pager { char *zFilename; /* Name of the database file */ char *zJournal; /* Name of the journal file */ char *zDirectory; /* Directory hold database and journal files */ - OsFile fd, jfd; /* File descriptors for database and journal */ - OsFile stfd; /* File descriptor for the statement subjournal*/ + OsFile *fd, *jfd; /* File descriptors for database and journal */ + OsFile *stfd; /* File descriptor for the statement subjournal*/ BusyHandler *pBusyHandler; /* Pointer to sqlite.busyHandler */ PgHdr *pFirst, *pLast; /* List of free pages */ PgHdr *pFirstSynced; /* First free page with PgHdr.needSync==0 */ @@ -291,6 +292,9 @@ struct Pager { void (*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */ void *pCodecArg; /* First argument to xCodec() */ PgHdr *aHash[N_PG_HASH]; /* Hash table to map page number to PgHdr */ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + Pager *pNext; /* Linked list of pagers in this thread */ +#endif }; /* @@ -303,15 +307,6 @@ struct Pager { # define TEST_INCR(x) #endif -/* -** These are bits that can be set in Pager.errMask. -*/ -#define PAGER_ERR_FULL 0x01 /* a write() failed */ -#define PAGER_ERR_MEM 0x02 /* malloc() failed */ -#define PAGER_ERR_LOCK 0x04 /* error in the locking protocol */ -#define PAGER_ERR_CORRUPT 0x08 /* database or journal corruption */ -#define PAGER_ERR_DISK 0x10 /* general disk I/O error - bad hard drive? */ - /* ** Journal files begin with the following magic string. The data ** was obtained from /dev/random. It is used only as a sanity check. @@ -411,28 +406,31 @@ static const unsigned char aJournalMagic[] = { ** All values are stored on disk as big-endian. */ static int read32bits(OsFile *fd, u32 *pRes){ - u32 res; - int rc; - rc = sqlite3OsRead(fd, &res, sizeof(res)); + unsigned char ac[4]; + int rc = sqlite3OsRead(fd, ac, sizeof(ac)); if( rc==SQLITE_OK ){ - unsigned char ac[4]; - memcpy(ac, &res, 4); - res = (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3]; + *pRes = (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3]; } - *pRes = res; return rc; } +/* +** Write a 32-bit integer into a string buffer in big-endian byte order. +*/ +static void put32bits(char *ac, u32 val){ + ac[0] = (val>>24) & 0xff; + ac[1] = (val>>16) & 0xff; + ac[2] = (val>>8) & 0xff; + ac[3] = val & 0xff; +} + /* ** Write a 32-bit integer into the given file descriptor. Return SQLITE_OK ** on success or an error code is something goes wrong. */ static int write32bits(OsFile *fd, u32 val){ - unsigned char ac[4]; - ac[0] = (val>>24) & 0xff; - ac[1] = (val>>16) & 0xff; - ac[2] = (val>>8) & 0xff; - ac[3] = val & 0xff; + char ac[4]; + put32bits(ac, val); return sqlite3OsWrite(fd, ac, 4); } @@ -441,12 +439,9 @@ static int write32bits(OsFile *fd, u32 val){ ** 'p' at offset 'offset'. */ static void store32bits(u32 val, PgHdr *p, int offset){ - unsigned char *ac; - ac = &((unsigned char*)PGHDR_TO_DATA(p))[offset]; - ac[0] = (val>>24) & 0xff; - ac[1] = (val>>16) & 0xff; - ac[2] = (val>>8) & 0xff; - ac[3] = val & 0xff; + char *ac; + ac = &((char*)PGHDR_TO_DATA(p))[offset]; + put32bits(ac, val); } /* @@ -461,16 +456,25 @@ static u32 retrieve32bits(PgHdr *p, int offset){ /* -** Convert the bits in the pPager->errMask into an approprate -** return code. +** This function should be called when an error occurs within the pager +** code. The first argument is a pointer to the pager structure, the +** second the error-code about to be returned by a pager API function. +** The value returned is a copy of the second argument to this function. +** +** If the second argument is SQLITE_IOERR, SQLITE_CORRUPT or SQLITE_PROTOCOL, +** the error becomes persistent. All subsequent API calls on this Pager +** will immediately return the same error code. */ -static int pager_errcode(Pager *pPager){ - int rc = SQLITE_OK; - if( pPager->errMask & PAGER_ERR_LOCK ) rc = SQLITE_PROTOCOL; - if( pPager->errMask & PAGER_ERR_DISK ) rc = SQLITE_IOERR; - if( pPager->errMask & PAGER_ERR_FULL ) rc = SQLITE_FULL; - if( pPager->errMask & PAGER_ERR_MEM ) rc = SQLITE_NOMEM; - if( pPager->errMask & PAGER_ERR_CORRUPT ) rc = SQLITE_CORRUPT; +static int pager_error(Pager *pPager, int rc){ + assert( pPager->errCode==SQLITE_FULL || pPager->errCode==SQLITE_OK ); + if( + rc==SQLITE_FULL || + rc==SQLITE_IOERR || + rc==SQLITE_CORRUPT || + rc==SQLITE_PROTOCOL + ){ + pPager->errCode = rc; + } return rc; } @@ -496,7 +500,7 @@ static u32 pager_pagehash(PgHdr *pPage){ #define CHECK_PAGE(x) checkPage(x) static void checkPage(PgHdr *pPg){ Pager *pPager = pPg->pPager; - assert( !pPg->pageHash || pPager->errMask || MEMDB || pPg->dirty || + assert( !pPg->pageHash || pPager->errCode || MEMDB || pPg->dirty || pPg->pageHash==pager_pagehash(pPg) ); } @@ -597,7 +601,7 @@ static int seekJournalHdr(Pager *pPager){ assert( offset>=c ); assert( (offset-c)journalOff = offset; - return sqlite3OsSeek(&pPager->jfd, pPager->journalOff); + return sqlite3OsSeek(pPager->jfd, pPager->journalOff); } /* @@ -615,6 +619,7 @@ static int seekJournalHdr(Pager *pPager){ ** Followed by (JOURNAL_HDR_SZ - 24) bytes of unused space. */ static int writeJournalHdr(Pager *pPager){ + char zHeader[sizeof(aJournalMagic)+16]; int rc = seekJournalHdr(pPager); if( rc ) return rc; @@ -633,33 +638,25 @@ static int writeJournalHdr(Pager *pPager){ ** Actually maybe the whole journal header should be delayed until that ** point. Think about this. */ - rc = sqlite3OsWrite(&pPager->jfd, aJournalMagic, sizeof(aJournalMagic)); - - if( rc==SQLITE_OK ){ - /* The nRec Field. 0xFFFFFFFF for no-sync journals. */ - rc = write32bits(&pPager->jfd, pPager->noSync ? 0xffffffff : 0); - } - if( rc==SQLITE_OK ){ - /* The random check-hash initialiser */ - sqlite3Randomness(sizeof(pPager->cksumInit), &pPager->cksumInit); - rc = write32bits(&pPager->jfd, pPager->cksumInit); - } - if( rc==SQLITE_OK ){ - /* The initial database size */ - rc = write32bits(&pPager->jfd, pPager->dbSize); - } - if( rc==SQLITE_OK ){ - /* The assumed sector size for this process */ - rc = write32bits(&pPager->jfd, pPager->sectorSize); - } + memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic)); + /* The nRec Field. 0xFFFFFFFF for no-sync journals. */ + put32bits(&zHeader[sizeof(aJournalMagic)], pPager->noSync ? 0xffffffff : 0); + /* The random check-hash initialiser */ + sqlite3Randomness(sizeof(pPager->cksumInit), &pPager->cksumInit); + put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit); + /* The initial database size */ + put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbSize); + /* The assumed sector size for this process */ + put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize); + rc = sqlite3OsWrite(pPager->jfd, zHeader, sizeof(zHeader)); /* The journal header has been written successfully. Seek the journal ** file descriptor to the end of the journal header sector. */ if( rc==SQLITE_OK ){ - rc = sqlite3OsSeek(&pPager->jfd, pPager->journalOff-1); + rc = sqlite3OsSeek(pPager->jfd, pPager->journalOff-1); if( rc==SQLITE_OK ){ - rc = sqlite3OsWrite(&pPager->jfd, "\000", 1); + rc = sqlite3OsWrite(pPager->jfd, "\000", 1); } } return rc; @@ -697,20 +694,20 @@ static int readJournalHdr( return SQLITE_DONE; } - rc = sqlite3OsRead(&pPager->jfd, aMagic, sizeof(aMagic)); + rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic)); if( rc ) return rc; if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){ return SQLITE_DONE; } - rc = read32bits(&pPager->jfd, pNRec); + rc = read32bits(pPager->jfd, pNRec); if( rc ) return rc; - rc = read32bits(&pPager->jfd, &pPager->cksumInit); + rc = read32bits(pPager->jfd, &pPager->cksumInit); if( rc ) return rc; - rc = read32bits(&pPager->jfd, pDbSize); + rc = read32bits(pPager->jfd, pDbSize); if( rc ) return rc; /* Update the assumed sector-size to match the value used by @@ -719,11 +716,11 @@ static int readJournalHdr( ** is being called from within pager_playback(). The local value ** of Pager.sectorSize is restored at the end of that routine. */ - rc = read32bits(&pPager->jfd, (u32 *)&pPager->sectorSize); + rc = read32bits(pPager->jfd, (u32 *)&pPager->sectorSize); if( rc ) return rc; pPager->journalOff += JOURNAL_HDR_SZ(pPager); - rc = sqlite3OsSeek(&pPager->jfd, pPager->journalOff); + rc = sqlite3OsSeek(pPager->jfd, pPager->journalOff); return rc; } @@ -743,12 +740,16 @@ static int readJournalHdr( ** ** The master journal page checksum is the sum of the bytes in the master ** journal name. +** +** If zMaster is a NULL pointer (occurs for a single database transaction), +** this call is a no-op. */ static int writeMasterJournal(Pager *pPager, const char *zMaster){ int rc; int len; int i; - u32 cksum = 0; + u32 cksum = 0; + char zBuf[sizeof(aJournalMagic)+2*4]; if( !zMaster || pPager->setMaster) return SQLITE_OK; pPager->setMaster = 1; @@ -768,19 +769,16 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){ } pPager->journalOff += (len+20); - rc = write32bits(&pPager->jfd, PAGER_MJ_PGNO(pPager)); + rc = write32bits(pPager->jfd, PAGER_MJ_PGNO(pPager)); if( rc!=SQLITE_OK ) return rc; - rc = sqlite3OsWrite(&pPager->jfd, zMaster, len); + rc = sqlite3OsWrite(pPager->jfd, zMaster, len); if( rc!=SQLITE_OK ) return rc; - rc = write32bits(&pPager->jfd, len); - if( rc!=SQLITE_OK ) return rc; - - rc = write32bits(&pPager->jfd, cksum); - if( rc!=SQLITE_OK ) return rc; - - rc = sqlite3OsWrite(&pPager->jfd, aJournalMagic, sizeof(aJournalMagic)); + put32bits(zBuf, len); + put32bits(&zBuf[4], cksum); + memcpy(&zBuf[8], aJournalMagic, sizeof(aJournalMagic)); + rc = sqlite3OsWrite(pPager->jfd, zBuf, 8+sizeof(aJournalMagic)); pPager->needSync = !pPager->noSync; return rc; } @@ -844,7 +842,7 @@ static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){ */ static void pager_reset(Pager *pPager){ PgHdr *pPg, *pNext; - if( pPager->errMask ) return; + if( pPager->errCode ) return; for(pPg=pPager->pAll; pPg; pPg=pNext){ pNext = pPg->pNextAll; sqliteFree(pPg); @@ -858,36 +856,13 @@ static void pager_reset(Pager *pPager){ if( pPager->state>=PAGER_RESERVED ){ sqlite3pager_rollback(pPager); } - sqlite3OsUnlock(&pPager->fd, NO_LOCK); + sqlite3OsUnlock(pPager->fd, NO_LOCK); pPager->state = PAGER_UNLOCK; pPager->dbSize = -1; pPager->nRef = 0; assert( pPager->journalOpen==0 ); } -/* -** This function is used to reset the pager after a malloc() failure. This -** doesn't work with in-memory databases. If a malloc() fails when an -** in-memory database is in use it is not possible to recover. -** -** If a transaction or statement transaction is active, it is rolled back. -** -** It is an error to call this function if any pages are in use. -*/ -#ifndef SQLITE_OMIT_GLOBALRECOVER -int sqlite3pager_reset(Pager *pPager){ - if( pPager ){ - if( pPager->nRef || MEMDB ){ - return SQLITE_ERROR; - } - pPager->errMask &= ~(PAGER_ERR_MEM); - pager_reset(pPager); - } - return SQLITE_OK; -} -#endif - - /* ** When this routine is called, the pager has the journal file open and ** a RESERVED or EXCLUSIVE lock on the database. This routine releases @@ -930,10 +905,12 @@ static int pager_unwritelock(Pager *pPager){ assert( pPager->aInJournal==0 ); assert( pPager->dirtyCache==0 || pPager->useJournal==0 ); } - rc = sqlite3OsUnlock(&pPager->fd, SHARED_LOCK); + rc = sqlite3OsUnlock(pPager->fd, SHARED_LOCK); pPager->state = PAGER_SHARED; pPager->origDbSize = 0; pPager->setMaster = 0; + pPager->needSync = 0; + pPager->pFirstSynced = pPager->pFirst; return rc; } @@ -957,7 +934,7 @@ static int pager_unwritelock(Pager *pPager){ ** only the middle sector is corrupt, we will still have a reasonable ** chance of failing the checksum and thus detecting the problem. */ -static u32 pager_cksum(Pager *pPager, Pgno pgno, const char *aData){ +static u32 pager_cksum(Pager *pPager, Pgno pgno, const u8 *aData){ u32 cksum = pPager->cksumInit; int i = pPager->pageSize-200; while( i>0 ){ @@ -985,7 +962,7 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){ /* useCksum should be true for the main journal and false for ** statement journals. Verify that this is always the case */ - assert( jfd == (useCksum ? &pPager->jfd : &pPager->stfd) ); + assert( jfd == (useCksum ? pPager->jfd : pPager->stfd) ); rc = read32bits(jfd, &pgno); @@ -1040,9 +1017,9 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){ assert( pPager->state>=PAGER_EXCLUSIVE || pPg!=0 ); TRACE3("PLAYBACK %d page %d\n", PAGERID(pPager), pgno); if( pPager->state>=PAGER_EXCLUSIVE && (pPg==0 || pPg->needSync==0) ){ - rc = sqlite3OsSeek(&pPager->fd, (pgno-1)*(i64)pPager->pageSize); + rc = sqlite3OsSeek(pPager->fd, (pgno-1)*(i64)pPager->pageSize); if( rc==SQLITE_OK ){ - rc = sqlite3OsWrite(&pPager->fd, aData, pPager->pageSize); + rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize); } if( pPg ) pPg->dirty = 0; } @@ -1082,18 +1059,17 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){ static int pager_delmaster(const char *zMaster){ int rc; int master_open = 0; - OsFile master; + OsFile *master = 0; char *zMasterJournal = 0; /* Contents of master journal file */ i64 nMasterJournal; /* Size of master journal file */ /* Open the master journal file exclusively in case some other process ** is running this routine also. Not that it makes too much difference. */ - memset(&master, 0, sizeof(master)); rc = sqlite3OsOpenReadOnly(zMaster, &master); if( rc!=SQLITE_OK ) goto delmaster_out; master_open = 1; - rc = sqlite3OsFileSize(&master, &nMasterJournal); + rc = sqlite3OsFileSize(master, &nMasterJournal); if( rc!=SQLITE_OK ) goto delmaster_out; if( nMasterJournal>0 ){ @@ -1108,7 +1084,7 @@ static int pager_delmaster(const char *zMaster){ rc = SQLITE_NOMEM; goto delmaster_out; } - rc = sqlite3OsRead(&master, zMasterJournal, nMasterJournal); + rc = sqlite3OsRead(master, zMasterJournal, nMasterJournal); if( rc!=SQLITE_OK ) goto delmaster_out; zJournal = zMasterJournal; @@ -1118,16 +1094,15 @@ static int pager_delmaster(const char *zMaster){ ** Open it and check if it points at the master journal. If ** so, return without deleting the master journal file. */ - OsFile journal; + OsFile *journal = 0; int c; - memset(&journal, 0, sizeof(journal)); rc = sqlite3OsOpenReadOnly(zJournal, &journal); if( rc!=SQLITE_OK ){ goto delmaster_out; } - rc = readMasterJournal(&journal, &zMasterPtr); + rc = readMasterJournal(journal, &zMasterPtr); sqlite3OsClose(&journal); if( rc!=SQLITE_OK ){ goto delmaster_out; @@ -1172,9 +1147,9 @@ static int pager_reload_cache(Pager *pPager){ char zBuf[SQLITE_MAX_PAGE_SIZE]; if( !pPg->dirty ) continue; if( (int)pPg->pgno <= pPager->origDbSize ){ - rc = sqlite3OsSeek(&pPager->fd, pPager->pageSize*(i64)(pPg->pgno-1)); + rc = sqlite3OsSeek(pPager->fd, pPager->pageSize*(i64)(pPg->pgno-1)); if( rc==SQLITE_OK ){ - rc = sqlite3OsRead(&pPager->fd, zBuf, pPager->pageSize); + rc = sqlite3OsRead(pPager->fd, zBuf, pPager->pageSize); } TRACE3("REFETCH %d page %d\n", PAGERID(pPager), pPg->pgno); if( rc ) break; @@ -1205,7 +1180,7 @@ static int pager_reload_cache(Pager *pPager){ */ static int pager_truncate(Pager *pPager, int nPage){ assert( pPager->state>=PAGER_EXCLUSIVE ); - return sqlite3OsTruncate(&pPager->fd, pPager->pageSize*(i64)nPage); + return sqlite3OsTruncate(pPager->fd, pPager->pageSize*(i64)nPage); } /* @@ -1273,7 +1248,7 @@ static int pager_playback(Pager *pPager){ ** the journal is empty. */ assert( pPager->journalOpen ); - rc = sqlite3OsFileSize(&pPager->jfd, &szJ); + rc = sqlite3OsFileSize(pPager->jfd, &szJ); if( rc!=SQLITE_OK ){ goto end_playback; } @@ -1283,7 +1258,7 @@ static int pager_playback(Pager *pPager){ ** present on disk, then the journal is not hot and does not need to be ** played back. */ - rc = readMasterJournal(&pPager->jfd, &zMaster); + rc = readMasterJournal(pPager->jfd, &zMaster); assert( rc!=SQLITE_DONE ); if( rc!=SQLITE_OK || (zMaster && !sqlite3OsFileExists(zMaster)) ){ sqliteFree(zMaster); @@ -1291,7 +1266,7 @@ static int pager_playback(Pager *pPager){ if( rc==SQLITE_DONE ) rc = SQLITE_OK; goto end_playback; } - sqlite3OsSeek(&pPager->jfd, 0); + sqlite3OsSeek(pPager->jfd, 0); pPager->journalOff = 0; /* This loop terminates either when the readJournalHdr() call returns @@ -1334,13 +1309,13 @@ static int pager_playback(Pager *pPager){ pPager->dbSize = mxPg; } - /* rc = sqlite3OsSeek(&pPager->jfd, JOURNAL_HDR_SZ(pPager)); */ + /* rc = sqlite3OsSeek(pPager->jfd, JOURNAL_HDR_SZ(pPager)); */ if( rc!=SQLITE_OK ) goto end_playback; /* Copy original pages out of the journal and back into the database file. */ for(i=0; ijfd, 1); + rc = pager_playback_one_page(pPager, pPager->jfd, 1); if( rc!=SQLITE_OK ){ if( rc==SQLITE_DONE ){ rc = SQLITE_OK; @@ -1407,7 +1382,7 @@ static int pager_stmt_playback(Pager *pPager){ #ifndef NDEBUG { i64 os_szJ; - rc = sqlite3OsFileSize(&pPager->jfd, &os_szJ); + rc = sqlite3OsFileSize(pPager->jfd, &os_szJ); if( rc!=SQLITE_OK ) return rc; assert( szJ==os_szJ ); } @@ -1433,7 +1408,7 @@ static int pager_stmt_playback(Pager *pPager){ /* Figure out how many records are in the statement journal. */ assert( pPager->stmtInUse && pPager->journalOpen ); - sqlite3OsSeek(&pPager->stfd, 0); + sqlite3OsSeek(pPager->stfd, 0); nRec = pPager->stmtNRec; /* Copy original pages out of the statement journal and back into the @@ -1442,7 +1417,7 @@ static int pager_stmt_playback(Pager *pPager){ ** journals. */ for(i=nRec-1; i>=0; i--){ - rc = pager_playback_one_page(pPager, &pPager->stfd, 0); + rc = pager_playback_one_page(pPager, pPager->stfd, 0); assert( rc!=SQLITE_DONE ); if( rc!=SQLITE_OK ) goto end_stmt_playback; } @@ -1455,7 +1430,7 @@ static int pager_stmt_playback(Pager *pPager){ ** If it is not zero, then Pager.stmtHdrOff is the offset to the start ** of the first journal header written during this statement transaction. */ - rc = sqlite3OsSeek(&pPager->jfd, pPager->stmtJSize); + rc = sqlite3OsSeek(pPager->jfd, pPager->stmtJSize); if( rc!=SQLITE_OK ){ goto end_stmt_playback; } @@ -1463,24 +1438,24 @@ static int pager_stmt_playback(Pager *pPager){ pPager->cksumInit = pPager->stmtCksum; assert( JOURNAL_HDR_SZ(pPager)<(pPager->pageSize+8) ); while( pPager->journalOff <= (hdrOff-(pPager->pageSize+8)) ){ - rc = pager_playback_one_page(pPager, &pPager->jfd, 1); + rc = pager_playback_one_page(pPager, pPager->jfd, 1); assert( rc!=SQLITE_DONE ); if( rc!=SQLITE_OK ) goto end_stmt_playback; } while( pPager->journalOff < szJ ){ - u32 nRec; + u32 nJRec; /* Number of Journal Records */ u32 dummy; - rc = readJournalHdr(pPager, szJ, &nRec, &dummy); + rc = readJournalHdr(pPager, szJ, &nJRec, &dummy); if( rc!=SQLITE_OK ){ assert( rc!=SQLITE_DONE ); goto end_stmt_playback; } - if( nRec==0 ){ - nRec = (szJ - pPager->journalOff) / (pPager->pageSize+8); + if( nJRec==0 ){ + nJRec = (szJ - pPager->journalOff) / (pPager->pageSize+8); } - for(i=nRec-1; i>=0 && pPager->journalOff < szJ; i--){ - rc = pager_playback_one_page(pPager, &pPager->jfd, 1); + for(i=nJRec-1; i>=0 && pPager->journalOff < szJ; i--){ + rc = pager_playback_one_page(pPager, pPager->jfd, 1); assert( rc!=SQLITE_DONE ); if( rc!=SQLITE_OK ) goto end_stmt_playback; } @@ -1489,10 +1464,7 @@ static int pager_stmt_playback(Pager *pPager){ pPager->journalOff = szJ; end_stmt_playback: - if( rc!=SQLITE_OK ){ - pPager->errMask |= PAGER_ERR_CORRUPT; - rc = SQLITE_CORRUPT; - }else{ + if( rc==SQLITE_OK) { pPager->journalOff = szJ; /* pager_reload_cache(pPager); */ } @@ -1560,14 +1532,14 @@ int sqlite3_opentemp_count = 0; ** The OS will automatically delete the temporary file when it is ** closed. */ -static int sqlite3pager_opentemp(char *zFile, OsFile *fd){ +static int sqlite3pager_opentemp(char *zFile, OsFile **pFd){ int cnt = 8; int rc; sqlite3_opentemp_count++; /* Used for testing and analysis only */ do{ cnt--; sqlite3OsTempFileName(zFile); - rc = sqlite3OsOpenExclusive(zFile, fd, 1); + rc = sqlite3OsOpenExclusive(zFile, pFd, 1); }while( cnt>0 && rc!=SQLITE_OK && rc!=SQLITE_NOMEM ); return rc; } @@ -1592,10 +1564,10 @@ int sqlite3pager_open( int nExtra, /* Extra bytes append to each in-memory page */ int flags /* flags controlling this file */ ){ - Pager *pPager; + Pager *pPager = 0; char *zFullPathname = 0; - int nameLen; - OsFile fd; + int nameLen; /* Compiler is wrong. This is always initialized before use */ + OsFile *fd; int rc = SQLITE_OK; int i; int tempFile = 0; @@ -1604,18 +1576,36 @@ int sqlite3pager_open( int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; int noReadlock = (flags & PAGER_NO_READLOCK)!=0; char zTemp[SQLITE_TEMPNAME_SIZE]; +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + /* A malloc() cannot fail in sqlite3ThreadData() as one or more calls to + ** malloc() must have already been made by this thread before it gets + ** to this point. This means the ThreadData must have been allocated already + ** so that ThreadData.nAlloc can be set. It would be nice to assert + ** that ThreadData.nAlloc is non-zero, but alas this breaks test cases + ** written to invoke the pager directly. + */ + ThreadData *pTsd = sqlite3ThreadData(); + assert( pTsd ); +#endif + /* If malloc() has already failed return SQLITE_NOMEM. Before even + ** testing for this, set *ppPager to NULL so the caller knows the pager + ** structure was never allocated. + */ *ppPager = 0; - memset(&fd, 0, sizeof(fd)); - if( sqlite3_malloc_failed ){ + if( sqlite3MallocFailed() ){ return SQLITE_NOMEM; } + memset(&fd, 0, sizeof(fd)); + + /* Open the pager file and set zFullPathname to point at malloc()ed + ** memory containing the complete filename (i.e. including the directory). + */ if( zFilename && zFilename[0] ){ #ifndef SQLITE_OMIT_MEMORYDB if( strcmp(zFilename,":memory:")==0 ){ memDb = 1; zFullPathname = sqliteStrDup(""); - rc = SQLITE_OK; }else #endif { @@ -1632,66 +1622,75 @@ int sqlite3pager_open( tempFile = 1; } } - if( !zFullPathname ){ - sqlite3OsClose(&fd); - return SQLITE_NOMEM; + + /* Allocate the Pager structure. As part of the same allocation, allocate + ** space for the full paths of the file, directory and journal + ** (Pager.zFilename, Pager.zDirectory and Pager.zJournal). + */ + if( zFullPathname ){ + nameLen = strlen(zFullPathname); + pPager = sqliteMalloc( sizeof(*pPager) + nameLen*3 + 30 ); } - if( rc!=SQLITE_OK ){ + + /* If an error occured in either of the blocks above, free the memory + ** pointed to by zFullPathname, free the Pager structure and close the + ** file. Since the pager is not allocated there is no need to set + ** any Pager.errMask variables. + */ + if( !pPager || !zFullPathname || rc!=SQLITE_OK ){ sqlite3OsClose(&fd); sqliteFree(zFullPathname); - return rc; - } - nameLen = strlen(zFullPathname); - pPager = sqliteMalloc( sizeof(*pPager) + nameLen*3 + 30 ); - if( pPager==0 ){ - sqlite3OsClose(&fd); - sqliteFree(zFullPathname); - return SQLITE_NOMEM; + sqliteFree(pPager); + return ((rc==SQLITE_OK)?SQLITE_NOMEM:rc); } + 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]; strcpy(pPager->zFilename, zFullPathname); strcpy(pPager->zDirectory, zFullPathname); + for(i=nameLen; i>0 && pPager->zDirectory[i-1]!='/'; i--){} if( i>0 ) pPager->zDirectory[i-1] = 0; strcpy(pPager->zJournal, zFullPathname); sqliteFree(zFullPathname); strcpy(&pPager->zJournal[nameLen], "-journal"); pPager->fd = fd; -#if OS_UNIX - pPager->fd.pPager = pPager; -#endif - pPager->journalOpen = 0; + /* pPager->journalOpen = 0; */ pPager->useJournal = useJournal && !memDb; pPager->noReadlock = noReadlock && readOnly; - pPager->stmtOpen = 0; - pPager->stmtInUse = 0; - pPager->nRef = 0; + /* pPager->stmtOpen = 0; */ + /* pPager->stmtInUse = 0; */ + /* pPager->nRef = 0; */ pPager->dbSize = memDb-1; pPager->pageSize = SQLITE_DEFAULT_PAGE_SIZE; - pPager->stmtSize = 0; - pPager->stmtJSize = 0; - pPager->nPage = 0; - pPager->nMaxPage = 0; + /* pPager->stmtSize = 0; */ + /* pPager->stmtJSize = 0; */ + /* pPager->nPage = 0; */ + /* pPager->nMaxPage = 0; */ pPager->mxPage = 100; - pPager->state = PAGER_UNLOCK; - pPager->errMask = 0; + assert( PAGER_UNLOCK==0 ); + /* pPager->state = PAGER_UNLOCK; */ + /* pPager->errMask = 0; */ pPager->tempFile = tempFile; pPager->memDb = memDb; pPager->readOnly = readOnly; - pPager->needSync = 0; + /* pPager->needSync = 0; */ pPager->noSync = pPager->tempFile || !useJournal; pPager->fullSync = (pPager->noSync?0:1); - pPager->pFirst = 0; - pPager->pFirstSynced = 0; - pPager->pLast = 0; + /* pPager->pFirst = 0; */ + /* pPager->pFirstSynced = 0; */ + /* pPager->pLast = 0; */ pPager->nExtra = FORCE_ALIGNMENT(nExtra); pPager->sectorSize = PAGER_SECTOR_SIZE; - pPager->pBusyHandler = 0; - memset(pPager->aHash, 0, sizeof(pPager->aHash)); + /* pPager->pBusyHandler = 0; */ + /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */ *ppPager = pPager; +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + pPager->pNext = pTsd->pPager; + pTsd->pPager = pPager; +#endif return SQLITE_OK; } @@ -1738,15 +1737,51 @@ int sqlite3pager_set_pagesize(Pager *pPager, int pageSize){ return pPager->pageSize; } +/* +** The following set of routines are used to disable the simulated +** I/O error mechanism. These routines are used to avoid simulated +** errors in places where we do not care about errors. +** +** Unless -DSQLITE_TEST=1 is used, these routines are all no-ops +** and generate no code. +*/ +#ifdef SQLITE_TEST +extern int sqlite3_io_error_pending; +extern int sqlite3_io_error_hit; +static int saved_cnt; +void clear_simulated_io_error(){ + sqlite3_io_error_hit = 0; +} +void disable_simulated_io_errors(void){ + saved_cnt = sqlite3_io_error_pending; + sqlite3_io_error_pending = -1; +} +void enable_simulated_io_errors(void){ + sqlite3_io_error_pending = saved_cnt; +} +#else +# define clear_simulated_io_error() +# define disable_simulated_io_errors() +# define enable_simulated_io_errors() +#endif + /* ** Read the first N bytes from the beginning of the file into memory -** that pDest points to. No error checking is done. +** that pDest points to. +** +** No error checking is done. The rational for this is that this function +** may be called even if the file does not exist or contain a header. In +** these cases sqlite3OsRead() will return an error, to which the correct +** response is to zero the memory at pDest and continue. A real IO error +** will presumably recur and be picked up later (Todo: Think about this). */ void sqlite3pager_read_fileheader(Pager *pPager, int N, unsigned char *pDest){ memset(pDest, 0, N); if( MEMDB==0 ){ - sqlite3OsSeek(&pPager->fd, 0); - sqlite3OsRead(&pPager->fd, pDest, N); + disable_simulated_io_errors(); + sqlite3OsSeek(pPager->fd, 0); + sqlite3OsRead(pPager->fd, pDest, N); + enable_simulated_io_errors(); } } @@ -1765,8 +1800,8 @@ int sqlite3pager_pagecount(Pager *pPager){ if( pPager->dbSize>=0 ){ n = pPager->dbSize; } else { - if( sqlite3OsFileSize(&pPager->fd, &n)!=SQLITE_OK ){ - pPager->errMask |= PAGER_ERR_DISK; + if( sqlite3OsFileSize(pPager->fd, &n)!=SQLITE_OK ){ + pager_error(pPager, SQLITE_IOERR); return 0; } if( n>0 && npageSize ){ @@ -1897,7 +1932,7 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){ rc = SQLITE_OK; }else{ do { - rc = sqlite3OsLock(&pPager->fd, locktype); + rc = sqlite3OsLock(pPager->fd, locktype); }while( rc==SQLITE_BUSY && sqlite3InvokeBusyHandler(pPager->pBusyHandler) ); if( rc==SQLITE_OK ){ pPager->state = locktype; @@ -1912,8 +1947,8 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){ int sqlite3pager_truncate(Pager *pPager, Pgno nPage){ int rc; sqlite3pager_pagecount(pPager); - if( pPager->errMask!=0 ){ - rc = pager_errcode(pPager); + if( pPager->errCode ){ + rc = pPager->errCode; return rc; } if( nPage>=(unsigned)pPager->dbSize ){ @@ -1950,9 +1985,25 @@ int sqlite3pager_truncate(Pager *pPager, Pgno nPage){ ** and their memory is freed. Any attempt to use a page associated ** with this page cache after this function returns will likely ** result in a coredump. +** +** This function always succeeds. If a transaction is active an attempt +** is made to roll it back. If an error occurs during the rollback +** a hot journal may be left in the filesystem but no error is returned +** to the caller. */ int sqlite3pager_close(Pager *pPager){ PgHdr *pPg, *pNext; +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + /* A malloc() cannot fail in sqlite3ThreadData() as one or more calls to + ** malloc() must have already been made by this thread before it gets + ** to this point. This means the ThreadData must have been allocated already + ** so that ThreadData.nAlloc can be set. + */ + ThreadData *pTsd = sqlite3ThreadData(); + assert( pPager ); + assert( pTsd && pTsd->nAlloc ); +#endif + switch( pPager->state ){ case PAGER_RESERVED: case PAGER_SYNCED: @@ -1961,24 +2012,18 @@ int sqlite3pager_close(Pager *pPager){ ** 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 + disable_simulated_io_errors(); sqlite3pager_rollback(pPager); -#if defined(SQLITE_TEST) && (defined(OS_UNIX) || defined(OS_WIN)) - sqlite3_io_error_pending = ioerr_cnt; -#endif + enable_simulated_io_errors(); if( !MEMDB ){ - sqlite3OsUnlock(&pPager->fd, NO_LOCK); + sqlite3OsUnlock(pPager->fd, NO_LOCK); } - assert( pPager->errMask || pPager->journalOpen==0 ); + assert( pPager->errCode || pPager->journalOpen==0 ); break; } case PAGER_SHARED: { if( !MEMDB ){ - sqlite3OsUnlock(&pPager->fd, NO_LOCK); + sqlite3OsUnlock(pPager->fd, NO_LOCK); } break; } @@ -2000,7 +2045,7 @@ int sqlite3pager_close(Pager *pPager){ sqliteFree(pPg); } TRACE2("CLOSE %d\n", PAGERID(pPager)); - assert( pPager->errMask || (pPager->journalOpen==0 && pPager->stmtOpen==0) ); + assert( pPager->errCode || (pPager->journalOpen==0 && pPager->stmtOpen==0) ); if( pPager->journalOpen ){ sqlite3OsClose(&pPager->jfd); } @@ -2015,6 +2060,19 @@ int sqlite3pager_close(Pager *pPager){ ** } */ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + /* Remove the pager from the linked list of pagers starting at + ** ThreadData.pPager if memory-management is enabled. + */ + if( pPager==pTsd->pPager ){ + pTsd->pPager = pPager->pNext; + }else{ + Pager *pTmp; + for(pTmp = pTsd->pPager; pTmp->pNext!=pPager; pTmp=pTmp->pNext); + pTmp->pNext = pPager->pNext; + } +#endif + sqliteFree(pPager); return SQLITE_OK; } @@ -2120,7 +2178,7 @@ static int syncJournal(Pager *pPager){ ** with the nRec computed from the size of the journal file. */ i64 jSz; - rc = sqlite3OsFileSize(&pPager->jfd, &jSz); + rc = sqlite3OsFileSize(pPager->jfd, &jSz); if( rc!=0 ) return rc; assert( pPager->journalOff==jSz ); } @@ -2133,20 +2191,20 @@ static int syncJournal(Pager *pPager){ */ if( pPager->fullSync ){ TRACE2("SYNC journal of %d\n", PAGERID(pPager)); - rc = sqlite3OsSync(&pPager->jfd, 0); + rc = sqlite3OsSync(pPager->jfd, 0); if( rc!=0 ) return rc; } - rc = sqlite3OsSeek(&pPager->jfd, + rc = sqlite3OsSeek(pPager->jfd, pPager->journalHdr + sizeof(aJournalMagic)); if( rc ) return rc; - rc = write32bits(&pPager->jfd, pPager->nRec); + rc = write32bits(pPager->jfd, pPager->nRec); if( rc ) return rc; - rc = sqlite3OsSeek(&pPager->jfd, pPager->journalOff); + rc = sqlite3OsSeek(pPager->jfd, pPager->journalOff); if( rc ) return rc; } TRACE2("SYNC journal of %d\n", PAGERID(pPager)); - rc = sqlite3OsSync(&pPager->jfd, pPager->fullSync); + rc = sqlite3OsSync(pPager->jfd, pPager->fullSync); if( rc!=0 ) return rc; pPager->journalStarted = 1; } @@ -2211,7 +2269,7 @@ static int pager_write_pagelist(PgHdr *pList){ while( pList ){ assert( pList->dirty ); - rc = sqlite3OsSeek(&pPager->fd, (pList->pgno-1)*(i64)pPager->pageSize); + rc = sqlite3OsSeek(pPager->fd, (pList->pgno-1)*(i64)pPager->pageSize); if( rc ) return rc; /* If there are dirty pages in the page cache with page numbers greater ** than Pager.dbSize, this means sqlite3pager_truncate() was called to @@ -2221,7 +2279,8 @@ static int pager_write_pagelist(PgHdr *pList){ 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); + rc = sqlite3OsWrite(pPager->fd, PGHDR_TO_DATA(pList), + pPager->pageSize); CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 0); TEST_INCR(pPager->nWrite); } @@ -2268,7 +2327,7 @@ static PgHdr *pager_get_all_dirty_pages(Pager *pPager){ static int hasHotJournal(Pager *pPager){ if( !pPager->useJournal ) return 0; if( !sqlite3OsFileExists(pPager->zJournal) ) return 0; - if( sqlite3OsCheckReservedLock(&pPager->fd) ) return 0; + if( sqlite3OsCheckReservedLock(pPager->fd) ) return 0; if( sqlite3pager_pagecount(pPager)==0 ){ sqlite3OsDelete(pPager->zJournal); return 0; @@ -2277,6 +2336,170 @@ static int hasHotJournal(Pager *pPager){ } } +/* +** Try to find a page in the cache that can be recycled. +** +** This routine may return SQLITE_IOERR, SQLITE_FULL or SQLITE_OK. It +** does not set the pPager->errCode variable. +*/ +static int pager_recycle(Pager *pPager, int syncOk, PgHdr **ppPg){ + PgHdr *pPg; + *ppPg = 0; + + /* Find a page to recycle. Try to locate a page that does not + ** require us to do an fsync() on the journal. + */ + pPg = pPager->pFirstSynced; + + /* If we could not find a page that does not require an fsync() + ** on the journal file then fsync the journal file. This is a + ** very slow operation, so we work hard to avoid it. But sometimes + ** it can't be helped. + */ + if( pPg==0 && pPager->pFirst && syncOk && !MEMDB){ + int rc = syncJournal(pPager); + if( rc!=0 ){ + return rc; + } + if( pPager->fullSync ){ + /* If in full-sync mode, write a new journal header into the + ** journal file. This is done to avoid ever modifying a journal + ** header that is involved in the rollback of pages that have + ** already been written to the database (in case the header is + ** trashed when the nRec field is updated). + */ + pPager->nRec = 0; + assert( pPager->journalOff > 0 ); + rc = writeJournalHdr(pPager); + if( rc!=0 ){ + return rc; + } + } + pPg = pPager->pFirst; + } + if( pPg==0 ){ + return SQLITE_OK; + } + + assert( pPg->nRef==0 ); + + /* Write the page to the database file if it is dirty. + */ + if( pPg->dirty ){ + int rc; + assert( pPg->needSync==0 ); + pPg->pDirty = 0; + rc = pager_write_pagelist( pPg ); + if( rc!=SQLITE_OK ){ + return rc; + } + } + assert( pPg->dirty==0 ); + + /* If the page we are recycling is marked as alwaysRollback, then + ** set the global alwaysRollback flag, thus disabling the + ** sqlite_dont_rollback() optimization for the rest of this transaction. + ** It is necessary to do this because the page marked alwaysRollback + ** might be reloaded at a later time but at that point we won't remember + ** that is was marked alwaysRollback. This means that all pages must + ** be marked as alwaysRollback from here on out. + */ + if( pPg->alwaysRollback ){ + pPager->alwaysRollback = 1; + } + + /* Unlink the old page from the free list and the hash table + */ + unlinkPage(pPg); + TEST_INCR(pPager->nOvfl); + + *ppPg = pPg; + return SQLITE_OK; +} + +/* +** This function is called to free superfluous dynamically allocated memory +** held by the pager system. Memory in use by any SQLite pager allocated +** by the current thread may be sqliteFree()ed. +** +** nReq is the number of bytes of memory required. Once this much has +** been released, the function returns. A negative value for nReq means +** free as much memory as possible. The return value is the total number +** of bytes of memory released. +*/ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +int sqlite3pager_release_memory(int nReq){ + const ThreadData *pTsdro = sqlite3ThreadDataReadOnly(); + Pager *p; + int nReleased = 0; + int i; + + /* If the the global mutex is held, this subroutine becomes a + ** o-op; zero bytes of memory are freed. This is because + ** some of the code invoked by this function may also + ** try to obtain the mutex, resulting in a deadlock. + */ + if( sqlite3OsInMutex(0) ){ + return 0; + } + + /* Outermost loop runs for at most two iterations. First iteration we + ** try to find memory that can be released without calling fsync(). Second + ** iteration (which only runs if the first failed to free nReq bytes of + ** memory) is permitted to call fsync(). This is of course much more + ** expensive. + */ + for(i=0; i<=1; i++){ + + /* Loop through all the SQLite pagers opened by the current thread. */ + for(p=pTsdro->pPager; p && (nReq<0 || nReleasedpNext){ + PgHdr *pPg; + int rc; + + /* For each pager, try to free as many pages as possible (without + ** calling fsync() if this is the first iteration of the outermost + ** loop). + */ + while( SQLITE_OK==(rc = pager_recycle(p, i, &pPg)) && pPg) { + /* We've found a page to free. At this point the page has been + ** removed from the page hash-table, free-list and synced-list + ** (pFirstSynced). It is still in the all pages (pAll) list. + ** Remove it from this list before freeing. + ** + ** Todo: Check the Pager.pStmt list to make sure this is Ok. It + ** probably is though. + */ + PgHdr *pTmp; + assert( pPg ); + page_remove_from_stmt_list(pPg); + if( pPg==p->pAll ){ + p->pAll = pPg->pNextAll; + }else{ + for( pTmp=p->pAll; pTmp->pNextAll!=pPg; pTmp=pTmp->pNextAll ); + pTmp->pNextAll = pPg->pNextAll; + } + nReleased += sqliteAllocSize(pPg); + sqliteFree(pPg); + } + + if( rc!=SQLITE_OK ){ + /* An error occured whilst writing to the database file or + ** journal in pager_recycle(). The error is not returned to the + ** caller of this function. Instead, set the Pager.errCode variable. + ** The error will be returned to the user (or users, in the case + ** of a shared pager cache) of the pager for which the error occured. + */ + assert( rc==SQLITE_IOERR || rc==SQLITE_FULL ); + assert( p->state>=PAGER_RESERVED ); + pager_error(p, rc); + } + } + } + + return nReleased; +} +#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */ + /* ** Acquire a page. ** @@ -2315,8 +2538,8 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ */ assert( pPager!=0 ); *ppPage = 0; - if( pPager->errMask & ~(PAGER_ERR_FULL) ){ - return pager_errcode(pPager); + if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ + return pPager->errCode; } /* If this is the first page accessed, then get a SHARED lock @@ -2326,7 +2549,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ if( !pPager->noReadlock ){ rc = pager_wait_on_lock(pPager, SHARED_LOCK); if( rc!=SQLITE_OK ){ - return rc; + return pager_error(pPager, rc); } } @@ -2334,8 +2557,6 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ ** database file, then it either needs to be played back or deleted. */ if( hasHotJournal(pPager) ){ - int rc; - /* Get an EXCLUSIVE lock on the database file. At this point it is ** important that a RESERVED lock is not obtained on the way to the ** EXCLUSIVE lock. If it were, another process might open the @@ -2347,11 +2568,11 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ ** second process will get to this point in the code and fail to ** obtain it's own EXCLUSIVE lock on the database file. */ - rc = sqlite3OsLock(&pPager->fd, EXCLUSIVE_LOCK); + rc = sqlite3OsLock(pPager->fd, EXCLUSIVE_LOCK); if( rc!=SQLITE_OK ){ - sqlite3OsUnlock(&pPager->fd, NO_LOCK); + sqlite3OsUnlock(pPager->fd, NO_LOCK); pPager->state = PAGER_UNLOCK; - return rc; + return pager_error(pPager, rc); } pPager->state = PAGER_EXCLUSIVE; @@ -2365,7 +2586,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ */ rc = sqlite3OsOpenReadOnly(pPager->zJournal, &pPager->jfd); if( rc!=SQLITE_OK ){ - sqlite3OsUnlock(&pPager->fd, NO_LOCK); + sqlite3OsUnlock(pPager->fd, NO_LOCK); pPager->state = PAGER_UNLOCK; return SQLITE_BUSY; } @@ -2380,7 +2601,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ */ rc = pager_playback(pPager); if( rc!=SQLITE_OK ){ - return rc; + return pager_error(pPager, rc); } } pPg = 0; @@ -2401,7 +2622,6 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ + sizeof(u32) + pPager->nExtra + MEMDB*sizeof(PgHistory) ); if( pPg==0 ){ - pPager->errMask |= PAGER_ERR_MEM; return SQLITE_NOMEM; } memset(pPg, 0, sizeof(*pPg)); @@ -2417,70 +2637,11 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ pPager->nMaxPage++; } }else{ - /* Find a page to recycle. Try to locate a page that does not - ** require us to do an fsync() on the journal. - */ - pPg = pPager->pFirstSynced; - - /* If we could not find a page that does not require an fsync() - ** on the journal file then fsync the journal file. This is a - ** very slow operation, so we work hard to avoid it. But sometimes - ** it can't be helped. - */ - if( pPg==0 ){ - int rc = syncJournal(pPager); - if( rc!=0 ){ - sqlite3pager_rollback(pPager); - return SQLITE_IOERR; - } - if( pPager->fullSync ){ - /* If in full-sync mode, write a new journal header into the - ** journal file. This is done to avoid ever modifying a journal - ** header that is involved in the rollback of pages that have - ** already been written to the database (in case the header is - ** trashed when the nRec field is updated). - */ - pPager->nRec = 0; - assert( pPager->journalOff > 0 ); - rc = writeJournalHdr(pPager); - if( rc!=0 ){ - sqlite3pager_rollback(pPager); - return SQLITE_IOERR; - } - } - pPg = pPager->pFirst; + rc = pager_recycle(pPager, 1, &pPg); + if( rc!=SQLITE_OK ){ + return rc; } - assert( pPg->nRef==0 ); - - /* Write the page to the database file if it is dirty. - */ - if( pPg->dirty ){ - assert( pPg->needSync==0 ); - pPg->pDirty = 0; - rc = pager_write_pagelist( pPg ); - if( rc!=SQLITE_OK ){ - sqlite3pager_rollback(pPager); - return SQLITE_IOERR; - } - } - assert( pPg->dirty==0 ); - - /* If the page we are recycling is marked as alwaysRollback, then - ** set the global alwaysRollback flag, thus disabling the - ** sqlite_dont_rollback() optimization for the rest of this transaction. - ** It is necessary to do this because the page marked alwaysRollback - ** might be reloaded at a later time but at that point we won't remember - ** that is was marked alwaysRollback. This means that all pages must - ** be marked as alwaysRollback from here on out. - */ - if( pPg->alwaysRollback ){ - pPager->alwaysRollback = 1; - } - - /* Unlink the old page from the free list and the hash table - */ - unlinkPage(pPg); - TEST_INCR(pPager->nOvfl); + assert(pPg) ; } pPg->pgno = pgno; if( pPager->aInJournal && (int)pgno<=pPager->origDbSize ){ @@ -2501,7 +2662,50 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ pPg->dirty = 0; pPg->nRef = 1; REFINFO(pPg); + pPager->nRef++; + if( pPager->nExtra>0 ){ + memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra); + } + if( pPager->errCode ){ + sqlite3pager_unref(PGHDR_TO_DATA(pPg)); + rc = pPager->errCode; + return rc; + } + + /* Populate the page with data, either by reading from the database + ** file, or by setting the entire page to zero. + */ + if( sqlite3pager_pagecount(pPager)<(int)pgno || MEMDB ){ + memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); + }else{ + assert( MEMDB==0 ); + rc = sqlite3OsSeek(pPager->fd, (pgno-1)*(i64)pPager->pageSize); + if( rc==SQLITE_OK ){ + rc = sqlite3OsRead(pPager->fd, PGHDR_TO_DATA(pPg), + pPager->pageSize); + } + 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; + int rc2 = sqlite3OsFileSize(pPager->fd, &fileSize); + if( rc2!=SQLITE_OK || fileSize>=pgno*pPager->pageSize ){ + /* An IO error occured in one of the the sqlite3OsSeek() or + ** sqlite3OsRead() calls above. */ + pPg->pgno = 0; + sqlite3pager_unref(PGHDR_TO_DATA(pPg)); + return rc; + }else{ + clear_simulated_io_error(); + memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); + } + }else{ + TEST_INCR(pPager->nRead); + } + } + + /* Link the page into the page hash table */ h = pager_hash(pgno); pPg->pNextHash = pPager->aHash[h]; pPager->aHash[h] = pPg; @@ -2509,38 +2713,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ assert( pPg->pNextHash->pPrevHash==0 ); pPg->pNextHash->pPrevHash = pPg; } - if( pPager->nExtra>0 ){ - memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra); - } - if( pPager->errMask!=0 ){ - sqlite3pager_unref(PGHDR_TO_DATA(pPg)); - rc = pager_errcode(pPager); - return rc; - } - if( sqlite3pager_pagecount(pPager)<(int)pgno ){ - memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); - }else{ - int rc; - assert( MEMDB==0 ); - rc = sqlite3OsSeek(&pPager->fd, (pgno-1)*(i64)pPager->pageSize); - if( rc==SQLITE_OK ){ - rc = sqlite3OsRead(&pPager->fd, PGHDR_TO_DATA(pPg), pPager->pageSize); - } - 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; - if( sqlite3OsFileSize(&pPager->fd,&fileSize)!=SQLITE_OK - || fileSize>=pgno*pPager->pageSize ){ - sqlite3pager_unref(PGHDR_TO_DATA(pPg)); - return rc; - }else{ - memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); - } - }else{ - TEST_INCR(pPager->nRead); - } - } + #ifdef SQLITE_CHECK_PAGES pPg->pageHash = pager_pagehash(pPg); #endif @@ -2569,7 +2742,7 @@ void *sqlite3pager_lookup(Pager *pPager, Pgno pgno){ assert( pPager!=0 ); assert( pgno!=0 ); - if( pPager->errMask & ~(PAGER_ERR_FULL) ){ + if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ return 0; } pPg = pager_lookup(pPager, pgno); @@ -2651,23 +2824,24 @@ static int pager_open_journal(Pager *pPager){ rc = SQLITE_NOMEM; goto failed_to_open_journal; } - rc = sqlite3OsOpenExclusive(pPager->zJournal, &pPager->jfd,pPager->tempFile); + rc = sqlite3OsOpenExclusive(pPager->zJournal, &pPager->jfd, + pPager->tempFile); pPager->journalOff = 0; pPager->setMaster = 0; pPager->journalHdr = 0; if( rc!=SQLITE_OK ){ goto failed_to_open_journal; } - SET_FULLSYNC(pPager->jfd, pPager->fullSync); - SET_FULLSYNC(pPager->fd, pPager->fullSync); - sqlite3OsOpenDirectory(pPager->zDirectory, &pPager->jfd); + sqlite3OsSetFullSync(pPager->jfd, pPager->fullSync); + sqlite3OsSetFullSync(pPager->fd, pPager->fullSync); + sqlite3OsOpenDirectory(pPager->jfd, pPager->zDirectory); pPager->journalOpen = 1; pPager->journalStarted = 0; pPager->needSync = 0; pPager->alwaysRollback = 0; pPager->nRec = 0; - if( pPager->errMask!=0 ){ - rc = pager_errcode(pPager); + if( pPager->errCode ){ + rc = pPager->errCode; goto failed_to_open_journal; } pPager->origDbSize = pPager->dbSize; @@ -2677,7 +2851,7 @@ static int pager_open_journal(Pager *pPager){ if( pPager->stmtAutoopen && rc==SQLITE_OK ){ rc = sqlite3pager_stmt_begin(pPager); } - if( rc!=SQLITE_OK ){ + if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){ rc = pager_unwritelock(pPager); if( rc==SQLITE_OK ){ rc = SQLITE_FULL; @@ -2688,8 +2862,17 @@ static int pager_open_journal(Pager *pPager){ failed_to_open_journal: sqliteFree(pPager->aInJournal); pPager->aInJournal = 0; - sqlite3OsUnlock(&pPager->fd, NO_LOCK); - pPager->state = PAGER_UNLOCK; + if( rc==SQLITE_NOMEM ){ + /* If this was a malloc() failure, then we will not be closing the pager + ** file. So delete any journal file we may have just created. Otherwise, + ** the system will get confused, we have a read-lock on the file and a + ** mysterious journal has appeared in the filesystem. + */ + sqlite3OsDelete(pPager->zJournal); + }else{ + sqlite3OsUnlock(pPager->fd, NO_LOCK); + pPager->state = PAGER_UNLOCK; + } return rc; } @@ -2732,7 +2915,7 @@ int sqlite3pager_begin(void *pData, int exFlag){ pPager->state = PAGER_EXCLUSIVE; pPager->origDbSize = pPager->dbSize; }else{ - rc = sqlite3OsLock(&pPager->fd, RESERVED_LOCK); + rc = sqlite3OsLock(pPager->fd, RESERVED_LOCK); if( rc==SQLITE_OK ){ pPager->state = PAGER_RESERVED; if( exFlag ){ @@ -2776,8 +2959,8 @@ int sqlite3pager_write(void *pData){ /* Check for errors */ - if( pPager->errMask ){ - return pager_errcode(pPager); + if( pPager->errCode ){ + return pPager->errCode; } if( pPager->readOnly ){ return SQLITE_PERM; @@ -2843,17 +3026,21 @@ int sqlite3pager_write(void *pData){ store32bits(cksum, pPg, pPager->pageSize); szPg = pPager->pageSize+8; store32bits(pPg->pgno, pPg, -4); - rc = sqlite3OsWrite(&pPager->jfd, &((char*)pData)[-4], szPg); + + 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; + + /* An error has occured writing to the journal file. The + ** transaction will be rolled back by the layer above. + */ 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); @@ -2892,12 +3079,11 @@ int sqlite3pager_write(void *pData){ }else{ store32bits(pPg->pgno, pPg, -4); CODEC(pPager, pData, pPg->pgno, 7); - rc = sqlite3OsWrite(&pPager->stfd,((char*)pData)-4, pPager->pageSize+4); + 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); if( rc!=SQLITE_OK ){ - sqlite3pager_rollback(pPager); - pPager->errMask |= PAGER_ERR_FULL; return rc; } pPager->stmtNRec++; @@ -2924,10 +3110,12 @@ int sqlite3pager_write(void *pData){ ** to sqlite3pager_write(). In other words, return TRUE if it is ok ** to change the content of the page. */ +#ifndef NDEBUG int sqlite3pager_iswriteable(void *pData){ PgHdr *pPg = DATA_TO_PGHDR(pData); return pPg->dirty; } +#endif #ifndef SQLITE_OMIT_VACUUM /* @@ -2981,7 +3169,7 @@ void sqlite3pager_dont_write(Pager *pPager, Pgno pgno){ pPg = pager_lookup(pPager, pgno); pPg->alwaysRollback = 1; - if( pPg && pPg->dirty ){ + if( pPg && pPg->dirty && !pPager->stmtInUse ){ if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSizedbSize ){ /* If this pages is the last page in the file and the file has grown ** during the current transaction, then do NOT mark the page as clean. @@ -3057,16 +3245,8 @@ int sqlite3pager_commit(Pager *pPager){ int rc; PgHdr *pPg; - if( pPager->errMask==PAGER_ERR_FULL ){ - rc = sqlite3pager_rollback(pPager); - if( rc==SQLITE_OK ){ - rc = SQLITE_FULL; - } - return rc; - } - if( pPager->errMask!=0 ){ - rc = pager_errcode(pPager); - return rc; + if( pPager->errCode ){ + return pPager->errCode; } if( pPager->statejournalOpen ); rc = sqlite3pager_sync(pPager, 0, 0); - if( rc!=SQLITE_OK ){ - goto commit_abort; + if( rc==SQLITE_OK ){ + rc = pager_unwritelock(pPager); + pPager->dbSize = -1; } - rc = pager_unwritelock(pPager); - pPager->dbSize = -1; - return rc; - - /* Jump here if anything goes wrong during the commit process. - */ -commit_abort: - sqlite3pager_rollback(pPager); return rc; } @@ -3176,11 +3349,11 @@ int sqlite3pager_rollback(Pager *pPager){ return rc; } - if( pPager->errMask!=0 && pPager->errMask!=PAGER_ERR_FULL ){ + if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ if( pPager->state>=PAGER_EXCLUSIVE ){ pager_playback(pPager); } - return pager_errcode(pPager); + return pPager->errCode; } if( pPager->state==PAGER_RESERVED ){ int rc2; @@ -3192,12 +3365,13 @@ int sqlite3pager_rollback(Pager *pPager){ }else{ rc = pager_playback(pPager); } - if( rc!=SQLITE_OK ){ - rc = SQLITE_CORRUPT_BKPT; - pPager->errMask |= PAGER_ERR_CORRUPT; - } pPager->dbSize = -1; - return rc; + + /* If an error occurs during a ROLLBACK, we can no longer trust the pager + ** cache. So call pager_error() on the way out to make any error + ** persistent. + */ + return pager_error(pPager, rc); } /* @@ -3218,7 +3392,7 @@ int *sqlite3pager_stats(Pager *pPager){ a[2] = pPager->mxPage; a[3] = pPager->dbSize; a[4] = pPager->state; - a[5] = pPager->errMask; + a[5] = pPager->errCode; #ifdef SQLITE_TEST a[6] = pPager->nHit; a[7] = pPager->nMiss; @@ -3254,11 +3428,11 @@ int sqlite3pager_stmt_begin(Pager *pPager){ assert( pPager->journalOpen ); pPager->aInStmt = sqliteMalloc( pPager->dbSize/8 + 1 ); if( pPager->aInStmt==0 ){ - sqlite3OsLock(&pPager->fd, SHARED_LOCK); + /* sqlite3OsLock(pPager->fd, SHARED_LOCK); */ return SQLITE_NOMEM; } #ifndef NDEBUG - rc = sqlite3OsFileSize(&pPager->jfd, &pPager->stmtJSize); + rc = sqlite3OsFileSize(pPager->jfd, &pPager->stmtJSize); if( rc ) goto stmt_begin_failed; assert( pPager->stmtJSize == pPager->journalOff ); #endif @@ -3291,8 +3465,8 @@ int sqlite3pager_stmt_commit(Pager *pPager){ PgHdr *pPg, *pNext; TRACE2("STMT-COMMIT %d\n", PAGERID(pPager)); if( !MEMDB ){ - sqlite3OsSeek(&pPager->stfd, 0); - /* sqlite3OsTruncate(&pPager->stfd, 0); */ + sqlite3OsSeek(pPager->stfd, 0); + /* sqlite3OsTruncate(pPager->stfd, 0); */ sqliteFree( pPager->aInStmt ); pPager->aInStmt = 0; } @@ -3495,7 +3669,7 @@ int sqlite3pager_sync(Pager *pPager, const char *zMaster, Pgno nTrunc){ /* Sync the database file. */ if( !pPager->noSync ){ - rc = sqlite3OsSync(&pPager->fd, 0); + rc = sqlite3OsSync(pPager->fd, 0); } pPager->state = PAGER_SYNCED; @@ -3609,11 +3783,7 @@ int sqlite3pager_movepage(Pager *pPager, void *pData, Pgno pgno){ ** PENDING_LOCK, or EXCLUSIVE_LOCK. */ int sqlite3pager_lockstate(Pager *pPager){ -#ifdef OS_TEST - return pPager->fd->fd.locktype; -#else - return pPager->fd.locktype; -#endif + return sqlite3OsLockState(pPager->fd); } #endif diff --git a/mozilla/db/sqlite3/src/pager.h b/mozilla/db/sqlite3/src/pager.h index f29ecac1f57..1d7069826f9 100644 --- a/mozilla/db/sqlite3/src/pager.h +++ b/mozilla/db/sqlite3/src/pager.h @@ -13,9 +13,12 @@ ** subsystem. The page cache subsystem reads and writes a file a page ** at a time and provides a journal for rollback. ** -** @(#) $Id: pager.h,v 1.46 2005/09/19 19:05:21 drh Exp $ +** @(#) $Id: pager.h,v 1.48 2005/12/19 14:18:11 danielk1977 Exp $ */ +#ifndef _PAGER_H_ +#define _PAGER_H_ + /* ** The default size of a database page. */ @@ -105,6 +108,7 @@ int sqlite3pager_rename(Pager*, const char *zNewName); void sqlite3pager_set_codec(Pager*,void(*)(void*,void*,Pgno,int),void*); int sqlite3pager_movepage(Pager*,void*,Pgno); int sqlite3pager_reset(Pager*); +int sqlite3pager_release_memory(int); #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) int sqlite3pager_lockstate(Pager*); @@ -114,3 +118,5 @@ int sqlite3pager_lockstate(Pager*); void sqlite3pager_refdump(Pager*); int pager3_refinfo_enable; #endif + +#endif /* _PAGER_H_ */ diff --git a/mozilla/db/sqlite3/src/parse.c b/mozilla/db/sqlite3/src/parse.c index 668f0012674..ac8bc0a4488 100644 --- a/mozilla/db/sqlite3/src/parse.c +++ b/mozilla/db/sqlite3/src/parse.c @@ -23,7 +23,7 @@ struct LimitVal { ** GLOB, NOT LIKE, and NOT GLOB operators. */ struct LikeOp { - Token operator; /* "like" or "glob" or "regexp" */ + Token eOperator; /* "like" or "glob" or "regexp" */ int not; /* True if the NOT keyword is present */ }; @@ -93,35 +93,35 @@ struct AttachKey { int type; Token key; }; ** defined, then do no error processing. */ #define YYCODETYPE unsigned char -#define YYNOCODE 247 +#define YYNOCODE 240 #define YYACTIONTYPE unsigned short int #define sqlite3ParserTOKENTYPE Token typedef union { sqlite3ParserTOKENTYPE yy0; - struct TrigEvent yy30; - Expr* yy62; - SrcList* yy151; - Token yy198; - struct LimitVal yy220; - struct LikeOp yy222; - IdList* yy240; - int yy280; - struct {int value; int mask;} yy359; - TriggerStep* yy360; - struct AttachKey yy361; - Select* yy375; - ExprList* yy418; - int yy493; + struct {int value; int mask;} yy13; + struct TrigEvent yy132; + IdList* yy160; + Expr* yy178; + int yy230; + Select* yy239; + TriggerStep* yy247; + struct LimitVal yy270; + SrcList* yy285; + Expr * yy292; + Token yy384; + struct LikeOp yy440; + ExprList* yy462; + int yy479; } 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 581 -#define YYNRULE 311 -#define YYERRORSYMBOL 146 -#define YYERRSYMDT yy493 +#define YYNSTATE 560 +#define YYNRULE 295 +#define YYERRORSYMBOL 137 +#define YYERRSYMDT yy479 #define YYFALLBACK 1 #define YY_NO_ACTION (YYNSTATE+YYNRULE+2) #define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1) @@ -175,485 +175,396 @@ typedef union { ** yy_default[] Default action for each state. */ static const YYACTIONTYPE yy_action[] = { - /* 0 */ 286, 584, 113, 140, 142, 138, 144, 581, 150, 152, - /* 10 */ 154, 156, 158, 160, 162, 164, 166, 168, 3, 577, - /* 20 */ 740, 170, 178, 150, 152, 154, 156, 158, 160, 162, - /* 30 */ 164, 166, 168, 158, 160, 162, 164, 166, 168, 135, - /* 40 */ 97, 171, 181, 186, 191, 180, 185, 146, 148, 140, - /* 50 */ 142, 138, 144, 51, 150, 152, 154, 156, 158, 160, - /* 60 */ 162, 164, 166, 168, 16, 17, 18, 114, 7, 248, - /* 70 */ 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, - /* 80 */ 13, 37, 362, 40, 59, 67, 69, 326, 357, 170, - /* 90 */ 6, 5, 331, 95, 364, 359, 25, 374, 258, 893, - /* 100 */ 1, 580, 514, 13, 4, 575, 33, 135, 97, 171, - /* 110 */ 181, 186, 191, 180, 185, 146, 148, 140, 142, 138, - /* 120 */ 144, 9, 150, 152, 154, 156, 158, 160, 162, 164, - /* 130 */ 166, 168, 374, 136, 592, 80, 112, 99, 269, 34, - /* 140 */ 32, 33, 132, 373, 115, 14, 15, 378, 333, 99, - /* 150 */ 380, 387, 392, 13, 367, 370, 194, 170, 78, 500, - /* 160 */ 525, 315, 395, 369, 375, 408, 10, 98, 14, 15, - /* 170 */ 78, 200, 286, 864, 113, 135, 97, 171, 181, 186, - /* 180 */ 191, 180, 185, 146, 148, 140, 142, 138, 144, 80, - /* 190 */ 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, - /* 200 */ 104, 105, 106, 661, 496, 376, 374, 170, 467, 13, - /* 210 */ 2, 28, 237, 4, 409, 33, 3, 577, 14, 15, - /* 220 */ 51, 132, 133, 115, 241, 135, 97, 171, 181, 186, - /* 230 */ 191, 180, 185, 146, 148, 140, 142, 138, 144, 114, - /* 240 */ 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, - /* 250 */ 40, 59, 67, 69, 326, 357, 136, 44, 45, 501, - /* 260 */ 473, 463, 359, 36, 361, 130, 128, 660, 275, 31, - /* 270 */ 84, 99, 356, 378, 14, 15, 380, 387, 392, 52, - /* 280 */ 170, 117, 122, 123, 113, 541, 369, 643, 395, 348, - /* 290 */ 98, 54, 78, 200, 302, 57, 58, 819, 135, 97, - /* 300 */ 171, 181, 186, 191, 180, 185, 146, 148, 140, 142, - /* 310 */ 138, 144, 861, 150, 152, 154, 156, 158, 160, 162, - /* 320 */ 164, 166, 168, 104, 105, 106, 817, 80, 48, 316, - /* 330 */ 162, 164, 166, 168, 319, 277, 12, 49, 99, 303, - /* 340 */ 283, 818, 99, 124, 304, 99, 241, 172, 593, 114, - /* 350 */ 50, 193, 46, 378, 170, 13, 380, 387, 392, 78, - /* 360 */ 260, 276, 47, 78, 200, 64, 78, 260, 395, 174, - /* 370 */ 175, 221, 135, 97, 171, 181, 186, 191, 180, 185, - /* 380 */ 146, 148, 140, 142, 138, 144, 199, 150, 152, 154, - /* 390 */ 156, 158, 160, 162, 164, 166, 168, 173, 252, 261, - /* 400 */ 120, 122, 123, 212, 170, 268, 254, 130, 128, 288, - /* 410 */ 590, 176, 246, 187, 192, 414, 195, 241, 197, 198, - /* 420 */ 14, 15, 135, 97, 171, 181, 186, 191, 180, 185, - /* 430 */ 146, 148, 140, 142, 138, 144, 433, 150, 152, 154, - /* 440 */ 156, 158, 160, 162, 164, 166, 168, 311, 99, 707, - /* 450 */ 99, 422, 708, 417, 275, 81, 318, 598, 99, 219, - /* 460 */ 13, 231, 124, 13, 176, 48, 187, 192, 20, 78, - /* 470 */ 317, 78, 214, 195, 49, 197, 198, 462, 170, 78, - /* 480 */ 200, 116, 27, 13, 410, 113, 591, 50, 80, 225, - /* 490 */ 195, 11, 197, 198, 506, 235, 135, 97, 171, 181, - /* 500 */ 186, 191, 180, 185, 146, 148, 140, 142, 138, 144, - /* 510 */ 80, 150, 152, 154, 156, 158, 160, 162, 164, 166, - /* 520 */ 168, 277, 215, 324, 606, 14, 15, 301, 14, 15, - /* 530 */ 512, 13, 508, 240, 196, 486, 195, 685, 197, 198, - /* 540 */ 22, 834, 445, 331, 462, 170, 444, 276, 14, 15, - /* 550 */ 114, 468, 278, 394, 599, 280, 470, 288, 446, 680, - /* 560 */ 13, 321, 404, 135, 97, 171, 181, 186, 191, 180, - /* 570 */ 185, 146, 148, 140, 142, 138, 144, 80, 150, 152, - /* 580 */ 154, 156, 158, 160, 162, 164, 166, 168, 74, 99, - /* 590 */ 540, 366, 73, 99, 352, 289, 14, 15, 176, 333, - /* 600 */ 187, 192, 486, 869, 359, 273, 283, 542, 543, 867, - /* 610 */ 78, 500, 510, 170, 78, 323, 682, 176, 472, 187, - /* 620 */ 192, 746, 118, 470, 119, 14, 15, 195, 346, 197, - /* 630 */ 198, 135, 97, 171, 181, 186, 191, 180, 185, 146, - /* 640 */ 148, 140, 142, 138, 144, 99, 150, 152, 154, 156, - /* 650 */ 158, 160, 162, 164, 166, 168, 532, 334, 341, 343, - /* 660 */ 841, 39, 195, 170, 197, 198, 78, 94, 124, 356, - /* 670 */ 271, 353, 439, 441, 440, 544, 883, 428, 72, 862, - /* 680 */ 288, 135, 97, 171, 181, 186, 191, 180, 185, 146, - /* 690 */ 148, 140, 142, 138, 144, 13, 150, 152, 154, 156, - /* 700 */ 158, 160, 162, 164, 166, 168, 195, 99, 197, 198, - /* 710 */ 406, 330, 195, 170, 197, 198, 568, 405, 306, 195, - /* 720 */ 42, 197, 198, 65, 195, 539, 197, 198, 78, 96, - /* 730 */ 66, 135, 97, 171, 181, 186, 191, 180, 185, 146, - /* 740 */ 148, 140, 142, 138, 144, 885, 150, 152, 154, 156, - /* 750 */ 158, 160, 162, 164, 166, 168, 99, 740, 99, 298, - /* 760 */ 14, 15, 272, 170, 13, 74, 572, 86, 600, 73, - /* 770 */ 126, 127, 614, 709, 309, 478, 24, 78, 247, 78, - /* 780 */ 111, 135, 97, 171, 181, 186, 191, 180, 185, 146, - /* 790 */ 148, 140, 142, 138, 144, 99, 150, 152, 154, 156, - /* 800 */ 158, 160, 162, 164, 166, 168, 99, 238, 113, 239, - /* 810 */ 295, 26, 296, 170, 338, 337, 78, 137, 294, 320, - /* 820 */ 347, 239, 348, 390, 211, 348, 30, 78, 139, 14, - /* 830 */ 15, 135, 189, 171, 181, 186, 191, 180, 185, 146, - /* 840 */ 148, 140, 142, 138, 144, 99, 150, 152, 154, 156, - /* 850 */ 158, 160, 162, 164, 166, 168, 99, 80, 99, 372, - /* 860 */ 399, 442, 348, 170, 298, 243, 78, 141, 363, 601, - /* 870 */ 428, 437, 438, 114, 411, 269, 605, 78, 143, 78, - /* 880 */ 145, 448, 97, 171, 181, 186, 191, 180, 185, 146, - /* 890 */ 148, 140, 142, 138, 144, 99, 150, 152, 154, 156, - /* 900 */ 158, 160, 162, 164, 166, 168, 99, 80, 99, 430, - /* 910 */ 99, 296, 555, 170, 413, 856, 78, 147, 672, 457, - /* 920 */ 352, 348, 298, 443, 465, 45, 35, 78, 149, 78, - /* 930 */ 151, 78, 153, 171, 181, 186, 191, 180, 185, 146, - /* 940 */ 148, 140, 142, 138, 144, 99, 150, 152, 154, 156, - /* 950 */ 158, 160, 162, 164, 166, 168, 99, 459, 99, 29, - /* 960 */ 79, 464, 183, 483, 71, 339, 78, 155, 709, 421, - /* 970 */ 428, 79, 109, 99, 491, 71, 296, 78, 157, 78, - /* 980 */ 159, 490, 243, 109, 99, 340, 99, 449, 857, 223, - /* 990 */ 99, 460, 182, 709, 78, 161, 99, 349, 827, 136, - /* 1000 */ 223, 99, 80, 201, 99, 78, 163, 78, 165, 507, - /* 1010 */ 136, 78, 167, 42, 201, 38, 493, 78, 169, 569, - /* 1020 */ 207, 205, 78, 177, 674, 78, 179, 477, 203, 76, - /* 1030 */ 77, 207, 205, 98, 99, 84, 99, 42, 336, 203, - /* 1040 */ 76, 77, 99, 43, 98, 41, 428, 79, 494, 80, - /* 1050 */ 428, 71, 84, 99, 352, 78, 188, 78, 190, 109, - /* 1060 */ 499, 428, 497, 78, 202, 60, 104, 105, 106, 107, - /* 1070 */ 108, 209, 213, 99, 78, 204, 223, 104, 105, 106, - /* 1080 */ 107, 108, 209, 213, 820, 509, 136, 53, 383, 511, - /* 1090 */ 201, 99, 56, 61, 78, 206, 55, 428, 428, 889, - /* 1100 */ 513, 99, 243, 99, 352, 99, 79, 207, 205, 312, - /* 1110 */ 71, 99, 78, 208, 483, 203, 76, 77, 109, 533, - /* 1120 */ 98, 497, 78, 220, 78, 222, 78, 232, 84, 99, - /* 1130 */ 428, 353, 78, 234, 352, 223, 517, 521, 389, 99, - /* 1140 */ 62, 530, 99, 64, 63, 136, 68, 529, 70, 201, - /* 1150 */ 78, 236, 352, 104, 105, 106, 107, 108, 209, 213, - /* 1160 */ 78, 249, 99, 78, 265, 877, 207, 205, 398, 527, - /* 1170 */ 99, 615, 616, 313, 203, 76, 77, 99, 523, 98, - /* 1180 */ 80, 353, 8, 78, 270, 99, 456, 19, 21, 23, - /* 1190 */ 412, 78, 300, 75, 78, 310, 82, 84, 78, 365, - /* 1200 */ 563, 83, 547, 99, 87, 553, 78, 393, 85, 557, - /* 1210 */ 99, 353, 104, 105, 106, 107, 108, 209, 213, 99, - /* 1220 */ 269, 536, 99, 467, 78, 434, 88, 266, 534, 353, - /* 1230 */ 560, 78, 481, 566, 264, 89, 250, 90, 93, 91, - /* 1240 */ 78, 485, 101, 78, 498, 92, 100, 102, 103, 110, - /* 1250 */ 131, 121, 134, 125, 129, 168, 184, 242, 686, 687, - /* 1260 */ 688, 210, 233, 218, 224, 216, 227, 226, 217, 229, - /* 1270 */ 228, 230, 243, 251, 515, 519, 463, 245, 253, 244, - /* 1280 */ 505, 257, 255, 256, 258, 84, 259, 262, 263, 239, - /* 1290 */ 267, 279, 274, 281, 282, 299, 285, 292, 284, 287, - /* 1300 */ 290, 293, 297, 305, 314, 291, 307, 322, 308, 325, - /* 1310 */ 327, 345, 329, 328, 332, 350, 354, 330, 358, 335, - /* 1320 */ 342, 379, 381, 382, 344, 351, 368, 385, 355, 371, - /* 1330 */ 388, 360, 396, 397, 400, 401, 415, 54, 416, 386, - /* 1340 */ 384, 391, 418, 402, 407, 419, 377, 420, 423, 424, - /* 1350 */ 403, 426, 425, 427, 429, 435, 431, 849, 436, 854, - /* 1360 */ 432, 855, 450, 447, 451, 452, 454, 453, 825, 455, - /* 1370 */ 458, 826, 469, 461, 466, 747, 748, 848, 471, 464, - /* 1380 */ 863, 480, 474, 475, 476, 482, 865, 479, 487, 484, - /* 1390 */ 489, 488, 492, 866, 495, 868, 504, 679, 502, 681, - /* 1400 */ 833, 875, 518, 503, 516, 739, 520, 524, 522, 742, - /* 1410 */ 745, 531, 526, 835, 535, 528, 538, 537, 836, 837, - /* 1420 */ 838, 839, 545, 546, 840, 550, 876, 556, 551, 878, - /* 1430 */ 548, 549, 554, 879, 559, 882, 884, 562, 886, 561, - /* 1440 */ 552, 558, 564, 567, 570, 565, 571, 887, 576, 574, - /* 1450 */ 573, 888, 578, 559, 559, 579, + /* 0 */ 279, 68, 283, 70, 148, 166, 546, 419, 62, 62, + /* 10 */ 62, 62, 202, 64, 64, 64, 64, 65, 65, 66, + /* 20 */ 66, 66, 67, 67, 548, 549, 432, 69, 64, 64, + /* 30 */ 64, 64, 65, 65, 66, 66, 66, 67, 68, 454, + /* 40 */ 70, 148, 499, 61, 59, 287, 440, 441, 437, 437, + /* 50 */ 63, 63, 62, 62, 62, 62, 501, 64, 64, 64, + /* 60 */ 64, 65, 65, 66, 66, 66, 67, 279, 371, 283, + /* 70 */ 419, 2, 377, 80, 158, 115, 220, 304, 225, 305, + /* 80 */ 170, 245, 856, 119, 559, 504, 204, 2, 246, 389, + /* 90 */ 496, 219, 22, 432, 514, 21, 419, 58, 493, 171, + /* 100 */ 64, 64, 64, 64, 65, 65, 66, 66, 66, 67, + /* 110 */ 61, 59, 287, 440, 441, 437, 437, 63, 63, 62, + /* 120 */ 62, 62, 62, 512, 64, 64, 64, 64, 65, 65, + /* 130 */ 66, 66, 66, 67, 279, 378, 379, 175, 202, 377, + /* 140 */ 330, 333, 334, 220, 304, 225, 305, 170, 245, 203, + /* 150 */ 146, 357, 335, 281, 377, 246, 55, 301, 373, 419, + /* 160 */ 432, 505, 92, 200, 530, 66, 66, 66, 67, 525, + /* 170 */ 192, 65, 65, 66, 66, 66, 67, 61, 59, 287, + /* 180 */ 440, 441, 437, 437, 63, 63, 62, 62, 62, 62, + /* 190 */ 433, 64, 64, 64, 64, 65, 65, 66, 66, 66, + /* 200 */ 67, 279, 378, 379, 411, 431, 110, 226, 427, 205, + /* 210 */ 435, 436, 308, 358, 261, 260, 175, 378, 379, 330, + /* 220 */ 333, 334, 372, 369, 202, 511, 480, 432, 547, 362, + /* 230 */ 466, 335, 510, 500, 410, 41, 276, 414, 434, 429, + /* 240 */ 503, 162, 233, 527, 61, 59, 287, 440, 441, 437, + /* 250 */ 437, 63, 63, 62, 62, 62, 62, 319, 64, 64, + /* 260 */ 64, 64, 65, 65, 66, 66, 66, 67, 279, 472, + /* 270 */ 416, 416, 416, 308, 322, 236, 308, 68, 308, 70, + /* 280 */ 148, 1, 308, 793, 308, 377, 68, 153, 70, 148, + /* 290 */ 149, 377, 325, 282, 432, 410, 35, 551, 410, 35, + /* 300 */ 410, 36, 427, 205, 410, 35, 410, 35, 286, 422, + /* 310 */ 423, 61, 59, 287, 440, 441, 437, 437, 63, 63, + /* 320 */ 62, 62, 62, 62, 411, 64, 64, 64, 64, 65, + /* 330 */ 65, 66, 66, 66, 67, 308, 504, 466, 290, 255, + /* 340 */ 279, 324, 485, 147, 237, 388, 21, 288, 378, 379, + /* 350 */ 451, 419, 232, 451, 378, 379, 308, 410, 28, 451, + /* 360 */ 175, 450, 486, 330, 333, 334, 432, 215, 347, 145, + /* 370 */ 513, 204, 350, 186, 168, 335, 238, 411, 410, 41, + /* 380 */ 256, 462, 76, 61, 59, 287, 440, 441, 437, 437, + /* 390 */ 63, 63, 62, 62, 62, 62, 309, 64, 64, 64, + /* 400 */ 64, 65, 65, 66, 66, 66, 67, 411, 411, 186, + /* 410 */ 396, 308, 279, 291, 419, 338, 476, 308, 390, 234, + /* 420 */ 169, 154, 397, 475, 396, 327, 493, 311, 422, 423, + /* 430 */ 444, 377, 356, 410, 49, 398, 397, 394, 432, 410, + /* 440 */ 49, 502, 171, 411, 429, 312, 162, 395, 351, 398, + /* 450 */ 497, 318, 470, 352, 79, 61, 59, 287, 440, 441, + /* 460 */ 437, 437, 63, 63, 62, 62, 62, 62, 356, 64, + /* 470 */ 64, 64, 64, 65, 65, 66, 66, 66, 67, 279, + /* 480 */ 298, 445, 376, 479, 532, 405, 299, 11, 504, 352, + /* 490 */ 204, 377, 406, 377, 378, 379, 281, 556, 21, 491, + /* 500 */ 491, 246, 560, 372, 369, 432, 392, 393, 314, 123, + /* 510 */ 443, 443, 166, 289, 419, 314, 116, 443, 443, 251, + /* 520 */ 264, 463, 61, 59, 287, 440, 441, 437, 437, 63, + /* 530 */ 63, 62, 62, 62, 62, 292, 64, 64, 64, 64, + /* 540 */ 65, 65, 66, 66, 66, 67, 279, 459, 328, 474, + /* 550 */ 498, 308, 202, 308, 378, 379, 378, 379, 181, 131, + /* 560 */ 179, 265, 308, 5, 308, 363, 314, 355, 443, 443, + /* 570 */ 410, 3, 432, 410, 29, 410, 24, 419, 243, 244, + /* 580 */ 380, 381, 382, 404, 410, 33, 410, 54, 466, 61, + /* 590 */ 59, 287, 440, 441, 437, 437, 63, 63, 62, 62, + /* 600 */ 62, 62, 308, 64, 64, 64, 64, 65, 65, 66, + /* 610 */ 66, 66, 67, 279, 521, 344, 521, 249, 308, 491, + /* 620 */ 308, 470, 308, 470, 410, 25, 308, 240, 308, 314, + /* 630 */ 308, 443, 443, 213, 172, 173, 174, 142, 266, 432, + /* 640 */ 410, 52, 410, 97, 410, 94, 528, 393, 410, 99, + /* 650 */ 410, 100, 410, 111, 212, 255, 61, 59, 287, 440, + /* 660 */ 441, 437, 437, 63, 63, 62, 62, 62, 62, 308, + /* 670 */ 64, 64, 64, 64, 65, 65, 66, 66, 66, 67, + /* 680 */ 279, 308, 345, 188, 297, 91, 308, 491, 308, 415, + /* 690 */ 308, 410, 112, 308, 428, 308, 537, 308, 244, 165, + /* 700 */ 154, 409, 355, 410, 18, 408, 432, 320, 410, 98, + /* 710 */ 410, 34, 410, 95, 313, 410, 53, 410, 113, 410, + /* 720 */ 114, 255, 293, 61, 59, 287, 440, 441, 437, 437, + /* 730 */ 63, 63, 62, 62, 62, 62, 308, 64, 64, 64, + /* 740 */ 64, 65, 65, 66, 66, 66, 67, 279, 308, 491, + /* 750 */ 491, 523, 308, 452, 308, 522, 308, 461, 410, 26, + /* 760 */ 308, 75, 539, 77, 308, 460, 244, 346, 214, 465, + /* 770 */ 410, 37, 469, 432, 410, 38, 410, 27, 410, 39, + /* 780 */ 242, 82, 410, 40, 294, 296, 410, 42, 438, 329, + /* 790 */ 61, 59, 287, 440, 441, 437, 437, 63, 63, 62, + /* 800 */ 62, 62, 62, 308, 64, 64, 64, 64, 65, 65, + /* 810 */ 66, 66, 66, 67, 279, 308, 409, 190, 221, 308, + /* 820 */ 408, 308, 152, 308, 159, 410, 43, 308, 244, 244, + /* 830 */ 222, 20, 308, 139, 425, 425, 481, 410, 44, 482, + /* 840 */ 432, 410, 30, 410, 31, 410, 45, 487, 461, 410, + /* 850 */ 46, 411, 506, 255, 410, 47, 488, 61, 71, 287, + /* 860 */ 440, 441, 437, 437, 63, 63, 62, 62, 62, 62, + /* 870 */ 308, 64, 64, 64, 64, 65, 65, 66, 66, 66, + /* 880 */ 67, 279, 308, 401, 402, 250, 308, 193, 308, 420, + /* 890 */ 308, 23, 410, 48, 540, 449, 255, 14, 468, 477, + /* 900 */ 167, 14, 484, 483, 410, 32, 252, 432, 410, 12, + /* 910 */ 410, 50, 410, 51, 255, 255, 594, 255, 255, 150, + /* 920 */ 489, 411, 123, 253, 279, 59, 287, 440, 441, 437, + /* 930 */ 437, 63, 63, 62, 62, 62, 62, 541, 64, 64, + /* 940 */ 64, 64, 65, 65, 66, 66, 66, 67, 254, 248, + /* 950 */ 432, 123, 337, 411, 123, 267, 269, 196, 361, 366, + /* 960 */ 183, 177, 180, 519, 520, 526, 534, 123, 167, 287, + /* 970 */ 440, 441, 437, 437, 63, 63, 62, 62, 62, 62, + /* 980 */ 342, 64, 64, 64, 64, 65, 65, 66, 66, 66, + /* 990 */ 67, 72, 315, 259, 4, 411, 411, 535, 285, 89, + /* 1000 */ 544, 349, 89, 353, 354, 19, 310, 72, 315, 368, + /* 1010 */ 4, 386, 262, 263, 285, 223, 545, 270, 364, 273, + /* 1020 */ 274, 141, 310, 317, 227, 316, 555, 424, 426, 480, + /* 1030 */ 455, 458, 490, 431, 332, 492, 533, 157, 543, 317, + /* 1040 */ 375, 383, 384, 385, 8, 302, 303, 391, 284, 431, + /* 1050 */ 404, 399, 74, 73, 224, 403, 407, 82, 323, 321, + /* 1060 */ 72, 306, 307, 400, 231, 414, 81, 206, 74, 73, + /* 1070 */ 473, 57, 78, 164, 453, 412, 72, 306, 307, 72, + /* 1080 */ 315, 414, 4, 228, 202, 229, 285, 235, 230, 456, + /* 1090 */ 457, 413, 207, 120, 310, 83, 326, 102, 416, 416, + /* 1100 */ 416, 417, 418, 13, 239, 495, 467, 241, 277, 208, + /* 1110 */ 471, 317, 494, 210, 416, 416, 416, 417, 418, 13, + /* 1120 */ 211, 431, 156, 278, 339, 507, 508, 216, 217, 218, + /* 1130 */ 106, 509, 515, 178, 343, 84, 341, 182, 517, 456, + /* 1140 */ 74, 73, 86, 198, 518, 271, 257, 184, 72, 306, + /* 1150 */ 307, 348, 272, 414, 118, 529, 187, 127, 536, 359, + /* 1160 */ 128, 136, 129, 542, 195, 130, 530, 133, 300, 552, + /* 1170 */ 553, 194, 137, 197, 431, 90, 554, 557, 96, 209, + /* 1180 */ 101, 374, 387, 117, 201, 56, 416, 416, 416, 417, + /* 1190 */ 418, 13, 93, 143, 144, 595, 596, 109, 160, 161, + /* 1200 */ 60, 439, 500, 421, 430, 442, 414, 138, 446, 151, + /* 1210 */ 6, 447, 155, 448, 163, 360, 268, 260, 15, 7, + /* 1220 */ 14, 280, 121, 464, 122, 478, 202, 103, 104, 331, + /* 1230 */ 247, 85, 105, 336, 222, 176, 340, 140, 516, 416, + /* 1240 */ 416, 416, 124, 295, 125, 167, 524, 258, 107, 185, + /* 1250 */ 365, 9, 531, 10, 126, 189, 16, 538, 191, 132, + /* 1260 */ 134, 87, 88, 135, 17, 108, 275, 550, 367, 199, + /* 1270 */ 370, 536, 558, }; static const YYCODETYPE yy_lookahead[] = { - /* 0 */ 28, 11, 30, 77, 78, 79, 80, 0, 82, 83, - /* 10 */ 84, 85, 86, 87, 88, 89, 90, 91, 11, 12, - /* 20 */ 11, 49, 81, 82, 83, 84, 85, 86, 87, 88, - /* 30 */ 89, 90, 91, 86, 87, 88, 89, 90, 91, 67, - /* 40 */ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, - /* 50 */ 78, 79, 80, 69, 82, 83, 84, 85, 86, 87, - /* 60 */ 88, 89, 90, 91, 17, 18, 19, 95, 11, 29, - /* 70 */ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - /* 80 */ 30, 97, 98, 99, 100, 101, 102, 103, 104, 49, - /* 90 */ 150, 151, 50, 53, 26, 111, 156, 155, 30, 147, - /* 100 */ 148, 149, 162, 30, 152, 163, 164, 67, 68, 69, - /* 110 */ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - /* 120 */ 80, 153, 82, 83, 84, 85, 86, 87, 88, 89, - /* 130 */ 90, 91, 155, 65, 11, 195, 28, 155, 129, 165, - /* 140 */ 163, 164, 168, 169, 170, 95, 96, 97, 106, 155, - /* 150 */ 100, 101, 102, 30, 86, 87, 162, 49, 176, 177, - /* 160 */ 220, 88, 112, 95, 187, 188, 154, 99, 95, 96, - /* 170 */ 176, 177, 28, 21, 30, 67, 68, 69, 70, 71, - /* 180 */ 72, 73, 74, 75, 76, 77, 78, 79, 80, 195, - /* 190 */ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - /* 200 */ 132, 133, 134, 27, 222, 29, 155, 49, 56, 30, - /* 210 */ 149, 160, 218, 152, 163, 164, 11, 12, 95, 96, - /* 220 */ 69, 168, 169, 170, 230, 67, 68, 69, 70, 71, - /* 230 */ 72, 73, 74, 75, 76, 77, 78, 79, 80, 95, - /* 240 */ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - /* 250 */ 99, 100, 101, 102, 103, 104, 65, 192, 193, 107, - /* 260 */ 108, 109, 111, 174, 175, 86, 87, 27, 29, 29, - /* 270 */ 118, 155, 183, 97, 95, 96, 100, 101, 102, 99, - /* 280 */ 49, 171, 172, 173, 30, 106, 95, 27, 112, 29, - /* 290 */ 99, 111, 176, 177, 162, 17, 18, 139, 67, 68, - /* 300 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - /* 310 */ 79, 80, 15, 82, 83, 84, 85, 86, 87, 88, - /* 320 */ 89, 90, 91, 132, 133, 134, 21, 195, 22, 27, - /* 330 */ 88, 89, 90, 91, 218, 96, 155, 31, 155, 207, - /* 340 */ 208, 21, 155, 233, 212, 155, 230, 49, 11, 95, - /* 350 */ 44, 26, 46, 97, 49, 30, 100, 101, 102, 176, - /* 360 */ 177, 122, 56, 176, 177, 105, 176, 177, 112, 71, - /* 370 */ 72, 140, 67, 68, 69, 70, 71, 72, 73, 74, - /* 380 */ 75, 76, 77, 78, 79, 80, 27, 82, 83, 84, - /* 390 */ 85, 86, 87, 88, 89, 90, 91, 99, 215, 216, - /* 400 */ 171, 172, 173, 27, 49, 218, 216, 86, 87, 168, - /* 410 */ 11, 223, 224, 225, 226, 24, 114, 230, 116, 117, - /* 420 */ 95, 96, 67, 68, 69, 70, 71, 72, 73, 74, - /* 430 */ 75, 76, 77, 78, 79, 80, 139, 82, 83, 84, - /* 440 */ 85, 86, 87, 88, 89, 90, 91, 206, 155, 27, - /* 450 */ 155, 60, 27, 62, 29, 162, 27, 11, 155, 139, - /* 460 */ 30, 141, 233, 30, 223, 22, 225, 226, 154, 176, - /* 470 */ 177, 176, 177, 114, 31, 116, 117, 162, 49, 176, - /* 480 */ 177, 26, 26, 30, 28, 30, 11, 44, 195, 46, - /* 490 */ 114, 16, 116, 117, 24, 140, 67, 68, 69, 70, - /* 500 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - /* 510 */ 195, 82, 83, 84, 85, 86, 87, 88, 89, 90, - /* 520 */ 91, 96, 227, 27, 11, 95, 96, 26, 95, 96, - /* 530 */ 60, 30, 62, 230, 115, 220, 114, 118, 116, 117, - /* 540 */ 154, 11, 32, 50, 162, 49, 36, 122, 95, 96, - /* 550 */ 95, 236, 122, 178, 11, 122, 241, 168, 48, 11, - /* 560 */ 30, 88, 69, 67, 68, 69, 70, 71, 72, 73, - /* 570 */ 74, 75, 76, 77, 78, 79, 80, 195, 82, 83, - /* 580 */ 84, 85, 86, 87, 88, 89, 90, 91, 115, 155, - /* 590 */ 155, 27, 119, 155, 155, 206, 95, 96, 223, 106, - /* 600 */ 225, 226, 220, 11, 111, 207, 208, 172, 173, 11, - /* 610 */ 176, 177, 142, 49, 176, 177, 11, 223, 236, 225, - /* 620 */ 226, 11, 27, 241, 29, 95, 96, 114, 189, 116, - /* 630 */ 117, 67, 68, 69, 70, 71, 72, 73, 74, 75, - /* 640 */ 76, 77, 78, 79, 80, 155, 82, 83, 84, 85, - /* 650 */ 86, 87, 88, 89, 90, 91, 222, 107, 108, 109, - /* 660 */ 11, 175, 114, 49, 116, 117, 176, 177, 233, 183, - /* 670 */ 29, 232, 107, 108, 109, 26, 11, 155, 26, 15, - /* 680 */ 168, 67, 68, 69, 70, 71, 72, 73, 74, 75, - /* 690 */ 76, 77, 78, 79, 80, 30, 82, 83, 84, 85, - /* 700 */ 86, 87, 88, 89, 90, 91, 114, 155, 116, 117, - /* 710 */ 183, 184, 114, 49, 116, 117, 194, 190, 206, 114, - /* 720 */ 106, 116, 117, 34, 114, 76, 116, 117, 176, 177, - /* 730 */ 41, 67, 68, 69, 70, 71, 72, 73, 74, 75, - /* 740 */ 76, 77, 78, 79, 80, 11, 82, 83, 84, 85, - /* 750 */ 86, 87, 88, 89, 90, 91, 155, 11, 155, 155, - /* 760 */ 95, 96, 121, 49, 30, 115, 244, 198, 11, 119, - /* 770 */ 132, 133, 120, 28, 205, 29, 154, 176, 177, 176, - /* 780 */ 177, 67, 68, 69, 70, 71, 72, 73, 74, 75, - /* 790 */ 76, 77, 78, 79, 80, 155, 82, 83, 84, 85, - /* 800 */ 86, 87, 88, 89, 90, 91, 155, 27, 30, 29, - /* 810 */ 27, 157, 29, 49, 98, 99, 176, 177, 214, 27, - /* 820 */ 27, 29, 29, 27, 162, 29, 27, 176, 177, 95, - /* 830 */ 96, 67, 68, 69, 70, 71, 72, 73, 74, 75, - /* 840 */ 76, 77, 78, 79, 80, 155, 82, 83, 84, 85, - /* 850 */ 86, 87, 88, 89, 90, 91, 155, 195, 155, 167, - /* 860 */ 27, 52, 29, 49, 155, 120, 176, 177, 176, 11, - /* 870 */ 155, 58, 59, 95, 162, 129, 11, 176, 177, 176, - /* 880 */ 177, 25, 68, 69, 70, 71, 72, 73, 74, 75, - /* 890 */ 76, 77, 78, 79, 80, 155, 82, 83, 84, 85, - /* 900 */ 86, 87, 88, 89, 90, 91, 155, 195, 155, 194, - /* 910 */ 155, 29, 134, 49, 158, 106, 176, 177, 11, 27, - /* 920 */ 155, 29, 155, 214, 192, 193, 166, 176, 177, 176, - /* 930 */ 177, 176, 177, 69, 70, 71, 72, 73, 74, 75, - /* 940 */ 76, 77, 78, 79, 80, 155, 82, 83, 84, 85, - /* 950 */ 86, 87, 88, 89, 90, 91, 155, 101, 155, 161, - /* 960 */ 26, 67, 69, 155, 30, 37, 176, 177, 106, 162, - /* 970 */ 155, 26, 38, 155, 27, 30, 29, 176, 177, 176, - /* 980 */ 177, 214, 120, 38, 155, 57, 155, 231, 106, 55, - /* 990 */ 155, 235, 99, 11, 176, 177, 155, 232, 142, 65, - /* 1000 */ 55, 155, 195, 69, 155, 176, 177, 176, 177, 194, - /* 1010 */ 65, 176, 177, 106, 69, 155, 162, 176, 177, 64, - /* 1020 */ 86, 87, 176, 177, 130, 176, 177, 219, 94, 95, - /* 1030 */ 96, 86, 87, 99, 155, 118, 155, 106, 110, 94, - /* 1040 */ 95, 96, 155, 39, 99, 178, 155, 26, 131, 195, - /* 1050 */ 155, 30, 118, 155, 155, 176, 177, 176, 177, 38, - /* 1060 */ 27, 155, 29, 176, 177, 51, 132, 133, 134, 135, - /* 1070 */ 136, 137, 138, 155, 176, 177, 55, 132, 133, 134, - /* 1080 */ 135, 136, 137, 138, 139, 194, 65, 178, 189, 194, - /* 1090 */ 69, 155, 47, 179, 176, 177, 186, 155, 155, 144, - /* 1100 */ 194, 155, 120, 155, 155, 155, 26, 86, 87, 88, - /* 1110 */ 30, 155, 176, 177, 155, 94, 95, 96, 38, 27, - /* 1120 */ 99, 29, 176, 177, 176, 177, 176, 177, 118, 155, - /* 1130 */ 155, 232, 176, 177, 155, 55, 194, 194, 189, 155, - /* 1140 */ 178, 131, 155, 105, 180, 65, 178, 162, 26, 69, - /* 1150 */ 176, 177, 155, 132, 133, 134, 135, 136, 137, 138, - /* 1160 */ 176, 177, 155, 176, 177, 11, 86, 87, 189, 194, - /* 1170 */ 155, 120, 120, 155, 94, 95, 96, 155, 219, 99, - /* 1180 */ 195, 232, 15, 176, 177, 155, 189, 20, 21, 22, - /* 1190 */ 23, 176, 177, 197, 176, 177, 196, 118, 176, 177, - /* 1200 */ 33, 195, 35, 155, 199, 51, 176, 177, 197, 42, - /* 1210 */ 155, 232, 132, 133, 134, 135, 136, 137, 138, 155, - /* 1220 */ 129, 54, 155, 56, 176, 177, 200, 126, 61, 232, - /* 1230 */ 63, 176, 177, 66, 127, 201, 124, 202, 128, 203, - /* 1240 */ 176, 177, 155, 176, 177, 204, 120, 120, 155, 26, - /* 1250 */ 168, 27, 27, 234, 234, 91, 99, 155, 118, 118, - /* 1260 */ 118, 26, 139, 21, 26, 228, 193, 27, 229, 155, - /* 1270 */ 29, 27, 120, 125, 107, 108, 109, 159, 29, 155, - /* 1280 */ 113, 104, 217, 179, 30, 118, 167, 217, 179, 29, - /* 1290 */ 125, 155, 209, 155, 122, 106, 159, 123, 155, 155, - /* 1300 */ 210, 26, 155, 27, 120, 211, 210, 27, 211, 178, - /* 1310 */ 155, 26, 182, 181, 155, 217, 217, 184, 167, 185, - /* 1320 */ 185, 155, 51, 26, 185, 179, 176, 27, 179, 176, - /* 1330 */ 26, 186, 51, 26, 103, 155, 155, 111, 159, 178, - /* 1340 */ 180, 178, 155, 181, 188, 159, 188, 28, 155, 159, - /* 1350 */ 182, 238, 237, 106, 159, 45, 239, 15, 43, 106, - /* 1360 */ 240, 106, 142, 52, 155, 159, 155, 106, 11, 26, - /* 1370 */ 178, 142, 21, 15, 191, 130, 130, 11, 11, 67, - /* 1380 */ 21, 76, 191, 155, 110, 200, 11, 155, 130, 76, - /* 1390 */ 26, 155, 221, 11, 26, 11, 200, 11, 121, 11, - /* 1400 */ 11, 11, 200, 155, 121, 11, 191, 200, 110, 11, - /* 1410 */ 11, 26, 130, 11, 155, 221, 159, 155, 11, 11, - /* 1420 */ 11, 11, 155, 27, 11, 28, 11, 40, 155, 11, - /* 1430 */ 242, 168, 168, 11, 155, 11, 11, 159, 11, 155, - /* 1440 */ 243, 242, 155, 24, 143, 159, 155, 11, 145, 245, - /* 1450 */ 144, 11, 13, 246, 246, 14, + /* 0 */ 16, 216, 16, 218, 219, 21, 146, 23, 68, 69, + /* 10 */ 70, 71, 109, 73, 74, 75, 76, 77, 78, 79, + /* 20 */ 80, 81, 82, 82, 164, 165, 42, 72, 73, 74, + /* 30 */ 75, 76, 77, 78, 79, 80, 81, 82, 216, 217, + /* 40 */ 218, 219, 168, 59, 60, 61, 62, 63, 64, 65, + /* 50 */ 66, 67, 68, 69, 70, 71, 168, 73, 74, 75, + /* 60 */ 76, 77, 78, 79, 80, 81, 82, 16, 140, 16, + /* 70 */ 86, 143, 23, 22, 88, 89, 90, 91, 92, 93, + /* 80 */ 94, 95, 138, 139, 140, 146, 226, 143, 102, 166, + /* 90 */ 167, 152, 19, 42, 155, 156, 23, 46, 175, 43, + /* 100 */ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + /* 110 */ 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + /* 120 */ 69, 70, 71, 180, 73, 74, 75, 76, 77, 78, + /* 130 */ 79, 80, 81, 82, 16, 86, 87, 88, 109, 23, + /* 140 */ 91, 92, 93, 90, 91, 92, 93, 94, 95, 191, + /* 150 */ 22, 122, 103, 97, 23, 102, 198, 141, 142, 86, + /* 160 */ 42, 180, 44, 147, 49, 79, 80, 81, 82, 18, + /* 170 */ 154, 77, 78, 79, 80, 81, 82, 59, 60, 61, + /* 180 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + /* 190 */ 42, 73, 74, 75, 76, 77, 78, 79, 80, 81, + /* 200 */ 82, 16, 86, 87, 188, 58, 21, 189, 77, 78, + /* 210 */ 62, 63, 146, 98, 99, 100, 88, 86, 87, 91, + /* 220 */ 92, 93, 1, 2, 109, 175, 176, 42, 97, 213, + /* 230 */ 160, 103, 182, 86, 168, 169, 157, 90, 90, 160, + /* 240 */ 161, 162, 146, 92, 59, 60, 61, 62, 63, 64, + /* 250 */ 65, 66, 67, 68, 69, 70, 71, 185, 73, 74, + /* 260 */ 75, 76, 77, 78, 79, 80, 81, 82, 16, 199, + /* 270 */ 123, 124, 125, 146, 208, 209, 146, 216, 146, 218, + /* 280 */ 219, 19, 146, 132, 146, 23, 216, 146, 218, 219, + /* 290 */ 154, 23, 146, 149, 42, 168, 169, 236, 168, 169, + /* 300 */ 168, 169, 77, 78, 168, 169, 168, 169, 163, 164, + /* 310 */ 165, 59, 60, 61, 62, 63, 64, 65, 66, 67, + /* 320 */ 68, 69, 70, 71, 188, 73, 74, 75, 76, 77, + /* 330 */ 78, 79, 80, 81, 82, 146, 146, 160, 211, 146, + /* 340 */ 16, 211, 30, 154, 146, 155, 156, 211, 86, 87, + /* 350 */ 223, 23, 220, 223, 86, 87, 146, 168, 169, 223, + /* 360 */ 88, 223, 50, 91, 92, 93, 42, 144, 224, 179, + /* 370 */ 180, 226, 228, 154, 154, 103, 199, 188, 168, 169, + /* 380 */ 187, 113, 130, 59, 60, 61, 62, 63, 64, 65, + /* 390 */ 66, 67, 68, 69, 70, 71, 146, 73, 74, 75, + /* 400 */ 76, 77, 78, 79, 80, 81, 82, 188, 188, 154, + /* 410 */ 12, 146, 16, 101, 86, 16, 20, 146, 167, 209, + /* 420 */ 200, 201, 24, 20, 12, 205, 175, 163, 164, 165, + /* 430 */ 20, 23, 213, 168, 169, 37, 24, 39, 42, 168, + /* 440 */ 169, 159, 43, 188, 160, 161, 162, 49, 229, 37, + /* 450 */ 168, 39, 146, 234, 130, 59, 60, 61, 62, 63, + /* 460 */ 64, 65, 66, 67, 68, 69, 70, 71, 213, 73, + /* 470 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 16, + /* 480 */ 215, 20, 146, 20, 229, 27, 215, 19, 146, 234, + /* 490 */ 226, 23, 34, 23, 86, 87, 97, 155, 156, 146, + /* 500 */ 146, 102, 0, 1, 2, 42, 184, 185, 105, 22, + /* 510 */ 107, 108, 21, 207, 23, 105, 146, 107, 108, 14, + /* 520 */ 14, 113, 59, 60, 61, 62, 63, 64, 65, 66, + /* 530 */ 67, 68, 69, 70, 71, 181, 73, 74, 75, 76, + /* 540 */ 77, 78, 79, 80, 81, 82, 16, 22, 146, 79, + /* 550 */ 20, 146, 109, 146, 86, 87, 86, 87, 53, 53, + /* 560 */ 55, 55, 146, 190, 146, 122, 105, 146, 107, 108, + /* 570 */ 168, 169, 42, 168, 169, 168, 169, 86, 225, 225, + /* 580 */ 7, 8, 9, 96, 168, 169, 168, 169, 160, 59, + /* 590 */ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + /* 600 */ 70, 71, 146, 73, 74, 75, 76, 77, 78, 79, + /* 610 */ 80, 81, 82, 16, 98, 99, 100, 20, 146, 146, + /* 620 */ 146, 146, 146, 146, 168, 169, 146, 199, 146, 105, + /* 630 */ 146, 107, 108, 212, 98, 99, 100, 112, 132, 42, + /* 640 */ 168, 169, 168, 169, 168, 169, 184, 185, 168, 169, + /* 650 */ 168, 169, 168, 169, 181, 146, 59, 60, 61, 62, + /* 660 */ 63, 64, 65, 66, 67, 68, 69, 70, 71, 146, + /* 670 */ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + /* 680 */ 16, 146, 207, 22, 207, 21, 146, 146, 146, 146, + /* 690 */ 146, 168, 169, 146, 160, 146, 187, 146, 225, 200, + /* 700 */ 201, 106, 146, 168, 169, 110, 42, 146, 168, 169, + /* 710 */ 168, 169, 168, 169, 16, 168, 169, 168, 169, 168, + /* 720 */ 169, 146, 181, 59, 60, 61, 62, 63, 64, 65, + /* 730 */ 66, 67, 68, 69, 70, 71, 146, 73, 74, 75, + /* 740 */ 76, 77, 78, 79, 80, 81, 82, 16, 146, 146, + /* 750 */ 146, 25, 146, 146, 146, 29, 146, 22, 168, 169, + /* 760 */ 146, 129, 187, 131, 146, 202, 225, 41, 212, 146, + /* 770 */ 168, 169, 146, 42, 168, 169, 168, 169, 168, 169, + /* 780 */ 146, 120, 168, 169, 181, 181, 168, 169, 90, 79, + /* 790 */ 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + /* 800 */ 69, 70, 71, 146, 73, 74, 75, 76, 77, 78, + /* 810 */ 79, 80, 81, 82, 16, 146, 106, 154, 90, 146, + /* 820 */ 110, 146, 87, 146, 19, 168, 169, 146, 225, 225, + /* 830 */ 102, 19, 146, 21, 123, 124, 146, 168, 169, 177, + /* 840 */ 42, 168, 169, 168, 169, 168, 169, 177, 113, 168, + /* 850 */ 169, 188, 146, 146, 168, 169, 177, 59, 60, 61, + /* 860 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + /* 870 */ 146, 73, 74, 75, 76, 77, 78, 79, 80, 81, + /* 880 */ 82, 16, 146, 7, 8, 146, 146, 154, 146, 20, + /* 890 */ 146, 22, 168, 169, 187, 20, 146, 22, 20, 20, + /* 900 */ 22, 22, 89, 90, 168, 169, 146, 42, 168, 169, + /* 910 */ 168, 169, 168, 169, 146, 146, 111, 146, 146, 154, + /* 920 */ 20, 188, 22, 146, 16, 60, 61, 62, 63, 64, + /* 930 */ 65, 66, 67, 68, 69, 70, 71, 187, 73, 74, + /* 940 */ 75, 76, 77, 78, 79, 80, 81, 82, 146, 20, + /* 950 */ 42, 22, 20, 188, 22, 187, 187, 19, 187, 187, + /* 960 */ 230, 154, 154, 51, 52, 20, 20, 22, 22, 61, + /* 970 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + /* 980 */ 231, 73, 74, 75, 76, 77, 78, 79, 80, 81, + /* 990 */ 82, 16, 17, 146, 19, 188, 188, 20, 23, 22, + /* 1000 */ 20, 146, 22, 146, 146, 67, 31, 16, 17, 237, + /* 1010 */ 19, 148, 146, 146, 23, 171, 146, 146, 146, 146, + /* 1020 */ 146, 190, 31, 48, 192, 222, 146, 227, 227, 176, + /* 1030 */ 171, 171, 171, 58, 172, 171, 193, 6, 193, 48, + /* 1040 */ 145, 145, 145, 145, 22, 153, 97, 170, 40, 58, + /* 1050 */ 96, 170, 77, 78, 170, 172, 170, 120, 117, 115, + /* 1060 */ 85, 86, 87, 178, 196, 90, 118, 221, 77, 78, + /* 1070 */ 79, 119, 129, 111, 151, 188, 85, 86, 87, 16, + /* 1080 */ 17, 90, 19, 193, 109, 194, 23, 95, 195, 23, + /* 1090 */ 159, 197, 210, 151, 31, 97, 114, 19, 123, 124, + /* 1100 */ 125, 126, 127, 128, 203, 178, 204, 203, 173, 210, + /* 1110 */ 204, 48, 159, 210, 123, 124, 125, 126, 127, 128, + /* 1120 */ 210, 58, 5, 173, 15, 170, 170, 10, 11, 12, + /* 1130 */ 13, 170, 151, 150, 38, 19, 151, 151, 151, 23, + /* 1140 */ 77, 78, 129, 26, 233, 28, 232, 150, 85, 86, + /* 1150 */ 87, 151, 35, 90, 59, 183, 183, 19, 193, 15, + /* 1160 */ 186, 214, 186, 193, 47, 186, 49, 183, 151, 33, + /* 1170 */ 151, 54, 214, 56, 58, 235, 151, 136, 158, 174, + /* 1180 */ 174, 1, 20, 32, 44, 19, 123, 124, 125, 126, + /* 1190 */ 127, 128, 235, 77, 78, 111, 111, 238, 111, 111, + /* 1200 */ 19, 90, 86, 20, 20, 106, 90, 19, 11, 19, + /* 1210 */ 116, 20, 111, 20, 22, 98, 99, 100, 22, 116, + /* 1220 */ 22, 104, 19, 113, 20, 20, 109, 19, 19, 44, + /* 1230 */ 20, 19, 19, 44, 102, 94, 16, 21, 17, 123, + /* 1240 */ 124, 125, 97, 36, 45, 22, 45, 132, 19, 97, + /* 1250 */ 133, 5, 11, 1, 101, 121, 19, 17, 112, 112, + /* 1260 */ 101, 67, 67, 121, 19, 14, 135, 20, 57, 134, + /* 1270 */ 3, 239, 4, }; -#define YY_SHIFT_USE_DFLT (-75) +#define YY_SHIFT_USE_DFLT (-98) +#define YY_SHIFT_MAX 370 static const short yy_shift_ofst[] = { - /* 0 */ 205, 7, -75, -75, 1167, -10, 57, -75, 47, 475, - /* 10 */ 399, 123, 337, -75, -75, -75, -75, -75, -75, 475, - /* 20 */ 446, 475, 543, 475, 757, 456, 858, 453, 240, 799, - /* 30 */ 865, 50, -75, 254, -75, -16, -75, 453, 151, -75, - /* 40 */ 931, -75, 1004, 306, -75, -75, -75, -75, -75, -75, - /* 50 */ -75, 180, 931, -75, 1045, -75, 278, -75, -75, 1014, - /* 60 */ 689, 931, 1038, -75, -75, -75, -75, 931, -75, 1122, - /* 70 */ 1080, 652, 473, -75, -75, 1080, 1051, 1052, -75, 934, - /* 80 */ -75, 302, 1079, -75, 650, -75, 641, 1091, 1101, 1107, - /* 90 */ 1112, 1110, -75, 1080, 40, 1080, 714, 1080, -75, 1126, - /* 100 */ 453, 1127, 453, -75, -75, -75, -75, -75, -75, 1223, - /* 110 */ 1080, 108, 254, -75, -75, 455, 321, 595, -75, 321, - /* 120 */ 1224, -75, -75, -75, 638, -75, -75, -75, 638, -75, - /* 130 */ -75, -75, -75, 1225, -75, 1080, -75, 814, 1080, -12, - /* 140 */ 1080, -12, 1080, -12, 1080, -12, 1080, -74, 1080, -74, - /* 150 */ 1080, -53, 1080, -53, 1080, -53, 1080, -53, 1080, 242, - /* 160 */ 1080, 242, 1080, 1164, 1080, 1164, 1080, 1164, 1080, -75, - /* 170 */ -75, 298, -75, -75, -75, -75, 1080, -59, 1080, -12, - /* 180 */ -75, 893, -75, 1157, -75, -75, -75, 1080, 764, 1080, - /* 190 */ -74, -75, 325, 934, 359, 419, 1140, 1141, 1142, -75, - /* 200 */ 714, 1080, 864, 1080, -75, 1080, -75, 1080, -75, 1235, - /* 210 */ 1079, 376, -75, 945, 158, 1123, 320, 1242, -75, 1080, - /* 220 */ 231, 1080, 714, 1238, 443, 1240, -75, 1241, 453, 1244, - /* 230 */ -75, 1080, 305, 1080, 355, 1080, 714, 780, -75, 1080, - /* 240 */ -75, -75, 1152, 453, -75, -75, -75, 864, 1080, 714, - /* 250 */ 1148, 1080, 1249, 1080, 1177, 689, -75, 1254, -75, -75, - /* 260 */ 714, 1177, 689, -75, 1080, 714, 1165, 1080, 1260, 1080, - /* 270 */ 714, -75, -75, 239, -75, -75, -75, 430, -75, 433, - /* 280 */ -75, 1172, -75, 501, 1152, 144, 453, -75, -75, 1189, - /* 290 */ 1174, -75, 1275, 453, 783, -75, 453, -75, -75, 1080, - /* 300 */ 714, 1079, 422, 425, 1276, 144, 1189, 1174, -75, 1021, - /* 310 */ -28, -75, -75, 1184, 73, -75, -75, 429, -75, 792, - /* 320 */ -75, 1280, -75, 496, 931, -75, 453, 1285, -75, 42, - /* 330 */ -75, 453, -75, 550, 928, -75, 716, -75, -75, -75, - /* 340 */ -75, 928, -75, 928, -75, 453, 793, -75, 453, 1177, - /* 350 */ 689, -75, -75, 1177, 689, -75, -75, 1254, -75, 1045, - /* 360 */ -75, -75, 68, -75, 1080, 564, -75, 191, -75, -75, - /* 370 */ 191, -75, -75, -75, -75, 176, 256, -75, 453, -75, - /* 380 */ 1271, 1297, 453, 260, 1300, 931, -75, 1304, 453, 796, - /* 390 */ 931, -75, 1080, 614, -75, 1281, 1307, 453, 833, 1231, - /* 400 */ 453, 1285, -75, 493, 1226, -75, -75, -75, -75, -75, - /* 410 */ 1079, 513, 856, 391, 453, 1152, -75, 453, 745, 1319, - /* 420 */ 1079, 548, 453, 1152, 510, 565, 1247, 453, 1152, -75, - /* 430 */ 1310, 297, 1342, 1080, 664, 1315, 813, -75, -75, 1253, - /* 440 */ 1255, 809, 453, 882, -75, -75, 1311, -75, -75, 1220, - /* 450 */ 453, 862, 1261, 453, 1343, 453, 892, 907, 1357, 1229, - /* 460 */ 1358, 152, 592, 894, 306, -75, 1245, 1246, 1351, 1366, - /* 470 */ 1367, 152, 1359, 1312, 453, 1274, 453, 746, 453, 1305, - /* 480 */ 1080, 714, 1375, 1313, 1080, 714, 1258, 453, 1364, 453, - /* 490 */ 947, -75, 917, 598, 1368, 1080, 1033, 1080, 714, 1382, - /* 500 */ 714, 1277, 453, 9, 1384, 470, 453, 1386, 453, 1388, - /* 510 */ 453, 1389, 453, 1390, 605, 1283, 453, 9, 1394, 1312, - /* 520 */ 453, 1298, 453, 746, 1398, 1282, 453, 1364, 1010, 610, - /* 530 */ 1385, 1080, 1092, 1399, 530, 1402, 453, 1152, 649, 179, - /* 540 */ 1407, 1408, 1409, 1410, 453, 1396, 1413, 1387, 254, 1397, - /* 550 */ 453, 1154, 1415, 778, 1418, 1422, -75, 1387, 453, 1424, - /* 560 */ 665, 982, 1425, 734, 982, 1427, 1419, 453, 955, 1301, - /* 570 */ 453, 1436, 1306, 1303, 453, 1440, -75, 1439, 1441, -75, - /* 580 */ -75, + /* 0 */ 221, 975, 1117, -16, 975, 1063, 1063, 1063, 49, 115, + /* 10 */ 115, -97, 118, 1063, 1063, 1063, 1063, 1063, -45, 131, + /* 20 */ 116, 328, 225, 225, 51, 185, 252, 324, 396, 463, + /* 30 */ 530, 597, 664, 731, 798, 731, 731, 731, 731, 731, + /* 40 */ 731, 731, 731, 731, 731, 731, 731, 731, 731, 731, + /* 50 */ 731, 731, 865, 908, 908, 991, 1063, 1063, 1063, 1063, + /* 60 */ 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, + /* 70 */ 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, + /* 80 */ 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, + /* 90 */ 1063, 1063, 1063, 1063, -60, -60, -14, 27, 27, 94, + /* 100 */ 86, 399, 116, 116, 116, 116, 151, 116, 116, 116, + /* 110 */ 328, -59, -98, -98, -98, 1116, 53, 398, 398, 502, + /* 120 */ 491, 116, 491, 116, 116, 116, 116, 116, 116, 116, + /* 130 */ 116, 116, 116, 116, 116, 116, 29, 443, -97, -97, + /* 140 */ -97, -98, -98, 147, 147, 128, 272, 403, 262, 410, + /* 150 */ 461, 412, 268, 408, 468, 470, 573, 116, 116, 710, + /* 160 */ 116, 116, 73, 116, 116, 735, 116, 116, 524, 735, + /* 170 */ 116, 116, 312, 312, 312, 116, 116, 524, 116, 116, + /* 180 */ 524, 116, 726, 516, 116, 116, 524, 116, 116, 116, + /* 190 */ 524, 116, 524, 524, 116, 116, 116, 116, 116, 116, + /* 200 */ 812, 458, 595, 525, 711, 711, 632, 458, 458, 56, + /* 210 */ 458, 458, 487, 661, 661, 1031, 1031, 1031, 1031, 1022, + /* 220 */ 949, 949, 1008, 949, 954, 949, -97, 937, 941, 948, + /* 230 */ 944, 952, 943, 962, 992, 1066, 992, 962, 998, 982, + /* 240 */ 998, 982, 1078, 992, 992, 1066, 1008, 949, 949, 949, + /* 250 */ 1078, 1109, 962, 962, 962, 962, 1096, 1013, 1109, 962, + /* 260 */ 1095, 1095, 1138, 937, 1144, 1144, 1144, 937, 1095, 1138, + /* 270 */ 962, 1136, 1136, 962, 962, 1041, -98, -98, -98, 148, + /* 280 */ 506, 536, 505, 728, 876, 805, 869, 698, 875, 878, + /* 290 */ 879, 813, 900, 929, 932, 912, 945, 946, 977, 980, + /* 300 */ 938, 1180, 1162, 1151, 1140, 1166, 1084, 1085, 1087, 1088, + /* 310 */ 1181, 1183, 1184, 1111, 1099, 1188, 1197, 1190, 1191, 1192, + /* 320 */ 1193, 1094, 1196, 1103, 1198, 1110, 1203, 1204, 1101, 1205, + /* 330 */ 1185, 1208, 1210, 1209, 1212, 1189, 1213, 1141, 1132, 1220, + /* 340 */ 1221, 1216, 1145, 1207, 1199, 1223, 1201, 1115, 1152, 1229, + /* 350 */ 1246, 1241, 1252, 1153, 1194, 1195, 1134, 1237, 1146, 1240, + /* 360 */ 1147, 1159, 1142, 1245, 1247, 1251, 1211, 1135, 1131, 1267, + /* 370 */ 1268, }; -#define YY_REDUCE_USE_DFLT (-61) +#define YY_REDUCE_USE_DFLT (-216) +#define YY_REDUCE_MAX 278 static const short yy_reduce_ofst[] = { - /* 0 */ -48, 61, -61, -61, -60, -61, -61, -61, -32, 12, - /* 10 */ -61, 181, -61, -61, -61, -61, -61, -61, -61, 314, - /* 20 */ -61, 386, -61, 622, -61, 654, -61, 51, 798, -61, - /* 30 */ -61, -23, -61, -26, 760, 89, -61, 860, 486, -61, - /* 40 */ 867, -61, -61, 65, -61, -61, -61, -61, -61, -61, - /* 50 */ -61, -61, 909, -61, 910, -61, -61, -61, -61, -61, - /* 60 */ 914, 962, 964, -61, -61, -61, -61, 968, -61, -61, - /* 70 */ 438, -61, 996, -61, -61, 116, -61, -61, -61, 293, - /* 80 */ -61, 1000, 1006, -61, 1011, 569, 1005, 1026, 1034, 1035, - /* 90 */ 1036, 1041, -61, 490, 394, 552, 394, 601, -61, -61, - /* 100 */ 1087, -61, 1093, -61, -61, -61, -61, -61, -61, -61, - /* 110 */ 603, 394, 53, -61, -61, 1082, 110, -61, -61, 229, - /* 120 */ -61, -61, -61, -61, 1019, -61, -61, -61, 1020, -61, - /* 130 */ -61, -61, -61, -61, -61, 640, -61, 394, 651, 394, - /* 140 */ 690, 394, 701, 394, 703, 394, 740, 394, 751, 394, - /* 150 */ 753, 394, 755, 394, 790, 394, 801, 394, 803, 394, - /* 160 */ 818, 394, 829, 394, 831, 394, 835, 394, 841, 394, - /* 170 */ -61, -61, -61, -61, -61, -61, 846, 188, 849, 394, - /* 180 */ -61, -61, -61, -61, -61, -61, -61, 879, 394, 881, - /* 190 */ 394, -61, 1102, -6, 1000, -61, -61, -61, -61, -61, - /* 200 */ 394, 887, 394, 898, 394, 918, 394, 936, 394, -61, - /* 210 */ 662, 1000, -61, 295, 394, 1037, 1039, -61, -61, 946, - /* 220 */ 394, 948, 394, -61, 1073, -61, -61, -61, 1114, -61, - /* 230 */ -61, 950, 394, 956, 394, 974, 394, -61, -61, 303, - /* 240 */ -61, -61, 1118, 1124, -61, -61, -61, 394, 984, 394, - /* 250 */ -61, 183, -61, 190, 1065, 1104, -61, 1119, -61, -61, - /* 260 */ 394, 1070, 1109, -61, 987, 394, -61, 187, -61, 1007, - /* 270 */ 394, -61, 398, 1083, -61, -61, -61, 1136, -61, 1138, - /* 280 */ -61, -61, -61, 1143, 1137, 389, 1144, -61, -61, 1090, - /* 290 */ 1094, -61, -61, 604, -61, -61, 1147, -61, -61, 1015, - /* 300 */ 394, 132, 1000, 1083, -61, 512, 1096, 1097, -61, 1018, - /* 310 */ 241, -61, -61, -61, 1087, -61, -61, 394, -61, -61, - /* 320 */ -61, -61, -61, 394, 1131, -61, 1155, 1132, 1130, 1133, - /* 330 */ -61, 1159, -61, -61, 1134, -61, -61, -61, -61, -61, - /* 340 */ -61, 1135, -61, 1139, -61, 439, -61, -61, 765, 1098, - /* 350 */ 1146, -61, -61, 1099, 1149, -61, -61, 1151, -61, 1145, - /* 360 */ -61, -61, 692, -61, 1022, 394, -61, 1150, -61, -61, - /* 370 */ 1153, -61, -61, -61, -61, 1156, 1158, -61, 1166, -61, - /* 380 */ -61, -61, 899, 1160, -61, 1161, -61, -61, 949, -61, - /* 390 */ 1163, -61, 1030, 375, -61, -61, -61, 979, -61, -61, - /* 400 */ 1180, 1162, 1168, 527, -61, -61, -61, -61, -61, -61, - /* 410 */ 712, 1000, 756, -61, 1181, 1179, -61, 1187, 1186, -61, - /* 420 */ 807, 1000, 1193, 1190, 1115, 1113, -61, 715, 1195, -61, - /* 430 */ 1117, 1120, -61, 1048, 394, -61, -61, -61, -61, -61, - /* 440 */ -61, -61, 709, -61, -61, -61, -61, -61, -61, -61, - /* 450 */ 1209, 1206, -61, 1211, -61, 997, -61, 1192, -61, -61, - /* 460 */ -61, 315, 1000, 1183, 732, -61, -61, -61, -61, -61, - /* 470 */ -61, 382, -61, 1191, 1228, -61, 808, 1185, 1232, -61, - /* 480 */ 1055, 394, -61, -61, 1064, 394, -61, 1236, 1171, 767, - /* 490 */ -61, -61, 854, 1000, -61, -18, -61, 1067, 394, -61, - /* 500 */ 394, -61, 1248, 1196, -61, -61, 815, -61, 891, -61, - /* 510 */ 895, -61, 906, -61, 1000, -61, 942, 1202, -61, 1215, - /* 520 */ 943, -61, 959, 1207, -61, -61, 975, 1194, 985, 1000, - /* 530 */ -61, 434, -61, -61, 1259, -61, 1262, 1257, -61, 435, - /* 540 */ -61, -61, -61, -61, 1267, -61, -61, 1188, 1263, -61, - /* 550 */ 1273, 1197, -61, 1264, -61, -61, -61, 1199, 1279, -61, - /* 560 */ 1284, 1278, -61, 1287, 1286, -61, -61, 522, -61, -61, - /* 570 */ 1291, -61, -61, 1204, -58, -61, -61, -61, -61, -61, - /* 580 */ -61, + /* 0 */ -56, 136, 16, 70, 189, 127, 66, 130, 190, 219, + /* 10 */ 255, 220, 61, 132, 138, 210, 265, 271, -178, -140, + /* 20 */ -61, 79, 145, 264, -215, -215, -215, -215, -215, -215, + /* 30 */ -215, -215, -215, -215, -215, -215, -215, -215, -215, -215, + /* 40 */ -215, -215, -215, -215, -215, -215, -215, -215, -215, -215, + /* 50 */ -215, -215, -215, -215, -215, 402, 405, 407, 416, 418, + /* 60 */ 456, 472, 474, 476, 480, 482, 484, 523, 535, 540, + /* 70 */ 542, 544, 547, 549, 551, 590, 602, 606, 608, 610, + /* 80 */ 614, 618, 657, 669, 673, 675, 677, 681, 686, 724, + /* 90 */ 736, 740, 742, 744, -215, -215, -77, -215, -215, -215, + /* 100 */ -215, 50, 354, 473, 541, 603, 144, 604, 772, 342, + /* 110 */ 284, -215, -215, -215, -215, 282, 251, 322, 462, -72, + /* 120 */ 177, 306, 428, 353, 193, 475, 421, 477, 509, 575, + /* 130 */ 707, 750, 768, 771, 556, 769, 663, 733, 765, 807, + /* 140 */ 808, -42, 499, -126, -112, -57, -19, 18, 96, 18, + /* 150 */ 18, 72, 141, 146, 198, 250, 223, 336, 370, 373, + /* 160 */ 250, 543, 534, 561, 607, 563, 623, 626, 18, 563, + /* 170 */ 634, 690, 662, 670, 679, 706, 739, 18, 760, 777, + /* 180 */ 18, 802, 730, 749, 847, 855, 18, 857, 858, 866, + /* 190 */ 18, 867, 18, 18, 870, 871, 872, 873, 874, 880, + /* 200 */ 863, 844, 831, 832, 800, 801, 803, 859, 860, 853, + /* 210 */ 861, 864, 862, 843, 845, 895, 896, 897, 898, 892, + /* 220 */ 877, 881, 885, 884, 883, 886, 887, 890, 891, 893, + /* 230 */ 868, 894, 846, 923, 882, 931, 899, 942, 901, 902, + /* 240 */ 904, 906, 935, 903, 910, 953, 927, 955, 956, 961, + /* 250 */ 950, 983, 981, 985, 986, 987, 914, 911, 997, 1000, + /* 260 */ 972, 973, 947, 965, 974, 976, 979, 970, 984, 958, + /* 270 */ 1017, 940, 957, 1019, 1025, 959, 1020, 1005, 1006, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 587, 587, 582, 585, 892, 892, 892, 586, 594, 892, - /* 10 */ 892, 892, 892, 614, 615, 616, 595, 596, 597, 892, - /* 20 */ 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, - /* 30 */ 892, 892, 607, 617, 627, 609, 626, 892, 892, 628, - /* 40 */ 672, 635, 892, 892, 673, 676, 677, 678, 872, 873, - /* 50 */ 874, 892, 672, 636, 657, 655, 892, 658, 659, 892, - /* 60 */ 728, 672, 643, 637, 644, 726, 727, 672, 638, 892, - /* 70 */ 892, 758, 692, 690, 691, 824, 764, 759, 755, 892, - /* 80 */ 683, 892, 892, 684, 692, 694, 701, 740, 731, 733, - /* 90 */ 721, 735, 689, 892, 736, 892, 737, 892, 757, 892, - /* 100 */ 892, 760, 892, 761, 762, 763, 765, 766, 767, 892, - /* 110 */ 892, 892, 892, 612, 613, 619, 847, 892, 620, 847, - /* 120 */ 892, 621, 624, 625, 892, 842, 844, 845, 892, 843, - /* 130 */ 846, 623, 622, 892, 768, 892, 771, 773, 892, 774, - /* 140 */ 892, 775, 892, 776, 892, 777, 892, 778, 892, 779, - /* 150 */ 892, 780, 892, 781, 892, 782, 892, 783, 892, 784, - /* 160 */ 892, 785, 892, 786, 892, 787, 892, 788, 892, 789, - /* 170 */ 790, 892, 791, 798, 805, 808, 892, 793, 892, 792, - /* 180 */ 795, 892, 796, 892, 799, 797, 804, 892, 892, 892, - /* 190 */ 806, 807, 892, 824, 892, 892, 892, 892, 892, 811, - /* 200 */ 823, 892, 800, 892, 801, 892, 802, 892, 803, 892, - /* 210 */ 892, 892, 813, 892, 892, 892, 892, 892, 814, 892, - /* 220 */ 892, 892, 815, 892, 892, 892, 870, 892, 892, 892, - /* 230 */ 871, 892, 892, 892, 892, 892, 816, 892, 809, 824, - /* 240 */ 821, 822, 709, 892, 710, 812, 794, 772, 892, 738, - /* 250 */ 892, 892, 722, 892, 729, 728, 723, 892, 611, 730, - /* 260 */ 725, 729, 728, 724, 892, 734, 892, 824, 732, 892, - /* 270 */ 741, 693, 704, 702, 703, 712, 713, 892, 714, 892, - /* 280 */ 715, 892, 716, 892, 709, 700, 892, 698, 699, 718, - /* 290 */ 720, 705, 892, 892, 892, 719, 892, 753, 754, 892, - /* 300 */ 717, 704, 892, 892, 892, 700, 718, 720, 706, 892, - /* 310 */ 700, 695, 696, 892, 892, 697, 810, 892, 756, 892, - /* 320 */ 769, 892, 770, 892, 672, 639, 892, 828, 645, 640, - /* 330 */ 646, 892, 647, 892, 892, 648, 892, 651, 652, 653, - /* 340 */ 654, 892, 649, 892, 650, 892, 892, 829, 892, 729, - /* 350 */ 728, 830, 832, 729, 728, 831, 641, 892, 642, 657, - /* 360 */ 656, 629, 892, 630, 892, 892, 631, 892, 632, 764, - /* 370 */ 892, 633, 634, 618, 610, 892, 892, 662, 892, 665, - /* 380 */ 892, 892, 892, 892, 892, 672, 666, 892, 892, 892, - /* 390 */ 672, 667, 892, 672, 668, 892, 892, 892, 892, 892, - /* 400 */ 892, 828, 645, 670, 892, 669, 671, 663, 664, 608, - /* 410 */ 892, 892, 604, 892, 892, 709, 602, 892, 892, 892, - /* 420 */ 892, 892, 892, 709, 853, 892, 892, 892, 709, 711, - /* 430 */ 858, 892, 892, 892, 892, 892, 892, 859, 860, 892, - /* 440 */ 892, 892, 892, 892, 850, 851, 892, 852, 603, 892, - /* 450 */ 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, - /* 460 */ 892, 892, 892, 892, 892, 675, 892, 892, 892, 892, - /* 470 */ 892, 892, 892, 674, 892, 892, 892, 892, 892, 892, - /* 480 */ 892, 743, 892, 892, 892, 744, 892, 892, 751, 892, - /* 490 */ 892, 752, 892, 892, 892, 892, 892, 892, 749, 892, - /* 500 */ 750, 892, 892, 892, 892, 892, 892, 892, 892, 892, - /* 510 */ 892, 892, 892, 892, 892, 892, 892, 892, 892, 674, - /* 520 */ 892, 892, 892, 892, 892, 892, 892, 751, 892, 892, - /* 530 */ 892, 892, 892, 892, 892, 892, 892, 709, 892, 847, - /* 540 */ 892, 892, 892, 892, 892, 892, 892, 881, 892, 892, - /* 550 */ 892, 892, 892, 892, 892, 892, 880, 881, 892, 892, - /* 560 */ 892, 892, 892, 892, 892, 892, 892, 892, 892, 892, - /* 570 */ 892, 892, 892, 890, 892, 892, 891, 588, 892, 589, - /* 580 */ 583, + /* 0 */ 566, 790, 855, 681, 855, 790, 855, 790, 855, 828, + /* 10 */ 828, 685, 841, 786, 790, 855, 855, 855, 761, 812, + /* 20 */ 855, 597, 812, 812, 716, 855, 855, 855, 855, 855, + /* 30 */ 855, 855, 855, 717, 855, 789, 785, 781, 783, 782, + /* 40 */ 718, 705, 714, 721, 697, 826, 723, 724, 729, 730, + /* 50 */ 842, 845, 751, 767, 750, 855, 855, 855, 855, 855, + /* 60 */ 855, 855, 855, 855, 855, 855, 855, 855, 855, 855, + /* 70 */ 855, 855, 855, 855, 855, 855, 855, 855, 855, 855, + /* 80 */ 855, 855, 855, 855, 855, 855, 855, 855, 855, 855, + /* 90 */ 855, 855, 855, 855, 753, 772, 590, 752, 760, 754, + /* 100 */ 755, 650, 855, 855, 855, 855, 585, 855, 855, 855, + /* 110 */ 855, 756, 757, 768, 769, 855, 855, 855, 855, 566, + /* 120 */ 681, 855, 681, 855, 855, 855, 855, 855, 855, 855, + /* 130 */ 855, 855, 855, 855, 855, 855, 855, 855, 855, 855, + /* 140 */ 855, 675, 685, 855, 855, 641, 855, 855, 855, 855, + /* 150 */ 855, 855, 855, 855, 855, 855, 573, 571, 855, 673, + /* 160 */ 855, 855, 599, 855, 855, 683, 855, 855, 688, 689, + /* 170 */ 855, 855, 855, 855, 855, 855, 855, 587, 855, 855, + /* 180 */ 662, 855, 818, 855, 855, 855, 833, 855, 855, 855, + /* 190 */ 831, 855, 664, 726, 800, 855, 855, 846, 848, 855, + /* 200 */ 855, 708, 673, 682, 855, 855, 784, 708, 708, 620, + /* 210 */ 708, 708, 623, 720, 720, 570, 570, 570, 570, 640, + /* 220 */ 652, 652, 637, 652, 623, 652, 855, 720, 711, 713, + /* 230 */ 701, 715, 855, 690, 709, 855, 709, 690, 698, 700, + /* 240 */ 698, 700, 794, 709, 709, 855, 637, 652, 652, 652, + /* 250 */ 794, 582, 690, 690, 690, 690, 822, 825, 582, 690, + /* 260 */ 654, 654, 731, 720, 661, 661, 661, 720, 654, 731, + /* 270 */ 690, 844, 844, 690, 690, 853, 607, 625, 625, 855, + /* 280 */ 855, 855, 855, 855, 855, 738, 855, 855, 855, 855, + /* 290 */ 855, 855, 855, 855, 855, 855, 855, 855, 855, 855, + /* 300 */ 807, 855, 855, 855, 855, 855, 743, 739, 855, 740, + /* 310 */ 855, 855, 855, 855, 667, 855, 855, 855, 855, 855, + /* 320 */ 855, 855, 702, 855, 712, 855, 855, 855, 855, 855, + /* 330 */ 855, 855, 855, 855, 855, 855, 855, 855, 855, 855, + /* 340 */ 855, 855, 855, 855, 820, 821, 855, 855, 855, 855, + /* 350 */ 855, 855, 855, 855, 855, 855, 855, 855, 855, 855, + /* 360 */ 855, 855, 855, 855, 855, 855, 852, 855, 855, 567, + /* 370 */ 855, 561, 564, 563, 565, 569, 572, 594, 595, 596, + /* 380 */ 574, 575, 576, 577, 578, 579, 580, 586, 588, 606, + /* 390 */ 608, 615, 653, 656, 657, 658, 836, 837, 838, 616, + /* 400 */ 635, 638, 639, 617, 624, 706, 707, 618, 671, 672, + /* 410 */ 735, 665, 666, 670, 737, 741, 742, 744, 745, 593, + /* 420 */ 600, 601, 604, 605, 808, 810, 809, 811, 603, 602, + /* 430 */ 746, 749, 758, 759, 765, 771, 774, 763, 764, 766, + /* 440 */ 770, 773, 668, 669, 777, 779, 780, 834, 835, 775, + /* 450 */ 787, 788, 691, 778, 762, 703, 592, 710, 704, 674, + /* 460 */ 684, 693, 694, 695, 696, 679, 680, 686, 699, 733, + /* 470 */ 734, 687, 676, 677, 678, 776, 736, 747, 748, 619, + /* 480 */ 626, 627, 628, 631, 632, 633, 634, 629, 630, 795, + /* 490 */ 796, 798, 797, 621, 622, 636, 609, 610, 611, 612, + /* 500 */ 743, 613, 614, 598, 591, 642, 645, 646, 647, 648, + /* 510 */ 649, 651, 643, 644, 589, 581, 583, 692, 814, 823, + /* 520 */ 824, 819, 815, 816, 817, 584, 791, 792, 655, 727, + /* 530 */ 728, 813, 827, 829, 732, 830, 832, 659, 660, 663, + /* 540 */ 799, 839, 719, 722, 725, 801, 802, 803, 804, 805, + /* 550 */ 806, 840, 843, 847, 849, 850, 851, 854, 568, 562, }; #define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0])) @@ -670,75 +581,66 @@ static const YYACTIONTYPE yy_default[] = { #ifdef YYFALLBACK static const YYCODETYPE yyFallback[] = { 0, /* $ => nothing */ - 0, /* END_OF_FILE => nothing */ - 0, /* ILLEGAL => nothing */ - 0, /* SPACE => nothing */ - 0, /* UNCLOSED_STRING => nothing */ - 0, /* COMMENT => nothing */ - 0, /* FUNCTION => nothing */ - 0, /* COLUMN => nothing */ - 0, /* AGG_FUNCTION => nothing */ - 0, /* AGG_COLUMN => nothing */ - 0, /* CONST_FUNC => nothing */ 0, /* SEMI => nothing */ - 30, /* EXPLAIN => ID */ - 30, /* QUERY => ID */ - 30, /* PLAN => ID */ - 30, /* BEGIN => ID */ + 23, /* EXPLAIN => ID */ + 23, /* QUERY => ID */ + 23, /* PLAN => ID */ + 23, /* BEGIN => ID */ 0, /* TRANSACTION => nothing */ - 30, /* DEFERRED => ID */ - 30, /* IMMEDIATE => ID */ - 30, /* EXCLUSIVE => ID */ + 23, /* DEFERRED => ID */ + 23, /* IMMEDIATE => ID */ + 23, /* EXCLUSIVE => ID */ 0, /* COMMIT => nothing */ - 30, /* END => ID */ + 23, /* END => ID */ 0, /* ROLLBACK => nothing */ 0, /* CREATE => nothing */ 0, /* TABLE => nothing */ - 30, /* TEMP => ID */ + 23, /* IF => ID */ + 0, /* NOT => nothing */ + 0, /* EXISTS => nothing */ + 23, /* TEMP => ID */ 0, /* LP => nothing */ 0, /* RP => nothing */ 0, /* AS => nothing */ 0, /* COMMA => nothing */ 0, /* ID => nothing */ - 30, /* ABORT => ID */ - 30, /* AFTER => ID */ - 30, /* ANALYZE => ID */ - 30, /* ASC => ID */ - 30, /* ATTACH => ID */ - 30, /* BEFORE => ID */ - 30, /* CASCADE => ID */ - 30, /* CAST => ID */ - 30, /* CONFLICT => ID */ - 30, /* DATABASE => ID */ - 30, /* DESC => ID */ - 30, /* DETACH => ID */ - 30, /* EACH => ID */ - 30, /* FAIL => ID */ - 30, /* FOR => ID */ - 30, /* IGNORE => ID */ - 30, /* INITIALLY => ID */ - 30, /* INSTEAD => ID */ - 30, /* LIKE_KW => ID */ - 30, /* MATCH => ID */ - 30, /* KEY => ID */ - 30, /* OF => ID */ - 30, /* OFFSET => ID */ - 30, /* PRAGMA => ID */ - 30, /* RAISE => ID */ - 30, /* REPLACE => ID */ - 30, /* RESTRICT => ID */ - 30, /* ROW => ID */ - 30, /* STATEMENT => ID */ - 30, /* TRIGGER => ID */ - 30, /* VACUUM => ID */ - 30, /* VIEW => ID */ - 30, /* REINDEX => ID */ - 30, /* RENAME => ID */ - 30, /* CTIME_KW => ID */ - 30, /* ALTER => ID */ + 23, /* ABORT => ID */ + 23, /* AFTER => ID */ + 23, /* ANALYZE => ID */ + 23, /* ASC => ID */ + 23, /* ATTACH => ID */ + 23, /* BEFORE => ID */ + 23, /* CASCADE => ID */ + 23, /* CAST => ID */ + 23, /* CONFLICT => ID */ + 23, /* DATABASE => ID */ + 23, /* DESC => ID */ + 23, /* DETACH => ID */ + 23, /* EACH => ID */ + 23, /* FAIL => ID */ + 23, /* FOR => ID */ + 23, /* IGNORE => ID */ + 23, /* INITIALLY => ID */ + 23, /* INSTEAD => ID */ + 23, /* LIKE_KW => ID */ + 23, /* MATCH => ID */ + 23, /* KEY => ID */ + 23, /* OF => ID */ + 23, /* OFFSET => ID */ + 23, /* PRAGMA => ID */ + 23, /* RAISE => ID */ + 23, /* REPLACE => ID */ + 23, /* RESTRICT => ID */ + 23, /* ROW => ID */ + 23, /* STATEMENT => ID */ + 23, /* TRIGGER => ID */ + 23, /* VACUUM => ID */ + 23, /* VIEW => ID */ + 23, /* REINDEX => ID */ + 23, /* RENAME => ID */ + 23, /* CTIME_KW => ID */ 0, /* OR => nothing */ 0, /* AND => nothing */ - 0, /* NOT => nothing */ 0, /* IS => nothing */ 0, /* BETWEEN => nothing */ 0, /* IN => nothing */ @@ -785,8 +687,8 @@ static const YYCODETYPE yyFallback[] = { 0, /* DROP => nothing */ 0, /* UNION => nothing */ 0, /* ALL => nothing */ - 0, /* INTERSECT => nothing */ 0, /* EXCEPT => nothing */ + 0, /* INTERSECT => nothing */ 0, /* SELECT => nothing */ 0, /* DISTINCT => nothing */ 0, /* DOT => nothing */ @@ -806,12 +708,12 @@ static const YYCODETYPE yyFallback[] = { 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, /* ALTER => nothing */ 0, /* TO => nothing */ 0, /* ADD => nothing */ 0, /* COLUMNKW => nothing */ @@ -885,46 +787,44 @@ void sqlite3ParserTrace(FILE *TraceFILE, char *zTracePrompt){ /* For tracing shifts, the names of all terminals and nonterminals ** are required. The following table supplies these names */ static const char *const yyTokenName[] = { - "$", "END_OF_FILE", "ILLEGAL", "SPACE", - "UNCLOSED_STRING", "COMMENT", "FUNCTION", "COLUMN", - "AGG_FUNCTION", "AGG_COLUMN", "CONST_FUNC", "SEMI", - "EXPLAIN", "QUERY", "PLAN", "BEGIN", - "TRANSACTION", "DEFERRED", "IMMEDIATE", "EXCLUSIVE", - "COMMIT", "END", "ROLLBACK", "CREATE", - "TABLE", "TEMP", "LP", "RP", - "AS", "COMMA", "ID", "ABORT", - "AFTER", "ANALYZE", "ASC", "ATTACH", - "BEFORE", "CASCADE", "CAST", "CONFLICT", - "DATABASE", "DESC", "DETACH", "EACH", - "FAIL", "FOR", "IGNORE", "INITIALLY", - "INSTEAD", "LIKE_KW", "MATCH", "KEY", - "OF", "OFFSET", "PRAGMA", "RAISE", - "REPLACE", "RESTRICT", "ROW", "STATEMENT", - "TRIGGER", "VACUUM", "VIEW", "REINDEX", - "RENAME", "CTIME_KW", "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", "DISTINCT", - "DOT", "FROM", "JOIN", "USING", - "ORDER", "BY", "GROUP", "HAVING", - "LIMIT", "WHERE", "INTO", "VALUES", - "INTEGER", "FLOAT", "BLOB", "REGISTER", - "VARIABLE", "EXISTS", "CASE", "WHEN", - "THEN", "ELSE", "INDEX", "TO", - "ADD", "COLUMNKW", "error", "input", - "cmdlist", "ecmd", "cmdx", "cmd", - "explain", "transtype", "trans_opt", "nm", - "create_table", "create_table_args", "temp", "dbnm", + "$", "SEMI", "EXPLAIN", "QUERY", + "PLAN", "BEGIN", "TRANSACTION", "DEFERRED", + "IMMEDIATE", "EXCLUSIVE", "COMMIT", "END", + "ROLLBACK", "CREATE", "TABLE", "IF", + "NOT", "EXISTS", "TEMP", "LP", + "RP", "AS", "COMMA", "ID", + "ABORT", "AFTER", "ANALYZE", "ASC", + "ATTACH", "BEFORE", "CASCADE", "CAST", + "CONFLICT", "DATABASE", "DESC", "DETACH", + "EACH", "FAIL", "FOR", "IGNORE", + "INITIALLY", "INSTEAD", "LIKE_KW", "MATCH", + "KEY", "OF", "OFFSET", "PRAGMA", + "RAISE", "REPLACE", "RESTRICT", "ROW", + "STATEMENT", "TRIGGER", "VACUUM", "VIEW", + "REINDEX", "RENAME", "CTIME_KW", "OR", + "AND", "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", "EXCEPT", + "INTERSECT", "SELECT", "DISTINCT", "DOT", + "FROM", "JOIN", "USING", "ORDER", + "BY", "GROUP", "HAVING", "LIMIT", + "WHERE", "INTO", "VALUES", "INTEGER", + "FLOAT", "BLOB", "REGISTER", "VARIABLE", + "CASE", "WHEN", "THEN", "ELSE", + "INDEX", "ALTER", "TO", "ADD", + "COLUMNKW", "error", "input", "cmdlist", + "ecmd", "cmdx", "cmd", "explain", + "transtype", "trans_opt", "nm", "create_table", + "create_table_args", "temp", "ifnotexists", "dbnm", "columnlist", "conslist_opt", "select", "column", "columnid", "type", "carglist", "id", "ids", "typetoken", "typename", "signed", @@ -933,20 +833,20 @@ static const char *const yyTokenName[] = { "autoinc", "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", - "add_column_fullname", "kwcolumn_opt", + "resolvetype", "raisetype", "ifexists", "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", "add_column_fullname", "kwcolumn_opt", }; #endif /* NDEBUG */ @@ -975,296 +875,280 @@ static const char *const yyRuleName[] = { /* 18 */ "cmd ::= END trans_opt", /* 19 */ "cmd ::= ROLLBACK trans_opt", /* 20 */ "cmd ::= create_table create_table_args", - /* 21 */ "create_table ::= CREATE temp TABLE nm dbnm", - /* 22 */ "temp ::= TEMP", - /* 23 */ "temp ::=", - /* 24 */ "create_table_args ::= LP columnlist conslist_opt RP", - /* 25 */ "create_table_args ::= AS select", - /* 26 */ "columnlist ::= columnlist COMMA column", - /* 27 */ "columnlist ::= column", - /* 28 */ "column ::= columnid type carglist", - /* 29 */ "columnid ::= nm", - /* 30 */ "id ::= ID", - /* 31 */ "ids ::= ID", - /* 32 */ "ids ::= STRING", - /* 33 */ "nm ::= ID", - /* 34 */ "nm ::= STRING", - /* 35 */ "nm ::= JOIN_KW", - /* 36 */ "type ::=", - /* 37 */ "type ::= typetoken", - /* 38 */ "typetoken ::= typename", - /* 39 */ "typetoken ::= typename LP signed RP", - /* 40 */ "typetoken ::= typename LP signed COMMA signed RP", - /* 41 */ "typename ::= ids", - /* 42 */ "typename ::= typename ids", - /* 43 */ "signed ::= plus_num", - /* 44 */ "signed ::= minus_num", - /* 45 */ "carglist ::= carglist carg", - /* 46 */ "carglist ::=", - /* 47 */ "carg ::= CONSTRAINT nm ccons", - /* 48 */ "carg ::= ccons", - /* 49 */ "carg ::= DEFAULT term", - /* 50 */ "carg ::= DEFAULT LP expr RP", - /* 51 */ "carg ::= DEFAULT PLUS term", - /* 52 */ "carg ::= DEFAULT MINUS term", - /* 53 */ "carg ::= DEFAULT id", - /* 54 */ "ccons ::= NULL onconf", - /* 55 */ "ccons ::= NOT NULL onconf", - /* 56 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc", - /* 57 */ "ccons ::= UNIQUE onconf", - /* 58 */ "ccons ::= CHECK LP expr RP onconf", - /* 59 */ "ccons ::= REFERENCES nm idxlist_opt refargs", - /* 60 */ "ccons ::= defer_subclause", - /* 61 */ "ccons ::= COLLATE id", - /* 62 */ "autoinc ::=", - /* 63 */ "autoinc ::= AUTOINCR", - /* 64 */ "refargs ::=", - /* 65 */ "refargs ::= refargs refarg", - /* 66 */ "refarg ::= MATCH nm", - /* 67 */ "refarg ::= ON DELETE refact", - /* 68 */ "refarg ::= ON UPDATE refact", - /* 69 */ "refarg ::= ON INSERT refact", - /* 70 */ "refact ::= SET NULL", - /* 71 */ "refact ::= SET DEFAULT", - /* 72 */ "refact ::= CASCADE", - /* 73 */ "refact ::= RESTRICT", - /* 74 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt", - /* 75 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt", - /* 76 */ "init_deferred_pred_opt ::=", - /* 77 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED", - /* 78 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE", - /* 79 */ "conslist_opt ::=", - /* 80 */ "conslist_opt ::= COMMA conslist", - /* 81 */ "conslist ::= conslist COMMA tcons", - /* 82 */ "conslist ::= conslist tcons", - /* 83 */ "conslist ::= tcons", - /* 84 */ "tcons ::= CONSTRAINT nm", - /* 85 */ "tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf", - /* 86 */ "tcons ::= UNIQUE LP idxlist RP onconf", - /* 87 */ "tcons ::= CHECK expr onconf", - /* 88 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt", - /* 89 */ "defer_subclause_opt ::=", - /* 90 */ "defer_subclause_opt ::= defer_subclause", - /* 91 */ "onconf ::=", - /* 92 */ "onconf ::= ON CONFLICT resolvetype", - /* 93 */ "orconf ::=", - /* 94 */ "orconf ::= OR resolvetype", - /* 95 */ "resolvetype ::= raisetype", - /* 96 */ "resolvetype ::= IGNORE", - /* 97 */ "resolvetype ::= REPLACE", - /* 98 */ "cmd ::= DROP TABLE fullname", - /* 99 */ "cmd ::= CREATE temp VIEW nm dbnm AS select", - /* 100 */ "cmd ::= DROP VIEW fullname", - /* 101 */ "cmd ::= select", - /* 102 */ "select ::= oneselect", - /* 103 */ "select ::= select multiselect_op oneselect", - /* 104 */ "multiselect_op ::= UNION", - /* 105 */ "multiselect_op ::= UNION ALL", - /* 106 */ "multiselect_op ::= INTERSECT", - /* 107 */ "multiselect_op ::= EXCEPT", - /* 108 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt", - /* 109 */ "distinct ::= DISTINCT", - /* 110 */ "distinct ::= ALL", - /* 111 */ "distinct ::=", - /* 112 */ "sclp ::= selcollist COMMA", - /* 113 */ "sclp ::=", - /* 114 */ "selcollist ::= sclp expr as", - /* 115 */ "selcollist ::= sclp STAR", - /* 116 */ "selcollist ::= sclp nm DOT STAR", - /* 117 */ "as ::= AS nm", - /* 118 */ "as ::= ids", - /* 119 */ "as ::=", - /* 120 */ "from ::=", - /* 121 */ "from ::= FROM seltablist", - /* 122 */ "stl_prefix ::= seltablist joinop", - /* 123 */ "stl_prefix ::=", - /* 124 */ "seltablist ::= stl_prefix nm dbnm as on_opt using_opt", - /* 125 */ "seltablist ::= stl_prefix LP seltablist_paren RP as on_opt using_opt", - /* 126 */ "seltablist_paren ::= select", - /* 127 */ "seltablist_paren ::= seltablist", - /* 128 */ "dbnm ::=", - /* 129 */ "dbnm ::= DOT nm", - /* 130 */ "fullname ::= nm dbnm", - /* 131 */ "joinop ::= COMMA", - /* 132 */ "joinop ::= JOIN", - /* 133 */ "joinop ::= JOIN_KW JOIN", - /* 134 */ "joinop ::= JOIN_KW nm JOIN", - /* 135 */ "joinop ::= JOIN_KW nm nm JOIN", - /* 136 */ "on_opt ::= ON expr", - /* 137 */ "on_opt ::=", - /* 138 */ "using_opt ::= USING LP inscollist RP", - /* 139 */ "using_opt ::=", - /* 140 */ "orderby_opt ::=", - /* 141 */ "orderby_opt ::= ORDER BY sortlist", - /* 142 */ "sortlist ::= sortlist COMMA sortitem collate sortorder", - /* 143 */ "sortlist ::= sortitem collate sortorder", - /* 144 */ "sortitem ::= expr", - /* 145 */ "sortorder ::= ASC", - /* 146 */ "sortorder ::= DESC", - /* 147 */ "sortorder ::=", - /* 148 */ "collate ::=", - /* 149 */ "collate ::= COLLATE id", - /* 150 */ "groupby_opt ::=", - /* 151 */ "groupby_opt ::= GROUP BY exprlist", - /* 152 */ "having_opt ::=", - /* 153 */ "having_opt ::= HAVING expr", - /* 154 */ "limit_opt ::=", - /* 155 */ "limit_opt ::= LIMIT expr", - /* 156 */ "limit_opt ::= LIMIT expr OFFSET expr", - /* 157 */ "limit_opt ::= LIMIT expr COMMA expr", - /* 158 */ "cmd ::= DELETE FROM fullname where_opt", - /* 159 */ "where_opt ::=", - /* 160 */ "where_opt ::= WHERE expr", - /* 161 */ "cmd ::= UPDATE orconf fullname SET setlist where_opt", - /* 162 */ "setlist ::= setlist COMMA nm EQ expr", - /* 163 */ "setlist ::= nm EQ expr", - /* 164 */ "cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP", - /* 165 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select", - /* 166 */ "insert_cmd ::= INSERT orconf", - /* 167 */ "insert_cmd ::= REPLACE", - /* 168 */ "itemlist ::= itemlist COMMA expr", - /* 169 */ "itemlist ::= expr", - /* 170 */ "inscollist_opt ::=", - /* 171 */ "inscollist_opt ::= LP inscollist RP", - /* 172 */ "inscollist ::= inscollist COMMA nm", - /* 173 */ "inscollist ::= nm", - /* 174 */ "expr ::= term", - /* 175 */ "expr ::= LP expr RP", - /* 176 */ "term ::= NULL", - /* 177 */ "expr ::= ID", - /* 178 */ "expr ::= JOIN_KW", - /* 179 */ "expr ::= nm DOT nm", - /* 180 */ "expr ::= nm DOT nm DOT nm", - /* 181 */ "term ::= INTEGER", - /* 182 */ "term ::= FLOAT", + /* 21 */ "create_table ::= CREATE temp TABLE ifnotexists nm dbnm", + /* 22 */ "ifnotexists ::=", + /* 23 */ "ifnotexists ::= IF NOT EXISTS", + /* 24 */ "temp ::= TEMP", + /* 25 */ "temp ::=", + /* 26 */ "create_table_args ::= LP columnlist conslist_opt RP", + /* 27 */ "create_table_args ::= AS select", + /* 28 */ "columnlist ::= columnlist COMMA column", + /* 29 */ "columnlist ::= column", + /* 30 */ "column ::= columnid type carglist", + /* 31 */ "columnid ::= nm", + /* 32 */ "id ::= ID", + /* 33 */ "ids ::= ID|STRING", + /* 34 */ "nm ::= ID", + /* 35 */ "nm ::= STRING", + /* 36 */ "nm ::= JOIN_KW", + /* 37 */ "type ::=", + /* 38 */ "type ::= typetoken", + /* 39 */ "typetoken ::= typename", + /* 40 */ "typetoken ::= typename LP signed RP", + /* 41 */ "typetoken ::= typename LP signed COMMA signed RP", + /* 42 */ "typename ::= ids", + /* 43 */ "typename ::= typename ids", + /* 44 */ "signed ::= plus_num", + /* 45 */ "signed ::= minus_num", + /* 46 */ "carglist ::= carglist carg", + /* 47 */ "carglist ::=", + /* 48 */ "carg ::= CONSTRAINT nm ccons", + /* 49 */ "carg ::= ccons", + /* 50 */ "carg ::= DEFAULT term", + /* 51 */ "carg ::= DEFAULT LP expr RP", + /* 52 */ "carg ::= DEFAULT PLUS term", + /* 53 */ "carg ::= DEFAULT MINUS term", + /* 54 */ "carg ::= DEFAULT id", + /* 55 */ "ccons ::= NULL onconf", + /* 56 */ "ccons ::= NOT NULL onconf", + /* 57 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc", + /* 58 */ "ccons ::= UNIQUE onconf", + /* 59 */ "ccons ::= CHECK LP expr RP", + /* 60 */ "ccons ::= REFERENCES nm idxlist_opt refargs", + /* 61 */ "ccons ::= defer_subclause", + /* 62 */ "ccons ::= COLLATE id", + /* 63 */ "autoinc ::=", + /* 64 */ "autoinc ::= AUTOINCR", + /* 65 */ "refargs ::=", + /* 66 */ "refargs ::= refargs refarg", + /* 67 */ "refarg ::= MATCH nm", + /* 68 */ "refarg ::= ON DELETE refact", + /* 69 */ "refarg ::= ON UPDATE refact", + /* 70 */ "refarg ::= ON INSERT refact", + /* 71 */ "refact ::= SET NULL", + /* 72 */ "refact ::= SET DEFAULT", + /* 73 */ "refact ::= CASCADE", + /* 74 */ "refact ::= RESTRICT", + /* 75 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt", + /* 76 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt", + /* 77 */ "init_deferred_pred_opt ::=", + /* 78 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED", + /* 79 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE", + /* 80 */ "conslist_opt ::=", + /* 81 */ "conslist_opt ::= COMMA conslist", + /* 82 */ "conslist ::= conslist COMMA tcons", + /* 83 */ "conslist ::= conslist tcons", + /* 84 */ "conslist ::= tcons", + /* 85 */ "tcons ::= CONSTRAINT nm", + /* 86 */ "tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf", + /* 87 */ "tcons ::= UNIQUE LP idxlist RP onconf", + /* 88 */ "tcons ::= CHECK LP expr RP onconf", + /* 89 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt", + /* 90 */ "defer_subclause_opt ::=", + /* 91 */ "defer_subclause_opt ::= defer_subclause", + /* 92 */ "onconf ::=", + /* 93 */ "onconf ::= ON CONFLICT resolvetype", + /* 94 */ "orconf ::=", + /* 95 */ "orconf ::= OR resolvetype", + /* 96 */ "resolvetype ::= raisetype", + /* 97 */ "resolvetype ::= IGNORE", + /* 98 */ "resolvetype ::= REPLACE", + /* 99 */ "cmd ::= DROP TABLE ifexists fullname", + /* 100 */ "ifexists ::= IF EXISTS", + /* 101 */ "ifexists ::=", + /* 102 */ "cmd ::= CREATE temp VIEW nm dbnm AS select", + /* 103 */ "cmd ::= DROP VIEW ifexists fullname", + /* 104 */ "cmd ::= select", + /* 105 */ "select ::= oneselect", + /* 106 */ "select ::= select multiselect_op oneselect", + /* 107 */ "multiselect_op ::= UNION", + /* 108 */ "multiselect_op ::= UNION ALL", + /* 109 */ "multiselect_op ::= EXCEPT|INTERSECT", + /* 110 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt", + /* 111 */ "distinct ::= DISTINCT", + /* 112 */ "distinct ::= ALL", + /* 113 */ "distinct ::=", + /* 114 */ "sclp ::= selcollist COMMA", + /* 115 */ "sclp ::=", + /* 116 */ "selcollist ::= sclp expr as", + /* 117 */ "selcollist ::= sclp STAR", + /* 118 */ "selcollist ::= sclp nm DOT STAR", + /* 119 */ "as ::= AS nm", + /* 120 */ "as ::= ids", + /* 121 */ "as ::=", + /* 122 */ "from ::=", + /* 123 */ "from ::= FROM seltablist", + /* 124 */ "stl_prefix ::= seltablist joinop", + /* 125 */ "stl_prefix ::=", + /* 126 */ "seltablist ::= stl_prefix nm dbnm as on_opt using_opt", + /* 127 */ "seltablist ::= stl_prefix LP seltablist_paren RP as on_opt using_opt", + /* 128 */ "seltablist_paren ::= select", + /* 129 */ "seltablist_paren ::= seltablist", + /* 130 */ "dbnm ::=", + /* 131 */ "dbnm ::= DOT nm", + /* 132 */ "fullname ::= nm dbnm", + /* 133 */ "joinop ::= COMMA|JOIN", + /* 134 */ "joinop ::= JOIN_KW JOIN", + /* 135 */ "joinop ::= JOIN_KW nm JOIN", + /* 136 */ "joinop ::= JOIN_KW nm nm JOIN", + /* 137 */ "on_opt ::= ON expr", + /* 138 */ "on_opt ::=", + /* 139 */ "using_opt ::= USING LP inscollist RP", + /* 140 */ "using_opt ::=", + /* 141 */ "orderby_opt ::=", + /* 142 */ "orderby_opt ::= ORDER BY sortlist", + /* 143 */ "sortlist ::= sortlist COMMA sortitem collate sortorder", + /* 144 */ "sortlist ::= sortitem collate sortorder", + /* 145 */ "sortitem ::= expr", + /* 146 */ "sortorder ::= ASC", + /* 147 */ "sortorder ::= DESC", + /* 148 */ "sortorder ::=", + /* 149 */ "collate ::=", + /* 150 */ "collate ::= COLLATE id", + /* 151 */ "groupby_opt ::=", + /* 152 */ "groupby_opt ::= GROUP BY exprlist", + /* 153 */ "having_opt ::=", + /* 154 */ "having_opt ::= HAVING expr", + /* 155 */ "limit_opt ::=", + /* 156 */ "limit_opt ::= LIMIT expr", + /* 157 */ "limit_opt ::= LIMIT expr OFFSET expr", + /* 158 */ "limit_opt ::= LIMIT expr COMMA expr", + /* 159 */ "cmd ::= DELETE FROM fullname where_opt", + /* 160 */ "where_opt ::=", + /* 161 */ "where_opt ::= WHERE expr", + /* 162 */ "cmd ::= UPDATE orconf fullname SET setlist where_opt", + /* 163 */ "setlist ::= setlist COMMA nm EQ expr", + /* 164 */ "setlist ::= nm EQ expr", + /* 165 */ "cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP", + /* 166 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select", + /* 167 */ "insert_cmd ::= INSERT orconf", + /* 168 */ "insert_cmd ::= REPLACE", + /* 169 */ "itemlist ::= itemlist COMMA expr", + /* 170 */ "itemlist ::= expr", + /* 171 */ "inscollist_opt ::=", + /* 172 */ "inscollist_opt ::= LP inscollist RP", + /* 173 */ "inscollist ::= inscollist COMMA nm", + /* 174 */ "inscollist ::= nm", + /* 175 */ "expr ::= term", + /* 176 */ "expr ::= LP expr RP", + /* 177 */ "term ::= NULL", + /* 178 */ "expr ::= ID", + /* 179 */ "expr ::= JOIN_KW", + /* 180 */ "expr ::= nm DOT nm", + /* 181 */ "expr ::= nm DOT nm DOT nm", + /* 182 */ "term ::= INTEGER|FLOAT|BLOB", /* 183 */ "term ::= STRING", - /* 184 */ "term ::= BLOB", - /* 185 */ "expr ::= REGISTER", - /* 186 */ "expr ::= VARIABLE", - /* 187 */ "expr ::= CAST LP expr AS typetoken RP", - /* 188 */ "expr ::= ID LP distinct exprlist RP", - /* 189 */ "expr ::= ID LP STAR RP", - /* 190 */ "term ::= CTIME_KW", - /* 191 */ "expr ::= expr AND expr", - /* 192 */ "expr ::= expr OR expr", - /* 193 */ "expr ::= expr LT expr", - /* 194 */ "expr ::= expr GT expr", - /* 195 */ "expr ::= expr LE expr", - /* 196 */ "expr ::= expr GE expr", - /* 197 */ "expr ::= expr NE expr", - /* 198 */ "expr ::= expr EQ expr", - /* 199 */ "expr ::= expr BITAND expr", - /* 200 */ "expr ::= expr BITOR expr", - /* 201 */ "expr ::= expr LSHIFT expr", - /* 202 */ "expr ::= expr RSHIFT expr", - /* 203 */ "expr ::= expr PLUS expr", - /* 204 */ "expr ::= expr MINUS expr", - /* 205 */ "expr ::= expr STAR expr", - /* 206 */ "expr ::= expr SLASH expr", - /* 207 */ "expr ::= expr REM expr", - /* 208 */ "expr ::= expr CONCAT expr", - /* 209 */ "likeop ::= LIKE_KW", - /* 210 */ "likeop ::= NOT LIKE_KW", - /* 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 ::= ANALYZE", - /* 305 */ "cmd ::= ANALYZE nm dbnm", - /* 306 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", - /* 307 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column", - /* 308 */ "add_column_fullname ::= fullname", - /* 309 */ "kwcolumn_opt ::=", - /* 310 */ "kwcolumn_opt ::= COLUMNKW", + /* 184 */ "expr ::= REGISTER", + /* 185 */ "expr ::= VARIABLE", + /* 186 */ "expr ::= CAST LP expr AS typetoken RP", + /* 187 */ "expr ::= ID LP distinct exprlist RP", + /* 188 */ "expr ::= ID LP STAR RP", + /* 189 */ "term ::= CTIME_KW", + /* 190 */ "expr ::= expr AND expr", + /* 191 */ "expr ::= expr OR expr", + /* 192 */ "expr ::= expr LT|GT|GE|LE expr", + /* 193 */ "expr ::= expr EQ|NE expr", + /* 194 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", + /* 195 */ "expr ::= expr PLUS|MINUS expr", + /* 196 */ "expr ::= expr STAR|SLASH|REM expr", + /* 197 */ "expr ::= expr CONCAT expr", + /* 198 */ "likeop ::= LIKE_KW", + /* 199 */ "likeop ::= NOT LIKE_KW", + /* 200 */ "escape ::= ESCAPE expr", + /* 201 */ "escape ::=", + /* 202 */ "expr ::= expr likeop expr escape", + /* 203 */ "expr ::= expr ISNULL|NOTNULL", + /* 204 */ "expr ::= expr IS NULL", + /* 205 */ "expr ::= expr NOT NULL", + /* 206 */ "expr ::= expr IS NOT NULL", + /* 207 */ "expr ::= NOT|BITNOT expr", + /* 208 */ "expr ::= MINUS expr", + /* 209 */ "expr ::= PLUS expr", + /* 210 */ "between_op ::= BETWEEN", + /* 211 */ "between_op ::= NOT BETWEEN", + /* 212 */ "expr ::= expr between_op expr AND expr", + /* 213 */ "in_op ::= IN", + /* 214 */ "in_op ::= NOT IN", + /* 215 */ "expr ::= expr in_op LP exprlist RP", + /* 216 */ "expr ::= LP select RP", + /* 217 */ "expr ::= expr in_op LP select RP", + /* 218 */ "expr ::= expr in_op nm dbnm", + /* 219 */ "expr ::= EXISTS LP select RP", + /* 220 */ "expr ::= CASE case_operand case_exprlist case_else END", + /* 221 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", + /* 222 */ "case_exprlist ::= WHEN expr THEN expr", + /* 223 */ "case_else ::= ELSE expr", + /* 224 */ "case_else ::=", + /* 225 */ "case_operand ::= expr", + /* 226 */ "case_operand ::=", + /* 227 */ "exprlist ::= exprlist COMMA expritem", + /* 228 */ "exprlist ::= expritem", + /* 229 */ "expritem ::= expr", + /* 230 */ "expritem ::=", + /* 231 */ "cmd ::= CREATE uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP", + /* 232 */ "uniqueflag ::= UNIQUE", + /* 233 */ "uniqueflag ::=", + /* 234 */ "idxlist_opt ::=", + /* 235 */ "idxlist_opt ::= LP idxlist RP", + /* 236 */ "idxlist ::= idxlist COMMA idxitem collate sortorder", + /* 237 */ "idxlist ::= idxitem collate sortorder", + /* 238 */ "idxitem ::= nm", + /* 239 */ "cmd ::= DROP INDEX ifexists fullname", + /* 240 */ "cmd ::= VACUUM", + /* 241 */ "cmd ::= VACUUM nm", + /* 242 */ "cmd ::= PRAGMA nm dbnm EQ nm", + /* 243 */ "cmd ::= PRAGMA nm dbnm EQ ON", + /* 244 */ "cmd ::= PRAGMA nm dbnm EQ plus_num", + /* 245 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", + /* 246 */ "cmd ::= PRAGMA nm dbnm LP nm RP", + /* 247 */ "cmd ::= PRAGMA nm dbnm", + /* 248 */ "plus_num ::= plus_opt number", + /* 249 */ "minus_num ::= MINUS number", + /* 250 */ "number ::= INTEGER|FLOAT", + /* 251 */ "plus_opt ::= PLUS", + /* 252 */ "plus_opt ::=", + /* 253 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END", + /* 254 */ "trigger_decl ::= temp TRIGGER nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", + /* 255 */ "trigger_time ::= BEFORE", + /* 256 */ "trigger_time ::= AFTER", + /* 257 */ "trigger_time ::= INSTEAD OF", + /* 258 */ "trigger_time ::=", + /* 259 */ "trigger_event ::= DELETE|INSERT", + /* 260 */ "trigger_event ::= UPDATE", + /* 261 */ "trigger_event ::= UPDATE OF inscollist", + /* 262 */ "foreach_clause ::=", + /* 263 */ "foreach_clause ::= FOR EACH ROW", + /* 264 */ "foreach_clause ::= FOR EACH STATEMENT", + /* 265 */ "when_clause ::=", + /* 266 */ "when_clause ::= WHEN expr", + /* 267 */ "trigger_cmd_list ::= trigger_cmd SEMI trigger_cmd_list", + /* 268 */ "trigger_cmd_list ::=", + /* 269 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt", + /* 270 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP", + /* 271 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select", + /* 272 */ "trigger_cmd ::= DELETE FROM nm where_opt", + /* 273 */ "trigger_cmd ::= select", + /* 274 */ "expr ::= RAISE LP IGNORE RP", + /* 275 */ "expr ::= RAISE LP raisetype COMMA nm RP", + /* 276 */ "raisetype ::= ROLLBACK", + /* 277 */ "raisetype ::= ABORT", + /* 278 */ "raisetype ::= FAIL", + /* 279 */ "cmd ::= DROP TRIGGER fullname", + /* 280 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", + /* 281 */ "key_opt ::=", + /* 282 */ "key_opt ::= KEY expr", + /* 283 */ "database_kw_opt ::= DATABASE", + /* 284 */ "database_kw_opt ::=", + /* 285 */ "cmd ::= DETACH database_kw_opt expr", + /* 286 */ "cmd ::= REINDEX", + /* 287 */ "cmd ::= REINDEX nm dbnm", + /* 288 */ "cmd ::= ANALYZE", + /* 289 */ "cmd ::= ANALYZE nm dbnm", + /* 290 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", + /* 291 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column", + /* 292 */ "add_column_fullname ::= fullname", + /* 293 */ "kwcolumn_opt ::=", + /* 294 */ "kwcolumn_opt ::= COLUMNKW", }; #endif /* NDEBUG */ @@ -1322,72 +1206,81 @@ 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 162: - case 195: - case 212: -#line 370 "parse.y" -{sqlite3SelectDelete((yypminor->yy375));} -#line 1332 "parse.c" - break; - case 176: - case 177: - case 200: - case 202: - case 210: - case 216: - case 230: -#line 629 "parse.y" -{sqlite3ExprDelete((yypminor->yy62));} -#line 1343 "parse.c" - break; - case 181: - case 189: - case 198: - case 201: - case 203: + case 154: + case 188: case 205: - case 215: - case 218: - case 219: - case 222: - case 228: -#line 876 "parse.y" -{sqlite3ExprListDelete((yypminor->yy418));} -#line 1358 "parse.c" +#line 368 "parse.y" +{sqlite3SelectDelete((yypminor->yy239));} +#line 1216 "parse.c" break; + case 168: + case 169: + case 193: + case 195: + case 203: + case 209: + case 217: + case 220: + case 222: + case 223: + case 233: +#line 625 "parse.y" +{sqlite3ExprDelete((yypminor->yy178));} +#line 1231 "parse.c" + break; + case 173: + case 181: + case 191: case 194: - case 199: - case 207: + case 196: + case 198: case 208: -#line 499 "parse.y" -{sqlite3SrcListDelete((yypminor->yy151));} -#line 1366 "parse.c" + case 211: + case 212: + case 215: + case 221: +#line 855 "parse.y" +{sqlite3ExprListDelete((yypminor->yy462));} +#line 1246 "parse.c" + break; + case 187: + case 192: + case 200: + case 201: +#line 496 "parse.y" +{sqlite3SrcListDelete((yypminor->yy285));} +#line 1254 "parse.c" + break; + case 197: +#line 557 "parse.y" +{ + sqlite3ExprDelete((yypminor->yy270).pLimit); + sqlite3ExprDelete((yypminor->yy270).pOffset); +} +#line 1262 "parse.c" break; case 204: -#line 561 "parse.y" -{ - sqlite3ExprDelete((yypminor->yy220).pLimit); - sqlite3ExprDelete((yypminor->yy220).pOffset); -} -#line 1374 "parse.c" - break; - case 211: + case 207: case 214: - case 221: -#line 517 "parse.y" -{sqlite3IdListDelete((yypminor->yy240));} -#line 1381 "parse.c" +#line 513 "parse.y" +{sqlite3IdListDelete((yypminor->yy160));} +#line 1269 "parse.c" + break; + case 229: + case 234: +#line 949 "parse.y" +{sqlite3DeleteTriggerStep((yypminor->yy247));} +#line 1275 "parse.c" + break; + case 231: +#line 933 "parse.y" +{sqlite3IdListDelete((yypminor->yy132).b);} +#line 1280 "parse.c" break; case 236: - case 241: -#line 969 "parse.y" -{sqlite3DeleteTriggerStep((yypminor->yy360));} -#line 1387 "parse.c" - break; - case 238: -#line 953 "parse.y" -{sqlite3IdListDelete((yypminor->yy30).b);} -#line 1392 "parse.c" +#line 1008 "parse.y" +{sqlite3ExprDelete((yypminor->yy292));} +#line 1285 "parse.c" break; default: break; /* If no destructor action specified: do nothing */ } @@ -1456,9 +1349,7 @@ static int yy_find_shift_action( int i; int stateno = pParser->yystack[pParser->yyidx].stateno; - /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */ - i = yy_shift_ofst[stateno]; - if( i==YY_SHIFT_USE_DFLT ){ + if( stateno>YY_SHIFT_MAX || (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){ return yy_default[stateno]; } if( iLookAhead==YYNOCODE ){ @@ -1500,8 +1391,8 @@ static int yy_find_reduce_action( int i; /* int stateno = pParser->yystack[pParser->yyidx].stateno; */ - i = yy_reduce_ofst[stateno]; - if( i==YY_REDUCE_USE_DFLT ){ + if( stateno>YY_REDUCE_MAX || + (i = yy_reduce_ofst[stateno])==YY_REDUCE_USE_DFLT ){ return yy_default[stateno]; } if( iLookAhead==YYNOCODE ){ @@ -1563,317 +1454,301 @@ 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[] = { - { 147, 1 }, - { 148, 2 }, - { 148, 1 }, - { 150, 1 }, + { 138, 1 }, + { 139, 2 }, + { 139, 1 }, + { 141, 1 }, + { 140, 1 }, + { 140, 3 }, + { 143, 0 }, + { 143, 1 }, + { 143, 3 }, + { 142, 3 }, + { 145, 0 }, + { 145, 1 }, + { 145, 2 }, + { 144, 0 }, + { 144, 1 }, + { 144, 1 }, + { 144, 1 }, + { 142, 2 }, + { 142, 2 }, + { 142, 2 }, + { 142, 2 }, + { 147, 6 }, + { 150, 0 }, + { 150, 3 }, { 149, 1 }, - { 149, 3 }, - { 152, 0 }, - { 152, 1 }, + { 149, 0 }, + { 148, 4 }, + { 148, 2 }, { 152, 3 }, - { 151, 3 }, - { 154, 0 }, - { 154, 1 }, - { 154, 2 }, - { 153, 0 }, - { 153, 1 }, - { 153, 1 }, - { 153, 1 }, - { 151, 2 }, - { 151, 2 }, - { 151, 2 }, - { 151, 2 }, - { 156, 5 }, - { 158, 1 }, - { 158, 0 }, - { 157, 4 }, - { 157, 2 }, - { 160, 3 }, + { 152, 1 }, + { 155, 3 }, + { 156, 1 }, + { 159, 1 }, { 160, 1 }, - { 163, 3 }, - { 164, 1 }, + { 146, 1 }, + { 146, 1 }, + { 146, 1 }, + { 157, 0 }, + { 157, 1 }, + { 161, 1 }, + { 161, 4 }, + { 161, 6 }, + { 162, 1 }, + { 162, 2 }, + { 163, 1 }, + { 163, 1 }, + { 158, 2 }, + { 158, 0 }, + { 166, 3 }, + { 166, 1 }, + { 166, 2 }, + { 166, 4 }, + { 166, 3 }, + { 166, 3 }, + { 166, 2 }, + { 167, 2 }, + { 167, 3 }, + { 167, 5 }, + { 167, 2 }, + { 167, 4 }, + { 167, 4 }, { 167, 1 }, - { 168, 1 }, - { 168, 1 }, - { 155, 1 }, - { 155, 1 }, - { 155, 1 }, - { 165, 0 }, - { 165, 1 }, + { 167, 2 }, + { 172, 0 }, + { 172, 1 }, + { 174, 0 }, + { 174, 2 }, + { 176, 2 }, + { 176, 3 }, + { 176, 3 }, + { 176, 3 }, + { 177, 2 }, + { 177, 2 }, + { 177, 1 }, + { 177, 1 }, + { 175, 3 }, + { 175, 2 }, + { 178, 0 }, + { 178, 2 }, + { 178, 2 }, + { 153, 0 }, + { 153, 2 }, + { 179, 3 }, + { 179, 2 }, + { 179, 1 }, + { 180, 2 }, + { 180, 7 }, + { 180, 5 }, + { 180, 5 }, + { 180, 10 }, + { 182, 0 }, + { 182, 1 }, + { 170, 0 }, + { 170, 3 }, + { 183, 0 }, + { 183, 2 }, + { 184, 1 }, + { 184, 1 }, + { 184, 1 }, + { 142, 4 }, + { 186, 2 }, + { 186, 0 }, + { 142, 7 }, + { 142, 4 }, + { 142, 1 }, + { 154, 1 }, + { 154, 3 }, + { 189, 1 }, + { 189, 2 }, + { 189, 1 }, + { 188, 9 }, + { 190, 1 }, + { 190, 1 }, + { 190, 0 }, + { 198, 2 }, + { 198, 0 }, + { 191, 3 }, + { 191, 2 }, + { 191, 4 }, + { 199, 2 }, + { 199, 1 }, + { 199, 0 }, + { 192, 0 }, + { 192, 2 }, + { 201, 2 }, + { 201, 0 }, + { 200, 6 }, + { 200, 7 }, + { 205, 1 }, + { 205, 1 }, + { 151, 0 }, + { 151, 2 }, + { 187, 2 }, + { 202, 1 }, + { 202, 2 }, + { 202, 3 }, + { 202, 4 }, + { 203, 2 }, + { 203, 0 }, + { 204, 4 }, + { 204, 0 }, + { 196, 0 }, + { 196, 3 }, + { 208, 5 }, + { 208, 3 }, + { 209, 1 }, + { 171, 1 }, + { 171, 1 }, + { 171, 0 }, + { 210, 0 }, + { 210, 2 }, + { 194, 0 }, + { 194, 3 }, + { 195, 0 }, + { 195, 2 }, + { 197, 0 }, + { 197, 2 }, + { 197, 4 }, + { 197, 4 }, + { 142, 4 }, + { 193, 0 }, + { 193, 2 }, + { 142, 6 }, + { 212, 5 }, + { 212, 3 }, + { 142, 8 }, + { 142, 5 }, + { 213, 2 }, + { 213, 1 }, + { 215, 3 }, + { 215, 1 }, + { 214, 0 }, + { 214, 3 }, + { 207, 3 }, + { 207, 1 }, { 169, 1 }, + { 169, 3 }, + { 168, 1 }, + { 169, 1 }, + { 169, 1 }, + { 169, 3 }, + { 169, 5 }, + { 168, 1 }, + { 168, 1 }, + { 169, 1 }, + { 169, 1 }, + { 169, 6 }, + { 169, 5 }, + { 169, 4 }, + { 168, 1 }, + { 169, 3 }, + { 169, 3 }, + { 169, 3 }, + { 169, 3 }, + { 169, 3 }, + { 169, 3 }, + { 169, 3 }, + { 169, 3 }, + { 216, 1 }, + { 216, 2 }, + { 217, 2 }, + { 217, 0 }, + { 169, 4 }, + { 169, 2 }, + { 169, 3 }, + { 169, 3 }, + { 169, 4 }, + { 169, 2 }, + { 169, 2 }, + { 169, 2 }, + { 218, 1 }, + { 218, 2 }, + { 169, 5 }, + { 219, 1 }, + { 219, 2 }, + { 169, 5 }, + { 169, 3 }, + { 169, 5 }, + { 169, 4 }, + { 169, 4 }, + { 169, 5 }, + { 221, 5 }, + { 221, 4 }, + { 222, 2 }, + { 222, 0 }, + { 220, 1 }, + { 220, 0 }, + { 211, 3 }, + { 211, 1 }, + { 223, 1 }, + { 223, 0 }, + { 142, 11 }, + { 224, 1 }, + { 224, 0 }, + { 173, 0 }, + { 173, 3 }, + { 181, 5 }, + { 181, 3 }, + { 225, 1 }, + { 142, 4 }, + { 142, 1 }, + { 142, 2 }, + { 142, 5 }, + { 142, 5 }, + { 142, 5 }, + { 142, 5 }, + { 142, 6 }, + { 142, 3 }, + { 164, 2 }, + { 165, 2 }, + { 227, 1 }, + { 226, 1 }, + { 226, 0 }, + { 142, 5 }, + { 228, 10 }, + { 230, 1 }, + { 230, 1 }, + { 230, 2 }, + { 230, 0 }, + { 231, 1 }, + { 231, 1 }, + { 231, 3 }, + { 232, 0 }, + { 232, 3 }, + { 232, 3 }, + { 233, 0 }, + { 233, 2 }, + { 229, 3 }, + { 229, 0 }, + { 234, 6 }, + { 234, 8 }, + { 234, 5 }, + { 234, 4 }, + { 234, 1 }, { 169, 4 }, { 169, 6 }, - { 170, 1 }, - { 170, 2 }, - { 171, 1 }, - { 171, 1 }, - { 166, 2 }, - { 166, 0 }, - { 174, 3 }, - { 174, 1 }, - { 174, 2 }, - { 174, 4 }, - { 174, 3 }, - { 174, 3 }, - { 174, 2 }, - { 175, 2 }, - { 175, 3 }, - { 175, 5 }, - { 175, 2 }, - { 175, 5 }, - { 175, 4 }, - { 175, 1 }, - { 175, 2 }, - { 180, 0 }, - { 180, 1 }, - { 182, 0 }, - { 182, 2 }, - { 184, 2 }, - { 184, 3 }, - { 184, 3 }, - { 184, 3 }, - { 185, 2 }, - { 185, 2 }, { 185, 1 }, { 185, 1 }, - { 183, 3 }, - { 183, 2 }, - { 186, 0 }, - { 186, 2 }, - { 186, 2 }, - { 161, 0 }, - { 161, 2 }, - { 187, 3 }, - { 187, 2 }, - { 187, 1 }, - { 188, 2 }, - { 188, 7 }, - { 188, 5 }, - { 188, 3 }, - { 188, 10 }, - { 190, 0 }, - { 190, 1 }, - { 178, 0 }, - { 178, 3 }, - { 191, 0 }, - { 191, 2 }, - { 192, 1 }, - { 192, 1 }, - { 192, 1 }, - { 151, 3 }, - { 151, 7 }, - { 151, 3 }, - { 151, 1 }, - { 162, 1 }, - { 162, 3 }, - { 196, 1 }, - { 196, 2 }, - { 196, 1 }, - { 196, 1 }, - { 195, 9 }, - { 197, 1 }, - { 197, 1 }, - { 197, 0 }, - { 205, 2 }, - { 205, 0 }, - { 198, 3 }, - { 198, 2 }, - { 198, 4 }, - { 206, 2 }, - { 206, 1 }, - { 206, 0 }, - { 199, 0 }, - { 199, 2 }, - { 208, 2 }, - { 208, 0 }, - { 207, 6 }, - { 207, 7 }, - { 212, 1 }, - { 212, 1 }, - { 159, 0 }, - { 159, 2 }, - { 194, 2 }, - { 209, 1 }, - { 209, 1 }, - { 209, 2 }, - { 209, 3 }, - { 209, 4 }, - { 210, 2 }, - { 210, 0 }, - { 211, 4 }, - { 211, 0 }, - { 203, 0 }, - { 203, 3 }, - { 215, 5 }, - { 215, 3 }, - { 216, 1 }, - { 179, 1 }, - { 179, 1 }, - { 179, 0 }, - { 217, 0 }, - { 217, 2 }, - { 201, 0 }, - { 201, 3 }, - { 202, 0 }, - { 202, 2 }, - { 204, 0 }, - { 204, 2 }, - { 204, 4 }, - { 204, 4 }, - { 151, 4 }, - { 200, 0 }, - { 200, 2 }, - { 151, 6 }, - { 219, 5 }, - { 219, 3 }, - { 151, 8 }, - { 151, 5 }, - { 220, 2 }, - { 220, 1 }, - { 222, 3 }, - { 222, 1 }, - { 221, 0 }, - { 221, 3 }, - { 214, 3 }, - { 214, 1 }, - { 177, 1 }, - { 177, 3 }, - { 176, 1 }, - { 177, 1 }, - { 177, 1 }, - { 177, 3 }, - { 177, 5 }, - { 176, 1 }, - { 176, 1 }, - { 176, 1 }, - { 176, 1 }, - { 177, 1 }, - { 177, 1 }, - { 177, 6 }, - { 177, 5 }, - { 177, 4 }, - { 176, 1 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 223, 1 }, - { 223, 2 }, - { 224, 2 }, - { 224, 0 }, - { 177, 4 }, - { 177, 2 }, - { 177, 3 }, - { 177, 2 }, - { 177, 3 }, - { 177, 4 }, - { 177, 2 }, - { 177, 2 }, - { 177, 2 }, - { 177, 2 }, - { 225, 1 }, - { 225, 2 }, - { 177, 5 }, - { 226, 1 }, - { 226, 2 }, - { 177, 5 }, - { 177, 3 }, - { 177, 5 }, - { 177, 4 }, - { 177, 4 }, - { 177, 5 }, - { 228, 5 }, - { 228, 4 }, - { 229, 2 }, - { 229, 0 }, - { 227, 1 }, - { 227, 0 }, - { 218, 3 }, - { 218, 1 }, - { 230, 1 }, - { 230, 0 }, - { 151, 11 }, - { 231, 1 }, - { 231, 0 }, - { 181, 0 }, - { 181, 3 }, - { 189, 5 }, - { 189, 3 }, - { 232, 1 }, - { 151, 3 }, - { 151, 1 }, - { 151, 2 }, - { 151, 5 }, - { 151, 5 }, - { 151, 5 }, - { 151, 5 }, - { 151, 6 }, - { 151, 3 }, - { 172, 2 }, - { 173, 2 }, - { 234, 1 }, - { 234, 1 }, - { 233, 1 }, - { 233, 0 }, - { 151, 5 }, - { 235, 10 }, - { 237, 1 }, - { 237, 1 }, - { 237, 2 }, - { 237, 0 }, - { 238, 1 }, - { 238, 1 }, - { 238, 1 }, - { 238, 3 }, - { 239, 0 }, - { 239, 3 }, - { 239, 3 }, - { 240, 0 }, - { 240, 2 }, - { 236, 3 }, + { 185, 1 }, + { 142, 3 }, + { 142, 6 }, { 236, 0 }, - { 241, 6 }, - { 241, 8 }, - { 241, 5 }, - { 241, 4 }, - { 241, 1 }, - { 177, 4 }, - { 177, 6 }, - { 193, 1 }, - { 193, 1 }, - { 193, 1 }, - { 151, 3 }, - { 151, 6 }, - { 243, 0 }, - { 243, 2 }, - { 243, 2 }, - { 242, 1 }, - { 242, 0 }, - { 151, 3 }, - { 151, 1 }, - { 151, 3 }, - { 151, 1 }, - { 151, 3 }, - { 151, 6 }, - { 151, 6 }, - { 244, 1 }, - { 245, 0 }, - { 245, 1 }, + { 236, 2 }, + { 235, 1 }, + { 235, 0 }, + { 142, 3 }, + { 142, 1 }, + { 142, 3 }, + { 142, 1 }, + { 142, 3 }, + { 142, 6 }, + { 142, 6 }, + { 237, 1 }, + { 238, 0 }, + { 238, 1 }, }; static void yy_accept(yyParser*); /* Forward Declaration */ @@ -1923,777 +1798,781 @@ static void yy_reduce( ** break; */ case 3: -#line 102 "parse.y" +#line 95 "parse.y" { sqlite3FinishCoding(pParse); } -#line 1930 "parse.c" +#line 1805 "parse.c" break; case 6: -#line 105 "parse.y" +#line 98 "parse.y" { sqlite3BeginParse(pParse, 0); } -#line 1935 "parse.c" +#line 1810 "parse.c" break; case 7: -#line 107 "parse.y" +#line 100 "parse.y" { sqlite3BeginParse(pParse, 1); } -#line 1940 "parse.c" +#line 1815 "parse.c" break; case 8: -#line 108 "parse.y" +#line 101 "parse.y" { sqlite3BeginParse(pParse, 2); } -#line 1945 "parse.c" +#line 1820 "parse.c" break; case 9: -#line 114 "parse.y" -{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy280);} -#line 1950 "parse.c" +#line 107 "parse.y" +{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy230);} +#line 1825 "parse.c" break; case 13: -#line 119 "parse.y" -{yygotominor.yy280 = TK_DEFERRED;} -#line 1955 "parse.c" +#line 112 "parse.y" +{yygotominor.yy230 = TK_DEFERRED;} +#line 1830 "parse.c" break; case 14: case 15: case 16: - case 104: - case 106: case 107: -#line 120 "parse.y" -{yygotominor.yy280 = yymsp[0].major;} -#line 1965 "parse.c" + case 109: +#line 113 "parse.y" +{yygotominor.yy230 = yymsp[0].major;} +#line 1839 "parse.c" break; case 17: case 18: -#line 123 "parse.y" +#line 116 "parse.y" {sqlite3CommitTransaction(pParse);} -#line 1971 "parse.c" +#line 1845 "parse.c" break; case 19: -#line 125 "parse.y" +#line 118 "parse.y" {sqlite3RollbackTransaction(pParse);} -#line 1976 "parse.c" +#line 1850 "parse.c" break; case 21: -#line 130 "parse.y" +#line 123 "parse.y" { - sqlite3StartTable(pParse,&yymsp[-4].minor.yy0,&yymsp[-1].minor.yy198,&yymsp[0].minor.yy198,yymsp[-3].minor.yy280,0); + sqlite3StartTable(pParse,&yymsp[-5].minor.yy0,&yymsp[-1].minor.yy384,&yymsp[0].minor.yy384,yymsp[-4].minor.yy230,0,yymsp[-2].minor.yy230); } -#line 1983 "parse.c" +#line 1857 "parse.c" break; case 22: + case 25: case 63: case 77: - case 109: - case 224: - case 227: -#line 135 "parse.y" -{yygotominor.yy280 = 1;} -#line 1993 "parse.c" + case 79: + case 90: + case 101: + case 112: + case 113: + case 210: + case 213: +#line 127 "parse.y" +{yygotominor.yy230 = 0;} +#line 1872 "parse.c" break; case 23: - case 62: - case 76: - case 78: - case 89: - case 110: - case 111: - case 223: - case 226: -#line 137 "parse.y" -{yygotominor.yy280 = 0;} -#line 2006 "parse.c" - break; case 24: -#line 138 "parse.y" -{ - sqlite3EndTable(pParse,&yymsp[-1].minor.yy198,&yymsp[0].minor.yy0,0); -} -#line 2013 "parse.c" + case 64: + case 78: + case 100: + case 111: + case 211: + case 214: +#line 128 "parse.y" +{yygotominor.yy230 = 1;} +#line 1884 "parse.c" break; - case 25: -#line 141 "parse.y" + case 26: +#line 134 "parse.y" { - sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy375); - sqlite3SelectDelete(yymsp[0].minor.yy375); + sqlite3EndTable(pParse,&yymsp[-1].minor.yy384,&yymsp[0].minor.yy0,0); } -#line 2021 "parse.c" +#line 1891 "parse.c" break; - case 28: -#line 153 "parse.y" + case 27: +#line 137 "parse.y" { - yygotominor.yy198.z = yymsp[-2].minor.yy198.z; - yygotominor.yy198.n = (pParse->sLastToken.z-yymsp[-2].minor.yy198.z) + pParse->sLastToken.n; + sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy239); + sqlite3SelectDelete(yymsp[0].minor.yy239); } -#line 2029 "parse.c" - break; - case 29: -#line 157 "parse.y" -{ - sqlite3AddColumn(pParse,&yymsp[0].minor.yy198); - yygotominor.yy198 = yymsp[0].minor.yy198; -} -#line 2037 "parse.c" +#line 1899 "parse.c" break; case 30: +#line 149 "parse.y" +{ + yygotominor.yy384.z = yymsp[-2].minor.yy384.z; + yygotominor.yy384.n = (pParse->sLastToken.z-yymsp[-2].minor.yy384.z) + pParse->sLastToken.n; +} +#line 1907 "parse.c" + break; case 31: +#line 153 "parse.y" +{ + sqlite3AddColumn(pParse,&yymsp[0].minor.yy384); + yygotominor.yy384 = yymsp[0].minor.yy384; +} +#line 1915 "parse.c" + break; case 32: case 33: case 34: case 35: - case 263: - case 264: -#line 167 "parse.y" -{yygotominor.yy198 = yymsp[0].minor.yy0;} -#line 2049 "parse.c" - break; - case 37: -#line 227 "parse.y" -{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy198);} -#line 2054 "parse.c" + case 36: + case 250: +#line 163 "parse.y" +{yygotominor.yy384 = yymsp[0].minor.yy0;} +#line 1925 "parse.c" break; case 38: - case 41: - case 117: - case 118: - case 129: - case 149: - case 251: - case 261: - case 262: -#line 228 "parse.y" -{yygotominor.yy198 = yymsp[0].minor.yy198;} -#line 2067 "parse.c" +#line 222 "parse.y" +{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy384);} +#line 1930 "parse.c" break; case 39: -#line 229 "parse.y" -{ - yygotominor.yy198.z = yymsp[-3].minor.yy198.z; - yygotominor.yy198.n = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy198.z; -} -#line 2075 "parse.c" + case 42: + case 119: + case 120: + case 131: + case 150: + case 238: + case 248: + case 249: +#line 223 "parse.y" +{yygotominor.yy384 = yymsp[0].minor.yy384;} +#line 1943 "parse.c" break; case 40: -#line 233 "parse.y" +#line 224 "parse.y" { - yygotominor.yy198.z = yymsp[-5].minor.yy198.z; - yygotominor.yy198.n = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy198.z; + yygotominor.yy384.z = yymsp[-3].minor.yy384.z; + yygotominor.yy384.n = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy384.z; } -#line 2083 "parse.c" +#line 1951 "parse.c" break; - case 42: -#line 239 "parse.y" -{yygotominor.yy198.z=yymsp[-1].minor.yy198.z; yygotominor.yy198.n=yymsp[0].minor.yy198.n+(yymsp[0].minor.yy198.z-yymsp[-1].minor.yy198.z);} -#line 2088 "parse.c" + case 41: +#line 228 "parse.y" +{ + yygotominor.yy384.z = yymsp[-5].minor.yy384.z; + yygotominor.yy384.n = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy384.z; +} +#line 1959 "parse.c" break; case 43: -#line 241 "parse.y" -{ yygotominor.yy280 = atoi(yymsp[0].minor.yy198.z); } -#line 2093 "parse.c" +#line 234 "parse.y" +{yygotominor.yy384.z=yymsp[-1].minor.yy384.z; yygotominor.yy384.n=yymsp[0].minor.yy384.n+(yymsp[0].minor.yy384.z-yymsp[-1].minor.yy384.z);} +#line 1964 "parse.c" break; case 44: -#line 242 "parse.y" -{ yygotominor.yy280 = -atoi(yymsp[0].minor.yy198.z); } -#line 2098 "parse.c" +#line 236 "parse.y" +{ yygotominor.yy230 = atoi((char*)yymsp[0].minor.yy384.z); } +#line 1969 "parse.c" break; - case 49: - case 51: -#line 251 "parse.y" -{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy62);} -#line 2104 "parse.c" + case 45: +#line 237 "parse.y" +{ yygotominor.yy230 = -atoi((char*)yymsp[0].minor.yy384.z); } +#line 1974 "parse.c" break; case 50: -#line 252 "parse.y" -{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy62);} -#line 2109 "parse.c" - break; case 52: -#line 254 "parse.y" -{ - Expr *p = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy62, 0, 0); - sqlite3AddDefaultValue(pParse,p); -} -#line 2117 "parse.c" +#line 246 "parse.y" +{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy178);} +#line 1980 "parse.c" + break; + case 51: +#line 247 "parse.y" +{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy178);} +#line 1985 "parse.c" break; case 53: -#line 258 "parse.y" +#line 249 "parse.y" { - Expr *p = sqlite3Expr(TK_STRING, 0, 0, &yymsp[0].minor.yy198); + Expr *p = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy178, 0, 0); sqlite3AddDefaultValue(pParse,p); } -#line 2125 "parse.c" +#line 1993 "parse.c" break; - case 55: -#line 267 "parse.y" -{sqlite3AddNotNull(pParse, yymsp[0].minor.yy280);} -#line 2130 "parse.c" + case 54: +#line 253 "parse.y" +{ + Expr *p = sqlite3Expr(TK_STRING, 0, 0, &yymsp[0].minor.yy384); + sqlite3AddDefaultValue(pParse,p); +} +#line 2001 "parse.c" break; case 56: -#line 269 "parse.y" -{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy280,yymsp[0].minor.yy280);} -#line 2135 "parse.c" +#line 262 "parse.y" +{sqlite3AddNotNull(pParse, yymsp[0].minor.yy230);} +#line 2006 "parse.c" break; case 57: -#line 270 "parse.y" -{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy280,0,0);} -#line 2140 "parse.c" +#line 264 "parse.y" +{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy230,yymsp[0].minor.yy230,yymsp[-2].minor.yy230);} +#line 2011 "parse.c" break; case 58: -#line 271 "parse.y" -{sqlite3ExprDelete(yymsp[-2].minor.yy62);} -#line 2145 "parse.c" +#line 265 "parse.y" +{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy230,0,0,0,0);} +#line 2016 "parse.c" break; case 59: -#line 273 "parse.y" -{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy198,yymsp[-1].minor.yy418,yymsp[0].minor.yy280);} -#line 2150 "parse.c" +#line 266 "parse.y" +{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy178);} +#line 2021 "parse.c" break; case 60: -#line 274 "parse.y" -{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy280);} -#line 2155 "parse.c" +#line 268 "parse.y" +{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy384,yymsp[-1].minor.yy462,yymsp[0].minor.yy230);} +#line 2026 "parse.c" break; case 61: -#line 275 "parse.y" -{sqlite3AddCollateType(pParse, yymsp[0].minor.yy198.z, yymsp[0].minor.yy198.n);} -#line 2160 "parse.c" +#line 269 "parse.y" +{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy230);} +#line 2031 "parse.c" break; - case 64: -#line 288 "parse.y" -{ yygotominor.yy280 = OE_Restrict * 0x010101; } -#line 2165 "parse.c" + case 62: +#line 270 "parse.y" +{sqlite3AddCollateType(pParse, (char*)yymsp[0].minor.yy384.z, yymsp[0].minor.yy384.n);} +#line 2036 "parse.c" break; case 65: -#line 289 "parse.y" -{ yygotominor.yy280 = (yymsp[-1].minor.yy280 & yymsp[0].minor.yy359.mask) | yymsp[0].minor.yy359.value; } -#line 2170 "parse.c" +#line 283 "parse.y" +{ yygotominor.yy230 = OE_Restrict * 0x010101; } +#line 2041 "parse.c" break; case 66: -#line 291 "parse.y" -{ yygotominor.yy359.value = 0; yygotominor.yy359.mask = 0x000000; } -#line 2175 "parse.c" +#line 284 "parse.y" +{ yygotominor.yy230 = (yymsp[-1].minor.yy230 & yymsp[0].minor.yy13.mask) | yymsp[0].minor.yy13.value; } +#line 2046 "parse.c" break; case 67: -#line 292 "parse.y" -{ yygotominor.yy359.value = yymsp[0].minor.yy280; yygotominor.yy359.mask = 0x0000ff; } -#line 2180 "parse.c" +#line 286 "parse.y" +{ yygotominor.yy13.value = 0; yygotominor.yy13.mask = 0x000000; } +#line 2051 "parse.c" break; case 68: -#line 293 "parse.y" -{ yygotominor.yy359.value = yymsp[0].minor.yy280<<8; yygotominor.yy359.mask = 0x00ff00; } -#line 2185 "parse.c" +#line 287 "parse.y" +{ yygotominor.yy13.value = yymsp[0].minor.yy230; yygotominor.yy13.mask = 0x0000ff; } +#line 2056 "parse.c" break; case 69: -#line 294 "parse.y" -{ yygotominor.yy359.value = yymsp[0].minor.yy280<<16; yygotominor.yy359.mask = 0xff0000; } -#line 2190 "parse.c" +#line 288 "parse.y" +{ yygotominor.yy13.value = yymsp[0].minor.yy230<<8; yygotominor.yy13.mask = 0x00ff00; } +#line 2061 "parse.c" break; case 70: -#line 296 "parse.y" -{ yygotominor.yy280 = OE_SetNull; } -#line 2195 "parse.c" +#line 289 "parse.y" +{ yygotominor.yy13.value = yymsp[0].minor.yy230<<16; yygotominor.yy13.mask = 0xff0000; } +#line 2066 "parse.c" break; case 71: -#line 297 "parse.y" -{ yygotominor.yy280 = OE_SetDflt; } -#line 2200 "parse.c" +#line 291 "parse.y" +{ yygotominor.yy230 = OE_SetNull; } +#line 2071 "parse.c" break; case 72: -#line 298 "parse.y" -{ yygotominor.yy280 = OE_Cascade; } -#line 2205 "parse.c" +#line 292 "parse.y" +{ yygotominor.yy230 = OE_SetDflt; } +#line 2076 "parse.c" break; case 73: -#line 299 "parse.y" -{ yygotominor.yy280 = OE_Restrict; } -#line 2210 "parse.c" +#line 293 "parse.y" +{ yygotominor.yy230 = OE_Cascade; } +#line 2081 "parse.c" break; case 74: +#line 294 "parse.y" +{ yygotominor.yy230 = OE_Restrict; } +#line 2086 "parse.c" + break; case 75: - case 90: - case 92: - case 94: - case 95: - case 166: -#line 301 "parse.y" -{yygotominor.yy280 = yymsp[0].minor.yy280;} -#line 2221 "parse.c" - break; - case 79: -#line 311 "parse.y" -{yygotominor.yy198.n = 0; yygotominor.yy198.z = 0;} -#line 2226 "parse.c" - break; - case 80: -#line 312 "parse.y" -{yygotominor.yy198 = yymsp[-1].minor.yy0;} -#line 2231 "parse.c" - break; - case 85: -#line 318 "parse.y" -{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy418,yymsp[0].minor.yy280,yymsp[-2].minor.yy280);} -#line 2236 "parse.c" - break; - case 86: -#line 320 "parse.y" -{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy418,yymsp[0].minor.yy280,0,0);} -#line 2241 "parse.c" - break; - case 88: -#line 323 "parse.y" -{ - sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy418, &yymsp[-3].minor.yy198, yymsp[-2].minor.yy418, yymsp[-1].minor.yy280); - sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy280); -} -#line 2249 "parse.c" - break; + case 76: case 91: case 93: -#line 337 "parse.y" -{yygotominor.yy280 = OE_Default;} -#line 2255 "parse.c" - break; + case 95: case 96: -#line 342 "parse.y" -{yygotominor.yy280 = OE_Ignore;} -#line 2260 "parse.c" + case 167: +#line 296 "parse.y" +{yygotominor.yy230 = yymsp[0].minor.yy230;} +#line 2097 "parse.c" + break; + case 80: +#line 306 "parse.y" +{yygotominor.yy384.n = 0; yygotominor.yy384.z = 0;} +#line 2102 "parse.c" + break; + case 81: +#line 307 "parse.y" +{yygotominor.yy384 = yymsp[-1].minor.yy0;} +#line 2107 "parse.c" + break; + case 86: +#line 313 "parse.y" +{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy462,yymsp[0].minor.yy230,yymsp[-2].minor.yy230,0);} +#line 2112 "parse.c" + break; + case 87: +#line 315 "parse.y" +{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy462,yymsp[0].minor.yy230,0,0,0,0);} +#line 2117 "parse.c" + break; + case 88: +#line 316 "parse.y" +{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy178);} +#line 2122 "parse.c" + break; + case 89: +#line 318 "parse.y" +{ + sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy462, &yymsp[-3].minor.yy384, yymsp[-2].minor.yy462, yymsp[-1].minor.yy230); + sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy230); +} +#line 2130 "parse.c" + break; + case 92: + case 94: +#line 332 "parse.y" +{yygotominor.yy230 = OE_Default;} +#line 2136 "parse.c" break; case 97: - case 167: -#line 343 "parse.y" -{yygotominor.yy280 = OE_Replace;} -#line 2266 "parse.c" +#line 337 "parse.y" +{yygotominor.yy230 = OE_Ignore;} +#line 2141 "parse.c" break; case 98: -#line 347 "parse.y" -{ - sqlite3DropTable(pParse, yymsp[0].minor.yy151, 0); -} -#line 2273 "parse.c" + case 168: +#line 338 "parse.y" +{yygotominor.yy230 = OE_Replace;} +#line 2147 "parse.c" break; case 99: -#line 354 "parse.y" +#line 342 "parse.y" { - sqlite3CreateView(pParse, &yymsp[-6].minor.yy0, &yymsp[-3].minor.yy198, &yymsp[-2].minor.yy198, yymsp[0].minor.yy375, yymsp[-5].minor.yy280); + sqlite3DropTable(pParse, yymsp[0].minor.yy285, 0, yymsp[-1].minor.yy230); } -#line 2280 "parse.c" - break; - case 100: -#line 357 "parse.y" -{ - sqlite3DropTable(pParse, yymsp[0].minor.yy151, 1); -} -#line 2287 "parse.c" - break; - case 101: -#line 364 "parse.y" -{ - sqlite3Select(pParse, yymsp[0].minor.yy375, SRT_Callback, 0, 0, 0, 0, 0); - sqlite3SelectDelete(yymsp[0].minor.yy375); -} -#line 2295 "parse.c" +#line 2154 "parse.c" break; case 102: - case 126: -#line 374 "parse.y" -{yygotominor.yy375 = yymsp[0].minor.yy375;} -#line 2301 "parse.c" +#line 352 "parse.y" +{ + sqlite3CreateView(pParse, &yymsp[-6].minor.yy0, &yymsp[-3].minor.yy384, &yymsp[-2].minor.yy384, yymsp[0].minor.yy239, yymsp[-5].minor.yy230); +} +#line 2161 "parse.c" break; case 103: -#line 376 "parse.y" +#line 355 "parse.y" { - if( yymsp[0].minor.yy375 ){ - yymsp[0].minor.yy375->op = yymsp[-1].minor.yy280; - yymsp[0].minor.yy375->pPrior = yymsp[-2].minor.yy375; - } - yygotominor.yy375 = yymsp[0].minor.yy375; + sqlite3DropTable(pParse, yymsp[0].minor.yy285, 1, yymsp[-1].minor.yy230); } -#line 2312 "parse.c" +#line 2168 "parse.c" + break; + case 104: +#line 362 "parse.y" +{ + sqlite3Select(pParse, yymsp[0].minor.yy239, SRT_Callback, 0, 0, 0, 0, 0); + sqlite3SelectDelete(yymsp[0].minor.yy239); +} +#line 2176 "parse.c" break; case 105: -#line 385 "parse.y" -{yygotominor.yy280 = TK_ALL;} -#line 2317 "parse.c" + case 128: +#line 372 "parse.y" +{yygotominor.yy239 = yymsp[0].minor.yy239;} +#line 2182 "parse.c" + break; + case 106: +#line 374 "parse.y" +{ + if( yymsp[0].minor.yy239 ){ + yymsp[0].minor.yy239->op = yymsp[-1].minor.yy230; + yymsp[0].minor.yy239->pPrior = yymsp[-2].minor.yy239; + } + yygotominor.yy239 = yymsp[0].minor.yy239; +} +#line 2193 "parse.c" break; case 108: -#line 390 "parse.y" +#line 383 "parse.y" +{yygotominor.yy230 = TK_ALL;} +#line 2198 "parse.c" + break; + case 110: +#line 387 "parse.y" { - yygotominor.yy375 = sqlite3SelectNew(yymsp[-6].minor.yy418,yymsp[-5].minor.yy151,yymsp[-4].minor.yy62,yymsp[-3].minor.yy418,yymsp[-2].minor.yy62,yymsp[-1].minor.yy418,yymsp[-7].minor.yy280,yymsp[0].minor.yy220.pLimit,yymsp[0].minor.yy220.pOffset); + yygotominor.yy239 = sqlite3SelectNew(yymsp[-6].minor.yy462,yymsp[-5].minor.yy285,yymsp[-4].minor.yy178,yymsp[-3].minor.yy462,yymsp[-2].minor.yy178,yymsp[-1].minor.yy462,yymsp[-7].minor.yy230,yymsp[0].minor.yy270.pLimit,yymsp[0].minor.yy270.pOffset); } -#line 2324 "parse.c" - break; - case 112: - case 248: -#line 411 "parse.y" -{yygotominor.yy418 = yymsp[-1].minor.yy418;} -#line 2330 "parse.c" - break; - case 113: - case 140: - case 150: - case 247: -#line 412 "parse.y" -{yygotominor.yy418 = 0;} -#line 2338 "parse.c" +#line 2205 "parse.c" break; case 114: -#line 413 "parse.y" -{ - yygotominor.yy418 = sqlite3ExprListAppend(yymsp[-2].minor.yy418,yymsp[-1].minor.yy62,yymsp[0].minor.yy198.n?&yymsp[0].minor.yy198:0); -} -#line 2345 "parse.c" + case 235: +#line 408 "parse.y" +{yygotominor.yy462 = yymsp[-1].minor.yy462;} +#line 2211 "parse.c" break; case 115: -#line 416 "parse.y" -{ - yygotominor.yy418 = sqlite3ExprListAppend(yymsp[-1].minor.yy418, sqlite3Expr(TK_ALL, 0, 0, 0), 0); -} -#line 2352 "parse.c" - break; - case 116: -#line 419 "parse.y" -{ - Expr *pRight = sqlite3Expr(TK_ALL, 0, 0, 0); - Expr *pLeft = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy198); - yygotominor.yy418 = sqlite3ExprListAppend(yymsp[-3].minor.yy418, sqlite3Expr(TK_DOT, pLeft, pRight, 0), 0); -} -#line 2361 "parse.c" - break; - case 119: -#line 431 "parse.y" -{yygotominor.yy198.n = 0;} -#line 2366 "parse.c" - break; - case 120: -#line 443 "parse.y" -{yygotominor.yy151 = sqliteMalloc(sizeof(*yygotominor.yy151));} -#line 2371 "parse.c" - break; - case 121: -#line 444 "parse.y" -{yygotominor.yy151 = yymsp[0].minor.yy151;} -#line 2376 "parse.c" - break; - case 122: -#line 449 "parse.y" -{ - yygotominor.yy151 = yymsp[-1].minor.yy151; - if( yygotominor.yy151 && yygotominor.yy151->nSrc>0 ) yygotominor.yy151->a[yygotominor.yy151->nSrc-1].jointype = yymsp[0].minor.yy280; -} -#line 2384 "parse.c" - break; - case 123: -#line 453 "parse.y" -{yygotominor.yy151 = 0;} -#line 2389 "parse.c" - break; - case 124: -#line 454 "parse.y" -{ - yygotominor.yy151 = sqlite3SrcListAppend(yymsp[-5].minor.yy151,&yymsp[-4].minor.yy198,&yymsp[-3].minor.yy198); - if( yymsp[-2].minor.yy198.n ) sqlite3SrcListAddAlias(yygotominor.yy151,&yymsp[-2].minor.yy198); - if( yymsp[-1].minor.yy62 ){ - if( yygotominor.yy151 && yygotominor.yy151->nSrc>1 ){ yygotominor.yy151->a[yygotominor.yy151->nSrc-2].pOn = yymsp[-1].minor.yy62; } - else { sqlite3ExprDelete(yymsp[-1].minor.yy62); } - } - if( yymsp[0].minor.yy240 ){ - if( yygotominor.yy151 && yygotominor.yy151->nSrc>1 ){ yygotominor.yy151->a[yygotominor.yy151->nSrc-2].pUsing = yymsp[0].minor.yy240; } - else { sqlite3IdListDelete(yymsp[0].minor.yy240); } - } -} -#line 2405 "parse.c" - break; - case 125: -#line 468 "parse.y" -{ - yygotominor.yy151 = sqlite3SrcListAppend(yymsp[-6].minor.yy151,0,0); - yygotominor.yy151->a[yygotominor.yy151->nSrc-1].pSelect = yymsp[-4].minor.yy375; - if( yymsp[-2].minor.yy198.n ) sqlite3SrcListAddAlias(yygotominor.yy151,&yymsp[-2].minor.yy198); - if( yymsp[-1].minor.yy62 ){ - if( yygotominor.yy151 && yygotominor.yy151->nSrc>1 ){ yygotominor.yy151->a[yygotominor.yy151->nSrc-2].pOn = yymsp[-1].minor.yy62; } - else { sqlite3ExprDelete(yymsp[-1].minor.yy62); } - } - if( yymsp[0].minor.yy240 ){ - if( yygotominor.yy151 && yygotominor.yy151->nSrc>1 ){ yygotominor.yy151->a[yygotominor.yy151->nSrc-2].pUsing = yymsp[0].minor.yy240; } - else { sqlite3IdListDelete(yymsp[0].minor.yy240); } - } - } -#line 2422 "parse.c" - break; - case 127: -#line 489 "parse.y" -{ - yygotominor.yy375 = sqlite3SelectNew(0,yymsp[0].minor.yy151,0,0,0,0,0,0,0); - } -#line 2429 "parse.c" - break; - case 128: -#line 495 "parse.y" -{yygotominor.yy198.z=0; yygotominor.yy198.n=0;} -#line 2434 "parse.c" - break; - case 130: -#line 500 "parse.y" -{yygotominor.yy151 = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy198,&yymsp[0].minor.yy198);} -#line 2439 "parse.c" - break; - case 131: - case 132: -#line 504 "parse.y" -{ yygotominor.yy280 = JT_INNER; } -#line 2445 "parse.c" - break; - case 133: -#line 506 "parse.y" -{ yygotominor.yy280 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); } -#line 2450 "parse.c" - break; - case 134: -#line 507 "parse.y" -{ yygotominor.yy280 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy198,0); } -#line 2455 "parse.c" - break; - case 135: -#line 509 "parse.y" -{ yygotominor.yy280 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy198,&yymsp[-1].minor.yy198); } -#line 2460 "parse.c" - break; - case 136: - case 144: - case 153: - case 160: - case 174: - case 211: - case 236: - case 238: - case 242: -#line 513 "parse.y" -{yygotominor.yy62 = yymsp[0].minor.yy62;} -#line 2473 "parse.c" - break; - case 137: - case 152: - case 159: - case 212: - case 237: - case 239: - case 243: -#line 514 "parse.y" -{yygotominor.yy62 = 0;} -#line 2484 "parse.c" - break; - case 138: - case 171: -#line 518 "parse.y" -{yygotominor.yy240 = yymsp[-1].minor.yy240;} -#line 2490 "parse.c" - break; - case 139: - case 170: -#line 519 "parse.y" -{yygotominor.yy240 = 0;} -#line 2496 "parse.c" - break; case 141: case 151: -#line 530 "parse.y" -{yygotominor.yy418 = yymsp[0].minor.yy418;} -#line 2502 "parse.c" + case 234: +#line 409 "parse.y" +{yygotominor.yy462 = 0;} +#line 2219 "parse.c" + break; + case 116: +#line 410 "parse.y" +{ + yygotominor.yy462 = sqlite3ExprListAppend(yymsp[-2].minor.yy462,yymsp[-1].minor.yy178,yymsp[0].minor.yy384.n?&yymsp[0].minor.yy384:0); +} +#line 2226 "parse.c" + break; + case 117: +#line 413 "parse.y" +{ + yygotominor.yy462 = sqlite3ExprListAppend(yymsp[-1].minor.yy462, sqlite3Expr(TK_ALL, 0, 0, 0), 0); +} +#line 2233 "parse.c" + break; + case 118: +#line 416 "parse.y" +{ + Expr *pRight = sqlite3Expr(TK_ALL, 0, 0, 0); + Expr *pLeft = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy384); + yygotominor.yy462 = sqlite3ExprListAppend(yymsp[-3].minor.yy462, sqlite3Expr(TK_DOT, pLeft, pRight, 0), 0); +} +#line 2242 "parse.c" + break; + case 121: +#line 428 "parse.y" +{yygotominor.yy384.n = 0;} +#line 2247 "parse.c" + break; + case 122: +#line 440 "parse.y" +{yygotominor.yy285 = sqliteMalloc(sizeof(*yygotominor.yy285));} +#line 2252 "parse.c" + break; + case 123: +#line 441 "parse.y" +{yygotominor.yy285 = yymsp[0].minor.yy285;} +#line 2257 "parse.c" + break; + case 124: +#line 446 "parse.y" +{ + yygotominor.yy285 = yymsp[-1].minor.yy285; + if( yygotominor.yy285 && yygotominor.yy285->nSrc>0 ) yygotominor.yy285->a[yygotominor.yy285->nSrc-1].jointype = yymsp[0].minor.yy230; +} +#line 2265 "parse.c" + break; + case 125: +#line 450 "parse.y" +{yygotominor.yy285 = 0;} +#line 2270 "parse.c" + break; + case 126: +#line 451 "parse.y" +{ + yygotominor.yy285 = sqlite3SrcListAppend(yymsp[-5].minor.yy285,&yymsp[-4].minor.yy384,&yymsp[-3].minor.yy384); + if( yymsp[-2].minor.yy384.n ) sqlite3SrcListAddAlias(yygotominor.yy285,&yymsp[-2].minor.yy384); + if( yymsp[-1].minor.yy178 ){ + if( yygotominor.yy285 && yygotominor.yy285->nSrc>1 ){ yygotominor.yy285->a[yygotominor.yy285->nSrc-2].pOn = yymsp[-1].minor.yy178; } + else { sqlite3ExprDelete(yymsp[-1].minor.yy178); } + } + if( yymsp[0].minor.yy160 ){ + if( yygotominor.yy285 && yygotominor.yy285->nSrc>1 ){ yygotominor.yy285->a[yygotominor.yy285->nSrc-2].pUsing = yymsp[0].minor.yy160; } + else { sqlite3IdListDelete(yymsp[0].minor.yy160); } + } +} +#line 2286 "parse.c" + break; + case 127: +#line 465 "parse.y" +{ + yygotominor.yy285 = sqlite3SrcListAppend(yymsp[-6].minor.yy285,0,0); + yygotominor.yy285->a[yygotominor.yy285->nSrc-1].pSelect = yymsp[-4].minor.yy239; + if( yymsp[-2].minor.yy384.n ) sqlite3SrcListAddAlias(yygotominor.yy285,&yymsp[-2].minor.yy384); + if( yymsp[-1].minor.yy178 ){ + if( yygotominor.yy285 && yygotominor.yy285->nSrc>1 ){ yygotominor.yy285->a[yygotominor.yy285->nSrc-2].pOn = yymsp[-1].minor.yy178; } + else { sqlite3ExprDelete(yymsp[-1].minor.yy178); } + } + if( yymsp[0].minor.yy160 ){ + if( yygotominor.yy285 && yygotominor.yy285->nSrc>1 ){ yygotominor.yy285->a[yygotominor.yy285->nSrc-2].pUsing = yymsp[0].minor.yy160; } + else { sqlite3IdListDelete(yymsp[0].minor.yy160); } + } + } +#line 2303 "parse.c" + break; + case 129: +#line 486 "parse.y" +{ + yygotominor.yy239 = sqlite3SelectNew(0,yymsp[0].minor.yy285,0,0,0,0,0,0,0); + } +#line 2310 "parse.c" + break; + case 130: +#line 492 "parse.y" +{yygotominor.yy384.z=0; yygotominor.yy384.n=0;} +#line 2315 "parse.c" + break; + case 132: +#line 497 "parse.y" +{yygotominor.yy285 = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy384,&yymsp[0].minor.yy384);} +#line 2320 "parse.c" + break; + case 133: +#line 501 "parse.y" +{ yygotominor.yy230 = JT_INNER; } +#line 2325 "parse.c" + break; + case 134: +#line 502 "parse.y" +{ yygotominor.yy230 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); } +#line 2330 "parse.c" + break; + case 135: +#line 503 "parse.y" +{ yygotominor.yy230 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy384,0); } +#line 2335 "parse.c" + break; + case 136: +#line 505 "parse.y" +{ yygotominor.yy230 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy384,&yymsp[-1].minor.yy384); } +#line 2340 "parse.c" + break; + case 137: + case 145: + case 154: + case 161: + case 175: + case 200: + case 223: + case 225: + case 229: +#line 509 "parse.y" +{yygotominor.yy178 = yymsp[0].minor.yy178;} +#line 2353 "parse.c" + break; + case 138: + case 153: + case 160: + case 201: + case 224: + case 226: + case 230: +#line 510 "parse.y" +{yygotominor.yy178 = 0;} +#line 2364 "parse.c" + break; + case 139: + case 172: +#line 514 "parse.y" +{yygotominor.yy160 = yymsp[-1].minor.yy160;} +#line 2370 "parse.c" + break; + case 140: + case 171: +#line 515 "parse.y" +{yygotominor.yy160 = 0;} +#line 2376 "parse.c" break; case 142: -#line 531 "parse.y" -{ - yygotominor.yy418 = sqlite3ExprListAppend(yymsp[-4].minor.yy418,yymsp[-2].minor.yy62,yymsp[-1].minor.yy198.n>0?&yymsp[-1].minor.yy198:0); - if( yygotominor.yy418 ) yygotominor.yy418->a[yygotominor.yy418->nExpr-1].sortOrder = yymsp[0].minor.yy280; -} -#line 2510 "parse.c" + case 152: +#line 526 "parse.y" +{yygotominor.yy462 = yymsp[0].minor.yy462;} +#line 2382 "parse.c" break; case 143: -#line 535 "parse.y" +#line 527 "parse.y" { - yygotominor.yy418 = sqlite3ExprListAppend(0,yymsp[-2].minor.yy62,yymsp[-1].minor.yy198.n>0?&yymsp[-1].minor.yy198:0); - if( yygotominor.yy418 && yygotominor.yy418->a ) yygotominor.yy418->a[0].sortOrder = yymsp[0].minor.yy280; + yygotominor.yy462 = sqlite3ExprListAppend(yymsp[-4].minor.yy462,yymsp[-2].minor.yy178,yymsp[-1].minor.yy384.n>0?&yymsp[-1].minor.yy384:0); + if( yygotominor.yy462 ) yygotominor.yy462->a[yygotominor.yy462->nExpr-1].sortOrder = yymsp[0].minor.yy230; } -#line 2518 "parse.c" +#line 2390 "parse.c" break; - case 145: - case 147: -#line 544 "parse.y" -{yygotominor.yy280 = SQLITE_SO_ASC;} -#line 2524 "parse.c" + case 144: +#line 531 "parse.y" +{ + yygotominor.yy462 = sqlite3ExprListAppend(0,yymsp[-2].minor.yy178,yymsp[-1].minor.yy384.n>0?&yymsp[-1].minor.yy384:0); + if( yygotominor.yy462 && yygotominor.yy462->a ) yygotominor.yy462->a[0].sortOrder = yymsp[0].minor.yy230; +} +#line 2398 "parse.c" break; case 146: -#line 545 "parse.y" -{yygotominor.yy280 = SQLITE_SO_DESC;} -#line 2529 "parse.c" - break; case 148: -#line 547 "parse.y" -{yygotominor.yy198.z = 0; yygotominor.yy198.n = 0;} -#line 2534 "parse.c" +#line 540 "parse.y" +{yygotominor.yy230 = SQLITE_SO_ASC;} +#line 2404 "parse.c" break; - case 154: -#line 565 "parse.y" -{yygotominor.yy220.pLimit = 0; yygotominor.yy220.pOffset = 0;} -#line 2539 "parse.c" + case 147: +#line 541 "parse.y" +{yygotominor.yy230 = SQLITE_SO_DESC;} +#line 2409 "parse.c" + break; + case 149: +#line 543 "parse.y" +{yygotominor.yy384.z = 0; yygotominor.yy384.n = 0;} +#line 2414 "parse.c" break; case 155: -#line 566 "parse.y" -{yygotominor.yy220.pLimit = yymsp[0].minor.yy62; yygotominor.yy220.pOffset = 0;} -#line 2544 "parse.c" +#line 561 "parse.y" +{yygotominor.yy270.pLimit = 0; yygotominor.yy270.pOffset = 0;} +#line 2419 "parse.c" break; case 156: -#line 568 "parse.y" -{yygotominor.yy220.pLimit = yymsp[-2].minor.yy62; yygotominor.yy220.pOffset = yymsp[0].minor.yy62;} -#line 2549 "parse.c" +#line 562 "parse.y" +{yygotominor.yy270.pLimit = yymsp[0].minor.yy178; yygotominor.yy270.pOffset = 0;} +#line 2424 "parse.c" break; case 157: -#line 570 "parse.y" -{yygotominor.yy220.pOffset = yymsp[-2].minor.yy62; yygotominor.yy220.pLimit = yymsp[0].minor.yy62;} -#line 2554 "parse.c" +#line 564 "parse.y" +{yygotominor.yy270.pLimit = yymsp[-2].minor.yy178; yygotominor.yy270.pOffset = yymsp[0].minor.yy178;} +#line 2429 "parse.c" break; case 158: -#line 574 "parse.y" -{sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy151,yymsp[0].minor.yy62);} -#line 2559 "parse.c" +#line 566 "parse.y" +{yygotominor.yy270.pOffset = yymsp[-2].minor.yy178; yygotominor.yy270.pLimit = yymsp[0].minor.yy178;} +#line 2434 "parse.c" break; - case 161: -#line 585 "parse.y" -{sqlite3Update(pParse,yymsp[-3].minor.yy151,yymsp[-1].minor.yy418,yymsp[0].minor.yy62,yymsp[-4].minor.yy280);} -#line 2564 "parse.c" + case 159: +#line 570 "parse.y" +{sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy285,yymsp[0].minor.yy178);} +#line 2439 "parse.c" break; case 162: -#line 591 "parse.y" -{yygotominor.yy418 = sqlite3ExprListAppend(yymsp[-4].minor.yy418,yymsp[0].minor.yy62,&yymsp[-2].minor.yy198);} -#line 2569 "parse.c" +#line 581 "parse.y" +{sqlite3Update(pParse,yymsp[-3].minor.yy285,yymsp[-1].minor.yy462,yymsp[0].minor.yy178,yymsp[-4].minor.yy230);} +#line 2444 "parse.c" break; case 163: -#line 592 "parse.y" -{yygotominor.yy418 = sqlite3ExprListAppend(0,yymsp[0].minor.yy62,&yymsp[-2].minor.yy198);} -#line 2574 "parse.c" +#line 587 "parse.y" +{yygotominor.yy462 = sqlite3ExprListAppend(yymsp[-4].minor.yy462,yymsp[0].minor.yy178,&yymsp[-2].minor.yy384);} +#line 2449 "parse.c" break; case 164: -#line 598 "parse.y" -{sqlite3Insert(pParse, yymsp[-5].minor.yy151, yymsp[-1].minor.yy418, 0, yymsp[-4].minor.yy240, yymsp[-7].minor.yy280);} -#line 2579 "parse.c" +#line 588 "parse.y" +{yygotominor.yy462 = sqlite3ExprListAppend(0,yymsp[0].minor.yy178,&yymsp[-2].minor.yy384);} +#line 2454 "parse.c" break; case 165: -#line 600 "parse.y" -{sqlite3Insert(pParse, yymsp[-2].minor.yy151, 0, yymsp[0].minor.yy375, yymsp[-1].minor.yy240, yymsp[-4].minor.yy280);} -#line 2584 "parse.c" +#line 594 "parse.y" +{sqlite3Insert(pParse, yymsp[-5].minor.yy285, yymsp[-1].minor.yy462, 0, yymsp[-4].minor.yy160, yymsp[-7].minor.yy230);} +#line 2459 "parse.c" break; - case 168: - case 240: -#line 610 "parse.y" -{yygotominor.yy418 = sqlite3ExprListAppend(yymsp[-2].minor.yy418,yymsp[0].minor.yy62,0);} -#line 2590 "parse.c" + case 166: +#line 596 "parse.y" +{sqlite3Insert(pParse, yymsp[-2].minor.yy285, 0, yymsp[0].minor.yy239, yymsp[-1].minor.yy160, yymsp[-4].minor.yy230);} +#line 2464 "parse.c" break; case 169: - case 241: -#line 611 "parse.y" -{yygotominor.yy418 = sqlite3ExprListAppend(0,yymsp[0].minor.yy62,0);} -#line 2596 "parse.c" + case 227: +#line 606 "parse.y" +{yygotominor.yy462 = sqlite3ExprListAppend(yymsp[-2].minor.yy462,yymsp[0].minor.yy178,0);} +#line 2470 "parse.c" break; - case 172: -#line 620 "parse.y" -{yygotominor.yy240 = sqlite3IdListAppend(yymsp[-2].minor.yy240,&yymsp[0].minor.yy198);} -#line 2601 "parse.c" + case 170: + case 228: +#line 607 "parse.y" +{yygotominor.yy462 = sqlite3ExprListAppend(0,yymsp[0].minor.yy178,0);} +#line 2476 "parse.c" break; case 173: -#line 621 "parse.y" -{yygotominor.yy240 = sqlite3IdListAppend(0,&yymsp[0].minor.yy198);} -#line 2606 "parse.c" +#line 616 "parse.y" +{yygotominor.yy160 = sqlite3IdListAppend(yymsp[-2].minor.yy160,&yymsp[0].minor.yy384);} +#line 2481 "parse.c" break; - case 175: -#line 632 "parse.y" -{yygotominor.yy62 = yymsp[-1].minor.yy62; sqlite3ExprSpan(yygotominor.yy62,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); } -#line 2611 "parse.c" + case 174: +#line 617 "parse.y" +{yygotominor.yy160 = sqlite3IdListAppend(0,&yymsp[0].minor.yy384);} +#line 2486 "parse.c" break; case 176: - case 181: - case 182: - case 183: - case 184: -#line 633 "parse.y" -{yygotominor.yy62 = sqlite3Expr(yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);} -#line 2620 "parse.c" +#line 628 "parse.y" +{yygotominor.yy178 = yymsp[-1].minor.yy178; sqlite3ExprSpan(yygotominor.yy178,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); } +#line 2491 "parse.c" break; case 177: - case 178: -#line 634 "parse.y" -{yygotominor.yy62 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy0);} -#line 2626 "parse.c" + case 182: + case 183: +#line 629 "parse.y" +{yygotominor.yy178 = sqlite3Expr(yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);} +#line 2498 "parse.c" break; + case 178: case 179: -#line 636 "parse.y" -{ - Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy198); - Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy198); - yygotominor.yy62 = sqlite3Expr(TK_DOT, temp1, temp2, 0); -} -#line 2635 "parse.c" +#line 630 "parse.y" +{yygotominor.yy178 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy0);} +#line 2504 "parse.c" break; case 180: -#line 641 "parse.y" +#line 632 "parse.y" { - Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-4].minor.yy198); - Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy198); - Expr *temp3 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy198); - Expr *temp4 = sqlite3Expr(TK_DOT, temp2, temp3, 0); - yygotominor.yy62 = sqlite3Expr(TK_DOT, temp1, temp4, 0); + Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy384); + Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy384); + yygotominor.yy178 = sqlite3Expr(TK_DOT, temp1, temp2, 0); } -#line 2646 "parse.c" +#line 2513 "parse.c" + break; + case 181: +#line 637 "parse.y" +{ + Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-4].minor.yy384); + Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy384); + Expr *temp3 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy384); + Expr *temp4 = sqlite3Expr(TK_DOT, temp2, temp3, 0); + yygotominor.yy178 = sqlite3Expr(TK_DOT, temp1, temp4, 0); +} +#line 2524 "parse.c" + break; + case 184: +#line 646 "parse.y" +{yygotominor.yy178 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);} +#line 2529 "parse.c" break; case 185: -#line 652 "parse.y" -{yygotominor.yy62 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);} -#line 2651 "parse.c" +#line 647 "parse.y" +{ + Token *pToken = &yymsp[0].minor.yy0; + Expr *pExpr = yygotominor.yy178 = sqlite3Expr(TK_VARIABLE, 0, 0, pToken); + sqlite3ExprAssignVarNumber(pParse, pExpr); +} +#line 2538 "parse.c" break; case 186: #line 653 "parse.y" { - Token *pToken = &yymsp[0].minor.yy0; - Expr *pExpr = yygotominor.yy62 = sqlite3Expr(TK_VARIABLE, 0, 0, pToken); - sqlite3ExprAssignVarNumber(pParse, pExpr); + yygotominor.yy178 = sqlite3Expr(TK_CAST, yymsp[-3].minor.yy178, 0, &yymsp[-1].minor.yy384); + sqlite3ExprSpan(yygotominor.yy178,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); } -#line 2660 "parse.c" +#line 2546 "parse.c" break; case 187: -#line 659 "parse.y" +#line 658 "parse.y" { - yygotominor.yy62 = sqlite3Expr(TK_CAST, yymsp[-3].minor.yy62, 0, &yymsp[-1].minor.yy198); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); -} -#line 2668 "parse.c" - break; - case 188: -#line 664 "parse.y" -{ - yygotominor.yy62 = sqlite3ExprFunction(yymsp[-1].minor.yy418, &yymsp[-4].minor.yy0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); - if( yymsp[-2].minor.yy280 ){ - yygotominor.yy62->flags |= EP_Distinct; + yygotominor.yy178 = sqlite3ExprFunction(yymsp[-1].minor.yy462, &yymsp[-4].minor.yy0); + sqlite3ExprSpan(yygotominor.yy178,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); + if( yymsp[-2].minor.yy230 ){ + yygotominor.yy178->flags |= EP_Distinct; } } -#line 2679 "parse.c" +#line 2557 "parse.c" + break; + case 188: +#line 665 "parse.y" +{ + yygotominor.yy178 = sqlite3ExprFunction(0, &yymsp[-3].minor.yy0); + sqlite3ExprSpan(yygotominor.yy178,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); +} +#line 2565 "parse.c" break; case 189: -#line 671 "parse.y" -{ - yygotominor.yy62 = sqlite3ExprFunction(0, &yymsp[-3].minor.yy0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); -} -#line 2687 "parse.c" - break; - case 190: -#line 675 "parse.y" +#line 669 "parse.y" { /* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are ** treated as functions that return constants */ - yygotominor.yy62 = sqlite3ExprFunction(0,&yymsp[0].minor.yy0); - if( yygotominor.yy62 ) yygotominor.yy62->op = TK_CONST_FUNC; + yygotominor.yy178 = sqlite3ExprFunction(0,&yymsp[0].minor.yy0); + if( yygotominor.yy178 ) yygotominor.yy178->op = TK_CONST_FUNC; } -#line 2697 "parse.c" +#line 2575 "parse.c" break; + case 190: case 191: case 192: case 193: @@ -2701,516 +2580,491 @@ static void yy_reduce( case 195: case 196: case 197: +#line 675 "parse.y" +{yygotominor.yy178 = sqlite3Expr(yymsp[-1].major, yymsp[-2].minor.yy178, yymsp[0].minor.yy178, 0);} +#line 2587 "parse.c" + break; case 198: +#line 685 "parse.y" +{yygotominor.yy440.eOperator = yymsp[0].minor.yy0; yygotominor.yy440.not = 0;} +#line 2592 "parse.c" + break; case 199: - case 200: - case 201: +#line 686 "parse.y" +{yygotominor.yy440.eOperator = yymsp[0].minor.yy0; yygotominor.yy440.not = 1;} +#line 2597 "parse.c" + break; case 202: +#line 691 "parse.y" +{ + ExprList *pList = sqlite3ExprListAppend(0, yymsp[-1].minor.yy178, 0); + pList = sqlite3ExprListAppend(pList, yymsp[-3].minor.yy178, 0); + if( yymsp[0].minor.yy178 ){ + pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy178, 0); + } + yygotominor.yy178 = sqlite3ExprFunction(pList, &yymsp[-2].minor.yy440.eOperator); + if( yymsp[-2].minor.yy440.not ) yygotominor.yy178 = sqlite3Expr(TK_NOT, yygotominor.yy178, 0, 0); + sqlite3ExprSpan(yygotominor.yy178, &yymsp[-3].minor.yy178->span, &yymsp[-1].minor.yy178->span); +} +#line 2611 "parse.c" + break; case 203: +#line 702 "parse.y" +{ + yygotominor.yy178 = sqlite3Expr(yymsp[0].major, yymsp[-1].minor.yy178, 0, 0); + sqlite3ExprSpan(yygotominor.yy178,&yymsp[-1].minor.yy178->span,&yymsp[0].minor.yy0); +} +#line 2619 "parse.c" + break; case 204: +#line 706 "parse.y" +{ + yygotominor.yy178 = sqlite3Expr(TK_ISNULL, yymsp[-2].minor.yy178, 0, 0); + sqlite3ExprSpan(yygotominor.yy178,&yymsp[-2].minor.yy178->span,&yymsp[0].minor.yy0); +} +#line 2627 "parse.c" + break; case 205: +#line 710 "parse.y" +{ + yygotominor.yy178 = sqlite3Expr(TK_NOTNULL, yymsp[-2].minor.yy178, 0, 0); + sqlite3ExprSpan(yygotominor.yy178,&yymsp[-2].minor.yy178->span,&yymsp[0].minor.yy0); +} +#line 2635 "parse.c" + break; case 206: +#line 714 "parse.y" +{ + yygotominor.yy178 = sqlite3Expr(TK_NOTNULL, yymsp[-3].minor.yy178, 0, 0); + sqlite3ExprSpan(yygotominor.yy178,&yymsp[-3].minor.yy178->span,&yymsp[0].minor.yy0); +} +#line 2643 "parse.c" + break; case 207: +#line 718 "parse.y" +{ + yygotominor.yy178 = sqlite3Expr(yymsp[-1].major, yymsp[0].minor.yy178, 0, 0); + sqlite3ExprSpan(yygotominor.yy178,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy178->span); +} +#line 2651 "parse.c" + break; case 208: -#line 681 "parse.y" -{yygotominor.yy62 = sqlite3Expr(yymsp[-1].major, yymsp[-2].minor.yy62, yymsp[0].minor.yy62, 0);} -#line 2719 "parse.c" +#line 722 "parse.y" +{ + yygotominor.yy178 = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy178, 0, 0); + sqlite3ExprSpan(yygotominor.yy178,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy178->span); +} +#line 2659 "parse.c" break; case 209: -#line 700 "parse.y" -{yygotominor.yy222.operator = yymsp[0].minor.yy0; yygotominor.yy222.not = 0;} -#line 2724 "parse.c" - break; - case 210: -#line 701 "parse.y" -{yygotominor.yy222.operator = yymsp[0].minor.yy0; yygotominor.yy222.not = 1;} -#line 2729 "parse.c" - break; - case 213: -#line 705 "parse.y" +#line 726 "parse.y" { - ExprList *pList = sqlite3ExprListAppend(0, yymsp[-1].minor.yy62, 0); - pList = sqlite3ExprListAppend(pList, yymsp[-3].minor.yy62, 0); - if( yymsp[0].minor.yy62 ){ - pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy62, 0); - } - yygotominor.yy62 = sqlite3ExprFunction(pList, &yymsp[-2].minor.yy222.operator); - if( yymsp[-2].minor.yy222.not ) yygotominor.yy62 = sqlite3Expr(TK_NOT, yygotominor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62, &yymsp[-3].minor.yy62->span, &yymsp[-1].minor.yy62->span); + yygotominor.yy178 = sqlite3Expr(TK_UPLUS, yymsp[0].minor.yy178, 0, 0); + sqlite3ExprSpan(yygotominor.yy178,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy178->span); } -#line 2743 "parse.c" +#line 2667 "parse.c" break; - case 214: -#line 716 "parse.y" + case 212: +#line 733 "parse.y" { - yygotominor.yy62 = sqlite3Expr(TK_ISNULL, yymsp[-1].minor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-1].minor.yy62->span,&yymsp[0].minor.yy0); -} -#line 2751 "parse.c" - break; - case 215: -#line 720 "parse.y" -{ - yygotominor.yy62 = sqlite3Expr(TK_ISNULL, yymsp[-2].minor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-2].minor.yy62->span,&yymsp[0].minor.yy0); -} -#line 2759 "parse.c" - break; - case 216: -#line 724 "parse.y" -{ - yygotominor.yy62 = sqlite3Expr(TK_NOTNULL, yymsp[-1].minor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-1].minor.yy62->span,&yymsp[0].minor.yy0); -} -#line 2767 "parse.c" - break; - case 217: -#line 728 "parse.y" -{ - yygotominor.yy62 = sqlite3Expr(TK_NOTNULL, yymsp[-2].minor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-2].minor.yy62->span,&yymsp[0].minor.yy0); -} -#line 2775 "parse.c" - break; - case 218: -#line 732 "parse.y" -{ - yygotominor.yy62 = sqlite3Expr(TK_NOTNULL, yymsp[-3].minor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-3].minor.yy62->span,&yymsp[0].minor.yy0); -} -#line 2783 "parse.c" - break; - case 219: - case 220: -#line 736 "parse.y" -{ - yygotominor.yy62 = sqlite3Expr(yymsp[-1].major, yymsp[0].minor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy62->span); -} -#line 2792 "parse.c" - break; - case 221: -#line 744 "parse.y" -{ - yygotominor.yy62 = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy62->span); -} -#line 2800 "parse.c" - break; - case 222: -#line 748 "parse.y" -{ - yygotominor.yy62 = sqlite3Expr(TK_UPLUS, yymsp[0].minor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy62->span); -} -#line 2808 "parse.c" - break; - case 225: -#line 755 "parse.y" -{ - ExprList *pList = sqlite3ExprListAppend(0, yymsp[-2].minor.yy62, 0); - pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy62, 0); - yygotominor.yy62 = sqlite3Expr(TK_BETWEEN, yymsp[-4].minor.yy62, 0, 0); - if( yygotominor.yy62 ){ - yygotominor.yy62->pList = pList; + ExprList *pList = sqlite3ExprListAppend(0, yymsp[-2].minor.yy178, 0); + pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy178, 0); + yygotominor.yy178 = sqlite3Expr(TK_BETWEEN, yymsp[-4].minor.yy178, 0, 0); + if( yygotominor.yy178 ){ + yygotominor.yy178->pList = pList; }else{ sqlite3ExprListDelete(pList); } - if( yymsp[-3].minor.yy280 ) yygotominor.yy62 = sqlite3Expr(TK_NOT, yygotominor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-4].minor.yy62->span,&yymsp[0].minor.yy62->span); + if( yymsp[-3].minor.yy230 ) yygotominor.yy178 = sqlite3Expr(TK_NOT, yygotominor.yy178, 0, 0); + sqlite3ExprSpan(yygotominor.yy178,&yymsp[-4].minor.yy178->span,&yymsp[0].minor.yy178->span); } -#line 2824 "parse.c" +#line 2683 "parse.c" break; - case 228: -#line 771 "parse.y" + case 215: +#line 749 "parse.y" { - yygotominor.yy62 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy62, 0, 0); - if( yygotominor.yy62 ){ - yygotominor.yy62->pList = yymsp[-1].minor.yy418; + yygotominor.yy178 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy178, 0, 0); + if( yygotominor.yy178 ){ + yygotominor.yy178->pList = yymsp[-1].minor.yy462; }else{ - sqlite3ExprListDelete(yymsp[-1].minor.yy418); + sqlite3ExprListDelete(yymsp[-1].minor.yy462); } - if( yymsp[-3].minor.yy280 ) yygotominor.yy62 = sqlite3Expr(TK_NOT, yygotominor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-4].minor.yy62->span,&yymsp[0].minor.yy0); + if( yymsp[-3].minor.yy230 ) yygotominor.yy178 = sqlite3Expr(TK_NOT, yygotominor.yy178, 0, 0); + sqlite3ExprSpan(yygotominor.yy178,&yymsp[-4].minor.yy178->span,&yymsp[0].minor.yy0); } -#line 2838 "parse.c" +#line 2697 "parse.c" break; - case 229: -#line 781 "parse.y" + case 216: +#line 759 "parse.y" { - yygotominor.yy62 = sqlite3Expr(TK_SELECT, 0, 0, 0); - if( yygotominor.yy62 ){ - yygotominor.yy62->pSelect = yymsp[-1].minor.yy375; + yygotominor.yy178 = sqlite3Expr(TK_SELECT, 0, 0, 0); + if( yygotominor.yy178 ){ + yygotominor.yy178->pSelect = yymsp[-1].minor.yy239; }else{ - sqlite3SelectDelete(yymsp[-1].minor.yy375); + sqlite3SelectDelete(yymsp[-1].minor.yy239); } - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); + sqlite3ExprSpan(yygotominor.yy178,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); } -#line 2851 "parse.c" +#line 2710 "parse.c" break; - case 230: -#line 790 "parse.y" + case 217: +#line 768 "parse.y" { - yygotominor.yy62 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy62, 0, 0); - if( yygotominor.yy62 ){ - yygotominor.yy62->pSelect = yymsp[-1].minor.yy375; + yygotominor.yy178 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy178, 0, 0); + if( yygotominor.yy178 ){ + yygotominor.yy178->pSelect = yymsp[-1].minor.yy239; }else{ - sqlite3SelectDelete(yymsp[-1].minor.yy375); + sqlite3SelectDelete(yymsp[-1].minor.yy239); } - if( yymsp[-3].minor.yy280 ) yygotominor.yy62 = sqlite3Expr(TK_NOT, yygotominor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-4].minor.yy62->span,&yymsp[0].minor.yy0); + if( yymsp[-3].minor.yy230 ) yygotominor.yy178 = sqlite3Expr(TK_NOT, yygotominor.yy178, 0, 0); + sqlite3ExprSpan(yygotominor.yy178,&yymsp[-4].minor.yy178->span,&yymsp[0].minor.yy0); } -#line 2865 "parse.c" +#line 2724 "parse.c" break; - case 231: -#line 800 "parse.y" + case 218: +#line 778 "parse.y" { - SrcList *pSrc = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy198,&yymsp[0].minor.yy198); - yygotominor.yy62 = sqlite3Expr(TK_IN, yymsp[-3].minor.yy62, 0, 0); - if( yygotominor.yy62 ){ - yygotominor.yy62->pSelect = sqlite3SelectNew(0,pSrc,0,0,0,0,0,0,0); + SrcList *pSrc = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy384,&yymsp[0].minor.yy384); + yygotominor.yy178 = sqlite3Expr(TK_IN, yymsp[-3].minor.yy178, 0, 0); + if( yygotominor.yy178 ){ + yygotominor.yy178->pSelect = sqlite3SelectNew(0,pSrc,0,0,0,0,0,0,0); }else{ sqlite3SrcListDelete(pSrc); } - if( yymsp[-2].minor.yy280 ) yygotominor.yy62 = sqlite3Expr(TK_NOT, yygotominor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-3].minor.yy62->span,yymsp[0].minor.yy198.z?&yymsp[0].minor.yy198:&yymsp[-1].minor.yy198); + if( yymsp[-2].minor.yy230 ) yygotominor.yy178 = sqlite3Expr(TK_NOT, yygotominor.yy178, 0, 0); + sqlite3ExprSpan(yygotominor.yy178,&yymsp[-3].minor.yy178->span,yymsp[0].minor.yy384.z?&yymsp[0].minor.yy384:&yymsp[-1].minor.yy384); } -#line 2880 "parse.c" +#line 2739 "parse.c" break; - case 232: -#line 811 "parse.y" + case 219: +#line 789 "parse.y" { - Expr *p = yygotominor.yy62 = sqlite3Expr(TK_EXISTS, 0, 0, 0); + Expr *p = yygotominor.yy178 = sqlite3Expr(TK_EXISTS, 0, 0, 0); if( p ){ - p->pSelect = yymsp[-1].minor.yy375; + p->pSelect = yymsp[-1].minor.yy239; sqlite3ExprSpan(p,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); }else{ - sqlite3SelectDelete(yymsp[-1].minor.yy375); + sqlite3SelectDelete(yymsp[-1].minor.yy239); } } -#line 2893 "parse.c" +#line 2752 "parse.c" + break; + case 220: +#line 801 "parse.y" +{ + yygotominor.yy178 = sqlite3Expr(TK_CASE, yymsp[-3].minor.yy178, yymsp[-1].minor.yy178, 0); + if( yygotominor.yy178 ){ + yygotominor.yy178->pList = yymsp[-2].minor.yy462; + }else{ + sqlite3ExprListDelete(yymsp[-2].minor.yy462); + } + sqlite3ExprSpan(yygotominor.yy178, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0); +} +#line 2765 "parse.c" + break; + case 221: +#line 812 "parse.y" +{ + yygotominor.yy462 = sqlite3ExprListAppend(yymsp[-4].minor.yy462, yymsp[-2].minor.yy178, 0); + yygotominor.yy462 = sqlite3ExprListAppend(yygotominor.yy462, yymsp[0].minor.yy178, 0); +} +#line 2773 "parse.c" + break; + case 222: +#line 816 "parse.y" +{ + yygotominor.yy462 = sqlite3ExprListAppend(0, yymsp[-2].minor.yy178, 0); + yygotominor.yy462 = sqlite3ExprListAppend(yygotominor.yy462, yymsp[0].minor.yy178, 0); +} +#line 2781 "parse.c" + break; + case 231: +#line 843 "parse.y" +{ + sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy384, &yymsp[-5].minor.yy384, sqlite3SrcListAppend(0,&yymsp[-3].minor.yy384,0), yymsp[-1].minor.yy462, yymsp[-9].minor.yy230, + &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy230); +} +#line 2789 "parse.c" + break; + case 232: + case 277: +#line 849 "parse.y" +{yygotominor.yy230 = OE_Abort;} +#line 2795 "parse.c" break; case 233: -#line 823 "parse.y" +#line 850 "parse.y" +{yygotominor.yy230 = OE_None;} +#line 2800 "parse.c" + break; + case 236: +#line 860 "parse.y" { - yygotominor.yy62 = sqlite3Expr(TK_CASE, yymsp[-3].minor.yy62, yymsp[-1].minor.yy62, 0); - if( yygotominor.yy62 ){ - yygotominor.yy62->pList = yymsp[-2].minor.yy418; - }else{ - sqlite3ExprListDelete(yymsp[-2].minor.yy418); + Expr *p = 0; + if( yymsp[-1].minor.yy384.n>0 ){ + p = sqlite3Expr(TK_COLUMN, 0, 0, 0); + if( p ) p->pColl = sqlite3LocateCollSeq(pParse, (char*)yymsp[-1].minor.yy384.z, yymsp[-1].minor.yy384.n); } - sqlite3ExprSpan(yygotominor.yy62, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0); + yygotominor.yy462 = sqlite3ExprListAppend(yymsp[-4].minor.yy462, p, &yymsp[-2].minor.yy384); + if( yygotominor.yy462 ) yygotominor.yy462->a[yygotominor.yy462->nExpr-1].sortOrder = yymsp[0].minor.yy230; } -#line 2906 "parse.c" +#line 2813 "parse.c" break; - case 234: -#line 834 "parse.y" + case 237: +#line 869 "parse.y" { - yygotominor.yy418 = sqlite3ExprListAppend(yymsp[-4].minor.yy418, yymsp[-2].minor.yy62, 0); - yygotominor.yy418 = sqlite3ExprListAppend(yygotominor.yy418, yymsp[0].minor.yy62, 0); + Expr *p = 0; + if( yymsp[-1].minor.yy384.n>0 ){ + p = sqlite3Expr(TK_COLUMN, 0, 0, 0); + if( p ) p->pColl = sqlite3LocateCollSeq(pParse, (char*)yymsp[-1].minor.yy384.z, yymsp[-1].minor.yy384.n); + } + yygotominor.yy462 = sqlite3ExprListAppend(0, p, &yymsp[-2].minor.yy384); + if( yygotominor.yy462 ) yygotominor.yy462->a[yygotominor.yy462->nExpr-1].sortOrder = yymsp[0].minor.yy230; } -#line 2914 "parse.c" +#line 2826 "parse.c" break; - case 235: -#line 838 "parse.y" -{ - yygotominor.yy418 = sqlite3ExprListAppend(0, yymsp[-2].minor.yy62, 0); - yygotominor.yy418 = sqlite3ExprListAppend(yygotominor.yy418, yymsp[0].minor.yy62, 0); -} -#line 2922 "parse.c" + case 239: +#line 883 "parse.y" +{sqlite3DropIndex(pParse, yymsp[0].minor.yy285, yymsp[-1].minor.yy230);} +#line 2831 "parse.c" break; + case 240: + case 241: +#line 887 "parse.y" +{sqlite3Vacuum(pParse,0);} +#line 2837 "parse.c" + break; + case 242: case 244: -#line 863 "parse.y" -{ - if( yymsp[-9].minor.yy280!=OE_None ) yymsp[-9].minor.yy280 = yymsp[0].minor.yy280; - if( yymsp[-9].minor.yy280==OE_Default) yymsp[-9].minor.yy280 = OE_Abort; - sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy198, &yymsp[-6].minor.yy198, sqlite3SrcListAppend(0,&yymsp[-4].minor.yy198,0),yymsp[-2].minor.yy418,yymsp[-9].minor.yy280, &yymsp[-10].minor.yy0, &yymsp[-1].minor.yy0); -} -#line 2931 "parse.c" +#line 893 "parse.y" +{sqlite3Pragma(pParse,&yymsp[-3].minor.yy384,&yymsp[-2].minor.yy384,&yymsp[0].minor.yy384,0);} +#line 2843 "parse.c" + break; + case 243: +#line 894 "parse.y" +{sqlite3Pragma(pParse,&yymsp[-3].minor.yy384,&yymsp[-2].minor.yy384,&yymsp[0].minor.yy0,0);} +#line 2848 "parse.c" break; case 245: - case 292: -#line 870 "parse.y" -{yygotominor.yy280 = OE_Abort;} -#line 2937 "parse.c" +#line 896 "parse.y" +{ + sqlite3Pragma(pParse,&yymsp[-3].minor.yy384,&yymsp[-2].minor.yy384,&yymsp[0].minor.yy384,1); +} +#line 2855 "parse.c" break; case 246: -#line 871 "parse.y" -{yygotominor.yy280 = OE_None;} -#line 2942 "parse.c" +#line 899 "parse.y" +{sqlite3Pragma(pParse,&yymsp[-4].minor.yy384,&yymsp[-3].minor.yy384,&yymsp[-1].minor.yy384,0);} +#line 2860 "parse.c" break; - case 249: -#line 881 "parse.y" -{ - Expr *p = 0; - if( yymsp[-1].minor.yy198.n>0 ){ - p = sqlite3Expr(TK_COLUMN, 0, 0, 0); - if( p ) p->pColl = sqlite3LocateCollSeq(pParse, yymsp[-1].minor.yy198.z, yymsp[-1].minor.yy198.n); - } - yygotominor.yy418 = sqlite3ExprListAppend(yymsp[-4].minor.yy418, p, &yymsp[-2].minor.yy198); -} -#line 2954 "parse.c" - break; - case 250: -#line 889 "parse.y" -{ - Expr *p = 0; - if( yymsp[-1].minor.yy198.n>0 ){ - p = sqlite3Expr(TK_COLUMN, 0, 0, 0); - if( p ) p->pColl = sqlite3LocateCollSeq(pParse, yymsp[-1].minor.yy198.z, yymsp[-1].minor.yy198.n); - } - yygotominor.yy418 = sqlite3ExprListAppend(0, p, &yymsp[-2].minor.yy198); -} -#line 2966 "parse.c" - break; - case 252: -#line 902 "parse.y" -{sqlite3DropIndex(pParse, yymsp[0].minor.yy151);} -#line 2971 "parse.c" + case 247: +#line 900 "parse.y" +{sqlite3Pragma(pParse,&yymsp[-1].minor.yy384,&yymsp[0].minor.yy384,0,0);} +#line 2865 "parse.c" break; case 253: - case 254: -#line 906 "parse.y" -{sqlite3Vacuum(pParse,0);} -#line 2977 "parse.c" - break; - case 255: - case 257: #line 912 "parse.y" -{sqlite3Pragma(pParse,&yymsp[-3].minor.yy198,&yymsp[-2].minor.yy198,&yymsp[0].minor.yy198,0);} -#line 2983 "parse.c" - break; - case 256: -#line 913 "parse.y" -{sqlite3Pragma(pParse,&yymsp[-3].minor.yy198,&yymsp[-2].minor.yy198,&yymsp[0].minor.yy0,0);} -#line 2988 "parse.c" - break; - case 258: -#line 915 "parse.y" -{ - sqlite3Pragma(pParse,&yymsp[-3].minor.yy198,&yymsp[-2].minor.yy198,&yymsp[0].minor.yy198,1); -} -#line 2995 "parse.c" - break; - case 259: -#line 918 "parse.y" -{sqlite3Pragma(pParse,&yymsp[-4].minor.yy198,&yymsp[-3].minor.yy198,&yymsp[-1].minor.yy198,0);} -#line 3000 "parse.c" - break; - case 260: -#line 919 "parse.y" -{sqlite3Pragma(pParse,&yymsp[-1].minor.yy198,&yymsp[0].minor.yy198,0,0);} -#line 3005 "parse.c" - break; - case 267: -#line 932 "parse.y" { Token all; - all.z = yymsp[-3].minor.yy198.z; - all.n = (yymsp[0].minor.yy0.z - yymsp[-3].minor.yy198.z) + yymsp[0].minor.yy0.n; - sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy360, &all); + all.z = yymsp[-3].minor.yy384.z; + all.n = (yymsp[0].minor.yy0.z - yymsp[-3].minor.yy384.z) + yymsp[0].minor.yy0.n; + sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy247, &all); } -#line 3015 "parse.c" +#line 2875 "parse.c" + break; + case 254: +#line 921 "parse.y" +{ + sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy384, &yymsp[-6].minor.yy384, yymsp[-5].minor.yy230, yymsp[-4].minor.yy132.a, yymsp[-4].minor.yy132.b, yymsp[-2].minor.yy285, yymsp[-1].minor.yy230, yymsp[0].minor.yy178, yymsp[-9].minor.yy230); + yygotominor.yy384 = (yymsp[-6].minor.yy384.n==0?yymsp[-7].minor.yy384:yymsp[-6].minor.yy384); +} +#line 2883 "parse.c" + break; + case 255: + case 258: +#line 927 "parse.y" +{ yygotominor.yy230 = TK_BEFORE; } +#line 2889 "parse.c" + break; + case 256: +#line 928 "parse.y" +{ yygotominor.yy230 = TK_AFTER; } +#line 2894 "parse.c" + break; + case 257: +#line 929 "parse.y" +{ yygotominor.yy230 = TK_INSTEAD;} +#line 2899 "parse.c" + break; + case 259: + case 260: +#line 934 "parse.y" +{yygotominor.yy132.a = yymsp[0].major; yygotominor.yy132.b = 0;} +#line 2905 "parse.c" + break; + case 261: +#line 936 "parse.y" +{yygotominor.yy132.a = TK_UPDATE; yygotominor.yy132.b = yymsp[0].minor.yy160;} +#line 2910 "parse.c" + break; + case 262: + case 263: +#line 939 "parse.y" +{ yygotominor.yy230 = TK_ROW; } +#line 2916 "parse.c" + break; + case 264: +#line 941 "parse.y" +{ yygotominor.yy230 = TK_STATEMENT; } +#line 2921 "parse.c" + break; + case 265: +#line 945 "parse.y" +{ yygotominor.yy178 = 0; } +#line 2926 "parse.c" + break; + case 266: +#line 946 "parse.y" +{ yygotominor.yy178 = yymsp[0].minor.yy178; } +#line 2931 "parse.c" + break; + case 267: +#line 950 "parse.y" +{ + yymsp[-2].minor.yy247->pNext = yymsp[0].minor.yy247; + yygotominor.yy247 = yymsp[-2].minor.yy247; +} +#line 2939 "parse.c" break; case 268: -#line 941 "parse.y" -{ - sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy198, &yymsp[-6].minor.yy198, yymsp[-5].minor.yy280, yymsp[-4].minor.yy30.a, yymsp[-4].minor.yy30.b, yymsp[-2].minor.yy151, yymsp[-1].minor.yy280, yymsp[0].minor.yy62, yymsp[-9].minor.yy280); - yygotominor.yy198 = (yymsp[-6].minor.yy198.n==0?yymsp[-7].minor.yy198:yymsp[-6].minor.yy198); -} -#line 3023 "parse.c" +#line 954 "parse.y" +{ yygotominor.yy247 = 0; } +#line 2944 "parse.c" break; case 269: - case 272: -#line 947 "parse.y" -{ yygotominor.yy280 = TK_BEFORE; } -#line 3029 "parse.c" +#line 960 "parse.y" +{ yygotominor.yy247 = sqlite3TriggerUpdateStep(&yymsp[-3].minor.yy384, yymsp[-1].minor.yy462, yymsp[0].minor.yy178, yymsp[-4].minor.yy230); } +#line 2949 "parse.c" break; case 270: -#line 948 "parse.y" -{ yygotominor.yy280 = TK_AFTER; } -#line 3034 "parse.c" +#line 965 "parse.y" +{yygotominor.yy247 = sqlite3TriggerInsertStep(&yymsp[-5].minor.yy384, yymsp[-4].minor.yy160, yymsp[-1].minor.yy462, 0, yymsp[-7].minor.yy230);} +#line 2954 "parse.c" break; case 271: -#line 949 "parse.y" -{ yygotominor.yy280 = TK_INSTEAD;} -#line 3039 "parse.c" +#line 968 "parse.y" +{yygotominor.yy247 = sqlite3TriggerInsertStep(&yymsp[-2].minor.yy384, yymsp[-1].minor.yy160, 0, yymsp[0].minor.yy239, yymsp[-4].minor.yy230);} +#line 2959 "parse.c" + break; + case 272: +#line 972 "parse.y" +{yygotominor.yy247 = sqlite3TriggerDeleteStep(&yymsp[-1].minor.yy384, yymsp[0].minor.yy178);} +#line 2964 "parse.c" break; case 273: +#line 975 "parse.y" +{yygotominor.yy247 = sqlite3TriggerSelectStep(yymsp[0].minor.yy239); } +#line 2969 "parse.c" + break; case 274: +#line 978 "parse.y" +{ + yygotominor.yy178 = sqlite3Expr(TK_RAISE, 0, 0, 0); + yygotominor.yy178->iColumn = OE_Ignore; + sqlite3ExprSpan(yygotominor.yy178, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0); +} +#line 2978 "parse.c" + break; case 275: -#line 954 "parse.y" -{yygotominor.yy30.a = yymsp[0].major; yygotominor.yy30.b = 0;} -#line 3046 "parse.c" +#line 983 "parse.y" +{ + yygotominor.yy178 = sqlite3Expr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy384); + yygotominor.yy178->iColumn = yymsp[-3].minor.yy230; + sqlite3ExprSpan(yygotominor.yy178, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0); +} +#line 2987 "parse.c" break; case 276: -#line 957 "parse.y" -{yygotominor.yy30.a = TK_UPDATE; yygotominor.yy30.b = yymsp[0].minor.yy240;} -#line 3051 "parse.c" +#line 991 "parse.y" +{yygotominor.yy230 = OE_Rollback;} +#line 2992 "parse.c" break; - case 277: case 278: -#line 960 "parse.y" -{ yygotominor.yy280 = TK_ROW; } -#line 3057 "parse.c" +#line 993 "parse.y" +{yygotominor.yy230 = OE_Fail;} +#line 2997 "parse.c" break; case 279: -#line 962 "parse.y" -{ yygotominor.yy280 = TK_STATEMENT; } -#line 3062 "parse.c" - break; - case 280: -#line 965 "parse.y" -{ yygotominor.yy62 = 0; } -#line 3067 "parse.c" - break; - case 281: -#line 966 "parse.y" -{ yygotominor.yy62 = yymsp[0].minor.yy62; } -#line 3072 "parse.c" - break; - case 282: -#line 970 "parse.y" -{ - yymsp[-2].minor.yy360->pNext = yymsp[0].minor.yy360; - yygotominor.yy360 = yymsp[-2].minor.yy360; -} -#line 3080 "parse.c" - break; - case 283: -#line 974 "parse.y" -{ yygotominor.yy360 = 0; } -#line 3085 "parse.c" - break; - case 284: -#line 980 "parse.y" -{ yygotominor.yy360 = sqlite3TriggerUpdateStep(&yymsp[-3].minor.yy198, yymsp[-1].minor.yy418, yymsp[0].minor.yy62, yymsp[-4].minor.yy280); } -#line 3090 "parse.c" - break; - case 285: -#line 985 "parse.y" -{yygotominor.yy360 = sqlite3TriggerInsertStep(&yymsp[-5].minor.yy198, yymsp[-4].minor.yy240, yymsp[-1].minor.yy418, 0, yymsp[-7].minor.yy280);} -#line 3095 "parse.c" - break; - case 286: -#line 988 "parse.y" -{yygotominor.yy360 = sqlite3TriggerInsertStep(&yymsp[-2].minor.yy198, yymsp[-1].minor.yy240, 0, yymsp[0].minor.yy375, yymsp[-4].minor.yy280);} -#line 3100 "parse.c" - break; - case 287: -#line 992 "parse.y" -{yygotominor.yy360 = sqlite3TriggerDeleteStep(&yymsp[-1].minor.yy198, yymsp[0].minor.yy62);} -#line 3105 "parse.c" - break; - case 288: -#line 995 "parse.y" -{yygotominor.yy360 = sqlite3TriggerSelectStep(yymsp[0].minor.yy375); } -#line 3110 "parse.c" - break; - case 289: #line 998 "parse.y" { - yygotominor.yy62 = sqlite3Expr(TK_RAISE, 0, 0, 0); - yygotominor.yy62->iColumn = OE_Ignore; - sqlite3ExprSpan(yygotominor.yy62, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0); + sqlite3DropTrigger(pParse,yymsp[0].minor.yy285); } -#line 3119 "parse.c" +#line 3004 "parse.c" + break; + case 280: +#line 1004 "parse.y" +{ + sqlite3Attach(pParse, yymsp[-3].minor.yy178, yymsp[-1].minor.yy178, yymsp[0].minor.yy292); +} +#line 3011 "parse.c" + break; + case 281: +#line 1009 "parse.y" +{ yygotominor.yy292 = 0; } +#line 3016 "parse.c" + break; + case 282: +#line 1010 "parse.y" +{ yygotominor.yy292 = yymsp[0].minor.yy178; } +#line 3021 "parse.c" + break; + case 285: +#line 1016 "parse.y" +{ + sqlite3Detach(pParse, yymsp[0].minor.yy178); +} +#line 3028 "parse.c" + break; + case 286: +#line 1022 "parse.y" +{sqlite3Reindex(pParse, 0, 0);} +#line 3033 "parse.c" + break; + case 287: +#line 1023 "parse.y" +{sqlite3Reindex(pParse, &yymsp[-1].minor.yy384, &yymsp[0].minor.yy384);} +#line 3038 "parse.c" + break; + case 288: +#line 1028 "parse.y" +{sqlite3Analyze(pParse, 0, 0);} +#line 3043 "parse.c" + break; + case 289: +#line 1029 "parse.y" +{sqlite3Analyze(pParse, &yymsp[-1].minor.yy384, &yymsp[0].minor.yy384);} +#line 3048 "parse.c" break; case 290: -#line 1003 "parse.y" +#line 1034 "parse.y" { - yygotominor.yy62 = sqlite3Expr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy198); - yygotominor.yy62->iColumn = yymsp[-3].minor.yy280; - sqlite3ExprSpan(yygotominor.yy62, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0); + sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy285,&yymsp[0].minor.yy384); } -#line 3128 "parse.c" +#line 3055 "parse.c" break; case 291: -#line 1011 "parse.y" -{yygotominor.yy280 = OE_Rollback;} -#line 3133 "parse.c" - break; - case 293: -#line 1013 "parse.y" -{yygotominor.yy280 = OE_Fail;} -#line 3138 "parse.c" - break; - case 294: -#line 1018 "parse.y" +#line 1037 "parse.y" { - sqlite3DropTrigger(pParse,yymsp[0].minor.yy151); + sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy384); } -#line 3145 "parse.c" +#line 3062 "parse.c" break; - case 295: -#line 1024 "parse.y" + case 292: +#line 1040 "parse.y" { - sqlite3Attach(pParse, &yymsp[-3].minor.yy198, &yymsp[-1].minor.yy198, yymsp[0].minor.yy361.type, &yymsp[0].minor.yy361.key); + sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy285); } -#line 3152 "parse.c" - break; - case 296: -#line 1028 "parse.y" -{ yygotominor.yy361.type = 0; } -#line 3157 "parse.c" - break; - case 297: -#line 1029 "parse.y" -{ yygotominor.yy361.type=1; yygotominor.yy361.key = yymsp[0].minor.yy198; } -#line 3162 "parse.c" - break; - case 298: -#line 1030 "parse.y" -{ yygotominor.yy361.type=2; yygotominor.yy361.key = yymsp[0].minor.yy0; } -#line 3167 "parse.c" - break; - case 301: -#line 1036 "parse.y" -{ - sqlite3Detach(pParse, &yymsp[0].minor.yy198); -} -#line 3174 "parse.c" - break; - case 302: -#line 1042 "parse.y" -{sqlite3Reindex(pParse, 0, 0);} -#line 3179 "parse.c" - break; - case 303: -#line 1043 "parse.y" -{sqlite3Reindex(pParse, &yymsp[-1].minor.yy198, &yymsp[0].minor.yy198);} -#line 3184 "parse.c" - break; - case 304: -#line 1048 "parse.y" -{sqlite3Analyze(pParse, 0, 0);} -#line 3189 "parse.c" - break; - case 305: -#line 1049 "parse.y" -{sqlite3Analyze(pParse, &yymsp[-1].minor.yy198, &yymsp[0].minor.yy198);} -#line 3194 "parse.c" - break; - case 306: -#line 1054 "parse.y" -{ - sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy151,&yymsp[0].minor.yy198); -} -#line 3201 "parse.c" - break; - case 307: -#line 1057 "parse.y" -{ - sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy198); -} -#line 3208 "parse.c" - break; - case 308: -#line 1060 "parse.y" -{ - sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy151); -} -#line 3215 "parse.c" +#line 3069 "parse.c" break; }; yygoto = yyRuleInfo[yyruleno].lhs; @@ -3276,7 +3130,7 @@ static void yy_syntax_error( sqlite3ErrorMsg(pParse, "incomplete SQL statement"); } } -#line 3282 "parse.c" +#line 3136 "parse.c" sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ } diff --git a/mozilla/db/sqlite3/src/parse.h b/mozilla/db/sqlite3/src/parse.h index fcedda58962..116e7f5bf85 100644 --- a/mozilla/db/sqlite3/src/parse.h +++ b/mozilla/db/sqlite3/src/parse.h @@ -1,145 +1,151 @@ -#define TK_END_OF_FILE 1 -#define TK_ILLEGAL 2 -#define TK_SPACE 3 -#define TK_UNCLOSED_STRING 4 -#define TK_COMMENT 5 -#define TK_FUNCTION 6 -#define TK_COLUMN 7 -#define TK_AGG_FUNCTION 8 -#define TK_AGG_COLUMN 9 -#define TK_CONST_FUNC 10 -#define TK_SEMI 11 -#define TK_EXPLAIN 12 -#define TK_QUERY 13 -#define TK_PLAN 14 -#define TK_BEGIN 15 -#define TK_TRANSACTION 16 -#define TK_DEFERRED 17 -#define TK_IMMEDIATE 18 -#define TK_EXCLUSIVE 19 -#define TK_COMMIT 20 -#define TK_END 21 -#define TK_ROLLBACK 22 -#define TK_CREATE 23 -#define TK_TABLE 24 -#define TK_TEMP 25 -#define TK_LP 26 -#define TK_RP 27 -#define TK_AS 28 -#define TK_COMMA 29 -#define TK_ID 30 -#define TK_ABORT 31 -#define TK_AFTER 32 -#define TK_ANALYZE 33 -#define TK_ASC 34 -#define TK_ATTACH 35 -#define TK_BEFORE 36 -#define TK_CASCADE 37 -#define TK_CAST 38 -#define TK_CONFLICT 39 -#define TK_DATABASE 40 -#define TK_DESC 41 -#define TK_DETACH 42 -#define TK_EACH 43 -#define TK_FAIL 44 -#define TK_FOR 45 -#define TK_IGNORE 46 -#define TK_INITIALLY 47 -#define TK_INSTEAD 48 -#define TK_LIKE_KW 49 -#define TK_MATCH 50 -#define TK_KEY 51 -#define TK_OF 52 -#define TK_OFFSET 53 -#define TK_PRAGMA 54 -#define TK_RAISE 55 -#define TK_REPLACE 56 -#define TK_RESTRICT 57 -#define TK_ROW 58 -#define TK_STATEMENT 59 -#define TK_TRIGGER 60 -#define TK_VACUUM 61 -#define TK_VIEW 62 -#define TK_REINDEX 63 -#define TK_RENAME 64 -#define TK_CTIME_KW 65 -#define TK_ALTER 66 -#define TK_OR 67 -#define TK_AND 68 -#define TK_NOT 69 -#define TK_IS 70 -#define TK_BETWEEN 71 -#define TK_IN 72 -#define TK_ISNULL 73 -#define TK_NOTNULL 74 -#define TK_NE 75 -#define TK_EQ 76 -#define TK_GT 77 -#define TK_LE 78 -#define TK_LT 79 -#define TK_GE 80 -#define TK_ESCAPE 81 -#define TK_BITAND 82 -#define TK_BITOR 83 -#define TK_LSHIFT 84 -#define TK_RSHIFT 85 -#define TK_PLUS 86 -#define TK_MINUS 87 -#define TK_STAR 88 -#define TK_SLASH 89 -#define TK_REM 90 -#define TK_CONCAT 91 -#define TK_UMINUS 92 -#define TK_UPLUS 93 -#define TK_BITNOT 94 -#define TK_STRING 95 -#define TK_JOIN_KW 96 -#define TK_CONSTRAINT 97 -#define TK_DEFAULT 98 -#define TK_NULL 99 -#define TK_PRIMARY 100 -#define TK_UNIQUE 101 -#define TK_CHECK 102 -#define TK_REFERENCES 103 -#define TK_COLLATE 104 -#define TK_AUTOINCR 105 -#define TK_ON 106 -#define TK_DELETE 107 -#define TK_UPDATE 108 -#define TK_INSERT 109 -#define TK_SET 110 -#define TK_DEFERRABLE 111 -#define TK_FOREIGN 112 -#define TK_DROP 113 -#define TK_UNION 114 -#define TK_ALL 115 -#define TK_INTERSECT 116 -#define TK_EXCEPT 117 -#define TK_SELECT 118 -#define TK_DISTINCT 119 -#define TK_DOT 120 -#define TK_FROM 121 -#define TK_JOIN 122 -#define TK_USING 123 -#define TK_ORDER 124 -#define TK_BY 125 -#define TK_GROUP 126 -#define TK_HAVING 127 -#define TK_LIMIT 128 -#define TK_WHERE 129 -#define TK_INTO 130 -#define TK_VALUES 131 -#define TK_INTEGER 132 -#define TK_FLOAT 133 -#define TK_BLOB 134 -#define TK_REGISTER 135 -#define TK_VARIABLE 136 -#define TK_EXISTS 137 -#define TK_CASE 138 -#define TK_WHEN 139 -#define TK_THEN 140 -#define TK_ELSE 141 -#define TK_INDEX 142 -#define TK_TO 143 -#define TK_ADD 144 -#define TK_COLUMNKW 145 +#define TK_SEMI 1 +#define TK_EXPLAIN 2 +#define TK_QUERY 3 +#define TK_PLAN 4 +#define TK_BEGIN 5 +#define TK_TRANSACTION 6 +#define TK_DEFERRED 7 +#define TK_IMMEDIATE 8 +#define TK_EXCLUSIVE 9 +#define TK_COMMIT 10 +#define TK_END 11 +#define TK_ROLLBACK 12 +#define TK_CREATE 13 +#define TK_TABLE 14 +#define TK_IF 15 +#define TK_NOT 16 +#define TK_EXISTS 17 +#define TK_TEMP 18 +#define TK_LP 19 +#define TK_RP 20 +#define TK_AS 21 +#define TK_COMMA 22 +#define TK_ID 23 +#define TK_ABORT 24 +#define TK_AFTER 25 +#define TK_ANALYZE 26 +#define TK_ASC 27 +#define TK_ATTACH 28 +#define TK_BEFORE 29 +#define TK_CASCADE 30 +#define TK_CAST 31 +#define TK_CONFLICT 32 +#define TK_DATABASE 33 +#define TK_DESC 34 +#define TK_DETACH 35 +#define TK_EACH 36 +#define TK_FAIL 37 +#define TK_FOR 38 +#define TK_IGNORE 39 +#define TK_INITIALLY 40 +#define TK_INSTEAD 41 +#define TK_LIKE_KW 42 +#define TK_MATCH 43 +#define TK_KEY 44 +#define TK_OF 45 +#define TK_OFFSET 46 +#define TK_PRAGMA 47 +#define TK_RAISE 48 +#define TK_REPLACE 49 +#define TK_RESTRICT 50 +#define TK_ROW 51 +#define TK_STATEMENT 52 +#define TK_TRIGGER 53 +#define TK_VACUUM 54 +#define TK_VIEW 55 +#define TK_REINDEX 56 +#define TK_RENAME 57 +#define TK_CTIME_KW 58 +#define TK_OR 59 +#define TK_AND 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_ESCAPE 72 +#define TK_BITAND 73 +#define TK_BITOR 74 +#define TK_LSHIFT 75 +#define TK_RSHIFT 76 +#define TK_PLUS 77 +#define TK_MINUS 78 +#define TK_STAR 79 +#define TK_SLASH 80 +#define TK_REM 81 +#define TK_CONCAT 82 +#define TK_UMINUS 83 +#define TK_UPLUS 84 +#define TK_BITNOT 85 +#define TK_STRING 86 +#define TK_JOIN_KW 87 +#define TK_CONSTRAINT 88 +#define TK_DEFAULT 89 +#define TK_NULL 90 +#define TK_PRIMARY 91 +#define TK_UNIQUE 92 +#define TK_CHECK 93 +#define TK_REFERENCES 94 +#define TK_COLLATE 95 +#define TK_AUTOINCR 96 +#define TK_ON 97 +#define TK_DELETE 98 +#define TK_UPDATE 99 +#define TK_INSERT 100 +#define TK_SET 101 +#define TK_DEFERRABLE 102 +#define TK_FOREIGN 103 +#define TK_DROP 104 +#define TK_UNION 105 +#define TK_ALL 106 +#define TK_EXCEPT 107 +#define TK_INTERSECT 108 +#define TK_SELECT 109 +#define TK_DISTINCT 110 +#define TK_DOT 111 +#define TK_FROM 112 +#define TK_JOIN 113 +#define TK_USING 114 +#define TK_ORDER 115 +#define TK_BY 116 +#define TK_GROUP 117 +#define TK_HAVING 118 +#define TK_LIMIT 119 +#define TK_WHERE 120 +#define TK_INTO 121 +#define TK_VALUES 122 +#define TK_INTEGER 123 +#define TK_FLOAT 124 +#define TK_BLOB 125 +#define TK_REGISTER 126 +#define TK_VARIABLE 127 +#define TK_CASE 128 +#define TK_WHEN 129 +#define TK_THEN 130 +#define TK_ELSE 131 +#define TK_INDEX 132 +#define TK_ALTER 133 +#define TK_TO 134 +#define TK_ADD 135 +#define TK_COLUMNKW 136 +#define TK_TO_TEXT 137 +#define TK_TO_BLOB 138 +#define TK_TO_NUMERIC 139 +#define TK_TO_INT 140 +#define TK_TO_REAL 141 +#define TK_END_OF_FILE 142 +#define TK_ILLEGAL 143 +#define TK_SPACE 144 +#define TK_UNCLOSED_STRING 145 +#define TK_COMMENT 146 +#define TK_FUNCTION 147 +#define TK_COLUMN 148 +#define TK_AGG_FUNCTION 149 +#define TK_AGG_COLUMN 150 +#define TK_CONST_FUNC 151 diff --git a/mozilla/db/sqlite3/src/pragma.c b/mozilla/db/sqlite3/src/pragma.c index 445ff36aef6..45318190ff7 100644 --- a/mozilla/db/sqlite3/src/pragma.c +++ b/mozilla/db/sqlite3/src/pragma.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** -** $Id: pragma.c,v 1.100 2005/09/20 17:42:23 drh Exp $ +** $Id: pragma.c,v 1.114 2006/01/12 01:56:44 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -36,7 +36,7 @@ ** 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(const u8 *z){ +static int getSafetyLevel(const char *z){ /* 123456789 123456789 */ static const char zText[] = "onoffalseyestruefull"; static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16}; @@ -58,7 +58,7 @@ static int getSafetyLevel(const u8 *z){ /* ** Interpret the given string as a boolean value. */ -static int getBoolean(const u8 *z){ +static int getBoolean(const char *z){ return getSafetyLevel(z)&1; } @@ -151,9 +151,17 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){ { "short_column_names", SQLITE_ShortColNames }, { "count_changes", SQLITE_CountRows }, { "empty_result_callbacks", SQLITE_NullCallback }, + { "legacy_file_format", SQLITE_LegacyFileFmt }, +#ifndef SQLITE_OMIT_CHECK + { "ignore_check_constraints", SQLITE_IgnoreChecks }, +#endif /* The following is VERY experimental */ { "writable_schema", SQLITE_WriteSchema }, { "omit_readlock", SQLITE_NoReadlock }, + + /* TODO: Maybe it shouldn't be possible to change the ReadUncommitted + ** flag if there are any active statements. */ + { "read_uncommitted", SQLITE_ReadUncommitted }, }; int i; const struct sPragmaType *p; @@ -280,8 +288,8 @@ void sqlite3Pragma( sqlite3VdbeAddOp(v, OP_Ge, 0, addr+3); sqlite3VdbeAddOp(v, OP_Negative, 0, 0); sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 2); - pDb->cache_size = size; - sqlite3BtreeSetCacheSize(pDb->pBt, pDb->cache_size); + pDb->pSchema->cache_size = size; + sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); } }else @@ -342,12 +350,12 @@ void sqlite3Pragma( if( sqlite3StrICmp(zLeft,"cache_size")==0 ){ if( sqlite3ReadSchema(pParse) ) goto pragma_out; if( !zRight ){ - returnSingleInt(pParse, "cache_size", pDb->cache_size); + returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size); }else{ int size = atoi(zRight); if( size<0 ) size = -size; - pDb->cache_size = size; - sqlite3BtreeSetCacheSize(pDb->pBt, pDb->cache_size); + pDb->pSchema->cache_size = size; + sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); } }else @@ -647,6 +655,7 @@ void sqlite3Pragma( /* Do an integrity check on each database file */ for(i=0; inDb; i++){ HashElem *x; + Hash *pTbls; int cnt = 0; if( OMIT_TEMPDB && i==1 ) continue; @@ -655,13 +664,13 @@ void sqlite3Pragma( /* Do an integrity check of the B-Tree */ - for(x=sqliteHashFirst(&db->aDb[i].tblHash); x; x=sqliteHashNext(x)){ + pTbls = &db->aDb[i].pSchema->tblHash; + for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ Table *pTab = sqliteHashData(x); Index *pIdx; sqlite3VdbeAddOp(v, OP_Integer, pTab->tnum, 0); cnt++; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - if( sqlite3CheckIndexCollSeq(pParse, pIdx) ) goto pragma_out; sqlite3VdbeAddOp(v, OP_Integer, pIdx->tnum, 0); cnt++; } @@ -670,18 +679,19 @@ void sqlite3Pragma( sqlite3VdbeAddOp(v, OP_IntegrityCk, cnt, i); sqlite3VdbeAddOp(v, OP_Dup, 0, 1); addr = sqlite3VdbeOp3(v, OP_String8, 0, 0, "ok", P3_STATIC); - sqlite3VdbeAddOp(v, OP_Eq, 0, addr+6); + sqlite3VdbeAddOp(v, OP_Eq, 0, addr+7); sqlite3VdbeOp3(v, OP_String8, 0, 0, sqlite3MPrintf("*** in database %s ***\n", db->aDb[i].zName), P3_DYNAMIC); sqlite3VdbeAddOp(v, OP_Pull, 1, 0); sqlite3VdbeAddOp(v, OP_Concat, 0, 1); sqlite3VdbeAddOp(v, OP_Callback, 1, 0); + sqlite3VdbeAddOp(v, OP_MemIncr, 1, 0); /* Make sure all the indices are constructed correctly. */ sqlite3CodeVerifySchema(pParse, i); - for(x=sqliteHashFirst(&db->aDb[i].tblHash); x; x=sqliteHashNext(x)){ + for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ Table *pTab = sqliteHashData(x); Index *pIdx; int loopTop; @@ -690,11 +700,11 @@ void sqlite3Pragma( sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead); sqlite3VdbeAddOp(v, OP_MemInt, 0, 1); loopTop = sqlite3VdbeAddOp(v, OP_Rewind, 1, 0); - sqlite3VdbeAddOp(v, OP_MemIncr, 1, 0); + sqlite3VdbeAddOp(v, OP_MemIncr, 1, 1); for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ int jmp2; static const VdbeOpList idxErr[] = { - { OP_MemIncr, 0, 0, 0}, + { OP_MemIncr, 1, 0, 0}, { OP_String8, 0, 0, "rowid "}, { OP_Rowid, 1, 0, 0}, { OP_String8, 0, 0, " missing from index "}, @@ -714,12 +724,12 @@ void sqlite3Pragma( static const VdbeOpList cntIdx[] = { { OP_MemInt, 0, 2, 0}, { OP_Rewind, 0, 0, 0}, /* 1 */ - { OP_MemIncr, 2, 0, 0}, + { OP_MemIncr, 1, 2, 0}, { OP_Next, 0, 0, 0}, /* 3 */ { OP_MemLoad, 1, 0, 0}, { OP_MemLoad, 2, 0, 0}, { OP_Eq, 0, 0, 0}, /* 6 */ - { OP_MemIncr, 0, 0, 0}, + { OP_MemIncr, 1, 0, 0}, { OP_String8, 0, 0, "wrong # of entries in index "}, { OP_String8, 0, 0, 0}, /* 9 */ { OP_Concat, 0, 0, 0}, @@ -787,7 +797,7 @@ void sqlite3Pragma( sqlite3VdbeSetColName(v, 0, "encoding", P3_STATIC); sqlite3VdbeAddOp(v, OP_String8, 0, 0); for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ - if( pEnc->enc==pParse->db->enc ){ + if( pEnc->enc==ENC(pParse->db) ){ sqlite3VdbeChangeP3(v, -1, pEnc->zName, P3_STATIC); break; } @@ -799,10 +809,13 @@ void sqlite3Pragma( ** will be overwritten when the schema is next loaded. If it does not ** already exists, it will be created to use the new encoding value. */ - if( !(pParse->db->flags&SQLITE_Initialized) ){ + if( + !(DbHasProperty(db, 0, DB_SchemaLoaded)) || + DbHasProperty(db, 0, DB_Empty) + ){ for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){ - pParse->db->enc = pEnc->enc; + ENC(pParse->db) = pEnc->enc; break; } } @@ -918,6 +931,12 @@ void sqlite3Pragma( }else #endif +#if SQLITE_HAS_CODEC + if( sqlite3StrICmp(zLeft, "key")==0 ){ + sqlite3_key(db, zRight, strlen(zRight)); + }else +#endif + {} if( v ){ diff --git a/mozilla/db/sqlite3/src/prepare.c b/mozilla/db/sqlite3/src/prepare.c index 8babc95b71c..97ab4b768f1 100644 --- a/mozilla/db/sqlite3/src/prepare.c +++ b/mozilla/db/sqlite3/src/prepare.c @@ -13,7 +13,7 @@ ** interface, and routines that contribute to loading the database schema ** from disk. ** -** $Id: prepare.c,v 1.2 2005-12-13 19:49:35 vladimir%pobox.com Exp $ +** $Id: prepare.c,v 1.3 2006-02-08 21:10:11 vladimir%pobox.com Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -24,7 +24,7 @@ ** that the database is corrupt. */ static void corruptSchema(InitData *pData, const char *zExtra){ - if( !sqlite3_malloc_failed ){ + if( !sqlite3MallocFailed() ){ sqlite3SetString(pData->pzErrMsg, "malformed database schema", zExtra!=0 && zExtra[0]!=0 ? " - " : (char*)0, zExtra, (char*)0); } @@ -49,6 +49,10 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **azColName){ sqlite3 *db = pData->db; int iDb; + if( sqlite3MallocFailed() ){ + return SQLITE_NOMEM; + } + assert( argc==4 ); if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */ if( argv[1]==0 || argv[3]==0 ){ @@ -71,7 +75,11 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **azColName){ rc = sqlite3_exec(db, argv[2], 0, 0, &zErr); db->init.iDb = 0; if( SQLITE_OK!=rc ){ - corruptSchema(pData, zErr); + if( rc==SQLITE_NOMEM ){ + sqlite3FailedMalloc(); + }else{ + corruptSchema(pData, zErr); + } sqlite3_free(zErr); return rc; } @@ -111,6 +119,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ BtCursor *curMain; int size; Table *pTab; + Db *pDb; char const *azArg[5]; char zDbNum[30]; int meta[10]; @@ -145,6 +154,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ #endif assert( iDb>=0 && iDbnDb ); + assert( db->aDb[iDb].pSchema ); /* zMasterSchema and zInitScript are set to point at the master schema ** and initialisation script appropriate for the database being @@ -180,11 +190,14 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ /* Create a cursor to hold the database open */ - if( db->aDb[iDb].pBt==0 ){ - if( !OMIT_TEMPDB && iDb==1 ) DbSetProperty(db, 1, DB_SchemaLoaded); + pDb = &db->aDb[iDb]; + if( pDb->pBt==0 ){ + if( !OMIT_TEMPDB && iDb==1 ){ + DbSetProperty(db, 1, DB_SchemaLoaded); + } return SQLITE_OK; } - rc = sqlite3BtreeCursor(db->aDb[iDb].pBt, MASTER_ROOT, 0, 0, 0, &curMain); + rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, 0, &curMain); if( rc!=SQLITE_OK && rc!=SQLITE_EMPTY ){ sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0); return rc; @@ -204,13 +217,13 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ ** meta[8] ** meta[9] ** - ** Note: The hash defined SQLITE_UTF* symbols in sqliteInt.h correspond to + ** Note: The #defined SQLITE_UTF* symbols in sqliteInt.h correspond to ** the possible values of meta[4]. */ if( rc==SQLITE_OK ){ int i; for(i=0; rc==SQLITE_OK && iaDb[iDb].pBt, i+1, (u32 *)&meta[i]); + rc = sqlite3BtreeGetMeta(pDb->pBt, i+1, (u32 *)&meta[i]); } if( rc ){ sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0); @@ -220,7 +233,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ }else{ memset(meta, 0, sizeof(meta)); } - db->aDb[iDb].schema_cookie = meta[0]; + pDb->pSchema->schema_cookie = meta[0]; /* If opening a non-empty database, check the text encoding. For the ** main database, set sqlite3.enc to the encoding of the main database. @@ -229,55 +242,44 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ */ if( meta[4] ){ /* text encoding */ if( iDb==0 ){ - /* If opening the main database, set db->enc. */ - db->enc = (u8)meta[4]; - db->pDfltColl = sqlite3FindCollSeq(db, db->enc, "BINARY", 6, 0); + /* If opening the main database, set ENC(db). */ + ENC(db) = (u8)meta[4]; + db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0); }else{ - /* If opening an attached database, the encoding much match db->enc */ - if( meta[4]!=db->enc ){ + /* If opening an attached database, the encoding much match ENC(db) */ + if( meta[4]!=ENC(db) ){ sqlite3BtreeCloseCursor(curMain); sqlite3SetString(pzErrMsg, "attached databases must use the same" " text encoding as main database", (char*)0); return SQLITE_ERROR; } } + }else{ + DbSetProperty(db, iDb, DB_Empty); } + pDb->pSchema->enc = ENC(db); size = meta[2]; if( size==0 ){ size = MAX_PAGES; } - db->aDb[iDb].cache_size = size; - - if( iDb==0 ){ - db->file_format = meta[1]; - if( db->file_format==0 ){ - /* This happens if the database was initially empty */ - db->file_format = 1; - } - - if( db->file_format==2 || db->file_format==3 ){ - /* File format 2 is treated exactly as file format 1. New - ** databases are created with file format 1. - */ - db->file_format = 1; - } - } + pDb->pSchema->cache_size = size; + sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); /* ** file_format==1 Version 3.0.0. - ** file_format==2 Version 3.1.3. - ** file_format==3 Version 3.1.4. - ** - ** 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. - ** Version 3.1.4 can read and write file formats 1, 2 and 3. + ** file_format==2 Version 3.1.3. // ALTER TABLE ADD COLUMN + ** file_format==3 Version 3.1.4. // ditto but with non-NULL defaults + ** file_format==4 Version 3.3.0. // DESC indices. Boolean constants */ - if( meta[1]>3 ){ + pDb->pSchema->file_format = meta[1]; + if( pDb->pSchema->file_format==0 ){ + pDb->pSchema->file_format = 1; + } + if( pDb->pSchema->file_format>SQLITE_MAX_FILE_FORMAT ){ sqlite3BtreeCloseCursor(curMain); sqlite3SetString(pzErrMsg, "unsupported file format", (char*)0); return SQLITE_ERROR; } - sqlite3BtreeSetCacheSize(db->aDb[iDb].pBt, db->aDb[iDb].cache_size); /* Read the schema information out of the schema tables */ @@ -301,8 +303,8 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ #endif sqlite3BtreeCloseCursor(curMain); } - if( sqlite3_malloc_failed ){ - sqlite3SetString(pzErrMsg, "out of memory", (char*)0); + if( sqlite3MallocFailed() ){ + /* sqlite3SetString(pzErrMsg, "out of memory", (char*)0); */ rc = SQLITE_NOMEM; sqlite3ResetInternalSchema(db, 0); } @@ -320,14 +322,15 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ ** created using ATTACH statements. Return a success code. If an ** error occurs, write an error message into *pzErrMsg. ** -** After the database is initialized, the SQLITE_Initialized -** bit is set in the flags field of the sqlite structure. +** After a database is initialized, the DB_SchemaLoaded bit is set +** bit is set in the flags field of the Db structure. If the database +** file was of zero-length, then the DB_Empty flag is also set. */ int sqlite3Init(sqlite3 *db, char **pzErrMsg){ int i, rc; + int called_initone = 0; if( db->init.busy ) return SQLITE_OK; - assert( (db->flags & SQLITE_Initialized)==0 ); rc = SQLITE_OK; db->init.busy = 1; for(i=0; rc==SQLITE_OK && inDb; i++){ @@ -336,6 +339,7 @@ int sqlite3Init(sqlite3 *db, char **pzErrMsg){ if( rc ){ sqlite3ResetInternalSchema(db, i); } + called_initone = 1; } /* Once all the other databases have been initialised, load the schema @@ -348,19 +352,16 @@ int sqlite3Init(sqlite3 *db, char **pzErrMsg){ if( rc ){ sqlite3ResetInternalSchema(db, 1); } + called_initone = 1; } #endif db->init.busy = 0; - if( rc==SQLITE_OK ){ - db->flags |= SQLITE_Initialized; + if( rc==SQLITE_OK && called_initone ){ sqlite3CommitInternalChanges(db); } - if( rc!=SQLITE_OK ){ - db->flags &= ~SQLITE_Initialized; - } - return rc; + return rc; } /* @@ -371,11 +372,8 @@ int sqlite3ReadSchema(Parse *pParse){ int rc = SQLITE_OK; sqlite3 *db = pParse->db; if( !db->init.busy ){ - if( (db->flags & SQLITE_Initialized)==0 ){ - rc = sqlite3Init(db, &pParse->zErrMsg); - } + rc = sqlite3Init(db, &pParse->zErrMsg); } - assert( rc!=SQLITE_OK || (db->flags & SQLITE_Initialized) || db->init.busy ); if( rc!=SQLITE_OK ){ pParse->rc = rc; pParse->nErr++; @@ -402,7 +400,7 @@ static int schemaIsValid(sqlite3 *db){ rc = sqlite3BtreeCursor(pBt, MASTER_ROOT, 0, 0, 0, &curTemp); if( rc==SQLITE_OK ){ rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&cookie); - if( rc==SQLITE_OK && cookie!=db->aDb[iDb].schema_cookie ){ + if( rc==SQLITE_OK && cookie!=db->aDb[iDb].pSchema->schema_cookie ){ allOk = 0; } sqlite3BtreeCloseCursor(curTemp); @@ -411,6 +409,88 @@ static int schemaIsValid(sqlite3 *db){ return allOk; } +/* +** Free all resources held by the schema structure. The void* argument points +** at a Schema struct. This function does not call sqliteFree() on the +** pointer itself, it just cleans up subsiduary resources (i.e. the contents +** of the schema hash tables). +*/ +void sqlite3SchemaFree(void *p){ + Hash temp1; + Hash temp2; + HashElem *pElem; + Schema *pSchema = (Schema *)p; + + temp1 = pSchema->tblHash; + temp2 = pSchema->trigHash; + sqlite3HashInit(&pSchema->trigHash, SQLITE_HASH_STRING, 0); + sqlite3HashClear(&pSchema->aFKey); + sqlite3HashClear(&pSchema->idxHash); + for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){ + sqlite3DeleteTrigger((Trigger*)sqliteHashData(pElem)); + } + sqlite3HashClear(&temp2); + sqlite3HashInit(&pSchema->tblHash, SQLITE_HASH_STRING, 0); + for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){ + Table *pTab = sqliteHashData(pElem); + sqlite3DeleteTable(0, pTab); + } + sqlite3HashClear(&temp1); + pSchema->pSeqTab = 0; + pSchema->flags &= ~DB_SchemaLoaded; +} + +/* +** Find and return the schema associated with a BTree. Create +** a new one if necessary. +*/ +Schema *sqlite3SchemaGet(Btree *pBt){ + Schema * p; + if( pBt ){ + p = (Schema *)sqlite3BtreeSchema(pBt,sizeof(Schema),sqlite3SchemaFree); + }else{ + p = (Schema *)sqliteMalloc(sizeof(Schema)); + } + if( p && 0==p->file_format ){ + sqlite3HashInit(&p->tblHash, SQLITE_HASH_STRING, 0); + sqlite3HashInit(&p->idxHash, SQLITE_HASH_STRING, 0); + sqlite3HashInit(&p->trigHash, SQLITE_HASH_STRING, 0); + sqlite3HashInit(&p->aFKey, SQLITE_HASH_STRING, 1); + } + return p; +} + +/* +** Convert a schema pointer into the iDb index that indicates +** which database file in db->aDb[] the schema refers to. +** +** If the same database is attached more than once, the first +** attached database is returned. +*/ +int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){ + int i = -1000000; + + /* If pSchema is NULL, then return -1000000. This happens when code in + ** expr.c is trying to resolve a reference to a transient table (i.e. one + ** created by a sub-select). In this case the return value of this + ** function should never be used. + ** + ** We return -1000000 instead of the more usual -1 simply because using + ** -1000000 as incorrectly using -1000000 index into db->aDb[] is much + ** more likely to cause a segfault than -1 (of course there are assert() + ** statements too, but it never hurts to play the odds). + */ + if( pSchema ){ + for(i=0; inDb; i++){ + if( db->aDb[i].pSchema==pSchema ){ + break; + } + } + assert( i>=0 &&i>=0 && inDb ); + } + return i; +} + /* ** Compile the UTF-8 encoded SQL statement zSql into a statement handle. */ @@ -424,10 +504,10 @@ int sqlite3_prepare( Parse sParse; char *zErrMsg = 0; int rc = SQLITE_OK; + int i; - if( sqlite3_malloc_failed ){ - return SQLITE_NOMEM; - } + /* Assert that malloc() has not failed */ + assert( !sqlite3MallocFailed() ); assert( ppStmt ); *ppStmt = 0; @@ -435,19 +515,35 @@ int sqlite3_prepare( return SQLITE_MISUSE; } + /* If any attached database schemas are locked, do not proceed with + ** compilation. Instead return SQLITE_LOCKED immediately. + */ + for(i=0; inDb; i++) { + Btree *pBt = db->aDb[i].pBt; + if( pBt && sqlite3BtreeSchemaLocked(pBt) ){ + const char *zDb = db->aDb[i].zName; + sqlite3Error(db, SQLITE_LOCKED, "database schema is locked: %s", zDb); + sqlite3SafetyOff(db); + return SQLITE_LOCKED; + } + } + memset(&sParse, 0, sizeof(sParse)); sParse.db = db; - sqlite3RunParser(&sParse, zSql, &zErrMsg); + if( nBytes>=0 && zSql[nBytes]!=0 ){ + char *zSqlCopy = sqlite3StrNDup(zSql, nBytes); + sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg); + sParse.zTail += zSql - zSqlCopy; + sqliteFree(zSqlCopy); + }else{ + sqlite3RunParser(&sParse, zSql, &zErrMsg); + } - if( sqlite3_malloc_failed ){ - rc = SQLITE_NOMEM; - sqlite3RollbackAll(db); - sqlite3ResetInternalSchema(db, 0); - db->flags &= ~SQLITE_InTrans; - goto prepare_out; + if( sqlite3MallocFailed() ){ + sParse.rc = SQLITE_NOMEM; } if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK; - if( sParse.rc!=SQLITE_OK && sParse.checkSchema && !schemaIsValid(db) ){ + if( sParse.checkSchema && !schemaIsValid(db) ){ sParse.rc = SQLITE_SCHEMA; } if( sParse.rc==SQLITE_SCHEMA ){ @@ -474,7 +570,6 @@ int sqlite3_prepare( } #endif -prepare_out: if( sqlite3SafetyOff(db) ){ rc = SQLITE_MISUSE; } @@ -490,6 +585,9 @@ prepare_out: }else{ sqlite3Error(db, rc, 0); } + + rc = sqlite3ApiExit(db, rc); + sqlite3ReleaseThreadData(); return rc; } @@ -508,22 +606,17 @@ int sqlite3_prepare16( ** encoded string to UTF-8, then invoking sqlite3_prepare(). The ** tricky bit is figuring out the pointer to return in *pzTail. */ - char const *zSql8 = 0; - char const *zTail8 = 0; - int rc; - sqlite3_value *pTmp; + char *zSql8; + const char *zTail8 = 0; + int rc = SQLITE_OK; if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } - pTmp = sqlite3GetTransientValue(db); - sqlite3ValueSetStr(pTmp, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC); - zSql8 = sqlite3ValueText(pTmp, SQLITE_UTF8); - if( !zSql8 ){ - sqlite3Error(db, SQLITE_NOMEM, 0); - return SQLITE_NOMEM; + zSql8 = sqlite3utf16to8(zSql, nBytes); + if( zSql8 ){ + rc = sqlite3_prepare(db, zSql8, -1, ppStmt, &zTail8); } - rc = sqlite3_prepare(db, zSql8, -1, ppStmt, &zTail8); if( zTail8 && pzTail ){ /* If sqlite3_prepare returns a tail pointer, we calculate the @@ -534,7 +627,7 @@ int sqlite3_prepare16( int chars_parsed = sqlite3utf8CharLen(zSql8, zTail8-zSql8); *pzTail = (u8 *)zSql + sqlite3utf16ByteLen(zSql, chars_parsed); } - - return rc; + sqliteFree(zSql8); + return sqlite3ApiExit(db, rc); } #endif /* SQLITE_OMIT_UTF16 */ diff --git a/mozilla/db/sqlite3/src/printf.c b/mozilla/db/sqlite3/src/printf.c index a669eb8d44d..261a5541426 100644 --- a/mozilla/db/sqlite3/src/printf.c +++ b/mozilla/db/sqlite3/src/printf.c @@ -120,10 +120,12 @@ static const et_info fmtinfo[] = { { 'u', 10, 0, etRADIX, 0, 0 }, { 'x', 16, 0, etRADIX, 16, 1 }, { 'X', 16, 0, etRADIX, 0, 4 }, +#ifndef SQLITE_OMIT_FLOATING_POINT { 'f', 0, 1, etFLOAT, 0, 0 }, { 'e', 0, 1, etEXP, 30, 0 }, { 'E', 0, 1, etEXP, 14, 0 }, { 'G', 0, 1, etGENERIC, 14, 0 }, +#endif { 'i', 10, 1, etRADIX, 0, 0 }, { 'n', 0, 0, etSIZE, 0, 0 }, { '%', 0, 0, etPERCENT, 0, 0 }, @@ -134,10 +136,10 @@ static const et_info fmtinfo[] = { #define etNINFO (sizeof(fmtinfo)/sizeof(fmtinfo[0])) /* -** If NOFLOATINGPOINT is defined, then none of the floating point +** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point ** conversions will work. */ -#ifndef etNOFLOATINGPOINT +#ifndef SQLITE_OMIT_FLOATING_POINT /* ** "*val" is a double such that 0.1 <= *val < 10.0 ** Return the ascii code for the leading digit of *val, then @@ -161,7 +163,7 @@ static int et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){ *val = (*val - d)*10.0; return digit; } -#endif +#endif /* SQLITE_OMIT_FLOATING_POINT */ /* ** On machines with a small stack size, you can redefine the @@ -234,7 +236,7 @@ static int vxprintf( static const char spaces[] = " "; #define etSPACESIZE (sizeof(spaces)-1) -#ifndef etNOFLOATINGPOINT +#ifndef SQLITE_OMIT_FLOATING_POINT int exp, e2; /* exponent of real numbers */ double rounder; /* Used for rounding floating point values */ etByte flag_dp; /* True if decimal point should be shown */ @@ -425,7 +427,7 @@ static int vxprintf( case etEXP: case etGENERIC: realvalue = va_arg(ap,double); -#ifndef etNOFLOATINGPOINT +#ifndef SQLITE_OMIT_FLOATING_POINT if( precision<0 ) precision = 6; /* Set default precision */ if( precision>etBUFSIZE/2-10 ) precision = etBUFSIZE/2-10; if( realvalue<0.0 ){ @@ -594,13 +596,13 @@ static int vxprintf( break; case etSQLESCAPE: case etSQLESCAPE2: { - int i, j, n, c, isnull; + int i, j, n, ch, 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++; + char *escarg = va_arg(ap,char*); + isnull = escarg==0; + if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)"); + for(i=n=0; (ch=escarg[i])!=0; i++){ + if( ch=='\'' ) n++; } needQuote = !isnull && xtype==etSQLESCAPE2; n += i + 1 + needQuote*2; @@ -612,9 +614,9 @@ static int vxprintf( } j = 0; if( needQuote ) bufpt[j++] = '\''; - for(i=0; (c=arg[i])!=0; i++){ - bufpt[j++] = c; - if( c=='\'' ) bufpt[j++] = c; + for(i=0; (ch=escarg[i])!=0; i++){ + bufpt[j++] = ch; + if( ch=='\'' ) bufpt[j++] = ch; } if( needQuote ) bufpt[j++] = '\''; bufpt[j] = 0; @@ -625,7 +627,7 @@ static int vxprintf( case etTOKEN: { Token *pToken = va_arg(ap, Token*); if( pToken && pToken->z ){ - (*func)(arg, pToken->z, pToken->n); + (*func)(arg, (char*)pToken->z, pToken->n); } length = width = 0; break; diff --git a/mozilla/db/sqlite3/src/random.c b/mozilla/db/sqlite3/src/random.c index 3d0903b4e98..cad6d166def 100644 --- a/mozilla/db/sqlite3/src/random.c +++ b/mozilla/db/sqlite3/src/random.c @@ -15,7 +15,7 @@ ** Random numbers are used by some of the database backends in order ** to generate random integer keys for tables or random filenames. ** -** $Id: random.c,v 1.13 2005/06/12 21:35:52 drh Exp $ +** $Id: random.c,v 1.15 2006/01/06 14:32:20 drh Exp $ */ #include "sqliteInt.h" #include "os.h" diff --git a/mozilla/db/sqlite3/src/select.c b/mozilla/db/sqlite3/src/select.c index 3b99cf408cd..14d8a00c140 100644 --- a/mozilla/db/sqlite3/src/select.c +++ b/mozilla/db/sqlite3/src/select.c @@ -12,11 +12,28 @@ ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.276 2005/09/20 18:13:24 drh Exp $ +** $Id: select.c,v 1.301 2006/01/24 12:09:19 danielk1977 Exp $ */ #include "sqliteInt.h" +/* +** Delete all the content of a Select structure but do not deallocate +** the select structure itself. +*/ +static void clearSelect(Select *p){ + sqlite3ExprListDelete(p->pEList); + sqlite3SrcListDelete(p->pSrc); + sqlite3ExprDelete(p->pWhere); + sqlite3ExprListDelete(p->pGroupBy); + sqlite3ExprDelete(p->pHaving); + sqlite3ExprListDelete(p->pOrderBy); + sqlite3SelectDelete(p->pPrior); + sqlite3ExprDelete(p->pLimit); + sqlite3ExprDelete(p->pOffset); +} + + /* ** Allocate a new Select structure and return a pointer to that ** structure. @@ -33,40 +50,48 @@ Select *sqlite3SelectNew( Expr *pOffset /* OFFSET value. NULL means no offset */ ){ Select *pNew; + Select standin; pNew = sqliteMalloc( sizeof(*pNew) ); assert( !pOffset || pLimit ); /* Can't have OFFSET without LIMIT. */ if( pNew==0 ){ - sqlite3ExprListDelete(pEList); - sqlite3SrcListDelete(pSrc); - sqlite3ExprDelete(pWhere); - sqlite3ExprListDelete(pGroupBy); - sqlite3ExprDelete(pHaving); - sqlite3ExprListDelete(pOrderBy); - sqlite3ExprDelete(pLimit); - sqlite3ExprDelete(pOffset); - }else{ - if( pEList==0 ){ - pEList = sqlite3ExprListAppend(0, sqlite3Expr(TK_ALL,0,0,0), 0); - } - pNew->pEList = pEList; - pNew->pSrc = pSrc; - pNew->pWhere = pWhere; - pNew->pGroupBy = pGroupBy; - pNew->pHaving = pHaving; - pNew->pOrderBy = pOrderBy; - pNew->isDistinct = isDistinct; - pNew->op = TK_SELECT; - pNew->pLimit = pLimit; - pNew->pOffset = pOffset; - pNew->iLimit = -1; - pNew->iOffset = -1; - pNew->addrOpenVirt[0] = -1; - pNew->addrOpenVirt[1] = -1; - pNew->addrOpenVirt[2] = -1; + pNew = &standin; + memset(pNew, 0, sizeof(*pNew)); + } + if( pEList==0 ){ + pEList = sqlite3ExprListAppend(0, sqlite3Expr(TK_ALL,0,0,0), 0); + } + pNew->pEList = pEList; + pNew->pSrc = pSrc; + pNew->pWhere = pWhere; + pNew->pGroupBy = pGroupBy; + pNew->pHaving = pHaving; + pNew->pOrderBy = pOrderBy; + pNew->isDistinct = isDistinct; + pNew->op = TK_SELECT; + pNew->pLimit = pLimit; + pNew->pOffset = pOffset; + pNew->iLimit = -1; + pNew->iOffset = -1; + pNew->addrOpenVirt[0] = -1; + pNew->addrOpenVirt[1] = -1; + pNew->addrOpenVirt[2] = -1; + if( pNew==&standin) { + clearSelect(pNew); + pNew = 0; } return pNew; } +/* +** Delete the given Select structure and all of its substructures. +*/ +void sqlite3SelectDelete(Select *p){ + if( p ){ + clearSelect(p); + sqliteFree(p); + } +} + /* ** Given 1 to 3 identifiers preceeding the JOIN keyword, determine the ** type of join. Return an integer constant that expresses that type @@ -109,7 +134,7 @@ int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){ p = apAll[i]; for(j=0; jn==keywords[j].nChar - && sqlite3StrNICmp(p->z, keywords[j].zKeyword, p->n)==0 ){ + && sqlite3StrNICmp((char*)p->z, keywords[j].zKeyword, p->n)==0 ){ jointype |= keywords[j].code; break; } @@ -154,8 +179,8 @@ static int columnIndex(Table *pTab, const char *zCol){ ** Set the value of a token to a '\000'-terminated string. */ static void setToken(Token *p, const char *z){ - p->z = z; - p->n = strlen(z); + p->z = (u8*)z; + p->n = z ? strlen(z) : 0; p->dyn = 0; } @@ -330,59 +355,53 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){ return 0; } -/* -** Delete the given Select structure and all of its substructures. -*/ -void sqlite3SelectDelete(Select *p){ - if( p==0 ) return; - sqlite3ExprListDelete(p->pEList); - sqlite3SrcListDelete(p->pSrc); - sqlite3ExprDelete(p->pWhere); - sqlite3ExprListDelete(p->pGroupBy); - sqlite3ExprDelete(p->pHaving); - sqlite3ExprListDelete(p->pOrderBy); - sqlite3SelectDelete(p->pPrior); - sqlite3ExprDelete(p->pLimit); - sqlite3ExprDelete(p->pOffset); - sqliteFree(p); -} - /* ** Insert code into "v" that will push the record on the top of the ** stack into the sorter. */ -static void pushOntoSorter(Parse *pParse, Vdbe *v, ExprList *pOrderBy){ +static void pushOntoSorter( + Parse *pParse, /* Parser context */ + ExprList *pOrderBy, /* The ORDER BY clause */ + Select *pSelect /* The whole SELECT statement */ +){ + Vdbe *v = pParse->pVdbe; sqlite3ExprCodeExprList(pParse, pOrderBy); sqlite3VdbeAddOp(v, OP_Sequence, pOrderBy->iECursor, 0); sqlite3VdbeAddOp(v, OP_Pull, pOrderBy->nExpr + 1, 0); sqlite3VdbeAddOp(v, OP_MakeRecord, pOrderBy->nExpr + 2, 0); sqlite3VdbeAddOp(v, OP_IdxInsert, pOrderBy->iECursor, 0); + if( pSelect->iLimit>=0 ){ + int addr1, addr2; + addr1 = sqlite3VdbeAddOp(v, OP_IfMemZero, pSelect->iLimit+1, 0); + sqlite3VdbeAddOp(v, OP_MemIncr, -1, pSelect->iLimit+1); + addr2 = sqlite3VdbeAddOp(v, OP_Goto, 0, 0); + sqlite3VdbeJumpHere(v, addr1); + sqlite3VdbeAddOp(v, OP_Last, pOrderBy->iECursor, 0); + sqlite3VdbeAddOp(v, OP_Delete, pOrderBy->iECursor, 0); + sqlite3VdbeJumpHere(v, addr2); + pSelect->iLimit = -1; + } } /* -** Add code to implement the OFFSET and LIMIT +** Add code to implement the OFFSET */ -static void codeLimiter( +static void codeOffset( Vdbe *v, /* Generate code into this VM */ Select *p, /* The SELECT statement being coded */ int iContinue, /* Jump here to skip the current record */ - int iBreak, /* Jump here to end the loop */ int nPop /* Number of times to pop stack when jumping */ ){ if( p->iOffset>=0 && iContinue!=0 ){ - int addr = sqlite3VdbeCurrentAddr(v) + 3; - if( nPop>0 ) addr++; - sqlite3VdbeAddOp(v, OP_MemIncr, p->iOffset, 0); - sqlite3VdbeAddOp(v, OP_IfMemPos, p->iOffset, addr); + int addr; + sqlite3VdbeAddOp(v, OP_MemIncr, -1, p->iOffset); + addr = sqlite3VdbeAddOp(v, OP_IfMemNeg, p->iOffset, 0); if( nPop>0 ){ sqlite3VdbeAddOp(v, OP_Pop, nPop, 0); } sqlite3VdbeAddOp(v, OP_Goto, 0, iContinue); VdbeComment((v, "# skip OFFSET records")); - } - if( p->iLimit>=0 && iBreak!=0 ){ - sqlite3VdbeAddOp(v, OP_MemIncr, p->iLimit, iBreak); - VdbeComment((v, "# exit when LIMIT reached")); + sqlite3VdbeJumpHere(v, addr); } } @@ -447,9 +466,9 @@ static int selectInnerLoop( /* If there was a LIMIT clause on the SELECT statement, then do the check ** to see if this row should be output. */ - hasDistinct = distinct>=0 && pEList && pEList->nExpr>0; + hasDistinct = distinct>=0 && pEList->nExpr>0; if( pOrderBy==0 && !hasDistinct ){ - codeLimiter(v, p, iContinue, iBreak, 0); + codeOffset(v, p, iContinue, 0); } /* Pull the requested columns. @@ -471,7 +490,7 @@ static int selectInnerLoop( int n = pEList->nExpr; codeDistinct(v, distinct, iContinue, n, n+1); if( pOrderBy==0 ){ - codeLimiter(v, p, iContinue, iBreak, nColumn); + codeOffset(v, p, iContinue, nColumn); } } @@ -509,7 +528,7 @@ static int selectInnerLoop( case SRT_VirtualTab: { sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); if( pOrderBy ){ - pushOntoSorter(pParse, v, pOrderBy); + pushOntoSorter(pParse, pOrderBy, p); }else{ sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0); sqlite3VdbeAddOp(v, OP_Pull, 1, 0); @@ -536,29 +555,37 @@ static int selectInnerLoop( ** ORDER BY in this case since the order of entries in the set ** does not matter. But there might be a LIMIT clause, in which ** case the order does matter */ - pushOntoSorter(pParse, v, pOrderBy); + pushOntoSorter(pParse, pOrderBy, p); }else{ - char aff = (iParm>>16)&0xFF; - aff = sqlite3CompareAffinity(pEList->a[0].pExpr, aff); - sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &aff, 1); + char affinity = (iParm>>16)&0xFF; + affinity = sqlite3CompareAffinity(pEList->a[0].pExpr, affinity); + sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &affinity, 1); sqlite3VdbeAddOp(v, OP_IdxInsert, (iParm&0x0000FFFF), 0); } sqlite3VdbeJumpHere(v, addr2); break; } + /* If any row exist in the result set, record that fact and abort. + */ + case SRT_Exists: { + sqlite3VdbeAddOp(v, OP_MemInt, 1, iParm); + sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0); + /* The LIMIT clause will terminate the loop for us */ + break; + } + /* If this is a scalar select that is part of an expression, then ** 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 ){ - pushOntoSorter(pParse, v, pOrderBy); + pushOntoSorter(pParse, pOrderBy, p); }else{ sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1); - sqlite3VdbeAddOp(v, OP_Goto, 0, iBreak); + /* The LIMIT clause will jump out of the loop for us */ } break; } @@ -572,7 +599,7 @@ static int selectInnerLoop( case SRT_Callback: { if( pOrderBy ){ sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); - pushOntoSorter(pParse, v, pOrderBy); + pushOntoSorter(pParse, pOrderBy, p); }else if( eDest==SRT_Subroutine ){ sqlite3VdbeAddOp(v, OP_Gosub, 0, iParm); }else{ @@ -594,6 +621,13 @@ static int selectInnerLoop( } #endif } + + /* Jump to the end of the loop if the LIMIT is reached. + */ + if( p->iLimit>=0 && pOrderBy==0 ){ + sqlite3VdbeAddOp(v, OP_MemIncr, -1, p->iLimit); + sqlite3VdbeAddOp(v, OP_IfMemZero, p->iLimit, iBreak); + } return 0; } @@ -622,9 +656,9 @@ static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList){ nExpr = pList->nExpr; pInfo = sqliteMalloc( sizeof(*pInfo) + nExpr*(sizeof(CollSeq*)+1) ); if( pInfo ){ - pInfo->aSortOrder = (char*)&pInfo->aColl[nExpr]; + pInfo->aSortOrder = (u8*)&pInfo->aColl[nExpr]; pInfo->nField = nExpr; - pInfo->enc = db->enc; + pInfo->enc = ENC(db); for(i=0, pItem=pList->a; ipExpr); @@ -661,7 +695,7 @@ static void generateSortTail( iTab = pOrderBy->iECursor; addr = 1 + sqlite3VdbeAddOp(v, OP_Sort, iTab, brk); - codeLimiter(v, p, cont, brk, 0); + codeOffset(v, p, cont, 0); sqlite3VdbeAddOp(v, OP_Column, iTab, pOrderBy->nExpr + 1); switch( eDest ){ case SRT_Table: @@ -677,15 +711,14 @@ static void generateSortTail( sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3); sqlite3VdbeAddOp(v, OP_Pop, 1, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3); - sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, "n", P3_STATIC); + sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, "c", P3_STATIC); sqlite3VdbeAddOp(v, OP_IdxInsert, (iParm&0x0000FFFF), 0); break; } - case SRT_Exists: case SRT_Mem: { assert( nColumn==1 ); sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1); - sqlite3VdbeAddOp(v, OP_Goto, 0, brk); + /* The LIMIT clause will terminate the loop for us */ break; } #endif @@ -710,6 +743,16 @@ static void generateSortTail( break; } } + + /* Jump to the end of the loop when the LIMIT is reached + */ + if( p->iLimit>=0 ){ + sqlite3VdbeAddOp(v, OP_MemIncr, -1, p->iLimit); + sqlite3VdbeAddOp(v, OP_IfMemZero, p->iLimit, brk); + } + + /* The bottom of the loop + */ sqlite3VdbeResolveLabel(v, cont); sqlite3VdbeAddOp(v, OP_Next, iTab, addr); sqlite3VdbeResolveLabel(v, brk); @@ -837,7 +880,7 @@ static void generateColumnNames( #endif assert( v!=0 ); - if( pParse->colNamesSet || v==0 || sqlite3_malloc_failed ) return; + if( pParse->colNamesSet || v==0 || sqlite3MallocFailed() ) return; pParse->colNamesSet = 1; fullNames = (db->flags & SQLITE_FullColNames)!=0; shortNames = (db->flags & SQLITE_ShortColNames)!=0; @@ -866,20 +909,20 @@ static void generateColumnNames( zCol = pTab->aCol[iCol].zName; } if( !shortNames && !fullNames && p->span.z && p->span.z[0] ){ - sqlite3VdbeSetColName(v, i, p->span.z, p->span.n); + sqlite3VdbeSetColName(v, i, (char*)p->span.z, p->span.n); }else if( fullNames || (!shortNames && pTabList->nSrc>1) ){ char *zName = 0; char *zTab; zTab = pTabList->a[j].zAlias; if( fullNames || zTab==0 ) zTab = pTab->zName; - sqlite3SetString(&zName, zTab, ".", zCol, 0); + sqlite3SetString(&zName, zTab, ".", zCol, (char*)0); sqlite3VdbeSetColName(v, i, zName, P3_DYNAMIC); }else{ sqlite3VdbeSetColName(v, i, zCol, strlen(zCol)); } }else if( p->span.z && p->span.z[0] ){ - sqlite3VdbeSetColName(v, i, p->span.z, p->span.n); + sqlite3VdbeSetColName(v, i, (char*)p->span.z, p->span.n); /* sqlite3VdbeCompressSpace(v, addr); */ }else{ char zName[30]; @@ -943,6 +986,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ char *zType; char *zName; char *zBasename; + CollSeq *pColl; int cnt; NameContext sNC; @@ -965,7 +1009,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ zName = sqlite3MPrintf("column%d", i+1); } sqlite3Dequote(zName); - if( sqlite3_malloc_failed ){ + if( sqlite3MallocFailed() ){ sqliteFree(zName); sqlite3DeleteTable(0, pTab); return 0; @@ -995,9 +1039,9 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ zType = sqliteStrDup(columnType(&sNC, p)); pCol->zType = zType; pCol->affinity = sqlite3ExprAffinity(p); - pCol->pColl = sqlite3ExprCollSeq(pParse, p); - if( !pCol->pColl ){ - pCol->pColl = pParse->db->pDfltColl; + pColl = sqlite3ExprCollSeq(pParse, p); + if( pColl ){ + pCol->zColl = sqliteStrDup(pColl->zName); } } pTab->iPKey = -1; @@ -1034,10 +1078,11 @@ static int prepSelectStmt(Parse *pParse, Select *p){ int i, j, k, rc; SrcList *pTabList; ExprList *pEList; - Table *pTab; struct SrcList_item *pFrom; - if( p==0 || p->pSrc==0 || sqlite3_malloc_failed ) return 1; + if( p==0 || p->pSrc==0 || sqlite3MallocFailed() ){ + return 1; + } pTabList = p->pSrc; pEList = p->pEList; @@ -1051,6 +1096,7 @@ static int prepSelectStmt(Parse *pParse, Select *p){ ** then create a transient table structure to describe the subquery. */ for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ + Table *pTab; if( pFrom->pTab!=0 ){ /* This statement has already been prepared. There is no need ** to go further. */ @@ -1145,7 +1191,11 @@ static int prepSelectStmt(Parse *pParse, Select *p){ /* This particular expression does not need to be expanded. */ pNew = sqlite3ExprListAppend(pNew, a[k].pExpr, 0); - pNew->a[pNew->nExpr-1].zName = a[k].zName; + if( pNew ){ + pNew->a[pNew->nExpr-1].zName = a[k].zName; + }else{ + rc = 1; + } a[k].pExpr = 0; a[k].zName = 0; }else{ @@ -1170,7 +1220,7 @@ static int prepSelectStmt(Parse *pParse, Select *p){ } tableSeen = 1; for(j=0; jnCol; j++){ - Expr *pExpr, *pLeft, *pRight; + Expr *pExpr, *pRight; char *zName = pTab->aCol[j].zName; if( i>0 ){ @@ -1191,7 +1241,7 @@ static int prepSelectStmt(Parse *pParse, Select *p){ if( pRight==0 ) break; setToken(&pRight->token, zName); if( zTabName && (longNames || pTabList->nSrc>1) ){ - pLeft = sqlite3Expr(TK_ID, 0, 0, 0); + Expr *pLeft = sqlite3Expr(TK_ID, 0, 0, 0); pExpr = sqlite3Expr(TK_DOT, pLeft, pRight, 0); if( pExpr==0 ) break; setToken(&pLeft->token, zTabName); @@ -1326,25 +1376,31 @@ Vdbe *sqlite3GetVdbe(Parse *pParse){ return v; } + /* ** Compute the iLimit and iOffset fields of the SELECT based on the -** pLimit and pOffset expressions. nLimit and nOffset hold the expressions +** pLimit and pOffset expressions. pLimit and pOffset hold the expressions ** that appear in the original SQL statement after the LIMIT and OFFSET ** 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 +** This routine changes the values of iLimit and iOffset only if +** a limit or offset is defined by pLimit and pOffset. iLimit and ** iOffset should have been preset to appropriate default values ** (usually but not always -1) prior to calling this routine. -** Only if nLimit>=0 or nOffset>0 do the limit registers get +** Only if pLimit!=0 or pOffset!=0 do the limit registers get ** redefined. The UNION ALL operator uses this property to force ** the reuse of the same limit and offset registers across multiple ** SELECT statements. */ -static void computeLimitRegisters(Parse *pParse, Select *p){ +static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ + Vdbe *v = 0; + int iLimit = 0; + int iOffset; + int addr1, addr2; + /* ** "LIMIT -1" always shows all rows. There is some ** contraversy about what the correct behavior should be. @@ -1352,26 +1408,41 @@ static void computeLimitRegisters(Parse *pParse, Select *p){ ** no rows. */ if( p->pLimit ){ - int iMem = pParse->nMem++; - Vdbe *v = sqlite3GetVdbe(pParse); + p->iLimit = iLimit = pParse->nMem; + pParse->nMem += 2; + v = sqlite3GetVdbe(pParse); if( v==0 ) return; sqlite3ExprCode(pParse, p->pLimit); sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0); - sqlite3VdbeAddOp(v, OP_Negative, 0, 0); - sqlite3VdbeAddOp(v, OP_MemStore, iMem, 1); + sqlite3VdbeAddOp(v, OP_MemStore, iLimit, 0); VdbeComment((v, "# LIMIT counter")); - p->iLimit = iMem; + sqlite3VdbeAddOp(v, OP_IfMemZero, iLimit, iBreak); } if( p->pOffset ){ - int iMem = pParse->nMem++; - Vdbe *v = sqlite3GetVdbe(pParse); + p->iOffset = iOffset = pParse->nMem++; + v = sqlite3GetVdbe(pParse); if( v==0 ) return; sqlite3ExprCode(pParse, p->pOffset); sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0); - sqlite3VdbeAddOp(v, OP_Negative, 0, 0); - sqlite3VdbeAddOp(v, OP_MemStore, iMem, 1); + sqlite3VdbeAddOp(v, OP_MemStore, iOffset, p->pLimit==0); VdbeComment((v, "# OFFSET counter")); - p->iOffset = iMem; + addr1 = sqlite3VdbeAddOp(v, OP_IfMemPos, iOffset, 0); + sqlite3VdbeAddOp(v, OP_Pop, 1, 0); + sqlite3VdbeAddOp(v, OP_Integer, 0, 0); + sqlite3VdbeJumpHere(v, addr1); + if( p->pLimit ){ + sqlite3VdbeAddOp(v, OP_Add, 0, 0); + } + } + if( p->pLimit ){ + addr1 = sqlite3VdbeAddOp(v, OP_IfMemPos, iLimit, 0); + sqlite3VdbeAddOp(v, OP_Pop, 1, 0); + sqlite3VdbeAddOp(v, OP_MemInt, -1, iLimit+1); + addr2 = sqlite3VdbeAddOp(v, OP_Goto, 0, 0); + sqlite3VdbeJumpHere(v, addr1); + sqlite3VdbeAddOp(v, OP_MemStore, iLimit+1, 1); + VdbeComment((v, "# LIMIT+OFFSET")); + sqlite3VdbeJumpHere(v, addr2); } } @@ -1519,23 +1590,31 @@ static int multiSelect( switch( p->op ){ case TK_ALL: { if( pOrderBy==0 ){ + int addr = 0; assert( !pPrior->pLimit ); pPrior->pLimit = p->pLimit; pPrior->pOffset = p->pOffset; rc = sqlite3Select(pParse, pPrior, eDest, iParm, 0, 0, 0, aff); + p->pLimit = 0; + p->pOffset = 0; if( rc ){ goto multi_select_end; } p->pPrior = 0; p->iLimit = pPrior->iLimit; p->iOffset = pPrior->iOffset; - p->pLimit = 0; - p->pOffset = 0; + if( p->iLimit>=0 ){ + addr = sqlite3VdbeAddOp(v, OP_IfMemZero, p->iLimit, 0); + VdbeComment((v, "# Jump ahead if LIMIT reached")); + } rc = sqlite3Select(pParse, p, eDest, iParm, 0, 0, 0, aff); p->pPrior = pPrior; if( rc ){ goto multi_select_end; } + if( addr ){ + sqlite3VdbeJumpHere(v, addr); + } break; } /* For UNION ALL ... ORDER BY fall through to the next case */ @@ -1622,8 +1701,8 @@ static int multiSelect( } iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); + computeLimitRegisters(pParse, p, iBreak); sqlite3VdbeAddOp(v, OP_Rewind, unionTab, iBreak); - computeLimitRegisters(pParse, p); iStart = sqlite3VdbeCurrentAddr(v); rc = selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr, pOrderBy, -1, eDest, iParm, @@ -1698,8 +1777,8 @@ static int multiSelect( } iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); + computeLimitRegisters(pParse, p, iBreak); sqlite3VdbeAddOp(v, OP_Rewind, tab1, iBreak); - computeLimitRegisters(pParse, p); iStart = sqlite3VdbeAddOp(v, OP_RowKey, tab1, 0); sqlite3VdbeAddOp(v, OP_NotFound, tab2, iCont); rc = selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr, @@ -1760,7 +1839,7 @@ static int multiSelect( goto multi_select_end; } - pKeyInfo->enc = pParse->db->enc; + pKeyInfo->enc = ENC(pParse->db); pKeyInfo->nField = nCol; for(i=0, apColl=pKeyInfo->aColl; ia; - int nExpr = pOrderBy->nExpr; + int nOrderByExpr = pOrderBy->nExpr; int addr; u8 *pSortOrder; - aCopy = (CollSeq**)&pKeyInfo[1]; - pSortOrder = pKeyInfo->aSortOrder = (u8*)&aCopy[nExpr]; + aCopy = &pKeyInfo->aColl[nCol]; + pSortOrder = pKeyInfo->aSortOrder = (u8*)&aCopy[nCol]; memcpy(aCopy, pKeyInfo->aColl, nCol*sizeof(CollSeq*)); apColl = pKeyInfo->aColl; - for(i=0; inExpr; i++, pOTerm++, apColl++, pSortOrder++){ + for(i=0; ipExpr; char *zName = pOTerm->zName; assert( pExpr->op==TK_COLUMN && pExpr->iColumnaddrOpenVirt[2]>=0 ); addr = p->addrOpenVirt[2]; sqlite3VdbeChangeP2(v, addr, p->pEList->nExpr+2); - pKeyInfo->nField = pOrderBy->nExpr; + pKeyInfo->nField = nOrderByExpr; sqlite3VdbeChangeP3(v, addr, (char*)pKeyInfo, P3_KEYINFO_HANDOFF); pKeyInfo = 0; generateSortTail(pParse, p, v, p->pEList->nExpr, eDest, iParm); @@ -1949,6 +2028,10 @@ static void substSelect(Select *p, int iTable, ExprList *pEList){ ** (12) The subquery is not the right term of a LEFT OUTER JOIN or the ** subquery has no WHERE clause. (added by ticket #350) ** +** (13) The subquery and outer query do not both use LIMIT +** +** (14) The subquery does not use OFFSET +** ** In this routine, the "p" parameter is a pointer to the outer query. ** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query ** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates. @@ -1983,18 +2066,26 @@ static int flattenSubquery( pSubitem = &pSrc->a[iFrom]; pSub = pSubitem->pSelect; assert( pSub!=0 ); - if( isAgg && subqueryIsAgg ) return 0; - if( subqueryIsAgg && pSrc->nSrc>1 ) return 0; + if( isAgg && subqueryIsAgg ) return 0; /* Restriction (1) */ + if( subqueryIsAgg && pSrc->nSrc>1 ) return 0; /* Restriction (2) */ 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 && (pSrc->nSrc>1 || isAgg) ){ - return 0; + /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants, + ** not arbitrary expresssions, we allowed some combining of LIMIT and OFFSET + ** because they could be computed at compile-time. But when LIMIT and OFFSET + ** became arbitrary expressions, we were forced to add restrictions (13) + ** and (14). */ + if( pSub->pLimit && p->pLimit ) return 0; /* Restriction (13) */ + if( pSub->pOffset ) return 0; /* Restriction (14) */ + if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */ + if( (pSub->isDistinct || pSub->pLimit) + && (pSrc->nSrc>1 || isAgg) ){ /* Restrictions (4)(5)(8)(9) */ + return 0; + } + if( p->isDistinct && subqueryIsAgg ) return 0; /* Restriction (6) */ + if( (p->disallowOrderBy || p->pOrderBy) && pSub->pOrderBy ){ + return 0; /* Restriction (11) */ } - if( p->isDistinct && subqueryIsAgg ) return 0; - if( (p->disallowOrderBy || p->pOrderBy) && pSub->pOrderBy ) return 0; /* Restriction 3: If the subquery is a join, make sure the subquery is ** not used as the right operand of an outer join. Examples of why this @@ -2085,7 +2176,7 @@ static int flattenSubquery( for(i=0; inExpr; i++){ Expr *pExpr; if( pList->a[i].zName==0 && (pExpr = pList->a[i].pExpr)->span.z!=0 ){ - pList->a[i].zName = sqliteStrNDup(pExpr->span.z, pExpr->span.n); + pList->a[i].zName = sqliteStrNDup((char*)pExpr->span.z, pExpr->span.n); } } if( isAgg ){ @@ -2124,6 +2215,9 @@ static int flattenSubquery( /* ** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y; + ** + ** One is tempted to try to add a and b to combine the limits. But this + ** does not work if either limit is negative. */ if( pSub->pLimit ){ p->pLimit = pSub->pLimit; @@ -2166,10 +2260,11 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ int base; Vdbe *v; int seekOp; - int cont; ExprList *pEList, *pList, eList; struct ExprList_item eListItem; SrcList *pSrc; + int brk; + int iDb; /* Check to see if this query is a simple min() or max() query. Return ** zero if it is not. @@ -2184,9 +2279,9 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ pList = pExpr->pList; if( pList==0 || pList->nExpr!=1 ) return 0; if( pExpr->token.n!=3 ) return 0; - if( sqlite3StrNICmp(pExpr->token.z,"min",3)==0 ){ + if( sqlite3StrNICmp((char*)pExpr->token.z,"min",3)==0 ){ seekOp = OP_Rewind; - }else if( sqlite3StrNICmp(pExpr->token.z,"max",3)==0 ){ + }else if( sqlite3StrNICmp((char*)pExpr->token.z,"max",3)==0 ){ seekOp = OP_Last; }else{ return 0; @@ -2196,6 +2291,7 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ iCol = pExpr->iColumn; pTab = pSrc->a[0].pTab; + /* If we get to here, it means the query is of the correct form. ** Check to make sure we have an index and make pIdx point to the ** appropriate index. If the min() or max() is on an INTEGER PRIMARY @@ -2208,7 +2304,10 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr); for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ assert( pIdx->nColumn>=1 ); - if( pIdx->aiColumn[0]==iCol && pIdx->keyInfo.aColl[0]==pColl ) break; + if( pIdx->aiColumn[0]==iCol && + 0==sqlite3StrICmp(pIdx->azColl[0], pColl->zName) ){ + break; + } } if( pIdx==0 ) return 0; } @@ -2231,13 +2330,16 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ ** the min() or max() is on the INTEGER PRIMARY KEY, then find the first ** or last entry in the main table. */ - sqlite3CodeVerifySchema(pParse, pTab->iDb); + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + assert( iDb>=0 || pTab->isTransient ); + sqlite3CodeVerifySchema(pParse, iDb); + sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); base = pSrc->a[0].iCursor; - computeLimitRegisters(pParse, p); + brk = sqlite3VdbeMakeLabel(v); + computeLimitRegisters(pParse, p, brk); if( pSrc->a[0].pSelect==0 ){ - sqlite3OpenTableForReading(v, base, pTab); + sqlite3OpenTable(pParse, base, iDb, pTab, OP_OpenRead); } - cont = sqlite3VdbeMakeLabel(v); if( pIdx==0 ){ sqlite3VdbeAddOp(v, seekOp, base, 0); }else{ @@ -2248,10 +2350,12 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ ** "INSERT INTO x SELECT max() FROM x". */ int iIdx; + KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); iIdx = pParse->nTab++; - sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0); - sqlite3VdbeOp3(v, OP_OpenRead, iIdx, pIdx->tnum, - (char*)&pIdx->keyInfo, P3_KEYINFO); + assert( pIdx->pSchema==pTab->pSchema ); + sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); + sqlite3VdbeOp3(v, OP_OpenRead, iIdx, pIdx->tnum, + (char*)pKey, P3_KEYINFO_HANDOFF); if( seekOp==OP_Rewind ){ sqlite3VdbeAddOp(v, OP_Null, 0, 0); sqlite3VdbeAddOp(v, OP_MakeRecord, 1, 0); @@ -2266,8 +2370,8 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ memset(&eListItem, 0, sizeof(eListItem)); eList.a = &eListItem; eList.a[0].pExpr = pExpr; - selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, eDest, iParm, cont, cont, 0); - sqlite3VdbeResolveLabel(v, cont); + selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, eDest, iParm, brk, brk, 0); + sqlite3VdbeResolveLabel(v, brk); sqlite3VdbeAddOp(v, OP_Close, base, 0); return 1; @@ -2356,14 +2460,8 @@ int sqlite3SelectResolve( /* Resolve the expressions in the LIMIT and OFFSET clauses. These ** are not allowed to refer to any names, so pass an empty NameContext. */ + memset(&sNC, 0, sizeof(sNC)); 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; @@ -2615,8 +2713,11 @@ int sqlite3Select( int rc = 1; /* Value to return from this function */ int addrSortIndex; /* Address of an OP_OpenVirtual instruction */ AggInfo sAggInfo; /* Information used by aggregate queries */ + int iEnd; /* Address of the end of the query */ - if( sqlite3_malloc_failed || pParse->nErr || p==0 ) return 1; + if( p==0 || sqlite3MallocFailed() || pParse->nErr ){ + return 1; + } if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; memset(&sAggInfo, 0, sizeof(sAggInfo)); @@ -2663,7 +2764,6 @@ int sqlite3Select( /* 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 " @@ -2772,7 +2872,8 @@ int sqlite3Select( /* Set the limiter. */ - computeLimitRegisters(pParse, p); + iEnd = sqlite3VdbeMakeLabel(v); + computeLimitRegisters(pParse, p, iEnd); /* If the output is destined for a temporary table, open that table. */ @@ -2780,15 +2881,6 @@ int sqlite3Select( sqlite3VdbeAddOp(v, OP_OpenVirtual, iParm, pEList->nExpr); } - - /* Initialize the memory cell to NULL for SRT_Mem or 0 for SRT_Exists - */ - if( eDest==SRT_Mem ){ - sqlite3VdbeAddOp(v, OP_MemNull, iParm, 0); - }else if( eDest==SRT_Exists ){ - sqlite3VdbeAddOp(v, OP_MemInt, 0, iParm); - } - /* Open a virtual index to use for the distinct set. */ if( isDistinct ){ @@ -2879,7 +2971,7 @@ int sqlite3Select( goto select_end; } } - if( sqlite3_malloc_failed ) goto select_end; + if( sqlite3MallocFailed() ) goto select_end; /* Processing for aggregates with GROUP BY is very different and ** much more complex tha aggregates without a GROUP BY. @@ -3112,6 +3204,10 @@ int sqlite3Select( } #endif + /* Jump here to skip this query + */ + sqlite3VdbeResolveLabel(v, iEnd); + /* The SELECT was successfully coded. Set the return code to 0 ** to indicate no errors. */ diff --git a/mozilla/db/sqlite3/src/shell.c b/mozilla/db/sqlite3/src/shell.c index 3296f44bfe6..02040a238be 100644 --- a/mozilla/db/sqlite3/src/shell.c +++ b/mozilla/db/sqlite3/src/shell.c @@ -12,7 +12,7 @@ ** This file contains code to implement the "sqlite" command line ** utility for accessing SQLite databases. ** -** $Id: shell.c,v 1.128 2005/09/11 02:03:04 drh Exp $ +** $Id: shell.c,v 1.131 2006/01/25 15:55:38 drh Exp $ */ #include #include @@ -81,7 +81,7 @@ static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */ /* ** Determines if a string is a number of not. */ -static int isNumber(const unsigned char *z, int *realnum){ +static int isNumber(const char *z, int *realnum){ if( *z=='-' || *z=='+' ) z++; if( !isdigit(*z) ){ return 0; @@ -690,8 +690,9 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){ zSelect = appendText(zSelect, " || ' VALUES(' || ", 0); rc = sqlite3_step(pTableInfo); while( rc==SQLITE_ROW ){ + const char *zText = (const char *)sqlite3_column_text(pTableInfo, 1); zSelect = appendText(zSelect, "quote(", 0); - zSelect = appendText(zSelect, sqlite3_column_text(pTableInfo, 1), '"'); + zSelect = appendText(zSelect, zText, '"'); rc = sqlite3_step(pTableInfo); if( rc==SQLITE_ROW ){ zSelect = appendText(zSelect, ") || ', ' || ", 0); @@ -773,9 +774,6 @@ static char zHelp[] = ".prompt MAIN CONTINUE Replace the standard prompts\n" ".quit Exit this program\n" ".read FILENAME Execute SQL in FILENAME\n" -#ifdef SQLITE_HAS_CODEC - ".rekey OLD NEW NEW Change the encryption key\n" -#endif ".schema ?TABLE? Show the CREATE statements\n" ".separator STRING Change separator used by output mode and .import\n" ".show Show the current values for various settings\n" @@ -795,9 +793,6 @@ static void open_db(struct callback_data *p){ if( p->db==0 ){ sqlite3_open(p->zDbFilename, &p->db); db = p->db; -#ifdef SQLITE_HAS_CODEC - sqlite3_key(p->db, p->zKey, p->zKey ? strlen(p->zKey) : 0); -#endif sqlite3_create_function(db, "shellstatic", 0, SQLITE_UTF8, 0, shellstaticFunc, 0, 0); if( SQLITE_OK!=sqlite3_errcode(db) ){ @@ -829,7 +824,7 @@ static void resolve_backslashes(char *z){ }else if( c=='r' ){ c = '\r'; }else if( c>='0' && c<='7' ){ - c =- '0'; + c -= '0'; if( z[i+1]>='0' && z[i+1]<='7' ){ i++; c = (c<<3) + z[i] - '0'; @@ -1226,22 +1221,6 @@ static int do_meta_command(char *zLine, struct callback_data *p){ } }else -#ifdef SQLITE_HAS_CODEC - if( c=='r' && strncmp(azArg[0],"rekey", n)==0 && nArg==4 ){ - char *zOld = p->zKey; - if( zOld==0 ) zOld = ""; - if( strcmp(azArg[1],zOld) ){ - fprintf(stderr,"old key is incorrect\n"); - }else if( strcmp(azArg[2], azArg[3]) ){ - fprintf(stderr,"2nd copy of new key does not match the 1st\n"); - }else{ - sqlite3_free(p->zKey); - p->zKey = sqlite3_mprintf("%s", azArg[2]); - sqlite3_rekey(p->db, p->zKey, strlen(p->zKey)); - } - }else -#endif - if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ struct callback_data data; char *zErrMsg = 0; @@ -1619,9 +1598,6 @@ static const char zOptions[] = " -[no]header turn headers on or off\n" " -column set output mode to 'column'\n" " -html set output mode to HTML\n" -#ifdef SQLITE_HAS_CODEC - " -key KEY encryption key\n" -#endif " -line set output mode to 'line'\n" " -list set output mode to 'list'\n" " -separator 'x' set output field separator (|)\n" diff --git a/mozilla/db/sqlite3/src/sqlite3.h b/mozilla/db/sqlite3/src/sqlite3.h index 5c8e6878e2a..a8f0322c30e 100644 --- a/mozilla/db/sqlite3/src/sqlite3.h +++ b/mozilla/db/sqlite3/src/sqlite3.h @@ -12,7 +12,7 @@ ** This header file defines the interface that the SQLite library ** presents to client programs. ** -** @(#) $Id: sqlite.h.in,v 1.141 2005/09/08 10:58:52 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.156 2006/01/12 02:50:10 drh Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -31,7 +31,7 @@ extern "C" { #ifdef SQLITE_VERSION # undef SQLITE_VERSION #endif -#define SQLITE_VERSION "3.2.7" +#define SQLITE_VERSION "3.3.3" /* ** The format of the version string is "X.Y.Z", where @@ -48,7 +48,7 @@ extern "C" { #ifdef SQLITE_VERSION_NUMBER # undef SQLITE_VERSION_NUMBER #endif -#define SQLITE_VERSION_NUMBER 3002007 +#define SQLITE_VERSION_NUMBER 3003003 /* ** The version string is also compiled into the library so that a program @@ -86,6 +86,13 @@ typedef struct sqlite3 sqlite3; typedef unsigned long long int sqlite_uint64; #endif +/* +** If compiling for a processor that lacks floating point support, +** substitute integer for floating-point +*/ +#ifdef SQLITE_OMIT_FLOATING_POINT +# define double sqlite_int64 +#endif /* ** A function to close the database. @@ -185,6 +192,7 @@ int sqlite3_exec( #define SQLITE_NOTADB 26 /* File opened that is not a database file */ #define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ #define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ +/* end-of-return-codes */ /* ** Each entry in an SQLite table has a unique integer key. (The key is @@ -1251,7 +1259,7 @@ extern char *sqlite3_temp_directory; ** This functionality can be omitted from a build by defining the ** SQLITE_OMIT_GLOBALRECOVER at compile time. */ -int sqlite3_global_recover(); +int sqlite3_global_recover(void); /* ** Test to see whether or not the database connection is in autocommit @@ -1269,6 +1277,106 @@ int sqlite3_get_autocommit(sqlite3*); */ sqlite3 *sqlite3_db_handle(sqlite3_stmt*); +/* +** Register a callback function with the database connection identified by the +** first argument to be invoked whenever a row is updated, inserted or deleted. +** Any callback set by a previous call to this function for the same +** database connection is overridden. +** +** The second argument is a pointer to the function to invoke when a +** row is updated, inserted or deleted. The first argument to the callback is +** a copy of the third argument to sqlite3_update_hook. The second callback +** argument is one of SQLITE_INSERT, SQLITE_DELETE or SQLITE_UPDATE, depending +** on the operation that caused the callback to be invoked. The third and +** fourth arguments to the callback contain pointers to the database and +** table name containing the affected row. The final callback parameter is +** the rowid of the row. In the case of an update, this is the rowid after +** the update takes place. +** +** The update hook is not invoked when internal system tables are +** modified (i.e. sqlite_master and sqlite_sequence). +** +** If another function was previously registered, its pArg value is returned. +** Otherwise NULL is returned. +*/ +void *sqlite3_update_hook( + sqlite3*, + void(*)(void *,int ,char const *,char const *,sqlite_int64), + void* +); + +/* +** Register a callback to be invoked whenever a transaction is rolled +** back. +** +** The new callback function overrides any existing rollback-hook +** callback. If there was an existing callback, then it's pArg value +** (the third argument to sqlite3_rollback_hook() when it was registered) +** is returned. Otherwise, NULL is returned. +** +** For the purposes of this API, a transaction is said to have been +** rolled back if an explicit "ROLLBACK" statement is executed, or +** an error or constraint causes an implicit rollback to occur. The +** callback is not invoked if a transaction is automatically rolled +** back because the database connection is closed. +*/ +void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); + +/* +** This function is only available if the library is compiled without +** the SQLITE_OMIT_SHARED_CACHE macro defined. It is used to enable or +** disable (if the argument is true or false, respectively) the +** "shared pager" feature. +*/ +int sqlite3_enable_shared_cache(int); + +/* +** Attempt to free N bytes of heap memory by deallocating non-essential +** memory allocations held by the database library (example: memory +** used to cache database pages to improve performance). +** +** This function is not a part of standard builds. It is only created +** if SQLite is compiled with the SQLITE_ENABLE_MEMORY_MANAGEMENT macro. +*/ +int sqlite3_release_memory(int); + +/* +** Place a "soft" limit on the amount of heap memory that may be allocated by +** SQLite within the current thread. If an internal allocation is requested +** that would exceed the specified limit, sqlite3_release_memory() is invoked +** one or more times to free up some space before the allocation is made. +** +** The limit is called "soft", because if sqlite3_release_memory() cannot free +** sufficient memory to prevent the limit from being exceeded, the memory is +** allocated anyway and the current operation proceeds. +** +** This function is only available if the library was compiled with the +** SQLITE_ENABLE_MEMORY_MANAGEMENT option set. +** memory-management has been enabled. +*/ +void sqlite3_soft_heap_limit(int); + +/* +** This routine makes sure that all thread-local storage has been +** deallocated for the current thread. +** +** This routine is not technically necessary. All thread-local storage +** will be automatically deallocated once memory-management and +** shared-cache are disabled and the soft heap limit has been set +** to zero. This routine is provided as a convenience for users who +** want to make absolutely sure they have not forgotten something +** prior to killing off a thread. +*/ +void sqlite3_thread_cleanup(void); + +/* +** Undo the hack that converts floating point types to integer for +** builds on processors without floating point support. +*/ +#ifdef SQLITE_OMIT_FLOATING_POINT +# undef double +#endif + /* ** Given a wildcard parameter name, return the set of indexes of the ** variables with that name. If there are no variables with the given diff --git a/mozilla/db/sqlite3/src/sqliteInt.h b/mozilla/db/sqlite3/src/sqliteInt.h index be44278a6da..20bf1c5e8b4 100644 --- a/mozilla/db/sqlite3/src/sqliteInt.h +++ b/mozilla/db/sqlite3/src/sqliteInt.h @@ -11,11 +11,18 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.421 2005/09/19 21:05:49 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.479 2006/01/24 16:37:58 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ +/* +** Extra interface definitions for those who need them +*/ +#ifdef SQLITE_EXTRA +# include "sqliteExtra.h" +#endif + /* ** Many people are failing to set -DNDEBUG=1 when compiling SQLite. ** Setting NDEBUG makes the code smaller and run faster. So the following @@ -23,7 +30,7 @@ ** option is set. Thus NDEBUG becomes an opt-in rather than an opt-out ** feature. */ -#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) +#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) # define NDEBUG 1 #endif @@ -50,8 +57,6 @@ # define _LARGEFILE_SOURCE 1 #endif -#include "config.h" - #include "sqlite3.h" #include "hash.h" #include "parse.h" @@ -61,6 +66,23 @@ #include #include +/* +** If compiling for a processor that lacks floating point support, +** substitute integer for floating-point +*/ +#ifdef SQLITE_OMIT_FLOATING_POINT +# define double sqlite_int64 +# define LONGDOUBLE_TYPE sqlite_int64 +# ifndef SQLITE_BIG_DBL +# define SQLITE_BIG_DBL (0x7fffffffffffffff) +# endif +# define SQLITE_OMIT_DATETIME_FUNCS 1 +# define SQLITE_OMIT_TRACE 1 +#endif +#ifndef SQLITE_BIG_DBL +# define SQLITE_BIG_DBL (1e99) +#endif + /* ** The maximum number of in-memory pages to use for the main database ** table and for temporary tables. Internally, the MAX_PAGES and @@ -131,18 +153,15 @@ #define SQLITE_MAX_VARIABLE_NUMBER 999 /* -** When building SQLite for embedded systems where memory is scarce, -** you can define one or more of the following macros to omit extra -** features of the library and thus keep the size of the library to -** a minimum. +** The "file format" number is an integer that is incremented whenever +** the VDBE-level file format changes. The following macros define the +** the default file format for new databases and the maximum file format +** that the library can read. */ -/* #define SQLITE_OMIT_AUTHORIZATION 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 */ +#define SQLITE_MAX_FILE_FORMAT 4 +#ifndef SQLITE_DEFAULT_FILE_FORMAT +# define SQLITE_DEFAULT_FILE_FORMAT 4 +#endif /* ** Provide a default value for TEMP_STORE in case it is not specified @@ -230,6 +249,7 @@ struct BusyHandler { */ #include "vdbe.h" #include "btree.h" +#include "pager.h" /* ** This macro casts a pointer to an integer. Useful for doing @@ -237,53 +257,66 @@ struct BusyHandler { */ #define Addr(X) ((uptr)X) -/* -** If memory allocation problems are found, recompile with -** -** -DSQLITE_DEBUG=1 -** -** to enable some sanity checking on malloc() and free(). To -** check for memory leaks, recompile with -** -** -DSQLITE_DEBUG=2 -** -** and a line of text will be written to standard error for -** each malloc() and free(). This output can be analyzed -** by an AWK script to determine if there are any leaks. -*/ #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__) -# define sqliteRealloc(X,Y) sqlite3Realloc_(X,Y,__FILE__,__LINE__) -# define sqliteStrDup(X) sqlite3StrDup_(X,__FILE__,__LINE__) -# define sqliteStrNDup(X,Y) sqlite3StrNDup_(X,Y,__FILE__,__LINE__) -#else -# define sqliteFree sqlite3FreeX -# define sqliteMalloc sqlite3Malloc -# define sqliteMallocRaw sqlite3MallocRaw -# define sqliteRealloc sqlite3Realloc -# define sqliteStrDup sqlite3StrDup -# define sqliteStrNDup sqlite3StrNDup -#endif - -/* -** This variable gets set if malloc() ever fails. After it gets set, -** the SQLite library shuts down permanently. -*/ -extern int sqlite3_malloc_failed; - /* ** The following global variables are used for testing and debugging -** only. They only work if SQLITE_DEBUG is defined. +** only. They only work if SQLITE_MEMDEBUG is defined. */ -#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 */ + + +extern void *sqlite3_pFirst; /* Pointer to linked list of allocations */ +extern int sqlite3_nMaxAlloc; /* High water mark of ThreadData.nAlloc */ +extern int sqlite3_mallocDisallowed; /* assert() in sqlite3Malloc() if set */ +extern int sqlite3_isFail; /* True if all malloc calls should fail */ +extern const char *sqlite3_zFile; /* Filename to associate debug info with */ +extern int sqlite3_iLine; /* Line number for debug info */ + +#define ENTER_MALLOC (sqlite3_zFile = __FILE__, sqlite3_iLine = __LINE__) +#define sqliteMalloc(x) (ENTER_MALLOC, sqlite3Malloc(x)) +#define sqliteMallocRaw(x) (ENTER_MALLOC, sqlite3MallocRaw(x)) +#define sqliteRealloc(x,y) (ENTER_MALLOC, sqlite3Realloc(x,y)) +#define sqliteStrDup(x) (ENTER_MALLOC, sqlite3StrDup(x)) +#define sqliteStrNDup(x,y) (ENTER_MALLOC, sqlite3StrNDup(x,y)) +#define sqliteReallocOrFree(x,y) (ENTER_MALLOC, sqlite3ReallocOrFree(x,y)) + +#else + +#define sqliteMalloc(x) sqlite3Malloc(x) +#define sqliteMallocRaw(x) sqlite3MallocRaw(x) +#define sqliteRealloc(x,y) sqlite3Realloc(x,y) +#define sqliteStrDup(x) sqlite3StrDup(x) +#define sqliteStrNDup(x,y) sqlite3StrNDup(x,y) +#define sqliteReallocOrFree(x,y) sqlite3ReallocOrFree(x,y) + #endif +#define sqliteFree(x) sqlite3FreeX(x) +#define sqliteAllocSize(x) sqlite3AllocSize(x) + + +/* +** An instance of this structure might be allocated to store information +** specific to a single thread. +*/ +struct ThreadData { + int dummy; /* So that this structure is never empty */ + +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + int nSoftHeapLimit; /* Suggested max mem allocation. No limit if <0 */ + int nAlloc; /* Number of bytes currently allocated */ + Pager *pPager; /* Linked list of all pagers in this thread */ +#endif + +#ifndef SQLITE_OMIT_SHARED_CACHE + u8 useSharedData; /* True if shared pagers and schemas are enabled */ + BtShared *pBtree; /* Linked list of all currently open BTrees */ +#endif +}; + /* ** Name of the master database table. The master database table ** is a special table that holds the names and attributes of all @@ -316,6 +349,7 @@ typedef struct AuthContext AuthContext; typedef struct CollSeq CollSeq; typedef struct Column Column; typedef struct Db Db; +typedef struct Schema Schema; typedef struct Expr Expr; typedef struct ExprList ExprList; typedef struct FKey FKey; @@ -328,7 +362,9 @@ typedef struct NameContext NameContext; typedef struct Parse Parse; typedef struct Select Select; typedef struct SrcList SrcList; +typedef struct ThreadData ThreadData; typedef struct Table Table; +typedef struct TableLock TableLock; typedef struct Token Token; typedef struct TriggerStack TriggerStack; typedef struct TriggerStep TriggerStep; @@ -346,28 +382,37 @@ typedef struct WhereLevel WhereLevel; struct Db { char *zName; /* Name of this database */ Btree *pBt; /* The B*Tree structure for this database file */ + u8 inTrans; /* 0: not writable. 1: Transaction. 2: Checkpoint */ + u8 safety_level; /* How aggressive at synching data to disk */ + void *pAux; /* Auxiliary data. Usually NULL */ + void (*xFreeAux)(void*); /* Routine to free pAux */ + Schema *pSchema; /* Pointer to database schema (possibly shared) */ +}; + +/* +** An instance of the following structure stores a database schema. +*/ +struct Schema { int schema_cookie; /* Database schema version number for this file */ Hash tblHash; /* All tables indexed by name */ Hash idxHash; /* All (named) indices indexed by name */ Hash trigHash; /* All triggers indexed by name */ Hash aFKey; /* Foreign keys indexed by to-table */ - u16 flags; /* Flags associated with this database */ - 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 */ Table *pSeqTab; /* The sqlite_sequence table used by AUTOINCREMENT */ - void *pAux; /* Auxiliary data. Usually NULL */ - void (*xFreeAux)(void*); /* Routine to free pAux */ + u8 file_format; /* Schema format version for this file */ + u8 enc; /* Text encoding used by this database */ + u16 flags; /* Flags associated with this schema */ + int cache_size; /* Number of pages to use in the cache */ }; /* ** These macros can be used to test, set, or clear bits in the ** Db.flags field. */ -#define DbHasProperty(D,I,P) (((D)->aDb[I].flags&(P))==(P)) -#define DbHasAnyProperty(D,I,P) (((D)->aDb[I].flags&(P))!=0) -#define DbSetProperty(D,I,P) (D)->aDb[I].flags|=(P) -#define DbClearProperty(D,I,P) (D)->aDb[I].flags&=~(P) +#define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))==(P)) +#define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))!=0) +#define DbSetProperty(D,I,P) (D)->aDb[I].pSchema->flags|=(P) +#define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->flags&=~(P) /* ** Allowed values for the DB.flags field. @@ -381,6 +426,7 @@ struct Db { */ #define DB_SchemaLoaded 0x0001 /* The schema has been loaded */ #define DB_UnresetViews 0x0002 /* Some views have defined column names */ +#define DB_Empty 0x0004 /* The file is empty (length 0 bytes) */ #define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE) @@ -415,9 +461,7 @@ struct sqlite3 { Db *aDb; /* All backends */ int flags; /* Miscellanous flags. See below */ int errCode; /* Most recent error code (SQLITE_*) */ - u8 enc; /* Text encoding for this database. */ u8 autoCommit; /* The auto-commit flag. */ - u8 file_format; /* What file format version is this database? */ u8 temp_store; /* 1: file 2: memory 0: default */ int nTable; /* Number of tables in the database */ CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ @@ -437,12 +481,15 @@ struct sqlite3 { void *pTraceArg; /* Argument to the trace function */ void (*xProfile)(void*,const char*,u64); /* Profiling function */ void *pProfileArg; /* Argument to profile function */ - void *pCommitArg; /* Argument to xCommitCallback() */ - int (*xCommitCallback)(void*);/* Invoked at every commit. */ + void *pCommitArg; /* Argument to xCommitCallback() */ + int (*xCommitCallback)(void*); /* Invoked at every commit. */ + void *pRollbackArg; /* Argument to xRollbackCallback() */ + void (*xRollbackCallback)(void*); /* Invoked at every commit. */ + void *pUpdateArg; + void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64); void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*); void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*); 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-16 encoded) */ @@ -469,6 +516,8 @@ struct sqlite3 { #endif }; +#define ENC(db) ((db)->aDb[0].pSchema->enc) + /* ** Possible values for the sqlite.flags and or Db.flags fields. ** @@ -477,7 +526,6 @@ struct sqlite3 { ** transaction is active on that particular database file. */ #define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ -#define SQLITE_Initialized 0x00000002 /* True after initialization */ #define SQLITE_Interrupt 0x00000004 /* Cancel current operation */ #define SQLITE_InTrans 0x00000008 /* True if in a transaction */ #define SQLITE_InternChanges 0x00000010 /* Uncommitted Hash table changes */ @@ -493,6 +541,9 @@ struct sqlite3 { #define SQLITE_WriteSchema 0x00000800 /* OK to update SQLITE_MASTER */ #define SQLITE_NoReadlock 0x00001000 /* Readlocks are omitted when ** accessing read-only databases */ +#define SQLITE_IgnoreChecks 0x00002000 /* Do not enforce check constraints */ +#define SQLITE_ReadUncommitted 0x00004000 /* For shared-cache mode */ +#define SQLITE_LegacyFileFmt 0x00008000 /* Create new databases in format 1 */ /* ** Possible values for the sqlite.magic field. @@ -537,7 +588,7 @@ struct Column { char *zName; /* Name 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 */ + char *zColl; /* Collating sequence. If NULL, use the default */ u8 notNull; /* True if there is a NOT NULL constraint */ u8 isPrimKey; /* True if this column is part of the PRIMARY KEY */ char affinity; /* One of the SQLITE_AFF_... values */ @@ -553,7 +604,7 @@ struct Column { ** processes text encoded in UTF-16 (CollSeq.xCmp16), using the machine ** native byte order. When a collation sequence is invoked, SQLite selects ** the version that will require the least expensive encoding -** transalations, if any. +** translations, if any. ** ** The CollSeq.pUser member variable is an extra parameter that passed in ** as the first argument to the UTF-8 comparison function, xCmp. @@ -588,12 +639,25 @@ struct CollSeq { /* ** Column affinity types. +** +** These used to have mnemonic name like 'i' for SQLITE_AFF_INTEGER and +** 't' for SQLITE_AFF_TEXT. But we can save a little space and improve +** the speed a little by number the values consecutively. +** +** But rather than start with 0 or 1, we begin with 'a'. That way, +** when multiple affinity types are concatenated into a string and +** used as the P3 operand, they will be more readable. +** +** Note also that the numeric types are grouped together so that testing +** for a numeric type is a single comparison. */ -#define SQLITE_AFF_INTEGER 'i' -#define SQLITE_AFF_NUMERIC 'n' -#define SQLITE_AFF_TEXT 't' -#define SQLITE_AFF_NONE 'o' +#define SQLITE_AFF_TEXT 'a' +#define SQLITE_AFF_NONE 'b' +#define SQLITE_AFF_NUMERIC 'c' +#define SQLITE_AFF_INTEGER 'd' +#define SQLITE_AFF_REAL 'e' +#define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC) /* ** Each SQL table is represented in memory by an instance of the @@ -634,7 +698,6 @@ struct Table { int tnum; /* Root BTree node for this table (see note above) */ Select *pSelect; /* NULL for tables. Points to definition if a view. */ u8 readOnly; /* True if this table should not be written by the user */ - u8 iDb; /* Index into sqlite.aDb[] of the backend for this 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 */ @@ -643,9 +706,13 @@ struct Table { 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 */ +#ifndef SQLITE_OMIT_CHECK + Expr *pCheck; /* The AND of all CHECK constraints */ +#endif #ifndef SQLITE_OMIT_ALTERTABLE int addColOffset; /* Offset in CREATE TABLE statement to add a new column */ #endif + Schema *pSchema; }; /* @@ -781,10 +848,11 @@ struct Index { int tnum; /* Page containing root of this index in database file */ u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ u8 autoIndex; /* True if is automatically created (ex: by UNIQUE) */ - u8 iDb; /* Index in sqlite.aDb[] of where this index is stored */ char *zColAff; /* String defining the affinity of each column */ Index *pNext; /* The next index associated with the same table */ - KeyInfo keyInfo; /* Info on how to order keys. MUST BE LAST */ + Schema *pSchema; /* Schema containing this index */ + u8 *aSortOrder; /* Array of size Index.nColumn. True==DESC, False==ASC */ + char **azColl; /* Array of collation sequence names for index */ }; /* @@ -893,7 +961,6 @@ struct AggInfo { struct Expr { u8 op; /* Operation performed by this node */ char affinity; /* The affinity of the column or 0 if not a column */ - u8 iDb; /* Database referenced by this expression */ u8 flags; /* Various flags. See below */ CollSeq *pColl; /* The collation type of the column or 0 */ Expr *pLeft, *pRight; /* Left and right subnodes */ @@ -909,6 +976,7 @@ struct Expr { Select *pSelect; /* When the expression is a sub-select. Also the ** right side of " IN (