diff options
Diffstat (limited to 'third_party/sqlite/src')
105 files changed, 106277 insertions, 0 deletions
diff --git a/third_party/sqlite/src/alter.c b/third_party/sqlite/src/alter.c new file mode 100755 index 0000000..ba929be --- /dev/null +++ b/third_party/sqlite/src/alter.c @@ -0,0 +1,621 @@ +/* +** 2005 February 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains C code routines that used to generate VDBE code +** that implements the ALTER TABLE command. +** +** $Id: alter.c,v 1.47 2008/07/28 19:34:53 drh Exp $ +*/ +#include "sqliteInt.h" +#include <ctype.h> + +/* +** The code in this file only exists if we are not omitting the +** ALTER TABLE logic from the build. +*/ +#ifndef SQLITE_OMIT_ALTERTABLE + + +/* +** This function is used by SQL generated to implement the +** ALTER TABLE command. The first argument is the text of a CREATE TABLE or +** CREATE INDEX command. The second is a table name. The table name in +** the CREATE TABLE or CREATE INDEX statement is replaced with the third +** argument and the result returned. Examples: +** +** sqlite_rename_table('CREATE TABLE abc(a, b, c)', 'def') +** -> 'CREATE TABLE def(a, b, c)' +** +** sqlite_rename_table('CREATE INDEX i ON abc(a)', 'def') +** -> 'CREATE INDEX i ON def(a, b, c)' +*/ +static void renameTableFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + unsigned char const *zSql = sqlite3_value_text(argv[0]); + unsigned char const *zTableName = sqlite3_value_text(argv[1]); + + int token; + Token tname; + unsigned char const *zCsr = zSql; + int len = 0; + char *zRet; + + sqlite3 *db = sqlite3_context_db_handle(context); + + /* The principle used to locate the table name in the CREATE TABLE + ** statement is that the table name is the first non-space token that + ** is immediately followed by a TK_LP or TK_USING token. + */ + if( zSql ){ + do { + if( !*zCsr ){ + /* Ran out of input before finding an opening bracket. Return NULL. */ + return; + } + + /* Store the token that zCsr points to in tname. */ + tname.z = zCsr; + tname.n = len; + + /* Advance zCsr to the next token. Store that token type in 'token', + ** and its length in 'len' (to be used next iteration of this loop). + */ + do { + zCsr += len; + len = sqlite3GetToken(zCsr, &token); + } while( token==TK_SPACE || token==TK_COMMENT ); + assert( len>0 ); + } while( token!=TK_LP && token!=TK_USING ); + + zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", tname.z - zSql, zSql, + zTableName, tname.z+tname.n); + sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); + } +} + +#ifndef SQLITE_OMIT_TRIGGER +/* This function is used by SQL generated to implement the +** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER +** statement. The second is a table name. The table name in the CREATE +** TRIGGER statement is replaced with the third argument and the result +** returned. This is analagous to renameTableFunc() above, except for CREATE +** TRIGGER, not CREATE INDEX and CREATE TABLE. +*/ +static void renameTriggerFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + unsigned char const *zSql = sqlite3_value_text(argv[0]); + unsigned char const *zTableName = sqlite3_value_text(argv[1]); + + int token; + Token tname; + int dist = 3; + unsigned char const *zCsr = zSql; + int len = 0; + char *zRet; + + sqlite3 *db = sqlite3_context_db_handle(context); + + /* The principle used to locate the table name in the CREATE TRIGGER + ** statement is that the table name is the first token that is immediatedly + ** preceded by either TK_ON or TK_DOT and immediatedly followed by one + ** of TK_WHEN, TK_BEGIN or TK_FOR. + */ + if( zSql ){ + do { + + if( !*zCsr ){ + /* Ran out of input before finding the table name. Return NULL. */ + return; + } + + /* Store the token that zCsr points to in tname. */ + tname.z = zCsr; + tname.n = len; + + /* Advance zCsr to the next token. Store that token type in 'token', + ** and its length in 'len' (to be used next iteration of this loop). + */ + do { + zCsr += len; + len = sqlite3GetToken(zCsr, &token); + }while( token==TK_SPACE ); + assert( len>0 ); + + /* Variable 'dist' stores the number of tokens read since the most + ** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN + ** token is read and 'dist' equals 2, the condition stated above + ** to be met. + ** + ** Note that ON cannot be a database, table or column name, so + ** there is no need to worry about syntax like + ** "CREATE TRIGGER ... ON ON.ON BEGIN ..." etc. + */ + dist++; + if( token==TK_DOT || token==TK_ON ){ + dist = 0; + } + } while( dist!=2 || (token!=TK_WHEN && token!=TK_FOR && token!=TK_BEGIN) ); + + /* Variable tname now contains the token that is the old table-name + ** in the CREATE TRIGGER statement. + */ + zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", tname.z - zSql, zSql, + zTableName, tname.z+tname.n); + sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); + } +} +#endif /* !SQLITE_OMIT_TRIGGER */ + +/* +** Register built-in functions used to help implement ALTER TABLE +*/ +void sqlite3AlterFunctions(sqlite3 *db){ + sqlite3CreateFunc(db, "sqlite_rename_table", 2, SQLITE_UTF8, 0, + renameTableFunc, 0, 0); +#ifndef SQLITE_OMIT_TRIGGER + sqlite3CreateFunc(db, "sqlite_rename_trigger", 2, SQLITE_UTF8, 0, + renameTriggerFunc, 0, 0); +#endif +} + +/* +** Generate the text of a WHERE expression which can be used to select all +** temporary triggers on table pTab from the sqlite_temp_master table. If +** table pTab has no temporary triggers, or is itself stored in the +** temporary database, NULL is returned. +*/ +static char *whereTempTriggers(Parse *pParse, Table *pTab){ + Trigger *pTrig; + char *zWhere = 0; + char *tmp = 0; + const Schema *pTempSchema = pParse->db->aDb[1].pSchema; /* Temp db schema */ + + /* If the table is not located in the temp-db (in which case NULL is + ** returned, loop through the tables list of triggers. For each trigger + ** that is not part of the temp-db schema, add a clause to the WHERE + ** expression being built up in zWhere. + */ + if( pTab->pSchema!=pTempSchema ){ + sqlite3 *db = pParse->db; + for( pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext ){ + if( pTrig->pSchema==pTempSchema ){ + if( !zWhere ){ + zWhere = sqlite3MPrintf(db, "name=%Q", pTrig->name); + }else{ + tmp = zWhere; + zWhere = sqlite3MPrintf(db, "%s OR name=%Q", zWhere, pTrig->name); + sqlite3DbFree(db, tmp); + } + } + } + } + return zWhere; +} + +/* +** Generate code to drop and reload the internal representation of table +** pTab from the database, including triggers and temporary triggers. +** Argument zName is the name of the table in the database schema at +** the time the generated code is executed. This can be different from +** pTab->zName if this function is being called to code part of an +** "ALTER TABLE RENAME TO" statement. +*/ +static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){ + Vdbe *v; + char *zWhere; + int iDb; /* Index of database containing pTab */ +#ifndef SQLITE_OMIT_TRIGGER + Trigger *pTrig; +#endif + + v = sqlite3GetVdbe(pParse); + if( !v ) return; + assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + assert( iDb>=0 ); + +#ifndef SQLITE_OMIT_TRIGGER + /* Drop any table triggers from the internal schema. */ + for(pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext){ + int iTrigDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); + assert( iTrigDb==iDb || iTrigDb==1 ); + sqlite3VdbeAddOp4(v, OP_DropTrigger, iTrigDb, 0, 0, pTrig->name, 0); + } +#endif + + /* Drop the table and index from the internal schema */ + sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0); + + /* Reload the table, index and permanent trigger schemas. */ + zWhere = sqlite3MPrintf(pParse->db, "tbl_name=%Q", zName); + if( !zWhere ) return; + sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC); + +#ifndef SQLITE_OMIT_TRIGGER + /* Now, if the table is not stored in the temp database, reload any temp + ** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined. + */ + if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){ + sqlite3VdbeAddOp4(v, OP_ParseSchema, 1, 0, 0, zWhere, P4_DYNAMIC); + } +#endif +} + +/* +** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy" +** command. +*/ +void sqlite3AlterRenameTable( + Parse *pParse, /* Parser context. */ + SrcList *pSrc, /* The table to rename. */ + Token *pName /* The new table name. */ +){ + int iDb; /* Database that contains the table */ + char *zDb; /* Name of database iDb */ + Table *pTab; /* Table being renamed */ + char *zName = 0; /* NULL-terminated version of pName */ + sqlite3 *db = pParse->db; /* Database connection */ + int nTabName; /* Number of UTF-8 characters in zTabName */ + const char *zTabName; /* Original name of the table */ + Vdbe *v; +#ifndef SQLITE_OMIT_TRIGGER + char *zWhere = 0; /* Where clause to locate temp triggers */ +#endif + int isVirtualRename = 0; /* True if this is a v-table with an xRename() */ + + if( db->mallocFailed ) goto exit_rename_table; + assert( pSrc->nSrc==1 ); + assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); + + pTab = sqlite3LocateTable(pParse, 0, pSrc->a[0].zName, pSrc->a[0].zDatabase); + if( !pTab ) goto exit_rename_table; + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + zDb = db->aDb[iDb].zName; + + /* Get a NULL terminated version of the new table name. */ + zName = sqlite3NameFromToken(db, pName); + if( !zName ) goto exit_rename_table; + + /* Check that a table or index named 'zName' does not already exist + ** in database iDb. If so, this is an error. + */ + if( sqlite3FindTable(db, zName, zDb) || sqlite3FindIndex(db, zName, zDb) ){ + sqlite3ErrorMsg(pParse, + "there is already another table or index with this name: %s", zName); + goto exit_rename_table; + } + + /* Make sure it is not a system table being altered, or a reserved name + ** that the table is being renamed to. + */ + if( strlen(pTab->zName)>6 && 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7) ){ + sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName); + goto exit_rename_table; + } + if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ + goto exit_rename_table; + } + +#ifndef SQLITE_OMIT_VIEW + if( pTab->pSelect ){ + sqlite3ErrorMsg(pParse, "view %s may not be altered", pTab->zName); + goto exit_rename_table; + } +#endif + +#ifndef SQLITE_OMIT_AUTHORIZATION + /* Invoke the authorization callback. */ + if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ + goto exit_rename_table; + } +#endif + +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( sqlite3ViewGetColumnNames(pParse, pTab) ){ + goto exit_rename_table; + } + if( IsVirtual(pTab) && pTab->pMod->pModule->xRename ){ + isVirtualRename = 1; + } +#endif + + /* Begin a transaction and code the VerifyCookie for database iDb. + ** Then modify the schema cookie (since the ALTER TABLE modifies the + ** schema). Open a statement transaction if the table is a virtual + ** table. + */ + v = sqlite3GetVdbe(pParse); + if( v==0 ){ + goto exit_rename_table; + } + sqlite3BeginWriteOperation(pParse, isVirtualRename, iDb); + sqlite3ChangeCookie(pParse, iDb); + + /* If this is a virtual table, invoke the xRename() function if + ** one is defined. The xRename() callback will modify the names + ** of any resources used by the v-table implementation (including other + ** SQLite tables) that are identified by the name of the virtual table. + */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( isVirtualRename ){ + int i = ++pParse->nMem; + sqlite3VdbeAddOp4(v, OP_String8, 0, i, 0, zName, 0); + sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pTab->pVtab, P4_VTAB); + } +#endif + + /* figure out how many UTF-8 characters are in zName */ + zTabName = pTab->zName; + nTabName = sqlite3Utf8CharLen(zTabName, -1); + + /* Modify the sqlite_master table to use the new table name. */ + sqlite3NestedParse(pParse, + "UPDATE %Q.%s SET " +#ifdef SQLITE_OMIT_TRIGGER + "sql = sqlite_rename_table(sql, %Q), " +#else + "sql = CASE " + "WHEN type = 'trigger' THEN sqlite_rename_trigger(sql, %Q)" + "ELSE sqlite_rename_table(sql, %Q) END, " +#endif + "tbl_name = %Q, " + "name = CASE " + "WHEN type='table' THEN %Q " + "WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN " + "'sqlite_autoindex_' || %Q || substr(name,%d+18) " + "ELSE name END " + "WHERE tbl_name=%Q AND " + "(type='table' OR type='index' OR type='trigger');", + zDb, SCHEMA_TABLE(iDb), zName, zName, zName, +#ifndef SQLITE_OMIT_TRIGGER + zName, +#endif + zName, nTabName, zTabName + ); + +#ifndef SQLITE_OMIT_AUTOINCREMENT + /* If the sqlite_sequence table exists in this database, then update + ** it with the new table name. + */ + if( sqlite3FindTable(db, "sqlite_sequence", zDb) ){ + sqlite3NestedParse(pParse, + "UPDATE \"%w\".sqlite_sequence set name = %Q WHERE name = %Q", + zDb, zName, pTab->zName); + } +#endif + +#ifndef SQLITE_OMIT_TRIGGER + /* If there are TEMP triggers on this table, modify the sqlite_temp_master + ** table. Don't do this if the table being ALTERed is itself located in + ** the temp database. + */ + if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){ + sqlite3NestedParse(pParse, + "UPDATE sqlite_temp_master SET " + "sql = sqlite_rename_trigger(sql, %Q), " + "tbl_name = %Q " + "WHERE %s;", zName, zName, zWhere); + sqlite3DbFree(db, zWhere); + } +#endif + + /* Drop and reload the internal table schema. */ + reloadTableSchema(pParse, pTab, zName); + +exit_rename_table: + sqlite3SrcListDelete(db, pSrc); + sqlite3DbFree(db, zName); +} + + +/* +** This function is called after an "ALTER TABLE ... ADD" statement +** has been parsed. Argument pColDef contains the text of the new +** column definition. +** +** The Table structure pParse->pNewTable was extended to include +** the new column during parsing. +*/ +void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ + Table *pNew; /* Copy of pParse->pNewTable */ + Table *pTab; /* Table being altered */ + int iDb; /* Database number */ + const char *zDb; /* Database name */ + const char *zTab; /* Table name */ + char *zCol; /* Null-terminated column definition */ + Column *pCol; /* The new column */ + Expr *pDflt; /* Default value for the new column */ + sqlite3 *db; /* The database connection; */ + + if( pParse->nErr ) return; + pNew = pParse->pNewTable; + assert( pNew ); + + db = pParse->db; + assert( sqlite3BtreeHoldsAllMutexes(db) ); + iDb = sqlite3SchemaToIndex(db, pNew->pSchema); + zDb = db->aDb[iDb].zName; + zTab = pNew->zName; + pCol = &pNew->aCol[pNew->nCol-1]; + pDflt = pCol->pDflt; + pTab = sqlite3FindTable(db, zTab, zDb); + assert( pTab ); + +#ifndef SQLITE_OMIT_AUTHORIZATION + /* Invoke the authorization callback. */ + if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ + return; + } +#endif + + /* If the default value for the new column was specified with a + ** literal NULL, then set pDflt to 0. This simplifies checking + ** for an SQL NULL default below. + */ + if( pDflt && pDflt->op==TK_NULL ){ + pDflt = 0; + } + + /* Check that the new column is not specified as PRIMARY KEY or UNIQUE. + ** If there is a NOT NULL constraint, then the default value for the + ** column must not be NULL. + */ + if( pCol->isPrimKey ){ + sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column"); + return; + } + if( pNew->pIndex ){ + sqlite3ErrorMsg(pParse, "Cannot add a UNIQUE column"); + return; + } + if( pCol->notNull && !pDflt ){ + sqlite3ErrorMsg(pParse, + "Cannot add a NOT NULL column with default value NULL"); + return; + } + + /* Ensure the default expression is something that sqlite3ValueFromExpr() + ** can handle (i.e. not CURRENT_TIME etc.) + */ + if( pDflt ){ + sqlite3_value *pVal; + if( sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal) ){ + db->mallocFailed = 1; + return; + } + if( !pVal ){ + sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default"); + return; + } + sqlite3ValueFree(pVal); + } + + /* Modify the CREATE TABLE statement. */ + zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n); + if( zCol ){ + char *zEnd = &zCol[pColDef->n-1]; + while( (zEnd>zCol && *zEnd==';') || isspace(*(unsigned char *)zEnd) ){ + *zEnd-- = '\0'; + } + sqlite3NestedParse(pParse, + "UPDATE \"%w\".%s SET " + "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) " + "WHERE type = 'table' AND name = %Q", + zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1, + zTab + ); + sqlite3DbFree(db, zCol); + } + + /* If the default value of the new column is NULL, then set the file + ** format to 2. If the default value of the new column is not NULL, + ** the file format becomes 3. + */ + sqlite3MinimumFileFormat(pParse, iDb, pDflt ? 3 : 2); + + /* Reload the schema of the modified table. */ + reloadTableSchema(pParse, pTab, pTab->zName); +} + +/* +** This function is called by the parser after the table-name in +** an "ALTER TABLE <table-name> ADD" statement is parsed. Argument +** pSrc is the full-name of the table being altered. +** +** This routine makes a (partial) copy of the Table structure +** for the table being altered and sets Parse.pNewTable to point +** to it. Routines called by the parser as the column definition +** is parsed (i.e. sqlite3AddColumn()) add the new Column data to +** the copy. The copy of the Table structure is deleted by tokenize.c +** after parsing is finished. +** +** Routine sqlite3AlterFinishAddColumn() will be called to complete +** coding the "ALTER TABLE ... ADD" statement. +*/ +void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ + Table *pNew; + Table *pTab; + Vdbe *v; + int iDb; + int i; + int nAlloc; + sqlite3 *db = pParse->db; + + /* Look up the table being altered. */ + assert( pParse->pNewTable==0 ); + assert( sqlite3BtreeHoldsAllMutexes(db) ); + if( db->mallocFailed ) goto exit_begin_add_column; + pTab = sqlite3LocateTable(pParse, 0, pSrc->a[0].zName, pSrc->a[0].zDatabase); + if( !pTab ) goto exit_begin_add_column; + +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( IsVirtual(pTab) ){ + sqlite3ErrorMsg(pParse, "virtual tables may not be altered"); + goto exit_begin_add_column; + } +#endif + + /* Make sure this is not an attempt to ALTER a view. */ + if( pTab->pSelect ){ + sqlite3ErrorMsg(pParse, "Cannot add a column to a view"); + goto exit_begin_add_column; + } + + assert( pTab->addColOffset>0 ); + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + + /* Put a copy of the Table struct in Parse.pNewTable for the + ** sqlite3AddColumn() function and friends to modify. + */ + pNew = (Table*)sqlite3DbMallocZero(db, sizeof(Table)); + if( !pNew ) goto exit_begin_add_column; + pParse->pNewTable = pNew; + pNew->nRef = 1; + pNew->db = db; + pNew->nCol = pTab->nCol; + assert( pNew->nCol>0 ); + nAlloc = (((pNew->nCol-1)/8)*8)+8; + assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 ); + pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nAlloc); + pNew->zName = sqlite3DbStrDup(db, pTab->zName); + if( !pNew->aCol || !pNew->zName ){ + db->mallocFailed = 1; + goto exit_begin_add_column; + } + memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol); + for(i=0; i<pNew->nCol; i++){ + Column *pCol = &pNew->aCol[i]; + pCol->zName = sqlite3DbStrDup(db, pCol->zName); + pCol->zColl = 0; + pCol->zType = 0; + pCol->pDflt = 0; + } + pNew->pSchema = db->aDb[iDb].pSchema; + pNew->addColOffset = pTab->addColOffset; + pNew->nRef = 1; + + /* Begin a transaction and increment the schema cookie. */ + sqlite3BeginWriteOperation(pParse, 0, iDb); + v = sqlite3GetVdbe(pParse); + if( !v ) goto exit_begin_add_column; + sqlite3ChangeCookie(pParse, iDb); + +exit_begin_add_column: + sqlite3SrcListDelete(db, pSrc); + return; +} +#endif /* SQLITE_ALTER_TABLE */ diff --git a/third_party/sqlite/src/analyze.c b/third_party/sqlite/src/analyze.c new file mode 100755 index 0000000..2c57d7f --- /dev/null +++ b/third_party/sqlite/src/analyze.c @@ -0,0 +1,425 @@ +/* +** 2005 July 8 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains code associated with the ANALYZE command. +** +** @(#) $Id: analyze.c,v 1.43 2008/07/28 19:34:53 drh Exp $ +*/ +#ifndef SQLITE_OMIT_ANALYZE +#include "sqliteInt.h" + +/* +** This routine generates code that opens the sqlite_stat1 table on cursor +** iStatCur. +** +** If the sqlite_stat1 tables does not previously exist, it is created. +** If it does previously exist, all entires associated with table zWhere +** are removed. If zWhere==0 then all entries are removed. +*/ +static void openStatTable( + Parse *pParse, /* Parsing context */ + int iDb, /* The database we are looking in */ + int iStatCur, /* Open the sqlite_stat1 table on this cursor */ + const char *zWhere /* Delete entries associated with this table */ +){ + sqlite3 *db = pParse->db; + Db *pDb; + int iRootPage; + int createStat1 = 0; + Table *pStat; + Vdbe *v = sqlite3GetVdbe(pParse); + + if( v==0 ) return; + assert( sqlite3BtreeHoldsAllMutexes(db) ); + assert( sqlite3VdbeDb(v)==db ); + pDb = &db->aDb[iDb]; + if( (pStat = sqlite3FindTable(db, "sqlite_stat1", pDb->zName))==0 ){ + /* The sqlite_stat1 tables does not exist. Create it. + ** Note that a side-effect of the CREATE TABLE statement is to leave + ** the rootpage of the new table in register pParse->regRoot. This is + ** important because the OpenWrite opcode below will be needing it. */ + sqlite3NestedParse(pParse, + "CREATE TABLE %Q.sqlite_stat1(tbl,idx,stat)", + pDb->zName + ); + iRootPage = pParse->regRoot; + createStat1 = 1; /* Cause rootpage to be taken from top of stack */ + }else if( zWhere ){ + /* The sqlite_stat1 table exists. Delete all entries associated with + ** the table zWhere. */ + sqlite3NestedParse(pParse, + "DELETE FROM %Q.sqlite_stat1 WHERE tbl=%Q", + pDb->zName, zWhere + ); + iRootPage = pStat->tnum; + }else{ + /* The sqlite_stat1 table already exists. Delete all rows. */ + iRootPage = pStat->tnum; + sqlite3VdbeAddOp2(v, OP_Clear, pStat->tnum, iDb); + } + + /* Open the sqlite_stat1 table for writing. Unless it was created + ** by this vdbe program, lock it for writing at the shared-cache level. + ** If this vdbe did create the sqlite_stat1 table, then it must have + ** already obtained a schema-lock, making the write-lock redundant. + */ + if( !createStat1 ){ + sqlite3TableLock(pParse, iDb, iRootPage, 1, "sqlite_stat1"); + } + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, 3); + sqlite3VdbeAddOp3(v, OP_OpenWrite, iStatCur, iRootPage, iDb); + sqlite3VdbeChangeP5(v, createStat1); +} + +/* +** Generate code to do an analysis of all indices associated with +** a single table. +*/ +static void analyzeOneTable( + Parse *pParse, /* Parser context */ + Table *pTab, /* Table whose indices are to be analyzed */ + int iStatCur, /* Cursor that writes to the sqlite_stat1 table */ + int iMem /* Available memory locations begin here */ +){ + Index *pIdx; /* An index to being analyzed */ + int iIdxCur; /* Cursor number for index being analyzed */ + int nCol; /* Number of columns in the index */ + Vdbe *v; /* The virtual machine being built up */ + int i; /* Loop counter */ + int topOfLoop; /* The top of the loop */ + int endOfLoop; /* The end of the loop */ + int addr; /* The address of an instruction */ + int iDb; /* Index of database containing pTab */ + + v = sqlite3GetVdbe(pParse); + if( v==0 || pTab==0 || pTab->pIndex==0 ){ + /* Do no analysis for tables that have no indices */ + return; + } + assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + assert( iDb>=0 ); +#ifndef SQLITE_OMIT_AUTHORIZATION + if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0, + 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); + int regFields; /* Register block for building records */ + int regRec; /* Register holding completed record */ + int regTemp; /* Temporary use register */ + int regCol; /* Content of a column from the table being analyzed */ + int regRowid; /* Rowid for the inserted record */ + int regF2; + + /* Open a cursor to the index to be analyzed + */ + assert( iDb==sqlite3SchemaToIndex(pParse->db, pIdx->pSchema) ); + nCol = pIdx->nColumn; + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, nCol+1); + sqlite3VdbeAddOp4(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb, + (char *)pKey, P4_KEYINFO_HANDOFF); + VdbeComment((v, "%s", pIdx->zName)); + regFields = iMem+nCol*2; + regTemp = regRowid = regCol = regFields+3; + regRec = regCol+1; + if( regRec>pParse->nMem ){ + pParse->nMem = regRec; + } + + /* Memory cells are used as follows: + ** + ** mem[iMem]: The total number of rows in the table. + ** mem[iMem+1]: Number of distinct values in column 1 + ** ... + ** mem[iMem+nCol]: Number of distinct values in column N + ** mem[iMem+nCol+1] Last observed value of column 1 + ** ... + ** mem[iMem+nCol+nCol]: Last observed value of column N + ** + ** Cells iMem through iMem+nCol are initialized to 0. The others + ** are initialized to NULL. + */ + for(i=0; i<=nCol; i++){ + sqlite3VdbeAddOp2(v, OP_Integer, 0, iMem+i); + } + for(i=0; i<nCol; i++){ + sqlite3VdbeAddOp2(v, OP_Null, 0, iMem+nCol+i+1); + } + + /* Do the analysis. + */ + endOfLoop = sqlite3VdbeMakeLabel(v); + sqlite3VdbeAddOp2(v, OP_Rewind, iIdxCur, endOfLoop); + topOfLoop = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp2(v, OP_AddImm, iMem, 1); + for(i=0; i<nCol; i++){ + sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regCol); + sqlite3VdbeAddOp3(v, OP_Ne, regCol, 0, iMem+nCol+i+1); + /**** TODO: add collating sequence *****/ + sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); + } + sqlite3VdbeAddOp2(v, OP_Goto, 0, endOfLoop); + for(i=0; i<nCol; i++){ + sqlite3VdbeJumpHere(v, topOfLoop + 2*(i + 1)); + sqlite3VdbeAddOp2(v, OP_AddImm, iMem+i+1, 1); + sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, iMem+nCol+i+1); + } + sqlite3VdbeResolveLabel(v, endOfLoop); + sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, topOfLoop); + sqlite3VdbeAddOp1(v, OP_Close, iIdxCur); + + /* Store the results. + ** + ** The result is a single row of the sqlite_stat1 table. The first + ** two columns are the names of the table and index. The third column + ** is a string composed of a list of integer statistics about the + ** index. The first integer in the list is the total number of entires + ** in the index. There is one additional integer in the list for each + ** column of the table. This additional integer is a guess of how many + ** rows of the table the index will select. If D is the count of distinct + ** values and K is the total number of rows, then the integer is computed + ** as: + ** + ** I = (K+D-1)/D + ** + ** If K==0 then no entry is made into the sqlite_stat1 table. + ** If K>0 then it is always the case the D>0 so division by zero + ** is never possible. + */ + addr = sqlite3VdbeAddOp1(v, OP_IfNot, iMem); + sqlite3VdbeAddOp4(v, OP_String8, 0, regFields, 0, pTab->zName, 0); + sqlite3VdbeAddOp4(v, OP_String8, 0, regFields+1, 0, pIdx->zName, 0); + regF2 = regFields+2; + sqlite3VdbeAddOp2(v, OP_SCopy, iMem, regF2); + for(i=0; i<nCol; i++){ + sqlite3VdbeAddOp4(v, OP_String8, 0, regTemp, 0, " ", 0); + sqlite3VdbeAddOp3(v, OP_Concat, regTemp, regF2, regF2); + sqlite3VdbeAddOp3(v, OP_Add, iMem, iMem+i+1, regTemp); + sqlite3VdbeAddOp2(v, OP_AddImm, regTemp, -1); + sqlite3VdbeAddOp3(v, OP_Divide, iMem+i+1, regTemp, regTemp); + sqlite3VdbeAddOp1(v, OP_ToInt, regTemp); + sqlite3VdbeAddOp3(v, OP_Concat, regTemp, regF2, regF2); + } + sqlite3VdbeAddOp4(v, OP_MakeRecord, regFields, 3, regRec, "aaa", 0); + sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regRowid); + sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regRowid); + sqlite3VdbeChangeP5(v, OPFLAG_APPEND); + sqlite3VdbeJumpHere(v, addr); + } +} + +/* +** Generate code that will cause the most recent index analysis to +** be laoded into internal hash tables where is can be used. +*/ +static void loadAnalysis(Parse *pParse, int iDb){ + Vdbe *v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3VdbeAddOp1(v, OP_LoadAnalysis, iDb); + } +} + +/* +** Generate code that will do an analysis of an entire database +*/ +static void analyzeDatabase(Parse *pParse, int iDb){ + sqlite3 *db = pParse->db; + Schema *pSchema = db->aDb[iDb].pSchema; /* Schema of database iDb */ + HashElem *k; + int iStatCur; + int iMem; + + sqlite3BeginWriteOperation(pParse, 0, iDb); + iStatCur = pParse->nTab++; + openStatTable(pParse, iDb, iStatCur, 0); + iMem = pParse->nMem+1; + for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){ + Table *pTab = (Table*)sqliteHashData(k); + analyzeOneTable(pParse, pTab, iStatCur, iMem); + } + loadAnalysis(pParse, iDb); +} + +/* +** Generate code that will do an analysis of a single table in +** a database. +*/ +static void analyzeTable(Parse *pParse, Table *pTab){ + int iDb; + int iStatCur; + + assert( pTab!=0 ); + assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + sqlite3BeginWriteOperation(pParse, 0, iDb); + iStatCur = pParse->nTab++; + openStatTable(pParse, iDb, iStatCur, pTab->zName); + analyzeOneTable(pParse, pTab, iStatCur, pParse->nMem+1); + loadAnalysis(pParse, iDb); +} + +/* +** Generate code for the ANALYZE command. The parser calls this routine +** when it recognizes an ANALYZE command. +** +** ANALYZE -- 1 +** ANALYZE <database> -- 2 +** ANALYZE ?<database>.?<tablename> -- 3 +** +** Form 1 causes all indices in all attached databases to be analyzed. +** Form 2 analyzes all indices the single database named. +** Form 3 analyzes all indices associated with the named table. +*/ +void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){ + sqlite3 *db = pParse->db; + int iDb; + int i; + char *z, *zDb; + Table *pTab; + Token *pTableName; + + /* Read the database schema. If an error occurs, leave an error message + ** and code in pParse and return NULL. */ + assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ + return; + } + + if( pName1==0 ){ + /* Form 1: Analyze everything */ + for(i=0; i<db->nDb; i++){ + if( i==1 ) continue; /* Do not analyze the TEMP database */ + analyzeDatabase(pParse, i); + } + }else if( pName2==0 || pName2->n==0 ){ + /* Form 2: Analyze the database or table named */ + iDb = sqlite3FindDb(db, pName1); + if( iDb>=0 ){ + analyzeDatabase(pParse, iDb); + }else{ + z = sqlite3NameFromToken(db, pName1); + if( z ){ + pTab = sqlite3LocateTable(pParse, 0, z, 0); + sqlite3DbFree(db, z); + if( pTab ){ + analyzeTable(pParse, pTab); + } + } + } + }else{ + /* Form 3: Analyze the fully qualified table name */ + iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName); + if( iDb>=0 ){ + zDb = db->aDb[iDb].zName; + z = sqlite3NameFromToken(db, pTableName); + if( z ){ + pTab = sqlite3LocateTable(pParse, 0, z, zDb); + sqlite3DbFree(db, z); + if( pTab ){ + analyzeTable(pParse, pTab); + } + } + } + } +} + +/* +** Used to pass information from the analyzer reader through to the +** callback routine. +*/ +typedef struct analysisInfo analysisInfo; +struct analysisInfo { + sqlite3 *db; + const char *zDatabase; +}; + +/* +** This callback is invoked once for each index when reading the +** sqlite_stat1 table. +** +** argv[0] = name of the index +** argv[1] = results of analysis - on integer for each column +*/ +static int analysisLoader(void *pData, int argc, char **argv, char **azNotUsed){ + analysisInfo *pInfo = (analysisInfo*)pData; + Index *pIndex; + int i, c; + unsigned int v; + const char *z; + + assert( argc==2 ); + if( argv==0 || argv[0]==0 || argv[1]==0 ){ + return 0; + } + pIndex = sqlite3FindIndex(pInfo->db, argv[0], pInfo->zDatabase); + if( pIndex==0 ){ + return 0; + } + z = argv[1]; + for(i=0; *z && i<=pIndex->nColumn; i++){ + v = 0; + while( (c=z[0])>='0' && c<='9' ){ + v = v*10 + c - '0'; + z++; + } + pIndex->aiRowEst[i] = v; + if( *z==' ' ) z++; + } + return 0; +} + +/* +** Load the content of the sqlite_stat1 table into the index hash tables. +*/ +int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ + analysisInfo sInfo; + HashElem *i; + char *zSql; + int rc; + + assert( iDb>=0 && iDb<db->nDb ); + assert( db->aDb[iDb].pBt!=0 ); + assert( sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); + + /* Clear any prior statistics */ + for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ + Index *pIdx = sqliteHashData(i); + sqlite3DefaultRowEst(pIdx); + } + + /* Check to make sure the sqlite_stat1 table existss */ + sInfo.db = db; + sInfo.zDatabase = db->aDb[iDb].zName; + if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)==0 ){ + return SQLITE_ERROR; + } + + + /* Load new statistics out of the sqlite_stat1 table */ + zSql = sqlite3MPrintf(db, "SELECT idx, stat FROM %Q.sqlite_stat1", + sInfo.zDatabase); + (void)sqlite3SafetyOff(db); + rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0); + (void)sqlite3SafetyOn(db); + sqlite3DbFree(db, zSql); + return rc; +} + + +#endif /* SQLITE_OMIT_ANALYZE */ diff --git a/third_party/sqlite/src/attach.c b/third_party/sqlite/src/attach.c new file mode 100755 index 0000000..b8668f5 --- /dev/null +++ b/third_party/sqlite/src/attach.c @@ -0,0 +1,524 @@ +/* +** 2003 April 6 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains code used to implement the ATTACH and DETACH commands. +** +** $Id: attach.c,v 1.77 2008/07/28 19:34:53 drh Exp $ +*/ +#include "sqliteInt.h" + +#ifndef SQLITE_OMIT_ATTACH +/* +** 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. +** +** i.e. if the parser sees: +** +** 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. +*/ +static int resolveAttachExpr(NameContext *pName, Expr *pExpr) +{ + int rc = SQLITE_OK; + if( pExpr ){ + if( pExpr->op!=TK_ID ){ + rc = sqlite3ExprResolveNames(pName, pExpr); + if( rc==SQLITE_OK && !sqlite3ExprIsConstant(pExpr) ){ + sqlite3ErrorMsg(pName->pParse, "invalid name: \"%T\"", &pExpr->span); + return SQLITE_ERROR; + } + }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_context_db_handle(context); + const char *zName; + const char *zFile; + Db *aNew; + char *zErrDyn = 0; + char zErr[128]; + + zFile = (const char *)sqlite3_value_text(argv[0]); + zName = (const char *)sqlite3_value_text(argv[1]); + if( zFile==0 ) zFile = ""; + if( zName==0 ) zName = ""; + + /* Check for the following errors: + ** + ** * Too many attached databases, + ** * Transaction currently open + ** * Specified database name already being used. + */ + if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){ + sqlite3_snprintf( + sizeof(zErr), zErr, "too many attached databases - max %d", + db->aLimit[SQLITE_LIMIT_ATTACHED] + ); + goto attach_error; + } + if( !db->autoCommit ){ + sqlite3_snprintf(sizeof(zErr), zErr, + "cannot ATTACH database within transaction"); + goto attach_error; + } + for(i=0; i<db->nDb; i++){ + char *z = db->aDb[i].zName; + if( z && zName && sqlite3StrICmp(z, zName)==0 ){ + sqlite3_snprintf(sizeof(zErr), 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 = sqlite3DbMallocRaw(db, sizeof(db->aDb[0])*3 ); + if( aNew==0 ) return; + memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); + }else{ + aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); + if( aNew==0 ) return; + } + db->aDb = aNew; + aNew = &db->aDb[db->nDb++]; + memset(aNew, 0, sizeof(*aNew)); + + /* 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, SQLITE_DEFAULT_CACHE_SIZE, + db->openFlags | SQLITE_OPEN_MAIN_DB, + &aNew->pBt); + if( rc==SQLITE_OK ){ + Pager *pPager; + aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt); + if( !aNew->pSchema ){ + rc = SQLITE_NOMEM; + }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){ + sqlite3_snprintf(sizeof(zErr), zErr, + "attached databases must use the same text encoding as main database"); + goto attach_error; + } + pPager = sqlite3BtreePager(aNew->pBt); + sqlite3PagerLockingMode(pPager, db->dfltLockMode); + sqlite3PagerJournalMode(pPager, db->dfltJournalMode); + } + aNew->zName = sqlite3DbStrDup(db, zName); + aNew->safety_level = 3; + +#if SQLITE_HAS_CODEC + { + extern int sqlite3CodecAttach(sqlite3*, int, const void*, int); + extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); + int nKey; + char *zKey; + int t = sqlite3_value_type(argv[2]); + switch( t ){ + case SQLITE_INTEGER: + case SQLITE_FLOAT: + zErrDyn = sqlite3DbStrDup(db, "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 + + /* 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 ){ + (void)sqlite3SafetyOn(db); + sqlite3BtreeEnterAll(db); + rc = sqlite3Init(db, &zErrDyn); + sqlite3BtreeLeaveAll(db); + (void)sqlite3SafetyOff(db); + } + if( rc ){ + 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); + db->nDb = iDb; + if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ + db->mallocFailed = 1; + sqlite3_snprintf(sizeof(zErr),zErr, "out of memory"); + }else{ + sqlite3_snprintf(sizeof(zErr),zErr, "unable to open database: %s", zFile); + } + goto attach_error; + } + + return; + +attach_error: + /* Return an error if we get here */ + if( zErrDyn ){ + sqlite3_result_error(context, zErrDyn, -1); + sqlite3DbFree(db, zErrDyn); + }else{ + zErr[sizeof(zErr)-1] = 0; + sqlite3_result_error(context, zErr, -1); + } + if( rc ) sqlite3_result_error_code(context, rc); +} + +/* +** 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 x +** +** SELECT sqlite_detach(x) +*/ +static void detachFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const char *zName = (const char *)sqlite3_value_text(argv[0]); + sqlite3 *db = sqlite3_context_db_handle(context); + int i; + Db *pDb = 0; + char zErr[128]; + + if( zName==0 ) zName = ""; + for(i=0; i<db->nDb; i++){ + pDb = &db->aDb[i]; + if( pDb->pBt==0 ) continue; + if( sqlite3StrICmp(pDb->zName, zName)==0 ) break; + } + + if( i>=db->nDb ){ + sqlite3_snprintf(sizeof(zErr),zErr, "no such database: %s", zName); + goto detach_error; + } + if( i<2 ){ + sqlite3_snprintf(sizeof(zErr),zErr, "cannot detach database %s", zName); + goto detach_error; + } + if( !db->autoCommit ){ + sqlite3_snprintf(sizeof(zErr), zErr, + "cannot DETACH database within transaction"); + goto detach_error; + } + if( sqlite3BtreeIsInReadTrans(pDb->pBt) ){ + sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName); + goto detach_error; + } + + 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; + int regArgs; + +#ifndef SQLITE_OMIT_AUTHORIZATION + assert( db->mallocFailed || pAuthArg ); + if( pAuthArg ){ + char *zAuthArg = sqlite3NameFromToken(db, &pAuthArg->span); + if( !zAuthArg ){ + goto attach_end; + } + rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0); + sqlite3DbFree(db, 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); + regArgs = sqlite3GetTempRange(pParse, 4); + sqlite3ExprCode(pParse, pFilename, regArgs); + sqlite3ExprCode(pParse, pDbname, regArgs+1); + sqlite3ExprCode(pParse, pKey, regArgs+2); + + assert( v || db->mallocFailed ); + if( v ){ + sqlite3VdbeAddOp3(v, OP_Function, 0, regArgs+3-nFunc, regArgs+3); + sqlite3VdbeChangeP5(v, nFunc); + pFunc = sqlite3FindFunction(db, zFunc, strlen(zFunc), nFunc, SQLITE_UTF8,0); + sqlite3VdbeChangeP4(v, -1, (char *)pFunc, P4_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). + */ + sqlite3VdbeAddOp1(v, OP_Expire, (type==SQLITE_ATTACH)); + } + +attach_end: + sqlite3ExprDelete(db, pFilename); + sqlite3ExprDelete(db, pDbname); + sqlite3ExprDelete(db, 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); +} +#endif /* SQLITE_OMIT_ATTACH */ + +/* +** Register the functions sqlite_attach and sqlite_detach. +*/ +void sqlite3AttachFunctions(sqlite3 *db){ +#ifndef SQLITE_OMIT_ATTACH + static const int enc = SQLITE_UTF8; + sqlite3CreateFunc(db, "sqlite_attach", 3, enc, 0, attachFunc, 0, 0); + sqlite3CreateFunc(db, "sqlite_detach", 1, enc, 0, detachFunc, 0, 0); +#endif +} + +/* +** Initialize a DbFixer structure. This routine must be called prior +** to passing the structure to one of the sqliteFixAAAA() routines below. +** +** The return value indicates whether or not fixation is required. TRUE +** means we do need to fix the database references, FALSE means we do not. +*/ +int sqlite3FixInit( + DbFixer *pFix, /* The fixer to be initialized */ + Parse *pParse, /* Error messages will be written here */ + int iDb, /* This is the database that must be used */ + const char *zType, /* "view", "trigger", or "index" */ + const Token *pName /* Name of the view, trigger, or index */ +){ + sqlite3 *db; + + if( iDb<0 || iDb==1 ) return 0; + db = pParse->db; + assert( db->nDb>iDb ); + pFix->pParse = pParse; + pFix->zDb = db->aDb[iDb].zName; + pFix->zType = zType; + pFix->pName = pName; + return 1; +} + +/* +** The following set of routines walk through the parse tree and assign +** a specific database to all table references where the database name +** was left unspecified in the original SQL statement. The pFix structure +** must have been initialized by a prior call to sqlite3FixInit(). +** +** These routines are used to make sure that an index, trigger, or +** view in one database does not refer to objects in a different database. +** (Exception: indices, triggers, and views in the TEMP database are +** allowed to refer to anything.) If a reference is explicitly made +** to an object in a different database, an error message is added to +** pParse->zErrMsg and these routines return non-zero. If everything +** checks out, these routines return 0. +*/ +int sqlite3FixSrcList( + DbFixer *pFix, /* Context of the fixation */ + SrcList *pList /* The Source list to check and modify */ +){ + int i; + const char *zDb; + struct SrcList_item *pItem; + + if( pList==0 ) return 0; + zDb = pFix->zDb; + for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){ + if( pItem->zDatabase==0 ){ + pItem->zDatabase = sqlite3DbStrDup(pFix->pParse->db, zDb); + }else if( sqlite3StrICmp(pItem->zDatabase,zDb)!=0 ){ + sqlite3ErrorMsg(pFix->pParse, + "%s %T cannot reference objects in database %s", + pFix->zType, pFix->pName, pItem->zDatabase); + return 1; + } +#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) + if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1; + if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1; +#endif + } + return 0; +} +#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) +int sqlite3FixSelect( + DbFixer *pFix, /* Context of the fixation */ + Select *pSelect /* The SELECT statement to be fixed to one database */ +){ + while( pSelect ){ + if( sqlite3FixExprList(pFix, pSelect->pEList) ){ + return 1; + } + if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){ + return 1; + } + if( sqlite3FixExpr(pFix, pSelect->pWhere) ){ + return 1; + } + if( sqlite3FixExpr(pFix, pSelect->pHaving) ){ + return 1; + } + pSelect = pSelect->pPrior; + } + return 0; +} +int sqlite3FixExpr( + DbFixer *pFix, /* Context of the fixation */ + Expr *pExpr /* The expression to be fixed to one database */ +){ + while( pExpr ){ + if( sqlite3FixSelect(pFix, pExpr->pSelect) ){ + return 1; + } + if( sqlite3FixExprList(pFix, pExpr->pList) ){ + return 1; + } + if( sqlite3FixExpr(pFix, pExpr->pRight) ){ + return 1; + } + pExpr = pExpr->pLeft; + } + return 0; +} +int sqlite3FixExprList( + DbFixer *pFix, /* Context of the fixation */ + ExprList *pList /* The expression to be fixed to one database */ +){ + int i; + struct ExprList_item *pItem; + if( pList==0 ) return 0; + for(i=0, pItem=pList->a; i<pList->nExpr; i++, pItem++){ + if( sqlite3FixExpr(pFix, pItem->pExpr) ){ + return 1; + } + } + return 0; +} +#endif + +#ifndef SQLITE_OMIT_TRIGGER +int sqlite3FixTriggerStep( + DbFixer *pFix, /* Context of the fixation */ + TriggerStep *pStep /* The trigger step be fixed to one database */ +){ + while( pStep ){ + if( sqlite3FixSelect(pFix, pStep->pSelect) ){ + return 1; + } + if( sqlite3FixExpr(pFix, pStep->pWhere) ){ + return 1; + } + if( sqlite3FixExprList(pFix, pStep->pExprList) ){ + return 1; + } + pStep = pStep->pNext; + } + return 0; +} +#endif diff --git a/third_party/sqlite/src/auth.c b/third_party/sqlite/src/auth.c new file mode 100755 index 0000000..5630c23 --- /dev/null +++ b/third_party/sqlite/src/auth.c @@ -0,0 +1,234 @@ +/* +** 2003 January 11 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains code used to implement the sqlite3_set_authorizer() +** API. This facility is an optional feature of the library. Embedded +** systems that do not need this facility may omit it by recompiling +** the library with -DSQLITE_OMIT_AUTHORIZATION=1 +** +** $Id: auth.c,v 1.29 2007/09/18 15:55:07 drh Exp $ +*/ +#include "sqliteInt.h" + +/* +** All of the code in this file may be omitted by defining a single +** macro. +*/ +#ifndef SQLITE_OMIT_AUTHORIZATION + +/* +** Set or clear the access authorization function. +** +** The access authorization function is be called during the compilation +** phase to verify that the user has read and/or write access permission on +** various fields of the database. The first argument to the auth function +** is a copy of the 3rd argument to this routine. The second argument +** to the auth function is one of these constants: +** +** SQLITE_CREATE_INDEX +** SQLITE_CREATE_TABLE +** SQLITE_CREATE_TEMP_INDEX +** SQLITE_CREATE_TEMP_TABLE +** SQLITE_CREATE_TEMP_TRIGGER +** SQLITE_CREATE_TEMP_VIEW +** SQLITE_CREATE_TRIGGER +** SQLITE_CREATE_VIEW +** SQLITE_DELETE +** SQLITE_DROP_INDEX +** SQLITE_DROP_TABLE +** SQLITE_DROP_TEMP_INDEX +** SQLITE_DROP_TEMP_TABLE +** SQLITE_DROP_TEMP_TRIGGER +** SQLITE_DROP_TEMP_VIEW +** SQLITE_DROP_TRIGGER +** SQLITE_DROP_VIEW +** SQLITE_INSERT +** SQLITE_PRAGMA +** SQLITE_READ +** SQLITE_SELECT +** SQLITE_TRANSACTION +** SQLITE_UPDATE +** +** The third and fourth arguments to the auth function are the name of +** the table and the column that are being accessed. The auth function +** should return either SQLITE_OK, SQLITE_DENY, or SQLITE_IGNORE. If +** SQLITE_OK is returned, it means that access is allowed. SQLITE_DENY +** means that the SQL statement will never-run - the sqlite3_exec() call +** will return with an error. SQLITE_IGNORE means that the SQL statement +** should run but attempts to read the specified column will return NULL +** and attempts to write the column will be ignored. +** +** Setting the auth function to NULL disables this hook. The default +** setting of the auth function is NULL. +*/ +int sqlite3_set_authorizer( + sqlite3 *db, + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), + void *pArg +){ + sqlite3_mutex_enter(db->mutex); + db->xAuth = xAuth; + db->pAuthArg = pArg; + sqlite3ExpirePreparedStatements(db); + sqlite3_mutex_leave(db->mutex); + return SQLITE_OK; +} + +/* +** Write an error message into pParse->zErrMsg that explains that the +** user-supplied authorization function returned an illegal value. +*/ +static void sqliteAuthBadReturnCode(Parse *pParse, int rc){ + sqlite3ErrorMsg(pParse, "illegal return value (%d) from the " + "authorization function - should be SQLITE_OK, SQLITE_IGNORE, " + "or SQLITE_DENY", rc); + pParse->rc = SQLITE_ERROR; +} + +/* +** The pExpr should be a TK_COLUMN expression. The table referred to +** is in pTabList or else it is the NEW or OLD table of a trigger. +** Check to see if it is OK to read this particular column. +** +** If the auth function returns SQLITE_IGNORE, change the TK_COLUMN +** instruction into a TK_NULL. If the auth function returns SQLITE_DENY, +** then generate an error. +*/ +void sqlite3AuthRead( + Parse *pParse, /* The parser context */ + Expr *pExpr, /* The expression to check authorization on */ + Schema *pSchema, /* The schema of the expression */ + SrcList *pTabList /* All table that pExpr might refer to */ +){ + sqlite3 *db = pParse->db; + int rc; + Table *pTab = 0; /* The table being read */ + const char *zCol; /* Name of the column of the table */ + 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_COLUMN ) return; + iDb = sqlite3SchemaToIndex(pParse->db, pSchema); + if( iDb<0 ){ + /* An attempt to read a column out of a subquery or other + ** temporary table. */ + return; + } + for(iSrc=0; pTabList && iSrc<pTabList->nSrc; iSrc++){ + if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break; + } + if( iSrc>=0 && pTabList && iSrc<pTabList->nSrc ){ + pTab = pTabList->a[iSrc].pTab; + }else if( (pStack = pParse->trigStack)!=0 ){ + /* This must be an attempt to read the NEW or OLD pseudo-tables + ** of a trigger. + */ + assert( pExpr->iTable==pStack->newIdx || pExpr->iTable==pStack->oldIdx ); + pTab = pStack->pTab; + } + if( pTab==0 ) return; + if( pExpr->iColumn>=0 ){ + assert( pExpr->iColumn<pTab->nCol ); + zCol = pTab->aCol[pExpr->iColumn].zName; + }else if( pTab->iPKey>=0 ){ + assert( pTab->iPKey<pTab->nCol ); + zCol = pTab->aCol[pTab->iPKey].zName; + }else{ + zCol = "ROWID"; + } + assert( iDb>=0 && iDb<db->nDb ); + 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 || iDb!=0 ){ + sqlite3ErrorMsg(pParse, "access to %s.%s.%s is prohibited", + zDBase, pTab->zName, zCol); + }else{ + sqlite3ErrorMsg(pParse, "access to %s.%s is prohibited",pTab->zName,zCol); + } + pParse->rc = SQLITE_AUTH; + }else if( rc!=SQLITE_OK ){ + sqliteAuthBadReturnCode(pParse, rc); + } +} + +/* +** Do an authorization check using the code and arguments given. Return +** either SQLITE_OK (zero) or SQLITE_IGNORE or SQLITE_DENY. If SQLITE_DENY +** is returned, then the error count and error message in pParse are +** modified appropriately. +*/ +int sqlite3AuthCheck( + Parse *pParse, + int code, + const char *zArg1, + const char *zArg2, + const char *zArg3 +){ + sqlite3 *db = pParse->db; + int rc; + + /* Don't do any authorization checks if the database is initialising + ** or if the parser is being invoked from within sqlite3_declare_vtab. + */ + if( db->init.busy || IN_DECLARE_VTAB ){ + return SQLITE_OK; + } + + if( db->xAuth==0 ){ + return SQLITE_OK; + } + rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext); + if( rc==SQLITE_DENY ){ + sqlite3ErrorMsg(pParse, "not authorized"); + pParse->rc = SQLITE_AUTH; + }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){ + rc = SQLITE_DENY; + sqliteAuthBadReturnCode(pParse, rc); + } + return rc; +} + +/* +** Push an authorization context. After this routine is called, the +** zArg3 argument to authorization callbacks will be zContext until +** popped. Or if pParse==0, this routine is a no-op. +*/ +void sqlite3AuthContextPush( + Parse *pParse, + AuthContext *pContext, + const char *zContext +){ + pContext->pParse = pParse; + if( pParse ){ + pContext->zAuthContext = pParse->zAuthContext; + pParse->zAuthContext = zContext; + } +} + +/* +** Pop an authorization context that was previously pushed +** by sqlite3AuthContextPush +*/ +void sqlite3AuthContextPop(AuthContext *pContext){ + if( pContext->pParse ){ + pContext->pParse->zAuthContext = pContext->zAuthContext; + pContext->pParse = 0; + } +} + +#endif /* SQLITE_OMIT_AUTHORIZATION */ diff --git a/third_party/sqlite/src/bitvec.c b/third_party/sqlite/src/bitvec.c new file mode 100755 index 0000000..e911315 --- /dev/null +++ b/third_party/sqlite/src/bitvec.c @@ -0,0 +1,325 @@ +/* +** 2008 February 16 +** +** 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 implements an object that represents a fixed-length +** bitmap. Bits are numbered starting with 1. +** +** A bitmap is used to record what pages a database file have been +** journalled during a transaction. Usually only a few pages are +** journalled. So the bitmap is usually sparse and has low cardinality. +** But sometimes (for example when during a DROP of a large table) most +** or all of the pages get journalled. In those cases, the bitmap becomes +** dense. The algorithm needs to handle both cases well. +** +** The size of the bitmap is fixed when the object is created. +** +** All bits are clear when the bitmap is created. Individual bits +** may be set or cleared one at a time. +** +** Test operations are about 100 times more common that set operations. +** Clear operations are exceedingly rare. There are usually between +** 5 and 500 set operations per Bitvec object, though the number of sets can +** sometimes grow into tens of thousands or larger. The size of the +** Bitvec object is the number of pages in the database file at the +** start of a transaction, and is thus usually less than a few thousand, +** but can be as large as 2 billion for a really big database. +** +** @(#) $Id: bitvec.c,v 1.6 2008/06/20 14:59:51 danielk1977 Exp $ +*/ +#include "sqliteInt.h" + +#define BITVEC_SZ 512 +/* Round the union size down to the nearest pointer boundary, since that's how +** it will be aligned within the Bitvec struct. */ +#define BITVEC_USIZE (((BITVEC_SZ-12)/sizeof(Bitvec*))*sizeof(Bitvec*)) +#define BITVEC_NCHAR BITVEC_USIZE +#define BITVEC_NBIT (BITVEC_NCHAR*8) +#define BITVEC_NINT (BITVEC_USIZE/4) +#define BITVEC_MXHASH (BITVEC_NINT/2) +#define BITVEC_NPTR (BITVEC_USIZE/sizeof(Bitvec *)) + +#define BITVEC_HASH(X) (((X)*37)%BITVEC_NINT) + +/* +** A bitmap is an instance of the following structure. +** +** This bitmap records the existance of zero or more bits +** with values between 1 and iSize, inclusive. +** +** There are three possible representations of the bitmap. +** If iSize<=BITVEC_NBIT, then Bitvec.u.aBitmap[] is a straight +** bitmap. The least significant bit is bit 1. +** +** If iSize>BITVEC_NBIT and iDivisor==0 then Bitvec.u.aHash[] is +** a hash table that will hold up to BITVEC_MXHASH distinct values. +** +** Otherwise, the value i is redirected into one of BITVEC_NPTR +** sub-bitmaps pointed to by Bitvec.u.apSub[]. Each subbitmap +** handles up to iDivisor separate values of i. apSub[0] holds +** values between 1 and iDivisor. apSub[1] holds values between +** iDivisor+1 and 2*iDivisor. apSub[N] holds values between +** N*iDivisor+1 and (N+1)*iDivisor. Each subbitmap is normalized +** to hold deal with values between 1 and iDivisor. +*/ +struct Bitvec { + u32 iSize; /* Maximum bit index */ + u32 nSet; /* Number of bits that are set */ + u32 iDivisor; /* Number of bits handled by each apSub[] entry */ + union { + u8 aBitmap[BITVEC_NCHAR]; /* Bitmap representation */ + u32 aHash[BITVEC_NINT]; /* Hash table representation */ + Bitvec *apSub[BITVEC_NPTR]; /* Recursive representation */ + } u; +}; + +/* +** Create a new bitmap object able to handle bits between 0 and iSize, +** inclusive. Return a pointer to the new object. Return NULL if +** malloc fails. +*/ +Bitvec *sqlite3BitvecCreate(u32 iSize){ + Bitvec *p; + assert( sizeof(*p)==BITVEC_SZ ); + p = sqlite3MallocZero( sizeof(*p) ); + if( p ){ + p->iSize = iSize; + } + return p; +} + +/* +** Check to see if the i-th bit is set. Return true or false. +** If p is NULL (if the bitmap has not been created) or if +** i is out of range, then return false. +*/ +int sqlite3BitvecTest(Bitvec *p, u32 i){ + if( p==0 ) return 0; + if( i>p->iSize || i==0 ) return 0; + if( p->iSize<=BITVEC_NBIT ){ + i--; + return (p->u.aBitmap[i/8] & (1<<(i&7)))!=0; + } + if( p->iDivisor>0 ){ + u32 bin = (i-1)/p->iDivisor; + i = (i-1)%p->iDivisor + 1; + return sqlite3BitvecTest(p->u.apSub[bin], i); + }else{ + u32 h = BITVEC_HASH(i); + while( p->u.aHash[h] ){ + if( p->u.aHash[h]==i ) return 1; + h++; + if( h>=BITVEC_NINT ) h = 0; + } + return 0; + } +} + +/* +** Set the i-th bit. Return 0 on success and an error code if +** anything goes wrong. +*/ +int sqlite3BitvecSet(Bitvec *p, u32 i){ + u32 h; + assert( p!=0 ); + assert( i>0 ); + assert( i<=p->iSize ); + if( p->iSize<=BITVEC_NBIT ){ + i--; + p->u.aBitmap[i/8] |= 1 << (i&7); + return SQLITE_OK; + } + if( p->iDivisor ){ + u32 bin = (i-1)/p->iDivisor; + i = (i-1)%p->iDivisor + 1; + if( p->u.apSub[bin]==0 ){ + sqlite3BeginBenignMalloc(); + p->u.apSub[bin] = sqlite3BitvecCreate( p->iDivisor ); + sqlite3EndBenignMalloc(); + if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM; + } + return sqlite3BitvecSet(p->u.apSub[bin], i); + } + h = BITVEC_HASH(i); + while( p->u.aHash[h] ){ + if( p->u.aHash[h]==i ) return SQLITE_OK; + h++; + if( h==BITVEC_NINT ) h = 0; + } + p->nSet++; + if( p->nSet>=BITVEC_MXHASH ){ + int j, rc; + u32 aiValues[BITVEC_NINT]; + memcpy(aiValues, p->u.aHash, sizeof(aiValues)); + memset(p->u.apSub, 0, sizeof(p->u.apSub[0])*BITVEC_NPTR); + p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR; + rc = sqlite3BitvecSet(p, i); + for(j=0; j<BITVEC_NINT; j++){ + if( aiValues[j] ) rc |= sqlite3BitvecSet(p, aiValues[j]); + } + return rc; + } + p->u.aHash[h] = i; + return SQLITE_OK; +} + +/* +** Clear the i-th bit. Return 0 on success and an error code if +** anything goes wrong. +*/ +void sqlite3BitvecClear(Bitvec *p, u32 i){ + assert( p!=0 ); + assert( i>0 ); + if( p->iSize<=BITVEC_NBIT ){ + i--; + p->u.aBitmap[i/8] &= ~(1 << (i&7)); + }else if( p->iDivisor ){ + u32 bin = (i-1)/p->iDivisor; + i = (i-1)%p->iDivisor + 1; + if( p->u.apSub[bin] ){ + sqlite3BitvecClear(p->u.apSub[bin], i); + } + }else{ + int j; + u32 aiValues[BITVEC_NINT]; + memcpy(aiValues, p->u.aHash, sizeof(aiValues)); + memset(p->u.aHash, 0, sizeof(p->u.aHash[0])*BITVEC_NINT); + p->nSet = 0; + for(j=0; j<BITVEC_NINT; j++){ + if( aiValues[j] && aiValues[j]!=i ){ + sqlite3BitvecSet(p, aiValues[j]); + } + } + } +} + +/* +** Destroy a bitmap object. Reclaim all memory used. +*/ +void sqlite3BitvecDestroy(Bitvec *p){ + if( p==0 ) return; + if( p->iDivisor ){ + int i; + for(i=0; i<BITVEC_NPTR; i++){ + sqlite3BitvecDestroy(p->u.apSub[i]); + } + } + sqlite3_free(p); +} + +#ifndef SQLITE_OMIT_BUILTIN_TEST +/* +** Let V[] be an array of unsigned characters sufficient to hold +** up to N bits. Let I be an integer between 0 and N. 0<=I<N. +** Then the following macros can be used to set, clear, or test +** individual bits within V. +*/ +#define SETBIT(V,I) V[I>>3] |= (1<<(I&7)) +#define CLEARBIT(V,I) V[I>>3] &= ~(1<<(I&7)) +#define TESTBIT(V,I) (V[I>>3]&(1<<(I&7)))!=0 + +/* +** This routine runs an extensive test of the Bitvec code. +** +** The input is an array of integers that acts as a program +** to test the Bitvec. The integers are opcodes followed +** by 0, 1, or 3 operands, depending on the opcode. Another +** opcode follows immediately after the last operand. +** +** There are 6 opcodes numbered from 0 through 5. 0 is the +** "halt" opcode and causes the test to end. +** +** 0 Halt and return the number of errors +** 1 N S X Set N bits beginning with S and incrementing by X +** 2 N S X Clear N bits beginning with S and incrementing by X +** 3 N Set N randomly chosen bits +** 4 N Clear N randomly chosen bits +** 5 N S X Set N bits from S increment X in array only, not in bitvec +** +** The opcodes 1 through 4 perform set and clear operations are performed +** on both a Bitvec object and on a linear array of bits obtained from malloc. +** Opcode 5 works on the linear array only, not on the Bitvec. +** Opcode 5 is used to deliberately induce a fault in order to +** confirm that error detection works. +** +** At the conclusion of the test the linear array is compared +** against the Bitvec object. If there are any differences, +** an error is returned. If they are the same, zero is returned. +** +** If a memory allocation error occurs, return -1. +*/ +int sqlite3BitvecBuiltinTest(int sz, int *aOp){ + Bitvec *pBitvec = 0; + unsigned char *pV = 0; + int rc = -1; + int i, nx, pc, op; + + /* Allocate the Bitvec to be tested and a linear array of + ** bits to act as the reference */ + pBitvec = sqlite3BitvecCreate( sz ); + pV = sqlite3_malloc( (sz+7)/8 + 1 ); + if( pBitvec==0 || pV==0 ) goto bitvec_end; + memset(pV, 0, (sz+7)/8 + 1); + + /* Run the program */ + pc = 0; + while( (op = aOp[pc])!=0 ){ + switch( op ){ + case 1: + case 2: + case 5: { + nx = 4; + i = aOp[pc+2] - 1; + aOp[pc+2] += aOp[pc+3]; + break; + } + case 3: + case 4: + default: { + nx = 2; + sqlite3_randomness(sizeof(i), &i); + break; + } + } + if( (--aOp[pc+1]) > 0 ) nx = 0; + pc += nx; + i = (i & 0x7fffffff)%sz; + if( (op & 1)!=0 ){ + SETBIT(pV, (i+1)); + if( op!=5 ){ + if( sqlite3BitvecSet(pBitvec, i+1) ) goto bitvec_end; + } + }else{ + CLEARBIT(pV, (i+1)); + sqlite3BitvecClear(pBitvec, i+1); + } + } + + /* Test to make sure the linear array exactly matches the + ** Bitvec object. Start with the assumption that they do + ** match (rc==0). Change rc to non-zero if a discrepancy + ** is found. + */ + rc = sqlite3BitvecTest(0,0) + sqlite3BitvecTest(pBitvec, sz+1) + + sqlite3BitvecTest(pBitvec, 0); + for(i=1; i<=sz; i++){ + if( (TESTBIT(pV,i))!=sqlite3BitvecTest(pBitvec,i) ){ + rc = i; + break; + } + } + + /* Free allocated structure */ +bitvec_end: + sqlite3_free(pV); + sqlite3BitvecDestroy(pBitvec); + return rc; +} +#endif /* SQLITE_OMIT_BUILTIN_TEST */ diff --git a/third_party/sqlite/src/btmutex.c b/third_party/sqlite/src/btmutex.c new file mode 100755 index 0000000..bf63617 --- /dev/null +++ b/third_party/sqlite/src/btmutex.c @@ -0,0 +1,317 @@ +/* +** 2007 August 27 +** +** 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. +** +************************************************************************* +** +** $Id: btmutex.c,v 1.10 2008/07/14 19:39:17 drh Exp $ +** +** This file contains code used to implement mutexes on Btree objects. +** This code really belongs in btree.c. But btree.c is getting too +** big and we want to break it down some. This packaged seemed like +** a good breakout. +*/ +#include "btreeInt.h" +#if SQLITE_THREADSAFE && !defined(SQLITE_OMIT_SHARED_CACHE) + + +/* +** Enter a mutex on the given BTree object. +** +** If the object is not sharable, then no mutex is ever required +** and this routine is a no-op. The underlying mutex is non-recursive. +** But we keep a reference count in Btree.wantToLock so the behavior +** of this interface is recursive. +** +** To avoid deadlocks, multiple Btrees are locked in the same order +** by all database connections. The p->pNext is a list of other +** Btrees belonging to the same database connection as the p Btree +** which need to be locked after p. If we cannot get a lock on +** p, then first unlock all of the others on p->pNext, then wait +** for the lock to become available on p, then relock all of the +** subsequent Btrees that desire a lock. +*/ +void sqlite3BtreeEnter(Btree *p){ + Btree *pLater; + + /* Some basic sanity checking on the Btree. The list of Btrees + ** connected by pNext and pPrev should be in sorted order by + ** Btree.pBt value. All elements of the list should belong to + ** the same connection. Only shared Btrees are on the list. */ + assert( p->pNext==0 || p->pNext->pBt>p->pBt ); + assert( p->pPrev==0 || p->pPrev->pBt<p->pBt ); + assert( p->pNext==0 || p->pNext->db==p->db ); + assert( p->pPrev==0 || p->pPrev->db==p->db ); + assert( p->sharable || (p->pNext==0 && p->pPrev==0) ); + + /* Check for locking consistency */ + assert( !p->locked || p->wantToLock>0 ); + assert( p->sharable || p->wantToLock==0 ); + + /* We should already hold a lock on the database connection */ + assert( sqlite3_mutex_held(p->db->mutex) ); + + if( !p->sharable ) return; + p->wantToLock++; + if( p->locked ) return; + +#ifndef SQLITE_MUTEX_NOOP + /* In most cases, we should be able to acquire the lock we + ** want without having to go throught the ascending lock + ** procedure that follows. Just be sure not to block. + */ + if( sqlite3_mutex_try(p->pBt->mutex)==SQLITE_OK ){ + p->locked = 1; + return; + } + + /* To avoid deadlock, first release all locks with a larger + ** BtShared address. Then acquire our lock. Then reacquire + ** the other BtShared locks that we used to hold in ascending + ** order. + */ + for(pLater=p->pNext; pLater; pLater=pLater->pNext){ + assert( pLater->sharable ); + assert( pLater->pNext==0 || pLater->pNext->pBt>pLater->pBt ); + assert( !pLater->locked || pLater->wantToLock>0 ); + if( pLater->locked ){ + sqlite3_mutex_leave(pLater->pBt->mutex); + pLater->locked = 0; + } + } + sqlite3_mutex_enter(p->pBt->mutex); + p->locked = 1; + for(pLater=p->pNext; pLater; pLater=pLater->pNext){ + if( pLater->wantToLock ){ + sqlite3_mutex_enter(pLater->pBt->mutex); + pLater->locked = 1; + } + } +#endif /* SQLITE_MUTEX_NOOP */ +} + +/* +** Exit the recursive mutex on a Btree. +*/ +void sqlite3BtreeLeave(Btree *p){ + if( p->sharable ){ + assert( p->wantToLock>0 ); + p->wantToLock--; + if( p->wantToLock==0 ){ + assert( p->locked ); + sqlite3_mutex_leave(p->pBt->mutex); + p->locked = 0; + } + } +} + +#ifndef NDEBUG +/* +** Return true if the BtShared mutex is held on the btree. +** +** This routine makes no determination one why or another if the +** database connection mutex is held. +** +** This routine is used only from within assert() statements. +*/ +int sqlite3BtreeHoldsMutex(Btree *p){ + return (p->sharable==0 || + (p->locked && p->wantToLock && sqlite3_mutex_held(p->pBt->mutex))); +} +#endif + + +#ifndef SQLITE_OMIT_INCRBLOB +/* +** Enter and leave a mutex on a Btree given a cursor owned by that +** Btree. These entry points are used by incremental I/O and can be +** omitted if that module is not used. +*/ +void sqlite3BtreeEnterCursor(BtCursor *pCur){ + sqlite3BtreeEnter(pCur->pBtree); +} +void sqlite3BtreeLeaveCursor(BtCursor *pCur){ + sqlite3BtreeLeave(pCur->pBtree); +} +#endif /* SQLITE_OMIT_INCRBLOB */ + + +/* +** Enter the mutex on every Btree associated with a database +** connection. This is needed (for example) prior to parsing +** a statement since we will be comparing table and column names +** against all schemas and we do not want those schemas being +** reset out from under us. +** +** There is a corresponding leave-all procedures. +** +** Enter the mutexes in accending order by BtShared pointer address +** to avoid the possibility of deadlock when two threads with +** two or more btrees in common both try to lock all their btrees +** at the same instant. +*/ +void sqlite3BtreeEnterAll(sqlite3 *db){ + int i; + Btree *p, *pLater; + assert( sqlite3_mutex_held(db->mutex) ); + for(i=0; i<db->nDb; i++){ + p = db->aDb[i].pBt; + if( p && p->sharable ){ + p->wantToLock++; + if( !p->locked ){ + assert( p->wantToLock==1 ); + while( p->pPrev ) p = p->pPrev; + while( p->locked && p->pNext ) p = p->pNext; + for(pLater = p->pNext; pLater; pLater=pLater->pNext){ + if( pLater->locked ){ + sqlite3_mutex_leave(pLater->pBt->mutex); + pLater->locked = 0; + } + } + while( p ){ + sqlite3_mutex_enter(p->pBt->mutex); + p->locked++; + p = p->pNext; + } + } + } + } +} +void sqlite3BtreeLeaveAll(sqlite3 *db){ + int i; + Btree *p; + assert( sqlite3_mutex_held(db->mutex) ); + for(i=0; i<db->nDb; i++){ + p = db->aDb[i].pBt; + if( p && p->sharable ){ + assert( p->wantToLock>0 ); + p->wantToLock--; + if( p->wantToLock==0 ){ + assert( p->locked ); + sqlite3_mutex_leave(p->pBt->mutex); + p->locked = 0; + } + } + } +} + +#ifndef NDEBUG +/* +** Return true if the current thread holds the database connection +** mutex and all required BtShared mutexes. +** +** This routine is used inside assert() statements only. +*/ +int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){ + int i; + if( !sqlite3_mutex_held(db->mutex) ){ + return 0; + } + for(i=0; i<db->nDb; i++){ + Btree *p; + p = db->aDb[i].pBt; + if( p && p->sharable && + (p->wantToLock==0 || !sqlite3_mutex_held(p->pBt->mutex)) ){ + return 0; + } + } + return 1; +} +#endif /* NDEBUG */ + +/* +** Add a new Btree pointer to a BtreeMutexArray. +** if the pointer can possibly be shared with +** another database connection. +** +** The pointers are kept in sorted order by pBtree->pBt. That +** way when we go to enter all the mutexes, we can enter them +** in order without every having to backup and retry and without +** worrying about deadlock. +** +** The number of shared btrees will always be small (usually 0 or 1) +** so an insertion sort is an adequate algorithm here. +*/ +void sqlite3BtreeMutexArrayInsert(BtreeMutexArray *pArray, Btree *pBtree){ + int i, j; + BtShared *pBt; + if( pBtree==0 || pBtree->sharable==0 ) return; +#ifndef NDEBUG + { + for(i=0; i<pArray->nMutex; i++){ + assert( pArray->aBtree[i]!=pBtree ); + } + } +#endif + assert( pArray->nMutex>=0 ); + assert( pArray->nMutex<sizeof(pArray->aBtree)/sizeof(pArray->aBtree[0])-1 ); + pBt = pBtree->pBt; + for(i=0; i<pArray->nMutex; i++){ + assert( pArray->aBtree[i]!=pBtree ); + if( pArray->aBtree[i]->pBt>pBt ){ + for(j=pArray->nMutex; j>i; j--){ + pArray->aBtree[j] = pArray->aBtree[j-1]; + } + pArray->aBtree[i] = pBtree; + pArray->nMutex++; + return; + } + } + pArray->aBtree[pArray->nMutex++] = pBtree; +} + +/* +** Enter the mutex of every btree in the array. This routine is +** called at the beginning of sqlite3VdbeExec(). The mutexes are +** exited at the end of the same function. +*/ +void sqlite3BtreeMutexArrayEnter(BtreeMutexArray *pArray){ + int i; + for(i=0; i<pArray->nMutex; i++){ + Btree *p = pArray->aBtree[i]; + /* Some basic sanity checking */ + assert( i==0 || pArray->aBtree[i-1]->pBt<p->pBt ); + assert( !p->locked || p->wantToLock>0 ); + + /* We should already hold a lock on the database connection */ + assert( sqlite3_mutex_held(p->db->mutex) ); + + p->wantToLock++; + if( !p->locked && p->sharable ){ + sqlite3_mutex_enter(p->pBt->mutex); + p->locked = 1; + } + } +} + +/* +** Leave the mutex of every btree in the group. +*/ +void sqlite3BtreeMutexArrayLeave(BtreeMutexArray *pArray){ + int i; + for(i=0; i<pArray->nMutex; i++){ + Btree *p = pArray->aBtree[i]; + /* Some basic sanity checking */ + assert( i==0 || pArray->aBtree[i-1]->pBt<p->pBt ); + assert( p->locked || !p->sharable ); + assert( p->wantToLock>0 ); + + /* We should already hold a lock on the database connection */ + assert( sqlite3_mutex_held(p->db->mutex) ); + + p->wantToLock--; + if( p->wantToLock==0 && p->locked ){ + sqlite3_mutex_leave(p->pBt->mutex); + p->locked = 0; + } + } +} + + +#endif /* SQLITE_THREADSAFE && !SQLITE_OMIT_SHARED_CACHE */ diff --git a/third_party/sqlite/src/btree.c b/third_party/sqlite/src/btree.c new file mode 100755 index 0000000..dc71523 --- /dev/null +++ b/third_party/sqlite/src/btree.c @@ -0,0 +1,7401 @@ +/* +** 2004 April 6 +** +** 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. +** +************************************************************************* +** $Id: btree.c,v 1.495 2008/08/02 17:36:46 danielk1977 Exp $ +** +** This file implements a external (disk-based) database using BTrees. +** See the header comment on "btreeInt.h" for additional information. +** Including a description of file format and an overview of operation. +*/ +#include "btreeInt.h" + +/* +** The header string that appears at the beginning of every +** SQLite database. +*/ +static const char zMagicHeader[] = SQLITE_FILE_HEADER; + +/* +** The header string that appears at the beginning of a SQLite +** database which has been poisoned. +*/ +static const char zPoisonHeader[] = "SQLite poison 3"; + +/* +** Set this global variable to 1 to enable tracing using the TRACE +** macro. +*/ +#if 0 +int sqlite3BtreeTrace=0; /* True to enable tracing */ +# define TRACE(X) if(sqlite3BtreeTrace){printf X;fflush(stdout);} +#else +# define TRACE(X) +#endif + + + +#ifndef SQLITE_OMIT_SHARED_CACHE +/* +** A flag to indicate whether or not shared cache is enabled. Also, +** a list of BtShared objects that are eligible for participation +** in shared cache. The variables have file scope during normal builds, +** but the test harness needs to access these variables so we make them +** global for test builds. +*/ +#ifdef SQLITE_TEST +BtShared *sqlite3SharedCacheList = 0; +int sqlite3SharedCacheEnabled = 0; +#else +static BtShared *sqlite3SharedCacheList = 0; +static int sqlite3SharedCacheEnabled = 0; +#endif +#endif /* SQLITE_OMIT_SHARED_CACHE */ + +#ifndef SQLITE_OMIT_SHARED_CACHE +/* +** Enable or disable the shared pager and schema features. +** +** This routine has no effect on existing database connections. +** The shared cache setting effects only future calls to +** sqlite3_open(), sqlite3_open16(), or sqlite3_open_v2(). +*/ +int sqlite3_enable_shared_cache(int enable){ + sqlite3SharedCacheEnabled = enable; + return SQLITE_OK; +} +#endif + + +/* +** Forward declaration +*/ +static int checkReadLocks(Btree*, Pgno, BtCursor*, i64); + + +#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) +#endif + +#ifndef SQLITE_OMIT_SHARED_CACHE +/* +** 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; + + assert( sqlite3BtreeHoldsMutex(p) ); + assert( eLock==READ_LOCK || eLock==WRITE_LOCK ); + assert( p->db!=0 ); + + /* This is a no-op if the shared-cache is not enabled */ + if( !p->sharable ){ + return SQLITE_OK; + } + + /* If some other connection is holding an exclusive lock, the + ** requested lock may not be obtained. + */ + if( pBt->pExclusive && pBt->pExclusive!=p ){ + return SQLITE_LOCKED; + } + + /* 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( + 0==(p->db->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; +} +#endif /* !SQLITE_OMIT_SHARED_CACHE */ + +#ifndef SQLITE_OMIT_SHARED_CACHE +/* +** 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; + + assert( sqlite3BtreeHoldsMutex(p) ); + assert( eLock==READ_LOCK || eLock==WRITE_LOCK ); + assert( p->db!=0 ); + + /* This is a no-op if the shared-cache is not enabled */ + if( !p->sharable ){ + 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->db->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 *)sqlite3MallocZero(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; +} +#endif /* !SQLITE_OMIT_SHARED_CACHE */ + +#ifndef SQLITE_OMIT_SHARED_CACHE +/* +** Release all the table locks (locks obtained via calls to the lockTable() +** procedure) held by Btree handle p. +*/ +static void unlockAllTables(Btree *p){ + BtShared *pBt = p->pBt; + BtLock **ppIter = &pBt->pLock; + + assert( sqlite3BtreeHoldsMutex(p) ); + assert( p->sharable || 0==*ppIter ); + + while( *ppIter ){ + BtLock *pLock = *ppIter; + assert( pBt->pExclusive==0 || pBt->pExclusive==pLock->pBtree ); + if( pLock->pBtree==p ){ + *ppIter = pLock->pNext; + sqlite3_free(pLock); + }else{ + ppIter = &pLock->pNext; + } + } + + if( pBt->pExclusive==p ){ + pBt->pExclusive = 0; + } +} +#endif /* SQLITE_OMIT_SHARED_CACHE */ + +static void releasePage(MemPage *pPage); /* Forward reference */ + +/* +** Verify that the cursor holds a mutex on the BtShared +*/ +#ifndef NDEBUG +static int cursorHoldsMutex(BtCursor *p){ + return sqlite3_mutex_held(p->pBt->mutex); +} +#endif + + +#ifndef SQLITE_OMIT_INCRBLOB +/* +** Invalidate the overflow page-list cache for cursor pCur, if any. +*/ +static void invalidateOverflowCache(BtCursor *pCur){ + assert( cursorHoldsMutex(pCur) ); + sqlite3_free(pCur->aOverflow); + pCur->aOverflow = 0; +} + +/* +** Invalidate the overflow page-list cache for all cursors opened +** on the shared btree structure pBt. +*/ +static void invalidateAllOverflowCache(BtShared *pBt){ + BtCursor *p; + assert( sqlite3_mutex_held(pBt->mutex) ); + for(p=pBt->pCursor; p; p=p->pNext){ + invalidateOverflowCache(p); + } +} +#else + #define invalidateOverflowCache(x) + #define invalidateAllOverflowCache(x) +#endif + +/* +** 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 ); + assert( cursorHoldsMutex(pCur) ); + + 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 = sqlite3Malloc(pCur->nKey); + if( pKey ){ + rc = sqlite3BtreeKey(pCur, 0, pCur->nKey, pKey); + if( rc==SQLITE_OK ){ + pCur->pKey = pKey; + }else{ + sqlite3_free(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; + } + + invalidateOverflowCache(pCur); + 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; + assert( sqlite3_mutex_held(pBt->mutex) ); + assert( pExcept==0 || pExcept->pBt==pBt ); + 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; +} + +/* +** Clear the current cursor position. +*/ +static void clearCursorPosition(BtCursor *pCur){ + assert( cursorHoldsMutex(pCur) ); + sqlite3_free(pCur->pKey); + pCur->pKey = 0; + pCur->eState = CURSOR_INVALID; +} + +/* +** 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 restoreCursorPosition() call after each +** saveCursorPosition(). +*/ +int sqlite3BtreeRestoreCursorPosition(BtCursor *pCur){ + int rc; + assert( cursorHoldsMutex(pCur) ); + assert( pCur->eState>=CURSOR_REQUIRESEEK ); + if( pCur->eState==CURSOR_FAULT ){ + return pCur->skip; + } + pCur->eState = CURSOR_INVALID; + rc = sqlite3BtreeMoveto(pCur, pCur->pKey, 0, pCur->nKey, 0, &pCur->skip); + if( rc==SQLITE_OK ){ + sqlite3_free(pCur->pKey); + pCur->pKey = 0; + assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID ); + } + return rc; +} + +#define restoreCursorPosition(p) \ + (p->eState>=CURSOR_REQUIRESEEK ? \ + sqlite3BtreeRestoreCursorPosition(p) : \ + SQLITE_OK) + +/* +** Determine whether or not a cursor has moved from the position it +** was last placed at. Cursor can move when the row they are pointing +** at is deleted out from under them. +** +** This routine returns an error code if something goes wrong. The +** integer *pHasMoved is set to one if the cursor has moved and 0 if not. +*/ +int sqlite3BtreeCursorHasMoved(BtCursor *pCur, int *pHasMoved){ + int rc; + + rc = restoreCursorPosition(pCur); + if( rc ){ + *pHasMoved = 1; + return rc; + } + if( pCur->eState!=CURSOR_VALID || pCur->skip!=0 ){ + *pHasMoved = 1; + }else{ + *pHasMoved = 0; + } + return SQLITE_OK; +} + +#ifndef SQLITE_OMIT_AUTOVACUUM +/* +** Given a page number of a regular database page, return the page +** number for the pointer-map page that contains the entry for the +** input page number. +*/ +static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){ + int nPagesPerMapPage, iPtrMap, ret; + assert( sqlite3_mutex_held(pBt->mutex) ); + nPagesPerMapPage = (pBt->usableSize/5)+1; + iPtrMap = (pgno-2)/nPagesPerMapPage; + ret = (iPtrMap*nPagesPerMapPage) + 2; + if( ret==PENDING_BYTE_PAGE(pBt) ){ + ret++; + } + return ret; +} + +/* +** Write an entry into the pointer map. +** +** This routine updates the pointer map entry for page number 'key' +** so that it maps to type 'eType' and parent page number 'pgno'. +** An error code is returned if something goes wrong, otherwise SQLITE_OK. +*/ +static int ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent){ + DbPage *pDbPage; /* The pointer map page */ + u8 *pPtrmap; /* The pointer map data */ + Pgno iPtrmap; /* The pointer map page number */ + int offset; /* Offset in pointer map page */ + int rc; + + assert( sqlite3_mutex_held(pBt->mutex) ); + /* The master-journal page number must never be used as a pointer map page */ + assert( 0==PTRMAP_ISPAGE(pBt, PENDING_BYTE_PAGE(pBt)) ); + + assert( pBt->autoVacuum ); + if( key==0 ){ + return SQLITE_CORRUPT_BKPT; + } + iPtrmap = PTRMAP_PAGENO(pBt, key); + rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage); + if( rc!=SQLITE_OK ){ + return rc; + } + offset = PTRMAP_PTROFFSET(iPtrmap, key); + pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage); + + if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){ + TRACE(("PTRMAP_UPDATE: %d->(%d,%d)\n", key, eType, parent)); + rc = sqlite3PagerWrite(pDbPage); + if( rc==SQLITE_OK ){ + pPtrmap[offset] = eType; + put4byte(&pPtrmap[offset+1], parent); + } + } + + sqlite3PagerUnref(pDbPage); + return rc; +} + +/* +** Read an entry from the pointer map. +** +** This routine retrieves the pointer map entry for page 'key', writing +** the type and parent page number to *pEType and *pPgno respectively. +** An error code is returned if something goes wrong, otherwise SQLITE_OK. +*/ +static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){ + DbPage *pDbPage; /* The pointer map page */ + int iPtrmap; /* Pointer map page index */ + u8 *pPtrmap; /* Pointer map page data */ + int offset; /* Offset of entry in pointer map */ + int rc; + + assert( sqlite3_mutex_held(pBt->mutex) ); + + iPtrmap = PTRMAP_PAGENO(pBt, key); + rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage); + if( rc!=0 ){ + return rc; + } + pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage); + + offset = PTRMAP_PTROFFSET(iPtrmap, key); + assert( pEType!=0 ); + *pEType = pPtrmap[offset]; + if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]); + + sqlite3PagerUnref(pDbPage); + if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_BKPT; + return SQLITE_OK; +} + +#else /* if defined SQLITE_OMIT_AUTOVACUUM */ + #define ptrmapPut(w,x,y,z) SQLITE_OK + #define ptrmapGet(w,x,y,z) SQLITE_OK + #define ptrmapPutOvfl(y,z) SQLITE_OK +#endif + +/* +** Given a btree page and a cell index (0 means the first cell on +** the page, 1 means the second cell, and so forth) return a pointer +** to the cell content. +** +** This routine works only for pages that do not contain overflow cells. +*/ +#define findCell(P,I) \ + ((P)->aData + ((P)->maskPage & get2byte(&(P)->aData[(P)->cellOffset+2*(I)]))) + +/* +** This a more complex version of findCell() that works for +** pages that do contain overflow cells. See insert +*/ +static u8 *findOverflowCell(MemPage *pPage, int iCell){ + int i; + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + for(i=pPage->nOverflow-1; i>=0; i--){ + int k; + struct _OvflCell *pOvfl; + pOvfl = &pPage->aOvfl[i]; + k = pOvfl->idx; + if( k<=iCell ){ + if( k==iCell ){ + return pOvfl->pCell; + } + iCell--; + } + } + return findCell(pPage, iCell); +} + +/* +** Parse a cell content block and fill in the CellInfo structure. There +** are two versions of this function. sqlite3BtreeParseCell() takes a +** cell index as the second argument and sqlite3BtreeParseCellPtr() +** takes a pointer to the body of the cell as its second argument. +** +** Within this file, the parseCell() macro can be called instead of +** sqlite3BtreeParseCellPtr(). Using some compilers, this will be faster. +*/ +void sqlite3BtreeParseCellPtr( + MemPage *pPage, /* Page containing the cell */ + u8 *pCell, /* Pointer to the cell text. */ + CellInfo *pInfo /* Fill in this structure */ +){ + int n; /* Number bytes in cell content header */ + u32 nPayload; /* Number of bytes of cell payload */ + + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + + pInfo->pCell = pCell; + assert( pPage->leaf==0 || pPage->leaf==1 ); + n = pPage->childPtrSize; + assert( n==4-4*pPage->leaf ); + if( pPage->intKey ){ + if( pPage->hasData ){ + n += getVarint32(&pCell[n], nPayload); + }else{ + nPayload = 0; + } + n += getVarint(&pCell[n], (u64*)&pInfo->nKey); + pInfo->nData = nPayload; + }else{ + pInfo->nData = 0; + n += getVarint32(&pCell[n], nPayload); + pInfo->nKey = nPayload; + } + pInfo->nPayload = nPayload; + pInfo->nHeader = n; + if( likely(nPayload<=pPage->maxLocal) ){ + /* This is the (easy) common case where the entire payload fits + ** on the local page. No overflow is required. + */ + int nSize; /* Total size of cell content in bytes */ + nSize = nPayload + n; + pInfo->nLocal = nPayload; + pInfo->iOverflow = 0; + if( (nSize & ~3)==0 ){ + nSize = 4; /* Minimum cell size is 4 */ + } + pInfo->nSize = nSize; + }else{ + /* If the payload will not fit completely on the local page, we have + ** to decide how much to store locally and how much to spill onto + ** overflow pages. The strategy is to minimize the amount of unused + ** space on overflow pages while keeping the amount of local storage + ** in between minLocal and maxLocal. + ** + ** Warning: changing the way overflow payload is distributed in any + ** way will result in an incompatible file format. + */ + int minLocal; /* Minimum amount of payload held locally */ + int maxLocal; /* Maximum amount of payload held locally */ + int surplus; /* Overflow payload available for local storage */ + + minLocal = pPage->minLocal; + maxLocal = pPage->maxLocal; + surplus = minLocal + (nPayload - minLocal)%(pPage->pBt->usableSize - 4); + if( surplus <= maxLocal ){ + pInfo->nLocal = surplus; + }else{ + pInfo->nLocal = minLocal; + } + pInfo->iOverflow = pInfo->nLocal + n; + pInfo->nSize = pInfo->iOverflow + 4; + } +} +#define parseCell(pPage, iCell, pInfo) \ + sqlite3BtreeParseCellPtr((pPage), findCell((pPage), (iCell)), (pInfo)) +void sqlite3BtreeParseCell( + MemPage *pPage, /* Page containing the cell */ + int iCell, /* The cell index. First cell is 0 */ + CellInfo *pInfo /* Fill in this structure */ +){ + parseCell(pPage, iCell, pInfo); +} + +/* +** Compute the total number of bytes that a Cell needs in the cell +** data area of the btree-page. The return number includes the cell +** data header and the local payload, but not any overflow page or +** the space used by the cell pointer. +*/ +#ifndef NDEBUG +static u16 cellSize(MemPage *pPage, int iCell){ + CellInfo info; + sqlite3BtreeParseCell(pPage, iCell, &info); + return info.nSize; +} +#endif +static u16 cellSizePtr(MemPage *pPage, u8 *pCell){ + CellInfo info; + sqlite3BtreeParseCellPtr(pPage, pCell, &info); + return info.nSize; +} + +#ifndef SQLITE_OMIT_AUTOVACUUM +/* +** If the cell pCell, part of page pPage contains a pointer +** to an overflow page, insert an entry into the pointer-map +** for the overflow page. +*/ +static int ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell){ + CellInfo info; + assert( pCell!=0 ); + sqlite3BtreeParseCellPtr(pPage, pCell, &info); + assert( (info.nData+(pPage->intKey?0:info.nKey))==info.nPayload ); + if( (info.nData+(pPage->intKey?0:info.nKey))>info.nLocal ){ + Pgno ovfl = get4byte(&pCell[info.iOverflow]); + return ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno); + } + return SQLITE_OK; +} +/* +** If the cell with index iCell on page pPage contains a pointer +** to an overflow page, insert an entry into the pointer-map +** for the overflow page. +*/ +static int ptrmapPutOvfl(MemPage *pPage, int iCell){ + u8 *pCell; + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + pCell = findOverflowCell(pPage, iCell); + return ptrmapPutOvflPtr(pPage, pCell); +} +#endif + + +/* +** Defragment the page given. All Cells are moved to the +** 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 void defragmentPage(MemPage *pPage){ + int i; /* Loop counter */ + int pc; /* Address of a i-th cell */ + int addr; /* Offset of first byte after cell pointer array */ + int hdr; /* Offset to the page header */ + int size; /* Size of a cell */ + int usableSize; /* Number of usable bytes on a page */ + int cellOffset; /* Offset to the cell pointer array */ + int brk; /* Offset to the cell content area */ + int nCell; /* Number of cells on the page */ + unsigned char *data; /* The page data */ + unsigned char *temp; /* Temp area for cell content */ + + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + assert( pPage->pBt!=0 ); + assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE ); + assert( pPage->nOverflow==0 ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + temp = sqlite3PagerTempSpace(pPage->pBt->pPager); + data = pPage->aData; + hdr = pPage->hdrOffset; + cellOffset = pPage->cellOffset; + nCell = pPage->nCell; + assert( nCell==get2byte(&data[hdr+3]) ); + usableSize = pPage->pBt->usableSize; + brk = get2byte(&data[hdr+5]); + memcpy(&temp[brk], &data[brk], usableSize - brk); + brk = usableSize; + for(i=0; i<nCell; i++){ + u8 *pAddr; /* The i-th cell pointer */ + pAddr = &data[cellOffset + i*2]; + pc = get2byte(pAddr); + assert( pc<pPage->pBt->usableSize ); + size = cellSizePtr(pPage, &temp[pc]); + brk -= size; + memcpy(&data[brk], &temp[pc], size); + put2byte(pAddr, brk); + } + assert( brk>=cellOffset+2*nCell ); + put2byte(&data[hdr+5], brk); + data[hdr+1] = 0; + data[hdr+2] = 0; + data[hdr+7] = 0; + addr = cellOffset+2*nCell; + memset(&data[addr], 0, brk-addr); +} + +/* +** Allocate nByte bytes of space on a page. +** +** Return the index into pPage->aData[] of the first byte of +** the new allocation. The caller guarantees that there is enough +** space. This routine will never fail. +** +** If the page contains nBytes of free space but does not contain +** nBytes of contiguous free space, then this routine automatically +** calls defragementPage() to consolidate all free space before +** allocating the new chunk. +*/ +static int allocateSpace(MemPage *pPage, int nByte){ + int addr, pc, hdr; + int size; + int nFrag; + int top; + int nCell; + int cellOffset; + unsigned char *data; + + data = pPage->aData; + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + assert( pPage->pBt ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + assert( nByte>=0 ); /* Minimum cell size is 4 */ + assert( pPage->nFree>=nByte ); + assert( pPage->nOverflow==0 ); + pPage->nFree -= nByte; + hdr = pPage->hdrOffset; + + nFrag = data[hdr+7]; + if( nFrag<60 ){ + /* Search the freelist looking for a slot big enough to satisfy the + ** space request. */ + addr = hdr+1; + while( (pc = get2byte(&data[addr]))>0 ){ + size = get2byte(&data[pc+2]); + if( size>=nByte ){ + if( size<nByte+4 ){ + memcpy(&data[addr], &data[pc], 2); + data[hdr+7] = nFrag + size - nByte; + return pc; + }else{ + put2byte(&data[pc+2], size-nByte); + return pc + size - nByte; + } + } + addr = pc; + } + } + + /* Allocate memory from the gap in between the cell pointer array + ** and the cell content area. + */ + top = get2byte(&data[hdr+5]); + nCell = get2byte(&data[hdr+3]); + cellOffset = pPage->cellOffset; + if( nFrag>=60 || cellOffset + 2*nCell > top - nByte ){ + defragmentPage(pPage); + top = get2byte(&data[hdr+5]); + } + top -= nByte; + assert( cellOffset + 2*nCell <= top ); + put2byte(&data[hdr+5], top); + return top; +} + +/* +** Return a section of the pPage->aData to the freelist. +** The first byte of the new free block is pPage->aDisk[start] +** and the size of the block is "size" bytes. +** +** Most of the effort here is involved in coalesing adjacent +** free blocks into a single big free block. +*/ +static void freeSpace(MemPage *pPage, int start, int size){ + int addr, pbegin, hdr; + unsigned char *data = pPage->aData; + + assert( pPage->pBt!=0 ); + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + assert( start>=pPage->hdrOffset+6+(pPage->leaf?0:4) ); + assert( (start + size)<=pPage->pBt->usableSize ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + assert( size>=0 ); /* Minimum cell size is 4 */ + +#ifdef SQLITE_SECURE_DELETE + /* Overwrite deleted information with zeros when the SECURE_DELETE + ** option is enabled at compile-time */ + memset(&data[start], 0, size); +#endif + + /* Add the space back into the linked list of freeblocks */ + hdr = pPage->hdrOffset; + addr = hdr + 1; + while( (pbegin = get2byte(&data[addr]))<start && pbegin>0 ){ + assert( pbegin<=pPage->pBt->usableSize-4 ); + assert( pbegin>addr ); + addr = pbegin; + } + assert( pbegin<=pPage->pBt->usableSize-4 ); + assert( pbegin>addr || pbegin==0 ); + put2byte(&data[addr], start); + put2byte(&data[start], pbegin); + put2byte(&data[start+2], size); + pPage->nFree += size; + + /* Coalesce adjacent free blocks */ + addr = pPage->hdrOffset + 1; + while( (pbegin = get2byte(&data[addr]))>0 ){ + int pnext, psize; + assert( pbegin>addr ); + assert( pbegin<=pPage->pBt->usableSize-4 ); + pnext = get2byte(&data[pbegin]); + psize = get2byte(&data[pbegin+2]); + if( pbegin + psize + 3 >= pnext && pnext>0 ){ + int frag = pnext - (pbegin+psize); + assert( frag<=data[pPage->hdrOffset+7] ); + data[pPage->hdrOffset+7] -= frag; + put2byte(&data[pbegin], get2byte(&data[pnext])); + put2byte(&data[pbegin+2], pnext+get2byte(&data[pnext+2])-pbegin); + }else{ + addr = pbegin; + } + } + + /* If the cell content area begins with a freeblock, remove it. */ + if( data[hdr+1]==data[hdr+5] && data[hdr+2]==data[hdr+6] ){ + int top; + pbegin = get2byte(&data[hdr+1]); + memcpy(&data[hdr+1], &data[pbegin], 2); + top = get2byte(&data[hdr+5]); + put2byte(&data[hdr+5], top + get2byte(&data[pbegin+2])); + } +} + +/* +** Decode the flags byte (the first byte of the header) for a page +** and initialize fields of the MemPage structure accordingly. +** +** Only the following combinations are supported. Anything different +** indicates a corrupt database files: +** +** PTF_ZERODATA +** PTF_ZERODATA | PTF_LEAF +** PTF_LEAFDATA | PTF_INTKEY +** PTF_LEAFDATA | PTF_INTKEY | PTF_LEAF +*/ +static int decodeFlags(MemPage *pPage, int flagByte){ + BtShared *pBt; /* A copy of pPage->pBt */ + + assert( pPage->hdrOffset==(pPage->pgno==1 ? 100 : 0) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + pPage->leaf = flagByte>>3; assert( PTF_LEAF == 1<<3 ); + flagByte &= ~PTF_LEAF; + pPage->childPtrSize = 4-4*pPage->leaf; + pBt = pPage->pBt; + if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){ + pPage->intKey = 1; + pPage->hasData = pPage->leaf; + pPage->maxLocal = pBt->maxLeaf; + pPage->minLocal = pBt->minLeaf; + }else if( flagByte==PTF_ZERODATA ){ + pPage->intKey = 0; + pPage->hasData = 0; + pPage->maxLocal = pBt->maxLocal; + pPage->minLocal = pBt->minLocal; + }else{ + return SQLITE_CORRUPT_BKPT; + } + return SQLITE_OK; +} + +/* +** Initialize the auxiliary information for a disk block. +** +** The pParent parameter must be a pointer to the MemPage which +** is the parent of the page being initialized. The root of a +** BTree has no parent and so for that page, pParent==NULL. +** +** Return SQLITE_OK on success. If we see that the page does +** not contain a well-formed database page, then return +** SQLITE_CORRUPT. Note that a return of SQLITE_OK does not +** guarantee that the page is well-formed. It only shows that +** we failed to detect any corruption. +*/ +int sqlite3BtreeInitPage( + MemPage *pPage, /* The page to be initialized */ + MemPage *pParent /* The parent. Might be NULL */ +){ + int pc; /* Address of a freeblock within pPage->aData[] */ + int hdr; /* Offset to beginning of page header */ + u8 *data; /* Equal to pPage->aData */ + 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 */ + int top; /* First byte of the cell content area */ + + pBt = pPage->pBt; + assert( pBt!=0 ); + assert( pParent==0 || pParent->pBt==pBt ); + assert( sqlite3_mutex_held(pBt->mutex) ); + assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); + assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) ); + assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) ); + if( pPage->pParent!=pParent && (pPage->pParent!=0 || pPage->isInit) ){ + /* The parent page should never change unless the file is corrupt */ + return SQLITE_CORRUPT_BKPT; + } + if( pPage->isInit ) return SQLITE_OK; + if( pPage->pParent==0 && pParent!=0 ){ + pPage->pParent = pParent; + sqlite3PagerRef(pParent->pDbPage); + } + hdr = pPage->hdrOffset; + data = pPage->aData; + if( decodeFlags(pPage, data[hdr]) ) return SQLITE_CORRUPT_BKPT; + assert( pBt->pageSize>=512 && pBt->pageSize<=32768 ); + pPage->maskPage = pBt->pageSize - 1; + pPage->nOverflow = 0; + pPage->idxShift = 0; + usableSize = pBt->usableSize; + pPage->cellOffset = cellOffset = hdr + 12 - 4*pPage->leaf; + top = get2byte(&data[hdr+5]); + pPage->nCell = get2byte(&data[hdr+3]); + if( pPage->nCell>MX_CELL(pBt) ){ + /* To many cells for a single page. The page must be corrupt */ + return SQLITE_CORRUPT_BKPT; + } + if( pPage->nCell==0 && pParent!=0 && pParent->pgno!=1 ){ + /* All pages must have at least one cell, except for root pages */ + return SQLITE_CORRUPT_BKPT; + } + + /* Compute the total free space on the page */ + pc = get2byte(&data[hdr+1]); + nFree = data[hdr+7] + top - (cellOffset + 2*pPage->nCell); + while( pc>0 ){ + int next, size; + if( pc>usableSize-4 ){ + /* Free block is off the page */ + return SQLITE_CORRUPT_BKPT; + } + next = get2byte(&data[pc]); + size = get2byte(&data[pc+2]); + if( next>0 && next<=pc+size+3 ){ + /* Free blocks must be in accending order */ + return SQLITE_CORRUPT_BKPT; + } + nFree += size; + pc = next; + } + pPage->nFree = nFree; + if( nFree>=usableSize ){ + /* Free space cannot exceed total page size */ + return SQLITE_CORRUPT_BKPT; + } + +#if 0 + /* Check that all the offsets in the cell offset array are within range. + ** + ** Omitting this consistency check and using the pPage->maskPage mask + ** to prevent overrunning the page buffer in findCell() results in a + ** 2.5% performance gain. + */ + { + u8 *pOff; /* Iterator used to check all cell offsets are in range */ + u8 *pEnd; /* Pointer to end of cell offset array */ + u8 mask; /* Mask of bits that must be zero in MSB of cell offsets */ + mask = ~(((u8)(pBt->pageSize>>8))-1); + pEnd = &data[cellOffset + pPage->nCell*2]; + for(pOff=&data[cellOffset]; pOff!=pEnd && !((*pOff)&mask); pOff+=2); + if( pOff!=pEnd ){ + return SQLITE_CORRUPT_BKPT; + } + } +#endif + + pPage->isInit = 1; + return SQLITE_OK; +} + +/* +** Set up a raw page so that it looks like a database page holding +** no entries. +*/ +static void zeroPage(MemPage *pPage, int flags){ + unsigned char *data = pPage->aData; + BtShared *pBt = pPage->pBt; + int hdr = pPage->hdrOffset; + int first; + + assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno ); + assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); + assert( sqlite3PagerGetData(pPage->pDbPage) == data ); + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + assert( sqlite3_mutex_held(pBt->mutex) ); + /*memset(&data[hdr], 0, pBt->usableSize - hdr);*/ + data[hdr] = flags; + first = hdr + 8 + 4*((flags&PTF_LEAF)==0); + memset(&data[hdr+1], 0, 4); + data[hdr+7] = 0; + put2byte(&data[hdr+5], pBt->usableSize); + pPage->nFree = pBt->usableSize - first; + decodeFlags(pPage, flags); + pPage->hdrOffset = hdr; + pPage->cellOffset = first; + pPage->nOverflow = 0; + assert( pBt->pageSize>=512 && pBt->pageSize<=32768 ); + pPage->maskPage = pBt->pageSize - 1; + pPage->idxShift = 0; + pPage->nCell = 0; + pPage->isInit = 1; +} + +/* +** Get a page from the pager. Initialize the MemPage.pBt and +** MemPage.aData elements if needed. +** +** If the noContent flag is set, it means that we do not care about +** the content of the page at this time. So do not go to the disk +** to fetch the content. Just fill in the content with zeros for now. +** If in the future we call sqlite3PagerWrite() on this page, that +** means we have started to be concerned about content and the disk +** read should occur at that point. +*/ +int sqlite3BtreeGetPage( + BtShared *pBt, /* The btree */ + Pgno pgno, /* Number of the page to fetch */ + MemPage **ppPage, /* Return the page in this parameter */ + int noContent /* Do not load page content if true */ +){ + int rc; + MemPage *pPage; + DbPage *pDbPage; + + assert( sqlite3_mutex_held(pBt->mutex) ); + rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, noContent); + if( rc ) return rc; + pPage = (MemPage *)sqlite3PagerGetExtra(pDbPage); + pPage->aData = sqlite3PagerGetData(pDbPage); + pPage->pDbPage = pDbPage; + pPage->pBt = pBt; + pPage->pgno = pgno; + pPage->hdrOffset = pPage->pgno==1 ? 100 : 0; + *ppPage = pPage; + return SQLITE_OK; +} + +/* +** Get a page from the pager and initialize it. This routine +** is just a convenience wrapper around separate calls to +** sqlite3BtreeGetPage() and sqlite3BtreeInitPage(). +*/ +static int getAndInitPage( + 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 */ +){ + int rc; + assert( sqlite3_mutex_held(pBt->mutex) ); + if( pgno==0 ){ + return SQLITE_CORRUPT_BKPT; + } + rc = sqlite3BtreeGetPage(pBt, pgno, ppPage, 0); + if( rc==SQLITE_OK && (*ppPage)->isInit==0 ){ + rc = sqlite3BtreeInitPage(*ppPage, pParent); + if( rc!=SQLITE_OK ){ + releasePage(*ppPage); + *ppPage = 0; + } + } + return rc; +} + +/* +** Release a MemPage. This should be called once for each prior +** call to sqlite3BtreeGetPage. +*/ +static void releasePage(MemPage *pPage){ + if( pPage ){ + assert( pPage->aData ); + assert( pPage->pBt ); + assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); + assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + sqlite3PagerUnref(pPage->pDbPage); + } +} + +/* +** This routine is called when the reference count for a page +** reaches zero. We need to unref the pParent pointer when that +** happens. +*/ +static void pageDestructor(DbPage *pData, int pageSize){ + MemPage *pPage; + assert( (pageSize & 7)==0 ); + pPage = (MemPage *)sqlite3PagerGetExtra(pData); + assert( pPage->isInit==0 || sqlite3_mutex_held(pPage->pBt->mutex) ); + if( pPage->pParent ){ + MemPage *pParent = pPage->pParent; + assert( pParent->pBt==pPage->pBt ); + pPage->pParent = 0; + releasePage(pParent); + } + pPage->isInit = 0; +} + +/* +** During a rollback, when the pager reloads information into the cache +** so that the cache is restored to its original state at the start of +** the transaction, for each page restored this routine is called. +** +** This routine needs to reset the extra data section at the end of the +** page to agree with the restored data. +*/ +static void pageReinit(DbPage *pData, int pageSize){ + MemPage *pPage; + assert( (pageSize & 7)==0 ); + pPage = (MemPage *)sqlite3PagerGetExtra(pData); + if( pPage->isInit ){ + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + pPage->isInit = 0; + sqlite3BtreeInitPage(pPage, pPage->pParent); + } +} + +/* +** Invoke the busy handler for a btree. +*/ +static int sqlite3BtreeInvokeBusyHandler(void *pArg, int n){ + BtShared *pBt = (BtShared*)pArg; + assert( pBt->db ); + assert( sqlite3_mutex_held(pBt->db->mutex) ); + return sqlite3InvokeBusyHandler(&pBt->db->busyHandler); +} + +/* +** Open a database file. +** +** zFilename is the name of the database file. If zFilename is NULL +** a new database with a random name is created. This randomly named +** database file will be deleted when sqlite3BtreeClose() is called. +** If zFilename is ":memory:" then an in-memory database is created +** that is automatically destroyed when it is closed. +*/ +int sqlite3BtreeOpen( + const char *zFilename, /* Name of the file containing the BTree database */ + sqlite3 *db, /* Associated database handle */ + Btree **ppBtree, /* Pointer to new Btree object written here */ + int flags, /* Options */ + int vfsFlags /* Flags passed through to sqlite3_vfs.xOpen() */ +){ + sqlite3_vfs *pVfs; /* The VFS to use for this btree */ + BtShared *pBt = 0; /* Shared part of btree structure */ + Btree *p; /* Handle to return */ + int rc = SQLITE_OK; + int nReserve; + unsigned char zDbHeader[100]; + + /* 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 = 0; + #else + const int isMemdb = zFilename && !strcmp(zFilename, ":memory:"); + #endif +#endif + + assert( db!=0 ); + assert( sqlite3_mutex_held(db->mutex) ); + + pVfs = db->pVfs; + p = sqlite3MallocZero(sizeof(Btree)); + if( !p ){ + return SQLITE_NOMEM; + } + p->inTrans = TRANS_NONE; + p->db = db; + +#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) + /* + ** If this Btree is a candidate for shared cache, try to find an + ** existing BtShared object that we can share with + */ + if( isMemdb==0 + && (db->flags & SQLITE_Vtab)==0 + && zFilename && zFilename[0] + ){ + if( sqlite3SharedCacheEnabled ){ + int nFullPathname = pVfs->mxPathname+1; + char *zFullPathname = sqlite3Malloc(nFullPathname); + sqlite3_mutex *mutexShared; + p->sharable = 1; + db->flags |= SQLITE_SharedCache; + if( !zFullPathname ){ + sqlite3_free(p); + return SQLITE_NOMEM; + } + sqlite3OsFullPathname(pVfs, zFilename, nFullPathname, zFullPathname); + mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); + sqlite3_mutex_enter(mutexShared); + for(pBt=sqlite3SharedCacheList; pBt; pBt=pBt->pNext){ + assert( pBt->nRef>0 ); + if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager)) + && sqlite3PagerVfs(pBt->pPager)==pVfs ){ + p->pBt = pBt; + pBt->nRef++; + break; + } + } + sqlite3_mutex_leave(mutexShared); + sqlite3_free(zFullPathname); + } +#ifdef SQLITE_DEBUG + else{ + /* In debug mode, we mark all persistent databases as sharable + ** even when they are not. This exercises the locking code and + ** gives more opportunity for asserts(sqlite3_mutex_held()) + ** statements to find locking problems. + */ + p->sharable = 1; + } +#endif + } +#endif + if( pBt==0 ){ + /* + ** The following asserts make sure that structures used by the btree are + ** the right size. This is to guard against size changes that result + ** when compiling on a different architecture. + */ + assert( sizeof(i64)==8 || sizeof(i64)==4 ); + assert( sizeof(u64)==8 || sizeof(u64)==4 ); + assert( sizeof(u32)==4 ); + assert( sizeof(u16)==2 ); + assert( sizeof(Pgno)==4 ); + + pBt = sqlite3MallocZero( sizeof(*pBt) ); + if( pBt==0 ){ + rc = SQLITE_NOMEM; + goto btree_open_out; + } + pBt->busyHdr.xFunc = sqlite3BtreeInvokeBusyHandler; + pBt->busyHdr.pArg = pBt; + rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename, + EXTRA_SIZE, flags, vfsFlags); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader); + } + if( rc!=SQLITE_OK ){ + goto btree_open_out; + } + sqlite3PagerSetBusyhandler(pBt->pPager, &pBt->busyHdr); + p->pBt = pBt; + + sqlite3PagerSetDestructor(pBt->pPager, pageDestructor); + sqlite3PagerSetReiniter(pBt->pPager, pageReinit); + pBt->pCursor = 0; + pBt->pPage1 = 0; + pBt->readOnly = sqlite3PagerIsreadonly(pBt->pPager); + pBt->pageSize = get2byte(&zDbHeader[16]); + if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE + || ((pBt->pageSize-1)&pBt->pageSize)!=0 ){ + pBt->pageSize = 0; + sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize); +#ifndef SQLITE_OMIT_AUTOVACUUM + /* If the magic name ":memory:" will create an in-memory database, then + ** leave the autoVacuum mode at 0 (do not auto-vacuum), even if + ** SQLITE_DEFAULT_AUTOVACUUM is true. On the other hand, if + ** SQLITE_OMIT_MEMORYDB has been defined, then ":memory:" is just a + ** regular file-name. In this case the auto-vacuum applies as per normal. + */ + if( zFilename && !isMemdb ){ + pBt->autoVacuum = (SQLITE_DEFAULT_AUTOVACUUM ? 1 : 0); + pBt->incrVacuum = (SQLITE_DEFAULT_AUTOVACUUM==2 ? 1 : 0); + } +#endif + nReserve = 0; + }else{ + nReserve = zDbHeader[20]; + pBt->pageSizeFixed = 1; +#ifndef SQLITE_OMIT_AUTOVACUUM + pBt->autoVacuum = (get4byte(&zDbHeader[36 + 4*4])?1:0); + pBt->incrVacuum = (get4byte(&zDbHeader[36 + 7*4])?1:0); +#endif + } + pBt->usableSize = pBt->pageSize - nReserve; + assert( (pBt->pageSize & 7)==0 ); /* 8-byte alignment of pageSize */ + sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize); + +#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) + /* Add the new BtShared object to the linked list sharable BtShareds. + */ + if( p->sharable ){ + sqlite3_mutex *mutexShared; + pBt->nRef = 1; + mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); + if( SQLITE_THREADSAFE && sqlite3Config.bCoreMutex ){ + pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST); + if( pBt->mutex==0 ){ + rc = SQLITE_NOMEM; + db->mallocFailed = 0; + goto btree_open_out; + } + } + sqlite3_mutex_enter(mutexShared); + pBt->pNext = sqlite3SharedCacheList; + sqlite3SharedCacheList = pBt; + sqlite3_mutex_leave(mutexShared); + } +#endif + } + +#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) + /* If the new Btree uses a sharable pBtShared, then link the new + ** Btree into the list of all sharable Btrees for the same connection. + ** The list is kept in ascending order by pBt address. + */ + if( p->sharable ){ + int i; + Btree *pSib; + for(i=0; i<db->nDb; i++){ + if( (pSib = db->aDb[i].pBt)!=0 && pSib->sharable ){ + while( pSib->pPrev ){ pSib = pSib->pPrev; } + if( p->pBt<pSib->pBt ){ + p->pNext = pSib; + p->pPrev = 0; + pSib->pPrev = p; + }else{ + while( pSib->pNext && pSib->pNext->pBt<p->pBt ){ + pSib = pSib->pNext; + } + p->pNext = pSib->pNext; + p->pPrev = pSib; + if( p->pNext ){ + p->pNext->pPrev = p; + } + pSib->pNext = p; + } + break; + } + } + } +#endif + *ppBtree = p; + +btree_open_out: + if( rc!=SQLITE_OK ){ + if( pBt && pBt->pPager ){ + sqlite3PagerClose(pBt->pPager); + } + sqlite3_free(pBt); + sqlite3_free(p); + *ppBtree = 0; + } + return rc; +} + +/* +** Decrement the BtShared.nRef counter. When it reaches zero, +** remove the BtShared structure from the sharing list. Return +** true if the BtShared.nRef counter reaches zero and return +** false if it is still positive. +*/ +static int removeFromSharingList(BtShared *pBt){ +#ifndef SQLITE_OMIT_SHARED_CACHE + sqlite3_mutex *pMaster; + BtShared *pList; + int removed = 0; + + assert( sqlite3_mutex_notheld(pBt->mutex) ); + pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); + sqlite3_mutex_enter(pMaster); + pBt->nRef--; + if( pBt->nRef<=0 ){ + if( sqlite3SharedCacheList==pBt ){ + sqlite3SharedCacheList = pBt->pNext; + }else{ + pList = sqlite3SharedCacheList; + while( ALWAYS(pList) && pList->pNext!=pBt ){ + pList=pList->pNext; + } + if( ALWAYS(pList) ){ + pList->pNext = pBt->pNext; + } + } + if( SQLITE_THREADSAFE ){ + sqlite3_mutex_free(pBt->mutex); + } + removed = 1; + } + sqlite3_mutex_leave(pMaster); + return removed; +#else + return 1; +#endif +} + +/* +** Make sure pBt->pTmpSpace points to an allocation of +** MX_CELL_SIZE(pBt) bytes. +*/ +static void allocateTempSpace(BtShared *pBt){ + if( !pBt->pTmpSpace ){ + pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize ); + } +} + +/* +** Free the pBt->pTmpSpace allocation +*/ +static void freeTempSpace(BtShared *pBt){ + sqlite3PageFree( pBt->pTmpSpace); + pBt->pTmpSpace = 0; +} + +/* +** Close an open database and invalidate all cursors. +*/ +int sqlite3BtreeClose(Btree *p){ + BtShared *pBt = p->pBt; + BtCursor *pCur; + + /* Close all cursors opened via this handle. */ + assert( sqlite3_mutex_held(p->db->mutex) ); + sqlite3BtreeEnter(p); + pBt->db = p->db; + 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); + sqlite3BtreeLeave(p); + + /* 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( p->wantToLock==0 && p->locked==0 ); + if( !p->sharable || removeFromSharingList(pBt) ){ + /* The pBt is no longer on the sharing list, so we can access + ** it without having to hold the mutex. + ** + ** Clean out and delete the BtShared object. + */ + assert( !pBt->pCursor ); + sqlite3PagerClose(pBt->pPager); + if( pBt->xFreeSchema && pBt->pSchema ){ + pBt->xFreeSchema(pBt->pSchema); + } + sqlite3_free(pBt->pSchema); + freeTempSpace(pBt); + sqlite3_free(pBt); + } + +#ifndef SQLITE_OMIT_SHARED_CACHE + assert( p->wantToLock==0 ); + assert( p->locked==0 ); + if( p->pPrev ) p->pPrev->pNext = p->pNext; + if( p->pNext ) p->pNext->pPrev = p->pPrev; +#endif + + sqlite3_free(p); + return SQLITE_OK; +} + +/* +** Change the limit on the number of pages allowed in the cache. +** +** The maximum number of cache pages is set to the absolute +** value of mxPage. If mxPage is negative, the pager will +** operate asynchronously - it will not stop to do fsync()s +** to insure data is written to the disk surface before +** continuing. Transactions still work if synchronous is off, +** and the database cannot be corrupted if this program +** crashes. But if the operating system crashes or there is +** an abrupt power failure when synchronous is off, the database +** could be left in an inconsistent and unrecoverable state. +** Synchronous is on by default so database corruption is not +** normally a worry. +*/ +int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){ + BtShared *pBt = p->pBt; + assert( sqlite3_mutex_held(p->db->mutex) ); + sqlite3BtreeEnter(p); + sqlite3PagerSetCachesize(pBt->pPager, mxPage); + sqlite3BtreeLeave(p); + return SQLITE_OK; +} + +/* +** Change the way data is synced to disk in order to increase or decrease +** how well the database resists damage due to OS crashes and power +** failures. Level 1 is the same as asynchronous (no syncs() occur and +** there is a high probability of damage) Level 2 is the default. There +** is a very low but non-zero probability of damage. Level 3 reduces the +** probability of damage to near zero but with a write performance reduction. +*/ +#ifndef SQLITE_OMIT_PAGER_PRAGMAS +int sqlite3BtreeSetSafetyLevel(Btree *p, int level, int fullSync){ + BtShared *pBt = p->pBt; + assert( sqlite3_mutex_held(p->db->mutex) ); + sqlite3BtreeEnter(p); + sqlite3PagerSetSafetyLevel(pBt->pPager, level, fullSync); + sqlite3BtreeLeave(p); + return SQLITE_OK; +} +#endif + +/* +** 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 *p){ + BtShared *pBt = p->pBt; + int rc; + assert( sqlite3_mutex_held(p->db->mutex) ); + sqlite3BtreeEnter(p); + assert( pBt && pBt->pPager ); + rc = sqlite3PagerNosync(pBt->pPager); + sqlite3BtreeLeave(p); + return rc; +} + +#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) +/* +** Change the default pages size and the number of reserved bytes per page. +** +** The page size must be a power of 2 between 512 and 65536. If the page +** size supplied does not meet this constraint then the page size is not +** changed. +** +** Page sizes are constrained to be a power of two so that the region +** of the database file used for locking (beginning at PENDING_BYTE, +** the first byte past the 1GB boundary, 0x40000000) needs to occur +** at the beginning of a page. +** +** If parameter nReserve is less than zero, then the number of reserved +** bytes per page is left unchanged. +*/ +int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve){ + int rc = SQLITE_OK; + BtShared *pBt = p->pBt; + sqlite3BtreeEnter(p); + if( pBt->pageSizeFixed ){ + sqlite3BtreeLeave(p); + return SQLITE_READONLY; + } + if( nReserve<0 ){ + nReserve = pBt->pageSize - pBt->usableSize; + } + if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE && + ((pageSize-1)&pageSize)==0 ){ + assert( (pageSize & 7)==0 ); + assert( !pBt->pPage1 && !pBt->pCursor ); + pBt->pageSize = pageSize; + freeTempSpace(pBt); + rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize); + } + pBt->usableSize = pBt->pageSize - nReserve; + sqlite3BtreeLeave(p); + return rc; +} + +/* +** Return the currently defined page size +*/ +int sqlite3BtreeGetPageSize(Btree *p){ + return p->pBt->pageSize; +} +int sqlite3BtreeGetReserve(Btree *p){ + int n; + sqlite3BtreeEnter(p); + n = p->pBt->pageSize - p->pBt->usableSize; + sqlite3BtreeLeave(p); + return n; +} + +/* +** Set the maximum page count for a database if mxPage is positive. +** No changes are made if mxPage is 0 or negative. +** Regardless of the value of mxPage, return the maximum page count. +*/ +int sqlite3BtreeMaxPageCount(Btree *p, int mxPage){ + int n; + sqlite3BtreeEnter(p); + n = sqlite3PagerMaxPageCount(p->pBt->pPager, mxPage); + sqlite3BtreeLeave(p); + return n; +} +#endif /* !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) */ + +/* +** Change the 'auto-vacuum' property of the database. If the 'autoVacuum' +** parameter is non-zero, then auto-vacuum mode is enabled. If zero, it +** is disabled. The default value for the auto-vacuum property is +** determined by the SQLITE_DEFAULT_AUTOVACUUM macro. +*/ +int sqlite3BtreeSetAutoVacuum(Btree *p, int autoVacuum){ +#ifdef SQLITE_OMIT_AUTOVACUUM + return SQLITE_READONLY; +#else + BtShared *pBt = p->pBt; + int rc = SQLITE_OK; + int av = (autoVacuum?1:0); + + sqlite3BtreeEnter(p); + if( pBt->pageSizeFixed && av!=pBt->autoVacuum ){ + rc = SQLITE_READONLY; + }else{ + pBt->autoVacuum = av; + } + sqlite3BtreeLeave(p); + return rc; +#endif +} + +/* +** Return the value of the 'auto-vacuum' property. If auto-vacuum is +** enabled 1 is returned. Otherwise 0. +*/ +int sqlite3BtreeGetAutoVacuum(Btree *p){ +#ifdef SQLITE_OMIT_AUTOVACUUM + return BTREE_AUTOVACUUM_NONE; +#else + int rc; + sqlite3BtreeEnter(p); + rc = ( + (!p->pBt->autoVacuum)?BTREE_AUTOVACUUM_NONE: + (!p->pBt->incrVacuum)?BTREE_AUTOVACUUM_FULL: + BTREE_AUTOVACUUM_INCR + ); + sqlite3BtreeLeave(p); + return rc; +#endif +} + + +/* +** Get a reference to pPage1 of the database file. This will +** also acquire a readlock on that file. +** +** SQLITE_OK is returned on success. If the file is not a +** well-formed database file, then SQLITE_CORRUPT is returned. +** SQLITE_BUSY is returned if the database is locked. SQLITE_NOMEM +** is returned if we run out of memory. +*/ +static int lockBtree(BtShared *pBt){ + int rc; + MemPage *pPage1; + int nPage; + + assert( sqlite3_mutex_held(pBt->mutex) ); + if( pBt->pPage1 ) return SQLITE_OK; + rc = sqlite3BtreeGetPage(pBt, 1, &pPage1, 0); + if( rc!=SQLITE_OK ) return rc; + + /* Do some checking to help insure the file we opened really is + ** a valid database file. + */ + rc = sqlite3PagerPagecount(pBt->pPager, &nPage); + if( rc!=SQLITE_OK ){ + goto page1_init_failed; + }else if( nPage>0 ){ + int pageSize; + int usableSize; + u8 *page1 = pPage1->aData; + rc = SQLITE_NOTADB; + if( memcmp(page1, zMagicHeader, 16)!=0 ){ + goto page1_init_failed; + } + if( page1[18]>1 ){ + pBt->readOnly = 1; + } + if( page1[19]>1 ){ + goto page1_init_failed; + } + + /* The maximum embedded fraction must be exactly 25%. And the minimum + ** embedded fraction must be 12.5% for both leaf-data and non-leaf-data. + ** The original design allowed these amounts to vary, but as of + ** version 3.6.0, we require them to be fixed. + */ + if( memcmp(&page1[21], "\100\040\040",3)!=0 ){ + goto page1_init_failed; + } + pageSize = get2byte(&page1[16]); + if( ((pageSize-1)&pageSize)!=0 || pageSize<512 || + (SQLITE_MAX_PAGE_SIZE<32768 && pageSize>SQLITE_MAX_PAGE_SIZE) + ){ + goto page1_init_failed; + } + assert( (pageSize & 7)==0 ); + usableSize = pageSize - page1[20]; + if( pageSize!=pBt->pageSize ){ + /* After reading the first page of the database assuming a page size + ** of BtShared.pageSize, we have discovered that the page-size is + ** actually pageSize. Unlock the database, leave pBt->pPage1 at + ** zero and return SQLITE_OK. The caller will call this function + ** again with the correct page-size. + */ + releasePage(pPage1); + pBt->usableSize = usableSize; + pBt->pageSize = pageSize; + freeTempSpace(pBt); + sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize); + return SQLITE_OK; + } + if( usableSize<500 ){ + goto page1_init_failed; + } + pBt->pageSize = pageSize; + pBt->usableSize = usableSize; +#ifndef SQLITE_OMIT_AUTOVACUUM + pBt->autoVacuum = (get4byte(&page1[36 + 4*4])?1:0); + pBt->incrVacuum = (get4byte(&page1[36 + 7*4])?1:0); +#endif + } + + /* maxLocal is the maximum amount of payload to store locally for + ** a cell. Make sure it is small enough so that at least minFanout + ** cells can will fit on one page. We assume a 10-byte page header. + ** Besides the payload, the cell must store: + ** 2-byte pointer to the cell + ** 4-byte child pointer + ** 9-byte nKey value + ** 4-byte nData value + ** 4-byte overflow page pointer + ** So a cell consists of a 2-byte poiner, a header which is as much as + ** 17 bytes long, 0 to N bytes of payload, and an optional 4 byte overflow + ** page pointer. + */ + pBt->maxLocal = (pBt->usableSize-12)*64/255 - 23; + pBt->minLocal = (pBt->usableSize-12)*32/255 - 23; + pBt->maxLeaf = pBt->usableSize - 35; + pBt->minLeaf = (pBt->usableSize-12)*32/255 - 23; + assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) ); + pBt->pPage1 = pPage1; + return SQLITE_OK; + +page1_init_failed: + releasePage(pPage1); + pBt->pPage1 = 0; + return rc; +} + +/* +** This routine works like lockBtree() except that it also invokes the +** busy callback if there is lock contention. +*/ +static int lockBtreeWithRetry(Btree *pRef){ + int rc = SQLITE_OK; + + assert( sqlite3BtreeHoldsMutex(pRef) ); + 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; +} + + +/* +** If there are no outstanding cursors and we are not in the middle +** of a transaction but there is a read lock on the database, then +** this routine unrefs the first page of the database file which +** has the effect of releasing the read lock. +** +** If there are any outstanding cursors, this routine is a no-op. +** +** If there is a transaction in progress, this routine is a no-op. +*/ +static void unlockBtreeIfUnused(BtShared *pBt){ + assert( sqlite3_mutex_held(pBt->mutex) ); + if( pBt->inTransaction==TRANS_NONE && pBt->pCursor==0 && pBt->pPage1!=0 ){ + if( sqlite3PagerRefcount(pBt->pPager)>=1 ){ + assert( pBt->pPage1->aData ); +#if 0 + if( pBt->pPage1->aData==0 ){ + MemPage *pPage = pBt->pPage1; + pPage->aData = sqlite3PagerGetData(pPage->pDbPage); + pPage->pBt = pBt; + pPage->pgno = 1; + } +#endif + releasePage(pBt->pPage1); + } + pBt->pPage1 = 0; + pBt->inStmt = 0; + } +} + +/* +** Create a new database by initializing the first page of the +** file. +*/ +static int newDatabase(BtShared *pBt){ + MemPage *pP1; + unsigned char *data; + int rc; + int nPage; + + assert( sqlite3_mutex_held(pBt->mutex) ); + rc = sqlite3PagerPagecount(pBt->pPager, &nPage); + if( rc!=SQLITE_OK || nPage>0 ){ + return rc; + } + pP1 = pBt->pPage1; + assert( pP1!=0 ); + data = pP1->aData; + rc = sqlite3PagerWrite(pP1->pDbPage); + if( rc ) return rc; + memcpy(data, zMagicHeader, sizeof(zMagicHeader)); + assert( sizeof(zMagicHeader)==16 ); + assert( sizeof(zMagicHeader)==sizeof(zPoisonHeader) ); + put2byte(&data[16], pBt->pageSize); + data[18] = 1; + data[19] = 1; + data[20] = pBt->pageSize - pBt->usableSize; + data[21] = 64; + data[22] = 32; + data[23] = 32; + memset(&data[24], 0, 100-24); + zeroPage(pP1, PTF_INTKEY|PTF_LEAF|PTF_LEAFDATA ); + pBt->pageSizeFixed = 1; +#ifndef SQLITE_OMIT_AUTOVACUUM + assert( pBt->autoVacuum==1 || pBt->autoVacuum==0 ); + assert( pBt->incrVacuum==1 || pBt->incrVacuum==0 ); + put4byte(&data[36 + 4*4], pBt->autoVacuum); + put4byte(&data[36 + 7*4], pBt->incrVacuum); +#endif + return SQLITE_OK; +} + +/* +** Attempt to start a new transaction. A write-transaction +** is started if the second argument is nonzero, otherwise a read- +** transaction. If the second argument is 2 or more and exclusive +** transaction is started, meaning that no other process is allowed +** to access the database. A preexisting transaction may not be +** upgraded to exclusive by calling this routine a second time - the +** exclusivity flag only works for a new transaction. +** +** A write-transaction must be started before attempting any +** changes to the database. None of the following routines +** will work unless a transaction is started first: +** +** sqlite3BtreeCreateTable() +** sqlite3BtreeCreateIndex() +** sqlite3BtreeClearTable() +** sqlite3BtreeDropTable() +** sqlite3BtreeInsert() +** sqlite3BtreeDelete() +** sqlite3BtreeUpdateMeta() +** +** If an initial attempt to acquire the lock fails because of lock contention +** and the database was previously unlocked, then invoke the busy handler +** if there is one. But if there was previously a read-lock, do not +** invoke the busy handler - just return SQLITE_BUSY. SQLITE_BUSY is +** returned when there is already a read-lock in order to avoid a deadlock. +** +** Suppose there are two processes A and B. A has a read lock and B has +** a reserved lock. B tries to promote to exclusive but is blocked because +** of A's read lock. A tries to promote to reserved but is blocked by B. +** One or the other of the two processes must give way or there can be +** no progress. By returning SQLITE_BUSY and not invoking the busy callback +** when A already has a read lock, we encourage A to give up and let B +** proceed. +*/ +int sqlite3BtreeBeginTrans(Btree *p, int wrflag){ + BtShared *pBt = p->pBt; + int rc = SQLITE_OK; + + sqlite3BtreeEnter(p); + pBt->db = p->db; + 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( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){ + goto trans_begun; + } + + /* Write transactions are not possible on a read-only database */ + if( pBt->readOnly && wrflag ){ + rc = SQLITE_READONLY; + goto trans_begun; + } + + /* 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 ){ + rc = SQLITE_BUSY; + goto trans_begun; + } + +#ifndef SQLITE_OMIT_SHARED_CACHE + if( wrflag>1 ){ + BtLock *pIter; + for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){ + if( pIter->pBtree!=p ){ + rc = SQLITE_BUSY; + goto trans_begun; + } + } + } +#endif + + do { + if( pBt->pPage1==0 ){ + do{ + rc = lockBtree(pBt); + }while( pBt->pPage1==0 && rc==SQLITE_OK ); + } + + if( rc==SQLITE_OK && wrflag ){ + if( pBt->readOnly ){ + rc = SQLITE_READONLY; + }else{ + rc = sqlite3PagerBegin(pBt->pPage1->pDbPage, wrflag>1); + if( rc==SQLITE_OK ){ + rc = newDatabase(pBt); + } + } + } + + if( rc==SQLITE_OK ){ + if( wrflag ) pBt->inStmt = 0; + }else{ + unlockBtreeIfUnused(pBt); + } + }while( rc==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE && + sqlite3BtreeInvokeBusyHandler(pBt, 0) ); + + 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; + } +#ifndef SQLITE_OMIT_SHARED_CACHE + if( wrflag>1 ){ + assert( !pBt->pExclusive ); + pBt->pExclusive = p; + } +#endif + } + + +trans_begun: + btreeIntegrity(p); + sqlite3BtreeLeave(p); + return rc; +} + +/* +** Return the size of the database file in pages. Or return -1 if +** there is any kind of error. +*/ +static int pagerPagecount(Pager *pPager){ + int rc; + int nPage; + rc = sqlite3PagerPagecount(pPager, &nPage); + return (rc==SQLITE_OK?nPage:-1); +} + + +#ifndef SQLITE_OMIT_AUTOVACUUM + +/* +** Set the pointer-map entries for all children of page pPage. Also, if +** pPage contains cells that point to overflow pages, set the pointer +** map entries for the overflow pages as well. +*/ +static int setChildPtrmaps(MemPage *pPage){ + int i; /* Counter variable */ + int nCell; /* Number of cells in page pPage */ + int rc; /* Return code */ + BtShared *pBt = pPage->pBt; + int isInitOrig = pPage->isInit; + Pgno pgno = pPage->pgno; + + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + rc = sqlite3BtreeInitPage(pPage, pPage->pParent); + if( rc!=SQLITE_OK ){ + goto set_child_ptrmaps_out; + } + nCell = pPage->nCell; + + for(i=0; i<nCell; i++){ + u8 *pCell = findCell(pPage, i); + + rc = ptrmapPutOvflPtr(pPage, pCell); + if( rc!=SQLITE_OK ){ + goto set_child_ptrmaps_out; + } + + if( !pPage->leaf ){ + Pgno childPgno = get4byte(pCell); + rc = ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno); + if( rc!=SQLITE_OK ) goto set_child_ptrmaps_out; + } + } + + if( !pPage->leaf ){ + Pgno childPgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); + rc = ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno); + } + +set_child_ptrmaps_out: + pPage->isInit = isInitOrig; + return rc; +} + +/* +** Somewhere on pPage, which is guarenteed to be a btree page, not an overflow +** page, is a pointer to page iFrom. Modify this pointer so that it points to +** iTo. Parameter eType describes the type of pointer to be modified, as +** follows: +** +** PTRMAP_BTREE: pPage is a btree-page. The pointer points at a child +** page of pPage. +** +** PTRMAP_OVERFLOW1: pPage is a btree-page. The pointer points at an overflow +** page pointed to by one of the cells on pPage. +** +** PTRMAP_OVERFLOW2: pPage is an overflow-page. The pointer points at the next +** overflow page in the list. +*/ +static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + if( eType==PTRMAP_OVERFLOW2 ){ + /* The pointer is always the first 4 bytes of the page in this case. */ + if( get4byte(pPage->aData)!=iFrom ){ + return SQLITE_CORRUPT_BKPT; + } + put4byte(pPage->aData, iTo); + }else{ + int isInitOrig = pPage->isInit; + int i; + int nCell; + + sqlite3BtreeInitPage(pPage, 0); + nCell = pPage->nCell; + + for(i=0; i<nCell; i++){ + u8 *pCell = findCell(pPage, i); + if( eType==PTRMAP_OVERFLOW1 ){ + CellInfo info; + sqlite3BtreeParseCellPtr(pPage, pCell, &info); + if( info.iOverflow ){ + if( iFrom==get4byte(&pCell[info.iOverflow]) ){ + put4byte(&pCell[info.iOverflow], iTo); + break; + } + } + }else{ + if( get4byte(pCell)==iFrom ){ + put4byte(pCell, iTo); + break; + } + } + } + + if( i==nCell ){ + if( eType!=PTRMAP_BTREE || + get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){ + return SQLITE_CORRUPT_BKPT; + } + put4byte(&pPage->aData[pPage->hdrOffset+8], iTo); + } + + pPage->isInit = isInitOrig; + } + return SQLITE_OK; +} + + +/* +** Move the open database page pDbPage to location iFreePage in the +** database. The pDbPage reference remains valid. +*/ +static int relocatePage( + 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 */ + Pgno iFreePage, /* The location to move pDbPage to */ + int isCommit +){ + MemPage *pPtrPage; /* The page that contains a pointer to pDbPage */ + Pgno iDbPage = pDbPage->pgno; + Pager *pPager = pBt->pPager; + int rc; + + assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 || + eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ); + assert( sqlite3_mutex_held(pBt->mutex) ); + assert( pDbPage->pBt==pBt ); + + /* Move page iDbPage from its current location to page number iFreePage */ + TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n", + iDbPage, iFreePage, iPtrPage, eType)); + rc = sqlite3PagerMovepage(pPager, pDbPage->pDbPage, iFreePage, isCommit); + if( rc!=SQLITE_OK ){ + return rc; + } + pDbPage->pgno = iFreePage; + + /* If pDbPage was a btree-page, then it may have child pages and/or cells + ** that point to overflow pages. The pointer map entries for all these + ** pages need to be changed. + ** + ** If pDbPage is an overflow page, then the first 4 bytes may store a + ** pointer to a subsequent overflow page. If this is the case, then + ** the pointer map needs to be updated for the subsequent overflow page. + */ + if( eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ){ + rc = setChildPtrmaps(pDbPage); + if( rc!=SQLITE_OK ){ + return rc; + } + }else{ + Pgno nextOvfl = get4byte(pDbPage->aData); + if( nextOvfl!=0 ){ + rc = ptrmapPut(pBt, nextOvfl, PTRMAP_OVERFLOW2, iFreePage); + if( rc!=SQLITE_OK ){ + return rc; + } + } + } + + /* Fix the database pointer on page iPtrPage that pointed at iDbPage so + ** that it points at iFreePage. Also fix the pointer map entry for + ** iPtrPage. + */ + if( eType!=PTRMAP_ROOTPAGE ){ + rc = sqlite3BtreeGetPage(pBt, iPtrPage, &pPtrPage, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + rc = sqlite3PagerWrite(pPtrPage->pDbPage); + if( rc!=SQLITE_OK ){ + releasePage(pPtrPage); + return rc; + } + rc = modifyPagePointer(pPtrPage, iDbPage, iFreePage, eType); + releasePage(pPtrPage); + if( rc==SQLITE_OK ){ + rc = ptrmapPut(pBt, iFreePage, eType, iPtrPage); + } + } + return rc; +} + +/* Forward declaration required by incrVacuumStep(). */ +static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8); + +/* +** Perform a single step of an incremental-vacuum. If successful, +** return SQLITE_OK. If there is no work to do (and therefore no +** point in calling this function again), return SQLITE_DONE. +** +** More specificly, this function attempts to re-organize the +** database so that the last page of the file currently in use +** is no longer in use. +** +** If the nFin parameter is non-zero, the implementation assumes +** that the caller will keep calling incrVacuumStep() until +** it returns SQLITE_DONE or an error, and that nFin is the +** number of pages the database file will contain after this +** process is complete. +*/ +static int incrVacuumStep(BtShared *pBt, Pgno nFin){ + Pgno iLastPg; /* Last page in the database */ + Pgno nFreeList; /* Number of pages still on the free-list */ + + assert( sqlite3_mutex_held(pBt->mutex) ); + iLastPg = pBt->nTrunc; + if( iLastPg==0 ){ + iLastPg = pagerPagecount(pBt->pPager); + } + + if( !PTRMAP_ISPAGE(pBt, iLastPg) && iLastPg!=PENDING_BYTE_PAGE(pBt) ){ + int rc; + u8 eType; + Pgno iPtrPage; + + nFreeList = get4byte(&pBt->pPage1->aData[36]); + if( nFreeList==0 || nFin==iLastPg ){ + return SQLITE_DONE; + } + + rc = ptrmapGet(pBt, iLastPg, &eType, &iPtrPage); + if( rc!=SQLITE_OK ){ + return rc; + } + if( eType==PTRMAP_ROOTPAGE ){ + return SQLITE_CORRUPT_BKPT; + } + + if( eType==PTRMAP_FREEPAGE ){ + if( nFin==0 ){ + /* Remove the page from the files free-list. This is not required + ** if nFin is non-zero. In that case, the free-list will be + ** truncated to zero after this function returns, so it doesn't + ** matter if it still contains some garbage entries. + */ + Pgno iFreePg; + MemPage *pFreePg; + rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iLastPg, 1); + if( rc!=SQLITE_OK ){ + return rc; + } + assert( iFreePg==iLastPg ); + releasePage(pFreePg); + } + } else { + Pgno iFreePg; /* Index of free page to move pLastPg to */ + MemPage *pLastPg; + + rc = sqlite3BtreeGetPage(pBt, iLastPg, &pLastPg, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + + /* If nFin is zero, this loop runs exactly once and page pLastPg + ** is swapped with the first free page pulled off the free list. + ** + ** On the other hand, if nFin is greater than zero, then keep + ** looping until a free-page located within the first nFin pages + ** of the file is found. + */ + do { + MemPage *pFreePg; + rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, 0, 0); + if( rc!=SQLITE_OK ){ + releasePage(pLastPg); + return rc; + } + releasePage(pFreePg); + }while( nFin!=0 && iFreePg>nFin ); + assert( iFreePg<iLastPg ); + + rc = sqlite3PagerWrite(pLastPg->pDbPage); + if( rc==SQLITE_OK ){ + rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, nFin!=0); + } + releasePage(pLastPg); + if( rc!=SQLITE_OK ){ + return rc; + } + } + } + + pBt->nTrunc = iLastPg - 1; + while( pBt->nTrunc==PENDING_BYTE_PAGE(pBt)||PTRMAP_ISPAGE(pBt, pBt->nTrunc) ){ + pBt->nTrunc--; + } + return SQLITE_OK; +} + +/* +** A write-transaction must be opened before calling this function. +** It performs a single unit of work towards an incremental vacuum. +** +** If the incremental vacuum is finished after this function has run, +** SQLITE_DONE is returned. If it is not finished, but no error occured, +** SQLITE_OK is returned. Otherwise an SQLite error code. +*/ +int sqlite3BtreeIncrVacuum(Btree *p){ + int rc; + BtShared *pBt = p->pBt; + + sqlite3BtreeEnter(p); + pBt->db = p->db; + assert( pBt->inTransaction==TRANS_WRITE && p->inTrans==TRANS_WRITE ); + if( !pBt->autoVacuum ){ + rc = SQLITE_DONE; + }else{ + invalidateAllOverflowCache(pBt); + rc = incrVacuumStep(pBt, 0); + } + sqlite3BtreeLeave(p); + return rc; +} + +/* +** This routine is called prior to sqlite3PagerCommit when a transaction +** is commited for an auto-vacuum database. +** +** If SQLITE_OK is returned, then *pnTrunc is set to the number of pages +** the database file should be truncated to during the commit process. +** i.e. the database has been reorganized so that only the first *pnTrunc +** pages are in use. +*/ +static int autoVacuumCommit(BtShared *pBt, Pgno *pnTrunc){ + int rc = SQLITE_OK; + Pager *pPager = pBt->pPager; +#ifndef NDEBUG + int nRef = sqlite3PagerRefcount(pPager); +#endif + + assert( sqlite3_mutex_held(pBt->mutex) ); + invalidateAllOverflowCache(pBt); + assert(pBt->autoVacuum); + if( !pBt->incrVacuum ){ + Pgno nFin = 0; + + if( pBt->nTrunc==0 ){ + Pgno nFree; + Pgno nPtrmap; + const int pgsz = pBt->pageSize; + int nOrig = pagerPagecount(pBt->pPager); + + if( PTRMAP_ISPAGE(pBt, nOrig) ){ + return SQLITE_CORRUPT_BKPT; + } + if( nOrig==PENDING_BYTE_PAGE(pBt) ){ + nOrig--; + } + nFree = get4byte(&pBt->pPage1->aData[36]); + nPtrmap = (nFree-nOrig+PTRMAP_PAGENO(pBt, nOrig)+pgsz/5)/(pgsz/5); + nFin = nOrig - nFree - nPtrmap; + if( nOrig>PENDING_BYTE_PAGE(pBt) && nFin<=PENDING_BYTE_PAGE(pBt) ){ + nFin--; + } + while( PTRMAP_ISPAGE(pBt, nFin) || nFin==PENDING_BYTE_PAGE(pBt) ){ + nFin--; + } + } + + while( rc==SQLITE_OK ){ + rc = incrVacuumStep(pBt, nFin); + } + if( rc==SQLITE_DONE ){ + assert(nFin==0 || pBt->nTrunc==0 || nFin<=pBt->nTrunc); + rc = SQLITE_OK; + if( pBt->nTrunc && nFin ){ + rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); + put4byte(&pBt->pPage1->aData[32], 0); + put4byte(&pBt->pPage1->aData[36], 0); + pBt->nTrunc = nFin; + } + } + if( rc!=SQLITE_OK ){ + sqlite3PagerRollback(pPager); + } + } + + if( rc==SQLITE_OK ){ + *pnTrunc = pBt->nTrunc; + pBt->nTrunc = 0; + } + assert( nRef==sqlite3PagerRefcount(pPager) ); + return rc; +} + +#endif + +/* +** This routine does the first phase of a two-phase commit. This routine +** causes a rollback journal to be created (if it does not already exist) +** and populated with enough information so that if a power loss occurs +** the database can be restored to its original state by playing back +** the journal. Then the contents of the journal are flushed out to +** the disk. After the journal is safely on oxide, the changes to the +** database are written into the database file and flushed to oxide. +** At the end of this call, the rollback journal still exists on the +** disk and we are still holding all locks, so the transaction has not +** committed. See sqlite3BtreeCommit() for the second phase of the +** commit process. +** +** This call is a no-op if no write-transaction is currently active on pBt. +** +** Otherwise, sync the database file for the btree pBt. zMaster points to +** the name of a master journal file that should be written into the +** individual journal file, or is NULL, indicating no master journal file +** (single database transaction). +** +** When this is called, the master journal should already have been +** created, populated with this journal pointer and synced to disk. +** +** 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 sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){ + int rc = SQLITE_OK; + if( p->inTrans==TRANS_WRITE ){ + BtShared *pBt = p->pBt; + Pgno nTrunc = 0; + sqlite3BtreeEnter(p); + pBt->db = p->db; +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + rc = autoVacuumCommit(pBt, &nTrunc); + if( rc!=SQLITE_OK ){ + sqlite3BtreeLeave(p); + return rc; + } + } +#endif + rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, nTrunc, 0); + sqlite3BtreeLeave(p); + } + return rc; +} + +/* +** Commit the transaction currently in progress. +** +** This routine implements the second phase of a 2-phase commit. The +** sqlite3BtreeSync() routine does the first phase and should be invoked +** prior to calling this routine. The sqlite3BtreeSync() routine did +** all the work of writing information out to disk and flushing the +** contents so that they are written onto the disk platter. All this +** routine has to do is delete or truncate the rollback journal +** (which causes the transaction to commit) and drop locks. +** +** This will release the write lock on the database file. If there +** are no active cursors, it also releases the read lock. +*/ +int sqlite3BtreeCommitPhaseTwo(Btree *p){ + BtShared *pBt = p->pBt; + + sqlite3BtreeEnter(p); + pBt->db = p->db; + 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 = sqlite3PagerCommitPhaseTwo(pBt->pPager); + if( rc!=SQLITE_OK ){ + sqlite3BtreeLeave(p); + return rc; + } + pBt->inTransaction = TRANS_READ; + 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); + + btreeIntegrity(p); + sqlite3BtreeLeave(p); + return SQLITE_OK; +} + +/* +** Do both phases of a commit. +*/ +int sqlite3BtreeCommit(Btree *p){ + int rc; + sqlite3BtreeEnter(p); + rc = sqlite3BtreeCommitPhaseOne(p, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3BtreeCommitPhaseTwo(p); + } + sqlite3BtreeLeave(p); + return rc; +} + +#ifndef NDEBUG +/* +** Return the number of write-cursors open on this handle. This is for use +** in assert() expressions, so it is only compiled if NDEBUG is not +** defined. +** +** For the purposes of this routine, a write-cursor is any cursor that +** is capable of writing to the databse. That means the cursor was +** originally opened for writing and the cursor has not be disabled +** by having its state changed to CURSOR_FAULT. +*/ +static int countWriteCursors(BtShared *pBt){ + BtCursor *pCur; + int r = 0; + for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ + if( pCur->wrFlag && pCur->eState!=CURSOR_FAULT ) r++; + } + return r; +} +#endif + +/* +** This routine sets the state to CURSOR_FAULT and the error +** code to errCode for every cursor on BtShared that pBtree +** references. +** +** Every cursor is tripped, including cursors that belong +** to other database connections that happen to be sharing +** the cache with pBtree. +** +** This routine gets called when a rollback occurs. +** All cursors using the same cache must be tripped +** to prevent them from trying to use the btree after +** the rollback. The rollback may have deleted tables +** or moved root pages, so it is not sufficient to +** save the state of the cursor. The cursor must be +** invalidated. +*/ +void sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode){ + BtCursor *p; + sqlite3BtreeEnter(pBtree); + for(p=pBtree->pBt->pCursor; p; p=p->pNext){ + clearCursorPosition(p); + p->eState = CURSOR_FAULT; + p->skip = errCode; + } + sqlite3BtreeLeave(pBtree); +} + +/* +** Rollback the transaction in progress. All cursors will be +** invalided by this operation. Any attempt to use a cursor +** that was open at the beginning of this operation will result +** in an error. +** +** 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 *p){ + int rc; + BtShared *pBt = p->pBt; + MemPage *pPage1; + + sqlite3BtreeEnter(p); + pBt->db = p->db; + 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. + */ + sqlite3BtreeTripAllCursors(p, rc); + } +#endif + btreeIntegrity(p); + unlockAllTables(p); + + if( p->inTrans==TRANS_WRITE ){ + int rc2; + +#ifndef SQLITE_OMIT_AUTOVACUUM + pBt->nTrunc = 0; +#endif + + assert( TRANS_WRITE==pBt->inTransaction ); + rc2 = sqlite3PagerRollback(pBt->pPager); + if( rc2!=SQLITE_OK ){ + rc = rc2; + } + + /* The rollback may have destroyed the pPage1->aData value. So + ** call sqlite3BtreeGetPage() on page 1 again to make + ** sure pPage1->aData is set correctly. */ + if( sqlite3BtreeGetPage(pBt, 1, &pPage1, 0)==SQLITE_OK ){ + releasePage(pPage1); + } + assert( countWriteCursors(pBt)==0 ); + pBt->inTransaction = TRANS_READ; + } + + 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); + sqlite3BtreeLeave(p); + return rc; +} + +/* +** Start a statement subtransaction. The subtransaction can +** can be rolled back independently of the main transaction. +** You must start a transaction before starting a subtransaction. +** The subtransaction is ended automatically if the main transaction +** commits or rolls back. +** +** Only one subtransaction may be active at a time. It is an error to try +** to start a new subtransaction if another subtransaction is already active. +** +** Statement subtransactions are used around individual SQL statements +** that are contained within a BEGIN...COMMIT block. If a constraint +** 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 *p){ + int rc; + BtShared *pBt = p->pBt; + sqlite3BtreeEnter(p); + pBt->db = p->db; + if( (p->inTrans!=TRANS_WRITE) || pBt->inStmt ){ + rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; + }else{ + assert( pBt->inTransaction==TRANS_WRITE ); + rc = pBt->readOnly ? SQLITE_OK : sqlite3PagerStmtBegin(pBt->pPager); + pBt->inStmt = 1; + } + sqlite3BtreeLeave(p); + return rc; +} + + +/* +** Commit the statment subtransaction currently in progress. If no +** subtransaction is active, this is a no-op. +*/ +int sqlite3BtreeCommitStmt(Btree *p){ + int rc; + BtShared *pBt = p->pBt; + sqlite3BtreeEnter(p); + pBt->db = p->db; + if( pBt->inStmt && !pBt->readOnly ){ + rc = sqlite3PagerStmtCommit(pBt->pPager); + }else{ + rc = SQLITE_OK; + } + pBt->inStmt = 0; + sqlite3BtreeLeave(p); + return rc; +} + +/* +** Rollback the active statement subtransaction. If no subtransaction +** is active this routine is a no-op. +** +** All cursors will be invalidated by this operation. Any attempt +** to use a cursor that was open at the beginning of this operation +** will result in an error. +*/ +int sqlite3BtreeRollbackStmt(Btree *p){ + int rc = SQLITE_OK; + BtShared *pBt = p->pBt; + sqlite3BtreeEnter(p); + pBt->db = p->db; + if( pBt->inStmt && !pBt->readOnly ){ + rc = sqlite3PagerStmtRollback(pBt->pPager); + pBt->inStmt = 0; + } + sqlite3BtreeLeave(p); + return rc; +} + +/* +** Create a new cursor for the BTree whose root is on the page +** iTable. The act of acquiring a cursor gets a read lock on +** the database file. +** +** If wrFlag==0, then the cursor can only be used for reading. +** If wrFlag==1, then the cursor can be used for reading or for +** writing if other conditions for writing are also met. These +** are the conditions that must be met in order for writing to +** be allowed: +** +** 1: The cursor must have been opened with wrFlag==1 +** +** 2: Other database connections that share the same pager cache +** but which are not in the READ_UNCOMMITTED state may not have +** cursors open with wrFlag==0 on the same table. Otherwise +** the changes made by this write cursor would be visible to +** the read cursors in the other database connection. +** +** 3: The database must be writable (not on read-only media) +** +** 4: There must be an active transaction. +** +** No checking is done to make sure that page iTable really is the +** root page of a b-tree. If it is not, then the cursor acquired +** will not work correctly. +*/ +static int btreeCursor( + Btree *p, /* The btree */ + int iTable, /* Root page of table to open */ + int wrFlag, /* 1 to write. 0 read-only */ + struct KeyInfo *pKeyInfo, /* First arg to comparison function */ + BtCursor *pCur /* Space for new cursor */ +){ + int rc; + BtShared *pBt = p->pBt; + + assert( sqlite3BtreeHoldsMutex(p) ); + if( wrFlag ){ + if( pBt->readOnly ){ + return SQLITE_READONLY; + } + if( checkReadLocks(p, iTable, 0, 0) ){ + return SQLITE_LOCKED; + } + } + + if( pBt->pPage1==0 ){ + rc = lockBtreeWithRetry(p); + if( rc!=SQLITE_OK ){ + return rc; + } + if( pBt->readOnly && wrFlag ){ + return SQLITE_READONLY; + } + } + pCur->pgnoRoot = (Pgno)iTable; + if( iTable==1 && pagerPagecount(pBt->pPager)==0 ){ + rc = SQLITE_EMPTY; + goto create_cursor_exception; + } + rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->pPage, 0); + 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->pKeyInfo = pKeyInfo; + pCur->pBtree = p; + pCur->pBt = pBt; + pCur->wrFlag = wrFlag; + pCur->pNext = pBt->pCursor; + if( pCur->pNext ){ + pCur->pNext->pPrev = pCur; + } + pBt->pCursor = pCur; + pCur->eState = CURSOR_INVALID; + + return SQLITE_OK; + +create_cursor_exception: + releasePage(pCur->pPage); + unlockBtreeIfUnused(pBt); + return rc; +} +int sqlite3BtreeCursor( + Btree *p, /* The btree */ + int iTable, /* Root page of table to open */ + int wrFlag, /* 1 to write. 0 read-only */ + struct KeyInfo *pKeyInfo, /* First arg to xCompare() */ + BtCursor *pCur /* Write new cursor here */ +){ + int rc; + sqlite3BtreeEnter(p); + p->pBt->db = p->db; + rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur); + sqlite3BtreeLeave(p); + return rc; +} +int sqlite3BtreeCursorSize(){ + return sizeof(BtCursor); +} + + + +/* +** Close a cursor. The read lock on the database file is released +** when the last cursor is closed. +*/ +int sqlite3BtreeCloseCursor(BtCursor *pCur){ + Btree *pBtree = pCur->pBtree; + if( pBtree ){ + BtShared *pBt = pCur->pBt; + sqlite3BtreeEnter(pBtree); + pBt->db = pBtree->db; + clearCursorPosition(pCur); + if( pCur->pPrev ){ + pCur->pPrev->pNext = pCur->pNext; + }else{ + pBt->pCursor = pCur->pNext; + } + if( pCur->pNext ){ + pCur->pNext->pPrev = pCur->pPrev; + } + releasePage(pCur->pPage); + unlockBtreeIfUnused(pBt); + invalidateOverflowCache(pCur); + /* sqlite3_free(pCur); */ + sqlite3BtreeLeave(pBtree); + } + return SQLITE_OK; +} + +/* +** Make a temporary cursor by filling in the fields of pTempCur. +** The temporary cursor is not on the cursor list for the Btree. +*/ +void sqlite3BtreeGetTempCursor(BtCursor *pCur, BtCursor *pTempCur){ + assert( cursorHoldsMutex(pCur) ); + memcpy(pTempCur, pCur, sizeof(*pCur)); + pTempCur->pNext = 0; + pTempCur->pPrev = 0; + if( pTempCur->pPage ){ + sqlite3PagerRef(pTempCur->pPage->pDbPage); + } +} + +/* +** Delete a temporary cursor such as was made by the CreateTemporaryCursor() +** function above. +*/ +void sqlite3BtreeReleaseTempCursor(BtCursor *pCur){ + assert( cursorHoldsMutex(pCur) ); + if( pCur->pPage ){ + sqlite3PagerUnref(pCur->pPage->pDbPage); + } +} + +/* +** Make sure the BtCursor* given in the argument has a valid +** BtCursor.info structure. If it is not already valid, call +** sqlite3BtreeParseCell() to fill it in. +** +** BtCursor.info is a cache of the information in the current cell. +** Using this cache reduces the number of calls to sqlite3BtreeParseCell(). +** +** 2007-06-25: There is a bug in some versions of MSVC that cause the +** compiler to crash when getCellInfo() is implemented as a macro. +** But there is a measureable speed advantage to using the macro on gcc +** (when less compiler optimizations like -Os or -O0 are used and the +** compiler is not doing agressive inlining.) So we use a real function +** for MSVC and a macro for everything else. Ticket #2457. +*/ +#ifndef NDEBUG + static void assertCellInfo(BtCursor *pCur){ + CellInfo info; + memset(&info, 0, sizeof(info)); + sqlite3BtreeParseCell(pCur->pPage, pCur->idx, &info); + assert( memcmp(&info, &pCur->info, sizeof(info))==0 ); + } +#else + #define assertCellInfo(x) +#endif +#ifdef _MSC_VER + /* Use a real function in MSVC to work around bugs in that compiler. */ + static void getCellInfo(BtCursor *pCur){ + if( pCur->info.nSize==0 ){ + sqlite3BtreeParseCell(pCur->pPage, pCur->idx, &pCur->info); + pCur->validNKey = 1; + }else{ + assertCellInfo(pCur); + } + } +#else /* if not _MSC_VER */ + /* Use a macro in all other compilers so that the function is inlined */ +#define getCellInfo(pCur) \ + if( pCur->info.nSize==0 ){ \ + sqlite3BtreeParseCell(pCur->pPage, pCur->idx, &pCur->info); \ + pCur->validNKey = 1; \ + }else{ \ + assertCellInfo(pCur); \ + } +#endif /* _MSC_VER */ + +/* +** Set *pSize to the size of the buffer needed to hold the value of +** the key for the current entry. If the cursor is not pointing +** to a valid entry, *pSize is set to 0. +** +** For a table with the INTKEY flag set, this routine returns the key +** itself, not the number of bytes in the key. +*/ +int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ + int rc; + + assert( cursorHoldsMutex(pCur) ); + rc = restoreCursorPosition(pCur); + 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 rc; +} + +/* +** Set *pSize to the number of bytes of data in the entry the +** cursor currently points to. Always return SQLITE_OK. +** Failure is not possible. If the cursor is not currently +** pointing to an entry (which can happen, for example, if +** the database is empty) then *pSize is set to 0. +*/ +int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){ + int rc; + + assert( cursorHoldsMutex(pCur) ); + rc = restoreCursorPosition(pCur); + 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 rc; +} + +/* +** Given the page number of an overflow page in the database (parameter +** ovfl), this function finds the page number of the next page in the +** linked list of overflow pages. If possible, it uses the auto-vacuum +** pointer-map data instead of reading the content of page ovfl to do so. +** +** If an error occurs an SQLite error code is returned. Otherwise: +** +** Unless pPgnoNext is NULL, the page number of the next overflow +** page in the linked list is written to *pPgnoNext. If page ovfl +** is the last page in its linked list, *pPgnoNext is set to zero. +** +** If ppPage is not NULL, *ppPage is set to the MemPage* handle +** for page ovfl. The underlying pager page may have been requested +** with the noContent flag set, so the page data accessable via +** this handle may not be trusted. +*/ +static int getOverflowPage( + BtShared *pBt, + Pgno ovfl, /* Overflow page */ + MemPage **ppPage, /* OUT: MemPage handle */ + Pgno *pPgnoNext /* OUT: Next overflow page number */ +){ + Pgno next = 0; + int rc; + + assert( sqlite3_mutex_held(pBt->mutex) ); + /* One of these must not be NULL. Otherwise, why call this function? */ + assert(ppPage || pPgnoNext); + + /* If pPgnoNext is NULL, then this function is being called to obtain + ** a MemPage* reference only. No page-data is required in this case. + */ + if( !pPgnoNext ){ + return sqlite3BtreeGetPage(pBt, ovfl, ppPage, 1); + } + +#ifndef SQLITE_OMIT_AUTOVACUUM + /* Try to find the next page in the overflow list using the + ** autovacuum pointer-map pages. Guess that the next page in + ** the overflow list is page number (ovfl+1). If that guess turns + ** out to be wrong, fall back to loading the data of page + ** number ovfl to determine the next page number. + */ + if( pBt->autoVacuum ){ + Pgno pgno; + Pgno iGuess = ovfl+1; + u8 eType; + + while( PTRMAP_ISPAGE(pBt, iGuess) || iGuess==PENDING_BYTE_PAGE(pBt) ){ + iGuess++; + } + + if( iGuess<=pagerPagecount(pBt->pPager) ){ + rc = ptrmapGet(pBt, iGuess, &eType, &pgno); + if( rc!=SQLITE_OK ){ + return rc; + } + if( eType==PTRMAP_OVERFLOW2 && pgno==ovfl ){ + next = iGuess; + } + } + } +#endif + + if( next==0 || ppPage ){ + MemPage *pPage = 0; + + rc = sqlite3BtreeGetPage(pBt, ovfl, &pPage, next!=0); + assert(rc==SQLITE_OK || pPage==0); + if( next==0 && rc==SQLITE_OK ){ + next = get4byte(pPage->aData); + } + + if( ppPage ){ + *ppPage = pPage; + }else{ + releasePage(pPage); + } + } + *pPgnoNext = next; + + return rc; +} + +/* +** Copy data from a buffer to a page, or from a page to a buffer. +** +** pPayload is a pointer to data stored on database page pDbPage. +** If argument eOp is false, then nByte bytes of data are copied +** from pPayload to the buffer pointed at by pBuf. If eOp is true, +** then sqlite3PagerWrite() is called on pDbPage and nByte bytes +** of data are copied from the buffer pBuf to pPayload. +** +** SQLITE_OK is returned on success, otherwise an error code. +*/ +static int copyPayload( + void *pPayload, /* Pointer to page data */ + void *pBuf, /* Pointer to buffer */ + int nByte, /* Number of bytes to copy */ + int eOp, /* 0 -> copy from page, 1 -> copy to page */ + DbPage *pDbPage /* Page containing pPayload */ +){ + if( eOp ){ + /* Copy data from buffer to page (a write operation) */ + int rc = sqlite3PagerWrite(pDbPage); + if( rc!=SQLITE_OK ){ + return rc; + } + memcpy(pPayload, pBuf, nByte); + }else{ + /* Copy data from page to buffer (a read operation) */ + memcpy(pBuf, pPayload, nByte); + } + return SQLITE_OK; +} + +/* +** This function is used to read or overwrite payload information +** for the entry that the pCur cursor is pointing to. If the eOp +** parameter is 0, this is a read operation (data copied into +** buffer pBuf). If it is non-zero, a write (data copied from +** buffer pBuf). +** +** A total of "amt" bytes are read or written beginning at "offset". +** Data is read to or from the buffer pBuf. +** +** This routine does not make a distinction between key and data. +** It just reads or writes bytes from the payload area. Data might +** appear on the main page or be scattered out on multiple overflow +** pages. +** +** If the BtCursor.isIncrblobHandle flag is set, and the current +** cursor entry uses one or more overflow pages, this function +** allocates space for and lazily popluates the overflow page-list +** cache array (BtCursor.aOverflow). Subsequent calls use this +** cache to make seeking to the supplied offset more efficient. +** +** Once an overflow page-list cache has been allocated, it may be +** invalidated if some other cursor writes to the same table, or if +** the cursor is moved to a different row. Additionally, in auto-vacuum +** mode, the following events may invalidate an overflow page-list cache. +** +** * An incremental vacuum, +** * A commit in auto_vacuum="full" mode, +** * Creating a table (may require moving an overflow page). +*/ +static int accessPayload( + BtCursor *pCur, /* Cursor pointing to entry to read from */ + int offset, /* Begin reading this far into payload */ + int amt, /* Read this many bytes */ + unsigned char *pBuf, /* Write the bytes into this buffer */ + int skipKey, /* offset begins at data if this is true */ + int eOp /* zero to read. non-zero to write. */ +){ + unsigned char *aPayload; + int rc = SQLITE_OK; + u32 nKey; + int iIdx = 0; + MemPage *pPage = pCur->pPage; /* Btree page of current cursor entry */ + BtShared *pBt; /* Btree this cursor belongs to */ + + assert( pPage ); + assert( pCur->eState==CURSOR_VALID ); + assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); + assert( offset>=0 ); + assert( cursorHoldsMutex(pCur) ); + + getCellInfo(pCur); + aPayload = pCur->info.pCell + pCur->info.nHeader; + nKey = (pPage->intKey ? 0 : pCur->info.nKey); + + if( skipKey ){ + offset += nKey; + } + if( offset+amt > nKey+pCur->info.nData ){ + /* Trying to read or write past the end of the data is an error */ + return SQLITE_ERROR; + } + + /* Check if data must be read/written to/from the btree page itself. */ + if( offset<pCur->info.nLocal ){ + int a = amt; + if( a+offset>pCur->info.nLocal ){ + a = pCur->info.nLocal - offset; + } + rc = copyPayload(&aPayload[offset], pBuf, a, eOp, pPage->pDbPage); + offset = 0; + pBuf += a; + amt -= a; + }else{ + offset -= pCur->info.nLocal; + } + + pBt = pCur->pBt; + if( rc==SQLITE_OK && amt>0 ){ + const int ovflSize = pBt->usableSize - 4; /* Bytes content per ovfl page */ + Pgno nextPage; + + nextPage = get4byte(&aPayload[pCur->info.nLocal]); + +#ifndef SQLITE_OMIT_INCRBLOB + /* If the isIncrblobHandle flag is set and the BtCursor.aOverflow[] + ** has not been allocated, allocate it now. The array is sized at + ** one entry for each overflow page in the overflow chain. The + ** page number of the first overflow page is stored in aOverflow[0], + ** etc. A value of 0 in the aOverflow[] array means "not yet known" + ** (the cache is lazily populated). + */ + if( pCur->isIncrblobHandle && !pCur->aOverflow ){ + int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize; + pCur->aOverflow = (Pgno *)sqlite3MallocZero(sizeof(Pgno)*nOvfl); + if( nOvfl && !pCur->aOverflow ){ + rc = SQLITE_NOMEM; + } + } + + /* If the overflow page-list cache has been allocated and the + ** entry for the first required overflow page is valid, skip + ** directly to it. + */ + if( pCur->aOverflow && pCur->aOverflow[offset/ovflSize] ){ + iIdx = (offset/ovflSize); + nextPage = pCur->aOverflow[iIdx]; + offset = (offset%ovflSize); + } +#endif + + for( ; rc==SQLITE_OK && amt>0 && nextPage; iIdx++){ + +#ifndef SQLITE_OMIT_INCRBLOB + /* If required, populate the overflow page-list cache. */ + if( pCur->aOverflow ){ + assert(!pCur->aOverflow[iIdx] || pCur->aOverflow[iIdx]==nextPage); + pCur->aOverflow[iIdx] = nextPage; + } +#endif + + if( offset>=ovflSize ){ + /* The only reason to read this page is to obtain the page + ** number for the next page in the overflow chain. The page + ** data is not required. So first try to lookup the overflow + ** page-list cache, if any, then fall back to the getOverflowPage() + ** function. + */ +#ifndef SQLITE_OMIT_INCRBLOB + if( pCur->aOverflow && pCur->aOverflow[iIdx+1] ){ + nextPage = pCur->aOverflow[iIdx+1]; + } else +#endif + rc = getOverflowPage(pBt, nextPage, 0, &nextPage); + offset -= ovflSize; + }else{ + /* Need to read this page properly. It contains some of the + ** range of data that is being read (eOp==0) or written (eOp!=0). + */ + DbPage *pDbPage; + int a = amt; + rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage); + if( rc==SQLITE_OK ){ + aPayload = sqlite3PagerGetData(pDbPage); + nextPage = get4byte(aPayload); + if( a + offset > ovflSize ){ + a = ovflSize - offset; + } + rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage); + sqlite3PagerUnref(pDbPage); + offset = 0; + amt -= a; + pBuf += a; + } + } + } + } + + if( rc==SQLITE_OK && amt>0 ){ + return SQLITE_CORRUPT_BKPT; + } + return rc; +} + +/* +** Read part of the key associated with cursor pCur. Exactly +** "amt" bytes will be transfered into pBuf[]. The transfer +** begins at "offset". +** +** Return SQLITE_OK on success or an error code if anything goes +** wrong. An error is returned if "offset+amt" is larger than +** the available payload. +*/ +int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ + int rc; + + assert( cursorHoldsMutex(pCur) ); + rc = restoreCursorPosition(pCur); + 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->idx<pCur->pPage->nCell ); + rc = accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0, 0); + } + return rc; +} + +/* +** Read part of the data associated with cursor pCur. Exactly +** "amt" bytes will be transfered into pBuf[]. The transfer +** begins at "offset". +** +** Return SQLITE_OK on success or an error code if anything goes +** wrong. An error is returned if "offset+amt" is larger than +** the available payload. +*/ +int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ + int rc; + +#ifndef SQLITE_OMIT_INCRBLOB + if ( pCur->eState==CURSOR_INVALID ){ + return SQLITE_ABORT; + } +#endif + + assert( cursorHoldsMutex(pCur) ); + rc = restoreCursorPosition(pCur); + if( rc==SQLITE_OK ){ + assert( pCur->eState==CURSOR_VALID ); + assert( pCur->pPage!=0 ); + assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell ); + rc = accessPayload(pCur, offset, amt, pBuf, 1, 0); + } + return rc; +} + +/* +** Return a pointer to payload information from the entry that the +** pCur cursor is pointing to. The pointer is to the beginning of +** the key if skipKey==0 and it points to the beginning of data if +** skipKey==1. The number of bytes of available key/data is written +** into *pAmt. If *pAmt==0, then the value returned will not be +** a valid pointer. +** +** This routine is an optimization. It is common for the entire key +** and data to fit on the local page and for there to be no overflow +** pages. When that is so, this routine can be used to access the +** key and data without making a copy. If the key and/or data spills +** onto overflow pages, then accessPayload() must be used to reassembly +** the key/data and copy it into a preallocated buffer. +** +** The pointer returned by this routine looks directly into the cached +** page of the database. The data might change or move the next time +** any btree routine is called. +*/ +static const unsigned char *fetchPayload( + BtCursor *pCur, /* Cursor pointing to entry to read from */ + int *pAmt, /* Write the number of available bytes here */ + int skipKey /* read beginning at data if this is true */ +){ + unsigned char *aPayload; + MemPage *pPage; + u32 nKey; + int nLocal; + + assert( pCur!=0 && pCur->pPage!=0 ); + assert( pCur->eState==CURSOR_VALID ); + assert( cursorHoldsMutex(pCur) ); + pPage = pCur->pPage; + assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); + getCellInfo(pCur); + aPayload = pCur->info.pCell; + aPayload += pCur->info.nHeader; + if( pPage->intKey ){ + nKey = 0; + }else{ + nKey = pCur->info.nKey; + } + if( skipKey ){ + aPayload += nKey; + nLocal = pCur->info.nLocal - nKey; + }else{ + nLocal = pCur->info.nLocal; + if( nLocal>nKey ){ + nLocal = nKey; + } + } + *pAmt = nLocal; + return aPayload; +} + + +/* +** For the entry that cursor pCur is point to, return as +** many bytes of the key or data as are available on the local +** b-tree page. Write the number of available bytes into *pAmt. +** +** The pointer returned is ephemeral. The key/data may move +** or be destroyed on the next call to any Btree routine, +** including calls from other threads against the same cache. +** Hence, a mutex on the BtShared should be held prior to calling +** this routine. +** +** These routines is used to get quick access to key and data +** in the common case where no overflow pages are used. +*/ +const void *sqlite3BtreeKeyFetch(BtCursor *pCur, int *pAmt){ + assert( cursorHoldsMutex(pCur) ); + if( pCur->eState==CURSOR_VALID ){ + return (const void*)fetchPayload(pCur, pAmt, 0); + } + return 0; +} +const void *sqlite3BtreeDataFetch(BtCursor *pCur, int *pAmt){ + assert( cursorHoldsMutex(pCur) ); + if( pCur->eState==CURSOR_VALID ){ + return (const void*)fetchPayload(pCur, pAmt, 1); + } + return 0; +} + + +/* +** Move the cursor down to a new child page. The newPgno argument is the +** page number of the child page to move to. +*/ +static int moveToChild(BtCursor *pCur, u32 newPgno){ + int rc; + MemPage *pNewPage; + MemPage *pOldPage; + BtShared *pBt = pCur->pBt; + + assert( cursorHoldsMutex(pCur) ); + assert( pCur->eState==CURSOR_VALID ); + rc = getAndInitPage(pBt, newPgno, &pNewPage, pCur->pPage); + if( rc ) return rc; + pNewPage->idxParent = pCur->idx; + pOldPage = pCur->pPage; + pOldPage->idxShift = 0; + releasePage(pOldPage); + pCur->pPage = pNewPage; + pCur->idx = 0; + pCur->info.nSize = 0; + pCur->validNKey = 0; + if( pNewPage->nCell<1 ){ + return SQLITE_CORRUPT_BKPT; + } + return SQLITE_OK; +} + +/* +** Return true if the page is the virtual root of its table. +** +** The virtual root page is the root page for most tables. But +** for the table rooted on page 1, sometime the real root page +** is empty except for the right-pointer. In such cases the +** virtual root page is the page that the right-pointer of page +** 1 is pointing to. +*/ +int sqlite3BtreeIsRootPage(MemPage *pPage){ + MemPage *pParent; + + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + pParent = pPage->pParent; + if( pParent==0 ) return 1; + if( pParent->pgno>1 ) return 0; + if( get2byte(&pParent->aData[pParent->hdrOffset+3])==0 ) return 1; + return 0; +} + +/* +** Move the cursor up to the parent page. +** +** pCur->idx is set to the cell index that contains the pointer +** to the page we are coming from. If we are coming from the +** right-most child page then pCur->idx is set to one more than +** the largest cell index. +*/ +void sqlite3BtreeMoveToParent(BtCursor *pCur){ + MemPage *pParent; + MemPage *pPage; + int idxParent; + + assert( cursorHoldsMutex(pCur) ); + assert( pCur->eState==CURSOR_VALID ); + pPage = pCur->pPage; + assert( pPage!=0 ); + assert( !sqlite3BtreeIsRootPage(pPage) ); + pParent = pPage->pParent; + assert( pParent!=0 ); + idxParent = pPage->idxParent; + sqlite3PagerRef(pParent->pDbPage); + releasePage(pPage); + pCur->pPage = pParent; + pCur->info.nSize = 0; + pCur->validNKey = 0; + assert( pParent->idxShift==0 ); + pCur->idx = idxParent; +} + +/* +** Move the cursor to the root page +*/ +static int moveToRoot(BtCursor *pCur){ + MemPage *pRoot; + int rc = SQLITE_OK; + Btree *p = pCur->pBtree; + BtShared *pBt = p->pBt; + + assert( cursorHoldsMutex(pCur) ); + assert( CURSOR_INVALID < CURSOR_REQUIRESEEK ); + assert( CURSOR_VALID < CURSOR_REQUIRESEEK ); + assert( CURSOR_FAULT > CURSOR_REQUIRESEEK ); + if( pCur->eState>=CURSOR_REQUIRESEEK ){ + if( pCur->eState==CURSOR_FAULT ){ + return pCur->skip; + } + clearCursorPosition(pCur); + } + 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); + pCur->pPage = pRoot; + } + pCur->idx = 0; + pCur->info.nSize = 0; + pCur->atLast = 0; + pCur->validNKey = 0; + if( pRoot->nCell==0 && !pRoot->leaf ){ + Pgno subpage; + assert( pRoot->pgno==1 ); + subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]); + assert( subpage>0 ); + pCur->eState = CURSOR_VALID; + rc = moveToChild(pCur, subpage); + } + 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 = SQLITE_OK; + MemPage *pPage; + + assert( cursorHoldsMutex(pCur) ); + assert( pCur->eState==CURSOR_VALID ); + while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){ + assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); + pgno = get4byte(findCell(pPage, pCur->idx)); + rc = moveToChild(pCur, pgno); + } + return rc; +} + +/* +** Move the cursor down to the right-most leaf entry beneath the +** page to which it is currently pointing. Notice the difference +** 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 = SQLITE_OK; + MemPage *pPage; + + assert( cursorHoldsMutex(pCur) ); + assert( pCur->eState==CURSOR_VALID ); + while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){ + pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); + pCur->idx = pPage->nCell; + rc = moveToChild(pCur, pgno); + } + if( rc==SQLITE_OK ){ + pCur->idx = pPage->nCell - 1; + pCur->info.nSize = 0; + pCur->validNKey = 0; + } + return SQLITE_OK; +} + +/* Move the cursor to the first entry in the table. Return SQLITE_OK +** on success. Set *pRes to 0 if the cursor actually points to something +** or set *pRes to 1 if the table is empty. +*/ +int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){ + int rc; + + assert( cursorHoldsMutex(pCur) ); + assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); + rc = moveToRoot(pCur); + if( rc==SQLITE_OK ){ + if( pCur->eState==CURSOR_INVALID ){ + assert( pCur->pPage->nCell==0 ); + *pRes = 1; + rc = SQLITE_OK; + }else{ + assert( pCur->pPage->nCell>0 ); + *pRes = 0; + rc = moveToLeftmost(pCur); + } + } + return rc; +} + +/* Move the cursor to the last entry in the table. Return SQLITE_OK +** on success. Set *pRes to 0 if the cursor actually points to something +** or set *pRes to 1 if the table is empty. +*/ +int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ + int rc; + + assert( cursorHoldsMutex(pCur) ); + assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); + rc = moveToRoot(pCur); + if( rc==SQLITE_OK ){ + if( CURSOR_INVALID==pCur->eState ){ + assert( pCur->pPage->nCell==0 ); + *pRes = 1; + }else{ + assert( pCur->eState==CURSOR_VALID ); + *pRes = 0; + rc = moveToRightmost(pCur); + getCellInfo(pCur); + pCur->atLast = rc==SQLITE_OK; + } + } + return rc; +} + +/* Move the cursor so that it points to an entry near the key +** specified by pKey/nKey/pUnKey. Return a success code. +** +** For INTKEY tables, only the nKey parameter is used. pKey +** and pUnKey must be NULL. For index tables, either pUnKey +** must point to a key that has already been unpacked, or else +** pKey/nKey describes a blob containing the key. +** +** If an exact match is not found, then the cursor is always +** left pointing at a leaf page which would hold the entry if it +** were present. The cursor might point to an entry that comes +** before or after the key. +** +** The result of comparing the key with the entry to which the +** cursor is written to *pRes if pRes!=NULL. The meaning of +** this value is as follows: +** +** *pRes<0 The cursor is left pointing at an entry that +** is smaller than pKey or if the table is empty +** and the cursor is therefore left point to nothing. +** +** *pRes==0 The cursor is left pointing at an entry that +** exactly matches pKey. +** +** *pRes>0 The cursor is left pointing at an entry that +** is larger than pKey. +** +*/ +int sqlite3BtreeMoveto( + BtCursor *pCur, /* The cursor to be moved */ + const void *pKey, /* The key content for indices. Not used by tables */ + UnpackedRecord *pUnKey,/* Unpacked version of pKey */ + i64 nKey, /* Size of pKey. Or the key for tables */ + int biasRight, /* If true, bias the search to the high end */ + int *pRes /* Search result flag */ +){ + int rc; + char aSpace[200]; + + assert( cursorHoldsMutex(pCur) ); + assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); + + /* If the cursor is already positioned at the point we are trying + ** to move to, then just return without doing any work */ + if( pCur->eState==CURSOR_VALID && pCur->validNKey && pCur->pPage->intKey ){ + if( pCur->info.nKey==nKey ){ + *pRes = 0; + return SQLITE_OK; + } + if( pCur->atLast && pCur->info.nKey<nKey ){ + *pRes = -1; + return SQLITE_OK; + } + } + + + rc = moveToRoot(pCur); + if( rc ){ + return rc; + } + assert( pCur->pPage ); + assert( pCur->pPage->isInit ); + if( pCur->eState==CURSOR_INVALID ){ + *pRes = -1; + assert( pCur->pPage->nCell==0 ); + return SQLITE_OK; + } + if( pCur->pPage->intKey ){ + /* We are given an SQL table to search. The key is the integer + ** rowid contained in nKey. pKey and pUnKey should both be NULL */ + assert( pUnKey==0 ); + assert( pKey==0 ); + }else if( pUnKey==0 ){ + /* We are to search an SQL index using a key encoded as a blob. + ** The blob is found at pKey and is nKey bytes in length. Unpack + ** this key so that we can use it. */ + assert( pKey!=0 ); + pUnKey = sqlite3VdbeRecordUnpack(pCur->pKeyInfo, nKey, pKey, + aSpace, sizeof(aSpace)); + if( pUnKey==0 ) return SQLITE_NOMEM; + }else{ + /* We are to search an SQL index using a key that is already unpacked + ** and handed to us in pUnKey. */ + assert( pKey==0 ); + } + for(;;){ + int lwr, upr; + Pgno chldPg; + MemPage *pPage = pCur->pPage; + int c = -1; /* pRes return if table is empty must be -1 */ + lwr = 0; + upr = pPage->nCell-1; + if( !pPage->intKey && pUnKey==0 ){ + rc = SQLITE_CORRUPT_BKPT; + goto moveto_finish; + } + if( biasRight ){ + pCur->idx = upr; + }else{ + pCur->idx = (upr+lwr)/2; + } + if( lwr<=upr ) for(;;){ + void *pCellKey; + i64 nCellKey; + pCur->info.nSize = 0; + pCur->validNKey = 1; + if( pPage->intKey ){ + u8 *pCell; + pCell = findCell(pPage, pCur->idx) + pPage->childPtrSize; + if( pPage->hasData ){ + u32 dummy; + pCell += getVarint32(pCell, dummy); + } + getVarint(pCell, (u64*)&nCellKey); + if( nCellKey==nKey ){ + c = 0; + }else if( nCellKey<nKey ){ + c = -1; + }else{ + assert( nCellKey>nKey ); + c = +1; + } + }else{ + int available; + pCellKey = (void *)fetchPayload(pCur, &available, 0); + nCellKey = pCur->info.nKey; + if( available>=nCellKey ){ + c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pUnKey); + }else{ + pCellKey = sqlite3Malloc( nCellKey ); + if( pCellKey==0 ){ + rc = SQLITE_NOMEM; + goto moveto_finish; + } + rc = sqlite3BtreeKey(pCur, 0, nCellKey, (void *)pCellKey); + c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pUnKey); + sqlite3_free(pCellKey); + if( rc ) goto moveto_finish; + } + } + if( c==0 ){ + pCur->info.nKey = nCellKey; + if( pPage->intKey && !pPage->leaf ){ + lwr = pCur->idx; + upr = lwr - 1; + break; + }else{ + if( pRes ) *pRes = 0; + rc = SQLITE_OK; + goto moveto_finish; + } + } + if( c<0 ){ + lwr = pCur->idx+1; + }else{ + upr = pCur->idx-1; + } + if( lwr>upr ){ + pCur->info.nKey = nCellKey; + break; + } + pCur->idx = (lwr+upr)/2; + } + assert( lwr==upr+1 ); + assert( pPage->isInit ); + if( pPage->leaf ){ + chldPg = 0; + }else if( lwr>=pPage->nCell ){ + chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]); + }else{ + chldPg = get4byte(findCell(pPage, lwr)); + } + if( chldPg==0 ){ + assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell ); + if( pRes ) *pRes = c; + rc = SQLITE_OK; + goto moveto_finish; + } + pCur->idx = lwr; + pCur->info.nSize = 0; + pCur->validNKey = 0; + rc = moveToChild(pCur, chldPg); + if( rc ) goto moveto_finish; + } +moveto_finish: + if( pKey ){ + /* If we created our own unpacked key at the top of this + ** procedure, then destroy that key before returning. */ + sqlite3VdbeDeleteUnpackedRecord(pUnKey); + } + return rc; +} + + +/* +** Return TRUE if the cursor is not pointing at an entry of the table. +** +** TRUE will be returned after a call to sqlite3BtreeNext() moves +** past the last entry in the table or sqlite3BtreePrev() moves past +** the first entry. TRUE is also returned if the table is empty. +*/ +int sqlite3BtreeEof(BtCursor *pCur){ + /* 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); +} + +/* +** Return the database connection handle for a cursor. +*/ +sqlite3 *sqlite3BtreeCursorDb(const BtCursor *pCur){ + assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); + return pCur->pBtree->db; +} + +/* +** Advance the cursor to the next entry in the database. If +** successful then set *pRes=0. If the cursor +** was already pointing to the last entry in the database before +** this routine was called, then set *pRes=1. +*/ +int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ + int rc; + MemPage *pPage; + + assert( cursorHoldsMutex(pCur) ); + rc = restoreCursorPosition(pCur); + if( rc!=SQLITE_OK ){ + return rc; + } + assert( pRes!=0 ); + pPage = pCur->pPage; + if( CURSOR_INVALID==pCur->eState ){ + *pRes = 1; + return SQLITE_OK; + } + if( pCur->skip>0 ){ + pCur->skip = 0; + *pRes = 0; + return SQLITE_OK; + } + pCur->skip = 0; + + assert( pPage->isInit ); + assert( pCur->idx<pPage->nCell ); + + pCur->idx++; + pCur->info.nSize = 0; + pCur->validNKey = 0; + if( pCur->idx>=pPage->nCell ){ + if( !pPage->leaf ){ + rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8])); + if( rc ) return rc; + rc = moveToLeftmost(pCur); + *pRes = 0; + return rc; + } + do{ + if( sqlite3BtreeIsRootPage(pPage) ){ + *pRes = 1; + pCur->eState = CURSOR_INVALID; + return SQLITE_OK; + } + sqlite3BtreeMoveToParent(pCur); + pPage = pCur->pPage; + }while( pCur->idx>=pPage->nCell ); + *pRes = 0; + if( pPage->intKey ){ + rc = sqlite3BtreeNext(pCur, pRes); + }else{ + rc = SQLITE_OK; + } + return rc; + } + *pRes = 0; + if( pPage->leaf ){ + return SQLITE_OK; + } + rc = moveToLeftmost(pCur); + return rc; +} + + +/* +** Step the cursor to the back to the previous entry in the database. If +** successful then set *pRes=0. If the cursor +** was already pointing to the first entry in the database before +** this routine was called, then set *pRes=1. +*/ +int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ + int rc; + Pgno pgno; + MemPage *pPage; + + assert( cursorHoldsMutex(pCur) ); + rc = restoreCursorPosition(pCur); + if( rc!=SQLITE_OK ){ + return rc; + } + pCur->atLast = 0; + if( CURSOR_INVALID==pCur->eState ){ + *pRes = 1; + return SQLITE_OK; + } + if( pCur->skip<0 ){ + pCur->skip = 0; + *pRes = 0; + return SQLITE_OK; + } + pCur->skip = 0; + + pPage = pCur->pPage; + assert( pPage->isInit ); + assert( pCur->idx>=0 ); + if( !pPage->leaf ){ + pgno = get4byte( findCell(pPage, pCur->idx) ); + rc = moveToChild(pCur, pgno); + if( rc ){ + return rc; + } + rc = moveToRightmost(pCur); + }else{ + while( pCur->idx==0 ){ + if( sqlite3BtreeIsRootPage(pPage) ){ + pCur->eState = CURSOR_INVALID; + *pRes = 1; + return SQLITE_OK; + } + sqlite3BtreeMoveToParent(pCur); + pPage = pCur->pPage; + } + pCur->idx--; + pCur->info.nSize = 0; + pCur->validNKey = 0; + if( pPage->intKey && !pPage->leaf ){ + rc = sqlite3BtreePrevious(pCur, pRes); + }else{ + rc = SQLITE_OK; + } + } + *pRes = 0; + return rc; +} + +/* +** Allocate a new page from the database file. +** +** The new page is marked as dirty. (In other words, sqlite3PagerWrite() +** has already been called on the new page.) The new page has also +** been referenced and the calling routine is responsible for calling +** sqlite3PagerUnref() on the new page when it is done. +** +** SQLITE_OK is returned on success. Any other return value indicates +** an error. *ppPage and *pPgno are undefined in the event of an error. +** Do not invoke sqlite3PagerUnref() on *ppPage if an error is returned. +** +** If the "nearby" parameter is not 0, then a (feeble) effort is made to +** locate a page close to the page number "nearby". This can be used in an +** attempt to keep related pages close to each other in the database file, +** which in turn can make database access faster. +** +** If the "exact" parameter is not 0, and the page-number nearby exists +** anywhere on the free-list, then it is guarenteed to be returned. This +** is only used by auto-vacuum databases when allocating a new table. +*/ +static int allocateBtreePage( + BtShared *pBt, + MemPage **ppPage, + Pgno *pPgno, + Pgno nearby, + u8 exact +){ + MemPage *pPage1; + int rc; + int n; /* Number of pages on the freelist */ + int k; /* Number of leaves on the trunk of the freelist */ + MemPage *pTrunk = 0; + MemPage *pPrevTrunk = 0; + + assert( sqlite3_mutex_held(pBt->mutex) ); + pPage1 = pBt->pPage1; + n = get4byte(&pPage1->aData[36]); + if( n>0 ){ + /* There are pages on the freelist. Reuse one of those pages. */ + Pgno iTrunk; + u8 searchList = 0; /* If the free-list must be searched for 'nearby' */ + + /* If the 'exact' parameter was true and a query of the pointer-map + ** shows that the page 'nearby' is somewhere on the free-list, then + ** the entire-list will be searched for that page. + */ +#ifndef SQLITE_OMIT_AUTOVACUUM + if( exact && nearby<=pagerPagecount(pBt->pPager) ){ + u8 eType; + assert( nearby>0 ); + assert( pBt->autoVacuum ); + rc = ptrmapGet(pBt, nearby, &eType, 0); + if( rc ) return rc; + if( eType==PTRMAP_FREEPAGE ){ + searchList = 1; + } + *pPgno = nearby; + } +#endif + + /* Decrement the free-list count by 1. Set iTrunk to the index of the + ** first free-list trunk page. iPrevTrunk is initially 1. + */ + rc = sqlite3PagerWrite(pPage1->pDbPage); + if( rc ) return rc; + put4byte(&pPage1->aData[36], n-1); + + /* The code within this loop is run only once if the 'searchList' variable + ** is not true. Otherwise, it runs once for each trunk-page on the + ** free-list until the page 'nearby' is located. + */ + do { + pPrevTrunk = pTrunk; + if( pPrevTrunk ){ + iTrunk = get4byte(&pPrevTrunk->aData[0]); + }else{ + iTrunk = get4byte(&pPage1->aData[32]); + } + rc = sqlite3BtreeGetPage(pBt, iTrunk, &pTrunk, 0); + if( rc ){ + pTrunk = 0; + goto end_allocate_page; + } + + k = get4byte(&pTrunk->aData[4]); + if( k==0 && !searchList ){ + /* The trunk has no leaves and the list is not being searched. + ** So extract the trunk page itself and use it as the newly + ** allocated page */ + assert( pPrevTrunk==0 ); + rc = sqlite3PagerWrite(pTrunk->pDbPage); + if( rc ){ + goto end_allocate_page; + } + *pPgno = iTrunk; + memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4); + *ppPage = pTrunk; + pTrunk = 0; + TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); + }else if( k>pBt->usableSize/4 - 2 ){ + /* Value of k is out of range. Database corruption */ + rc = SQLITE_CORRUPT_BKPT; + goto end_allocate_page; +#ifndef SQLITE_OMIT_AUTOVACUUM + }else if( searchList && nearby==iTrunk ){ + /* The list is being searched and this trunk page is the page + ** to allocate, regardless of whether it has leaves. + */ + assert( *pPgno==iTrunk ); + *ppPage = pTrunk; + searchList = 0; + rc = sqlite3PagerWrite(pTrunk->pDbPage); + if( rc ){ + goto end_allocate_page; + } + if( k==0 ){ + if( !pPrevTrunk ){ + memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4); + }else{ + memcpy(&pPrevTrunk->aData[0], &pTrunk->aData[0], 4); + } + }else{ + /* The trunk page is required by the caller but it contains + ** pointers to free-list leaves. The first leaf becomes a trunk + ** page in this case. + */ + MemPage *pNewTrunk; + Pgno iNewTrunk = get4byte(&pTrunk->aData[8]); + rc = sqlite3BtreeGetPage(pBt, iNewTrunk, &pNewTrunk, 0); + if( rc!=SQLITE_OK ){ + goto end_allocate_page; + } + rc = sqlite3PagerWrite(pNewTrunk->pDbPage); + if( rc!=SQLITE_OK ){ + releasePage(pNewTrunk); + goto end_allocate_page; + } + memcpy(&pNewTrunk->aData[0], &pTrunk->aData[0], 4); + put4byte(&pNewTrunk->aData[4], k-1); + memcpy(&pNewTrunk->aData[8], &pTrunk->aData[12], (k-1)*4); + releasePage(pNewTrunk); + if( !pPrevTrunk ){ + put4byte(&pPage1->aData[32], iNewTrunk); + }else{ + rc = sqlite3PagerWrite(pPrevTrunk->pDbPage); + if( rc ){ + goto end_allocate_page; + } + put4byte(&pPrevTrunk->aData[0], iNewTrunk); + } + } + pTrunk = 0; + TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); +#endif + }else{ + /* Extract a leaf from the trunk */ + int closest; + Pgno iPage; + unsigned char *aData = pTrunk->aData; + rc = sqlite3PagerWrite(pTrunk->pDbPage); + if( rc ){ + goto end_allocate_page; + } + if( nearby>0 ){ + int i, dist; + closest = 0; + dist = get4byte(&aData[8]) - nearby; + if( dist<0 ) dist = -dist; + for(i=1; i<k; i++){ + int d2 = get4byte(&aData[8+i*4]) - nearby; + if( d2<0 ) d2 = -d2; + if( d2<dist ){ + closest = i; + dist = d2; + } + } + }else{ + closest = 0; + } + + iPage = get4byte(&aData[8+closest*4]); + if( !searchList || iPage==nearby ){ + int nPage; + *pPgno = iPage; + nPage = pagerPagecount(pBt->pPager); + if( *pPgno>nPage ){ + /* Free page off the end of the file */ + rc = SQLITE_CORRUPT_BKPT; + goto end_allocate_page; + } + TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d" + ": %d more free pages\n", + *pPgno, closest+1, k, pTrunk->pgno, n-1)); + if( closest<k-1 ){ + memcpy(&aData[8+closest*4], &aData[4+k*4], 4); + } + put4byte(&aData[4], k-1); + rc = sqlite3BtreeGetPage(pBt, *pPgno, ppPage, 1); + if( rc==SQLITE_OK ){ + sqlite3PagerDontRollback((*ppPage)->pDbPage); + rc = sqlite3PagerWrite((*ppPage)->pDbPage); + if( rc!=SQLITE_OK ){ + releasePage(*ppPage); + } + } + searchList = 0; + } + } + releasePage(pPrevTrunk); + pPrevTrunk = 0; + }while( searchList ); + }else{ + /* There are no pages on the freelist, so create a new page at the + ** end of the file */ + int nPage = pagerPagecount(pBt->pPager); + *pPgno = nPage + 1; + +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->nTrunc ){ + /* An incr-vacuum has already run within this transaction. So the + ** page to allocate is not from the physical end of the file, but + ** at pBt->nTrunc. + */ + *pPgno = pBt->nTrunc+1; + if( *pPgno==PENDING_BYTE_PAGE(pBt) ){ + (*pPgno)++; + } + } + if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, *pPgno) ){ + /* If *pPgno refers to a pointer-map page, allocate two new pages + ** at the end of the file instead of one. The first allocated page + ** becomes a new pointer-map page, the second is used by the caller. + */ + TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", *pPgno)); + assert( *pPgno!=PENDING_BYTE_PAGE(pBt) ); + (*pPgno)++; + if( *pPgno==PENDING_BYTE_PAGE(pBt) ){ (*pPgno)++; } + } + if( pBt->nTrunc ){ + pBt->nTrunc = *pPgno; + } +#endif + + assert( *pPgno!=PENDING_BYTE_PAGE(pBt) ); + rc = sqlite3BtreeGetPage(pBt, *pPgno, ppPage, 0); + if( rc ) return rc; + rc = sqlite3PagerWrite((*ppPage)->pDbPage); + if( rc!=SQLITE_OK ){ + releasePage(*ppPage); + } + TRACE(("ALLOCATE: %d from end of file\n", *pPgno)); + } + + assert( *pPgno!=PENDING_BYTE_PAGE(pBt) ); + +end_allocate_page: + releasePage(pTrunk); + releasePage(pPrevTrunk); + return rc; +} + +/* +** Add a page of the database file to the freelist. +** +** sqlite3PagerUnref() is NOT called for pPage. +*/ +static int freePage(MemPage *pPage){ + BtShared *pBt = pPage->pBt; + MemPage *pPage1 = pBt->pPage1; + int rc, n, k; + + /* Prepare the page for freeing */ + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + assert( pPage->pgno>1 ); + pPage->isInit = 0; + releasePage(pPage->pParent); + pPage->pParent = 0; + + /* Increment the free page count on pPage1 */ + rc = sqlite3PagerWrite(pPage1->pDbPage); + if( rc ) return rc; + n = get4byte(&pPage1->aData[36]); + put4byte(&pPage1->aData[36], n+1); + +#ifdef SQLITE_SECURE_DELETE + /* If the SQLITE_SECURE_DELETE compile-time option is enabled, then + ** always fully overwrite deleted information with zeros. + */ + rc = sqlite3PagerWrite(pPage->pDbPage); + if( rc ) return rc; + memset(pPage->aData, 0, pPage->pBt->pageSize); +#endif + + /* If the database supports auto-vacuum, write an entry in the pointer-map + ** to indicate that the page is free. + */ + if( ISAUTOVACUUM ){ + rc = ptrmapPut(pBt, pPage->pgno, PTRMAP_FREEPAGE, 0); + if( rc ) return rc; + } + + if( n==0 ){ + /* This is the first free page */ + rc = sqlite3PagerWrite(pPage->pDbPage); + if( rc ) return rc; + memset(pPage->aData, 0, 8); + put4byte(&pPage1->aData[32], pPage->pgno); + TRACE(("FREE-PAGE: %d first\n", pPage->pgno)); + }else{ + /* Other free pages already exist. Retrive the first trunk page + ** of the freelist and find out how many leaves it has. */ + MemPage *pTrunk; + rc = sqlite3BtreeGetPage(pBt, get4byte(&pPage1->aData[32]), &pTrunk, 0); + if( rc ) return rc; + k = get4byte(&pTrunk->aData[4]); + if( k>=pBt->usableSize/4 - 8 ){ + /* The trunk is full. Turn the page being freed into a new + ** trunk page with no leaves. + ** + ** Note that the trunk page is not really full until it contains + ** usableSize/4 - 2 entries, not usableSize/4 - 8 entries as we have + ** coded. But due to a coding error in versions of SQLite prior to + ** 3.6.0, databases with freelist trunk pages holding more than + ** usableSize/4 - 8 entries will be reported as corrupt. In order + ** to maintain backwards compatibility with older versions of SQLite, + ** we will contain to restrict the number of entries to usableSize/4 - 8 + ** for now. At some point in the future (once everyone has upgraded + ** to 3.6.0 or later) we should consider fixing the conditional above + ** to read "usableSize/4-2" instead of "usableSize/4-8". + */ + rc = sqlite3PagerWrite(pPage->pDbPage); + if( rc==SQLITE_OK ){ + put4byte(pPage->aData, pTrunk->pgno); + put4byte(&pPage->aData[4], 0); + put4byte(&pPage1->aData[32], pPage->pgno); + TRACE(("FREE-PAGE: %d new trunk page replacing %d\n", + pPage->pgno, pTrunk->pgno)); + } + }else if( k<0 ){ + rc = SQLITE_CORRUPT; + }else{ + /* Add the newly freed page as a leaf on the current trunk */ + rc = sqlite3PagerWrite(pTrunk->pDbPage); + if( rc==SQLITE_OK ){ + put4byte(&pTrunk->aData[4], k+1); + put4byte(&pTrunk->aData[8+k*4], pPage->pgno); +#ifndef SQLITE_SECURE_DELETE + sqlite3PagerDontWrite(pPage->pDbPage); +#endif + } + TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno)); + } + releasePage(pTrunk); + } + return rc; +} + +/* +** Free any overflow pages associated with the given Cell. +*/ +static int clearCell(MemPage *pPage, unsigned char *pCell){ + BtShared *pBt = pPage->pBt; + CellInfo info; + Pgno ovflPgno; + int rc; + int nOvfl; + int ovflPageSize; + + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + sqlite3BtreeParseCellPtr(pPage, pCell, &info); + if( info.iOverflow==0 ){ + return SQLITE_OK; /* No overflow pages. Return without doing anything */ + } + ovflPgno = get4byte(&pCell[info.iOverflow]); + ovflPageSize = pBt->usableSize - 4; + nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize; + assert( ovflPgno==0 || nOvfl>0 ); + while( nOvfl-- ){ + MemPage *pOvfl; + if( ovflPgno==0 || ovflPgno>pagerPagecount(pBt->pPager) ){ + return SQLITE_CORRUPT_BKPT; + } + + rc = getOverflowPage(pBt, ovflPgno, &pOvfl, (nOvfl==0)?0:&ovflPgno); + if( rc ) return rc; + rc = freePage(pOvfl); + sqlite3PagerUnref(pOvfl->pDbPage); + if( rc ) return rc; + } + return SQLITE_OK; +} + +/* +** Create the byte sequence used to represent a cell on page pPage +** and write that byte sequence into pCell[]. Overflow pages are +** allocated and filled in as necessary. The calling procedure +** is responsible for making sure sufficient space has been allocated +** for pCell[]. +** +** Note that pCell does not necessary need to point to the pPage->aData +** area. pCell might point to some temporary storage. The cell will +** be constructed in this temporary area then copied into pPage->aData +** later. +*/ +static int fillInCell( + MemPage *pPage, /* The page that contains the cell */ + unsigned char *pCell, /* Complete text of the cell */ + const void *pKey, i64 nKey, /* The key */ + const void *pData,int nData, /* The data */ + int nZero, /* Extra zero bytes to append to pData */ + int *pnSize /* Write cell size here */ +){ + int nPayload; + const u8 *pSrc; + int nSrc, n, rc; + int spaceLeft; + MemPage *pOvfl = 0; + MemPage *pToRelease = 0; + unsigned char *pPrior; + unsigned char *pPayload; + BtShared *pBt = pPage->pBt; + Pgno pgnoOvfl = 0; + int nHeader; + CellInfo info; + + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + + /* Fill in the header. */ + nHeader = 0; + if( !pPage->leaf ){ + nHeader += 4; + } + if( pPage->hasData ){ + nHeader += putVarint(&pCell[nHeader], nData+nZero); + }else{ + nData = nZero = 0; + } + nHeader += putVarint(&pCell[nHeader], *(u64*)&nKey); + sqlite3BtreeParseCellPtr(pPage, pCell, &info); + assert( info.nHeader==nHeader ); + assert( info.nKey==nKey ); + assert( info.nData==nData+nZero ); + + /* Fill in the payload */ + nPayload = nData + nZero; + if( pPage->intKey ){ + pSrc = pData; + nSrc = nData; + nData = 0; + }else{ + nPayload += nKey; + pSrc = pKey; + nSrc = nKey; + } + *pnSize = info.nSize; + spaceLeft = info.nLocal; + pPayload = &pCell[nHeader]; + pPrior = &pCell[info.iOverflow]; + + while( nPayload>0 ){ + if( spaceLeft==0 ){ + int isExact = 0; +#ifndef SQLITE_OMIT_AUTOVACUUM + Pgno pgnoPtrmap = pgnoOvfl; /* Overflow page pointer-map entry page */ + if( pBt->autoVacuum ){ + do{ + pgnoOvfl++; + } while( + PTRMAP_ISPAGE(pBt, pgnoOvfl) || pgnoOvfl==PENDING_BYTE_PAGE(pBt) + ); + if( pgnoOvfl>1 ){ + /* isExact = 1; */ + } + } +#endif + rc = allocateBtreePage(pBt, &pOvfl, &pgnoOvfl, pgnoOvfl, isExact); +#ifndef SQLITE_OMIT_AUTOVACUUM + /* If the database supports auto-vacuum, and the second or subsequent + ** overflow page is being allocated, add an entry to the pointer-map + ** for that page now. + ** + ** If this is the first overflow page, then write a partial entry + ** to the pointer-map. If we write nothing to this pointer-map slot, + ** then the optimistic overflow chain processing in clearCell() + ** may misinterpret the uninitialised values and delete the + ** wrong pages from the database. + */ + if( pBt->autoVacuum && rc==SQLITE_OK ){ + u8 eType = (pgnoPtrmap?PTRMAP_OVERFLOW2:PTRMAP_OVERFLOW1); + rc = ptrmapPut(pBt, pgnoOvfl, eType, pgnoPtrmap); + if( rc ){ + releasePage(pOvfl); + } + } +#endif + if( rc ){ + releasePage(pToRelease); + return rc; + } + put4byte(pPrior, pgnoOvfl); + releasePage(pToRelease); + pToRelease = pOvfl; + pPrior = pOvfl->aData; + put4byte(pPrior, 0); + pPayload = &pOvfl->aData[4]; + spaceLeft = pBt->usableSize - 4; + } + n = nPayload; + if( n>spaceLeft ) n = spaceLeft; + if( nSrc>0 ){ + if( n>nSrc ) n = nSrc; + assert( pSrc ); + memcpy(pPayload, pSrc, n); + }else{ + memset(pPayload, 0, n); + } + nPayload -= n; + pPayload += n; + pSrc += n; + nSrc -= n; + spaceLeft -= n; + if( nSrc==0 ){ + nSrc = nData; + pSrc = pData; + } + } + releasePage(pToRelease); + return SQLITE_OK; +} + + +/* +** Change the MemPage.pParent pointer on the page whose number is +** given in the second argument so that MemPage.pParent holds the +** pointer in the third argument. +** +** If the final argument, updatePtrmap, is non-zero and the database +** is an auto-vacuum database, then the pointer-map entry for pgno +** is updated. +*/ +static int reparentPage( + BtShared *pBt, /* B-Tree structure */ + Pgno pgno, /* Page number of child being adopted */ + MemPage *pNewParent, /* New parent of pgno */ + int idx, /* Index of child page pgno in pNewParent */ + int updatePtrmap /* If true, update pointer-map for pgno */ +){ + MemPage *pThis; + DbPage *pDbPage; + + assert( sqlite3_mutex_held(pBt->mutex) ); + assert( pNewParent!=0 ); + if( pgno==0 ) return SQLITE_OK; + assert( pBt->pPager!=0 ); + pDbPage = sqlite3PagerLookup(pBt->pPager, pgno); + if( pDbPage ){ + pThis = (MemPage *)sqlite3PagerGetExtra(pDbPage); + if( pThis->isInit ){ + assert( pThis->aData==sqlite3PagerGetData(pDbPage) ); + if( pThis->pParent!=pNewParent ){ + if( pThis->pParent ) sqlite3PagerUnref(pThis->pParent->pDbPage); + pThis->pParent = pNewParent; + sqlite3PagerRef(pNewParent->pDbPage); + } + pThis->idxParent = idx; + } + sqlite3PagerUnref(pDbPage); + } + + if( ISAUTOVACUUM && updatePtrmap ){ + return ptrmapPut(pBt, pgno, PTRMAP_BTREE, pNewParent->pgno); + } + +#ifndef NDEBUG + /* If the updatePtrmap flag was clear, assert that the entry in the + ** pointer-map is already correct. + */ + if( ISAUTOVACUUM ){ + pDbPage = sqlite3PagerLookup(pBt->pPager,PTRMAP_PAGENO(pBt,pgno)); + if( pDbPage ){ + u8 eType; + Pgno ii; + int rc = ptrmapGet(pBt, pgno, &eType, &ii); + assert( rc==SQLITE_OK && ii==pNewParent->pgno && eType==PTRMAP_BTREE ); + sqlite3PagerUnref(pDbPage); + } + } +#endif + + return SQLITE_OK; +} + + + +/* +** Change the pParent pointer of all children of pPage to point back +** to pPage. +** +** In other words, for every child of pPage, invoke reparentPage() +** to make sure that each child knows that pPage is its parent. +** +** This routine gets called after you memcpy() one page into +** another. +** +** If updatePtrmap is true, then the pointer-map entries for all child +** pages of pPage are updated. +*/ +static int reparentChildPages(MemPage *pPage, int updatePtrmap){ + int rc = SQLITE_OK; + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + if( !pPage->leaf ){ + int i; + BtShared *pBt = pPage->pBt; + Pgno iRight = get4byte(&pPage->aData[pPage->hdrOffset+8]); + + for(i=0; i<pPage->nCell; i++){ + u8 *pCell = findCell(pPage, i); + rc = reparentPage(pBt, get4byte(pCell), pPage, i, updatePtrmap); + if( rc!=SQLITE_OK ) return rc; + } + rc = reparentPage(pBt, iRight, pPage, i, updatePtrmap); + pPage->idxShift = 0; + } + return rc; +} + +/* +** Remove the i-th cell from pPage. This routine effects pPage only. +** The cell content is not freed or deallocated. It is assumed that +** the cell content has been copied someplace else. This routine just +** removes the reference to the cell from pPage. +** +** "sz" must be the number of bytes in the cell. +*/ +static void dropCell(MemPage *pPage, int idx, int sz){ + int i; /* Loop counter */ + int pc; /* Offset to cell content of cell being deleted */ + u8 *data; /* pPage->aData */ + u8 *ptr; /* Used to move bytes around within data[] */ + + assert( idx>=0 && idx<pPage->nCell ); + assert( sz==cellSize(pPage, idx) ); + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + data = pPage->aData; + ptr = &data[pPage->cellOffset + 2*idx]; + pc = get2byte(ptr); + assert( pc>10 && pc+sz<=pPage->pBt->usableSize ); + freeSpace(pPage, pc, sz); + for(i=idx+1; i<pPage->nCell; i++, ptr+=2){ + ptr[0] = ptr[2]; + ptr[1] = ptr[3]; + } + pPage->nCell--; + put2byte(&data[pPage->hdrOffset+3], pPage->nCell); + pPage->nFree += 2; + pPage->idxShift = 1; +} + +/* +** Insert a new cell on pPage at cell index "i". pCell points to the +** content of the cell. +** +** If the cell content will fit on the page, then put it there. If it +** will not fit, then make a copy of the cell content into pTemp if +** pTemp is not null. Regardless of pTemp, allocate a new entry +** in pPage->aOvfl[] and make it point to the cell content (either +** in pTemp or the original pCell) and also record its index. +** Allocating a new entry in pPage->aCell[] implies that +** pPage->nOverflow is incremented. +** +** If nSkip is non-zero, then do not copy the first nSkip bytes of the +** cell. The caller will overwrite them after this function returns. If +** nSkip is non-zero, then pCell may not point to an invalid memory location +** (but pCell+nSkip is always valid). +*/ +static int insertCell( + MemPage *pPage, /* Page into which we are copying */ + int i, /* New cell becomes the i-th cell of the page */ + u8 *pCell, /* Content of the new cell */ + int sz, /* Bytes of content in pCell */ + u8 *pTemp, /* Temp storage space for pCell, if needed */ + u8 nSkip /* Do not write the first nSkip bytes of the cell */ +){ + int idx; /* Where to write new cell content in data[] */ + int j; /* Loop counter */ + int top; /* First byte of content for any cell in data[] */ + int end; /* First byte past the last cell pointer in data[] */ + int ins; /* Index in data[] where new cell pointer is inserted */ + int hdr; /* Offset into data[] of the page header */ + int cellOffset; /* Address of first cell pointer in data[] */ + u8 *data; /* The content of the whole page */ + u8 *ptr; /* Used for moving information around in data[] */ + + assert( i>=0 && i<=pPage->nCell+pPage->nOverflow ); + assert( sz==cellSizePtr(pPage, pCell) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + if( pPage->nOverflow || sz+2>pPage->nFree ){ + if( pTemp ){ + memcpy(pTemp+nSkip, pCell+nSkip, sz-nSkip); + pCell = pTemp; + } + j = pPage->nOverflow++; + assert( j<sizeof(pPage->aOvfl)/sizeof(pPage->aOvfl[0]) ); + pPage->aOvfl[j].pCell = pCell; + pPage->aOvfl[j].idx = i; + pPage->nFree = 0; + }else{ + int rc = sqlite3PagerWrite(pPage->pDbPage); + if( rc!=SQLITE_OK ){ + return rc; + } + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + data = pPage->aData; + hdr = pPage->hdrOffset; + top = get2byte(&data[hdr+5]); + cellOffset = pPage->cellOffset; + end = cellOffset + 2*pPage->nCell + 2; + ins = cellOffset + 2*i; + if( end > top - sz ){ + defragmentPage(pPage); + top = get2byte(&data[hdr+5]); + assert( end + sz <= top ); + } + idx = allocateSpace(pPage, sz); + assert( idx>0 ); + assert( end <= get2byte(&data[hdr+5]) ); + pPage->nCell++; + pPage->nFree -= 2; + memcpy(&data[idx+nSkip], pCell+nSkip, sz-nSkip); + for(j=end-2, ptr=&data[j]; j>ins; j-=2, ptr-=2){ + ptr[0] = ptr[-2]; + ptr[1] = ptr[-1]; + } + put2byte(&data[ins], idx); + put2byte(&data[hdr+3], pPage->nCell); + pPage->idxShift = 1; +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pPage->pBt->autoVacuum ){ + /* The cell may contain a pointer to an overflow page. If so, write + ** the entry for the overflow page into the pointer map. + */ + CellInfo info; + sqlite3BtreeParseCellPtr(pPage, pCell, &info); + assert( (info.nData+(pPage->intKey?0:info.nKey))==info.nPayload ); + if( (info.nData+(pPage->intKey?0:info.nKey))>info.nLocal ){ + Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]); + rc = ptrmapPut(pPage->pBt, pgnoOvfl, PTRMAP_OVERFLOW1, pPage->pgno); + if( rc!=SQLITE_OK ) return rc; + } + } +#endif + } + + return SQLITE_OK; +} + +/* +** Add a list of cells to a page. The page should be initially empty. +** The cells are guaranteed to fit on the page. +*/ +static void assemblePage( + MemPage *pPage, /* The page to be assemblied */ + int nCell, /* The number of cells to add to this page */ + u8 **apCell, /* Pointers to cell bodies */ + u16 *aSize /* Sizes of the cells */ +){ + int i; /* Loop counter */ + int totalSize; /* Total size of all cells */ + int hdr; /* Index of page header */ + int cellptr; /* Address of next cell pointer */ + int cellbody; /* Address of next cell body */ + u8 *data; /* Data for the page */ + + assert( pPage->nOverflow==0 ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + totalSize = 0; + for(i=0; i<nCell; i++){ + totalSize += aSize[i]; + } + assert( totalSize+2*nCell<=pPage->nFree ); + assert( pPage->nCell==0 ); + cellptr = pPage->cellOffset; + data = pPage->aData; + hdr = pPage->hdrOffset; + put2byte(&data[hdr+3], nCell); + if( nCell ){ + cellbody = allocateSpace(pPage, totalSize); + assert( cellbody>0 ); + assert( pPage->nFree >= 2*nCell ); + pPage->nFree -= 2*nCell; + for(i=0; i<nCell; i++){ + put2byte(&data[cellptr], cellbody); + memcpy(&data[cellbody], apCell[i], aSize[i]); + cellptr += 2; + cellbody += aSize[i]; + } + assert( cellbody==pPage->pBt->usableSize ); + } + pPage->nCell = nCell; +} + +/* +** The following parameters determine how many adjacent pages get involved +** in a balancing operation. NN is the number of neighbors on either side +** of the page that participate in the balancing operation. NB is the +** total number of pages that participate, including the target page and +** NN neighbors on either side. +** +** The minimum value of NN is 1 (of course). Increasing NN above 1 +** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance +** in exchange for a larger degradation in INSERT and UPDATE performance. +** The value of NN appears to give the best results overall. +*/ +#define NN 1 /* Number of neighbors on either side of pPage */ +#define NB (NN*2+1) /* Total pages involved in the balance */ + +/* Forward reference */ +static int balance(MemPage*, int); + +#ifndef SQLITE_OMIT_QUICKBALANCE +/* +** This version of balance() handles the common special case where +** a new entry is being inserted on the extreme right-end of the +** tree, in other words, when the new entry will become the largest +** entry in the tree. +** +** Instead of trying balance the 3 right-most leaf pages, just add +** a new page to the right-hand side and put the one new entry in +** that page. This leaves the right side of the tree somewhat +** unbalanced. But odds are that we will be inserting new entries +** at the end soon afterwards so the nearly empty page will quickly +** fill up. On average. +** +** pPage is the leaf page which is the right-most page in the tree. +** pParent is its parent. pPage must have a single overflow entry +** which is also the right-most entry on the page. +*/ +static int balance_quick(MemPage *pPage, MemPage *pParent){ + int rc; + MemPage *pNew; + Pgno pgnoNew; + u8 *pCell; + u16 szCell; + CellInfo info; + 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 */ + + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + + /* Allocate a new page. Insert the overflow cell from pPage + ** into it. Then remove the overflow cell from pPage. + */ + rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + pCell = pPage->aOvfl[0].pCell; + szCell = cellSizePtr(pPage, pCell); + zeroPage(pNew, pPage->aData[0]); + assemblePage(pNew, 1, &pCell, &szCell); + pPage->nOverflow = 0; + + /* Set the parent of the newly allocated page to pParent. */ + pNew->pParent = pParent; + sqlite3PagerRef(pParent->pDbPage); + + /* pPage is currently the right-child of pParent. Change this + ** so that the right-child is the new page allocated above and + ** pPage is the next-to-right child. + ** + ** Ignore the return value of the call to fillInCell(). fillInCell() + ** may only return other than SQLITE_OK if it is required to allocate + ** one or more overflow pages. Since an internal table B-Tree cell + ** may never spill over onto an overflow page (it is a maximum of + ** 13 bytes in size), it is not neccessary to check the return code. + ** + ** Similarly, the insertCell() function cannot fail if the page + ** being inserted into is already writable and the cell does not + ** contain an overflow pointer. So ignore this return code too. + */ + assert( pPage->nCell>0 ); + pCell = findCell(pPage, pPage->nCell-1); + sqlite3BtreeParseCellPtr(pPage, pCell, &info); + fillInCell(pParent, parentCell, 0, info.nKey, 0, 0, 0, &parentSize); + assert( parentSize<64 ); + assert( sqlite3PagerIswriteable(pParent->pDbPage) ); + insertCell(pParent, parentIdx, parentCell, parentSize, 0, 4); + put4byte(findOverflowCell(pParent,parentIdx), pPage->pgno); + put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew); + + /* If this is an auto-vacuum database, update the pointer map + ** with entries for the new page, and any pointer from the + ** cell on the page to an overflow page. + */ + if( ISAUTOVACUUM ){ + rc = ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno); + if( rc==SQLITE_OK ){ + rc = ptrmapPutOvfl(pNew, 0); + } + if( rc!=SQLITE_OK ){ + releasePage(pNew); + return rc; + } + } + + /* Release the reference to the new page and balance the parent page, + ** in case the divider cell inserted caused it to become overfull. + */ + releasePage(pNew); + return balance(pParent, 0); +} +#endif /* SQLITE_OMIT_QUICKBALANCE */ + +/* +** This routine redistributes Cells on pPage and up to NN*2 siblings +** of pPage so that all pages have about the same amount of free space. +** Usually NN siblings on either side of pPage is used in the balancing, +** though more siblings might come from one side if pPage is the first +** or last child of its parent. If pPage has fewer than 2*NN siblings +** (something which can only happen if pPage is the root page or a +** child of root) then all available siblings participate in the balancing. +** +** The number of siblings of pPage might be increased or decreased by one or +** two in an effort to keep pages nearly full but not over full. The root page +** is special and is allowed to be nearly empty. If pPage is +** the root page, then the depth of the tree might be increased +** or decreased by one, as necessary, to keep the root page from being +** overfull or completely empty. +** +** Note that when this routine is called, some of the Cells on pPage +** might not actually be stored in pPage->aData[]. This can happen +** if the page is overfull. Part of the job of this routine is to +** make sure all Cells for pPage once again fit in pPage->aData[]. +** +** In the course of balancing the siblings of pPage, the parent of pPage +** might become overfull or underfull. If that happens, then this routine +** is called recursively on the parent. +** +** If this routine fails for any reason, it might leave the database +** in a corrupted state. So if this routine fails, the database should +** be rolled back. +*/ +static int balance_nonroot(MemPage *pPage){ + MemPage *pParent; /* The parent of pPage */ + 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[] */ + int nNew; /* Number of pages in apNew[] */ + int nDiv; /* Number of cells in apDiv[] */ + int i, j, k; /* Loop counters */ + int idx; /* Index of pPage in pParent->aCell[] */ + int nxDiv; /* Next divider slot in pParent->aCell[] */ + int rc; /* The return code */ + int leafCorrection; /* 4 if pPage is a leaf. 0 if not */ + int leafData; /* True if pPage is a leaf of a LEAFDATA tree */ + int usableSpace; /* Bytes in pPage beyond the header */ + int pageFlags; /* Value of pPage->aData[0] */ + int subtotal; /* Subtotal of bytes in cells on one page */ + int iSpace1 = 0; /* First unused byte of aSpace1[] */ + int iSpace2 = 0; /* First unused byte of aSpace2[] */ + int szScratch; /* Size of scratch memory requested */ + MemPage *apOld[NB]; /* pPage and up to two siblings */ + Pgno pgnoOld[NB]; /* Page numbers for each page in apOld[] */ + 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[] */ + 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 */ + u8 **apCell = 0; /* All cells begin balanced */ + u16 *szCell; /* Local size of all cells in apCell[] */ + u8 *aCopy[NB]; /* Space for holding data of apCopy[] */ + u8 *aSpace1; /* Space for copies of dividers cells before balance */ + u8 *aSpace2 = 0; /* Space for overflow dividers cells after balance */ + u8 *aFrom = 0; + + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + + /* + ** Find the parent page. + */ + assert( pPage->isInit ); + assert( sqlite3PagerIswriteable(pPage->pDbPage) || pPage->nOverflow==1 ); + pBt = pPage->pBt; + pParent = pPage->pParent; + assert( pParent ); + if( SQLITE_OK!=(rc = sqlite3PagerWrite(pParent->pDbPage)) ){ + return rc; + } + + TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno)); + +#ifndef SQLITE_OMIT_QUICKBALANCE + /* + ** A special case: If a new entry has just been inserted into a + ** table (that is, a btree with integer keys and all data at the leaves) + ** and the new entry is the right-most entry in the tree (it has the + ** largest key) then use the special balance_quick() routine for + ** balancing. balance_quick() is much faster and results in a tighter + ** packing of data in the common case. + */ + if( pPage->leaf && + pPage->intKey && + pPage->nOverflow==1 && + pPage->aOvfl[0].idx==pPage->nCell && + pPage->pParent->pgno!=1 && + get4byte(&pParent->aData[pParent->hdrOffset+8])==pPage->pgno + ){ + assert( pPage->intKey ); + /* + ** TODO: Check the siblings to the left of pPage. It may be that + ** they are not full and no new page is required. + */ + return balance_quick(pPage, pParent); + } +#endif + + if( SQLITE_OK!=(rc = sqlite3PagerWrite(pPage->pDbPage)) ){ + return rc; + } + + /* + ** Find the cell in the parent page whose left child points back + ** to pPage. The "idx" variable is the index of that cell. If pPage + ** is the rightmost child of pParent then set idx to pParent->nCell + */ + if( pParent->idxShift ){ + Pgno pgno; + pgno = pPage->pgno; + assert( pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); + for(idx=0; idx<pParent->nCell; idx++){ + if( get4byte(findCell(pParent, idx))==pgno ){ + break; + } + } + assert( idx<pParent->nCell + || get4byte(&pParent->aData[pParent->hdrOffset+8])==pgno ); + }else{ + idx = pPage->idxParent; + } + + /* + ** Initialize variables so that it will be safe to jump + ** directly to balance_cleanup at any moment. + */ + nOld = nNew = 0; + sqlite3PagerRef(pParent->pDbPage); + + /* + ** Find sibling pages to pPage and the cells in pParent that divide + ** the siblings. An attempt is made to find NN siblings on either + ** side of pPage. More siblings are taken from one side, however, if + ** pPage there are fewer than NN siblings on the other side. If pParent + ** has NB or fewer children then all children of pParent are taken. + */ + nxDiv = idx - NN; + if( nxDiv + NB > pParent->nCell ){ + nxDiv = pParent->nCell - NB + 1; + } + if( nxDiv<0 ){ + nxDiv = 0; + } + nDiv = 0; + for(i=0, k=nxDiv; i<NB; i++, k++){ + if( k<pParent->nCell ){ + apDiv[i] = findCell(pParent, k); + nDiv++; + assert( !pParent->leaf ); + pgnoOld[i] = get4byte(apDiv[i]); + }else if( k==pParent->nCell ){ + pgnoOld[i] = get4byte(&pParent->aData[pParent->hdrOffset+8]); + }else{ + break; + } + rc = getAndInitPage(pBt, pgnoOld[i], &apOld[i], pParent); + if( rc ) goto balance_cleanup; + apOld[i]->idxParent = k; + apCopy[i] = 0; + assert( i==nOld ); + nOld++; + nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow; + } + + /* Make nMaxCells a multiple of 4 in order to preserve 8-byte + ** alignment */ + nMaxCells = (nMaxCells + 3)&~3; + + /* + ** Allocate space for memory structures + */ + szScratch = + nMaxCells*sizeof(u8*) /* apCell */ + + nMaxCells*sizeof(u16) /* szCell */ + + (ROUND8(sizeof(MemPage))+pBt->pageSize)*NB /* aCopy */ + + pBt->pageSize /* aSpace1 */ + + (ISAUTOVACUUM ? nMaxCells : 0); /* aFrom */ + apCell = sqlite3ScratchMalloc( szScratch ); + if( apCell==0 ){ + rc = SQLITE_NOMEM; + goto balance_cleanup; + } + szCell = (u16*)&apCell[nMaxCells]; + aCopy[0] = (u8*)&szCell[nMaxCells]; + assert( ((aCopy[0] - (u8*)apCell) & 7)==0 ); /* 8-byte alignment required */ + for(i=1; i<NB; i++){ + aCopy[i] = &aCopy[i-1][pBt->pageSize+ROUND8(sizeof(MemPage))]; + assert( ((aCopy[i] - (u8*)apCell) & 7)==0 ); /* 8-byte alignment required */ + } + aSpace1 = &aCopy[NB-1][pBt->pageSize+ROUND8(sizeof(MemPage))]; + assert( ((aSpace1 - (u8*)apCell) & 7)==0 ); /* 8-byte alignment required */ + if( ISAUTOVACUUM ){ + aFrom = &aSpace1[pBt->pageSize]; + } + aSpace2 = sqlite3PageMalloc(pBt->pageSize); + if( aSpace2==0 ){ + rc = SQLITE_NOMEM; + goto balance_cleanup; + } + + /* + ** Make copies of the content of pPage and its siblings into aOld[]. + ** The rest of this function will use data from the copies rather + ** that the original pages since the original pages will be in the + ** process of being overwritten. + */ + for(i=0; i<nOld; i++){ + MemPage *p = apCopy[i] = (MemPage*)aCopy[i]; + memcpy(p, apOld[i], sizeof(MemPage)); + p->aData = (void*)&p[1]; + memcpy(p->aData, apOld[i]->aData, pBt->pageSize); + } + + /* + ** Load pointers to all cells on sibling pages and the divider cells + ** into the local apCell[] array. Make copies of the divider cells + ** into space obtained form aSpace1[] and remove the the divider Cells + ** from pParent. + ** + ** If the siblings are on leaf pages, then the child pointers of the + ** divider cells are stripped from the cells before they are copied + ** into aSpace1[]. In this way, all cells in apCell[] are without + ** child pointers. If siblings are not leaves, then all cell in + ** apCell[] include child pointers. Either way, all cells in apCell[] + ** are alike. + ** + ** leafCorrection: 4 if pPage is a leaf. 0 if pPage is not a leaf. + ** leafData: 1 if pPage holds key+data and pParent holds only keys. + */ + nCell = 0; + leafCorrection = pPage->leaf*4; + leafData = pPage->hasData; + for(i=0; i<nOld; i++){ + MemPage *pOld = apCopy[i]; + int limit = pOld->nCell+pOld->nOverflow; + for(j=0; j<limit; j++){ + assert( nCell<nMaxCells ); + apCell[nCell] = findOverflowCell(pOld, j); + szCell[nCell] = cellSizePtr(pOld, apCell[nCell]); + if( ISAUTOVACUUM ){ + int a; + aFrom[nCell] = i; + for(a=0; a<pOld->nOverflow; a++){ + if( pOld->aOvfl[a].pCell==apCell[nCell] ){ + aFrom[nCell] = 0xFF; + break; + } + } + } + nCell++; + } + if( i<nOld-1 ){ + u16 sz = cellSizePtr(pParent, apDiv[i]); + if( leafData ){ + /* With the LEAFDATA flag, pParent cells hold only INTKEYs that + ** are duplicates of keys on the child pages. We need to remove + ** the divider cells from pParent, but the dividers cells are not + ** added to apCell[] because they are duplicates of child cells. + */ + dropCell(pParent, nxDiv, sz); + }else{ + u8 *pTemp; + assert( nCell<nMaxCells ); + szCell[nCell] = sz; + pTemp = &aSpace1[iSpace1]; + iSpace1 += sz; + assert( sz<=pBt->pageSize/4 ); + assert( iSpace1<=pBt->pageSize ); + memcpy(pTemp, apDiv[i], sz); + apCell[nCell] = pTemp+leafCorrection; + if( ISAUTOVACUUM ){ + aFrom[nCell] = 0xFF; + } + dropCell(pParent, nxDiv, sz); + szCell[nCell] -= leafCorrection; + assert( get4byte(pTemp)==pgnoOld[i] ); + if( !pOld->leaf ){ + assert( leafCorrection==0 ); + /* The right pointer of the child page pOld becomes the left + ** pointer of the divider cell */ + memcpy(apCell[nCell], &pOld->aData[pOld->hdrOffset+8], 4); + }else{ + assert( leafCorrection==4 ); + if( szCell[nCell]<4 ){ + /* Do not allow any cells smaller than 4 bytes. */ + szCell[nCell] = 4; + } + } + nCell++; + } + } + } + + /* + ** Figure out the number of pages needed to hold all nCell cells. + ** Store this number in "k". Also compute szNew[] which is the total + ** size of all cells on the i-th page and cntNew[] which is the index + ** in apCell[] of the cell that divides page i from page i+1. + ** cntNew[k] should equal nCell. + ** + ** Values computed by this block: + ** + ** k: The total number of sibling pages + ** szNew[i]: Spaced used on the i-th sibling page. + ** cntNew[i]: Index in apCell[] and szCell[] for the first cell to + ** the right of the i-th sibling page. + ** usableSpace: Number of bytes of space available on each sibling. + ** + */ + usableSpace = pBt->usableSize - 12 + leafCorrection; + for(subtotal=k=i=0; i<nCell; i++){ + assert( i<nMaxCells ); + subtotal += szCell[i] + 2; + if( subtotal > usableSpace ){ + szNew[k] = subtotal - szCell[i]; + cntNew[k] = i; + if( leafData ){ i--; } + subtotal = 0; + k++; + } + } + szNew[k] = subtotal; + cntNew[k] = nCell; + k++; + + /* + ** The packing computed by the previous block is biased toward the siblings + ** on the left side. The left siblings are always nearly full, while the + ** right-most sibling might be nearly empty. This block of code attempts + ** to adjust the packing of siblings to get a better balance. + ** + ** This adjustment is more than an optimization. The packing above might + ** be so out of balance as to be illegal. For example, the right-most + ** sibling might be completely empty. This adjustment is not optional. + */ + for(i=k-1; i>0; i--){ + int szRight = szNew[i]; /* Size of sibling on the right */ + int szLeft = szNew[i-1]; /* Size of sibling on the left */ + int r; /* Index of right-most cell in left sibling */ + int d; /* Index of first cell to the left of right sibling */ + + r = cntNew[i-1] - 1; + d = r + 1 - leafData; + assert( d<nMaxCells ); + assert( r<nMaxCells ); + while( szRight==0 || szRight+szCell[d]+2<=szLeft-(szCell[r]+2) ){ + szRight += szCell[d] + 2; + szLeft -= szCell[r] + 2; + cntNew[i-1]--; + r = cntNew[i-1] - 1; + d = r + 1 - leafData; + } + szNew[i] = szRight; + szNew[i-1] = szLeft; + } + + /* Either we found one or more cells (cntnew[0])>0) or we are the + ** a virtual root page. A virtual root page is when the real root + ** page is page 1 and we are the only child of that page. + */ + assert( cntNew[0]>0 || (pParent->pgno==1 && pParent->nCell==0) ); + + /* + ** Allocate k new pages. Reuse old pages where possible. + */ + assert( pPage->pgno>1 ); + pageFlags = pPage->aData[0]; + for(i=0; i<k; i++){ + MemPage *pNew; + if( i<nOld ){ + pNew = apNew[i] = apOld[i]; + pgnoNew[i] = pgnoOld[i]; + apOld[i] = 0; + rc = sqlite3PagerWrite(pNew->pDbPage); + nNew++; + if( rc ) goto balance_cleanup; + }else{ + assert( i>0 ); + rc = allocateBtreePage(pBt, &pNew, &pgnoNew[i], pgnoNew[i-1], 0); + if( rc ) goto balance_cleanup; + apNew[i] = pNew; + nNew++; + } + } + + /* Free any old pages that were not reused as new pages. + */ + while( i<nOld ){ + rc = freePage(apOld[i]); + if( rc ) goto balance_cleanup; + releasePage(apOld[i]); + apOld[i] = 0; + i++; + } + + /* + ** Put the new pages in accending order. This helps to + ** keep entries in the disk file in order so that a scan + ** of the table is a linear scan through the file. That + ** in turn helps the operating system to deliver pages + ** from the disk more rapidly. + ** + ** An O(n^2) insertion sort algorithm is used, but since + ** n is never more than NB (a small constant), that should + ** not be a problem. + ** + ** When NB==3, this one optimization makes the database + ** about 25% faster for large insertions and deletions. + */ + for(i=0; i<k-1; i++){ + int minV = pgnoNew[i]; + int minI = i; + for(j=i+1; j<k; j++){ + if( pgnoNew[j]<(unsigned)minV ){ + minI = j; + minV = pgnoNew[j]; + } + } + if( minI>i ){ + int t; + MemPage *pT; + t = pgnoNew[i]; + pT = apNew[i]; + pgnoNew[i] = pgnoNew[minI]; + apNew[i] = apNew[minI]; + pgnoNew[minI] = t; + apNew[minI] = pT; + } + } + TRACE(("BALANCE: old: %d %d %d new: %d(%d) %d(%d) %d(%d) %d(%d) %d(%d)\n", + pgnoOld[0], + nOld>=2 ? pgnoOld[1] : 0, + nOld>=3 ? pgnoOld[2] : 0, + pgnoNew[0], szNew[0], + nNew>=2 ? pgnoNew[1] : 0, nNew>=2 ? szNew[1] : 0, + nNew>=3 ? pgnoNew[2] : 0, nNew>=3 ? szNew[2] : 0, + nNew>=4 ? pgnoNew[3] : 0, nNew>=4 ? szNew[3] : 0, + nNew>=5 ? pgnoNew[4] : 0, nNew>=5 ? szNew[4] : 0)); + + /* + ** Evenly distribute the data in apCell[] across the new pages. + ** Insert divider cells into pParent as necessary. + */ + j = 0; + for(i=0; i<nNew; i++){ + /* Assemble the new sibling page. */ + MemPage *pNew = apNew[i]; + assert( j<nMaxCells ); + assert( pNew->pgno==pgnoNew[i] ); + zeroPage(pNew, pageFlags); + assemblePage(pNew, cntNew[i]-j, &apCell[j], &szCell[j]); + assert( pNew->nCell>0 || (nNew==1 && cntNew[0]==0) ); + assert( pNew->nOverflow==0 ); + + /* If this is an auto-vacuum database, update the pointer map entries + ** that point to the siblings that were rearranged. These can be: left + ** children of cells, the right-child of the page, or overflow pages + ** pointed to by cells. + */ + if( ISAUTOVACUUM ){ + for(k=j; k<cntNew[i]; k++){ + assert( k<nMaxCells ); + if( aFrom[k]==0xFF || apCopy[aFrom[k]]->pgno!=pNew->pgno ){ + rc = ptrmapPutOvfl(pNew, k-j); + if( rc==SQLITE_OK && leafCorrection==0 ){ + rc = ptrmapPut(pBt, get4byte(apCell[k]), PTRMAP_BTREE, pNew->pgno); + } + if( rc!=SQLITE_OK ){ + goto balance_cleanup; + } + } + } + } + + j = cntNew[i]; + + /* If the sibling page assembled above was not the right-most sibling, + ** insert a divider cell into the parent page. + */ + if( i<nNew-1 && j<nCell ){ + u8 *pCell; + u8 *pTemp; + int sz; + + assert( j<nMaxCells ); + pCell = apCell[j]; + sz = szCell[j] + leafCorrection; + pTemp = &aSpace2[iSpace2]; + if( !pNew->leaf ){ + memcpy(&pNew->aData[8], pCell, 4); + if( ISAUTOVACUUM + && (aFrom[j]==0xFF || apCopy[aFrom[j]]->pgno!=pNew->pgno) + ){ + rc = ptrmapPut(pBt, get4byte(pCell), PTRMAP_BTREE, pNew->pgno); + if( rc!=SQLITE_OK ){ + goto balance_cleanup; + } + } + }else if( leafData ){ + /* If the tree is a leaf-data tree, and the siblings are leaves, + ** then there is no divider cell in apCell[]. Instead, the divider + ** cell consists of the integer key for the right-most cell of + ** the sibling-page assembled above only. + */ + CellInfo info; + j--; + sqlite3BtreeParseCellPtr(pNew, apCell[j], &info); + pCell = pTemp; + fillInCell(pParent, pCell, 0, info.nKey, 0, 0, 0, &sz); + pTemp = 0; + }else{ + pCell -= 4; + /* Obscure case for non-leaf-data trees: If the cell at pCell was + ** previously stored on a leaf node, and its reported size was 4 + ** bytes, then it may actually be smaller than this + ** (see sqlite3BtreeParseCellPtr(), 4 bytes is the minimum size of + ** any cell). But it is important to pass the correct size to + ** insertCell(), so reparse the cell now. + ** + ** Note that this can never happen in an SQLite data file, as all + ** cells are at least 4 bytes. It only happens in b-trees used + ** to evaluate "IN (SELECT ...)" and similar clauses. + */ + if( szCell[j]==4 ){ + assert(leafCorrection==4); + sz = cellSizePtr(pParent, pCell); + } + } + iSpace2 += sz; + assert( sz<=pBt->pageSize/4 ); + assert( iSpace2<=pBt->pageSize ); + rc = insertCell(pParent, nxDiv, pCell, sz, pTemp, 4); + if( rc!=SQLITE_OK ) goto balance_cleanup; + put4byte(findOverflowCell(pParent,nxDiv), pNew->pgno); + + /* If this is an auto-vacuum database, and not a leaf-data tree, + ** then update the pointer map with an entry for the overflow page + ** that the cell just inserted points to (if any). + */ + if( ISAUTOVACUUM && !leafData ){ + rc = ptrmapPutOvfl(pParent, nxDiv); + if( rc!=SQLITE_OK ){ + goto balance_cleanup; + } + } + j++; + nxDiv++; + } + + /* Set the pointer-map entry for the new sibling page. */ + if( ISAUTOVACUUM ){ + rc = ptrmapPut(pBt, pNew->pgno, PTRMAP_BTREE, pParent->pgno); + if( rc!=SQLITE_OK ){ + goto balance_cleanup; + } + } + } + assert( j==nCell ); + assert( nOld>0 ); + assert( nNew>0 ); + if( (pageFlags & PTF_LEAF)==0 ){ + u8 *zChild = &apCopy[nOld-1]->aData[8]; + memcpy(&apNew[nNew-1]->aData[8], zChild, 4); + if( ISAUTOVACUUM ){ + rc = ptrmapPut(pBt, get4byte(zChild), PTRMAP_BTREE, apNew[nNew-1]->pgno); + if( rc!=SQLITE_OK ){ + goto balance_cleanup; + } + } + } + if( nxDiv==pParent->nCell+pParent->nOverflow ){ + /* Right-most sibling is the right-most child of pParent */ + put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew[nNew-1]); + }else{ + /* Right-most sibling is the left child of the first entry in pParent + ** past the right-most divider entry */ + put4byte(findOverflowCell(pParent, nxDiv), pgnoNew[nNew-1]); + } + + /* + ** Reparent children of all cells. + */ + for(i=0; i<nNew; i++){ + rc = reparentChildPages(apNew[i], 0); + if( rc!=SQLITE_OK ) goto balance_cleanup; + } + rc = reparentChildPages(pParent, 0); + if( rc!=SQLITE_OK ) goto balance_cleanup; + + /* + ** Balance the parent page. Note that the current page (pPage) might + ** have been added to the freelist so it might no longer be initialized. + ** But the parent page will always be initialized. + */ + assert( pParent->isInit ); + sqlite3ScratchFree(apCell); + apCell = 0; + rc = balance(pParent, 0); + + /* + ** Cleanup before returning. + */ +balance_cleanup: + sqlite3PageFree(aSpace2); + sqlite3ScratchFree(apCell); + for(i=0; i<nOld; i++){ + releasePage(apOld[i]); + } + for(i=0; i<nNew; i++){ + releasePage(apNew[i]); + } + releasePage(pParent); + TRACE(("BALANCE: finished with %d: old=%d new=%d cells=%d\n", + pPage->pgno, nOld, nNew, nCell)); + return rc; +} + +/* +** This routine is called for the root page of a btree when the root +** page contains no cells. This is an opportunity to make the tree +** shallower by one level. +*/ +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 */ + BtShared *pBt; /* The main BTree structure */ + int mxCellPerPage; /* Maximum number of cells per page */ + u8 **apCell; /* All cells from pages being balanced */ + u16 *szCell; /* Local size of all cells */ + + assert( pPage->pParent==0 ); + assert( pPage->nCell==0 ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + pBt = pPage->pBt; + mxCellPerPage = MX_CELL(pBt); + apCell = sqlite3Malloc( mxCellPerPage*(sizeof(u8*)+sizeof(u16)) ); + if( apCell==0 ) return SQLITE_NOMEM; + szCell = (u16*)&apCell[mxCellPerPage]; + if( pPage->leaf ){ + /* The table is completely empty */ + TRACE(("BALANCE: empty table %d\n", pPage->pgno)); + }else{ + /* The root page is empty but has one child. Transfer the + ** information from that one child into the root page if it + ** will fit. This reduces the depth of the tree by one. + ** + ** If the root page is page 1, it has less space available than + ** its child (due to the 100 byte header that occurs at the beginning + ** of the database fle), so it might not be able to hold all of the + ** information currently contained in the child. If this is the + ** case, then do not do the transfer. Leave page 1 empty except + ** for the right-pointer to the child page. The child page becomes + ** the virtual root of the tree. + */ + pgnoChild = get4byte(&pPage->aData[pPage->hdrOffset+8]); + assert( pgnoChild>0 ); + assert( pgnoChild<=pagerPagecount(pPage->pBt->pPager) ); + rc = sqlite3BtreeGetPage(pPage->pBt, pgnoChild, &pChild, 0); + if( rc ) goto end_shallow_balance; + if( pPage->pgno==1 ){ + rc = sqlite3BtreeInitPage(pChild, pPage); + if( rc ) goto end_shallow_balance; + assert( pChild->nOverflow==0 ); + if( pChild->nFree>=100 ){ + /* The child information will fit on the root page, so do the + ** copy */ + int i; + zeroPage(pPage, pChild->aData[0]); + for(i=0; i<pChild->nCell; i++){ + apCell[i] = findCell(pChild,i); + szCell[i] = cellSizePtr(pChild, apCell[i]); + } + assemblePage(pPage, pChild->nCell, apCell, szCell); + /* Copy the right-pointer of the child to the parent. */ + put4byte(&pPage->aData[pPage->hdrOffset+8], + get4byte(&pChild->aData[pChild->hdrOffset+8])); + freePage(pChild); + TRACE(("BALANCE: child %d transfer to page 1\n", pChild->pgno)); + }else{ + /* The child has more information that will fit on the root. + ** The tree is already balanced. Do nothing. */ + TRACE(("BALANCE: child %d will not fit on page 1\n", pChild->pgno)); + } + }else{ + memcpy(pPage->aData, pChild->aData, pPage->pBt->usableSize); + pPage->isInit = 0; + pPage->pParent = 0; + rc = sqlite3BtreeInitPage(pPage, 0); + assert( rc==SQLITE_OK ); + freePage(pChild); + TRACE(("BALANCE: transfer child %d into root %d\n", + pChild->pgno, pPage->pgno)); + } + rc = reparentChildPages(pPage, 1); + assert( pPage->nOverflow==0 ); + if( ISAUTOVACUUM ){ + int i; + for(i=0; i<pPage->nCell; i++){ + rc = ptrmapPutOvfl(pPage, i); + if( rc!=SQLITE_OK ){ + goto end_shallow_balance; + } + } + } + releasePage(pChild); + } +end_shallow_balance: + sqlite3_free(apCell); + return rc; +} + + +/* +** The root page is overfull +** +** When this happens, Create a new child page and copy the +** contents of the root into the child. Then make the root +** page an empty page with rightChild pointing to the new +** child. Finally, call balance_internal() on the new child +** to cause it to split. +*/ +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 */ + 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 */ + int hdr; /* Offset to page header in parent */ + int brk; /* Offset to content of first cell in parent */ + + assert( pPage->pParent==0 ); + assert( pPage->nOverflow>0 ); + pBt = pPage->pBt; + assert( sqlite3_mutex_held(pBt->mutex) ); + rc = allocateBtreePage(pBt, &pChild, &pgnoChild, pPage->pgno, 0); + if( rc ) return rc; + assert( sqlite3PagerIswriteable(pChild->pDbPage) ); + usableSize = pBt->usableSize; + data = pPage->aData; + hdr = pPage->hdrOffset; + brk = get2byte(&data[hdr+5]); + cdata = pChild->aData; + memcpy(cdata, &data[hdr], pPage->cellOffset+2*pPage->nCell-hdr); + memcpy(&cdata[brk], &data[brk], usableSize-brk); + if( pChild->isInit ) return SQLITE_CORRUPT; + rc = sqlite3BtreeInitPage(pChild, pPage); + if( rc ) goto balancedeeper_out; + memcpy(pChild->aOvfl, pPage->aOvfl, pPage->nOverflow*sizeof(pPage->aOvfl[0])); + pChild->nOverflow = pPage->nOverflow; + if( pChild->nOverflow ){ + pChild->nFree = 0; + } + assert( pChild->nCell==pPage->nCell ); + zeroPage(pPage, pChild->aData[0] & ~PTF_LEAF); + put4byte(&pPage->aData[pPage->hdrOffset+8], pgnoChild); + TRACE(("BALANCE: copy root %d into %d\n", pPage->pgno, pChild->pgno)); + if( ISAUTOVACUUM ){ + int i; + rc = ptrmapPut(pBt, pChild->pgno, PTRMAP_BTREE, pPage->pgno); + if( rc ) goto balancedeeper_out; + for(i=0; i<pChild->nCell; i++){ + rc = ptrmapPutOvfl(pChild, i); + if( rc!=SQLITE_OK ){ + goto balancedeeper_out; + } + } + rc = reparentChildPages(pChild, 1); + } + if( rc==SQLITE_OK ){ + rc = balance_nonroot(pChild); + } + +balancedeeper_out: + releasePage(pChild); + return rc; +} + +/* +** Decide if the page pPage needs to be balanced. If balancing is +** required, call the appropriate balancing routine. +*/ +static int balance(MemPage *pPage, int insert){ + int rc = SQLITE_OK; + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + if( pPage->pParent==0 ){ + rc = sqlite3PagerWrite(pPage->pDbPage); + if( rc==SQLITE_OK && pPage->nOverflow>0 ){ + rc = balance_deeper(pPage); + } + if( rc==SQLITE_OK && pPage->nCell==0 ){ + rc = balance_shallower(pPage); + } + }else{ + if( pPage->nOverflow>0 || + (!insert && pPage->nFree>pPage->pBt->usableSize*2/3) ){ + rc = balance_nonroot(pPage); + } + } + return rc; +} + +/* +** This routine checks all cursors that point to table pgnoRoot. +** If any of those cursors were opened with wrFlag==0 in a different +** database connection (a database connection that shares the pager +** cache with the current connection) and that other connection +** is not in the ReadUncommmitted state, then this routine returns +** SQLITE_LOCKED. +** +** As well as cursors with wrFlag==0, cursors with wrFlag==1 and +** isIncrblobHandle==1 are also considered 'read' cursors. Incremental +** blob cursors are used for both reading and writing. +** +** When pgnoRoot is the root page of an intkey table, this function is also +** responsible for invalidating incremental blob cursors when the table row +** on which they are opened is deleted or modified. Cursors are invalidated +** according to the following rules: +** +** 1) When BtreeClearTable() is called to completely delete the contents +** of a B-Tree table, pExclude is set to zero and parameter iRow is +** set to non-zero. In this case all incremental blob cursors open +** on the table rooted at pgnoRoot are invalidated. +** +** 2) When BtreeInsert(), BtreeDelete() or BtreePutData() is called to +** modify a table row via an SQL statement, pExclude is set to the +** write cursor used to do the modification and parameter iRow is set +** to the integer row id of the B-Tree entry being modified. Unless +** pExclude is itself an incremental blob cursor, then all incremental +** blob cursors open on row iRow of the B-Tree are invalidated. +** +** 3) If both pExclude and iRow are set to zero, no incremental blob +** cursors are invalidated. +*/ +static int checkReadLocks( + Btree *pBtree, + Pgno pgnoRoot, + BtCursor *pExclude, + i64 iRow +){ + BtCursor *p; + BtShared *pBt = pBtree->pBt; + sqlite3 *db = pBtree->db; + assert( sqlite3BtreeHoldsMutex(pBtree) ); + for(p=pBt->pCursor; p; p=p->pNext){ + if( p==pExclude ) continue; + if( p->pgnoRoot!=pgnoRoot ) continue; +#ifndef SQLITE_OMIT_INCRBLOB + if( p->isIncrblobHandle && ( + (!pExclude && iRow) + || (pExclude && !pExclude->isIncrblobHandle && p->info.nKey==iRow) + )){ + p->eState = CURSOR_INVALID; + } +#endif + if( p->eState!=CURSOR_VALID ) continue; + if( p->wrFlag==0 +#ifndef SQLITE_OMIT_INCRBLOB + || p->isIncrblobHandle +#endif + ){ + sqlite3 *dbOther = p->pBtree->db; + if( dbOther==0 || + (dbOther!=db && (dbOther->flags & SQLITE_ReadUncommitted)==0) ){ + return SQLITE_LOCKED; + } + } + } + return SQLITE_OK; +} + +/* +** Insert a new record into the BTree. The key is given by (pKey,nKey) +** and the data is given by (pData,nData). The cursor is used only to +** define what table the record should be inserted into. The cursor +** is left pointing at a random location. +** +** For an INTKEY table, only the nKey value of the key is used. pKey is +** ignored. For a ZERODATA table, the pData and nData are both ignored. +*/ +int sqlite3BtreeInsert( + BtCursor *pCur, /* Insert data into the table of this cursor */ + const void *pKey, i64 nKey, /* The key of the new record */ + const void *pData, int nData, /* The data of the new record */ + int nZero, /* Number of extra 0 bytes to append to data */ + int appendBias /* True if this is likely an append */ +){ + int rc; + int loc; + int szNew; + MemPage *pPage; + Btree *p = pCur->pBtree; + BtShared *pBt = p->pBt; + unsigned char *oldCell; + unsigned char *newCell = 0; + + assert( cursorHoldsMutex(pCur) ); + if( pBt->inTransaction!=TRANS_WRITE ){ + /* Must start a transaction before doing an insert */ + rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; + return rc; + } + assert( !pBt->readOnly ); + if( !pCur->wrFlag ){ + return SQLITE_PERM; /* Cursor not open for writing */ + } + if( checkReadLocks(pCur->pBtree, pCur->pgnoRoot, pCur, nKey) ){ + return SQLITE_LOCKED; /* The table pCur points to has a read lock */ + } + if( pCur->eState==CURSOR_FAULT ){ + return pCur->skip; + } + + /* Save the positions of any other cursors open on this table */ + clearCursorPosition(pCur); + if( + SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) || + SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, 0, nKey, appendBias, &loc)) + ){ + return rc; + } + + pPage = pCur->pPage; + assert( pPage->intKey || nKey>=0 ); + assert( pPage->leaf || !pPage->intKey ); + TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n", + pCur->pgnoRoot, nKey, nData, pPage->pgno, + loc==0 ? "overwrite" : "new entry")); + assert( pPage->isInit ); + allocateTempSpace(pBt); + newCell = pBt->pTmpSpace; + if( newCell==0 ) return SQLITE_NOMEM; + rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, nZero, &szNew); + if( rc ) goto end_insert; + assert( szNew==cellSizePtr(pPage, newCell) ); + assert( szNew<=MX_CELL_SIZE(pBt) ); + if( loc==0 && CURSOR_VALID==pCur->eState ){ + u16 szOld; + assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); + rc = sqlite3PagerWrite(pPage->pDbPage); + if( rc ){ + goto end_insert; + } + oldCell = findCell(pPage, pCur->idx); + if( !pPage->leaf ){ + memcpy(newCell, oldCell, 4); + } + szOld = cellSizePtr(pPage, oldCell); + rc = clearCell(pPage, oldCell); + if( rc ) goto end_insert; + dropCell(pPage, pCur->idx, szOld); + }else if( loc<0 && pPage->nCell>0 ){ + assert( pPage->leaf ); + pCur->idx++; + pCur->info.nSize = 0; + pCur->validNKey = 0; + }else{ + assert( pPage->leaf ); + } + rc = insertCell(pPage, pCur->idx, newCell, szNew, 0, 0); + if( rc!=SQLITE_OK ) goto end_insert; + rc = balance(pPage, 1); + if( rc==SQLITE_OK ){ + moveToRoot(pCur); + } +end_insert: + return rc; +} + +/* +** Delete the entry that the cursor is pointing to. The cursor +** is left pointing at a random location. +*/ +int sqlite3BtreeDelete(BtCursor *pCur){ + MemPage *pPage = pCur->pPage; + unsigned char *pCell; + int rc; + Pgno pgnoChild = 0; + Btree *p = pCur->pBtree; + BtShared *pBt = p->pBt; + + assert( cursorHoldsMutex(pCur) ); + assert( pPage->isInit ); + if( pBt->inTransaction!=TRANS_WRITE ){ + /* Must start a transaction before doing a delete */ + rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; + return rc; + } + assert( !pBt->readOnly ); + if( pCur->eState==CURSOR_FAULT ){ + return pCur->skip; + } + if( pCur->idx >= pPage->nCell ){ + return SQLITE_ERROR; /* The cursor is not pointing to anything */ + } + if( !pCur->wrFlag ){ + return SQLITE_PERM; /* Did not open this cursor for writing */ + } + if( checkReadLocks(pCur->pBtree, pCur->pgnoRoot, pCur, pCur->info.nKey) ){ + return SQLITE_LOCKED; /* The table pCur points to has a read lock */ + } + + /* 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 sqlite3PagerWrite() on the page + ** that the entry will be deleted from. + */ + if( + (rc = restoreCursorPosition(pCur))!=0 || + (rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur))!=0 || + (rc = sqlite3PagerWrite(pPage->pDbPage))!=0 + ){ + return rc; + } + + /* Locate the cell within its page and leave pCell pointing to the + ** data. The clearCell() call frees any overflow pages associated with the + ** cell. The cell itself is still intact. + */ + pCell = findCell(pPage, pCur->idx); + if( !pPage->leaf ){ + pgnoChild = get4byte(pCell); + } + rc = clearCell(pPage, pCell); + if( rc ){ + return rc; + } + + if( !pPage->leaf ){ + /* + ** The entry we are about to delete is not a leaf so if we do not + ** do something we will leave a hole on an internal page. + ** We have to fill the hole by moving in a cell from a leaf. The + ** next Cell after the one to be deleted is guaranteed to exist and + ** to be a leaf so we can use it. + */ + BtCursor leafCur; + unsigned char *pNext; + int notUsed; + unsigned char *tempCell = 0; + assert( !pPage->intKey ); + sqlite3BtreeGetTempCursor(pCur, &leafCur); + rc = sqlite3BtreeNext(&leafCur, ¬Used); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerWrite(leafCur.pPage->pDbPage); + } + if( rc==SQLITE_OK ){ + u16 szNext; + TRACE(("DELETE: table=%d delete internal from %d replace from leaf %d\n", + pCur->pgnoRoot, pPage->pgno, leafCur.pPage->pgno)); + dropCell(pPage, pCur->idx, cellSizePtr(pPage, pCell)); + pNext = findCell(leafCur.pPage, leafCur.idx); + szNext = cellSizePtr(leafCur.pPage, pNext); + assert( MX_CELL_SIZE(pBt)>=szNext+4 ); + allocateTempSpace(pBt); + tempCell = pBt->pTmpSpace; + if( tempCell==0 ){ + rc = SQLITE_NOMEM; + } + if( rc==SQLITE_OK ){ + rc = insertCell(pPage, pCur->idx, pNext-4, szNext+4, tempCell, 0); + } + if( rc==SQLITE_OK ){ + put4byte(findOverflowCell(pPage, pCur->idx), pgnoChild); + rc = balance(pPage, 0); + } + if( rc==SQLITE_OK ){ + dropCell(leafCur.pPage, leafCur.idx, szNext); + rc = balance(leafCur.pPage, 0); + } + } + sqlite3BtreeReleaseTempCursor(&leafCur); + }else{ + TRACE(("DELETE: table=%d delete from leaf %d\n", + pCur->pgnoRoot, pPage->pgno)); + dropCell(pPage, pCur->idx, cellSizePtr(pPage, pCell)); + rc = balance(pPage, 0); + } + if( rc==SQLITE_OK ){ + moveToRoot(pCur); + } + return rc; +} + +/* +** Create a new BTree table. Write into *piTable the page +** number for the root page of the new table. +** +** The type of type is determined by the flags parameter. Only the +** following values of flags are currently in use. Other values for +** flags might not work: +** +** BTREE_INTKEY|BTREE_LEAFDATA Used for SQL tables with rowid keys +** BTREE_ZERODATA Used for SQL indices +*/ +static int btreeCreateTable(Btree *p, int *piTable, int flags){ + BtShared *pBt = p->pBt; + MemPage *pRoot; + Pgno pgnoRoot; + int rc; + + assert( sqlite3BtreeHoldsMutex(p) ); + if( pBt->inTransaction!=TRANS_WRITE ){ + /* Must start a transaction first */ + rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; + return rc; + } + assert( !pBt->readOnly ); + +#ifdef SQLITE_OMIT_AUTOVACUUM + rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0); + if( rc ){ + return rc; + } +#else + if( pBt->autoVacuum ){ + Pgno pgnoMove; /* Move a page here to make room for the root-page */ + MemPage *pPageMove; /* The page to move to. */ + + /* Creating a new table may probably require moving an existing database + ** to make room for the new tables root page. In case this page turns + ** out to be an overflow page, delete all overflow page-map caches + ** held by open cursors. + */ + invalidateAllOverflowCache(pBt); + + /* Read the value of meta[3] from the database to determine where the + ** root page of the new table should go. meta[3] is the largest root-page + ** created so far, so the new root-page is (meta[3]+1). + */ + rc = sqlite3BtreeGetMeta(p, 4, &pgnoRoot); + if( rc!=SQLITE_OK ){ + return rc; + } + pgnoRoot++; + + /* The new root-page may not be allocated on a pointer-map page, or the + ** PENDING_BYTE page. + */ + while( pgnoRoot==PTRMAP_PAGENO(pBt, pgnoRoot) || + pgnoRoot==PENDING_BYTE_PAGE(pBt) ){ + pgnoRoot++; + } + assert( pgnoRoot>=3 ); + + /* Allocate a page. The page that currently resides at pgnoRoot will + ** be moved to the allocated page (unless the allocated page happens + ** to reside at pgnoRoot). + */ + rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, 1); + if( rc!=SQLITE_OK ){ + return rc; + } + + if( pgnoMove!=pgnoRoot ){ + /* pgnoRoot is the page that will be used for the root-page of + ** the new table (assuming an error did not occur). But we were + ** allocated pgnoMove. If required (i.e. if it was not allocated + ** by extending the file), the current page at position pgnoMove + ** is already journaled. + */ + u8 eType; + Pgno iPtrPage; + + releasePage(pPageMove); + + /* Move the page currently at pgnoRoot to pgnoMove. */ + rc = sqlite3BtreeGetPage(pBt, pgnoRoot, &pRoot, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage); + if( rc!=SQLITE_OK || eType==PTRMAP_ROOTPAGE || eType==PTRMAP_FREEPAGE ){ + releasePage(pRoot); + return rc; + } + assert( eType!=PTRMAP_ROOTPAGE ); + assert( eType!=PTRMAP_FREEPAGE ); + rc = sqlite3PagerWrite(pRoot->pDbPage); + if( rc!=SQLITE_OK ){ + releasePage(pRoot); + return rc; + } + rc = relocatePage(pBt, pRoot, eType, iPtrPage, pgnoMove, 0); + releasePage(pRoot); + + /* Obtain the page at pgnoRoot */ + if( rc!=SQLITE_OK ){ + return rc; + } + rc = sqlite3BtreeGetPage(pBt, pgnoRoot, &pRoot, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + rc = sqlite3PagerWrite(pRoot->pDbPage); + if( rc!=SQLITE_OK ){ + releasePage(pRoot); + return rc; + } + }else{ + pRoot = pPageMove; + } + + /* Update the pointer-map and meta-data with the new root-page number. */ + rc = ptrmapPut(pBt, pgnoRoot, PTRMAP_ROOTPAGE, 0); + if( rc ){ + releasePage(pRoot); + return rc; + } + rc = sqlite3BtreeUpdateMeta(p, 4, pgnoRoot); + if( rc ){ + releasePage(pRoot); + return rc; + } + + }else{ + rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0); + if( rc ) return rc; + } +#endif + assert( sqlite3PagerIswriteable(pRoot->pDbPage) ); + zeroPage(pRoot, flags | PTF_LEAF); + sqlite3PagerUnref(pRoot->pDbPage); + *piTable = (int)pgnoRoot; + return SQLITE_OK; +} +int sqlite3BtreeCreateTable(Btree *p, int *piTable, int flags){ + int rc; + sqlite3BtreeEnter(p); + p->pBt->db = p->db; + rc = btreeCreateTable(p, piTable, flags); + sqlite3BtreeLeave(p); + return rc; +} + +/* +** Erase the given database page and all its children. Return +** the page to the freelist. +*/ +static int clearDatabasePage( + 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 */ +){ + MemPage *pPage = 0; + int rc; + unsigned char *pCell; + int i; + + assert( sqlite3_mutex_held(pBt->mutex) ); + if( pgno>pagerPagecount(pBt->pPager) ){ + return SQLITE_CORRUPT_BKPT; + } + + rc = getAndInitPage(pBt, pgno, &pPage, pParent); + if( rc ) goto cleardatabasepage_out; + for(i=0; i<pPage->nCell; i++){ + pCell = findCell(pPage, i); + if( !pPage->leaf ){ + rc = clearDatabasePage(pBt, get4byte(pCell), pPage->pParent, 1); + if( rc ) goto cleardatabasepage_out; + } + rc = clearCell(pPage, pCell); + if( rc ) goto cleardatabasepage_out; + } + if( !pPage->leaf ){ + rc = clearDatabasePage(pBt, get4byte(&pPage->aData[8]), pPage->pParent, 1); + if( rc ) goto cleardatabasepage_out; + } + if( freePageFlag ){ + rc = freePage(pPage); + }else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){ + zeroPage(pPage, pPage->aData[0] | PTF_LEAF); + } + +cleardatabasepage_out: + releasePage(pPage); + return rc; +} + +/* +** Delete all information from a single table in the database. iTable is +** the page number of the root of the table. After this routine returns, +** the root page is empty, but still exists. +** +** This routine will fail with SQLITE_LOCKED if there are any open +** read cursors on the table. Open write cursors are moved to the +** root of the table. +*/ +int sqlite3BtreeClearTable(Btree *p, int iTable){ + int rc; + BtShared *pBt = p->pBt; + sqlite3BtreeEnter(p); + pBt->db = p->db; + if( p->inTrans!=TRANS_WRITE ){ + rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; + }else if( (rc = checkReadLocks(p, iTable, 0, 1))!=SQLITE_OK ){ + /* nothing to do */ + }else if( SQLITE_OK!=(rc = saveAllCursors(pBt, iTable, 0)) ){ + /* nothing to do */ + }else{ + rc = clearDatabasePage(pBt, (Pgno)iTable, 0, 0); + } + sqlite3BtreeLeave(p); + return rc; +} + +/* +** Erase all information in a table and add the root of the table to +** the freelist. Except, the root of the principle table (the one on +** page 1) is never added to the freelist. +** +** This routine will fail with SQLITE_LOCKED if there are any open +** cursors on the table. +** +** If AUTOVACUUM is enabled and the page at iTable is not the last +** root page in the database file, then the last root page +** in the database file is moved into the slot formerly occupied by +** iTable and that last slot formerly occupied by the last root page +** is added to the freelist instead of iTable. In this say, all +** root pages are kept at the beginning of the database file, which +** is necessary for AUTOVACUUM to work right. *piMoved is set to the +** page number that used to be the last root page in the file before +** the move. If no page gets moved, *piMoved is set to 0. +** The last root page is recorded in meta[3] and the value of +** meta[3] is updated by this procedure. +*/ +static int btreeDropTable(Btree *p, int iTable, int *piMoved){ + int rc; + MemPage *pPage = 0; + BtShared *pBt = p->pBt; + + assert( sqlite3BtreeHoldsMutex(p) ); + if( p->inTrans!=TRANS_WRITE ){ + return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; + } + + /* It is illegal to drop a table if any cursors are open on the + ** database. This is because in auto-vacuum mode the backend may + ** need to move another root-page to fill a gap left by the deleted + ** root page. If an open cursor was using this page a problem would + ** occur. + */ + if( pBt->pCursor ){ + return SQLITE_LOCKED; + } + + rc = sqlite3BtreeGetPage(pBt, (Pgno)iTable, &pPage, 0); + if( rc ) return rc; + rc = sqlite3BtreeClearTable(p, iTable); + if( rc ){ + releasePage(pPage); + return rc; + } + + *piMoved = 0; + + if( iTable>1 ){ +#ifdef SQLITE_OMIT_AUTOVACUUM + rc = freePage(pPage); + releasePage(pPage); +#else + if( pBt->autoVacuum ){ + Pgno maxRootPgno; + rc = sqlite3BtreeGetMeta(p, 4, &maxRootPgno); + if( rc!=SQLITE_OK ){ + releasePage(pPage); + return rc; + } + + if( iTable==maxRootPgno ){ + /* If the table being dropped is the table with the largest root-page + ** number in the database, put the root page on the free list. + */ + rc = freePage(pPage); + releasePage(pPage); + if( rc!=SQLITE_OK ){ + return rc; + } + }else{ + /* The table being dropped does not have the largest root-page + ** number in the database. So move the page that does into the + ** gap left by the deleted root-page. + */ + MemPage *pMove; + releasePage(pPage); + rc = sqlite3BtreeGetPage(pBt, maxRootPgno, &pMove, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + rc = relocatePage(pBt, pMove, PTRMAP_ROOTPAGE, 0, iTable, 0); + releasePage(pMove); + if( rc!=SQLITE_OK ){ + return rc; + } + rc = sqlite3BtreeGetPage(pBt, maxRootPgno, &pMove, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + rc = freePage(pMove); + releasePage(pMove); + if( rc!=SQLITE_OK ){ + return rc; + } + *piMoved = maxRootPgno; + } + + /* Set the new 'max-root-page' value in the database header. This + ** is the old value less one, less one more if that happens to + ** be a root-page number, less one again if that is the + ** PENDING_BYTE_PAGE. + */ + maxRootPgno--; + if( maxRootPgno==PENDING_BYTE_PAGE(pBt) ){ + maxRootPgno--; + } + if( maxRootPgno==PTRMAP_PAGENO(pBt, maxRootPgno) ){ + maxRootPgno--; + } + assert( maxRootPgno!=PENDING_BYTE_PAGE(pBt) ); + + rc = sqlite3BtreeUpdateMeta(p, 4, maxRootPgno); + }else{ + rc = freePage(pPage); + releasePage(pPage); + } +#endif + }else{ + /* If sqlite3BtreeDropTable was called on page 1. */ + zeroPage(pPage, PTF_INTKEY|PTF_LEAF ); + releasePage(pPage); + } + return rc; +} +int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){ + int rc; + sqlite3BtreeEnter(p); + p->pBt->db = p->db; + rc = btreeDropTable(p, iTable, piMoved); + sqlite3BtreeLeave(p); + return rc; +} + + +/* +** Read the meta-information out of a database file. Meta[0] +** is the number of free pages currently in the database. Meta[1] +** through meta[15] are available for use by higher layers. Meta[0] +** is read-only, the others are read/write. +** +** The schema layer numbers meta values differently. At the schema +** 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 *p, int idx, u32 *pMeta){ + DbPage *pDbPage; + int rc; + unsigned char *pP1; + BtShared *pBt = p->pBt; + + sqlite3BtreeEnter(p); + pBt->db = p->db; + + /* 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 ){ + sqlite3BtreeLeave(p); + return rc; + } + + assert( idx>=0 && idx<=15 ); + rc = sqlite3PagerGet(pBt->pPager, 1, &pDbPage); + if( rc ){ + sqlite3BtreeLeave(p); + return rc; + } + pP1 = (unsigned char *)sqlite3PagerGetData(pDbPage); + *pMeta = get4byte(&pP1[36 + idx*4]); + sqlite3PagerUnref(pDbPage); + + /* If autovacuumed is disabled in this build but we are trying to + ** access an autovacuumed database, then make the database readonly. + */ +#ifdef SQLITE_OMIT_AUTOVACUUM + if( idx==4 && *pMeta>0 ) pBt->readOnly = 1; +#endif + + /* Grab the read-lock on page 1. */ + rc = lockTable(p, 1, READ_LOCK); + sqlite3BtreeLeave(p); + return rc; +} + +/* +** Write meta-information back into the database. Meta[0] is +** read-only and may not be written. +*/ +int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){ + BtShared *pBt = p->pBt; + unsigned char *pP1; + int rc; + assert( idx>=1 && idx<=15 ); + sqlite3BtreeEnter(p); + pBt->db = p->db; + if( p->inTrans!=TRANS_WRITE ){ + rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; + }else{ + assert( pBt->pPage1!=0 ); + pP1 = pBt->pPage1->aData; + rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); + if( rc==SQLITE_OK ){ + put4byte(&pP1[36 + idx*4], iMeta); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( idx==7 ){ + assert( pBt->autoVacuum || iMeta==0 ); + assert( iMeta==0 || iMeta==1 ); + pBt->incrVacuum = iMeta; + } +#endif + } + } + sqlite3BtreeLeave(p); + return rc; +} + +/* +** Return the flag byte at the beginning of the page that the cursor +** is currently pointing to. +*/ +int sqlite3BtreeFlags(BtCursor *pCur){ + /* TODO: What about CURSOR_REQUIRESEEK state? Probably need to call + ** restoreCursorPosition() here. + */ + MemPage *pPage; + restoreCursorPosition(pCur); + pPage = pCur->pPage; + assert( cursorHoldsMutex(pCur) ); + assert( pPage->pBt==pCur->pBt ); + return pPage ? pPage->aData[pPage->hdrOffset] : 0; +} + + +/* +** Return the pager associated with a BTree. This routine is used for +** testing and debugging only. +*/ +Pager *sqlite3BtreePager(Btree *p){ + return p->pBt->pPager; +} + +#ifndef SQLITE_OMIT_INTEGRITY_CHECK +/* +** Append a message to the error message string. +*/ +static void checkAppendMsg( + IntegrityCk *pCheck, + char *zMsg1, + const char *zFormat, + ... +){ + va_list ap; + if( !pCheck->mxErr ) return; + pCheck->mxErr--; + pCheck->nErr++; + va_start(ap, zFormat); + if( pCheck->errMsg.nChar ){ + sqlite3StrAccumAppend(&pCheck->errMsg, "\n", 1); + } + if( zMsg1 ){ + sqlite3StrAccumAppend(&pCheck->errMsg, zMsg1, -1); + } + sqlite3VXPrintf(&pCheck->errMsg, 1, zFormat, ap); + va_end(ap); + if( pCheck->errMsg.mallocFailed ){ + pCheck->mallocFailed = 1; + } +} +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ + +#ifndef SQLITE_OMIT_INTEGRITY_CHECK +/* +** Add 1 to the reference count for page iPage. If this is the second +** reference to the page, add an error message to pCheck->zErrMsg. +** Return 1 if there are 2 ore more references to the page and 0 if +** if this is the first reference to the page. +** +** Also check that the page number is in bounds. +*/ +static int checkRef(IntegrityCk *pCheck, int iPage, char *zContext){ + if( iPage==0 ) return 1; + if( iPage>pCheck->nPage || iPage<0 ){ + checkAppendMsg(pCheck, zContext, "invalid page number %d", iPage); + return 1; + } + if( pCheck->anRef[iPage]==1 ){ + checkAppendMsg(pCheck, zContext, "2nd reference to page %d", iPage); + return 1; + } + return (pCheck->anRef[iPage]++)>1; +} + +#ifndef SQLITE_OMIT_AUTOVACUUM +/* +** Check that the entry in the pointer-map for page iChild maps to +** page iParent, pointer type ptrType. If not, append an error message +** to pCheck. +*/ +static void checkPtrmap( + IntegrityCk *pCheck, /* Integrity check context */ + Pgno iChild, /* Child page number */ + u8 eType, /* Expected pointer map type */ + Pgno iParent, /* Expected pointer map parent page number */ + char *zContext /* Context description (used for error msg) */ +){ + int rc; + u8 ePtrmapType; + Pgno iPtrmapParent; + + rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent); + if( rc!=SQLITE_OK ){ + checkAppendMsg(pCheck, zContext, "Failed to read ptrmap key=%d", iChild); + return; + } + + if( ePtrmapType!=eType || iPtrmapParent!=iParent ){ + checkAppendMsg(pCheck, zContext, + "Bad ptr map entry key=%d expected=(%d,%d) got=(%d,%d)", + iChild, eType, iParent, ePtrmapType, iPtrmapParent); + } +} +#endif + +/* +** Check the integrity of the freelist or of an overflow page list. +** Verify that the number of pages on the list is N. +*/ +static void checkList( + IntegrityCk *pCheck, /* Integrity checking context */ + int isFreeList, /* True for a freelist. False for overflow page list */ + int iPage, /* Page number for first page in the list */ + int N, /* Expected number of pages in the list */ + char *zContext /* Context for error messages */ +){ + int i; + int expected = N; + int iFirst = iPage; + while( N-- > 0 && pCheck->mxErr ){ + DbPage *pOvflPage; + unsigned char *pOvflData; + if( iPage<1 ){ + checkAppendMsg(pCheck, zContext, + "%d of %d pages missing from overflow list starting at %d", + N+1, expected, iFirst); + break; + } + if( checkRef(pCheck, iPage, zContext) ) break; + if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage) ){ + checkAppendMsg(pCheck, zContext, "failed to get page %d", iPage); + break; + } + pOvflData = (unsigned char *)sqlite3PagerGetData(pOvflPage); + if( isFreeList ){ + int n = get4byte(&pOvflData[4]); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pCheck->pBt->autoVacuum ){ + checkPtrmap(pCheck, iPage, PTRMAP_FREEPAGE, 0, zContext); + } +#endif + if( n>pCheck->pBt->usableSize/4-2 ){ + checkAppendMsg(pCheck, zContext, + "freelist leaf count too big on page %d", iPage); + N--; + }else{ + for(i=0; i<n; i++){ + Pgno iFreePage = get4byte(&pOvflData[8+i*4]); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pCheck->pBt->autoVacuum ){ + checkPtrmap(pCheck, iFreePage, PTRMAP_FREEPAGE, 0, zContext); + } +#endif + checkRef(pCheck, iFreePage, zContext); + } + N -= n; + } + } +#ifndef SQLITE_OMIT_AUTOVACUUM + else{ + /* If this database supports auto-vacuum and iPage is not the last + ** page in this overflow list, check that the pointer-map entry for + ** the following page matches iPage. + */ + if( pCheck->pBt->autoVacuum && N>0 ){ + i = get4byte(pOvflData); + checkPtrmap(pCheck, i, PTRMAP_OVERFLOW2, iPage, zContext); + } + } +#endif + iPage = get4byte(pOvflData); + sqlite3PagerUnref(pOvflPage); + } +} +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ + +#ifndef SQLITE_OMIT_INTEGRITY_CHECK +/* +** Do various sanity checks on a single page of a tree. Return +** the tree depth. Root pages return 0. Parents of root pages +** return 1, and so forth. +** +** These checks are done: +** +** 1. Make sure that cells and freeblocks do not overlap +** but combine to completely cover the page. +** NO 2. Make sure cell keys are in order. +** NO 3. Make sure no key is less than or equal to zLowerBound. +** NO 4. Make sure no key is greater than or equal to zUpperBound. +** 5. Check the integrity of overflow pages. +** 6. Recursively call checkTreePage on all children. +** 7. Verify that the depth of all children is the same. +** 8. Make sure this page is at least 33% full or else it is +** the root of the tree. +*/ +static int checkTreePage( + IntegrityCk *pCheck, /* Context for the sanity check */ + int iPage, /* Page number of the page to check */ + MemPage *pParent, /* Parent page */ + char *zParentContext /* Parent context */ +){ + MemPage *pPage; + int i, rc, depth, d2, pgno, cnt; + int hdr, cellStart; + int nCell; + u8 *data; + BtShared *pBt; + int usableSize; + char zContext[100]; + char *hit; + + sqlite3_snprintf(sizeof(zContext), zContext, "Page %d: ", iPage); + + /* Check that the page exists + */ + pBt = pCheck->pBt; + usableSize = pBt->usableSize; + if( iPage==0 ) return 0; + if( checkRef(pCheck, iPage, zParentContext) ) return 0; + if( (rc = sqlite3BtreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){ + checkAppendMsg(pCheck, zContext, + "unable to get the page. error code=%d", rc); + return 0; + } + if( (rc = sqlite3BtreeInitPage(pPage, pParent))!=0 ){ + checkAppendMsg(pCheck, zContext, + "sqlite3BtreeInitPage() returns error code %d", rc); + releasePage(pPage); + return 0; + } + + /* Check out all the cells. + */ + depth = 0; + for(i=0; i<pPage->nCell && pCheck->mxErr; i++){ + u8 *pCell; + int sz; + CellInfo info; + + /* Check payload overflow pages + */ + sqlite3_snprintf(sizeof(zContext), zContext, + "On tree page %d cell %d: ", iPage, i); + pCell = findCell(pPage,i); + sqlite3BtreeParseCellPtr(pPage, pCell, &info); + sz = info.nData; + if( !pPage->intKey ) sz += info.nKey; + assert( sz==info.nPayload ); + if( sz>info.nLocal ){ + int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4); + Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage, zContext); + } +#endif + checkList(pCheck, 0, pgnoOvfl, nPage, zContext); + } + + /* Check sanity of left child page. + */ + if( !pPage->leaf ){ + pgno = get4byte(pCell); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext); + } +#endif + d2 = checkTreePage(pCheck,pgno,pPage,zContext); + if( i>0 && d2!=depth ){ + checkAppendMsg(pCheck, zContext, "Child page depth differs"); + } + depth = d2; + } + } + if( !pPage->leaf ){ + pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); + sqlite3_snprintf(sizeof(zContext), zContext, + "On page %d at right child: ", iPage); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, 0); + } +#endif + checkTreePage(pCheck, pgno, pPage, zContext); + } + + /* Check for complete coverage of the page + */ + data = pPage->aData; + hdr = pPage->hdrOffset; + hit = sqlite3PageMalloc( pBt->pageSize ); + if( hit==0 ){ + pCheck->mallocFailed = 1; + }else{ + memset(hit, 0, usableSize ); + memset(hit, 1, get2byte(&data[hdr+5])); + nCell = get2byte(&data[hdr+3]); + cellStart = hdr + 12 - 4*pPage->leaf; + for(i=0; i<nCell; i++){ + int pc = get2byte(&data[cellStart+i*2]); + u16 size = cellSizePtr(pPage, &data[pc]); + int j; + if( (pc+size-1)>=usableSize || pc<0 ){ + checkAppendMsg(pCheck, 0, + "Corruption detected in cell %d on page %d",i,iPage,0); + }else{ + for(j=pc+size-1; j>=pc; j--) hit[j]++; + } + } + for(cnt=0, i=get2byte(&data[hdr+1]); i>0 && i<usableSize && cnt<10000; + cnt++){ + int size = get2byte(&data[i+2]); + int j; + if( (i+size-1)>=usableSize || i<0 ){ + checkAppendMsg(pCheck, 0, + "Corruption detected in cell %d on page %d",i,iPage,0); + }else{ + for(j=i+size-1; j>=i; j--) hit[j]++; + } + i = get2byte(&data[i]); + } + for(i=cnt=0; i<usableSize; i++){ + if( hit[i]==0 ){ + cnt++; + }else if( hit[i]>1 ){ + checkAppendMsg(pCheck, 0, + "Multiple uses for byte %d of page %d", i, iPage); + break; + } + } + if( cnt!=data[hdr+7] ){ + checkAppendMsg(pCheck, 0, + "Fragmented space is %d byte reported as %d on page %d", + cnt, data[hdr+7], iPage); + } + } + sqlite3PageFree(hit); + + releasePage(pPage); + return depth+1; +} +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ + +#ifndef SQLITE_OMIT_INTEGRITY_CHECK +/* +** This routine does a complete check of the given BTree file. aRoot[] is +** an array of pages numbers were each page number is the root page of +** a table. nRoot is the number of entries in aRoot. +** +** Write the number of error seen in *pnErr. Except for some memory +** allocation errors, nn error message is held in memory obtained from +** malloc is returned if *pnErr is non-zero. If *pnErr==0 then NULL is +** returned. +*/ +char *sqlite3BtreeIntegrityCheck( + Btree *p, /* The btree to be checked */ + int *aRoot, /* An array of root pages numbers for individual trees */ + int nRoot, /* Number of entries in aRoot[] */ + int mxErr, /* Stop reporting errors after this many */ + int *pnErr /* Write number of errors seen to this variable */ +){ + int i; + int nRef; + IntegrityCk sCheck; + BtShared *pBt = p->pBt; + char zErr[100]; + + sqlite3BtreeEnter(p); + pBt->db = p->db; + nRef = sqlite3PagerRefcount(pBt->pPager); + if( lockBtreeWithRetry(p)!=SQLITE_OK ){ + *pnErr = 1; + sqlite3BtreeLeave(p); + return sqlite3DbStrDup(0, "cannot acquire a read lock on the database"); + } + sCheck.pBt = pBt; + sCheck.pPager = pBt->pPager; + sCheck.nPage = pagerPagecount(sCheck.pPager); + sCheck.mxErr = mxErr; + sCheck.nErr = 0; + sCheck.mallocFailed = 0; + *pnErr = 0; +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->nTrunc!=0 ){ + sCheck.nPage = pBt->nTrunc; + } +#endif + if( sCheck.nPage==0 ){ + unlockBtreeIfUnused(pBt); + sqlite3BtreeLeave(p); + return 0; + } + sCheck.anRef = sqlite3Malloc( (sCheck.nPage+1)*sizeof(sCheck.anRef[0]) ); + if( !sCheck.anRef ){ + unlockBtreeIfUnused(pBt); + *pnErr = 1; + sqlite3BtreeLeave(p); + return 0; + } + for(i=0; i<=sCheck.nPage; i++){ sCheck.anRef[i] = 0; } + i = PENDING_BYTE_PAGE(pBt); + if( i<=sCheck.nPage ){ + sCheck.anRef[i] = 1; + } + sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), 20000); + + /* Check the integrity of the freelist + */ + checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]), + get4byte(&pBt->pPage1->aData[36]), "Main freelist: "); + + /* Check all the tables. + */ + for(i=0; i<nRoot && sCheck.mxErr; i++){ + if( aRoot[i]==0 ) continue; +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum && aRoot[i]>1 ){ + checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0, 0); + } +#endif + checkTreePage(&sCheck, aRoot[i], 0, "List of tree roots: "); + } + + /* Make sure every page in the file is referenced + */ + for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){ +#ifdef SQLITE_OMIT_AUTOVACUUM + if( sCheck.anRef[i]==0 ){ + checkAppendMsg(&sCheck, 0, "Page %d is never used", i); + } +#else + /* If the database supports auto-vacuum, make sure no tables contain + ** references to pointer-map pages. + */ + if( sCheck.anRef[i]==0 && + (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){ + checkAppendMsg(&sCheck, 0, "Page %d is never used", i); + } + if( sCheck.anRef[i]!=0 && + (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){ + checkAppendMsg(&sCheck, 0, "Pointer map page %d is referenced", i); + } +#endif + } + + /* Make sure this analysis did not leave any unref() pages + */ + unlockBtreeIfUnused(pBt); + if( nRef != sqlite3PagerRefcount(pBt->pPager) ){ + checkAppendMsg(&sCheck, 0, + "Outstanding page count goes from %d to %d during this analysis", + nRef, sqlite3PagerRefcount(pBt->pPager) + ); + } + + /* Clean up and report errors. + */ + sqlite3BtreeLeave(p); + sqlite3_free(sCheck.anRef); + if( sCheck.mallocFailed ){ + sqlite3StrAccumReset(&sCheck.errMsg); + *pnErr = sCheck.nErr+1; + return 0; + } + *pnErr = sCheck.nErr; + if( sCheck.nErr==0 ) sqlite3StrAccumReset(&sCheck.errMsg); + return sqlite3StrAccumFinish(&sCheck.errMsg); +} +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ + +/* +** Return the full pathname of the underlying database file. +** +** The pager filename is invariant as long as the pager is +** open so it is safe to access without the BtShared mutex. +*/ +const char *sqlite3BtreeGetFilename(Btree *p){ + assert( p->pBt->pPager!=0 ); + return sqlite3PagerFilename(p->pBt->pPager); +} + +/* +** Return the pathname of the directory that contains the database file. +** +** The pager directory name is invariant as long as the pager is +** open so it is safe to access without the BtShared mutex. +*/ +const char *sqlite3BtreeGetDirname(Btree *p){ + assert( p->pBt->pPager!=0 ); + return sqlite3PagerDirname(p->pBt->pPager); +} + +/* +** Return the pathname of the journal file for this database. The return +** value of this routine is the same regardless of whether the journal file +** has been created or not. +** +** The pager journal filename is invariant as long as the pager is +** open so it is safe to access without the BtShared mutex. +*/ +const char *sqlite3BtreeGetJournalname(Btree *p){ + assert( p->pBt->pPager!=0 ); + return sqlite3PagerJournalname(p->pBt->pPager); +} + +#ifndef SQLITE_OMIT_VACUUM +/* +** Copy the complete content of pBtFrom into pBtTo. A transaction +** must be active for both files. +** +** The size of file pTo may be reduced by this operation. +** If anything goes wrong, the transaction on pTo is rolled back. +** +** If successful, CommitPhaseOne() may be called on pTo before returning. +** The caller should finish committing the transaction on pTo by calling +** sqlite3BtreeCommit(). +*/ +static int btreeCopyFile(Btree *pTo, Btree *pFrom){ + int rc = SQLITE_OK; + Pgno i; + + Pgno nFromPage; /* Number of pages in pFrom */ + Pgno nToPage; /* Number of pages in pTo */ + Pgno nNewPage; /* Number of pages in pTo after the copy */ + + Pgno iSkip; /* Pending byte page in pTo */ + int nToPageSize; /* Page size of pTo in bytes */ + int nFromPageSize; /* Page size of pFrom in bytes */ + + BtShared *pBtTo = pTo->pBt; + BtShared *pBtFrom = pFrom->pBt; + pBtTo->db = pTo->db; + pBtFrom->db = pFrom->db; + + nToPageSize = pBtTo->pageSize; + nFromPageSize = pBtFrom->pageSize; + + if( pTo->inTrans!=TRANS_WRITE || pFrom->inTrans!=TRANS_WRITE ){ + return SQLITE_ERROR; + } + if( pBtTo->pCursor ){ + return SQLITE_BUSY; + } + + nToPage = pagerPagecount(pBtTo->pPager); + nFromPage = pagerPagecount(pBtFrom->pPager); + iSkip = PENDING_BYTE_PAGE(pBtTo); + + /* Variable nNewPage is the number of pages required to store the + ** contents of pFrom using the current page-size of pTo. + */ + nNewPage = ((i64)nFromPage * (i64)nFromPageSize + (i64)nToPageSize - 1) / + (i64)nToPageSize; + + for(i=1; rc==SQLITE_OK && (i<=nToPage || i<=nNewPage); i++){ + + /* Journal the original page. + ** + ** iSkip is the page number of the locking page (PENDING_BYTE_PAGE) + ** in database *pTo (before the copy). This page is never written + ** into the journal file. Unless i==iSkip or the page was not + ** present in pTo before the copy operation, journal page i from pTo. + */ + if( i!=iSkip && i<=nToPage ){ + DbPage *pDbPage = 0; + rc = sqlite3PagerGet(pBtTo->pPager, i, &pDbPage); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerWrite(pDbPage); + if( rc==SQLITE_OK && i>nFromPage ){ + /* Yeah. It seems wierd to call DontWrite() right after Write(). But + ** that is because the names of those procedures do not exactly + ** represent what they do. Write() really means "put this page in the + ** rollback journal and mark it as dirty so that it will be written + ** to the database file later." DontWrite() undoes the second part of + ** that and prevents the page from being written to the database. The + ** page is still on the rollback journal, though. And that is the + ** whole point of this block: to put pages on the rollback journal. + */ + sqlite3PagerDontWrite(pDbPage); + } + sqlite3PagerUnref(pDbPage); + } + } + + /* Overwrite the data in page i of the target database */ + if( rc==SQLITE_OK && i!=iSkip && i<=nNewPage ){ + + DbPage *pToPage = 0; + sqlite3_int64 iOff; + + rc = sqlite3PagerGet(pBtTo->pPager, i, &pToPage); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerWrite(pToPage); + } + + for( + iOff=(i-1)*nToPageSize; + rc==SQLITE_OK && iOff<i*nToPageSize; + iOff += nFromPageSize + ){ + DbPage *pFromPage = 0; + Pgno iFrom = (iOff/nFromPageSize)+1; + + if( iFrom==PENDING_BYTE_PAGE(pBtFrom) ){ + continue; + } + + rc = sqlite3PagerGet(pBtFrom->pPager, iFrom, &pFromPage); + if( rc==SQLITE_OK ){ + char *zTo = sqlite3PagerGetData(pToPage); + char *zFrom = sqlite3PagerGetData(pFromPage); + int nCopy; + + if( nFromPageSize>=nToPageSize ){ + zFrom += ((i-1)*nToPageSize - ((iFrom-1)*nFromPageSize)); + nCopy = nToPageSize; + }else{ + zTo += (((iFrom-1)*nFromPageSize) - (i-1)*nToPageSize); + nCopy = nFromPageSize; + } + + memcpy(zTo, zFrom, nCopy); + sqlite3PagerUnref(pFromPage); + } + } + + if( pToPage ) sqlite3PagerUnref(pToPage); + } + } + + /* If things have worked so far, the database file may need to be + ** truncated. The complex part is that it may need to be truncated to + ** a size that is not an integer multiple of nToPageSize - the current + ** page size used by the pager associated with B-Tree pTo. + ** + ** For example, say the page-size of pTo is 2048 bytes and the original + ** number of pages is 5 (10 KB file). If pFrom has a page size of 1024 + ** bytes and 9 pages, then the file needs to be truncated to 9KB. + */ + if( rc==SQLITE_OK ){ + if( nFromPageSize!=nToPageSize ){ + sqlite3_file *pFile = sqlite3PagerFile(pBtTo->pPager); + i64 iSize = (i64)nFromPageSize * (i64)nFromPage; + i64 iNow = (i64)((nToPage>nNewPage)?nToPage:nNewPage) * (i64)nToPageSize; + i64 iPending = ((i64)PENDING_BYTE_PAGE(pBtTo)-1) *(i64)nToPageSize; + + assert( iSize<=iNow ); + + /* Commit phase one syncs the journal file associated with pTo + ** containing the original data. It does not sync the database file + ** itself. After doing this it is safe to use OsTruncate() and other + ** file APIs on the database file directly. + */ + pBtTo->db = pTo->db; + rc = sqlite3PagerCommitPhaseOne(pBtTo->pPager, 0, 0, 1); + if( iSize<iNow && rc==SQLITE_OK ){ + rc = sqlite3OsTruncate(pFile, iSize); + } + + /* The loop that copied data from database pFrom to pTo did not + ** populate the locking page of database pTo. If the page-size of + ** pFrom is smaller than that of pTo, this means some data will + ** not have been copied. + ** + ** This block copies the missing data from database pFrom to pTo + ** using file APIs. This is safe because at this point we know that + ** all of the original data from pTo has been synced into the + ** journal file. At this point it would be safe to do anything at + ** all to the database file except truncate it to zero bytes. + */ + if( rc==SQLITE_OK && nFromPageSize<nToPageSize && iSize>iPending){ + i64 iOff; + for( + iOff=iPending; + rc==SQLITE_OK && iOff<(iPending+nToPageSize); + iOff += nFromPageSize + ){ + DbPage *pFromPage = 0; + Pgno iFrom = (iOff/nFromPageSize)+1; + + if( iFrom==PENDING_BYTE_PAGE(pBtFrom) || iFrom>nFromPage ){ + continue; + } + + rc = sqlite3PagerGet(pBtFrom->pPager, iFrom, &pFromPage); + if( rc==SQLITE_OK ){ + char *zFrom = sqlite3PagerGetData(pFromPage); + rc = sqlite3OsWrite(pFile, zFrom, nFromPageSize, iOff); + sqlite3PagerUnref(pFromPage); + } + } + } + + /* Sync the database file */ + if( rc==SQLITE_OK ){ + rc = sqlite3PagerSync(pBtTo->pPager); + } + }else{ + rc = sqlite3PagerTruncate(pBtTo->pPager, nNewPage); + } + if( rc==SQLITE_OK ){ + pBtTo->pageSizeFixed = 0; + } + } + + if( rc ){ + sqlite3BtreeRollback(pTo); + } + + return rc; +} +int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){ + int rc; + sqlite3BtreeEnter(pTo); + sqlite3BtreeEnter(pFrom); + rc = btreeCopyFile(pTo, pFrom); + sqlite3BtreeLeave(pFrom); + sqlite3BtreeLeave(pTo); + return rc; +} + +#endif /* SQLITE_OMIT_VACUUM */ + +/* +** Return non-zero if a transaction is active. +*/ +int sqlite3BtreeIsInTrans(Btree *p){ + assert( p==0 || sqlite3_mutex_held(p->db->mutex) ); + return (p && (p->inTrans==TRANS_WRITE)); +} + +/* +** Return non-zero if a statement transaction is active. +*/ +int sqlite3BtreeIsInStmt(Btree *p){ + assert( sqlite3BtreeHoldsMutex(p) ); + return (p->pBt && p->pBt->inStmt); +} + +/* +** Return non-zero if a read (or write) transaction is active. +*/ +int sqlite3BtreeIsInReadTrans(Btree *p){ + assert( sqlite3_mutex_held(p->db->mutex) ); + return (p && (p->inTrans!=TRANS_NONE)); +} + +/* +** This function returns a pointer to a blob of memory associated with +** a single shared-btree. The memory is used by client code for its 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. +** +** If the nBytes parameter is 0 and the blob of memory has not yet been +** allocated, a null pointer is returned. If the blob has already been +** allocated, it is returned as normal. +** +** 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 sqlite3_free() +** on the memory, the btree layer does that. +*/ +void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){ + BtShared *pBt = p->pBt; + sqlite3BtreeEnter(p); + if( !pBt->pSchema && nBytes ){ + pBt->pSchema = sqlite3MallocZero(nBytes); + pBt->xFreeSchema = xFree; + } + sqlite3BtreeLeave(p); + 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){ + int rc; + assert( sqlite3_mutex_held(p->db->mutex) ); + sqlite3BtreeEnter(p); + rc = (queryTableLock(p, MASTER_ROOT, READ_LOCK)!=SQLITE_OK); + sqlite3BtreeLeave(p); + return rc; +} + + +#ifndef SQLITE_OMIT_SHARED_CACHE +/* +** Obtain a lock on the table whose root page is iTab. The +** lock is a write lock if isWritelock is true or a read lock +** if it is false. +*/ +int sqlite3BtreeLockTable(Btree *p, int iTab, u8 isWriteLock){ + int rc = SQLITE_OK; + if( p->sharable ){ + u8 lockType = READ_LOCK + isWriteLock; + assert( READ_LOCK+1==WRITE_LOCK ); + assert( isWriteLock==0 || isWriteLock==1 ); + sqlite3BtreeEnter(p); + rc = queryTableLock(p, iTab, lockType); + if( rc==SQLITE_OK ){ + rc = lockTable(p, iTab, lockType); + } + sqlite3BtreeLeave(p); + } + return rc; +} +#endif + +#ifndef SQLITE_OMIT_INCRBLOB +/* +** Argument pCsr must be a cursor opened for writing on an +** INTKEY table currently pointing at a valid table entry. +** This function modifies the data stored as part of that entry. +** Only the data content may only be modified, it is not possible +** to change the length of the data stored. +*/ +int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){ + assert( cursorHoldsMutex(pCsr) ); + assert( sqlite3_mutex_held(pCsr->pBtree->db->mutex) ); + assert(pCsr->isIncrblobHandle); + + restoreCursorPosition(pCsr); + assert( pCsr->eState!=CURSOR_REQUIRESEEK ); + if( pCsr->eState!=CURSOR_VALID ){ + return SQLITE_ABORT; + } + + /* Check some preconditions: + ** (a) the cursor is open for writing, + ** (b) there is no read-lock on the table being modified and + ** (c) the cursor points at a valid row of an intKey table. + */ + if( !pCsr->wrFlag ){ + return SQLITE_READONLY; + } + assert( !pCsr->pBt->readOnly + && pCsr->pBt->inTransaction==TRANS_WRITE ); + if( checkReadLocks(pCsr->pBtree, pCsr->pgnoRoot, pCsr, 0) ){ + return SQLITE_LOCKED; /* The table pCur points to has a read lock */ + } + if( pCsr->eState==CURSOR_INVALID || !pCsr->pPage->intKey ){ + return SQLITE_ERROR; + } + + return accessPayload(pCsr, offset, amt, (unsigned char *)z, 0, 1); +} + +/* +** Set a flag on this cursor to cache the locations of pages from the +** overflow list for the current row. This is used by cursors opened +** for incremental blob IO only. +** +** This function sets a flag only. The actual page location cache +** (stored in BtCursor.aOverflow[]) is allocated and used by function +** accessPayload() (the worker function for sqlite3BtreeData() and +** sqlite3BtreePutData()). +*/ +void sqlite3BtreeCacheOverflow(BtCursor *pCur){ + assert( cursorHoldsMutex(pCur) ); + assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); + assert(!pCur->isIncrblobHandle); + assert(!pCur->aOverflow); + pCur->isIncrblobHandle = 1; +} + +/* Poison the db so that other clients error out as quickly as +** possible. +*/ +int sqlite3Poison(sqlite3 *db){ + int rc; + Btree *p; + BtShared *pBt; + unsigned char *pP1; + + if( db == NULL) return SQLITE_OK; + + /* Database 0 corrosponds to the main database. */ + if( db->nDb<1 ) return SQLITE_OK; + p = db->aDb[0].pBt; + pBt = p->pBt; + + /* If in a transaction, roll it back. Committing any changes to a + ** corrupt database may mess up evidence, we definitely don't want + ** to allow poisoning to be rolled back, and the database is anyhow + ** going bye-bye RSN. + */ + /* TODO(shess): Figure out if this might release the lock and let + ** someone else get in there, which might deny us the lock a couple + ** lines down. + */ + if( sqlite3BtreeIsInTrans(p) ) sqlite3BtreeRollback(p); + + /* Start an exclusive transaction. This will check the headers, so + ** if someone else poisoned the database we should get an error. + */ + rc = sqlite3BtreeBeginTrans(p, 2); + /* TODO(shess): Handle SQLITE_BUSY? */ + if( rc!=SQLITE_OK ) return rc; + + /* Copied from sqlite3BtreeUpdateMeta(). Writing the old version of + ** the page to the journal may be overkill, but it probably won't + ** hurt. + */ + assert( pBt->inTrans==TRANS_WRITE ); + assert( pBt->pPage1!=0 ); + rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); + if( rc ) goto err; + + /* "SQLite format 3" changes to + ** "SQLite poison 3". Be extra paranoid about making this change. + */ + if( sizeof(zMagicHeader)!=16 || + sizeof(zPoisonHeader)!=sizeof(zMagicHeader) ){ + rc = SQLITE_ERROR; + goto err; + } + pP1 = pBt->pPage1->aData; + if( memcmp(pP1, zMagicHeader, 16)!=0 ){ + rc = SQLITE_CORRUPT; + goto err; + } + memcpy(pP1, zPoisonHeader, 16); + + /* Push it to the database file. */ + return sqlite3BtreeCommit(p); + + err: + /* TODO(shess): What about errors, here? */ + sqlite3BtreeRollback(p); + return rc; +} + +#endif diff --git a/third_party/sqlite/src/btree.h b/third_party/sqlite/src/btree.h new file mode 100755 index 0000000..3fe01cb --- /dev/null +++ b/third_party/sqlite/src/btree.h @@ -0,0 +1,219 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This header file defines the interface that the sqlite B-Tree file +** subsystem. See comments in the source code for a detailed description +** of what each interface routine does. +** +** @(#) $Id: btree.h,v 1.102 2008/07/11 21:02:54 drh Exp $ +*/ +#ifndef _BTREE_H_ +#define _BTREE_H_ + +/* TODO: This definition is just included so other modules compile. It +** needs to be revisited. +*/ +#define SQLITE_N_BTREE_META 10 + +/* +** If defined as non-zero, auto-vacuum is enabled by default. Otherwise +** it must be turned on for each database using "PRAGMA auto_vacuum = 1". +*/ +#ifndef SQLITE_DEFAULT_AUTOVACUUM + #define SQLITE_DEFAULT_AUTOVACUUM 0 +#endif + +#define BTREE_AUTOVACUUM_NONE 0 /* Do not do auto-vacuum */ +#define BTREE_AUTOVACUUM_FULL 1 /* Do full auto-vacuum */ +#define BTREE_AUTOVACUUM_INCR 2 /* Incremental vacuum */ + +/* +** Forward declarations of structure +*/ +typedef struct Btree Btree; +typedef struct BtCursor BtCursor; +typedef struct BtShared BtShared; +typedef struct BtreeMutexArray BtreeMutexArray; + +/* +** This structure records all of the Btrees that need to hold +** a mutex before we enter sqlite3VdbeExec(). The Btrees are +** are placed in aBtree[] in order of aBtree[]->pBt. That way, +** we can always lock and unlock them all quickly. +*/ +struct BtreeMutexArray { + int nMutex; + Btree *aBtree[SQLITE_MAX_ATTACHED+1]; +}; + + +int sqlite3BtreeOpen( + const char *zFilename, /* Name of database file to open */ + sqlite3 *db, /* Associated database connection */ + Btree **, /* Return open Btree* here */ + int flags, /* Flags */ + int vfsFlags /* Flags passed through to VFS open */ +); + +/* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the +** following values. +** +** NOTE: These values must match the corresponding PAGER_ values in +** pager.h. +*/ +#define BTREE_OMIT_JOURNAL 1 /* Do not use journal. No argument */ +#define BTREE_NO_READLOCK 2 /* Omit readlocks on readonly files */ +#define BTREE_MEMORY 4 /* In-memory DB. No argument */ +#define BTREE_READONLY 8 /* Open the database in read-only mode */ +#define BTREE_READWRITE 16 /* Open for both reading and writing */ +#define BTREE_CREATE 32 /* Create the database if it does not exist */ + +int sqlite3BtreeClose(Btree*); +int sqlite3BtreeSetCacheSize(Btree*,int); +int sqlite3BtreeSetSafetyLevel(Btree*,int,int); +int sqlite3BtreeSyncDisabled(Btree*); +int sqlite3BtreeSetPageSize(Btree*,int,int); +int sqlite3BtreeGetPageSize(Btree*); +int sqlite3BtreeMaxPageCount(Btree*,int); +int sqlite3BtreeGetReserve(Btree*); +int sqlite3BtreeSetAutoVacuum(Btree *, int); +int sqlite3BtreeGetAutoVacuum(Btree *); +int sqlite3BtreeBeginTrans(Btree*,int); +int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); +int sqlite3BtreeCommitPhaseTwo(Btree*); +int sqlite3BtreeCommit(Btree*); +int sqlite3BtreeRollback(Btree*); +int sqlite3BtreeBeginStmt(Btree*); +int sqlite3BtreeCommitStmt(Btree*); +int sqlite3BtreeRollbackStmt(Btree*); +int sqlite3BtreeCreateTable(Btree*, int*, int flags); +int sqlite3BtreeIsInTrans(Btree*); +int sqlite3BtreeIsInStmt(Btree*); +int sqlite3BtreeIsInReadTrans(Btree*); +void *sqlite3BtreeSchema(Btree *, int, void(*)(void *)); +int sqlite3BtreeSchemaLocked(Btree *); +int sqlite3BtreeLockTable(Btree *, int, u8); + +const char *sqlite3BtreeGetFilename(Btree *); +const char *sqlite3BtreeGetDirname(Btree *); +const char *sqlite3BtreeGetJournalname(Btree *); +int sqlite3BtreeCopyFile(Btree *, Btree *); + +int sqlite3BtreeIncrVacuum(Btree *); + +/* The flags parameter to sqlite3BtreeCreateTable can be the bitwise OR +** of the following flags: +*/ +#define BTREE_INTKEY 1 /* Table has only 64-bit signed integer keys */ +#define BTREE_ZERODATA 2 /* Table has keys only - no data */ +#define BTREE_LEAFDATA 4 /* Data stored in leaves only. Implies INTKEY */ + +int sqlite3BtreeDropTable(Btree*, int, int*); +int sqlite3BtreeClearTable(Btree*, int); +int sqlite3BtreeGetMeta(Btree*, int idx, u32 *pValue); +int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); +void sqlite3BtreeTripAllCursors(Btree*, int); + +struct UnpackedRecord; /* Forward declaration. Definition in vdbeaux.c. */ + +int sqlite3BtreeCursor( + Btree*, /* BTree containing table to open */ + int iTable, /* Index of root page */ + int wrFlag, /* 1 for writing. 0 for read-only */ + struct KeyInfo*, /* First argument to compare function */ + BtCursor *pCursor /* Space to write cursor structure */ +); +int sqlite3BtreeCursorSize(void); + +int sqlite3BtreeCloseCursor(BtCursor*); +int sqlite3BtreeMoveto( + BtCursor*, + const void *pKey, + struct UnpackedRecord *pUnKey, + i64 nKey, + int bias, + int *pRes +); +int sqlite3BtreeCursorHasMoved(BtCursor*, int*); +int sqlite3BtreeDelete(BtCursor*); +int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey, + const void *pData, int nData, + int nZero, int bias); +int sqlite3BtreeFirst(BtCursor*, int *pRes); +int sqlite3BtreeLast(BtCursor*, int *pRes); +int sqlite3BtreeNext(BtCursor*, int *pRes); +int sqlite3BtreeEof(BtCursor*); +int sqlite3BtreeFlags(BtCursor*); +int sqlite3BtreePrevious(BtCursor*, int *pRes); +int sqlite3BtreeKeySize(BtCursor*, i64 *pSize); +int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*); +sqlite3 *sqlite3BtreeCursorDb(const BtCursor*); +const void *sqlite3BtreeKeyFetch(BtCursor*, int *pAmt); +const void *sqlite3BtreeDataFetch(BtCursor*, int *pAmt); +int sqlite3BtreeDataSize(BtCursor*, u32 *pSize); +int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*); + +char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*); +struct Pager *sqlite3BtreePager(Btree*); + +int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); +void sqlite3BtreeCacheOverflow(BtCursor *); + +#ifdef SQLITE_TEST +int sqlite3BtreeCursorInfo(BtCursor*, int*, int); +void sqlite3BtreeCursorList(Btree*); +#endif + +/* +** If we are not using shared cache, then there is no need to +** use mutexes to access the BtShared structures. So make the +** Enter and Leave procedures no-ops. +*/ +#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE + void sqlite3BtreeEnter(Btree*); + void sqlite3BtreeLeave(Btree*); +#ifndef NDEBUG + /* This routine is used inside assert() statements only. */ + int sqlite3BtreeHoldsMutex(Btree*); +#endif + void sqlite3BtreeEnterCursor(BtCursor*); + void sqlite3BtreeLeaveCursor(BtCursor*); + void sqlite3BtreeEnterAll(sqlite3*); + void sqlite3BtreeLeaveAll(sqlite3*); +#ifndef NDEBUG + /* This routine is used inside assert() statements only. */ + int sqlite3BtreeHoldsAllMutexes(sqlite3*); +#endif + void sqlite3BtreeMutexArrayEnter(BtreeMutexArray*); + void sqlite3BtreeMutexArrayLeave(BtreeMutexArray*); + void sqlite3BtreeMutexArrayInsert(BtreeMutexArray*, Btree*); +#else +# define sqlite3BtreeEnter(X) +# define sqlite3BtreeLeave(X) +#ifndef NDEBUG + /* This routine is used inside assert() statements only. */ +# define sqlite3BtreeHoldsMutex(X) 1 +#endif +# define sqlite3BtreeEnterCursor(X) +# define sqlite3BtreeLeaveCursor(X) +# define sqlite3BtreeEnterAll(X) +# define sqlite3BtreeLeaveAll(X) +#ifndef NDEBUG + /* This routine is used inside assert() statements only. */ +# define sqlite3BtreeHoldsAllMutexes(X) 1 +#endif +# define sqlite3BtreeMutexArrayEnter(X) +# define sqlite3BtreeMutexArrayLeave(X) +# define sqlite3BtreeMutexArrayInsert(X,Y) +#endif + + +#endif /* _BTREE_H_ */ diff --git a/third_party/sqlite/src/btreeInt.h b/third_party/sqlite/src/btreeInt.h new file mode 100755 index 0000000..663a41e --- /dev/null +++ b/third_party/sqlite/src/btreeInt.h @@ -0,0 +1,627 @@ +/* +** 2004 April 6 +** +** 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. +** +************************************************************************* +** $Id: btreeInt.h,v 1.30 2008/08/01 20:10:08 drh Exp $ +** +** This file implements a external (disk-based) database using BTrees. +** For a detailed discussion of BTrees, refer to +** +** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: +** "Sorting And Searching", pages 473-480. Addison-Wesley +** Publishing Company, Reading, Massachusetts. +** +** The basic idea is that each page of the file contains N database +** entries and N+1 pointers to subpages. +** +** ---------------------------------------------------------------- +** | Ptr(0) | Key(0) | Ptr(1) | Key(1) | ... | Key(N-1) | Ptr(N) | +** ---------------------------------------------------------------- +** +** All of the keys on the page that Ptr(0) points to have values less +** than Key(0). All of the keys on page Ptr(1) and its subpages have +** values greater than Key(0) and less than Key(1). All of the keys +** on Ptr(N) and its subpages have values greater than Key(N-1). And +** so forth. +** +** Finding a particular key requires reading O(log(M)) pages from the +** disk where M is the number of entries in the tree. +** +** In this implementation, a single file can hold one or more separate +** BTrees. Each BTree is identified by the index of its root page. The +** key and data for any entry are combined to form the "payload". A +** fixed amount of payload can be carried directly on the database +** page. If the payload is larger than the preset amount then surplus +** bytes are stored on overflow pages. The payload for an entry +** and the preceding pointer are combined to form a "Cell". Each +** page has a small header which contains the Ptr(N) pointer and other +** information such as the size of key and data. +** +** FORMAT DETAILS +** +** The file is divided into pages. The first page is called page 1, +** the second is page 2, and so forth. A page number of zero indicates +** "no such page". The page size can be anything between 512 and 65536. +** Each page can be either a btree page, a freelist page or an overflow +** page. +** +** The first page is always a btree page. The first 100 bytes of the first +** page contain a special header (the "file header") that describes the file. +** The format of the file header is as follows: +** +** OFFSET SIZE DESCRIPTION +** 0 16 Header string: "SQLite format 3\000" +** 16 2 Page size in bytes. +** 18 1 File format write version +** 19 1 File format read version +** 20 1 Bytes of unused space at the end of each page +** 21 1 Max embedded payload fraction +** 22 1 Min embedded payload fraction +** 23 1 Min leaf payload fraction +** 24 4 File change counter +** 28 4 Reserved for future use +** 32 4 First freelist page +** 36 4 Number of freelist pages in the file +** 40 60 15 4-byte meta values passed to higher layers +** +** All of the integer values are big-endian (most significant byte first). +** +** The file change counter is incremented when the database is changed +** This counter allows other processes to know when the file has changed +** and thus when they need to flush their cache. +** +** The max embedded payload fraction is the amount of the total usable +** space in a page that can be consumed by a single cell for standard +** B-tree (non-LEAFDATA) tables. A value of 255 means 100%. The default +** is to limit the maximum cell size so that at least 4 cells will fit +** on one page. Thus the default max embedded payload fraction is 64. +** +** If the payload for a cell is larger than the max payload, then extra +** payload is spilled to overflow pages. Once an overflow page is allocated, +** as many bytes as possible are moved into the overflow pages without letting +** the cell size drop below the min embedded payload fraction. +** +** The min leaf payload fraction is like the min embedded payload fraction +** except that it applies to leaf nodes in a LEAFDATA tree. The maximum +** payload fraction for a LEAFDATA tree is always 100% (or 255) and it +** not specified in the header. +** +** Each btree pages is divided into three sections: The header, the +** cell pointer array, and the cell content area. Page 1 also has a 100-byte +** file header that occurs before the page header. +** +** |----------------| +** | file header | 100 bytes. Page 1 only. +** |----------------| +** | page header | 8 bytes for leaves. 12 bytes for interior nodes +** |----------------| +** | cell pointer | | 2 bytes per cell. Sorted order. +** | array | | Grows downward +** | | v +** |----------------| +** | unallocated | +** | space | +** |----------------| ^ Grows upwards +** | cell content | | Arbitrary order interspersed with freeblocks. +** | area | | and free space fragments. +** |----------------| +** +** The page headers looks like this: +** +** OFFSET SIZE DESCRIPTION +** 0 1 Flags. 1: intkey, 2: zerodata, 4: leafdata, 8: leaf +** 1 2 byte offset to the first freeblock +** 3 2 number of cells on this page +** 5 2 first byte of the cell content area +** 7 1 number of fragmented free bytes +** 8 4 Right child (the Ptr(N) value). Omitted on leaves. +** +** The flags define the format of this btree page. The leaf flag means that +** this page has no children. The zerodata flag means that this page carries +** only keys and no data. The intkey flag means that the key is a integer +** which is stored in the key size entry of the cell header rather than in +** the payload area. +** +** The cell pointer array begins on the first byte after the page header. +** The cell pointer array contains zero or more 2-byte numbers which are +** offsets from the beginning of the page to the cell content in the cell +** content area. The cell pointers occur in sorted order. The system strives +** to keep free space after the last cell pointer so that new cells can +** be easily added without having to defragment the page. +** +** Cell content is stored at the very end of the page and grows toward the +** beginning of the page. +** +** Unused space within the cell content area is collected into a linked list of +** freeblocks. Each freeblock is at least 4 bytes in size. The byte offset +** to the first freeblock is given in the header. Freeblocks occur in +** increasing order. Because a freeblock must be at least 4 bytes in size, +** any group of 3 or fewer unused bytes in the cell content area cannot +** exist on the freeblock chain. A group of 3 or fewer free bytes is called +** a fragment. The total number of bytes in all fragments is recorded. +** in the page header at offset 7. +** +** SIZE DESCRIPTION +** 2 Byte offset of the next freeblock +** 2 Bytes in this freeblock +** +** Cells are of variable length. Cells are stored in the cell content area at +** the end of the page. Pointers to the cells are in the cell pointer array +** that immediately follows the page header. Cells is not necessarily +** contiguous or in order, but cell pointers are contiguous and in order. +** +** Cell content makes use of variable length integers. A variable +** length integer is 1 to 9 bytes where the lower 7 bits of each +** byte are used. The integer consists of all bytes that have bit 8 set and +** the first byte with bit 8 clear. The most significant byte of the integer +** appears first. A variable-length integer may not be more than 9 bytes long. +** As a special case, all 8 bytes of the 9th byte are used as data. This +** allows a 64-bit integer to be encoded in 9 bytes. +** +** 0x00 becomes 0x00000000 +** 0x7f becomes 0x0000007f +** 0x81 0x00 becomes 0x00000080 +** 0x82 0x00 becomes 0x00000100 +** 0x80 0x7f becomes 0x0000007f +** 0x8a 0x91 0xd1 0xac 0x78 becomes 0x12345678 +** 0x81 0x81 0x81 0x81 0x01 becomes 0x10204081 +** +** Variable length integers are used for rowids and to hold the number of +** bytes of key and data in a btree cell. +** +** The content of a cell looks like this: +** +** SIZE DESCRIPTION +** 4 Page number of the left child. Omitted if leaf flag is set. +** var Number of bytes of data. Omitted if the zerodata flag is set. +** var Number of bytes of key. Or the key itself if intkey flag is set. +** * Payload +** 4 First page of the overflow chain. Omitted if no overflow +** +** Overflow pages form a linked list. Each page except the last is completely +** filled with data (pagesize - 4 bytes). The last page can have as little +** as 1 byte of data. +** +** SIZE DESCRIPTION +** 4 Page number of next overflow page +** * Data +** +** Freelist pages come in two subtypes: trunk pages and leaf pages. The +** file header points to the first in a linked list of trunk page. Each trunk +** page points to multiple leaf pages. The content of a leaf page is +** unspecified. A trunk page looks like this: +** +** SIZE DESCRIPTION +** 4 Page number of next trunk page +** 4 Number of leaf pointers on this page +** * zero or more pages numbers of leaves +*/ +#include "sqliteInt.h" +#include "pager.h" +#include "btree.h" +#include "os.h" +#include <assert.h> + +/* Round up a number to the next larger multiple of 8. This is used +** to force 8-byte alignment on 64-bit architectures. +*/ +#define ROUND8(x) ((x+7)&~7) + + +/* The following value is the maximum cell size assuming a maximum page +** size give above. +*/ +#define MX_CELL_SIZE(pBt) (pBt->pageSize-8) + +/* The maximum number of cells on a single page of the database. This +** assumes a minimum cell size of 6 bytes (4 bytes for the cell itself +** plus 2 bytes for the index to the cell in the page header). Such +** small cells will be rare, but they are possible. +*/ +#define MX_CELL(pBt) ((pBt->pageSize-8)/6) + +/* Forward declarations */ +typedef struct MemPage MemPage; +typedef struct BtLock BtLock; + +/* +** This is a magic string that appears at the beginning of every +** SQLite database in order to identify the file as a real database. +** +** You can change this value at compile-time by specifying a +** -DSQLITE_FILE_HEADER="..." on the compiler command-line. The +** header must be exactly 16 bytes including the zero-terminator so +** the string itself should be 15 characters long. If you change +** the header, then your custom library will not be able to read +** databases generated by the standard tools and the standard tools +** will not be able to read databases created by your custom library. +*/ +#ifndef SQLITE_FILE_HEADER /* 123456789 123456 */ +# define SQLITE_FILE_HEADER "SQLite format 3" +#endif + +/* +** Page type flags. An ORed combination of these flags appear as the +** first byte of on-disk image of every BTree page. +*/ +#define PTF_INTKEY 0x01 +#define PTF_ZERODATA 0x02 +#define PTF_LEAFDATA 0x04 +#define PTF_LEAF 0x08 + +/* +** As each page of the file is loaded into memory, an instance of the following +** structure is appended and initialized to zero. This structure stores +** information about the page that is decoded from the raw file page. +** +** The pParent field points back to the parent page. This allows us to +** walk up the BTree from any leaf to the root. Care must be taken to +** unref() the parent page pointer when this page is no longer referenced. +** The pageDestructor() routine handles that chore. +** +** Access to all fields of this structure is controlled by the mutex +** stored in MemPage.pBt->mutex. +*/ +struct MemPage { + u8 isInit; /* True if previously initialized. MUST BE FIRST! */ + u8 idxShift; /* True if Cell indices have changed */ + u8 nOverflow; /* Number of overflow cell bodies in aCell[] */ + u8 intKey; /* True if intkey flag is set */ + u8 leaf; /* True if leaf flag is set */ + u8 hasData; /* True if this page stores data */ + u8 hdrOffset; /* 100 for page 1. 0 otherwise */ + u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */ + u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */ + u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */ + u16 cellOffset; /* Index in aData of first cell pointer */ + u16 idxParent; /* Index in parent of this node */ + u16 nFree; /* Number of free bytes on the page */ + u16 nCell; /* Number of cells on this page, local and ovfl */ + u16 maskPage; /* Mask for page offset */ + 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 */ + } aOvfl[5]; + BtShared *pBt; /* Pointer to BtShared that this page is part of */ + u8 *aData; /* Pointer to disk image of the page data */ + DbPage *pDbPage; /* Pager page handle */ + Pgno pgno; /* Page number for this page */ + MemPage *pParent; /* The parent of this page. NULL for root */ +}; + +/* +** The in-memory image of a disk page has the auxiliary information appended +** to the end. EXTRA_SIZE is the number of bytes of space needed to hold +** that extra information. +*/ +#define EXTRA_SIZE sizeof(MemPage) + +/* A Btree handle +** +** A database connection contains a pointer to an instance of +** this object for every database file that it has open. This structure +** is opaque to the database connection. The database connection cannot +** see the internals of this structure and only deals with pointers to +** this structure. +** +** For some database files, the same underlying database cache might be +** shared between multiple connections. In that case, each contection +** has it own pointer to this object. But each instance of this object +** points to the same BtShared object. The database cache and the +** schema associated with the database file are all contained within +** the BtShared object. +** +** All fields in this structure are accessed under sqlite3.mutex. +** The pBt pointer itself may not be changed while there exists cursors +** in the referenced BtShared that point back to this Btree since those +** cursors have to do go through this Btree to find their BtShared and +** they often do so without holding sqlite3.mutex. +*/ +struct Btree { + sqlite3 *db; /* The database connection holding this btree */ + BtShared *pBt; /* Sharable content of this btree */ + u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */ + u8 sharable; /* True if we can share pBt with another db */ + u8 locked; /* True if db currently has pBt locked */ + int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */ + Btree *pNext; /* List of other sharable Btrees from the same db */ + Btree *pPrev; /* Back pointer of the same list */ +}; + +/* +** 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. +*/ +#define TRANS_NONE 0 +#define TRANS_READ 1 +#define TRANS_WRITE 2 + +/* +** An instance of this object represents a single database file. +** +** A single database file can be in use as the same time by two +** or more database connections. When two or more connections are +** sharing the same database file, each connection has it own +** private Btree object for the file and each of those Btrees points +** to this one BtShared object. BtShared.nRef is the number of +** connections currently sharing this database file. +** +** Fields in this structure are accessed under the BtShared.mutex +** mutex, except for nRef and pNext which are accessed under the +** global SQLITE_MUTEX_STATIC_MASTER mutex. The pPager field +** may not be modified once it is initially set as long as nRef>0. +** The pSchema field may be set once under BtShared.mutex and +** thereafter is unchanged as long as nRef>0. +*/ +struct BtShared { + Pager *pPager; /* The page cache */ + sqlite3 *db; /* Database connection currently using this Btree */ + BtCursor *pCursor; /* A list of all open cursors */ + MemPage *pPage1; /* First page of the database */ + u8 inStmt; /* True if we are in a statement subtransaction */ + u8 readOnly; /* True if the underlying file is readonly */ + u8 pageSizeFixed; /* True if the page size can no longer be changed */ +#ifndef SQLITE_OMIT_AUTOVACUUM + u8 autoVacuum; /* True if auto-vacuum is enabled */ + u8 incrVacuum; /* True if incr-vacuum is enabled */ + Pgno nTrunc; /* Non-zero if the db will be truncated (incr vacuum) */ +#endif + u16 pageSize; /* Total number of bytes on a page */ + u16 usableSize; /* Number of usable bytes on each page */ + int maxLocal; /* Maximum local payload in non-LEAFDATA tables */ + int minLocal; /* Minimum local payload in non-LEAFDATA tables */ + int maxLeaf; /* Maximum local payload in a LEAFDATA table */ + int minLeaf; /* Minimum local payload in a LEAFDATA table */ + u8 inTransaction; /* Transaction state */ + int nTransaction; /* Number of open transactions (read + write) */ + void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */ + void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */ + sqlite3_mutex *mutex; /* Non-recursive mutex required to access this struct */ + BusyHandler busyHdr; /* The busy handler for this btree */ +#ifndef SQLITE_OMIT_SHARED_CACHE + int nRef; /* Number of references to this structure */ + BtShared *pNext; /* Next on a list of sharable BtShared structs */ + BtLock *pLock; /* List of locks held on this shared-btree struct */ + Btree *pExclusive; /* Btree with an EXCLUSIVE lock on the whole db */ +#endif + u8 *pTmpSpace; /* BtShared.pageSize bytes of space for tmp use */ +}; + +/* +** An instance of the following structure is used to hold information +** about a cell. The parseCellPtr() function fills in this structure +** based on information extract from the raw disk page. +*/ +typedef struct CellInfo CellInfo; +struct CellInfo { + u8 *pCell; /* Pointer to the start of cell content */ + i64 nKey; /* The key for INTKEY tables, or number of bytes in key */ + u32 nData; /* Number of bytes of data */ + u32 nPayload; /* Total amount of payload */ + u16 nHeader; /* Size of the cell content header in bytes */ + u16 nLocal; /* Amount of payload held locally */ + u16 iOverflow; /* Offset to overflow page number. Zero if no overflow */ + u16 nSize; /* Size of the cell content on the main b-tree page */ +}; + +/* +** A cursor is a pointer to a particular entry within a particular +** b-tree within a database file. +** +** The entry is identified by its MemPage and the index in +** MemPage.aCell[] of the entry. +** +** When a single database file can shared by two more database connections, +** but cursors cannot be shared. Each cursor is associated with a +** particular database connection identified BtCursor.pBtree.db. +** +** Fields in this structure are accessed under the BtShared.mutex +** found at self->pBt->mutex. +*/ +struct BtCursor { + Btree *pBtree; /* The Btree to which this cursor belongs */ + BtShared *pBt; /* The BtShared this cursor points to */ + BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */ + struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */ + Pgno pgnoRoot; /* The root page of this tree */ + MemPage *pPage; /* Page that contains the entry */ + 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 atLast; /* Cursor pointing to the last entry */ + u8 validNKey; /* True if info.nKey is valid */ + u8 eState; /* One of the CURSOR_XXX constants (see below) */ + void *pKey; /* Saved key that was cursor's last known position */ + i64 nKey; /* Size of pKey, or last integer key */ + int skip; /* (skip<0) -> Prev() is a no-op. (skip>0) -> Next() is */ +#ifndef SQLITE_OMIT_INCRBLOB + u8 isIncrblobHandle; /* True if this cursor is an incr. io handle */ + Pgno *aOverflow; /* Cache of overflow page locations */ +#endif +}; + +/* +** Potential values for BtCursor.eState. +** +** 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, restoreCursorPosition() can be called to attempt to +** seek the cursor to the saved position. +** +** CURSOR_FAULT: +** A unrecoverable error (an I/O error or a malloc failure) has occurred +** on a different connection that shares the BtShared cache with this +** cursor. The error has left the cache in an inconsistent state. +** Do nothing else with this cursor. Any attempt to use the cursor +** should return the error code stored in BtCursor.skip +*/ +#define CURSOR_INVALID 0 +#define CURSOR_VALID 1 +#define CURSOR_REQUIRESEEK 2 +#define CURSOR_FAULT 3 + +/* The database page the PENDING_BYTE occupies. This page is never used. +** TODO: This macro is very similary to PAGER_MJ_PGNO() in pager.c. They +** should possibly be consolidated (presumably in pager.h). +** +** If disk I/O is omitted (meaning that the database is stored purely +** in memory) then there is no pending byte. +*/ +#ifdef SQLITE_OMIT_DISKIO +# define PENDING_BYTE_PAGE(pBt) 0x7fffffff +#else +# define PENDING_BYTE_PAGE(pBt) ((PENDING_BYTE/(pBt)->pageSize)+1) +#endif + +/* +** 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 + +/* +** These macros define the location of the pointer-map entry for a +** database page. The first argument to each is the number of usable +** bytes on each page of the database (often 1024). The second is the +** page number to look up in the pointer map. +** +** PTRMAP_PAGENO returns the database page number of the pointer-map +** page that stores the required pointer. PTRMAP_PTROFFSET returns +** the offset of the requested map entry. +** +** If the pgno argument passed to PTRMAP_PAGENO is a pointer-map page, +** then pgno is returned. So (pgno==PTRMAP_PAGENO(pgsz, pgno)) can be +** used to test if pgno is a pointer-map page. PTRMAP_ISPAGE implements +** this test. +*/ +#define PTRMAP_PAGENO(pBt, pgno) ptrmapPageno(pBt, pgno) +#define PTRMAP_PTROFFSET(pgptrmap, pgno) (5*(pgno-pgptrmap-1)) +#define PTRMAP_ISPAGE(pBt, pgno) (PTRMAP_PAGENO((pBt),(pgno))==(pgno)) + +/* +** The pointer map is a lookup table that identifies the parent page for +** each child page in the database file. The parent page is the page that +** contains a pointer to the child. Every page in the database contains +** 0 or 1 parent pages. (In this context 'database page' refers +** to any page that is not part of the pointer map itself.) Each pointer map +** entry consists of a single byte 'type' and a 4 byte parent page number. +** The PTRMAP_XXX identifiers below are the valid types. +** +** The purpose of the pointer map is to facility moving pages from one +** position in the file to another as part of autovacuum. When a page +** is moved, the pointer in its parent must be updated to point to the +** new location. The pointer map is used to locate the parent page quickly. +** +** PTRMAP_ROOTPAGE: The database page is a root-page. The page-number is not +** used in this case. +** +** PTRMAP_FREEPAGE: The database page is an unused (free) page. The page-number +** is not used in this case. +** +** PTRMAP_OVERFLOW1: The database page is the first page in a list of +** overflow pages. The page number identifies the page that +** contains the cell with a pointer to this overflow page. +** +** PTRMAP_OVERFLOW2: The database page is the second or later page in a list of +** overflow pages. The page-number identifies the previous +** page in the overflow page list. +** +** PTRMAP_BTREE: The database page is a non-root btree page. The page number +** identifies the parent page in the btree. +*/ +#define PTRMAP_ROOTPAGE 1 +#define PTRMAP_FREEPAGE 2 +#define PTRMAP_OVERFLOW1 3 +#define PTRMAP_OVERFLOW2 4 +#define PTRMAP_BTREE 5 + +/* A bunch of assert() statements to check the transaction state variables +** of handle p (type Btree*) are internally consistent. +*/ +#define btreeIntegrity(p) \ + assert( p->pBt->inTransaction!=TRANS_NONE || p->pBt->nTransaction==0 ); \ + assert( p->pBt->inTransaction>=p->inTrans ); + + +/* +** The ISAUTOVACUUM macro is used within balance_nonroot() to determine +** if the database supports auto-vacuum or not. Because it is used +** within an expression that is an argument to another macro +** (sqliteMallocRaw), it is not possible to use conditional compilation. +** So, this macro is defined instead. +*/ +#ifndef SQLITE_OMIT_AUTOVACUUM +#define ISAUTOVACUUM (pBt->autoVacuum) +#else +#define ISAUTOVACUUM 0 +#endif + + +/* +** This structure is passed around through all the sanity checking routines +** in order to keep track of some global state information. +*/ +typedef struct IntegrityCk IntegrityCk; +struct IntegrityCk { + 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 */ + int mxErr; /* Stop accumulating errors when this reaches zero */ + int nErr; /* Number of messages written to zErrMsg so far */ + int mallocFailed; /* A memory allocation error has occurred */ + StrAccum errMsg; /* Accumulate the error message text here */ +}; + +/* +** Read or write a two- and four-byte big-endian integer values. +*/ +#define get2byte(x) ((x)[0]<<8 | (x)[1]) +#define put2byte(p,v) ((p)[0] = (v)>>8, (p)[1] = (v)) +#define get4byte sqlite3Get4byte +#define put4byte sqlite3Put4byte + +/* +** Internal routines that should be accessed by the btree layer only. +*/ +int sqlite3BtreeGetPage(BtShared*, Pgno, MemPage**, int); +int sqlite3BtreeInitPage(MemPage *pPage, MemPage *pParent); +void sqlite3BtreeParseCellPtr(MemPage*, u8*, CellInfo*); +void sqlite3BtreeParseCell(MemPage*, int, CellInfo*); +int sqlite3BtreeRestoreCursorPosition(BtCursor *pCur); +void sqlite3BtreeGetTempCursor(BtCursor *pCur, BtCursor *pTempCur); +void sqlite3BtreeReleaseTempCursor(BtCursor *pCur); +int sqlite3BtreeIsRootPage(MemPage *pPage); +void sqlite3BtreeMoveToParent(BtCursor *pCur); diff --git a/third_party/sqlite/src/build.c b/third_party/sqlite/src/build.c new file mode 100755 index 0000000..a20ee69 --- /dev/null +++ b/third_party/sqlite/src/build.c @@ -0,0 +1,3525 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains C code routines that are called by the SQLite parser +** when syntax rules are reduced. The routines in this file handle the +** following kinds of SQL syntax: +** +** CREATE TABLE +** DROP TABLE +** CREATE INDEX +** DROP INDEX +** creating ID lists +** BEGIN TRANSACTION +** COMMIT +** ROLLBACK +** +** $Id: build.c,v 1.494 2008/08/06 13:47:41 danielk1977 Exp $ +*/ +#include "sqliteInt.h" +#include <ctype.h> + +#include "pager.h" +#include "btree.h" + +/* +** This routine is called when a new SQL statement is beginning to +** be parsed. Initialize the pParse structure as needed. +*/ +void sqlite3BeginParse(Parse *pParse, int explainFlag){ + pParse->explain = 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; /* The database containing the table to be locked */ + int iTab; /* The root page of the table to be locked */ + u8 isWriteLock; /* True for write lock. False for a read lock */ + const char *zName; /* Name of the table */ +}; + +/* +** Record the fact that we want to lock a table at run-time. +** +** The table to be locked has root page iTab and is found in database iDb. +** A read or a write lock can be taken depending on isWritelock. +** +** This routine just records the fact that the lock is desired. The +** code to make the lock occur is generated by a later call to +** codeTableLocks() which occurs during sqlite3FinishCoding(). +*/ +void sqlite3TableLock( + Parse *pParse, /* Parsing context */ + int iDb, /* Index of the database containing the table to lock */ + int iTab, /* Root page number of the table to be locked */ + u8 isWriteLock, /* True for a write lock */ + const char *zName /* Name of the table to be locked */ +){ + int i; + int nBytes; + TableLock *p; + + if( iDb<0 ){ + return; + } + + for(i=0; i<pParse->nTableLock; i++){ + p = &pParse->aTableLock[i]; + if( p->iDb==iDb && p->iTab==iTab ){ + p->isWriteLock = (p->isWriteLock || isWriteLock); + return; + } + } + + nBytes = sizeof(TableLock) * (pParse->nTableLock+1); + pParse->aTableLock = + sqlite3DbReallocOrFree(pParse->db, pParse->aTableLock, nBytes); + if( pParse->aTableLock ){ + p = &pParse->aTableLock[pParse->nTableLock++]; + p->iDb = iDb; + p->iTab = iTab; + p->isWriteLock = isWriteLock; + p->zName = zName; + }else{ + pParse->nTableLock = 0; + pParse->db->mallocFailed = 1; + } +} + +/* +** 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; + + if( 0==(pVdbe = sqlite3GetVdbe(pParse)) ){ + return; + } + + for(i=0; i<pParse->nTableLock; i++){ + TableLock *p = &pParse->aTableLock[i]; + int p1 = p->iDb; + sqlite3VdbeAddOp4(pVdbe, OP_TableLock, p1, p->iTab, p->isWriteLock, + p->zName, P4_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 +** prepared. This routine puts the finishing touches on the +** VDBE program and resets the pParse structure for the next +** parse. +** +** Note that if an error occurred, it might be the case that +** no VDBE code was generated. +*/ +void sqlite3FinishCoding(Parse *pParse){ + sqlite3 *db; + Vdbe *v; + + db = pParse->db; + if( db->mallocFailed ) return; + if( pParse->nested ) return; + if( pParse->nErr ) return; + + /* Begin by generating some termination code at the end of the + ** vdbe program + */ + v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3VdbeAddOp0(v, OP_Halt); + + /* The cookie mask contains one bit for each database file open. + ** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are + ** set for each database that is used. Generate code to start a + ** transaction on each used database and to verify the schema cookie + ** on each used database. + */ + if( pParse->cookieGoto>0 ){ + u32 mask; + int iDb; + sqlite3VdbeJumpHere(v, pParse->cookieGoto-1); + for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){ + if( (mask & pParse->cookieMask)==0 ) continue; + sqlite3VdbeUsesBtree(v, iDb); + sqlite3VdbeAddOp2(v,OP_Transaction, iDb, (mask & pParse->writeMask)!=0); + sqlite3VdbeAddOp2(v,OP_VerifyCookie, iDb, pParse->cookieValue[iDb]); + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + { + int i; + for(i=0; i<pParse->nVtabLock; i++){ + char *vtab = (char *)pParse->apVtabLock[i]->pVtab; + sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB); + } + pParse->nVtabLock = 0; + } +#endif + + /* 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); + sqlite3VdbeAddOp2(v, OP_Goto, 0, pParse->cookieGoto); + } + +#ifndef SQLITE_OMIT_TRACE + if( !db->init.busy ){ + /* Change the P4 argument of the first opcode (which will always be + ** an OP_Trace) to be the complete text of the current SQL statement. + */ + VdbeOp *pOp = sqlite3VdbeGetOp(v, 0); + if( pOp && pOp->opcode==OP_Trace ){ + sqlite3VdbeChangeP4(v, 0, pParse->zSql, pParse->zTail-pParse->zSql); + } + } +#endif /* SQLITE_OMIT_TRACE */ + } + + + /* Get the VDBE program ready for execution + */ + if( v && pParse->nErr==0 && !db->mallocFailed ){ +#ifdef SQLITE_DEBUG + FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0; + sqlite3VdbeTrace(v, trace); +#endif + assert( pParse->disableColCache==0 ); /* Disables and re-enables match */ + sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem+3, + pParse->nTab+3, pParse->explain); + pParse->rc = SQLITE_DONE; + pParse->colNamesSet = 0; + }else if( pParse->rc==SQLITE_OK ){ + pParse->rc = SQLITE_ERROR; + } + pParse->nTab = 0; + pParse->nMem = 0; + pParse->nSet = 0; + pParse->nVar = 0; + pParse->cookieMask = 0; + pParse->cookieGoto = 0; +} + +/* +** Run the parser and code generator recursively in order to generate +** code for the SQL statement given onto the end of the pParse context +** currently under construction. When the parser is run recursively +** this way, the final OP_Halt is not appended and other initialization +** and finalization steps are omitted because those are handling by the +** outermost parser. +** +** Not everything is nestable. This facility is designed to permit +** INSERT, UPDATE, and DELETE operations against SQLITE_MASTER. Use +** care if you decide to try to use this routine for some other purposes. +*/ +void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){ + va_list ap; + char *zSql; + char *zErrMsg = 0; + sqlite3 *db = pParse->db; +# define SAVE_SZ (sizeof(Parse) - offsetof(Parse,nVar)) + char saveBuf[SAVE_SZ]; + + if( pParse->nErr ) return; + assert( pParse->nested<10 ); /* Nesting should only be of limited depth */ + va_start(ap, zFormat); + zSql = sqlite3VMPrintf(db, zFormat, ap); + va_end(ap); + if( zSql==0 ){ + return; /* A malloc must have failed */ + } + pParse->nested++; + memcpy(saveBuf, &pParse->nVar, SAVE_SZ); + memset(&pParse->nVar, 0, SAVE_SZ); + sqlite3RunParser(pParse, zSql, &zErrMsg); + sqlite3DbFree(db, zErrMsg); + sqlite3DbFree(db, zSql); + memcpy(&pParse->nVar, saveBuf, SAVE_SZ); + pParse->nested--; +} + +/* +** Locate the in-memory structure that describes a particular database +** table given the name of that table and (optionally) the name of the +** database containing the table. Return NULL if not found. +** +** If zDatabase is 0, all databases are searched for the table and the +** first matching table is returned. (No checking for duplicate table +** names is done.) The search order is TEMP first, then MAIN, then any +** auxiliary databases added using the ATTACH command. +** +** See also sqlite3LocateTable(). +*/ +Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){ + Table *p = 0; + int i; + int nName; + assert( zName!=0 ); + nName = sqlite3Strlen(db, zName) + 1; + for(i=OMIT_TEMPDB; i<db->nDb; 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].pSchema->tblHash, zName, nName); + if( p ) break; + } + return p; +} + +/* +** Locate the in-memory structure that describes a particular database +** table given the name of that table and (optionally) the name of the +** database containing the table. Return NULL if not found. Also leave an +** error message in pParse->zErrMsg. +** +** The difference between this routine and sqlite3FindTable() is that this +** routine leaves an error message in pParse->zErrMsg where +** sqlite3FindTable() does not. +*/ +Table *sqlite3LocateTable( + Parse *pParse, /* context in which to report errors */ + int isView, /* True if looking for a VIEW rather than a TABLE */ + const char *zName, /* Name of the table we are looking for */ + const char *zDbase /* Name of the database. Might be NULL */ +){ + Table *p; + + /* Read the database schema. If an error occurs, leave an error message + ** and code in pParse and return NULL. */ + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ + return 0; + } + + p = sqlite3FindTable(pParse->db, zName, zDbase); + if( p==0 ){ + const char *zMsg = isView ? "no such view" : "no such table"; + if( zDbase ){ + sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName); + }else{ + sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName); + } + pParse->checkSchema = 1; + } + return p; +} + +/* +** Locate the in-memory structure that describes +** a particular index given the name of that index +** and the name of the database that contains the index. +** Return NULL if not found. +** +** If zDatabase is 0, all databases are searched for the +** table and the first matching index is returned. (No checking +** for duplicate index names is done.) The search order is +** TEMP first, then MAIN, then any auxiliary databases added +** using the ATTACH command. +*/ +Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){ + Index *p = 0; + int i; + int nName = sqlite3Strlen(db, zName)+1; + for(i=OMIT_TEMPDB; i<db->nDb; 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; + assert( pSchema || (j==1 && !db->aDb[1].pBt) ); + if( pSchema ){ + p = sqlite3HashFind(&pSchema->idxHash, zName, nName); + } + if( p ) break; + } + return p; +} + +/* +** Reclaim the memory used by an index +*/ +static void freeIndex(Index *p){ + sqlite3 *db = p->pTable->db; + sqlite3DbFree(db, p->zColAff); + sqlite3DbFree(db, p); +} + +/* +** Remove the given index from the index hash table, and free +** its memory structures. +** +** The index is removed from the database hash tables but +** it is not unlinked from the Table that it indexes. +** Unlinking from the Table must be done by the calling function. +*/ +static void sqliteDeleteIndex(Index *p){ + Index *pOld; + const char *zName = p->zName; + + pOld = sqlite3HashInsert(&p->pSchema->idxHash, zName, strlen(zName)+1, 0); + assert( pOld==0 || pOld==p ); + freeIndex(p); +} + +/* +** For the index called zIdxName which is found in the database iDb, +** unlike that index from its Table then remove the index from +** the index hash table and free all memory structures associated +** with the index. +*/ +void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){ + Index *pIndex; + int len; + Hash *pHash = &db->aDb[iDb].pSchema->idxHash; + + len = sqlite3Strlen(db, zIdxName); + pIndex = sqlite3HashInsert(pHash, zIdxName, len+1, 0); + if( pIndex ){ + if( pIndex->pTable->pIndex==pIndex ){ + pIndex->pTable->pIndex = pIndex->pNext; + }else{ + Index *p; + for(p=pIndex->pTable->pIndex; p && p->pNext!=pIndex; p=p->pNext){} + if( p && p->pNext==pIndex ){ + p->pNext = pIndex->pNext; + } + } + freeIndex(pIndex); + } + db->flags |= SQLITE_InternChanges; +} + +/* +** Erase all schema information from the in-memory hash tables of +** a single database. This routine is called to reclaim memory +** before the database closes. It is also called during a rollback +** if there were schema changes during the transaction or if a +** schema-cookie mismatch occurs. +** +** If iDb<=0 then reset the internal schema tables for all database +** files. If iDb>=2 then reset the internal schema for only the +** single file indicated. +*/ +void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){ + int i, j; + assert( iDb>=0 && iDb<db->nDb ); + + if( iDb==0 ){ + sqlite3BtreeEnterAll(db); + } + for(i=iDb; i<db->nDb; i++){ + Db *pDb = &db->aDb[i]; + if( pDb->pSchema ){ + assert(i==1 || (pDb->pBt && sqlite3BtreeHoldsMutex(pDb->pBt))); + sqlite3SchemaFree(pDb->pSchema); + } + if( iDb>0 ) return; + } + assert( iDb==0 ); + db->flags &= ~SQLITE_InternChanges; + sqlite3BtreeLeaveAll(db); + + /* If one or more of the auxiliary database files has been closed, + ** 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. + */ + for(i=0; i<db->nDb; i++){ + struct Db *pDb = &db->aDb[i]; + if( pDb->pBt==0 ){ + if( pDb->pAux && pDb->xFreeAux ) pDb->xFreeAux(pDb->pAux); + pDb->pAux = 0; + } + } + for(i=j=2; i<db->nDb; i++){ + struct Db *pDb = &db->aDb[i]; + if( pDb->pBt==0 ){ + sqlite3DbFree(db, pDb->zName); + pDb->zName = 0; + continue; + } + if( j<i ){ + db->aDb[j] = db->aDb[i]; + } + j++; + } + memset(&db->aDb[j], 0, (db->nDb-j)*sizeof(db->aDb[j])); + db->nDb = j; + if( db->nDb<=2 && db->aDb!=db->aDbStatic ){ + memcpy(db->aDbStatic, db->aDb, 2*sizeof(db->aDb[0])); + sqlite3DbFree(db, db->aDb); + db->aDb = db->aDbStatic; + } +} + +/* +** This routine is called when a commit occurs. +*/ +void sqlite3CommitInternalChanges(sqlite3 *db){ + db->flags &= ~SQLITE_InternChanges; +} + +/* +** Clear the column names from a table or view. +*/ +static void sqliteResetColumnNames(Table *pTable){ + int i; + Column *pCol; + sqlite3 *db = pTable->db; + assert( pTable!=0 ); + if( (pCol = pTable->aCol)!=0 ){ + for(i=0; i<pTable->nCol; i++, pCol++){ + sqlite3DbFree(db, pCol->zName); + sqlite3ExprDelete(db, pCol->pDflt); + sqlite3DbFree(db, pCol->zType); + sqlite3DbFree(db, pCol->zColl); + } + sqlite3DbFree(db, pTable->aCol); + } + pTable->aCol = 0; + pTable->nCol = 0; +} + +/* +** Remove the memory data structures associated with the given +** Table. No changes are made to disk by this routine. +** +** This routine just deletes the data structure. It does not unlink +** the table data structure from the hash table. Nor does it remove +** foreign keys from the sqlite.aFKey hash table. But it does destroy +** memory structures of the indices and foreign keys associated with +** the table. +*/ +void sqlite3DeleteTable(Table *pTable){ + Index *pIndex, *pNext; + FKey *pFKey, *pNextFKey; + sqlite3 *db; + + if( pTable==0 ) return; + db = pTable->db; + + /* Do not delete the table until the reference count reaches zero. */ + pTable->nRef--; + if( pTable->nRef>0 ){ + return; + } + assert( pTable->nRef==0 ); + + /* Delete all indices associated with this table + */ + for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ + pNext = pIndex->pNext; + assert( pIndex->pSchema==pTable->pSchema ); + sqliteDeleteIndex(pIndex); + } + +#ifndef SQLITE_OMIT_FOREIGN_KEY + /* Delete all foreign keys associated with this table. The keys + ** should have already been unlinked from the pSchema->aFKey hash table + */ + for(pFKey=pTable->pFKey; pFKey; pFKey=pNextFKey){ + pNextFKey = pFKey->pNextFrom; + assert( sqlite3HashFind(&pTable->pSchema->aFKey, + pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey ); + sqlite3DbFree(db, pFKey); + } +#endif + + /* Delete the Table structure itself. + */ + sqliteResetColumnNames(pTable); + sqlite3DbFree(db, pTable->zName); + sqlite3DbFree(db, pTable->zColAff); + sqlite3SelectDelete(db, pTable->pSelect); +#ifndef SQLITE_OMIT_CHECK + sqlite3ExprDelete(db, pTable->pCheck); +#endif + sqlite3VtabClear(pTable); + sqlite3DbFree(db, pTable); +} + +/* +** Unlink the given table from the hash tables and the delete the +** table structure with all its indices and foreign keys. +*/ +void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){ + Table *p; + FKey *pF1, *pF2; + Db *pDb; + + assert( db!=0 ); + assert( iDb>=0 && iDb<db->nDb ); + assert( zTabName && zTabName[0] ); + pDb = &db->aDb[iDb]; + 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->pSchema->aFKey, pF1->zTo, nTo); + if( pF2==pF1 ){ + sqlite3HashInsert(&pDb->pSchema->aFKey, pF1->zTo, nTo, pF1->pNextTo); + }else{ + while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; } + if( pF2 ){ + pF2->pNextTo = pF1->pNextTo; + } + } + } +#endif + sqlite3DeleteTable(p); + } + db->flags |= SQLITE_InternChanges; +} + +/* +** Given a token, return a string that consists of the text of that +** token with any quotations removed. Space to hold the returned string +** is obtained from sqliteMalloc() and must be freed by the calling +** function. +** +** Tokens are often just pointers into the original SQL text and so +** are not \000 terminated and are not persistent. The returned string +** is \000 terminated and is persistent. +*/ +char *sqlite3NameFromToken(sqlite3 *db, Token *pName){ + char *zName; + if( pName ){ + zName = sqlite3DbStrNDup(db, (char*)pName->z, pName->n); + sqlite3Dequote(zName); + }else{ + zName = 0; + } + return zName; +} + +/* +** Open the sqlite_master table stored in database number iDb for +** writing. The table is opened using cursor 0. +*/ +void sqlite3OpenMasterTable(Parse *p, int iDb){ + Vdbe *v = sqlite3GetVdbe(p); + sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb)); + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, 5);/* sqlite_master has 5 columns */ + sqlite3VdbeAddOp3(v, OP_OpenWrite, 0, MASTER_ROOT, iDb); +} + +/* +** The token *pName contains the name of a database (either "main" or +** "temp" or the name of an attached db). This routine returns the +** index of the named database in db->aDb[], or -1 if the named db +** does not exist. +*/ +int sqlite3FindDb(sqlite3 *db, Token *pName){ + int i = -1; /* Database number */ + int n; /* Number of characters in the name */ + Db *pDb; /* A database whose name space is being searched */ + char *zName; /* Name we are searching for */ + + zName = sqlite3NameFromToken(db, pName); + if( zName ){ + n = strlen(zName); + for(i=(db->nDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){ + if( (!OMIT_TEMPDB || i!=1 ) && n==strlen(pDb->zName) && + 0==sqlite3StrICmp(pDb->zName, zName) ){ + break; + } + } + sqlite3DbFree(db, zName); + } + return i; +} + +/* The table or view or trigger name is passed to this routine via tokens +** pName1 and pName2. If the table name was fully qualified, for example: +** +** CREATE TABLE xxx.yyy (...); +** +** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if +** the table name is not fully qualified, i.e.: +** +** CREATE TABLE yyy(...); +** +** Then pName1 is set to "yyy" and pName2 is "". +** +** This routine sets the *ppUnqual pointer to point at the token (pName1 or +** pName2) that stores the unqualified table name. The index of the +** database "xxx" is returned. +*/ +int sqlite3TwoPartName( + Parse *pParse, /* Parsing and code generating context */ + Token *pName1, /* The "xxx" in the name "xxx.yyy" or "xxx" */ + Token *pName2, /* The "yyy" in the name "xxx.yyy" */ + Token **pUnqual /* Write the unqualified object name here */ +){ + int iDb; /* Database holding the object */ + sqlite3 *db = pParse->db; + + if( pName2 && pName2->n>0 ){ + assert( !db->init.busy ); + *pUnqual = pName2; + iDb = sqlite3FindDb(db, pName1); + if( iDb<0 ){ + sqlite3ErrorMsg(pParse, "unknown database %T", pName1); + pParse->nErr++; + return -1; + } + }else{ + assert( db->init.iDb==0 || db->init.busy ); + iDb = db->init.iDb; + *pUnqual = pName1; + } + return iDb; +} + +/* +** This routine is used to check if the UTF-8 string zName is a legal +** unqualified name for a new schema object (table, index, view or +** trigger). All names are legal except those that begin with the string +** "sqlite_" (in upper, lower or mixed case). This portion of the namespace +** is reserved for internal use. +*/ +int sqlite3CheckObjectName(Parse *pParse, const char *zName){ + if( !pParse->db->init.busy && pParse->nested==0 + && (pParse->db->flags & SQLITE_WriteSchema)==0 + && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ + sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName); + return SQLITE_ERROR; + } + return SQLITE_OK; +} + +/* +** Begin constructing a new table representation in memory. This is +** the first of several action routines that get called in response +** to a CREATE TABLE statement. In particular, this routine is called +** after seeing tokens "CREATE" and "TABLE" and the table name. The isTemp +** flag is true if the table should be stored in the auxiliary database +** file instead of in the main database file. This is normally the case +** when the "TEMP" or "TEMPORARY" keyword occurs in between +** CREATE and TABLE. +** +** The new table record is initialized and put in pParse->pNewTable. +** As more of the CREATE TABLE statement is parsed, additional action +** routines will be called to add more information to this record. +** At the end of the CREATE TABLE statement, the sqlite3EndTable() routine +** is called to complete the construction of the new table record. +*/ +void sqlite3StartTable( + Parse *pParse, /* Parser context */ + 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 isVirtual, /* True if this is a VIRTUAL table */ + int noErr /* Do nothing if table already exists */ +){ + Table *pTable; + char *zName = 0; /* The name of the new table */ + sqlite3 *db = pParse->db; + Vdbe *v; + int iDb; /* Database number to create the table in */ + Token *pName; /* Unqualified name of the table to create */ + + /* The table or view name to create is passed to this routine via tokens + ** pName1 and pName2. If the table name was fully qualified, for example: + ** + ** CREATE TABLE xxx.yyy (...); + ** + ** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if + ** the table name is not fully qualified, i.e.: + ** + ** CREATE TABLE yyy(...); + ** + ** Then pName1 is set to "yyy" and pName2 is "". + ** + ** The call below sets the pName pointer to point at the token (pName1 or + ** pName2) that stores the unqualified table name. The variable iDb is + ** set to the index of the database that the table or view is to be + ** created in. + */ + iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); + if( iDb<0 ) return; + if( !OMIT_TEMPDB && isTemp && iDb>1 ){ + /* If creating a temp table, the name may not be qualified */ + sqlite3ErrorMsg(pParse, "temporary table name must be unqualified"); + return; + } + if( !OMIT_TEMPDB && isTemp ) iDb = 1; + + pParse->sNameToken = *pName; + zName = sqlite3NameFromToken(db, pName); + if( zName==0 ) return; + if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ + goto begin_table_error; + } + if( db->init.iDb==1 ) isTemp = 1; +#ifndef SQLITE_OMIT_AUTHORIZATION + assert( (isTemp & 1)==isTemp ); + { + int code; + char *zDb = db->aDb[iDb].zName; + if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){ + goto begin_table_error; + } + if( isView ){ + if( !OMIT_TEMPDB && isTemp ){ + code = SQLITE_CREATE_TEMP_VIEW; + }else{ + code = SQLITE_CREATE_VIEW; + } + }else{ + if( !OMIT_TEMPDB && isTemp ){ + code = SQLITE_CREATE_TEMP_TABLE; + }else{ + code = SQLITE_CREATE_TABLE; + } + } + if( !isVirtual && sqlite3AuthCheck(pParse, code, zName, 0, zDb) ){ + goto begin_table_error; + } + } +#endif + + /* Make sure the new table name does not collide with an existing + ** index or table name in the same database. Issue an error message if + ** it does. The exception is if the statement being parsed was passed + ** to an sqlite3_declare_vtab() call. In that case only the column names + ** and types will be used, so there is no need to test for namespace + ** collisions. + */ + if( !IN_DECLARE_VTAB ){ + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ + goto begin_table_error; + } + pTable = sqlite3FindTable(db, zName, db->aDb[iDb].zName); + if( pTable ){ + if( !noErr ){ + sqlite3ErrorMsg(pParse, "table %T already exists", pName); + } + goto begin_table_error; + } + if( sqlite3FindIndex(db, zName, 0)!=0 && (iDb==0 || !db->init.busy) ){ + sqlite3ErrorMsg(pParse, "there is already an index named %s", zName); + goto begin_table_error; + } + } + + pTable = sqlite3DbMallocZero(db, sizeof(Table)); + if( pTable==0 ){ + db->mallocFailed = 1; + pParse->rc = SQLITE_NOMEM; + pParse->nErr++; + goto begin_table_error; + } + pTable->zName = zName; + pTable->iPKey = -1; + pTable->pSchema = db->aDb[iDb].pSchema; + pTable->nRef = 1; + pTable->db = db; + if( pParse->pNewTable ) sqlite3DeleteTable(pParse->pNewTable); + pParse->pNewTable = pTable; + + /* If this is the magic sqlite_sequence table used by autoincrement, + ** then record a pointer to this table in the main database structure + ** so that INSERT can find the table easily. + */ +#ifndef SQLITE_OMIT_AUTOINCREMENT + if( !pParse->nested && strcmp(zName, "sqlite_sequence")==0 ){ + pTable->pSchema->pSeqTab = pTable; + } +#endif + + /* Begin generating the code that will insert the table record into + ** the SQLITE_MASTER table. Note in particular that we must go ahead + ** and allocate the record number for the table entry now. Before any + ** PRIMARY KEY or UNIQUE keywords are parsed. Those keywords will cause + ** indices to be created and the table record must come before the + ** indices. Hence, the record number for the table must be allocated + ** now. + */ + if( !db->init.busy && (v = sqlite3GetVdbe(pParse))!=0 ){ + int j1; + int fileFormat; + int reg1, reg2, reg3; + sqlite3BeginWriteOperation(pParse, 0, iDb); + +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( isVirtual ){ + sqlite3VdbeAddOp0(v, OP_VBegin); + } +#endif + + /* If the file format and encoding in the database have not been set, + ** set them now. + */ + reg1 = pParse->regRowid = ++pParse->nMem; + reg2 = pParse->regRoot = ++pParse->nMem; + reg3 = ++pParse->nMem; + sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, reg3, 1); /* file_format */ + sqlite3VdbeUsesBtree(v, iDb); + j1 = sqlite3VdbeAddOp1(v, OP_If, reg3); + fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ? + 1 : SQLITE_MAX_FILE_FORMAT; + sqlite3VdbeAddOp2(v, OP_Integer, fileFormat, reg3); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 1, reg3); + sqlite3VdbeAddOp2(v, OP_Integer, ENC(db), reg3); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 4, reg3); + sqlite3VdbeJumpHere(v, j1); + + /* This just creates a place-holder record in the sqlite_master table. + ** The record created does not contain anything yet. It will be replaced + ** by the real entry in code generated at sqlite3EndTable(). + ** + ** The rowid for the new entry is left on the top of the stack. + ** The rowid value is needed by the code that sqlite3EndTable will + ** generate. + */ +#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) + if( isView || isVirtual ){ + sqlite3VdbeAddOp2(v, OP_Integer, 0, reg2); + }else +#endif + { + sqlite3VdbeAddOp2(v, OP_CreateTable, iDb, reg2); + } + sqlite3OpenMasterTable(pParse, iDb); + sqlite3VdbeAddOp2(v, OP_NewRowid, 0, reg1); + sqlite3VdbeAddOp2(v, OP_Null, 0, reg3); + sqlite3VdbeAddOp3(v, OP_Insert, 0, reg3, reg1); + sqlite3VdbeChangeP5(v, OPFLAG_APPEND); + sqlite3VdbeAddOp0(v, OP_Close); + } + + /* Normal (non-error) return. */ + return; + + /* If an error occurs, we jump here */ +begin_table_error: + sqlite3DbFree(db, zName); + return; +} + +/* +** This macro is used to compare two strings in a case-insensitive manner. +** It is slightly faster than calling sqlite3StrICmp() directly, but +** produces larger code. +** +** WARNING: This macro is not compatible with the strcmp() family. It +** returns true if the two strings are equal, otherwise false. +*/ +#define STRICMP(x, y) (\ +sqlite3UpperToLower[*(unsigned char *)(x)]== \ +sqlite3UpperToLower[*(unsigned char *)(y)] \ +&& sqlite3StrICmp((x)+1,(y)+1)==0 ) + +/* +** Add a new column to the table currently being constructed. +** +** The parser calls this routine once for each column declaration +** in a CREATE TABLE statement. sqlite3StartTable() gets called +** first to get things going. Then this routine is called for each +** column. +*/ +void sqlite3AddColumn(Parse *pParse, Token *pName){ + Table *p; + int i; + char *z; + Column *pCol; + sqlite3 *db = pParse->db; + if( (p = pParse->pNewTable)==0 ) return; +#if SQLITE_MAX_COLUMN + if( p->nCol+1>db->aLimit[SQLITE_LIMIT_COLUMN] ){ + sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName); + return; + } +#endif + z = sqlite3NameFromToken(pParse->db, pName); + if( z==0 ) return; + for(i=0; i<p->nCol; i++){ + if( STRICMP(z, p->aCol[i].zName) ){ + sqlite3ErrorMsg(pParse, "duplicate column name: %s", z); + sqlite3DbFree(db, z); + return; + } + } + if( (p->nCol & 0x7)==0 ){ + Column *aNew; + aNew = sqlite3DbRealloc(pParse->db,p->aCol,(p->nCol+8)*sizeof(p->aCol[0])); + if( aNew==0 ){ + sqlite3DbFree(db, z); + return; + } + p->aCol = aNew; + } + pCol = &p->aCol[p->nCol]; + memset(pCol, 0, sizeof(p->aCol[0])); + pCol->zName = z; + + /* If there is no type specified, columns have the default affinity + ** 'NONE'. If there is a type specified, then sqlite3AddColumnType() will + ** be called next to set pCol->affinity correctly. + */ + pCol->affinity = SQLITE_AFF_NONE; + p->nCol++; +} + +/* +** This routine is called by the parser while in the middle of +** parsing a CREATE TABLE statement. A "NOT NULL" constraint has +** been seen on a column. This routine sets the notNull flag on +** the column currently under construction. +*/ +void sqlite3AddNotNull(Parse *pParse, int onError){ + Table *p; + int i; + if( (p = pParse->pNewTable)==0 ) return; + i = p->nCol-1; + if( i>=0 ) p->aCol[i].notNull = onError; +} + +/* +** Scan the column type name zType (length nType) and return the +** associated affinity type. +** +** This routine does a case-independent search of zType for the +** substrings in the following table. If one of the substrings is +** found, the corresponding affinity is returned. If zType contains +** more than one of the substrings, entries toward the top of +** the table take priority. For example, if zType is 'BLOBINT', +** SQLITE_AFF_INTEGER is returned. +** +** Substring | Affinity +** -------------------------------- +** 'INT' | SQLITE_AFF_INTEGER +** 'CHAR' | SQLITE_AFF_TEXT +** 'CLOB' | SQLITE_AFF_TEXT +** 'TEXT' | SQLITE_AFF_TEXT +** 'BLOB' | SQLITE_AFF_NONE +** '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. +*/ +char sqlite3AffinityType(const Token *pType){ + u32 h = 0; + char aff = SQLITE_AFF_NUMERIC; + const unsigned char *zIn = pType->z; + const unsigned char *zEnd = &pType->z[pType->n]; + + while( zIn!=zEnd ){ + h = (h<<8) + sqlite3UpperToLower[*zIn]; + zIn++; + if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */ + aff = SQLITE_AFF_TEXT; + }else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){ /* CLOB */ + aff = SQLITE_AFF_TEXT; + }else if( h==(('t'<<24)+('e'<<16)+('x'<<8)+'t') ){ /* TEXT */ + aff = SQLITE_AFF_TEXT; + }else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b') /* BLOB */ + && (aff==SQLITE_AFF_NUMERIC || aff==SQLITE_AFF_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; + break; + } + } + + return aff; +} + +/* +** This routine is called by the parser while in the middle of +** parsing a CREATE TABLE statement. The pFirst token is the first +** token in the sequence of tokens that describe the type of the +** column currently under construction. pLast is the last token +** in the sequence. Use this information to construct a string +** that contains the typename of the column and store that string +** in zType. +*/ +void sqlite3AddColumnType(Parse *pParse, Token *pType){ + Table *p; + int i; + Column *pCol; + sqlite3 *db; + + if( (p = pParse->pNewTable)==0 ) return; + i = p->nCol-1; + if( i<0 ) return; + pCol = &p->aCol[i]; + db = pParse->db; + sqlite3DbFree(db, pCol->zType); + pCol->zType = sqlite3NameFromToken(db, pType); + pCol->affinity = sqlite3AffinityType(pType); +} + +/* +** The expression is the default value for the most recently added column +** of the table currently under construction. +** +** Default value expressions must be constant. Raise an exception if this +** is not the case. +** +** This routine is called by the parser while in the middle of +** parsing a CREATE TABLE statement. +*/ +void sqlite3AddDefaultValue(Parse *pParse, Expr *pExpr){ + Table *p; + Column *pCol; + sqlite3 *db = pParse->db; + if( (p = pParse->pNewTable)!=0 ){ + pCol = &(p->aCol[p->nCol-1]); + if( !sqlite3ExprIsConstantOrFunction(pExpr) ){ + sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant", + pCol->zName); + }else{ + Expr *pCopy; + sqlite3ExprDelete(db, pCol->pDflt); + pCol->pDflt = pCopy = sqlite3ExprDup(db, pExpr); + if( pCopy ){ + sqlite3TokenCopy(db, &pCopy->span, &pExpr->span); + } + } + } + sqlite3ExprDelete(db, pExpr); +} + +/* +** Designate the PRIMARY KEY for the table. pList is a list of names +** of columns that form the primary key. If pList is NULL, then the +** most recently added column of the table is the primary key. +** +** A table can have at most one primary key. If the table already has +** a primary key (and this is the second primary key) then create an +** error. +** +** If the PRIMARY KEY is on a single column whose datatype is INTEGER, +** then we will try to use that column as the rowid. Set the Table.iPKey +** field of the table under construction to be the index of the +** INTEGER PRIMARY KEY column. Table.iPKey is set to -1 if there is +** no INTEGER PRIMARY KEY. +** +** If the key is not an INTEGER PRIMARY KEY, then create a unique +** index for the key. No index is created for INTEGER PRIMARY KEYs. +*/ +void sqlite3AddPrimaryKey( + Parse *pParse, /* 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 sortOrder /* SQLITE_SO_ASC or SQLITE_SO_DESC */ +){ + Table *pTab = pParse->pNewTable; + char *zType = 0; + int iCol = -1, i; + if( pTab==0 || IN_DECLARE_VTAB ) goto primary_key_exit; + if( pTab->hasPrimKey ){ + sqlite3ErrorMsg(pParse, + "table \"%s\" has more than one primary key", pTab->zName); + goto primary_key_exit; + } + pTab->hasPrimKey = 1; + if( pList==0 ){ + iCol = pTab->nCol - 1; + pTab->aCol[iCol].isPrimKey = 1; + }else{ + for(i=0; i<pList->nExpr; i++){ + for(iCol=0; iCol<pTab->nCol; iCol++){ + if( sqlite3StrICmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ){ + break; + } + } + if( iCol<pTab->nCol ){ + pTab->aCol[iCol].isPrimKey = 1; + } + } + if( pList->nExpr>1 ) iCol = -1; + } + if( iCol>=0 && iCol<pTab->nCol ){ + zType = pTab->aCol[iCol].zType; + } + if( zType && sqlite3StrICmp(zType, "INTEGER")==0 + && sortOrder==SQLITE_SO_ASC ){ + pTab->iPKey = iCol; + pTab->keyConf = onError; + pTab->autoInc = autoInc; + }else if( autoInc ){ +#ifndef SQLITE_OMIT_AUTOINCREMENT + sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an " + "INTEGER PRIMARY KEY"); +#endif + }else{ + sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, 0, sortOrder, 0); + pList = 0; + } + +primary_key_exit: + sqlite3ExprListDelete(pParse->db, pList); + return; +} + +/* +** Add a new CHECK constraint to the table currently under construction. +*/ +void sqlite3AddCheckConstraint( + Parse *pParse, /* Parsing context */ + Expr *pCheckExpr /* The check expression */ +){ + sqlite3 *db = pParse->db; +#ifndef SQLITE_OMIT_CHECK + Table *pTab = pParse->pNewTable; + if( pTab && !IN_DECLARE_VTAB ){ + /* 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(db, pTab->pCheck, + sqlite3ExprDup(db, pCheckExpr)); + } +#endif + sqlite3ExprDelete(db, pCheckExpr); +} + +/* +** Set the collation function of the most recently parsed table column +** to the CollSeq given. +*/ +void sqlite3AddCollateType(Parse *pParse, Token *pToken){ + Table *p; + int i; + char *zColl; /* Dequoted name of collation sequence */ + sqlite3 *db; + + if( (p = pParse->pNewTable)==0 ) return; + i = p->nCol-1; + db = pParse->db; + zColl = sqlite3NameFromToken(db, pToken); + if( !zColl ) return; + + if( sqlite3LocateCollSeq(pParse, zColl, -1) ){ + Index *pIdx; + p->aCol[i].zColl = zColl; + + /* If the column is declared as "<name> PRIMARY KEY COLLATE <type>", + ** 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; + } + } + }else{ + sqlite3DbFree(db, zColl); + } +} + +/* +** This function returns the collation sequence for database native text +** encoding identified by the string zName, length nName. +** +** If the requested collation sequence is not available, or not available +** in the database native encoding, the collation factory is invoked to +** request it. If the collation factory does not supply such a sequence, +** and the sequence is available in another text encoding, then that is +** returned instead. +** +** If no versions of the requested collations sequence are available, or +** another error occurs, NULL is returned and an error message written into +** pParse. +** +** This routine is a wrapper around sqlite3FindCollSeq(). This routine +** invokes the collation factory if the named collation cannot be found +** and generates an error message. +*/ +CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName){ + sqlite3 *db = pParse->db; + u8 enc = ENC(db); + u8 initbusy = db->init.busy; + CollSeq *pColl; + + pColl = sqlite3FindCollSeq(db, enc, zName, nName, initbusy); + if( !initbusy && (!pColl || !pColl->xCmp) ){ + pColl = sqlite3GetCollSeq(db, pColl, zName, nName); + if( !pColl ){ + if( nName<0 ){ + nName = sqlite3Strlen(db, zName); + } + sqlite3ErrorMsg(pParse, "no such collation sequence: %.*s", nName, zName); + pColl = 0; + } + } + + return pColl; +} + + +/* +** Generate code that will increment the schema cookie. +** +** The schema cookie is used to determine when the schema for the +** database changes. After each schema change, the cookie value +** changes. When a process first reads the schema it records the +** cookie. Thereafter, whenever it goes to access the database, +** it checks the cookie to make sure the schema has not changed +** since it was last read. +** +** This plan is not completely bullet-proof. It is possible for +** the schema to change multiple times and for the cookie to be +** set back to prior value. But schema changes are infrequent +** and the probability of hitting the same cookie value is only +** 1 chance in 2^32. So we're safe enough. +*/ +void sqlite3ChangeCookie(Parse *pParse, int iDb){ + int r1 = sqlite3GetTempReg(pParse); + sqlite3 *db = pParse->db; + Vdbe *v = pParse->pVdbe; + sqlite3VdbeAddOp2(v, OP_Integer, db->aDb[iDb].pSchema->schema_cookie+1, r1); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 0, r1); + sqlite3ReleaseTempReg(pParse, r1); +} + +/* +** Measure the number of characters needed to output the given +** identifier. The number returned includes any quotes used +** but does not include the null terminator. +** +** The estimate is conservative. It might be larger that what is +** really needed. +*/ +static int identLength(const char *z){ + int n; + for(n=0; *z; n++, z++){ + if( *z=='"' ){ n++; } + } + return n + 2; +} + +/* +** Write an identifier onto the end of the given string. Add +** quote characters as needed. +*/ +static void identPut(char *z, int *pIdx, char *zSignedIdent){ + unsigned char *zIdent = (unsigned char*)zSignedIdent; + int i, j, needQuote; + i = *pIdx; + for(j=0; zIdent[j]; j++){ + if( !isalnum(zIdent[j]) && zIdent[j]!='_' ) break; + } + needQuote = zIdent[j]!=0 || isdigit(zIdent[0]) + || sqlite3KeywordCode(zIdent, j)!=TK_ID; + if( needQuote ) z[i++] = '"'; + for(j=0; zIdent[j]; j++){ + z[i++] = zIdent[j]; + if( zIdent[j]=='"' ) z[i++] = '"'; + } + if( needQuote ) z[i++] = '"'; + z[i] = 0; + *pIdx = i; +} + +/* +** Generate a CREATE TABLE statement appropriate for the given +** table. Memory to hold the text of the statement is obtained +** from sqliteMalloc() and must be freed by the calling function. +*/ +static char *createTableStmt(sqlite3 *db, Table *p, int isTemp){ + int i, k, n; + char *zStmt; + char *zSep, *zSep2, *zEnd, *z; + Column *pCol; + n = 0; + for(pCol = p->aCol, i=0; i<p->nCol; i++, pCol++){ + n += identLength(pCol->zName); + z = pCol->zType; + if( z ){ + n += (strlen(z) + 1); + } + } + n += identLength(p->zName); + if( n<50 ){ + zSep = ""; + zSep2 = ","; + zEnd = ")"; + }else{ + zSep = "\n "; + zSep2 = ",\n "; + zEnd = "\n)"; + } + n += 35 + 6*p->nCol; + zStmt = sqlite3Malloc( n ); + if( zStmt==0 ){ + db->mallocFailed = 1; + return 0; + } + sqlite3_snprintf(n, zStmt, + !OMIT_TEMPDB&&isTemp ? "CREATE TEMP TABLE ":"CREATE TABLE "); + k = strlen(zStmt); + identPut(zStmt, &k, p->zName); + zStmt[k++] = '('; + for(pCol=p->aCol, i=0; i<p->nCol; i++, pCol++){ + sqlite3_snprintf(n-k, &zStmt[k], zSep); + k += strlen(&zStmt[k]); + zSep = zSep2; + identPut(zStmt, &k, pCol->zName); + if( (z = pCol->zType)!=0 ){ + zStmt[k++] = ' '; + assert( strlen(z)+k+1<=n ); + sqlite3_snprintf(n-k, &zStmt[k], "%s", z); + k += strlen(z); + } + } + sqlite3_snprintf(n-k, &zStmt[k], "%s", zEnd); + return zStmt; +} + +/* +** This routine is called to report the final ")" that terminates +** a CREATE TABLE statement. +** +** The table structure that other action routines have been building +** is added to the internal hash tables, assuming no errors have +** occurred. +** +** An entry for the table is made in the master table on disk, unless +** this is a temporary table or db->init.busy==1. When db->init.busy==1 +** it means we are reading the sqlite_master table because we just +** connected to the database or because the sqlite_master table has +** recently changed, so the entry for this table already exists in +** the sqlite_master table. We do not want to create it again. +** +** If the pSelect argument is not NULL, it means that this routine +** was called to create a table generated from a +** "CREATE TABLE ... AS SELECT ..." statement. The column names of +** the new table will match the result set of the SELECT. +*/ +void sqlite3EndTable( + Parse *pParse, /* Parse context */ + Token *pCons, /* The ',' token after the last column defn. */ + Token *pEnd, /* The final ')' token in the CREATE TABLE */ + Select *pSelect /* Select from a "CREATE ... AS SELECT" */ +){ + Table *p; + sqlite3 *db = pParse->db; + int iDb; + + if( (pEnd==0 && pSelect==0) || pParse->nErr || db->mallocFailed ) { + return; + } + p = pParse->pNewTable; + if( p==0 ) return; + + assert( !db->init.busy || !pSelect ); + + iDb = sqlite3SchemaToIndex(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 + ** for the table from the db->init.newTnum field. (The page number + ** should have been put there by the sqliteOpenCb routine.) + */ + if( db->init.busy ){ + p->tnum = db->init.newTnum; + } + + /* If not initializing, then create a record for the new table + ** in the SQLITE_MASTER table of the database. The record number + ** for the new table entry should already be on the stack. + ** + ** If this is a TEMPORARY table, write the entry into the auxiliary + ** file instead of into the main database file. + */ + if( !db->init.busy ){ + int n; + Vdbe *v; + char *zType; /* "view" or "table" */ + char *zType2; /* "VIEW" or "TABLE" */ + char *zStmt; /* Text of the CREATE TABLE or CREATE VIEW statement */ + + v = sqlite3GetVdbe(pParse); + if( v==0 ) return; + + sqlite3VdbeAddOp1(v, OP_Close, 0); + + /* Create the rootpage for the new table and push it onto the stack. + ** A view has no rootpage, so just push a zero onto the stack for + ** views. Initialize zType at the same time. + */ + if( p->pSelect==0 ){ + /* A regular table */ + zType = "table"; + zType2 = "TABLE"; +#ifndef SQLITE_OMIT_VIEW + }else{ + /* A view */ + zType = "view"; + zType2 = "VIEW"; +#endif + } + + /* If this is a CREATE TABLE xx AS SELECT ..., execute the SELECT + ** statement to populate the new table. The root-page number for the + ** new table is on the top of the vdbe stack. + ** + ** 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 ){ + SelectDest dest; + Table *pSelTab; + + assert(pParse->nTab==0); + sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb); + sqlite3VdbeChangeP5(v, 1); + pParse->nTab = 2; + sqlite3SelectDestInit(&dest, SRT_Table, 1); + sqlite3Select(pParse, pSelect, &dest, 0, 0, 0); + sqlite3VdbeAddOp1(v, OP_Close, 1); + if( pParse->nErr==0 ){ + pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSelect); + if( pSelTab==0 ) return; + assert( p->aCol==0 ); + p->nCol = pSelTab->nCol; + p->aCol = pSelTab->aCol; + pSelTab->nCol = 0; + pSelTab->aCol = 0; + sqlite3DeleteTable(pSelTab); + } + } + + /* Compute the complete text of the CREATE statement */ + if( pSelect ){ + zStmt = createTableStmt(db, p, p->pSchema==db->aDb[1].pSchema); + }else{ + n = pEnd->z - pParse->sNameToken.z + 1; + zStmt = sqlite3MPrintf(db, + "CREATE %s %.*s", zType2, n, pParse->sNameToken.z + ); + } + + /* A slot for the record has already been allocated in the + ** SQLITE_MASTER table. We just need to update that slot with all + ** the information we've collected. The rowid for the preallocated + ** slot is the 2nd item on the stack. The top of the stack is the + ** root page for the new table (or a 0 if this is a view). + */ + sqlite3NestedParse(pParse, + "UPDATE %Q.%s " + "SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q " + "WHERE rowid=#%d", + db->aDb[iDb].zName, SCHEMA_TABLE(iDb), + zType, + p->zName, + p->zName, + pParse->regRoot, + zStmt, + pParse->regRowid + ); + sqlite3DbFree(db, zStmt); + sqlite3ChangeCookie(pParse, 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[iDb]; + if( pDb->pSchema->pSeqTab==0 ){ + sqlite3NestedParse(pParse, + "CREATE TABLE %Q.sqlite_sequence(name,seq)", + pDb->zName + ); + } + } +#endif + + /* Reparse everything to update our internal data structures */ + sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, + sqlite3MPrintf(db, "tbl_name='%q'",p->zName), P4_DYNAMIC); + } + + + /* Add the table to the in-memory representation of the database. + */ + if( db->init.busy && pParse->nErr==0 ){ + Table *pOld; + FKey *pFKey; + 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() */ + db->mallocFailed = 1; + return; + } +#ifndef SQLITE_OMIT_FOREIGN_KEY + for(pFKey=p->pFKey; pFKey; pFKey=pFKey->pNextFrom){ + void *data; + int nTo = strlen(pFKey->zTo) + 1; + pFKey->pNextTo = sqlite3HashFind(&pSchema->aFKey, pFKey->zTo, nTo); + data = sqlite3HashInsert(&pSchema->aFKey, pFKey->zTo, nTo, pFKey); + if( data==(void *)pFKey ){ + db->mallocFailed = 1; + } + } +#endif + pParse->pNewTable = 0; + db->nTable++; + db->flags |= SQLITE_InternChanges; + +#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; + } + nName = (const char *)pCons->z - zName; + p->addColOffset = 13 + sqlite3Utf8CharLen(zName, nName); + } +#endif + } +} + +#ifndef SQLITE_OMIT_VIEW +/* +** The parser calls this routine in order to create a new VIEW +*/ +void sqlite3CreateView( + Parse *pParse, /* The parsing context */ + Token *pBegin, /* The CREATE token that begins the statement */ + Token *pName1, /* The token that holds the name of the view */ + Token *pName2, /* The token that holds the name of the view */ + Select *pSelect, /* A SELECT statement that will become the new view */ + int isTemp, /* TRUE for a TEMPORARY view */ + int noErr /* Suppress error messages if VIEW already exists */ +){ + Table *p; + int n; + const unsigned char *z; + Token sEnd; + DbFixer sFix; + Token *pName; + int iDb; + sqlite3 *db = pParse->db; + + if( pParse->nVar>0 ){ + sqlite3ErrorMsg(pParse, "parameters are not allowed in views"); + sqlite3SelectDelete(db, pSelect); + return; + } + sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr); + p = pParse->pNewTable; + if( p==0 || pParse->nErr ){ + sqlite3SelectDelete(db, pSelect); + return; + } + sqlite3TwoPartName(pParse, pName1, pName2, &pName); + iDb = sqlite3SchemaToIndex(db, p->pSchema); + if( sqlite3FixInit(&sFix, pParse, iDb, "view", pName) + && sqlite3FixSelect(&sFix, pSelect) + ){ + sqlite3SelectDelete(db, pSelect); + return; + } + + /* Make a copy of the entire SELECT statement that defines the view. + ** This will force all the Expr.token.z values to be dynamically + ** allocated rather than point to the input string - which means that + ** they will persist after the current sqlite3_exec() call returns. + */ + p->pSelect = sqlite3SelectDup(db, pSelect); + sqlite3SelectDelete(db, pSelect); + if( db->mallocFailed ){ + return; + } + if( !db->init.busy ){ + sqlite3ViewGetColumnNames(pParse, p); + } + + /* Locate the end of the CREATE VIEW statement. Make sEnd point to + ** the end. + */ + sEnd = pParse->sLastToken; + if( sEnd.z[0]!=0 && sEnd.z[0]!=';' ){ + sEnd.z += sEnd.n; + } + sEnd.n = 0; + n = sEnd.z - pBegin->z; + z = (const unsigned char*)pBegin->z; + while( n>0 && (z[n-1]==';' || isspace(z[n-1])) ){ n--; } + sEnd.z = &z[n-1]; + sEnd.n = 1; + + /* Use sqlite3EndTable() to add the view to the SQLITE_MASTER table */ + sqlite3EndTable(pParse, 0, &sEnd, 0); + return; +} +#endif /* SQLITE_OMIT_VIEW */ + +#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) +/* +** The Table structure pTable is really a VIEW. Fill in the names of +** the columns of the view in the pTable structure. Return the number +** of errors. If an error is seen leave an error message in pParse->zErrMsg. +*/ +int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ + Table *pSelTab; /* A fake table from which we get the result set */ + Select *pSel; /* Copy of the SELECT that implements the view */ + int nErr = 0; /* Number of errors encountered */ + int n; /* Temporarily holds the number of cursors assigned */ + sqlite3 *db = pParse->db; /* Database connection for malloc errors */ + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); + + assert( pTable ); + +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( sqlite3VtabCallConnect(pParse, pTable) ){ + return SQLITE_ERROR; + } + if( IsVirtual(pTable) ) return 0; +#endif + +#ifndef SQLITE_OMIT_VIEW + /* A positive nCol means the columns names for this view are + ** already known. + */ + if( pTable->nCol>0 ) return 0; + + /* A negative nCol is a special marker meaning that we are currently + ** trying to compute the column names. If we enter this routine with + ** a negative nCol, it means two or more views form a loop, like this: + ** + ** CREATE VIEW one AS SELECT * FROM two; + ** CREATE VIEW two AS SELECT * FROM one; + ** + ** Actually, this error is caught previously and so the following test + ** should always fail. But we will leave it in place just to be safe. + */ + if( pTable->nCol<0 ){ + sqlite3ErrorMsg(pParse, "view %s is circularly defined", pTable->zName); + return 1; + } + assert( pTable->nCol>=0 ); + + /* If we get this far, it means we need to compute the table names. + ** Note that the call to sqlite3ResultSetOfSelect() will expand any + ** "*" elements in the results set of the view and will assign cursors + ** to the elements of the FROM clause. But we do not want these changes + ** to be permanent. So the computation is done on a copy of the SELECT + ** statement that defines the view. + */ + assert( pTable->pSelect ); + pSel = sqlite3SelectDup(db, pTable->pSelect); + if( pSel ){ + n = pParse->nTab; + sqlite3SrcListAssignCursors(pParse, pSel->pSrc); + pTable->nCol = -1; +#ifndef SQLITE_OMIT_AUTHORIZATION + xAuth = db->xAuth; + db->xAuth = 0; + pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSel); + db->xAuth = xAuth; +#else + pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSel); +#endif + pParse->nTab = n; + if( pSelTab ){ + assert( pTable->aCol==0 ); + pTable->nCol = pSelTab->nCol; + pTable->aCol = pSelTab->aCol; + pSelTab->nCol = 0; + pSelTab->aCol = 0; + sqlite3DeleteTable(pSelTab); + pTable->pSchema->flags |= DB_UnresetViews; + }else{ + pTable->nCol = 0; + nErr++; + } + sqlite3SelectDelete(db, pSel); + } else { + nErr++; + } +#endif /* SQLITE_OMIT_VIEW */ + return nErr; +} +#endif /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */ + +#ifndef SQLITE_OMIT_VIEW +/* +** Clear the column names from every VIEW in database idx. +*/ +static void sqliteViewResetAll(sqlite3 *db, int idx){ + HashElem *i; + if( !DbHasProperty(db, idx, DB_UnresetViews) ) return; + for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){ + Table *pTab = sqliteHashData(i); + if( pTab->pSelect ){ + sqliteResetColumnNames(pTab); + } + } + DbClearProperty(db, idx, DB_UnresetViews); +} +#else +# define sqliteViewResetAll(A,B) +#endif /* SQLITE_OMIT_VIEW */ + +/* +** This function is called by the VDBE to adjust the internal schema +** used by SQLite when the btree layer moves a table root page. The +** root-page of a table or index in database iDb has changed from iFrom +** to iTo. +** +** Ticket #1728: The symbol table might still contain information +** on tables and/or indices that are the process of being deleted. +** If you are unlucky, one of those deleted indices or tables might +** have the same rootpage number as the real table or index that is +** being moved. So we cannot stop searching after the first match +** because the first match might be for one of the deleted indices +** or tables and not the table/index that is actually being moved. +** We must continue looping until all tables and indices with +** rootpage==iFrom have been converted to have a rootpage of iTo +** in order to be certain that we got the right one. +*/ +#ifndef SQLITE_OMIT_AUTOVACUUM +void sqlite3RootPageMoved(Db *pDb, int iFrom, int iTo){ + HashElem *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; + } + } + pHash = &pDb->pSchema->idxHash; + for(pElem=sqliteHashFirst(pHash); pElem; pElem=sqliteHashNext(pElem)){ + Index *pIdx = sqliteHashData(pElem); + if( pIdx->tnum==iFrom ){ + pIdx->tnum = iTo; + } + } +} +#endif + +/* +** Write code to erase the table with root-page iTable from database iDb. +** Also write code to modify the sqlite_master table and internal schema +** if a root-page of another table is moved by the btree-layer whilst +** erasing iTable (this can happen with an auto-vacuum database). +*/ +static void destroyRootPage(Parse *pParse, int iTable, int iDb){ + Vdbe *v = sqlite3GetVdbe(pParse); + int r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_Destroy, iTable, r1, iDb); +#ifndef SQLITE_OMIT_AUTOVACUUM + /* OP_Destroy stores an in integer r1. If this integer + ** is non-zero, then it is the root page number of a table moved to + ** location iTable. The following code modifies the sqlite_master table to + ** reflect this. + ** + ** The "#%d" in the SQL is a special constant that means whatever value + ** is on the top of the stack. See sqlite3RegisterExpr(). + */ + sqlite3NestedParse(pParse, + "UPDATE %Q.%s SET rootpage=%d WHERE #%d AND rootpage=#%d", + pParse->db->aDb[iDb].zName, SCHEMA_TABLE(iDb), iTable, r1, r1); +#endif + sqlite3ReleaseTempReg(pParse, r1); +} + +/* +** Write VDBE code to erase table pTab and all associated indices on disk. +** Code to update the sqlite_master tables and internal schema definitions +** in case a root-page belonging to another table is moved by the btree layer +** is also added (this can happen with an auto-vacuum database). +*/ +static void destroyTable(Parse *pParse, Table *pTab){ +#ifdef SQLITE_OMIT_AUTOVACUUM + Index *pIdx; + int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + destroyRootPage(pParse, pTab->tnum, iDb); + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + destroyRootPage(pParse, pIdx->tnum, iDb); + } +#else + /* If the database may be auto-vacuum capable (if SQLITE_OMIT_AUTOVACUUM + ** is not defined), then it is important to call OP_Destroy on the + ** table and index root-pages in order, starting with the numerically + ** largest root-page number. This guarantees that none of the root-pages + ** to be destroyed is relocated by an earlier OP_Destroy. i.e. if the + ** following were coded: + ** + ** OP_Destroy 4 0 + ** ... + ** OP_Destroy 5 0 + ** + ** and root page 5 happened to be the largest root-page number in the + ** database, then root page 5 would be moved to page 4 by the + ** "OP_Destroy 4 0" opcode. The subsequent "OP_Destroy 5 0" would hit + ** a free-list page. + */ + int iTab = pTab->tnum; + int iDestroyed = 0; + + while( 1 ){ + Index *pIdx; + int iLargest = 0; + + if( iDestroyed==0 || iTab<iDestroyed ){ + iLargest = iTab; + } + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + int iIdx = pIdx->tnum; + assert( pIdx->pSchema==pTab->pSchema ); + if( (iDestroyed==0 || (iIdx<iDestroyed)) && iIdx>iLargest ){ + iLargest = iIdx; + } + } + if( iLargest==0 ){ + return; + }else{ + int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + destroyRootPage(pParse, iLargest, iDb); + iDestroyed = iLargest; + } + } +#endif +} + +/* +** 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, int noErr){ + Table *pTab; + Vdbe *v; + sqlite3 *db = pParse->db; + int iDb; + + if( pParse->nErr || db->mallocFailed ){ + goto exit_drop_table; + } + assert( pName->nSrc==1 ); + pTab = sqlite3LocateTable(pParse, isView, + pName->a[0].zName, pName->a[0].zDatabase); + + if( pTab==0 ){ + if( noErr ){ + sqlite3ErrorClear(pParse); + } + goto exit_drop_table; + } + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + assert( iDb>=0 && iDb<db->nDb ); + + /* If pTab is a virtual table, call ViewGetColumnNames() to ensure + ** it is initialized. + */ + if( IsVirtual(pTab) && sqlite3ViewGetColumnNames(pParse, pTab) ){ + goto exit_drop_table; + } +#ifndef SQLITE_OMIT_AUTHORIZATION + { + int code; + const char *zTab = SCHEMA_TABLE(iDb); + const char *zDb = db->aDb[iDb].zName; + const char *zArg2 = 0; + if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){ + goto exit_drop_table; + } + if( isView ){ + if( !OMIT_TEMPDB && iDb==1 ){ + code = SQLITE_DROP_TEMP_VIEW; + }else{ + code = SQLITE_DROP_VIEW; + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + }else if( IsVirtual(pTab) ){ + code = SQLITE_DROP_VTABLE; + zArg2 = pTab->pMod->zName; +#endif + }else{ + if( !OMIT_TEMPDB && iDb==1 ){ + code = SQLITE_DROP_TEMP_TABLE; + }else{ + code = SQLITE_DROP_TABLE; + } + } + if( sqlite3AuthCheck(pParse, code, pTab->zName, zArg2, zDb) ){ + goto exit_drop_table; + } + if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){ + goto exit_drop_table; + } + } +#endif + if( pTab->readOnly || pTab==db->aDb[iDb].pSchema->pSeqTab ){ + sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName); + goto exit_drop_table; + } + +#ifndef SQLITE_OMIT_VIEW + /* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used + ** on a table. + */ + if( isView && pTab->pSelect==0 ){ + sqlite3ErrorMsg(pParse, "use DROP TABLE to delete table %s", pTab->zName); + goto exit_drop_table; + } + if( !isView && pTab->pSelect ){ + sqlite3ErrorMsg(pParse, "use DROP VIEW to delete view %s", pTab->zName); + goto exit_drop_table; + } +#endif + + /* Generate code to remove the table from the master table + ** on disk. + */ + v = sqlite3GetVdbe(pParse); + if( v ){ + Trigger *pTrigger; + Db *pDb = &db->aDb[iDb]; + sqlite3BeginWriteOperation(pParse, 1, iDb); + +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( IsVirtual(pTab) ){ + Vdbe *v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3VdbeAddOp0(v, OP_VBegin); + } + } +#endif + + /* Drop all triggers associated with the table being dropped. Code + ** is generated to remove entries from sqlite_master and/or + ** sqlite_temp_master if required. + */ + pTrigger = pTab->pTrigger; + while( pTrigger ){ + assert( pTrigger->pSchema==pTab->pSchema || + pTrigger->pSchema==db->aDb[1].pSchema ); + sqlite3DropTriggerPtr(pParse, pTrigger); + pTrigger = pTrigger->pNext; + } + +#ifndef SQLITE_OMIT_AUTOINCREMENT + /* Remove any entries of the sqlite_sequence table associated with + ** the table being dropped. This is done before the table is dropped + ** at the btree level, in case the sqlite_sequence table needs to + ** move as a result of the drop (can happen in auto-vacuum mode). + */ + if( pTab->autoInc ){ + sqlite3NestedParse(pParse, + "DELETE FROM %s.sqlite_sequence WHERE name=%Q", + pDb->zName, pTab->zName + ); + } +#endif + + /* Drop all SQLITE_MASTER table and index entries that refer to the + ** table. The program name loops through the master table and deletes + ** every row that refers to a table of the same name as the one being + ** dropped. Triggers are handled seperately because a trigger can be + ** created in the temp database that refers to a table in another + ** database. + */ + sqlite3NestedParse(pParse, + "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'", + pDb->zName, SCHEMA_TABLE(iDb), pTab->zName); + + /* Drop any statistics from the sqlite_stat1 table, if it exists */ + if( sqlite3FindTable(db, "sqlite_stat1", db->aDb[iDb].zName) ){ + sqlite3NestedParse(pParse, + "DELETE FROM %Q.sqlite_stat1 WHERE tbl=%Q", pDb->zName, pTab->zName + ); + } + + if( !isView && !IsVirtual(pTab) ){ + destroyTable(pParse, pTab); + } + + /* Remove the table entry from SQLite's internal schema and modify + ** the schema cookie. + */ + if( IsVirtual(pTab) ){ + sqlite3VdbeAddOp4(v, OP_VDestroy, iDb, 0, 0, pTab->zName, 0); + } + sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0); + sqlite3ChangeCookie(pParse, iDb); + } + sqliteViewResetAll(db, iDb); + +exit_drop_table: + sqlite3SrcListDelete(db, pName); +} + +/* +** This routine is called to create a new foreign key on the table +** currently under construction. pFromCol determines which columns +** in the current table point to the foreign key. If pFromCol==0 then +** connect the key to the last column inserted. pTo is the name of +** the table referred to. pToCol is a list of tables in the other +** pTo table that the foreign key points to. flags contains all +** information about the conflict resolution algorithms specified +** in the ON DELETE, ON UPDATE and ON INSERT clauses. +** +** An FKey structure is created and added to the table currently +** under construction in the pParse->pNewTable field. The new FKey +** is not linked into db->aFKey at this point - that does not happen +** until sqlite3EndTable(). +** +** The foreign key is set for IMMEDIATE processing. A subsequent call +** to sqlite3DeferForeignKey() might change this to DEFERRED. +*/ +void sqlite3CreateForeignKey( + Parse *pParse, /* Parsing context */ + ExprList *pFromCol, /* Columns in this table that point to other table */ + Token *pTo, /* Name of the other table */ + ExprList *pToCol, /* Columns in the other table */ + int flags /* Conflict resolution algorithms. */ +){ + sqlite3 *db = pParse->db; +#ifndef SQLITE_OMIT_FOREIGN_KEY + FKey *pFKey = 0; + Table *p = pParse->pNewTable; + int nByte; + int i; + int nCol; + char *z; + + assert( pTo!=0 ); + if( p==0 || pParse->nErr || IN_DECLARE_VTAB ) goto fk_end; + if( pFromCol==0 ){ + int iCol = p->nCol-1; + if( iCol<0 ) goto fk_end; + if( pToCol && pToCol->nExpr!=1 ){ + sqlite3ErrorMsg(pParse, "foreign key on %s" + " should reference only one column of table %T", + p->aCol[iCol].zName, pTo); + goto fk_end; + } + nCol = 1; + }else if( pToCol && pToCol->nExpr!=pFromCol->nExpr ){ + sqlite3ErrorMsg(pParse, + "number of columns in foreign key does not match the number of " + "columns in the referenced table"); + goto fk_end; + }else{ + nCol = pFromCol->nExpr; + } + nByte = sizeof(*pFKey) + nCol*sizeof(pFKey->aCol[0]) + pTo->n + 1; + if( pToCol ){ + for(i=0; i<pToCol->nExpr; i++){ + nByte += strlen(pToCol->a[i].zName) + 1; + } + } + pFKey = sqlite3DbMallocZero(db, nByte ); + if( pFKey==0 ){ + goto fk_end; + } + pFKey->pFrom = p; + pFKey->pNextFrom = p->pFKey; + z = (char*)&pFKey[1]; + pFKey->aCol = (struct sColMap*)z; + z += sizeof(struct sColMap)*nCol; + pFKey->zTo = z; + memcpy(z, pTo->z, pTo->n); + z[pTo->n] = 0; + z += pTo->n+1; + pFKey->pNextTo = 0; + pFKey->nCol = nCol; + if( pFromCol==0 ){ + pFKey->aCol[0].iFrom = p->nCol-1; + }else{ + for(i=0; i<nCol; i++){ + int j; + for(j=0; j<p->nCol; j++){ + if( sqlite3StrICmp(p->aCol[j].zName, pFromCol->a[i].zName)==0 ){ + pFKey->aCol[i].iFrom = j; + break; + } + } + if( j>=p->nCol ){ + sqlite3ErrorMsg(pParse, + "unknown column \"%s\" in foreign key definition", + pFromCol->a[i].zName); + goto fk_end; + } + } + } + if( pToCol ){ + for(i=0; i<nCol; i++){ + int n = strlen(pToCol->a[i].zName); + pFKey->aCol[i].zCol = z; + memcpy(z, pToCol->a[i].zName, n); + z[n] = 0; + z += n+1; + } + } + pFKey->isDeferred = 0; + pFKey->deleteConf = flags & 0xff; + pFKey->updateConf = (flags >> 8 ) & 0xff; + pFKey->insertConf = (flags >> 16 ) & 0xff; + + /* Link the foreign key to the table as the last step. + */ + p->pFKey = pFKey; + pFKey = 0; + +fk_end: + sqlite3DbFree(db, pFKey); +#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ + sqlite3ExprListDelete(db, pFromCol); + sqlite3ExprListDelete(db, pToCol); +} + +/* +** This routine is called when an INITIALLY IMMEDIATE or INITIALLY DEFERRED +** clause is seen as part of a foreign key definition. The isDeferred +** parameter is 1 for INITIALLY DEFERRED and 0 for INITIALLY IMMEDIATE. +** The behavior of the most recently created foreign key is adjusted +** accordingly. +*/ +void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){ +#ifndef SQLITE_OMIT_FOREIGN_KEY + Table *pTab; + FKey *pFKey; + if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return; + pFKey->isDeferred = isDeferred; +#endif +} + +/* +** Generate code that will erase and refill index *pIdx. This is +** used to initialize a newly created index or to recompute the +** content of an index in response to a REINDEX command. +** +** if memRootPage is not negative, it means that the index is newly +** created. The register specified by memRootPage contains the +** root page number of the index. If memRootPage is negative, then +** the index already exists and must be cleared before being refilled and +** the root page number of the index is taken from pIndex->tnum. +*/ +static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ + Table *pTab = pIndex->pTable; /* The table that is indexed */ + int iTab = pParse->nTab; /* Btree cursor used for pTab */ + int iIdx = pParse->nTab+1; /* Btree cursor used for pIndex */ + int addr1; /* Address of top of loop */ + int tnum; /* Root page of index */ + Vdbe *v; /* Generate code into this virtual machine */ + KeyInfo *pKey; /* KeyInfo for index */ + int regIdxKey; /* Registers containing the index key */ + int regRecord; /* Register holding assemblied index record */ + sqlite3 *db = pParse->db; /* The database connection */ + int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema); + +#ifndef SQLITE_OMIT_AUTHORIZATION + if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0, + db->aDb[iDb].zName ) ){ + return; + } +#endif + + /* 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; + if( memRootPage>=0 ){ + tnum = memRootPage; + }else{ + tnum = pIndex->tnum; + sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb); + } + pKey = sqlite3IndexKeyinfo(pParse, pIndex); + sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, + (char *)pKey, P4_KEYINFO_HANDOFF); + if( memRootPage>=0 ){ + sqlite3VdbeChangeP5(v, 1); + } + sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); + addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); + regRecord = sqlite3GetTempReg(pParse); + regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1); + if( pIndex->onError!=OE_None ){ + int j1, j2; + int regRowid; + + regRowid = regIdxKey + pIndex->nColumn; + j1 = sqlite3VdbeAddOp3(v, OP_IsNull, regIdxKey, 0, pIndex->nColumn); + j2 = sqlite3VdbeAddOp4(v, OP_IsUnique, iIdx, + 0, regRowid, SQLITE_INT_TO_PTR(regRecord), P4_INT32); + sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, OE_Abort, 0, + "indexed columns are not unique", P4_STATIC); + sqlite3VdbeJumpHere(v, j1); + sqlite3VdbeJumpHere(v, j2); + } + sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord); + sqlite3ReleaseTempReg(pParse, regRecord); + sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1); + sqlite3VdbeJumpHere(v, addr1); + sqlite3VdbeAddOp1(v, OP_Close, iTab); + sqlite3VdbeAddOp1(v, OP_Close, iIdx); +} + +/* +** Create a new index for an SQL table. pName1.pName2 is the name of the index +** and pTblList is the name of the table that is to be indexed. Both will +** be NULL for a primary key or an index that is created to satisfy a +** UNIQUE constraint. If pTable and pIndex are NULL, use pParse->pNewTable +** as the table to be indexed. pParse->pNewTable is a table that is +** currently being constructed by a CREATE TABLE statement. +** +** pList is a list of columns to be indexed. pList will be NULL if this +** is a primary key or unique-constraint on the most recent column added +** to the table currently under construction. +*/ +void sqlite3CreateIndex( + Parse *pParse, /* All information about this parse */ + Token *pName1, /* First part of index name. May be NULL */ + Token *pName2, /* Second part of index name. May be NULL */ + SrcList *pTblName, /* Table to index. Use pParse->pNewTable if 0 */ + 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 this 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; /* 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 */ + 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; + + if( pParse->nErr || db->mallocFailed || IN_DECLARE_VTAB ){ + goto exit_create_index; + } + + /* + ** Find the table that is to be indexed. Return early if not found. + */ + if( pTblName!=0 ){ + + /* Use the two-part index name to determine the database + ** to search for the table. 'Fix' the table name to this db + ** before looking up the table. + */ + assert( pName1 && pName2 ); + iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); + if( iDb<0 ) goto exit_create_index; + +#ifndef SQLITE_OMIT_TEMPDB + /* If the index name was unqualified, check if the the table + ** is a temp table. If so, set the database to 1. Do not do this + ** if initialising a database schema. + */ + if( !db->init.busy ){ + pTab = sqlite3SrcListLookup(pParse, pTblName); + if( pName2 && pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){ + iDb = 1; + } + } +#endif + + if( sqlite3FixInit(&sFix, pParse, iDb, "index", pName) && + sqlite3FixSrcList(&sFix, pTblName) + ){ + /* Because the parser constructs pTblName from a single identifier, + ** sqlite3FixSrcList can never fail. */ + assert(0); + } + pTab = sqlite3LocateTable(pParse, 0, pTblName->a[0].zName, + pTblName->a[0].zDatabase); + if( !pTab ) goto exit_create_index; + assert( db->aDb[iDb].pSchema==pTab->pSchema ); + }else{ + assert( pName==0 ); + 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 ){ + sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName); + goto exit_create_index; + } +#ifndef SQLITE_OMIT_VIEW + if( pTab->pSelect ){ + sqlite3ErrorMsg(pParse, "views may not be indexed"); + goto exit_create_index; + } +#endif +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( IsVirtual(pTab) ){ + sqlite3ErrorMsg(pParse, "virtual tables may not be indexed"); + goto exit_create_index; + } +#endif + + /* + ** Find the name of the index. Make sure there is not already another + ** index or table with the same name. + ** + ** Exception: If we are reading the names of permanent indices from the + ** sqlite_master table (because some other process changed the schema) and + ** one of the index names collides with the name of a temporary table or + ** index, then we will continue to process this index. + ** + ** If pName==0 it means that we are + ** dealing with a primary key or UNIQUE constraint. We have to invent our + ** own name. + */ + if( pName ){ + zName = sqlite3NameFromToken(db, pName); + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto exit_create_index; + if( zName==0 ) goto exit_create_index; + if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ + goto exit_create_index; + } + if( !db->init.busy ){ + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto exit_create_index; + if( sqlite3FindTable(db, zName, 0)!=0 ){ + sqlite3ErrorMsg(pParse, "there is already a table named %s", zName); + goto exit_create_index; + } + } + if( sqlite3FindIndex(db, zName, pDb->zName)!=0 ){ + if( !ifNotExist ){ + sqlite3ErrorMsg(pParse, "index %s already exists", zName); + } + goto exit_create_index; + } + }else{ + int n; + Index *pLoop; + for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){} + zName = sqlite3MPrintf(db, "sqlite_autoindex_%s_%d", pTab->zName, n); + if( zName==0 ){ + goto exit_create_index; + } + } + + /* Check for authorization to create an index. + */ +#ifndef SQLITE_OMIT_AUTHORIZATION + { + const char *zDb = pDb->zName; + if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iDb), 0, zDb) ){ + goto exit_create_index; + } + i = SQLITE_CREATE_INDEX; + if( !OMIT_TEMPDB && iDb==1 ) i = SQLITE_CREATE_TEMP_INDEX; + if( sqlite3AuthCheck(pParse, i, zName, pTab->zName, zDb) ){ + goto exit_create_index; + } + } +#endif + + /* If pList==0, it means this routine was called to make a primary + ** key out of the last column added to the table under construction. + ** So create a fake list to simulate this. + */ + if( pList==0 ){ + nullId.z = (u8*)pTab->aCol[pTab->nCol-1].zName; + nullId.n = strlen((char*)nullId.z); + pList = sqlite3ExprListAppend(pParse, 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; i<pList->nExpr; i++){ + Expr *pExpr = pList->a[i].pExpr; + if( pExpr ){ + nExtra += (1 + strlen(pExpr->pColl->zName)); + } + } + + /* + ** Allocate the index structure. + */ + nName = strlen(zName); + nCol = pList->nExpr; + pIndex = sqlite3DbMallocZero(db, + 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( db->mallocFailed ){ + goto exit_create_index; + } + pIndex->azColl = (char**)(&pIndex[1]); + pIndex->aiColumn = (int *)(&pIndex->azColl[nCol]); + pIndex->aiRowEst = (unsigned *)(&pIndex->aiColumn[nCol]); + pIndex->aSortOrder = (u8 *)(&pIndex->aiRowEst[nCol+1]); + pIndex->zName = (char *)(&pIndex->aSortOrder[nCol]); + zExtra = (char *)(&pIndex->zName[nName+1]); + memcpy(pIndex->zName, zName, nName+1); + pIndex->pTable = pTab; + pIndex->nColumn = pList->nExpr; + pIndex->onError = onError; + pIndex->autoIndex = pName==0; + 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, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){ + const char *zColName = pListItem->zName; + Column *pTabCol; + int requestedSortOrder; + char *zColl; /* Collation sequence name */ + + for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){ + if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break; + } + if( j>=pTab->nCol ){ + sqlite3ErrorMsg(pParse, "table %s has no column named %s", + pTab->zName, zColName); + goto exit_create_index; + } + /* TODO: Add a test to make sure that the same column is not named + ** more than once within the same index. Only the first instance of + ** the column will ever be used by the optimizer. Note that using the + ** same column more than once cannot be an error because that would + ** break backwards compatibility - it needs to be a warning. + */ + pIndex->aiColumn[i] = j; + if( pListItem->pExpr ){ + assert( pListItem->pExpr->pColl ); + zColl = zExtra; + sqlite3_snprintf(nExtra, zExtra, "%s", pListItem->pExpr->pColl->zName); + zExtra += (strlen(zColl) + 1); + }else{ + zColl = pTab->aCol[j].zColl; + if( !zColl ){ + zColl = db->pDfltColl->zName; + } + } + if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl, -1) ){ + goto exit_create_index; + } + pIndex->azColl[i] = zColl; + requestedSortOrder = pListItem->sortOrder & sortOrderMask; + pIndex->aSortOrder[i] = requestedSortOrder; + } + sqlite3DefaultRowEst(pIndex); + + if( pTab==pParse->pNewTable ){ + /* This routine has been called to create an automatic index as a + ** result of a PRIMARY KEY or UNIQUE clause on a column definition, or + ** a PRIMARY KEY or UNIQUE clause following the column definitions. + ** i.e. one of: + ** + ** CREATE TABLE t(x PRIMARY KEY, y); + ** CREATE TABLE t(x, y, UNIQUE(x, y)); + ** + ** Either way, check to see if the table already has such an index. If + ** so, don't bother creating this one. This only applies to + ** automatically created indices. Users can do as they wish with + ** explicit indices. + */ + Index *pIdx; + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + int k; + assert( pIdx->onError!=OE_None ); + assert( pIdx->autoIndex ); + assert( pIndex->onError!=OE_None ); + + if( pIdx->nColumn!=pIndex->nColumn ) continue; + for(k=0; k<pIdx->nColumn; k++){ + const char *z1 = pIdx->azColl[k]; + const char *z2 = pIndex->azColl[k]; + if( pIdx->aiColumn[k]!=pIndex->aiColumn[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 ){ + /* This constraint creates the same index as a previous + ** constraint specified somewhere in the CREATE TABLE statement. + ** However the ON CONFLICT clauses are different. If both this + ** constraint and the previous equivalent constraint have explicit + ** ON CONFLICT clauses this is an error. Otherwise, use the + ** explicitly specified behaviour for the index. + */ + if( !(pIdx->onError==OE_Default || pIndex->onError==OE_Default) ){ + sqlite3ErrorMsg(pParse, + "conflicting ON CONFLICT clauses specified", 0); + } + if( pIdx->onError==OE_Default ){ + pIdx->onError = pIndex->onError; + } + } + goto exit_create_index; + } + } + } + + /* Link the new Index structure to its table and to the other + ** in-memory database structures. + */ + if( db->init.busy ){ + Index *p; + p = sqlite3HashInsert(&pIndex->pSchema->idxHash, + pIndex->zName, strlen(pIndex->zName)+1, pIndex); + if( p ){ + assert( p==pIndex ); /* Malloc must have failed */ + db->mallocFailed = 1; + goto exit_create_index; + } + db->flags |= SQLITE_InternChanges; + if( pTblName!=0 ){ + pIndex->tnum = db->init.newTnum; + } + } + + /* If the db->init.busy is 0 then create the index on disk. This + ** involves writing the index into the master table and filling in the + ** index with the current table contents. + ** + ** The db->init.busy is 0 when the user first enters a CREATE INDEX + ** command. db->init.busy is 1 when a database is opened and + ** CREATE INDEX statements are read out of the master table. In + ** the latter case the index already exists on disk, which is why + ** we don't want to recreate it. + ** + ** If pTblName==0 it means this index is generated as a primary key + ** or UNIQUE constraint of a CREATE TABLE statement. Since the table + ** has just been created, it contains no data and the index initialization + ** step can be skipped. + */ + else if( db->init.busy==0 ){ + Vdbe *v; + char *zStmt; + int iMem = ++pParse->nMem; + + v = sqlite3GetVdbe(pParse); + if( v==0 ) goto exit_create_index; + + + /* Create the rootpage for the index + */ + sqlite3BeginWriteOperation(pParse, 1, iDb); + sqlite3VdbeAddOp2(v, OP_CreateIndex, iDb, iMem); + + /* Gather the complete text of the CREATE INDEX statement into + ** the zStmt variable + */ + if( pStart && pEnd ){ + /* A named index with an explicit CREATE INDEX statement */ + zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s", + onError==OE_None ? "" : " UNIQUE", + pEnd->z - pName->z + 1, + pName->z); + }else{ + /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */ + /* zStmt = sqlite3MPrintf(""); */ + zStmt = 0; + } + + /* Add an entry in sqlite_master for this index + */ + sqlite3NestedParse(pParse, + "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);", + db->aDb[iDb].zName, SCHEMA_TABLE(iDb), + pIndex->zName, + pTab->zName, + iMem, + zStmt + ); + sqlite3DbFree(db, zStmt); + + /* Fill the index with data and reparse the schema. Code an OP_Expire + ** to invalidate all pre-compiled statements. + */ + if( pTblName ){ + sqlite3RefillIndex(pParse, pIndex, iMem); + sqlite3ChangeCookie(pParse, iDb); + sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, + sqlite3MPrintf(db, "name='%q'", pIndex->zName), P4_DYNAMIC); + sqlite3VdbeAddOp1(v, OP_Expire, 0); + } + } + + /* When adding an index to the list of indices for a table, make + ** sure all indices labeled OE_Replace come after all those labeled + ** OE_Ignore. This is necessary for the correct operation of UPDATE + ** and INSERT. + */ + if( db->init.busy || pTblName==0 ){ + if( onError!=OE_Replace || pTab->pIndex==0 + || pTab->pIndex->onError==OE_Replace){ + pIndex->pNext = pTab->pIndex; + pTab->pIndex = pIndex; + }else{ + Index *pOther = pTab->pIndex; + while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){ + pOther = pOther->pNext; + } + pIndex->pNext = pOther->pNext; + pOther->pNext = pIndex; + } + pIndex = 0; + } + + /* Clean up before exiting */ +exit_create_index: + if( pIndex ){ + freeIndex(pIndex); + } + sqlite3ExprListDelete(db, pList); + sqlite3SrcListDelete(db, pTblName); + sqlite3DbFree(db, zName); + 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 ){ + int r1 = sqlite3GetTempReg(pParse); + int r2 = sqlite3GetTempReg(pParse); + int j1; + sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, 1); + sqlite3VdbeUsesBtree(v, iDb); + sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2); + j1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 1, r2); + sqlite3VdbeJumpHere(v, j1); + sqlite3ReleaseTempReg(pParse, r1); + sqlite3ReleaseTempReg(pParse, r2); + } +} + +/* +** Fill the Index.aiRowEst[] array with default information - information +** to be used when we have not run the ANALYZE command. +** +** aiRowEst[0] is suppose to contain the number of elements in the index. +** Since we do not know, guess 1 million. aiRowEst[1] is an estimate of the +** number of rows in the table that match any particular value of the +** first column of the index. aiRowEst[2] is an estimate of the number +** of rows that match any particular combiniation of the first 2 columns +** of the index. And so forth. It must always be the case that +* +** aiRowEst[N]<=aiRowEst[N-1] +** aiRowEst[N]>=1 +** +** Apart from that, we have little to go on besides intuition as to +** how aiRowEst[] should be initialized. The numbers generated here +** are based on typical values found in actual indices. +*/ +void sqlite3DefaultRowEst(Index *pIdx){ + unsigned *a = pIdx->aiRowEst; + int i; + assert( a!=0 ); + a[0] = 1000000; + for(i=pIdx->nColumn; i>=5; i--){ + a[i] = 5; + } + while( i>=1 ){ + a[i] = 11 - i; + i--; + } + if( pIdx->onError!=OE_None ){ + a[pIdx->nColumn] = 1; + } +} + +/* +** This routine will drop an existing named index. This routine +** implements the DROP INDEX statement. +*/ +void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){ + Index *pIndex; + Vdbe *v; + sqlite3 *db = pParse->db; + int iDb; + + if( pParse->nErr || db->mallocFailed ){ + goto exit_drop_index; + } + assert( pName->nSrc==1 ); + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ + goto exit_drop_index; + } + pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase); + if( pIndex==0 ){ + if( !ifExists ){ + sqlite3ErrorMsg(pParse, "no such index: %S", pName, 0); + } + pParse->checkSchema = 1; + goto exit_drop_index; + } + if( pIndex->autoIndex ){ + sqlite3ErrorMsg(pParse, "index associated with UNIQUE " + "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[iDb].zName; + const char *zTab = SCHEMA_TABLE(iDb); + if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ + goto exit_drop_index; + } + if( !OMIT_TEMPDB && iDb ) code = SQLITE_DROP_TEMP_INDEX; + if( sqlite3AuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){ + goto exit_drop_index; + } + } +#endif + + /* Generate code to remove the index and from the master table */ + v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3BeginWriteOperation(pParse, 1, iDb); + sqlite3NestedParse(pParse, + "DELETE FROM %Q.%s WHERE name=%Q", + db->aDb[iDb].zName, SCHEMA_TABLE(iDb), + pIndex->zName + ); + if( sqlite3FindTable(db, "sqlite_stat1", db->aDb[iDb].zName) ){ + sqlite3NestedParse(pParse, + "DELETE FROM %Q.sqlite_stat1 WHERE idx=%Q", + db->aDb[iDb].zName, pIndex->zName + ); + } + sqlite3ChangeCookie(pParse, iDb); + destroyRootPage(pParse, pIndex->tnum, iDb); + sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0); + } + +exit_drop_index: + sqlite3SrcListDelete(db, pName); +} + +/* +** pArray is a pointer to an array of objects. Each object in the +** array is szEntry bytes in size. This routine allocates a new +** object on the end of the array. +** +** *pnEntry is the number of entries already in use. *pnAlloc is +** the previously allocated size of the array. initSize is the +** suggested initial array size allocation. +** +** The index of the new entry is returned in *pIdx. +** +** This routine returns a pointer to the array of objects. This +** might be the same as the pArray parameter or it might be a different +** pointer if the array was resized. +*/ +void *sqlite3ArrayAllocate( + sqlite3 *db, /* Connection to notify of malloc failures */ + void *pArray, /* Array of objects. Might be reallocated */ + int szEntry, /* Size of each object in the array */ + int initSize, /* Suggested initial allocation, in elements */ + int *pnEntry, /* Number of objects currently in use */ + int *pnAlloc, /* Current size of the allocation, in elements */ + int *pIdx /* Write the index of a new slot here */ +){ + char *z; + if( *pnEntry >= *pnAlloc ){ + void *pNew; + int newSize; + newSize = (*pnAlloc)*2 + initSize; + pNew = sqlite3DbRealloc(db, pArray, newSize*szEntry); + if( pNew==0 ){ + *pIdx = -1; + return pArray; + } + *pnAlloc = newSize; + pArray = pNew; + } + z = (char*)pArray; + memset(&z[*pnEntry * szEntry], 0, szEntry); + *pIdx = *pnEntry; + ++*pnEntry; + return pArray; +} + +/* +** Append a new element to the given IdList. Create a new IdList if +** need be. +** +** A new IdList is returned, or NULL if malloc() fails. +*/ +IdList *sqlite3IdListAppend(sqlite3 *db, IdList *pList, Token *pToken){ + int i; + if( pList==0 ){ + pList = sqlite3DbMallocZero(db, sizeof(IdList) ); + if( pList==0 ) return 0; + pList->nAlloc = 0; + } + pList->a = sqlite3ArrayAllocate( + db, + pList->a, + sizeof(pList->a[0]), + 5, + &pList->nId, + &pList->nAlloc, + &i + ); + if( i<0 ){ + sqlite3IdListDelete(db, pList); + return 0; + } + pList->a[i].zName = sqlite3NameFromToken(db, pToken); + return pList; +} + +/* +** Delete an IdList. +*/ +void sqlite3IdListDelete(sqlite3 *db, IdList *pList){ + int i; + if( pList==0 ) return; + for(i=0; i<pList->nId; i++){ + sqlite3DbFree(db, pList->a[i].zName); + } + sqlite3DbFree(db, pList->a); + sqlite3DbFree(db, pList); +} + +/* +** Return the index in pList of the identifier named zId. Return -1 +** if not found. +*/ +int sqlite3IdListIndex(IdList *pList, const char *zName){ + int i; + if( pList==0 ) return -1; + for(i=0; i<pList->nId; i++){ + if( sqlite3StrICmp(pList->a[i].zName, zName)==0 ) return i; + } + return -1; +} + +/* +** Append a new table name to the given SrcList. Create a new SrcList if +** need be. A new entry is created in the SrcList even if pToken is NULL. +** +** A new SrcList is returned, or NULL if malloc() fails. +** +** If pDatabase is not null, it means that the table has an optional +** database name prefix. Like this: "database.table". The pDatabase +** points to the table name and the pTable points to the database name. +** The SrcList.a[].zName field is filled with the table name which might +** come from pTable (if pDatabase is NULL) or from pDatabase. +** SrcList.a[].zDatabase is filled with the database name from pTable, +** or with NULL if no database is specified. +** +** In other words, if call like this: +** +** sqlite3SrcListAppend(D,A,B,0); +** +** Then B is a table name and the database name is unspecified. If called +** like this: +** +** sqlite3SrcListAppend(D,A,B,C); +** +** Then C is the table name and B is the database name. +*/ +SrcList *sqlite3SrcListAppend( + sqlite3 *db, /* Connection to notify of malloc failures */ + SrcList *pList, /* Append to this SrcList. NULL creates a new SrcList */ + Token *pTable, /* Table to append */ + Token *pDatabase /* Database of the table */ +){ + struct SrcList_item *pItem; + if( pList==0 ){ + pList = sqlite3DbMallocZero(db, sizeof(SrcList) ); + if( pList==0 ) return 0; + pList->nAlloc = 1; + } + if( pList->nSrc>=pList->nAlloc ){ + SrcList *pNew; + pList->nAlloc *= 2; + pNew = sqlite3DbRealloc(db, pList, + sizeof(*pList) + (pList->nAlloc-1)*sizeof(pList->a[0]) ); + if( pNew==0 ){ + sqlite3SrcListDelete(db, pList); + return 0; + } + pList = pNew; + } + pItem = &pList->a[pList->nSrc]; + memset(pItem, 0, sizeof(pList->a[0])); + if( pDatabase && pDatabase->z==0 ){ + pDatabase = 0; + } + if( pDatabase && pTable ){ + Token *pTemp = pDatabase; + pDatabase = pTable; + pTable = pTemp; + } + pItem->zName = sqlite3NameFromToken(db, pTable); + pItem->zDatabase = sqlite3NameFromToken(db, pDatabase); + pItem->iCursor = -1; + pItem->isPopulated = 0; + pList->nSrc++; + return pList; +} + +/* +** Assign cursors to all tables in a SrcList +*/ +void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){ + int i; + struct SrcList_item *pItem; + assert(pList || pParse->db->mallocFailed ); + if( pList ){ + for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){ + if( pItem->iCursor>=0 ) break; + pItem->iCursor = pParse->nTab++; + if( pItem->pSelect ){ + sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc); + } + } + } +} + +/* +** Delete an entire SrcList including all its substructure. +*/ +void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){ + int i; + struct SrcList_item *pItem; + if( pList==0 ) return; + for(pItem=pList->a, i=0; i<pList->nSrc; i++, pItem++){ + sqlite3DbFree(db, pItem->zDatabase); + sqlite3DbFree(db, pItem->zName); + sqlite3DbFree(db, pItem->zAlias); + sqlite3DeleteTable(pItem->pTab); + sqlite3SelectDelete(db, pItem->pSelect); + sqlite3ExprDelete(db, pItem->pOn); + sqlite3IdListDelete(db, pItem->pUsing); + } + sqlite3DbFree(db, pList); +} + +/* +** This routine is called by the parser to add a new term to the +** end of a growing FROM clause. The "p" parameter is the part of +** the FROM clause that has already been constructed. "p" is NULL +** if this is the first term of the FROM clause. pTable and pDatabase +** are the name of the table and database named in the FROM clause term. +** pDatabase is NULL if the database name qualifier is missing - the +** usual case. If the term has a alias, then pAlias points to the +** alias token. If the term is a subquery, then pSubquery is the +** SELECT statement that the subquery encodes. The pTable and +** pDatabase parameters are NULL for subqueries. The pOn and pUsing +** parameters are the content of the ON and USING clauses. +** +** Return a new SrcList which encodes is the FROM with the new +** term added. +*/ +SrcList *sqlite3SrcListAppendFromTerm( + Parse *pParse, /* Parsing context */ + SrcList *p, /* The left part of the FROM clause already seen */ + Token *pTable, /* Name of the table to add to the FROM clause */ + Token *pDatabase, /* Name of the database containing pTable */ + Token *pAlias, /* The right-hand side of the AS subexpression */ + Select *pSubquery, /* A subquery used in place of a table name */ + Expr *pOn, /* The ON clause of a join */ + IdList *pUsing /* The USING clause of a join */ +){ + struct SrcList_item *pItem; + sqlite3 *db = pParse->db; + p = sqlite3SrcListAppend(db, p, pTable, pDatabase); + if( p==0 || p->nSrc==0 ){ + sqlite3ExprDelete(db, pOn); + sqlite3IdListDelete(db, pUsing); + sqlite3SelectDelete(db, pSubquery); + return p; + } + pItem = &p->a[p->nSrc-1]; + if( pAlias && pAlias->n ){ + pItem->zAlias = sqlite3NameFromToken(db, pAlias); + } + pItem->pSelect = pSubquery; + pItem->pOn = pOn; + pItem->pUsing = pUsing; + return p; +} + +/* +** When building up a FROM clause in the parser, the join operator +** is initially attached to the left operand. But the code generator +** expects the join operator to be on the right operand. This routine +** Shifts all join operators from left to right for an entire FROM +** clause. +** +** Example: Suppose the join is like this: +** +** A natural cross join B +** +** The operator is "natural cross join". The A and B operands are stored +** in p->a[0] and p->a[1], respectively. The parser initially stores the +** operator with A. This routine shifts that operator over to B. +*/ +void sqlite3SrcListShiftJoinType(SrcList *p){ + if( p && p->a ){ + int i; + for(i=p->nSrc-1; i>0; i--){ + p->a[i].jointype = p->a[i-1].jointype; + } + p->a[0].jointype = 0; + } +} + +/* +** Begin a transaction +*/ +void sqlite3BeginTransaction(Parse *pParse, int type){ + sqlite3 *db; + Vdbe *v; + int i; + + if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; + if( pParse->nErr || db->mallocFailed ) return; + if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ) return; + + v = sqlite3GetVdbe(pParse); + if( !v ) return; + if( type!=TK_DEFERRED ){ + for(i=0; i<db->nDb; i++){ + sqlite3VdbeAddOp2(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1); + sqlite3VdbeUsesBtree(v, i); + } + } + sqlite3VdbeAddOp2(v, OP_AutoCommit, 0, 0); +} + +/* +** Commit a transaction +*/ +void sqlite3CommitTransaction(Parse *pParse){ + sqlite3 *db; + Vdbe *v; + + if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; + if( pParse->nErr || db->mallocFailed ) return; + if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ) return; + + v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3VdbeAddOp2(v, OP_AutoCommit, 1, 0); + } +} + +/* +** Rollback a transaction +*/ +void sqlite3RollbackTransaction(Parse *pParse){ + sqlite3 *db; + Vdbe *v; + + if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; + if( pParse->nErr || db->mallocFailed ) return; + if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ) return; + + v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3VdbeAddOp2(v, OP_AutoCommit, 1, 1); + } +} + +/* +** Make sure the TEMP database is open and available for use. Return +** the number of errors. Leave any error messages in the pParse structure. +*/ +int sqlite3OpenTempDatabase(Parse *pParse){ + sqlite3 *db = pParse->db; + if( db->aDb[1].pBt==0 && !pParse->explain ){ + int rc; + static const int flags = + SQLITE_OPEN_READWRITE | + SQLITE_OPEN_CREATE | + SQLITE_OPEN_EXCLUSIVE | + SQLITE_OPEN_DELETEONCLOSE | + SQLITE_OPEN_TEMP_DB; + + rc = sqlite3BtreeFactory(db, 0, 0, SQLITE_DEFAULT_CACHE_SIZE, flags, + &db->aDb[1].pBt); + if( rc!=SQLITE_OK ){ + sqlite3ErrorMsg(pParse, "unable to open a temporary database " + "file for storing temporary tables"); + pParse->rc = rc; + return 1; + } + assert( (db->flags & SQLITE_InTrans)==0 || db->autoCommit ); + assert( db->aDb[1].pSchema ); + sqlite3PagerJournalMode(sqlite3BtreePager(db->aDb[1].pBt), + db->dfltJournalMode); + } + return 0; +} + +/* +** Generate VDBE code that will verify the schema cookie and start +** a read-transaction for all named database files. +** +** It is important that all schema cookies be verified and all +** read transactions be started before anything else happens in +** the VDBE program. But this routine can be called after much other +** code has been generated. So here is what we do: +** +** The first time this routine is called, we code an OP_Goto that +** will jump to a subroutine at the end of the program. Then we +** record every database that needs its schema verified in the +** pParse->cookieMask field. Later, after all other code has been +** generated, the subroutine that does the cookie verifications and +** starts the transactions will be coded and the OP_Goto P2 value +** will be made to point to that subroutine. The generation of the +** cookie verification subroutine code happens in sqlite3FinishCoding(). +** +** If iDb<0 then code the OP_Goto only - don't set flag to verify the +** schema on any databases. This can be used to position the OP_Goto +** early in the code, before we know if any database tables will be used. +*/ +void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ + sqlite3 *db; + Vdbe *v; + int mask; + + v = sqlite3GetVdbe(pParse); + if( v==0 ) return; /* This only happens if there was a prior error */ + db = pParse->db; + if( pParse->cookieGoto==0 ){ + pParse->cookieGoto = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0)+1; + } + if( iDb>=0 ){ + assert( iDb<db->nDb ); + assert( db->aDb[iDb].pBt!=0 || iDb==1 ); + assert( iDb<SQLITE_MAX_ATTACHED+2 ); + mask = 1<<iDb; + if( (pParse->cookieMask & mask)==0 ){ + pParse->cookieMask |= mask; + pParse->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie; + if( !OMIT_TEMPDB && iDb==1 ){ + sqlite3OpenTempDatabase(pParse); + } + } + } +} + +/* +** Generate VDBE code that prepares for doing an operation that +** might change the database. +** +** This routine starts a new transaction if we are not already within +** a transaction. If we are already within a transaction, then a checkpoint +** is set if the setStatement parameter is true. A checkpoint should +** be set for operations that might fail (due to a constraint) part of +** the way through and which will need to undo some writes without having to +** rollback the whole transaction. For operations where all constraints +** can be checked before any changes are made to the database, it is never +** necessary to undo a write and the checkpoint should not be set. +** +** Only database iDb and the temp database are made writable by this call. +** If iDb==0, then the main and temp databases are made writable. If +** iDb==1 then only the temp database is made writable. If iDb>1 then the +** specified auxiliary database and the temp database are made writable. +*/ +void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){ + Vdbe *v = sqlite3GetVdbe(pParse); + if( v==0 ) return; + sqlite3CodeVerifySchema(pParse, iDb); + pParse->writeMask |= 1<<iDb; + if( setStatement && pParse->nested==0 ){ + sqlite3VdbeAddOp1(v, OP_Statement, iDb); + } + if( (OMIT_TEMPDB || iDb!=1) && pParse->db->aDb[1].pBt!=0 ){ + sqlite3BeginWriteOperation(pParse, setStatement, 1); + } +} + +/* +** Check to see if pIndex uses the collating sequence pColl. Return +** true if it does and false if it does not. +*/ +#ifndef SQLITE_OMIT_REINDEX +static int collationMatch(const char *zColl, Index *pIndex){ + int i; + for(i=0; i<pIndex->nColumn; i++){ + const char *z = pIndex->azColl[i]; + if( z==zColl || (z && zColl && 0==sqlite3StrICmp(z, zColl)) ){ + return 1; + } + } + return 0; +} +#endif + +/* +** Recompute all indices of pTab that use the collating sequence pColl. +** If pColl==0 then recompute all indices of pTab. +*/ +#ifndef SQLITE_OMIT_REINDEX +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( zColl==0 || collationMatch(zColl, pIndex) ){ + int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + sqlite3BeginWriteOperation(pParse, 0, iDb); + sqlite3RefillIndex(pParse, pIndex, -1); + } + } +} +#endif + +/* +** Recompute all indices of all tables in all databases where the +** indices use the collating sequence pColl. If pColl==0 then recompute +** all indices everywhere. +*/ +#ifndef SQLITE_OMIT_REINDEX +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 */ + HashElem *k; /* For looping over tables in pDb */ + Table *pTab; /* A table in the database */ + + for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){ + assert( pDb!=0 ); + for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){ + pTab = (Table*)sqliteHashData(k); + reindexTable(pParse, pTab, zColl); + } + } +} +#endif + +/* +** Generate code for the REINDEX command. +** +** REINDEX -- 1 +** REINDEX <collation> -- 2 +** REINDEX ?<database>.?<tablename> -- 3 +** REINDEX ?<database>.?<indexname> -- 4 +** +** Form 1 causes all indices in all attached databases to be rebuilt. +** Form 2 rebuilds all indices in all databases that use the named +** collating function. Forms 3 and 4 rebuild the named index or all +** indices associated with the named table. +*/ +#ifndef SQLITE_OMIT_REINDEX +void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){ + CollSeq *pColl; /* Collating sequence to be reindexed, or NULL */ + char *z; /* Name of a table or index */ + const char *zDb; /* Name of the database */ + Table *pTab; /* A table in the database */ + Index *pIndex; /* An index associated with pTab */ + int iDb; /* The database index number */ + sqlite3 *db = pParse->db; /* The database connection */ + Token *pObjName; /* Name of the table or index to be reindexed */ + + /* Read the database schema. If an error occurs, leave an error message + ** and code in pParse and return NULL. */ + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ + return; + } + + if( pName1==0 || pName1->z==0 ){ + reindexDatabases(pParse, 0); + return; + }else if( pName2==0 || pName2->z==0 ){ + char *zColl; + assert( pName1->z ); + zColl = sqlite3NameFromToken(pParse->db, pName1); + if( !zColl ) return; + pColl = sqlite3FindCollSeq(db, ENC(db), zColl, -1, 0); + if( pColl ){ + if( zColl ){ + reindexDatabases(pParse, zColl); + sqlite3DbFree(db, zColl); + } + return; + } + sqlite3DbFree(db, zColl); + } + iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName); + if( iDb<0 ) return; + z = sqlite3NameFromToken(db, pObjName); + if( z==0 ) return; + zDb = db->aDb[iDb].zName; + pTab = sqlite3FindTable(db, z, zDb); + if( pTab ){ + reindexTable(pParse, pTab, 0); + sqlite3DbFree(db, z); + return; + } + pIndex = sqlite3FindIndex(db, z, zDb); + sqlite3DbFree(db, z); + if( pIndex ){ + sqlite3BeginWriteOperation(pParse, 0, iDb); + sqlite3RefillIndex(pParse, pIndex, -1); + return; + } + 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 sqlite3DbFree(db, ) 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; + sqlite3 *db = pParse->db; + KeyInfo *pKey = (KeyInfo *)sqlite3DbMallocZero(db, nBytes); + + if( pKey ){ + pKey->db = pParse->db; + pKey->aSortOrder = (u8 *)&(pKey->aColl[nCol]); + assert( &pKey->aSortOrder[nCol]==&(((u8 *)pKey)[nBytes]) ); + for(i=0; i<nCol; i++){ + char *zColl = pIdx->azColl[i]; + assert( zColl ); + pKey->aColl[i] = sqlite3LocateCollSeq(pParse, zColl, -1); + pKey->aSortOrder[i] = pIdx->aSortOrder[i]; + } + pKey->nField = nCol; + } + + if( pParse->nErr ){ + sqlite3DbFree(db, pKey); + pKey = 0; + } + return pKey; +} + +/* Begin preload-cache.patch for Chromium */ +/* See declaration in sqlite3.h for information */ +int sqlite3Preload(sqlite3 *db) +{ + Pager *pPager; + Btree *pBt; + int rc; + int i; + int dbsLoaded = 0; + + for(i=0; i<db->nDb; i++) { + pBt = db->aDb[i].pBt; + if( !pBt ) + continue; + pPager = sqlite3BtreePager(pBt); + if( pPager ) { + rc = sqlite3PagerLoadall(pPager); + if (rc == SQLITE_OK) + dbsLoaded++; + } + } + if (dbsLoaded == 0) + return SQLITE_ERROR; + return SQLITE_OK; +} +/* End preload-cache.patch for Chromium */ diff --git a/third_party/sqlite/src/callback.c b/third_party/sqlite/src/callback.c new file mode 100755 index 0000000..a77f994 --- /dev/null +++ b/third_party/sqlite/src/callback.c @@ -0,0 +1,380 @@ +/* +** 2005 May 23 +** +** 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 functions used to access the internal hash tables +** of user defined functions and collation sequences. +** +** $Id: callback.c,v 1.26 2008/07/28 19:34:53 drh Exp $ +*/ + +#include "sqliteInt.h" + +/* +** Invoke the 'collation needed' callback to request a collation sequence +** in the database text encoding of name zName, length nName. +** If the collation sequence +*/ +static void callCollNeeded(sqlite3 *db, const char *zName, int nName){ + assert( !db->xCollNeeded || !db->xCollNeeded16 ); + if( nName<0 ) nName = sqlite3Strlen(db, zName); + if( db->xCollNeeded ){ + char *zExternal = sqlite3DbStrNDup(db, zName, nName); + if( !zExternal ) return; + db->xCollNeeded(db->pCollNeededArg, db, (int)ENC(db), zExternal); + sqlite3DbFree(db, zExternal); + } +#ifndef SQLITE_OMIT_UTF16 + if( db->xCollNeeded16 ){ + char const *zExternal; + sqlite3_value *pTmp = sqlite3ValueNew(db); + sqlite3ValueSetStr(pTmp, nName, zName, SQLITE_UTF8, SQLITE_STATIC); + zExternal = sqlite3ValueText(pTmp, SQLITE_UTF16NATIVE); + if( zExternal ){ + db->xCollNeeded16(db->pCollNeededArg, db, (int)ENC(db), zExternal); + } + sqlite3ValueFree(pTmp); + } +#endif +} + +/* +** This routine is called if the collation factory fails to deliver a +** collation function in the best encoding but there may be other versions +** of this collation function (for other text encodings) available. Use one +** of these instead if they exist. Avoid a UTF-8 <-> UTF-16 conversion if +** possible. +*/ +static int synthCollSeq(sqlite3 *db, CollSeq *pColl){ + CollSeq *pColl2; + char *z = pColl->zName; + int n = strlen(z); + int i; + static const u8 aEnc[] = { SQLITE_UTF16BE, SQLITE_UTF16LE, SQLITE_UTF8 }; + for(i=0; i<3; i++){ + pColl2 = sqlite3FindCollSeq(db, aEnc[i], z, n, 0); + if( pColl2->xCmp!=0 ){ + memcpy(pColl, pColl2, sizeof(CollSeq)); + pColl->xDel = 0; /* Do not copy the destructor */ + return SQLITE_OK; + } + } + return SQLITE_ERROR; +} + +/* +** This function is responsible for invoking the collation factory callback +** or substituting a collation sequence of a different encoding when the +** requested collation sequence is not available in the database native +** encoding. +** +** If it is not NULL, then pColl must point to the database native encoding +** collation sequence with name zName, length nName. +** +** The return value is either the collation sequence to be used in database +** db for collation type name zName, length nName, or NULL, if no collation +** sequence can be found. +*/ +CollSeq *sqlite3GetCollSeq( + sqlite3* db, + CollSeq *pColl, + const char *zName, + int nName +){ + CollSeq *p; + + p = pColl; + if( !p ){ + 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, ENC(db), zName, nName, 0); + } + if( p && !p->xCmp && synthCollSeq(db, p) ){ + p = 0; + } + assert( !p || p->xCmp ); + return p; +} + +/* +** This routine is called on a collation sequence before it is used to +** check that it is defined. An undefined collation sequence exists when +** a database is loaded that contains references to collation sequences +** that have not been defined by sqlite3_create_collation() etc. +** +** If required, this routine calls the 'collation needed' callback to +** request a definition of the collating sequence. If this doesn't work, +** an equivalent collating sequence that uses a text encoding different +** from the main database is substituted, if one is available. +*/ +int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){ + if( pColl ){ + const char *zName = pColl->zName; + CollSeq *p = sqlite3GetCollSeq(pParse->db, pColl, zName, -1); + if( !p ){ + if( pParse->nErr==0 ){ + sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName); + } + pParse->nErr++; + return SQLITE_ERROR; + } + assert( p==pColl ); + } + return SQLITE_OK; +} + + + +/* +** Locate and return an entry from the db.aCollSeq hash table. If the entry +** specified by zName and nName is not found and parameter 'create' is +** true, then create a new entry. Otherwise return NULL. +** +** Each pointer stored in the sqlite3.aCollSeq hash table contains an +** array of three CollSeq structures. The first is the collation sequence +** prefferred for UTF-8, the second UTF-16le, and the third UTF-16be. +** +** Stored immediately after the three collation sequences is a copy of +** the collation sequence name. A pointer to this string is stored in +** each collation sequence structure. +*/ +static CollSeq *findCollSeqEntry( + sqlite3 *db, + const char *zName, + int nName, + int create +){ + CollSeq *pColl; + if( nName<0 ) nName = sqlite3Strlen(db, zName); + pColl = sqlite3HashFind(&db->aCollSeq, zName, nName); + + if( 0==pColl && create ){ + pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName + 1 ); + if( pColl ){ + CollSeq *pDel = 0; + pColl[0].zName = (char*)&pColl[3]; + pColl[0].enc = SQLITE_UTF8; + pColl[1].zName = (char*)&pColl[3]; + pColl[1].enc = SQLITE_UTF16LE; + pColl[2].zName = (char*)&pColl[3]; + pColl[2].enc = SQLITE_UTF16BE; + memcpy(pColl[0].zName, zName, nName); + pColl[0].zName[nName] = 0; + pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl); + + /* If a malloc() failure occured in sqlite3HashInsert(), it will + ** return the pColl pointer to be deleted (because it wasn't added + ** to the hash table). + */ + assert( pDel==0 || pDel==pColl ); + if( pDel!=0 ){ + db->mallocFailed = 1; + sqlite3DbFree(db, pDel); + pColl = 0; + } + } + } + return pColl; +} + +/* +** Parameter zName points to a UTF-8 encoded string nName bytes long. +** Return the CollSeq* pointer for the collation sequence named zName +** for the encoding 'enc' from the database 'db'. +** +** If the entry specified is not found and 'create' is true, then create a +** new entry. Otherwise return NULL. +** +** A separate function sqlite3LocateCollSeq() is a wrapper around +** this routine. sqlite3LocateCollSeq() invokes the collation factory +** if necessary and generates an error message if the collating sequence +** cannot be found. +*/ +CollSeq *sqlite3FindCollSeq( + sqlite3 *db, + u8 enc, + const char *zName, + int nName, + int 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; + return pColl; +} + +/* +** Locate a user function given a name, a number of arguments and a flag +** indicating whether the function prefers UTF-16 over UTF-8. Return a +** pointer to the FuncDef structure that defines that function, or return +** NULL if the function does not exist. +** +** If the createFlag argument is true, then a new (blank) FuncDef +** structure is created and liked into the "db" structure if a +** no matching function previously existed. When createFlag is true +** and the nArg parameter is -1, then only a function that accepts +** any number of arguments will be returned. +** +** If createFlag is false and nArg is -1, then the first valid +** function found is returned. A function is valid if either xFunc +** or xStep is non-zero. +** +** If createFlag is false, then a function with the required name and +** number of arguments may be returned even if the eTextRep flag does not +** match that requested. +*/ +FuncDef *sqlite3FindFunction( + sqlite3 *db, /* An open database */ + const char *zName, /* Name of the function. Not null-terminated */ + int nName, /* Number of characters in the name */ + int nArg, /* Number of arguments. -1 means any number */ + u8 enc, /* Preferred text encoding */ + int createFlag /* Create new entry if true and does not otherwise exist */ +){ + FuncDef *p; /* Iterator variable */ + FuncDef *pFirst; /* First function with this name */ + FuncDef *pBest = 0; /* Best match found so far */ + int bestmatch = 0; + + + assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); + if( nArg<-1 ) nArg = -1; + + pFirst = (FuncDef*)sqlite3HashFind(&db->aFunc, zName, nName); + for(p=pFirst; p; p=p->pNext){ + /* During the search for the best function definition, bestmatch is set + ** as follows to indicate the quality of the match with the definition + ** pointed to by pBest: + ** + ** 0: pBest is NULL. No match has been found. + ** 1: A variable arguments function that prefers UTF-8 when a UTF-16 + ** encoding is requested, or vice versa. + ** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is + ** requested, or vice versa. + ** 3: A variable arguments function using the same text encoding. + ** 4: A function with the exact number of arguments requested that + ** prefers UTF-8 when a UTF-16 encoding is requested, or vice versa. + ** 5: A function with the exact number of arguments requested that + ** prefers UTF-16LE when UTF-16BE is requested, or vice versa. + ** 6: An exact match. + ** + ** A larger value of 'matchqual' indicates a more desirable match. + */ + if( p->nArg==-1 || p->nArg==nArg || nArg==-1 ){ + int match = 1; /* Quality of this match */ + if( p->nArg==nArg || nArg==-1 ){ + match = 4; + } + if( enc==p->iPrefEnc ){ + match += 2; + } + else if( (enc==SQLITE_UTF16LE && p->iPrefEnc==SQLITE_UTF16BE) || + (enc==SQLITE_UTF16BE && p->iPrefEnc==SQLITE_UTF16LE) ){ + match += 1; + } + + if( match>bestmatch ){ + pBest = p; + bestmatch = match; + } + } + } + + /* If the createFlag parameter is true, and the seach did not reveal an + ** exact match for the name, number of arguments and encoding, then add a + ** new entry to the hash table and return it. + */ + if( createFlag && bestmatch<6 && + (pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName))!=0 ){ + pBest->nArg = nArg; + pBest->pNext = pFirst; + pBest->iPrefEnc = enc; + memcpy(pBest->zName, zName, nName); + pBest->zName[nName] = 0; + if( pBest==sqlite3HashInsert(&db->aFunc,pBest->zName,nName,(void*)pBest) ){ + db->mallocFailed = 1; + sqlite3DbFree(db, pBest); + return 0; + } + } + + if( pBest && (pBest->xStep || pBest->xFunc || createFlag) ){ + return pBest; + } + return 0; +} + +/* +** Free all resources held by the schema structure. The void* argument points +** at a Schema struct. This function does not call sqlite3DbFree(db, ) on the +** pointer itself, it just cleans up subsiduary resources (i.e. the contents +** of the schema hash tables). +** +** The Schema.cache_size variable is not cleared. +*/ +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(0, (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(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(sqlite3 *db, Btree *pBt){ + Schema * p; + if( pBt ){ + p = (Schema *)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaFree); + }else{ + p = (Schema *)sqlite3MallocZero(sizeof(Schema)); + } + if( !p ){ + db->mallocFailed = 1; + }else if ( 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); + p->enc = SQLITE_UTF8; + } + return p; +} diff --git a/third_party/sqlite/src/complete.c b/third_party/sqlite/src/complete.c new file mode 100755 index 0000000..8e2dbc2 --- /dev/null +++ b/third_party/sqlite/src/complete.c @@ -0,0 +1,277 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** An tokenizer for SQL +** +** This file contains C code that implements the sqlite3_complete() API. +** This code used to be part of the tokenizer.c source file. But by +** separating it out, the code will be automatically omitted from +** static links that do not use it. +** +** $Id: complete.c,v 1.7 2008/06/13 18:24:27 drh Exp $ +*/ +#include "sqliteInt.h" +#ifndef SQLITE_OMIT_COMPLETE + +/* +** This is defined in tokenize.c. We just have to import the definition. +*/ +#ifndef SQLITE_AMALGAMATION +#ifdef SQLITE_ASCII +extern const char sqlite3IsAsciiIdChar[]; +#define IdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && sqlite3IsAsciiIdChar[c-0x20])) +#endif +#ifdef SQLITE_EBCDIC +extern const char sqlite3IsEbcdicIdChar[]; +#define IdChar(C) (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40])) +#endif +#endif /* SQLITE_AMALGAMATION */ + + +/* +** Token types used by the sqlite3_complete() routine. See the header +** comments on that procedure for additional information. +*/ +#define tkSEMI 0 +#define tkWS 1 +#define tkOTHER 2 +#define tkEXPLAIN 3 +#define tkCREATE 4 +#define tkTEMP 5 +#define tkTRIGGER 6 +#define tkEND 7 + +/* +** Return TRUE if the given SQL string ends in a semicolon. +** +** Special handling is require for CREATE TRIGGER statements. +** Whenever the CREATE TRIGGER keywords are seen, the statement +** must end with ";END;". +** +** This implementation uses a state machine with 7 states: +** +** (0) START At the beginning or end of an SQL statement. This routine +** returns 1 if it ends in the START state and 0 if it ends +** in any other state. +** +** (1) NORMAL We are in the middle of statement which ends with a single +** semicolon. +** +** (2) EXPLAIN The keyword EXPLAIN has been seen at the beginning of +** a statement. +** +** (3) CREATE The keyword CREATE has been seen at the beginning of a +** statement, possibly preceeded by EXPLAIN and/or followed by +** TEMP or TEMPORARY +** +** (4) TRIGGER We are in the middle of a trigger definition that must be +** ended by a semicolon, the keyword END, and another semicolon. +** +** (5) SEMI We've seen the first semicolon in the ";END;" that occurs at +** the end of a trigger definition. +** +** (6) END We've seen the ";END" of the ";END;" that occurs at the end +** of a trigger difinition. +** +** Transitions between states above are determined by tokens extracted +** from the input. The following tokens are significant: +** +** (0) tkSEMI A semicolon. +** (1) tkWS Whitespace +** (2) tkOTHER Any other SQL token. +** (3) tkEXPLAIN The "explain" keyword. +** (4) tkCREATE The "create" keyword. +** (5) tkTEMP The "temp" or "temporary" keyword. +** (6) tkTRIGGER The "trigger" keyword. +** (7) tkEND The "end" keyword. +** +** Whitespace never causes a state transition and is always ignored. +** +** If we compile with SQLITE_OMIT_TRIGGER, all of the computation needed +** to recognize the end of a trigger can be omitted. All we have to do +** is look for a semicolon that is not part of an string or comment. +*/ +int sqlite3_complete(const char *zSql){ + u8 state = 0; /* Current state, using numbers defined in header comment */ + u8 token; /* Value of the next token */ + +#ifndef SQLITE_OMIT_TRIGGER + /* A complex statement machine used to detect the end of a CREATE TRIGGER + ** statement. This is the normal case. + */ + static const u8 trans[7][8] = { + /* Token: */ + /* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */ + /* 0 START: */ { 0, 0, 1, 2, 3, 1, 1, 1, }, + /* 1 NORMAL: */ { 0, 1, 1, 1, 1, 1, 1, 1, }, + /* 2 EXPLAIN: */ { 0, 2, 1, 1, 3, 1, 1, 1, }, + /* 3 CREATE: */ { 0, 3, 1, 1, 1, 3, 4, 1, }, + /* 4 TRIGGER: */ { 5, 4, 4, 4, 4, 4, 4, 4, }, + /* 5 SEMI: */ { 5, 5, 4, 4, 4, 4, 4, 6, }, + /* 6 END: */ { 0, 6, 4, 4, 4, 4, 4, 4, }, + }; +#else + /* If triggers are not suppored by this compile then the statement machine + ** used to detect the end of a statement is much simplier + */ + static const u8 trans[2][3] = { + /* Token: */ + /* State: ** SEMI WS OTHER */ + /* 0 START: */ { 0, 0, 1, }, + /* 1 NORMAL: */ { 0, 1, 1, }, + }; +#endif /* SQLITE_OMIT_TRIGGER */ + + while( *zSql ){ + switch( *zSql ){ + case ';': { /* A semicolon */ + token = tkSEMI; + break; + } + case ' ': + case '\r': + case '\t': + case '\n': + case '\f': { /* White space is ignored */ + token = tkWS; + break; + } + case '/': { /* C-style comments */ + if( zSql[1]!='*' ){ + token = tkOTHER; + break; + } + zSql += 2; + while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; } + if( zSql[0]==0 ) return 0; + zSql++; + token = tkWS; + break; + } + case '-': { /* SQL-style comments from "--" to end of line */ + if( zSql[1]!='-' ){ + token = tkOTHER; + break; + } + while( *zSql && *zSql!='\n' ){ zSql++; } + if( *zSql==0 ) return state==0; + token = tkWS; + break; + } + case '[': { /* Microsoft-style identifiers in [...] */ + zSql++; + while( *zSql && *zSql!=']' ){ zSql++; } + if( *zSql==0 ) return 0; + token = tkOTHER; + break; + } + case '`': /* Grave-accent quoted symbols used by MySQL */ + case '"': /* single- and double-quoted strings */ + case '\'': { + int c = *zSql; + zSql++; + while( *zSql && *zSql!=c ){ zSql++; } + if( *zSql==0 ) return 0; + token = tkOTHER; + break; + } + default: { + int c; + if( IdChar((u8)*zSql) ){ + /* Keywords and unquoted identifiers */ + int nId; + for(nId=1; IdChar(zSql[nId]); nId++){} +#ifdef SQLITE_OMIT_TRIGGER + token = tkOTHER; +#else + switch( *zSql ){ + case 'c': case 'C': { + if( nId==6 && sqlite3StrNICmp(zSql, "create", 6)==0 ){ + token = tkCREATE; + }else{ + token = tkOTHER; + } + break; + } + case 't': case 'T': { + if( nId==7 && sqlite3StrNICmp(zSql, "trigger", 7)==0 ){ + token = tkTRIGGER; + }else if( nId==4 && sqlite3StrNICmp(zSql, "temp", 4)==0 ){ + token = tkTEMP; + }else if( nId==9 && sqlite3StrNICmp(zSql, "temporary", 9)==0 ){ + token = tkTEMP; + }else{ + token = tkOTHER; + } + break; + } + case 'e': case 'E': { + if( nId==3 && sqlite3StrNICmp(zSql, "end", 3)==0 ){ + token = tkEND; + }else +#ifndef SQLITE_OMIT_EXPLAIN + if( nId==7 && sqlite3StrNICmp(zSql, "explain", 7)==0 ){ + token = tkEXPLAIN; + }else +#endif + { + token = tkOTHER; + } + break; + } + default: { + token = tkOTHER; + break; + } + } +#endif /* SQLITE_OMIT_TRIGGER */ + zSql += nId-1; + }else{ + /* Operators and special symbols */ + token = tkOTHER; + } + break; + } + } + state = trans[state][token]; + zSql++; + } + return state==0; +} + +#ifndef SQLITE_OMIT_UTF16 +/* +** This routine is the same as the sqlite3_complete() routine described +** above, except that the parameter is required to be UTF-16 encoded, not +** UTF-8. +*/ +int sqlite3_complete16(const void *zSql){ + sqlite3_value *pVal; + char const *zSql8; + int rc = SQLITE_NOMEM; + +#ifndef SQLITE_OMIT_AUTOINIT + rc = sqlite3_initialize(); + if( rc ) return rc; +#endif + pVal = sqlite3ValueNew(0); + sqlite3ValueSetStr(pVal, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC); + zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8); + if( zSql8 ){ + rc = sqlite3_complete(zSql8); + }else{ + rc = SQLITE_NOMEM; + } + sqlite3ValueFree(pVal); + return sqlite3ApiExit(0, rc); +} +#endif /* SQLITE_OMIT_UTF16 */ +#endif /* SQLITE_OMIT_COMPLETE */ diff --git a/third_party/sqlite/src/date.c b/third_party/sqlite/src/date.c new file mode 100755 index 0000000..08ee30c --- /dev/null +++ b/third_party/sqlite/src/date.c @@ -0,0 +1,1093 @@ +/* +** 2003 October 31 +** +** 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 the C functions that implement date and time +** functions for SQLite. +** +** There is only one exported symbol in this file - the function +** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. +** All other code has file scope. +** +** $Id: date.c,v 1.87 2008/07/28 19:34:53 drh Exp $ +** +** SQLite processes all times and dates as Julian Day numbers. The +** dates and times are stored as the number of days since noon +** in Greenwich on November 24, 4714 B.C. according to the Gregorian +** calendar system. +** +** 1970-01-01 00:00:00 is JD 2440587.5 +** 2000-01-01 00:00:00 is JD 2451544.5 +** +** This implemention requires years to be expressed as a 4-digit number +** which means that only dates between 0000-01-01 and 9999-12-31 can +** be represented, even though julian day numbers allow a much wider +** range of dates. +** +** The Gregorian calendar system is used for all dates and times, +** even those that predate the Gregorian calendar. Historians usually +** use the Julian calendar for dates prior to 1582-10-15 and for some +** dates afterwards, depending on locale. Beware of this difference. +** +** The conversion algorithms are implemented based on descriptions +** in the following text: +** +** Jean Meeus +** Astronomical Algorithms, 2nd Edition, 1998 +** ISBM 0-943396-61-1 +** Willmann-Bell, Inc +** Richmond, Virginia (USA) +*/ +#include "sqliteInt.h" +#include <ctype.h> +#include <stdlib.h> +#include <assert.h> +#include <time.h> + +#ifndef SQLITE_OMIT_DATETIME_FUNCS + +/* +** On recent Windows platforms, the localtime_s() function is available +** as part of the "Secure CRT". It is essentially equivalent to +** localtime_r() available under most POSIX platforms, except that the +** order of the parameters is reversed. +** +** See http://msdn.microsoft.com/en-us/library/a442x3ye(VS.80).aspx. +** +** If the user has not indicated to use localtime_r() or localtime_s() +** already, check for an MSVC build environment that provides +** localtime_s(). +*/ +#if !defined(HAVE_LOCALTIME_R) && !defined(HAVE_LOCALTIME_S) && \ + defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE) +#define HAVE_LOCALTIME_S 1 +#endif + +/* +** A structure for holding a single date and time. +*/ +typedef struct DateTime DateTime; +struct DateTime { + sqlite3_int64 iJD; /* The julian day number times 86400000 */ + int Y, M, D; /* Year, month, and day */ + int h, m; /* Hour and minutes */ + int tz; /* Timezone offset in minutes */ + double s; /* Seconds */ + char validYMD; /* True if Y,M,D are valid */ + char validHMS; /* True if h,m,s are valid */ + char validJD; /* True if iJD is valid */ + char validTZ; /* True if tz is valid */ +}; + + +/* +** Convert zDate into one or more integers. Additional arguments +** come in groups of 5 as follows: +** +** N number of digits in the integer +** min minimum allowed value of the integer +** max maximum allowed value of the integer +** nextC first character after the integer +** pVal where to write the integers value. +** +** Conversions continue until one with nextC==0 is encountered. +** The function returns the number of successful conversions. +*/ +static int getDigits(const char *zDate, ...){ + va_list ap; + int val; + int N; + int min; + int max; + int nextC; + int *pVal; + int cnt = 0; + va_start(ap, zDate); + do{ + N = va_arg(ap, int); + min = va_arg(ap, int); + max = va_arg(ap, int); + nextC = va_arg(ap, int); + pVal = va_arg(ap, int*); + val = 0; + while( N-- ){ + if( !isdigit(*(u8*)zDate) ){ + goto end_getDigits; + } + val = val*10 + *zDate - '0'; + zDate++; + } + if( val<min || val>max || (nextC!=0 && nextC!=*zDate) ){ + goto end_getDigits; + } + *pVal = val; + zDate++; + cnt++; + }while( nextC ); +end_getDigits: + va_end(ap); + return cnt; +} + +/* +** Read text from z[] and convert into a floating point number. Return +** the number of digits converted. +*/ +#define getValue sqlite3AtoF + +/* +** Parse a timezone extension on the end of a date-time. +** The extension is of the form: +** +** (+/-)HH:MM +** +** Or the "zulu" notation: +** +** Z +** +** If the parse is successful, write the number of minutes +** of change in p->tz and return 0. If a parser error occurs, +** return non-zero. +** +** A missing specifier is not considered an error. +*/ +static int parseTimezone(const char *zDate, DateTime *p){ + int sgn = 0; + int nHr, nMn; + int c; + while( isspace(*(u8*)zDate) ){ zDate++; } + p->tz = 0; + c = *zDate; + if( c=='-' ){ + sgn = -1; + }else if( c=='+' ){ + sgn = +1; + }else if( c=='Z' || c=='z' ){ + zDate++; + goto zulu_time; + }else{ + return c!=0; + } + zDate++; + if( getDigits(zDate, 2, 0, 14, ':', &nHr, 2, 0, 59, 0, &nMn)!=2 ){ + return 1; + } + zDate += 5; + p->tz = sgn*(nMn + nHr*60); +zulu_time: + while( isspace(*(u8*)zDate) ){ zDate++; } + return *zDate!=0; +} + +/* +** Parse times of the form HH:MM or HH:MM:SS or HH:MM:SS.FFFF. +** The HH, MM, and SS must each be exactly 2 digits. The +** fractional seconds FFFF can be one or more digits. +** +** Return 1 if there is a parsing error and 0 on success. +*/ +static int parseHhMmSs(const char *zDate, DateTime *p){ + int h, m, s; + double ms = 0.0; + if( getDigits(zDate, 2, 0, 24, ':', &h, 2, 0, 59, 0, &m)!=2 ){ + return 1; + } + zDate += 5; + if( *zDate==':' ){ + zDate++; + if( getDigits(zDate, 2, 0, 59, 0, &s)!=1 ){ + return 1; + } + zDate += 2; + if( *zDate=='.' && isdigit((u8)zDate[1]) ){ + double rScale = 1.0; + zDate++; + while( isdigit(*(u8*)zDate) ){ + ms = ms*10.0 + *zDate - '0'; + rScale *= 10.0; + zDate++; + } + ms /= rScale; + } + }else{ + s = 0; + } + p->validJD = 0; + p->validHMS = 1; + p->h = h; + p->m = m; + p->s = s + ms; + if( parseTimezone(zDate, p) ) return 1; + p->validTZ = p->tz!=0; + return 0; +} + +/* +** Convert from YYYY-MM-DD HH:MM:SS to julian day. We always assume +** that the YYYY-MM-DD is according to the Gregorian calendar. +** +** Reference: Meeus page 61 +*/ +static void computeJD(DateTime *p){ + int Y, M, D, A, B, X1, X2; + + if( p->validJD ) return; + if( p->validYMD ){ + Y = p->Y; + M = p->M; + D = p->D; + }else{ + Y = 2000; /* If no YMD specified, assume 2000-Jan-01 */ + M = 1; + D = 1; + } + if( M<=2 ){ + Y--; + M += 12; + } + A = Y/100; + B = 2 - A + (A/4); + X1 = 365.25*(Y+4716); + X2 = 30.6001*(M+1); + p->iJD = (X1 + X2 + D + B - 1524.5)*86400000; + p->validJD = 1; + if( p->validHMS ){ + p->iJD += p->h*3600000 + p->m*60000 + p->s*1000; + if( p->validTZ ){ + p->iJD -= p->tz*60000; + p->validYMD = 0; + p->validHMS = 0; + p->validTZ = 0; + } + } +} + +/* +** Parse dates of the form +** +** YYYY-MM-DD HH:MM:SS.FFF +** YYYY-MM-DD HH:MM:SS +** YYYY-MM-DD HH:MM +** YYYY-MM-DD +** +** Write the result into the DateTime structure and return 0 +** on success and 1 if the input string is not a well-formed +** date. +*/ +static int parseYyyyMmDd(const char *zDate, DateTime *p){ + int Y, M, D, neg; + + if( zDate[0]=='-' ){ + zDate++; + neg = 1; + }else{ + neg = 0; + } + if( getDigits(zDate,4,0,9999,'-',&Y,2,1,12,'-',&M,2,1,31,0,&D)!=3 ){ + return 1; + } + zDate += 10; + while( isspace(*(u8*)zDate) || 'T'==*(u8*)zDate ){ zDate++; } + if( parseHhMmSs(zDate, p)==0 ){ + /* We got the time */ + }else if( *zDate==0 ){ + p->validHMS = 0; + }else{ + return 1; + } + p->validJD = 0; + p->validYMD = 1; + p->Y = neg ? -Y : Y; + p->M = M; + p->D = D; + if( p->validTZ ){ + computeJD(p); + } + return 0; +} + +/* +** Set the time to the current time reported by the VFS +*/ +static void setDateTimeToCurrent(sqlite3_context *context, DateTime *p){ + double r; + sqlite3 *db = sqlite3_context_db_handle(context); + sqlite3OsCurrentTime(db->pVfs, &r); + p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5); + p->validJD = 1; +} + +/* +** Attempt to parse the given string into a Julian Day Number. Return +** the number of errors. +** +** The following are acceptable forms for the input string: +** +** YYYY-MM-DD HH:MM:SS.FFF +/-HH:MM +** DDDD.DD +** now +** +** In the first form, the +/-HH:MM is always optional. The fractional +** seconds extension (the ".FFF") is optional. The seconds portion +** (":SS.FFF") is option. The year and date can be omitted as long +** as there is a time string. The time string can be omitted as long +** as there is a year and date. +*/ +static int parseDateOrTime( + sqlite3_context *context, + const char *zDate, + DateTime *p +){ + if( parseYyyyMmDd(zDate,p)==0 ){ + return 0; + }else if( parseHhMmSs(zDate, p)==0 ){ + return 0; + }else if( sqlite3StrICmp(zDate,"now")==0){ + setDateTimeToCurrent(context, p); + return 0; + }else if( sqlite3IsNumber(zDate, 0, SQLITE_UTF8) ){ + double r; + getValue(zDate, &r); + p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5); + p->validJD = 1; + return 0; + } + return 1; +} + +/* +** Compute the Year, Month, and Day from the julian day number. +*/ +static void computeYMD(DateTime *p){ + int Z, A, B, C, D, E, X1; + if( p->validYMD ) return; + if( !p->validJD ){ + p->Y = 2000; + p->M = 1; + p->D = 1; + }else{ + Z = (p->iJD + 43200000)/86400000; + A = (Z - 1867216.25)/36524.25; + A = Z + 1 + A - (A/4); + B = A + 1524; + C = (B - 122.1)/365.25; + D = 365.25*C; + E = (B-D)/30.6001; + X1 = 30.6001*E; + p->D = B - D - X1; + p->M = E<14 ? E-1 : E-13; + p->Y = p->M>2 ? C - 4716 : C - 4715; + } + p->validYMD = 1; +} + +/* +** Compute the Hour, Minute, and Seconds from the julian day number. +*/ +static void computeHMS(DateTime *p){ + int s; + if( p->validHMS ) return; + computeJD(p); + s = (p->iJD + 43200000) % 86400000; + p->s = s/1000.0; + s = p->s; + p->s -= s; + p->h = s/3600; + s -= p->h*3600; + p->m = s/60; + p->s += s - p->m*60; + p->validHMS = 1; +} + +/* +** Compute both YMD and HMS +*/ +static void computeYMD_HMS(DateTime *p){ + computeYMD(p); + computeHMS(p); +} + +/* +** Clear the YMD and HMS and the TZ +*/ +static void clearYMD_HMS_TZ(DateTime *p){ + p->validYMD = 0; + p->validHMS = 0; + p->validTZ = 0; +} + +#ifndef SQLITE_OMIT_LOCALTIME +/* +** Compute the difference (in milliseconds) +** between localtime and UTC (a.k.a. GMT) +** for the time value p where p is in UTC. +*/ +static int localtimeOffset(DateTime *p){ + DateTime x, y; + time_t t; + x = *p; + computeYMD_HMS(&x); + if( x.Y<1971 || x.Y>=2038 ){ + x.Y = 2000; + x.M = 1; + x.D = 1; + x.h = 0; + x.m = 0; + x.s = 0.0; + } else { + int s = x.s + 0.5; + x.s = s; + } + x.tz = 0; + x.validJD = 0; + computeJD(&x); + t = x.iJD/1000 - 2440587.5*86400.0; +#ifdef HAVE_LOCALTIME_R + { + struct tm sLocal; + localtime_r(&t, &sLocal); + y.Y = sLocal.tm_year + 1900; + y.M = sLocal.tm_mon + 1; + y.D = sLocal.tm_mday; + y.h = sLocal.tm_hour; + y.m = sLocal.tm_min; + y.s = sLocal.tm_sec; + } +#elif defined(HAVE_LOCALTIME_S) + { + struct tm sLocal; + localtime_s(&sLocal, &t); + y.Y = sLocal.tm_year + 1900; + y.M = sLocal.tm_mon + 1; + y.D = sLocal.tm_mday; + y.h = sLocal.tm_hour; + y.m = sLocal.tm_min; + y.s = sLocal.tm_sec; + } +#else + { + struct tm *pTm; + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); + pTm = localtime(&t); + y.Y = pTm->tm_year + 1900; + y.M = pTm->tm_mon + 1; + y.D = pTm->tm_mday; + y.h = pTm->tm_hour; + y.m = pTm->tm_min; + y.s = pTm->tm_sec; + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); + } +#endif + y.validYMD = 1; + y.validHMS = 1; + y.validJD = 0; + y.validTZ = 0; + computeJD(&y); + return y.iJD - x.iJD; +} +#endif /* SQLITE_OMIT_LOCALTIME */ + +/* +** Process a modifier to a date-time stamp. The modifiers are +** as follows: +** +** NNN days +** NNN hours +** NNN minutes +** NNN.NNNN seconds +** NNN months +** NNN years +** start of month +** start of year +** start of week +** start of day +** weekday N +** unixepoch +** localtime +** utc +** +** Return 0 on success and 1 if there is any kind of error. +*/ +static int parseModifier(const char *zMod, DateTime *p){ + int rc = 1; + int n; + double r; + char *z, zBuf[30]; + z = zBuf; + for(n=0; n<sizeof(zBuf)-1 && zMod[n]; n++){ + z[n] = tolower(zMod[n]); + } + z[n] = 0; + switch( z[0] ){ +#ifndef SQLITE_OMIT_LOCALTIME + case 'l': { + /* localtime + ** + ** Assuming the current time value is UTC (a.k.a. GMT), shift it to + ** show local time. + */ + if( strcmp(z, "localtime")==0 ){ + computeJD(p); + p->iJD += localtimeOffset(p); + clearYMD_HMS_TZ(p); + rc = 0; + } + break; + } +#endif + case 'u': { + /* + ** unixepoch + ** + ** Treat the current value of p->iJD as the number of + ** seconds since 1970. Convert to a real julian day number. + */ + if( strcmp(z, "unixepoch")==0 && p->validJD ){ + p->iJD = p->iJD/86400.0 + 2440587.5*86400000.0; + clearYMD_HMS_TZ(p); + rc = 0; + } +#ifndef SQLITE_OMIT_LOCALTIME + else if( strcmp(z, "utc")==0 ){ + double c1; + computeJD(p); + c1 = localtimeOffset(p); + p->iJD -= c1; + clearYMD_HMS_TZ(p); + p->iJD += c1 - localtimeOffset(p); + rc = 0; + } +#endif + break; + } + case 'w': { + /* + ** weekday N + ** + ** Move the date to the same time on the next occurrence of + ** weekday N where 0==Sunday, 1==Monday, and so forth. If the + ** date is already on the appropriate weekday, this is a no-op. + */ + if( strncmp(z, "weekday ", 8)==0 && getValue(&z[8],&r)>0 + && (n=r)==r && n>=0 && r<7 ){ + sqlite3_int64 Z; + computeYMD_HMS(p); + p->validTZ = 0; + p->validJD = 0; + computeJD(p); + Z = ((p->iJD + 129600000)/86400000) % 7; + if( Z>n ) Z -= 7; + p->iJD += (n - Z)*86400000; + clearYMD_HMS_TZ(p); + rc = 0; + } + break; + } + case 's': { + /* + ** start of TTTTT + ** + ** Move the date backwards to the beginning of the current day, + ** or month or year. + */ + if( strncmp(z, "start of ", 9)!=0 ) break; + z += 9; + computeYMD(p); + p->validHMS = 1; + p->h = p->m = 0; + p->s = 0.0; + p->validTZ = 0; + p->validJD = 0; + if( strcmp(z,"month")==0 ){ + p->D = 1; + rc = 0; + }else if( strcmp(z,"year")==0 ){ + computeYMD(p); + p->M = 1; + p->D = 1; + rc = 0; + }else if( strcmp(z,"day")==0 ){ + rc = 0; + } + break; + } + case '+': + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + n = getValue(z, &r); + assert( n>=1 ); + if( z[n]==':' ){ + /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the + ** specified number of hours, minutes, seconds, and fractional seconds + ** to the time. The ".FFF" may be omitted. The ":SS.FFF" may be + ** omitted. + */ + const char *z2 = z; + DateTime tx; + sqlite3_int64 day; + if( !isdigit(*(u8*)z2) ) z2++; + memset(&tx, 0, sizeof(tx)); + if( parseHhMmSs(z2, &tx) ) break; + computeJD(&tx); + tx.iJD -= 43200000; + day = tx.iJD/86400000; + tx.iJD -= day*86400000; + if( z[0]=='-' ) tx.iJD = -tx.iJD; + computeJD(p); + clearYMD_HMS_TZ(p); + p->iJD += tx.iJD; + rc = 0; + break; + } + z += n; + while( isspace(*(u8*)z) ) z++; + n = strlen(z); + if( n>10 || n<3 ) break; + if( z[n-1]=='s' ){ z[n-1] = 0; n--; } + computeJD(p); + rc = 0; + if( n==3 && strcmp(z,"day")==0 ){ + p->iJD += r*86400000.0 + 0.5; + }else if( n==4 && strcmp(z,"hour")==0 ){ + p->iJD += r*(86400000.0/24.0) + 0.5; + }else if( n==6 && strcmp(z,"minute")==0 ){ + p->iJD += r*(86400000.0/(24.0*60.0)) + 0.5; + }else if( n==6 && strcmp(z,"second")==0 ){ + p->iJD += r*(86400000.0/(24.0*60.0*60.0)) + 0.5; + }else if( n==5 && strcmp(z,"month")==0 ){ + int x, y; + computeYMD_HMS(p); + p->M += r; + x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12; + p->Y += x; + p->M -= x*12; + p->validJD = 0; + computeJD(p); + y = r; + if( y!=r ){ + p->iJD += (r - y)*30.0*86400000.0 + 0.5; + } + }else if( n==4 && strcmp(z,"year")==0 ){ + computeYMD_HMS(p); + p->Y += r; + p->validJD = 0; + computeJD(p); + }else{ + rc = 1; + } + clearYMD_HMS_TZ(p); + break; + } + default: { + break; + } + } + return rc; +} + +/* +** Process time function arguments. argv[0] is a date-time stamp. +** argv[1] and following are modifiers. Parse them all and write +** the resulting time into the DateTime structure p. Return 0 +** on success and 1 if there are any errors. +** +** If there are zero parameters (if even argv[0] is undefined) +** then assume a default value of "now" for argv[0]. +*/ +static int isDate( + sqlite3_context *context, + int argc, + sqlite3_value **argv, + DateTime *p +){ + int i; + const unsigned char *z; + int eType; + memset(p, 0, sizeof(*p)); + if( argc==0 ){ + setDateTimeToCurrent(context, p); + }else if( (eType = sqlite3_value_type(argv[0]))==SQLITE_FLOAT + || eType==SQLITE_INTEGER ){ + p->iJD = sqlite3_value_double(argv[0])*86400000.0 + 0.5; + p->validJD = 1; + }else{ + z = sqlite3_value_text(argv[0]); + if( !z || parseDateOrTime(context, (char*)z, p) ){ + return 1; + } + } + for(i=1; i<argc; i++){ + if( (z = sqlite3_value_text(argv[i]))==0 || parseModifier((char*)z, p) ){ + return 1; + } + } + return 0; +} + + +/* +** The following routines implement the various date and time functions +** of SQLite. +*/ + +/* +** julianday( TIMESTRING, MOD, MOD, ...) +** +** Return the julian day number of the date specified in the arguments +*/ +static void juliandayFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + DateTime x; + if( isDate(context, argc, argv, &x)==0 ){ + computeJD(&x); + sqlite3_result_double(context, x.iJD/86400000.0); + } +} + +/* +** datetime( TIMESTRING, MOD, MOD, ...) +** +** Return YYYY-MM-DD HH:MM:SS +*/ +static void datetimeFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + DateTime x; + if( isDate(context, argc, argv, &x)==0 ){ + char zBuf[100]; + computeYMD_HMS(&x); + sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d %02d:%02d:%02d", + x.Y, x.M, x.D, x.h, x.m, (int)(x.s)); + sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); + } +} + +/* +** time( TIMESTRING, MOD, MOD, ...) +** +** Return HH:MM:SS +*/ +static void timeFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + DateTime x; + if( isDate(context, argc, argv, &x)==0 ){ + char zBuf[100]; + computeHMS(&x); + sqlite3_snprintf(sizeof(zBuf), zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s); + sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); + } +} + +/* +** date( TIMESTRING, MOD, MOD, ...) +** +** Return YYYY-MM-DD +*/ +static void dateFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + DateTime x; + if( isDate(context, argc, argv, &x)==0 ){ + char zBuf[100]; + computeYMD(&x); + sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D); + sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); + } +} + +/* +** strftime( FORMAT, TIMESTRING, MOD, MOD, ...) +** +** Return a string described by FORMAT. Conversions as follows: +** +** %d day of month +** %f ** fractional seconds SS.SSS +** %H hour 00-24 +** %j day of year 000-366 +** %J ** Julian day number +** %m month 01-12 +** %M minute 00-59 +** %s seconds since 1970-01-01 +** %S seconds 00-59 +** %w day of week 0-6 sunday==0 +** %W week of year 00-53 +** %Y year 0000-9999 +** %% % +*/ +static void strftimeFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + DateTime x; + u64 n; + int i, j; + char *z; + sqlite3 *db; + const char *zFmt = (const char*)sqlite3_value_text(argv[0]); + char zBuf[100]; + if( zFmt==0 || isDate(context, argc-1, argv+1, &x) ) return; + db = sqlite3_context_db_handle(context); + for(i=0, n=1; zFmt[i]; i++, n++){ + if( zFmt[i]=='%' ){ + switch( zFmt[i+1] ){ + case 'd': + case 'H': + case 'm': + case 'M': + case 'S': + case 'W': + n++; + /* fall thru */ + case 'w': + case '%': + break; + case 'f': + n += 8; + break; + case 'j': + n += 3; + break; + case 'Y': + n += 8; + break; + case 's': + case 'J': + n += 50; + break; + default: + return; /* ERROR. return a NULL */ + } + i++; + } + } + if( n<sizeof(zBuf) ){ + z = zBuf; + }else if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + sqlite3_result_error_toobig(context); + return; + }else{ + z = sqlite3DbMallocRaw(db, n); + if( z==0 ){ + sqlite3_result_error_nomem(context); + return; + } + } + computeJD(&x); + computeYMD_HMS(&x); + for(i=j=0; zFmt[i]; i++){ + if( zFmt[i]!='%' ){ + z[j++] = zFmt[i]; + }else{ + i++; + switch( zFmt[i] ){ + case 'd': sqlite3_snprintf(3, &z[j],"%02d",x.D); j+=2; break; + case 'f': { + double s = x.s; + if( s>59.999 ) s = 59.999; + sqlite3_snprintf(7, &z[j],"%06.3f", s); + j += strlen(&z[j]); + break; + } + case 'H': sqlite3_snprintf(3, &z[j],"%02d",x.h); j+=2; break; + case 'W': /* Fall thru */ + case 'j': { + int nDay; /* Number of days since 1st day of year */ + DateTime y = x; + y.validJD = 0; + y.M = 1; + y.D = 1; + computeJD(&y); + nDay = (x.iJD - y.iJD)/86400000.0 + 0.5; + if( zFmt[i]=='W' ){ + int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */ + wd = ((x.iJD+43200000)/86400000) % 7; + sqlite3_snprintf(3, &z[j],"%02d",(nDay+7-wd)/7); + j += 2; + }else{ + sqlite3_snprintf(4, &z[j],"%03d",nDay+1); + j += 3; + } + break; + } + case 'J': { + sqlite3_snprintf(20, &z[j],"%.16g",x.iJD/86400000.0); + j+=strlen(&z[j]); + break; + } + case 'm': sqlite3_snprintf(3, &z[j],"%02d",x.M); j+=2; break; + case 'M': sqlite3_snprintf(3, &z[j],"%02d",x.m); j+=2; break; + case 's': { + sqlite3_snprintf(30,&z[j],"%d", + (int)(x.iJD/1000.0 - 210866760000.0)); + j += strlen(&z[j]); + break; + } + case 'S': sqlite3_snprintf(3,&z[j],"%02d",(int)x.s); j+=2; break; + case 'w': z[j++] = (((x.iJD+129600000)/86400000) % 7) + '0'; break; + case 'Y': sqlite3_snprintf(5,&z[j],"%04d",x.Y); j+=strlen(&z[j]);break; + default: z[j++] = '%'; break; + } + } + } + z[j] = 0; + sqlite3_result_text(context, z, -1, + z==zBuf ? SQLITE_TRANSIENT : SQLITE_DYNAMIC); +} + +/* +** current_time() +** +** This function returns the same value as time('now'). +*/ +static void ctimeFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + timeFunc(context, 0, 0); +} + +/* +** current_date() +** +** This function returns the same value as date('now'). +*/ +static void cdateFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + dateFunc(context, 0, 0); +} + +/* +** current_timestamp() +** +** This function returns the same value as datetime('now'). +*/ +static void ctimestampFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + datetimeFunc(context, 0, 0); +} +#endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */ + +#ifdef SQLITE_OMIT_DATETIME_FUNCS +/* +** If the library is compiled to omit the full-scale date and time +** handling (to get a smaller binary), the following minimal version +** of the functions current_time(), current_date() and current_timestamp() +** are included instead. This is to support column declarations that +** include "DEFAULT CURRENT_TIME" etc. +** +** This function uses the C-library functions time(), gmtime() +** and strftime(). The format string to pass to strftime() is supplied +** as the user-data for the function. +*/ +static void currentTimeFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + time_t t; + char *zFormat = (char *)sqlite3_user_data(context); + sqlite3 *db; + double rT; + char zBuf[20]; + + db = sqlite3_context_db_handle(context); + sqlite3OsCurrentTime(db->pVfs, &rT); + t = 86400.0*(rT - 2440587.5) + 0.5; +#ifdef HAVE_GMTIME_R + { + struct tm sNow; + gmtime_r(&t, &sNow); + strftime(zBuf, 20, zFormat, &sNow); + } +#else + { + struct tm *pTm; + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); + pTm = gmtime(&t); + strftime(zBuf, 20, zFormat, pTm); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); + } +#endif + + sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); +} +#endif + +/* +** This function registered all of the above C functions as SQL +** functions. This should be the only routine in this file with +** external linkage. +*/ +void sqlite3RegisterDateTimeFunctions(sqlite3 *db){ +#ifndef SQLITE_OMIT_DATETIME_FUNCS + static const struct { + char *zName; + int nArg; + void (*xFunc)(sqlite3_context*,int,sqlite3_value**); + } aFuncs[] = { + { "julianday", -1, juliandayFunc }, + { "date", -1, dateFunc }, + { "time", -1, timeFunc }, + { "datetime", -1, datetimeFunc }, + { "strftime", -1, strftimeFunc }, + { "current_time", 0, ctimeFunc }, + { "current_timestamp", 0, ctimestampFunc }, + { "current_date", 0, cdateFunc }, + }; + int i; + + for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ + sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg, + SQLITE_UTF8, 0, aFuncs[i].xFunc, 0, 0); + } +#else + static const struct { + char *zName; + char *zFormat; + } aFuncs[] = { + { "current_time", "%H:%M:%S" }, + { "current_date", "%Y-%m-%d" }, + { "current_timestamp", "%Y-%m-%d %H:%M:%S" } + }; + int i; + + for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ + sqlite3CreateFunc(db, aFuncs[i].zName, 0, SQLITE_UTF8, + aFuncs[i].zFormat, currentTimeFunc, 0, 0); + } +#endif +} diff --git a/third_party/sqlite/src/delete.c b/third_party/sqlite/src/delete.c new file mode 100755 index 0000000..2682424 --- /dev/null +++ b/third_party/sqlite/src/delete.c @@ -0,0 +1,544 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains C code routines that are called by the parser +** in order to generate code for DELETE FROM statements. +** +** $Id: delete.c,v 1.171 2008/07/28 19:34:53 drh Exp $ +*/ +#include "sqliteInt.h" + +/* +** Look up every table that is named in pSrc. If any table is not found, +** add an error message to pParse->zErrMsg and return NULL. If all tables +** are found, return a pointer to the last table. +*/ +Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){ + Table *pTab = 0; + int i; + struct SrcList_item *pItem; + for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){ + pTab = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase); + sqlite3DeleteTable(pItem->pTab); + pItem->pTab = pTab; + if( pTab ){ + pTab->nRef++; + } + } + return pTab; +} + +/* +** Check to make sure the given table is writable. If it is not +** writable, generate an error message and return 1. If it is +** writable return 0; +*/ +int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){ + if( (pTab->readOnly && (pParse->db->flags & SQLITE_WriteSchema)==0 + && pParse->nested==0) +#ifndef SQLITE_OMIT_VIRTUALTABLE + || (pTab->pMod && pTab->pMod->pModule->xUpdate==0) +#endif + ){ + sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName); + return 1; + } +#ifndef SQLITE_OMIT_VIEW + if( !viewOk && pTab->pSelect ){ + sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName); + return 1; + } +#endif + return 0; +} + +/* +** Generate code that will open a table for reading. +*/ +void sqlite3OpenTable( + Parse *p, /* Generate code into this VDBE */ + int iCur, /* The cursor number of the table */ + int iDb, /* The database index in sqlite3.aDb[] */ + Table *pTab, /* The table to be opened */ + int opcode /* OP_OpenRead or OP_OpenWrite */ +){ + Vdbe *v; + if( IsVirtual(pTab) ) return; + v = sqlite3GetVdbe(p); + assert( opcode==OP_OpenWrite || opcode==OP_OpenRead ); + sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite), pTab->zName); + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol); + sqlite3VdbeAddOp3(v, opcode, iCur, pTab->tnum, iDb); + VdbeComment((v, "%s", pTab->zName)); +} + + +#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) +/* +** Evaluate a view and store its result in an ephemeral table. The +** pWhere argument is an optional WHERE clause that restricts the +** set of rows in the view that are to be added to the ephemeral table. +*/ +void sqlite3MaterializeView( + Parse *pParse, /* Parsing context */ + Select *pView, /* View definition */ + Expr *pWhere, /* Optional WHERE clause to be added */ + int iCur /* Cursor number for ephemerial table */ +){ + SelectDest dest; + Select *pDup; + sqlite3 *db = pParse->db; + + pDup = sqlite3SelectDup(db, pView); + if( pWhere ){ + SrcList *pFrom; + + pWhere = sqlite3ExprDup(db, pWhere); + pFrom = sqlite3SrcListAppendFromTerm(pParse, 0, 0, 0, 0, pDup, 0, 0); + pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0); + } + sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur); + sqlite3Select(pParse, pDup, &dest, 0, 0, 0); + sqlite3SelectDelete(db, pDup); +} +#endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */ + + +/* +** Generate code for a DELETE FROM statement. +** +** DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL; +** \________/ \________________/ +** pTabList pWhere +*/ +void sqlite3DeleteFrom( + Parse *pParse, /* The parser context */ + SrcList *pTabList, /* The table from which we should delete things */ + Expr *pWhere /* The WHERE clause. May be null */ +){ + Vdbe *v; /* The virtual database engine */ + Table *pTab; /* The table from which records will be deleted */ + const char *zDb; /* Name of database holding pTab */ + int end, addr = 0; /* A couple addresses of generated code */ + int i; /* Loop counter */ + WhereInfo *pWInfo; /* Information about the WHERE clause */ + Index *pIdx; /* For looping over indices of the table */ + int iCur; /* VDBE Cursor number for pTab */ + sqlite3 *db; /* Main database structure */ + 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; /* Database number */ + int memCnt = 0; /* Memory cell used for change counting */ + +#ifndef SQLITE_OMIT_TRIGGER + int isView; /* True if attempting to delete from a view */ + int triggers_exist = 0; /* True if any triggers exist */ +#endif + int iBeginAfterTrigger; /* Address of after trigger program */ + int iEndAfterTrigger; /* Exit of after trigger program */ + int iBeginBeforeTrigger; /* Address of before trigger program */ + int iEndBeforeTrigger; /* Exit of before trigger program */ + u32 old_col_mask = 0; /* Mask of OLD.* columns in use */ + + sContext.pParse = 0; + db = pParse->db; + if( pParse->nErr || db->mallocFailed ){ + goto delete_from_cleanup; + } + assert( pTabList->nSrc==1 ); + + /* Locate the table which we want to delete. This table has to be + ** put in an SrcList structure because some of the subroutines we + ** will be calling are designed to work with multiple tables and expect + ** an SrcList* parameter instead of just a Table* parameter. + */ + pTab = sqlite3SrcListLookup(pParse, pTabList); + if( pTab==0 ) goto delete_from_cleanup; + + /* Figure out if we have any triggers and if the table being + ** deleted from is a view + */ +#ifndef SQLITE_OMIT_TRIGGER + triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0); + isView = pTab->pSelect!=0; +#else +# define triggers_exist 0 +# define isView 0 +#endif +#ifdef SQLITE_OMIT_VIEW +# undef isView +# define isView 0 +#endif + + if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){ + goto delete_from_cleanup; + } + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + assert( iDb<db->nDb ); + zDb = db->aDb[iDb].zName; + if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){ + goto delete_from_cleanup; + } + + /* If pTab is really a view, make sure it has been initialized. + */ + if( sqlite3ViewGetColumnNames(pParse, pTab) ){ + goto delete_from_cleanup; + } + + /* Allocate a cursor used to store the old.* data for a trigger. + */ + if( triggers_exist ){ + oldIdx = pParse->nTab++; + } + + /* Assign cursor number to the table and all its indices. + */ + assert( pTabList->nSrc==1 ); + iCur = pTabList->a[0].iCursor = pParse->nTab++; + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + pParse->nTab++; + } + + /* Start the view context + */ + if( isView ){ + sqlite3AuthContextPush(pParse, &sContext, pTab->zName); + } + + /* Begin generating code. + */ + v = sqlite3GetVdbe(pParse); + if( v==0 ){ + goto delete_from_cleanup; + } + if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); + sqlite3BeginWriteOperation(pParse, triggers_exist, iDb); + + if( triggers_exist ){ + int orconf = ((pParse->trigStack)?pParse->trigStack->orconf:OE_Default); + int iGoto = sqlite3VdbeAddOp0(v, OP_Goto); + addr = sqlite3VdbeMakeLabel(v); + + iBeginBeforeTrigger = sqlite3VdbeCurrentAddr(v); + (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_BEFORE, pTab, + -1, oldIdx, orconf, addr, &old_col_mask, 0); + iEndBeforeTrigger = sqlite3VdbeAddOp0(v, OP_Goto); + + iBeginAfterTrigger = sqlite3VdbeCurrentAddr(v); + (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_AFTER, pTab, -1, + oldIdx, orconf, addr, &old_col_mask, 0); + iEndAfterTrigger = sqlite3VdbeAddOp0(v, OP_Goto); + + sqlite3VdbeJumpHere(v, iGoto); + } + + /* If we are trying to delete from a view, realize that view into + ** a ephemeral table. + */ + if( isView ){ + sqlite3MaterializeView(pParse, pTab->pSelect, pWhere, iCur); + } + + /* Resolve the column names in the WHERE clause. + */ + memset(&sNC, 0, sizeof(sNC)); + sNC.pParse = pParse; + sNC.pSrcList = pTabList; + if( sqlite3ExprResolveNames(&sNC, pWhere) ){ + goto delete_from_cleanup; + } + + /* Initialize the counter of the number of rows deleted, if + ** we are counting rows. + */ + if( db->flags & SQLITE_CountRows ){ + memCnt = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Integer, 0, memCnt); + } + + /* Special case: A DELETE without a WHERE clause deletes everything. + ** It is easier just to erase the whole table. Note, however, that + ** this means that the row change count will be incorrect. + */ + if( pWhere==0 && !triggers_exist && !IsVirtual(pTab) ){ + if( db->flags & SQLITE_CountRows ){ + /* If counting rows deleted, just count the total number of + ** entries in the table. */ + int addr2; + if( !isView ){ + sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead); + } + sqlite3VdbeAddOp2(v, OP_Rewind, iCur, sqlite3VdbeCurrentAddr(v)+2); + addr2 = sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1); + sqlite3VdbeAddOp2(v, OP_Next, iCur, addr2); + sqlite3VdbeAddOp1(v, OP_Close, iCur); + } + if( !isView ){ + sqlite3VdbeAddOp2(v, OP_Clear, pTab->tnum, iDb); + if( !pParse->nested ){ + sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC); + } + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + assert( pIdx->pSchema==pTab->pSchema ); + sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb); + } + } + } + /* The usual case: There is a WHERE clause so we have to scan through + ** the table and pick which records to delete. + */ + else{ + int iRowid = ++pParse->nMem; /* Used for storing rowid values. */ + + /* Begin the database scan + */ + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0); + if( pWInfo==0 ) goto delete_from_cleanup; + + /* Remember the rowid of every item to be deleted. + */ + sqlite3VdbeAddOp2(v, IsVirtual(pTab) ? OP_VRowid : OP_Rowid, iCur, iRowid); + sqlite3VdbeAddOp1(v, OP_FifoWrite, iRowid); + if( db->flags & SQLITE_CountRows ){ + sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1); + } + + /* End the database scan loop. + */ + sqlite3WhereEnd(pWInfo); + + /* Open the pseudo-table used to store OLD if there are triggers. + */ + if( triggers_exist ){ + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol); + sqlite3VdbeAddOp1(v, OP_OpenPseudo, oldIdx); + } + + /* Delete every item whose key was written to the list during the + ** database scan. We have to delete items after the scan is complete + ** because deleting an item can change the scan order. + */ + end = sqlite3VdbeMakeLabel(v); + + if( !isView ){ + /* Open cursors for the table we are deleting from and + ** all its indices. + */ + sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite); + } + + /* This is the beginning of the delete loop. If a trigger encounters + ** an IGNORE constraint, it jumps back to here. + */ + if( triggers_exist ){ + sqlite3VdbeResolveLabel(v, addr); + } + addr = sqlite3VdbeAddOp2(v, OP_FifoRead, iRowid, end); + + if( triggers_exist ){ + int iData = ++pParse->nMem; /* For storing row data of OLD table */ + + /* If the record is no longer present in the table, jump to the + ** next iteration of the loop through the contents of the fifo. + */ + sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, iRowid); + + /* Populate the OLD.* pseudo-table */ + if( old_col_mask ){ + sqlite3VdbeAddOp2(v, OP_RowData, iCur, iData); + }else{ + sqlite3VdbeAddOp2(v, OP_Null, 0, iData); + } + sqlite3VdbeAddOp3(v, OP_Insert, oldIdx, iData, iRowid); + + /* Jump back and run the BEFORE triggers */ + sqlite3VdbeAddOp2(v, OP_Goto, 0, iBeginBeforeTrigger); + sqlite3VdbeJumpHere(v, iEndBeforeTrigger); + } + + if( !isView ){ + /* Delete the row */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( IsVirtual(pTab) ){ + const char *pVtab = (const char *)pTab->pVtab; + sqlite3VtabMakeWritable(pParse, pTab); + sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVtab, P4_VTAB); + }else +#endif + { + sqlite3GenerateRowDelete(pParse, pTab, iCur, iRowid, pParse->nested==0); + } + } + + /* If there are row triggers, close all cursors then invoke + ** the AFTER triggers + */ + if( triggers_exist ){ + /* Jump back and run the AFTER triggers */ + sqlite3VdbeAddOp2(v, OP_Goto, 0, iBeginAfterTrigger); + sqlite3VdbeJumpHere(v, iEndAfterTrigger); + } + + /* End of the delete loop */ + sqlite3VdbeAddOp2(v, OP_Goto, 0, addr); + sqlite3VdbeResolveLabel(v, end); + + /* Close the cursors after the loop if there are no row triggers */ + if( !isView && !IsVirtual(pTab) ){ + for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ + sqlite3VdbeAddOp2(v, OP_Close, iCur + i, pIdx->tnum); + } + sqlite3VdbeAddOp1(v, OP_Close, iCur); + } + } + + /* + ** Return the number of rows that were deleted. If this routine is + ** generating code because of a call to sqlite3NestedParse(), do not + ** invoke the callback function. + */ + if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){ + sqlite3VdbeAddOp2(v, OP_ResultRow, memCnt, 1); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", P4_STATIC); + } + +delete_from_cleanup: + sqlite3AuthContextPop(&sContext); + sqlite3SrcListDelete(db, pTabList); + sqlite3ExprDelete(db, pWhere); + return; +} + +/* +** This routine generates VDBE code that causes a single row of a +** single table to be deleted. +** +** The VDBE must be in a particular state when this routine is called. +** These are the requirements: +** +** 1. A read/write cursor pointing to pTab, the table containing the row +** to be deleted, must be opened as cursor number "base". +** +** 2. Read/write cursors for all indices of pTab must be open as +** cursor number base+i for the i-th index. +** +** 3. The record number of the row to be deleted must be stored in +** memory cell iRowid. +** +** This routine pops the top of the stack to remove the record number +** and then generates code to remove both the table record and all index +** entries that point to that record. +*/ +void sqlite3GenerateRowDelete( + Parse *pParse, /* Parsing context */ + Table *pTab, /* Table containing the row to be deleted */ + int iCur, /* Cursor number for the table */ + int iRowid, /* Memory cell that contains the rowid to delete */ + int count /* Increment the row change counter */ +){ + int addr; + Vdbe *v; + + v = pParse->pVdbe; + addr = sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowid); + sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, 0); + sqlite3VdbeAddOp2(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0)); + if( count ){ + sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC); + } + sqlite3VdbeJumpHere(v, addr); +} + +/* +** This routine generates VDBE code that causes the deletion of all +** index entries associated with a single row of a single table. +** +** The VDBE must be in a particular state when this routine is called. +** These are the requirements: +** +** 1. A read/write cursor pointing to pTab, the table containing the row +** to be deleted, must be opened as cursor number "iCur". +** +** 2. Read/write cursors for all indices of pTab must be open as +** cursor number iCur+i for the i-th index. +** +** 3. The "iCur" cursor must be pointing to the row that is to be +** deleted. +*/ +void sqlite3GenerateRowIndexDelete( + Parse *pParse, /* Parsing and code generating context */ + Table *pTab, /* Table containing the row to be deleted */ + int iCur, /* Cursor number for the table */ + int *aRegIdx /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */ +){ + int i; + Index *pIdx; + int r1; + + for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ + if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue; + r1 = sqlite3GenerateIndexKey(pParse, pIdx, iCur, 0, 0); + sqlite3VdbeAddOp3(pParse->pVdbe, OP_IdxDelete, iCur+i, r1,pIdx->nColumn+1); + } +} + +/* +** Generate code that will assemble an index key and put it in register +** regOut. The key with be for index pIdx which is an index on pTab. +** iCur is the index of a cursor open on the pTab table and pointing to +** the entry that needs indexing. +** +** Return a register number which is the first in a block of +** registers that holds the elements of the index key. The +** block of registers has already been deallocated by the time +** this routine returns. +*/ +int sqlite3GenerateIndexKey( + Parse *pParse, /* Parsing context */ + Index *pIdx, /* The index for which to generate a key */ + int iCur, /* Cursor number for the pIdx->pTable table */ + int regOut, /* Write the new index key to this register */ + int doMakeRec /* Run the OP_MakeRecord instruction if true */ +){ + Vdbe *v = pParse->pVdbe; + int j; + Table *pTab = pIdx->pTable; + int regBase; + int nCol; + + nCol = pIdx->nColumn; + regBase = sqlite3GetTempRange(pParse, nCol+1); + sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regBase+nCol); + for(j=0; j<nCol; j++){ + int idx = pIdx->aiColumn[j]; + if( idx==pTab->iPKey ){ + sqlite3VdbeAddOp2(v, OP_SCopy, regBase+nCol, regBase+j); + }else{ + sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j); + sqlite3ColumnDefault(v, pTab, idx); + } + } + if( doMakeRec ){ + sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut); + sqlite3IndexAffinityStr(v, pIdx); + sqlite3ExprCacheAffinityChange(pParse, regBase, nCol+1); + } + sqlite3ReleaseTempRange(pParse, regBase, nCol+1); + return regBase; +} + +/* Make sure "isView" gets undefined in case this file becomes part of +** the amalgamation - so that subsequent files do not see isView as a +** macro. */ +#undef isView diff --git a/third_party/sqlite/src/expr.c b/third_party/sqlite/src/expr.c new file mode 100755 index 0000000..e8d8a1e --- /dev/null +++ b/third_party/sqlite/src/expr.c @@ -0,0 +1,3586 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains routines used for analyzing expressions and +** for generating VDBE code that evaluates expressions in SQLite. +** +** $Id: expr.c,v 1.387 2008/07/28 19:34:53 drh Exp $ +*/ +#include "sqliteInt.h" +#include <ctype.h> + +/* +** Return the 'affinity' of the expression pExpr if any. +** +** If pExpr is a column, a reference to a column via an 'AS' alias, +** or a sub-select with a column as the return value, then the +** affinity of that column is returned. Otherwise, 0x00 is returned, +** indicating no affinity for the expression. +** +** i.e. the WHERE clause expresssions in the following statements all +** have an affinity: +** +** CREATE TABLE t1(a); +** SELECT * FROM t1 WHERE a; +** SELECT a AS b FROM t1 WHERE b; +** SELECT * FROM t1 WHERE (select a from t1); +*/ +char sqlite3ExprAffinity(Expr *pExpr){ + int op = pExpr->op; + if( op==TK_SELECT ){ + return sqlite3ExprAffinity(pExpr->pSelect->pEList->a[0].pExpr); + } +#ifndef SQLITE_OMIT_CAST + if( op==TK_CAST ){ + return sqlite3AffinityType(&pExpr->token); + } +#endif + return pExpr->affinity; +} + +/* +** Set the collating sequence for expression pExpr to be the collating +** sequence named by pToken. Return a pointer to the revised expression. +** The collating sequence is marked as "explicit" using the EP_ExpCollate +** flag. An explicit collating sequence will override implicit +** collating sequences. +*/ +Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pName){ + char *zColl = 0; /* Dequoted name of collation sequence */ + CollSeq *pColl; + sqlite3 *db = pParse->db; + zColl = sqlite3NameFromToken(db, pName); + if( pExpr && zColl ){ + pColl = sqlite3LocateCollSeq(pParse, zColl, -1); + if( pColl ){ + pExpr->pColl = pColl; + pExpr->flags |= EP_ExpCollate; + } + } + sqlite3DbFree(db, zColl); + return pExpr; +} + +/* +** Return the default collation sequence for the expression pExpr. If +** there is no default collation type, return 0. +*/ +CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ + CollSeq *pColl = 0; + if( pExpr ){ + int op; + pColl = pExpr->pColl; + op = pExpr->op; + if( (op==TK_CAST || op==TK_UPLUS) && !pColl ){ + return sqlite3ExprCollSeq(pParse, pExpr->pLeft); + } + } + if( sqlite3CheckCollSeq(pParse, pColl) ){ + pColl = 0; + } + return pColl; +} + +/* +** pExpr is an operand of a comparison operator. aff2 is the +** type affinity of the other operand. This routine returns the +** type affinity that should be used for the comparison operator. +*/ +char sqlite3CompareAffinity(Expr *pExpr, char aff2){ + char aff1 = sqlite3ExprAffinity(pExpr); + if( aff1 && aff2 ){ + /* Both sides of the comparison are columns. If one has numeric + ** affinity, use that. Otherwise use no affinity. + */ + if( sqlite3IsNumericAffinity(aff1) || sqlite3IsNumericAffinity(aff2) ){ + return SQLITE_AFF_NUMERIC; + }else{ + return SQLITE_AFF_NONE; + } + }else if( !aff1 && !aff2 ){ + /* Neither side of the comparison is a column. Compare the + ** results directly. + */ + return SQLITE_AFF_NONE; + }else{ + /* One side is a column, the other is not. Use the columns affinity. */ + assert( aff1==0 || aff2==0 ); + return (aff1 + aff2); + } +} + +/* +** pExpr is a comparison operator. Return the type affinity that should +** be applied to both operands prior to doing the comparison. +*/ +static char comparisonAffinity(Expr *pExpr){ + char aff; + assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT || + pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE || + pExpr->op==TK_NE ); + assert( pExpr->pLeft ); + aff = sqlite3ExprAffinity(pExpr->pLeft); + if( pExpr->pRight ){ + aff = sqlite3CompareAffinity(pExpr->pRight, aff); + } + else if( pExpr->pSelect ){ + aff = sqlite3CompareAffinity(pExpr->pSelect->pEList->a[0].pExpr, aff); + } + else if( !aff ){ + aff = SQLITE_AFF_NONE; + } + return aff; +} + +/* +** pExpr is a comparison expression, eg. '=', '<', IN(...) etc. +** idx_affinity is the affinity of an indexed column. Return true +** if the index with affinity idx_affinity may be used to implement +** the comparison in pExpr. +*/ +int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){ + char aff = comparisonAffinity(pExpr); + switch( aff ){ + case SQLITE_AFF_NONE: + return 1; + case SQLITE_AFF_TEXT: + return idx_affinity==SQLITE_AFF_TEXT; + default: + return sqlite3IsNumericAffinity(idx_affinity); + } +} + +/* +** Return the P5 value that should be used for a binary comparison +** opcode (OP_Eq, OP_Ge etc.) used to compare pExpr1 and pExpr2. +*/ +static u8 binaryCompareP5(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){ + u8 aff = (char)sqlite3ExprAffinity(pExpr2); + aff = sqlite3CompareAffinity(pExpr1, aff) | jumpIfNull; + return aff; +} + +/* +** Return a pointer to the collation sequence that should be used by +** a binary comparison operator comparing pLeft and pRight. +** +** If the left hand expression has a collating sequence type, then it is +** used. Otherwise the collation sequence for the right hand expression +** is used, or the default (BINARY) if neither expression has a collating +** type. +** +** Argument pRight (but not pLeft) may be a null pointer. In this case, +** it is not considered. +*/ +CollSeq *sqlite3BinaryCompareCollSeq( + Parse *pParse, + Expr *pLeft, + Expr *pRight +){ + CollSeq *pColl; + assert( pLeft ); + if( pLeft->flags & EP_ExpCollate ){ + assert( pLeft->pColl ); + pColl = pLeft->pColl; + }else if( pRight && pRight->flags & EP_ExpCollate ){ + assert( pRight->pColl ); + pColl = pRight->pColl; + }else{ + pColl = sqlite3ExprCollSeq(pParse, pLeft); + if( !pColl ){ + pColl = sqlite3ExprCollSeq(pParse, pRight); + } + } + return pColl; +} + +/* +** Generate the operands for a comparison operation. Before +** generating the code for each operand, set the EP_AnyAff +** flag on the expression so that it will be able to used a +** cached column value that has previously undergone an +** affinity change. +*/ +static void codeCompareOperands( + Parse *pParse, /* Parsing and code generating context */ + Expr *pLeft, /* The left operand */ + int *pRegLeft, /* Register where left operand is stored */ + int *pFreeLeft, /* Free this register when done */ + Expr *pRight, /* The right operand */ + int *pRegRight, /* Register where right operand is stored */ + int *pFreeRight /* Write temp register for right operand there */ +){ + while( pLeft->op==TK_UPLUS ) pLeft = pLeft->pLeft; + pLeft->flags |= EP_AnyAff; + *pRegLeft = sqlite3ExprCodeTemp(pParse, pLeft, pFreeLeft); + while( pRight->op==TK_UPLUS ) pRight = pRight->pLeft; + pRight->flags |= EP_AnyAff; + *pRegRight = sqlite3ExprCodeTemp(pParse, pRight, pFreeRight); +} + +/* +** Generate code for a comparison operator. +*/ +static int codeCompare( + Parse *pParse, /* The parsing (and code generating) context */ + Expr *pLeft, /* The left operand */ + Expr *pRight, /* The right operand */ + int opcode, /* The comparison opcode */ + int in1, int in2, /* Register holding operands */ + int dest, /* Jump here if true. */ + int jumpIfNull /* If true, jump if either operand is NULL */ +){ + int p5; + int addr; + CollSeq *p4; + + p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight); + p5 = binaryCompareP5(pLeft, pRight, jumpIfNull); + addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1, + (void*)p4, P4_COLLSEQ); + sqlite3VdbeChangeP5(pParse->pVdbe, p5); + if( (p5 & SQLITE_AFF_MASK)!=SQLITE_AFF_NONE ){ + sqlite3ExprCacheAffinityChange(pParse, in1, 1); + sqlite3ExprCacheAffinityChange(pParse, in2, 1); + } + return addr; +} + +#if SQLITE_MAX_EXPR_DEPTH>0 +/* +** Check that argument nHeight is less than or equal to the maximum +** expression depth allowed. If it is not, leave an error message in +** pParse. +*/ +static int checkExprHeight(Parse *pParse, int nHeight){ + int rc = SQLITE_OK; + int mxHeight = pParse->db->aLimit[SQLITE_LIMIT_EXPR_DEPTH]; + if( nHeight>mxHeight ){ + sqlite3ErrorMsg(pParse, + "Expression tree is too large (maximum depth %d)", mxHeight + ); + rc = SQLITE_ERROR; + } + return rc; +} + +/* The following three functions, heightOfExpr(), heightOfExprList() +** and heightOfSelect(), are used to determine the maximum height +** of any expression tree referenced by the structure passed as the +** first argument. +** +** If this maximum height is greater than the current value pointed +** to by pnHeight, the second parameter, then set *pnHeight to that +** value. +*/ +static void heightOfExpr(Expr *p, int *pnHeight){ + if( p ){ + if( p->nHeight>*pnHeight ){ + *pnHeight = p->nHeight; + } + } +} +static void heightOfExprList(ExprList *p, int *pnHeight){ + if( p ){ + int i; + for(i=0; i<p->nExpr; i++){ + heightOfExpr(p->a[i].pExpr, pnHeight); + } + } +} +static void heightOfSelect(Select *p, int *pnHeight){ + if( p ){ + heightOfExpr(p->pWhere, pnHeight); + heightOfExpr(p->pHaving, pnHeight); + heightOfExpr(p->pLimit, pnHeight); + heightOfExpr(p->pOffset, pnHeight); + heightOfExprList(p->pEList, pnHeight); + heightOfExprList(p->pGroupBy, pnHeight); + heightOfExprList(p->pOrderBy, pnHeight); + heightOfSelect(p->pPrior, pnHeight); + } +} + +/* +** Set the Expr.nHeight variable in the structure passed as an +** argument. An expression with no children, Expr.pList or +** Expr.pSelect member has a height of 1. Any other expression +** has a height equal to the maximum height of any other +** referenced Expr plus one. +*/ +static void exprSetHeight(Expr *p){ + int nHeight = 0; + heightOfExpr(p->pLeft, &nHeight); + heightOfExpr(p->pRight, &nHeight); + heightOfExprList(p->pList, &nHeight); + heightOfSelect(p->pSelect, &nHeight); + p->nHeight = nHeight + 1; +} + +/* +** Set the Expr.nHeight variable using the exprSetHeight() function. If +** the height is greater than the maximum allowed expression depth, +** leave an error in pParse. +*/ +void sqlite3ExprSetHeight(Parse *pParse, Expr *p){ + exprSetHeight(p); + checkExprHeight(pParse, p->nHeight); +} + +/* +** Return the maximum height of any expression tree referenced +** by the select statement passed as an argument. +*/ +int sqlite3SelectExprHeight(Select *p){ + int nHeight = 0; + heightOfSelect(p, &nHeight); + return nHeight; +} +#else + #define checkExprHeight(x,y) + #define exprSetHeight(y) +#endif /* SQLITE_MAX_EXPR_DEPTH>0 */ + +/* +** Construct a new expression node and return a pointer to it. Memory +** for this node is obtained from sqlite3_malloc(). The calling function +** is responsible for making sure the node eventually gets freed. +*/ +Expr *sqlite3Expr( + sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */ + int op, /* Expression opcode */ + Expr *pLeft, /* Left operand */ + Expr *pRight, /* Right operand */ + const Token *pToken /* Argument token */ +){ + Expr *pNew; + pNew = sqlite3DbMallocZero(db, sizeof(Expr)); + if( pNew==0 ){ + /* When malloc fails, delete pLeft and pRight. Expressions passed to + ** this function must always be allocated with sqlite3Expr() for this + ** reason. + */ + sqlite3ExprDelete(db, pLeft); + sqlite3ExprDelete(db, pRight); + return 0; + } + pNew->op = op; + pNew->pLeft = pLeft; + pNew->pRight = pRight; + pNew->iAgg = -1; + pNew->span.z = (u8*)""; + if( pToken ){ + assert( pToken->dyn==0 ); + pNew->span = pNew->token = *pToken; + }else if( pLeft ){ + if( pRight ){ + if( pRight->span.dyn==0 && pLeft->span.dyn==0 ){ + sqlite3ExprSpan(pNew, &pLeft->span, &pRight->span); + } + if( pRight->flags & EP_ExpCollate ){ + pNew->flags |= EP_ExpCollate; + pNew->pColl = pRight->pColl; + } + } + if( pLeft->flags & EP_ExpCollate ){ + pNew->flags |= EP_ExpCollate; + pNew->pColl = pLeft->pColl; + } + } + + exprSetHeight(pNew); + return pNew; +} + +/* +** Works like sqlite3Expr() except that it takes an extra Parse* +** argument and notifies the associated connection object if malloc fails. +*/ +Expr *sqlite3PExpr( + Parse *pParse, /* Parsing context */ + int op, /* Expression opcode */ + Expr *pLeft, /* Left operand */ + Expr *pRight, /* Right operand */ + const Token *pToken /* Argument token */ +){ + Expr *p = sqlite3Expr(pParse->db, op, pLeft, pRight, pToken); + if( p ){ + checkExprHeight(pParse, p->nHeight); + } + return p; +} + +/* +** When doing a nested parse, you can include terms in an expression +** that look like this: #1 #2 ... These terms refer to registers +** in the virtual machine. #N is the N-th register. +** +** This routine is called by the parser to deal with on of those terms. +** It immediately generates code to store the value in a memory location. +** The returns an expression that will code to extract the value from +** that memory location as needed. +*/ +Expr *sqlite3RegisterExpr(Parse *pParse, Token *pToken){ + Vdbe *v = pParse->pVdbe; + Expr *p; + if( pParse->nested==0 ){ + sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", pToken); + return sqlite3PExpr(pParse, TK_NULL, 0, 0, 0); + } + if( v==0 ) return 0; + p = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, pToken); + if( p==0 ){ + return 0; /* Malloc failed */ + } + p->iTable = atoi((char*)&pToken->z[1]); + return p; +} + +/* +** Join two expressions using an AND operator. If either expression is +** NULL, then just return the other expression. +*/ +Expr *sqlite3ExprAnd(sqlite3 *db, Expr *pLeft, Expr *pRight){ + if( pLeft==0 ){ + return pRight; + }else if( pRight==0 ){ + return pLeft; + }else{ + return sqlite3Expr(db, TK_AND, pLeft, pRight, 0); + } +} + +/* +** Set the Expr.span field of the given expression to span all +** text between the two given tokens. Both tokens must be pointing +** at the same string. +*/ +void sqlite3ExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){ + assert( pRight!=0 ); + assert( pLeft!=0 ); + if( pExpr ){ + pExpr->span.z = pLeft->z; + pExpr->span.n = pRight->n + (pRight->z - pLeft->z); + } +} + +/* +** Construct a new expression node for a function with multiple +** arguments. +*/ +Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){ + Expr *pNew; + sqlite3 *db = pParse->db; + assert( pToken ); + pNew = sqlite3DbMallocZero(db, sizeof(Expr) ); + if( pNew==0 ){ + sqlite3ExprListDelete(db, pList); /* Avoid leaking memory when malloc fails */ + return 0; + } + pNew->op = TK_FUNCTION; + pNew->pList = pList; + assert( pToken->dyn==0 ); + pNew->token = *pToken; + pNew->span = pNew->token; + + sqlite3ExprSetHeight(pParse, pNew); + return pNew; +} + +/* +** Assign a variable number to an expression that encodes a wildcard +** in the original SQL statement. +** +** Wildcards consisting of a single "?" are assigned the next sequential +** variable number. +** +** Wildcards of the form "?nnn" are assigned the number "nnn". We make +** sure "nnn" is not too be to avoid a denial of service attack when +** the SQL statement comes from an external source. +** +** Wildcards of the form ":aaa" or "$aaa" are assigned the same number +** as the previous instance of the same wildcard. Or if this is the first +** instance of the wildcard, the next sequenial variable number is +** assigned. +*/ +void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ + Token *pToken; + sqlite3 *db = pParse->db; + + if( pExpr==0 ) return; + pToken = &pExpr->token; + assert( pToken->n>=1 ); + assert( pToken->z!=0 ); + assert( pToken->z[0]!=0 ); + if( pToken->n==1 ){ + /* Wildcard of the form "?". Assign the next variable number */ + pExpr->iTable = ++pParse->nVar; + }else if( pToken->z[0]=='?' ){ + /* Wildcard of the form "?nnn". Convert "nnn" to an integer and + ** use it as the variable number */ + int i; + pExpr->iTable = i = atoi((char*)&pToken->z[1]); + testcase( i==0 ); + testcase( i==1 ); + testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 ); + testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ); + if( i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ + sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d", + db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]); + } + if( i>pParse->nVar ){ + pParse->nVar = i; + } + }else{ + /* Wildcards of the form ":aaa" or "$aaa". Reuse the same variable + ** number as the prior appearance of the same name, or if the name + ** has never appeared before, reuse the same variable number + */ + int i, n; + n = pToken->n; + for(i=0; i<pParse->nVarExpr; i++){ + Expr *pE; + if( (pE = pParse->apVarExpr[i])!=0 + && pE->token.n==n + && memcmp(pE->token.z, pToken->z, n)==0 ){ + pExpr->iTable = pE->iTable; + break; + } + } + if( i>=pParse->nVarExpr ){ + pExpr->iTable = ++pParse->nVar; + if( pParse->nVarExpr>=pParse->nVarExprAlloc-1 ){ + pParse->nVarExprAlloc += pParse->nVarExprAlloc + 10; + pParse->apVarExpr = + sqlite3DbReallocOrFree( + db, + pParse->apVarExpr, + pParse->nVarExprAlloc*sizeof(pParse->apVarExpr[0]) + ); + } + if( !db->mallocFailed ){ + assert( pParse->apVarExpr!=0 ); + pParse->apVarExpr[pParse->nVarExpr++] = pExpr; + } + } + } + if( !pParse->nErr && pParse->nVar>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ + sqlite3ErrorMsg(pParse, "too many SQL variables"); + } +} + +/* +** Recursively delete an expression tree. +*/ +void sqlite3ExprDelete(sqlite3 *db, Expr *p){ + if( p==0 ) return; + if( p->span.dyn ) sqlite3DbFree(db, (char*)p->span.z); + if( p->token.dyn ) sqlite3DbFree(db, (char*)p->token.z); + sqlite3ExprDelete(db, p->pLeft); + sqlite3ExprDelete(db, p->pRight); + sqlite3ExprListDelete(db, p->pList); + sqlite3SelectDelete(db, p->pSelect); + sqlite3DbFree(db, p); +} + +/* +** The Expr.token field might be a string literal that is quoted. +** If so, remove the quotation marks. +*/ +void sqlite3DequoteExpr(sqlite3 *db, Expr *p){ + if( ExprHasAnyProperty(p, EP_Dequoted) ){ + return; + } + ExprSetProperty(p, EP_Dequoted); + if( p->token.dyn==0 ){ + sqlite3TokenCopy(db, &p->token, &p->token); + } + sqlite3Dequote((char*)p->token.z); +} + + +/* +** The following group of routines make deep copies of expressions, +** expression lists, ID lists, and select statements. The copies can +** be deleted (by being passed to their respective ...Delete() routines) +** without effecting the originals. +** +** The expression list, ID, and source lists return by sqlite3ExprListDup(), +** sqlite3IdListDup(), and sqlite3SrcListDup() can not be further expanded +** by subsequent calls to sqlite*ListAppend() routines. +** +** Any tables that the SrcList might point to are not duplicated. +*/ +Expr *sqlite3ExprDup(sqlite3 *db, Expr *p){ + Expr *pNew; + if( p==0 ) return 0; + pNew = sqlite3DbMallocRaw(db, sizeof(*p) ); + if( pNew==0 ) return 0; + memcpy(pNew, p, sizeof(*pNew)); + if( p->token.z!=0 ){ + pNew->token.z = (u8*)sqlite3DbStrNDup(db, (char*)p->token.z, p->token.n); + pNew->token.dyn = 1; + }else{ + assert( pNew->token.z==0 ); + } + pNew->span.z = 0; + pNew->pLeft = sqlite3ExprDup(db, p->pLeft); + pNew->pRight = sqlite3ExprDup(db, p->pRight); + pNew->pList = sqlite3ExprListDup(db, p->pList); + pNew->pSelect = sqlite3SelectDup(db, p->pSelect); + return pNew; +} +void sqlite3TokenCopy(sqlite3 *db, Token *pTo, Token *pFrom){ + if( pTo->dyn ) sqlite3DbFree(db, (char*)pTo->z); + if( pFrom->z ){ + pTo->n = pFrom->n; + pTo->z = (u8*)sqlite3DbStrNDup(db, (char*)pFrom->z, pFrom->n); + pTo->dyn = 1; + }else{ + pTo->z = 0; + } +} +ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p){ + ExprList *pNew; + struct ExprList_item *pItem, *pOldItem; + int i; + if( p==0 ) return 0; + pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) ); + if( pNew==0 ) return 0; + pNew->iECursor = 0; + pNew->nExpr = pNew->nAlloc = p->nExpr; + pNew->a = pItem = sqlite3DbMallocRaw(db, p->nExpr*sizeof(p->a[0]) ); + if( pItem==0 ){ + sqlite3DbFree(db, pNew); + return 0; + } + pOldItem = p->a; + for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){ + Expr *pNewExpr, *pOldExpr; + pItem->pExpr = pNewExpr = sqlite3ExprDup(db, pOldExpr = pOldItem->pExpr); + if( pOldExpr->span.z!=0 && pNewExpr ){ + /* Always make a copy of the span for top-level expressions in the + ** expression list. The logic in SELECT processing that determines + ** the names of columns in the result set needs this information */ + sqlite3TokenCopy(db, &pNewExpr->span, &pOldExpr->span); + } + assert( pNewExpr==0 || pNewExpr->span.z!=0 + || pOldExpr->span.z==0 + || db->mallocFailed ); + pItem->zName = sqlite3DbStrDup(db, pOldItem->zName); + pItem->sortOrder = pOldItem->sortOrder; + pItem->isAgg = pOldItem->isAgg; + pItem->done = 0; + } + return pNew; +} + +/* +** If cursors, triggers, views and subqueries are all omitted from +** the build, then none of the following routines, except for +** sqlite3SelectDup(), can be called. sqlite3SelectDup() is sometimes +** called with a NULL argument. +*/ +#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) \ + || !defined(SQLITE_OMIT_SUBQUERY) +SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p){ + SrcList *pNew; + int i; + int nByte; + if( p==0 ) return 0; + nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0); + pNew = sqlite3DbMallocRaw(db, nByte ); + if( pNew==0 ) return 0; + pNew->nSrc = pNew->nAlloc = p->nSrc; + for(i=0; i<p->nSrc; i++){ + struct SrcList_item *pNewItem = &pNew->a[i]; + struct SrcList_item *pOldItem = &p->a[i]; + Table *pTab; + pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase); + pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); + pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias); + pNewItem->jointype = pOldItem->jointype; + pNewItem->iCursor = pOldItem->iCursor; + pNewItem->isPopulated = pOldItem->isPopulated; + pTab = pNewItem->pTab = pOldItem->pTab; + if( pTab ){ + pTab->nRef++; + } + pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect); + pNewItem->pOn = sqlite3ExprDup(db, pOldItem->pOn); + pNewItem->pUsing = sqlite3IdListDup(db, pOldItem->pUsing); + pNewItem->colUsed = pOldItem->colUsed; + } + return pNew; +} +IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){ + IdList *pNew; + int i; + if( p==0 ) return 0; + pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) ); + if( pNew==0 ) return 0; + pNew->nId = pNew->nAlloc = p->nId; + pNew->a = sqlite3DbMallocRaw(db, p->nId*sizeof(p->a[0]) ); + if( pNew->a==0 ){ + sqlite3DbFree(db, pNew); + return 0; + } + for(i=0; i<p->nId; i++){ + struct IdList_item *pNewItem = &pNew->a[i]; + struct IdList_item *pOldItem = &p->a[i]; + pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); + pNewItem->idx = pOldItem->idx; + } + return pNew; +} +Select *sqlite3SelectDup(sqlite3 *db, Select *p){ + Select *pNew; + if( p==0 ) return 0; + pNew = sqlite3DbMallocRaw(db, sizeof(*p) ); + if( pNew==0 ) return 0; + pNew->isDistinct = p->isDistinct; + pNew->pEList = sqlite3ExprListDup(db, p->pEList); + pNew->pSrc = sqlite3SrcListDup(db, p->pSrc); + pNew->pWhere = sqlite3ExprDup(db, p->pWhere); + pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy); + pNew->pHaving = sqlite3ExprDup(db, p->pHaving); + pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy); + pNew->op = p->op; + pNew->pPrior = sqlite3SelectDup(db, p->pPrior); + pNew->pLimit = sqlite3ExprDup(db, p->pLimit); + pNew->pOffset = sqlite3ExprDup(db, p->pOffset); + pNew->iLimit = 0; + pNew->iOffset = 0; + pNew->isResolved = p->isResolved; + pNew->isAgg = p->isAgg; + pNew->usesEphm = 0; + pNew->disallowOrderBy = 0; + pNew->pRightmost = 0; + pNew->addrOpenEphm[0] = -1; + pNew->addrOpenEphm[1] = -1; + pNew->addrOpenEphm[2] = -1; + return pNew; +} +#else +Select *sqlite3SelectDup(sqlite3 *db, Select *p){ + assert( p==0 ); + return 0; +} +#endif + + +/* +** Add a new element to the end of an expression list. If pList is +** initially NULL, then create a new expression list. +*/ +ExprList *sqlite3ExprListAppend( + Parse *pParse, /* Parsing context */ + ExprList *pList, /* List to which to append. Might be NULL */ + Expr *pExpr, /* Expression to be appended */ + Token *pName /* AS keyword for the expression */ +){ + sqlite3 *db = pParse->db; + if( pList==0 ){ + pList = sqlite3DbMallocZero(db, sizeof(ExprList) ); + if( pList==0 ){ + goto no_mem; + } + assert( pList->nAlloc==0 ); + } + if( pList->nAlloc<=pList->nExpr ){ + struct ExprList_item *a; + int n = pList->nAlloc*2 + 4; + a = sqlite3DbRealloc(db, pList->a, n*sizeof(pList->a[0])); + if( a==0 ){ + goto no_mem; + } + pList->a = a; + pList->nAlloc = n; + } + assert( pList->a!=0 ); + if( pExpr || pName ){ + struct ExprList_item *pItem = &pList->a[pList->nExpr++]; + memset(pItem, 0, sizeof(*pItem)); + pItem->zName = sqlite3NameFromToken(db, pName); + pItem->pExpr = pExpr; + } + return pList; + +no_mem: + /* Avoid leaking memory if malloc has failed. */ + sqlite3ExprDelete(db, pExpr); + sqlite3ExprListDelete(db, pList); + return 0; +} + +/* +** If the expression list pEList contains more than iLimit elements, +** leave an error message in pParse. +*/ +void sqlite3ExprListCheckLength( + Parse *pParse, + ExprList *pEList, + const char *zObject +){ + int mx = pParse->db->aLimit[SQLITE_LIMIT_COLUMN]; + testcase( pEList && pEList->nExpr==mx ); + testcase( pEList && pEList->nExpr==mx+1 ); + if( pEList && pEList->nExpr>mx ){ + sqlite3ErrorMsg(pParse, "too many columns in %s", zObject); + } +} + +/* +** Delete an entire expression list. +*/ +void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){ + int i; + struct ExprList_item *pItem; + if( pList==0 ) return; + assert( pList->a!=0 || (pList->nExpr==0 && pList->nAlloc==0) ); + assert( pList->nExpr<=pList->nAlloc ); + for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){ + sqlite3ExprDelete(db, pItem->pExpr); + sqlite3DbFree(db, pItem->zName); + } + sqlite3DbFree(db, pList->a); + sqlite3DbFree(db, pList); +} + +/* +** Walk an expression tree. Call xFunc for each node visited. xFunc +** is called on the node before xFunc is called on the nodes children. +** +** The return value from xFunc determines whether the tree walk continues. +** 0 means continue walking the tree. 1 means do not walk children +** of the current node but continue with siblings. 2 means abandon +** the tree walk completely. +** +** The return value from this routine is 1 to abandon the tree walk +** and 0 to continue. +** +** NOTICE: This routine does *not* descend into subqueries. +*/ +static int walkExprList(ExprList *, int (*)(void *, Expr*), void *); +static int walkExprTree(Expr *pExpr, int (*xFunc)(void*,Expr*), void *pArg){ + int rc; + if( pExpr==0 ) return 0; + rc = (*xFunc)(pArg, pExpr); + if( rc==0 ){ + if( walkExprTree(pExpr->pLeft, xFunc, pArg) ) return 1; + if( walkExprTree(pExpr->pRight, xFunc, pArg) ) return 1; + if( walkExprList(pExpr->pList, xFunc, pArg) ) return 1; + } + return rc>1; +} + +/* +** Call walkExprTree() for every expression in list p. +*/ +static int walkExprList(ExprList *p, int (*xFunc)(void *, Expr*), void *pArg){ + int i; + struct ExprList_item *pItem; + if( !p ) return 0; + for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){ + if( walkExprTree(pItem->pExpr, xFunc, pArg) ) return 1; + } + return 0; +} + +/* +** Call walkExprTree() for every expression in Select p, not including +** expressions that are part of sub-selects in any FROM clause or the LIMIT +** or OFFSET expressions.. +*/ +static int walkSelectExpr(Select *p, int (*xFunc)(void *, Expr*), void *pArg){ + walkExprList(p->pEList, xFunc, pArg); + walkExprTree(p->pWhere, xFunc, pArg); + walkExprList(p->pGroupBy, xFunc, pArg); + walkExprTree(p->pHaving, xFunc, pArg); + walkExprList(p->pOrderBy, xFunc, pArg); + if( p->pPrior ){ + walkSelectExpr(p->pPrior, xFunc, pArg); + } + return 0; +} + + +/* +** This routine is designed as an xFunc for walkExprTree(). +** +** pArg is really a pointer to an integer. If we can tell by looking +** at pExpr that the expression that contains pExpr is not a constant +** expression, then set *pArg to 0 and return 2 to abandon the tree walk. +** If pExpr does does not disqualify the expression from being a constant +** then do nothing. +** +** After walking the whole tree, if no nodes are found that disqualify +** the expression as constant, then we assume the whole expression +** is constant. See sqlite3ExprIsConstant() for additional information. +*/ +static int exprNodeIsConstant(void *pArg, Expr *pExpr){ + int *pN = (int*)pArg; + + /* If *pArg is 3 then any term of the expression that comes from + ** the ON or USING clauses of a join disqualifies the expression + ** from being considered constant. */ + if( (*pN)==3 && ExprHasAnyProperty(pExpr, EP_FromJoin) ){ + *pN = 0; + return 2; + } + + switch( pExpr->op ){ + /* Consider functions to be constant if all their arguments are constant + ** and *pArg==2 */ + case TK_FUNCTION: + if( (*pN)==2 ) return 0; + /* Fall through */ + case TK_ID: + case TK_COLUMN: + case TK_DOT: + case TK_AGG_FUNCTION: + case TK_AGG_COLUMN: +#ifndef SQLITE_OMIT_SUBQUERY + case TK_SELECT: + case TK_EXISTS: + testcase( pExpr->op==TK_SELECT ); + testcase( pExpr->op==TK_EXISTS ); +#endif + testcase( pExpr->op==TK_ID ); + testcase( pExpr->op==TK_COLUMN ); + testcase( pExpr->op==TK_DOT ); + testcase( pExpr->op==TK_AGG_FUNCTION ); + testcase( pExpr->op==TK_AGG_COLUMN ); + *pN = 0; + return 2; + case TK_IN: + if( pExpr->pSelect ){ + *pN = 0; + return 2; + } + default: + return 0; + } +} + +/* +** Walk an expression tree. Return 1 if the expression is constant +** and 0 if it involves variables or function calls. +** +** For the purposes of this function, a double-quoted string (ex: "abc") +** is considered a variable but a single-quoted string (ex: 'abc') is +** a constant. +*/ +int sqlite3ExprIsConstant(Expr *p){ + int isConst = 1; + walkExprTree(p, exprNodeIsConstant, &isConst); + return isConst; +} + +/* +** Walk an expression tree. Return 1 if the expression is constant +** that does no originate from the ON or USING clauses of a join. +** Return 0 if it involves variables or function calls or terms from +** an ON or USING clause. +*/ +int sqlite3ExprIsConstantNotJoin(Expr *p){ + int isConst = 3; + walkExprTree(p, exprNodeIsConstant, &isConst); + return isConst!=0; +} + +/* +** Walk an expression tree. Return 1 if the expression is constant +** or a function call with constant arguments. Return and 0 if there +** are any variables. +** +** For the purposes of this function, a double-quoted string (ex: "abc") +** is considered a variable but a single-quoted string (ex: 'abc') is +** a constant. +*/ +int sqlite3ExprIsConstantOrFunction(Expr *p){ + int isConst = 2; + walkExprTree(p, exprNodeIsConstant, &isConst); + return isConst!=0; +} + +/* +** If the expression p codes a constant integer that is small enough +** to fit in a 32-bit integer, return 1 and put the value of the integer +** in *pValue. If the expression is not an integer or if it is too big +** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged. +*/ +int sqlite3ExprIsInteger(Expr *p, int *pValue){ + int rc = 0; + if( p->flags & EP_IntValue ){ + *pValue = p->iTable; + return 1; + } + switch( p->op ){ + case TK_INTEGER: { + rc = sqlite3GetInt32((char*)p->token.z, pValue); + break; + } + case TK_UPLUS: { + rc = sqlite3ExprIsInteger(p->pLeft, pValue); + break; + } + case TK_UMINUS: { + int v; + if( sqlite3ExprIsInteger(p->pLeft, &v) ){ + *pValue = -v; + rc = 1; + } + break; + } + default: break; + } + if( rc ){ + p->op = TK_INTEGER; + p->flags |= EP_IntValue; + p->iTable = *pValue; + } + return rc; +} + +/* +** Return TRUE if the given string is a row-id column name. +*/ +int sqlite3IsRowid(const char *z){ + if( sqlite3StrICmp(z, "_ROWID_")==0 ) return 1; + if( sqlite3StrICmp(z, "ROWID")==0 ) return 1; + if( sqlite3StrICmp(z, "OID")==0 ) return 1; + return 0; +} + +/* +** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up +** that name in the set of source tables in pSrcList and make the pExpr +** expression node refer back to that source column. The following changes +** are made to pExpr: +** +** pExpr->iDb Set the index in db->aDb[] of the database holding +** the table. +** pExpr->iTable Set to the cursor number for the table obtained +** from pSrcList. +** pExpr->iColumn Set to the column number within the table. +** pExpr->op Set to TK_COLUMN. +** pExpr->pLeft Any expression this points to is deleted +** pExpr->pRight Any expression this points to is deleted. +** +** The pDbToken is the name of the database (the "X"). This value may be +** NULL meaning that name is of the form Y.Z or Z. Any available database +** can be used. The pTableToken is the name of the table (the "Y"). This +** value can be NULL if pDbToken is also NULL. If pTableToken is NULL it +** means that the form of the name is Z and that columns from any table +** can be used. +** +** If the name cannot be resolved unambiguously, leave an error message +** in pParse and return non-zero. Return zero on success. +*/ +static int lookupName( + 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. */ + NameContext *pNC, /* The name context used to resolve the name */ + Expr *pExpr /* Make this EXPR node point to the selected column */ +){ + char *zDb = 0; /* Name of the database. The "X" in X.Y.Z */ + char *zTab = 0; /* Name of the table. The "Y" in X.Y.Z or Y.Z */ + char *zCol = 0; /* Name of the column. The "Z" */ + int i, j; /* Loop counters */ + int cnt = 0; /* Number of matching column names */ + int cntTab = 0; /* Number of matching table names */ + sqlite3 *db = pParse->db; /* The database */ + struct SrcList_item *pItem; /* Use for looping over pSrcList items */ + struct SrcList_item *pMatch = 0; /* The matching pSrcList item */ + NameContext *pTopNC = pNC; /* First namecontext in the list */ + Schema *pSchema = 0; /* Schema of the expression */ + + assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */ + zDb = sqlite3NameFromToken(db, pDbToken); + zTab = sqlite3NameFromToken(db, pTableToken); + zCol = sqlite3NameFromToken(db, pColumnToken); + if( db->mallocFailed ){ + goto lookupname_end; + } + + pExpr->iTable = -1; + while( pNC && cnt==0 ){ + ExprList *pEList; + SrcList *pSrcList = pNC->pSrcList; + + if( pSrcList ){ + for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){ + Table *pTab; + int iDb; + Column *pCol; + + pTab = pItem->pTab; + assert( pTab!=0 ); + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + assert( pTab->nCol>0 ); + if( zTab ){ + if( pItem->zAlias ){ + char *zTabName = pItem->zAlias; + if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue; + }else{ + char *zTabName = pTab->zName; + if( zTabName==0 || sqlite3StrICmp(zTabName, zTab)!=0 ) continue; + if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){ + continue; + } + } + } + if( 0==(cntTab++) ){ + pExpr->iTable = pItem->iCursor; + pSchema = pTab->pSchema; + pMatch = pItem; + } + for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){ + if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ + const char *zColl = pTab->aCol[j].zColl; + IdList *pUsing; + cnt++; + pExpr->iTable = pItem->iCursor; + pMatch = pItem; + 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; + if( (pExpr->flags & EP_ExpCollate)==0 ){ + pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0); + } + if( i<pSrcList->nSrc-1 ){ + if( pItem[1].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 */ + pItem++; + i++; + }else if( (pUsing = pItem[1].pUsing)!=0 ){ + /* If this match occurs on a column that is in the USING clause + ** of a join, skip the search of the right table of the join + ** to avoid a duplicate match there. */ + int k; + for(k=0; k<pUsing->nId; k++){ + if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ){ + pItem++; + i++; + break; + } + } + } + } + break; + } + } + } + } + +#ifndef SQLITE_OMIT_TRIGGER + /* If we have not already resolved the name, then maybe + ** it is a new.* or old.* trigger argument reference + */ + if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){ + TriggerStack *pTriggerStack = pParse->trigStack; + Table *pTab = 0; + u32 *piColMask; + if( pTriggerStack->newIdx != -1 && sqlite3StrICmp("new", zTab) == 0 ){ + pExpr->iTable = pTriggerStack->newIdx; + assert( pTriggerStack->pTab ); + pTab = pTriggerStack->pTab; + piColMask = &(pTriggerStack->newColMask); + }else if( pTriggerStack->oldIdx != -1 && sqlite3StrICmp("old", zTab)==0 ){ + pExpr->iTable = pTriggerStack->oldIdx; + assert( pTriggerStack->pTab ); + pTab = pTriggerStack->pTab; + piColMask = &(pTriggerStack->oldColMask); + } + + if( pTab ){ + int iCol; + Column *pCol = pTab->aCol; + + pSchema = pTab->pSchema; + cntTab++; + for(iCol=0; iCol < pTab->nCol; iCol++, pCol++) { + if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ + const char *zColl = pTab->aCol[iCol].zColl; + cnt++; + pExpr->iColumn = iCol==pTab->iPKey ? -1 : iCol; + pExpr->affinity = pTab->aCol[iCol].affinity; + if( (pExpr->flags & EP_ExpCollate)==0 ){ + pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0); + } + pExpr->pTab = pTab; + if( iCol>=0 ){ + testcase( iCol==31 ); + testcase( iCol==32 ); + *piColMask |= ((u32)1<<iCol) | (iCol>=32?0xffffffff:0); + } + break; + } + } + } + } +#endif /* !defined(SQLITE_OMIT_TRIGGER) */ + + /* + ** Perhaps the name is a reference to the ROWID + */ + if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){ + cnt = 1; + pExpr->iColumn = -1; + pExpr->affinity = SQLITE_AFF_INTEGER; + } + + /* + ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z + ** might refer to an result-set alias. This happens, for example, when + ** we are resolving names in the WHERE clause of the following command: + ** + ** SELECT a+b AS x FROM table WHERE x<10; + ** + ** In cases like this, replace pExpr with a copy of the expression that + ** forms the result set entry ("a+b" in the example) and return immediately. + ** Note that the expression in the result set should have already been + ** resolved by the time the WHERE clause is resolved. + */ + if( cnt==0 && (pEList = pNC->pEList)!=0 && zTab==0 ){ + for(j=0; j<pEList->nExpr; j++){ + char *zAs = pEList->a[j].zName; + if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ + Expr *pDup, *pOrig; + assert( pExpr->pLeft==0 && pExpr->pRight==0 ); + assert( pExpr->pList==0 ); + assert( pExpr->pSelect==0 ); + pOrig = pEList->a[j].pExpr; + if( !pNC->allowAgg && ExprHasProperty(pOrig, EP_Agg) ){ + sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs); + sqlite3DbFree(db, zCol); + return 2; + } + pDup = sqlite3ExprDup(db, pOrig); + if( pExpr->flags & EP_ExpCollate ){ + pDup->pColl = pExpr->pColl; + pDup->flags |= EP_ExpCollate; + } + if( pExpr->span.dyn ) sqlite3DbFree(db, (char*)pExpr->span.z); + if( pExpr->token.dyn ) sqlite3DbFree(db, (char*)pExpr->token.z); + memcpy(pExpr, pDup, sizeof(*pExpr)); + sqlite3DbFree(db, pDup); + cnt = 1; + pMatch = 0; + assert( zTab==0 && zDb==0 ); + goto lookupname_end_2; + } + } + } + + /* Advance to the next name context. The loop will exit when either + ** we have a match (cnt>0) or when we run out of name contexts. + */ + if( cnt==0 ){ + pNC = pNC->pNext; + } + } + + /* + ** If X and Y are NULL (in other words if only the column name Z is + ** supplied) and the value of Z is enclosed in double-quotes, then + ** Z is a string literal if it doesn't match any column names. In that + ** case, we need to return right away and not make any changes to + ** pExpr. + ** + ** Because no reference was made to outer contexts, the pNC->nRef + ** fields are not changed in any context. + */ + if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){ + sqlite3DbFree(db, zCol); + return 0; + } + + /* + ** cnt==0 means there was not match. cnt>1 means there were two or + ** more matches. Either way, we have an error. + */ + if( cnt!=1 ){ + const char *zErr; + zErr = cnt==0 ? "no such column" : "ambiguous column name"; + if( zDb ){ + sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol); + }else if( zTab ){ + sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol); + }else{ + sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol); + } + pTopNC->nErr++; + } + + /* If a column from a table in pSrcList is referenced, then record + ** this fact in the pSrcList.a[].colUsed bitmask. Column 0 causes + ** bit 0 to be set. Column 1 sets bit 1. And so forth. If the + ** column number is greater than the number of bits in the bitmask + ** then set the high-order bit of the bitmask. + */ + if( pExpr->iColumn>=0 && pMatch!=0 ){ + int n = pExpr->iColumn; + testcase( n==sizeof(Bitmask)*8-1 ); + if( n>=sizeof(Bitmask)*8 ){ + n = sizeof(Bitmask)*8-1; + } + assert( pMatch->iCursor==pExpr->iTable ); + pMatch->colUsed |= ((Bitmask)1)<<n; + } + +lookupname_end: + /* Clean up and return + */ + sqlite3DbFree(db, zDb); + sqlite3DbFree(db, zTab); + sqlite3ExprDelete(db, pExpr->pLeft); + pExpr->pLeft = 0; + sqlite3ExprDelete(db, pExpr->pRight); + pExpr->pRight = 0; + pExpr->op = TK_COLUMN; +lookupname_end_2: + sqlite3DbFree(db, zCol); + if( cnt==1 ){ + assert( pNC!=0 ); + sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList); + if( pMatch && !pMatch->pSelect ){ + pExpr->pTab = pMatch->pTab; + } + /* Increment the nRef value on all name contexts from TopNC up to + ** the point where the name matched. */ + for(;;){ + assert( pTopNC!=0 ); + pTopNC->nRef++; + if( pTopNC==pNC ) break; + pTopNC = pTopNC->pNext; + } + return 0; + } else { + return 1; + } +} + +/* +** This routine is designed as an xFunc for walkExprTree(). +** +** Resolve symbolic names into TK_COLUMN operators for the current +** node in the expression tree. Return 0 to continue the search down +** the tree or 2 to abort the tree walk. +** +** This routine also does error checking and name resolution for +** function names. The operator for aggregate functions is changed +** to TK_AGG_FUNCTION. +*/ +static int nameResolverStep(void *pArg, Expr *pExpr){ + NameContext *pNC = (NameContext*)pArg; + Parse *pParse; + + if( pExpr==0 ) return 1; + assert( pNC!=0 ); + pParse = pNC->pParse; + + if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return 1; + ExprSetProperty(pExpr, EP_Resolved); +#ifndef NDEBUG + if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){ + SrcList *pSrcList = pNC->pSrcList; + int i; + for(i=0; i<pNC->pSrcList->nSrc; i++){ + assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab); + } + } +#endif + switch( pExpr->op ){ + /* Double-quoted strings (ex: "abc") are used as identifiers if + ** possible. Otherwise they remain as strings. Single-quoted + ** strings (ex: 'abc') are always string literals. + */ + case TK_STRING: { + if( pExpr->token.z[0]=='\'' ) break; + /* Fall thru into the TK_ID case if this is a double-quoted string */ + } + /* A lone identifier is the name of a column. + */ + case TK_ID: { + lookupName(pParse, 0, 0, &pExpr->token, pNC, pExpr); + return 1; + } + + /* A table name and column name: ID.ID + ** Or a database, table and column: ID.ID.ID + */ + case TK_DOT: { + Token *pColumn; + Token *pTable; + Token *pDb; + Expr *pRight; + + /* if( pSrcList==0 ) break; */ + pRight = pExpr->pRight; + if( pRight->op==TK_ID ){ + pDb = 0; + pTable = &pExpr->pLeft->token; + pColumn = &pRight->token; + }else{ + assert( pRight->op==TK_DOT ); + pDb = &pExpr->pLeft->token; + pTable = &pRight->pLeft->token; + pColumn = &pRight->pRight->token; + } + lookupName(pParse, pDb, pTable, pColumn, pNC, pExpr); + return 1; + } + + /* Resolve function names + */ + case TK_CONST_FUNC: + case TK_FUNCTION: { + ExprList *pList = pExpr->pList; /* The argument list */ + int n = pList ? pList->nExpr : 0; /* Number of arguments */ + int no_such_func = 0; /* True if no such function exists */ + int wrong_num_args = 0; /* True if wrong number of arguments */ + int is_agg = 0; /* True if is an aggregate function */ + int i; + int auth; /* Authorization to use the function */ + int nId; /* Number of characters in function name */ + const char *zId; /* The function name. */ + FuncDef *pDef; /* Information about the function */ + int enc = ENC(pParse->db); /* The database encoding */ + + zId = (char*)pExpr->token.z; + nId = pExpr->token.n; + pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); + if( pDef==0 ){ + pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0); + if( pDef==0 ){ + no_such_func = 1; + }else{ + wrong_num_args = 1; + } + }else{ + is_agg = pDef->xFunc==0; + } +#ifndef SQLITE_OMIT_AUTHORIZATION + if( pDef ){ + auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0); + if( auth!=SQLITE_OK ){ + if( auth==SQLITE_DENY ){ + sqlite3ErrorMsg(pParse, "not authorized to use function: %s", + pDef->zName); + pNC->nErr++; + } + pExpr->op = TK_NULL; + return 1; + } + } +#endif + if( is_agg && !pNC->allowAgg ){ + sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); + pNC->nErr++; + is_agg = 0; + }else if( no_such_func ){ + sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId); + pNC->nErr++; + }else if( wrong_num_args ){ + sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()", + nId, zId); + pNC->nErr++; + } + if( is_agg ){ + pExpr->op = TK_AGG_FUNCTION; + pNC->hasAgg = 1; + } + if( is_agg ) pNC->allowAgg = 0; + for(i=0; pNC->nErr==0 && i<n; i++){ + walkExprTree(pList->a[i].pExpr, nameResolverStep, pNC); + } + if( is_agg ) pNC->allowAgg = 1; + /* FIX ME: Compute pExpr->affinity based on the expected return + ** type of the function + */ + return is_agg; + } +#ifndef SQLITE_OMIT_SUBQUERY + case TK_SELECT: + case TK_EXISTS: +#endif + case TK_IN: { + if( pExpr->pSelect ){ + int nRef = pNC->nRef; +#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; +} + +/* +** This routine walks an expression tree and resolves references to +** table columns. Nodes of the form ID.ID or ID resolve into an +** index to the table in the table list and a column offset. The +** Expr.opcode for such nodes is changed to TK_COLUMN. The Expr.iTable +** value is changed to the index of the referenced table in pTabList +** plus the "base" value. The base value will ultimately become the +** VDBE cursor number for a cursor that is pointing into the referenced +** table. The Expr.iColumn value is changed to the index of the column +** of the referenced table. The Expr.iColumn value for the special +** ROWID column is -1. Any INTEGER PRIMARY KEY column is tried as an +** alias for ROWID. +** +** Also resolve function names and check the functions for proper +** usage. Make sure all function names are recognized and all functions +** have the correct number of arguments. Leave an error message +** in pParse->zErrMsg if anything is amiss. Return the number of errors. +** +** If the expression contains aggregate functions then set the EP_Agg +** property on the expression. +*/ +int sqlite3ExprResolveNames( + NameContext *pNC, /* Namespace to resolve expressions in. */ + Expr *pExpr /* The expression to be analyzed. */ +){ + int savedHasAgg; + + if( pExpr==0 ) return 0; +#if SQLITE_MAX_EXPR_DEPTH>0 + { + if( checkExprHeight(pNC->pParse, pExpr->nHeight + pNC->pParse->nHeight) ){ + return 1; + } + pNC->pParse->nHeight += pExpr->nHeight; + } +#endif + savedHasAgg = pNC->hasAgg; + pNC->hasAgg = 0; + walkExprTree(pExpr, nameResolverStep, pNC); +#if SQLITE_MAX_EXPR_DEPTH>0 + pNC->pParse->nHeight -= pExpr->nHeight; +#endif + if( pNC->nErr>0 ){ + ExprSetProperty(pExpr, EP_Error); + } + if( pNC->hasAgg ){ + ExprSetProperty(pExpr, EP_Agg); + }else if( savedHasAgg ){ + pNC->hasAgg = 1; + } + return ExprHasProperty(pExpr, EP_Error); +} + +/* +** A pointer instance of this structure is used to pass information +** through walkExprTree into codeSubqueryStep(). +*/ +typedef struct QueryCoder QueryCoder; +struct QueryCoder { + Parse *pParse; /* The parsing context */ + NameContext *pNC; /* Namespace of first enclosing query */ +}; + +#ifdef SQLITE_TEST + int sqlite3_enable_in_opt = 1; +#else + #define sqlite3_enable_in_opt 1 +#endif + +/* +** Return true if the IN operator optimization is enabled and +** the SELECT statement p exists and is of the +** simple form: +** +** SELECT <column> FROM <table> +** +** If this is the case, it may be possible to use an existing table +** or index instead of generating an epheremal table. +*/ +#ifndef SQLITE_OMIT_SUBQUERY +static int isCandidateForInOpt(Select *p){ + SrcList *pSrc; + ExprList *pEList; + Table *pTab; + if( !sqlite3_enable_in_opt ) return 0; /* IN optimization must be enabled */ + if( p==0 ) return 0; /* right-hand side of IN is SELECT */ + if( p->pPrior ) return 0; /* Not a compound SELECT */ + if( p->isDistinct ) return 0; /* No DISTINCT keyword */ + if( p->isAgg ) return 0; /* Contains no aggregate functions */ + if( p->pGroupBy ) return 0; /* Has no GROUP BY clause */ + if( p->pLimit ) return 0; /* Has no LIMIT clause */ + if( p->pOffset ) return 0; + if( p->pWhere ) return 0; /* Has no WHERE clause */ + pSrc = p->pSrc; + if( pSrc==0 ) return 0; /* A single table in the FROM clause */ + if( pSrc->nSrc!=1 ) return 0; + if( pSrc->a[0].pSelect ) return 0; /* FROM clause is not a subquery */ + pTab = pSrc->a[0].pTab; + if( pTab==0 ) return 0; + if( pTab->pSelect ) return 0; /* FROM clause is not a view */ + if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */ + pEList = p->pEList; + if( pEList->nExpr!=1 ) return 0; /* One column in the result set */ + if( pEList->a[0].pExpr->op!=TK_COLUMN ) return 0; /* Result is a column */ + return 1; +} +#endif /* SQLITE_OMIT_SUBQUERY */ + +/* +** This function is used by the implementation of the IN (...) operator. +** It's job is to find or create a b-tree structure that may be used +** either to test for membership of the (...) set or to iterate through +** its members, skipping duplicates. +** +** The cursor opened on the structure (database table, database index +** or ephermal table) is stored in pX->iTable before this function returns. +** The returned value indicates the structure type, as follows: +** +** IN_INDEX_ROWID - The cursor was opened on a database table. +** IN_INDEX_INDEX - The cursor was opened on a database index. +** IN_INDEX_EPH - The cursor was opened on a specially created and +** populated epheremal table. +** +** An existing structure may only be used if the SELECT is of the simple +** form: +** +** SELECT <column> FROM <table> +** +** If prNotFound parameter is 0, then the structure will be used to iterate +** through the set members, skipping any duplicates. In this case an +** epheremal table must be used unless the selected <column> is guaranteed +** to be unique - either because it is an INTEGER PRIMARY KEY or it +** is unique by virtue of a constraint or implicit index. +** +** If the prNotFound parameter is not 0, then the structure will be used +** for fast set membership tests. In this case an epheremal table must +** be used unless <column> is an INTEGER PRIMARY KEY or an index can +** be found with <column> as its left-most column. +** +** When the structure is being used for set membership tests, the user +** needs to know whether or not the structure contains an SQL NULL +** value in order to correctly evaluate expressions like "X IN (Y, Z)". +** If there is a chance that the structure may contain a NULL value at +** runtime, then a register is allocated and the register number written +** to *prNotFound. If there is no chance that the structure contains a +** NULL value, then *prNotFound is left unchanged. +** +** If a register is allocated and its location stored in *prNotFound, then +** its initial value is NULL. If the structure does not remain constant +** for the duration of the query (i.e. the set is a correlated sub-select), +** the value of the allocated register is reset to NULL each time the +** structure is repopulated. This allows the caller to use vdbe code +** equivalent to the following: +** +** if( register==NULL ){ +** has_null = <test if data structure contains null> +** register = 1 +** } +** +** in order to avoid running the <test if data structure contains null> +** test more often than is necessary. +*/ +#ifndef SQLITE_OMIT_SUBQUERY +int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){ + Select *p; + int eType = 0; + int iTab = pParse->nTab++; + int mustBeUnique = !prNotFound; + + /* The follwing if(...) expression is true if the SELECT is of the + ** simple form: + ** + ** SELECT <column> FROM <table> + ** + ** If this is the case, it may be possible to use an existing table + ** or index instead of generating an epheremal table. + */ + p = pX->pSelect; + if( isCandidateForInOpt(p) ){ + sqlite3 *db = pParse->db; + Index *pIdx; + Expr *pExpr = p->pEList->a[0].pExpr; + int iCol = pExpr->iColumn; + Vdbe *v = sqlite3GetVdbe(pParse); + + /* This function is only called from two places. In both cases the vdbe + ** has already been allocated. So assume sqlite3GetVdbe() is always + ** successful here. + */ + assert(v); + if( iCol<0 ){ + int iMem = ++pParse->nMem; + int iAddr; + Table *pTab = p->pSrc->a[0].pTab; + int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + sqlite3VdbeUsesBtree(v, iDb); + + iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem); + sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem); + + sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); + eType = IN_INDEX_ROWID; + + sqlite3VdbeJumpHere(v, iAddr); + }else{ + /* The collation sequence used by the comparison. If an index is to + ** be used in place of a temp-table, it must be ordered according + ** to this collation sequence. + */ + CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pExpr); + + /* Check that the affinity that will be used to perform the + ** comparison is the same as the affinity of the column. If + ** it is not, it is not possible to use any index. + */ + Table *pTab = p->pSrc->a[0].pTab; + char aff = comparisonAffinity(pX); + int affinity_ok = (pTab->aCol[iCol].affinity==aff||aff==SQLITE_AFF_NONE); + + for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){ + if( (pIdx->aiColumn[0]==iCol) + && (pReq==sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], -1, 0)) + && (!mustBeUnique || (pIdx->nColumn==1 && pIdx->onError!=OE_None)) + ){ + int iDb; + int iMem = ++pParse->nMem; + int iAddr; + char *pKey; + + pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx); + iDb = sqlite3SchemaToIndex(db, pIdx->pSchema); + sqlite3VdbeUsesBtree(v, iDb); + + iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem); + sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem); + + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pIdx->nColumn); + sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb, + pKey,P4_KEYINFO_HANDOFF); + VdbeComment((v, "%s", pIdx->zName)); + eType = IN_INDEX_INDEX; + + sqlite3VdbeJumpHere(v, iAddr); + if( prNotFound && !pTab->aCol[iCol].notNull ){ + *prNotFound = ++pParse->nMem; + } + } + } + } + } + + if( eType==0 ){ + int rMayHaveNull = 0; + if( prNotFound ){ + *prNotFound = rMayHaveNull = ++pParse->nMem; + } + sqlite3CodeSubselect(pParse, pX, rMayHaveNull); + eType = IN_INDEX_EPH; + }else{ + pX->iTable = iTab; + } + return eType; +} +#endif + +/* +** Generate code for scalar subqueries used as an expression +** and IN operators. Examples: +** +** (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 +** +** The pExpr parameter describes the expression that contains the IN +** operator or subquery. +*/ +#ifndef SQLITE_OMIT_SUBQUERY +void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr, int rMayHaveNull){ + int testAddr = 0; /* One-time test address */ + Vdbe *v = sqlite3GetVdbe(pParse); + if( v==0 ) return; + + + /* This code must be run in its entirety every time it is encountered + ** if any of the following is true: + ** + ** * The right-hand side is a correlated subquery + ** * The right-hand side is an expression list containing variables + ** * We are inside a trigger + ** + ** If all of the above are false, then we can run this code just once + ** save the results, and reuse the same result on subsequent invocations. + */ + if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->trigStack ){ + int mem = ++pParse->nMem; + sqlite3VdbeAddOp1(v, OP_If, mem); + testAddr = sqlite3VdbeAddOp2(v, OP_Integer, 1, mem); + assert( testAddr>0 || pParse->db->mallocFailed ); + } + + switch( pExpr->op ){ + case TK_IN: { + char affinity; + KeyInfo keyInfo; + int addr; /* Address of OP_OpenEphemeral instruction */ + + if( rMayHaveNull ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, rMayHaveNull); + } + + affinity = sqlite3ExprAffinity(pExpr->pLeft); + + /* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)' + ** expression it is handled the same way. A virtual table is + ** filled with single-field index keys representing the results + ** from the SELECT or the <exprlist>. + ** + ** If the 'x' expression is a column value, or the SELECT... + ** statement returns a column value, then the affinity of that + ** column is used to build the index keys. If both 'x' and the + ** SELECT... statement are columns, then numeric affinity is used + ** if either column has NUMERIC or INTEGER affinity. If neither + ** 'x' nor the SELECT... statement are columns, then numeric affinity + ** is used. + */ + pExpr->iTable = pParse->nTab++; + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, 1); + memset(&keyInfo, 0, sizeof(keyInfo)); + keyInfo.nField = 1; + + if( pExpr->pSelect ){ + /* Case 1: expr IN (SELECT ...) + ** + ** Generate code to write the results of the select into the temporary + ** table allocated and opened above. + */ + SelectDest dest; + ExprList *pEList; + + sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable); + dest.affinity = (int)affinity; + assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); + if( sqlite3Select(pParse, pExpr->pSelect, &dest, 0, 0, 0) ){ + return; + } + pEList = pExpr->pSelect->pEList; + if( pEList && pEList->nExpr>0 ){ + keyInfo.aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, + pEList->a[0].pExpr); + } + }else if( pExpr->pList ){ + /* Case 2: expr IN (exprlist) + ** + ** For each expression, build an index key from the evaluation and + ** store it in the temporary table. If <expr> is a column, then use + ** that columns affinity when building index keys. If <expr> is not + ** a column, use numeric affinity. + */ + int i; + ExprList *pList = pExpr->pList; + struct ExprList_item *pItem; + int r1, r2, r3; + + if( !affinity ){ + affinity = SQLITE_AFF_NONE; + } + keyInfo.aColl[0] = pExpr->pLeft->pColl; + + /* Loop through each expression in <exprlist>. */ + r1 = sqlite3GetTempReg(pParse); + r2 = sqlite3GetTempReg(pParse); + for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){ + Expr *pE2 = pItem->pExpr; + + /* If the expression is not constant then we will need to + ** disable the test that was generated above that makes sure + ** this code only executes once. Because for a non-constant + ** expression we need to rerun this code each time. + */ + if( testAddr && !sqlite3ExprIsConstant(pE2) ){ + sqlite3VdbeChangeToNoop(v, testAddr-1, 2); + testAddr = 0; + } + + /* Evaluate the expression and insert it into the temp table */ + pParse->disableColCache++; + r3 = sqlite3ExprCodeTarget(pParse, pE2, r1); + assert( pParse->disableColCache>0 ); + pParse->disableColCache--; + sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1); + sqlite3ExprCacheAffinityChange(pParse, r3, 1); + sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2); + } + sqlite3ReleaseTempReg(pParse, r1); + sqlite3ReleaseTempReg(pParse, r2); + } + sqlite3VdbeChangeP4(v, addr, (void *)&keyInfo, P4_KEYINFO); + break; + } + + case TK_EXISTS: + case TK_SELECT: { + /* This has to be a scalar SELECT. Generate code to put the + ** value of this select in a memory cell and record the number + ** of the memory cell in iColumn. + */ + static const Token one = { (u8*)"1", 0, 1 }; + Select *pSel; + SelectDest dest; + + pSel = pExpr->pSelect; + sqlite3SelectDestInit(&dest, 0, ++pParse->nMem); + if( pExpr->op==TK_SELECT ){ + dest.eDest = SRT_Mem; + sqlite3VdbeAddOp2(v, OP_Null, 0, dest.iParm); + VdbeComment((v, "Init subquery result")); + }else{ + dest.eDest = SRT_Exists; + sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iParm); + VdbeComment((v, "Init EXISTS result")); + } + sqlite3ExprDelete(pParse->db, pSel->pLimit); + pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &one); + if( sqlite3Select(pParse, pSel, &dest, 0, 0, 0) ){ + return; + } + pExpr->iColumn = dest.iParm; + break; + } + } + + if( testAddr ){ + sqlite3VdbeJumpHere(v, testAddr-1); + } + + return; +} +#endif /* SQLITE_OMIT_SUBQUERY */ + +/* +** Duplicate an 8-byte value +*/ +static char *dup8bytes(Vdbe *v, const char *in){ + char *out = sqlite3DbMallocRaw(sqlite3VdbeDb(v), 8); + if( out ){ + memcpy(out, in, 8); + } + return out; +} + +/* +** Generate an instruction that will put the floating point +** value described by z[0..n-1] into register iMem. +** +** The z[] string will probably not be zero-terminated. But the +** z[n] character is guaranteed to be something that does not look +** like the continuation of the number. +*/ +static void codeReal(Vdbe *v, const char *z, int n, int negateFlag, int iMem){ + assert( z || v==0 || sqlite3VdbeDb(v)->mallocFailed ); + if( z ){ + double value; + char *zV; + assert( !isdigit(z[n]) ); + sqlite3AtoF(z, &value); + if( sqlite3IsNaN(value) ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, iMem); + }else{ + if( negateFlag ) value = -value; + zV = dup8bytes(v, (char*)&value); + sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL); + } + } +} + + +/* +** Generate an instruction that will put the integer describe by +** text z[0..n-1] into register iMem. +** +** The z[] string will probably not be zero-terminated. But the +** z[n] character is guaranteed to be something that does not look +** like the continuation of the number. +*/ +static void codeInteger(Vdbe *v, Expr *pExpr, int negFlag, int iMem){ + const char *z; + if( pExpr->flags & EP_IntValue ){ + int i = pExpr->iTable; + if( negFlag ) i = -i; + sqlite3VdbeAddOp2(v, OP_Integer, i, iMem); + }else if( (z = (char*)pExpr->token.z)!=0 ){ + int i; + int n = pExpr->token.n; + assert( !isdigit(z[n]) ); + if( sqlite3GetInt32(z, &i) ){ + if( negFlag ) i = -i; + sqlite3VdbeAddOp2(v, OP_Integer, i, iMem); + }else if( sqlite3FitsIn64Bits(z, negFlag) ){ + i64 value; + char *zV; + sqlite3Atoi64(z, &value); + if( negFlag ) value = -value; + zV = dup8bytes(v, (char*)&value); + sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64); + }else{ + codeReal(v, z, n, negFlag, iMem); + } + } +} + + +/* +** Generate code that will extract the iColumn-th column from +** table pTab and store the column value in a register. An effort +** is made to store the column value in register iReg, but this is +** not guaranteed. The location of the column value is returned. +** +** There must be an open cursor to pTab in iTable when this routine +** is called. If iColumn<0 then code is generated that extracts the rowid. +** +** This routine might attempt to reuse the value of the column that +** has already been loaded into a register. The value will always +** be used if it has not undergone any affinity changes. But if +** an affinity change has occurred, then the cached value will only be +** used if allowAffChng is true. +*/ +int sqlite3ExprCodeGetColumn( + Parse *pParse, /* Parsing and code generating context */ + Table *pTab, /* Description of the table we are reading from */ + int iColumn, /* Index of the table column */ + int iTable, /* The cursor pointing to the table */ + int iReg, /* Store results here */ + int allowAffChng /* True if prior affinity changes are OK */ +){ + Vdbe *v = pParse->pVdbe; + int i; + struct yColCache *p; + + for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){ + if( p->iTable==iTable && p->iColumn==iColumn + && (!p->affChange || allowAffChng) ){ +#if 0 + sqlite3VdbeAddOp0(v, OP_Noop); + VdbeComment((v, "OPT: tab%d.col%d -> r%d", iTable, iColumn, p->iReg)); +#endif + return p->iReg; + } + } + assert( v!=0 ); + if( iColumn<0 ){ + int op = (pTab && IsVirtual(pTab)) ? OP_VRowid : OP_Rowid; + sqlite3VdbeAddOp2(v, op, iTable, iReg); + }else if( pTab==0 ){ + sqlite3VdbeAddOp3(v, OP_Column, iTable, iColumn, iReg); + }else{ + int op = IsVirtual(pTab) ? OP_VColumn : OP_Column; + sqlite3VdbeAddOp3(v, op, iTable, iColumn, iReg); + sqlite3ColumnDefault(v, pTab, iColumn); +#ifndef SQLITE_OMIT_FLOATING_POINT + if( pTab->aCol[iColumn].affinity==SQLITE_AFF_REAL ){ + sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg); + } +#endif + } + if( pParse->disableColCache==0 ){ + i = pParse->iColCache; + p = &pParse->aColCache[i]; + p->iTable = iTable; + p->iColumn = iColumn; + p->iReg = iReg; + p->affChange = 0; + i++; + if( i>=ArraySize(pParse->aColCache) ) i = 0; + if( i>pParse->nColCache ) pParse->nColCache = i; + pParse->iColCache = i; + } + return iReg; +} + +/* +** Clear all column cache entries associated with the vdbe +** cursor with cursor number iTable. +*/ +void sqlite3ExprClearColumnCache(Parse *pParse, int iTable){ + if( iTable<0 ){ + pParse->nColCache = 0; + pParse->iColCache = 0; + }else{ + int i; + for(i=0; i<pParse->nColCache; i++){ + if( pParse->aColCache[i].iTable==iTable ){ + testcase( i==pParse->nColCache-1 ); + pParse->aColCache[i] = pParse->aColCache[--pParse->nColCache]; + pParse->iColCache = pParse->nColCache; + } + } + } +} + +/* +** Record the fact that an affinity change has occurred on iCount +** registers starting with iStart. +*/ +void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){ + int iEnd = iStart + iCount - 1; + int i; + for(i=0; i<pParse->nColCache; i++){ + int r = pParse->aColCache[i].iReg; + if( r>=iStart && r<=iEnd ){ + pParse->aColCache[i].affChange = 1; + } + } +} + +/* +** Generate code to move content from registers iFrom...iFrom+nReg-1 +** over to iTo..iTo+nReg-1. Keep the column cache up-to-date. +*/ +void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){ + int i; + if( iFrom==iTo ) return; + sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg); + for(i=0; i<pParse->nColCache; i++){ + int x = pParse->aColCache[i].iReg; + if( x>=iFrom && x<iFrom+nReg ){ + pParse->aColCache[i].iReg += iTo-iFrom; + } + } +} + +/* +** Generate code to copy content from registers iFrom...iFrom+nReg-1 +** over to iTo..iTo+nReg-1. +*/ +void sqlite3ExprCodeCopy(Parse *pParse, int iFrom, int iTo, int nReg){ + int i; + if( iFrom==iTo ) return; + for(i=0; i<nReg; i++){ + sqlite3VdbeAddOp2(pParse->pVdbe, OP_Copy, iFrom+i, iTo+i); + } +} + +/* +** Return true if any register in the range iFrom..iTo (inclusive) +** is used as part of the column cache. +*/ +static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){ + int i; + for(i=0; i<pParse->nColCache; i++){ + int r = pParse->aColCache[i].iReg; + if( r>=iFrom && r<=iTo ) return 1; + } + return 0; +} + +/* +** Theres is a value in register iCurrent. We ultimately want +** the value to be in register iTarget. It might be that +** iCurrent and iTarget are the same register. +** +** We are going to modify the value, so we need to make sure it +** is not a cached register. If iCurrent is a cached register, +** then try to move the value over to iTarget. If iTarget is a +** cached register, then clear the corresponding cache line. +** +** Return the register that the value ends up in. +*/ +int sqlite3ExprWritableRegister(Parse *pParse, int iCurrent, int iTarget){ + int i; + assert( pParse->pVdbe!=0 ); + if( !usedAsColumnCache(pParse, iCurrent, iCurrent) ){ + return iCurrent; + } + if( iCurrent!=iTarget ){ + sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, iCurrent, iTarget); + } + for(i=0; i<pParse->nColCache; i++){ + if( pParse->aColCache[i].iReg==iTarget ){ + pParse->aColCache[i] = pParse->aColCache[--pParse->nColCache]; + pParse->iColCache = pParse->nColCache; + } + } + return iTarget; +} + +/* +** If the last instruction coded is an ephemeral copy of any of +** the registers in the nReg registers beginning with iReg, then +** convert the last instruction from OP_SCopy to OP_Copy. +*/ +void sqlite3ExprHardCopy(Parse *pParse, int iReg, int nReg){ + int addr; + VdbeOp *pOp; + Vdbe *v; + + v = pParse->pVdbe; + addr = sqlite3VdbeCurrentAddr(v); + pOp = sqlite3VdbeGetOp(v, addr-1); + assert( pOp || pParse->db->mallocFailed ); + if( pOp && pOp->opcode==OP_SCopy && pOp->p1>=iReg && pOp->p1<iReg+nReg ){ + pOp->opcode = OP_Copy; + } +} + +/* +** Generate code into the current Vdbe to evaluate the given +** expression. Attempt to store the results in register "target". +** Return the register where results are stored. +** +** With this routine, there is no guaranteed that results will +** be stored in target. The result might be stored in some other +** register if it is convenient to do so. The calling function +** must check the return code and move the results to the desired +** register. +*/ +int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ + Vdbe *v = pParse->pVdbe; /* The VM under construction */ + int op; /* The opcode being coded */ + int inReg = target; /* Results stored in register inReg */ + int regFree1 = 0; /* If non-zero free this temporary register */ + int regFree2 = 0; /* If non-zero free this temporary register */ + int r1, r2, r3, r4; /* Various register numbers */ + + assert( v!=0 || pParse->db->mallocFailed ); + assert( target>0 && target<=pParse->nMem ); + if( v==0 ) return 0; + + if( pExpr==0 ){ + op = TK_NULL; + }else{ + op = pExpr->op; + } + switch( op ){ + case TK_AGG_COLUMN: { + AggInfo *pAggInfo = pExpr->pAggInfo; + struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg]; + if( !pAggInfo->directMode ){ + assert( pCol->iMem>0 ); + inReg = pCol->iMem; + break; + }else if( pAggInfo->useSortingIdx ){ + sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdx, + pCol->iSorterColumn, target); + break; + } + /* Otherwise, fall thru into the TK_COLUMN case */ + } + case TK_COLUMN: { + if( pExpr->iTable<0 ){ + /* This only happens when coding check constraints */ + assert( pParse->ckBase>0 ); + inReg = pExpr->iColumn + pParse->ckBase; + }else{ + testcase( (pExpr->flags & EP_AnyAff)!=0 ); + inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab, + pExpr->iColumn, pExpr->iTable, target, + pExpr->flags & EP_AnyAff); + } + break; + } + case TK_INTEGER: { + codeInteger(v, pExpr, 0, target); + break; + } + case TK_FLOAT: { + codeReal(v, (char*)pExpr->token.z, pExpr->token.n, 0, target); + break; + } + case TK_STRING: { + sqlite3DequoteExpr(pParse->db, pExpr); + sqlite3VdbeAddOp4(v,OP_String8, 0, target, 0, + (char*)pExpr->token.z, pExpr->token.n); + break; + } + case TK_NULL: { + sqlite3VdbeAddOp2(v, OP_Null, 0, target); + break; + } +#ifndef SQLITE_OMIT_BLOB_LITERAL + case TK_BLOB: { + int n; + const char *z; + char *zBlob; + assert( pExpr->token.n>=3 ); + assert( pExpr->token.z[0]=='x' || pExpr->token.z[0]=='X' ); + assert( pExpr->token.z[1]=='\'' ); + assert( pExpr->token.z[pExpr->token.n-1]=='\'' ); + n = pExpr->token.n - 3; + z = (char*)pExpr->token.z + 2; + zBlob = sqlite3HexToBlob(sqlite3VdbeDb(v), z, n); + sqlite3VdbeAddOp4(v, OP_Blob, n/2, target, 0, zBlob, P4_DYNAMIC); + break; + } +#endif + case TK_VARIABLE: { + sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iTable, target); + if( pExpr->token.n>1 ){ + sqlite3VdbeChangeP4(v, -1, (char*)pExpr->token.z, pExpr->token.n); + } + break; + } + case TK_REGISTER: { + inReg = pExpr->iTable; + break; + } +#ifndef SQLITE_OMIT_CAST + case TK_CAST: { + /* Expressions of the form: CAST(pLeft AS token) */ + int aff, to_op; + inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); + aff = sqlite3AffinityType(&pExpr->token); + 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 ); + testcase( to_op==OP_ToText ); + testcase( to_op==OP_ToBlob ); + testcase( to_op==OP_ToNumeric ); + testcase( to_op==OP_ToInt ); + testcase( to_op==OP_ToReal ); + sqlite3VdbeAddOp1(v, to_op, inReg); + testcase( usedAsColumnCache(pParse, inReg, inReg) ); + sqlite3ExprCacheAffinityChange(pParse, inReg, 1); + break; + } +#endif /* SQLITE_OMIT_CAST */ + case TK_LT: + case TK_LE: + case TK_GT: + case TK_GE: + case TK_NE: + case TK_EQ: { + assert( TK_LT==OP_Lt ); + assert( TK_LE==OP_Le ); + assert( TK_GT==OP_Gt ); + assert( TK_GE==OP_Ge ); + assert( TK_EQ==OP_Eq ); + assert( TK_NE==OP_Ne ); + testcase( op==TK_LT ); + testcase( op==TK_LE ); + testcase( op==TK_GT ); + testcase( op==TK_GE ); + testcase( op==TK_EQ ); + testcase( op==TK_NE ); + codeCompareOperands(pParse, pExpr->pLeft, &r1, ®Free1, + pExpr->pRight, &r2, ®Free2); + codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, + r1, r2, inReg, SQLITE_STOREP2); + testcase( regFree1==0 ); + testcase( regFree2==0 ); + break; + } + case TK_AND: + case TK_OR: + case TK_PLUS: + case TK_STAR: + case TK_MINUS: + case TK_REM: + case TK_BITAND: + case TK_BITOR: + case TK_SLASH: + case TK_LSHIFT: + case TK_RSHIFT: + case TK_CONCAT: { + assert( TK_AND==OP_And ); + assert( TK_OR==OP_Or ); + assert( TK_PLUS==OP_Add ); + assert( TK_MINUS==OP_Subtract ); + assert( TK_REM==OP_Remainder ); + assert( TK_BITAND==OP_BitAnd ); + assert( TK_BITOR==OP_BitOr ); + assert( TK_SLASH==OP_Divide ); + assert( TK_LSHIFT==OP_ShiftLeft ); + assert( TK_RSHIFT==OP_ShiftRight ); + assert( TK_CONCAT==OP_Concat ); + testcase( op==TK_AND ); + testcase( op==TK_OR ); + testcase( op==TK_PLUS ); + testcase( op==TK_MINUS ); + testcase( op==TK_REM ); + testcase( op==TK_BITAND ); + testcase( op==TK_BITOR ); + testcase( op==TK_SLASH ); + testcase( op==TK_LSHIFT ); + testcase( op==TK_RSHIFT ); + testcase( op==TK_CONCAT ); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); + sqlite3VdbeAddOp3(v, op, r2, r1, target); + testcase( regFree1==0 ); + testcase( regFree2==0 ); + break; + } + case TK_UMINUS: { + Expr *pLeft = pExpr->pLeft; + assert( pLeft ); + if( pLeft->op==TK_FLOAT || pLeft->op==TK_INTEGER ){ + if( pLeft->op==TK_FLOAT ){ + codeReal(v, (char*)pLeft->token.z, pLeft->token.n, 1, target); + }else{ + codeInteger(v, pLeft, 1, target); + } + }else{ + regFree1 = r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp2(v, OP_Integer, 0, r1); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free2); + sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target); + testcase( regFree2==0 ); + } + inReg = target; + break; + } + case TK_BITNOT: + case TK_NOT: { + assert( TK_BITNOT==OP_BitNot ); + assert( TK_NOT==OP_Not ); + testcase( op==TK_BITNOT ); + testcase( op==TK_NOT ); + inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); + testcase( inReg==target ); + testcase( usedAsColumnCache(pParse, inReg, inReg) ); + inReg = sqlite3ExprWritableRegister(pParse, inReg, target); + sqlite3VdbeAddOp1(v, op, inReg); + break; + } + case TK_ISNULL: + case TK_NOTNULL: { + int addr; + assert( TK_ISNULL==OP_IsNull ); + assert( TK_NOTNULL==OP_NotNull ); + testcase( op==TK_ISNULL ); + testcase( op==TK_NOTNULL ); + sqlite3VdbeAddOp2(v, OP_Integer, 1, target); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + testcase( regFree1==0 ); + addr = sqlite3VdbeAddOp1(v, op, r1); + sqlite3VdbeAddOp2(v, OP_AddImm, target, -1); + sqlite3VdbeJumpHere(v, addr); + break; + } + case TK_AGG_FUNCTION: { + AggInfo *pInfo = pExpr->pAggInfo; + if( pInfo==0 ){ + sqlite3ErrorMsg(pParse, "misuse of aggregate: %T", + &pExpr->span); + }else{ + inReg = pInfo->aFunc[pExpr->iAgg].iMem; + } + break; + } + case TK_CONST_FUNC: + case TK_FUNCTION: { + ExprList *pList = pExpr->pList; + int nExpr = pList ? pList->nExpr : 0; + FuncDef *pDef; + int nId; + const char *zId; + int constMask = 0; + int i; + sqlite3 *db = pParse->db; + u8 enc = ENC(db); + CollSeq *pColl = 0; + + testcase( op==TK_CONST_FUNC ); + testcase( op==TK_FUNCTION ); + zId = (char*)pExpr->token.z; + nId = pExpr->token.n; + pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0); + assert( pDef!=0 ); + if( pList ){ + nExpr = pList->nExpr; + r1 = sqlite3GetTempRange(pParse, nExpr); + sqlite3ExprCodeExprList(pParse, pList, r1, 1); + }else{ + nExpr = r1 = 0; + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + /* Possibly overload the function if the first argument is + ** a virtual table column. + ** + ** For infix functions (LIKE, GLOB, REGEXP, and MATCH) use the + ** second argument, not the first, as the argument to test to + ** see if it is a column in a virtual table. This is done because + ** the left operand of infix functions (the operand we want to + ** control overloading) ends up as the second argument to the + ** function. The expression "A glob B" is equivalent to + ** "glob(B,A). We want to use the A in "A glob B" to test + ** for function overloading. But we use the B term in "glob(B,A)". + */ + if( nExpr>=2 && (pExpr->flags & EP_InfixFunc) ){ + pDef = sqlite3VtabOverloadFunction(db, pDef, nExpr, pList->a[1].pExpr); + }else if( nExpr>0 ){ + pDef = sqlite3VtabOverloadFunction(db, pDef, nExpr, pList->a[0].pExpr); + } +#endif + for(i=0; i<nExpr && i<32; i++){ + if( sqlite3ExprIsConstant(pList->a[i].pExpr) ){ + constMask |= (1<<i); + } + if( pDef->needCollSeq && !pColl ){ + pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr); + } + } + if( pDef->needCollSeq ){ + if( !pColl ) pColl = pParse->db->pDfltColl; + sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); + } + sqlite3VdbeAddOp4(v, OP_Function, constMask, r1, target, + (char*)pDef, P4_FUNCDEF); + sqlite3VdbeChangeP5(v, nExpr); + if( nExpr ){ + sqlite3ReleaseTempRange(pParse, r1, nExpr); + } + sqlite3ExprCacheAffinityChange(pParse, r1, nExpr); + break; + } +#ifndef SQLITE_OMIT_SUBQUERY + case TK_EXISTS: + case TK_SELECT: { + testcase( op==TK_EXISTS ); + testcase( op==TK_SELECT ); + if( pExpr->iColumn==0 ){ + sqlite3CodeSubselect(pParse, pExpr, 0); + } + inReg = pExpr->iColumn; + break; + } + case TK_IN: { + int rNotFound = 0; + int rMayHaveNull = 0; + int j2, j3, j4, j5; + char affinity; + int eType; + + VdbeNoopComment((v, "begin IN expr r%d", target)); + eType = sqlite3FindInIndex(pParse, pExpr, &rMayHaveNull); + if( rMayHaveNull ){ + rNotFound = ++pParse->nMem; + } + + /* Figure out the affinity to use to create a key from the results + ** of the expression. affinityStr stores a static string suitable for + ** P4 of OP_MakeRecord. + */ + affinity = comparisonAffinity(pExpr); + + + /* Code the <expr> from "<expr> IN (...)". The temporary table + ** pExpr->iTable contains the values that make up the (...) set. + */ + pParse->disableColCache++; + sqlite3ExprCode(pParse, pExpr->pLeft, target); + pParse->disableColCache--; + j2 = sqlite3VdbeAddOp1(v, OP_IsNull, target); + if( eType==IN_INDEX_ROWID ){ + j3 = sqlite3VdbeAddOp1(v, OP_MustBeInt, target); + j4 = sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, 0, target); + sqlite3VdbeAddOp2(v, OP_Integer, 1, target); + j5 = sqlite3VdbeAddOp0(v, OP_Goto); + sqlite3VdbeJumpHere(v, j3); + sqlite3VdbeJumpHere(v, j4); + sqlite3VdbeAddOp2(v, OP_Integer, 0, target); + }else{ + r2 = regFree2 = sqlite3GetTempReg(pParse); + + /* Create a record and test for set membership. If the set contains + ** the value, then jump to the end of the test code. The target + ** register still contains the true (1) value written to it earlier. + */ + sqlite3VdbeAddOp4(v, OP_MakeRecord, target, 1, r2, &affinity, 1); + sqlite3VdbeAddOp2(v, OP_Integer, 1, target); + j5 = sqlite3VdbeAddOp3(v, OP_Found, pExpr->iTable, 0, r2); + + /* If the set membership test fails, then the result of the + ** "x IN (...)" expression must be either 0 or NULL. If the set + ** contains no NULL values, then the result is 0. If the set + ** contains one or more NULL values, then the result of the + ** expression is also NULL. + */ + if( rNotFound==0 ){ + /* This branch runs if it is known at compile time (now) that + ** the set contains no NULL values. This happens as the result + ** of a "NOT NULL" constraint in the database schema. No need + ** to test the data structure at runtime in this case. + */ + sqlite3VdbeAddOp2(v, OP_Integer, 0, target); + }else{ + /* This block populates the rNotFound register with either NULL + ** or 0 (an integer value). If the data structure contains one + ** or more NULLs, then set rNotFound to NULL. Otherwise, set it + ** to 0. If register rMayHaveNull is already set to some value + ** other than NULL, then the test has already been run and + ** rNotFound is already populated. + */ + static const char nullRecord[] = { 0x02, 0x00 }; + j3 = sqlite3VdbeAddOp1(v, OP_NotNull, rMayHaveNull); + sqlite3VdbeAddOp2(v, OP_Null, 0, rNotFound); + sqlite3VdbeAddOp4(v, OP_Blob, 2, rMayHaveNull, 0, + nullRecord, P4_STATIC); + j4 = sqlite3VdbeAddOp3(v, OP_Found, pExpr->iTable, 0, rMayHaveNull); + sqlite3VdbeAddOp2(v, OP_Integer, 0, rNotFound); + sqlite3VdbeJumpHere(v, j4); + sqlite3VdbeJumpHere(v, j3); + + /* Copy the value of register rNotFound (which is either NULL or 0) + ** into the target register. This will be the result of the + ** expression. + */ + sqlite3VdbeAddOp2(v, OP_Copy, rNotFound, target); + } + } + sqlite3VdbeJumpHere(v, j2); + sqlite3VdbeJumpHere(v, j5); + VdbeComment((v, "end IN expr r%d", target)); + break; + } +#endif + /* + ** x BETWEEN y AND z + ** + ** This is equivalent to + ** + ** x>=y AND x<=z + ** + ** X is stored in pExpr->pLeft. + ** Y is stored in pExpr->pList->a[0].pExpr. + ** Z is stored in pExpr->pList->a[1].pExpr. + */ + case TK_BETWEEN: { + Expr *pLeft = pExpr->pLeft; + struct ExprList_item *pLItem = pExpr->pList->a; + Expr *pRight = pLItem->pExpr; + + codeCompareOperands(pParse, pLeft, &r1, ®Free1, + pRight, &r2, ®Free2); + testcase( regFree1==0 ); + testcase( regFree2==0 ); + r3 = sqlite3GetTempReg(pParse); + r4 = sqlite3GetTempReg(pParse); + codeCompare(pParse, pLeft, pRight, OP_Ge, + r1, r2, r3, SQLITE_STOREP2); + pLItem++; + pRight = pLItem->pExpr; + sqlite3ReleaseTempReg(pParse, regFree2); + r2 = sqlite3ExprCodeTemp(pParse, pRight, ®Free2); + testcase( regFree2==0 ); + codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r4, SQLITE_STOREP2); + sqlite3VdbeAddOp3(v, OP_And, r3, r4, target); + sqlite3ReleaseTempReg(pParse, r3); + sqlite3ReleaseTempReg(pParse, r4); + break; + } + case TK_UPLUS: { + inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); + break; + } + + /* + ** Form A: + ** CASE x WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END + ** + ** Form B: + ** CASE WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END + ** + ** Form A is can be transformed into the equivalent form B as follows: + ** CASE WHEN x=e1 THEN r1 WHEN x=e2 THEN r2 ... + ** WHEN x=eN THEN rN ELSE y END + ** + ** X (if it exists) is in pExpr->pLeft. + ** Y is in pExpr->pRight. The Y is also optional. If there is no + ** ELSE clause and no other term matches, then the result of the + ** exprssion is NULL. + ** Ei is in pExpr->pList->a[i*2] and Ri is pExpr->pList->a[i*2+1]. + ** + ** The result of the expression is the Ri for the first matching Ei, + ** or if there is no matching Ei, the ELSE term Y, or if there is + ** no ELSE term, NULL. + */ + case TK_CASE: { + int endLabel; /* GOTO label for end of CASE stmt */ + int nextCase; /* GOTO label for next WHEN clause */ + int nExpr; /* 2x number of WHEN terms */ + int i; /* Loop counter */ + ExprList *pEList; /* List of WHEN terms */ + struct ExprList_item *aListelem; /* Array of WHEN terms */ + Expr opCompare; /* The X==Ei expression */ + Expr cacheX; /* Cached expression X */ + Expr *pX; /* The X expression */ + Expr *pTest; /* X==Ei (form A) or just Ei (form B) */ + + assert(pExpr->pList); + assert((pExpr->pList->nExpr % 2) == 0); + assert(pExpr->pList->nExpr > 0); + pEList = pExpr->pList; + aListelem = pEList->a; + nExpr = pEList->nExpr; + endLabel = sqlite3VdbeMakeLabel(v); + if( (pX = pExpr->pLeft)!=0 ){ + cacheX = *pX; + testcase( pX->op==TK_COLUMN || pX->op==TK_REGISTER ); + cacheX.iTable = sqlite3ExprCodeTemp(pParse, pX, ®Free1); + testcase( regFree1==0 ); + cacheX.op = TK_REGISTER; + cacheX.iColumn = 0; + opCompare.op = TK_EQ; + opCompare.pLeft = &cacheX; + pTest = &opCompare; + } + pParse->disableColCache++; + for(i=0; i<nExpr; i=i+2){ + if( pX ){ + opCompare.pRight = aListelem[i].pExpr; + }else{ + pTest = aListelem[i].pExpr; + } + nextCase = sqlite3VdbeMakeLabel(v); + testcase( pTest->op==TK_COLUMN || pTest->op==TK_REGISTER ); + sqlite3ExprIfFalse(pParse, pTest, nextCase, SQLITE_JUMPIFNULL); + testcase( aListelem[i+1].pExpr->op==TK_COLUMN ); + testcase( aListelem[i+1].pExpr->op==TK_REGISTER ); + sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target); + sqlite3VdbeAddOp2(v, OP_Goto, 0, endLabel); + sqlite3VdbeResolveLabel(v, nextCase); + } + if( pExpr->pRight ){ + sqlite3ExprCode(pParse, pExpr->pRight, target); + }else{ + sqlite3VdbeAddOp2(v, OP_Null, 0, target); + } + sqlite3VdbeResolveLabel(v, endLabel); + assert( pParse->disableColCache>0 ); + pParse->disableColCache--; + break; + } +#ifndef SQLITE_OMIT_TRIGGER + case TK_RAISE: { + if( !pParse->trigStack ){ + sqlite3ErrorMsg(pParse, + "RAISE() may only be used within a trigger-program"); + return 0; + } + if( pExpr->iColumn!=OE_Ignore ){ + assert( pExpr->iColumn==OE_Rollback || + pExpr->iColumn == OE_Abort || + pExpr->iColumn == OE_Fail ); + sqlite3DequoteExpr(pParse->db, pExpr); + sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn, 0, + (char*)pExpr->token.z, pExpr->token.n); + } else { + assert( pExpr->iColumn == OE_Ignore ); + sqlite3VdbeAddOp2(v, OP_ContextPop, 0, 0); + sqlite3VdbeAddOp2(v, OP_Goto, 0, pParse->trigStack->ignoreJump); + VdbeComment((v, "raise(IGNORE)")); + } + break; + } +#endif + } + sqlite3ReleaseTempReg(pParse, regFree1); + sqlite3ReleaseTempReg(pParse, regFree2); + return inReg; +} + +/* +** Generate code to evaluate an expression and store the results +** into a register. Return the register number where the results +** are stored. +** +** If the register is a temporary register that can be deallocated, +** then write its number into *pReg. If the result register is not +** a temporary, then set *pReg to zero. +*/ +int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){ + int r1 = sqlite3GetTempReg(pParse); + int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1); + if( r2==r1 ){ + *pReg = r1; + }else{ + sqlite3ReleaseTempReg(pParse, r1); + *pReg = 0; + } + return r2; +} + +/* +** Generate code that will evaluate expression pExpr and store the +** results in register target. The results are guaranteed to appear +** in register target. +*/ +int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ + int inReg; + + assert( target>0 && target<=pParse->nMem ); + inReg = sqlite3ExprCodeTarget(pParse, pExpr, target); + assert( pParse->pVdbe || pParse->db->mallocFailed ); + if( inReg!=target && pParse->pVdbe ){ + sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, inReg, target); + } + return target; +} + +/* +** Generate code that evalutes the given expression and puts the result +** in register target. +** +** Also make a copy of the expression results into another "cache" register +** and modify the expression so that the next time it is evaluated, +** the result is a copy of the cache register. +** +** This routine is used for expressions that are used multiple +** times. They are evaluated once and the results of the expression +** are reused. +*/ +int sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){ + Vdbe *v = pParse->pVdbe; + int inReg; + inReg = sqlite3ExprCode(pParse, pExpr, target); + assert( target>0 ); + if( pExpr->op!=TK_REGISTER ){ + int iMem; + iMem = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Copy, inReg, iMem); + pExpr->iTable = iMem; + pExpr->iColumn = pExpr->op; + pExpr->op = TK_REGISTER; + } + return inReg; +} + +/* +** Return TRUE if pExpr is an constant expression that is appropriate +** for factoring out of a loop. Appropriate expressions are: +** +** * Any expression that evaluates to two or more opcodes. +** +** * Any OP_Integer, OP_Real, OP_String, OP_Blob, OP_Null, +** or OP_Variable that does not need to be placed in a +** specific register. +** +** There is no point in factoring out single-instruction constant +** expressions that need to be placed in a particular register. +** We could factor them out, but then we would end up adding an +** OP_SCopy instruction to move the value into the correct register +** later. We might as well just use the original instruction and +** avoid the OP_SCopy. +*/ +static int isAppropriateForFactoring(Expr *p){ + if( !sqlite3ExprIsConstantNotJoin(p) ){ + return 0; /* Only constant expressions are appropriate for factoring */ + } + if( (p->flags & EP_FixedDest)==0 ){ + return 1; /* Any constant without a fixed destination is appropriate */ + } + while( p->op==TK_UPLUS ) p = p->pLeft; + switch( p->op ){ +#ifndef SQLITE_OMIT_BLOB_LITERAL + case TK_BLOB: +#endif + case TK_VARIABLE: + case TK_INTEGER: + case TK_FLOAT: + case TK_NULL: + case TK_STRING: { + testcase( p->op==TK_BLOB ); + testcase( p->op==TK_VARIABLE ); + testcase( p->op==TK_INTEGER ); + testcase( p->op==TK_FLOAT ); + testcase( p->op==TK_NULL ); + testcase( p->op==TK_STRING ); + /* Single-instruction constants with a fixed destination are + ** better done in-line. If we factor them, they will just end + ** up generating an OP_SCopy to move the value to the destination + ** register. */ + return 0; + } + case TK_UMINUS: { + if( p->pLeft->op==TK_FLOAT || p->pLeft->op==TK_INTEGER ){ + return 0; + } + break; + } + default: { + break; + } + } + return 1; +} + +/* +** If pExpr is a constant expression that is appropriate for +** factoring out of a loop, then evaluate the expression +** into a register and convert the expression into a TK_REGISTER +** expression. +*/ +static int evalConstExpr(void *pArg, Expr *pExpr){ + Parse *pParse = (Parse*)pArg; + switch( pExpr->op ){ + case TK_REGISTER: { + return 1; + } + case TK_FUNCTION: + case TK_AGG_FUNCTION: + case TK_CONST_FUNC: { + /* The arguments to a function have a fixed destination. + ** Mark them this way to avoid generated unneeded OP_SCopy + ** instructions. + */ + ExprList *pList = pExpr->pList; + if( pList ){ + int i = pList->nExpr; + struct ExprList_item *pItem = pList->a; + for(; i>0; i--, pItem++){ + if( pItem->pExpr ) pItem->pExpr->flags |= EP_FixedDest; + } + } + break; + } + } + if( isAppropriateForFactoring(pExpr) ){ + int r1 = ++pParse->nMem; + int r2; + r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1); + if( r1!=r2 ) sqlite3ReleaseTempReg(pParse, r1); + pExpr->iColumn = pExpr->op; + pExpr->op = TK_REGISTER; + pExpr->iTable = r2; + return 1; + } + return 0; +} + +/* +** Preevaluate constant subexpressions within pExpr and store the +** results in registers. Modify pExpr so that the constant subexpresions +** are TK_REGISTER opcodes that refer to the precomputed values. +*/ +void sqlite3ExprCodeConstants(Parse *pParse, Expr *pExpr){ + walkExprTree(pExpr, evalConstExpr, pParse); +} + + +/* +** Generate code that pushes the value of every element of the given +** expression list into a sequence of registers beginning at target. +** +** Return the number of elements evaluated. +*/ +int sqlite3ExprCodeExprList( + Parse *pParse, /* Parsing context */ + ExprList *pList, /* The expression list to be coded */ + int target, /* Where to write results */ + int doHardCopy /* Call sqlite3ExprHardCopy on each element if true */ +){ + struct ExprList_item *pItem; + int i, n; + assert( pList!=0 || pParse->db->mallocFailed ); + if( pList==0 ){ + return 0; + } + assert( target>0 ); + n = pList->nExpr; + for(pItem=pList->a, i=0; i<n; i++, pItem++){ + sqlite3ExprCode(pParse, pItem->pExpr, target+i); + if( doHardCopy ) sqlite3ExprHardCopy(pParse, target, n); + } + return n; +} + +/* +** Generate code for a boolean expression such that a jump is made +** to the label "dest" if the expression is true but execution +** continues straight thru if the expression is false. +** +** If the expression evaluates to NULL (neither true nor false), then +** take the jump if the jumpIfNull flag is SQLITE_JUMPIFNULL. +** +** This code depends on the fact that certain token values (ex: TK_EQ) +** are the same as opcode values (ex: OP_Eq) that implement the corresponding +** operation. Special comments in vdbe.c and the mkopcodeh.awk script in +** the make process cause these values to align. Assert()s in the code +** below verify that the numbers are aligned correctly. +*/ +void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ + Vdbe *v = pParse->pVdbe; + int op = 0; + int regFree1 = 0; + int regFree2 = 0; + int r1, r2; + + assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 ); + if( v==0 || pExpr==0 ) return; + op = pExpr->op; + switch( op ){ + case TK_AND: { + int d2 = sqlite3VdbeMakeLabel(v); + testcase( jumpIfNull==0 ); + testcase( pParse->disableColCache==0 ); + sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL); + pParse->disableColCache++; + sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); + assert( pParse->disableColCache>0 ); + pParse->disableColCache--; + sqlite3VdbeResolveLabel(v, d2); + break; + } + case TK_OR: { + testcase( jumpIfNull==0 ); + testcase( pParse->disableColCache==0 ); + sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); + pParse->disableColCache++; + sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); + assert( pParse->disableColCache>0 ); + pParse->disableColCache--; + break; + } + case TK_NOT: { + testcase( jumpIfNull==0 ); + sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); + break; + } + case TK_LT: + case TK_LE: + case TK_GT: + case TK_GE: + case TK_NE: + case TK_EQ: { + assert( TK_LT==OP_Lt ); + assert( TK_LE==OP_Le ); + assert( TK_GT==OP_Gt ); + assert( TK_GE==OP_Ge ); + assert( TK_EQ==OP_Eq ); + assert( TK_NE==OP_Ne ); + testcase( op==TK_LT ); + testcase( op==TK_LE ); + testcase( op==TK_GT ); + testcase( op==TK_GE ); + testcase( op==TK_EQ ); + testcase( op==TK_NE ); + testcase( jumpIfNull==0 ); + codeCompareOperands(pParse, pExpr->pLeft, &r1, ®Free1, + pExpr->pRight, &r2, ®Free2); + codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, + r1, r2, dest, jumpIfNull); + testcase( regFree1==0 ); + testcase( regFree2==0 ); + break; + } + case TK_ISNULL: + case TK_NOTNULL: { + assert( TK_ISNULL==OP_IsNull ); + assert( TK_NOTNULL==OP_NotNull ); + testcase( op==TK_ISNULL ); + testcase( op==TK_NOTNULL ); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + sqlite3VdbeAddOp2(v, op, r1, dest); + testcase( regFree1==0 ); + break; + } + case TK_BETWEEN: { + /* x BETWEEN y AND z + ** + ** Is equivalent to + ** + ** x>=y AND x<=z + ** + ** Code it as such, taking care to do the common subexpression + ** elementation of x. + */ + Expr exprAnd; + Expr compLeft; + Expr compRight; + Expr exprX; + + exprX = *pExpr->pLeft; + exprAnd.op = TK_AND; + exprAnd.pLeft = &compLeft; + exprAnd.pRight = &compRight; + compLeft.op = TK_GE; + compLeft.pLeft = &exprX; + compLeft.pRight = pExpr->pList->a[0].pExpr; + compRight.op = TK_LE; + compRight.pLeft = &exprX; + compRight.pRight = pExpr->pList->a[1].pExpr; + exprX.iTable = sqlite3ExprCodeTemp(pParse, &exprX, ®Free1); + testcase( regFree1==0 ); + exprX.op = TK_REGISTER; + testcase( jumpIfNull==0 ); + sqlite3ExprIfTrue(pParse, &exprAnd, dest, jumpIfNull); + break; + } + default: { + r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1); + sqlite3VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull!=0); + testcase( regFree1==0 ); + testcase( jumpIfNull==0 ); + break; + } + } + sqlite3ReleaseTempReg(pParse, regFree1); + sqlite3ReleaseTempReg(pParse, regFree2); +} + +/* +** Generate code for a boolean expression such that a jump is made +** to the label "dest" if the expression is false but execution +** continues straight thru if the expression is true. +** +** If the expression evaluates to NULL (neither true nor false) then +** jump if jumpIfNull is SQLITE_JUMPIFNULL or fall through if jumpIfNull +** is 0. +*/ +void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ + Vdbe *v = pParse->pVdbe; + int op = 0; + int regFree1 = 0; + int regFree2 = 0; + int r1, r2; + + assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 ); + if( v==0 || pExpr==0 ) return; + + /* The value of pExpr->op and op are related as follows: + ** + ** pExpr->op op + ** --------- ---------- + ** TK_ISNULL OP_NotNull + ** TK_NOTNULL OP_IsNull + ** TK_NE OP_Eq + ** TK_EQ OP_Ne + ** TK_GT OP_Le + ** TK_LE OP_Gt + ** TK_GE OP_Lt + ** TK_LT OP_Ge + ** + ** For other values of pExpr->op, op is undefined and unused. + ** The value of TK_ and OP_ constants are arranged such that we + ** can compute the mapping above using the following expression. + ** Assert()s verify that the computation is correct. + */ + op = ((pExpr->op+(TK_ISNULL&1))^1)-(TK_ISNULL&1); + + /* Verify correct alignment of TK_ and OP_ constants + */ + assert( pExpr->op!=TK_ISNULL || op==OP_NotNull ); + assert( pExpr->op!=TK_NOTNULL || op==OP_IsNull ); + assert( pExpr->op!=TK_NE || op==OP_Eq ); + assert( pExpr->op!=TK_EQ || op==OP_Ne ); + assert( pExpr->op!=TK_LT || op==OP_Ge ); + assert( pExpr->op!=TK_LE || op==OP_Gt ); + assert( pExpr->op!=TK_GT || op==OP_Le ); + assert( pExpr->op!=TK_GE || op==OP_Lt ); + + switch( pExpr->op ){ + case TK_AND: { + testcase( jumpIfNull==0 ); + testcase( pParse->disableColCache==0 ); + sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); + pParse->disableColCache++; + sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); + assert( pParse->disableColCache>0 ); + pParse->disableColCache--; + break; + } + case TK_OR: { + int d2 = sqlite3VdbeMakeLabel(v); + testcase( jumpIfNull==0 ); + testcase( pParse->disableColCache==0 ); + sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL); + pParse->disableColCache++; + sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); + assert( pParse->disableColCache>0 ); + pParse->disableColCache--; + sqlite3VdbeResolveLabel(v, d2); + break; + } + case TK_NOT: { + sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); + break; + } + case TK_LT: + case TK_LE: + case TK_GT: + case TK_GE: + case TK_NE: + case TK_EQ: { + testcase( op==TK_LT ); + testcase( op==TK_LE ); + testcase( op==TK_GT ); + testcase( op==TK_GE ); + testcase( op==TK_EQ ); + testcase( op==TK_NE ); + testcase( jumpIfNull==0 ); + codeCompareOperands(pParse, pExpr->pLeft, &r1, ®Free1, + pExpr->pRight, &r2, ®Free2); + codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, + r1, r2, dest, jumpIfNull); + testcase( regFree1==0 ); + testcase( regFree2==0 ); + break; + } + case TK_ISNULL: + case TK_NOTNULL: { + testcase( op==TK_ISNULL ); + testcase( op==TK_NOTNULL ); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + sqlite3VdbeAddOp2(v, op, r1, dest); + testcase( regFree1==0 ); + break; + } + case TK_BETWEEN: { + /* x BETWEEN y AND z + ** + ** Is equivalent to + ** + ** x>=y AND x<=z + ** + ** Code it as such, taking care to do the common subexpression + ** elementation of x. + */ + Expr exprAnd; + Expr compLeft; + Expr compRight; + Expr exprX; + + exprX = *pExpr->pLeft; + exprAnd.op = TK_AND; + exprAnd.pLeft = &compLeft; + exprAnd.pRight = &compRight; + compLeft.op = TK_GE; + compLeft.pLeft = &exprX; + compLeft.pRight = pExpr->pList->a[0].pExpr; + compRight.op = TK_LE; + compRight.pLeft = &exprX; + compRight.pRight = pExpr->pList->a[1].pExpr; + exprX.iTable = sqlite3ExprCodeTemp(pParse, &exprX, ®Free1); + testcase( regFree1==0 ); + exprX.op = TK_REGISTER; + testcase( jumpIfNull==0 ); + sqlite3ExprIfFalse(pParse, &exprAnd, dest, jumpIfNull); + break; + } + default: { + r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1); + sqlite3VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull!=0); + testcase( regFree1==0 ); + testcase( jumpIfNull==0 ); + break; + } + } + sqlite3ReleaseTempReg(pParse, regFree1); + sqlite3ReleaseTempReg(pParse, regFree2); +} + +/* +** Do a deep comparison of two expression trees. Return TRUE (non-zero) +** if they are identical and return FALSE if they differ in any way. +** +** Sometimes this routine will return FALSE even if the two expressions +** really are equivalent. If we cannot prove that the expressions are +** identical, we return FALSE just to be safe. So if this routine +** returns false, then you do not really know for certain if the two +** expressions are the same. But if you get a TRUE return, then you +** can be sure the expressions are the same. In the places where +** this routine is used, it does not hurt to get an extra FALSE - that +** just might result in some slightly slower code. But returning +** an incorrect TRUE could lead to a malfunction. +*/ +int sqlite3ExprCompare(Expr *pA, Expr *pB){ + int i; + 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; + if( !sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 0; + if( !sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 0; + if( pA->pList ){ + if( pB->pList==0 ) return 0; + if( pA->pList->nExpr!=pB->pList->nExpr ) return 0; + for(i=0; i<pA->pList->nExpr; i++){ + if( !sqlite3ExprCompare(pA->pList->a[i].pExpr, pB->pList->a[i].pExpr) ){ + return 0; + } + } + }else if( pB->pList ){ + return 0; + } + if( pA->pSelect || pB->pSelect ) return 0; + if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0; + if( pA->op!=TK_COLUMN && pA->token.z ){ + if( pB->token.z==0 ) return 0; + if( pB->token.n!=pA->token.n ) return 0; + if( sqlite3StrNICmp((char*)pA->token.z,(char*)pB->token.z,pB->token.n)!=0 ){ + return 0; + } + } + return 1; +} + + +/* +** Add a new element to the pAggInfo->aCol[] array. Return the index of +** the new element. Return a negative number if malloc fails. +*/ +static int addAggInfoColumn(sqlite3 *db, AggInfo *pInfo){ + int i; + pInfo->aCol = sqlite3ArrayAllocate( + db, + pInfo->aCol, + sizeof(pInfo->aCol[0]), + 3, + &pInfo->nColumn, + &pInfo->nColumnAlloc, + &i + ); + return i; +} + +/* +** Add a new element to the pAggInfo->aFunc[] array. Return the index of +** the new element. Return a negative number if malloc fails. +*/ +static int addAggInfoFunc(sqlite3 *db, AggInfo *pInfo){ + int i; + pInfo->aFunc = sqlite3ArrayAllocate( + db, + pInfo->aFunc, + sizeof(pInfo->aFunc[0]), + 3, + &pInfo->nFunc, + &pInfo->nFuncAlloc, + &i + ); + return i; +} + +/* +** This is an xFunc for walkExprTree() used to implement +** sqlite3ExprAnalyzeAggregates(). See sqlite3ExprAnalyzeAggregates +** for additional information. +** +** This routine analyzes the aggregate function at pExpr. +*/ +static int analyzeAggregate(void *pArg, Expr *pExpr){ + int i; + NameContext *pNC = (NameContext *)pArg; + Parse *pParse = pNC->pParse; + SrcList *pSrcList = pNC->pSrcList; + AggInfo *pAggInfo = pNC->pAggInfo; + + switch( pExpr->op ){ + case TK_AGG_COLUMN: + case TK_COLUMN: { + /* Check to see if the column is in one of the tables in the FROM + ** clause of the aggregate query */ + if( pSrcList ){ + struct SrcList_item *pItem = pSrcList->a; + for(i=0; i<pSrcList->nSrc; i++, pItem++){ + struct AggInfo_col *pCol; + if( pExpr->iTable==pItem->iCursor ){ + /* If we reach this point, it means that pExpr refers to a table + ** that is in the FROM clause of the aggregate query. + ** + ** Make an entry for the column in pAggInfo->aCol[] if there + ** is not an entry there already. + */ + int k; + pCol = pAggInfo->aCol; + for(k=0; k<pAggInfo->nColumn; k++, pCol++){ + if( pCol->iTable==pExpr->iTable && + pCol->iColumn==pExpr->iColumn ){ + break; + } + } + if( (k>=pAggInfo->nColumn) + && (k = addAggInfoColumn(pParse->db, pAggInfo))>=0 + ){ + pCol = &pAggInfo->aCol[k]; + pCol->pTab = pExpr->pTab; + pCol->iTable = pExpr->iTable; + pCol->iColumn = pExpr->iColumn; + pCol->iMem = ++pParse->nMem; + pCol->iSorterColumn = -1; + pCol->pExpr = pExpr; + if( pAggInfo->pGroupBy ){ + int j, n; + ExprList *pGB = pAggInfo->pGroupBy; + struct ExprList_item *pTerm = pGB->a; + n = pGB->nExpr; + for(j=0; j<n; j++, pTerm++){ + Expr *pE = pTerm->pExpr; + if( pE->op==TK_COLUMN && pE->iTable==pExpr->iTable && + pE->iColumn==pExpr->iColumn ){ + pCol->iSorterColumn = j; + break; + } + } + } + if( pCol->iSorterColumn<0 ){ + pCol->iSorterColumn = pAggInfo->nSortingColumn++; + } + } + /* There is now an entry for pExpr in pAggInfo->aCol[] (either + ** because it was there before or because we just created it). + ** Convert the pExpr to be a TK_AGG_COLUMN referring to that + ** pAggInfo->aCol[] entry. + */ + pExpr->pAggInfo = pAggInfo; + pExpr->op = TK_AGG_COLUMN; + pExpr->iAgg = k; + break; + } /* endif pExpr->iTable==pItem->iCursor */ + } /* end loop over pSrcList */ + } + return 1; + } + case TK_AGG_FUNCTION: { + /* The pNC->nDepth==0 test causes aggregate functions in subqueries + ** to be ignored */ + if( pNC->nDepth==0 ){ + /* Check to see if pExpr is a duplicate of another aggregate + ** function that is already in the pAggInfo structure + */ + struct AggInfo_func *pItem = pAggInfo->aFunc; + for(i=0; i<pAggInfo->nFunc; i++, pItem++){ + if( sqlite3ExprCompare(pItem->pExpr, pExpr) ){ + break; + } + } + if( i>=pAggInfo->nFunc ){ + /* pExpr is original. Make a new entry in pAggInfo->aFunc[] + */ + u8 enc = ENC(pParse->db); + i = addAggInfoFunc(pParse->db, pAggInfo); + if( i>=0 ){ + pItem = &pAggInfo->aFunc[i]; + pItem->pExpr = pExpr; + pItem->iMem = ++pParse->nMem; + pItem->pFunc = sqlite3FindFunction(pParse->db, + (char*)pExpr->token.z, pExpr->token.n, + pExpr->pList ? pExpr->pList->nExpr : 0, enc, 0); + if( pExpr->flags & EP_Distinct ){ + pItem->iDistinct = pParse->nTab++; + }else{ + pItem->iDistinct = -1; + } + } + } + /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry + */ + pExpr->iAgg = i; + pExpr->pAggInfo = pAggInfo; + return 1; + } + } + } + + /* Recursively walk subqueries looking for TK_COLUMN nodes that need + ** to be changed to TK_AGG_COLUMN. But increment nDepth so that + ** TK_AGG_FUNCTION nodes in subqueries will be unchanged. + */ + if( pExpr->pSelect ){ + pNC->nDepth++; + walkSelectExpr(pExpr->pSelect, analyzeAggregate, pNC); + pNC->nDepth--; + } + return 0; +} + +/* +** Analyze the given expression looking for aggregate functions and +** for variables that need to be added to the pParse->aAgg[] array. +** Make additional entries to the pParse->aAgg[] array as necessary. +** +** This routine should only be called after the expression has been +** analyzed by sqlite3ExprResolveNames(). +*/ +void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){ + walkExprTree(pExpr, analyzeAggregate, pNC); +} + +/* +** Call sqlite3ExprAnalyzeAggregates() for every expression in an +** expression list. Return the number of errors. +** +** If an error is found, the analysis is cut short. +*/ +void sqlite3ExprAnalyzeAggList(NameContext *pNC, ExprList *pList){ + struct ExprList_item *pItem; + int i; + if( pList ){ + for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){ + sqlite3ExprAnalyzeAggregates(pNC, pItem->pExpr); + } + } +} + +/* +** Allocate or deallocate temporary use registers during code generation. +*/ +int sqlite3GetTempReg(Parse *pParse){ + if( pParse->nTempReg==0 ){ + return ++pParse->nMem; + } + return pParse->aTempReg[--pParse->nTempReg]; +} +void sqlite3ReleaseTempReg(Parse *pParse, int iReg){ + if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){ + sqlite3ExprWritableRegister(pParse, iReg, iReg); + pParse->aTempReg[pParse->nTempReg++] = iReg; + } +} + +/* +** Allocate or deallocate a block of nReg consecutive registers +*/ +int sqlite3GetTempRange(Parse *pParse, int nReg){ + int i, n; + i = pParse->iRangeReg; + n = pParse->nRangeReg; + if( nReg<=n && !usedAsColumnCache(pParse, i, i+n-1) ){ + pParse->iRangeReg += nReg; + pParse->nRangeReg -= nReg; + }else{ + i = pParse->nMem+1; + pParse->nMem += nReg; + } + return i; +} +void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){ + if( nReg>pParse->nRangeReg ){ + pParse->nRangeReg = nReg; + pParse->iRangeReg = iReg; + } +} diff --git a/third_party/sqlite/src/fault.c b/third_party/sqlite/src/fault.c new file mode 100755 index 0000000..5ede8b9 --- /dev/null +++ b/third_party/sqlite/src/fault.c @@ -0,0 +1,71 @@ +/* +** 2008 Jan 22 +** +** 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. +** +************************************************************************* +** +** $Id: fault.c,v 1.10 2008/06/22 12:37:58 drh Exp $ +*/ + +/* +** This file contains code to support the concept of "benign" +** malloc failures (when the xMalloc() or xRealloc() method of the +** sqlite3_mem_methods structure fails to allocate a block of memory +** and returns 0). +** +** Most malloc failures are non-benign. After they occur, SQLite +** abandons the current operation and returns an error code (usually +** SQLITE_NOMEM) to the user. However, sometimes a fault is not necessarily +** fatal. For example, if a malloc fails while resizing a hash table, this +** is completely recoverable simply by not carrying out the resize. The +** hash table will continue to function normally. So a malloc failure +** during a hash table resize is a benign fault. +*/ + +#include "sqliteInt.h" + +#ifndef SQLITE_OMIT_BUILTIN_TEST + +/* +** Global variables. +*/ +static struct BenignMallocHooks { + void (*xBenignBegin)(void); + void (*xBenignEnd)(void); +} hooks; + +/* +** Register hooks to call when sqlite3BeginBenignMalloc() and +** sqlite3EndBenignMalloc() are called, respectively. +*/ +void sqlite3BenignMallocHooks( + void (*xBenignBegin)(void), + void (*xBenignEnd)(void) +){ + hooks.xBenignBegin = xBenignBegin; + hooks.xBenignEnd = xBenignEnd; +} + +/* +** This (sqlite3EndBenignMalloc()) is called by SQLite code to indicate that +** subsequent malloc failures are benign. A call to sqlite3EndBenignMalloc() +** indicates that subsequent malloc failures are non-benign. +*/ +void sqlite3BeginBenignMalloc(void){ + if( hooks.xBenignBegin ){ + hooks.xBenignBegin(); + } +} +void sqlite3EndBenignMalloc(void){ + if( hooks.xBenignEnd ){ + hooks.xBenignEnd(); + } +} + +#endif /* #ifndef SQLITE_OMIT_BUILTIN_TEST */ diff --git a/third_party/sqlite/src/func.c b/third_party/sqlite/src/func.c new file mode 100755 index 0000000..7316c74 --- /dev/null +++ b/third_party/sqlite/src/func.c @@ -0,0 +1,1399 @@ +/* +** 2002 February 23 +** +** 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 the C functions that implement various SQL +** functions of SQLite. +** +** There is only one exported symbol in this file - the function +** sqliteRegisterBuildinFunctions() found at the bottom of the file. +** All other code has file scope. +** +** $Id: func.c,v 1.196 2008/07/28 19:34:53 drh Exp $ +*/ +#include "sqliteInt.h" +#include <ctype.h> +#include <stdlib.h> +#include <assert.h> +#include "vdbeInt.h" + + +/* +** Return the collating function associated with a function. +*/ +static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){ + return context->pColl; +} + +/* +** Implementation of the non-aggregate min() and max() functions +*/ +static void minmaxFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + int i; + int mask; /* 0 for min() or 0xffffffff for max() */ + int iBest; + CollSeq *pColl; + + if( argc==0 ) return; + mask = sqlite3_user_data(context)==0 ? 0 : -1; + pColl = sqlite3GetFuncCollSeq(context); + assert( pColl ); + assert( mask==-1 || mask==0 ); + iBest = 0; + if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; + for(i=1; i<argc; i++){ + if( sqlite3_value_type(argv[i])==SQLITE_NULL ) return; + if( (sqlite3MemCompare(argv[iBest], argv[i], pColl)^mask)>=0 ){ + iBest = i; + } + } + sqlite3_result_value(context, argv[iBest]); +} + +/* +** Return the type of the argument. +*/ +static void typeofFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const char *z = 0; + switch( sqlite3_value_type(argv[0]) ){ + case SQLITE_NULL: z = "null"; break; + case SQLITE_INTEGER: z = "integer"; break; + case SQLITE_TEXT: z = "text"; break; + case SQLITE_FLOAT: z = "real"; break; + case SQLITE_BLOB: z = "blob"; break; + } + sqlite3_result_text(context, z, -1, SQLITE_STATIC); +} + + +/* +** Implementation of the length() function +*/ +static void lengthFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + int len; + + assert( argc==1 ); + switch( sqlite3_value_type(argv[0]) ){ + case SQLITE_BLOB: + case SQLITE_INTEGER: + case SQLITE_FLOAT: { + sqlite3_result_int(context, sqlite3_value_bytes(argv[0])); + break; + } + case SQLITE_TEXT: { + const unsigned char *z = sqlite3_value_text(argv[0]); + if( z==0 ) return; + len = 0; + while( *z ){ + len++; + SQLITE_SKIP_UTF8(z); + } + sqlite3_result_int(context, len); + break; + } + default: { + sqlite3_result_null(context); + break; + } + } +} + +/* +** Implementation of the abs() function +*/ +static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + assert( argc==1 ); + switch( sqlite3_value_type(argv[0]) ){ + case SQLITE_INTEGER: { + i64 iVal = sqlite3_value_int64(argv[0]); + if( iVal<0 ){ + if( (iVal<<1)==0 ){ + sqlite3_result_error(context, "integer overflow", -1); + return; + } + iVal = -iVal; + } + sqlite3_result_int64(context, iVal); + break; + } + case SQLITE_NULL: { + sqlite3_result_null(context); + break; + } + default: { + double rVal = sqlite3_value_double(argv[0]); + if( rVal<0 ) rVal = -rVal; + sqlite3_result_double(context, rVal); + break; + } + } +} + +/* +** Implementation of the substr() function. +** +** substr(x,p1,p2) returns p2 characters of x[] beginning with p1. +** p1 is 1-indexed. So substr(x,1,1) returns the first character +** of x. If x is text, then we actually count UTF-8 characters. +** If x is a blob, then we count bytes. +** +** If p1 is negative, then we begin abs(p1) from the end of x[]. +*/ +static void substrFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const unsigned char *z; + const unsigned char *z2; + int len; + int p0type; + i64 p1, p2; + + assert( argc==3 || argc==2 ); + p0type = sqlite3_value_type(argv[0]); + if( p0type==SQLITE_BLOB ){ + len = sqlite3_value_bytes(argv[0]); + z = sqlite3_value_blob(argv[0]); + if( z==0 ) return; + assert( len==sqlite3_value_bytes(argv[0]) ); + }else{ + z = sqlite3_value_text(argv[0]); + if( z==0 ) return; + len = 0; + for(z2=z; *z2; len++){ + SQLITE_SKIP_UTF8(z2); + } + } + p1 = sqlite3_value_int(argv[1]); + if( argc==3 ){ + p2 = sqlite3_value_int(argv[2]); + }else{ + p2 = sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH]; + } + if( p1<0 ){ + p1 += len; + if( p1<0 ){ + p2 += p1; + p1 = 0; + } + }else if( p1>0 ){ + p1--; + } + if( p1+p2>len ){ + p2 = len-p1; + } + if( p0type!=SQLITE_BLOB ){ + while( *z && p1 ){ + SQLITE_SKIP_UTF8(z); + p1--; + } + for(z2=z; *z2 && p2; p2--){ + SQLITE_SKIP_UTF8(z2); + } + sqlite3_result_text(context, (char*)z, z2-z, SQLITE_TRANSIENT); + }else{ + if( p2<0 ) p2 = 0; + sqlite3_result_blob(context, (char*)&z[p1], p2, SQLITE_TRANSIENT); + } +} + +/* +** Implementation of the round() function +*/ +static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + int n = 0; + double r; + char zBuf[500]; /* larger than the %f representation of the largest double */ + assert( argc==1 || argc==2 ); + if( argc==2 ){ + if( SQLITE_NULL==sqlite3_value_type(argv[1]) ) return; + n = sqlite3_value_int(argv[1]); + if( n>30 ) n = 30; + if( n<0 ) n = 0; + } + if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; + r = sqlite3_value_double(argv[0]); + sqlite3_snprintf(sizeof(zBuf),zBuf,"%.*f",n,r); + sqlite3AtoF(zBuf, &r); + sqlite3_result_double(context, r); +} + +/* +** Allocate nByte bytes of space using sqlite3_malloc(). If the +** allocation fails, call sqlite3_result_error_nomem() to notify +** the database handle that malloc() has failed. +*/ +static void *contextMalloc(sqlite3_context *context, i64 nByte){ + char *z; + if( nByte>sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH] ){ + sqlite3_result_error_toobig(context); + z = 0; + }else{ + z = sqlite3Malloc(nByte); + if( !z && nByte>0 ){ + sqlite3_result_error_nomem(context); + } + } + return z; +} + +/* +** Implementation of the upper() and lower() SQL functions. +*/ +static void upperFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + char *z1; + const char *z2; + int i, n; + if( argc<1 || SQLITE_NULL==sqlite3_value_type(argv[0]) ) return; + z2 = (char*)sqlite3_value_text(argv[0]); + n = sqlite3_value_bytes(argv[0]); + /* Verify that the call to _bytes() does not invalidate the _text() pointer */ + assert( z2==(char*)sqlite3_value_text(argv[0]) ); + if( z2 ){ + z1 = contextMalloc(context, ((i64)n)+1); + if( z1 ){ + memcpy(z1, z2, n+1); + for(i=0; z1[i]; i++){ + z1[i] = toupper(z1[i]); + } + sqlite3_result_text(context, z1, -1, sqlite3_free); + } + } +} +static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + char *z1; + const char *z2; + int i, n; + if( argc<1 || SQLITE_NULL==sqlite3_value_type(argv[0]) ) return; + z2 = (char*)sqlite3_value_text(argv[0]); + n = sqlite3_value_bytes(argv[0]); + /* Verify that the call to _bytes() does not invalidate the _text() pointer */ + assert( z2==(char*)sqlite3_value_text(argv[0]) ); + if( z2 ){ + z1 = contextMalloc(context, ((i64)n)+1); + if( z1 ){ + memcpy(z1, z2, n+1); + for(i=0; z1[i]; i++){ + z1[i] = tolower(z1[i]); + } + sqlite3_result_text(context, z1, -1, sqlite3_free); + } + } +} + +/* +** Implementation of the IFNULL(), NVL(), and COALESCE() functions. +** All three do the same thing. They return the first non-NULL +** argument. +*/ +static void ifnullFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + int i; + for(i=0; i<argc; i++){ + if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){ + sqlite3_result_value(context, argv[i]); + break; + } + } +} + +/* +** Implementation of random(). Return a random integer. +*/ +static void randomFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + sqlite_int64 r; + sqlite3_randomness(sizeof(r), &r); + if( (r<<1)==0 ) r = 0; /* Prevent 0x8000.... as the result so that we */ + /* can always do abs() of the result */ + sqlite3_result_int64(context, r); +} + +/* +** Implementation of randomblob(N). Return a random blob +** that is N bytes long. +*/ +static void randomBlob( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + int n; + unsigned char *p; + assert( argc==1 ); + n = sqlite3_value_int(argv[0]); + if( n<1 ){ + n = 1; + } + p = contextMalloc(context, n); + if( p ){ + sqlite3_randomness(n, p); + sqlite3_result_blob(context, (char*)p, n, sqlite3_free); + } +} + +/* +** Implementation of the last_insert_rowid() SQL function. The return +** value is the same as the sqlite3_last_insert_rowid() API function. +*/ +static void last_insert_rowid( + sqlite3_context *context, + int arg, + sqlite3_value **argv +){ + sqlite3 *db = sqlite3_context_db_handle(context); + sqlite3_result_int64(context, sqlite3_last_insert_rowid(db)); +} + +/* +** Implementation of the changes() SQL function. The return value is the +** same as the sqlite3_changes() API function. +*/ +static void changes( + sqlite3_context *context, + int arg, + sqlite3_value **argv +){ + sqlite3 *db = sqlite3_context_db_handle(context); + sqlite3_result_int(context, sqlite3_changes(db)); +} + +/* +** Implementation of the total_changes() SQL function. The return value is +** the same as the sqlite3_total_changes() API function. +*/ +static void total_changes( + sqlite3_context *context, + int arg, + sqlite3_value **argv +){ + sqlite3 *db = sqlite3_context_db_handle(context); + sqlite3_result_int(context, sqlite3_total_changes(db)); +} + +/* +** A structure defining how to do GLOB-style comparisons. +*/ +struct compareInfo { + u8 matchAll; + u8 matchOne; + u8 matchSet; + u8 noCase; +}; + +/* +** For LIKE and GLOB matching on EBCDIC machines, assume that every +** character is exactly one byte in size. Also, all characters are +** able to participate in upper-case-to-lower-case mappings in EBCDIC +** whereas only characters less than 0x80 do in ASCII. +*/ +#if defined(SQLITE_EBCDIC) +# define sqlite3Utf8Read(A,B,C) (*(A++)) +# define GlogUpperToLower(A) A = sqlite3UpperToLower[A] +#else +# define GlogUpperToLower(A) if( A<0x80 ){ A = sqlite3UpperToLower[A]; } +#endif + +static const struct compareInfo globInfo = { '*', '?', '[', 0 }; +/* The correct SQL-92 behavior is for the LIKE operator to ignore +** case. Thus 'a' LIKE 'A' would be true. */ +static const struct compareInfo likeInfoNorm = { '%', '_', 0, 1 }; +/* If SQLITE_CASE_SENSITIVE_LIKE is defined, then the LIKE operator +** is case sensitive causing 'a' LIKE 'A' to be false */ +static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 }; + +/* +** Compare two UTF-8 strings for equality where the first string can +** potentially be a "glob" expression. Return true (1) if they +** are the same and false (0) if they are different. +** +** Globbing rules: +** +** '*' Matches any sequence of zero or more characters. +** +** '?' Matches exactly one character. +** +** [...] Matches one character from the enclosed list of +** characters. +** +** [^...] Matches one character not in the enclosed list. +** +** With the [...] and [^...] matching, a ']' character can be included +** in the list by making it the first character after '[' or '^'. A +** range of characters can be specified using '-'. Example: +** "[a-z]" matches any single lower-case letter. To match a '-', make +** it the last character in the list. +** +** This routine is usually quick, but can be N**2 in the worst case. +** +** Hints: to match '*' or '?', put them in "[]". Like this: +** +** abc[*]xyz Matches "abc*xyz" only +*/ +static int patternCompare( + const u8 *zPattern, /* The glob pattern */ + const u8 *zString, /* The string to compare against the glob */ + const struct compareInfo *pInfo, /* Information about how to do the compare */ + const int esc /* The escape character */ +){ + int c, c2; + int invert; + int seen; + u8 matchOne = pInfo->matchOne; + u8 matchAll = pInfo->matchAll; + u8 matchSet = pInfo->matchSet; + u8 noCase = pInfo->noCase; + int prevEscape = 0; /* True if the previous character was 'escape' */ + + while( (c = sqlite3Utf8Read(zPattern,0,&zPattern))!=0 ){ + if( !prevEscape && c==matchAll ){ + while( (c=sqlite3Utf8Read(zPattern,0,&zPattern)) == matchAll + || c == matchOne ){ + if( c==matchOne && sqlite3Utf8Read(zString, 0, &zString)==0 ){ + return 0; + } + } + if( c==0 ){ + return 1; + }else if( c==esc ){ + c = sqlite3Utf8Read(zPattern, 0, &zPattern); + if( c==0 ){ + return 0; + } + }else if( c==matchSet ){ + assert( esc==0 ); /* This is GLOB, not LIKE */ + assert( matchSet<0x80 ); /* '[' is a single-byte character */ + while( *zString && patternCompare(&zPattern[-1],zString,pInfo,esc)==0 ){ + SQLITE_SKIP_UTF8(zString); + } + return *zString!=0; + } + while( (c2 = sqlite3Utf8Read(zString,0,&zString))!=0 ){ + if( noCase ){ + GlogUpperToLower(c2); + GlogUpperToLower(c); + while( c2 != 0 && c2 != c ){ + c2 = sqlite3Utf8Read(zString, 0, &zString); + GlogUpperToLower(c2); + } + }else{ + while( c2 != 0 && c2 != c ){ + c2 = sqlite3Utf8Read(zString, 0, &zString); + } + } + if( c2==0 ) return 0; + if( patternCompare(zPattern,zString,pInfo,esc) ) return 1; + } + return 0; + }else if( !prevEscape && c==matchOne ){ + if( sqlite3Utf8Read(zString, 0, &zString)==0 ){ + return 0; + } + }else if( c==matchSet ){ + int prior_c = 0; + assert( esc==0 ); /* This only occurs for GLOB, not LIKE */ + seen = 0; + invert = 0; + c = sqlite3Utf8Read(zString, 0, &zString); + if( c==0 ) return 0; + c2 = sqlite3Utf8Read(zPattern, 0, &zPattern); + if( c2=='^' ){ + invert = 1; + c2 = sqlite3Utf8Read(zPattern, 0, &zPattern); + } + if( c2==']' ){ + if( c==']' ) seen = 1; + c2 = sqlite3Utf8Read(zPattern, 0, &zPattern); + } + while( c2 && c2!=']' ){ + if( c2=='-' && zPattern[0]!=']' && zPattern[0]!=0 && prior_c>0 ){ + c2 = sqlite3Utf8Read(zPattern, 0, &zPattern); + if( c>=prior_c && c<=c2 ) seen = 1; + prior_c = 0; + }else{ + if( c==c2 ){ + seen = 1; + } + prior_c = c2; + } + c2 = sqlite3Utf8Read(zPattern, 0, &zPattern); + } + if( c2==0 || (seen ^ invert)==0 ){ + return 0; + } + }else if( esc==c && !prevEscape ){ + prevEscape = 1; + }else{ + c2 = sqlite3Utf8Read(zString, 0, &zString); + if( noCase ){ + GlogUpperToLower(c); + GlogUpperToLower(c2); + } + if( c!=c2 ){ + return 0; + } + prevEscape = 0; + } + } + return *zString==0; +} + +/* +** Count the number of times that the LIKE operator (or GLOB which is +** just a variation of LIKE) gets called. This is used for testing +** only. +*/ +#ifdef SQLITE_TEST +int sqlite3_like_count = 0; +#endif + + +/* +** Implementation of the like() SQL function. This function implements +** the build-in LIKE operator. The first argument to the function is the +** pattern and the second argument is the string. So, the SQL statements: +** +** A LIKE B +** +** is implemented as like(B,A). +** +** This same function (with a different compareInfo structure) computes +** the GLOB operator. +*/ +static void likeFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const unsigned char *zA, *zB; + int escape = 0; + sqlite3 *db = sqlite3_context_db_handle(context); + + zB = sqlite3_value_text(argv[0]); + zA = sqlite3_value_text(argv[1]); + + /* Limit the length of the LIKE or GLOB pattern to avoid problems + ** of deep recursion and N*N behavior in patternCompare(). + */ + if( sqlite3_value_bytes(argv[0]) > + db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] ){ + sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1); + return; + } + assert( zB==sqlite3_value_text(argv[0]) ); /* Encoding did not change */ + + if( argc==3 ){ + /* The escape character string must consist of a single UTF-8 character. + ** Otherwise, return an error. + */ + const unsigned char *zEsc = sqlite3_value_text(argv[2]); + if( zEsc==0 ) return; + if( sqlite3Utf8CharLen((char*)zEsc, -1)!=1 ){ + sqlite3_result_error(context, + "ESCAPE expression must be a single character", -1); + return; + } + escape = sqlite3Utf8Read(zEsc, 0, &zEsc); + } + if( zA && zB ){ + struct compareInfo *pInfo = sqlite3_user_data(context); +#ifdef SQLITE_TEST + sqlite3_like_count++; +#endif + + sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape)); + } +} + +/* +** Implementation of the NULLIF(x,y) function. The result is the first +** argument if the arguments are different. The result is NULL if the +** arguments are equal to each other. +*/ +static void nullifFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + CollSeq *pColl = sqlite3GetFuncCollSeq(context); + if( sqlite3MemCompare(argv[0], argv[1], pColl)!=0 ){ + sqlite3_result_value(context, argv[0]); + } +} + +/* +** Implementation of the VERSION(*) function. The result is the version +** of the SQLite library that is running. +*/ +static void versionFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + sqlite3_result_text(context, sqlite3_version, -1, SQLITE_STATIC); +} + +/* Array for converting from half-bytes (nybbles) into ASCII hex +** digits. */ +static const char hexdigits[] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' +}; + +/* +** EXPERIMENTAL - This is not an official function. The interface may +** change. This function may disappear. Do not write code that depends +** on this function. +** +** Implementation of the QUOTE() function. This function takes a single +** argument. If the argument is numeric, the return value is the same as +** the argument. If the argument is NULL, the return value is the string +** "NULL". Otherwise, the argument is enclosed in single quotes with +** single-quote escapes. +*/ +static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + if( argc<1 ) return; + switch( sqlite3_value_type(argv[0]) ){ + case SQLITE_NULL: { + sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC); + break; + } + case SQLITE_INTEGER: + case SQLITE_FLOAT: { + sqlite3_result_value(context, argv[0]); + break; + } + case SQLITE_BLOB: { + char *zText = 0; + char const *zBlob = sqlite3_value_blob(argv[0]); + int nBlob = sqlite3_value_bytes(argv[0]); + assert( zBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */ + zText = (char *)contextMalloc(context, (2*(i64)nBlob)+4); + if( zText ){ + int i; + for(i=0; i<nBlob; i++){ + zText[(i*2)+2] = hexdigits[(zBlob[i]>>4)&0x0F]; + zText[(i*2)+3] = hexdigits[(zBlob[i])&0x0F]; + } + zText[(nBlob*2)+2] = '\''; + zText[(nBlob*2)+3] = '\0'; + zText[0] = 'X'; + zText[1] = '\''; + sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT); + sqlite3_free(zText); + } + break; + } + case SQLITE_TEXT: { + int i,j; + u64 n; + const unsigned char *zArg = sqlite3_value_text(argv[0]); + char *z; + + if( zArg==0 ) return; + for(i=0, n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; } + z = contextMalloc(context, ((i64)i)+((i64)n)+3); + if( z ){ + z[0] = '\''; + for(i=0, j=1; zArg[i]; i++){ + z[j++] = zArg[i]; + if( zArg[i]=='\'' ){ + z[j++] = '\''; + } + } + z[j++] = '\''; + z[j] = 0; + sqlite3_result_text(context, z, j, sqlite3_free); + } + } + } +} + +/* +** The hex() function. Interpret the argument as a blob. Return +** a hexadecimal rendering as text. +*/ +static void hexFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + int i, n; + const unsigned char *pBlob; + char *zHex, *z; + assert( argc==1 ); + pBlob = sqlite3_value_blob(argv[0]); + n = sqlite3_value_bytes(argv[0]); + assert( pBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */ + z = zHex = contextMalloc(context, ((i64)n)*2 + 1); + if( zHex ){ + for(i=0; i<n; i++, pBlob++){ + unsigned char c = *pBlob; + *(z++) = hexdigits[(c>>4)&0xf]; + *(z++) = hexdigits[c&0xf]; + } + *z = 0; + sqlite3_result_text(context, zHex, n*2, sqlite3_free); + } +} + +/* +** The zeroblob(N) function returns a zero-filled blob of size N bytes. +*/ +static void zeroblobFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + i64 n; + assert( argc==1 ); + n = sqlite3_value_int64(argv[0]); + if( n>SQLITE_MAX_LENGTH ){ + sqlite3_result_error_toobig(context); + }else{ + sqlite3_result_zeroblob(context, n); + } +} + +/* +** The replace() function. Three arguments are all strings: call +** them A, B, and C. The result is also a string which is derived +** from A by replacing every occurance of B with C. The match +** must be exact. Collating sequences are not used. +*/ +static void replaceFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const unsigned char *zStr; /* The input string A */ + const unsigned char *zPattern; /* The pattern string B */ + const unsigned char *zRep; /* The replacement string C */ + unsigned char *zOut; /* The output */ + int nStr; /* Size of zStr */ + int nPattern; /* Size of zPattern */ + int nRep; /* Size of zRep */ + i64 nOut; /* Maximum size of zOut */ + int loopLimit; /* Last zStr[] that might match zPattern[] */ + int i, j; /* Loop counters */ + + assert( argc==3 ); + zStr = sqlite3_value_text(argv[0]); + if( zStr==0 ) return; + nStr = sqlite3_value_bytes(argv[0]); + assert( zStr==sqlite3_value_text(argv[0]) ); /* No encoding change */ + zPattern = sqlite3_value_text(argv[1]); + if( zPattern==0 || zPattern[0]==0 ) return; + nPattern = sqlite3_value_bytes(argv[1]); + assert( zPattern==sqlite3_value_text(argv[1]) ); /* No encoding change */ + zRep = sqlite3_value_text(argv[2]); + if( zRep==0 ) return; + nRep = sqlite3_value_bytes(argv[2]); + assert( zRep==sqlite3_value_text(argv[2]) ); + nOut = nStr + 1; + assert( nOut<SQLITE_MAX_LENGTH ); + zOut = contextMalloc(context, (i64)nOut); + if( zOut==0 ){ + return; + } + loopLimit = nStr - nPattern; + for(i=j=0; i<=loopLimit; i++){ + if( zStr[i]!=zPattern[0] || memcmp(&zStr[i], zPattern, nPattern) ){ + zOut[j++] = zStr[i]; + }else{ + u8 *zOld; + sqlite3 *db = sqlite3_context_db_handle(context); + nOut += nRep - nPattern; + if( nOut>=db->aLimit[SQLITE_LIMIT_LENGTH] ){ + sqlite3_result_error_toobig(context); + sqlite3DbFree(db, zOut); + return; + } + zOld = zOut; + zOut = sqlite3_realloc(zOut, (int)nOut); + if( zOut==0 ){ + sqlite3_result_error_nomem(context); + sqlite3DbFree(db, zOld); + return; + } + memcpy(&zOut[j], zRep, nRep); + j += nRep; + i += nPattern-1; + } + } + assert( j+nStr-i+1==nOut ); + memcpy(&zOut[j], &zStr[i], nStr-i); + j += nStr - i; + assert( j<=nOut ); + zOut[j] = 0; + sqlite3_result_text(context, (char*)zOut, j, sqlite3_free); +} + +/* +** Implementation of the TRIM(), LTRIM(), and RTRIM() functions. +** The userdata is 0x1 for left trim, 0x2 for right trim, 0x3 for both. +*/ +static void trimFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const unsigned char *zIn; /* Input string */ + const unsigned char *zCharSet; /* Set of characters to trim */ + int nIn; /* Number of bytes in input */ + int flags; /* 1: trimleft 2: trimright 3: trim */ + int i; /* Loop counter */ + unsigned char *aLen; /* Length of each character in zCharSet */ + unsigned char **azChar; /* Individual characters in zCharSet */ + int nChar; /* Number of characters in zCharSet */ + + if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ + return; + } + zIn = sqlite3_value_text(argv[0]); + if( zIn==0 ) return; + nIn = sqlite3_value_bytes(argv[0]); + assert( zIn==sqlite3_value_text(argv[0]) ); + if( argc==1 ){ + static const unsigned char lenOne[] = { 1 }; + static const unsigned char *azOne[] = { (u8*)" " }; + nChar = 1; + aLen = (u8*)lenOne; + azChar = (unsigned char **)azOne; + zCharSet = 0; + }else if( (zCharSet = sqlite3_value_text(argv[1]))==0 ){ + return; + }else{ + const unsigned char *z; + for(z=zCharSet, nChar=0; *z; nChar++){ + SQLITE_SKIP_UTF8(z); + } + if( nChar>0 ){ + azChar = contextMalloc(context, ((i64)nChar)*(sizeof(char*)+1)); + if( azChar==0 ){ + return; + } + aLen = (unsigned char*)&azChar[nChar]; + for(z=zCharSet, nChar=0; *z; nChar++){ + azChar[nChar] = (unsigned char *)z; + SQLITE_SKIP_UTF8(z); + aLen[nChar] = z - azChar[nChar]; + } + } + } + if( nChar>0 ){ + flags = SQLITE_PTR_TO_INT(sqlite3_user_data(context)); + if( flags & 1 ){ + while( nIn>0 ){ + int len; + for(i=0; i<nChar; i++){ + len = aLen[i]; + if( memcmp(zIn, azChar[i], len)==0 ) break; + } + if( i>=nChar ) break; + zIn += len; + nIn -= len; + } + } + if( flags & 2 ){ + while( nIn>0 ){ + int len; + for(i=0; i<nChar; i++){ + len = aLen[i]; + if( len<=nIn && memcmp(&zIn[nIn-len],azChar[i],len)==0 ) break; + } + if( i>=nChar ) break; + nIn -= len; + } + } + if( zCharSet ){ + sqlite3_free((void*)azChar); + } + } + sqlite3_result_text(context, (char*)zIn, nIn, SQLITE_TRANSIENT); +} + +#ifdef SQLITE_SOUNDEX +/* +** Compute the soundex encoding of a word. +*/ +static void soundexFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + char zResult[8]; + const u8 *zIn; + int i, j; + static const unsigned char iCode[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0, + 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0, + 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, + }; + assert( argc==1 ); + zIn = (u8*)sqlite3_value_text(argv[0]); + if( zIn==0 ) zIn = (u8*)""; + for(i=0; zIn[i] && !isalpha(zIn[i]); i++){} + if( zIn[i] ){ + u8 prevcode = iCode[zIn[i]&0x7f]; + zResult[0] = toupper(zIn[i]); + for(j=1; j<4 && zIn[i]; i++){ + int code = iCode[zIn[i]&0x7f]; + if( code>0 ){ + if( code!=prevcode ){ + prevcode = code; + zResult[j++] = code + '0'; + } + }else{ + prevcode = 0; + } + } + while( j<4 ){ + zResult[j++] = '0'; + } + zResult[j] = 0; + sqlite3_result_text(context, zResult, 4, SQLITE_TRANSIENT); + }else{ + sqlite3_result_text(context, "?000", 4, SQLITE_STATIC); + } +} +#endif + +#ifndef SQLITE_OMIT_LOAD_EXTENSION +/* +** A function that loads a shared-library extension then returns NULL. +*/ +static void loadExt(sqlite3_context *context, int argc, sqlite3_value **argv){ + const char *zFile = (const char *)sqlite3_value_text(argv[0]); + const char *zProc; + sqlite3 *db = sqlite3_context_db_handle(context); + char *zErrMsg = 0; + + if( argc==2 ){ + zProc = (const char *)sqlite3_value_text(argv[1]); + }else{ + zProc = 0; + } + if( zFile && sqlite3_load_extension(db, zFile, zProc, &zErrMsg) ){ + sqlite3_result_error(context, zErrMsg, -1); + sqlite3_free(zErrMsg); + } +} +#endif + + +/* +** An instance of the following structure holds the context of a +** sum() or avg() aggregate computation. +*/ +typedef struct SumCtx SumCtx; +struct SumCtx { + double rSum; /* Floating point sum */ + i64 iSum; /* Integer sum */ + i64 cnt; /* Number of elements summed */ + u8 overflow; /* True if integer overflow seen */ + u8 approx; /* True if non-integer value was input to the sum */ +}; + +/* +** Routines used to compute the sum, average, and total. +** +** The SUM() function follows the (broken) SQL standard which means +** that it returns NULL if it sums over no inputs. TOTAL returns +** 0.0 in that case. In addition, TOTAL always returns a float where +** SUM might return an integer if it never encounters a floating point +** value. TOTAL never fails, but SUM might through an exception if +** it overflows an integer. +*/ +static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){ + SumCtx *p; + int type; + assert( argc==1 ); + p = sqlite3_aggregate_context(context, sizeof(*p)); + type = sqlite3_value_numeric_type(argv[0]); + if( p && type!=SQLITE_NULL ){ + p->cnt++; + if( type==SQLITE_INTEGER ){ + i64 v = sqlite3_value_int64(argv[0]); + p->rSum += v; + if( (p->approx|p->overflow)==0 ){ + i64 iNewSum = p->iSum + v; + int s1 = p->iSum >> (sizeof(i64)*8-1); + int s2 = v >> (sizeof(i64)*8-1); + int s3 = iNewSum >> (sizeof(i64)*8-1); + p->overflow = (s1&s2&~s3) | (~s1&~s2&s3); + p->iSum = iNewSum; + } + }else{ + p->rSum += sqlite3_value_double(argv[0]); + p->approx = 1; + } + } +} +static void sumFinalize(sqlite3_context *context){ + SumCtx *p; + p = sqlite3_aggregate_context(context, 0); + if( p && p->cnt>0 ){ + if( p->overflow ){ + sqlite3_result_error(context,"integer overflow",-1); + }else if( p->approx ){ + sqlite3_result_double(context, p->rSum); + }else{ + sqlite3_result_int64(context, p->iSum); + } + } +} +static void avgFinalize(sqlite3_context *context){ + SumCtx *p; + p = sqlite3_aggregate_context(context, 0); + if( p && p->cnt>0 ){ + sqlite3_result_double(context, p->rSum/(double)p->cnt); + } +} +static void totalFinalize(sqlite3_context *context){ + SumCtx *p; + p = sqlite3_aggregate_context(context, 0); + sqlite3_result_double(context, p ? p->rSum : 0.0); +} + +/* +** The following structure keeps track of state information for the +** count() aggregate function. +*/ +typedef struct CountCtx CountCtx; +struct CountCtx { + i64 n; +}; + +/* +** Routines to implement the count() aggregate function. +*/ +static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){ + CountCtx *p; + p = sqlite3_aggregate_context(context, sizeof(*p)); + if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0])) && p ){ + p->n++; + } +} +static void countFinalize(sqlite3_context *context){ + CountCtx *p; + p = sqlite3_aggregate_context(context, 0); + sqlite3_result_int64(context, p ? p->n : 0); +} + +/* +** Routines to implement min() and max() aggregate functions. +*/ +static void minmaxStep(sqlite3_context *context, int argc, sqlite3_value **argv){ + Mem *pArg = (Mem *)argv[0]; + Mem *pBest; + + if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; + pBest = (Mem *)sqlite3_aggregate_context(context, sizeof(*pBest)); + if( !pBest ) return; + + if( pBest->flags ){ + int max; + int cmp; + CollSeq *pColl = sqlite3GetFuncCollSeq(context); + /* This step function is used for both the min() and max() aggregates, + ** the only difference between the two being that the sense of the + ** comparison is inverted. For the max() aggregate, the + ** sqlite3_user_data() function returns (void *)-1. For min() it + ** returns (void *)db, where db is the sqlite3* database pointer. + ** Therefore the next statement sets variable 'max' to 1 for the max() + ** aggregate, or 0 for min(). + */ + max = sqlite3_user_data(context)!=0; + cmp = sqlite3MemCompare(pBest, pArg, pColl); + if( (max && cmp<0) || (!max && cmp>0) ){ + sqlite3VdbeMemCopy(pBest, pArg); + } + }else{ + sqlite3VdbeMemCopy(pBest, pArg); + } +} +static void minMaxFinalize(sqlite3_context *context){ + sqlite3_value *pRes; + pRes = (sqlite3_value *)sqlite3_aggregate_context(context, 0); + if( pRes ){ + if( pRes->flags ){ + sqlite3_result_value(context, pRes); + } + sqlite3VdbeMemRelease(pRes); + } +} + +/* +** group_concat(EXPR, ?SEPARATOR?) +*/ +static void groupConcatStep( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const char *zVal; + StrAccum *pAccum; + const char *zSep; + int nVal, nSep, i; + if( argc==0 || sqlite3_value_type(argv[0])==SQLITE_NULL ) return; + pAccum = (StrAccum*)sqlite3_aggregate_context(context, sizeof(*pAccum)); + + if( pAccum ){ + sqlite3 *db = sqlite3_context_db_handle(context); + pAccum->useMalloc = 1; + pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH]; + if( pAccum->nChar ){ + if( argc>1 ){ + zSep = (char*)sqlite3_value_text(argv[argc-1]); + nSep = sqlite3_value_bytes(argv[argc-1]); + }else{ + zSep = ","; + nSep = 1; + } + sqlite3StrAccumAppend(pAccum, zSep, nSep); + } + i = 0; + do{ + zVal = (char*)sqlite3_value_text(argv[i]); + nVal = sqlite3_value_bytes(argv[i]); + sqlite3StrAccumAppend(pAccum, zVal, nVal); + i++; + }while( i<argc-1 ); + } +} +static void groupConcatFinalize(sqlite3_context *context){ + StrAccum *pAccum; + pAccum = sqlite3_aggregate_context(context, 0); + if( pAccum ){ + if( pAccum->tooBig ){ + sqlite3_result_error_toobig(context); + }else if( pAccum->mallocFailed ){ + sqlite3_result_error_nomem(context); + }else{ + sqlite3_result_text(context, sqlite3StrAccumFinish(pAccum), -1, + sqlite3_free); + } + } +} + +/* +** This function registered all of the above C functions as SQL +** functions. This should be the only routine in this file with +** external linkage. +*/ +void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ + static const struct { + char *zName; + signed char nArg; + u8 argType; /* 1: 0, 2: 1, 3: 2,... N: N-1. */ + u8 eTextRep; /* 1: UTF-16. 0: UTF-8 */ + u8 needCollSeq; + void (*xFunc)(sqlite3_context*,int,sqlite3_value **); + } aFuncs[] = { + { "min", -1, 0, SQLITE_UTF8, 1, minmaxFunc }, + { "min", 0, 0, SQLITE_UTF8, 1, 0 }, + { "max", -1, 1, SQLITE_UTF8, 1, minmaxFunc }, + { "max", 0, 1, SQLITE_UTF8, 1, 0 }, + { "typeof", 1, 0, SQLITE_UTF8, 0, typeofFunc }, + { "length", 1, 0, SQLITE_UTF8, 0, lengthFunc }, + { "substr", 2, 0, SQLITE_UTF8, 0, substrFunc }, + { "substr", 3, 0, SQLITE_UTF8, 0, substrFunc }, + { "abs", 1, 0, SQLITE_UTF8, 0, absFunc }, + { "round", 1, 0, SQLITE_UTF8, 0, roundFunc }, + { "round", 2, 0, SQLITE_UTF8, 0, roundFunc }, + { "upper", 1, 0, SQLITE_UTF8, 0, upperFunc }, + { "lower", 1, 0, SQLITE_UTF8, 0, lowerFunc }, + { "coalesce", -1, 0, SQLITE_UTF8, 0, ifnullFunc }, + { "coalesce", 0, 0, SQLITE_UTF8, 0, 0 }, + { "coalesce", 1, 0, SQLITE_UTF8, 0, 0 }, + { "hex", 1, 0, SQLITE_UTF8, 0, hexFunc }, + { "ifnull", 2, 0, SQLITE_UTF8, 1, ifnullFunc }, + { "random", -1, 0, SQLITE_UTF8, 0, randomFunc }, + { "randomblob", 1, 0, SQLITE_UTF8, 0, randomBlob }, + { "nullif", 2, 0, SQLITE_UTF8, 1, nullifFunc }, + { "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc}, + { "quote", 1, 0, SQLITE_UTF8, 0, quoteFunc }, + { "last_insert_rowid", 0, 0, SQLITE_UTF8, 0, last_insert_rowid }, + { "changes", 0, 0, SQLITE_UTF8, 0, changes }, + { "total_changes", 0, 0, SQLITE_UTF8, 0, total_changes }, + { "replace", 3, 0, SQLITE_UTF8, 0, replaceFunc }, + { "ltrim", 1, 1, SQLITE_UTF8, 0, trimFunc }, + { "ltrim", 2, 1, SQLITE_UTF8, 0, trimFunc }, + { "rtrim", 1, 2, SQLITE_UTF8, 0, trimFunc }, + { "rtrim", 2, 2, SQLITE_UTF8, 0, trimFunc }, + { "trim", 1, 3, SQLITE_UTF8, 0, trimFunc }, + { "trim", 2, 3, SQLITE_UTF8, 0, trimFunc }, + { "zeroblob", 1, 0, SQLITE_UTF8, 0, zeroblobFunc }, +#ifdef SQLITE_SOUNDEX + { "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc}, +#endif +#ifndef SQLITE_OMIT_LOAD_EXTENSION + { "load_extension", 1, 0, SQLITE_UTF8, 0, loadExt }, + { "load_extension", 2, 0, SQLITE_UTF8, 0, loadExt }, +#endif + }; + static const struct { + char *zName; + signed char nArg; + u8 argType; + u8 needCollSeq; + void (*xStep)(sqlite3_context*,int,sqlite3_value**); + void (*xFinalize)(sqlite3_context*); + } aAggs[] = { + { "min", 1, 0, 1, minmaxStep, minMaxFinalize }, + { "max", 1, 1, 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 }, + { "group_concat", -1, 0, 0, groupConcatStep, groupConcatFinalize }, + }; + int i; + + for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ + void *pArg; + u8 argType = aFuncs[i].argType; + pArg = SQLITE_INT_TO_PTR(argType); + 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, + strlen(aFuncs[i].zName), aFuncs[i].nArg, aFuncs[i].eTextRep, 0); + if( pFunc && aFuncs[i].needCollSeq ){ + pFunc->needCollSeq = 1; + } + } + } +#ifndef SQLITE_OMIT_ALTERTABLE + sqlite3AlterFunctions(db); +#endif +#ifndef SQLITE_OMIT_PARSER + sqlite3AttachFunctions(db); +#endif + for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){ + void *pArg = SQLITE_INT_TO_PTR(aAggs[i].argType); + sqlite3CreateFunc(db, aAggs[i].zName, aAggs[i].nArg, SQLITE_UTF8, + pArg, 0, aAggs[i].xStep, aAggs[i].xFinalize); + if( aAggs[i].needCollSeq ){ + FuncDef *pFunc = sqlite3FindFunction( db, aAggs[i].zName, + strlen(aAggs[i].zName), aAggs[i].nArg, SQLITE_UTF8, 0); + if( pFunc && aAggs[i].needCollSeq ){ + pFunc->needCollSeq = 1; + } + } + } + sqlite3RegisterDateTimeFunctions(db); + if( !db->mallocFailed ){ + int rc = sqlite3_overload_function(db, "MATCH", 2); + assert( rc==SQLITE_NOMEM || rc==SQLITE_OK ); + if( rc==SQLITE_NOMEM ){ + db->mallocFailed = 1; + } + } +#ifdef SQLITE_SSE + (void)sqlite3SseFunctions(db); +#endif +#ifdef SQLITE_CASE_SENSITIVE_LIKE + sqlite3RegisterLikeFunctions(db, 1); +#else + sqlite3RegisterLikeFunctions(db, 0); +#endif +} + +/* +** Set the LIKEOPT flag on the 2-argument function with the given name. +*/ +static void setLikeOptFlag(sqlite3 *db, const char *zName, int flagVal){ + FuncDef *pDef; + pDef = sqlite3FindFunction(db, zName, strlen(zName), 2, SQLITE_UTF8, 0); + if( pDef ){ + pDef->flags = flagVal; + } +} + +/* +** Register the built-in LIKE and GLOB functions. The caseSensitive +** parameter determines whether or not the LIKE operator is case +** sensitive. GLOB is always case sensitive. +*/ +void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){ + struct compareInfo *pInfo; + if( caseSensitive ){ + pInfo = (struct compareInfo*)&likeInfoAlt; + }else{ + pInfo = (struct compareInfo*)&likeInfoNorm; + } + sqlite3CreateFunc(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0); + sqlite3CreateFunc(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0); + sqlite3CreateFunc(db, "glob", 2, SQLITE_UTF8, + (struct compareInfo*)&globInfo, likeFunc, 0,0); + setLikeOptFlag(db, "glob", SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE); + setLikeOptFlag(db, "like", + caseSensitive ? (SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE) : SQLITE_FUNC_LIKE); +} + +/* +** pExpr points to an expression which implements a function. If +** it is appropriate to apply the LIKE optimization to that function +** then set aWc[0] through aWc[2] to the wildcard characters and +** return TRUE. If the function is not a LIKE-style function then +** return FALSE. +*/ +int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){ + FuncDef *pDef; + if( pExpr->op!=TK_FUNCTION || !pExpr->pList ){ + return 0; + } + if( pExpr->pList->nExpr!=2 ){ + return 0; + } + 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; + } + + /* The memcpy() statement assumes that the wildcard characters are + ** the first three statements in the compareInfo structure. The + ** asserts() that follow verify that assumption + */ + memcpy(aWc, pDef->pUserData, 3); + assert( (char*)&likeInfoAlt == (char*)&likeInfoAlt.matchAll ); + assert( &((char*)&likeInfoAlt)[1] == (char*)&likeInfoAlt.matchOne ); + assert( &((char*)&likeInfoAlt)[2] == (char*)&likeInfoAlt.matchSet ); + *pIsNocase = (pDef->flags & SQLITE_FUNC_CASE)==0; + return 1; +} diff --git a/third_party/sqlite/src/global.c b/third_party/sqlite/src/global.c new file mode 100755 index 0000000..fa59d4a --- /dev/null +++ b/third_party/sqlite/src/global.c @@ -0,0 +1,77 @@ +/* +** 2008 June 13 +** +** 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 definitions of global variables and contants. +** +** $Id: global.c,v 1.4 2008/07/28 19:34:53 drh Exp $ +*/ +#include "sqliteInt.h" + + +/* An array to map all upper-case characters into their corresponding +** lower-case character. +** +** SQLite only considers US-ASCII (or EBCDIC) characters. We do not +** handle case conversions for the UTF character set since the tables +** involved are nearly as big or bigger than SQLite itself. +*/ +const unsigned char sqlite3UpperToLower[] = { +#ifdef SQLITE_ASCII + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103, + 104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121, + 122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107, + 108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125, + 126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161, + 162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179, + 180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197, + 198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215, + 216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233, + 234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251, + 252,253,254,255 +#endif +#ifdef SQLITE_EBCDIC + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 0x */ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 1x */ + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 2x */ + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 3x */ + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 4x */ + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, /* 5x */ + 96, 97, 66, 67, 68, 69, 70, 71, 72, 73,106,107,108,109,110,111, /* 6x */ + 112, 81, 82, 83, 84, 85, 86, 87, 88, 89,122,123,124,125,126,127, /* 7x */ + 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, /* 8x */ + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,156,159, /* 9x */ + 160,161,162,163,164,165,166,167,168,169,170,171,140,141,142,175, /* Ax */ + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, /* Bx */ + 192,129,130,131,132,133,134,135,136,137,202,203,204,205,206,207, /* Cx */ + 208,145,146,147,148,149,150,151,152,153,218,219,220,221,222,223, /* Dx */ + 224,225,162,163,164,165,166,167,168,169,232,203,204,205,206,207, /* Ex */ + 239,240,241,242,243,244,245,246,247,248,249,219,220,221,222,255, /* Fx */ +#endif +}; + +/* +** The following singleton contains the global configuration for +** the SQLite library. +*/ +struct Sqlite3Config sqlite3Config = { + 1, /* bMemstat */ + 1, /* bCoreMutex */ + 1, /* bFullMutex */ + 0x7ffffffe, /* mxStrlen */ + 100, /* szLookaside */ + 500, /* nLookaside */ + /* Other fields all default to zero */ +}; diff --git a/third_party/sqlite/src/hash.c b/third_party/sqlite/src/hash.c new file mode 100755 index 0000000..df73698 --- /dev/null +++ b/third_party/sqlite/src/hash.c @@ -0,0 +1,423 @@ +/* +** 2001 September 22 +** +** 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 is the implementation of generic hash-tables +** used in SQLite. +** +** $Id: hash.c,v 1.30 2008/06/20 14:59:51 danielk1977 Exp $ +*/ +#include "sqliteInt.h" +#include <assert.h> + +/* Turn bulk memory into a hash table object by initializing the +** fields of the Hash structure. +** +** "pNew" is a pointer to the hash table that is to be initialized. +** keyClass is one of the constants SQLITE_HASH_INT, SQLITE_HASH_POINTER, +** SQLITE_HASH_BINARY, or SQLITE_HASH_STRING. The value of keyClass +** determines what kind of key the hash table will use. "copyKey" is +** true if the hash table should make its own private copy of keys and +** false if it should just use the supplied pointer. CopyKey only makes +** sense for SQLITE_HASH_STRING and SQLITE_HASH_BINARY and is ignored +** for other key classes. +*/ +void sqlite3HashInit(Hash *pNew, int keyClass, int copyKey){ + assert( pNew!=0 ); + assert( keyClass>=SQLITE_HASH_STRING && keyClass<=SQLITE_HASH_BINARY ); + pNew->keyClass = keyClass; +#if 0 + if( keyClass==SQLITE_HASH_POINTER || keyClass==SQLITE_HASH_INT ) copyKey = 0; +#endif + pNew->copyKey = copyKey; + pNew->first = 0; + pNew->count = 0; + pNew->htsize = 0; + pNew->ht = 0; +} + +/* Remove all entries from a hash table. Reclaim all memory. +** Call this routine to delete a hash table or to reset a hash table +** to the empty state. +*/ +void sqlite3HashClear(Hash *pH){ + HashElem *elem; /* For looping over all elements of the table */ + + assert( pH!=0 ); + elem = pH->first; + pH->first = 0; + sqlite3_free(pH->ht); + pH->ht = 0; + pH->htsize = 0; + while( elem ){ + HashElem *next_elem = elem->next; + if( pH->copyKey && elem->pKey ){ + sqlite3_free(elem->pKey); + } + sqlite3_free(elem); + elem = next_elem; + } + pH->count = 0; +} + +#if 0 /* NOT USED */ +/* +** Hash and comparison functions when the mode is SQLITE_HASH_INT +*/ +static int intHash(const void *pKey, int nKey){ + return nKey ^ (nKey<<8) ^ (nKey>>8); +} +static int intCompare(const void *pKey1, int n1, const void *pKey2, int n2){ + return n2 - n1; +} +#endif + +#if 0 /* NOT USED */ +/* +** Hash and comparison functions when the mode is SQLITE_HASH_POINTER +*/ +static int ptrHash(const void *pKey, int nKey){ + uptr x = Addr(pKey); + return x ^ (x<<8) ^ (x>>8); +} +static int ptrCompare(const void *pKey1, int n1, const void *pKey2, int n2){ + if( pKey1==pKey2 ) return 0; + if( pKey1<pKey2 ) return -1; + return 1; +} +#endif + +/* +** Hash and comparison functions when the mode is SQLITE_HASH_STRING +*/ +static int strHash(const void *pKey, int nKey){ + const char *z = (const char *)pKey; + int h = 0; + if( nKey<=0 ) nKey = strlen(z); + while( nKey > 0 ){ + h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++]; + nKey--; + } + return h & 0x7fffffff; +} +static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){ + if( n1!=n2 ) return 1; + return sqlite3StrNICmp((const char*)pKey1,(const char*)pKey2,n1); +} + +/* +** Hash and comparison functions when the mode is SQLITE_HASH_BINARY +*/ +static int binHash(const void *pKey, int nKey){ + int h = 0; + const char *z = (const char *)pKey; + while( nKey-- > 0 ){ + h = (h<<3) ^ h ^ *(z++); + } + return h & 0x7fffffff; +} +static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){ + if( n1!=n2 ) return 1; + return memcmp(pKey1,pKey2,n1); +} + +/* +** Return a pointer to the appropriate hash function given the key class. +** +** The C syntax in this function definition may be unfamilar to some +** programmers, so we provide the following additional explanation: +** +** The name of the function is "hashFunction". The function takes a +** single parameter "keyClass". The return value of hashFunction() +** is a pointer to another function. Specifically, the return value +** of hashFunction() is a pointer to a function that takes two parameters +** with types "const void*" and "int" and returns an "int". +*/ +static int (*hashFunction(int keyClass))(const void*,int){ +#if 0 /* HASH_INT and HASH_POINTER are never used */ + switch( keyClass ){ + case SQLITE_HASH_INT: return &intHash; + case SQLITE_HASH_POINTER: return &ptrHash; + case SQLITE_HASH_STRING: return &strHash; + case SQLITE_HASH_BINARY: return &binHash;; + default: break; + } + return 0; +#else + if( keyClass==SQLITE_HASH_STRING ){ + return &strHash; + }else{ + assert( keyClass==SQLITE_HASH_BINARY ); + return &binHash; + } +#endif +} + +/* +** Return a pointer to the appropriate hash function given the key class. +** +** For help in interpreted the obscure C code in the function definition, +** see the header comment on the previous function. +*/ +static int (*compareFunction(int keyClass))(const void*,int,const void*,int){ +#if 0 /* HASH_INT and HASH_POINTER are never used */ + switch( keyClass ){ + case SQLITE_HASH_INT: return &intCompare; + case SQLITE_HASH_POINTER: return &ptrCompare; + case SQLITE_HASH_STRING: return &strCompare; + case SQLITE_HASH_BINARY: return &binCompare; + default: break; + } + return 0; +#else + if( keyClass==SQLITE_HASH_STRING ){ + return &strCompare; + }else{ + assert( keyClass==SQLITE_HASH_BINARY ); + return &binCompare; + } +#endif +} + +/* Link an element into the hash table +*/ +static void insertElement( + Hash *pH, /* The complete hash table */ + struct _ht *pEntry, /* The entry into which pNew is inserted */ + HashElem *pNew /* The element to be inserted */ +){ + HashElem *pHead; /* First element already in pEntry */ + pHead = pEntry->chain; + if( pHead ){ + pNew->next = pHead; + pNew->prev = pHead->prev; + if( pHead->prev ){ pHead->prev->next = pNew; } + else { pH->first = pNew; } + pHead->prev = pNew; + }else{ + pNew->next = pH->first; + if( pH->first ){ pH->first->prev = pNew; } + pNew->prev = 0; + pH->first = pNew; + } + pEntry->count++; + pEntry->chain = pNew; +} + + +/* Resize the hash table so that it cantains "new_size" buckets. +** "new_size" must be a power of 2. The hash table might fail +** to resize if sqlite3_malloc() fails. +*/ +static void rehash(Hash *pH, int new_size){ + struct _ht *new_ht; /* The new hash table */ + HashElem *elem, *next_elem; /* For looping over existing elements */ + int (*xHash)(const void*,int); /* The hash function */ + +#ifdef SQLITE_MALLOC_SOFT_LIMIT + if( new_size*sizeof(struct _ht)>SQLITE_MALLOC_SOFT_LIMIT ){ + new_size = SQLITE_MALLOC_SOFT_LIMIT/sizeof(struct _ht); + } + if( new_size==pH->htsize ) return; +#endif + + /* There is a call to sqlite3_malloc() inside rehash(). If there is + ** already an allocation at pH->ht, then if this malloc() fails it + ** is benign (since failing to resize a hash table is a performance + ** hit only, not a fatal error). + */ + if( pH->htsize>0 ) sqlite3BeginBenignMalloc(); + new_ht = (struct _ht *)sqlite3MallocZero( new_size*sizeof(struct _ht) ); + if( pH->htsize>0 ) sqlite3EndBenignMalloc(); + + if( new_ht==0 ) return; + sqlite3_free(pH->ht); + pH->ht = new_ht; + pH->htsize = new_size; + xHash = hashFunction(pH->keyClass); + for(elem=pH->first, pH->first=0; elem; elem = next_elem){ + int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1); + next_elem = elem->next; + insertElement(pH, &new_ht[h], elem); + } +} + +/* This function (for internal use only) locates an element in an +** hash table that matches the given key. The hash for this key has +** already been computed and is passed as the 4th parameter. +*/ +static HashElem *findElementGivenHash( + const Hash *pH, /* The pH to be searched */ + const void *pKey, /* The key we are searching for */ + int nKey, + int h /* The hash for this key. */ +){ + HashElem *elem; /* Used to loop thru the element list */ + int count; /* Number of elements left to test */ + int (*xCompare)(const void*,int,const void*,int); /* comparison function */ + + if( pH->ht ){ + struct _ht *pEntry = &pH->ht[h]; + elem = pEntry->chain; + count = pEntry->count; + xCompare = compareFunction(pH->keyClass); + while( count-- && elem ){ + if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){ + return elem; + } + elem = elem->next; + } + } + return 0; +} + +/* Remove a single entry from the hash table given a pointer to that +** element and a hash on the element's key. +*/ +static void removeElementGivenHash( + Hash *pH, /* The pH containing "elem" */ + HashElem* elem, /* The element to be removed from the pH */ + int h /* Hash value for the element */ +){ + struct _ht *pEntry; + if( elem->prev ){ + elem->prev->next = elem->next; + }else{ + pH->first = elem->next; + } + if( elem->next ){ + elem->next->prev = elem->prev; + } + pEntry = &pH->ht[h]; + if( pEntry->chain==elem ){ + pEntry->chain = elem->next; + } + pEntry->count--; + if( pEntry->count<=0 ){ + pEntry->chain = 0; + } + if( pH->copyKey ){ + sqlite3_free(elem->pKey); + } + sqlite3_free( 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 +** that matches pKey,nKey. Return a pointer to the corresponding +** HashElem structure for this element if it is found, or NULL +** otherwise. +*/ +HashElem *sqlite3HashFindElem(const Hash *pH, const void *pKey, int nKey){ + int h; /* A hash on key */ + HashElem *elem; /* The element that matches key */ + int (*xHash)(const void*,int); /* The hash function */ + + if( pH==0 || pH->ht==0 ) return 0; + xHash = hashFunction(pH->keyClass); + assert( xHash!=0 ); + h = (*xHash)(pKey,nKey); + elem = findElementGivenHash(pH,pKey,nKey, h % pH->htsize); + return elem; +} + +/* Attempt to locate an element of the hash table pH with a key +** that matches pKey,nKey. Return the data for this element if it is +** found, or NULL if there is no match. +*/ +void *sqlite3HashFind(const Hash *pH, const void *pKey, int nKey){ + HashElem *elem; /* The element that matches key */ + elem = sqlite3HashFindElem(pH, pKey, nKey); + return elem ? elem->data : 0; +} + +/* Insert an element into the hash table pH. The key is pKey,nKey +** and the data is "data". +** +** If no element exists with a matching key, then a new +** element is created. A copy of the key is made if the copyKey +** flag is set. NULL is returned. +** +** If another element already exists with the same key, then the +** new data replaces the old data and the old data is returned. +** The key is not copied in this instance. If a malloc fails, then +** the new data is returned and the hash table is unchanged. +** +** If the "data" parameter to this function is NULL, then the +** element corresponding to "key" is removed from the hash table. +*/ +void *sqlite3HashInsert(Hash *pH, const void *pKey, int nKey, void *data){ + int hraw; /* Raw hash value of the key */ + int h; /* the hash of the key modulo hash table size */ + HashElem *elem; /* Used to loop thru the element list */ + HashElem *new_elem; /* New element added to the pH */ + int (*xHash)(const void*,int); /* The hash function */ + + assert( pH!=0 ); + xHash = hashFunction(pH->keyClass); + assert( xHash!=0 ); + hraw = (*xHash)(pKey, nKey); + if( pH->htsize ){ + h = hraw % pH->htsize; + elem = findElementGivenHash(pH,pKey,nKey,h); + if( elem ){ + void *old_data = elem->data; + if( data==0 ){ + removeElementGivenHash(pH,elem,h); + }else{ + elem->data = data; + if( !pH->copyKey ){ + elem->pKey = (void *)pKey; + } + assert(nKey==elem->nKey); + } + return old_data; + } + } + if( data==0 ) return 0; + new_elem = (HashElem*)sqlite3Malloc( sizeof(HashElem) ); + if( new_elem==0 ) return data; + if( pH->copyKey && pKey!=0 ){ + new_elem->pKey = sqlite3Malloc( nKey ); + if( new_elem->pKey==0 ){ + sqlite3_free(new_elem); + return data; + } + memcpy((void*)new_elem->pKey, pKey, nKey); + }else{ + new_elem->pKey = (void*)pKey; + } + new_elem->nKey = nKey; + pH->count++; + if( pH->htsize==0 ){ + rehash(pH, 128/sizeof(pH->ht[0])); + if( pH->htsize==0 ){ + pH->count = 0; + if( pH->copyKey ){ + sqlite3_free(new_elem->pKey); + } + sqlite3_free(new_elem); + return data; + } + } + if( pH->count > pH->htsize ){ + rehash(pH,pH->htsize*2); + } + assert( pH->htsize>0 ); + h = hraw % pH->htsize; + insertElement(pH, &pH->ht[h], new_elem); + new_elem->data = data; + return 0; +} diff --git a/third_party/sqlite/src/hash.h b/third_party/sqlite/src/hash.h new file mode 100755 index 0000000..e3274e9 --- /dev/null +++ b/third_party/sqlite/src/hash.h @@ -0,0 +1,110 @@ +/* +** 2001 September 22 +** +** 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 is the header file for the generic hash-table implemenation +** used in SQLite. +** +** $Id: hash.h,v 1.11 2007/09/04 14:31:47 danielk1977 Exp $ +*/ +#ifndef _SQLITE_HASH_H_ +#define _SQLITE_HASH_H_ + +/* Forward declarations of structures. */ +typedef struct Hash Hash; +typedef struct HashElem HashElem; + +/* A complete hash table is an instance of the following structure. +** The internals of this structure are intended to be opaque -- client +** code should not attempt to access or modify the fields of this structure +** directly. Change this structure only by using the routines below. +** However, many of the "procedures" and "functions" for modifying and +** accessing this structure are really macros, so we can't really make +** this structure opaque. +*/ +struct Hash { + char keyClass; /* SQLITE_HASH_INT, _POINTER, _STRING, _BINARY */ + char copyKey; /* True if copy of key made on insert */ + int count; /* Number of entries in this table */ + int htsize; /* Number of buckets in the hash table */ + HashElem *first; /* The first element of the array */ + struct _ht { /* the hash table */ + int count; /* Number of entries with this hash */ + HashElem *chain; /* Pointer to first entry with this hash */ + } *ht; +}; + +/* Each element in the hash table is an instance of the following +** structure. All elements are stored on a single doubly-linked list. +** +** Again, this structure is intended to be opaque, but it can't really +** be opaque because it is used by macros. +*/ +struct HashElem { + HashElem *next, *prev; /* Next and previous elements in the table */ + void *data; /* Data associated with this element */ + void *pKey; int nKey; /* Key associated with this element */ +}; + +/* +** There are 4 different modes of operation for a hash table: +** +** SQLITE_HASH_INT nKey is used as the key and pKey is ignored. +** +** SQLITE_HASH_POINTER pKey is used as the key and nKey is ignored. +** +** SQLITE_HASH_STRING pKey points to a string that is nKey bytes long +** (including the null-terminator, if any). Case +** is ignored in comparisons. +** +** SQLITE_HASH_BINARY pKey points to binary data nKey bytes long. +** memcmp() is used to compare keys. +** +** A copy of the key is made for SQLITE_HASH_STRING and SQLITE_HASH_BINARY +** if the copyKey parameter to HashInit is 1. +*/ +/* #define SQLITE_HASH_INT 1 // NOT USED */ +/* #define SQLITE_HASH_POINTER 2 // NOT USED */ +#define SQLITE_HASH_STRING 3 +#define SQLITE_HASH_BINARY 4 + +/* +** Access routines. To delete, insert a NULL pointer. +*/ +void sqlite3HashInit(Hash*, int keytype, int copyKey); +void *sqlite3HashInsert(Hash*, const void *pKey, int nKey, void *pData); +void *sqlite3HashFind(const Hash*, const void *pKey, int nKey); +HashElem *sqlite3HashFindElem(const Hash*, const void *pKey, int nKey); +void sqlite3HashClear(Hash*); + +/* +** Macros for looping over all elements of a hash table. The idiom is +** like this: +** +** Hash h; +** HashElem *p; +** ... +** for(p=sqliteHashFirst(&h); p; p=sqliteHashNext(p)){ +** SomeStructure *pData = sqliteHashData(p); +** // do something with pData +** } +*/ +#define sqliteHashFirst(H) ((H)->first) +#define sqliteHashNext(E) ((E)->next) +#define sqliteHashData(E) ((E)->data) +#define sqliteHashKey(E) ((E)->pKey) +#define sqliteHashKeysize(E) ((E)->nKey) + +/* +** Number of entries in a hash table +*/ +#define sqliteHashCount(H) ((H)->count) + +#endif /* _SQLITE_HASH_H_ */ diff --git a/third_party/sqlite/src/hwtime.h b/third_party/sqlite/src/hwtime.h new file mode 100755 index 0000000..896041e --- /dev/null +++ b/third_party/sqlite/src/hwtime.h @@ -0,0 +1,87 @@ +/* +** 2008 May 27 +** +** 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 inline asm code for retrieving "high-performance" +** counters for x86 class CPUs. +** +** $Id: hwtime.h,v 1.3 2008/08/01 14:33:15 shane Exp $ +*/ +#ifndef _HWTIME_H_ +#define _HWTIME_H_ + +/* +** The following routine only works on pentium-class (or newer) processors. +** It uses the RDTSC opcode to read the cycle count value out of the +** processor and returns that value. This can be used for high-res +** profiling. +*/ +#if (defined(__GNUC__) || defined(_MSC_VER)) && \ + (defined(i386) || defined(__i386__) || defined(_M_IX86)) + + #if defined(__GNUC__) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned int lo, hi; + __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); + return (sqlite_uint64)hi << 32 | lo; + } + + #elif defined(_MSC_VER) + + __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){ + __asm { + rdtsc + ret ; return value at EDX:EAX + } + } + + #endif + +#elif (defined(__GNUC__) && defined(__x86_64__)) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned long val; + __asm__ __volatile__ ("rdtsc" : "=A" (val)); + return val; + } + +#elif (defined(__GNUC__) && defined(__ppc__)) + + __inline__ sqlite_uint64 sqlite3Hwtime(void){ + unsigned long long retval; + unsigned long junk; + __asm__ __volatile__ ("\n\ + 1: mftbu %1\n\ + mftb %L0\n\ + mftbu %0\n\ + cmpw %0,%1\n\ + bne 1b" + : "=r" (retval), "=r" (junk)); + return retval; + } + +#else + + #error Need implementation of sqlite3Hwtime() for your platform. + + /* + ** To compile without implementing sqlite3Hwtime() for your platform, + ** you can remove the above #error and use the following + ** stub function. You will lose timing support for many + ** of the debugging and testing utilities, but it should at + ** least compile and run. + */ + sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); } + +#endif + +#endif /* !defined(_HWTIME_H_) */ diff --git a/third_party/sqlite/src/insert.c b/third_party/sqlite/src/insert.c new file mode 100755 index 0000000..9a3d46f --- /dev/null +++ b/third_party/sqlite/src/insert.c @@ -0,0 +1,1738 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains C code routines that are called by the parser +** to handle INSERT statements in SQLite. +** +** $Id: insert.c,v 1.248 2008/07/28 19:34:53 drh Exp $ +*/ +#include "sqliteInt.h" + +/* +** Set P4 of the most recently inserted opcode to a column affinity +** string for index pIdx. A column affinity string has one character +** for each column in the table, according to the affinity of the column: +** +** Character Column affinity +** ------------------------------ +** 'a' TEXT +** 'b' NONE +** 'c' NUMERIC +** 'd' INTEGER +** 'e' REAL +** +** An extra 'b' is appended to the end of the string to cover the +** rowid that appears as the last column in every index. +*/ +void sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){ + if( !pIdx->zColAff ){ + /* The first time a column affinity string for a particular index is + ** required, it is allocated and populated here. It is then stored as + ** a member of the Index structure for subsequent use. + ** + ** The column affinity string will eventually be deleted by + ** sqliteDeleteIndex() when the Index structure itself is cleaned + ** up. + */ + int n; + Table *pTab = pIdx->pTable; + sqlite3 *db = sqlite3VdbeDb(v); + pIdx->zColAff = (char *)sqlite3Malloc(pIdx->nColumn+2); + if( !pIdx->zColAff ){ + db->mallocFailed = 1; + return; + } + for(n=0; n<pIdx->nColumn; n++){ + pIdx->zColAff[n] = pTab->aCol[pIdx->aiColumn[n]].affinity; + } + pIdx->zColAff[n++] = SQLITE_AFF_NONE; + pIdx->zColAff[n] = 0; + } + + sqlite3VdbeChangeP4(v, -1, pIdx->zColAff, 0); +} + +/* +** Set P4 of the most recently inserted opcode to a column affinity +** string for table pTab. A column affinity string has one character +** for each column indexed by the index, according to the affinity of the +** column: +** +** Character Column affinity +** ------------------------------ +** '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 + ** is required, it is allocated and populated here. It is then + ** stored as a member of the Table structure for subsequent use. + ** + ** The column affinity string will eventually be deleted by + ** sqlite3DeleteTable() when the Table structure itself is cleaned up. + */ + if( !pTab->zColAff ){ + char *zColAff; + int i; + sqlite3 *db = sqlite3VdbeDb(v); + + zColAff = (char *)sqlite3Malloc(pTab->nCol+1); + if( !zColAff ){ + db->mallocFailed = 1; + return; + } + + for(i=0; i<pTab->nCol; i++){ + zColAff[i] = pTab->aCol[i].affinity; + } + zColAff[pTab->nCol] = '\0'; + + pTab->zColAff = zColAff; + } + + sqlite3VdbeChangeP4(v, -1, pTab->zColAff, 0); +} + +/* +** Return non-zero if the table pTab in database iDb or any of its indices +** have been opened at any point in the VDBE program beginning at location +** iStartAddr throught the end of the program. This is used to see if +** a statement of the form "INSERT INTO <iDb, pTab> SELECT ..." can +** run without using temporary table for the results of the SELECT. +*/ +static int readsTable(Vdbe *v, int iStartAddr, int iDb, Table *pTab){ + int i; + int iEnd = sqlite3VdbeCurrentAddr(v); + for(i=iStartAddr; i<iEnd; i++){ + VdbeOp *pOp = sqlite3VdbeGetOp(v, i); + assert( pOp!=0 ); + if( pOp->opcode==OP_OpenRead && pOp->p3==iDb ){ + Index *pIndex; + int tnum = pOp->p2; + if( tnum==pTab->tnum ){ + return 1; + } + for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){ + if( tnum==pIndex->tnum ){ + return 1; + } + } + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( pOp->opcode==OP_VOpen && pOp->p4.pVtab==pTab->pVtab ){ + assert( pOp->p4.pVtab!=0 ); + assert( pOp->p4type==P4_VTAB ); + return 1; + } +#endif + } + return 0; +} + +#ifndef SQLITE_OMIT_AUTOINCREMENT +/* +** Write out code to initialize the autoincrement logic. This code +** looks up the current autoincrement value in the sqlite_sequence +** table and stores that value in a register. Code generated by +** autoIncStep() will keep that register holding the largest +** rowid value. Code generated by autoIncEnd() will write the new +** largest value of the counter back into the sqlite_sequence table. +** +** This routine returns the index of the mem[] cell that contains +** the maximum rowid counter. +** +** Three consecutive registers are allocated by this routine. The +** first two hold the name of the target table and the maximum rowid +** inserted into the target table, respectively. +** The third holds the rowid in sqlite_sequence where we will +** write back the revised maximum rowid. This routine returns the +** index of the second of these three registers. +*/ +static int autoIncBegin( + Parse *pParse, /* Parsing context */ + int iDb, /* Index of the database holding pTab */ + Table *pTab /* The table we are writing to */ +){ + int memId = 0; /* Register holding maximum rowid */ + if( pTab->autoInc ){ + Vdbe *v = pParse->pVdbe; + Db *pDb = &pParse->db->aDb[iDb]; + int iCur = pParse->nTab; + int addr; /* Address of the top of the loop */ + assert( v ); + pParse->nMem++; /* Holds name of table */ + memId = ++pParse->nMem; + pParse->nMem++; + sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenRead); + addr = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, pTab->zName, 0); + sqlite3VdbeAddOp2(v, OP_Rewind, iCur, addr+9); + sqlite3VdbeAddOp3(v, OP_Column, iCur, 0, memId); + sqlite3VdbeAddOp3(v, OP_Ne, memId-1, addr+7, memId); + sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); + sqlite3VdbeAddOp2(v, OP_Rowid, iCur, memId+1); + sqlite3VdbeAddOp3(v, OP_Column, iCur, 1, memId); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+9); + sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+2); + sqlite3VdbeAddOp2(v, OP_Integer, 0, memId); + sqlite3VdbeAddOp2(v, OP_Close, iCur, 0); + } + return memId; +} + +/* +** Update the maximum rowid for an autoincrement calculation. +** +** This routine should be called when the top of the stack holds a +** new rowid that is about to be inserted. If that new rowid is +** larger than the maximum rowid in the memId memory cell, then the +** memory cell is updated. The stack is unchanged. +*/ +static void autoIncStep(Parse *pParse, int memId, int regRowid){ + if( memId>0 ){ + sqlite3VdbeAddOp2(pParse->pVdbe, OP_MemMax, memId, regRowid); + } +} + +/* +** After doing one or more inserts, the maximum rowid is stored +** in reg[memId]. Generate code to write this value back into the +** the sqlite_sequence table. +*/ +static void autoIncEnd( + Parse *pParse, /* The parsing context */ + int iDb, /* Index of the database holding pTab */ + Table *pTab, /* Table we are inserting into */ + int memId /* Memory cell holding the maximum rowid */ +){ + if( pTab->autoInc ){ + int iCur = pParse->nTab; + Vdbe *v = pParse->pVdbe; + Db *pDb = &pParse->db->aDb[iDb]; + int j1; + int iRec = ++pParse->nMem; /* Memory cell used for record */ + + assert( v ); + sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); + j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); + sqlite3VdbeAddOp2(v, OP_NewRowid, iCur, memId+1); + sqlite3VdbeJumpHere(v, j1); + sqlite3VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, iRec); + sqlite3VdbeAddOp3(v, OP_Insert, iCur, iRec, memId+1); + sqlite3VdbeChangeP5(v, OPFLAG_APPEND); + sqlite3VdbeAddOp1(v, OP_Close, iCur); + } +} +#else +/* +** If SQLITE_OMIT_AUTOINCREMENT is defined, then the three routines +** above are all no-ops +*/ +# define autoIncBegin(A,B,C) (0) +# define autoIncStep(A,B,C) +# define autoIncEnd(A,B,C,D) +#endif /* SQLITE_OMIT_AUTOINCREMENT */ + + +/* Forward declaration */ +static int xferOptimization( + Parse *pParse, /* Parser context */ + Table *pDest, /* The table we are inserting into */ + Select *pSelect, /* A SELECT statement to use as the data source */ + int onError, /* How to handle constraint errors */ + int iDbDest /* The database of pDest */ +); + +/* +** This routine is call to handle SQL of the following forms: +** +** insert into TABLE (IDLIST) values(EXPRLIST) +** insert into TABLE (IDLIST) select +** +** The IDLIST following the table name is always optional. If omitted, +** then a list of all columns for the table is substituted. The IDLIST +** appears in the pColumn parameter. pColumn is NULL if IDLIST is omitted. +** +** The pList parameter holds EXPRLIST in the first form of the INSERT +** statement above, and pSelect is NULL. For the second form, pList is +** NULL and pSelect is a pointer to the select statement used to generate +** data for the insert. +** +** The code generated follows one of four templates. For a simple +** select with data coming from a VALUES clause, the code executes +** once straight down through. Pseudo-code follows (we call this +** the "1st template"): +** +** open write cursor to <table> and its indices +** puts VALUES clause expressions onto the stack +** write the resulting record into <table> +** cleanup +** +** The three remaining templates assume the statement is of the form +** +** INSERT INTO <table> SELECT ... +** +** If the SELECT clause is of the restricted form "SELECT * FROM <table2>" - +** in other words if the SELECT pulls all columns from a single table +** and there is no WHERE or LIMIT or GROUP BY or ORDER BY clauses, and +** if <table2> and <table1> are distinct tables but have identical +** schemas, including all the same indices, then a special optimization +** is invoked that copies raw records from <table2> over to <table1>. +** See the xferOptimization() function for the implementation of this +** template. This is the 2nd template. +** +** open a write cursor to <table> +** open read cursor on <table2> +** transfer all records in <table2> over to <table> +** close cursors +** foreach index on <table> +** open a write cursor on the <table> index +** open a read cursor on the corresponding <table2> index +** transfer all records from the read to the write cursors +** close cursors +** end foreach +** +** The 3rd template is for when the second template does not apply +** and the SELECT clause does not read from <table> at any time. +** The generated code follows this template: +** +** EOF <- 0 +** X <- A +** goto B +** A: setup for the SELECT +** loop over the rows in the SELECT +** load values into registers R..R+n +** yield X +** end loop +** cleanup after the SELECT +** EOF <- 1 +** yield X +** goto A +** B: open write cursor to <table> and its indices +** C: yield X +** if EOF goto D +** insert the select result into <table> from R..R+n +** goto C +** D: cleanup +** +** The 4th template is used if the insert statement takes its +** values from a SELECT but the data is being inserted into a table +** that is also read as part of the SELECT. In the third form, +** we have to use a intermediate table to store the results of +** the select. The template is like this: +** +** EOF <- 0 +** X <- A +** goto B +** A: setup for the SELECT +** loop over the tables in the SELECT +** load value into register R..R+n +** yield X +** end loop +** cleanup after the SELECT +** EOF <- 1 +** yield X +** halt-error +** B: open temp table +** L: yield X +** if EOF goto M +** insert row from R..R+n into temp table +** goto L +** M: open write cursor to <table> and its indices +** rewind temp table +** C: loop over rows of intermediate table +** transfer values form intermediate table into <table> +** end loop +** D: cleanup +*/ +void sqlite3Insert( + Parse *pParse, /* Parser context */ + SrcList *pTabList, /* Name of table into which we are inserting */ + ExprList *pList, /* List of values to be inserted */ + Select *pSelect, /* A SELECT statement to use as the data source */ + IdList *pColumn, /* Column names corresponding to IDLIST. */ + int onError /* How to handle constraint errors */ +){ + sqlite3 *db; /* The main database structure */ + Table *pTab; /* The table to insert into. aka TABLE */ + char *zTab; /* Name of the table into which we are inserting */ + const char *zDb; /* Name of the database holding this table */ + int i, j, idx; /* Loop counters */ + Vdbe *v; /* Generate code into this virtual machine */ + Index *pIdx; /* For looping over indices of the table */ + int nColumn; /* Number of columns in the data */ + int nHidden = 0; /* Number of hidden columns if TABLE is virtual */ + int baseCur = 0; /* VDBE Cursor number for pTab */ + int keyColumn = -1; /* Column that is the INTEGER PRIMARY KEY */ + int endOfLoop; /* Label for the end of the insertion loop */ + int useTempTable = 0; /* Store SELECT results in intermediate table */ + int srcTab = 0; /* Data comes from this temporary cursor if >=0 */ + int addrInsTop = 0; /* Jump to label "D" */ + int addrCont = 0; /* Top of insert loop. Label "C" in templates 3 and 4 */ + int addrSelect = 0; /* Address of coroutine that implements the SELECT */ + SelectDest dest; /* Destination for SELECT on rhs of INSERT */ + int newIdx = -1; /* Cursor for the NEW pseudo-table */ + int iDb; /* Index of database holding TABLE */ + Db *pDb; /* The database containing table being inserted into */ + int appendFlag = 0; /* True if the insert is likely to be an append */ + + /* Register allocations */ + int regFromSelect; /* Base register for data coming from SELECT */ + int regAutoinc = 0; /* Register holding the AUTOINCREMENT counter */ + int regRowCount = 0; /* Memory cell used for the row counter */ + int regIns; /* Block of regs holding rowid+data being inserted */ + int regRowid; /* registers holding insert rowid */ + int regData; /* register holding first column to insert */ + int regRecord; /* Holds the assemblied row record */ + int regEof; /* Register recording end of SELECT data */ + int *aRegIdx = 0; /* One register allocated to each index */ + + +#ifndef SQLITE_OMIT_TRIGGER + int isView; /* True if attempting to insert into a view */ + int triggers_exist = 0; /* True if there are FOR EACH ROW triggers */ +#endif + + db = pParse->db; + if( pParse->nErr || db->mallocFailed ){ + goto insert_cleanup; + } + + /* Locate the table into which we will be inserting new information. + */ + assert( pTabList->nSrc==1 ); + zTab = pTabList->a[0].zName; + if( zTab==0 ) goto insert_cleanup; + pTab = sqlite3SrcListLookup(pParse, pTabList); + if( pTab==0 ){ + goto insert_cleanup; + } + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + assert( iDb<db->nDb ); + pDb = &db->aDb[iDb]; + zDb = pDb->zName; + if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){ + goto insert_cleanup; + } + + /* Figure out if we have any triggers and if the table being + ** inserted into is a view + */ +#ifndef SQLITE_OMIT_TRIGGER + triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0); + isView = pTab->pSelect!=0; +#else +# define triggers_exist 0 +# define isView 0 +#endif +#ifdef SQLITE_OMIT_VIEW +# undef isView +# define isView 0 +#endif + + /* Ensure that: + * (a) the table is not read-only, + * (b) that if it is a view then ON INSERT triggers exist + */ + if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){ + goto insert_cleanup; + } + assert( pTab!=0 ); + + /* If pTab is really a view, make sure it has been initialized. + ** ViewGetColumnNames() is a no-op if pTab is not a view (or virtual + ** module table). + */ + if( sqlite3ViewGetColumnNames(pParse, pTab) ){ + 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, iDb); + + /* if there are row triggers, allocate a temp table for new.* references. */ + if( triggers_exist ){ + newIdx = pParse->nTab++; + } + +#ifndef SQLITE_OMIT_XFER_OPT + /* If the statement is of the form + ** + ** INSERT INTO <table1> SELECT * FROM <table2>; + ** + ** Then special optimizations can be applied that make the transfer + ** very fast and which reduce fragmentation of indices. + ** + ** This is the 2nd template. + */ + if( pColumn==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){ + assert( !triggers_exist ); + assert( pList==0 ); + goto insert_cleanup; + } +#endif /* SQLITE_OMIT_XFER_OPT */ + + /* If this is an AUTOINCREMENT table, look up the sequence number in the + ** sqlite_sequence table and store it in memory cell regAutoinc. + */ + regAutoinc = autoIncBegin(pParse, iDb, pTab); + + /* Figure out how many columns of data are supplied. If the data + ** is coming from a SELECT statement, then generate a co-routine that + ** produces a single row of the SELECT on each invocation. The + ** co-routine is the common header to the 3rd and 4th templates. + */ + if( pSelect ){ + /* Data is coming from a SELECT. Generate code to implement that SELECT + ** as a co-routine. The code is common to both the 3rd and 4th + ** templates: + ** + ** EOF <- 0 + ** X <- A + ** goto B + ** A: setup for the SELECT + ** loop over the tables in the SELECT + ** load value into register R..R+n + ** yield X + ** end loop + ** cleanup after the SELECT + ** EOF <- 1 + ** yield X + ** halt-error + ** + ** On each invocation of the co-routine, it puts a single row of the + ** SELECT result into registers dest.iMem...dest.iMem+dest.nMem-1. + ** (These output registers are allocated by sqlite3Select().) When + ** the SELECT completes, it sets the EOF flag stored in regEof. + */ + int rc, j1; + + regEof = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Integer, 0, regEof); /* EOF <- 0 */ + VdbeComment((v, "SELECT eof flag")); + sqlite3SelectDestInit(&dest, SRT_Coroutine, ++pParse->nMem); + addrSelect = sqlite3VdbeCurrentAddr(v)+2; + sqlite3VdbeAddOp2(v, OP_Integer, addrSelect-1, dest.iParm); + j1 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); + VdbeComment((v, "Jump over SELECT coroutine")); + + /* Resolve the expressions in the SELECT statement and execute it. */ + rc = sqlite3Select(pParse, pSelect, &dest, 0, 0, 0); + if( rc || pParse->nErr || db->mallocFailed ){ + goto insert_cleanup; + } + sqlite3VdbeAddOp2(v, OP_Integer, 1, regEof); /* EOF <- 1 */ + sqlite3VdbeAddOp1(v, OP_Yield, dest.iParm); /* yield X */ + sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_INTERNAL, OE_Abort); + VdbeComment((v, "End of SELECT coroutine")); + sqlite3VdbeJumpHere(v, j1); /* label B: */ + + regFromSelect = dest.iMem; + assert( pSelect->pEList ); + nColumn = pSelect->pEList->nExpr; + assert( dest.nMem==nColumn ); + + /* Set useTempTable to TRUE if the result of the SELECT statement + ** should be written into a temporary table (template 4). Set to + ** FALSE if each* row of the SELECT can be written directly into + ** the destination table (template 3). + ** + ** A temp table must be used if the table being updated is also one + ** of the tables being read by the SELECT statement. Also use a + ** temp table in the case of row triggers. + */ + if( triggers_exist || readsTable(v, addrSelect, iDb, pTab) ){ + useTempTable = 1; + } + + if( useTempTable ){ + /* Invoke the coroutine to extract information from the SELECT + ** and add it to a transient table srcTab. The code generated + ** here is from the 4th template: + ** + ** B: open temp table + ** L: yield X + ** if EOF goto M + ** insert row from R..R+n into temp table + ** goto L + ** M: ... + */ + int regRec; /* Register to hold packed record */ + int regRowid; /* Register to hold temp table ROWID */ + int addrTop; /* Label "L" */ + int addrIf; /* Address of jump to M */ + + srcTab = pParse->nTab++; + regRec = sqlite3GetTempReg(pParse); + regRowid = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn); + addrTop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iParm); + addrIf = sqlite3VdbeAddOp1(v, OP_If, regEof); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec); + sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regRowid); + sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regRowid); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop); + sqlite3VdbeJumpHere(v, addrIf); + sqlite3ReleaseTempReg(pParse, regRec); + sqlite3ReleaseTempReg(pParse, regRowid); + } + }else{ + /* This is the case if the data for the INSERT is coming from a VALUES + ** clause + */ + NameContext sNC; + memset(&sNC, 0, sizeof(sNC)); + sNC.pParse = pParse; + srcTab = -1; + assert( useTempTable==0 ); + nColumn = pList ? pList->nExpr : 0; + for(i=0; i<nColumn; i++){ + if( sqlite3ExprResolveNames(&sNC, pList->a[i].pExpr) ){ + goto insert_cleanup; + } + } + } + + /* Make sure the number of columns in the source data matches the number + ** of columns to be inserted into the table. + */ + if( IsVirtual(pTab) ){ + for(i=0; i<pTab->nCol; i++){ + nHidden += (IsHiddenColumn(&pTab->aCol[i]) ? 1 : 0); + } + } + if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){ + sqlite3ErrorMsg(pParse, + "table %S has %d columns but %d values were supplied", + pTabList, 0, pTab->nCol, nColumn); + goto insert_cleanup; + } + if( pColumn!=0 && nColumn!=pColumn->nId ){ + sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId); + goto insert_cleanup; + } + + /* If the INSERT statement included an IDLIST term, then make sure + ** all elements of the IDLIST really are columns of the table and + ** remember the column indices. + ** + ** If the table has an INTEGER PRIMARY KEY column and that column + ** is named in the IDLIST, then record in the keyColumn variable + ** the index into IDLIST of the primary key column. keyColumn is + ** the index of the primary key as it appears in IDLIST, not as + ** is appears in the original table. (The index of the primary + ** key in the original table is pTab->iPKey.) + */ + if( pColumn ){ + for(i=0; i<pColumn->nId; i++){ + pColumn->a[i].idx = -1; + } + for(i=0; i<pColumn->nId; i++){ + for(j=0; j<pTab->nCol; j++){ + if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){ + pColumn->a[i].idx = j; + if( j==pTab->iPKey ){ + keyColumn = i; + } + break; + } + } + if( j>=pTab->nCol ){ + if( sqlite3IsRowid(pColumn->a[i].zName) ){ + keyColumn = i; + }else{ + sqlite3ErrorMsg(pParse, "table %S has no column named %s", + pTabList, 0, pColumn->a[i].zName); + pParse->nErr++; + goto insert_cleanup; + } + } + } + } + + /* If there is no IDLIST term but the table has an integer primary + ** key, the set the keyColumn variable to the primary key column index + ** in the original table definition. + */ + if( pColumn==0 && nColumn>0 ){ + keyColumn = pTab->iPKey; + } + + /* Open the temp table for FOR EACH ROW triggers + */ + if( triggers_exist ){ + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol); + sqlite3VdbeAddOp2(v, OP_OpenPseudo, newIdx, 0); + } + + /* Initialize the count of rows to be inserted + */ + if( db->flags & SQLITE_CountRows ){ + regRowCount = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); + } + + /* If this is not a view, open the table and and all indices */ + if( !isView ){ + int nIdx; + int i; + + baseCur = pParse->nTab; + nIdx = sqlite3OpenTableAndIndices(pParse, pTab, baseCur, OP_OpenWrite); + aRegIdx = sqlite3DbMallocRaw(db, sizeof(int)*(nIdx+1)); + if( aRegIdx==0 ){ + goto insert_cleanup; + } + for(i=0; i<nIdx; i++){ + aRegIdx[i] = ++pParse->nMem; + } + } + + /* This is the top of the main insertion loop */ + if( useTempTable ){ + /* This block codes the top of loop only. The complete loop is the + ** following pseudocode (template 4): + ** + ** rewind temp table + ** C: loop over rows of intermediate table + ** transfer values form intermediate table into <table> + ** end loop + ** D: ... + */ + addrInsTop = sqlite3VdbeAddOp1(v, OP_Rewind, srcTab); + addrCont = sqlite3VdbeCurrentAddr(v); + }else if( pSelect ){ + /* This block codes the top of loop only. The complete loop is the + ** following pseudocode (template 3): + ** + ** C: yield X + ** if EOF goto D + ** insert the select result into <table> from R..R+n + ** goto C + ** D: ... + */ + addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iParm); + addrInsTop = sqlite3VdbeAddOp1(v, OP_If, regEof); + } + + /* Allocate registers for holding the rowid of the new row, + ** the content of the new row, and the assemblied row record. + */ + regRecord = ++pParse->nMem; + regRowid = regIns = pParse->nMem+1; + pParse->nMem += pTab->nCol + 1; + if( IsVirtual(pTab) ){ + regRowid++; + pParse->nMem++; + } + regData = regRowid+1; + + /* Run the BEFORE and INSTEAD OF triggers, if there are any + */ + endOfLoop = sqlite3VdbeMakeLabel(v); + if( triggers_exist & TRIGGER_BEFORE ){ + int regRowid; + int regCols; + int regRec; + + /* build the NEW.* reference row. Note that if there is an INTEGER + ** PRIMARY KEY into which a NULL is being inserted, that NULL will be + ** translated into a unique ID for the row. But on a BEFORE trigger, + ** we do not know what the unique ID will be (because the insert has + ** not happened yet) so we substitute a rowid of -1 + */ + regRowid = sqlite3GetTempReg(pParse); + if( keyColumn<0 ){ + sqlite3VdbeAddOp2(v, OP_Integer, -1, regRowid); + }else if( useTempTable ){ + sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regRowid); + }else{ + int j1; + assert( pSelect==0 ); /* Otherwise useTempTable is true */ + sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regRowid); + j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid); + sqlite3VdbeAddOp2(v, OP_Integer, -1, regRowid); + sqlite3VdbeJumpHere(v, j1); + sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid); + } + + /* Cannot have triggers on a virtual table. If it were possible, + ** this block would have to account for hidden column. + */ + assert(!IsVirtual(pTab)); + + /* Create the new column data + */ + regCols = sqlite3GetTempRange(pParse, pTab->nCol); + for(i=0; i<pTab->nCol; i++){ + if( pColumn==0 ){ + j = i; + }else{ + for(j=0; j<pColumn->nId; j++){ + if( pColumn->a[j].idx==i ) break; + } + } + if( pColumn && j>=pColumn->nId ){ + sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regCols+i); + }else if( useTempTable ){ + sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i); + }else{ + assert( pSelect==0 ); /* Otherwise useTempTable is true */ + sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr, regCols+i); + } + } + regRec = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regCols, pTab->nCol, regRec); + + /* If this is an INSERT on a view with an INSTEAD OF INSERT trigger, + ** do not attempt any conversions before assembling the record. + ** If this is a real table, attempt conversions as required by the + ** table column affinities. + */ + if( !isView ){ + sqlite3TableAffinityStr(v, pTab); + } + sqlite3VdbeAddOp3(v, OP_Insert, newIdx, regRec, regRowid); + sqlite3ReleaseTempReg(pParse, regRec); + sqlite3ReleaseTempReg(pParse, regRowid); + sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol); + + /* Fire BEFORE or INSTEAD OF triggers */ + if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_BEFORE, pTab, + newIdx, -1, onError, endOfLoop, 0, 0) ){ + goto insert_cleanup; + } + } + + /* Push the record number for the new entry onto the stack. The + ** record number is a randomly generate integer created by NewRowid + ** except when the table has an INTEGER PRIMARY KEY column, in which + ** case the record number is the same as that column. + */ + if( !isView ){ + if( IsVirtual(pTab) ){ + /* The row that the VUpdate opcode will delete: none */ + sqlite3VdbeAddOp2(v, OP_Null, 0, regIns); + } + if( keyColumn>=0 ){ + if( useTempTable ){ + sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regRowid); + }else if( pSelect ){ + sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+keyColumn, regRowid); + }else{ + VdbeOp *pOp; + sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regRowid); + pOp = sqlite3VdbeGetOp(v, sqlite3VdbeCurrentAddr(v) - 1); + if( pOp && pOp->opcode==OP_Null && !IsVirtual(pTab) ){ + appendFlag = 1; + pOp->opcode = OP_NewRowid; + pOp->p1 = baseCur; + pOp->p2 = regRowid; + pOp->p3 = regAutoinc; + } + } + /* If the PRIMARY KEY expression is NULL, then use OP_NewRowid + ** to generate a unique primary key value. + */ + if( !appendFlag ){ + int j1; + if( !IsVirtual(pTab) ){ + j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid); + sqlite3VdbeAddOp3(v, OP_NewRowid, baseCur, regRowid, regAutoinc); + sqlite3VdbeJumpHere(v, j1); + }else{ + j1 = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp2(v, OP_IsNull, regRowid, j1+2); + } + sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid); + } + }else if( IsVirtual(pTab) ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, regRowid); + }else{ + sqlite3VdbeAddOp3(v, OP_NewRowid, baseCur, regRowid, regAutoinc); + appendFlag = 1; + } + autoIncStep(pParse, regAutoinc, regRowid); + + /* Push onto the stack, data for all columns of the new entry, beginning + ** with the first column. + */ + nHidden = 0; + for(i=0; i<pTab->nCol; i++){ + int iRegStore = regRowid+1+i; + if( i==pTab->iPKey ){ + /* The value of the INTEGER PRIMARY KEY column is always a NULL. + ** Whenever this column is read, the record number will be substituted + ** in its place. So will fill this column with a NULL to avoid + ** taking up data space with information that will never be used. */ + sqlite3VdbeAddOp2(v, OP_Null, 0, iRegStore); + continue; + } + if( pColumn==0 ){ + if( IsHiddenColumn(&pTab->aCol[i]) ){ + assert( IsVirtual(pTab) ); + j = -1; + nHidden++; + }else{ + j = i - nHidden; + } + }else{ + for(j=0; j<pColumn->nId; j++){ + if( pColumn->a[j].idx==i ) break; + } + } + if( j<0 || nColumn==0 || (pColumn && j>=pColumn->nId) ){ + sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, iRegStore); + }else if( useTempTable ){ + sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore); + }else if( pSelect ){ + sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+j, iRegStore); + }else{ + sqlite3ExprCode(pParse, pList->a[j].pExpr, iRegStore); + } + } + + /* Generate code to check constraints and generate index keys and + ** do the insertion. + */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( IsVirtual(pTab) ){ + sqlite3VtabMakeWritable(pParse, pTab); + sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, + (const char*)pTab->pVtab, P4_VTAB); + }else +#endif + { + sqlite3GenerateConstraintChecks( + pParse, + pTab, + baseCur, + regIns, + aRegIdx, + keyColumn>=0, + 0, + onError, + endOfLoop + ); + sqlite3CompleteInsertion( + pParse, + pTab, + baseCur, + regIns, + aRegIdx, + 0, + 0, + (triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1, + appendFlag + ); + } + } + + /* Update the count of rows that are inserted + */ + if( (db->flags & SQLITE_CountRows)!=0 ){ + sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); + } + + if( triggers_exist ){ + /* Code AFTER triggers */ + if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_AFTER, pTab, + newIdx, -1, onError, endOfLoop, 0, 0) ){ + goto insert_cleanup; + } + } + + /* The bottom of the main insertion loop, if the data source + ** is a SELECT statement. + */ + sqlite3VdbeResolveLabel(v, endOfLoop); + if( useTempTable ){ + sqlite3VdbeAddOp2(v, OP_Next, srcTab, addrCont); + sqlite3VdbeJumpHere(v, addrInsTop); + sqlite3VdbeAddOp1(v, OP_Close, srcTab); + }else if( pSelect ){ + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrCont); + sqlite3VdbeJumpHere(v, addrInsTop); + } + + if( !IsVirtual(pTab) && !isView ){ + /* Close all tables opened */ + sqlite3VdbeAddOp1(v, OP_Close, baseCur); + for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){ + sqlite3VdbeAddOp1(v, OP_Close, idx+baseCur); + } + } + + /* Update the sqlite_sequence table by storing the content of the + ** counter value in memory regAutoinc back into the sqlite_sequence + ** table. + */ + autoIncEnd(pParse, iDb, pTab, regAutoinc); + + /* + ** Return the number of rows inserted. If this routine is + ** generating code because of a call to sqlite3NestedParse(), do not + ** invoke the callback function. + */ + if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){ + sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", P4_STATIC); + } + +insert_cleanup: + sqlite3SrcListDelete(db, pTabList); + sqlite3ExprListDelete(db, pList); + sqlite3SelectDelete(db, pSelect); + sqlite3IdListDelete(db, pColumn); + sqlite3DbFree(db, aRegIdx); +} + +/* +** Generate code to do constraint checks prior to an INSERT or an UPDATE. +** +** The input is a range of consecutive registers as follows: +** +** 1. The rowid of the row to be updated before the update. This +** value is omitted unless we are doing an UPDATE that involves a +** change to the record number or writing to a virtual table. +** +** 2. The rowid of the row after the update. +** +** 3. The data in the first column of the entry after the update. +** +** i. Data from middle columns... +** +** N. The data in the last column of the entry after the update. +** +** The regRowid parameter is the index of the register containing (2). +** +** The old rowid shown as entry (1) above is omitted unless both isUpdate +** and rowidChng are 1. isUpdate is true for UPDATEs and false for +** INSERTs. RowidChng means that the new rowid is explicitly specified by +** the update or insert statement. If rowidChng is false, it means that +** the rowid is computed automatically in an insert or that the rowid value +** is not modified by the update. +** +** The code generated by this routine store new index entries into +** registers identified by aRegIdx[]. No index entry is created for +** indices where aRegIdx[i]==0. The order of indices in aRegIdx[] is +** the same as the order of indices on the linked list of indices +** attached to the table. +** +** This routine also generates code to check constraints. NOT NULL, +** CHECK, and UNIQUE constraints are all checked. If a constraint fails, +** then the appropriate action is performed. There are five possible +** actions: ROLLBACK, ABORT, FAIL, REPLACE, and IGNORE. +** +** Constraint type Action What Happens +** --------------- ---------- ---------------------------------------- +** any ROLLBACK The current transaction is rolled back and +** sqlite3_exec() returns immediately with a +** return code of SQLITE_CONSTRAINT. +** +** any ABORT Back out changes from the current command +** only (do not do a complete rollback) then +** cause sqlite3_exec() to return immediately +** with SQLITE_CONSTRAINT. +** +** any FAIL Sqlite_exec() returns immediately with a +** return code of SQLITE_CONSTRAINT. The +** transaction is not rolled back and any +** prior changes are retained. +** +** any IGNORE The record number and data is popped from +** the stack and there is an immediate jump +** to label ignoreDest. +** +** NOT NULL REPLACE The NULL value is replace by the default +** value for that column. If the default value +** is NULL, the action is the same as ABORT. +** +** UNIQUE REPLACE The other row that conflicts with the row +** being inserted is removed. +** +** CHECK REPLACE Illegal. The results in an exception. +** +** Which action to take is determined by the overrideError parameter. +** Or if overrideError==OE_Default, then the pParse->onError parameter +** is used. Or if pParse->onError==OE_Default then the onError value +** for the constraint is used. +** +** The calling routine must open a read/write cursor for pTab with +** cursor number "baseCur". All indices of pTab must also have open +** read/write cursors with cursor number baseCur+i for the i-th cursor. +** Except, if there is no possibility of a REPLACE action then +** cursors do not need to be open for indices where aRegIdx[i]==0. +*/ +void sqlite3GenerateConstraintChecks( + Parse *pParse, /* The parser context */ + Table *pTab, /* the table into which we are inserting */ + int baseCur, /* Index of a read/write cursor pointing at pTab */ + int regRowid, /* Index of the range of input registers */ + int *aRegIdx, /* Register used by each index. 0 for unused indices */ + int rowidChng, /* True if the rowid might collide with existing entry */ + int isUpdate, /* True for UPDATE, False for INSERT */ + int overrideError, /* Override onError to this if not OE_Default */ + int ignoreDest /* Jump to this label on an OE_Ignore resolution */ +){ + int i; + Vdbe *v; + int nCol; + int onError; + int j1, j2, j3; /* Addresses of jump instructions */ + int regData; /* Register containing first data column */ + int iCur; + Index *pIdx; + int seenReplace = 0; + int hasTwoRowids = (isUpdate && rowidChng); + + v = sqlite3GetVdbe(pParse); + assert( v!=0 ); + assert( pTab->pSelect==0 ); /* This table is not a VIEW */ + nCol = pTab->nCol; + regData = regRowid + 1; + + + /* Test all NOT NULL constraints. + */ + for(i=0; i<nCol; i++){ + if( i==pTab->iPKey ){ + continue; + } + onError = pTab->aCol[i].notNull; + if( onError==OE_None ) continue; + if( overrideError!=OE_Default ){ + onError = overrideError; + }else if( onError==OE_Default ){ + onError = OE_Abort; + } + if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){ + onError = OE_Abort; + } + j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regData+i); + assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail + || onError==OE_Ignore || onError==OE_Replace ); + switch( onError ){ + case OE_Rollback: + case OE_Abort: + case OE_Fail: { + char *zMsg; + sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_CONSTRAINT, onError); + zMsg = sqlite3MPrintf(pParse->db, "%s.%s may not be NULL", + pTab->zName, pTab->aCol[i].zName); + sqlite3VdbeChangeP4(v, -1, zMsg, P4_DYNAMIC); + break; + } + case OE_Ignore: { + sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); + break; + } + case OE_Replace: { + sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regData+i); + break; + } + } + sqlite3VdbeJumpHere(v, j1); + } + + /* Test all CHECK constraints + */ +#ifndef SQLITE_OMIT_CHECK + if( pTab->pCheck && (pParse->db->flags & SQLITE_IgnoreChecks)==0 ){ + int allOk = sqlite3VdbeMakeLabel(v); + pParse->ckBase = regData; + sqlite3ExprIfTrue(pParse, pTab->pCheck, allOk, SQLITE_JUMPIFNULL); + onError = overrideError!=OE_Default ? overrideError : OE_Abort; + if( onError==OE_Ignore ){ + sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); + }else{ + sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_CONSTRAINT, onError); + } + 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 + ** is an UPDATE and the primary key is not changing, that is OK. + */ + if( rowidChng ){ + onError = pTab->keyConf; + if( overrideError!=OE_Default ){ + onError = overrideError; + }else if( onError==OE_Default ){ + onError = OE_Abort; + } + + if( onError!=OE_Replace || pTab->pIndex ){ + if( isUpdate ){ + j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, regRowid-1); + } + j3 = sqlite3VdbeAddOp3(v, OP_NotExists, baseCur, 0, regRowid); + switch( onError ){ + default: { + onError = OE_Abort; + /* Fall thru into the next case */ + } + case OE_Rollback: + case OE_Abort: + case OE_Fail: { + sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, + "PRIMARY KEY must be unique", P4_STATIC); + break; + } + case OE_Replace: { + sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0); + seenReplace = 1; + break; + } + case OE_Ignore: { + assert( seenReplace==0 ); + sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); + break; + } + } + sqlite3VdbeJumpHere(v, j3); + if( isUpdate ){ + sqlite3VdbeJumpHere(v, j2); + } + } + } + + /* Test all UNIQUE constraints by creating entries for each UNIQUE + ** index and making sure that duplicate entries do not already exist. + ** Add the new records to the indices as we go. + */ + for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){ + int regIdx; + int regR; + + if( aRegIdx[iCur]==0 ) continue; /* Skip unused indices */ + + /* Create a key for accessing the index entry */ + regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn+1); + for(i=0; i<pIdx->nColumn; i++){ + int idx = pIdx->aiColumn[i]; + if( idx==pTab->iPKey ){ + sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i); + }else{ + sqlite3VdbeAddOp2(v, OP_SCopy, regData+idx, regIdx+i); + } + } + sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn+1, aRegIdx[iCur]); + sqlite3IndexAffinityStr(v, pIdx); + sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn+1); + sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1); + + /* Find out what action to take in case there is an indexing conflict */ + onError = pIdx->onError; + if( onError==OE_None ) continue; /* pIdx is not a UNIQUE index */ + if( overrideError!=OE_Default ){ + onError = overrideError; + }else if( onError==OE_Default ){ + onError = OE_Abort; + } + if( seenReplace ){ + if( onError==OE_Ignore ) onError = OE_Replace; + else if( onError==OE_Fail ) onError = OE_Abort; + } + + + /* Check to see if the new index entry will be unique */ + j2 = sqlite3VdbeAddOp3(v, OP_IsNull, regIdx, 0, pIdx->nColumn); + regR = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp2(v, OP_SCopy, regRowid-hasTwoRowids, regR); + j3 = sqlite3VdbeAddOp4(v, OP_IsUnique, baseCur+iCur+1, 0, + regR, SQLITE_INT_TO_PTR(aRegIdx[iCur]), + P4_INT32); + + /* Generate code that executes if the new index entry is not unique */ + assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail + || onError==OE_Ignore || onError==OE_Replace ); + switch( onError ){ + case OE_Rollback: + case OE_Abort: + case OE_Fail: { + int j, n1, n2; + char zErrMsg[200]; + sqlite3_snprintf(sizeof(zErrMsg), zErrMsg, + pIdx->nColumn>1 ? "columns " : "column "); + n1 = strlen(zErrMsg); + for(j=0; j<pIdx->nColumn && n1<sizeof(zErrMsg)-30; j++){ + char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName; + n2 = strlen(zCol); + if( j>0 ){ + sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1], ", "); + n1 += 2; + } + if( n1+n2>sizeof(zErrMsg)-30 ){ + sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1], "..."); + n1 += 3; + break; + }else{ + sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1], "%s", zCol); + n1 += n2; + } + } + sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1], + pIdx->nColumn>1 ? " are not unique" : " is not unique"); + sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, zErrMsg,0); + break; + } + case OE_Ignore: { + assert( seenReplace==0 ); + sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); + break; + } + case OE_Replace: { + sqlite3GenerateRowDelete(pParse, pTab, baseCur, regR, 0); + seenReplace = 1; + break; + } + } + sqlite3VdbeJumpHere(v, j2); + sqlite3VdbeJumpHere(v, j3); + sqlite3ReleaseTempReg(pParse, regR); + } +} + +/* +** This routine generates code to finish the INSERT or UPDATE operation +** that was started by a prior call to sqlite3GenerateConstraintChecks. +** A consecutive range of registers starting at regRowid contains the +** rowid and the content to be inserted. +** +** The arguments to this routine should be the same as the first six +** arguments to sqlite3GenerateConstraintChecks. +*/ +void sqlite3CompleteInsertion( + Parse *pParse, /* The parser context */ + Table *pTab, /* the table into which we are inserting */ + int baseCur, /* Index of a read/write cursor pointing at pTab */ + int regRowid, /* Range of content */ + int *aRegIdx, /* Register used by each index. 0 for unused indices */ + int rowidChng, /* True if the record number will change */ + int isUpdate, /* True for UPDATE, False for INSERT */ + int newIdx, /* Index of NEW table for triggers. -1 if none */ + int appendBias /* True if this is likely to be an append */ +){ + int i; + Vdbe *v; + int nIdx; + Index *pIdx; + int pik_flags; + int regData; + int regRec; + + v = sqlite3GetVdbe(pParse); + assert( v!=0 ); + assert( pTab->pSelect==0 ); /* This table is not a VIEW */ + for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){} + for(i=nIdx-1; i>=0; i--){ + if( aRegIdx[i]==0 ) continue; + sqlite3VdbeAddOp2(v, OP_IdxInsert, baseCur+i+1, aRegIdx[i]); + } + regData = regRowid + 1; + regRec = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec); + sqlite3TableAffinityStr(v, pTab); + sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol); +#ifndef SQLITE_OMIT_TRIGGER + if( newIdx>=0 ){ + sqlite3VdbeAddOp3(v, OP_Insert, newIdx, regRec, regRowid); + } +#endif + if( pParse->nested ){ + pik_flags = 0; + }else{ + pik_flags = OPFLAG_NCHANGE; + pik_flags |= (isUpdate?OPFLAG_ISUPDATE:OPFLAG_LASTROWID); + } + if( appendBias ){ + pik_flags |= OPFLAG_APPEND; + } + sqlite3VdbeAddOp3(v, OP_Insert, baseCur, regRec, regRowid); + if( !pParse->nested ){ + sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC); + } + sqlite3VdbeChangeP5(v, pik_flags); +} + +/* +** Generate code that will open cursors for a table and for all +** indices of that table. The "baseCur" parameter is the cursor number used +** for the table. Indices are opened on subsequent cursors. +** +** Return the number of indices on the table. +*/ +int sqlite3OpenTableAndIndices( + Parse *pParse, /* Parsing context */ + Table *pTab, /* Table to be opened */ + int baseCur, /* Cursor number assigned to the table */ + int op /* OP_OpenRead or OP_OpenWrite */ +){ + int i; + int iDb; + Index *pIdx; + Vdbe *v; + + if( IsVirtual(pTab) ) return 0; + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + v = sqlite3GetVdbe(pParse); + assert( v!=0 ); + sqlite3OpenTable(pParse, baseCur, iDb, pTab, op); + for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ + KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); + assert( pIdx->pSchema==pTab->pSchema ); + sqlite3VdbeAddOp4(v, op, i+baseCur, pIdx->tnum, iDb, + (char*)pKey, P4_KEYINFO_HANDOFF); + VdbeComment((v, "%s", pIdx->zName)); + } + if( pParse->nTab<=baseCur+i ){ + pParse->nTab = baseCur+i; + } + return i-1; +} + + +#ifdef SQLITE_TEST +/* +** The following global variable is incremented whenever the +** transfer optimization is used. This is used for testing +** purposes only - to make sure the transfer optimization really +** is happening when it is suppose to. +*/ +int sqlite3_xferopt_count; +#endif /* SQLITE_TEST */ + + +#ifndef SQLITE_OMIT_XFER_OPT +/* +** Check to collation names to see if they are compatible. +*/ +static int xferCompatibleCollation(const char *z1, const char *z2){ + if( z1==0 ){ + return z2==0; + } + if( z2==0 ){ + return 0; + } + return sqlite3StrICmp(z1, z2)==0; +} + + +/* +** Check to see if index pSrc is compatible as a source of data +** for index pDest in an insert transfer optimization. The rules +** for a compatible index: +** +** * The index is over the same set of columns +** * The same DESC and ASC markings occurs on all columns +** * The same onError processing (OE_Abort, OE_Ignore, etc) +** * The same collating sequence on each column +*/ +static int xferCompatibleIndex(Index *pDest, Index *pSrc){ + int i; + assert( pDest && pSrc ); + assert( pDest->pTable!=pSrc->pTable ); + if( pDest->nColumn!=pSrc->nColumn ){ + return 0; /* Different number of columns */ + } + if( pDest->onError!=pSrc->onError ){ + return 0; /* Different conflict resolution strategies */ + } + for(i=0; i<pSrc->nColumn; i++){ + if( pSrc->aiColumn[i]!=pDest->aiColumn[i] ){ + return 0; /* Different columns indexed */ + } + if( pSrc->aSortOrder[i]!=pDest->aSortOrder[i] ){ + return 0; /* Different sort orders */ + } + if( pSrc->azColl[i]!=pDest->azColl[i] ){ + return 0; /* Different collating sequences */ + } + } + + /* If no test above fails then the indices must be compatible */ + return 1; +} + +/* +** Attempt the transfer optimization on INSERTs of the form +** +** INSERT INTO tab1 SELECT * FROM tab2; +** +** This optimization is only attempted if +** +** (1) tab1 and tab2 have identical schemas including all the +** same indices and constraints +** +** (2) tab1 and tab2 are different tables +** +** (3) There must be no triggers on tab1 +** +** (4) The result set of the SELECT statement is "*" +** +** (5) The SELECT statement has no WHERE, HAVING, ORDER BY, GROUP BY, +** or LIMIT clause. +** +** (6) The SELECT statement is a simple (not a compound) select that +** contains only tab2 in its FROM clause +** +** This method for implementing the INSERT transfers raw records from +** tab2 over to tab1. The columns are not decoded. Raw records from +** the indices of tab2 are transfered to tab1 as well. In so doing, +** the resulting tab1 has much less fragmentation. +** +** This routine returns TRUE if the optimization is attempted. If any +** of the conditions above fail so that the optimization should not +** be attempted, then this routine returns FALSE. +*/ +static int xferOptimization( + Parse *pParse, /* Parser context */ + Table *pDest, /* The table we are inserting into */ + Select *pSelect, /* A SELECT statement to use as the data source */ + int onError, /* How to handle constraint errors */ + int iDbDest /* The database of pDest */ +){ + ExprList *pEList; /* The result set of the SELECT */ + Table *pSrc; /* The table in the FROM clause of SELECT */ + Index *pSrcIdx, *pDestIdx; /* Source and destination indices */ + struct SrcList_item *pItem; /* An element of pSelect->pSrc */ + int i; /* Loop counter */ + int iDbSrc; /* The database of pSrc */ + int iSrc, iDest; /* Cursors from source and destination */ + int addr1, addr2; /* Loop addresses */ + int emptyDestTest; /* Address of test for empty pDest */ + int emptySrcTest; /* Address of test for empty pSrc */ + Vdbe *v; /* The VDBE we are building */ + KeyInfo *pKey; /* Key information for an index */ + int regAutoinc; /* Memory register used by AUTOINC */ + int destHasUniqueIdx = 0; /* True if pDest has a UNIQUE index */ + int regData, regRowid; /* Registers holding data and rowid */ + + if( pSelect==0 ){ + return 0; /* Must be of the form INSERT INTO ... SELECT ... */ + } + if( pDest->pTrigger ){ + return 0; /* tab1 must not have triggers */ + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( pDest->isVirtual ){ + return 0; /* tab1 must not be a virtual table */ + } +#endif + if( onError==OE_Default ){ + onError = OE_Abort; + } + if( onError!=OE_Abort && onError!=OE_Rollback ){ + return 0; /* Cannot do OR REPLACE or OR IGNORE or OR FAIL */ + } + assert(pSelect->pSrc); /* allocated even if there is no FROM clause */ + if( pSelect->pSrc->nSrc!=1 ){ + return 0; /* FROM clause must have exactly one term */ + } + if( pSelect->pSrc->a[0].pSelect ){ + return 0; /* FROM clause cannot contain a subquery */ + } + if( pSelect->pWhere ){ + return 0; /* SELECT may not have a WHERE clause */ + } + if( pSelect->pOrderBy ){ + return 0; /* SELECT may not have an ORDER BY clause */ + } + /* Do not need to test for a HAVING clause. If HAVING is present but + ** there is no ORDER BY, we will get an error. */ + if( pSelect->pGroupBy ){ + return 0; /* SELECT may not have a GROUP BY clause */ + } + if( pSelect->pLimit ){ + return 0; /* SELECT may not have a LIMIT clause */ + } + assert( pSelect->pOffset==0 ); /* Must be so if pLimit==0 */ + if( pSelect->pPrior ){ + return 0; /* SELECT may not be a compound query */ + } + if( pSelect->isDistinct ){ + return 0; /* SELECT may not be DISTINCT */ + } + pEList = pSelect->pEList; + assert( pEList!=0 ); + if( pEList->nExpr!=1 ){ + return 0; /* The result set must have exactly one column */ + } + assert( pEList->a[0].pExpr ); + if( pEList->a[0].pExpr->op!=TK_ALL ){ + return 0; /* The result set must be the special operator "*" */ + } + + /* At this point we have established that the statement is of the + ** correct syntactic form to participate in this optimization. Now + ** we have to check the semantics. + */ + pItem = pSelect->pSrc->a; + pSrc = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase); + if( pSrc==0 ){ + return 0; /* FROM clause does not contain a real table */ + } + if( pSrc==pDest ){ + return 0; /* tab1 and tab2 may not be the same table */ + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( pSrc->isVirtual ){ + return 0; /* tab2 must not be a virtual table */ + } +#endif + if( pSrc->pSelect ){ + return 0; /* tab2 may not be a view */ + } + if( pDest->nCol!=pSrc->nCol ){ + return 0; /* Number of columns must be the same in tab1 and tab2 */ + } + if( pDest->iPKey!=pSrc->iPKey ){ + return 0; /* Both tables must have the same INTEGER PRIMARY KEY */ + } + for(i=0; i<pDest->nCol; i++){ + if( pDest->aCol[i].affinity!=pSrc->aCol[i].affinity ){ + return 0; /* Affinity must be the same on all columns */ + } + if( !xferCompatibleCollation(pDest->aCol[i].zColl, pSrc->aCol[i].zColl) ){ + return 0; /* Collating sequence must be the same on all columns */ + } + if( pDest->aCol[i].notNull && !pSrc->aCol[i].notNull ){ + return 0; /* tab2 must be NOT NULL if tab1 is */ + } + } + for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ + if( pDestIdx->onError!=OE_None ){ + destHasUniqueIdx = 1; + } + for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){ + if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; + } + if( pSrcIdx==0 ){ + return 0; /* pDestIdx has no corresponding index in pSrc */ + } + } +#ifndef SQLITE_OMIT_CHECK + if( pDest->pCheck && !sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){ + return 0; /* Tables have different CHECK constraints. Ticket #2252 */ + } +#endif + + /* If we get this far, it means either: + ** + ** * We can always do the transfer if the table contains an + ** an integer primary key + ** + ** * We can conditionally do the transfer if the destination + ** table is empty. + */ +#ifdef SQLITE_TEST + sqlite3_xferopt_count++; +#endif + iDbSrc = sqlite3SchemaToIndex(pParse->db, pSrc->pSchema); + v = sqlite3GetVdbe(pParse); + sqlite3CodeVerifySchema(pParse, iDbSrc); + iSrc = pParse->nTab++; + iDest = pParse->nTab++; + regAutoinc = autoIncBegin(pParse, iDbDest, pDest); + sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite); + if( (pDest->iPKey<0 && pDest->pIndex!=0) || destHasUniqueIdx ){ + /* If tables do not have an INTEGER PRIMARY KEY and there + ** are indices to be copied and the destination is not empty, + ** we have to disallow the transfer optimization because the + ** the rowids might change which will mess up indexing. + ** + ** Or if the destination has a UNIQUE index and is not empty, + ** we also disallow the transfer optimization because we cannot + ** insure that all entries in the union of DEST and SRC will be + ** unique. + */ + addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iDest, 0); + emptyDestTest = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); + sqlite3VdbeJumpHere(v, addr1); + }else{ + emptyDestTest = 0; + } + sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead); + emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); + regData = sqlite3GetTempReg(pParse); + regRowid = sqlite3GetTempReg(pParse); + if( pDest->iPKey>=0 ){ + addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); + addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid); + sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, + "PRIMARY KEY must be unique", P4_STATIC); + sqlite3VdbeJumpHere(v, addr2); + autoIncStep(pParse, regAutoinc, regRowid); + }else if( pDest->pIndex==0 ){ + addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid); + }else{ + addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); + assert( pDest->autoInc==0 ); + } + sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData); + sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid); + sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND); + sqlite3VdbeChangeP4(v, -1, pDest->zName, 0); + sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); + autoIncEnd(pParse, iDbDest, pDest, regAutoinc); + for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ + for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){ + if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; + } + assert( pSrcIdx ); + sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); + sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); + pKey = sqlite3IndexKeyinfo(pParse, pSrcIdx); + sqlite3VdbeAddOp4(v, OP_OpenRead, iSrc, pSrcIdx->tnum, iDbSrc, + (char*)pKey, P4_KEYINFO_HANDOFF); + VdbeComment((v, "%s", pSrcIdx->zName)); + pKey = sqlite3IndexKeyinfo(pParse, pDestIdx); + sqlite3VdbeAddOp4(v, OP_OpenWrite, iDest, pDestIdx->tnum, iDbDest, + (char*)pKey, P4_KEYINFO_HANDOFF); + VdbeComment((v, "%s", pDestIdx->zName)); + addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); + sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData); + sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1); + sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); + sqlite3VdbeJumpHere(v, addr1); + } + sqlite3VdbeJumpHere(v, emptySrcTest); + sqlite3ReleaseTempReg(pParse, regRowid); + sqlite3ReleaseTempReg(pParse, regData); + sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); + sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); + if( emptyDestTest ){ + sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, 0); + sqlite3VdbeJumpHere(v, emptyDestTest); + sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); + return 0; + }else{ + return 1; + } +} +#endif /* SQLITE_OMIT_XFER_OPT */ + +/* Make sure "isView" gets undefined in case this file becomes part of +** the amalgamation - so that subsequent files do not see isView as a +** macro. */ +#undef isView diff --git a/third_party/sqlite/src/journal.c b/third_party/sqlite/src/journal.c new file mode 100755 index 0000000..bdc36bc --- /dev/null +++ b/third_party/sqlite/src/journal.c @@ -0,0 +1,239 @@ +/* +** 2007 August 22 +** +** 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. +** +************************************************************************* +** +** @(#) $Id: journal.c,v 1.8 2008/05/01 18:01:47 drh Exp $ +*/ + +#ifdef SQLITE_ENABLE_ATOMIC_WRITE + +/* +** This file implements a special kind of sqlite3_file object used +** by SQLite to create journal files if the atomic-write optimization +** is enabled. +** +** The distinctive characteristic of this sqlite3_file is that the +** actual on disk file is created lazily. When the file is created, +** the caller specifies a buffer size for an in-memory buffer to +** be used to service read() and write() requests. The actual file +** on disk is not created or populated until either: +** +** 1) The in-memory representation grows too large for the allocated +** buffer, or +** 2) The xSync() method is called. +*/ + +#include "sqliteInt.h" + + +/* +** A JournalFile object is a subclass of sqlite3_file used by +** as an open file handle for journal files. +*/ +struct JournalFile { + sqlite3_io_methods *pMethod; /* I/O methods on journal files */ + int nBuf; /* Size of zBuf[] in bytes */ + char *zBuf; /* Space to buffer journal writes */ + int iSize; /* Amount of zBuf[] currently used */ + int flags; /* xOpen flags */ + sqlite3_vfs *pVfs; /* The "real" underlying VFS */ + sqlite3_file *pReal; /* The "real" underlying file descriptor */ + const char *zJournal; /* Name of the journal file */ +}; +typedef struct JournalFile JournalFile; + +/* +** If it does not already exists, create and populate the on-disk file +** for JournalFile p. +*/ +static int createFile(JournalFile *p){ + int rc = SQLITE_OK; + if( !p->pReal ){ + sqlite3_file *pReal = (sqlite3_file *)&p[1]; + rc = sqlite3OsOpen(p->pVfs, p->zJournal, pReal, p->flags, 0); + if( rc==SQLITE_OK ){ + p->pReal = pReal; + if( p->iSize>0 ){ + assert(p->iSize<=p->nBuf); + rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0); + } + } + } + return rc; +} + +/* +** Close the file. +*/ +static int jrnlClose(sqlite3_file *pJfd){ + JournalFile *p = (JournalFile *)pJfd; + if( p->pReal ){ + sqlite3OsClose(p->pReal); + } + sqlite3_free(p->zBuf); + return SQLITE_OK; +} + +/* +** Read data from the file. +*/ +static int jrnlRead( + sqlite3_file *pJfd, /* The journal file from which to read */ + void *zBuf, /* Put the results here */ + int iAmt, /* Number of bytes to read */ + sqlite_int64 iOfst /* Begin reading at this offset */ +){ + int rc = SQLITE_OK; + JournalFile *p = (JournalFile *)pJfd; + if( p->pReal ){ + rc = sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst); + }else{ + assert( iAmt+iOfst<=p->iSize ); + memcpy(zBuf, &p->zBuf[iOfst], iAmt); + } + return rc; +} + +/* +** Write data to the file. +*/ +static int jrnlWrite( + sqlite3_file *pJfd, /* The journal file into which to write */ + const void *zBuf, /* Take data to be written from here */ + int iAmt, /* Number of bytes to write */ + sqlite_int64 iOfst /* Begin writing at this offset into the file */ +){ + int rc = SQLITE_OK; + JournalFile *p = (JournalFile *)pJfd; + if( !p->pReal && (iOfst+iAmt)>p->nBuf ){ + rc = createFile(p); + } + if( rc==SQLITE_OK ){ + if( p->pReal ){ + rc = sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst); + }else{ + memcpy(&p->zBuf[iOfst], zBuf, iAmt); + if( p->iSize<(iOfst+iAmt) ){ + p->iSize = (iOfst+iAmt); + } + } + } + return rc; +} + +/* +** Truncate the file. +*/ +static int jrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){ + int rc = SQLITE_OK; + JournalFile *p = (JournalFile *)pJfd; + if( p->pReal ){ + rc = sqlite3OsTruncate(p->pReal, size); + }else if( size<p->iSize ){ + p->iSize = size; + } + return rc; +} + +/* +** Sync the file. +*/ +static int jrnlSync(sqlite3_file *pJfd, int flags){ + int rc; + JournalFile *p = (JournalFile *)pJfd; + if( p->pReal ){ + rc = sqlite3OsSync(p->pReal, flags); + }else{ + rc = SQLITE_OK; + } + return rc; +} + +/* +** Query the size of the file in bytes. +*/ +static int jrnlFileSize(sqlite3_file *pJfd, sqlite_int64 *pSize){ + int rc = SQLITE_OK; + JournalFile *p = (JournalFile *)pJfd; + if( p->pReal ){ + rc = sqlite3OsFileSize(p->pReal, pSize); + }else{ + *pSize = (sqlite_int64) p->iSize; + } + return rc; +} + +/* +** Table of methods for JournalFile sqlite3_file object. +*/ +static struct sqlite3_io_methods JournalFileMethods = { + 1, /* iVersion */ + jrnlClose, /* xClose */ + jrnlRead, /* xRead */ + jrnlWrite, /* xWrite */ + jrnlTruncate, /* xTruncate */ + jrnlSync, /* xSync */ + jrnlFileSize, /* xFileSize */ + 0, /* xLock */ + 0, /* xUnlock */ + 0, /* xCheckReservedLock */ + 0, /* xFileControl */ + 0, /* xSectorSize */ + 0 /* xDeviceCharacteristics */ +}; + +/* +** Open a journal file. +*/ +int sqlite3JournalOpen( + sqlite3_vfs *pVfs, /* The VFS to use for actual file I/O */ + const char *zName, /* Name of the journal file */ + sqlite3_file *pJfd, /* Preallocated, blank file handle */ + int flags, /* Opening flags */ + int nBuf /* Bytes buffered before opening the file */ +){ + JournalFile *p = (JournalFile *)pJfd; + memset(p, 0, sqlite3JournalSize(pVfs)); + if( nBuf>0 ){ + p->zBuf = sqlite3MallocZero(nBuf); + if( !p->zBuf ){ + return SQLITE_NOMEM; + } + }else{ + return sqlite3OsOpen(pVfs, zName, pJfd, flags, 0); + } + p->pMethod = &JournalFileMethods; + p->nBuf = nBuf; + p->flags = flags; + p->zJournal = zName; + p->pVfs = pVfs; + return SQLITE_OK; +} + +/* +** If the argument p points to a JournalFile structure, and the underlying +** file has not yet been created, create it now. +*/ +int sqlite3JournalCreate(sqlite3_file *p){ + if( p->pMethods!=&JournalFileMethods ){ + return SQLITE_OK; + } + return createFile((JournalFile *)p); +} + +/* +** Return the number of bytes required to store a JournalFile that uses vfs +** pVfs to create the underlying on-disk files. +*/ +int sqlite3JournalSize(sqlite3_vfs *pVfs){ + return (pVfs->szOsFile+sizeof(JournalFile)); +} +#endif diff --git a/third_party/sqlite/src/legacy.c b/third_party/sqlite/src/legacy.c new file mode 100755 index 0000000..e6b75c0 --- /dev/null +++ b/third_party/sqlite/src/legacy.c @@ -0,0 +1,146 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** Main file for the SQLite library. The routines in this file +** implement the programmer interface to the library. Routines in +** other files are for internal use by SQLite and should not be +** accessed by users of the library. +** +** $Id: legacy.c,v 1.29 2008/08/02 03:50:39 drh Exp $ +*/ + +#include "sqliteInt.h" +#include <ctype.h> + +/* +** Execute SQL code. Return one of the SQLITE_ success/failure +** codes. Also write an error message into memory obtained from +** malloc() and make *pzErrMsg point to that message. +** +** If the SQL is a query, then for each row in the query result +** the xCallback() function is called. pArg becomes the first +** argument to xCallback(). If xCallback=NULL then no callback +** is invoked, even for queries. +*/ +int sqlite3_exec( + sqlite3 *db, /* The database on which the SQL executes */ + const char *zSql, /* The SQL to be executed */ + sqlite3_callback xCallback, /* Invoke this callback routine */ + void *pArg, /* First argument to xCallback() */ + char **pzErrMsg /* Write error messages here */ +){ + int rc = SQLITE_OK; + const char *zLeftover; + sqlite3_stmt *pStmt = 0; + char **azCols = 0; + + int nRetry = 0; + int nCallback; + + if( zSql==0 ) zSql = ""; + + sqlite3_mutex_enter(db->mutex); + sqlite3Error(db, SQLITE_OK, 0); + while( (rc==SQLITE_OK || (rc==SQLITE_SCHEMA && (++nRetry)<2)) && zSql[0] ){ + int nCol; + char **azVals = 0; + + pStmt = 0; + rc = sqlite3_prepare(db, zSql, -1, &pStmt, &zLeftover); + assert( rc==SQLITE_OK || pStmt==0 ); + if( rc!=SQLITE_OK ){ + continue; + } + if( !pStmt ){ + /* this happens for a comment or white-space */ + zSql = zLeftover; + continue; + } + + nCallback = 0; + nCol = sqlite3_column_count(pStmt); + + while( 1 ){ + int i; + rc = sqlite3_step(pStmt); + + /* Invoke the callback function if required */ + if( xCallback && (SQLITE_ROW==rc || + (SQLITE_DONE==rc && !nCallback && db->flags&SQLITE_NullCallback)) ){ + if( 0==nCallback ){ + if( azCols==0 ){ + azCols = sqlite3DbMallocZero(db, 2*nCol*sizeof(const char*) + 1); + if( azCols==0 ){ + goto exec_out; + } + } + for(i=0; i<nCol; i++){ + azCols[i] = (char *)sqlite3_column_name(pStmt, i); + /* sqlite3VdbeSetColName() installs column names as UTF8 + ** strings so there is no way for sqlite3_column_name() to fail. */ + assert( azCols[i]!=0 ); + } + nCallback++; + } + if( rc==SQLITE_ROW ){ + azVals = &azCols[nCol]; + for(i=0; i<nCol; i++){ + azVals[i] = (char *)sqlite3_column_text(pStmt, i); + if( !azVals[i] && sqlite3_column_type(pStmt, i)!=SQLITE_NULL ){ + db->mallocFailed = 1; + goto exec_out; + } + } + } + if( xCallback(pArg, nCol, azVals, azCols) ){ + rc = SQLITE_ABORT; + sqlite3_finalize(pStmt); + pStmt = 0; + sqlite3Error(db, SQLITE_ABORT, 0); + goto exec_out; + } + } + + if( rc!=SQLITE_ROW ){ + rc = sqlite3_finalize(pStmt); + pStmt = 0; + if( rc!=SQLITE_SCHEMA ){ + nRetry = 0; + zSql = zLeftover; + while( isspace((unsigned char)zSql[0]) ) zSql++; + } + break; + } + } + + sqlite3DbFree(db, azCols); + azCols = 0; + } + +exec_out: + if( pStmt ) sqlite3_finalize(pStmt); + sqlite3DbFree(db, azCols); + + rc = sqlite3ApiExit(db, rc); + if( rc!=SQLITE_OK && rc==sqlite3_errcode(db) && pzErrMsg ){ + int nErrMsg = 1 + strlen(sqlite3_errmsg(db)); + *pzErrMsg = sqlite3Malloc(nErrMsg); + if( *pzErrMsg ){ + memcpy(*pzErrMsg, sqlite3_errmsg(db), nErrMsg); + } + }else if( pzErrMsg ){ + *pzErrMsg = 0; + } + + assert( (rc&db->errMask)==rc ); + sqlite3_mutex_leave(db->mutex); + return rc; +} diff --git a/third_party/sqlite/src/loadext.c b/third_party/sqlite/src/loadext.c new file mode 100755 index 0000000..2f7ca52 --- /dev/null +++ b/third_party/sqlite/src/loadext.c @@ -0,0 +1,569 @@ +/* +** 2006 June 7 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains code used to dynamically load extensions into +** the SQLite library. +** +** $Id: loadext.c,v 1.53 2008/08/02 03:50:39 drh Exp $ +*/ + +#ifndef SQLITE_CORE + #define SQLITE_CORE 1 /* Disable the API redefinition in sqlite3ext.h */ +#endif +#include "sqlite3ext.h" +#include "sqliteInt.h" +#include <string.h> +#include <ctype.h> + +#ifndef SQLITE_OMIT_LOAD_EXTENSION + +/* +** Some API routines are omitted when various features are +** excluded from a build of SQLite. Substitute a NULL pointer +** for any missing APIs. +*/ +#ifndef SQLITE_ENABLE_COLUMN_METADATA +# define sqlite3_column_database_name 0 +# define sqlite3_column_database_name16 0 +# define sqlite3_column_table_name 0 +# define sqlite3_column_table_name16 0 +# define sqlite3_column_origin_name 0 +# define sqlite3_column_origin_name16 0 +# define sqlite3_table_column_metadata 0 +#endif + +#ifdef SQLITE_OMIT_AUTHORIZATION +# define sqlite3_set_authorizer 0 +#endif + +#ifdef SQLITE_OMIT_UTF16 +# define sqlite3_bind_text16 0 +# define sqlite3_collation_needed16 0 +# define sqlite3_column_decltype16 0 +# define sqlite3_column_name16 0 +# define sqlite3_column_text16 0 +# define sqlite3_complete16 0 +# define sqlite3_create_collation16 0 +# define sqlite3_create_function16 0 +# define sqlite3_errmsg16 0 +# define sqlite3_open16 0 +# define sqlite3_prepare16 0 +# define sqlite3_prepare16_v2 0 +# define sqlite3_result_error16 0 +# define sqlite3_result_text16 0 +# define sqlite3_result_text16be 0 +# define sqlite3_result_text16le 0 +# define sqlite3_value_text16 0 +# define sqlite3_value_text16be 0 +# define sqlite3_value_text16le 0 +# define sqlite3_column_database_name16 0 +# define sqlite3_column_table_name16 0 +# define sqlite3_column_origin_name16 0 +#endif + +#ifdef SQLITE_OMIT_COMPLETE +# define sqlite3_complete 0 +# define sqlite3_complete16 0 +#endif + +#ifdef SQLITE_OMIT_PROGRESS_CALLBACK +# define sqlite3_progress_handler 0 +#endif + +#ifdef SQLITE_OMIT_VIRTUALTABLE +# define sqlite3_create_module 0 +# define sqlite3_create_module_v2 0 +# define sqlite3_declare_vtab 0 +#endif + +#ifdef SQLITE_OMIT_SHARED_CACHE +# define sqlite3_enable_shared_cache 0 +#endif + +#ifdef SQLITE_OMIT_TRACE +# define sqlite3_profile 0 +# define sqlite3_trace 0 +#endif + +#ifdef SQLITE_OMIT_GET_TABLE +# define sqlite3_free_table 0 +# define sqlite3_get_table 0 +#endif + +#ifdef SQLITE_OMIT_INCRBLOB +#define sqlite3_bind_zeroblob 0 +#define sqlite3_blob_bytes 0 +#define sqlite3_blob_close 0 +#define sqlite3_blob_open 0 +#define sqlite3_blob_read 0 +#define sqlite3_blob_write 0 +#endif + +/* +** The following structure contains pointers to all SQLite API routines. +** A pointer to this structure is passed into extensions when they are +** loaded so that the extension can make calls back into the SQLite +** library. +** +** When adding new APIs, add them to the bottom of this structure +** in order to preserve backwards compatibility. +** +** Extensions that use newer APIs should first call the +** sqlite3_libversion_number() to make sure that the API they +** intend to use is supported by the library. Extensions should +** also check to make sure that the pointer to the function is +** not NULL before calling it. +*/ +static const sqlite3_api_routines sqlite3Apis = { + sqlite3_aggregate_context, + sqlite3_aggregate_count, + sqlite3_bind_blob, + sqlite3_bind_double, + sqlite3_bind_int, + sqlite3_bind_int64, + sqlite3_bind_null, + sqlite3_bind_parameter_count, + sqlite3_bind_parameter_index, + sqlite3_bind_parameter_name, + sqlite3_bind_text, + sqlite3_bind_text16, + sqlite3_bind_value, + sqlite3_busy_handler, + sqlite3_busy_timeout, + sqlite3_changes, + sqlite3_close, + sqlite3_collation_needed, + sqlite3_collation_needed16, + sqlite3_column_blob, + sqlite3_column_bytes, + sqlite3_column_bytes16, + sqlite3_column_count, + sqlite3_column_database_name, + sqlite3_column_database_name16, + sqlite3_column_decltype, + sqlite3_column_decltype16, + sqlite3_column_double, + sqlite3_column_int, + sqlite3_column_int64, + sqlite3_column_name, + sqlite3_column_name16, + sqlite3_column_origin_name, + sqlite3_column_origin_name16, + sqlite3_column_table_name, + sqlite3_column_table_name16, + sqlite3_column_text, + sqlite3_column_text16, + sqlite3_column_type, + sqlite3_column_value, + sqlite3_commit_hook, + sqlite3_complete, + sqlite3_complete16, + sqlite3_create_collation, + sqlite3_create_collation16, + sqlite3_create_function, + sqlite3_create_function16, + sqlite3_create_module, + sqlite3_data_count, + sqlite3_db_handle, + sqlite3_declare_vtab, + sqlite3_enable_shared_cache, + sqlite3_errcode, + sqlite3_errmsg, + sqlite3_errmsg16, + sqlite3_exec, + sqlite3_expired, + sqlite3_finalize, + sqlite3_free, + sqlite3_free_table, + sqlite3_get_autocommit, + sqlite3_get_auxdata, + sqlite3_get_table, + 0, /* Was sqlite3_global_recover(), but that function is deprecated */ + sqlite3_interrupt, + sqlite3_last_insert_rowid, + sqlite3_libversion, + sqlite3_libversion_number, + sqlite3_malloc, + sqlite3_mprintf, + sqlite3_open, + sqlite3_open16, + sqlite3_prepare, + sqlite3_prepare16, + sqlite3_profile, + sqlite3_progress_handler, + sqlite3_realloc, + sqlite3_reset, + sqlite3_result_blob, + sqlite3_result_double, + sqlite3_result_error, + sqlite3_result_error16, + sqlite3_result_int, + sqlite3_result_int64, + sqlite3_result_null, + sqlite3_result_text, + sqlite3_result_text16, + sqlite3_result_text16be, + sqlite3_result_text16le, + sqlite3_result_value, + sqlite3_rollback_hook, + sqlite3_set_authorizer, + sqlite3_set_auxdata, + sqlite3_snprintf, + sqlite3_step, + sqlite3_table_column_metadata, + sqlite3_thread_cleanup, + sqlite3_total_changes, + sqlite3_trace, + sqlite3_transfer_bindings, + sqlite3_update_hook, + sqlite3_user_data, + sqlite3_value_blob, + sqlite3_value_bytes, + sqlite3_value_bytes16, + sqlite3_value_double, + sqlite3_value_int, + sqlite3_value_int64, + sqlite3_value_numeric_type, + sqlite3_value_text, + sqlite3_value_text16, + sqlite3_value_text16be, + sqlite3_value_text16le, + sqlite3_value_type, + sqlite3_vmprintf, + /* + ** The original API set ends here. All extensions can call any + ** of the APIs above provided that the pointer is not NULL. But + ** before calling APIs that follow, extension should check the + ** sqlite3_libversion_number() to make sure they are dealing with + ** a library that is new enough to support that API. + ************************************************************************* + */ + sqlite3_overload_function, + + /* + ** Added after 3.3.13 + */ + sqlite3_prepare_v2, + sqlite3_prepare16_v2, + sqlite3_clear_bindings, + + /* + ** Added for 3.4.1 + */ + sqlite3_create_module_v2, + + /* + ** Added for 3.5.0 + */ + sqlite3_bind_zeroblob, + sqlite3_blob_bytes, + sqlite3_blob_close, + sqlite3_blob_open, + sqlite3_blob_read, + sqlite3_blob_write, + sqlite3_create_collation_v2, + sqlite3_file_control, + sqlite3_memory_highwater, + sqlite3_memory_used, +#ifdef SQLITE_MUTEX_NOOP + 0, + 0, + 0, + 0, + 0, +#else + sqlite3_mutex_alloc, + sqlite3_mutex_enter, + sqlite3_mutex_free, + sqlite3_mutex_leave, + sqlite3_mutex_try, +#endif + sqlite3_open_v2, + sqlite3_release_memory, + sqlite3_result_error_nomem, + sqlite3_result_error_toobig, + sqlite3_sleep, + sqlite3_soft_heap_limit, + sqlite3_vfs_find, + sqlite3_vfs_register, + sqlite3_vfs_unregister, + + /* + ** Added for 3.5.8 + */ + sqlite3_threadsafe, + sqlite3_result_zeroblob, + sqlite3_result_error_code, + sqlite3_test_control, + sqlite3_randomness, + sqlite3_context_db_handle, + + /* + ** Added for 3.6.0 + */ + sqlite3_extended_result_codes, + sqlite3_limit, + sqlite3_next_stmt, + sqlite3_sql, + sqlite3_status, +}; + +/* +** Attempt to load an SQLite extension library contained in the file +** zFile. The entry point is zProc. zProc may be 0 in which case a +** default entry point name (sqlite3_extension_init) is used. Use +** of the default name is recommended. +** +** Return SQLITE_OK on success and SQLITE_ERROR if something goes wrong. +** +** If an error occurs and pzErrMsg is not 0, then fill *pzErrMsg with +** error message text. The calling function should free this memory +** by calling sqlite3DbFree(db, ). +*/ +static int sqlite3LoadExtension( + sqlite3 *db, /* Load the extension into this database connection */ + const char *zFile, /* Name of the shared library containing extension */ + const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */ + char **pzErrMsg /* Put error message here if not 0 */ +){ + sqlite3_vfs *pVfs = db->pVfs; + void *handle; + int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*); + char *zErrmsg = 0; + void **aHandle; + + /* Ticket #1863. To avoid a creating security problems for older + ** applications that relink against newer versions of SQLite, the + ** ability to run load_extension is turned off by default. One + ** must call sqlite3_enable_load_extension() to turn on extension + ** loading. Otherwise you get the following error. + */ + if( (db->flags & SQLITE_LoadExtension)==0 ){ + if( pzErrMsg ){ + *pzErrMsg = sqlite3_mprintf("not authorized"); + } + return SQLITE_ERROR; + } + + if( zProc==0 ){ + zProc = "sqlite3_extension_init"; + } + + handle = sqlite3OsDlOpen(pVfs, zFile); + if( handle==0 ){ + if( pzErrMsg ){ + char zErr[256]; + zErr[sizeof(zErr)-1] = '\0'; + sqlite3_snprintf(sizeof(zErr)-1, zErr, + "unable to open shared library [%s]", zFile); + sqlite3OsDlError(pVfs, sizeof(zErr)-1, zErr); + *pzErrMsg = sqlite3DbStrDup(0, zErr); + } + return SQLITE_ERROR; + } + xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*)) + sqlite3OsDlSym(pVfs, handle, zProc); + if( xInit==0 ){ + if( pzErrMsg ){ + char zErr[256]; + zErr[sizeof(zErr)-1] = '\0'; + sqlite3_snprintf(sizeof(zErr)-1, zErr, + "no entry point [%s] in shared library [%s]", zProc,zFile); + sqlite3OsDlError(pVfs, sizeof(zErr)-1, zErr); + *pzErrMsg = sqlite3DbStrDup(0, zErr); + sqlite3OsDlClose(pVfs, handle); + } + return SQLITE_ERROR; + }else if( xInit(db, &zErrmsg, &sqlite3Apis) ){ + if( pzErrMsg ){ + *pzErrMsg = sqlite3_mprintf("error during initialization: %s", zErrmsg); + } + sqlite3_free(zErrmsg); + sqlite3OsDlClose(pVfs, handle); + return SQLITE_ERROR; + } + + /* Append the new shared library handle to the db->aExtension array. */ + aHandle = sqlite3DbMallocZero(db, sizeof(handle)*(db->nExtension+1)); + if( aHandle==0 ){ + return SQLITE_NOMEM; + } + if( db->nExtension>0 ){ + memcpy(aHandle, db->aExtension, sizeof(handle)*db->nExtension); + } + sqlite3DbFree(db, db->aExtension); + db->aExtension = aHandle; + + db->aExtension[db->nExtension++] = handle; + return SQLITE_OK; +} +int sqlite3_load_extension( + sqlite3 *db, /* Load the extension into this database connection */ + const char *zFile, /* Name of the shared library containing extension */ + const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */ + char **pzErrMsg /* Put error message here if not 0 */ +){ + int rc; + sqlite3_mutex_enter(db->mutex); + rc = sqlite3LoadExtension(db, zFile, zProc, pzErrMsg); + sqlite3_mutex_leave(db->mutex); + return rc; +} + +/* +** Call this routine when the database connection is closing in order +** to clean up loaded extensions +*/ +void sqlite3CloseExtensions(sqlite3 *db){ + int i; + assert( sqlite3_mutex_held(db->mutex) ); + for(i=0; i<db->nExtension; i++){ + sqlite3OsDlClose(db->pVfs, db->aExtension[i]); + } + sqlite3DbFree(db, db->aExtension); +} + +/* +** Enable or disable extension loading. Extension loading is disabled by +** default so as not to open security holes in older applications. +*/ +int sqlite3_enable_load_extension(sqlite3 *db, int onoff){ + sqlite3_mutex_enter(db->mutex); + if( onoff ){ + db->flags |= SQLITE_LoadExtension; + }else{ + db->flags &= ~SQLITE_LoadExtension; + } + sqlite3_mutex_leave(db->mutex); + return SQLITE_OK; +} + +#endif /* SQLITE_OMIT_LOAD_EXTENSION */ + +/* +** The auto-extension code added regardless of whether or not extension +** loading is supported. We need a dummy sqlite3Apis pointer for that +** code if regular extension loading is not available. This is that +** dummy pointer. +*/ +#ifdef SQLITE_OMIT_LOAD_EXTENSION +static const sqlite3_api_routines sqlite3Apis = { 0 }; +#endif + + +/* +** The following object holds the list of automatically loaded +** extensions. +** +** This list is shared across threads. The SQLITE_MUTEX_STATIC_MASTER +** mutex must be held while accessing this list. +*/ +static struct { + int nExt; /* Number of entries in aExt[] */ + void **aExt; /* Pointers to the extension init functions */ +} autoext = { 0, 0 }; + + +/* +** Register a statically linked extension that is automatically +** loaded by every new database connection. +*/ +int sqlite3_auto_extension(void *xInit){ + int rc = SQLITE_OK; +#ifndef SQLITE_OMIT_AUTOINIT + rc = sqlite3_initialize(); + if( rc ){ + return rc; + }else +#endif + { + int i; +#ifndef SQLITE_MUTEX_NOOP + sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); +#endif + sqlite3_mutex_enter(mutex); + for(i=0; i<autoext.nExt; i++){ + if( autoext.aExt[i]==xInit ) break; + } + if( i==autoext.nExt ){ + int nByte = (autoext.nExt+1)*sizeof(autoext.aExt[0]); + void **aNew; + aNew = sqlite3_realloc(autoext.aExt, nByte); + if( aNew==0 ){ + rc = SQLITE_NOMEM; + }else{ + autoext.aExt = aNew; + autoext.aExt[autoext.nExt] = xInit; + autoext.nExt++; + } + } + sqlite3_mutex_leave(mutex); + assert( (rc&0xff)==rc ); + return rc; + } +} + +/* +** Reset the automatic extension loading mechanism. +*/ +void sqlite3_reset_auto_extension(void){ +#ifndef SQLITE_OMIT_AUTOINIT + if( sqlite3_initialize()==SQLITE_OK ) +#endif + { +#ifndef SQLITE_MUTEX_NOOP + sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); +#endif + sqlite3_mutex_enter(mutex); + sqlite3_free(autoext.aExt); + autoext.aExt = 0; + autoext.nExt = 0; + sqlite3_mutex_leave(mutex); + } +} + +/* +** Load all automatic extensions. +*/ +int sqlite3AutoLoadExtensions(sqlite3 *db){ + int i; + int go = 1; + int rc = SQLITE_OK; + int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*); + + if( autoext.nExt==0 ){ + /* Common case: early out without every having to acquire a mutex */ + return SQLITE_OK; + } + for(i=0; go; i++){ + char *zErrmsg = 0; +#ifndef SQLITE_MUTEX_NOOP + sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); +#endif + sqlite3_mutex_enter(mutex); + if( i>=autoext.nExt ){ + xInit = 0; + go = 0; + }else{ + xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*)) + autoext.aExt[i]; + } + sqlite3_mutex_leave(mutex); + if( xInit && xInit(db, &zErrmsg, &sqlite3Apis) ){ + sqlite3Error(db, SQLITE_ERROR, + "automatic extension loading failed: %s", zErrmsg); + go = 0; + rc = SQLITE_ERROR; + sqlite3_free(zErrmsg); + } + } + return rc; +} diff --git a/third_party/sqlite/src/main.c b/third_party/sqlite/src/main.c new file mode 100755 index 0000000..68500eb --- /dev/null +++ b/third_party/sqlite/src/main.c @@ -0,0 +1,2005 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** Main file for the SQLite library. The routines in this file +** implement the programmer interface to the library. Routines in +** other files are for internal use by SQLite and should not be +** accessed by users of the library. +** +** $Id: main.c,v 1.486 2008/08/04 20:13:27 drh Exp $ +*/ +#include "sqliteInt.h" +#include <ctype.h> + +#ifdef SQLITE_ENABLE_FTS3 +# include "fts3.h" +#endif +#ifdef SQLITE_ENABLE_RTREE +# include "rtree.h" +#endif + +/* +** The version of the library +*/ +const char sqlite3_version[] = SQLITE_VERSION; +const char *sqlite3_libversion(void){ return sqlite3_version; } +int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; } +int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; } + +#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE) +/* +** If the following function pointer is not NULL and if +** SQLITE_ENABLE_IOTRACE is enabled, then messages describing +** I/O active are written using this function. These messages +** are intended for debugging activity only. +*/ +void (*sqlite3IoTrace)(const char*, ...) = 0; +#endif + +/* +** 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; + +/* +** Initialize SQLite. +** +** This routine must be called to initialize the memory allocation, +** VFS, and mutex subsystesms prior to doing any serious work with +** SQLite. But as long as you do not compile with SQLITE_OMIT_AUTOINIT +** this routine will be called automatically by key routines such as +** sqlite3_open(). +** +** This routine is a no-op except on its very first call for the process, +** or for the first call after a call to sqlite3_shutdown. +*/ +int sqlite3_initialize(void){ + static int inProgress = 0; + int rc; + + /* If SQLite is already initialized, this call is a no-op. */ + if( sqlite3Config.isInit ) return SQLITE_OK; + + /* Make sure the mutex system is initialized. */ + rc = sqlite3MutexInit(); + + if( rc==SQLITE_OK ){ + + /* Initialize the malloc() system and the recursive pInitMutex mutex. + ** This operation is protected by the STATIC_MASTER mutex. + */ + sqlite3_mutex *pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); + sqlite3_mutex_enter(pMaster); + if( !sqlite3Config.isMallocInit ){ + rc = sqlite3MallocInit(); + } + if( rc==SQLITE_OK ){ + sqlite3Config.isMallocInit = 1; + if( !sqlite3Config.pInitMutex ){ + sqlite3Config.pInitMutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); + if( sqlite3Config.bCoreMutex && !sqlite3Config.pInitMutex ){ + rc = SQLITE_NOMEM; + } + } + } + sqlite3_mutex_leave(pMaster); + if( rc!=SQLITE_OK ){ + return rc; + } + + /* Enter the recursive pInitMutex mutex. After doing so, if the + ** sqlite3Config.isInit flag is true, then some other thread has + ** finished doing the initialization. If the inProgress flag is + ** true, then this function is being called recursively from within + ** the sqlite3_os_init() call below. In either case, exit early. + */ + sqlite3_mutex_enter(sqlite3Config.pInitMutex); + if( sqlite3Config.isInit || inProgress ){ + sqlite3_mutex_leave(sqlite3Config.pInitMutex); + return SQLITE_OK; + } + sqlite3StatusReset(); + inProgress = 1; + rc = sqlite3_os_init(); + inProgress = 0; + sqlite3Config.isInit = (rc==SQLITE_OK ? 1 : 0); + sqlite3_mutex_leave(sqlite3Config.pInitMutex); + } + + /* Check NaN support. */ +#ifndef NDEBUG + /* This section of code's only "output" is via assert() statements. */ + if ( rc==SQLITE_OK ){ + u64 x = (((u64)1)<<63)-1; + double y; + assert(sizeof(x)==8); + assert(sizeof(x)==sizeof(y)); + memcpy(&y, &x, 8); + assert( sqlite3IsNaN(y) ); + } +#endif + + return rc; +} + +/* +** Undo the effects of sqlite3_initialize(). Must not be called while +** there are outstanding database connections or memory allocations or +** while any part of SQLite is otherwise in use in any thread. This +** routine is not threadsafe. Not by a long shot. +*/ +int sqlite3_shutdown(void){ + sqlite3_mutex_free(sqlite3Config.pInitMutex); + sqlite3Config.pInitMutex = 0; + sqlite3Config.isMallocInit = 0; + if( sqlite3Config.isInit ){ + sqlite3_os_end(); + } + if( sqlite3Config.m.xShutdown ){ + sqlite3MallocEnd(); + } + if( sqlite3Config.mutex.xMutexEnd ){ + sqlite3MutexEnd(); + } + sqlite3Config.isInit = 0; + return SQLITE_OK; +} + +/* +** This API allows applications to modify the global configuration of +** the SQLite library at run-time. +** +** This routine should only be called when there are no outstanding +** database connections or memory allocations. This routine is not +** threadsafe. Failure to heed these warnings can lead to unpredictable +** behavior. +*/ +int sqlite3_config(int op, ...){ + va_list ap; + int rc = SQLITE_OK; + + /* sqlite3_config() shall return SQLITE_MISUSE if it is invoked while + ** the SQLite library is in use. */ + if( sqlite3Config.isInit ) return SQLITE_MISUSE; + + va_start(ap, op); + switch( op ){ + case SQLITE_CONFIG_SINGLETHREAD: { + /* Disable all mutexing */ + sqlite3Config.bCoreMutex = 0; + sqlite3Config.bFullMutex = 0; + break; + } + case SQLITE_CONFIG_MULTITHREAD: { + /* Disable mutexing of database connections */ + /* Enable mutexing of core data structures */ + sqlite3Config.bCoreMutex = 1; + sqlite3Config.bFullMutex = 0; + break; + } + case SQLITE_CONFIG_SERIALIZED: { + /* Enable all mutexing */ + sqlite3Config.bCoreMutex = 1; + sqlite3Config.bFullMutex = 1; + break; + } + case SQLITE_CONFIG_MALLOC: { + /* Specify an alternative malloc implementation */ + sqlite3Config.m = *va_arg(ap, sqlite3_mem_methods*); + break; + } + case SQLITE_CONFIG_GETMALLOC: { + /* Retrieve the current malloc() implementation */ + if( sqlite3Config.m.xMalloc==0 ) sqlite3MemSetDefault(); + *va_arg(ap, sqlite3_mem_methods*) = sqlite3Config.m; + break; + } + case SQLITE_CONFIG_MUTEX: { + /* Specify an alternative mutex implementation */ + sqlite3Config.mutex = *va_arg(ap, sqlite3_mutex_methods*); + break; + } + case SQLITE_CONFIG_GETMUTEX: { + /* Retrieve the current mutex implementation */ + *va_arg(ap, sqlite3_mutex_methods*) = sqlite3Config.mutex; + break; + } + case SQLITE_CONFIG_MEMSTATUS: { + /* Enable or disable the malloc status collection */ + sqlite3Config.bMemstat = va_arg(ap, int); + break; + } + case SQLITE_CONFIG_SCRATCH: { + /* Designate a buffer for scratch memory space */ + sqlite3Config.pScratch = va_arg(ap, void*); + sqlite3Config.szScratch = va_arg(ap, int); + sqlite3Config.nScratch = va_arg(ap, int); + break; + } + case SQLITE_CONFIG_PAGECACHE: { + /* Designate a buffer for scratch memory space */ + sqlite3Config.pPage = va_arg(ap, void*); + sqlite3Config.szPage = va_arg(ap, int); + sqlite3Config.nPage = va_arg(ap, int); + break; + } + +#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) + case SQLITE_CONFIG_HEAP: { + /* Designate a buffer for heap memory space */ + sqlite3Config.pHeap = va_arg(ap, void*); + sqlite3Config.nHeap = va_arg(ap, int); + sqlite3Config.mnReq = va_arg(ap, int); + + if( sqlite3Config.pHeap==0 ){ + /* If the heap pointer is NULL, then restore the malloc implementation + ** back to NULL pointers too. This will cause the malloc to go + ** back to its default implementation when sqlite3_initialize() is + ** run. + */ + memset(&sqlite3Config.m, 0, sizeof(sqlite3Config.m)); + }else{ + /* The heap pointer is not NULL, then install one of the + ** mem5.c/mem3.c methods. If neither ENABLE_MEMSYS3 nor + ** ENABLE_MEMSYS5 is defined, return an error. + ** the default case and return an error. + */ +#ifdef SQLITE_ENABLE_MEMSYS3 + sqlite3Config.m = *sqlite3MemGetMemsys3(); +#endif +#ifdef SQLITE_ENABLE_MEMSYS5 + sqlite3Config.m = *sqlite3MemGetMemsys5(); +#endif + } + break; + } +#endif + +#if defined(SQLITE_ENABLE_MEMSYS6) + case SQLITE_CONFIG_CHUNKALLOC: { + sqlite3Config.nSmall = va_arg(ap, int); + sqlite3Config.m = *sqlite3MemGetMemsys6(); + break; + } +#endif + + case SQLITE_CONFIG_LOOKASIDE: { + sqlite3Config.szLookaside = va_arg(ap, int); + sqlite3Config.nLookaside = va_arg(ap, int); + break; + } + + default: { + rc = SQLITE_ERROR; + break; + } + } + va_end(ap); + return rc; +} + +/* +** Set up the lookaside buffers for a database connection. +** Return SQLITE_OK on success. +** If lookaside is already active, return SQLITE_BUSY. +** +** The sz parameter is the number of bytes in each lookaside slot. +** The cnt parameter is the number of slots. If pStart is NULL the +** space for the lookaside memory is obtained from sqlite3_malloc(). +** If pStart is not NULL then it is sz*cnt bytes of memory to use for +** the lookaside memory. +*/ +static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){ + void *pStart; + if( db->lookaside.nOut ){ + return SQLITE_BUSY; + } + if( sz<0 ) sz = 0; + if( cnt<0 ) cnt = 0; + sz = (sz+7)&~7; + if( pBuf==0 ){ + sqlite3BeginBenignMalloc(); + pStart = sqlite3Malloc( sz*cnt ); + sqlite3EndBenignMalloc(); + }else{ + pStart = pBuf; + } + if( db->lookaside.bMalloced ){ + sqlite3_free(db->lookaside.pStart); + } + db->lookaside.pStart = pStart; + db->lookaside.pFree = 0; + db->lookaside.sz = sz; + db->lookaside.bMalloced = pBuf==0; + if( pStart ){ + int i; + LookasideSlot *p; + p = (LookasideSlot*)pStart; + for(i=cnt-1; i>=0; i--){ + p->pNext = db->lookaside.pFree; + db->lookaside.pFree = p; + p = (LookasideSlot*)&((u8*)p)[sz]; + } + db->lookaside.pEnd = p; + db->lookaside.bEnabled = 1; + }else{ + db->lookaside.pEnd = 0; + db->lookaside.bEnabled = 0; + } + return SQLITE_OK; +} + +/* +** Configuration settings for an individual database connection +*/ +int sqlite3_db_config(sqlite3 *db, int op, ...){ + va_list ap; + int rc; + va_start(ap, op); + switch( op ){ + case SQLITE_DBCONFIG_LOOKASIDE: { + void *pBuf = va_arg(ap, void*); + int sz = va_arg(ap, int); + int cnt = va_arg(ap, int); + rc = setupLookaside(db, pBuf, sz, cnt); + break; + } + default: { + rc = SQLITE_ERROR; + break; + } + } + va_end(ap); + return rc; +} + +/* +** Routine needed to support the testcase() macro. +*/ +#ifdef SQLITE_COVERAGE_TEST +void sqlite3Coverage(int x){ + static int dummy = 0; + dummy += x; +} +#endif + + +/* +** Return true if the buffer z[0..n-1] contains all spaces. +*/ +static int allSpaces(const char *z, int n){ + while( n>0 && z[n-1]==' ' ){ n--; } + return n==0; +} + +/* +** This is the default collating function named "BINARY" which is always +** available. +** +** If the padFlag argument is not NULL then space padding at the end +** of strings is ignored. This implements the RTRIM collation. +*/ +static int binCollFunc( + void *padFlag, + int nKey1, const void *pKey1, + int nKey2, const void *pKey2 +){ + int rc, n; + n = nKey1<nKey2 ? nKey1 : nKey2; + rc = memcmp(pKey1, pKey2, n); + if( rc==0 ){ + if( padFlag + && allSpaces(((char*)pKey1)+n, nKey1-n) + && allSpaces(((char*)pKey2)+n, nKey2-n) + ){ + /* Leave rc unchanged at 0 */ + }else{ + rc = nKey1 - nKey2; + } + } + return rc; +} + +/* +** Another built-in collating sequence: NOCASE. +** +** This collating sequence is intended to be used for "case independant +** comparison". SQLite's knowledge of upper and lower case equivalents +** extends only to the 26 characters used in the English language. +** +** At the moment there is only a UTF-8 implementation. +*/ +static int nocaseCollatingFunc( + void *NotUsed, + int nKey1, const void *pKey1, + int nKey2, const void *pKey2 +){ + int r = sqlite3StrNICmp( + (const char *)pKey1, (const char *)pKey2, (nKey1<nKey2)?nKey1:nKey2); + if( 0==r ){ + r = nKey1-nKey2; + } + return r; +} + +/* +** Return the ROWID of the most recent insert +*/ +sqlite_int64 sqlite3_last_insert_rowid(sqlite3 *db){ + return db->lastRowid; +} + +/* +** Return the number of changes in the most recent call to sqlite3_exec(). +*/ +int sqlite3_changes(sqlite3 *db){ + return db->nChange; +} + +/* +** Return the number of changes since the database handle was opened. +*/ +int sqlite3_total_changes(sqlite3 *db){ + return db->nTotalChange; +} + +/* +** Close an existing SQLite database +*/ +int sqlite3_close(sqlite3 *db){ + HashElem *i; + int j; + + if( !db ){ + return SQLITE_OK; + } + if( !sqlite3SafetyCheckSickOrOk(db) ){ + return SQLITE_MISUSE; + } + sqlite3_mutex_enter(db->mutex); + +#ifdef SQLITE_SSE + { + extern void sqlite3SseCleanup(sqlite3*); + sqlite3SseCleanup(db); + } +#endif + + sqlite3ResetInternalSchema(db, 0); + + /* If a transaction is open, the ResetInternalSchema() call above + ** will not have called the xDisconnect() method on any virtual + ** tables in the db->aVTrans[] array. The following sqlite3VtabRollback() + ** call will do so. We need to do this before the check for active + ** SQL statements below, as the v-table implementation may be storing + ** some prepared statements internally. + */ + sqlite3VtabRollback(db); + + /* If there are any outstanding VMs, return SQLITE_BUSY. */ + if( db->pVdbe ){ + sqlite3Error(db, SQLITE_BUSY, + "Unable to close due to unfinalised statements"); + sqlite3_mutex_leave(db->mutex); + return SQLITE_BUSY; + } + assert( sqlite3SafetyCheckSickOrOk(db) ); + + for(j=0; j<db->nDb; j++){ + struct Db *pDb = &db->aDb[j]; + if( pDb->pBt ){ + sqlite3BtreeClose(pDb->pBt); + pDb->pBt = 0; + if( j!=1 ){ + pDb->pSchema = 0; + } + } + } + sqlite3ResetInternalSchema(db, 0); + assert( db->nDb<=2 ); + assert( db->aDb==db->aDbStatic ); + for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){ + FuncDef *pFunc, *pNext; + for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){ + pNext = pFunc->pNext; + sqlite3DbFree(db, pFunc); + } + } + + for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){ + CollSeq *pColl = (CollSeq *)sqliteHashData(i); + /* Invoke any destructors registered for collation sequence user data. */ + for(j=0; j<3; j++){ + if( pColl[j].xDel ){ + pColl[j].xDel(pColl[j].pUser); + } + } + sqlite3DbFree(db, pColl); + } + sqlite3HashClear(&db->aCollSeq); +#ifndef SQLITE_OMIT_VIRTUALTABLE + for(i=sqliteHashFirst(&db->aModule); i; i=sqliteHashNext(i)){ + Module *pMod = (Module *)sqliteHashData(i); + if( pMod->xDestroy ){ + pMod->xDestroy(pMod->pAux); + } + sqlite3DbFree(db, pMod); + } + sqlite3HashClear(&db->aModule); +#endif + + sqlite3HashClear(&db->aFunc); + sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */ + if( db->pErr ){ + sqlite3ValueFree(db->pErr); + } + sqlite3CloseExtensions(db); + + 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? + */ + sqlite3DbFree(db, db->aDb[1].pSchema); + sqlite3_mutex_leave(db->mutex); + db->magic = SQLITE_MAGIC_CLOSED; + sqlite3_mutex_free(db->mutex); + if( db->lookaside.bMalloced ){ + sqlite3_free(db->lookaside.pStart); + } + sqlite3_free(db); + return SQLITE_OK; +} + +/* +** Rollback all database files. +*/ +void sqlite3RollbackAll(sqlite3 *db){ + int i; + int inTrans = 0; + assert( sqlite3_mutex_held(db->mutex) ); + sqlite3BeginBenignMalloc(); + for(i=0; i<db->nDb; i++){ + if( db->aDb[i].pBt ){ + if( sqlite3BtreeIsInTrans(db->aDb[i].pBt) ){ + inTrans = 1; + } + sqlite3BtreeRollback(db->aDb[i].pBt); + db->aDb[i].inTrans = 0; + } + } + sqlite3VtabRollback(db); + sqlite3EndBenignMalloc(); + + if( db->flags&SQLITE_InternChanges ){ + sqlite3ExpirePreparedStatements(db); + sqlite3ResetInternalSchema(db, 0); + } + + /* If one has been configured, invoke the rollback-hook callback */ + if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){ + db->xRollbackCallback(db->pRollbackArg); + } +} + +/* +** Return a static string that describes the kind of error specified in the +** argument. +*/ +const char *sqlite3ErrStr(int rc){ + const char *z; + switch( rc & 0xff ){ + case SQLITE_ROW: + case SQLITE_DONE: + case SQLITE_OK: z = "not an error"; break; + case SQLITE_ERROR: z = "SQL logic error or missing database"; break; + case SQLITE_PERM: z = "access permission denied"; break; + case SQLITE_ABORT: z = "callback requested query abort"; break; + case SQLITE_BUSY: z = "database is locked"; break; + case SQLITE_LOCKED: z = "database table is locked"; break; + case SQLITE_NOMEM: z = "out of memory"; break; + case SQLITE_READONLY: z = "attempt to write a readonly database"; break; + case SQLITE_INTERRUPT: z = "interrupted"; break; + case SQLITE_IOERR: z = "disk I/O error"; break; + case SQLITE_CORRUPT: z = "database disk image is malformed"; break; + case SQLITE_FULL: z = "database or disk is full"; break; + case SQLITE_CANTOPEN: z = "unable to open database file"; break; + case SQLITE_EMPTY: z = "table contains no data"; break; + case SQLITE_SCHEMA: z = "database schema has changed"; break; + case SQLITE_TOOBIG: z = "String or BLOB exceeded size limit"; break; + case SQLITE_CONSTRAINT: z = "constraint failed"; break; + case SQLITE_MISMATCH: z = "datatype mismatch"; break; + case SQLITE_MISUSE: z = "library routine called out of sequence";break; + case SQLITE_NOLFS: z = "large file support is disabled"; break; + case SQLITE_AUTH: z = "authorization denied"; break; + case SQLITE_FORMAT: z = "auxiliary database format error"; break; + case SQLITE_RANGE: z = "bind or column index out of range"; break; + case SQLITE_NOTADB: z = "file is encrypted or is not a database";break; + default: z = "unknown error"; break; + } + return z; +} + +/* +** This routine implements a busy callback that sleeps and tries +** again until a timeout value is reached. The timeout value is +** an integer number of milliseconds passed in as the first +** argument. +*/ +static int sqliteDefaultBusyCallback( + void *ptr, /* Database connection */ + int count /* Number of times table has been busy */ +){ +#if SQLITE_OS_WIN || (defined(HAVE_USLEEP) && HAVE_USLEEP) + static const u8 delays[] = + { 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100 }; + static const u8 totals[] = + { 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228 }; +# define NDELAY (sizeof(delays)/sizeof(delays[0])) + sqlite3 *db = (sqlite3 *)ptr; + int timeout = db->busyTimeout; + int delay, prior; + + assert( count>=0 ); + if( count < NDELAY ){ + delay = delays[count]; + prior = totals[count]; + }else{ + delay = delays[NDELAY-1]; + prior = totals[NDELAY-1] + delay*(count-(NDELAY-1)); + } + if( prior + delay > timeout ){ + delay = timeout - prior; + if( delay<=0 ) return 0; + } + sqlite3OsSleep(db->pVfs, delay*1000); + return 1; +#else + sqlite3 *db = (sqlite3 *)ptr; + int timeout = ((sqlite3 *)ptr)->busyTimeout; + if( (count+1)*1000 > timeout ){ + return 0; + } + sqlite3OsSleep(db->pVfs, 1000000); + return 1; +#endif +} + +/* +** Invoke the given busy handler. +** +** This routine is called when an operation failed with a lock. +** If this routine returns non-zero, the lock is retried. If it +** returns 0, the operation aborts with an SQLITE_BUSY error. +*/ +int sqlite3InvokeBusyHandler(BusyHandler *p){ + int rc; + if( NEVER(p==0) || p->xFunc==0 || p->nBusy<0 ) return 0; + rc = p->xFunc(p->pArg, p->nBusy); + if( rc==0 ){ + p->nBusy = -1; + }else{ + p->nBusy++; + } + return rc; +} + +/* +** This routine sets the busy callback for an Sqlite database to the +** given callback function with the given argument. +*/ +int sqlite3_busy_handler( + sqlite3 *db, + int (*xBusy)(void*,int), + void *pArg +){ + sqlite3_mutex_enter(db->mutex); + db->busyHandler.xFunc = xBusy; + db->busyHandler.pArg = pArg; + db->busyHandler.nBusy = 0; + sqlite3_mutex_leave(db->mutex); + return SQLITE_OK; +} + +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK +/* +** This routine sets the progress callback for an Sqlite database to the +** given callback function with the given argument. The progress callback will +** be invoked every nOps opcodes. +*/ +void sqlite3_progress_handler( + sqlite3 *db, + int nOps, + int (*xProgress)(void*), + void *pArg +){ + sqlite3_mutex_enter(db->mutex); + if( nOps>0 ){ + db->xProgress = xProgress; + db->nProgressOps = nOps; + db->pProgressArg = pArg; + }else{ + db->xProgress = 0; + db->nProgressOps = 0; + db->pProgressArg = 0; + } + sqlite3_mutex_leave(db->mutex); +} +#endif + + +/* +** This routine installs a default busy handler that waits for the +** specified number of milliseconds before returning 0. +*/ +int sqlite3_busy_timeout(sqlite3 *db, int ms){ + if( ms>0 ){ + db->busyTimeout = ms; + sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db); + }else{ + sqlite3_busy_handler(db, 0, 0); + } + return SQLITE_OK; +} + +/* +** Cause any pending operation to stop at its earliest opportunity. +*/ +void sqlite3_interrupt(sqlite3 *db){ + db->u1.isInterrupted = 1; +} + + +/* +** 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 sqlite3CreateFunc( + sqlite3 *db, + const char *zFunctionName, + int nArg, + int enc, + void *pUserData, + void (*xFunc)(sqlite3_context*,int,sqlite3_value **), + void (*xStep)(sqlite3_context*,int,sqlite3_value **), + void (*xFinal)(sqlite3_context*) +){ + FuncDef *p; + int nName; + + assert( sqlite3_mutex_held(db->mutex) ); + if( zFunctionName==0 || + (xFunc && (xFinal || xStep)) || + (!xFunc && (xFinal && !xStep)) || + (!xFunc && (!xFinal && xStep)) || + (nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) || + (255<(nName = sqlite3Strlen(db, zFunctionName))) ){ + sqlite3Error(db, SQLITE_ERROR, "bad parameters"); + return SQLITE_ERROR; + } + +#ifndef SQLITE_OMIT_UTF16 + /* If SQLITE_UTF16 is specified as the encoding type, transform this + ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the + ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally. + ** + ** If SQLITE_ANY is specified, add three versions of the function + ** to the hash table. + */ + if( enc==SQLITE_UTF16 ){ + enc = SQLITE_UTF16NATIVE; + }else if( enc==SQLITE_ANY ){ + int rc; + rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8, + pUserData, xFunc, xStep, xFinal); + if( rc==SQLITE_OK ){ + rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE, + pUserData, xFunc, xStep, xFinal); + } + if( rc!=SQLITE_OK ){ + return rc; + } + enc = SQLITE_UTF16BE; + } +#else + enc = SQLITE_UTF8; +#endif + + /* Check if an existing function is being overridden or deleted. If so, + ** and there are active VMs, then return SQLITE_BUSY. If a function + ** is being overridden/deleted but there are no active VMs, allow the + ** operation to continue but invalidate all precompiled statements. + */ + p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 0); + if( p && p->iPrefEnc==enc && p->nArg==nArg ){ + if( db->activeVdbeCnt ){ + sqlite3Error(db, SQLITE_BUSY, + "Unable to delete/modify user-function due to active statements"); + assert( !db->mallocFailed ); + return SQLITE_BUSY; + }else{ + sqlite3ExpirePreparedStatements(db); + } + } + + p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 1); + assert(p || db->mallocFailed); + if( !p ){ + return SQLITE_NOMEM; + } + p->flags = 0; + p->xFunc = xFunc; + p->xStep = xStep; + p->xFinalize = xFinal; + p->pUserData = pUserData; + p->nArg = nArg; + 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; + sqlite3_mutex_enter(db->mutex); + rc = sqlite3CreateFunc(db, zFunctionName, nArg, enc, p, xFunc, xStep, xFinal); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; +} + +#ifndef SQLITE_OMIT_UTF16 +int sqlite3_create_function16( + sqlite3 *db, + const void *zFunctionName, + int nArg, + int eTextRep, + void *p, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*) +){ + int rc; + char *zFunc8; + sqlite3_mutex_enter(db->mutex); + assert( !db->mallocFailed ); + zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1); + rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xFunc, xStep, xFinal); + sqlite3DbFree(db, zFunc8); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; +} +#endif + + +/* +** Declare that a function has been overloaded by a virtual table. +** +** If the function already exists as a regular global function, then +** this routine is a no-op. If the function does not exist, then create +** a new one that always throws a run-time error. +** +** When virtual tables intend to provide an overloaded function, they +** should call this routine to make sure the global function exists. +** A global function must exist in order for name resolution to work +** properly. +*/ +int sqlite3_overload_function( + sqlite3 *db, + const char *zName, + int nArg +){ + int nName = sqlite3Strlen(db, zName); + int rc; + sqlite3_mutex_enter(db->mutex); + if( sqlite3FindFunction(db, zName, nName, nArg, SQLITE_UTF8, 0)==0 ){ + sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8, + 0, sqlite3InvalidFunction, 0, 0); + } + rc = sqlite3ApiExit(db, SQLITE_OK); + sqlite3_mutex_leave(db->mutex); + return rc; +} + +#ifndef SQLITE_OMIT_TRACE +/* +** Register a trace function. The pArg from the previously registered trace +** is returned. +** +** A NULL trace function means that no tracing is executes. A non-NULL +** trace is a pointer to a function that is invoked at the start of each +** SQL statement. +*/ +void *sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), void *pArg){ + void *pOld; + sqlite3_mutex_enter(db->mutex); + pOld = db->pTraceArg; + db->xTrace = xTrace; + db->pTraceArg = pArg; + sqlite3_mutex_leave(db->mutex); + return pOld; +} +/* +** Register a profile function. The pArg from the previously registered +** profile function is returned. +** +** A NULL profile function means that no profiling is executes. A non-NULL +** profile is a pointer to a function that is invoked at the conclusion of +** each SQL statement that is run. +*/ +void *sqlite3_profile( + sqlite3 *db, + void (*xProfile)(void*,const char*,sqlite_uint64), + void *pArg +){ + void *pOld; + sqlite3_mutex_enter(db->mutex); + pOld = db->pProfileArg; + db->xProfile = xProfile; + db->pProfileArg = pArg; + sqlite3_mutex_leave(db->mutex); + return pOld; +} +#endif /* SQLITE_OMIT_TRACE */ + +/*** EXPERIMENTAL *** +** +** Register a function to be invoked when a transaction comments. +** If the invoked function returns non-zero, then the commit becomes a +** rollback. +*/ +void *sqlite3_commit_hook( + sqlite3 *db, /* Attach the hook to this database */ + int (*xCallback)(void*), /* Function to invoke on each commit */ + void *pArg /* Argument to the function */ +){ + void *pOld; + sqlite3_mutex_enter(db->mutex); + pOld = db->pCommitArg; + db->xCommitCallback = xCallback; + db->pCommitArg = pArg; + sqlite3_mutex_leave(db->mutex); + 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; + sqlite3_mutex_enter(db->mutex); + pRet = db->pUpdateArg; + db->xUpdateCallback = xCallback; + db->pUpdateArg = pArg; + sqlite3_mutex_leave(db->mutex); + 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; + sqlite3_mutex_enter(db->mutex); + pRet = db->pRollbackArg; + db->xRollbackCallback = xCallback; + db->pRollbackArg = pArg; + sqlite3_mutex_leave(db->mutex); + return pRet; +} + +/* +** This routine is called to create a connection to a database BTree +** driver. If zFilename is the name of a file, then that file is +** opened and used. If zFilename is the magic name ":memory:" then +** the database is stored in memory (and is thus forgotten as soon as +** the connection is closed.) If zFilename is NULL then the database +** is a "virtual" database for transient use only and is deleted as +** soon as the connection is closed. +** +** A virtual database can be either a disk file (that is automatically +** deleted when the file is closed) or it an be held entirely in memory, +** depending on the values of the SQLITE_TEMP_STORE compile-time macro and the +** db->temp_store variable, according to the following chart: +** +** SQLITE_TEMP_STORE db->temp_store Location of temporary database +** ----------------- -------------- ------------------------------ +** 0 any file +** 1 1 file +** 1 2 memory +** 1 0 file +** 2 1 file +** 2 2 memory +** 2 0 memory +** 3 any memory +*/ +int sqlite3BtreeFactory( + const sqlite3 *db, /* Main database when opening aux otherwise 0 */ + const char *zFilename, /* Name of the file containing the BTree database */ + int omitJournal, /* if TRUE then do not journal this file */ + int nCache, /* How many pages in the page cache */ + int vfsFlags, /* Flags passed through to vfsOpen */ + Btree **ppBtree /* Pointer to new Btree object written here */ +){ + int btFlags = 0; + int rc; + + assert( sqlite3_mutex_held(db->mutex) ); + assert( ppBtree != 0); + if( omitJournal ){ + btFlags |= BTREE_OMIT_JOURNAL; + } + if( db->flags & SQLITE_NoReadlock ){ + btFlags |= BTREE_NO_READLOCK; + } + if( zFilename==0 ){ +#if SQLITE_TEMP_STORE==0 + /* Do nothing */ +#endif +#ifndef SQLITE_OMIT_MEMORYDB +#if SQLITE_TEMP_STORE==1 + if( db->temp_store==2 ) zFilename = ":memory:"; +#endif +#if SQLITE_TEMP_STORE==2 + if( db->temp_store!=1 ) zFilename = ":memory:"; +#endif +#if SQLITE_TEMP_STORE==3 + zFilename = ":memory:"; +#endif +#endif /* SQLITE_OMIT_MEMORYDB */ + } + + if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (zFilename==0 || *zFilename==0) ){ + vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB; + } + rc = sqlite3BtreeOpen(zFilename, (sqlite3 *)db, ppBtree, btFlags, vfsFlags); + + /* If the B-Tree was successfully opened, set the pager-cache size to the + ** default value. Except, if the call to BtreeOpen() returned a handle + ** open on an existing shared pager-cache, do not change the pager-cache + ** size. + */ + if( rc==SQLITE_OK && 0==sqlite3BtreeSchema(*ppBtree, 0, 0) ){ + sqlite3BtreeSetCacheSize(*ppBtree, nCache); + } + return rc; +} + +/* +** Return UTF-8 encoded English language explanation of the most recent +** error. +*/ +const char *sqlite3_errmsg(sqlite3 *db){ + const char *z; + if( !db ){ + return sqlite3ErrStr(SQLITE_NOMEM); + } + if( !sqlite3SafetyCheckSickOrOk(db) ){ + return sqlite3ErrStr(SQLITE_MISUSE); + } + sqlite3_mutex_enter(db->mutex); + assert( !db->mallocFailed ); + z = (char*)sqlite3_value_text(db->pErr); + assert( !db->mallocFailed ); + if( z==0 ){ + z = sqlite3ErrStr(db->errCode); + } + sqlite3_mutex_leave(db->mutex); + return z; +} + +#ifndef SQLITE_OMIT_UTF16 +/* +** Return UTF-16 encoded English language explanation of the most recent +** error. +*/ +const void *sqlite3_errmsg16(sqlite3 *db){ + /* Because all the characters in the string are in the unicode + ** range 0x00-0xFF, if we pad the big-endian string with a + ** zero byte, we can obtain the little-endian string with + ** &big_endian[1]. + */ + static const char outOfMemBe[] = { + 0, 'o', 0, 'u', 0, 't', 0, ' ', + 0, 'o', 0, 'f', 0, ' ', + 0, 'm', 0, 'e', 0, 'm', 0, 'o', 0, 'r', 0, 'y', 0, 0, 0 + }; + static const char misuseBe [] = { + 0, 'l', 0, 'i', 0, 'b', 0, 'r', 0, 'a', 0, 'r', 0, 'y', 0, ' ', + 0, 'r', 0, 'o', 0, 'u', 0, 't', 0, 'i', 0, 'n', 0, 'e', 0, ' ', + 0, 'c', 0, 'a', 0, 'l', 0, 'l', 0, 'e', 0, 'd', 0, ' ', + 0, 'o', 0, 'u', 0, 't', 0, ' ', + 0, 'o', 0, 'f', 0, ' ', + 0, 's', 0, 'e', 0, 'q', 0, 'u', 0, 'e', 0, 'n', 0, 'c', 0, 'e', 0, 0, 0 + }; + + const void *z; + if( !db ){ + return (void *)(&outOfMemBe[SQLITE_UTF16NATIVE==SQLITE_UTF16LE?1:0]); + } + if( !sqlite3SafetyCheckSickOrOk(db) ){ + return (void *)(&misuseBe[SQLITE_UTF16NATIVE==SQLITE_UTF16LE?1:0]); + } + sqlite3_mutex_enter(db->mutex); + assert( !db->mallocFailed ); + z = sqlite3_value_text16(db->pErr); + if( z==0 ){ + sqlite3ValueSetStr(db->pErr, -1, sqlite3ErrStr(db->errCode), + SQLITE_UTF8, SQLITE_STATIC); + z = sqlite3_value_text16(db->pErr); + } + /* A malloc() may have failed within the call to sqlite3_value_text16() + ** above. If this is the case, then the db->mallocFailed flag needs to + ** be cleared before returning. Do this directly, instead of via + ** sqlite3ApiExit(), to avoid setting the database handle error message. + */ + db->mallocFailed = 0; + sqlite3_mutex_leave(db->mutex); + return z; +} +#endif /* SQLITE_OMIT_UTF16 */ + +/* +** 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( db && !sqlite3SafetyCheckSickOrOk(db) ){ + return SQLITE_MISUSE; + } + if( !db || db->mallocFailed ){ + return SQLITE_NOMEM; + } + return db->errCode & db->errMask; +} + +/* +** Create a new collating function for database "db". The name is zName +** and the encoding is enc. +*/ +static int createCollation( + sqlite3* db, + const char *zName, + int enc, + void* pCtx, + int(*xCompare)(void*,int,const void*,int,const void*), + void(*xDel)(void*) +){ + CollSeq *pColl; + int enc2; + int nName; + + assert( sqlite3_mutex_held(db->mutex) ); + + /* 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. + */ + enc2 = enc & ~SQLITE_UTF16_ALIGNED; + if( enc2==SQLITE_UTF16 ){ + enc2 = SQLITE_UTF16NATIVE; + } + if( (enc2&~3)!=0 ){ + return SQLITE_MISUSE; + } + + /* 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. + */ + nName = sqlite3Strlen(db, zName); + pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, nName, 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); + + /* If collation sequence pColl was created directly by a call to + ** sqlite3_create_collation, and not generated by synthCollSeq(), + ** then any copies made by synthCollSeq() need to be invalidated. + ** Also, collation destructor - CollSeq.xDel() - function may need + ** to be called. + */ + if( (pColl->enc & ~SQLITE_UTF16_ALIGNED)==enc2 ){ + CollSeq *aColl = sqlite3HashFind(&db->aCollSeq, zName, nName); + int j; + for(j=0; j<3; j++){ + CollSeq *p = &aColl[j]; + if( p->enc==pColl->enc ){ + if( p->xDel ){ + p->xDel(p->pUser); + } + p->xCmp = 0; + } + } + } + } + + pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, nName, 1); + if( pColl ){ + pColl->xCmp = xCompare; + pColl->pUser = pCtx; + pColl->xDel = xDel; + pColl->enc = enc2 | (enc & SQLITE_UTF16_ALIGNED); + } + sqlite3Error(db, SQLITE_OK, 0); + return SQLITE_OK; +} + + +/* +** This array defines hard upper bounds on limit values. The +** initializer must be kept in sync with the SQLITE_LIMIT_* +** #defines in sqlite3.h. +*/ +static const int aHardLimit[] = { + SQLITE_MAX_LENGTH, + SQLITE_MAX_SQL_LENGTH, + SQLITE_MAX_COLUMN, + SQLITE_MAX_EXPR_DEPTH, + SQLITE_MAX_COMPOUND_SELECT, + SQLITE_MAX_VDBE_OP, + SQLITE_MAX_FUNCTION_ARG, + SQLITE_MAX_ATTACHED, + SQLITE_MAX_LIKE_PATTERN_LENGTH, + SQLITE_MAX_VARIABLE_NUMBER, +}; + +/* +** Make sure the hard limits are set to reasonable values +*/ +#if SQLITE_MAX_LENGTH<100 +# error SQLITE_MAX_LENGTH must be at least 100 +#endif +#if SQLITE_MAX_SQL_LENGTH<100 +# error SQLITE_MAX_SQL_LENGTH must be at least 100 +#endif +#if SQLITE_MAX_SQL_LENGTH>SQLITE_MAX_LENGTH +# error SQLITE_MAX_SQL_LENGTH must not be greater than SQLITE_MAX_LENGTH +#endif +#if SQLITE_MAX_COMPOUND_SELECT<2 +# error SQLITE_MAX_COMPOUND_SELECT must be at least 2 +#endif +#if SQLITE_MAX_VDBE_OP<40 +# error SQLITE_MAX_VDBE_OP must be at least 40 +#endif +#if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>127 +# error SQLITE_MAX_FUNCTION_ARG must be between 0 and 127 +#endif +#if SQLITE_MAX_ATTACH<0 || SQLITE_MAX_ATTACH>30 +# error SQLITE_MAX_ATTACH must be between 0 and 30 +#endif +#if SQLITE_MAX_LIKE_PATTERN_LENGTH<1 +# error SQLITE_MAX_LIKE_PATTERN_LENGTH must be at least 1 +#endif +#if SQLITE_MAX_VARIABLE_NUMBER<1 +# error SQLITE_MAX_VARIABLE_NUMBER must be at least 1 +#endif + + +/* +** Change the value of a limit. Report the old value. +** If an invalid limit index is supplied, report -1. +** Make no changes but still report the old value if the +** new limit is negative. +** +** A new lower limit does not shrink existing constructs. +** It merely prevents new constructs that exceed the limit +** from forming. +*/ +int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){ + int oldLimit; + if( limitId<0 || limitId>=SQLITE_N_LIMIT ){ + return -1; + } + oldLimit = db->aLimit[limitId]; + if( newLimit>=0 ){ + if( newLimit>aHardLimit[limitId] ){ + newLimit = aHardLimit[limitId]; + } + db->aLimit[limitId] = newLimit; + } + return oldLimit; +} + +/* +** This routine does the work of opening a database on behalf of +** sqlite3_open() and sqlite3_open16(). The database filename "zFilename" +** is UTF-8 encoded. +*/ +static int openDatabase( + const char *zFilename, /* Database filename UTF-8 encoded */ + sqlite3 **ppDb, /* OUT: Returned database handle */ + unsigned flags, /* Operational flags */ + const char *zVfs /* Name of the VFS to use */ +){ + sqlite3 *db; + int rc; + CollSeq *pColl; + int isThreadsafe = 1; + +#ifndef SQLITE_OMIT_AUTOINIT + rc = sqlite3_initialize(); + if( rc ) return rc; +#endif + + if( flags&SQLITE_OPEN_NOMUTEX ){ + isThreadsafe = 0; + } + + /* Remove harmful bits from the flags parameter */ + flags &= ~( SQLITE_OPEN_DELETEONCLOSE | + SQLITE_OPEN_MAIN_DB | + SQLITE_OPEN_TEMP_DB | + SQLITE_OPEN_TRANSIENT_DB | + SQLITE_OPEN_MAIN_JOURNAL | + SQLITE_OPEN_TEMP_JOURNAL | + SQLITE_OPEN_SUBJOURNAL | + SQLITE_OPEN_MASTER_JOURNAL | + SQLITE_OPEN_NOMUTEX + ); + + /* Allocate the sqlite data structure */ + db = sqlite3MallocZero( sizeof(sqlite3) ); + if( db==0 ) goto opendb_out; + if( sqlite3Config.bFullMutex && isThreadsafe ){ + db->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); + if( db->mutex==0 ){ + sqlite3_free(db); + db = 0; + goto opendb_out; + } + } + sqlite3_mutex_enter(db->mutex); + db->errMask = 0xff; + db->priorNewRowid = 0; + db->nDb = 2; + db->magic = SQLITE_MAGIC_BUSY; + db->aDb = db->aDbStatic; + + assert( sizeof(db->aLimit)==sizeof(aHardLimit) ); + memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit)); + db->autoCommit = 1; + db->nextAutovac = -1; + db->nextPagesize = 0; + db->flags |= SQLITE_ShortColNames +#if SQLITE_DEFAULT_FILE_FORMAT<4 + | SQLITE_LegacyFileFmt +#endif +#ifdef SQLITE_ENABLE_LOAD_EXTENSION + | SQLITE_LoadExtension +#endif + ; + sqlite3HashInit(&db->aFunc, SQLITE_HASH_STRING, 0); + sqlite3HashInit(&db->aCollSeq, SQLITE_HASH_STRING, 0); +#ifndef SQLITE_OMIT_VIRTUALTABLE + sqlite3HashInit(&db->aModule, SQLITE_HASH_STRING, 0); +#endif + + db->pVfs = sqlite3_vfs_find(zVfs); + if( !db->pVfs ){ + rc = SQLITE_ERROR; + db->magic = SQLITE_MAGIC_SICK; + sqlite3Error(db, rc, "no such vfs: %s", zVfs); + goto opendb_out; + } + + /* 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. + */ + createCollation(db, "BINARY", SQLITE_UTF8, 0, binCollFunc, 0); + createCollation(db, "BINARY", SQLITE_UTF16BE, 0, binCollFunc, 0); + createCollation(db, "BINARY", SQLITE_UTF16LE, 0, binCollFunc, 0); + createCollation(db, "RTRIM", SQLITE_UTF8, (void*)1, binCollFunc, 0); + if( db->mallocFailed ){ + db->magic = SQLITE_MAGIC_SICK; + goto opendb_out; + } + db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0); + assert( db->pDfltColl!=0 ); + + /* Also add a UTF-8 case-insensitive collation sequence. */ + createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc, 0); + + /* Set flags on the built-in collating sequences */ + db->pDfltColl->type = SQLITE_COLL_BINARY; + pColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "NOCASE", 6, 0); + if( pColl ){ + pColl->type = SQLITE_COLL_NOCASE; + } + + /* Open the backend database driver */ + db->openFlags = flags; + rc = sqlite3BtreeFactory(db, zFilename, 0, SQLITE_DEFAULT_CACHE_SIZE, + flags | SQLITE_OPEN_MAIN_DB, + &db->aDb[0].pBt); + if( rc!=SQLITE_OK ){ + sqlite3Error(db, rc, 0); + db->magic = SQLITE_MAGIC_SICK; + goto opendb_out; + } + db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt); + db->aDb[1].pSchema = sqlite3SchemaGet(db, 0); + + + /* The default safety_level for the main database is 'full'; for the temp + ** database it is 'NONE'. This matches the pager layer defaults. + */ + db->aDb[0].zName = "main"; + db->aDb[0].safety_level = 3; +#ifndef SQLITE_OMIT_TEMPDB + db->aDb[1].zName = "temp"; + db->aDb[1].safety_level = 1; +#endif + + db->magic = SQLITE_MAGIC_OPEN; + if( db->mallocFailed ){ + goto opendb_out; + } + + /* 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. + */ + sqlite3Error(db, SQLITE_OK, 0); + sqlite3RegisterBuiltinFunctions(db); + + /* Load automatic extensions - extensions that have been registered + ** using the sqlite3_automatic_extension() API. + */ + (void)sqlite3AutoLoadExtensions(db); + if( sqlite3_errcode(db)!=SQLITE_OK ){ + goto opendb_out; + } + +#ifdef SQLITE_ENABLE_FTS1 + if( !db->mallocFailed ){ + extern int sqlite3Fts1Init(sqlite3*); + rc = sqlite3Fts1Init(db); + } +#endif + +#ifdef SQLITE_ENABLE_FTS2 + if( !db->mallocFailed && rc==SQLITE_OK ){ + extern int sqlite3Fts2Init(sqlite3*); + rc = sqlite3Fts2Init(db); + } +#endif + +#ifdef SQLITE_ENABLE_FTS3 + if( !db->mallocFailed && rc==SQLITE_OK ){ + rc = sqlite3Fts3Init(db); + } +#endif + +#ifdef SQLITE_ENABLE_ICU + if( !db->mallocFailed && rc==SQLITE_OK ){ + extern int sqlite3IcuInit(sqlite3*); + rc = sqlite3IcuInit(db); + } +#endif + +#ifdef SQLITE_ENABLE_RTREE + if( !db->mallocFailed && rc==SQLITE_OK){ + rc = sqlite3RtreeInit(db); + } +#endif + + sqlite3Error(db, rc, 0); + + /* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking + ** mode. -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking + ** mode. Doing nothing at all also makes NORMAL the default. + */ +#ifdef SQLITE_DEFAULT_LOCKING_MODE + db->dfltLockMode = SQLITE_DEFAULT_LOCKING_MODE; + sqlite3PagerLockingMode(sqlite3BtreePager(db->aDb[0].pBt), + SQLITE_DEFAULT_LOCKING_MODE); +#endif + + /* Enable the lookaside-malloc subsystem */ + setupLookaside(db, 0, sqlite3Config.szLookaside, sqlite3Config.nLookaside); + +opendb_out: + if( db ){ + assert( db->mutex!=0 || isThreadsafe==0 || sqlite3Config.bFullMutex==0 ); + sqlite3_mutex_leave(db->mutex); + } + if( SQLITE_NOMEM==(rc = sqlite3_errcode(db)) ){ + sqlite3_close(db); + db = 0; + } + *ppDb = db; + return sqlite3ApiExit(0, rc); +} + +/* +** Open a new database handle. +*/ +int sqlite3_open( + const char *zFilename, + sqlite3 **ppDb +){ + return openDatabase(zFilename, ppDb, + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0); +} +int sqlite3_open_v2( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb, /* OUT: SQLite db handle */ + int flags, /* Flags */ + const char *zVfs /* Name of VFS module to use */ +){ + return openDatabase(filename, ppDb, flags, zVfs); +} + +#ifndef SQLITE_OMIT_UTF16 +/* +** Open a new database handle. +*/ +int sqlite3_open16( + const void *zFilename, + sqlite3 **ppDb +){ + char const *zFilename8; /* zFilename encoded in UTF-8 instead of UTF-16 */ + sqlite3_value *pVal; + int rc; + + assert( zFilename ); + assert( ppDb ); + *ppDb = 0; +#ifndef SQLITE_OMIT_AUTOINIT + rc = sqlite3_initialize(); + if( rc ) return rc; +#endif + pVal = sqlite3ValueNew(0); + sqlite3ValueSetStr(pVal, -1, zFilename, SQLITE_UTF16NATIVE, SQLITE_STATIC); + zFilename8 = sqlite3ValueText(pVal, SQLITE_UTF8); + if( zFilename8 ){ + rc = openDatabase(zFilename8, ppDb, + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0); + assert( *ppDb || rc==SQLITE_NOMEM ); + if( rc==SQLITE_OK && !DbHasProperty(*ppDb, 0, DB_SchemaLoaded) ){ + ENC(*ppDb) = SQLITE_UTF16NATIVE; + } + }else{ + rc = SQLITE_NOMEM; + } + sqlite3ValueFree(pVal); + + return sqlite3ApiExit(0, rc); +} +#endif /* SQLITE_OMIT_UTF16 */ + +/* +** Register a new collation sequence with the database handle db. +*/ +int sqlite3_create_collation( + sqlite3* db, + const char *zName, + int enc, + void* pCtx, + int(*xCompare)(void*,int,const void*,int,const void*) +){ + int rc; + sqlite3_mutex_enter(db->mutex); + assert( !db->mallocFailed ); + rc = createCollation(db, zName, enc, pCtx, xCompare, 0); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; +} + +/* +** Register a new collation sequence with the database handle db. +*/ +int sqlite3_create_collation_v2( + sqlite3* db, + const char *zName, + int enc, + void* pCtx, + int(*xCompare)(void*,int,const void*,int,const void*), + void(*xDel)(void*) +){ + int rc; + sqlite3_mutex_enter(db->mutex); + assert( !db->mallocFailed ); + rc = createCollation(db, zName, enc, pCtx, xCompare, xDel); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; +} + +#ifndef SQLITE_OMIT_UTF16 +/* +** Register a new collation sequence with the database handle db. +*/ +int sqlite3_create_collation16( + sqlite3* db, + const void *zName, + int enc, + void* pCtx, + int(*xCompare)(void*,int,const void*,int,const void*) +){ + int rc = SQLITE_OK; + char *zName8; + sqlite3_mutex_enter(db->mutex); + assert( !db->mallocFailed ); + zName8 = sqlite3Utf16to8(db, zName, -1); + if( zName8 ){ + rc = createCollation(db, zName8, enc, pCtx, xCompare, 0); + sqlite3DbFree(db, zName8); + } + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; +} +#endif /* SQLITE_OMIT_UTF16 */ + +/* +** Register a collation sequence factory callback with the database handle +** db. Replace any previously installed collation sequence factory. +*/ +int sqlite3_collation_needed( + sqlite3 *db, + void *pCollNeededArg, + void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*) +){ + sqlite3_mutex_enter(db->mutex); + db->xCollNeeded = xCollNeeded; + db->xCollNeeded16 = 0; + db->pCollNeededArg = pCollNeededArg; + sqlite3_mutex_leave(db->mutex); + return SQLITE_OK; +} + +#ifndef SQLITE_OMIT_UTF16 +/* +** Register a collation sequence factory callback with the database handle +** db. Replace any previously installed collation sequence factory. +*/ +int sqlite3_collation_needed16( + sqlite3 *db, + void *pCollNeededArg, + void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*) +){ + sqlite3_mutex_enter(db->mutex); + db->xCollNeeded = 0; + db->xCollNeeded16 = xCollNeeded16; + db->pCollNeededArg = pCollNeededArg; + sqlite3_mutex_leave(db->mutex); + return SQLITE_OK; +} +#endif /* SQLITE_OMIT_UTF16 */ + +#ifndef SQLITE_OMIT_GLOBALRECOVER +/* +** 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(void){ + return SQLITE_OK; +} +#endif + +/* +** Test to see whether or not the database connection is in autocommit +** mode. Return TRUE if it is and FALSE if not. Autocommit mode is on +** by default. Autocommit is disabled by a BEGIN statement and reenabled +** by the next COMMIT or ROLLBACK. +** +******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** +*/ +int sqlite3_get_autocommit(sqlite3 *db){ + return db->autoCommit; +} + +#ifdef SQLITE_DEBUG +/* +** The following routine is subtituted for constant SQLITE_CORRUPT in +** debugging builds. This provides a way to set a breakpoint for when +** corruption is first detected. +*/ +int sqlite3Corrupt(void){ + return SQLITE_CORRUPT; +} +#endif + +/* +** This is a convenience routine that makes sure that all thread-specific +** data for this thread has been deallocated. +** +** SQLite no longer uses thread-specific data so this routine is now a +** no-op. It is retained for historical compatibility. +*/ +void sqlite3_thread_cleanup(void){ +} + +/* +** Return meta information about a specific column of a database table. +** See comment in sqlite3.h (sqlite.h.in) for details. +*/ +#ifdef SQLITE_ENABLE_COLUMN_METADATA +int sqlite3_table_column_metadata( + sqlite3 *db, /* Connection handle */ + const char *zDbName, /* Database name or NULL */ + const char *zTableName, /* Table name */ + const char *zColumnName, /* Column name */ + char const **pzDataType, /* OUTPUT: Declared data type */ + char const **pzCollSeq, /* OUTPUT: Collation sequence name */ + int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ + int *pPrimaryKey, /* OUTPUT: True if column part of PK */ + int *pAutoinc /* OUTPUT: True if column is auto-increment */ +){ + int rc; + char *zErrMsg = 0; + Table *pTab = 0; + Column *pCol = 0; + int iCol; + + char const *zDataType = 0; + char const *zCollSeq = 0; + int notnull = 0; + int primarykey = 0; + int autoinc = 0; + + /* Ensure the database schema has been loaded */ + sqlite3_mutex_enter(db->mutex); + (void)sqlite3SafetyOn(db); + sqlite3BtreeEnterAll(db); + rc = sqlite3Init(db, &zErrMsg); + sqlite3BtreeLeaveAll(db); + if( SQLITE_OK!=rc ){ + goto error_out; + } + + /* Locate the table in question */ + pTab = sqlite3FindTable(db, zTableName, zDbName); + if( !pTab || pTab->pSelect ){ + pTab = 0; + goto error_out; + } + + /* Find the column for which info is requested */ + if( sqlite3IsRowid(zColumnName) ){ + iCol = pTab->iPKey; + if( iCol>=0 ){ + pCol = &pTab->aCol[iCol]; + } + }else{ + for(iCol=0; iCol<pTab->nCol; iCol++){ + pCol = &pTab->aCol[iCol]; + if( 0==sqlite3StrICmp(pCol->zName, zColumnName) ){ + break; + } + } + if( iCol==pTab->nCol ){ + pTab = 0; + goto error_out; + } + } + + /* The following block stores the meta information that will be returned + ** to the caller in local variables zDataType, zCollSeq, notnull, primarykey + ** and autoinc. At this point there are two possibilities: + ** + ** 1. The specified column name was rowid", "oid" or "_rowid_" + ** and there is no explicitly declared IPK column. + ** + ** 2. The table is not a view and the column name identified an + ** explicitly declared column. Copy meta information from *pCol. + */ + if( pCol ){ + zDataType = pCol->zType; + zCollSeq = pCol->zColl; + notnull = pCol->notNull!=0; + primarykey = pCol->isPrimKey!=0; + autoinc = pTab->iPKey==iCol && pTab->autoInc; + }else{ + zDataType = "INTEGER"; + primarykey = 1; + } + if( !zCollSeq ){ + zCollSeq = "BINARY"; + } + +error_out: + (void)sqlite3SafetyOff(db); + + /* Whether the function call succeeded or failed, set the output parameters + ** to whatever their local counterparts contain. If an error did occur, + ** this has the effect of zeroing all output parameters. + */ + if( pzDataType ) *pzDataType = zDataType; + if( pzCollSeq ) *pzCollSeq = zCollSeq; + if( pNotNull ) *pNotNull = notnull; + if( pPrimaryKey ) *pPrimaryKey = primarykey; + if( pAutoinc ) *pAutoinc = autoinc; + + if( SQLITE_OK==rc && !pTab ){ + sqlite3DbFree(db, zErrMsg); + zErrMsg = sqlite3MPrintf(db, "no such table column: %s.%s", zTableName, + zColumnName); + rc = SQLITE_ERROR; + } + sqlite3Error(db, rc, (zErrMsg?"%s":0), zErrMsg); + sqlite3DbFree(db, zErrMsg); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; +} +#endif + +/* +** Sleep for a little while. Return the amount of time slept. +*/ +int sqlite3_sleep(int ms){ + sqlite3_vfs *pVfs; + int rc; + pVfs = sqlite3_vfs_find(0); + if( pVfs==0 ) return 0; + + /* This function works in milliseconds, but the underlying OsSleep() + ** API uses microseconds. Hence the 1000's. + */ + rc = (sqlite3OsSleep(pVfs, 1000*ms)/1000); + return rc; +} + +/* +** Enable or disable the extended result codes. +*/ +int sqlite3_extended_result_codes(sqlite3 *db, int onoff){ + sqlite3_mutex_enter(db->mutex); + db->errMask = onoff ? 0xffffffff : 0xff; + sqlite3_mutex_leave(db->mutex); + return SQLITE_OK; +} + +/* +** Invoke the xFileControl method on a particular database. +*/ +int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ + int rc = SQLITE_ERROR; + int iDb; + sqlite3_mutex_enter(db->mutex); + if( zDbName==0 ){ + iDb = 0; + }else{ + for(iDb=0; iDb<db->nDb; iDb++){ + if( strcmp(db->aDb[iDb].zName, zDbName)==0 ) break; + } + } + if( iDb<db->nDb ){ + Btree *pBtree = db->aDb[iDb].pBt; + if( pBtree ){ + Pager *pPager; + sqlite3_file *fd; + sqlite3BtreeEnter(pBtree); + pPager = sqlite3BtreePager(pBtree); + assert( pPager!=0 ); + fd = sqlite3PagerFile(pPager); + assert( fd!=0 ); + if( fd->pMethods ){ + rc = sqlite3OsFileControl(fd, op, pArg); + } + sqlite3BtreeLeave(pBtree); + } + } + sqlite3_mutex_leave(db->mutex); + return rc; +} + +/* +** Interface to the testing logic. +*/ +int sqlite3_test_control(int op, ...){ + int rc = 0; +#ifndef SQLITE_OMIT_BUILTIN_TEST + va_list ap; + va_start(ap, op); + switch( op ){ + + /* + ** Save the current state of the PRNG. + */ + case SQLITE_TESTCTRL_PRNG_SAVE: { + sqlite3PrngSaveState(); + break; + } + + /* + ** Restore the state of the PRNG to the last state saved using + ** PRNG_SAVE. If PRNG_SAVE has never before been called, then + ** this verb acts like PRNG_RESET. + */ + case SQLITE_TESTCTRL_PRNG_RESTORE: { + sqlite3PrngRestoreState(); + break; + } + + /* + ** Reset the PRNG back to its uninitialized state. The next call + ** to sqlite3_randomness() will reseed the PRNG using a single call + ** to the xRandomness method of the default VFS. + */ + case SQLITE_TESTCTRL_PRNG_RESET: { + sqlite3PrngResetState(); + break; + } + + /* + ** sqlite3_test_control(BITVEC_TEST, size, program) + ** + ** Run a test against a Bitvec object of size. The program argument + ** is an array of integers that defines the test. Return -1 on a + ** memory allocation error, 0 on success, or non-zero for an error. + ** See the sqlite3BitvecBuiltinTest() for additional information. + */ + case SQLITE_TESTCTRL_BITVEC_TEST: { + int sz = va_arg(ap, int); + int *aProg = va_arg(ap, int*); + rc = sqlite3BitvecBuiltinTest(sz, aProg); + break; + } + + /* + ** sqlite3_test_control(BENIGN_MALLOC_HOOKS, xBegin, xEnd) + ** + ** Register hooks to call to indicate which malloc() failures + ** are benign. + */ + case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: { + typedef void (*void_function)(void); + void_function xBenignBegin; + void_function xBenignEnd; + xBenignBegin = va_arg(ap, void_function); + xBenignEnd = va_arg(ap, void_function); + sqlite3BenignMallocHooks(xBenignBegin, xBenignEnd); + break; + } + } + va_end(ap); +#endif /* SQLITE_OMIT_BUILTIN_TEST */ + return rc; +} diff --git a/third_party/sqlite/src/malloc.c b/third_party/sqlite/src/malloc.c new file mode 100755 index 0000000..fa9c88f --- /dev/null +++ b/third_party/sqlite/src/malloc.c @@ -0,0 +1,742 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** Memory allocation functions used throughout sqlite. +** +** $Id: malloc.c,v 1.34 2008/08/05 17:53:23 drh Exp $ +*/ +#include "sqliteInt.h" +#include <stdarg.h> +#include <ctype.h> + +/* +** This routine runs when the memory allocator sees that the +** total memory allocation is about to exceed the soft heap +** limit. +*/ +static void softHeapLimitEnforcer( + void *NotUsed, + sqlite3_int64 inUse, + int allocSize +){ + sqlite3_release_memory(allocSize); +} + +/* +** Set the soft heap-size limit for the library. Passing a zero or +** negative value indicates no limit. +*/ +void sqlite3_soft_heap_limit(int n){ + sqlite3_uint64 iLimit; + int overage; + if( n<0 ){ + iLimit = 0; + }else{ + iLimit = n; + } + sqlite3_initialize(); + if( iLimit>0 ){ + sqlite3_memory_alarm(softHeapLimitEnforcer, 0, iLimit); + }else{ + sqlite3_memory_alarm(0, 0, 0); + } + overage = sqlite3_memory_used() - n; + if( overage>0 ){ + sqlite3_release_memory(overage); + } +} + +/* +** Attempt to release up to n bytes of non-essential memory currently +** held by SQLite. An example of non-essential memory is memory used to +** cache database pages that are not currently in use. +*/ +int sqlite3_release_memory(int n){ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + int nRet = sqlite3VdbeReleaseMemory(n); + nRet += sqlite3PagerReleaseMemory(n-nRet); + return nRet; +#else + return SQLITE_OK; +#endif +} + +/* +** State information local to the memory allocation subsystem. +*/ +static struct { + sqlite3_mutex *mutex; /* Mutex to serialize access */ + + /* + ** The alarm callback and its arguments. The mem0.mutex lock will + ** be held while the callback is running. Recursive calls into + ** the memory subsystem are allowed, but no new callbacks will be + ** issued. The alarmBusy variable is set to prevent recursive + ** callbacks. + */ + sqlite3_int64 alarmThreshold; + void (*alarmCallback)(void*, sqlite3_int64,int); + void *alarmArg; + int alarmBusy; + + /* + ** Pointers to the end of sqlite3Config.pScratch and + ** sqlite3Config.pPage to a block of memory that records + ** which pages are available. + */ + u32 *aScratchFree; + u32 *aPageFree; + + /* Number of free pages for scratch and page-cache memory */ + u32 nScratchFree; + u32 nPageFree; +} mem0; + +/* +** Initialize the memory allocation subsystem. +*/ +int sqlite3MallocInit(void){ + if( sqlite3Config.m.xMalloc==0 ){ + sqlite3MemSetDefault(); + } + memset(&mem0, 0, sizeof(mem0)); + if( sqlite3Config.bCoreMutex ){ + mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); + } + if( sqlite3Config.pScratch && sqlite3Config.szScratch>=100 + && sqlite3Config.nScratch>=0 ){ + int i; + sqlite3Config.szScratch -= 4; + mem0.aScratchFree = (u32*)&((char*)sqlite3Config.pScratch) + [sqlite3Config.szScratch*sqlite3Config.nScratch]; + for(i=0; i<sqlite3Config.nScratch; i++){ mem0.aScratchFree[i] = i; } + mem0.nScratchFree = sqlite3Config.nScratch; + }else{ + sqlite3Config.pScratch = 0; + sqlite3Config.szScratch = 0; + } + if( sqlite3Config.pPage && sqlite3Config.szPage>=512 + && sqlite3Config.nPage>=1 ){ + int i; + int overhead; + int sz = sqlite3Config.szPage; + int n = sqlite3Config.nPage; + overhead = (4*n + sz - 1)/sz; + sqlite3Config.nPage -= overhead; + mem0.aPageFree = (u32*)&((char*)sqlite3Config.pPage) + [sqlite3Config.szPage*sqlite3Config.nPage]; + for(i=0; i<sqlite3Config.nPage; i++){ mem0.aPageFree[i] = i; } + mem0.nPageFree = sqlite3Config.nPage; + }else{ + sqlite3Config.pPage = 0; + sqlite3Config.szPage = 0; + } + return sqlite3Config.m.xInit(sqlite3Config.m.pAppData); +} + +/* +** Deinitialize the memory allocation subsystem. +*/ +void sqlite3MallocEnd(void){ + sqlite3Config.m.xShutdown(sqlite3Config.m.pAppData); + memset(&mem0, 0, sizeof(mem0)); +} + +/* +** Return the amount of memory currently checked out. +*/ +sqlite3_int64 sqlite3_memory_used(void){ + int n, mx; + sqlite3_int64 res; + sqlite3_status(SQLITE_STATUS_MEMORY_USED, &n, &mx, 0); + res = (sqlite3_int64)n; /* Work around bug in Borland C. Ticket #3216 */ + return res; +} + +/* +** Return the maximum amount of memory that has ever been +** checked out since either the beginning of this process +** or since the most recent reset. +*/ +sqlite3_int64 sqlite3_memory_highwater(int resetFlag){ + int n, mx; + sqlite3_int64 res; + sqlite3_status(SQLITE_STATUS_MEMORY_USED, &n, &mx, resetFlag); + res = (sqlite3_int64)mx; /* Work around bug in Borland C. Ticket #3216 */ + return res; +} + +/* +** Change the alarm callback +*/ +int sqlite3_memory_alarm( + void(*xCallback)(void *pArg, sqlite3_int64 used,int N), + void *pArg, + sqlite3_int64 iThreshold +){ + sqlite3_mutex_enter(mem0.mutex); + mem0.alarmCallback = xCallback; + mem0.alarmArg = pArg; + mem0.alarmThreshold = iThreshold; + sqlite3_mutex_leave(mem0.mutex); + return SQLITE_OK; +} + +/* +** Trigger the alarm +*/ +static void sqlite3MallocAlarm(int nByte){ + void (*xCallback)(void*,sqlite3_int64,int); + sqlite3_int64 nowUsed; + void *pArg; + if( mem0.alarmCallback==0 || mem0.alarmBusy ) return; + mem0.alarmBusy = 1; + xCallback = mem0.alarmCallback; + nowUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); + pArg = mem0.alarmArg; + sqlite3_mutex_leave(mem0.mutex); + xCallback(pArg, nowUsed, nByte); + sqlite3_mutex_enter(mem0.mutex); + mem0.alarmBusy = 0; +} + +/* +** Do a memory allocation with statistics and alarms. Assume the +** lock is already held. +*/ +static int mallocWithAlarm(int n, void **pp){ + int nFull; + void *p; + assert( sqlite3_mutex_held(mem0.mutex) ); + nFull = sqlite3Config.m.xRoundup(n); + sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n); + if( mem0.alarmCallback!=0 ){ + int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); + if( nUsed+nFull >= mem0.alarmThreshold ){ + sqlite3MallocAlarm(nFull); + } + } + p = sqlite3Config.m.xMalloc(nFull); + if( p==0 && mem0.alarmCallback ){ + sqlite3MallocAlarm(nFull); + p = sqlite3Config.m.xMalloc(nFull); + } + if( p ){ + nFull = sqlite3MallocSize(p); + sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull); + } + *pp = p; + return nFull; +} + +/* +** Allocate memory. This routine is like sqlite3_malloc() except that it +** assumes the memory subsystem has already been initialized. +*/ +void *sqlite3Malloc(int n){ + void *p; + if( n<=0 ){ + p = 0; + }else if( sqlite3Config.bMemstat ){ + sqlite3_mutex_enter(mem0.mutex); + mallocWithAlarm(n, &p); + sqlite3_mutex_leave(mem0.mutex); + }else{ + p = sqlite3Config.m.xMalloc(n); + } + return p; +} + +/* +** This version of the memory allocation is for use by the application. +** First make sure the memory subsystem is initialized, then do the +** allocation. +*/ +void *sqlite3_malloc(int n){ +#ifndef SQLITE_OMIT_AUTOINIT + if( sqlite3_initialize() ) return 0; +#endif + return sqlite3Malloc(n); +} + +/* +** Each thread may only have a single outstanding allocation from +** xScratchMalloc(). We verify this constraint in the single-threaded +** case by setting scratchAllocOut to 1 when an allocation +** is outstanding clearing it when the allocation is freed. +*/ +#if SQLITE_THREADSAFE==0 && !defined(NDEBUG) +static int scratchAllocOut = 0; +#endif + + +/* +** Allocate memory that is to be used and released right away. +** This routine is similar to alloca() in that it is not intended +** for situations where the memory might be held long-term. This +** routine is intended to get memory to old large transient data +** structures that would not normally fit on the stack of an +** embedded processor. +*/ +void *sqlite3ScratchMalloc(int n){ + void *p; + assert( n>0 ); + +#if SQLITE_THREADSAFE==0 && !defined(NDEBUG) + /* Verify that no more than one scratch allocation per thread + ** is outstanding at one time. (This is only checked in the + ** single-threaded case since checking in the multi-threaded case + ** would be much more complicated.) */ + assert( scratchAllocOut==0 ); +#endif + + if( sqlite3Config.szScratch<n ){ + goto scratch_overflow; + }else{ + sqlite3_mutex_enter(mem0.mutex); + if( mem0.nScratchFree==0 ){ + sqlite3_mutex_leave(mem0.mutex); + goto scratch_overflow; + }else{ + int i; + i = mem0.aScratchFree[--mem0.nScratchFree]; + sqlite3_mutex_leave(mem0.mutex); + i *= sqlite3Config.szScratch; + sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1); + sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n); + p = (void*)&((char*)sqlite3Config.pScratch)[i]; + } + } +#if SQLITE_THREADSAFE==0 && !defined(NDEBUG) + scratchAllocOut = p!=0; +#endif + + return p; + +scratch_overflow: + if( sqlite3Config.bMemstat ){ + sqlite3_mutex_enter(mem0.mutex); + sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n); + n = mallocWithAlarm(n, &p); + if( p ) sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n); + sqlite3_mutex_leave(mem0.mutex); + }else{ + p = sqlite3Config.m.xMalloc(n); + } +#if SQLITE_THREADSAFE==0 && !defined(NDEBUG) + scratchAllocOut = p!=0; +#endif + return p; +} +void sqlite3ScratchFree(void *p){ + if( p ){ + +#if SQLITE_THREADSAFE==0 && !defined(NDEBUG) + /* Verify that no more than one scratch allocation per thread + ** is outstanding at one time. (This is only checked in the + ** single-threaded case since checking in the multi-threaded case + ** would be much more complicated.) */ + assert( scratchAllocOut==1 ); + scratchAllocOut = 0; +#endif + + if( sqlite3Config.pScratch==0 + || p<sqlite3Config.pScratch + || p>=(void*)mem0.aScratchFree ){ + if( sqlite3Config.bMemstat ){ + int iSize = sqlite3MallocSize(p); + sqlite3_mutex_enter(mem0.mutex); + sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, -iSize); + sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -iSize); + sqlite3Config.m.xFree(p); + sqlite3_mutex_leave(mem0.mutex); + }else{ + sqlite3Config.m.xFree(p); + } + }else{ + int i; + i = (u8 *)p - (u8 *)sqlite3Config.pScratch; + i /= sqlite3Config.szScratch; + assert( i>=0 && i<sqlite3Config.nScratch ); + sqlite3_mutex_enter(mem0.mutex); + assert( mem0.nScratchFree<sqlite3Config.nScratch ); + mem0.aScratchFree[mem0.nScratchFree++] = i; + sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, -1); + sqlite3_mutex_leave(mem0.mutex); + } + } +} + +/* +** Allocate memory to be used by the page cache. Make use of the +** memory buffer provided by SQLITE_CONFIG_PAGECACHE if there is one +** and that memory is of the right size and is not completely +** consumed. Otherwise, failover to sqlite3Malloc(). +*/ +void *sqlite3PageMalloc(int n){ + void *p; + assert( n>0 ); + assert( (n & (n-1))==0 ); + assert( n>=512 && n<=32768 ); + + if( sqlite3Config.szPage<n ){ + goto page_overflow; + }else{ + sqlite3_mutex_enter(mem0.mutex); + if( mem0.nPageFree==0 ){ + sqlite3_mutex_leave(mem0.mutex); + goto page_overflow; + }else{ + int i; + i = mem0.aPageFree[--mem0.nPageFree]; + sqlite3_mutex_leave(mem0.mutex); + i *= sqlite3Config.szPage; + sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, n); + sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1); + p = (void*)&((char*)sqlite3Config.pPage)[i]; + } + } + return p; + +page_overflow: + if( sqlite3Config.bMemstat ){ + sqlite3_mutex_enter(mem0.mutex); + sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, n); + n = mallocWithAlarm(n, &p); + if( p ) sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, n); + sqlite3_mutex_leave(mem0.mutex); + }else{ + p = sqlite3Config.m.xMalloc(n); + } + return p; +} +void sqlite3PageFree(void *p){ + if( p ){ + if( sqlite3Config.pPage==0 + || p<sqlite3Config.pPage + || p>=(void*)mem0.aPageFree ){ + /* In this case, the page allocation was obtained from a regular + ** call to sqlite3_mem_methods.xMalloc() (a page-cache-memory + ** "overflow"). Free the block with sqlite3_mem_methods.xFree(). + */ + if( sqlite3Config.bMemstat ){ + int iSize = sqlite3MallocSize(p); + sqlite3_mutex_enter(mem0.mutex); + sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -iSize); + sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -iSize); + sqlite3Config.m.xFree(p); + sqlite3_mutex_leave(mem0.mutex); + }else{ + sqlite3Config.m.xFree(p); + } + }else{ + /* The page allocation was allocated from the sqlite3Config.pPage + ** buffer. In this case all that is add the index of the page in + ** the sqlite3Config.pPage array to the set of free indexes stored + ** in the mem0.aPageFree[] array. + */ + int i; + i = (u8 *)p - (u8 *)sqlite3Config.pPage; + i /= sqlite3Config.szPage; + assert( i>=0 && i<sqlite3Config.nPage ); + sqlite3_mutex_enter(mem0.mutex); + assert( mem0.nPageFree<sqlite3Config.nPage ); + mem0.aPageFree[mem0.nPageFree++] = i; + sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1); + sqlite3_mutex_leave(mem0.mutex); +#if !defined(NDEBUG) && 0 + /* Assert that a duplicate was not just inserted into aPageFree[]. */ + for(i=0; i<mem0.nPageFree-1; i++){ + assert( mem0.aPageFree[i]!=mem0.aPageFree[mem0.nPageFree-1] ); + } +#endif + } + } +} + +/* +** TRUE if p is a lookaside memory allocation from db +*/ +static int isLookaside(sqlite3 *db, void *p){ + return db && p && p>=db->lookaside.pStart && p<db->lookaside.pEnd; +} + +/* +** Return the size of a memory allocation previously obtained from +** sqlite3Malloc() or sqlite3_malloc(). +*/ +int sqlite3MallocSize(void *p){ + return sqlite3Config.m.xSize(p); +} +int sqlite3DbMallocSize(sqlite3 *db, void *p){ + if( isLookaside(db, p) ){ + return db->lookaside.sz; + }else{ + return sqlite3Config.m.xSize(p); + } +} + +/* +** Free memory previously obtained from sqlite3Malloc(). +*/ +void sqlite3_free(void *p){ + if( p==0 ) return; + if( sqlite3Config.bMemstat ){ + sqlite3_mutex_enter(mem0.mutex); + sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p)); + sqlite3Config.m.xFree(p); + sqlite3_mutex_leave(mem0.mutex); + }else{ + sqlite3Config.m.xFree(p); + } +} + +/* +** Free memory that might be associated with a particular database +** connection. +*/ +void sqlite3DbFree(sqlite3 *db, void *p){ + if( isLookaside(db, p) ){ + LookasideSlot *pBuf = (LookasideSlot*)p; + pBuf->pNext = db->lookaside.pFree; + db->lookaside.pFree = pBuf; + db->lookaside.nOut--; + }else{ + sqlite3_free(p); + } +} + +/* +** Change the size of an existing memory allocation +*/ +void *sqlite3Realloc(void *pOld, int nBytes){ + int nOld, nNew; + void *pNew; + if( pOld==0 ){ + return sqlite3Malloc(nBytes); + } + if( nBytes<=0 ){ + sqlite3_free(pOld); + return 0; + } + nOld = sqlite3MallocSize(pOld); + if( sqlite3Config.bMemstat ){ + sqlite3_mutex_enter(mem0.mutex); + sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, nBytes); + nNew = sqlite3Config.m.xRoundup(nBytes); + if( nOld==nNew ){ + pNew = pOld; + }else{ + if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)+nNew-nOld >= + mem0.alarmThreshold ){ + sqlite3MallocAlarm(nNew-nOld); + } + pNew = sqlite3Config.m.xRealloc(pOld, nNew); + if( pNew==0 && mem0.alarmCallback ){ + sqlite3MallocAlarm(nBytes); + pNew = sqlite3Config.m.xRealloc(pOld, nNew); + } + if( pNew ){ + nNew = sqlite3MallocSize(pNew); + sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nNew-nOld); + } + } + sqlite3_mutex_leave(mem0.mutex); + }else{ + pNew = sqlite3Config.m.xRealloc(pOld, nBytes); + } + return pNew; +} + +/* +** The public interface to sqlite3Realloc. Make sure that the memory +** subsystem is initialized prior to invoking sqliteRealloc. +*/ +void *sqlite3_realloc(void *pOld, int n){ +#ifndef SQLITE_OMIT_AUTOINIT + if( sqlite3_initialize() ) return 0; +#endif + return sqlite3Realloc(pOld, n); +} + + +/* +** Allocate and zero memory. +*/ +void *sqlite3MallocZero(int n){ + void *p = sqlite3Malloc(n); + if( p ){ + memset(p, 0, n); + } + return p; +} + +/* +** Allocate and zero memory. If the allocation fails, make +** the mallocFailed flag in the connection pointer. +*/ +void *sqlite3DbMallocZero(sqlite3 *db, int n){ + void *p = sqlite3DbMallocRaw(db, n); + if( p ){ + memset(p, 0, n); + } + return p; +} + +/* +** Allocate and zero memory. If the allocation fails, make +** the mallocFailed flag in the connection pointer. +*/ +void *sqlite3DbMallocRaw(sqlite3 *db, int n){ + void *p; + if( db ){ + LookasideSlot *pBuf; + if( db->mallocFailed ){ + return 0; + } + if( db->lookaside.bEnabled && n<=db->lookaside.sz + && (pBuf = db->lookaside.pFree)!=0 ){ + db->lookaside.pFree = pBuf->pNext; + db->lookaside.nOut++; + if( db->lookaside.nOut>db->lookaside.mxOut ){ + db->lookaside.mxOut = db->lookaside.nOut; + } + return (void*)pBuf; + } + } + p = sqlite3Malloc(n); + if( !p && db ){ + db->mallocFailed = 1; + } + return p; +} + +/* +** Resize the block of memory pointed to by p to n bytes. If the +** resize fails, set the mallocFailed flag in the connection object. +*/ +void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){ + void *pNew = 0; + if( db->mallocFailed==0 ){ + if( p==0 ){ + return sqlite3DbMallocRaw(db, n); + } + if( isLookaside(db, p) ){ + if( n<=db->lookaside.sz ){ + return p; + } + pNew = sqlite3DbMallocRaw(db, n); + if( pNew ){ + memcpy(pNew, p, db->lookaside.sz); + sqlite3DbFree(db, p); + } + }else{ + pNew = sqlite3_realloc(p, n); + if( !pNew ){ + db->mallocFailed = 1; + } + } + } + return pNew; +} + +/* +** Attempt to reallocate p. If the reallocation fails, then free p +** and set the mallocFailed flag in the database connection. +*/ +void *sqlite3DbReallocOrFree(sqlite3 *db, void *p, int n){ + void *pNew; + pNew = sqlite3DbRealloc(db, p, n); + if( !pNew ){ + sqlite3DbFree(db, p); + } + return pNew; +} + +/* +** Make a copy of a string in memory obtained from sqliteMalloc(). These +** functions call sqlite3MallocRaw() directly instead of sqliteMalloc(). This +** is because when memory debugging is turned on, these two functions are +** called via macros that record the current file and line number in the +** ThreadData structure. +*/ +char *sqlite3DbStrDup(sqlite3 *db, const char *z){ + char *zNew; + size_t n; + if( z==0 ){ + return 0; + } + n = strlen(z)+1; + assert( (n&0x7fffffff)==n ); + zNew = sqlite3DbMallocRaw(db, (int)n); + if( zNew ){ + memcpy(zNew, z, n); + } + return zNew; +} +char *sqlite3DbStrNDup(sqlite3 *db, const char *z, int n){ + char *zNew; + if( z==0 ){ + return 0; + } + assert( (n&0x7fffffff)==n ); + zNew = sqlite3DbMallocRaw(db, n+1); + if( zNew ){ + memcpy(zNew, z, n); + zNew[n] = 0; + } + return zNew; +} + +/* +** Create a string from the zFromat argument and the va_list that follows. +** Store the string in memory obtained from sqliteMalloc() and make *pz +** point to that string. +*/ +void sqlite3SetString(char **pz, sqlite3 *db, const char *zFormat, ...){ + va_list ap; + char *z; + + va_start(ap, zFormat); + z = sqlite3VMPrintf(db, zFormat, ap); + va_end(ap); + sqlite3DbFree(db, *pz); + *pz = z; +} + + +/* +** This function must be called before exiting any API function (i.e. +** returning control to the user) that has called sqlite3_malloc or +** sqlite3_realloc. +** +** The returned value is normally a copy of the second argument to this +** function. However, if a malloc() failure has occured since the previous +** invocation SQLITE_NOMEM is returned instead. +** +** If the first argument, db, is not NULL and a malloc() error has occured, +** then the connection error-code (the value returned by sqlite3_errcode()) +** is set to SQLITE_NOMEM. +*/ +int sqlite3ApiExit(sqlite3* db, int rc){ + /* If the db handle is not NULL, then we must hold the connection handle + ** mutex here. Otherwise the read (and possible write) of db->mallocFailed + ** is unsafe, as is the call to sqlite3Error(). + */ + assert( !db || sqlite3_mutex_held(db->mutex) ); + if( db && db->mallocFailed ){ + sqlite3Error(db, SQLITE_NOMEM, 0); + db->mallocFailed = 0; + rc = SQLITE_NOMEM; + } + return rc & (db ? db->errMask : 0xff); +} diff --git a/third_party/sqlite/src/md5.c b/third_party/sqlite/src/md5.c new file mode 100755 index 0000000..a6b9abb --- /dev/null +++ b/third_party/sqlite/src/md5.c @@ -0,0 +1,389 @@ +/* +** SQLite uses this code for testing only. It is not a part of +** the SQLite library. This file implements two new TCL commands +** "md5" and "md5file" that compute md5 checksums on arbitrary text +** and on complete files. These commands are used by the "testfixture" +** program to help verify the correct operation of the SQLite library. +** +** The original use of these TCL commands was to test the ROLLBACK +** feature of SQLite. First compute the MD5-checksum of the database. +** Then make some changes but rollback the changes rather than commit +** them. Compute a second MD5-checksum of the file and verify that the +** two checksums are the same. Such is the original use of this code. +** New uses may have been added since this comment was written. +** +** $Id: md5.c,v 1.17 2008/05/16 04:51:55 danielk1977 Exp $ +*/ +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ +#include <tcl.h> +#include <string.h> +#include "sqlite3.h" + +/* + * If compiled on a machine that doesn't have a 32-bit integer, + * you just set "uint32" to the appropriate datatype for an + * unsigned 32-bit integer. For example: + * + * cc -Duint32='unsigned long' md5.c + * + */ +#ifndef uint32 +# define uint32 unsigned int +#endif + +struct Context { + uint32 buf[4]; + uint32 bits[2]; + unsigned char in[64]; +}; +typedef char MD5Context[88]; + +/* + * Note: this code is harmless on little-endian machines. + */ +static void byteReverse (unsigned char *buf, unsigned longs){ + uint32 t; + do { + t = (uint32)((unsigned)buf[3]<<8 | buf[2]) << 16 | + ((unsigned)buf[1]<<8 | buf[0]); + *(uint32 *)buf = t; + buf += 4; + } while (--longs); +} +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +static void MD5Transform(uint32 buf[4], const uint32 in[16]){ + register uint32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +static void MD5Init(MD5Context *pCtx){ + struct Context *ctx = (struct Context *)pCtx; + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +static +void MD5Update(MD5Context *pCtx, const unsigned char *buf, unsigned int len){ + struct Context *ctx = (struct Context *)pCtx; + uint32 t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((uint32)len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if ( t ) { + unsigned char *p = (unsigned char *)ctx->in + t; + + t = 64-t; + if (len < t) { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *)ctx->in); + buf += t; + len -= t; + } + + /* Process data in 64-byte chunks */ + + while (len >= 64) { + memcpy(ctx->in, buf, 64); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *)ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memcpy(ctx->in, buf, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +static void MD5Final(unsigned char digest[16], MD5Context *pCtx){ + struct Context *ctx = (struct Context *)pCtx; + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *)ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset(p, 0, count-8); + } + byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + ((uint32 *)ctx->in)[ 14 ] = ctx->bits[0]; + ((uint32 *)ctx->in)[ 15 ] = ctx->bits[1]; + + MD5Transform(ctx->buf, (uint32 *)ctx->in); + byteReverse((unsigned char *)ctx->buf, 4); + memcpy(digest, ctx->buf, 16); + memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ +} + +/* +** Convert a digest into base-16. digest should be declared as +** "unsigned char digest[16]" in the calling function. The MD5 +** digest is stored in the first 16 bytes. zBuf should +** be "char zBuf[33]". +*/ +static void DigestToBase16(unsigned char *digest, char *zBuf){ + static char const zEncode[] = "0123456789abcdef"; + int i, j; + + for(j=i=0; i<16; i++){ + int a = digest[i]; + zBuf[j++] = zEncode[(a>>4)&0xf]; + zBuf[j++] = zEncode[a & 0xf]; + } + zBuf[j] = 0; +} + +/* +** A TCL command for md5. The argument is the text to be hashed. The +** Result is the hash in base64. +*/ +static int md5_cmd(void*cd, Tcl_Interp *interp, int argc, const char **argv){ + MD5Context ctx; + unsigned char digest[16]; + + if( argc!=2 ){ + Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0], + " TEXT\"", 0); + return TCL_ERROR; + } + MD5Init(&ctx); + MD5Update(&ctx, (unsigned char*)argv[1], (unsigned)strlen(argv[1])); + MD5Final(digest, &ctx); + DigestToBase16(digest, interp->result); + return TCL_OK; +} + +/* +** A TCL command to take the md5 hash of a file. The argument is the +** name of the file. +*/ +static int md5file_cmd(void*cd, Tcl_Interp*interp, int argc, const char **argv){ + FILE *in; + MD5Context ctx; + unsigned char digest[16]; + char zBuf[10240]; + + if( argc!=2 ){ + Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0], + " FILENAME\"", 0); + return TCL_ERROR; + } + in = fopen(argv[1],"rb"); + if( in==0 ){ + Tcl_AppendResult(interp,"unable to open file \"", argv[1], + "\" for reading", 0); + return TCL_ERROR; + } + MD5Init(&ctx); + for(;;){ + int n; + n = fread(zBuf, 1, sizeof(zBuf), in); + if( n<=0 ) break; + MD5Update(&ctx, (unsigned char*)zBuf, (unsigned)n); + } + fclose(in); + MD5Final(digest, &ctx); + DigestToBase16(digest, interp->result); + return TCL_OK; +} + +/* +** Register the two TCL commands above with the TCL interpreter. +*/ +int Md5_Init(Tcl_Interp *interp){ + Tcl_CreateCommand(interp, "md5", (Tcl_CmdProc*)md5_cmd, 0, 0); + Tcl_CreateCommand(interp, "md5file", (Tcl_CmdProc*)md5file_cmd, 0, 0); + return TCL_OK; +} + +/* +** During testing, the special md5sum() aggregate function is available. +** inside SQLite. The following routines implement that function. +*/ +static void md5step(sqlite3_context *context, int argc, sqlite3_value **argv){ + MD5Context *p; + int i; + if( argc<1 ) return; + p = sqlite3_aggregate_context(context, sizeof(*p)); + if( p==0 ) return; + if( sqlite3_aggregate_count(context)==1 ){ + MD5Init(p); + } + for(i=0; i<argc; i++){ + const char *zData = (char*)sqlite3_value_text(argv[i]); + if( zData ){ + MD5Update(p, (unsigned char*)zData, strlen(zData)); + } + } +} +static void md5finalize(sqlite3_context *context){ + MD5Context *p; + unsigned char digest[16]; + char zBuf[33]; + p = sqlite3_aggregate_context(context, sizeof(*p)); + MD5Final(digest,p); + DigestToBase16(digest, zBuf); + sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); +} +void Md5_Register(sqlite3 *db){ + sqlite3_create_function(db, "md5sum", -1, SQLITE_UTF8, 0, 0, + md5step, md5finalize); +} diff --git a/third_party/sqlite/src/mem1.c b/third_party/sqlite/src/mem1.c new file mode 100755 index 0000000..1a3a68e --- /dev/null +++ b/third_party/sqlite/src/mem1.c @@ -0,0 +1,147 @@ +/* +** 2007 August 14 +** +** 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 low-level memory allocation drivers for when +** SQLite will use the standard C-library malloc/realloc/free interface +** to obtain the memory it needs. +** +** This file contains implementations of the low-level memory allocation +** routines specified in the sqlite3_mem_methods object. +** +** $Id: mem1.c,v 1.25 2008/07/25 08:49:00 danielk1977 Exp $ +*/ +#include "sqliteInt.h" + +/* +** This version of the memory allocator is the default. It is +** used when no other memory allocator is specified using compile-time +** macros. +*/ +#ifdef SQLITE_SYSTEM_MALLOC + +/* +** Like malloc(), but remember the size of the allocation +** so that we can find it later using sqlite3MemSize(). +** +** For this low-level routine, we are guaranteed that nByte>0 because +** cases of nByte<=0 will be intercepted and dealt with by higher level +** routines. +*/ +static void *sqlite3MemMalloc(int nByte){ + sqlite3_int64 *p; + assert( nByte>0 ); + nByte = (nByte+7)&~7; + p = malloc( nByte+8 ); + if( p ){ + p[0] = nByte; + p++; + } + return (void *)p; +} + +/* +** Like free() but works for allocations obtained from sqlite3MemMalloc() +** or sqlite3MemRealloc(). +** +** For this low-level routine, we already know that pPrior!=0 since +** cases where pPrior==0 will have been intecepted and dealt with +** by higher-level routines. +*/ +static void sqlite3MemFree(void *pPrior){ + sqlite3_int64 *p = (sqlite3_int64*)pPrior; + assert( pPrior!=0 ); + p--; + free(p); +} + +/* +** Like realloc(). Resize an allocation previously obtained from +** sqlite3MemMalloc(). +** +** For this low-level interface, we know that pPrior!=0. Cases where +** pPrior==0 while have been intercepted by higher-level routine and +** redirected to xMalloc. Similarly, we know that nByte>0 becauses +** cases where nByte<=0 will have been intercepted by higher-level +** routines and redirected to xFree. +*/ +static void *sqlite3MemRealloc(void *pPrior, int nByte){ + sqlite3_int64 *p = (sqlite3_int64*)pPrior; + assert( pPrior!=0 && nByte>0 ); + nByte = (nByte+7)&~7; + p = (sqlite3_int64*)pPrior; + p--; + p = realloc(p, nByte+8 ); + if( p ){ + p[0] = nByte; + p++; + } + return (void*)p; +} + +/* +** Report the allocated size of a prior return from xMalloc() +** or xRealloc(). +*/ +static int sqlite3MemSize(void *pPrior){ + sqlite3_int64 *p; + if( pPrior==0 ) return 0; + p = (sqlite3_int64*)pPrior; + p--; + return p[0]; +} + +/* +** Round up a request size to the next valid allocation size. +*/ +static int sqlite3MemRoundup(int n){ + return (n+7) & ~7; +} + +/* +** Initialize this module. +*/ +static int sqlite3MemInit(void *NotUsed){ + return SQLITE_OK; +} + +/* +** Deinitialize this module. +*/ +static void sqlite3MemShutdown(void *NotUsed){ + return; +} + +const sqlite3_mem_methods *sqlite3MemGetDefault(void){ + static const sqlite3_mem_methods defaultMethods = { + sqlite3MemMalloc, + sqlite3MemFree, + sqlite3MemRealloc, + sqlite3MemSize, + sqlite3MemRoundup, + sqlite3MemInit, + sqlite3MemShutdown, + 0 + }; + return &defaultMethods; +} + +/* +** This routine is the only routine in this file with external linkage. +** +** Populate the low-level memory allocation function pointers in +** sqlite3Config.m with pointers to the routines in this file. +*/ +void sqlite3MemSetDefault(void){ + sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetDefault()); +} + +#endif /* SQLITE_SYSTEM_MALLOC */ diff --git a/third_party/sqlite/src/mem2.c b/third_party/sqlite/src/mem2.c new file mode 100755 index 0000000..f1425e8 --- /dev/null +++ b/third_party/sqlite/src/mem2.c @@ -0,0 +1,443 @@ +/* +** 2007 August 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file contains low-level memory allocation drivers for when +** SQLite will use the standard C-library malloc/realloc/free interface +** to obtain the memory it needs while adding lots of additional debugging +** information to each allocation in order to help detect and fix memory +** leaks and memory usage errors. +** +** This file contains implementations of the low-level memory allocation +** routines specified in the sqlite3_mem_methods object. +** +** $Id: mem2.c,v 1.37 2008/07/25 08:49:00 danielk1977 Exp $ +*/ +#include "sqliteInt.h" + +/* +** This version of the memory allocator is used only if the +** SQLITE_MEMDEBUG macro is defined +*/ +#ifdef SQLITE_MEMDEBUG + +/* +** The backtrace functionality is only available with GLIBC +*/ +#ifdef __GLIBC__ + extern int backtrace(void**,int); + extern void backtrace_symbols_fd(void*const*,int,int); +#else +# define backtrace(A,B) 0 +# define backtrace_symbols_fd(A,B,C) +#endif +#include <stdio.h> + +/* +** Each memory allocation looks like this: +** +** ------------------------------------------------------------------------ +** | Title | backtrace pointers | MemBlockHdr | allocation | EndGuard | +** ------------------------------------------------------------------------ +** +** The application code sees only a pointer to the allocation. We have +** to back up from the allocation pointer to find the MemBlockHdr. The +** MemBlockHdr tells us the size of the allocation and the number of +** backtrace pointers. There is also a guard word at the end of the +** MemBlockHdr. +*/ +struct MemBlockHdr { + i64 iSize; /* Size of this allocation */ + struct MemBlockHdr *pNext, *pPrev; /* Linked list of all unfreed memory */ + char nBacktrace; /* Number of backtraces on this alloc */ + char nBacktraceSlots; /* Available backtrace slots */ + short nTitle; /* Bytes of title; includes '\0' */ + int iForeGuard; /* Guard word for sanity */ +}; + +/* +** Guard words +*/ +#define FOREGUARD 0x80F5E153 +#define REARGUARD 0xE4676B53 + +/* +** Number of malloc size increments to track. +*/ +#define NCSIZE 1000 + +/* +** All of the static variables used by this module are collected +** into a single structure named "mem". This is to keep the +** static variables organized and to reduce namespace pollution +** when this module is combined with other in the amalgamation. +*/ +static struct { + + /* + ** Mutex to control access to the memory allocation subsystem. + */ + sqlite3_mutex *mutex; + + /* + ** Head and tail of a linked list of all outstanding allocations + */ + struct MemBlockHdr *pFirst; + struct MemBlockHdr *pLast; + + /* + ** The number of levels of backtrace to save in new allocations. + */ + int nBacktrace; + void (*xBacktrace)(int, int, void **); + + /* + ** Title text to insert in front of each block + */ + int nTitle; /* Bytes of zTitle to save. Includes '\0' and padding */ + char zTitle[100]; /* The title text */ + + /* + ** sqlite3MallocDisallow() increments the following counter. + ** sqlite3MallocAllow() decrements it. + */ + int disallow; /* Do not allow memory allocation */ + + /* + ** Gather statistics on the sizes of memory allocations. + ** nAlloc[i] is the number of allocation attempts of i*8 + ** bytes. i==NCSIZE is the number of allocation attempts for + ** sizes more than NCSIZE*8 bytes. + */ + int nAlloc[NCSIZE]; /* Total number of allocations */ + int nCurrent[NCSIZE]; /* Current number of allocations */ + int mxCurrent[NCSIZE]; /* Highwater mark for nCurrent */ + +} mem; + + +/* +** Adjust memory usage statistics +*/ +static void adjustStats(int iSize, int increment){ + int i = ((iSize+7)&~7)/8; + if( i>NCSIZE-1 ){ + i = NCSIZE - 1; + } + if( increment>0 ){ + mem.nAlloc[i]++; + mem.nCurrent[i]++; + if( mem.nCurrent[i]>mem.mxCurrent[i] ){ + mem.mxCurrent[i] = mem.nCurrent[i]; + } + }else{ + mem.nCurrent[i]--; + assert( mem.nCurrent[i]>=0 ); + } +} + +/* +** Given an allocation, find the MemBlockHdr for that allocation. +** +** This routine checks the guards at either end of the allocation and +** if they are incorrect it asserts. +*/ +static struct MemBlockHdr *sqlite3MemsysGetHeader(void *pAllocation){ + struct MemBlockHdr *p; + int *pInt; + u8 *pU8; + int nReserve; + + p = (struct MemBlockHdr*)pAllocation; + p--; + assert( p->iForeGuard==FOREGUARD ); + nReserve = (p->iSize+7)&~7; + pInt = (int*)pAllocation; + pU8 = (u8*)pAllocation; + assert( pInt[nReserve/sizeof(int)]==REARGUARD ); + assert( (nReserve-0)<=p->iSize || pU8[nReserve-1]==0x65 ); + assert( (nReserve-1)<=p->iSize || pU8[nReserve-2]==0x65 ); + assert( (nReserve-2)<=p->iSize || pU8[nReserve-3]==0x65 ); + return p; +} + +/* +** Return the number of bytes currently allocated at address p. +*/ +static int sqlite3MemSize(void *p){ + struct MemBlockHdr *pHdr; + if( !p ){ + return 0; + } + pHdr = sqlite3MemsysGetHeader(p); + return pHdr->iSize; +} + +/* +** Initialize the memory allocation subsystem. +*/ +static int sqlite3MemInit(void *NotUsed){ + if( !sqlite3Config.bMemstat ){ + /* If memory status is enabled, then the malloc.c wrapper will already + ** hold the STATIC_MEM mutex when the routines here are invoked. */ + mem.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); + } + return SQLITE_OK; +} + +/* +** Deinitialize the memory allocation subsystem. +*/ +static void sqlite3MemShutdown(void *NotUsed){ + mem.mutex = 0; +} + +/* +** Round up a request size to the next valid allocation size. +*/ +static int sqlite3MemRoundup(int n){ + return (n+7) & ~7; +} + +/* +** Allocate nByte bytes of memory. +*/ +static void *sqlite3MemMalloc(int nByte){ + struct MemBlockHdr *pHdr; + void **pBt; + char *z; + int *pInt; + void *p = 0; + int totalSize; + int nReserve; + sqlite3_mutex_enter(mem.mutex); + assert( mem.disallow==0 ); + nReserve = (nByte+7)&~7; + totalSize = nReserve + sizeof(*pHdr) + sizeof(int) + + mem.nBacktrace*sizeof(void*) + mem.nTitle; + p = malloc(totalSize); + if( p ){ + z = p; + pBt = (void**)&z[mem.nTitle]; + pHdr = (struct MemBlockHdr*)&pBt[mem.nBacktrace]; + pHdr->pNext = 0; + pHdr->pPrev = mem.pLast; + if( mem.pLast ){ + mem.pLast->pNext = pHdr; + }else{ + mem.pFirst = pHdr; + } + mem.pLast = pHdr; + pHdr->iForeGuard = FOREGUARD; + pHdr->nBacktraceSlots = mem.nBacktrace; + pHdr->nTitle = mem.nTitle; + if( mem.nBacktrace ){ + void *aAddr[40]; + pHdr->nBacktrace = backtrace(aAddr, mem.nBacktrace+1)-1; + memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*)); + if( mem.xBacktrace ){ + mem.xBacktrace(nByte, pHdr->nBacktrace-1, &aAddr[1]); + } + }else{ + pHdr->nBacktrace = 0; + } + if( mem.nTitle ){ + memcpy(z, mem.zTitle, mem.nTitle); + } + pHdr->iSize = nByte; + adjustStats(nByte, +1); + pInt = (int*)&pHdr[1]; + pInt[nReserve/sizeof(int)] = REARGUARD; + memset(pInt, 0x65, nReserve); + p = (void*)pInt; + } + sqlite3_mutex_leave(mem.mutex); + return p; +} + +/* +** Free memory. +*/ +static void sqlite3MemFree(void *pPrior){ + struct MemBlockHdr *pHdr; + void **pBt; + char *z; + assert( sqlite3Config.bMemstat || mem.mutex!=0 ); + pHdr = sqlite3MemsysGetHeader(pPrior); + pBt = (void**)pHdr; + pBt -= pHdr->nBacktraceSlots; + sqlite3_mutex_enter(mem.mutex); + if( pHdr->pPrev ){ + assert( pHdr->pPrev->pNext==pHdr ); + pHdr->pPrev->pNext = pHdr->pNext; + }else{ + assert( mem.pFirst==pHdr ); + mem.pFirst = pHdr->pNext; + } + if( pHdr->pNext ){ + assert( pHdr->pNext->pPrev==pHdr ); + pHdr->pNext->pPrev = pHdr->pPrev; + }else{ + assert( mem.pLast==pHdr ); + mem.pLast = pHdr->pPrev; + } + z = (char*)pBt; + z -= pHdr->nTitle; + adjustStats(pHdr->iSize, -1); + memset(z, 0x2b, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) + + pHdr->iSize + sizeof(int) + pHdr->nTitle); + free(z); + sqlite3_mutex_leave(mem.mutex); +} + +/* +** Change the size of an existing memory allocation. +** +** For this debugging implementation, we *always* make a copy of the +** allocation into a new place in memory. In this way, if the +** higher level code is using pointer to the old allocation, it is +** much more likely to break and we are much more liking to find +** the error. +*/ +static void *sqlite3MemRealloc(void *pPrior, int nByte){ + struct MemBlockHdr *pOldHdr; + void *pNew; + assert( mem.disallow==0 ); + pOldHdr = sqlite3MemsysGetHeader(pPrior); + pNew = sqlite3MemMalloc(nByte); + if( pNew ){ + memcpy(pNew, pPrior, nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize); + if( nByte>pOldHdr->iSize ){ + memset(&((char*)pNew)[pOldHdr->iSize], 0x2b, nByte - pOldHdr->iSize); + } + sqlite3MemFree(pPrior); + } + return pNew; +} + + +const sqlite3_mem_methods *sqlite3MemGetDefault(void){ + static const sqlite3_mem_methods defaultMethods = { + sqlite3MemMalloc, + sqlite3MemFree, + sqlite3MemRealloc, + sqlite3MemSize, + sqlite3MemRoundup, + sqlite3MemInit, + sqlite3MemShutdown, + 0 + }; + return &defaultMethods; +} + +/* +** Populate the low-level memory allocation function pointers in +** sqlite3Config.m with pointers to the routines in this file. +*/ +void sqlite3MemSetDefault(void){ + sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetDefault()); +} + +/* +** Set the number of backtrace levels kept for each allocation. +** A value of zero turns off backtracing. The number is always rounded +** up to a multiple of 2. +*/ +void sqlite3MemdebugBacktrace(int depth){ + if( depth<0 ){ depth = 0; } + if( depth>20 ){ depth = 20; } + depth = (depth+1)&0xfe; + mem.nBacktrace = depth; +} + +void sqlite3MemdebugBacktraceCallback(void (*xBacktrace)(int, int, void **)){ + mem.xBacktrace = xBacktrace; +} + +/* +** Set the title string for subsequent allocations. +*/ +void sqlite3MemdebugSettitle(const char *zTitle){ + int n = strlen(zTitle) + 1; + sqlite3_mutex_enter(mem.mutex); + if( n>=sizeof(mem.zTitle) ) n = sizeof(mem.zTitle)-1; + memcpy(mem.zTitle, zTitle, n); + mem.zTitle[n] = 0; + mem.nTitle = (n+7)&~7; + sqlite3_mutex_leave(mem.mutex); +} + +void sqlite3MemdebugSync(){ + struct MemBlockHdr *pHdr; + for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){ + void **pBt = (void**)pHdr; + pBt -= pHdr->nBacktraceSlots; + mem.xBacktrace(pHdr->iSize, pHdr->nBacktrace-1, &pBt[1]); + } +} + +/* +** Open the file indicated and write a log of all unfreed memory +** allocations into that log. +*/ +void sqlite3MemdebugDump(const char *zFilename){ + FILE *out; + struct MemBlockHdr *pHdr; + void **pBt; + int i; + out = fopen(zFilename, "w"); + if( out==0 ){ + fprintf(stderr, "** Unable to output memory debug output log: %s **\n", + zFilename); + return; + } + for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){ + char *z = (char*)pHdr; + z -= pHdr->nBacktraceSlots*sizeof(void*) + pHdr->nTitle; + fprintf(out, "**** %lld bytes at %p from %s ****\n", + pHdr->iSize, &pHdr[1], pHdr->nTitle ? z : "???"); + if( pHdr->nBacktrace ){ + fflush(out); + pBt = (void**)pHdr; + pBt -= pHdr->nBacktraceSlots; + backtrace_symbols_fd(pBt, pHdr->nBacktrace, fileno(out)); + fprintf(out, "\n"); + } + } + fprintf(out, "COUNTS:\n"); + for(i=0; i<NCSIZE-1; i++){ + if( mem.nAlloc[i] ){ + fprintf(out, " %5d: %10d %10d %10d\n", + i*8, mem.nAlloc[i], mem.nCurrent[i], mem.mxCurrent[i]); + } + } + if( mem.nAlloc[NCSIZE-1] ){ + fprintf(out, " %5d: %10d %10d %10d\n", + NCSIZE*8-8, mem.nAlloc[NCSIZE-1], + mem.nCurrent[NCSIZE-1], mem.mxCurrent[NCSIZE-1]); + } + fclose(out); +} + +/* +** Return the number of times sqlite3MemMalloc() has been called. +*/ +int sqlite3MemdebugMallocCount(){ + int i; + int nTotal = 0; + for(i=0; i<NCSIZE; i++){ + nTotal += mem.nAlloc[i]; + } + return nTotal; +} + + +#endif /* SQLITE_MEMDEBUG */ diff --git a/third_party/sqlite/src/mem3.c b/third_party/sqlite/src/mem3.c new file mode 100755 index 0000000..46a5898 --- /dev/null +++ b/third_party/sqlite/src/mem3.c @@ -0,0 +1,682 @@ +/* +** 2007 October 14 +** +** 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 the C functions that implement a memory +** allocation subsystem for use by SQLite. +** +** This version of the memory allocation subsystem omits all +** use of malloc(). The SQLite user supplies a block of memory +** before calling sqlite3_initialize() from which allocations +** are made and returned by the xMalloc() and xRealloc() +** implementations. Once sqlite3_initialize() has been called, +** the amount of memory available to SQLite is fixed and cannot +** be changed. +** +** This version of the memory allocation subsystem is included +** in the build only if SQLITE_ENABLE_MEMSYS3 is defined. +** +** $Id: mem3.c,v 1.20 2008/07/18 18:56:17 drh Exp $ +*/ +#include "sqliteInt.h" + +/* +** This version of the memory allocator is only built into the library +** SQLITE_ENABLE_MEMSYS3 is defined. Defining this symbol does not +** mean that the library will use a memory-pool by default, just that +** it is available. The mempool allocator is activated by calling +** sqlite3_config(). +*/ +#ifdef SQLITE_ENABLE_MEMSYS3 + +/* +** Maximum size (in Mem3Blocks) of a "small" chunk. +*/ +#define MX_SMALL 10 + + +/* +** Number of freelist hash slots +*/ +#define N_HASH 61 + +/* +** A memory allocation (also called a "chunk") consists of two or +** more blocks where each block is 8 bytes. The first 8 bytes are +** a header that is not returned to the user. +** +** A chunk is two or more blocks that is either checked out or +** free. The first block has format u.hdr. u.hdr.size4x is 4 times the +** size of the allocation in blocks if the allocation is free. +** The u.hdr.size4x&1 bit is true if the chunk is checked out and +** false if the chunk is on the freelist. The u.hdr.size4x&2 bit +** is true if the previous chunk is checked out and false if the +** previous chunk is free. The u.hdr.prevSize field is the size of +** the previous chunk in blocks if the previous chunk is on the +** freelist. If the previous chunk is checked out, then +** u.hdr.prevSize can be part of the data for that chunk and should +** not be read or written. +** +** We often identify a chunk by its index in mem3.aPool[]. When +** this is done, the chunk index refers to the second block of +** the chunk. In this way, the first chunk has an index of 1. +** A chunk index of 0 means "no such chunk" and is the equivalent +** of a NULL pointer. +** +** The second block of free chunks is of the form u.list. The +** two fields form a double-linked list of chunks of related sizes. +** Pointers to the head of the list are stored in mem3.aiSmall[] +** for smaller chunks and mem3.aiHash[] for larger chunks. +** +** The second block of a chunk is user data if the chunk is checked +** out. If a chunk is checked out, the user data may extend into +** the u.hdr.prevSize value of the following chunk. +*/ +typedef struct Mem3Block Mem3Block; +struct Mem3Block { + union { + struct { + u32 prevSize; /* Size of previous chunk in Mem3Block elements */ + u32 size4x; /* 4x the size of current chunk in Mem3Block elements */ + } hdr; + struct { + u32 next; /* Index in mem3.aPool[] of next free chunk */ + u32 prev; /* Index in mem3.aPool[] of previous free chunk */ + } list; + } u; +}; + +/* +** All of the static variables used by this module are collected +** into a single structure named "mem3". This is to keep the +** static variables organized and to reduce namespace pollution +** when this module is combined with other in the amalgamation. +*/ +static struct { + /* + ** True if we are evaluating an out-of-memory callback. + */ + int alarmBusy; + + /* + ** Mutex to control access to the memory allocation subsystem. + */ + sqlite3_mutex *mutex; + + /* + ** The minimum amount of free space that we have seen. + */ + u32 mnMaster; + + /* + ** iMaster is the index of the master chunk. Most new allocations + ** occur off of this chunk. szMaster is the size (in Mem3Blocks) + ** of the current master. iMaster is 0 if there is not master chunk. + ** The master chunk is not in either the aiHash[] or aiSmall[]. + */ + u32 iMaster; + u32 szMaster; + + /* + ** Array of lists of free blocks according to the block size + ** for smaller chunks, or a hash on the block size for larger + ** chunks. + */ + u32 aiSmall[MX_SMALL-1]; /* For sizes 2 through MX_SMALL, inclusive */ + u32 aiHash[N_HASH]; /* For sizes MX_SMALL+1 and larger */ + + /* + ** Memory available for allocation. nPool is the size of the array + ** (in Mem3Blocks) pointed to by aPool less 2. + */ + u32 nPool; + Mem3Block *aPool; +} mem3; + +/* +** Unlink the chunk at mem3.aPool[i] from list it is currently +** on. *pRoot is the list that i is a member of. +*/ +static void memsys3UnlinkFromList(u32 i, u32 *pRoot){ + u32 next = mem3.aPool[i].u.list.next; + u32 prev = mem3.aPool[i].u.list.prev; + assert( sqlite3_mutex_held(mem3.mutex) ); + if( prev==0 ){ + *pRoot = next; + }else{ + mem3.aPool[prev].u.list.next = next; + } + if( next ){ + mem3.aPool[next].u.list.prev = prev; + } + mem3.aPool[i].u.list.next = 0; + mem3.aPool[i].u.list.prev = 0; +} + +/* +** Unlink the chunk at index i from +** whatever list is currently a member of. +*/ +static void memsys3Unlink(u32 i){ + u32 size, hash; + assert( sqlite3_mutex_held(mem3.mutex) ); + assert( (mem3.aPool[i-1].u.hdr.size4x & 1)==0 ); + assert( i>=1 ); + size = mem3.aPool[i-1].u.hdr.size4x/4; + assert( size==mem3.aPool[i+size-1].u.hdr.prevSize ); + assert( size>=2 ); + if( size <= MX_SMALL ){ + memsys3UnlinkFromList(i, &mem3.aiSmall[size-2]); + }else{ + hash = size % N_HASH; + memsys3UnlinkFromList(i, &mem3.aiHash[hash]); + } +} + +/* +** Link the chunk at mem3.aPool[i] so that is on the list rooted +** at *pRoot. +*/ +static void memsys3LinkIntoList(u32 i, u32 *pRoot){ + assert( sqlite3_mutex_held(mem3.mutex) ); + mem3.aPool[i].u.list.next = *pRoot; + mem3.aPool[i].u.list.prev = 0; + if( *pRoot ){ + mem3.aPool[*pRoot].u.list.prev = i; + } + *pRoot = i; +} + +/* +** Link the chunk at index i into either the appropriate +** small chunk list, or into the large chunk hash table. +*/ +static void memsys3Link(u32 i){ + u32 size, hash; + assert( sqlite3_mutex_held(mem3.mutex) ); + assert( i>=1 ); + assert( (mem3.aPool[i-1].u.hdr.size4x & 1)==0 ); + size = mem3.aPool[i-1].u.hdr.size4x/4; + assert( size==mem3.aPool[i+size-1].u.hdr.prevSize ); + assert( size>=2 ); + if( size <= MX_SMALL ){ + memsys3LinkIntoList(i, &mem3.aiSmall[size-2]); + }else{ + hash = size % N_HASH; + memsys3LinkIntoList(i, &mem3.aiHash[hash]); + } +} + +/* +** If the STATIC_MEM mutex is not already held, obtain it now. The mutex +** will already be held (obtained by code in malloc.c) if +** sqlite3Config.bMemStat is true. +*/ +static void memsys3Enter(void){ + if( sqlite3Config.bMemstat==0 && mem3.mutex==0 ){ + mem3.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); + } + sqlite3_mutex_enter(mem3.mutex); +} +static void memsys3Leave(void){ + sqlite3_mutex_leave(mem3.mutex); +} + +/* +** Called when we are unable to satisfy an allocation of nBytes. +*/ +static void memsys3OutOfMemory(int nByte){ + if( !mem3.alarmBusy ){ + mem3.alarmBusy = 1; + assert( sqlite3_mutex_held(mem3.mutex) ); + sqlite3_mutex_leave(mem3.mutex); + sqlite3_release_memory(nByte); + sqlite3_mutex_enter(mem3.mutex); + mem3.alarmBusy = 0; + } +} + + +/* +** Chunk i is a free chunk that has been unlinked. Adjust its +** size parameters for check-out and return a pointer to the +** user portion of the chunk. +*/ +static void *memsys3Checkout(u32 i, int nBlock){ + u32 x; + assert( sqlite3_mutex_held(mem3.mutex) ); + assert( i>=1 ); + assert( mem3.aPool[i-1].u.hdr.size4x/4==nBlock ); + assert( mem3.aPool[i+nBlock-1].u.hdr.prevSize==nBlock ); + x = mem3.aPool[i-1].u.hdr.size4x; + mem3.aPool[i-1].u.hdr.size4x = nBlock*4 | 1 | (x&2); + mem3.aPool[i+nBlock-1].u.hdr.prevSize = nBlock; + mem3.aPool[i+nBlock-1].u.hdr.size4x |= 2; + return &mem3.aPool[i]; +} + +/* +** Carve a piece off of the end of the mem3.iMaster free chunk. +** Return a pointer to the new allocation. Or, if the master chunk +** is not large enough, return 0. +*/ +static void *memsys3FromMaster(int nBlock){ + assert( sqlite3_mutex_held(mem3.mutex) ); + assert( mem3.szMaster>=nBlock ); + if( nBlock>=mem3.szMaster-1 ){ + /* Use the entire master */ + void *p = memsys3Checkout(mem3.iMaster, mem3.szMaster); + mem3.iMaster = 0; + mem3.szMaster = 0; + mem3.mnMaster = 0; + return p; + }else{ + /* Split the master block. Return the tail. */ + u32 newi, x; + newi = mem3.iMaster + mem3.szMaster - nBlock; + assert( newi > mem3.iMaster+1 ); + mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = nBlock; + mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x |= 2; + mem3.aPool[newi-1].u.hdr.size4x = nBlock*4 + 1; + mem3.szMaster -= nBlock; + mem3.aPool[newi-1].u.hdr.prevSize = mem3.szMaster; + x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2; + mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x; + if( mem3.szMaster < mem3.mnMaster ){ + mem3.mnMaster = mem3.szMaster; + } + return (void*)&mem3.aPool[newi]; + } +} + +/* +** *pRoot is the head of a list of free chunks of the same size +** or same size hash. In other words, *pRoot is an entry in either +** mem3.aiSmall[] or mem3.aiHash[]. +** +** This routine examines all entries on the given list and tries +** to coalesce each entries with adjacent free chunks. +** +** If it sees a chunk that is larger than mem3.iMaster, it replaces +** the current mem3.iMaster with the new larger chunk. In order for +** this mem3.iMaster replacement to work, the master chunk must be +** linked into the hash tables. That is not the normal state of +** affairs, of course. The calling routine must link the master +** chunk before invoking this routine, then must unlink the (possibly +** changed) master chunk once this routine has finished. +*/ +static void memsys3Merge(u32 *pRoot){ + u32 iNext, prev, size, i, x; + + assert( sqlite3_mutex_held(mem3.mutex) ); + for(i=*pRoot; i>0; i=iNext){ + iNext = mem3.aPool[i].u.list.next; + size = mem3.aPool[i-1].u.hdr.size4x; + assert( (size&1)==0 ); + if( (size&2)==0 ){ + memsys3UnlinkFromList(i, pRoot); + assert( i > mem3.aPool[i-1].u.hdr.prevSize ); + prev = i - mem3.aPool[i-1].u.hdr.prevSize; + if( prev==iNext ){ + iNext = mem3.aPool[prev].u.list.next; + } + memsys3Unlink(prev); + size = i + size/4 - prev; + x = mem3.aPool[prev-1].u.hdr.size4x & 2; + mem3.aPool[prev-1].u.hdr.size4x = size*4 | x; + mem3.aPool[prev+size-1].u.hdr.prevSize = size; + memsys3Link(prev); + i = prev; + }else{ + size /= 4; + } + if( size>mem3.szMaster ){ + mem3.iMaster = i; + mem3.szMaster = size; + } + } +} + +/* +** Return a block of memory of at least nBytes in size. +** Return NULL if unable. +** +** This function assumes that the necessary mutexes, if any, are +** already held by the caller. Hence "Unsafe". +*/ +static void *memsys3MallocUnsafe(int nByte){ + u32 i; + int nBlock; + int toFree; + + assert( sqlite3_mutex_held(mem3.mutex) ); + assert( sizeof(Mem3Block)==8 ); + if( nByte<=12 ){ + nBlock = 2; + }else{ + nBlock = (nByte + 11)/8; + } + assert( nBlock>=2 ); + + /* STEP 1: + ** Look for an entry of the correct size in either the small + ** chunk table or in the large chunk hash table. This is + ** successful most of the time (about 9 times out of 10). + */ + if( nBlock <= MX_SMALL ){ + i = mem3.aiSmall[nBlock-2]; + if( i>0 ){ + memsys3UnlinkFromList(i, &mem3.aiSmall[nBlock-2]); + return memsys3Checkout(i, nBlock); + } + }else{ + int hash = nBlock % N_HASH; + for(i=mem3.aiHash[hash]; i>0; i=mem3.aPool[i].u.list.next){ + if( mem3.aPool[i-1].u.hdr.size4x/4==nBlock ){ + memsys3UnlinkFromList(i, &mem3.aiHash[hash]); + return memsys3Checkout(i, nBlock); + } + } + } + + /* STEP 2: + ** Try to satisfy the allocation by carving a piece off of the end + ** of the master chunk. This step usually works if step 1 fails. + */ + if( mem3.szMaster>=nBlock ){ + return memsys3FromMaster(nBlock); + } + + + /* STEP 3: + ** Loop through the entire memory pool. Coalesce adjacent free + ** chunks. Recompute the master chunk as the largest free chunk. + ** Then try again to satisfy the allocation by carving a piece off + ** of the end of the master chunk. This step happens very + ** rarely (we hope!) + */ + for(toFree=nBlock*16; toFree<(mem3.nPool*16); toFree *= 2){ + memsys3OutOfMemory(toFree); + if( mem3.iMaster ){ + memsys3Link(mem3.iMaster); + mem3.iMaster = 0; + mem3.szMaster = 0; + } + for(i=0; i<N_HASH; i++){ + memsys3Merge(&mem3.aiHash[i]); + } + for(i=0; i<MX_SMALL-1; i++){ + memsys3Merge(&mem3.aiSmall[i]); + } + if( mem3.szMaster ){ + memsys3Unlink(mem3.iMaster); + if( mem3.szMaster>=nBlock ){ + return memsys3FromMaster(nBlock); + } + } + } + + /* If none of the above worked, then we fail. */ + return 0; +} + +/* +** Free an outstanding memory allocation. +** +** This function assumes that the necessary mutexes, if any, are +** already held by the caller. Hence "Unsafe". +*/ +void memsys3FreeUnsafe(void *pOld){ + Mem3Block *p = (Mem3Block*)pOld; + int i; + u32 size, x; + assert( sqlite3_mutex_held(mem3.mutex) ); + assert( p>mem3.aPool && p<&mem3.aPool[mem3.nPool] ); + i = p - mem3.aPool; + assert( (mem3.aPool[i-1].u.hdr.size4x&1)==1 ); + size = mem3.aPool[i-1].u.hdr.size4x/4; + assert( i+size<=mem3.nPool+1 ); + mem3.aPool[i-1].u.hdr.size4x &= ~1; + mem3.aPool[i+size-1].u.hdr.prevSize = size; + mem3.aPool[i+size-1].u.hdr.size4x &= ~2; + memsys3Link(i); + + /* Try to expand the master using the newly freed chunk */ + if( mem3.iMaster ){ + while( (mem3.aPool[mem3.iMaster-1].u.hdr.size4x&2)==0 ){ + size = mem3.aPool[mem3.iMaster-1].u.hdr.prevSize; + mem3.iMaster -= size; + mem3.szMaster += size; + memsys3Unlink(mem3.iMaster); + x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2; + mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x; + mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster; + } + x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2; + while( (mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x&1)==0 ){ + memsys3Unlink(mem3.iMaster+mem3.szMaster); + mem3.szMaster += mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x/4; + mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x; + mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster; + } + } +} + +/* +** Return the size of an outstanding allocation, in bytes. The +** size returned omits the 8-byte header overhead. This only +** works for chunks that are currently checked out. +*/ +static int memsys3Size(void *p){ + Mem3Block *pBlock; + if( p==0 ) return 0; + pBlock = (Mem3Block*)p; + assert( (pBlock[-1].u.hdr.size4x&1)!=0 ); + return (pBlock[-1].u.hdr.size4x&~3)*2 - 4; +} + +/* +** Round up a request size to the next valid allocation size. +*/ +static int memsys3Roundup(int n){ + if( n<=12 ){ + return 12; + }else{ + return ((n+11)&~7) - 4; + } +} + +/* +** Allocate nBytes of memory. +*/ +static void *memsys3Malloc(int nBytes){ + sqlite3_int64 *p; + assert( nBytes>0 ); /* malloc.c filters out 0 byte requests */ + memsys3Enter(); + p = memsys3MallocUnsafe(nBytes); + memsys3Leave(); + return (void*)p; +} + +/* +** Free memory. +*/ +void memsys3Free(void *pPrior){ + assert( pPrior ); + memsys3Enter(); + memsys3FreeUnsafe(pPrior); + memsys3Leave(); +} + +/* +** Change the size of an existing memory allocation +*/ +void *memsys3Realloc(void *pPrior, int nBytes){ + int nOld; + void *p; + if( pPrior==0 ){ + return sqlite3_malloc(nBytes); + } + if( nBytes<=0 ){ + sqlite3_free(pPrior); + return 0; + } + nOld = memsys3Size(pPrior); + if( nBytes<=nOld && nBytes>=nOld-128 ){ + return pPrior; + } + memsys3Enter(); + p = memsys3MallocUnsafe(nBytes); + if( p ){ + if( nOld<nBytes ){ + memcpy(p, pPrior, nOld); + }else{ + memcpy(p, pPrior, nBytes); + } + memsys3FreeUnsafe(pPrior); + } + memsys3Leave(); + return p; +} + +/* +** Initialize this module. +*/ +static int memsys3Init(void *NotUsed){ + if( !sqlite3Config.pHeap ){ + return SQLITE_ERROR; + } + + /* Store a pointer to the memory block in global structure mem3. */ + assert( sizeof(Mem3Block)==8 ); + mem3.aPool = (Mem3Block *)sqlite3Config.pHeap; + mem3.nPool = (sqlite3Config.nHeap / sizeof(Mem3Block)) - 2; + + /* Initialize the master block. */ + mem3.szMaster = mem3.nPool; + mem3.mnMaster = mem3.szMaster; + mem3.iMaster = 1; + mem3.aPool[0].u.hdr.size4x = (mem3.szMaster<<2) + 2; + mem3.aPool[mem3.nPool].u.hdr.prevSize = mem3.nPool; + mem3.aPool[mem3.nPool].u.hdr.size4x = 1; + + return SQLITE_OK; +} + +/* +** Deinitialize this module. +*/ +static void memsys3Shutdown(void *NotUsed){ + return; +} + + + +/* +** Open the file indicated and write a log of all unfreed memory +** allocations into that log. +*/ +#ifdef SQLITE_DEBUG +void sqlite3Memsys3Dump(const char *zFilename){ + FILE *out; + int i, j; + u32 size; + if( zFilename==0 || zFilename[0]==0 ){ + out = stdout; + }else{ + out = fopen(zFilename, "w"); + if( out==0 ){ + fprintf(stderr, "** Unable to output memory debug output log: %s **\n", + zFilename); + return; + } + } + memsys3Enter(); + fprintf(out, "CHUNKS:\n"); + for(i=1; i<=mem3.nPool; i+=size/4){ + size = mem3.aPool[i-1].u.hdr.size4x; + if( size/4<=1 ){ + fprintf(out, "%p size error\n", &mem3.aPool[i]); + assert( 0 ); + break; + } + if( (size&1)==0 && mem3.aPool[i+size/4-1].u.hdr.prevSize!=size/4 ){ + fprintf(out, "%p tail size does not match\n", &mem3.aPool[i]); + assert( 0 ); + break; + } + if( ((mem3.aPool[i+size/4-1].u.hdr.size4x&2)>>1)!=(size&1) ){ + fprintf(out, "%p tail checkout bit is incorrect\n", &mem3.aPool[i]); + assert( 0 ); + break; + } + if( size&1 ){ + fprintf(out, "%p %6d bytes checked out\n", &mem3.aPool[i], (size/4)*8-8); + }else{ + fprintf(out, "%p %6d bytes free%s\n", &mem3.aPool[i], (size/4)*8-8, + i==mem3.iMaster ? " **master**" : ""); + } + } + for(i=0; i<MX_SMALL-1; i++){ + if( mem3.aiSmall[i]==0 ) continue; + fprintf(out, "small(%2d):", i); + for(j = mem3.aiSmall[i]; j>0; j=mem3.aPool[j].u.list.next){ + fprintf(out, " %p(%d)", &mem3.aPool[j], + (mem3.aPool[j-1].u.hdr.size4x/4)*8-8); + } + fprintf(out, "\n"); + } + for(i=0; i<N_HASH; i++){ + if( mem3.aiHash[i]==0 ) continue; + fprintf(out, "hash(%2d):", i); + for(j = mem3.aiHash[i]; j>0; j=mem3.aPool[j].u.list.next){ + fprintf(out, " %p(%d)", &mem3.aPool[j], + (mem3.aPool[j-1].u.hdr.size4x/4)*8-8); + } + fprintf(out, "\n"); + } + fprintf(out, "master=%d\n", mem3.iMaster); + fprintf(out, "nowUsed=%d\n", mem3.nPool*8 - mem3.szMaster*8); + fprintf(out, "mxUsed=%d\n", mem3.nPool*8 - mem3.mnMaster*8); + sqlite3_mutex_leave(mem3.mutex); + if( out==stdout ){ + fflush(stdout); + }else{ + fclose(out); + } +} +#endif + +/* +** This routine is the only routine in this file with external +** linkage. +** +** Populate the low-level memory allocation function pointers in +** sqlite3Config.m with pointers to the routines in this file. The +** arguments specify the block of memory to manage. +** +** This routine is only called by sqlite3_config(), and therefore +** is not required to be threadsafe (it is not). +*/ +const sqlite3_mem_methods *sqlite3MemGetMemsys3(void){ + static const sqlite3_mem_methods mempoolMethods = { + memsys3Malloc, + memsys3Free, + memsys3Realloc, + memsys3Size, + memsys3Roundup, + memsys3Init, + memsys3Shutdown, + 0 + }; + return &mempoolMethods; +} + +#endif /* SQLITE_ENABLE_MEMSYS3 */ diff --git a/third_party/sqlite/src/mem4.c b/third_party/sqlite/src/mem4.c new file mode 100755 index 0000000..5a78098 --- /dev/null +++ b/third_party/sqlite/src/mem4.c @@ -0,0 +1,393 @@ +/* +** 2007 August 14 +** +** 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 the C functions that implement a memory +** allocation subsystem for use by SQLite. +** +** $Id: mem4.c,v 1.3 2008/06/18 17:09:10 danielk1977 Exp $ +*/ +#include "sqliteInt.h" + +/* +** This version of the memory allocator attempts to obtain memory +** from mmap() if the size of the allocation is close to the size +** of a virtual memory page. If the size of the allocation is different +** from the virtual memory page size, then ordinary malloc() is used. +** Ordinary malloc is also used if space allocated to mmap() is +** exhausted. +** +** Enable this memory allocation by compiling with -DSQLITE_MMAP_HEAP_SIZE=nnn +** where nnn is the maximum number of bytes of mmap-ed memory you want +** to support. This module may choose to use less memory than requested. +** +*/ +#ifdef SQLITE_MMAP_HEAP_SIZE + +/* +** This is a test version of the memory allocator that attempts to +** use mmap() and madvise() for allocations and frees of approximately +** the virtual memory page size. +*/ +#include <sys/types.h> +#include <sys/mman.h> +#include <errno.h> +#include <unistd.h> + + +/* +** All of the static variables used by this module are collected +** into a single structure named "mem". This is to keep the +** static variables organized and to reduce namespace pollution +** when this module is combined with other in the amalgamation. +*/ +static struct { + /* + ** The alarm callback and its arguments. The mem.mutex lock will + ** be held while the callback is running. Recursive calls into + ** the memory subsystem are allowed, but no new callbacks will be + ** issued. The alarmBusy variable is set to prevent recursive + ** callbacks. + */ + sqlite3_int64 alarmThreshold; + void (*alarmCallback)(void*, sqlite3_int64,int); + void *alarmArg; + int alarmBusy; + + /* + ** Mutex to control access to the memory allocation subsystem. + */ + sqlite3_mutex *mutex; + + /* + ** Current allocation and high-water mark. + */ + sqlite3_int64 nowUsed; + sqlite3_int64 mxUsed; + + /* + ** Current allocation and high-water marks for mmap allocated memory. + */ + sqlite3_int64 nowUsedMMap; + sqlite3_int64 mxUsedMMap; + + /* + ** Size of a single mmap page. Obtained from sysconf(). + */ + int szPage; + int mnPage; + + /* + ** The number of available mmap pages. + */ + int nPage; + + /* + ** Index of the first free page. 0 means no pages have been freed. + */ + int firstFree; + + /* First unused page on the top of the heap. + */ + int firstUnused; + + /* + ** Bulk memory obtained from from mmap(). + */ + char *mmapHeap; /* first byte of the heap */ + +} mem; + + +/* +** Enter the mutex mem.mutex. Allocate it if it is not already allocated. +** The mmap() region is initialized the first time this routine is called. +*/ +static void memsys4Enter(void){ + if( mem.mutex==0 ){ + mem.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); + } + sqlite3_mutex_enter(mem.mutex); +} + +/* +** Attempt to free memory to the mmap heap. This only works if +** the pointer p is within the range of memory addresses that +** comprise the mmap heap. Return 1 if the memory was freed +** successfully. Return 0 if the pointer is out of range. +*/ +static int mmapFree(void *p){ + char *z; + int idx, *a; + if( mem.mmapHeap==MAP_FAILED || mem.nPage==0 ){ + return 0; + } + z = (char*)p; + idx = (z - mem.mmapHeap)/mem.szPage; + if( idx<1 || idx>=mem.nPage ){ + return 0; + } + a = (int*)mem.mmapHeap; + a[idx] = a[mem.firstFree]; + mem.firstFree = idx; + mem.nowUsedMMap -= mem.szPage; + madvise(p, mem.szPage, MADV_DONTNEED); + return 1; +} + +/* +** Attempt to allocate nBytes from the mmap heap. Return a pointer +** to the allocated page. Or, return NULL if the allocation fails. +** +** The allocation will fail if nBytes is not the right size. +** Or, the allocation will fail if the mmap heap has been exhausted. +*/ +static void *mmapAlloc(int nBytes){ + int idx = 0; + if( nBytes>mem.szPage || nBytes<mem.mnPage ){ + return 0; + } + if( mem.nPage==0 ){ + mem.szPage = sysconf(_SC_PAGE_SIZE); + mem.mnPage = mem.szPage - mem.szPage/10; + mem.nPage = SQLITE_MMAP_HEAP_SIZE/mem.szPage; + if( mem.nPage * sizeof(int) > mem.szPage ){ + mem.nPage = mem.szPage/sizeof(int); + } + mem.mmapHeap = mmap(0, mem.szPage*mem.nPage, PROT_WRITE|PROT_READ, + MAP_ANONYMOUS|MAP_SHARED, -1, 0); + if( mem.mmapHeap==MAP_FAILED ){ + mem.firstUnused = errno; + }else{ + mem.firstUnused = 1; + mem.nowUsedMMap = mem.szPage; + } + } + if( mem.mmapHeap==MAP_FAILED ){ + return 0; + } + if( mem.firstFree ){ + int idx = mem.firstFree; + int *a = (int*)mem.mmapHeap; + mem.firstFree = a[idx]; + }else if( mem.firstUnused<mem.nPage ){ + idx = mem.firstUnused++; + } + if( idx ){ + mem.nowUsedMMap += mem.szPage; + if( mem.nowUsedMMap>mem.mxUsedMMap ){ + mem.mxUsedMMap = mem.nowUsedMMap; + } + return (void*)&mem.mmapHeap[idx*mem.szPage]; + }else{ + return 0; + } +} + +/* +** Release the mmap-ed memory region if it is currently allocated and +** is not in use. +*/ +static void mmapUnmap(void){ + if( mem.mmapHeap==MAP_FAILED ) return; + if( mem.nPage==0 ) return; + if( mem.nowUsedMMap>mem.szPage ) return; + munmap(mem.mmapHeap, mem.nPage*mem.szPage); + mem.nowUsedMMap = 0; + mem.nPage = 0; +} + + +/* +** Return the amount of memory currently checked out. +*/ +sqlite3_int64 sqlite3_memory_used(void){ + sqlite3_int64 n; + memsys4Enter(); + n = mem.nowUsed + mem.nowUsedMMap; + sqlite3_mutex_leave(mem.mutex); + return n; +} + +/* +** Return the maximum amount of memory that has ever been +** checked out since either the beginning of this process +** or since the most recent reset. +*/ +sqlite3_int64 sqlite3_memory_highwater(int resetFlag){ + sqlite3_int64 n; + memsys4Enter(); + n = mem.mxUsed + mem.mxUsedMMap; + if( resetFlag ){ + mem.mxUsed = mem.nowUsed; + mem.mxUsedMMap = mem.nowUsedMMap; + } + sqlite3_mutex_leave(mem.mutex); + return n; +} + +/* +** Change the alarm callback +*/ +int sqlite3_memory_alarm( + void(*xCallback)(void *pArg, sqlite3_int64 used,int N), + void *pArg, + sqlite3_int64 iThreshold +){ + memsys4Enter(); + mem.alarmCallback = xCallback; + mem.alarmArg = pArg; + mem.alarmThreshold = iThreshold; + sqlite3_mutex_leave(mem.mutex); + return SQLITE_OK; +} + +/* +** Trigger the alarm +*/ +static void sqlite3MemsysAlarm(int nByte){ + void (*xCallback)(void*,sqlite3_int64,int); + sqlite3_int64 nowUsed; + void *pArg; + if( mem.alarmCallback==0 || mem.alarmBusy ) return; + mem.alarmBusy = 1; + xCallback = mem.alarmCallback; + nowUsed = mem.nowUsed; + pArg = mem.alarmArg; + sqlite3_mutex_leave(mem.mutex); + xCallback(pArg, nowUsed, nByte); + sqlite3_mutex_enter(mem.mutex); + mem.alarmBusy = 0; +} + +/* +** Allocate nBytes of memory +*/ +static void *memsys4Malloc(int nBytes){ + sqlite3_int64 *p = 0; + if( mem.alarmCallback!=0 + && mem.nowUsed+mem.nowUsedMMap+nBytes>=mem.alarmThreshold ){ + sqlite3MemsysAlarm(nBytes); + } + if( (p = mmapAlloc(nBytes))==0 ){ + p = malloc(nBytes+8); + if( p==0 ){ + sqlite3MemsysAlarm(nBytes); + p = malloc(nBytes+8); + } + if( p ){ + p[0] = nBytes; + p++; + mem.nowUsed += nBytes; + if( mem.nowUsed>mem.mxUsed ){ + mem.mxUsed = mem.nowUsed; + } + } + } + return (void*)p; +} + +/* +** Return the size of a memory allocation +*/ +static int memsys4Size(void *pPrior){ + char *z = (char*)pPrior; + int idx = mem.nPage ? (z - mem.mmapHeap)/mem.szPage : 0; + int nByte; + if( idx>=1 && idx<mem.nPage ){ + nByte = mem.szPage; + }else{ + sqlite3_int64 *p = pPrior; + p--; + nByte = (int)*p; + } + return nByte; +} + +/* +** Free memory. +*/ +static void memsys4Free(void *pPrior){ + sqlite3_int64 *p; + int nByte; + if( mmapFree(pPrior)==0 ){ + p = pPrior; + p--; + nByte = (int)*p; + mem.nowUsed -= nByte; + free(p); + if( mem.nowUsed==0 ){ + mmapUnmap(); + } + } +} + +/* +** Allocate nBytes of memory +*/ +void *sqlite3_malloc(int nBytes){ + sqlite3_int64 *p = 0; + if( nBytes>0 ){ + memsys4Enter(); + p = memsys4Malloc(nBytes); + sqlite3_mutex_leave(mem.mutex); + } + return (void*)p; +} + +/* +** Free memory. +*/ +void sqlite3_free(void *pPrior){ + if( pPrior==0 ){ + return; + } + assert( mem.mutex!=0 ); + sqlite3_mutex_enter(mem.mutex); + memsys4Free(pPrior); + sqlite3_mutex_leave(mem.mutex); +} + + + +/* +** Change the size of an existing memory allocation +*/ +void *sqlite3_realloc(void *pPrior, int nBytes){ + int nOld; + sqlite3_int64 *p; + if( pPrior==0 ){ + return sqlite3_malloc(nBytes); + } + if( nBytes<=0 ){ + sqlite3_free(pPrior); + return 0; + } + nOld = memsys4Size(pPrior); + if( nBytes<=nOld && nBytes>=nOld-128 ){ + return pPrior; + } + assert( mem.mutex!=0 ); + sqlite3_mutex_enter(mem.mutex); + p = memsys4Malloc(nBytes); + if( p ){ + if( nOld<nBytes ){ + memcpy(p, pPrior, nOld); + }else{ + memcpy(p, pPrior, nBytes); + } + memsys4Free(pPrior); + } + assert( mem.mutex!=0 ); + sqlite3_mutex_leave(mem.mutex); + return (void*)p; +} + +#endif /* SQLITE_MMAP_HEAP_SIZE */ diff --git a/third_party/sqlite/src/mem5.c b/third_party/sqlite/src/mem5.c new file mode 100755 index 0000000..7ce28a3 --- /dev/null +++ b/third_party/sqlite/src/mem5.c @@ -0,0 +1,515 @@ +/* +** 2007 October 14 +** +** 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 the C functions that implement a memory +** allocation subsystem for use by SQLite. +** +** This version of the memory allocation subsystem omits all +** use of malloc(). The SQLite user supplies a block of memory +** before calling sqlite3_initialize() from which allocations +** are made and returned by the xMalloc() and xRealloc() +** implementations. Once sqlite3_initialize() has been called, +** the amount of memory available to SQLite is fixed and cannot +** be changed. +** +** This version of the memory allocation subsystem is included +** in the build only if SQLITE_ENABLE_MEMSYS5 is defined. +** +** $Id: mem5.c,v 1.11 2008/07/16 12:25:32 drh Exp $ +*/ +#include "sqliteInt.h" + +/* +** This version of the memory allocator is used only when +** SQLITE_POW2_MEMORY_SIZE is defined. +*/ +#ifdef SQLITE_ENABLE_MEMSYS5 + +/* +** Log2 of the minimum size of an allocation. For example, if +** 4 then all allocations will be rounded up to at least 16 bytes. +** If 5 then all allocations will be rounded up to at least 32 bytes. +*/ +#ifndef SQLITE_POW2_LOGMIN +# define SQLITE_POW2_LOGMIN 6 +#endif + +/* +** Log2 of the maximum size of an allocation. +*/ +#ifndef SQLITE_POW2_LOGMAX +# define SQLITE_POW2_LOGMAX 20 +#endif +#define POW2_MAX (((unsigned int)1)<<SQLITE_POW2_LOGMAX) + +/* +** Number of distinct allocation sizes. +*/ +#define NSIZE (SQLITE_POW2_LOGMAX - SQLITE_POW2_LOGMIN + 1) + +/* +** A minimum allocation is an instance of the following structure. +** Larger allocations are an array of these structures where the +** size of the array is a power of 2. +*/ +typedef struct Mem5Link Mem5Link; +struct Mem5Link { + int next; /* Index of next free chunk */ + int prev; /* Index of previous free chunk */ +}; + +/* +** Maximum size of any allocation is ((1<<LOGMAX)*mem5.nAtom). Since +** mem5.nAtom is always at least 8, this is not really a practical +** limitation. +*/ +#define LOGMAX 30 + +/* +** Masks used for mem5.aCtrl[] elements. +*/ +#define CTRL_LOGSIZE 0x1f /* Log2 Size of this block relative to POW2_MIN */ +#define CTRL_FREE 0x20 /* True if not checked out */ + +/* +** All of the static variables used by this module are collected +** into a single structure named "mem5". This is to keep the +** static variables organized and to reduce namespace pollution +** when this module is combined with other in the amalgamation. +*/ +static struct { + /* + ** The alarm callback and its arguments. The mem5.mutex lock will + ** be held while the callback is running. Recursive calls into + ** the memory subsystem are allowed, but no new callbacks will be + ** issued. The alarmBusy variable is set to prevent recursive + ** callbacks. + */ + sqlite3_int64 alarmThreshold; + void (*alarmCallback)(void*, sqlite3_int64,int); + void *alarmArg; + int alarmBusy; + + /* + ** Mutex to control access to the memory allocation subsystem. + */ + sqlite3_mutex *mutex; + + /* + ** Performance statistics + */ + u64 nAlloc; /* Total number of calls to malloc */ + u64 totalAlloc; /* Total of all malloc calls - includes internal frag */ + u64 totalExcess; /* Total internal fragmentation */ + u32 currentOut; /* Current checkout, including internal fragmentation */ + u32 currentCount; /* Current number of distinct checkouts */ + u32 maxOut; /* Maximum instantaneous currentOut */ + u32 maxCount; /* Maximum instantaneous currentCount */ + u32 maxRequest; /* Largest allocation (exclusive of internal frag) */ + + /* + ** Lists of free blocks of various sizes. + */ + int aiFreelist[LOGMAX+1]; + + /* + ** Space for tracking which blocks are checked out and the size + ** of each block. One byte per block. + */ + u8 *aCtrl; + + /* + ** Memory available for allocation + */ + int nAtom; /* Smallest possible allocation in bytes */ + int nBlock; /* Number of nAtom sized blocks in zPool */ + u8 *zPool; +} mem5; + +#define MEM5LINK(idx) ((Mem5Link *)(&mem5.zPool[(idx)*mem5.nAtom])) + +/* +** Unlink the chunk at mem5.aPool[i] from list it is currently +** on. It should be found on mem5.aiFreelist[iLogsize]. +*/ +static void memsys5Unlink(int i, int iLogsize){ + int next, prev; + assert( i>=0 && i<mem5.nBlock ); + assert( iLogsize>=0 && iLogsize<=LOGMAX ); + assert( (mem5.aCtrl[i] & CTRL_LOGSIZE)==iLogsize ); + + next = MEM5LINK(i)->next; + prev = MEM5LINK(i)->prev; + if( prev<0 ){ + mem5.aiFreelist[iLogsize] = next; + }else{ + MEM5LINK(prev)->next = next; + } + if( next>=0 ){ + MEM5LINK(next)->prev = prev; + } +} + +/* +** Link the chunk at mem5.aPool[i] so that is on the iLogsize +** free list. +*/ +static void memsys5Link(int i, int iLogsize){ + int x; + assert( sqlite3_mutex_held(mem5.mutex) ); + assert( i>=0 && i<mem5.nBlock ); + assert( iLogsize>=0 && iLogsize<=LOGMAX ); + assert( (mem5.aCtrl[i] & CTRL_LOGSIZE)==iLogsize ); + + x = MEM5LINK(i)->next = mem5.aiFreelist[iLogsize]; + MEM5LINK(i)->prev = -1; + if( x>=0 ){ + assert( x<mem5.nBlock ); + MEM5LINK(x)->prev = i; + } + mem5.aiFreelist[iLogsize] = i; +} + +/* +** If the STATIC_MEM mutex is not already held, obtain it now. The mutex +** will already be held (obtained by code in malloc.c) if +** sqlite3Config.bMemStat is true. +*/ +static void memsys5Enter(void){ + if( sqlite3Config.bMemstat==0 && mem5.mutex==0 ){ + mem5.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); + } + sqlite3_mutex_enter(mem5.mutex); +} +static void memsys5Leave(void){ + sqlite3_mutex_leave(mem5.mutex); +} + +/* +** Return the size of an outstanding allocation, in bytes. The +** size returned omits the 8-byte header overhead. This only +** works for chunks that are currently checked out. +*/ +static int memsys5Size(void *p){ + int iSize = 0; + if( p ){ + int i = ((u8 *)p-mem5.zPool)/mem5.nAtom; + assert( i>=0 && i<mem5.nBlock ); + iSize = mem5.nAtom * (1 << (mem5.aCtrl[i]&CTRL_LOGSIZE)); + } + return iSize; +} + +/* +** Find the first entry on the freelist iLogsize. Unlink that +** entry and return its index. +*/ +static int memsys5UnlinkFirst(int iLogsize){ + int i; + int iFirst; + + assert( iLogsize>=0 && iLogsize<=LOGMAX ); + i = iFirst = mem5.aiFreelist[iLogsize]; + assert( iFirst>=0 ); + while( i>0 ){ + if( i<iFirst ) iFirst = i; + i = MEM5LINK(i)->next; + } + memsys5Unlink(iFirst, iLogsize); + return iFirst; +} + +/* +** Return a block of memory of at least nBytes in size. +** Return NULL if unable. +*/ +static void *memsys5MallocUnsafe(int nByte){ + int i; /* Index of a mem5.aPool[] slot */ + int iBin; /* Index into mem5.aiFreelist[] */ + int iFullSz; /* Size of allocation rounded up to power of 2 */ + int iLogsize; /* Log2 of iFullSz/POW2_MIN */ + + /* Keep track of the maximum allocation request. Even unfulfilled + ** requests are counted */ + if( nByte>mem5.maxRequest ){ + mem5.maxRequest = nByte; + } + + /* Round nByte up to the next valid power of two */ + if( nByte>POW2_MAX ) return 0; + for(iFullSz=mem5.nAtom, iLogsize=0; iFullSz<nByte; iFullSz *= 2, iLogsize++){} + + /* Make sure mem5.aiFreelist[iLogsize] contains at least one free + ** block. If not, then split a block of the next larger power of + ** two in order to create a new free block of size iLogsize. + */ + for(iBin=iLogsize; mem5.aiFreelist[iBin]<0 && iBin<=LOGMAX; iBin++){} + if( iBin>LOGMAX ) return 0; + i = memsys5UnlinkFirst(iBin); + while( iBin>iLogsize ){ + int newSize; + + iBin--; + newSize = 1 << iBin; + mem5.aCtrl[i+newSize] = CTRL_FREE | iBin; + memsys5Link(i+newSize, iBin); + } + mem5.aCtrl[i] = iLogsize; + + /* Update allocator performance statistics. */ + mem5.nAlloc++; + mem5.totalAlloc += iFullSz; + mem5.totalExcess += iFullSz - nByte; + mem5.currentCount++; + mem5.currentOut += iFullSz; + if( mem5.maxCount<mem5.currentCount ) mem5.maxCount = mem5.currentCount; + if( mem5.maxOut<mem5.currentOut ) mem5.maxOut = mem5.currentOut; + + /* Return a pointer to the allocated memory. */ + return (void*)&mem5.zPool[i*mem5.nAtom]; +} + +/* +** Free an outstanding memory allocation. +*/ +static void memsys5FreeUnsafe(void *pOld){ + u32 size, iLogsize; + int iBlock; + + /* Set iBlock to the index of the block pointed to by pOld in + ** the array of mem5.nAtom byte blocks pointed to by mem5.zPool. + */ + iBlock = ((u8 *)pOld-mem5.zPool)/mem5.nAtom; + + /* Check that the pointer pOld points to a valid, non-free block. */ + assert( iBlock>=0 && iBlock<mem5.nBlock ); + assert( ((u8 *)pOld-mem5.zPool)%mem5.nAtom==0 ); + assert( (mem5.aCtrl[iBlock] & CTRL_FREE)==0 ); + + iLogsize = mem5.aCtrl[iBlock] & CTRL_LOGSIZE; + size = 1<<iLogsize; + assert( iBlock+size-1<mem5.nBlock ); + + mem5.aCtrl[iBlock] |= CTRL_FREE; + mem5.aCtrl[iBlock+size-1] |= CTRL_FREE; + assert( mem5.currentCount>0 ); + assert( mem5.currentOut>=0 ); + mem5.currentCount--; + mem5.currentOut -= size*mem5.nAtom; + assert( mem5.currentOut>0 || mem5.currentCount==0 ); + assert( mem5.currentCount>0 || mem5.currentOut==0 ); + + mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize; + while( iLogsize<LOGMAX ){ + int iBuddy; + if( (iBlock>>iLogsize) & 1 ){ + iBuddy = iBlock - size; + }else{ + iBuddy = iBlock + size; + } + assert( iBuddy>=0 ); + if( (iBuddy+(1<<iLogsize))>mem5.nBlock ) break; + if( mem5.aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break; + memsys5Unlink(iBuddy, iLogsize); + iLogsize++; + if( iBuddy<iBlock ){ + mem5.aCtrl[iBuddy] = CTRL_FREE | iLogsize; + mem5.aCtrl[iBlock] = 0; + iBlock = iBuddy; + }else{ + mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize; + mem5.aCtrl[iBuddy] = 0; + } + size *= 2; + } + memsys5Link(iBlock, iLogsize); +} + +/* +** Allocate nBytes of memory +*/ +static void *memsys5Malloc(int nBytes){ + sqlite3_int64 *p = 0; + if( nBytes>0 ){ + memsys5Enter(); + p = memsys5MallocUnsafe(nBytes); + memsys5Leave(); + } + return (void*)p; +} + +/* +** Free memory. +*/ +static void memsys5Free(void *pPrior){ + if( pPrior==0 ){ +assert(0); + return; + } + memsys5Enter(); + memsys5FreeUnsafe(pPrior); + memsys5Leave(); +} + +/* +** Change the size of an existing memory allocation +*/ +static void *memsys5Realloc(void *pPrior, int nBytes){ + int nOld; + void *p; + if( pPrior==0 ){ + return memsys5Malloc(nBytes); + } + if( nBytes<=0 ){ + memsys5Free(pPrior); + return 0; + } + nOld = memsys5Size(pPrior); + if( nBytes<=nOld ){ + return pPrior; + } + memsys5Enter(); + p = memsys5MallocUnsafe(nBytes); + if( p ){ + memcpy(p, pPrior, nOld); + memsys5FreeUnsafe(pPrior); + } + memsys5Leave(); + return p; +} + +/* +** Round up a request size to the next valid allocation size. +*/ +static int memsys5Roundup(int n){ + int iFullSz; + for(iFullSz=mem5.nAtom; iFullSz<n; iFullSz *= 2); + return iFullSz; +} + +static int memsys5Log(int iValue){ + int iLog; + for(iLog=0; (1<<iLog)<iValue; iLog++); + return iLog; +} + +/* +** Initialize this module. +*/ +static int memsys5Init(void *NotUsed){ + int ii; + int nByte = sqlite3Config.nHeap; + u8 *zByte = (u8 *)sqlite3Config.pHeap; + int nMinLog; /* Log of minimum allocation size in bytes*/ + int iOffset; + + if( !zByte ){ + return SQLITE_ERROR; + } + + nMinLog = memsys5Log(sqlite3Config.mnReq); + mem5.nAtom = (1<<nMinLog); + while( sizeof(Mem5Link)>mem5.nAtom ){ + mem5.nAtom = mem5.nAtom << 1; + } + + mem5.nBlock = (nByte / (mem5.nAtom+sizeof(u8))); + mem5.zPool = zByte; + mem5.aCtrl = (u8 *)&mem5.zPool[mem5.nBlock*mem5.nAtom]; + + for(ii=0; ii<=LOGMAX; ii++){ + mem5.aiFreelist[ii] = -1; + } + + iOffset = 0; + for(ii=LOGMAX; ii>=0; ii--){ + int nAlloc = (1<<ii); + if( (iOffset+nAlloc)<=mem5.nBlock ){ + mem5.aCtrl[iOffset] = ii | CTRL_FREE; + memsys5Link(iOffset, ii); + iOffset += nAlloc; + } + assert((iOffset+nAlloc)>mem5.nBlock); + } + + return SQLITE_OK; +} + +/* +** Deinitialize this module. +*/ +static void memsys5Shutdown(void *NotUsed){ + return; +} + +/* +** Open the file indicated and write a log of all unfreed memory +** allocations into that log. +*/ +void sqlite3Memsys5Dump(const char *zFilename){ +#ifdef SQLITE_DEBUG + FILE *out; + int i, j, n; + int nMinLog; + + if( zFilename==0 || zFilename[0]==0 ){ + out = stdout; + }else{ + out = fopen(zFilename, "w"); + if( out==0 ){ + fprintf(stderr, "** Unable to output memory debug output log: %s **\n", + zFilename); + return; + } + } + memsys5Enter(); + nMinLog = memsys5Log(mem5.nAtom); + for(i=0; i<=LOGMAX && i+nMinLog<32; i++){ + for(n=0, j=mem5.aiFreelist[i]; j>=0; j = MEM5LINK(j)->next, n++){} + fprintf(out, "freelist items of size %d: %d\n", mem5.nAtom << i, n); + } + fprintf(out, "mem5.nAlloc = %llu\n", mem5.nAlloc); + fprintf(out, "mem5.totalAlloc = %llu\n", mem5.totalAlloc); + fprintf(out, "mem5.totalExcess = %llu\n", mem5.totalExcess); + fprintf(out, "mem5.currentOut = %u\n", mem5.currentOut); + fprintf(out, "mem5.currentCount = %u\n", mem5.currentCount); + fprintf(out, "mem5.maxOut = %u\n", mem5.maxOut); + fprintf(out, "mem5.maxCount = %u\n", mem5.maxCount); + fprintf(out, "mem5.maxRequest = %u\n", mem5.maxRequest); + memsys5Leave(); + if( out==stdout ){ + fflush(stdout); + }else{ + fclose(out); + } +#endif +} + +/* +** This routine is the only routine in this file with external +** linkage. It returns a pointer to a static sqlite3_mem_methods +** struct populated with the memsys5 methods. +*/ +const sqlite3_mem_methods *sqlite3MemGetMemsys5(void){ + static const sqlite3_mem_methods memsys5Methods = { + memsys5Malloc, + memsys5Free, + memsys5Realloc, + memsys5Size, + memsys5Roundup, + memsys5Init, + memsys5Shutdown, + 0 + }; + return &memsys5Methods; +} + +#endif /* SQLITE_ENABLE_MEMSYS5 */ diff --git a/third_party/sqlite/src/mem6.c b/third_party/sqlite/src/mem6.c new file mode 100755 index 0000000..95723ad --- /dev/null +++ b/third_party/sqlite/src/mem6.c @@ -0,0 +1,496 @@ +/* +** 2008 July 24 +** +** 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 an alternative memory allocation system for SQLite. +** This system is implemented as a wrapper around the system provided +** by the operating system - vanilla malloc(), realloc() and free(). +** +** This system differentiates between requests for "small" allocations +** (by default those of 128 bytes or less) and "large" allocations (all +** others). The 256 byte threshhold is configurable at runtime. +** +** All requests for large allocations are passed through to the +** default system. +** +** Requests for small allocations are met by allocating space within +** one or more larger "chunks" of memory obtained from the default +** memory allocation system. Chunks of memory are usually 64KB or +** larger. The algorithm used to manage space within each chunk is +** the same as that used by mem5.c. +** +** This strategy is designed to prevent the default memory allocation +** system (usually the system malloc) from suffering from heap +** fragmentation. On some systems, heap fragmentation can cause a +** significant real-time slowdown. +** +** $Id: mem6.c,v 1.7 2008/07/28 19:34:53 drh Exp $ +*/ + +#ifdef SQLITE_ENABLE_MEMSYS6 + +#include "sqliteInt.h" + +/* +** Maximum size of any "small" allocation is ((1<<LOGMAX)*Mem6Chunk.nAtom). +** Mem6Chunk.nAtom is always at least 8, so this is not a practical +** limitation +*/ +#define LOGMAX 30 + +/* +** Default value for the "small" allocation size threshold. +*/ +#define SMALL_MALLOC_DEFAULT_THRESHOLD 256 + +/* +** Minimum size for a memory chunk. +*/ +#define MIN_CHUNKSIZE (1<<16) + +#define LOG2_MINALLOC 4 + + +typedef struct Mem6Chunk Mem6Chunk; +typedef struct Mem6Link Mem6Link; + +/* +** A minimum allocation is an instance of the following structure. +** Larger allocations are an array of these structures where the +** size of the array is a power of 2. +*/ +struct Mem6Link { + int next; /* Index of next free chunk */ + int prev; /* Index of previous free chunk */ +}; + +/* +** Masks used for mem5.aCtrl[] elements. +*/ +#define CTRL_LOGSIZE 0x1f /* Log2 Size of this block relative to POW2_MIN */ +#define CTRL_FREE 0x20 /* True if not checked out */ + +struct Mem6Chunk { + Mem6Chunk *pNext; + + /* + ** Lists of free blocks of various sizes. + */ + int aiFreelist[LOGMAX+1]; + + int nCheckedOut; /* Number of currently outstanding allocations */ + + /* + ** Space for tracking which blocks are checked out and the size + ** of each block. One byte per block. + */ + u8 *aCtrl; + + /* + ** Memory available for allocation + */ + int nAtom; /* Smallest possible allocation in bytes */ + int nBlock; /* Number of nAtom sized blocks in zPool */ + u8 *zPool; /* Pointer to memory chunk from which allocations are made */ +}; + +#define MEM6LINK(idx) ((Mem6Link *)(&pChunk->zPool[(idx)*pChunk->nAtom])) + +struct Mem6Global { + int nMinAlloc; /* Minimum allowed allocation size */ + int nThreshold; /* Allocs larger than this go to malloc() */ + int nLogThreshold; /* log2 of (nThreshold/nMinAlloc) */ + sqlite3_mutex *mutex; + Mem6Chunk *pChunk; /* Singly linked list of all memory chunks */ +} mem6; + +/* +** Unlink the chunk at pChunk->aPool[i] from list it is currently +** on. It should be found on pChunk->aiFreelist[iLogsize]. +*/ +static void memsys6Unlink(Mem6Chunk *pChunk, int i, int iLogsize){ + int next, prev; + assert( i>=0 && i<pChunk->nBlock ); + assert( iLogsize>=0 && iLogsize<=mem6.nLogThreshold ); + assert( (pChunk->aCtrl[i] & CTRL_LOGSIZE)==iLogsize ); + + next = MEM6LINK(i)->next; + prev = MEM6LINK(i)->prev; + if( prev<0 ){ + pChunk->aiFreelist[iLogsize] = next; + }else{ + MEM6LINK(prev)->next = next; + } + if( next>=0 ){ + MEM6LINK(next)->prev = prev; + } +} + +/* +** Link the chunk at mem5.aPool[i] so that is on the iLogsize +** free list. +*/ +static void memsys6Link(Mem6Chunk *pChunk, int i, int iLogsize){ + int x; + assert( i>=0 && i<pChunk->nBlock ); + assert( iLogsize>=0 && iLogsize<=mem6.nLogThreshold ); + assert( (pChunk->aCtrl[i] & CTRL_LOGSIZE)==iLogsize ); + + x = MEM6LINK(i)->next = pChunk->aiFreelist[iLogsize]; + MEM6LINK(i)->prev = -1; + if( x>=0 ){ + assert( x<pChunk->nBlock ); + MEM6LINK(x)->prev = i; + } + pChunk->aiFreelist[iLogsize] = i; +} + + +/* +** Find the first entry on the freelist iLogsize. Unlink that +** entry and return its index. +*/ +static int memsys6UnlinkFirst(Mem6Chunk *pChunk, int iLogsize){ + int i; + int iFirst; + + assert( iLogsize>=0 && iLogsize<=mem6.nLogThreshold ); + i = iFirst = pChunk->aiFreelist[iLogsize]; + assert( iFirst>=0 ); + memsys6Unlink(pChunk, iFirst, iLogsize); + return iFirst; +} + +static int roundupLog2(int n){ + static const char LogTable256[256] = { + 0, /* 1 */ + 1, /* 2 */ + 2, 2, /* 3..4 */ + 3, 3, 3, 3, /* 5..8 */ + 4, 4, 4, 4, 4, 4, 4, 4, /* 9..16 */ + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, /* 17..32 */ + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, /* 33..64 */ + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, /* 65..128 */ + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, /* 129..256 */ + }; + + assert(n<=(1<<16) && n>0); + if( n<=256 ) return LogTable256[n-1]; + return LogTable256[(n>>8) - ((n&0xFF)?0:1)] + 8; +} + +/* +** Allocate and return a block of (pChunk->nAtom << iLogsize) bytes from chunk +** pChunk. If the allocation request cannot be satisfied, return 0. +*/ +static void *chunkMalloc(Mem6Chunk *pChunk, int iLogsize){ + int i; /* Index of a mem5.aPool[] slot */ + int iBin; /* Index into mem5.aiFreelist[] */ + + /* Make sure mem5.aiFreelist[iLogsize] contains at least one free + ** block. If not, then split a block of the next larger power of + ** two in order to create a new free block of size iLogsize. + */ + for(iBin=iLogsize; pChunk->aiFreelist[iBin]<0 && iBin<=mem6.nLogThreshold; iBin++){} + if( iBin>mem6.nLogThreshold ) return 0; + i = memsys6UnlinkFirst(pChunk, iBin); + while( iBin>iLogsize ){ + int newSize; + iBin--; + newSize = 1 << iBin; + pChunk->aCtrl[i+newSize] = CTRL_FREE | iBin; + memsys6Link(pChunk, i+newSize, iBin); + } + pChunk->aCtrl[i] = iLogsize; + + /* Return a pointer to the allocated memory. */ + pChunk->nCheckedOut++; + return (void*)&pChunk->zPool[i*pChunk->nAtom]; +} + +/* +** Free the allocation pointed to by p, which is guaranteed to be non-zero +** and a part of chunk object pChunk. +*/ +static void chunkFree(Mem6Chunk *pChunk, void *pOld){ + u32 size, iLogsize; + int iBlock; + + /* Set iBlock to the index of the block pointed to by pOld in + ** the array of pChunk->nAtom byte blocks pointed to by pChunk->zPool. + */ + iBlock = ((u8 *)pOld-pChunk->zPool)/pChunk->nAtom; + + /* Check that the pointer pOld points to a valid, non-free block. */ + assert( iBlock>=0 && iBlock<pChunk->nBlock ); + assert( ((u8 *)pOld-pChunk->zPool)%pChunk->nAtom==0 ); + assert( (pChunk->aCtrl[iBlock] & CTRL_FREE)==0 ); + + iLogsize = pChunk->aCtrl[iBlock] & CTRL_LOGSIZE; + size = 1<<iLogsize; + assert( iBlock+size-1<pChunk->nBlock ); + + pChunk->aCtrl[iBlock] |= CTRL_FREE; + pChunk->aCtrl[iBlock+size-1] |= CTRL_FREE; + + pChunk->aCtrl[iBlock] = CTRL_FREE | iLogsize; + while( iLogsize<mem6.nLogThreshold ){ + int iBuddy; + if( (iBlock>>iLogsize) & 1 ){ + iBuddy = iBlock - size; + }else{ + iBuddy = iBlock + size; + } + assert( iBuddy>=0 ); + if( (iBuddy+(1<<iLogsize))>pChunk->nBlock ) break; + if( pChunk->aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break; + memsys6Unlink(pChunk, iBuddy, iLogsize); + iLogsize++; + if( iBuddy<iBlock ){ + pChunk->aCtrl[iBuddy] = CTRL_FREE | iLogsize; + pChunk->aCtrl[iBlock] = 0; + iBlock = iBuddy; + }else{ + pChunk->aCtrl[iBlock] = CTRL_FREE | iLogsize; + pChunk->aCtrl[iBuddy] = 0; + } + size *= 2; + } + pChunk->nCheckedOut--; + memsys6Link(pChunk, iBlock, iLogsize); +} + +/* +** Return the actual size of the block pointed to by p, which is guaranteed +** to have been allocated from chunk pChunk. +*/ +static int chunkSize(Mem6Chunk *pChunk, void *p){ + int iSize = 0; + if( p ){ + int i = ((u8 *)p-pChunk->zPool)/pChunk->nAtom; + assert( i>=0 && i<pChunk->nBlock ); + iSize = pChunk->nAtom * (1 << (pChunk->aCtrl[i]&CTRL_LOGSIZE)); + } + return iSize; +} + +/* +** Return true if there are currently no outstanding allocations. +*/ +static int chunkIsEmpty(Mem6Chunk *pChunk){ + return (pChunk->nCheckedOut==0); +} + +/* +** Initialize the buffer zChunk, which is nChunk bytes in size, as +** an Mem6Chunk object. Return a copy of the zChunk pointer. +*/ +static Mem6Chunk *chunkInit(u8 *zChunk, int nChunk, int nMinAlloc){ + int ii; + int iOffset; + Mem6Chunk *pChunk = (Mem6Chunk *)zChunk; + + assert( nChunk>sizeof(Mem6Chunk) ); + assert( nMinAlloc>sizeof(Mem6Link) ); + + memset(pChunk, 0, sizeof(Mem6Chunk)); + pChunk->nAtom = nMinAlloc; + pChunk->nBlock = ((nChunk-sizeof(Mem6Chunk)) / (pChunk->nAtom+sizeof(u8))); + + pChunk->zPool = (u8 *)&pChunk[1]; + pChunk->aCtrl = &pChunk->zPool[pChunk->nBlock*pChunk->nAtom]; + + for(ii=0; ii<=mem6.nLogThreshold; ii++){ + pChunk->aiFreelist[ii] = -1; + } + + iOffset = 0; + for(ii=mem6.nLogThreshold; ii>=0; ii--){ + int nAlloc = (1<<ii); + while( (iOffset+nAlloc)<=pChunk->nBlock ){ + pChunk->aCtrl[iOffset] = ii | CTRL_FREE; + memsys6Link(pChunk, iOffset, ii); + iOffset += nAlloc; + } + } + + return pChunk; +} + + +static void mem6Enter(void){ + sqlite3_mutex_enter(mem6.mutex); +} + +static void mem6Leave(void){ + sqlite3_mutex_leave(mem6.mutex); +} + +/* +** Based on the number and size of the currently allocated chunks, return +** the size of the next chunk to allocate, in bytes. +*/ +static int nextChunkSize(void){ + int iTotal = MIN_CHUNKSIZE; + Mem6Chunk *p; + for(p=mem6.pChunk; p; p=p->pNext){ + iTotal = iTotal*2; + } + return iTotal; +} + +static void freeChunk(Mem6Chunk *pChunk){ + Mem6Chunk **pp = &mem6.pChunk; + for( pp=&mem6.pChunk; *pp!=pChunk; pp = &(*pp)->pNext ); + *pp = (*pp)->pNext; + free(pChunk); +} + +static void *memsys6Malloc(int nByte){ + Mem6Chunk *pChunk; + void *p = 0; + int nTotal = nByte+8; + int iOffset = 0; + + if( nTotal>mem6.nThreshold ){ + p = malloc(nTotal); + }else{ + int iLogsize = 0; + if( nTotal>(1<<LOG2_MINALLOC) ){ + iLogsize = roundupLog2(nTotal) - LOG2_MINALLOC; + } + mem6Enter(); + for(pChunk=mem6.pChunk; pChunk; pChunk=pChunk->pNext){ + p = chunkMalloc(pChunk, iLogsize); + if( p ){ + break; + } + } + if( !p ){ + int iSize = nextChunkSize(); + p = malloc(iSize); + if( p ){ + pChunk = chunkInit((u8 *)p, iSize, mem6.nMinAlloc); + pChunk->pNext = mem6.pChunk; + mem6.pChunk = pChunk; + p = chunkMalloc(pChunk, iLogsize); + assert(p); + } + } + iOffset = ((u8*)p - (u8*)pChunk); + mem6Leave(); + } + + if( !p ){ + return 0; + } + ((u32 *)p)[0] = iOffset; + ((u32 *)p)[1] = nByte; + return &((u32 *)p)[2]; +} + +static int memsys6Size(void *pPrior){ + if( pPrior==0 ) return 0; + return ((u32*)pPrior)[-1]; +} + +static void memsys6Free(void *pPrior){ + int iSlot; + void *p = &((u32 *)pPrior)[-2]; + iSlot = ((u32 *)p)[0]; + if( iSlot ){ + Mem6Chunk *pChunk; + mem6Enter(); + pChunk = (Mem6Chunk *)(&((u8 *)p)[-1 * iSlot]); + chunkFree(pChunk, p); + if( chunkIsEmpty(pChunk) ){ + freeChunk(pChunk); + } + mem6Leave(); + }else{ + free(p); + } +} + +static void *memsys6Realloc(void *p, int nByte){ + void *p2; + + if( p && nByte<=memsys6Size(p) ){ + p2 = p; + }else{ + p2 = memsys6Malloc(nByte); + if( p && p2 ){ + memcpy(p2, p, memsys6Size(p)); + memsys6Free(p); + } + } + + return p2; +} + +static int memsys6Roundup(int n){ + if( n>mem6.nThreshold ){ + return n; + }else{ + return (1<<roundupLog2(n)); + } +} + +static int memsys6Init(void *pCtx){ + u8 bMemstat = sqlite3Config.bMemstat; + mem6.nMinAlloc = (1 << LOG2_MINALLOC); + mem6.pChunk = 0; + mem6.nThreshold = sqlite3Config.nSmall; + if( mem6.nThreshold<=0 ){ + mem6.nThreshold = SMALL_MALLOC_DEFAULT_THRESHOLD; + } + mem6.nLogThreshold = roundupLog2(mem6.nThreshold) - LOG2_MINALLOC; + if( !bMemstat ){ + mem6.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); + } + return SQLITE_OK; +} + +static void memsys6Shutdown(void *pCtx){ + memset(&mem6, 0, sizeof(mem6)); +} + +/* +** This routine is the only routine in this file with external +** linkage. It returns a pointer to a static sqlite3_mem_methods +** struct populated with the memsys6 methods. +*/ +const sqlite3_mem_methods *sqlite3MemGetMemsys6(void){ + static const sqlite3_mem_methods memsys6Methods = { + memsys6Malloc, + memsys6Free, + memsys6Realloc, + memsys6Size, + memsys6Roundup, + memsys6Init, + memsys6Shutdown, + 0 + }; + return &memsys6Methods; +} + +#endif diff --git a/third_party/sqlite/src/mutex.c b/third_party/sqlite/src/mutex.c new file mode 100755 index 0000000..43e1965eb --- /dev/null +++ b/third_party/sqlite/src/mutex.c @@ -0,0 +1,273 @@ +/* +** 2007 August 14 +** +** 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 the C functions that implement mutexes. +** +** The implementation in this file does not provide any mutual +** exclusion and is thus suitable for use only in applications +** that use SQLite in a single thread. But this implementation +** does do a lot of error checking on mutexes to make sure they +** are called correctly and at appropriate times. Hence, this +** implementation is suitable for testing. +** debugging purposes +** +** $Id: mutex.c,v 1.27 2008/06/19 08:51:24 danielk1977 Exp $ +*/ +#include "sqliteInt.h" + +#ifndef SQLITE_MUTEX_NOOP +/* +** Initialize the mutex system. +*/ +int sqlite3MutexInit(void){ + int rc = SQLITE_OK; + if( sqlite3Config.bCoreMutex ){ + if( !sqlite3Config.mutex.xMutexAlloc ){ + /* If the xMutexAlloc method has not been set, then the user did not + ** install a mutex implementation via sqlite3_config() prior to + ** sqlite3_initialize() being called. This block copies pointers to + ** the default implementation into the sqlite3Config structure. + ** + ** The danger is that although sqlite3_config() is not a threadsafe + ** API, sqlite3_initialize() is, and so multiple threads may be + ** attempting to run this function simultaneously. To guard write + ** access to the sqlite3Config structure, the 'MASTER' static mutex + ** is obtained before modifying it. + */ + sqlite3_mutex_methods *p = sqlite3DefaultMutex(); + sqlite3_mutex *pMaster = 0; + + rc = p->xMutexInit(); + if( rc==SQLITE_OK ){ + pMaster = p->xMutexAlloc(SQLITE_MUTEX_STATIC_MASTER); + assert(pMaster); + p->xMutexEnter(pMaster); + assert( sqlite3Config.mutex.xMutexAlloc==0 + || sqlite3Config.mutex.xMutexAlloc==p->xMutexAlloc + ); + if( !sqlite3Config.mutex.xMutexAlloc ){ + sqlite3Config.mutex = *p; + } + p->xMutexLeave(pMaster); + } + }else{ + rc = sqlite3Config.mutex.xMutexInit(); + } + } + + return rc; +} + +/* +** Shutdown the mutex system. This call frees resources allocated by +** sqlite3MutexInit(). +*/ +int sqlite3MutexEnd(void){ + int rc = SQLITE_OK; + rc = sqlite3Config.mutex.xMutexEnd(); + return rc; +} + +/* +** Retrieve a pointer to a static mutex or allocate a new dynamic one. +*/ +sqlite3_mutex *sqlite3_mutex_alloc(int id){ +#ifndef SQLITE_OMIT_AUTOINIT + if( sqlite3_initialize() ) return 0; +#endif + return sqlite3Config.mutex.xMutexAlloc(id); +} + +sqlite3_mutex *sqlite3MutexAlloc(int id){ + if( !sqlite3Config.bCoreMutex ){ + return 0; + } + return sqlite3Config.mutex.xMutexAlloc(id); +} + +/* +** Free a dynamic mutex. +*/ +void sqlite3_mutex_free(sqlite3_mutex *p){ + if( p ){ + sqlite3Config.mutex.xMutexFree(p); + } +} + +/* +** Obtain the mutex p. If some other thread already has the mutex, block +** until it can be obtained. +*/ +void sqlite3_mutex_enter(sqlite3_mutex *p){ + if( p ){ + sqlite3Config.mutex.xMutexEnter(p); + } +} + +/* +** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another +** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY. +*/ +int sqlite3_mutex_try(sqlite3_mutex *p){ + int rc = SQLITE_OK; + if( p ){ + return sqlite3Config.mutex.xMutexTry(p); + } + return rc; +} + +/* +** The sqlite3_mutex_leave() routine exits a mutex that was previously +** entered by the same thread. The behavior is undefined if the mutex +** is not currently entered. If a NULL pointer is passed as an argument +** this function is a no-op. +*/ +void sqlite3_mutex_leave(sqlite3_mutex *p){ + if( p ){ + sqlite3Config.mutex.xMutexLeave(p); + } +} + +#ifndef NDEBUG +/* +** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are +** intended for use inside assert() statements. +*/ +int sqlite3_mutex_held(sqlite3_mutex *p){ + return p==0 || sqlite3Config.mutex.xMutexHeld(p); +} +int sqlite3_mutex_notheld(sqlite3_mutex *p){ + return p==0 || sqlite3Config.mutex.xMutexNotheld(p); +} +#endif + +#endif + +#ifdef SQLITE_MUTEX_NOOP_DEBUG +/* +** In this implementation, mutexes do not provide any mutual exclusion. +** But the error checking is provided. This implementation is useful +** for test purposes. +*/ + +/* +** The mutex object +*/ +struct sqlite3_mutex { + int id; /* The mutex type */ + int cnt; /* Number of entries without a matching leave */ +}; + +/* +** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are +** intended for use inside assert() statements. +*/ +static int noopMutexHeld(sqlite3_mutex *p){ + return p==0 || p->cnt>0; +} +static int noopMutexNotheld(sqlite3_mutex *p){ + return p==0 || p->cnt==0; +} + +/* +** Initialize and deinitialize the mutex subsystem. +*/ +static int noopMutexInit(void){ return SQLITE_OK; } +static int noopMutexEnd(void){ return SQLITE_OK; } + +/* +** The sqlite3_mutex_alloc() routine allocates a new +** mutex and returns a pointer to it. If it returns NULL +** that means that a mutex could not be allocated. +*/ +static sqlite3_mutex *noopMutexAlloc(int id){ + static sqlite3_mutex aStatic[6]; + sqlite3_mutex *pNew = 0; + switch( id ){ + case SQLITE_MUTEX_FAST: + case SQLITE_MUTEX_RECURSIVE: { + pNew = sqlite3Malloc(sizeof(*pNew)); + if( pNew ){ + pNew->id = id; + pNew->cnt = 0; + } + break; + } + default: { + assert( id-2 >= 0 ); + assert( id-2 < sizeof(aStatic)/sizeof(aStatic[0]) ); + pNew = &aStatic[id-2]; + pNew->id = id; + break; + } + } + return pNew; +} + +/* +** This routine deallocates a previously allocated mutex. +*/ +static void noopMutexFree(sqlite3_mutex *p){ + assert( p->cnt==0 ); + assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); + sqlite3_free(p); +} + +/* +** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt +** to enter a mutex. If another thread is already within the mutex, +** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return +** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK +** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can +** be entered multiple times by the same thread. In such cases the, +** mutex must be exited an equal number of times before another thread +** can enter. If the same thread tries to enter any other kind of mutex +** more than once, the behavior is undefined. +*/ +static void noopMutexEnter(sqlite3_mutex *p){ + assert( p->id==SQLITE_MUTEX_RECURSIVE || noopMutexNotheld(p) ); + p->cnt++; +} +static int noopMutexTry(sqlite3_mutex *p){ + assert( p->id==SQLITE_MUTEX_RECURSIVE || noopMutexNotheld(p) ); + p->cnt++; + return SQLITE_OK; +} + +/* +** The sqlite3_mutex_leave() routine exits a mutex that was +** previously entered by the same thread. The behavior +** is undefined if the mutex is not currently entered or +** is not currently allocated. SQLite will never do either. +*/ +static void noopMutexLeave(sqlite3_mutex *p){ + assert( noopMutexHeld(p) ); + p->cnt--; + assert( p->id==SQLITE_MUTEX_RECURSIVE || noopMutexNotheld(p) ); +} + +sqlite3_mutex_methods *sqlite3DefaultMutex(void){ + static sqlite3_mutex_methods sMutex = { + noopMutexInit, + noopMutexEnd, + noopMutexAlloc, + noopMutexFree, + noopMutexEnter, + noopMutexTry, + noopMutexLeave, + + noopMutexHeld, + noopMutexNotheld + }; + + return &sMutex; +} +#endif /* SQLITE_MUTEX_NOOP_DEBUG */ diff --git a/third_party/sqlite/src/mutex.h b/third_party/sqlite/src/mutex.h new file mode 100755 index 0000000..5f51dda --- /dev/null +++ b/third_party/sqlite/src/mutex.h @@ -0,0 +1,85 @@ +/* +** 2007 August 28 +** +** 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 the common header for all mutex implementations. +** The sqliteInt.h header #includes this file so that it is available +** to all source files. We break it out in an effort to keep the code +** better organized. +** +** NOTE: source files should *not* #include this header file directly. +** Source files should #include the sqliteInt.h file and let that file +** include this one indirectly. +** +** $Id: mutex.h,v 1.8 2008/06/26 10:41:19 danielk1977 Exp $ +*/ + + +#ifdef SQLITE_MUTEX_APPDEF +/* +** If SQLITE_MUTEX_APPDEF is defined, then this whole module is +** omitted and equivalent functionality must be provided by the +** application that links against the SQLite library. +*/ +#else +/* +** Figure out what version of the code to use. The choices are +** +** SQLITE_MUTEX_NOOP For single-threaded applications that +** do not desire error checking. +** +** SQLITE_MUTEX_NOOP_DEBUG For single-threaded applications with +** error checking to help verify that mutexes +** are being used correctly even though they +** are not needed. Used when SQLITE_DEBUG is +** defined on single-threaded builds. +** +** SQLITE_MUTEX_PTHREADS For multi-threaded applications on Unix. +** +** SQLITE_MUTEX_W32 For multi-threaded applications on Win32. +** +** SQLITE_MUTEX_OS2 For multi-threaded applications on OS/2. +*/ +#define SQLITE_MUTEX_NOOP 1 /* The default */ +#if defined(SQLITE_DEBUG) && !SQLITE_THREADSAFE +# undef SQLITE_MUTEX_NOOP +# define SQLITE_MUTEX_NOOP_DEBUG +#endif +#if defined(SQLITE_MUTEX_NOOP) && SQLITE_THREADSAFE && SQLITE_OS_UNIX +# undef SQLITE_MUTEX_NOOP +# define SQLITE_MUTEX_PTHREADS +#endif +#if defined(SQLITE_MUTEX_NOOP) && SQLITE_THREADSAFE && SQLITE_OS_WIN +# undef SQLITE_MUTEX_NOOP +# define SQLITE_MUTEX_W32 +#endif +#if defined(SQLITE_MUTEX_NOOP) && SQLITE_THREADSAFE && SQLITE_OS_OS2 +# undef SQLITE_MUTEX_NOOP +# define SQLITE_MUTEX_OS2 +#endif + +#ifdef SQLITE_MUTEX_NOOP +/* +** If this is a no-op implementation, implement everything as macros. +*/ +#define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8) +#define sqlite3_mutex_free(X) +#define sqlite3_mutex_enter(X) +#define sqlite3_mutex_try(X) SQLITE_OK +#define sqlite3_mutex_leave(X) +#define sqlite3_mutex_held(X) 1 +#define sqlite3_mutex_notheld(X) 1 +#define sqlite3MutexAlloc(X) ((sqlite3_mutex*)8) +#define sqlite3MutexInit() SQLITE_OK +#define sqlite3MutexEnd() +#endif + +#endif /* SQLITE_MUTEX_APPDEF */ diff --git a/third_party/sqlite/src/mutex_os2.c b/third_party/sqlite/src/mutex_os2.c new file mode 100755 index 0000000..6a44370 --- /dev/null +++ b/third_party/sqlite/src/mutex_os2.c @@ -0,0 +1,273 @@ +/* +** 2007 August 28 +** +** 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 the C functions that implement mutexes for OS/2 +** +** $Id: mutex_os2.c,v 1.10 2008/06/23 22:13:28 pweilbacher Exp $ +*/ +#include "sqliteInt.h" + +/* +** The code in this file is only used if SQLITE_MUTEX_OS2 is defined. +** See the mutex.h file for details. +*/ +#ifdef SQLITE_MUTEX_OS2 + +/********************** OS/2 Mutex Implementation ********************** +** +** This implementation of mutexes is built using the OS/2 API. +*/ + +/* +** The mutex object +** Each recursive mutex is an instance of the following structure. +*/ +struct sqlite3_mutex { + HMTX mutex; /* Mutex controlling the lock */ + int id; /* Mutex type */ + int nRef; /* Number of references */ + TID owner; /* Thread holding this mutex */ +}; + +#define OS2_MUTEX_INITIALIZER 0,0,0,0 + +/* +** Initialize and deinitialize the mutex subsystem. +*/ +static int os2MutexInit(void){ return SQLITE_OK; } +static int os2MutexEnd(void){ return SQLITE_OK; } + +/* +** The sqlite3_mutex_alloc() routine allocates a new +** mutex and returns a pointer to it. If it returns NULL +** that means that a mutex could not be allocated. +** SQLite will unwind its stack and return an error. The argument +** to sqlite3_mutex_alloc() is one of these integer constants: +** +** <ul> +** <li> SQLITE_MUTEX_FAST 0 +** <li> SQLITE_MUTEX_RECURSIVE 1 +** <li> SQLITE_MUTEX_STATIC_MASTER 2 +** <li> SQLITE_MUTEX_STATIC_MEM 3 +** <li> SQLITE_MUTEX_STATIC_PRNG 4 +** </ul> +** +** The first two constants cause sqlite3_mutex_alloc() to create +** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE +** is used but not necessarily so when SQLITE_MUTEX_FAST is used. +** The mutex implementation does not need to make a distinction +** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does +** not want to. But SQLite will only request a recursive mutex in +** cases where it really needs one. If a faster non-recursive mutex +** implementation is available on the host platform, the mutex subsystem +** might return such a mutex in response to SQLITE_MUTEX_FAST. +** +** The other allowed parameters to sqlite3_mutex_alloc() each return +** a pointer to a static preexisting mutex. Three static mutexes are +** used by the current version of SQLite. Future versions of SQLite +** may add additional static mutexes. Static mutexes are for internal +** use by SQLite only. Applications that use SQLite mutexes should +** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or +** SQLITE_MUTEX_RECURSIVE. +** +** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST +** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() +** returns a different mutex on every call. But for the static +** mutex types, the same mutex is returned on every call that has +** the same type number. +*/ +static sqlite3_mutex *os2MutexAlloc(int iType){ + sqlite3_mutex *p = NULL; + switch( iType ){ + case SQLITE_MUTEX_FAST: + case SQLITE_MUTEX_RECURSIVE: { + p = sqlite3MallocZero( sizeof(*p) ); + if( p ){ + p->id = iType; + if( DosCreateMutexSem( 0, &p->mutex, 0, FALSE ) != NO_ERROR ){ + sqlite3_free( p ); + p = NULL; + } + } + break; + } + default: { + static volatile int isInit = 0; + static sqlite3_mutex staticMutexes[] = { + { OS2_MUTEX_INITIALIZER, }, + { OS2_MUTEX_INITIALIZER, }, + { OS2_MUTEX_INITIALIZER, }, + { OS2_MUTEX_INITIALIZER, }, + { OS2_MUTEX_INITIALIZER, }, + { OS2_MUTEX_INITIALIZER, }, + }; + if ( !isInit ){ + APIRET rc; + PTIB ptib; + PPIB ppib; + HMTX mutex; + char name[32]; + DosGetInfoBlocks( &ptib, &ppib ); + sqlite3_snprintf( sizeof(name), name, "\\SEM32\\SQLITE%04x", + ppib->pib_ulpid ); + while( !isInit ){ + mutex = 0; + rc = DosCreateMutexSem( name, &mutex, 0, FALSE); + if( rc == NO_ERROR ){ + int i; + if( !isInit ){ + for( i = 0; i < sizeof(staticMutexes)/sizeof(staticMutexes[0]); i++ ){ + DosCreateMutexSem( 0, &staticMutexes[i].mutex, 0, FALSE ); + } + isInit = 1; + } + DosCloseMutexSem( mutex ); + }else if( rc == ERROR_DUPLICATE_NAME ){ + DosSleep( 1 ); + }else{ + return p; + } + } + } + assert( iType-2 >= 0 ); + assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) ); + p = &staticMutexes[iType-2]; + p->id = iType; + break; + } + } + return p; +} + + +/* +** This routine deallocates a previously allocated mutex. +** SQLite is careful to deallocate every mutex that it allocates. +*/ +static void os2MutexFree(sqlite3_mutex *p){ + if( p==0 ) return; + assert( p->nRef==0 ); + assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); + DosCloseMutexSem( p->mutex ); + sqlite3_free( p ); +} + +/* +** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt +** to enter a mutex. If another thread is already within the mutex, +** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return +** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK +** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can +** be entered multiple times by the same thread. In such cases the, +** mutex must be exited an equal number of times before another thread +** can enter. If the same thread tries to enter any other kind of mutex +** more than once, the behavior is undefined. +*/ +static void os2MutexEnter(sqlite3_mutex *p){ + TID tid; + PID holder1; + ULONG holder2; + if( p==0 ) return; + assert( p->id==SQLITE_MUTEX_RECURSIVE || os2MutexNotheld(p) ); + DosRequestMutexSem(p->mutex, SEM_INDEFINITE_WAIT); + DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2); + p->owner = tid; + p->nRef++; +} +static int os2MutexTry(sqlite3_mutex *p){ + int rc; + TID tid; + PID holder1; + ULONG holder2; + if( p==0 ) return SQLITE_OK; + assert( p->id==SQLITE_MUTEX_RECURSIVE || os2MutexNotheld(p) ); + if( DosRequestMutexSem(p->mutex, SEM_IMMEDIATE_RETURN) == NO_ERROR) { + DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2); + p->owner = tid; + p->nRef++; + rc = SQLITE_OK; + } else { + rc = SQLITE_BUSY; + } + + return rc; +} + +/* +** The sqlite3_mutex_leave() routine exits a mutex that was +** previously entered by the same thread. The behavior +** is undefined if the mutex is not currently entered or +** is not currently allocated. SQLite will never do either. +*/ +static void os2MutexLeave(sqlite3_mutex *p){ + TID tid; + PID holder1; + ULONG holder2; + if( p==0 ) return; + assert( p->nRef>0 ); + DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2); + assert( p->owner==tid ); + p->nRef--; + assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); + DosReleaseMutexSem(p->mutex); +} + +#ifdef SQLITE_DEBUG +/* +** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are +** intended for use inside assert() statements. +*/ +static int os2MutexHeld(sqlite3_mutex *p){ + TID tid; + PID pid; + ULONG ulCount; + PTIB ptib; + if( p!=0 ) { + DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount); + } else { + DosGetInfoBlocks(&ptib, NULL); + tid = ptib->tib_ptib2->tib2_ultid; + } + return p==0 || (p->nRef!=0 && p->owner==tid); +} +static int os2MutexNotheld(sqlite3_mutex *p){ + TID tid; + PID pid; + ULONG ulCount; + PTIB ptib; + if( p!= 0 ) { + DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount); + } else { + DosGetInfoBlocks(&ptib, NULL); + tid = ptib->tib_ptib2->tib2_ultid; + } + return p==0 || p->nRef==0 || p->owner!=tid; +} +#endif + +sqlite3_mutex_methods *sqlite3DefaultMutex(void){ + static sqlite3_mutex_methods sMutex = { + os2MutexInit, + os2MutexEnd, + os2MutexAlloc, + os2MutexFree, + os2MutexEnter, + os2MutexTry, + os2MutexLeave, +#ifdef SQLITE_DEBUG + os2MutexHeld, + os2MutexNotheld +#endif + }; + + return &sMutex; +} +#endif /* SQLITE_MUTEX_OS2 */ diff --git a/third_party/sqlite/src/mutex_unix.c b/third_party/sqlite/src/mutex_unix.c new file mode 100755 index 0000000..31f9a97 --- /dev/null +++ b/third_party/sqlite/src/mutex_unix.c @@ -0,0 +1,325 @@ +/* +** 2007 August 28 +** +** 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 the C functions that implement mutexes for pthreads +** +** $Id: mutex_unix.c,v 1.13 2008/07/16 12:33:24 drh Exp $ +*/ +#include "sqliteInt.h" + +/* +** The code in this file is only used if we are compiling threadsafe +** under unix with pthreads. +** +** Note that this implementation requires a version of pthreads that +** supports recursive mutexes. +*/ +#ifdef SQLITE_MUTEX_PTHREADS + +#include <pthread.h> + + +/* +** Each recursive mutex is an instance of the following structure. +*/ +struct sqlite3_mutex { + pthread_mutex_t mutex; /* Mutex controlling the lock */ + int id; /* Mutex type */ + int nRef; /* Number of entrances */ + pthread_t owner; /* Thread that is within this mutex */ +#ifdef SQLITE_DEBUG + int trace; /* True to trace changes */ +#endif +}; +#ifdef SQLITE_DEBUG +#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0, 0, (pthread_t)0, 0 } +#else +#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0, 0, (pthread_t)0 } +#endif + +/* +** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are +** intended for use only inside assert() statements. On some platforms, +** there might be race conditions that can cause these routines to +** deliver incorrect results. In particular, if pthread_equal() is +** not an atomic operation, then these routines might delivery +** incorrect results. On most platforms, pthread_equal() is a +** comparison of two integers and is therefore atomic. But we are +** told that HPUX is not such a platform. If so, then these routines +** will not always work correctly on HPUX. +** +** On those platforms where pthread_equal() is not atomic, SQLite +** should be compiled without -DSQLITE_DEBUG and with -DNDEBUG to +** make sure no assert() statements are evaluated and hence these +** routines are never called. +*/ +#ifndef NDEBUG +static int pthreadMutexHeld(sqlite3_mutex *p){ + return (p->nRef!=0 && pthread_equal(p->owner, pthread_self())); +} +static int pthreadMutexNotheld(sqlite3_mutex *p){ + return p->nRef==0 || pthread_equal(p->owner, pthread_self())==0; +} +#endif + +/* +** Initialize and deinitialize the mutex subsystem. +*/ +static int pthreadMutexInit(void){ return SQLITE_OK; } +static int pthreadMutexEnd(void){ return SQLITE_OK; } + +/* +** The sqlite3_mutex_alloc() routine allocates a new +** mutex and returns a pointer to it. If it returns NULL +** that means that a mutex could not be allocated. SQLite +** will unwind its stack and return an error. The argument +** to sqlite3_mutex_alloc() is one of these integer constants: +** +** <ul> +** <li> SQLITE_MUTEX_FAST +** <li> SQLITE_MUTEX_RECURSIVE +** <li> SQLITE_MUTEX_STATIC_MASTER +** <li> SQLITE_MUTEX_STATIC_MEM +** <li> SQLITE_MUTEX_STATIC_MEM2 +** <li> SQLITE_MUTEX_STATIC_PRNG +** <li> SQLITE_MUTEX_STATIC_LRU +** </ul> +** +** The first two constants cause sqlite3_mutex_alloc() to create +** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE +** is used but not necessarily so when SQLITE_MUTEX_FAST is used. +** The mutex implementation does not need to make a distinction +** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does +** not want to. But SQLite will only request a recursive mutex in +** cases where it really needs one. If a faster non-recursive mutex +** implementation is available on the host platform, the mutex subsystem +** might return such a mutex in response to SQLITE_MUTEX_FAST. +** +** The other allowed parameters to sqlite3_mutex_alloc() each return +** a pointer to a static preexisting mutex. Three static mutexes are +** used by the current version of SQLite. Future versions of SQLite +** may add additional static mutexes. Static mutexes are for internal +** use by SQLite only. Applications that use SQLite mutexes should +** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or +** SQLITE_MUTEX_RECURSIVE. +** +** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST +** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() +** returns a different mutex on every call. But for the static +** mutex types, the same mutex is returned on every call that has +** the same type number. +*/ +static sqlite3_mutex *pthreadMutexAlloc(int iType){ + static sqlite3_mutex staticMutexes[] = { + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER + }; + sqlite3_mutex *p; + switch( iType ){ + case SQLITE_MUTEX_RECURSIVE: { + p = sqlite3MallocZero( sizeof(*p) ); + if( p ){ +#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX + /* If recursive mutexes are not available, we will have to + ** build our own. See below. */ + pthread_mutex_init(&p->mutex, 0); +#else + /* Use a recursive mutex if it is available */ + pthread_mutexattr_t recursiveAttr; + pthread_mutexattr_init(&recursiveAttr); + pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&p->mutex, &recursiveAttr); + pthread_mutexattr_destroy(&recursiveAttr); +#endif + p->id = iType; + } + break; + } + case SQLITE_MUTEX_FAST: { + p = sqlite3MallocZero( sizeof(*p) ); + if( p ){ + p->id = iType; + pthread_mutex_init(&p->mutex, 0); + } + break; + } + default: { + assert( iType-2 >= 0 ); + assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) ); + p = &staticMutexes[iType-2]; + p->id = iType; + break; + } + } + return p; +} + + +/* +** This routine deallocates a previously +** allocated mutex. SQLite is careful to deallocate every +** mutex that it allocates. +*/ +static void pthreadMutexFree(sqlite3_mutex *p){ + assert( p->nRef==0 ); + assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); + pthread_mutex_destroy(&p->mutex); + sqlite3_free(p); +} + +/* +** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt +** to enter a mutex. If another thread is already within the mutex, +** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return +** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK +** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can +** be entered multiple times by the same thread. In such cases the, +** mutex must be exited an equal number of times before another thread +** can enter. If the same thread tries to enter any other kind of mutex +** more than once, the behavior is undefined. +*/ +static void pthreadMutexEnter(sqlite3_mutex *p){ + assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) ); + +#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX + /* If recursive mutexes are not available, then we have to grow + ** our own. This implementation assumes that pthread_equal() + ** is atomic - that it cannot be deceived into thinking self + ** and p->owner are equal if p->owner changes between two values + ** that are not equal to self while the comparison is taking place. + ** This implementation also assumes a coherent cache - that + ** separate processes cannot read different values from the same + ** address at the same time. If either of these two conditions + ** are not met, then the mutexes will fail and problems will result. + */ + { + pthread_t self = pthread_self(); + if( p->nRef>0 && pthread_equal(p->owner, self) ){ + p->nRef++; + }else{ + pthread_mutex_lock(&p->mutex); + assert( p->nRef==0 ); + p->owner = self; + p->nRef = 1; + } + } +#else + /* Use the built-in recursive mutexes if they are available. + */ + pthread_mutex_lock(&p->mutex); + p->owner = pthread_self(); + p->nRef++; +#endif + +#ifdef SQLITE_DEBUG + if( p->trace ){ + printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); + } +#endif +} +static int pthreadMutexTry(sqlite3_mutex *p){ + int rc; + assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) ); + +#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX + /* If recursive mutexes are not available, then we have to grow + ** our own. This implementation assumes that pthread_equal() + ** is atomic - that it cannot be deceived into thinking self + ** and p->owner are equal if p->owner changes between two values + ** that are not equal to self while the comparison is taking place. + ** This implementation also assumes a coherent cache - that + ** separate processes cannot read different values from the same + ** address at the same time. If either of these two conditions + ** are not met, then the mutexes will fail and problems will result. + */ + { + pthread_t self = pthread_self(); + if( p->nRef>0 && pthread_equal(p->owner, self) ){ + p->nRef++; + rc = SQLITE_OK; + }else if( pthread_mutex_trylock(&p->mutex)==0 ){ + assert( p->nRef==0 ); + p->owner = self; + p->nRef = 1; + rc = SQLITE_OK; + }else{ + rc = SQLITE_BUSY; + } + } +#else + /* Use the built-in recursive mutexes if they are available. + */ + if( pthread_mutex_trylock(&p->mutex)==0 ){ + p->owner = pthread_self(); + p->nRef++; + rc = SQLITE_OK; + }else{ + rc = SQLITE_BUSY; + } +#endif + +#ifdef SQLITE_DEBUG + if( rc==SQLITE_OK && p->trace ){ + printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); + } +#endif + return rc; +} + +/* +** The sqlite3_mutex_leave() routine exits a mutex that was +** previously entered by the same thread. The behavior +** is undefined if the mutex is not currently entered or +** is not currently allocated. SQLite will never do either. +*/ +static void pthreadMutexLeave(sqlite3_mutex *p){ + assert( pthreadMutexHeld(p) ); + p->nRef--; + assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); + +#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX + if( p->nRef==0 ){ + pthread_mutex_unlock(&p->mutex); + } +#else + pthread_mutex_unlock(&p->mutex); +#endif + +#ifdef SQLITE_DEBUG + if( p->trace ){ + printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); + } +#endif +} + +sqlite3_mutex_methods *sqlite3DefaultMutex(void){ + static sqlite3_mutex_methods sMutex = { + pthreadMutexInit, + pthreadMutexEnd, + pthreadMutexAlloc, + pthreadMutexFree, + pthreadMutexEnter, + pthreadMutexTry, + pthreadMutexLeave, +#ifdef SQLITE_DEBUG + pthreadMutexHeld, + pthreadMutexNotheld +#endif + }; + + return &sMutex; +} + +#endif /* SQLITE_MUTEX_PTHREAD */ diff --git a/third_party/sqlite/src/mutex_w32.c b/third_party/sqlite/src/mutex_w32.c new file mode 100755 index 0000000..d72f0a3 --- /dev/null +++ b/third_party/sqlite/src/mutex_w32.c @@ -0,0 +1,244 @@ +/* +** 2007 August 14 +** +** 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 the C functions that implement mutexes for win32 +** +** $Id: mutex_w32.c,v 1.11 2008/06/26 10:41:19 danielk1977 Exp $ +*/ +#include "sqliteInt.h" + +/* +** The code in this file is only used if we are compiling multithreaded +** on a win32 system. +*/ +#ifdef SQLITE_MUTEX_W32 + +/* +** Each recursive mutex is an instance of the following structure. +*/ +struct sqlite3_mutex { + CRITICAL_SECTION mutex; /* Mutex controlling the lock */ + int id; /* Mutex type */ + int nRef; /* Number of enterances */ + DWORD owner; /* Thread holding this mutex */ +}; + +/* +** 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 +** API as long as we don't call it win running Win95/98/ME. A call to +** this routine is used to determine if the host is Win95/98/ME or +** WinNT/2K/XP so that we will know whether or not we can safely call +** the LockFileEx() API. +*/ +#if SQLITE_OS_WINCE +# define mutexIsNT() (1) +#else + static int mutexIsNT(void){ + static int osType = 0; + if( osType==0 ){ + OSVERSIONINFO sInfo; + sInfo.dwOSVersionInfoSize = sizeof(sInfo); + GetVersionEx(&sInfo); + osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; + } + return osType==2; + } +#endif /* SQLITE_OS_WINCE */ + + +#ifdef SQLITE_DEBUG +/* +** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are +** intended for use only inside assert() statements. +*/ +static int winMutexHeld(sqlite3_mutex *p){ + return p->nRef!=0 && p->owner==GetCurrentThreadId(); +} +static int winMutexNotheld(sqlite3_mutex *p){ + return p->nRef==0 || p->owner!=GetCurrentThreadId(); +} +#endif + + +/* +** Initialize and deinitialize the mutex subsystem. +*/ +static int winMutexInit(void){ return SQLITE_OK; } +static int winMutexEnd(void){ return SQLITE_OK; } + +/* +** The sqlite3_mutex_alloc() routine allocates a new +** mutex and returns a pointer to it. If it returns NULL +** that means that a mutex could not be allocated. SQLite +** will unwind its stack and return an error. The argument +** to sqlite3_mutex_alloc() is one of these integer constants: +** +** <ul> +** <li> SQLITE_MUTEX_FAST 0 +** <li> SQLITE_MUTEX_RECURSIVE 1 +** <li> SQLITE_MUTEX_STATIC_MASTER 2 +** <li> SQLITE_MUTEX_STATIC_MEM 3 +** <li> SQLITE_MUTEX_STATIC_PRNG 4 +** </ul> +** +** The first two constants cause sqlite3_mutex_alloc() to create +** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE +** is used but not necessarily so when SQLITE_MUTEX_FAST is used. +** The mutex implementation does not need to make a distinction +** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does +** not want to. But SQLite will only request a recursive mutex in +** cases where it really needs one. If a faster non-recursive mutex +** implementation is available on the host platform, the mutex subsystem +** might return such a mutex in response to SQLITE_MUTEX_FAST. +** +** The other allowed parameters to sqlite3_mutex_alloc() each return +** a pointer to a static preexisting mutex. Three static mutexes are +** used by the current version of SQLite. Future versions of SQLite +** may add additional static mutexes. Static mutexes are for internal +** use by SQLite only. Applications that use SQLite mutexes should +** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or +** SQLITE_MUTEX_RECURSIVE. +** +** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST +** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() +** returns a different mutex on every call. But for the static +** mutex types, the same mutex is returned on every call that has +** the same type number. +*/ +static sqlite3_mutex *winMutexAlloc(int iType){ + sqlite3_mutex *p; + + switch( iType ){ + case SQLITE_MUTEX_FAST: + case SQLITE_MUTEX_RECURSIVE: { + p = sqlite3MallocZero( sizeof(*p) ); + if( p ){ + p->id = iType; + InitializeCriticalSection(&p->mutex); + } + break; + } + default: { + static sqlite3_mutex staticMutexes[6]; + static int isInit = 0; + while( !isInit ){ + static long lock = 0; + if( InterlockedIncrement(&lock)==1 ){ + int i; + for(i=0; i<sizeof(staticMutexes)/sizeof(staticMutexes[0]); i++){ + InitializeCriticalSection(&staticMutexes[i].mutex); + } + isInit = 1; + }else{ + Sleep(1); + } + } + assert( iType-2 >= 0 ); + assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) ); + p = &staticMutexes[iType-2]; + p->id = iType; + break; + } + } + return p; +} + + +/* +** This routine deallocates a previously +** allocated mutex. SQLite is careful to deallocate every +** mutex that it allocates. +*/ +static void winMutexFree(sqlite3_mutex *p){ + assert( p ); + assert( p->nRef==0 ); + assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); + DeleteCriticalSection(&p->mutex); + sqlite3_free(p); +} + +/* +** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt +** to enter a mutex. If another thread is already within the mutex, +** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return +** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK +** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can +** be entered multiple times by the same thread. In such cases the, +** mutex must be exited an equal number of times before another thread +** can enter. If the same thread tries to enter any other kind of mutex +** more than once, the behavior is undefined. +*/ +static void winMutexEnter(sqlite3_mutex *p){ + assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) ); + EnterCriticalSection(&p->mutex); + p->owner = GetCurrentThreadId(); + p->nRef++; +} +static int winMutexTry(sqlite3_mutex *p){ + int rc = SQLITE_BUSY; + assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) ); + /* + ** The sqlite3_mutex_try() routine is very rarely used, and when it + ** is used it is merely an optimization. So it is OK for it to always + ** fail. + ** + ** The TryEnterCriticalSection() interface is only available on WinNT. + ** And some windows compilers complain if you try to use it without + ** first doing some #defines that prevent SQLite from building on Win98. + ** For that reason, we will omit this optimization for now. See + ** ticket #2685. + */ +#if 0 + if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){ + p->owner = GetCurrentThreadId(); + p->nRef++; + rc = SQLITE_OK; + } +#endif + return rc; +} + +/* +** The sqlite3_mutex_leave() routine exits a mutex that was +** previously entered by the same thread. The behavior +** is undefined if the mutex is not currently entered or +** is not currently allocated. SQLite will never do either. +*/ +static void winMutexLeave(sqlite3_mutex *p){ + assert( p->nRef>0 ); + assert( p->owner==GetCurrentThreadId() ); + p->nRef--; + assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); + LeaveCriticalSection(&p->mutex); +} + +sqlite3_mutex_methods *sqlite3DefaultMutex(void){ + static sqlite3_mutex_methods sMutex = { + winMutexInit, + winMutexEnd, + winMutexAlloc, + winMutexFree, + winMutexEnter, + winMutexTry, + winMutexLeave, +#ifdef SQLITE_DEBUG + winMutexHeld, + winMutexNotheld +#endif + }; + + return &sMutex; +} +#endif /* SQLITE_MUTEX_W32 */ diff --git a/third_party/sqlite/src/os.c b/third_party/sqlite/src/os.c new file mode 100755 index 0000000..0f141c37 --- /dev/null +++ b/third_party/sqlite/src/os.c @@ -0,0 +1,277 @@ +/* +** 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. +** +** $Id: os.c,v 1.120 2008/07/28 19:34:53 drh Exp $ +*/ +#define _SQLITE_OS_C_ 1 +#include "sqliteInt.h" +#undef _SQLITE_OS_C_ + +/* +** The default SQLite sqlite3_vfs implementations do not allocate +** memory (actually, os_unix.c allocates a small amount of memory +** from within OsOpen()), but some third-party implementations may. +** So we test the effects of a malloc() failing and the sqlite3OsXXX() +** function returning SQLITE_IOERR_NOMEM using the DO_OS_MALLOC_TEST macro. +** +** The following functions are instrumented for malloc() failure +** testing: +** +** sqlite3OsOpen() +** sqlite3OsRead() +** sqlite3OsWrite() +** sqlite3OsSync() +** sqlite3OsLock() +** +*/ +#if defined(SQLITE_TEST) && (SQLITE_OS_WIN==0) && 0 + #define DO_OS_MALLOC_TEST if (1) { \ + void *pTstAlloc = sqlite3Malloc(10); \ + if (!pTstAlloc) return SQLITE_IOERR_NOMEM; \ + sqlite3_free(pTstAlloc); \ + } +#else + #define DO_OS_MALLOC_TEST +#endif + +/* +** The following routines are convenience wrappers around methods +** of the sqlite3_file 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(sqlite3_file *pId){ + int rc = SQLITE_OK; + if( pId->pMethods ){ + rc = pId->pMethods->xClose(pId); + pId->pMethods = 0; + } + return rc; +} +int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){ + DO_OS_MALLOC_TEST; + return id->pMethods->xRead(id, pBuf, amt, offset); +} +int sqlite3OsWrite(sqlite3_file *id, const void *pBuf, int amt, i64 offset){ + DO_OS_MALLOC_TEST; + return id->pMethods->xWrite(id, pBuf, amt, offset); +} +int sqlite3OsTruncate(sqlite3_file *id, i64 size){ + return id->pMethods->xTruncate(id, size); +} +int sqlite3OsSync(sqlite3_file *id, int flags){ + DO_OS_MALLOC_TEST; + return id->pMethods->xSync(id, flags); +} +int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){ + DO_OS_MALLOC_TEST; + return id->pMethods->xFileSize(id, pSize); +} +int sqlite3OsLock(sqlite3_file *id, int lockType){ + DO_OS_MALLOC_TEST; + return id->pMethods->xLock(id, lockType); +} +int sqlite3OsUnlock(sqlite3_file *id, int lockType){ + return id->pMethods->xUnlock(id, lockType); +} +int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){ + DO_OS_MALLOC_TEST; + return id->pMethods->xCheckReservedLock(id, pResOut); +} +int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){ + return id->pMethods->xFileControl(id, op, pArg); +} +int sqlite3OsSectorSize(sqlite3_file *id){ + int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize; + return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE); +} +int sqlite3OsDeviceCharacteristics(sqlite3_file *id){ + return id->pMethods->xDeviceCharacteristics(id); +} + +/* +** The next group of routines are convenience wrappers around the +** VFS methods. +*/ +int sqlite3OsOpen( + sqlite3_vfs *pVfs, + const char *zPath, + sqlite3_file *pFile, + int flags, + int *pFlagsOut +){ + DO_OS_MALLOC_TEST; + return pVfs->xOpen(pVfs, zPath, pFile, flags, pFlagsOut); +} +int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ + return pVfs->xDelete(pVfs, zPath, dirSync); +} +int sqlite3OsAccess( + sqlite3_vfs *pVfs, + const char *zPath, + int flags, + int *pResOut +){ + DO_OS_MALLOC_TEST; + return pVfs->xAccess(pVfs, zPath, flags, pResOut); +} +int sqlite3OsFullPathname( + sqlite3_vfs *pVfs, + const char *zPath, + int nPathOut, + char *zPathOut +){ + return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut); +} +#ifndef SQLITE_OMIT_LOAD_EXTENSION +void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){ + return pVfs->xDlOpen(pVfs, zPath); +} +void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ + pVfs->xDlError(pVfs, nByte, zBufOut); +} +void *sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){ + return pVfs->xDlSym(pVfs, pHandle, zSymbol); +} +void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){ + pVfs->xDlClose(pVfs, pHandle); +} +#endif /* SQLITE_OMIT_LOAD_EXTENSION */ +int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ + return pVfs->xRandomness(pVfs, nByte, zBufOut); +} +int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){ + return pVfs->xSleep(pVfs, nMicro); +} +int sqlite3OsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ + return pVfs->xCurrentTime(pVfs, pTimeOut); +} + +int sqlite3OsOpenMalloc( + sqlite3_vfs *pVfs, + const char *zFile, + sqlite3_file **ppFile, + int flags, + int *pOutFlags +){ + int rc = SQLITE_NOMEM; + sqlite3_file *pFile; + pFile = (sqlite3_file *)sqlite3Malloc(pVfs->szOsFile); + if( pFile ){ + rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags); + if( rc!=SQLITE_OK ){ + sqlite3_free(pFile); + }else{ + *ppFile = pFile; + } + } + return rc; +} +int sqlite3OsCloseFree(sqlite3_file *pFile){ + int rc = SQLITE_OK; + assert( pFile ); + rc = sqlite3OsClose(pFile); + sqlite3_free(pFile); + return rc; +} + +/* +** The list of all registered VFS implementations. +*/ +static sqlite3_vfs *vfsList = 0; + +/* +** Locate a VFS by name. If no name is given, simply return the +** first VFS on the list. +*/ +sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){ + sqlite3_vfs *pVfs = 0; +#ifndef SQLITE_MUTEX_NOOP + sqlite3_mutex *mutex; +#endif +#ifndef SQLITE_OMIT_AUTOINIT + int rc = sqlite3_initialize(); + if( rc ) return 0; +#endif +#ifndef SQLITE_MUTEX_NOOP + mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); +#endif + sqlite3_mutex_enter(mutex); + for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){ + if( zVfs==0 ) break; + if( strcmp(zVfs, pVfs->zName)==0 ) break; + } + sqlite3_mutex_leave(mutex); + return pVfs; +} + +/* +** Unlink a VFS from the linked list +*/ +static void vfsUnlink(sqlite3_vfs *pVfs){ + assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)) ); + if( pVfs==0 ){ + /* No-op */ + }else if( vfsList==pVfs ){ + vfsList = pVfs->pNext; + }else if( vfsList ){ + sqlite3_vfs *p = vfsList; + while( p->pNext && p->pNext!=pVfs ){ + p = p->pNext; + } + if( p->pNext==pVfs ){ + p->pNext = pVfs->pNext; + } + } +} + +/* +** Register a VFS with the system. It is harmless to register the same +** VFS multiple times. The new VFS becomes the default if makeDflt is +** true. +*/ +int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){ + sqlite3_mutex *mutex = 0; +#ifndef SQLITE_OMIT_AUTOINIT + int rc = sqlite3_initialize(); + if( rc ) return rc; +#endif + mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); + sqlite3_mutex_enter(mutex); + vfsUnlink(pVfs); + if( makeDflt || vfsList==0 ){ + pVfs->pNext = vfsList; + vfsList = pVfs; + }else{ + pVfs->pNext = vfsList->pNext; + vfsList->pNext = pVfs; + } + assert(vfsList); + sqlite3_mutex_leave(mutex); + return SQLITE_OK; +} + +/* +** Unregister a VFS so that it is no longer accessible. +*/ +int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ +#ifndef SQLITE_MUTEX_NOOP + sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); +#endif + sqlite3_mutex_enter(mutex); + vfsUnlink(pVfs); + sqlite3_mutex_leave(mutex); + return SQLITE_OK; +} diff --git a/third_party/sqlite/src/os.h b/third_party/sqlite/src/os.h new file mode 100755 index 0000000..04ce381 --- /dev/null +++ b/third_party/sqlite/src/os.h @@ -0,0 +1,279 @@ +/* +** 2001 September 16 +** +** 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 header file (together with is companion C source-code file +** "os.c") attempt to abstract the underlying operating system so that +** the SQLite library will work on both POSIX and windows systems. +** +** This header file is #include-ed by sqliteInt.h and thus ends up +** being included by every source file. +** +** $Id: os.h,v 1.105 2008/06/26 10:41:19 danielk1977 Exp $ +*/ +#ifndef _SQLITE_OS_H_ +#define _SQLITE_OS_H_ + +/* +** Figure out if we are dealing with Unix, Windows, or some other +** operating system. After the following block of preprocess macros, +** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, SQLITE_OS_OS2, and SQLITE_OS_OTHER +** will defined to either 1 or 0. One of the four will be 1. The other +** three will be 0. +*/ +#ifdef OS_SYMBIAN +# define SQLITE_OS_SYMBIAN 1 +# define SQLITE_OS_OTHER 1 +#endif +#if defined(SQLITE_OS_OTHER) +# if SQLITE_OS_OTHER==1 +# undef SQLITE_OS_UNIX +# define SQLITE_OS_UNIX 0 +# undef SQLITE_OS_WIN +# define SQLITE_OS_WIN 0 +# undef SQLITE_OS_OS2 +# define SQLITE_OS_OS2 0 +# else +# undef SQLITE_OS_OTHER +# endif +#endif +#if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER) +# define SQLITE_OS_OTHER 0 +# ifndef SQLITE_OS_WIN +# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__) +# define SQLITE_OS_WIN 1 +# define SQLITE_OS_UNIX 0 +# define SQLITE_OS_OS2 0 +# elif defined(__EMX__) || defined(_OS2) || defined(OS2) || defined(_OS2_) || defined(__OS2__) +# define SQLITE_OS_WIN 0 +# define SQLITE_OS_UNIX 0 +# define SQLITE_OS_OS2 1 +# else +# define SQLITE_OS_WIN 0 +# define SQLITE_OS_UNIX 1 +# define SQLITE_OS_OS2 0 +# endif +# else +# define SQLITE_OS_UNIX 0 +# define SQLITE_OS_OS2 0 +# endif +#else +# ifndef SQLITE_OS_WIN +# define SQLITE_OS_WIN 0 +# endif +#endif + +/* +** Determine if we are dealing with WindowsCE - which has a much +** reduced API. +*/ +#if defined(_WIN32_WCE) +# define SQLITE_OS_WINCE 1 +#else +# define SQLITE_OS_WINCE 0 +#endif + + +/* +** Define the maximum size of a temporary filename +*/ +#if SQLITE_OS_WIN +# include <windows.h> +# define SQLITE_TEMPNAME_SIZE (MAX_PATH+50) +#elif SQLITE_OS_OS2 +# if (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 3) && defined(OS2_HIGH_MEMORY) +# include <os2safe.h> /* has to be included before os2.h for linking to work */ +# endif +# define INCL_DOSDATETIME +# define INCL_DOSFILEMGR +# define INCL_DOSERRORS +# define INCL_DOSMISC +# define INCL_DOSPROCESS +# define INCL_DOSMODULEMGR +# define INCL_DOSSEMAPHORES +# include <os2.h> +# include <uconv.h> +# define SQLITE_TEMPNAME_SIZE (CCHMAXPATHCOMP) +#else +# define SQLITE_TEMPNAME_SIZE 200 +#endif + +/* If the SET_FULLSYNC macro is not defined above, then make it +** a no-op +*/ +#ifndef SET_FULLSYNC +# define SET_FULLSYNC(x,y) +#endif + +/* +** The default size of a disk sector +*/ +#ifndef SQLITE_DEFAULT_SECTOR_SIZE +# define SQLITE_DEFAULT_SECTOR_SIZE 512 +#endif + +/* +** Temporary files are named starting with this prefix followed by 16 random +** alphanumeric characters, and no file extension. They are stored in the +** OS's standard temporary file directory, and are deleted prior to exit. +** If sqlite is being embedded in another program, you may wish to change the +** prefix to reflect your program's name, so that if your program exits +** prematurely, old temporary files can be easily identified. This can be done +** using -DSQLITE_TEMP_FILE_PREFIX=myprefix_ on the compiler command line. +** +** 2006-10-31: The default prefix used to be "sqlite_". But then +** Mcafee started using SQLite in their anti-virus product and it +** started putting files with the "sqlite" name in the c:/temp folder. +** This annoyed many windows users. Those users would then do a +** Google search for "sqlite", find the telephone numbers of the +** developers and call to wake them up at night and complain. +** For this reason, the default name prefix is changed to be "sqlite" +** spelled backwards. So the temp files are still identified, but +** anybody smart enough to figure out the code is also likely smart +** enough to know that calling the developer will not help get rid +** of the file. +*/ +#ifndef SQLITE_TEMP_FILE_PREFIX +# define SQLITE_TEMP_FILE_PREFIX "etilqs_" +#endif + +/* +** The following values may be passed as the second argument to +** sqlite3OsLock(). The various locks exhibit the following semantics: +** +** SHARED: Any number of processes may hold a SHARED lock simultaneously. +** RESERVED: A single process may hold a RESERVED lock on a file at +** any time. Other processes may hold and obtain new SHARED locks. +** PENDING: A single process may hold a PENDING lock on a file at +** any one time. Existing SHARED locks may persist, but no new +** SHARED locks may be obtained by other processes. +** EXCLUSIVE: An EXCLUSIVE lock precludes all other locks. +** +** PENDING_LOCK may not be passed directly to sqlite3OsLock(). Instead, a +** process that requests an EXCLUSIVE lock may actually obtain a PENDING +** lock. This can be upgraded to an EXCLUSIVE lock by a subsequent call to +** sqlite3OsLock(). +*/ +#define NO_LOCK 0 +#define SHARED_LOCK 1 +#define RESERVED_LOCK 2 +#define PENDING_LOCK 3 +#define EXCLUSIVE_LOCK 4 + +/* +** File Locking Notes: (Mostly about windows but also some info for Unix) +** +** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because +** those functions are not available. So we use only LockFile() and +** UnlockFile(). +** +** LockFile() prevents not just writing but also reading by other processes. +** A SHARED_LOCK is obtained by locking a single randomly-chosen +** byte out of a specific range of bytes. The lock byte is obtained at +** random so two separate readers can probably access the file at the +** same time, unless they are unlucky and choose the same lock byte. +** An EXCLUSIVE_LOCK is obtained by locking all bytes in the range. +** There can only be one writer. A RESERVED_LOCK is obtained by locking +** a single byte of the file that is designated as the reserved lock byte. +** A PENDING_LOCK is obtained by locking a designated byte different from +** the RESERVED_LOCK byte. +** +** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available, +** which means we can use reader/writer locks. When reader/writer locks +** are used, the lock is placed on the same range of bytes that is used +** for probabilistic locking in Win95/98/ME. Hence, the locking scheme +** will support two or more Win95 readers or two or more WinNT readers. +** But a single Win95 reader will lock out all WinNT readers and a single +** WinNT reader will lock out all other Win95 readers. +** +** The following #defines specify the range of bytes used for locking. +** SHARED_SIZE is the number of bytes available in the pool from which +** 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 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 +** windows and unix. I'm guessing that isn't likely to happen, but by +** using the same locking range we are at least open to the possibility. +** +** Locking in windows is manditory. For this reason, we cannot store +** actual data in the bytes used for locking. The pager never allocates +** the pages involved in locking therefore. SHARED_SIZE is selected so +** that all locks will fit on a single page even at the minimum page size. +** PENDING_BYTE defines the beginning of the locks. By default PENDING_BYTE +** is set high so that we don't have to allocate an unused page except +** for very large databases. But one should test the page skipping logic +** by setting PENDING_BYTE low and running the entire regression suite. +** +** Changing the value of PENDING_BYTE results in a subtly incompatible +** file format. Depending on how it is changed, you might not notice +** the incompatibility right away, even running a full regression test. +** The default location of PENDING_BYTE is the first byte past the +** 1GB boundary. +** +*/ +#ifndef SQLITE_TEST +#define PENDING_BYTE 0x40000000 /* First byte past the 1GB boundary */ +#else +extern unsigned int sqlite3_pending_byte; +#define PENDING_BYTE sqlite3_pending_byte +#endif + +#define RESERVED_BYTE (PENDING_BYTE+1) +#define SHARED_FIRST (PENDING_BYTE+2) +#define SHARED_SIZE 510 + +/* +** Functions for accessing sqlite3_file methods +*/ +int sqlite3OsClose(sqlite3_file*); +int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset); +int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset); +int sqlite3OsTruncate(sqlite3_file*, i64 size); +int sqlite3OsSync(sqlite3_file*, int); +int sqlite3OsFileSize(sqlite3_file*, i64 *pSize); +int sqlite3OsLock(sqlite3_file*, int); +int sqlite3OsUnlock(sqlite3_file*, int); +int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut); +int sqlite3OsFileControl(sqlite3_file*,int,void*); +int sqlite3OsSectorSize(sqlite3_file *id); +int sqlite3OsDeviceCharacteristics(sqlite3_file *id); + +/* +** Functions for accessing sqlite3_vfs methods +*/ +int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *); +int sqlite3OsDelete(sqlite3_vfs *, const char *, int); +int sqlite3OsAccess(sqlite3_vfs *, const char *, int, int *pResOut); +int sqlite3OsFullPathname(sqlite3_vfs *, const char *, int, char *); +#ifndef SQLITE_OMIT_LOAD_EXTENSION +void *sqlite3OsDlOpen(sqlite3_vfs *, const char *); +void sqlite3OsDlError(sqlite3_vfs *, int, char *); +void *sqlite3OsDlSym(sqlite3_vfs *, void *, const char *); +void sqlite3OsDlClose(sqlite3_vfs *, void *); +#endif /* SQLITE_OMIT_LOAD_EXTENSION */ +int sqlite3OsRandomness(sqlite3_vfs *, int, char *); +int sqlite3OsSleep(sqlite3_vfs *, int); +int sqlite3OsCurrentTime(sqlite3_vfs *, double*); + +/* +** Convenience functions for opening and closing files using +** sqlite3_malloc() to obtain space for the file-handle structure. +*/ +int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int,int*); +int sqlite3OsCloseFree(sqlite3_file *); + +#endif /* _SQLITE_OS_H_ */ diff --git a/third_party/sqlite/src/os_common.h b/third_party/sqlite/src/os_common.h new file mode 100755 index 0000000..5fab7a4 --- /dev/null +++ b/third_party/sqlite/src/os_common.h @@ -0,0 +1,137 @@ +/* +** 2004 May 22 +** +** 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 macros and a little bit of code that is common to +** all of the platform-specific files (os_*.c) and is #included into those +** files. +** +** This file should be #included by the os_*.c files only. It is not a +** general purpose header file. +** +** $Id: os_common.h,v 1.37 2008/05/29 20:22:37 shane Exp $ +*/ +#ifndef _OS_COMMON_H_ +#define _OS_COMMON_H_ + +/* +** At least two bugs have slipped in because we changed the MEMORY_DEBUG +** macro to SQLITE_DEBUG and some older makefiles have not yet made the +** switch. The following code should catch this problem at compile-time. +*/ +#ifdef MEMORY_DEBUG +# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead." +#endif + + +/* + * When testing, this global variable stores the location of the + * pending-byte in the database file. + */ +#ifdef SQLITE_TEST +unsigned int sqlite3_pending_byte = 0x40000000; +#endif + +#ifdef SQLITE_DEBUG +int sqlite3OSTrace = 0; +#define OSTRACE1(X) if( sqlite3OSTrace ) sqlite3DebugPrintf(X) +#define OSTRACE2(X,Y) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y) +#define OSTRACE3(X,Y,Z) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y,Z) +#define OSTRACE4(X,Y,Z,A) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y,Z,A) +#define OSTRACE5(X,Y,Z,A,B) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y,Z,A,B) +#define OSTRACE6(X,Y,Z,A,B,C) \ + if(sqlite3OSTrace) sqlite3DebugPrintf(X,Y,Z,A,B,C) +#define OSTRACE7(X,Y,Z,A,B,C,D) \ + if(sqlite3OSTrace) sqlite3DebugPrintf(X,Y,Z,A,B,C,D) +#else +#define OSTRACE1(X) +#define OSTRACE2(X,Y) +#define OSTRACE3(X,Y,Z) +#define OSTRACE4(X,Y,Z,A) +#define OSTRACE5(X,Y,Z,A,B) +#define OSTRACE6(X,Y,Z,A,B,C) +#define OSTRACE7(X,Y,Z,A,B,C,D) +#endif + +/* +** Macros for performance tracing. Normally turned off. Only works +** on i486 hardware. +*/ +#ifdef SQLITE_PERFORMANCE_TRACE + +/* +** hwtime.h contains inline assembler code for implementing +** high-performance timing routines. +*/ +#include "hwtime.h" + +static sqlite_uint64 g_start; +static sqlite_uint64 g_elapsed; +#define TIMER_START g_start=sqlite3Hwtime() +#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start +#define TIMER_ELAPSED g_elapsed +#else +#define TIMER_START +#define TIMER_END +#define TIMER_ELAPSED ((sqlite_uint64)0) +#endif + +/* +** If we compile with the SQLITE_TEST macro set, then the following block +** of code will give us the ability to simulate a disk I/O error. This +** is used for testing the I/O recovery logic. +*/ +#ifdef SQLITE_TEST +int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */ +int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */ +int sqlite3_io_error_pending = 0; /* Count down to first I/O error */ +int sqlite3_io_error_persist = 0; /* True if I/O errors persist */ +int sqlite3_io_error_benign = 0; /* True if errors are benign */ +int sqlite3_diskfull_pending = 0; +int sqlite3_diskfull = 0; +#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X) +#define SimulateIOError(CODE) \ + if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \ + || sqlite3_io_error_pending-- == 1 ) \ + { local_ioerr(); CODE; } +static void local_ioerr(){ + IOTRACE(("IOERR\n")); + sqlite3_io_error_hit++; + if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++; +} +#define SimulateDiskfullError(CODE) \ + if( sqlite3_diskfull_pending ){ \ + if( sqlite3_diskfull_pending == 1 ){ \ + local_ioerr(); \ + sqlite3_diskfull = 1; \ + sqlite3_io_error_hit = 1; \ + CODE; \ + }else{ \ + sqlite3_diskfull_pending--; \ + } \ + } +#else +#define SimulateIOErrorBenign(X) +#define SimulateIOError(A) +#define SimulateDiskfullError(A) +#endif + +/* +** When testing, keep a count of the number of open files. +*/ +#ifdef SQLITE_TEST +int sqlite3_open_file_count = 0; +#define OpenCounter(X) sqlite3_open_file_count+=(X) +#else +#define OpenCounter(X) +#endif + +#endif /* !defined(_OS_COMMON_H_) */ diff --git a/third_party/sqlite/src/os_os2.c b/third_party/sqlite/src/os_os2.c new file mode 100755 index 0000000..f1af91d --- /dev/null +++ b/third_party/sqlite/src/os_os2.c @@ -0,0 +1,1119 @@ +/* +** 2006 Feb 14 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains code that is specific to OS/2. +** +** $Id: os_os2.c,v 1.55 2008/07/29 18:49:29 pweilbacher Exp $ +*/ + +#include "sqliteInt.h" + +#if SQLITE_OS_OS2 + +/* +** A Note About Memory Allocation: +** +** This driver uses malloc()/free() directly rather than going through +** the SQLite-wrappers sqlite3_malloc()/sqlite3_free(). Those wrappers +** are designed for use on embedded systems where memory is scarce and +** malloc failures happen frequently. OS/2 does not typically run on +** embedded systems, and when it does the developers normally have bigger +** problems to worry about than running out of memory. So there is not +** a compelling need to use the wrappers. +** +** But there is a good reason to not use the wrappers. If we use the +** wrappers then we will get simulated malloc() failures within this +** driver. And that causes all kinds of problems for our tests. We +** could enhance SQLite to deal with simulated malloc failures within +** the OS driver, but the code to deal with those failure would not +** be exercised on Linux (which does not need to malloc() in the driver) +** and so we would have difficulty writing coverage tests for that +** code. Better to leave the code out, we think. +** +** The point of this discussion is as follows: When creating a new +** OS layer for an embedded system, if you use this file as an example, +** avoid the use of malloc()/free(). Those routines work ok on OS/2 +** desktops but not so well in embedded systems. +*/ + +/* +** Macros used to determine whether or not to use threads. +*/ +#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE +# define SQLITE_OS2_THREADS 1 +#endif + +/* +** Include code that is common to all os_*.c files +*/ +#include "os_common.h" + +/* +** The os2File structure is subclass of sqlite3_file specific for the OS/2 +** protability layer. +*/ +typedef struct os2File os2File; +struct os2File { + const sqlite3_io_methods *pMethod; /* Always the first entry */ + HFILE h; /* Handle for accessing the file */ + char* pathToDel; /* Name of file to delete on close, NULL if not */ + unsigned char locktype; /* Type of lock currently held on this file */ +}; + +#define LOCK_TIMEOUT 10L /* the default locking timeout */ + +/***************************************************************************** +** The next group of routines implement the I/O methods specified +** by the sqlite3_io_methods object. +******************************************************************************/ + +/* +** Close a file. +*/ +static int os2Close( sqlite3_file *id ){ + APIRET rc = NO_ERROR; + os2File *pFile; + if( id && (pFile = (os2File*)id) != 0 ){ + OSTRACE2( "CLOSE %d\n", pFile->h ); + rc = DosClose( pFile->h ); + pFile->locktype = NO_LOCK; + if( pFile->pathToDel != NULL ){ + rc = DosForceDelete( (PSZ)pFile->pathToDel ); + free( pFile->pathToDel ); + pFile->pathToDel = NULL; + } + id = 0; + OpenCounter( -1 ); + } + + return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR; +} + +/* +** Read data from a file into a buffer. Return SQLITE_OK if all +** bytes were read successfully and SQLITE_IOERR if anything goes +** wrong. +*/ +static int os2Read( + sqlite3_file *id, /* File to read from */ + void *pBuf, /* Write content into this buffer */ + int amt, /* Number of bytes to read */ + sqlite3_int64 offset /* Begin reading at this offset */ +){ + ULONG fileLocation = 0L; + ULONG got; + os2File *pFile = (os2File*)id; + assert( id!=0 ); + SimulateIOError( return SQLITE_IOERR_READ ); + OSTRACE3( "READ %d lock=%d\n", pFile->h, pFile->locktype ); + if( DosSetFilePtr(pFile->h, offset, FILE_BEGIN, &fileLocation) != NO_ERROR ){ + return SQLITE_IOERR; + } + if( DosRead( pFile->h, pBuf, amt, &got ) != NO_ERROR ){ + return SQLITE_IOERR_READ; + } + if( got == (ULONG)amt ) + return SQLITE_OK; + else { + memset(&((char*)pBuf)[got], 0, amt-got); + return SQLITE_IOERR_SHORT_READ; + } +} + +/* +** Write data from a buffer into a file. Return SQLITE_OK on success +** or some other error code on failure. +*/ +static int os2Write( + sqlite3_file *id, /* File to write into */ + const void *pBuf, /* The bytes to be written */ + int amt, /* Number of bytes to write */ + sqlite3_int64 offset /* Offset into the file to begin writing at */ +){ + ULONG fileLocation = 0L; + APIRET rc = NO_ERROR; + ULONG wrote; + os2File *pFile = (os2File*)id; + assert( id!=0 ); + SimulateIOError( return SQLITE_IOERR_WRITE ); + SimulateDiskfullError( return SQLITE_FULL ); + OSTRACE3( "WRITE %d lock=%d\n", pFile->h, pFile->locktype ); + if( DosSetFilePtr(pFile->h, offset, FILE_BEGIN, &fileLocation) != NO_ERROR ){ + return SQLITE_IOERR; + } + assert( amt>0 ); + while( amt > 0 && + ( rc = DosWrite( pFile->h, (PVOID)pBuf, amt, &wrote ) ) == NO_ERROR && + wrote > 0 + ){ + amt -= wrote; + pBuf = &((char*)pBuf)[wrote]; + } + + return ( rc != NO_ERROR || amt > (int)wrote ) ? SQLITE_FULL : SQLITE_OK; +} + +/* +** Truncate an open file to a specified size +*/ +static int os2Truncate( sqlite3_file *id, i64 nByte ){ + APIRET rc = NO_ERROR; + os2File *pFile = (os2File*)id; + OSTRACE3( "TRUNCATE %d %lld\n", pFile->h, nByte ); + SimulateIOError( return SQLITE_IOERR_TRUNCATE ); + rc = DosSetFileSize( pFile->h, nByte ); + return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR; +} + +#ifdef SQLITE_TEST +/* +** Count the number of fullsyncs and normal syncs. This is used to test +** that syncs and fullsyncs are occuring at the right times. +*/ +int sqlite3_sync_count = 0; +int sqlite3_fullsync_count = 0; +#endif + +/* +** Make sure all writes to a particular file are committed to disk. +*/ +static int os2Sync( sqlite3_file *id, int flags ){ + os2File *pFile = (os2File*)id; + OSTRACE3( "SYNC %d lock=%d\n", pFile->h, pFile->locktype ); +#ifdef SQLITE_TEST + if( flags & SQLITE_SYNC_FULL){ + sqlite3_fullsync_count++; + } + sqlite3_sync_count++; +#endif + return DosResetBuffer( pFile->h ) == NO_ERROR ? SQLITE_OK : SQLITE_IOERR; +} + +/* +** Determine the current size of a file in bytes +*/ +static int os2FileSize( sqlite3_file *id, sqlite3_int64 *pSize ){ + APIRET rc = NO_ERROR; + FILESTATUS3 fsts3FileInfo; + memset(&fsts3FileInfo, 0, sizeof(fsts3FileInfo)); + assert( id!=0 ); + SimulateIOError( return SQLITE_IOERR ); + rc = DosQueryFileInfo( ((os2File*)id)->h, FIL_STANDARD, &fsts3FileInfo, sizeof(FILESTATUS3) ); + if( rc == NO_ERROR ){ + *pSize = fsts3FileInfo.cbFile; + return SQLITE_OK; + }else{ + return SQLITE_IOERR; + } +} + +/* +** Acquire a reader lock. +*/ +static int getReadLock( os2File *pFile ){ + FILELOCK LockArea, + UnlockArea; + APIRET res; + memset(&LockArea, 0, sizeof(LockArea)); + memset(&UnlockArea, 0, sizeof(UnlockArea)); + LockArea.lOffset = SHARED_FIRST; + LockArea.lRange = SHARED_SIZE; + UnlockArea.lOffset = 0L; + UnlockArea.lRange = 0L; + res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 1L ); + OSTRACE3( "GETREADLOCK %d res=%d\n", pFile->h, res ); + return res; +} + +/* +** Undo a readlock +*/ +static int unlockReadLock( os2File *id ){ + FILELOCK LockArea, + UnlockArea; + APIRET res; + memset(&LockArea, 0, sizeof(LockArea)); + memset(&UnlockArea, 0, sizeof(UnlockArea)); + LockArea.lOffset = 0L; + LockArea.lRange = 0L; + UnlockArea.lOffset = SHARED_FIRST; + UnlockArea.lRange = SHARED_SIZE; + res = DosSetFileLocks( id->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 1L ); + OSTRACE3( "UNLOCK-READLOCK file handle=%d res=%d?\n", id->h, res ); + return res; +} + +/* +** Lock the file with the lock specified by parameter locktype - one +** of the following: +** +** (1) SHARED_LOCK +** (2) RESERVED_LOCK +** (3) PENDING_LOCK +** (4) EXCLUSIVE_LOCK +** +** Sometimes when requesting one lock state, additional lock states +** are inserted in between. The locking might fail on one of the later +** transitions leaving the lock state different from what it started but +** still short of its goal. The following chart shows the allowed +** transitions and the inserted intermediate states: +** +** UNLOCKED -> SHARED +** SHARED -> RESERVED +** SHARED -> (PENDING) -> EXCLUSIVE +** RESERVED -> (PENDING) -> EXCLUSIVE +** PENDING -> EXCLUSIVE +** +** This routine will only increase a lock. The os2Unlock() 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. +*/ +static int os2Lock( sqlite3_file *id, int locktype ){ + int rc = SQLITE_OK; /* Return code from subroutines */ + APIRET res = NO_ERROR; /* Result of an OS/2 lock call */ + int newLocktype; /* Set pFile->locktype to this value before exiting */ + int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */ + FILELOCK LockArea, + UnlockArea; + os2File *pFile = (os2File*)id; + memset(&LockArea, 0, sizeof(LockArea)); + memset(&UnlockArea, 0, sizeof(UnlockArea)); + assert( pFile!=0 ); + OSTRACE4( "LOCK %d %d was %d\n", pFile->h, locktype, pFile->locktype ); + + /* If there is already a lock of this type or more restrictive on the + ** os2File, do nothing. Don't use the end_lock: exit path, as + ** sqlite3_mutex_enter() hasn't been called yet. + */ + if( pFile->locktype>=locktype ){ + OSTRACE3( "LOCK %d %d ok (already held)\n", pFile->h, locktype ); + return SQLITE_OK; + } + + /* Make sure the locking sequence is correct + */ + assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); + assert( locktype!=PENDING_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 = pFile->locktype; + if( pFile->locktype==NO_LOCK + || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK) + ){ + LockArea.lOffset = PENDING_BYTE; + LockArea.lRange = 1L; + UnlockArea.lOffset = 0L; + UnlockArea.lRange = 0L; + + /* wait longer than LOCK_TIMEOUT here not to have to try multiple times */ + res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 100L, 0L ); + if( res == NO_ERROR ){ + gotPendingLock = 1; + OSTRACE3( "LOCK %d pending lock boolean set. res=%d\n", pFile->h, res ); + } + } + + /* Acquire a shared lock + */ + if( locktype==SHARED_LOCK && res == NO_ERROR ){ + assert( pFile->locktype==NO_LOCK ); + res = getReadLock(pFile); + if( res == NO_ERROR ){ + newLocktype = SHARED_LOCK; + } + OSTRACE3( "LOCK %d acquire shared lock. res=%d\n", pFile->h, res ); + } + + /* Acquire a RESERVED lock + */ + if( locktype==RESERVED_LOCK && res == NO_ERROR ){ + assert( pFile->locktype==SHARED_LOCK ); + LockArea.lOffset = RESERVED_BYTE; + LockArea.lRange = 1L; + UnlockArea.lOffset = 0L; + UnlockArea.lRange = 0L; + res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L ); + if( res == NO_ERROR ){ + newLocktype = RESERVED_LOCK; + } + OSTRACE3( "LOCK %d acquire reserved lock. res=%d\n", pFile->h, res ); + } + + /* Acquire a PENDING lock + */ + if( locktype==EXCLUSIVE_LOCK && res == NO_ERROR ){ + newLocktype = PENDING_LOCK; + gotPendingLock = 0; + OSTRACE2( "LOCK %d acquire pending lock. pending lock boolean unset.\n", pFile->h ); + } + + /* Acquire an EXCLUSIVE lock + */ + if( locktype==EXCLUSIVE_LOCK && res == NO_ERROR ){ + assert( pFile->locktype>=SHARED_LOCK ); + res = unlockReadLock(pFile); + OSTRACE2( "unreadlock = %d\n", res ); + LockArea.lOffset = SHARED_FIRST; + LockArea.lRange = SHARED_SIZE; + UnlockArea.lOffset = 0L; + UnlockArea.lRange = 0L; + res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L ); + if( res == NO_ERROR ){ + newLocktype = EXCLUSIVE_LOCK; + }else{ + OSTRACE2( "OS/2 error-code = %d\n", res ); + getReadLock(pFile); + } + OSTRACE3( "LOCK %d acquire exclusive lock. res=%d\n", pFile->h, res ); + } + + /* If we are holding a PENDING lock that ought to be released, then + ** release it now. + */ + if( gotPendingLock && locktype==SHARED_LOCK ){ + int r; + LockArea.lOffset = 0L; + LockArea.lRange = 0L; + UnlockArea.lOffset = PENDING_BYTE; + UnlockArea.lRange = 1L; + r = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L ); + OSTRACE3( "LOCK %d unlocking pending/is shared. r=%d\n", pFile->h, r ); + } + + /* Update the state of the lock has held in the file descriptor then + ** return the appropriate result code. + */ + if( res == NO_ERROR ){ + rc = SQLITE_OK; + }else{ + OSTRACE4( "LOCK FAILED %d trying for %d but got %d\n", pFile->h, + locktype, newLocktype ); + rc = SQLITE_BUSY; + } + pFile->locktype = newLocktype; + OSTRACE3( "LOCK %d now %d\n", pFile->h, pFile->locktype ); + return rc; +} + +/* +** This routine checks if there is a RESERVED lock held on the specified +** file by this or any other process. If such a lock is held, return +** non-zero, otherwise zero. +*/ +static int os2CheckReservedLock( sqlite3_file *id, int *pOut ){ + int r = 0; + os2File *pFile = (os2File*)id; + assert( pFile!=0 ); + if( pFile->locktype>=RESERVED_LOCK ){ + r = 1; + OSTRACE3( "TEST WR-LOCK %d %d (local)\n", pFile->h, r ); + }else{ + FILELOCK LockArea, + UnlockArea; + APIRET rc = NO_ERROR; + memset(&LockArea, 0, sizeof(LockArea)); + memset(&UnlockArea, 0, sizeof(UnlockArea)); + LockArea.lOffset = RESERVED_BYTE; + LockArea.lRange = 1L; + UnlockArea.lOffset = 0L; + UnlockArea.lRange = 0L; + rc = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L ); + OSTRACE3( "TEST WR-LOCK %d lock reserved byte rc=%d\n", pFile->h, rc ); + if( rc == NO_ERROR ){ + APIRET rcu = NO_ERROR; /* return code for unlocking */ + LockArea.lOffset = 0L; + LockArea.lRange = 0L; + UnlockArea.lOffset = RESERVED_BYTE; + UnlockArea.lRange = 1L; + rcu = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L ); + OSTRACE3( "TEST WR-LOCK %d unlock reserved byte r=%d\n", pFile->h, rcu ); + } + r = !(rc == NO_ERROR); + OSTRACE3( "TEST WR-LOCK %d %d (remote)\n", pFile->h, r ); + } + *pOut = r; + return SQLITE_OK; +} + +/* +** Lower the locking level on file descriptor id 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 then this routine +** might return SQLITE_IOERR; +*/ +static int os2Unlock( sqlite3_file *id, int locktype ){ + int type; + os2File *pFile = (os2File*)id; + APIRET rc = SQLITE_OK; + APIRET res = NO_ERROR; + FILELOCK LockArea, + UnlockArea; + memset(&LockArea, 0, sizeof(LockArea)); + memset(&UnlockArea, 0, sizeof(UnlockArea)); + assert( pFile!=0 ); + assert( locktype<=SHARED_LOCK ); + OSTRACE4( "UNLOCK %d to %d was %d\n", pFile->h, locktype, pFile->locktype ); + type = pFile->locktype; + if( type>=EXCLUSIVE_LOCK ){ + LockArea.lOffset = 0L; + LockArea.lRange = 0L; + UnlockArea.lOffset = SHARED_FIRST; + UnlockArea.lRange = SHARED_SIZE; + res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L ); + OSTRACE3( "UNLOCK %d exclusive lock res=%d\n", pFile->h, res ); + if( locktype==SHARED_LOCK && getReadLock(pFile) != NO_ERROR ){ + /* This should never happen. We should always be able to + ** reacquire the read lock */ + OSTRACE3( "UNLOCK %d to %d getReadLock() failed\n", pFile->h, locktype ); + rc = SQLITE_IOERR_UNLOCK; + } + } + if( type>=RESERVED_LOCK ){ + LockArea.lOffset = 0L; + LockArea.lRange = 0L; + UnlockArea.lOffset = RESERVED_BYTE; + UnlockArea.lRange = 1L; + res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L ); + OSTRACE3( "UNLOCK %d reserved res=%d\n", pFile->h, res ); + } + if( locktype==NO_LOCK && type>=SHARED_LOCK ){ + res = unlockReadLock(pFile); + OSTRACE5( "UNLOCK %d is %d want %d res=%d\n", pFile->h, type, locktype, res ); + } + if( type>=PENDING_LOCK ){ + LockArea.lOffset = 0L; + LockArea.lRange = 0L; + UnlockArea.lOffset = PENDING_BYTE; + UnlockArea.lRange = 1L; + res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L ); + OSTRACE3( "UNLOCK %d pending res=%d\n", pFile->h, res ); + } + pFile->locktype = locktype; + OSTRACE3( "UNLOCK %d now %d\n", pFile->h, pFile->locktype ); + return rc; +} + +/* +** Control and query of the open file handle. +*/ +static int os2FileControl(sqlite3_file *id, int op, void *pArg){ + switch( op ){ + case SQLITE_FCNTL_LOCKSTATE: { + *(int*)pArg = ((os2File*)id)->locktype; + OSTRACE3( "FCNTL_LOCKSTATE %d lock=%d\n", ((os2File*)id)->h, ((os2File*)id)->locktype ); + return SQLITE_OK; + } + } + return SQLITE_ERROR; +} + +/* +** Return the sector size in bytes of the underlying block device for +** the specified file. This is almost always 512 bytes, but may be +** larger for some devices. +** +** SQLite code assumes this function cannot fail. It also assumes that +** if two files are created in the same file-system directory (i.e. +** a database and its journal file) that the sector size will be the +** same for both. +*/ +static int os2SectorSize(sqlite3_file *id){ + return SQLITE_DEFAULT_SECTOR_SIZE; +} + +/* +** Return a vector of device characteristics. +*/ +static int os2DeviceCharacteristics(sqlite3_file *id){ + return 0; +} + + +/* +** Character set conversion objects used by conversion routines. +*/ +static UconvObject ucUtf8 = NULL; /* convert between UTF-8 and UCS-2 */ +static UconvObject uclCp = NULL; /* convert between local codepage and UCS-2 */ + +/* +** Helper function to initialize the conversion objects from and to UTF-8. +*/ +static void initUconvObjects( void ){ + if( UniCreateUconvObject( UTF_8, &ucUtf8 ) != ULS_SUCCESS ) + ucUtf8 = NULL; + if ( UniCreateUconvObject( (UniChar *)L"@path=yes", &uclCp ) != ULS_SUCCESS ) + uclCp = NULL; +} + +/* +** Helper function to free the conversion objects from and to UTF-8. +*/ +static void freeUconvObjects( void ){ + if ( ucUtf8 ) + UniFreeUconvObject( ucUtf8 ); + if ( uclCp ) + UniFreeUconvObject( uclCp ); + ucUtf8 = NULL; + uclCp = NULL; +} + +/* +** Helper function to convert UTF-8 filenames to local OS/2 codepage. +** The two-step process: first convert the incoming UTF-8 string +** into UCS-2 and then from UCS-2 to the current codepage. +** The returned char pointer has to be freed. +*/ +static char *convertUtf8PathToCp( const char *in ){ + UniChar tempPath[CCHMAXPATH]; + char *out = (char *)calloc( CCHMAXPATH, 1 ); + + if( !out ) + return NULL; + + if( !ucUtf8 || !uclCp ) + initUconvObjects(); + + /* determine string for the conversion of UTF-8 which is CP1208 */ + if( UniStrToUcs( ucUtf8, tempPath, (char *)in, CCHMAXPATH ) != ULS_SUCCESS ) + return out; /* if conversion fails, return the empty string */ + + /* conversion for current codepage which can be used for paths */ + UniStrFromUcs( uclCp, out, tempPath, CCHMAXPATH ); + + return out; +} + +/* +** Helper function to convert filenames from local codepage to UTF-8. +** The two-step process: first convert the incoming codepage-specific +** string into UCS-2 and then from UCS-2 to the codepage of UTF-8. +** The returned char pointer has to be freed. +** +** This function is non-static to be able to use this in shell.c and +** similar applications that take command line arguments. +*/ +char *convertCpPathToUtf8( const char *in ){ + UniChar tempPath[CCHMAXPATH]; + char *out = (char *)calloc( CCHMAXPATH, 1 ); + + if( !out ) + return NULL; + + if( !ucUtf8 || !uclCp ) + initUconvObjects(); + + /* conversion for current codepage which can be used for paths */ + if( UniStrToUcs( uclCp, tempPath, (char *)in, CCHMAXPATH ) != ULS_SUCCESS ) + return out; /* if conversion fails, return the empty string */ + + /* determine string for the conversion of UTF-8 which is CP1208 */ + UniStrFromUcs( ucUtf8, out, tempPath, CCHMAXPATH ); + + return out; +} + +/* +** This vector defines all the methods that can operate on an +** sqlite3_file for os2. +*/ +static const sqlite3_io_methods os2IoMethod = { + 1, /* iVersion */ + os2Close, + os2Read, + os2Write, + os2Truncate, + os2Sync, + os2FileSize, + os2Lock, + os2Unlock, + os2CheckReservedLock, + os2FileControl, + os2SectorSize, + os2DeviceCharacteristics +}; + +/*************************************************************************** +** Here ends the I/O methods that form the sqlite3_io_methods object. +** +** The next block of code implements the VFS methods. +****************************************************************************/ + +/* +** Create a temporary file name in zBuf. zBuf must be big enough to +** hold at pVfs->mxPathname characters. +*/ +static int getTempname(int nBuf, char *zBuf ){ + static const unsigned char zChars[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789"; + int i, j; + char zTempPathBuf[3]; + PSZ zTempPath = (PSZ)&zTempPathBuf; + if( sqlite3_temp_directory ){ + zTempPath = sqlite3_temp_directory; + }else{ + if( DosScanEnv( (PSZ)"TEMP", &zTempPath ) ){ + if( DosScanEnv( (PSZ)"TMP", &zTempPath ) ){ + if( DosScanEnv( (PSZ)"TMPDIR", &zTempPath ) ){ + ULONG ulDriveNum = 0, ulDriveMap = 0; + DosQueryCurrentDisk( &ulDriveNum, &ulDriveMap ); + sprintf( (char*)zTempPath, "%c:", (char)( 'A' + ulDriveNum - 1 ) ); + } + } + } + } + /* Strip off a trailing slashes or backslashes, otherwise we would get * + * multiple (back)slashes which causes DosOpen() to fail. * + * Trailing spaces are not allowed, either. */ + j = strlen(zTempPath); + while( j > 0 && ( zTempPath[j-1] == '\\' || zTempPath[j-1] == '/' + || zTempPath[j-1] == ' ' ) ){ + j--; + } + zTempPath[j] = '\0'; + if( !sqlite3_temp_directory ){ + char *zTempPathUTF = convertCpPathToUtf8( zTempPath ); + sqlite3_snprintf( nBuf-30, zBuf, + "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPathUTF ); + free( zTempPathUTF ); + }else{ + sqlite3_snprintf( nBuf-30, zBuf, + "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath ); + } + j = strlen( zBuf ); + sqlite3_randomness( 20, &zBuf[j] ); + for( i = 0; i < 20; i++, j++ ){ + zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; + } + zBuf[j] = 0; + OSTRACE2( "TEMP FILENAME: %s\n", zBuf ); + return SQLITE_OK; +} + + +/* +** Turn a relative pathname into a full pathname. Write the full +** pathname into zFull[]. zFull[] will be at least pVfs->mxPathname +** bytes in size. +*/ +static int os2FullPathname( + sqlite3_vfs *pVfs, /* Pointer to vfs object */ + const char *zRelative, /* Possibly relative input path */ + int nFull, /* Size of output buffer in bytes */ + char *zFull /* Output buffer */ +){ + char *zRelativeCp = convertUtf8PathToCp( zRelative ); + char zFullCp[CCHMAXPATH] = "\0"; + char *zFullUTF; + APIRET rc = DosQueryPathInfo( zRelativeCp, FIL_QUERYFULLNAME, zFullCp, + CCHMAXPATH ); + free( zRelativeCp ); + zFullUTF = convertCpPathToUtf8( zFullCp ); + sqlite3_snprintf( nFull, zFull, zFullUTF ); + free( zFullUTF ); + return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR; +} + + +/* +** Open a file. +*/ +static int os2Open( + sqlite3_vfs *pVfs, /* Not used */ + const char *zName, /* Name of the file */ + sqlite3_file *id, /* Write the SQLite file handle here */ + int flags, /* Open mode flags */ + int *pOutFlags /* Status return flags */ +){ + HFILE h; + ULONG ulFileAttribute = 0; + ULONG ulOpenFlags = 0; + ULONG ulOpenMode = 0; + os2File *pFile = (os2File*)id; + APIRET rc = NO_ERROR; + ULONG ulAction; + char *zNameCp; + char zTmpname[CCHMAXPATH+1]; /* Buffer to hold name of temp file */ + + /* If the second argument to this function is NULL, generate a + ** temporary file name to use + */ + if( !zName ){ + int rc = getTempname(CCHMAXPATH+1, zTmpname); + if( rc!=SQLITE_OK ){ + return rc; + } + zName = zTmpname; + } + + + memset( pFile, 0, sizeof(*pFile) ); + + OSTRACE2( "OPEN want %d\n", flags ); + + /*ulOpenMode = flags & SQLITE_OPEN_READWRITE ? OPEN_ACCESS_READWRITE : OPEN_ACCESS_READONLY;*/ + if( flags & SQLITE_OPEN_READWRITE ){ + ulOpenMode |= OPEN_ACCESS_READWRITE; + OSTRACE1( "OPEN read/write\n" ); + }else{ + ulOpenMode |= OPEN_ACCESS_READONLY; + OSTRACE1( "OPEN read only\n" ); + } + + /*ulOpenFlags = flags & SQLITE_OPEN_CREATE ? OPEN_ACTION_CREATE_IF_NEW : OPEN_ACTION_FAIL_IF_NEW;*/ + if( flags & SQLITE_OPEN_CREATE ){ + ulOpenFlags |= OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW; + OSTRACE1( "OPEN open new/create\n" ); + }else{ + ulOpenFlags |= OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW; + OSTRACE1( "OPEN open existing\n" ); + } + + /*ulOpenMode |= flags & SQLITE_OPEN_MAIN_DB ? OPEN_SHARE_DENYNONE : OPEN_SHARE_DENYWRITE;*/ + if( flags & SQLITE_OPEN_MAIN_DB ){ + ulOpenMode |= OPEN_SHARE_DENYNONE; + OSTRACE1( "OPEN share read/write\n" ); + }else{ + ulOpenMode |= OPEN_SHARE_DENYWRITE; + OSTRACE1( "OPEN share read only\n" ); + } + + if( flags & (SQLITE_OPEN_TEMP_DB | SQLITE_OPEN_TEMP_JOURNAL + | SQLITE_OPEN_SUBJOURNAL) ){ + char pathUtf8[CCHMAXPATH]; +#ifdef NDEBUG /* when debugging we want to make sure it is deleted */ + ulFileAttribute = FILE_HIDDEN; +#endif + ulFileAttribute = FILE_NORMAL; + os2FullPathname( pVfs, zName, CCHMAXPATH, pathUtf8 ); + pFile->pathToDel = convertUtf8PathToCp( pathUtf8 ); + OSTRACE1( "OPEN hidden/delete on close file attributes\n" ); + }else{ + ulFileAttribute = FILE_ARCHIVED | FILE_NORMAL; + pFile->pathToDel = NULL; + OSTRACE1( "OPEN normal file attribute\n" ); + } + + /* always open in random access mode for possibly better speed */ + ulOpenMode |= OPEN_FLAGS_RANDOM; + ulOpenMode |= OPEN_FLAGS_FAIL_ON_ERROR; + ulOpenMode |= OPEN_FLAGS_NOINHERIT; + + zNameCp = convertUtf8PathToCp( zName ); + rc = DosOpen( (PSZ)zNameCp, + &h, + &ulAction, + 0L, + ulFileAttribute, + ulOpenFlags, + ulOpenMode, + (PEAOP2)NULL ); + free( zNameCp ); + if( rc != NO_ERROR ){ + OSTRACE7( "OPEN Invalid handle rc=%d: zName=%s, ulAction=%#lx, ulAttr=%#lx, ulFlags=%#lx, ulMode=%#lx\n", + rc, zName, ulAction, ulFileAttribute, ulOpenFlags, ulOpenMode ); + if( pFile->pathToDel ) + free( pFile->pathToDel ); + pFile->pathToDel = NULL; + if( flags & SQLITE_OPEN_READWRITE ){ + OSTRACE2( "OPEN %d Invalid handle\n", ((flags | SQLITE_OPEN_READONLY) & ~SQLITE_OPEN_READWRITE) ); + return os2Open( pVfs, zName, id, + ((flags | SQLITE_OPEN_READONLY) & ~SQLITE_OPEN_READWRITE), + pOutFlags ); + }else{ + return SQLITE_CANTOPEN; + } + } + + if( pOutFlags ){ + *pOutFlags = flags & SQLITE_OPEN_READWRITE ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY; + } + + pFile->pMethod = &os2IoMethod; + pFile->h = h; + OpenCounter(+1); + OSTRACE3( "OPEN %d pOutFlags=%d\n", pFile->h, pOutFlags ); + return SQLITE_OK; +} + +/* +** Delete the named file. +*/ +static int os2Delete( + sqlite3_vfs *pVfs, /* Not used on os2 */ + const char *zFilename, /* Name of file to delete */ + int syncDir /* Not used on os2 */ +){ + APIRET rc = NO_ERROR; + char *zFilenameCp = convertUtf8PathToCp( zFilename ); + SimulateIOError( return SQLITE_IOERR_DELETE ); + rc = DosDelete( (PSZ)zFilenameCp ); + free( zFilenameCp ); + OSTRACE2( "DELETE \"%s\"\n", zFilename ); + return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR; +} + +/* +** Check the existance and status of a file. +*/ +static int os2Access( + sqlite3_vfs *pVfs, /* Not used on os2 */ + const char *zFilename, /* Name of file to check */ + int flags, /* Type of test to make on this file */ + int *pOut /* Write results here */ +){ + FILESTATUS3 fsts3ConfigInfo; + APIRET rc = NO_ERROR; + char *zFilenameCp = convertUtf8PathToCp( zFilename ); + + memset( &fsts3ConfigInfo, 0, sizeof(fsts3ConfigInfo) ); + rc = DosQueryPathInfo( (PSZ)zFilenameCp, FIL_STANDARD, + &fsts3ConfigInfo, sizeof(FILESTATUS3) ); + free( zFilenameCp ); + OSTRACE4( "ACCESS fsts3ConfigInfo.attrFile=%d flags=%d rc=%d\n", + fsts3ConfigInfo.attrFile, flags, rc ); + switch( flags ){ + case SQLITE_ACCESS_READ: + case SQLITE_ACCESS_EXISTS: + rc = (rc == NO_ERROR); + OSTRACE3( "ACCESS %s access of read and exists rc=%d\n", zFilename, rc ); + break; + case SQLITE_ACCESS_READWRITE: + rc = (rc == NO_ERROR) && ( (fsts3ConfigInfo.attrFile & FILE_READONLY) == 0 ); + OSTRACE3( "ACCESS %s access of read/write rc=%d\n", zFilename, rc ); + break; + default: + assert( !"Invalid flags argument" ); + } + *pOut = rc; + return SQLITE_OK; +} + + +#ifndef SQLITE_OMIT_LOAD_EXTENSION +/* +** Interfaces for opening a shared library, finding entry points +** within the shared library, and closing the shared library. +*/ +/* +** Interfaces for opening a shared library, finding entry points +** within the shared library, and closing the shared library. +*/ +static void *os2DlOpen(sqlite3_vfs *pVfs, const char *zFilename){ + UCHAR loadErr[256]; + HMODULE hmod; + APIRET rc; + char *zFilenameCp = convertUtf8PathToCp(zFilename); + rc = DosLoadModule((PSZ)loadErr, sizeof(loadErr), zFilenameCp, &hmod); + free(zFilenameCp); + return rc != NO_ERROR ? 0 : (void*)hmod; +} +/* +** A no-op since the error code is returned on the DosLoadModule call. +** os2Dlopen returns zero if DosLoadModule is not successful. +*/ +static void os2DlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){ +/* no-op */ +} +static void *os2DlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){ + PFN pfn; + APIRET rc; + rc = DosQueryProcAddr((HMODULE)pHandle, 0L, zSymbol, &pfn); + if( rc != NO_ERROR ){ + /* if the symbol itself was not found, search again for the same + * symbol with an extra underscore, that might be needed depending + * on the calling convention */ + char _zSymbol[256] = "_"; + strncat(_zSymbol, zSymbol, 255); + rc = DosQueryProcAddr((HMODULE)pHandle, 0L, _zSymbol, &pfn); + } + return rc != NO_ERROR ? 0 : (void*)pfn; +} +static void os2DlClose(sqlite3_vfs *pVfs, void *pHandle){ + DosFreeModule((HMODULE)pHandle); +} +#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */ + #define os2DlOpen 0 + #define os2DlError 0 + #define os2DlSym 0 + #define os2DlClose 0 +#endif + + +/* +** Write up to nBuf bytes of randomness into zBuf. +*/ +static int os2Randomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf ){ + ULONG sizeofULong = sizeof(ULONG); + int n = 0; + if( sizeof(DATETIME) <= nBuf - n ){ + DATETIME x; + DosGetDateTime(&x); + memcpy(&zBuf[n], &x, sizeof(x)); + n += sizeof(x); + } + + if( sizeofULong <= nBuf - n ){ + PPIB ppib; + DosGetInfoBlocks(NULL, &ppib); + memcpy(&zBuf[n], &ppib->pib_ulpid, sizeofULong); + n += sizeofULong; + } + + if( sizeofULong <= nBuf - n ){ + PTIB ptib; + DosGetInfoBlocks(&ptib, NULL); + memcpy(&zBuf[n], &ptib->tib_ptib2->tib2_ultid, sizeofULong); + n += sizeofULong; + } + + /* if we still haven't filled the buffer yet the following will */ + /* grab everything once instead of making several calls for a single item */ + if( sizeofULong <= nBuf - n ){ + ULONG ulSysInfo[QSV_MAX]; + DosQuerySysInfo(1L, QSV_MAX, ulSysInfo, sizeofULong * QSV_MAX); + + memcpy(&zBuf[n], &ulSysInfo[QSV_MS_COUNT - 1], sizeofULong); + n += sizeofULong; + + if( sizeofULong <= nBuf - n ){ + memcpy(&zBuf[n], &ulSysInfo[QSV_TIMER_INTERVAL - 1], sizeofULong); + n += sizeofULong; + } + if( sizeofULong <= nBuf - n ){ + memcpy(&zBuf[n], &ulSysInfo[QSV_TIME_LOW - 1], sizeofULong); + n += sizeofULong; + } + if( sizeofULong <= nBuf - n ){ + memcpy(&zBuf[n], &ulSysInfo[QSV_TIME_HIGH - 1], sizeofULong); + n += sizeofULong; + } + if( sizeofULong <= nBuf - n ){ + memcpy(&zBuf[n], &ulSysInfo[QSV_TOTAVAILMEM - 1], sizeofULong); + n += sizeofULong; + } + } + + return n; +} + +/* +** Sleep for a little while. Return the amount of time slept. +** The argument is the number of microseconds we want to sleep. +** The return value is the number of microseconds of sleep actually +** requested from the underlying operating system, a number which +** might be greater than or equal to the argument, but not less +** than the argument. +*/ +static int os2Sleep( sqlite3_vfs *pVfs, int microsec ){ + DosSleep( (microsec/1000) ); + return microsec; +} + +/* +** The following variable, if set to a non-zero value, becomes the result +** returned from sqlite3OsCurrentTime(). This is used for testing. +*/ +#ifdef SQLITE_TEST +int sqlite3_current_time = 0; +#endif + +/* +** Find the current time (in Universal Coordinated Time). Write the +** 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 os2CurrentTime( sqlite3_vfs *pVfs, double *prNow ){ + double now; + SHORT minute; /* needs to be able to cope with negative timezone offset */ + USHORT second, hour, + day, month, year; + DATETIME dt; + DosGetDateTime( &dt ); + second = (USHORT)dt.seconds; + minute = (SHORT)dt.minutes + dt.timezone; + hour = (USHORT)dt.hours; + day = (USHORT)dt.day; + month = (USHORT)dt.month; + year = (USHORT)dt.year; + + /* Calculations from http://www.astro.keele.ac.uk/~rno/Astronomy/hjd.html + http://www.astro.keele.ac.uk/~rno/Astronomy/hjd-0.1.c */ + /* Calculate the Julian days */ + now = day - 32076 + + 1461*(year + 4800 + (month - 14)/12)/4 + + 367*(month - 2 - (month - 14)/12*12)/12 - + 3*((year + 4900 + (month - 14)/12)/100)/4; + + /* Add the fractional hours, mins and seconds */ + now += (hour + 12.0)/24.0; + now += minute/1440.0; + now += second/86400.0; + *prNow = now; +#ifdef SQLITE_TEST + if( sqlite3_current_time ){ + *prNow = sqlite3_current_time/86400.0 + 2440587.5; + } +#endif + return 0; +} + +static int os2GetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ + return 0; +} + +/* +** Initialize and deinitialize the operating system interface. +*/ +int sqlite3_os_init(void){ + static sqlite3_vfs os2Vfs = { + 1, /* iVersion */ + sizeof(os2File), /* szOsFile */ + CCHMAXPATH, /* mxPathname */ + 0, /* pNext */ + "os2", /* zName */ + 0, /* pAppData */ + + os2Open, /* xOpen */ + os2Delete, /* xDelete */ + os2Access, /* xAccess */ + os2FullPathname, /* xFullPathname */ + os2DlOpen, /* xDlOpen */ + os2DlError, /* xDlError */ + os2DlSym, /* xDlSym */ + os2DlClose, /* xDlClose */ + os2Randomness, /* xRandomness */ + os2Sleep, /* xSleep */ + os2CurrentTime, /* xCurrentTime */ + os2GetLastError /* xGetLastError */ + }; + sqlite3_vfs_register(&os2Vfs, 1); + initUconvObjects(); + return SQLITE_OK; +} +int sqlite3_os_end(void){ + freeUconvObjects(); + return SQLITE_OK; +} + +#endif /* SQLITE_OS_OS2 */ diff --git a/third_party/sqlite/src/os_symbian.cc b/third_party/sqlite/src/os_symbian.cc new file mode 100755 index 0000000..5b86338 --- /dev/null +++ b/third_party/sqlite/src/os_symbian.cc @@ -0,0 +1,579 @@ +// Copyright 2008, Google Inc. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// 3. Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This file contains code that is specific to Symbian. +// Differently from the rest of SQLite, it is implemented in C++ as this is +// the native language of the OS and all interfaces we need to use are C++. +// +// This file follows the Gears code style guidelines. + +#ifdef OS_SYMBIAN +#include <coemain.h> +#include <e32math.h> +#include <f32file.h> +#include <utf.h> + +extern "C" { +#include "sqliteInt.h" +#include "os_common.h" +} + +const TInt kFileLockAttempts = 3; + +// The global file system session. +RFs g_fs_session; + +static TInt UTF8ToUTF16(const char *in, TDes *out16) { + assert(in); + TPtrC8 in_des(reinterpret_cast<const unsigned char*>(in)); + return CnvUtfConverter::ConvertToUnicodeFromUtf8(*out16, in_des); +} + +static TInt UTF16ToUTF8(const TDesC16& in16, TDes8 *out8) { + return CnvUtfConverter::ConvertFromUnicodeToUtf8(*out8, in16); +} + +// The SymbianFile structure is a subclass of sqlite3_file* specific to the +// Symbian portability layer. +struct SymbianFile { + const sqlite3_io_methods *methods; + RFile handle; // The file handle + TUint8 lock_type; // Type of lock currently held on this file + TUint16 shared_lock_byte; // Randomly chosen byte used as a shared lock +}; + +static SymbianFile* ConvertToSymbianFile(sqlite3_file* const id) { + assert(id); + return reinterpret_cast<SymbianFile*>(id); +} + +static int SymbianClose(sqlite3_file *id) { + SymbianFile *file_id = ConvertToSymbianFile(id); + file_id->handle.Close(); + OpenCounter(-1); + return SQLITE_OK; +} + +static int SymbianRead(sqlite3_file *id, + void *buffer, + int amount, + sqlite3_int64 offset) { + assert(buffer); + assert(amount >=0); + assert(offset >=0); + + SymbianFile* file_id = ConvertToSymbianFile(id); + TPtr8 dest(static_cast<unsigned char*>(buffer), amount); + + if (KErrNone == file_id->handle.Read(offset, dest, amount)) { + if (dest.Length() == amount) { + return SQLITE_OK; + } else { + return SQLITE_IOERR_SHORT_READ; + } + } else { + return SQLITE_IOERR; + } +} + +static int SymbianWrite(sqlite3_file *id, + const void *buffer, + int amount, + sqlite3_int64 offset) { + assert(buffer); + assert(amount >=0); + assert(offset >=0); + + SymbianFile *file_id = ConvertToSymbianFile(id); + TPtrC8 src(static_cast<const unsigned char*>(buffer), amount); + if (file_id->handle.Write(offset, src) != KErrNone) { + return SQLITE_IOERR_WRITE; + } + + return SQLITE_OK; +} + +static int SymbianTruncate(sqlite3_file *id, sqlite3_int64 bytes) { + assert(bytes >=0); + + SymbianFile *file_id = ConvertToSymbianFile(id); + if (file_id->handle.SetSize(bytes) != KErrNone) { + return SQLITE_IOERR; + } + return SQLITE_OK; +} + +static int SymbianSync(sqlite3_file *id, int /*flags*/) { + SymbianFile *file_id = ConvertToSymbianFile(id); + if (file_id->handle.Flush() != KErrNone) { + return SQLITE_IOERR; + } else { + return SQLITE_OK; + } +} + +static int SymbianFileSize(sqlite3_file *id, sqlite3_int64 *size) { + assert(size); + + SymbianFile *file_id = ConvertToSymbianFile(id); + TInt size_tmp; + if (file_id->handle.Size(size_tmp) != KErrNone) { + return SQLITE_IOERR; + } + *size = size_tmp; + return SQLITE_OK; +} + +// File lock/unlock functions; see os_win.c for a description +// of the algorithm used. +static int GetReadLock(SymbianFile *file) { + file->shared_lock_byte = Math::Random() % (SHARED_SIZE - 1); + return file->handle.Lock(SHARED_FIRST + file->shared_lock_byte, 1); +} + +static int UnlockReadLock(SymbianFile *file) { + return file->handle.UnLock(SHARED_FIRST + file->shared_lock_byte, 1); +} + +static int SymbianLock(sqlite3_file *id, int lock_type) { + SymbianFile *file = ConvertToSymbianFile(id); + if (file->lock_type >= lock_type) { + return SQLITE_OK; + } + + // Make sure the locking sequence is correct + assert(file->lock_type != NO_LOCK || lock_type == SHARED_LOCK); + assert(lock_type != PENDING_LOCK); + assert(lock_type != RESERVED_LOCK || file->lock_type == 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. + int new_lock_type = file->lock_type; + int got_pending_lock = 0; + int res = KErrNone; + if (file->lock_type == NO_LOCK || + (lock_type == EXCLUSIVE_LOCK && file->lock_type == RESERVED_LOCK)) { + int count = kFileLockAttempts; + while (count-- > 0 && + (res = file->handle.Lock(PENDING_BYTE, 1)) != KErrNone ) { + // Try 3 times to get the pending lock. The pending lock might be + // held by another reader process who will release it momentarily. + OSTRACE2("could not get a PENDING lock. cnt=%d\n", cnt); + User::After(1000); + } + got_pending_lock = (res == KErrNone? 1 : 0); + } + + // Acquire a shared lock + if (lock_type == SHARED_LOCK && res == KErrNone) { + assert(file->lock_type == NO_LOCK); + res = GetReadLock(file); + if (res == KErrNone) { + new_lock_type = SHARED_LOCK; + } + } + + // Acquire a RESERVED lock + if (lock_type == RESERVED_LOCK && res == KErrNone) { + assert(file->lock_type == SHARED_LOCK); + res = file->handle.Lock(RESERVED_BYTE, 1); + if (res == KErrNone) { + new_lock_type = RESERVED_LOCK; + } + } + + // Acquire a PENDING lock + if (lock_type == EXCLUSIVE_LOCK && res == KErrNone) { + new_lock_type = PENDING_LOCK; + got_pending_lock = 0; + } + + // Acquire an EXCLUSIVE lock + if (lock_type == EXCLUSIVE_LOCK && res == KErrNone) { + assert(file->lock_type >= SHARED_LOCK); + res = UnlockReadLock(file); + OSTRACE2("unreadlock = %d\n", res); + res = file->handle.Lock(SHARED_FIRST, SHARED_SIZE); + if (res == KErrNone) { + new_lock_type = EXCLUSIVE_LOCK; + } else { + OSTRACE2("error-code = %d\n", GetLastError()); + GetReadLock(file); + } + } + + // If we are holding a PENDING lock that ought to be released, then + // release it now. + if (got_pending_lock && lock_type == SHARED_LOCK) { + file->handle.UnLock(PENDING_BYTE, 1); + } + + // Update the state of the lock held in the file descriptor, then + // return the appropriate result code. + file->lock_type = new_lock_type; + if (res == KErrNone) { + return SQLITE_OK; + } else { + OSTRACE4("LOCK FAILED %d trying for %d but got %d\n", file->handle, + lock_type, new_lock_type); + return SQLITE_BUSY; + } +} + +static int SymbianUnlock(sqlite3_file *id, int lock_type) { + int type; + int rc = SQLITE_OK; + SymbianFile *file = ConvertToSymbianFile(id); + assert(lock_type <= SHARED_LOCK); + OSTRACE5("UNLOCK %d to %d was %d(%d)\n", file->handle, lock_type, + file->lock_type, file->shared_lock_byte); + type = file->lock_type; + if (type >= EXCLUSIVE_LOCK) { + file->handle.UnLock(SHARED_FIRST, SHARED_SIZE); + if (lock_type == SHARED_LOCK && GetReadLock(file) != KErrNone) { + // This should never happen. We should always be able to + // reacquire the read lock + rc = SQLITE_IOERR_UNLOCK; + } + } + if (type >= RESERVED_LOCK) { + file->handle.UnLock(RESERVED_BYTE, 1); + } + if (lock_type == NO_LOCK && type >= SHARED_LOCK) { + UnlockReadLock(file); + } + if (type >= PENDING_LOCK) { + file->handle.UnLock(PENDING_BYTE, 1); + } + file->lock_type = lock_type; + return rc; +} + +static int SymbianCheckReservedLock(sqlite3_file *id, int *result) { + int rc; + SymbianFile *file = ConvertToSymbianFile(id); + if (file->lock_type >= RESERVED_LOCK) { + rc = 1; + OSTRACE3("TEST WR-LOCK %d %d (local)\n", pFile->h, rc); + } else { + rc = file->handle.Lock(RESERVED_BYTE, 1); + if (rc == KErrNone) { + file->handle.UnLock(RESERVED_BYTE, 1); + } + rc = !rc; + OSTRACE3("TEST WR-LOCK %d %d (remote)\n", file->handle, rc); + } + *result = rc; + return SQLITE_OK; +} + +static int SymbianFileControl(sqlite3_file */*id*/, + int /*op*/, + void */*arg*/) { + return SQLITE_OK; +} + +static int SymbianSectorSize(sqlite3_file */*id*/) { + return SQLITE_DEFAULT_SECTOR_SIZE; +} + +static int SymbianDeviceCharacteristics(sqlite3_file */*id*/) { + return 0; +} + +/* +** This vector defines all the methods that can operate on a +** sqlite3_file for Symbian. +*/ +static const sqlite3_io_methods SymbianIoMethod = { + 1, // iVersion + SymbianClose, + SymbianRead, + SymbianWrite, + SymbianTruncate, + SymbianSync, + SymbianFileSize, + SymbianLock, + SymbianUnlock, + SymbianCheckReservedLock, + SymbianFileControl, + SymbianSectorSize, + SymbianDeviceCharacteristics +}; + +// ============================================================================ +// vfs methods begin here +// ============================================================================ +static int SymbianOpen(sqlite3_vfs */*vfs*/, + const char *name, + sqlite3_file *id, + int flags, + int *out_flags) { + TUint desired_access; + TUint share_mode; + TInt err = KErrNone; + TFileName name_utf16; + SymbianFile *file = ConvertToSymbianFile(id); + + if (out_flags) { + *out_flags = flags; + } + + // if the name is NULL we have to open a temporary file. + if (!name) { + TPath private_path; + TFileName file_name; + if (g_fs_session.PrivatePath(private_path) != KErrNone) { + return SQLITE_CANTOPEN; + } + if (file->handle.Temp(g_fs_session, + private_path, + file_name, + EFileWrite) != + KErrNone) { + return SQLITE_CANTOPEN; + } + file->methods = &SymbianIoMethod; + file->lock_type = NO_LOCK; + file->shared_lock_byte = 0; + OpenCounter(+1); + return SQLITE_OK; + } + + if (UTF8ToUTF16(name, &name_utf16) != KErrNone) + return SQLITE_CANTOPEN; + + if (flags & SQLITE_OPEN_READWRITE) { + desired_access = EFileWrite; + } else { + desired_access = EFileRead; + } + if (flags & SQLITE_OPEN_MAIN_DB) { + share_mode = EFileShareReadersOrWriters; + } else { + share_mode = 0; + } + + if (flags & SQLITE_OPEN_CREATE) { + err = file->handle.Create(g_fs_session, + name_utf16, + desired_access | share_mode); + if (err != KErrNone && err != KErrAlreadyExists) { + return SQLITE_CANTOPEN; + } + } + + if (err != KErrNone) { + err = file->handle.Open(g_fs_session, + name_utf16, + desired_access | share_mode); + if (err != KErrNone && flags & SQLITE_OPEN_READWRITE) { + if (out_flags) { + *out_flags = (flags | SQLITE_OPEN_READONLY) & ~SQLITE_OPEN_READWRITE; + } + desired_access = EFileRead; + err = file->handle.Open(g_fs_session, + name_utf16, + desired_access | share_mode); + } + if (err != KErrNone) { + return SQLITE_CANTOPEN; + } + } + file->methods = &SymbianIoMethod; + file->lock_type = NO_LOCK; + file->shared_lock_byte = 0; + OpenCounter(+1); + return SQLITE_OK; +} + +static int SymbianDelete(sqlite3_vfs */*vfs*/, + const char *file_name, + int /*sync_dir*/) { + assert(file_name); + TFileName file_name_utf16; + + if (UTF8ToUTF16(file_name, &file_name_utf16) != KErrNone) { + return SQLITE_ERROR; + } + + TInt result = g_fs_session.Delete(file_name_utf16); + return (result == KErrNone || result == KErrPathNotFound)? + SQLITE_OK : SQLITE_IOERR_DELETE; +} + +static int SymbianAccess(sqlite3_vfs */*vfs*/, + const char *file_name, + int flags, + int *result) { + assert(file_name); + TEntry entry; + TFileName file_name_utf16; + + if (UTF8ToUTF16(file_name, &file_name_utf16) != KErrNone) { + return SQLITE_ERROR; + } + + if (g_fs_session.Entry(file_name_utf16, entry) != KErrNone) { + *result = 0; + return SQLITE_OK; + } + + switch (flags) { + case SQLITE_ACCESS_READ: + case SQLITE_ACCESS_EXISTS: + *result = !entry.IsDir(); + break; + case SQLITE_ACCESS_READWRITE: + *result = !entry.IsDir() && !entry.IsReadOnly(); + break; + default: + return SQLITE_ERROR; + } + + return SQLITE_OK; +} + +static int SymbianFullPathname(sqlite3_vfs */*vfs*/, + const char *relative, + int full_len, + char *full) { + assert(relative); + assert(full); + + TParse parse; + TPath relative_utf16; + TPath base_path; + TPtr8 full_utf8(reinterpret_cast<unsigned char*>(full), full_len); + + g_fs_session.PrivatePath(base_path); + + if (UTF8ToUTF16(relative, &relative_utf16) != KErrNone) { + return SQLITE_ERROR; + } + + if (parse.Set(relative_utf16, &base_path, NULL) != KErrNone) { + return SQLITE_ERROR; + } + + TDesC full_utf16(parse.FullName()); + if (UTF16ToUTF8(relative_utf16, &full_utf8) != KErrNone) { + return SQLITE_ERROR; + } + + full_utf8.PtrZ(); + return SQLITE_OK; +} + +static int SymbianRandomness(sqlite3_vfs */*vfs*/, int buf_len, char *buffer) { + assert(buffer); + TInt64 seed = User::TickCount(); + for (TInt i = 0; i < buf_len; i++) { + buffer[i] = Math::Rand(seed) % 255; + } + return SQLITE_OK; +} + +static int SymbianSleep(sqlite3_vfs */*vfs*/, int microsec) { + User::After(microsec); + return SQLITE_OK; +} + +int SymbianCurrentTime(sqlite3_vfs */*vfs*/, double *now) { + _LIT(kEpoch, "19700101:000000.000000"); + assert(now); + TTime time; + TTime epoch_time(kEpoch); + TTimeIntervalSeconds interval; + + time.HomeTime(); + // calculate seconds elapsed since 1-1-1970 + time.SecondsFrom(epoch_time, interval); + + // Julian date @ 1-1-1970 = 2440587.5 + // seconds per day = 86400.0 + *now = interval.Int()/86400.0 + 2440587.5; + return SQLITE_OK; +} + +static int SymbianGetLastError(sqlite3_vfs */*vfs*/, + int /*buf_len*/, + char */*buf*/) { + assert(buf[0] == '\0'); + return 0; +} + +// Interfaces for opening a shared library, finding entry points +// within the shared library, and closing the shared library. +// TODO(marcogelmi): implement. +#define SymbianDlOpen 0 +#define SymbianDlError 0 +#define SymbianDlSym 0 +#define SymbianDlClose 0 + +// Initialize and deinitialize the operating system interface. +int sqlite3_os_init(void) { + static sqlite3_vfs symbian_vfs = { + 1, // iVersion + sizeof(SymbianFile), // szOsFile + KMaxPath, // mxPathname + 0, // pNext + "symbian", // name + 0, // pAppData + + SymbianOpen, // xOpen + SymbianDelete, // xDelete + SymbianAccess, // xAccess + SymbianFullPathname, // xFullPathname + SymbianDlOpen, // xDlOpen + SymbianDlError, // xDlError + SymbianDlSym, // xDlSym + SymbianDlClose, // xDlClose + SymbianRandomness, // xRandomness + SymbianSleep, // xSleep + SymbianCurrentTime, // xCurrentTime + SymbianGetLastError // xGetLastError + }; + + if (g_fs_session.Connect() != KErrNone) { + return SQLITE_ERROR; + } + + if (g_fs_session.ShareAuto() != KErrNone) { + g_fs_session.Close(); + return SQLITE_ERROR; + } + + sqlite3_vfs_register(&symbian_vfs, 1); + return SQLITE_OK; +} + +int sqlite3_os_end(void) { + g_fs_session.Close(); + return SQLITE_OK; +} + +#endif /* OS_SYMBIAN*/ diff --git a/third_party/sqlite/src/os_unix.c b/third_party/sqlite/src/os_unix.c new file mode 100755 index 0000000..4874a64 --- /dev/null +++ b/third_party/sqlite/src/os_unix.c @@ -0,0 +1,2750 @@ +/* +** 2004 May 22 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains code that is specific to Unix systems. +** +** $Id: os_unix.c,v 1.195 2008/07/30 17:28:04 drh Exp $ +*/ +#include "sqliteInt.h" +#if SQLITE_OS_UNIX /* This file is used on unix only */ + +/* +** If SQLITE_ENABLE_LOCKING_STYLE is defined, then several different +** locking implementations are provided: +** +** * POSIX locking (the default), +** * No locking, +** * Dot-file locking, +** * flock() locking, +** * AFP locking (OSX only). +*/ +/* #define SQLITE_ENABLE_LOCKING_STYLE 0 */ + +/* +** 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 <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <time.h> +#include <sys/time.h> +#include <errno.h> + +#ifdef SQLITE_ENABLE_LOCKING_STYLE +#include <sys/ioctl.h> +#include <sys/param.h> +#include <sys/mount.h> +#endif /* SQLITE_ENABLE_LOCKING_STYLE */ + +/* +** If we are to be thread-safe, include the pthreads header and define +** the SQLITE_UNIX_THREADS macro. +*/ +#if SQLITE_THREADSAFE +# include <pthread.h> +# 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 + +/* +** Maximum supported path-length. +*/ +#define MAX_PATHNAME 512 + + +/* +** The unixFile structure is subclass of sqlite3_file specific for the unix +** protability layer. +*/ +typedef struct unixFile unixFile; +struct unixFile { + sqlite3_io_methods const *pMethod; /* Always the first entry */ +#ifdef SQLITE_TEST + /* In test mode, increase the size of this structure a bit so that + ** it is larger than the struct CrashFile defined in test6.c. + */ + char aPadding[32]; +#endif + struct openCnt *pOpen; /* Info about all open fd's on this inode */ + struct lockInfo *pLock; /* Info about locks on this inode */ +#ifdef SQLITE_ENABLE_LOCKING_STYLE + void *lockingContext; /* Locking style specific state */ +#endif + int h; /* The file descriptor */ + unsigned char locktype; /* The type of lock held on this fd */ + int dirfd; /* File descriptor for the directory */ +#if SQLITE_THREADSAFE + pthread_t tid; /* The thread that "owns" this unixFile */ +#endif +}; + +/* +** Include code that is common to all os_*.c files +*/ +#include "os_common.h" + +/* +** Define various macros that are missing from some systems. +*/ +#ifndef O_LARGEFILE +# define O_LARGEFILE 0 +#endif +#ifdef SQLITE_DISABLE_LFS +# undef O_LARGEFILE +# define O_LARGEFILE 0 +#endif +#ifndef O_NOFOLLOW +# define O_NOFOLLOW 0 +#endif +#ifndef O_BINARY +# define O_BINARY 0 +#endif + +/* +** 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 it is DOS - what did you expect? +*/ +#ifdef __DJGPP__ +# define fcntl(A,B,C) 0 +#endif + +/* +** The threadid macro resolves to the thread-id or to 0. Used for +** testing and debugging only. +*/ +#if SQLITE_THREADSAFE +#define threadid pthread_self() +#else +#define threadid 0 +#endif + +/* +** Set or check the unixFile.tid field. This field is set when an unixFile +** is first opened. All subsequent uses of the unixFile verify that the +** same thread is operating on the unixFile. Some operating systems do +** not allow locks to be overridden by other threads and that restriction +** 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): unixFile 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 unixFile.pLock field needs to be +** recomputed because its key includes the thread-id. See the +** transferOwnership() function below for additional information +*/ +#if SQLITE_THREADSAFE +# 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 +#endif + +/* +** Here is the dirt on POSIX advisory locks: ANSI STD 1003.1 (1996) +** section 6.5.2.2 lines 483 through 490 specify that when a process +** sets or clears a lock, that operation overrides any prior locks set +** by the same process. It does not explicitly say so, but this implies +** that it overrides locks set by the same process using a different +** file descriptor. Consider this test case: +** int fd2 = open("./file2", O_RDWR|O_CREAT, 0644); +** +** Suppose ./file1 and ./file2 are really the same file (because +** one is a hard or symbolic link to the other) then if you set +** an exclusive lock on fd1, then try to get an exclusive lock +** on fd2, it works. I would have expected the second lock to +** fail since there was already a lock on the file due to fd1. +** But not so. Since both locks came from the same process, the +** second overrides the first, even though they were on different +** file descriptors opened on different file names. +** +** Bummer. If you ask me, this is broken. Badly broken. It means +** that we cannot use POSIX locks to synchronize file access among +** competing threads of the same process. POSIX locks will work fine +** to synchronize access for threads in separate processes, but not +** threads within the same process. +** +** To work around the problem, SQLite has to manage file locks internally +** on its own. Whenever a new database is opened, we have to find the +** specific inode of the database file (the inode is determined by the +** st_dev and st_ino fields of the stat structure that fstat() fills in) +** and check for locks already existing on that inode. When locks are +** created or removed, we have to look at our own internal record of the +** locks to see if another thread has previously set a lock on that same +** inode. +** +** The sqlite3_file structure for POSIX is no longer just an integer file +** descriptor. It is now a structure that holds the integer file +** descriptor and a pointer to a structure that describes the internal +** locks on the corresponding inode. There is one locking structure +** per inode, so if the same inode is opened twice, both unixFile structures +** point to the same locking structure. The locking structure keeps +** a reference count (so we will know when to delete it) and a "cnt" +** field that tells us its internal lock status. cnt==0 means the +** file is unlocked. cnt==-1 means the file has an exclusive lock. +** cnt>0 means there are cnt shared locks on the file. +** +** Any attempt to lock or unlock a file first checks the locking +** structure. The fcntl() system call is only invoked to set a +** POSIX lock if the internal lock structure transitions between +** a locked and an unlocked state. +** +** 2004-Jan-11: +** More recent discoveries about POSIX advisory locks. (The more +** I discover, the more I realize the a POSIX advisory locks are +** an abomination.) +** +** If you close a file descriptor that points to a file that has locks, +** all locks on that file that are owned by the current process are +** released. To work around this problem, each unixFile structure contains +** a pointer to an openCnt structure. There is one openCnt structure +** per open inode, which means that multiple unixFile can point to a single +** openCnt. When an attempt is made to close an unixFile, if there are +** other unixFile open on the same inode that are holding locks, the call +** to close() the file descriptor is deferred until all of the locks clear. +** The openCnt structure keeps a list of file descriptors that need to +** be closed and that list is walked (and cleared) when the last lock +** clears. +** +** First, under Linux threads, because each thread has a separate +** process ID, lock operations in one thread do not override locks +** to the same file in other threads. Linux threads behave like +** separate processes in this respect. But, if you close a file +** descriptor in linux threads, all locks are cleared, even locks +** on other threads and even though the other threads have different +** process IDs. Linux threads is inconsistent in this respect. +** (I'm beginning to think that linux threads is an abomination too.) +** The consequence of this all is that the hash table for the lockInfo +** structure has to include the process id as part of its key because +** locks in different threads are treated as distinct. But the +** openCnt structure should not include the process id in its +** key because close() clears lock on all threads, not just the current +** thread. Were it not for this goofiness in linux threads, we could +** combine the lockInfo and openCnt structures into a single structure. +** +** 2004-Jun-28: +** On some versions of linux, threads can override each others locks. +** On others not. Sometimes you can change the behavior on the same +** system by setting the LD_ASSUME_KERNEL environment variable. The +** POSIX standard is silent as to which behavior is correct, as far +** as I can tell, so other versions of unix might show the same +** inconsistency. There is no little doubt in my mind that posix +** advisory locks and linux threads are profoundly broken. +** +** To work around the inconsistencies, we have to test at runtime +** whether or not threads can override each others locks. This test +** is run once, the first time any lock is attempted. A static +** variable is set to record the results of this test for future +** use. +*/ + +/* +** An instance of the following structure serves as the key used +** to locate a particular lockInfo structure given its inode. +** +** 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 omitted +** if we compile without threading support. +*/ +struct lockKey { + dev_t dev; /* Device number */ + ino_t ino; /* Inode number */ +#if SQLITE_THREADSAFE + pthread_t tid; /* Thread ID or zero if threads can override each other */ +#endif +}; + +/* +** An instance of the following structure is allocated for each open +** inode on each thread with a different process ID. (Threads have +** different process IDs on linux, but not on most other unixes.) +** +** A single inode can have multiple file descriptors, so each unixFile +** structure contains a pointer to an instance of this object and this +** object keeps a count of the number of unixFile pointing to it. +*/ +struct lockInfo { + struct lockKey key; /* The lookup key */ + int cnt; /* Number of SHARED locks held */ + int locktype; /* One of SHARED_LOCK, RESERVED_LOCK etc. */ + int nRef; /* Number of pointers to this structure */ + struct lockInfo *pNext, *pPrev; /* List of all lockInfo objects */ +}; + +/* +** An instance of the following structure serves as the key used +** to locate a particular openCnt structure given its inode. This +** is the same as the lockKey except that the thread ID is omitted. +*/ +struct openKey { + dev_t dev; /* Device number */ + ino_t ino; /* Inode number */ +}; + +/* +** An instance of the following structure is allocated for each open +** inode. This structure keeps track of the number of locks on that +** inode. If a close is attempted against an inode that is holding +** locks, the close is deferred until all locks clear by adding the +** file descriptor to be closed to the pending list. +*/ +struct openCnt { + struct openKey key; /* The lookup key */ + int nRef; /* Number of pointers to this structure */ + int nLock; /* Number of outstanding locks */ + int nPending; /* Number of pending close() operations */ + int *aPending; /* Malloced space holding fd's awaiting a close() */ + struct openCnt *pNext, *pPrev; /* List of all openCnt objects */ +}; + +/* +** List of all lockInfo and openCnt objects. This used to be a hash +** table. But the number of objects is rarely more than a dozen and +** never exceeds a few thousand. And lookup is not on a critical +** path oo a simple linked list will suffice. +*/ +static struct lockInfo *lockList = 0; +static struct openCnt *openList = 0; + +/* +** The locking styles are associated with the different file locking +** capabilities supported by different file systems. +** +** POSIX locking style fully supports shared and exclusive byte-range locks +** AFP locking only supports exclusive byte-range locks +** FLOCK only supports a single file-global exclusive lock +** DOTLOCK isn't a true locking style, it refers to the use of a special +** file named the same as the database file with a '.lock' extension, this +** can be used on file systems that do not offer any reliable file locking +** NO locking means that no locking will be attempted, this is only used for +** read-only file systems currently +** UNSUPPORTED means that no locking will be attempted, this is only used for +** file systems that are known to be unsupported +*/ +#define LOCKING_STYLE_POSIX 1 +#define LOCKING_STYLE_NONE 2 +#define LOCKING_STYLE_DOTFILE 3 +#define LOCKING_STYLE_FLOCK 4 +#define LOCKING_STYLE_AFP 5 + +/* +** Helper functions to obtain and relinquish the global mutex. +*/ +static void enterMutex(){ + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); +} +static void leaveMutex(){ + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); +} + +#if SQLITE_THREADSAFE +/* +** This variable records whether or not threads can override each others +** locks. +** +** 0: No. Threads cannot override each others locks. +** 1: Yes. Threads can override each others locks. +** -1: We don't know yet. +** +** On some systems, we know at compile-time if threads can override each +** others locks. On those systems, the SQLITE_THREAD_OVERRIDE_LOCK macro +** will be set appropriately. On other systems, we have to check at +** runtime. On these latter systems, SQLTIE_THREAD_OVERRIDE_LOCK is +** undefined. +** +** 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. +*/ +#ifndef SQLITE_THREAD_OVERRIDE_LOCK +# define SQLITE_THREAD_OVERRIDE_LOCK -1 +#endif +#ifdef SQLITE_TEST +int threadsOverrideEachOthersLocks = SQLITE_THREAD_OVERRIDE_LOCK; +#else +static int threadsOverrideEachOthersLocks = SQLITE_THREAD_OVERRIDE_LOCK; +#endif + +/* +** This structure holds information passed into individual test +** threads by the testThreadLockingBehavior() routine. +*/ +struct threadTestData { + int fd; /* File to be locked */ + struct flock lock; /* The locking operation */ + int result; /* Result of the locking operation */ +}; + +#ifdef SQLITE_LOCK_TRACE +/* +** Print out information about all locking operations. +** +** 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 +** turned off. +*/ +static int lockTrace(int fd, int op, struct flock *p){ + char *zOpName, *zType; + int s; + int savedErrno; + if( op==F_GETLK ){ + zOpName = "GETLK"; + }else if( op==F_SETLK ){ + zOpName = "SETLK"; + }else{ + s = fcntl(fd, op, p); + sqlite3DebugPrintf("fcntl unknown %d %d %d\n", fd, op, s); + return s; + } + if( p->l_type==F_RDLCK ){ + zType = "RDLCK"; + }else if( p->l_type==F_WRLCK ){ + zType = "WRLCK"; + }else if( p->l_type==F_UNLCK ){ + zType = "UNLCK"; + }else{ + assert( 0 ); + } + assert( p->l_whence==SEEK_SET ); + s = fcntl(fd, op, p); + savedErrno = errno; + sqlite3DebugPrintf("fcntl %d %d %s %s %d %d %d %d\n", + threadid, fd, zOpName, zType, (int)p->l_start, (int)p->l_len, + (int)p->l_pid, s); + if( s==(-1) && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){ + struct flock l2; + l2 = *p; + fcntl(fd, F_GETLK, &l2); + if( l2.l_type==F_RDLCK ){ + zType = "RDLCK"; + }else if( l2.l_type==F_WRLCK ){ + zType = "WRLCK"; + }else if( l2.l_type==F_UNLCK ){ + zType = "UNLCK"; + }else{ + assert( 0 ); + } + sqlite3DebugPrintf("fcntl-failure-reason: %s %d %d %d\n", + zType, (int)l2.l_start, (int)l2.l_len, (int)l2.l_pid); + } + errno = savedErrno; + return s; +} +#define fcntl lockTrace +#endif /* SQLITE_LOCK_TRACE */ + +/* +** The testThreadLockingBehavior() routine launches two separate +** threads on this routine. This routine attempts to lock a file +** descriptor then returns. The success or failure of that attempt +** allows the testThreadLockingBehavior() procedure to determine +** whether or not threads can override each others locks. +*/ +static void *threadLockingTest(void *pArg){ + struct threadTestData *pData = (struct threadTestData*)pArg; + pData->result = fcntl(pData->fd, F_SETLK, &pData->lock); + return pArg; +} + +/* +** This procedure attempts to determine whether or not threads +** can override each others locks then sets the +** threadsOverrideEachOthersLocks variable appropriately. +*/ +static void testThreadLockingBehavior(int fd_orig){ + int fd; + struct threadTestData d[2]; + pthread_t t[2]; + + fd = dup(fd_orig); + if( fd<0 ) return; + memset(d, 0, sizeof(d)); + d[0].fd = fd; + d[0].lock.l_type = F_RDLCK; + d[0].lock.l_len = 1; + d[0].lock.l_start = 0; + d[0].lock.l_whence = SEEK_SET; + d[1] = d[0]; + d[1].lock.l_type = F_WRLCK; + pthread_create(&t[0], 0, threadLockingTest, &d[0]); + pthread_create(&t[1], 0, threadLockingTest, &d[1]); + pthread_join(t[0], 0); + pthread_join(t[1], 0); + close(fd); + threadsOverrideEachOthersLocks = d[0].result==0 && d[1].result==0; +} +#endif /* SQLITE_THREADSAFE */ + +/* +** Release a lockInfo structure previously allocated by findLockInfo(). +*/ +static void releaseLockInfo(struct lockInfo *pLock){ + if( pLock ){ + pLock->nRef--; + if( pLock->nRef==0 ){ + if( pLock->pPrev ){ + assert( pLock->pPrev->pNext==pLock ); + pLock->pPrev->pNext = pLock->pNext; + }else{ + assert( lockList==pLock ); + lockList = pLock->pNext; + } + if( pLock->pNext ){ + assert( pLock->pNext->pPrev==pLock ); + pLock->pNext->pPrev = pLock->pPrev; + } + sqlite3_free(pLock); + } + } +} + +/* +** Release a openCnt structure previously allocated by findLockInfo(). +*/ +static void releaseOpenCnt(struct openCnt *pOpen){ + if( pOpen ){ + pOpen->nRef--; + if( pOpen->nRef==0 ){ + if( pOpen->pPrev ){ + assert( pOpen->pPrev->pNext==pOpen ); + pOpen->pPrev->pNext = pOpen->pNext; + }else{ + assert( openList==pOpen ); + openList = pOpen->pNext; + } + if( pOpen->pNext ){ + assert( pOpen->pNext->pPrev==pOpen ); + pOpen->pNext->pPrev = pOpen->pPrev; + } + sqlite3_free(pOpen->aPending); + sqlite3_free(pOpen); + } + } +} + +#ifdef SQLITE_ENABLE_LOCKING_STYLE +/* +** Tests a byte-range locking query to see if byte range locks are +** supported, if not we fall back to dotlockLockingStyle. +*/ +static int testLockingStyle(int fd){ + struct flock lockInfo; + + /* Test byte-range lock using fcntl(). If the call succeeds, + ** assume that the file-system supports POSIX style locks. + */ + lockInfo.l_len = 1; + lockInfo.l_start = 0; + lockInfo.l_whence = SEEK_SET; + lockInfo.l_type = F_RDLCK; + if( fcntl(fd, F_GETLK, &lockInfo)!=-1 ) { + return LOCKING_STYLE_POSIX; + } + + /* Testing for flock() can give false positives. So if if the above + ** test fails, then we fall back to using dot-file style locking. + */ + return LOCKING_STYLE_DOTFILE; +} +#endif + +/* +** If SQLITE_ENABLE_LOCKING_STYLE is defined, this function Examines the +** f_fstypename entry in the statfs structure as returned by stat() for +** the file system hosting the database file and selects the appropriate +** locking style based on its value. These values and assignments are +** based on Darwin/OSX behavior and have not been thoroughly tested on +** other systems. +** +** If SQLITE_ENABLE_LOCKING_STYLE is not defined, this function always +** returns LOCKING_STYLE_POSIX. +*/ +static int detectLockingStyle( + sqlite3_vfs *pVfs, + const char *filePath, + int fd +){ +#ifdef SQLITE_ENABLE_LOCKING_STYLE + struct Mapping { + const char *zFilesystem; + int eLockingStyle; + } aMap[] = { + { "hfs", LOCKING_STYLE_POSIX }, + { "ufs", LOCKING_STYLE_POSIX }, + { "afpfs", LOCKING_STYLE_AFP }, + { "smbfs", LOCKING_STYLE_FLOCK }, + { "msdos", LOCKING_STYLE_DOTFILE }, + { "webdav", LOCKING_STYLE_NONE }, + { 0, 0 } + }; + int i; + struct statfs fsInfo; + + if( !filePath ){ + return LOCKING_STYLE_NONE; + } + if( pVfs->pAppData ){ + return (int)pVfs->pAppData; + } + + if( statfs(filePath, &fsInfo) != -1 ){ + if( fsInfo.f_flags & MNT_RDONLY ){ + return LOCKING_STYLE_NONE; + } + for(i=0; aMap[i].zFilesystem; i++){ + if( strcmp(fsInfo.f_fstypename, aMap[i].zFilesystem)==0 ){ + return aMap[i].eLockingStyle; + } + } + } + + /* Default case. Handles, amongst others, "nfs". */ + return testLockingStyle(fd); +#endif + return LOCKING_STYLE_POSIX; +} + +/* +** Given a file descriptor, locate lockInfo and openCnt structures that +** describes that file descriptor. Create new ones if necessary. The +** return values might be uninitialized if an error occurs. +** +** Return an appropriate error code. +*/ +static int findLockInfo( + int fd, /* The file descriptor used in the key */ + struct lockInfo **ppLock, /* Return the lockInfo structure here */ + struct openCnt **ppOpen /* Return the openCnt structure here */ +){ + int rc; + struct lockKey key1; + struct openKey key2; + struct stat statbuf; + struct lockInfo *pLock; + struct openCnt *pOpen; + rc = fstat(fd, &statbuf); + if( rc!=0 ){ +#ifdef EOVERFLOW + if( errno==EOVERFLOW ) return SQLITE_NOLFS; +#endif + return SQLITE_IOERR; + } + + /* On OS X on an msdos filesystem, the inode number is reported + ** incorrectly for zero-size files. See ticket #3260. To work + ** around this problem (we consider it a bug in OS X, not SQLite) + ** we always increase the file size to 1 by writing a single byte + ** prior to accessing the inode number. The one byte written is + ** an ASCII 'S' character which also happens to be the first byte + ** in the header of every SQLite database. In this way, if there + ** is a race condition such that another thread has already populated + ** the first page of the database, no damage is done. + */ + if( statbuf.st_size==0 ){ + write(fd, "S", 1); + rc = fstat(fd, &statbuf); + if( rc!=0 ){ + return SQLITE_IOERR; + } + } + + memset(&key1, 0, sizeof(key1)); + key1.dev = statbuf.st_dev; + key1.ino = statbuf.st_ino; +#if SQLITE_THREADSAFE + if( threadsOverrideEachOthersLocks<0 ){ + testThreadLockingBehavior(fd); + } + key1.tid = threadsOverrideEachOthersLocks ? 0 : pthread_self(); +#endif + memset(&key2, 0, sizeof(key2)); + key2.dev = statbuf.st_dev; + key2.ino = statbuf.st_ino; + pLock = lockList; + while( pLock && memcmp(&key1, &pLock->key, sizeof(key1)) ){ + pLock = pLock->pNext; + } + if( pLock==0 ){ + pLock = sqlite3_malloc( sizeof(*pLock) ); + if( pLock==0 ){ + rc = SQLITE_NOMEM; + goto exit_findlockinfo; + } + pLock->key = key1; + pLock->nRef = 1; + pLock->cnt = 0; + pLock->locktype = 0; + pLock->pNext = lockList; + pLock->pPrev = 0; + if( lockList ) lockList->pPrev = pLock; + lockList = pLock; + }else{ + pLock->nRef++; + } + *ppLock = pLock; + if( ppOpen!=0 ){ + pOpen = openList; + while( pOpen && memcmp(&key2, &pOpen->key, sizeof(key2)) ){ + pOpen = pOpen->pNext; + } + if( pOpen==0 ){ + pOpen = sqlite3_malloc( sizeof(*pOpen) ); + if( pOpen==0 ){ + releaseLockInfo(pLock); + rc = SQLITE_NOMEM; + goto exit_findlockinfo; + } + pOpen->key = key2; + pOpen->nRef = 1; + pOpen->nLock = 0; + pOpen->nPending = 0; + pOpen->aPending = 0; + pOpen->pNext = openList; + pOpen->pPrev = 0; + if( openList ) openList->pPrev = pOpen; + openList = pOpen; + }else{ + pOpen->nRef++; + } + *ppOpen = pOpen; + } + +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. +*/ +#if SQLITE_THREADSAFE +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 */ + OSTRACE1("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; + } + OSTRACE4("Transfer ownership of %d from %d to %d\n", + pFile->h, pFile->tid, hSelf); + pFile->tid = hSelf; + if (pFile->pLock != NULL) { + releaseLockInfo(pFile->pLock); + rc = findLockInfo(pFile->h, &pFile->pLock, 0); + OSTRACE5("LOCK %d is now %s(%s,%d)\n", pFile->h, + locktypeName(pFile->locktype), + locktypeName(pFile->pLock->locktype), pFile->pLock->cnt); + return rc; + } else { + return SQLITE_OK; + } +} +#else + /* On single-threaded builds, ownership transfer is a no-op */ +# define transferOwnership(X) SQLITE_OK +#endif + +/* +** Seek to the offset passed as the second argument, then read cnt +** bytes into pBuf. Return the number of bytes actually read. +** +** NB: If you define USE_PREAD or USE_PREAD64, then it might also +** be necessary to define _XOPEN_SOURCE to be 500. This varies from +** one system to another. Since SQLite does not define USE_PREAD +** any any form by default, we will not attempt to define _XOPEN_SOURCE. +** See tickets #2741 and #2681. +*/ +static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){ + int got; + i64 newOffset; + TIMER_START; +#if defined(USE_PREAD) + got = pread(id->h, pBuf, cnt, offset); + SimulateIOError( got = -1 ); +#elif defined(USE_PREAD64) + got = pread64(id->h, pBuf, cnt, offset); + SimulateIOError( got = -1 ); +#else + newOffset = lseek(id->h, offset, SEEK_SET); + SimulateIOError( newOffset-- ); + if( newOffset!=offset ){ + return -1; + } + got = read(id->h, pBuf, cnt); +#endif + TIMER_END; + OSTRACE5("READ %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED); + return got; +} + +/* +** Read data from a file into a buffer. Return SQLITE_OK if all +** bytes were read successfully and SQLITE_IOERR if anything goes +** wrong. +*/ +static int unixRead( + sqlite3_file *id, + void *pBuf, + int amt, + sqlite3_int64 offset +){ + int got; + assert( id ); + got = seekAndRead((unixFile*)id, offset, pBuf, amt); + if( got==amt ){ + return SQLITE_OK; + }else if( got<0 ){ + return SQLITE_IOERR_READ; + }else{ + memset(&((char*)pBuf)[got], 0, amt-got); + return SQLITE_IOERR_SHORT_READ; + } +} + +/* +** Seek to the offset in id->offset then read cnt bytes into pBuf. +** Return the number of bytes actually read. Update the offset. +*/ +static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){ + int got; + i64 newOffset; + TIMER_START; +#if defined(USE_PREAD) + got = pwrite(id->h, pBuf, cnt, offset); +#elif defined(USE_PREAD64) + got = pwrite64(id->h, pBuf, cnt, offset); +#else + newOffset = lseek(id->h, offset, SEEK_SET); + if( newOffset!=offset ){ + return -1; + } + got = write(id->h, pBuf, cnt); +#endif + TIMER_END; + OSTRACE5("WRITE %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED); + return got; +} + + +/* +** Write data from a buffer into a file. Return SQLITE_OK on success +** or some other error code on failure. +*/ +static int unixWrite( + sqlite3_file *id, + const void *pBuf, + int amt, + sqlite3_int64 offset +){ + int wrote = 0; + assert( id ); + assert( amt>0 ); + while( amt>0 && (wrote = seekAndWrite((unixFile*)id, offset, pBuf, amt))>0 ){ + amt -= wrote; + offset += wrote; + pBuf = &((char*)pBuf)[wrote]; + } + SimulateIOError(( wrote=(-1), amt=1 )); + SimulateDiskfullError(( wrote=0, amt=1 )); + if( amt>0 ){ + if( wrote<0 ){ + return SQLITE_IOERR_WRITE; + }else{ + return SQLITE_FULL; + } + } + return SQLITE_OK; +} + +#ifdef SQLITE_TEST +/* +** Count the number of fullsyncs and normal syncs. This is used to test +** that syncs and fullsyncs are occuring at the right times. +*/ +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 + +/* +** Define HAVE_FULLFSYNC to 0 or 1 depending on whether or not +** the F_FULLFSYNC macro is defined. F_FULLFSYNC is currently +** only available on Mac OS X. But that could change. +*/ +#ifdef F_FULLFSYNC +# define HAVE_FULLFSYNC 1 +#else +# define HAVE_FULLFSYNC 0 +#endif + + +/* +** The fsync() system call does not work as advertised on many +** unix systems. The following procedure is an attempt to make +** it work better. +** +** The SQLITE_NO_SYNC macro disables all fsync()s. This is useful +** for testing when we want to run through the test suite quickly. +** You are strongly advised *not* to deploy with SQLITE_NO_SYNC +** enabled, however, since with SQLITE_NO_SYNC enabled, an OS crash +** or power failure will likely corrupt the database file. +*/ +static int full_fsync(int fd, int fullSync, int dataOnly){ + int rc; + + /* Record the number of times that we do a normal fsync() and + ** FULLSYNC. This is used during testing to verify that this procedure + ** gets called with the correct arguments. + */ +#ifdef SQLITE_TEST + if( fullSync ) sqlite3_fullsync_count++; + sqlite3_sync_count++; +#endif + + /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a + ** no-op + */ +#ifdef SQLITE_NO_SYNC + rc = SQLITE_OK; +#else + +#if HAVE_FULLFSYNC + if( fullSync ){ + rc = fcntl(fd, F_FULLFSYNC, 0); + }else{ + rc = 1; + } + /* If the FULLFSYNC failed, fall back to attempting an fsync(). + * It shouldn't be possible for fullfsync to fail on the local + * file system (on OSX), so failure indicates that FULLFSYNC + * isn't supported for this file system. So, attempt an fsync + * and (for now) ignore the overhead of a superfluous fcntl call. + * It'd be better to detect fullfsync support once and avoid + * the fcntl call every time sync is called. + */ + if( rc ) rc = fsync(fd); + +#else + if( dataOnly ){ + rc = fdatasync(fd); + }else{ + rc = fsync(fd); + } +#endif /* HAVE_FULLFSYNC */ +#endif /* defined(SQLITE_NO_SYNC) */ + + return rc; +} + +/* +** Make sure all writes to a particular file are committed to disk. +** +** If dataOnly==0 then both the file itself and its metadata (file +** size, access time, etc) are synced. If dataOnly!=0 then only the +** file data is synced. +** +** Under Unix, also make sure that the directory entry for the file +** has been created by fsync-ing the directory that contains the file. +** If we do not do this and we encounter a power failure, the directory +** entry for the journal might not exist after we reboot. The next +** SQLite to access the file will not know that the journal exists (because +** the directory entry for the journal was never created) and the transaction +** will not roll back - possibly leading to database corruption. +*/ +static int unixSync(sqlite3_file *id, int flags){ + int rc; + unixFile *pFile = (unixFile*)id; + + int isDataOnly = (flags&SQLITE_SYNC_DATAONLY); + int isFullsync = (flags&0x0F)==SQLITE_SYNC_FULL; + + /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */ + assert((flags&0x0F)==SQLITE_SYNC_NORMAL + || (flags&0x0F)==SQLITE_SYNC_FULL + ); + + assert( pFile ); + OSTRACE2("SYNC %-3d\n", pFile->h); + rc = full_fsync(pFile->h, isFullsync, isDataOnly); + SimulateIOError( rc=1 ); + if( rc ){ + return SQLITE_IOERR_FSYNC; + } + if( pFile->dirfd>=0 ){ + OSTRACE4("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd, + HAVE_FULLFSYNC, isFullsync); +#ifndef SQLITE_DISABLE_DIRSYNC + /* The directory sync is only attempted if full_fsync is + ** turned off or unavailable. If a full_fsync occurred above, + ** then the directory sync is superfluous. + */ + if( (!HAVE_FULLFSYNC || !isFullsync) && full_fsync(pFile->dirfd,0,0) ){ + /* + ** We have received multiple reports of fsync() returning + ** errors when applied to directories on certain file systems. + ** A failed directory sync is not a big deal. So it seems + ** better to ignore the error. Ticket #1657 + */ + /* 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; +} + +/* +** Truncate an open file to a specified size +*/ +static int unixTruncate(sqlite3_file *id, i64 nByte){ + int rc; + assert( id ); + SimulateIOError( return SQLITE_IOERR_TRUNCATE ); + rc = ftruncate(((unixFile*)id)->h, (off_t)nByte); + if( rc ){ + return SQLITE_IOERR_TRUNCATE; + }else{ + return SQLITE_OK; + } +} + +/* +** Determine the current size of a file in bytes +*/ +static int unixFileSize(sqlite3_file *id, i64 *pSize){ + int rc; + struct stat buf; + assert( id ); + rc = fstat(((unixFile*)id)->h, &buf); + SimulateIOError( rc=1 ); + if( rc!=0 ){ + return SQLITE_IOERR_FSTAT; + } + *pSize = buf.st_size; + + /* When opening a zero-size database, the findLockInfo() procedure + ** writes a single byte into that file in order to work around a bug + ** in the OS-X msdos filesystem. In order to avoid problems with upper + ** layers, we need to report this file size as zero even though it is + ** really 1. Ticket #3260. + */ + if( *pSize==1 ) *pSize = 0; + + + return SQLITE_OK; +} + +/* +** This routine checks if there is a RESERVED lock held on the specified +** file by this or any other process. If such a lock is held, return +** non-zero. If the file is unlocked or holds only SHARED locks, then +** return zero. +*/ +static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){ + int r = 0; + unixFile *pFile = (unixFile*)id; + + SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); + + assert( pFile ); + enterMutex(); /* Because pFile->pLock is shared across threads */ + + /* Check if a thread in this process holds such a lock */ + if( pFile->pLock->locktype>SHARED_LOCK ){ + r = 1; + } + + /* Otherwise see if some other process holds it. + */ + if( !r ){ + struct flock lock; + lock.l_whence = SEEK_SET; + lock.l_start = RESERVED_BYTE; + lock.l_len = 1; + lock.l_type = F_WRLCK; + fcntl(pFile->h, F_GETLK, &lock); + if( lock.l_type!=F_UNLCK ){ + r = 1; + } + } + + leaveMutex(); + OSTRACE3("TEST WR-LOCK %d %d\n", pFile->h, r); + + *pResOut = r; + return SQLITE_OK; +} + +/* +** Lock the file with the lock specified by parameter locktype - one +** of the following: +** +** (1) SHARED_LOCK +** (2) RESERVED_LOCK +** (3) PENDING_LOCK +** (4) EXCLUSIVE_LOCK +** +** Sometimes when requesting one lock state, additional lock states +** are inserted in between. The locking might fail on one of the later +** transitions leaving the lock state different from what it started but +** still short of its goal. The following chart shows the allowed +** transitions and the inserted intermediate states: +** +** UNLOCKED -> SHARED +** SHARED -> RESERVED +** SHARED -> (PENDING) -> EXCLUSIVE +** RESERVED -> (PENDING) -> EXCLUSIVE +** PENDING -> EXCLUSIVE +** +** This routine will only increase a lock. Use the sqlite3OsUnlock() +** routine to lower a locking level. +*/ +static int unixLock(sqlite3_file *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 + ** confusion with SQLite lock names). The algorithms are complicated + ** slightly in order to be compatible with windows systems simultaneously + ** accessing the same database file, in case that is ever required. + ** + ** Symbols defined in os.h indentify the 'pending byte' and the 'reserved + ** byte', each single bytes at well known offsets, and the 'shared byte + ** range', a range of 510 bytes at a well known offset. + ** + ** To obtain a SHARED lock, a read-lock is obtained on the 'pending + ** byte'. If this is successful, a random byte from the 'shared byte + ** range' is read-locked and the lock on the 'pending byte' released. + ** + ** A process may only obtain a RESERVED lock after it has a SHARED lock. + ** A RESERVED lock is implemented by grabbing a write-lock on the + ** 'reserved byte'. + ** + ** A process may only obtain a PENDING lock after it has obtained a + ** SHARED lock. A PENDING lock is implemented by obtaining a write-lock + ** on the 'pending byte'. This ensures that no new SHARED locks can be + ** obtained, but existing SHARED locks are allowed to persist. A process + ** does not have to obtain a RESERVED lock on the way to a PENDING lock. + ** This property is used by the algorithm for rolling back a journal file + ** after a crash. + ** + ** An EXCLUSIVE lock, obtained after a PENDING lock is held, is + ** implemented by obtaining a write-lock on the entire 'shared byte + ** range'. Since all other locks require a read-lock on one of the bytes + ** within this range, this ensures that no other locks are held on the + ** database. + ** + ** The reason a single byte cannot be used instead of the 'shared byte + ** range' is that some versions of windows do not support read-locks. By + ** locking a random byte from a range, concurrent SHARED locks may exist + ** even if the locking primitive used is always a write-lock. + */ + int rc = SQLITE_OK; + unixFile *pFile = (unixFile*)id; + struct lockInfo *pLock = pFile->pLock; + struct flock lock; + int s; + + assert( pFile ); + OSTRACE7("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 + ** unixFile, do nothing. Don't use the end_lock: exit path, as + ** enterMutex() hasn't been called yet. + */ + if( pFile->locktype>=locktype ){ + OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h, + locktypeName(locktype)); + return SQLITE_OK; + } + + /* Make sure the locking sequence is correct + */ + assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); + assert( locktype!=PENDING_LOCK ); + assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); + + /* This mutex is needed because pFile->pLock is shared across threads + */ + enterMutex(); + + /* Make sure the current thread owns the pFile. + */ + rc = transferOwnership(pFile); + if( rc!=SQLITE_OK ){ + leaveMutex(); + return rc; + } + pLock = pFile->pLock; + + /* If some thread using this PID has a lock via a different unixFile* + ** handle that precludes the requested lock, return BUSY. + */ + if( (pFile->locktype!=pLock->locktype && + (pLock->locktype>=PENDING_LOCK || locktype>SHARED_LOCK)) + ){ + rc = SQLITE_BUSY; + goto end_lock; + } + + /* If a SHARED lock is requested, and some thread using this PID already + ** has a SHARED or RESERVED lock, then increment reference counts and + ** return SQLITE_OK. + */ + if( locktype==SHARED_LOCK && + (pLock->locktype==SHARED_LOCK || pLock->locktype==RESERVED_LOCK) ){ + assert( locktype==SHARED_LOCK ); + assert( pFile->locktype==0 ); + assert( pLock->cnt>0 ); + pFile->locktype = SHARED_LOCK; + pLock->cnt++; + pFile->pOpen->nLock++; + goto end_lock; + } + + lock.l_len = 1L; + + lock.l_whence = SEEK_SET; + + /* A PENDING lock is needed before acquiring a SHARED lock and before + ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will + ** be released. + */ + if( locktype==SHARED_LOCK + || (locktype==EXCLUSIVE_LOCK && pFile->locktype<PENDING_LOCK) + ){ + lock.l_type = (locktype==SHARED_LOCK?F_RDLCK:F_WRLCK); + lock.l_start = PENDING_BYTE; + s = fcntl(pFile->h, F_SETLK, &lock); + if( s==(-1) ){ + rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; + goto end_lock; + } + } + + + /* If control gets to this point, then actually go ahead and make + ** operating system calls for the specified lock. + */ + if( locktype==SHARED_LOCK ){ + assert( pLock->cnt==0 ); + assert( pLock->locktype==0 ); + + /* Now get the read-lock */ + lock.l_start = SHARED_FIRST; + lock.l_len = SHARED_SIZE; + 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(pFile->h, F_SETLK, &lock)!=0 ){ + rc = SQLITE_IOERR_UNLOCK; /* This should never happen */ + goto end_lock; + } + if( s==(-1) ){ + rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; + }else{ + pFile->locktype = SHARED_LOCK; + pFile->pOpen->nLock++; + pLock->cnt = 1; + } + }else if( locktype==EXCLUSIVE_LOCK && pLock->cnt>1 ){ + /* We are trying for an exclusive lock but another thread in this + ** same process is still holding a shared lock. */ + rc = SQLITE_BUSY; + }else{ + /* The request was for a RESERVED or EXCLUSIVE lock. It is + ** assumed that there is a SHARED or greater lock on the file + ** already. + */ + assert( 0!=pFile->locktype ); + lock.l_type = F_WRLCK; + switch( locktype ){ + case RESERVED_LOCK: + lock.l_start = RESERVED_BYTE; + break; + case EXCLUSIVE_LOCK: + lock.l_start = SHARED_FIRST; + lock.l_len = SHARED_SIZE; + break; + default: + assert(0); + } + s = fcntl(pFile->h, F_SETLK, &lock); + if( s==(-1) ){ + rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; + } + } + + if( rc==SQLITE_OK ){ + pFile->locktype = locktype; + pLock->locktype = locktype; + }else if( locktype==EXCLUSIVE_LOCK ){ + pFile->locktype = PENDING_LOCK; + pLock->locktype = PENDING_LOCK; + } + +end_lock: + leaveMutex(); + OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype), + rc==SQLITE_OK ? "ok" : "failed"); + return rc; +} + +/* +** 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. +*/ +static int unixUnlock(sqlite3_file *id, int locktype){ + struct lockInfo *pLock; + struct flock lock; + int rc = SQLITE_OK; + unixFile *pFile = (unixFile*)id; + int h; + + assert( pFile ); + OSTRACE7("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( pFile->locktype<=locktype ){ + return SQLITE_OK; + } + if( CHECK_THREADID(pFile) ){ + return SQLITE_MISUSE; + } + enterMutex(); + h = pFile->h; + pLock = pFile->pLock; + assert( pLock->cnt!=0 ); + if( pFile->locktype>SHARED_LOCK ){ + assert( pLock->locktype==pFile->locktype ); + SimulateIOErrorBenign(1); + SimulateIOError( h=(-1) ) + SimulateIOErrorBenign(0); + 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(h, F_SETLK, &lock)==(-1) ){ + rc = SQLITE_IOERR_RDLOCK; + } + } + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + lock.l_start = PENDING_BYTE; + lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE ); + if( fcntl(h, F_SETLK, &lock)!=(-1) ){ + pLock->locktype = SHARED_LOCK; + }else{ + rc = SQLITE_IOERR_UNLOCK; + } + } + if( locktype==NO_LOCK ){ + struct openCnt *pOpen; + + /* Decrement the shared lock counter. Release the lock using an + ** OS call only when all threads in this same process have released + ** the lock. + */ + pLock->cnt--; + if( pLock->cnt==0 ){ + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + lock.l_start = lock.l_len = 0L; + SimulateIOErrorBenign(1); + SimulateIOError( h=(-1) ) + SimulateIOErrorBenign(0); + if( fcntl(h, F_SETLK, &lock)!=(-1) ){ + pLock->locktype = NO_LOCK; + }else{ + rc = SQLITE_IOERR_UNLOCK; + pLock->cnt = 1; + } + } + + /* Decrement the count of locks against this same file. When the + ** count reaches zero, close any other file descriptors whose close + ** was deferred because of outstanding locks. + */ + if( rc==SQLITE_OK ){ + pOpen = pFile->pOpen; + pOpen->nLock--; + assert( pOpen->nLock>=0 ); + if( pOpen->nLock==0 && pOpen->nPending>0 ){ + int i; + for(i=0; i<pOpen->nPending; i++){ + close(pOpen->aPending[i]); + } + sqlite3_free(pOpen->aPending); + pOpen->nPending = 0; + pOpen->aPending = 0; + } + } + } + leaveMutex(); + if( rc==SQLITE_OK ) pFile->locktype = locktype; + return rc; +} + +/* +** This function performs the parts of the "close file" operation +** common to all locking schemes. It closes the directory and file +** handles, if they are valid, and sets all fields of the unixFile +** structure to 0. +*/ +static int closeUnixFile(sqlite3_file *id){ + unixFile *pFile = (unixFile*)id; + if( pFile ){ + if( pFile->dirfd>=0 ){ + close(pFile->dirfd); + } + if( pFile->h>=0 ){ + close(pFile->h); + } + OSTRACE2("CLOSE %-3d\n", pFile->h); + OpenCounter(-1); + memset(pFile, 0, sizeof(unixFile)); + } + return SQLITE_OK; +} + +/* +** Close a file. +*/ +static int unixClose(sqlite3_file *id){ + if( id ){ + unixFile *pFile = (unixFile *)id; + unixUnlock(id, NO_LOCK); + enterMutex(); + if( pFile->pOpen && pFile->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 + ** descriptor to pOpen->aPending. It will be automatically closed when + ** the last lock is cleared. + */ + int *aNew; + struct openCnt *pOpen = pFile->pOpen; + aNew = sqlite3_realloc(pOpen->aPending, (pOpen->nPending+1)*sizeof(int) ); + if( aNew==0 ){ + /* If a malloc fails, just leak the file descriptor */ + }else{ + pOpen->aPending = aNew; + pOpen->aPending[pOpen->nPending] = pFile->h; + pOpen->nPending++; + pFile->h = -1; + } + } + releaseLockInfo(pFile->pLock); + releaseOpenCnt(pFile->pOpen); + closeUnixFile(id); + leaveMutex(); + } + return SQLITE_OK; +} + + +#ifdef SQLITE_ENABLE_LOCKING_STYLE +#pragma mark AFP Support + +/* + ** The afpLockingContext structure contains all afp lock specific state + */ +typedef struct afpLockingContext afpLockingContext; +struct afpLockingContext { + unsigned long long sharedLockByte; + const char *filePath; +}; + +struct ByteRangeLockPB2 +{ + unsigned long long offset; /* offset to first byte to lock */ + unsigned long long length; /* nbr of bytes to lock */ + unsigned long long retRangeStart; /* nbr of 1st byte locked if successful */ + unsigned char unLockFlag; /* 1 = unlock, 0 = lock */ + unsigned char startEndFlag; /* 1=rel to end of fork, 0=rel to start */ + int fd; /* file desc to assoc this lock with */ +}; + +#define afpfsByteRangeLock2FSCTL _IOWR('z', 23, struct ByteRangeLockPB2) + +/* +** Return 0 on success, 1 on failure. To match the behavior of the +** normal posix file locking (used in unixLock for example), we should +** provide 'richer' return codes - specifically to differentiate between +** 'file busy' and 'file system error' results. +*/ +static int _AFPFSSetLock( + const char *path, + int fd, + unsigned long long offset, + unsigned long long length, + int setLockFlag +){ + struct ByteRangeLockPB2 pb; + int err; + + pb.unLockFlag = setLockFlag ? 0 : 1; + pb.startEndFlag = 0; + pb.offset = offset; + pb.length = length; + pb.fd = fd; + OSTRACE5("AFPLOCK setting lock %s for %d in range %llx:%llx\n", + (setLockFlag?"ON":"OFF"), fd, offset, length); + err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0); + if ( err==-1 ) { + OSTRACE4("AFPLOCK failed to fsctl() '%s' %d %s\n", path, errno, + strerror(errno)); + return 1; /* error */ + } else { + return 0; + } +} + +/* + ** This routine checks if there is a RESERVED lock held on the specified + ** file by this or any other process. If such a lock is held, return + ** non-zero. If the file is unlocked or holds only SHARED locks, then + ** return zero. + */ +static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){ + int r = 0; + unixFile *pFile = (unixFile*)id; + + assert( pFile ); + afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; + + /* Check if a thread in this process holds such a lock */ + if( pFile->locktype>SHARED_LOCK ){ + r = 1; + } + + /* Otherwise see if some other process holds it. + */ + if ( !r ) { + /* lock the byte */ + int failed = _AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1,1); + if (failed) { + /* if we failed to get the lock then someone else must have it */ + r = 1; + } else { + /* if we succeeded in taking the reserved lock, unlock it to restore + ** the original state */ + _AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1, 0); + } + } + OSTRACE3("TEST WR-LOCK %d %d\n", pFile->h, r); + + *pResOut = r; + return SQLITE_OK; +} + +/* AFP-style locking following the behavior of unixLock, see the unixLock +** function comments for details of lock management. */ +static int afpLock(sqlite3_file *id, int locktype){ + int rc = SQLITE_OK; + unixFile *pFile = (unixFile*)id; + afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; + + assert( pFile ); + OSTRACE5("LOCK %d %s was %s pid=%d\n", pFile->h, + locktypeName(locktype), locktypeName(pFile->locktype), getpid()); + + /* If there is already a lock of this type or more restrictive on the + ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as + ** enterMutex() hasn't been called yet. + */ + if( pFile->locktype>=locktype ){ + OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h, + locktypeName(locktype)); + return SQLITE_OK; + } + + /* Make sure the locking sequence is correct + */ + assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); + assert( locktype!=PENDING_LOCK ); + assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); + + /* This mutex is needed because pFile->pLock is shared across threads + */ + enterMutex(); + + /* Make sure the current thread owns the pFile. + */ + rc = transferOwnership(pFile); + if( rc!=SQLITE_OK ){ + leaveMutex(); + return rc; + } + + /* A PENDING lock is needed before acquiring a SHARED lock and before + ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will + ** be released. + */ + if( locktype==SHARED_LOCK + || (locktype==EXCLUSIVE_LOCK && pFile->locktype<PENDING_LOCK) + ){ + int failed; + failed = _AFPFSSetLock(context->filePath, pFile->h, PENDING_BYTE, 1, 1); + if (failed) { + rc = SQLITE_BUSY; + goto afp_end_lock; + } + } + + /* If control gets to this point, then actually go ahead and make + ** operating system calls for the specified lock. + */ + if( locktype==SHARED_LOCK ){ + int lk, failed; + + /* Now get the read-lock */ + /* note that the quality of the randomness doesn't matter that much */ + lk = random(); + context->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1); + failed = _AFPFSSetLock(context->filePath, pFile->h, + SHARED_FIRST+context->sharedLockByte, 1, 1); + + /* Drop the temporary PENDING lock */ + if (_AFPFSSetLock(context->filePath, pFile->h, PENDING_BYTE, 1, 0)) { + rc = SQLITE_IOERR_UNLOCK; /* This should never happen */ + goto afp_end_lock; + } + + if( failed ){ + rc = SQLITE_BUSY; + } else { + pFile->locktype = SHARED_LOCK; + } + }else{ + /* The request was for a RESERVED or EXCLUSIVE lock. It is + ** assumed that there is a SHARED or greater lock on the file + ** already. + */ + int failed = 0; + assert( 0!=pFile->locktype ); + if (locktype >= RESERVED_LOCK && pFile->locktype < RESERVED_LOCK) { + /* Acquire a RESERVED lock */ + failed = _AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1,1); + } + if (!failed && locktype == EXCLUSIVE_LOCK) { + /* Acquire an EXCLUSIVE lock */ + + /* Remove the shared lock before trying the range. we'll need to + ** reestablish the shared lock if we can't get the afpUnlock + */ + if (!_AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST + + context->sharedLockByte, 1, 0)) { + /* now attemmpt to get the exclusive lock range */ + failed = _AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST, + SHARED_SIZE, 1); + if (failed && _AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST + + context->sharedLockByte, 1, 1)) { + rc = SQLITE_IOERR_RDLOCK; /* this should never happen */ + } + } else { + /* */ + rc = SQLITE_IOERR_UNLOCK; /* this should never happen */ + } + } + if( failed && rc == SQLITE_OK){ + rc = SQLITE_BUSY; + } + } + + if( rc==SQLITE_OK ){ + pFile->locktype = locktype; + }else if( locktype==EXCLUSIVE_LOCK ){ + pFile->locktype = PENDING_LOCK; + } + +afp_end_lock: + leaveMutex(); + OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype), + rc==SQLITE_OK ? "ok" : "failed"); + return rc; +} + +/* +** 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. +*/ +static int afpUnlock(sqlite3_file *id, int locktype) { + int rc = SQLITE_OK; + unixFile *pFile = (unixFile*)id; + afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; + + assert( pFile ); + OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype, + pFile->locktype, getpid()); + + assert( locktype<=SHARED_LOCK ); + if( pFile->locktype<=locktype ){ + return SQLITE_OK; + } + if( CHECK_THREADID(pFile) ){ + return SQLITE_MISUSE; + } + enterMutex(); + if( pFile->locktype>SHARED_LOCK ){ + if( locktype==SHARED_LOCK ){ + int failed = 0; + + /* unlock the exclusive range - then re-establish the shared lock */ + if (pFile->locktype==EXCLUSIVE_LOCK) { + failed = _AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST, + SHARED_SIZE, 0); + if (!failed) { + /* successfully removed the exclusive lock */ + if (_AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST+ + context->sharedLockByte, 1, 1)) { + /* failed to re-establish our shared lock */ + rc = SQLITE_IOERR_RDLOCK; /* This should never happen */ + } + } else { + /* This should never happen - failed to unlock the exclusive range */ + rc = SQLITE_IOERR_UNLOCK; + } + } + } + if (rc == SQLITE_OK && pFile->locktype>=PENDING_LOCK) { + if (_AFPFSSetLock(context->filePath, pFile->h, PENDING_BYTE, 1, 0)){ + /* failed to release the pending lock */ + rc = SQLITE_IOERR_UNLOCK; /* This should never happen */ + } + } + if (rc == SQLITE_OK && pFile->locktype>=RESERVED_LOCK) { + if (_AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1, 0)) { + /* failed to release the reserved lock */ + rc = SQLITE_IOERR_UNLOCK; /* This should never happen */ + } + } + } + if( locktype==NO_LOCK ){ + int failed = _AFPFSSetLock(context->filePath, pFile->h, + SHARED_FIRST + context->sharedLockByte, 1, 0); + if (failed) { + rc = SQLITE_IOERR_UNLOCK; /* This should never happen */ + } + } + if (rc == SQLITE_OK) + pFile->locktype = locktype; + leaveMutex(); + return rc; +} + +/* +** Close a file & cleanup AFP specific locking context +*/ +static int afpClose(sqlite3_file *id) { + if( id ){ + unixFile *pFile = (unixFile*)id; + afpUnlock(id, NO_LOCK); + sqlite3_free(pFile->lockingContext); + } + return closeUnixFile(id); +} + + +#pragma mark flock() style locking + +/* +** The flockLockingContext is not used +*/ +typedef void flockLockingContext; + +static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){ + int r = 1; + unixFile *pFile = (unixFile*)id; + + if (pFile->locktype != RESERVED_LOCK) { + /* attempt to get the lock */ + int rc = flock(pFile->h, LOCK_EX | LOCK_NB); + if (!rc) { + /* got the lock, unlock it */ + flock(pFile->h, LOCK_UN); + r = 0; /* no one has it reserved */ + } + } + + *pResOut = r; + return SQLITE_OK; +} + +static int flockLock(sqlite3_file *id, int locktype) { + unixFile *pFile = (unixFile*)id; + + /* if we already have a lock, it is exclusive. + ** Just adjust level and punt on outta here. */ + if (pFile->locktype > NO_LOCK) { + pFile->locktype = locktype; + return SQLITE_OK; + } + + /* grab an exclusive lock */ + int rc = flock(pFile->h, LOCK_EX | LOCK_NB); + if (rc) { + /* didn't get, must be busy */ + return SQLITE_BUSY; + } else { + /* got it, set the type and return ok */ + pFile->locktype = locktype; + return SQLITE_OK; + } +} + +static int flockUnlock(sqlite3_file *id, int locktype) { + unixFile *pFile = (unixFile*)id; + + assert( locktype<=SHARED_LOCK ); + + /* no-op if possible */ + if( pFile->locktype==locktype ){ + return SQLITE_OK; + } + + /* shared can just be set because we always have an exclusive */ + if (locktype==SHARED_LOCK) { + pFile->locktype = locktype; + return SQLITE_OK; + } + + /* no, really, unlock. */ + int rc = flock(pFile->h, LOCK_UN); + if (rc) + return SQLITE_IOERR_UNLOCK; + else { + pFile->locktype = NO_LOCK; + return SQLITE_OK; + } +} + +/* +** Close a file. +*/ +static int flockClose(sqlite3_file *id) { + if( id ){ + flockUnlock(id, NO_LOCK); + } + return closeUnixFile(id); +} + +#pragma mark Old-School .lock file based locking + +static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) { + int r = 1; + unixFile *pFile = (unixFile*)id; + char *zLockFile = (char *)pFile->lockingContext; + + if (pFile->locktype != RESERVED_LOCK) { + struct stat statBuf; + if (lstat(zLockFile, &statBuf) != 0){ + /* file does not exist, we could have it if we want it */ + r = 0; + } + } + + *pResOut = r; + return SQLITE_OK; +} + +static int dotlockLock(sqlite3_file *id, int locktype) { + unixFile *pFile = (unixFile*)id; + int fd; + char *zLockFile = (char *)pFile->lockingContext; + + /* if we already have a lock, it is exclusive. + ** Just adjust level and punt on outta here. */ + if (pFile->locktype > NO_LOCK) { + pFile->locktype = locktype; + + /* Always update the timestamp on the old file */ + utimes(zLockFile, NULL); + return SQLITE_OK; + } + + /* check to see if lock file already exists */ + struct stat statBuf; + if (lstat(zLockFile,&statBuf) == 0){ + return SQLITE_BUSY; /* it does, busy */ + } + + /* grab an exclusive lock */ + fd = open(zLockFile,O_RDONLY|O_CREAT|O_EXCL,0600); + if( fd<0 ){ + /* failed to open/create the file, someone else may have stolen the lock */ + return SQLITE_BUSY; + } + close(fd); + + /* got it, set the type and return ok */ + pFile->locktype = locktype; + return SQLITE_OK; +} + +static int dotlockUnlock(sqlite3_file *id, int locktype) { + unixFile *pFile = (unixFile*)id; + char *zLockFile = (char *)pFile->lockingContext; + + assert( locktype<=SHARED_LOCK ); + + /* no-op if possible */ + if( pFile->locktype==locktype ){ + return SQLITE_OK; + } + + /* shared can just be set because we always have an exclusive */ + if (locktype==SHARED_LOCK) { + pFile->locktype = locktype; + return SQLITE_OK; + } + + /* no, really, unlock. */ + unlink(zLockFile); + pFile->locktype = NO_LOCK; + return SQLITE_OK; +} + +/* + ** Close a file. + */ +static int dotlockClose(sqlite3_file *id) { + if( id ){ + unixFile *pFile = (unixFile*)id; + dotlockUnlock(id, NO_LOCK); + sqlite3_free(pFile->lockingContext); + } + return closeUnixFile(id); +} + + +#endif /* SQLITE_ENABLE_LOCKING_STYLE */ + +/* +** The nolockLockingContext is void +*/ +typedef void nolockLockingContext; + +static int nolockCheckReservedLock(sqlite3_file *id, int *pResOut) { + *pResOut = 0; + return SQLITE_OK; +} + +static int nolockLock(sqlite3_file *id, int locktype) { + return SQLITE_OK; +} + +static int nolockUnlock(sqlite3_file *id, int locktype) { + return SQLITE_OK; +} + +/* +** Close a file. +*/ +static int nolockClose(sqlite3_file *id) { + return closeUnixFile(id); +} + + +/* +** Information and control of an open file handle. +*/ +static int unixFileControl(sqlite3_file *id, int op, void *pArg){ + switch( op ){ + case SQLITE_FCNTL_LOCKSTATE: { + *(int*)pArg = ((unixFile*)id)->locktype; + return SQLITE_OK; + } + } + return SQLITE_ERROR; +} + +/* +** Return the sector size in bytes of the underlying block device for +** the specified file. This is almost always 512 bytes, but may be +** larger for some devices. +** +** SQLite code assumes this function cannot fail. It also assumes that +** if two files are created in the same file-system directory (i.e. +** a database and its journal file) that the sector size will be the +** same for both. +*/ +static int unixSectorSize(sqlite3_file *id){ + return SQLITE_DEFAULT_SECTOR_SIZE; +} + +/* +** Return the device characteristics for the file. This is always 0. +*/ +static int unixDeviceCharacteristics(sqlite3_file *id){ + return 0; +} + +/* +** Initialize the contents of the unixFile structure pointed to by pId. +** +** When locking extensions are enabled, the filepath and locking style +** are needed to determine the unixFile pMethod to use for locking operations. +** The locking-style specific lockingContext data structure is created +** and assigned here also. +*/ +static int fillInUnixFile( + sqlite3_vfs *pVfs, /* Pointer to vfs object */ + int h, /* Open file descriptor of file being opened */ + int dirfd, /* Directory file descriptor */ + sqlite3_file *pId, /* Write to the unixFile structure here */ + const char *zFilename, /* Name of the file being opened */ + int noLock /* Omit locking if true */ +){ + int eLockingStyle; + unixFile *pNew = (unixFile *)pId; + int rc = SQLITE_OK; + + /* Macro to define the static contents of an sqlite3_io_methods + ** structure for a unix backend file. Different locking methods + ** require different functions for the xClose, xLock, xUnlock and + ** xCheckReservedLock methods. + */ + #define IOMETHODS(xClose, xLock, xUnlock, xCheckReservedLock) { \ + 1, /* iVersion */ \ + xClose, /* xClose */ \ + unixRead, /* xRead */ \ + unixWrite, /* xWrite */ \ + unixTruncate, /* xTruncate */ \ + unixSync, /* xSync */ \ + unixFileSize, /* xFileSize */ \ + xLock, /* xLock */ \ + xUnlock, /* xUnlock */ \ + xCheckReservedLock, /* xCheckReservedLock */ \ + unixFileControl, /* xFileControl */ \ + unixSectorSize, /* xSectorSize */ \ + unixDeviceCharacteristics /* xDeviceCapabilities */ \ + } + static sqlite3_io_methods aIoMethod[] = { + IOMETHODS(unixClose, unixLock, unixUnlock, unixCheckReservedLock) + ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock) +#ifdef SQLITE_ENABLE_LOCKING_STYLE + ,IOMETHODS(dotlockClose, dotlockLock, dotlockUnlock,dotlockCheckReservedLock) + ,IOMETHODS(flockClose, flockLock, flockUnlock, flockCheckReservedLock) + ,IOMETHODS(afpClose, afpLock, afpUnlock, afpCheckReservedLock) +#endif + }; + /* The order of the IOMETHODS macros above is important. It must be the + ** same order as the LOCKING_STYLE numbers + */ + assert(LOCKING_STYLE_POSIX==1); + assert(LOCKING_STYLE_NONE==2); + assert(LOCKING_STYLE_DOTFILE==3); + assert(LOCKING_STYLE_FLOCK==4); + assert(LOCKING_STYLE_AFP==5); + + assert( pNew->pLock==NULL ); + assert( pNew->pOpen==NULL ); + + OSTRACE3("OPEN %-3d %s\n", h, zFilename); + pNew->h = h; + pNew->dirfd = dirfd; + SET_THREADID(pNew); + + if( noLock ){ + eLockingStyle = LOCKING_STYLE_NONE; + }else{ + eLockingStyle = detectLockingStyle(pVfs, zFilename, h); + } + + switch( eLockingStyle ){ + + case LOCKING_STYLE_POSIX: { + enterMutex(); + rc = findLockInfo(h, &pNew->pLock, &pNew->pOpen); + leaveMutex(); + break; + } + +#ifdef SQLITE_ENABLE_LOCKING_STYLE + case LOCKING_STYLE_AFP: { + /* AFP locking uses the file path so it needs to be included in + ** the afpLockingContext. + */ + afpLockingContext *pCtx; + pNew->lockingContext = pCtx = sqlite3_malloc( sizeof(*pCtx) ); + if( pCtx==0 ){ + rc = SQLITE_NOMEM; + }else{ + /* NB: zFilename exists and remains valid until the file is closed + ** according to requirement F11141. So we do not need to make a + ** copy of the filename. */ + pCtx->filePath = zFilename; + srandomdev(); + } + break; + } + + case LOCKING_STYLE_DOTFILE: { + /* Dotfile locking uses the file path so it needs to be included in + ** the dotlockLockingContext + */ + char *zLockFile; + int nFilename; + nFilename = strlen(zFilename) + 6; + zLockFile = (char *)sqlite3_malloc(nFilename); + if( zLockFile==0 ){ + rc = SQLITE_NOMEM; + }else{ + sqlite3_snprintf(nFilename, zLockFile, "%s.lock", zFilename); + } + pNew->lockingContext = zLockFile; + break; + } + + case LOCKING_STYLE_FLOCK: + case LOCKING_STYLE_NONE: + break; +#endif + } + + if( rc!=SQLITE_OK ){ + if( dirfd>=0 ) close(dirfd); + close(h); + }else{ + pNew->pMethod = &aIoMethod[eLockingStyle-1]; + OpenCounter(+1); + } + return rc; +} + +/* +** Open a file descriptor to the directory containing file zFilename. +** If successful, *pFd is set to the opened file descriptor and +** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM +** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined +** value. +** +** If SQLITE_OK is returned, the caller is responsible for closing +** the file descriptor *pFd using close(). +*/ +static int openDirectory(const char *zFilename, int *pFd){ + int ii; + int fd = -1; + char zDirname[MAX_PATHNAME+1]; + + sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename); + for(ii=strlen(zDirname); ii>=0 && zDirname[ii]!='/'; ii--); + if( ii>0 ){ + zDirname[ii] = '\0'; + fd = open(zDirname, O_RDONLY|O_BINARY, 0); + if( fd>=0 ){ +#ifdef FD_CLOEXEC + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC); +#endif + OSTRACE3("OPENDIR %-3d %s\n", fd, zDirname); + } + } + *pFd = fd; + return (fd>=0?SQLITE_OK:SQLITE_CANTOPEN); +} + +/* +** Create a temporary file name in zBuf. zBuf must be allocated +** by the calling process and must be big enough to hold at least +** pVfs->mxPathname bytes. +*/ +static int getTempname(int nBuf, char *zBuf){ + static const char *azDirs[] = { + 0, + "/var/tmp", + "/usr/tmp", + "/tmp", + ".", + }; + static const unsigned char zChars[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789"; + int i, j; + struct stat buf; + const char *zDir = "."; + + /* It's odd to simulate an io-error here, but really this is just + ** using the io-error infrastructure to test that SQLite handles this + ** function failing. + */ + SimulateIOError( return SQLITE_IOERR ); + + azDirs[0] = sqlite3_temp_directory; + for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){ + if( azDirs[i]==0 ) continue; + if( stat(azDirs[i], &buf) ) continue; + if( !S_ISDIR(buf.st_mode) ) continue; + if( access(azDirs[i], 07) ) continue; + zDir = azDirs[i]; + break; + } + + /* Check that the output buffer is large enough for the temporary file + ** name. If it is not, return SQLITE_ERROR. + */ + if( (strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 17) >= nBuf ){ + return SQLITE_ERROR; + } + + do{ + sqlite3_snprintf(nBuf-17, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir); + j = strlen(zBuf); + sqlite3_randomness(15, &zBuf[j]); + for(i=0; i<15; i++, j++){ + zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; + } + zBuf[j] = 0; + }while( access(zBuf,0)==0 ); + return SQLITE_OK; +} + + +/* +** Open the file zPath. +** +** Previously, the SQLite OS layer used three functions in place of this +** one: +** +** sqlite3OsOpenReadWrite(); +** sqlite3OsOpenReadOnly(); +** sqlite3OsOpenExclusive(); +** +** These calls correspond to the following combinations of flags: +** +** ReadWrite() -> (READWRITE | CREATE) +** ReadOnly() -> (READONLY) +** OpenExclusive() -> (READWRITE | CREATE | EXCLUSIVE) +** +** The old OpenExclusive() accepted a boolean argument - "delFlag". If +** true, the file was configured to be automatically deleted when the +** file handle closed. To achieve the same effect using this new +** interface, add the DELETEONCLOSE flag to those specified above for +** OpenExclusive(). +*/ +static int unixOpen( + sqlite3_vfs *pVfs, + const char *zPath, + sqlite3_file *pFile, + int flags, + int *pOutFlags +){ + int fd = 0; /* File descriptor returned by open() */ + int dirfd = -1; /* Directory file descriptor */ + int oflags = 0; /* Flags to pass to open() */ + int eType = flags&0xFFFFFF00; /* Type of file to open */ + int noLock; /* True to omit locking primitives */ + + int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); + int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE); + int isCreate = (flags & SQLITE_OPEN_CREATE); + int isReadonly = (flags & SQLITE_OPEN_READONLY); + int isReadWrite = (flags & SQLITE_OPEN_READWRITE); + + /* If creating a master or main-file journal, this function will open + ** a file-descriptor on the directory too. The first time unixSync() + ** is called the directory file descriptor will be fsync()ed and close()d. + */ + int isOpenDirectory = (isCreate && + (eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL) + ); + + /* If argument zPath is a NULL pointer, this function is required to open + ** a temporary file. Use this buffer to store the file name in. + */ + char zTmpname[MAX_PATHNAME+1]; + const char *zName = zPath; + + /* Check the following statements are true: + ** + ** (a) Exactly one of the READWRITE and READONLY flags must be set, and + ** (b) if CREATE is set, then READWRITE must also be set, and + ** (c) if EXCLUSIVE is set, then CREATE must also be set. + ** (d) if DELETEONCLOSE is set, then CREATE must also be set. + */ + assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly)); + assert(isCreate==0 || isReadWrite); + assert(isExclusive==0 || isCreate); + assert(isDelete==0 || isCreate); + + /* The main DB, main journal, and master journal are never automatically + ** deleted + */ + assert( eType!=SQLITE_OPEN_MAIN_DB || !isDelete ); + assert( eType!=SQLITE_OPEN_MAIN_JOURNAL || !isDelete ); + assert( eType!=SQLITE_OPEN_MASTER_JOURNAL || !isDelete ); + + /* Assert that the upper layer has set one of the "file-type" flags. */ + assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB + || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL + || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL + || eType==SQLITE_OPEN_TRANSIENT_DB + ); + + memset(pFile, 0, sizeof(unixFile)); + + if( !zName ){ + int rc; + assert(isDelete && !isOpenDirectory); + rc = getTempname(MAX_PATHNAME+1, zTmpname); + if( rc!=SQLITE_OK ){ + return rc; + } + zName = zTmpname; + } + + if( isReadonly ) oflags |= O_RDONLY; + if( isReadWrite ) oflags |= O_RDWR; + if( isCreate ) oflags |= O_CREAT; + if( isExclusive ) oflags |= (O_EXCL|O_NOFOLLOW); + oflags |= (O_LARGEFILE|O_BINARY); + + fd = open(zName, oflags, isDelete?0600:SQLITE_DEFAULT_FILE_PERMISSIONS); + if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){ + /* Failed to open the file for read/write access. Try read-only. */ + flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); + flags |= SQLITE_OPEN_READONLY; + return unixOpen(pVfs, zPath, pFile, flags, pOutFlags); + } + if( fd<0 ){ + return SQLITE_CANTOPEN; + } + if( isDelete ){ + unlink(zName); + } + if( pOutFlags ){ + *pOutFlags = flags; + } + + assert(fd!=0); + if( isOpenDirectory ){ + int rc = openDirectory(zPath, &dirfd); + if( rc!=SQLITE_OK ){ + close(fd); + return rc; + } + } + +#ifdef FD_CLOEXEC + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC); +#endif + + noLock = eType!=SQLITE_OPEN_MAIN_DB; + return fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock); +} + +/* +** Delete the file at zPath. If the dirSync argument is true, fsync() +** the directory after deleting the file. +*/ +static int unixDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ + int rc = SQLITE_OK; + SimulateIOError(return SQLITE_IOERR_DELETE); + unlink(zPath); + if( dirSync ){ + int fd; + rc = openDirectory(zPath, &fd); + if( rc==SQLITE_OK ){ + if( fsync(fd) ){ + rc = SQLITE_IOERR_DIR_FSYNC; + } + close(fd); + } + } + return rc; +} + +/* +** Test the existance of or access permissions of file zPath. The +** test performed depends on the value of flags: +** +** SQLITE_ACCESS_EXISTS: Return 1 if the file exists +** SQLITE_ACCESS_READWRITE: Return 1 if the file is read and writable. +** SQLITE_ACCESS_READONLY: Return 1 if the file is readable. +** +** Otherwise return 0. +*/ +static int unixAccess( + sqlite3_vfs *pVfs, + const char *zPath, + int flags, + int *pResOut +){ + int amode = 0; + SimulateIOError( return SQLITE_IOERR_ACCESS; ); + switch( flags ){ + case SQLITE_ACCESS_EXISTS: + amode = F_OK; + break; + case SQLITE_ACCESS_READWRITE: + amode = W_OK|R_OK; + break; + case SQLITE_ACCESS_READ: + amode = R_OK; + break; + + default: + assert(!"Invalid flags argument"); + } + *pResOut = (access(zPath, amode)==0); + return SQLITE_OK; +} + + +/* +** Turn a relative pathname into a full pathname. The relative path +** is stored as a nul-terminated string in the buffer pointed to by +** zPath. +** +** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes +** (in this case, MAX_PATHNAME bytes). The full-path is written to +** this buffer before returning. +*/ +static int unixFullPathname( + sqlite3_vfs *pVfs, /* Pointer to vfs object */ + const char *zPath, /* Possibly relative input path */ + int nOut, /* Size of output buffer in bytes */ + char *zOut /* Output buffer */ +){ + + /* It's odd to simulate an io-error here, but really this is just + ** using the io-error infrastructure to test that SQLite handles this + ** function failing. This function could fail if, for example, the + ** current working directly has been unlinked. + */ + SimulateIOError( return SQLITE_ERROR ); + + assert( pVfs->mxPathname==MAX_PATHNAME ); + zOut[nOut-1] = '\0'; + if( zPath[0]=='/' ){ + sqlite3_snprintf(nOut, zOut, "%s", zPath); + }else{ + int nCwd; + if( getcwd(zOut, nOut-1)==0 ){ + return SQLITE_CANTOPEN; + } + nCwd = strlen(zOut); + sqlite3_snprintf(nOut-nCwd, &zOut[nCwd], "/%s", zPath); + } + return SQLITE_OK; + +#if 0 + /* + ** Remove "/./" path elements and convert "/A/./" path elements + ** to just "/". + */ + if( zFull ){ + int i, j; + for(i=j=0; zFull[i]; i++){ + if( zFull[i]=='/' ){ + if( zFull[i+1]=='/' ) continue; + if( zFull[i+1]=='.' && zFull[i+2]=='/' ){ + i += 1; + continue; + } + if( zFull[i+1]=='.' && zFull[i+2]=='.' && zFull[i+3]=='/' ){ + while( j>0 && zFull[j-1]!='/' ){ j--; } + i += 3; + continue; + } + } + zFull[j++] = zFull[i]; + } + zFull[j] = 0; + } +#endif +} + + +#ifndef SQLITE_OMIT_LOAD_EXTENSION +/* +** Interfaces for opening a shared library, finding entry points +** within the shared library, and closing the shared library. +*/ +#include <dlfcn.h> +static void *unixDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ + return dlopen(zFilename, RTLD_NOW | RTLD_GLOBAL); +} + +/* +** SQLite calls this function immediately after a call to unixDlSym() or +** unixDlOpen() fails (returns a null pointer). If a more detailed error +** message is available, it is written to zBufOut. If no error message +** is available, zBufOut is left unmodified and SQLite uses a default +** error message. +*/ +static void unixDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){ + char *zErr; + enterMutex(); + zErr = dlerror(); + if( zErr ){ + sqlite3_snprintf(nBuf, zBufOut, "%s", zErr); + } + leaveMutex(); +} +static void *unixDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){ + return dlsym(pHandle, zSymbol); +} +static void unixDlClose(sqlite3_vfs *pVfs, void *pHandle){ + dlclose(pHandle); +} +#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */ + #define unixDlOpen 0 + #define unixDlError 0 + #define unixDlSym 0 + #define unixDlClose 0 +#endif + +/* +** Write nBuf bytes of random data to the supplied buffer zBuf. +*/ +static int unixRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ + + assert(nBuf>=(sizeof(time_t)+sizeof(int))); + + /* 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 + ** uninitialized space in zBuf - but valgrind errors tend to worry + ** some users. Rather than argue, it seems easier just to initialize + ** the whole array and silence valgrind, even if that means less randomness + ** 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 + ** tests repeatable. + */ + memset(zBuf, 0, nBuf); +#if !defined(SQLITE_TEST) + { + int pid, fd; + fd = open("/dev/urandom", O_RDONLY); + if( fd<0 ){ + time_t t; + time(&t); + memcpy(zBuf, &t, sizeof(t)); + pid = getpid(); + memcpy(&zBuf[sizeof(t)], &pid, sizeof(pid)); + }else{ + read(fd, zBuf, nBuf); + close(fd); + } + } +#endif + return SQLITE_OK; +} + + +/* +** Sleep for a little while. Return the amount of time slept. +** The argument is the number of microseconds we want to sleep. +** The return value is the number of microseconds of sleep actually +** requested from the underlying operating system, a number which +** might be greater than or equal to the argument, but not less +** than the argument. +*/ +static int unixSleep(sqlite3_vfs *pVfs, int microseconds){ +#if defined(HAVE_USLEEP) && HAVE_USLEEP + usleep(microseconds); + return microseconds; +#else + int seconds = (microseconds+999999)/1000000; + sleep(seconds); + return seconds*1000000; +#endif +} + +/* +** The following variable, if set to a non-zero value, becomes the result +** returned from sqlite3OsCurrentTime(). This is used for testing. +*/ +#ifdef SQLITE_TEST +int sqlite3_current_time = 0; +#endif + +/* +** Find the current time (in Universal Coordinated Time). Write the +** current time and date as a Julian Day number into *prNow and +** return 0. Return 1 if the time and date cannot be found. +*/ +static int unixCurrentTime(sqlite3_vfs *pVfs, double *prNow){ +#ifdef NO_GETTOD + time_t t; + time(&t); + *prNow = t/86400.0 + 2440587.5; +#else + struct timeval sNow; + gettimeofday(&sNow, 0); + *prNow = 2440587.5 + sNow.tv_sec/86400.0 + sNow.tv_usec/86400000000.0; +#endif +#ifdef SQLITE_TEST + if( sqlite3_current_time ){ + *prNow = sqlite3_current_time/86400.0 + 2440587.5; + } +#endif + return 0; +} + +static int unixGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ + return 0; +} + +/* +** Initialize the operating system interface. +*/ +int sqlite3_os_init(void){ + /* Macro to define the static contents of an sqlite3_vfs structure for + ** the unix backend. The two parameters are the values to use for + ** the sqlite3_vfs.zName and sqlite3_vfs.pAppData fields, respectively. + ** + */ + #define UNIXVFS(zVfsName, pVfsAppData) { \ + 1, /* iVersion */ \ + sizeof(unixFile), /* szOsFile */ \ + MAX_PATHNAME, /* mxPathname */ \ + 0, /* pNext */ \ + zVfsName, /* zName */ \ + (void *)pVfsAppData, /* pAppData */ \ + unixOpen, /* xOpen */ \ + unixDelete, /* xDelete */ \ + unixAccess, /* xAccess */ \ + unixFullPathname, /* xFullPathname */ \ + unixDlOpen, /* xDlOpen */ \ + unixDlError, /* xDlError */ \ + unixDlSym, /* xDlSym */ \ + unixDlClose, /* xDlClose */ \ + unixRandomness, /* xRandomness */ \ + unixSleep, /* xSleep */ \ + unixCurrentTime, /* xCurrentTime */ \ + unixGetLastError /* xGetLastError */ \ + } + + static sqlite3_vfs unixVfs = UNIXVFS("unix", 0); +#ifdef SQLITE_ENABLE_LOCKING_STYLE +#if 0 + int i; + static sqlite3_vfs aVfs[] = { + UNIXVFS("unix-posix", LOCKING_STYLE_POSIX), + UNIXVFS("unix-afp", LOCKING_STYLE_AFP), + UNIXVFS("unix-flock", LOCKING_STYLE_FLOCK), + UNIXVFS("unix-dotfile", LOCKING_STYLE_DOTFILE), + UNIXVFS("unix-none", LOCKING_STYLE_NONE) + }; + for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ + sqlite3_vfs_register(&aVfs[i], 0); + } +#endif +#endif + sqlite3_vfs_register(&unixVfs, 1); + return SQLITE_OK; +} + +/* +** Shutdown the operating system interface. This is a no-op for unix. +*/ +int sqlite3_os_end(void){ + return SQLITE_OK; +} + +#endif /* SQLITE_OS_UNIX */ diff --git a/third_party/sqlite/src/os_win.c b/third_party/sqlite/src/os_win.c new file mode 100755 index 0000000..ec30add --- /dev/null +++ b/third_party/sqlite/src/os_win.c @@ -0,0 +1,1638 @@ +/* +** 2004 May 22 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains code that is specific to windows. +** +** $Id: os_win.c,v 1.132 2008/07/31 01:34:34 shane Exp $ +*/ +#include "sqliteInt.h" +#if SQLITE_OS_WIN /* This file is used for windows only */ + + +/* +** A Note About Memory Allocation: +** +** This driver uses malloc()/free() directly rather than going through +** the SQLite-wrappers sqlite3_malloc()/sqlite3_free(). Those wrappers +** are designed for use on embedded systems where memory is scarce and +** malloc failures happen frequently. Win32 does not typically run on +** embedded systems, and when it does the developers normally have bigger +** problems to worry about than running out of memory. So there is not +** a compelling need to use the wrappers. +** +** But there is a good reason to not use the wrappers. If we use the +** wrappers then we will get simulated malloc() failures within this +** driver. And that causes all kinds of problems for our tests. We +** could enhance SQLite to deal with simulated malloc failures within +** the OS driver, but the code to deal with those failure would not +** be exercised on Linux (which does not need to malloc() in the driver) +** and so we would have difficulty writing coverage tests for that +** code. Better to leave the code out, we think. +** +** The point of this discussion is as follows: When creating a new +** OS layer for an embedded system, if you use this file as an example, +** avoid the use of malloc()/free(). Those routines work ok on windows +** desktops but not so well in embedded systems. +*/ + +#include <winbase.h> + +#ifdef __CYGWIN__ +# include <sys/cygwin.h> +#endif + +/* +** Macros used to determine whether or not to use threads. +*/ +#if defined(THREADSAFE) && THREADSAFE +# define SQLITE_W32_THREADS 1 +#endif + +/* +** Include code that is common to all os_*.c files +*/ +#include "os_common.h" + +/* +** Determine if we are dealing with WindowsCE - which has a much +** reduced API. +*/ +#if defined(SQLITE_OS_WINCE) +# define AreFileApisANSI() 1 +#endif + +/* +** WinCE lacks native support for file locking so we have to fake it +** with some code of our own. +*/ +#if SQLITE_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 sqlite3_file* specific to the win32 +** portability layer. +*/ +typedef struct winFile winFile; +struct winFile { + const sqlite3_io_methods *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 SQLITE_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 +}; + + +/* +** The following variable is (normally) set once and never changes +** thereafter. It records whether the operating system is Win95 +** or WinNT. +** +** 0: Operating system unknown. +** 1: Operating system is Win95. +** 2: Operating system is WinNT. +** +** In order to facilitate testing on a WinNT system, the test fixture +** can manually set this value to 1 to emulate Win98 behavior. +*/ +#ifdef SQLITE_TEST +int sqlite3_os_type = 0; +#else +static int sqlite3_os_type = 0; +#endif + +/* +** 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 +** API as long as we don't call it win running Win95/98/ME. A call to +** this routine is used to determine if the host is Win95/98/ME or +** WinNT/2K/XP so that we will know whether or not we can safely call +** the LockFileEx() API. +*/ +#if SQLITE_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; + } +#endif /* SQLITE_OS_WINCE */ + +/* +** Convert a UTF-8 string to microsoft unicode (UTF-16?). +** +** Space to hold the returned string is obtained from malloc. +*/ +static WCHAR *utf8ToUnicode(const char *zFilename){ + int nChar; + WCHAR *zWideFilename; + + nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); + zWideFilename = malloc( nChar*sizeof(zWideFilename[0]) ); + if( zWideFilename==0 ){ + return 0; + } + nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nChar); + if( nChar==0 ){ + free(zWideFilename); + zWideFilename = 0; + } + return zWideFilename; +} + +/* +** Convert microsoft unicode to UTF-8. Space to hold the returned string is +** obtained from malloc(). +*/ +static char *unicodeToUtf8(const WCHAR *zWideFilename){ + int nByte; + char *zFilename; + + nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0); + zFilename = malloc( nByte ); + if( zFilename==0 ){ + return 0; + } + nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte, + 0, 0); + if( nByte == 0 ){ + free(zFilename); + zFilename = 0; + } + return zFilename; +} + +/* +** Convert an ansi string to microsoft unicode, based on the +** current codepage settings for file apis. +** +** Space to hold the returned string is obtained +** from malloc. +*/ +static WCHAR *mbcsToUnicode(const char *zFilename){ + int nByte; + WCHAR *zMbcsFilename; + int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; + + nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, NULL,0)*sizeof(WCHAR); + zMbcsFilename = malloc( nByte*sizeof(zMbcsFilename[0]) ); + if( zMbcsFilename==0 ){ + return 0; + } + nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename, nByte); + if( nByte==0 ){ + free(zMbcsFilename); + zMbcsFilename = 0; + } + return zMbcsFilename; +} + +/* +** Convert microsoft unicode to multibyte character string, based on the +** user's Ansi codepage. +** +** Space to hold the returned string is obtained from +** malloc(). +*/ +static char *unicodeToMbcs(const WCHAR *zWideFilename){ + int nByte; + char *zFilename; + int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; + + nByte = WideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0); + zFilename = malloc( nByte ); + if( zFilename==0 ){ + return 0; + } + nByte = WideCharToMultiByte(codepage, 0, zWideFilename, -1, zFilename, nByte, + 0, 0); + if( nByte == 0 ){ + free(zFilename); + zFilename = 0; + } + return zFilename; +} + +/* +** Convert multibyte character string to UTF-8. Space to hold the +** returned string is obtained from malloc(). +*/ +static char *mbcsToUtf8(const char *zFilename){ + char *zFilenameUtf8; + WCHAR *zTmpWide; + + zTmpWide = mbcsToUnicode(zFilename); + if( zTmpWide==0 ){ + return 0; + } + zFilenameUtf8 = unicodeToUtf8(zTmpWide); + free(zTmpWide); + return zFilenameUtf8; +} + +/* +** Convert UTF-8 to multibyte character string. Space to hold the +** returned string is obtained from malloc(). +*/ +static char *utf8ToMbcs(const char *zFilename){ + char *zFilenameMbcs; + WCHAR *zTmpWide; + + zTmpWide = utf8ToUnicode(zFilename); + if( zTmpWide==0 ){ + return 0; + } + zFilenameMbcs = unicodeToMbcs(zTmpWide); + free(zTmpWide); + return zFilenameMbcs; +} + +#if SQLITE_OS_WINCE +/************************************************************************* +** This section contains code for WinCE only. +*/ +/* +** WindowsCE does not have a localtime() function. So create a +** substitute. +*/ +#include <time.h> +struct tm *__cdecl localtime(const time_t *t) +{ + static struct tm y; + FILETIME uTm, lTm; + SYSTEMTIME pTm; + sqlite3_int64 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){ + free(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; + } + + free(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 /* SQLITE_OS_WINCE */ + +/***************************************************************************** +** The next group of routines implement the I/O methods specified +** by the sqlite3_io_methods object. +******************************************************************************/ + +/* +** Close a file. +** +** It is reported that an attempt to close a handle might sometimes +** fail. This is a very unreasonable result, but windows is notorious +** for being unreasonable so I do not doubt that it might happen. If +** the close fails, we pause for 100 milliseconds and try again. As +** many as MX_CLOSE_ATTEMPT attempts to close the handle are made before +** giving up and returning an error. +*/ +#define MX_CLOSE_ATTEMPT 3 +static int winClose(sqlite3_file *id){ + int rc, cnt = 0; + winFile *pFile = (winFile*)id; + OSTRACE2("CLOSE %d\n", pFile->h); + do{ + rc = CloseHandle(pFile->h); + }while( rc==0 && cnt++ < MX_CLOSE_ATTEMPT && (Sleep(100), 1) ); +#if SQLITE_OS_WINCE +#define WINCE_DELETION_ATTEMPTS 3 + winceDestroyLock(pFile); + if( pFile->zDeleteOnClose ){ + int cnt = 0; + while( + DeleteFileW(pFile->zDeleteOnClose)==0 + && GetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff + && cnt++ < WINCE_DELETION_ATTEMPTS + ){ + Sleep(100); /* Wait a little before trying again */ + } + free(pFile->zDeleteOnClose); + } +#endif + OpenCounter(-1); + return rc ? SQLITE_OK : SQLITE_IOERR; +} + +/* +** Some microsoft compilers lack this definition. +*/ +#ifndef INVALID_SET_FILE_POINTER +# define INVALID_SET_FILE_POINTER ((DWORD)-1) +#endif + +/* +** Read data from a file into a buffer. Return SQLITE_OK if all +** bytes were read successfully and SQLITE_IOERR if anything goes +** wrong. +*/ +static int winRead( + sqlite3_file *id, /* File to read from */ + void *pBuf, /* Write content into this buffer */ + int amt, /* Number of bytes to read */ + sqlite3_int64 offset /* Begin reading at this offset */ +){ + LONG upperBits = (offset>>32) & 0x7fffffff; + LONG lowerBits = offset & 0xffffffff; + DWORD rc; + DWORD got; + winFile *pFile = (winFile*)id; + assert( id!=0 ); + SimulateIOError(return SQLITE_IOERR_READ); + OSTRACE3("READ %d lock=%d\n", pFile->h, pFile->locktype); + rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); + if( rc==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR ){ + return SQLITE_FULL; + } + if( !ReadFile(pFile->h, pBuf, amt, &got, 0) ){ + return SQLITE_IOERR_READ; + } + if( got==(DWORD)amt ){ + return SQLITE_OK; + }else{ + memset(&((char*)pBuf)[got], 0, amt-got); + return SQLITE_IOERR_SHORT_READ; + } +} + +/* +** Write data from a buffer into a file. Return SQLITE_OK on success +** or some other error code on failure. +*/ +static int winWrite( + sqlite3_file *id, /* File to write into */ + const void *pBuf, /* The bytes to be written */ + int amt, /* Number of bytes to write */ + sqlite3_int64 offset /* Offset into the file to begin writing at */ +){ + LONG upperBits = (offset>>32) & 0x7fffffff; + LONG lowerBits = offset & 0xffffffff; + DWORD rc; + DWORD wrote; + winFile *pFile = (winFile*)id; + assert( id!=0 ); + SimulateIOError(return SQLITE_IOERR_WRITE); + SimulateDiskfullError(return SQLITE_FULL); + OSTRACE3("WRITE %d lock=%d\n", pFile->h, pFile->locktype); + rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); + if( rc==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR ){ + return SQLITE_FULL; + } + assert( amt>0 ); + while( + amt>0 + && (rc = WriteFile(pFile->h, pBuf, amt, &wrote, 0))!=0 + && wrote>0 + ){ + amt -= wrote; + pBuf = &((char*)pBuf)[wrote]; + } + if( !rc || amt>(int)wrote ){ + return SQLITE_FULL; + } + return SQLITE_OK; +} + +/* +** Truncate an open file to a specified size +*/ +static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ + LONG upperBits = (nByte>>32) & 0x7fffffff; + LONG lowerBits = nByte & 0xffffffff; + winFile *pFile = (winFile*)id; + OSTRACE3("TRUNCATE %d %lld\n", pFile->h, nByte); + SimulateIOError(return SQLITE_IOERR_TRUNCATE); + SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); + SetEndOfFile(pFile->h); + return SQLITE_OK; +} + +#ifdef SQLITE_TEST +/* +** Count the number of fullsyncs and normal syncs. This is used to test +** that syncs and fullsyncs are occuring at the right times. +*/ +int sqlite3_sync_count = 0; +int sqlite3_fullsync_count = 0; +#endif + +/* +** Make sure all writes to a particular file are committed to disk. +*/ +static int winSync(sqlite3_file *id, int flags){ + winFile *pFile = (winFile*)id; + OSTRACE3("SYNC %d lock=%d\n", pFile->h, pFile->locktype); +#ifdef SQLITE_TEST + if( flags & SQLITE_SYNC_FULL ){ + sqlite3_fullsync_count++; + } + sqlite3_sync_count++; +#endif + if( FlushFileBuffers(pFile->h) ){ + return SQLITE_OK; + }else{ + return SQLITE_IOERR; + } +} + +/* +** Determine the current size of a file in bytes +*/ +static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){ + winFile *pFile = (winFile*)id; + DWORD upperBits, lowerBits; + SimulateIOError(return SQLITE_IOERR_FSTAT); + lowerBits = GetFileSize(pFile->h, &upperBits); + *pSize = (((sqlite3_int64)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(winFile *pFile){ + int res; + if( isNT() ){ + OVERLAPPED ovlp; + ovlp.Offset = SHARED_FIRST; + ovlp.OffsetHigh = 0; + ovlp.hEvent = 0; + res = LockFileEx(pFile->h, LOCKFILE_FAIL_IMMEDIATELY, + 0, SHARED_SIZE, 0, &ovlp); + }else{ + int lk; + sqlite3_randomness(sizeof(lk), &lk); + pFile->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1); + res = LockFile(pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0); + } + return res; +} + +/* +** Undo a readlock +*/ +static int unlockReadLock(winFile *pFile){ + int res; + if( isNT() ){ + res = UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); + }else{ + res = UnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0); + } + return res; +} + +/* +** Lock the file with the lock specified by parameter locktype - one +** of the following: +** +** (1) SHARED_LOCK +** (2) RESERVED_LOCK +** (3) PENDING_LOCK +** (4) EXCLUSIVE_LOCK +** +** Sometimes when requesting one lock state, additional lock states +** are inserted in between. The locking might fail on one of the later +** transitions leaving the lock state different from what it started but +** still short of its goal. The following chart shows the allowed +** transitions and the inserted intermediate states: +** +** UNLOCKED -> SHARED +** SHARED -> RESERVED +** SHARED -> (PENDING) -> EXCLUSIVE +** RESERVED -> (PENDING) -> EXCLUSIVE +** PENDING -> EXCLUSIVE +** +** 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. +*/ +static int winLock(sqlite3_file *id, int locktype){ + int rc = SQLITE_OK; /* Return code from subroutines */ + int res = 1; /* Result of a windows lock call */ + int newLocktype; /* Set pFile->locktype to this value before exiting */ + int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */ + winFile *pFile = (winFile*)id; + + assert( pFile!=0 ); + OSTRACE5("LOCK %d %d was %d(%d)\n", + 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( pFile->locktype>=locktype ){ + return SQLITE_OK; + } + + /* Make sure the locking sequence is correct + */ + assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); + assert( locktype!=PENDING_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 = pFile->locktype; + if( pFile->locktype==NO_LOCK + || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK) + ){ + int cnt = 3; + 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. + */ + OSTRACE2("could not get a PENDING lock. cnt=%d\n", cnt); + Sleep(1); + } + gotPendingLock = res; + } + + /* Acquire a shared lock + */ + if( locktype==SHARED_LOCK && res ){ + assert( pFile->locktype==NO_LOCK ); + res = getReadLock(pFile); + if( res ){ + newLocktype = SHARED_LOCK; + } + } + + /* Acquire a RESERVED lock + */ + if( locktype==RESERVED_LOCK && res ){ + assert( pFile->locktype==SHARED_LOCK ); + res = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); + if( res ){ + newLocktype = RESERVED_LOCK; + } + } + + /* Acquire a PENDING lock + */ + if( locktype==EXCLUSIVE_LOCK && res ){ + newLocktype = PENDING_LOCK; + gotPendingLock = 0; + } + + /* Acquire an EXCLUSIVE lock + */ + if( locktype==EXCLUSIVE_LOCK && res ){ + assert( pFile->locktype>=SHARED_LOCK ); + res = unlockReadLock(pFile); + OSTRACE2("unreadlock = %d\n", res); + res = LockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); + if( res ){ + newLocktype = EXCLUSIVE_LOCK; + }else{ + OSTRACE2("error-code = %d\n", GetLastError()); + getReadLock(pFile); + } + } + + /* If we are holding a PENDING lock that ought to be released, then + ** release it now. + */ + if( gotPendingLock && locktype==SHARED_LOCK ){ + UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0); + } + + /* Update the state of the lock has held in the file descriptor then + ** return the appropriate result code. + */ + if( res ){ + rc = SQLITE_OK; + }else{ + OSTRACE4("LOCK FAILED %d trying for %d but got %d\n", pFile->h, + locktype, newLocktype); + rc = SQLITE_BUSY; + } + pFile->locktype = newLocktype; + return rc; +} + +/* +** This routine checks if there is a RESERVED lock held on the specified +** file by this or any other process. If such a lock is held, return +** non-zero, otherwise zero. +*/ +static int winCheckReservedLock(sqlite3_file *id, int *pResOut){ + int rc; + winFile *pFile = (winFile*)id; + assert( pFile!=0 ); + if( pFile->locktype>=RESERVED_LOCK ){ + rc = 1; + OSTRACE3("TEST WR-LOCK %d %d (local)\n", pFile->h, rc); + }else{ + rc = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); + if( rc ){ + UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); + } + rc = !rc; + OSTRACE3("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc); + } + *pResOut = rc; + return SQLITE_OK; +} + +/* +** Lower the locking level on file descriptor id 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 then this routine +** might return SQLITE_IOERR; +*/ +static int winUnlock(sqlite3_file *id, int locktype){ + int type; + winFile *pFile = (winFile*)id; + int rc = SQLITE_OK; + assert( pFile!=0 ); + assert( locktype<=SHARED_LOCK ); + OSTRACE5("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype, + pFile->locktype, pFile->sharedLockByte); + type = pFile->locktype; + if( type>=EXCLUSIVE_LOCK ){ + 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_UNLOCK; + } + } + if( type>=RESERVED_LOCK ){ + UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); + } + if( locktype==NO_LOCK && type>=SHARED_LOCK ){ + unlockReadLock(pFile); + } + if( type>=PENDING_LOCK ){ + UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0); + } + pFile->locktype = locktype; + return rc; +} + +/* +** Control and query of the open file handle. +*/ +static int winFileControl(sqlite3_file *id, int op, void *pArg){ + switch( op ){ + case SQLITE_FCNTL_LOCKSTATE: { + *(int*)pArg = ((winFile*)id)->locktype; + return SQLITE_OK; + } + } + return SQLITE_ERROR; +} + +/* +** Return the sector size in bytes of the underlying block device for +** the specified file. This is almost always 512 bytes, but may be +** larger for some devices. +** +** SQLite code assumes this function cannot fail. It also assumes that +** if two files are created in the same file-system directory (i.e. +** a database and its journal file) that the sector size will be the +** same for both. +*/ +static int winSectorSize(sqlite3_file *id){ + return SQLITE_DEFAULT_SECTOR_SIZE; +} + +/* +** Return a vector of device characteristics. +*/ +static int winDeviceCharacteristics(sqlite3_file *id){ + return 0; +} + +/* +** This vector defines all the methods that can operate on an +** sqlite3_file for win32. +*/ +static const sqlite3_io_methods winIoMethod = { + 1, /* iVersion */ + winClose, + winRead, + winWrite, + winTruncate, + winSync, + winFileSize, + winLock, + winUnlock, + winCheckReservedLock, + winFileControl, + winSectorSize, + winDeviceCharacteristics +}; + +/*************************************************************************** +** Here ends the I/O methods that form the sqlite3_io_methods object. +** +** The next block of code implements the VFS methods. +****************************************************************************/ + +/* +** Convert a UTF-8 filename into whatever form the underlying +** operating system wants filenames in. Space to hold the result +** is obtained from malloc and must be freed by the calling +** function. +*/ +static void *convertUtf8Filename(const char *zFilename){ + void *zConverted = 0; + if( isNT() ){ + zConverted = utf8ToUnicode(zFilename); + }else{ + zConverted = utf8ToMbcs(zFilename); + } + /* caller will handle out of memory */ + return zConverted; +} + +/* +** Create a temporary file name in zBuf. zBuf must be big enough to +** hold at pVfs->mxPathname characters. +*/ +static int getTempname(int nBuf, char *zBuf){ + static char zChars[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789"; + size_t i, j; + char zTempPath[MAX_PATH+1]; + if( sqlite3_temp_directory ){ + sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory); + }else if( isNT() ){ + char *zMulti; + WCHAR zWidePath[MAX_PATH]; + GetTempPathW(MAX_PATH-30, zWidePath); + zMulti = unicodeToUtf8(zWidePath); + if( zMulti ){ + sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zMulti); + free(zMulti); + }else{ + return SQLITE_NOMEM; + } + }else{ + char *zUtf8; + char zMbcsPath[MAX_PATH]; + GetTempPathA(MAX_PATH-30, zMbcsPath); + zUtf8 = mbcsToUtf8(zMbcsPath); + if( zUtf8 ){ + sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zUtf8); + free(zUtf8); + }else{ + return SQLITE_NOMEM; + } + } + for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){} + zTempPath[i] = 0; + sqlite3_snprintf(nBuf-30, zBuf, + "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath); + j = strlen(zBuf); + sqlite3_randomness(20, &zBuf[j]); + for(i=0; i<20; i++, j++){ + zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; + } + zBuf[j] = 0; + OSTRACE2("TEMP FILENAME: %s\n", zBuf); + return SQLITE_OK; +} + +/* +** The return value of getLastErrorMsg +** is zero if the error message fits in the buffer, or non-zero +** otherwise (if the message was truncated). +*/ +static int getLastErrorMsg(int nBuf, char *zBuf){ + DWORD error = GetLastError(); + +#if SQLITE_OS_WINCE + sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", error, error); +#else + /* FormatMessage returns 0 on failure. Otherwise it + ** returns the number of TCHARs written to the output + ** buffer, excluding the terminating null char. + */ + if (!FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + error, + 0, + zBuf, + nBuf-1, + 0)) + { + sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", error, error); + } +#endif + + return 0; +} + + +/* +** Open a file. +*/ +static int winOpen( + sqlite3_vfs *pVfs, /* Not used */ + const char *zName, /* Name of the file (UTF-8) */ + sqlite3_file *id, /* Write the SQLite file handle here */ + int flags, /* Open mode flags */ + int *pOutFlags /* Status return flags */ +){ + HANDLE h; + DWORD dwDesiredAccess; + DWORD dwShareMode; + DWORD dwCreationDisposition; + DWORD dwFlagsAndAttributes = 0; + int isTemp; + winFile *pFile = (winFile*)id; + void *zConverted; /* Filename in OS encoding */ + const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */ + char zTmpname[MAX_PATH+1]; /* Buffer used to create temp filename */ + + /* If the second argument to this function is NULL, generate a + ** temporary file name to use + */ + if( !zUtf8Name ){ + int rc = getTempname(MAX_PATH+1, zTmpname); + if( rc!=SQLITE_OK ){ + return rc; + } + zUtf8Name = zTmpname; + } + + /* Convert the filename to the system encoding. */ + zConverted = convertUtf8Filename(zUtf8Name); + if( zConverted==0 ){ + return SQLITE_NOMEM; + } + + if( flags & SQLITE_OPEN_READWRITE ){ + dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; + }else{ + dwDesiredAccess = GENERIC_READ; + } + if( flags & SQLITE_OPEN_CREATE ){ + dwCreationDisposition = OPEN_ALWAYS; + }else{ + dwCreationDisposition = OPEN_EXISTING; + } + if( flags & SQLITE_OPEN_MAIN_DB ){ + dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; + }else{ + dwShareMode = 0; + } + if( flags & SQLITE_OPEN_DELETEONCLOSE ){ +#if SQLITE_OS_WINCE + dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN; +#else + dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY + | FILE_ATTRIBUTE_HIDDEN + | FILE_FLAG_DELETE_ON_CLOSE; +#endif + isTemp = 1; + }else{ + dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; + isTemp = 0; + } + /* Reports from the internet are that performance is always + ** better if FILE_FLAG_RANDOM_ACCESS is used. Ticket #2699. */ + dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS; + if( isNT() ){ + h = CreateFileW((WCHAR*)zConverted, + dwDesiredAccess, + dwShareMode, + NULL, + dwCreationDisposition, + dwFlagsAndAttributes, + NULL + ); + }else{ +#if SQLITE_OS_WINCE + free(zConverted); + return SQLITE_NOMEM; +#else + h = CreateFileA((char*)zConverted, + dwDesiredAccess, + dwShareMode, + NULL, + dwCreationDisposition, + dwFlagsAndAttributes, + NULL + ); +#endif + } + if( h==INVALID_HANDLE_VALUE ){ + free(zConverted); + if( flags & SQLITE_OPEN_READWRITE ){ + return winOpen(0, zName, id, + ((flags|SQLITE_OPEN_READONLY)&~SQLITE_OPEN_READWRITE), pOutFlags); + }else{ + return SQLITE_CANTOPEN; + } + } + if( pOutFlags ){ + if( flags & SQLITE_OPEN_READWRITE ){ + *pOutFlags = SQLITE_OPEN_READWRITE; + }else{ + *pOutFlags = SQLITE_OPEN_READONLY; + } + } + memset(pFile, 0, sizeof(*pFile)); + pFile->pMethod = &winIoMethod; + pFile->h = h; +#if SQLITE_OS_WINCE + if( (flags & (SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB)) == + (SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB) + && !winceCreateLock(zName, pFile) + ){ + CloseHandle(h); + free(zConverted); + return SQLITE_CANTOPEN; + } + if( isTemp ){ + pFile->zDeleteOnClose = zConverted; + }else +#endif + { + free(zConverted); + } + OpenCounter(+1); + return SQLITE_OK; +} + +/* +** Delete the named file. +** +** Note that windows does not allow a file to be deleted if some other +** process has it open. Sometimes a virus scanner or indexing program +** will open a journal file shortly after it is created in order to do +** whatever it does. While this other process is holding the +** file open, we will be unable to delete it. To work around this +** problem, we delay 100 milliseconds and try to delete again. Up +** to MX_DELETION_ATTEMPTs deletion attempts are run before giving +** up and returning an error. +*/ +#define MX_DELETION_ATTEMPTS 5 +static int winDelete( + sqlite3_vfs *pVfs, /* Not used on win32 */ + const char *zFilename, /* Name of file to delete */ + int syncDir /* Not used on win32 */ +){ + int cnt = 0; + int rc; + DWORD error; + void *zConverted = convertUtf8Filename(zFilename); + if( zConverted==0 ){ + return SQLITE_NOMEM; + } + SimulateIOError(return SQLITE_IOERR_DELETE); + if( isNT() ){ + do{ + DeleteFileW(zConverted); + }while( ( ((rc = GetFileAttributesW(zConverted)) != INVALID_FILE_ATTRIBUTES) + || ((error = GetLastError()) == ERROR_ACCESS_DENIED)) + && (cnt++ < MX_DELETION_ATTEMPTS) + && (Sleep(100), 1) ); + }else{ +#if SQLITE_OS_WINCE + free(zConverted); + return SQLITE_NOMEM; +#else + do{ + DeleteFileA(zConverted); + }while( ( ((rc = GetFileAttributesA(zConverted)) != INVALID_FILE_ATTRIBUTES) + || ((error = GetLastError()) == ERROR_ACCESS_DENIED)) + && (cnt++ < MX_DELETION_ATTEMPTS) + && (Sleep(100), 1) ); +#endif + } + free(zConverted); + OSTRACE2("DELETE \"%s\"\n", zFilename); + return ( (rc==INVALID_FILE_ATTRIBUTES) + && (error == ERROR_FILE_NOT_FOUND)) ? SQLITE_OK : SQLITE_IOERR_DELETE; +} + +/* +** Check the existance and status of a file. +*/ +static int winAccess( + sqlite3_vfs *pVfs, /* Not used on win32 */ + const char *zFilename, /* Name of file to check */ + int flags, /* Type of test to make on this file */ + int *pResOut /* OUT: Result */ +){ + DWORD attr; + int rc; + void *zConverted = convertUtf8Filename(zFilename); + if( zConverted==0 ){ + return SQLITE_NOMEM; + } + if( isNT() ){ + attr = GetFileAttributesW((WCHAR*)zConverted); + }else{ +#if SQLITE_OS_WINCE + free(zConverted); + return SQLITE_NOMEM; +#else + attr = GetFileAttributesA((char*)zConverted); +#endif + } + free(zConverted); + switch( flags ){ + case SQLITE_ACCESS_READ: + case SQLITE_ACCESS_EXISTS: + rc = attr!=INVALID_FILE_ATTRIBUTES; + break; + case SQLITE_ACCESS_READWRITE: + rc = (attr & FILE_ATTRIBUTE_READONLY)==0; + break; + default: + assert(!"Invalid flags argument"); + } + *pResOut = rc; + return SQLITE_OK; +} + + +/* +** Turn a relative pathname into a full pathname. Write the full +** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname +** bytes in size. +*/ +static int winFullPathname( + sqlite3_vfs *pVfs, /* Pointer to vfs object */ + const char *zRelative, /* Possibly relative input path */ + int nFull, /* Size of output buffer in bytes */ + char *zFull /* Output buffer */ +){ + +#if defined(__CYGWIN__) + cygwin_conv_to_full_win32_path(zRelative, zFull); + return SQLITE_OK; +#endif + +#if SQLITE_OS_WINCE + /* WinCE has no concept of a relative pathname, or so I am told. */ + sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zRelative); + return SQLITE_OK; +#endif + +#if !SQLITE_OS_WINCE && !defined(__CYGWIN__) + int nByte; + void *zConverted; + char *zOut; + zConverted = convertUtf8Filename(zRelative); + if( isNT() ){ + WCHAR *zTemp; + nByte = GetFullPathNameW((WCHAR*)zConverted, 0, 0, 0) + 3; + zTemp = malloc( nByte*sizeof(zTemp[0]) ); + if( zTemp==0 ){ + free(zConverted); + return SQLITE_NOMEM; + } + GetFullPathNameW((WCHAR*)zConverted, nByte, zTemp, 0); + free(zConverted); + zOut = unicodeToUtf8(zTemp); + free(zTemp); + }else{ + char *zTemp; + nByte = GetFullPathNameA((char*)zConverted, 0, 0, 0) + 3; + zTemp = malloc( nByte*sizeof(zTemp[0]) ); + if( zTemp==0 ){ + free(zConverted); + return SQLITE_NOMEM; + } + GetFullPathNameA((char*)zConverted, nByte, zTemp, 0); + free(zConverted); + zOut = mbcsToUtf8(zTemp); + free(zTemp); + } + if( zOut ){ + sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zOut); + free(zOut); + return SQLITE_OK; + }else{ + return SQLITE_NOMEM; + } +#endif +} + +#ifndef SQLITE_OMIT_LOAD_EXTENSION +/* +** Interfaces for opening a shared library, finding entry points +** within the shared library, and closing the shared library. +*/ +/* +** Interfaces for opening a shared library, finding entry points +** within the shared library, and closing the shared library. +*/ +static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ + HANDLE h; + void *zConverted = convertUtf8Filename(zFilename); + if( zConverted==0 ){ + return 0; + } + if( isNT() ){ + h = LoadLibraryW((WCHAR*)zConverted); + }else{ + h = LoadLibraryA((char*)zConverted); + } + free(zConverted); + return (void*)h; +} +static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){ + getLastErrorMsg(nBuf, zBufOut); +} +void *winDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){ +#if SQLITE_OS_WINCE + /* The GetProcAddressA() routine is only available on wince. */ + return GetProcAddressA((HANDLE)pHandle, zSymbol); +#else + /* All other windows platforms expect GetProcAddress() to take + ** an Ansi string regardless of the _UNICODE setting */ + return GetProcAddress((HANDLE)pHandle, zSymbol); +#endif +} +void winDlClose(sqlite3_vfs *pVfs, void *pHandle){ + FreeLibrary((HANDLE)pHandle); +} +#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */ + #define winDlOpen 0 + #define winDlError 0 + #define winDlSym 0 + #define winDlClose 0 +#endif + + +/* +** Write up to nBuf bytes of randomness into zBuf. +*/ +static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ + int n = 0; + if( sizeof(SYSTEMTIME)<=nBuf-n ){ + SYSTEMTIME x; + GetSystemTime(&x); + memcpy(&zBuf[n], &x, sizeof(x)); + n += sizeof(x); + } + if( sizeof(DWORD)<=nBuf-n ){ + DWORD pid = GetCurrentProcessId(); + memcpy(&zBuf[n], &pid, sizeof(pid)); + n += sizeof(pid); + } + if( sizeof(DWORD)<=nBuf-n ){ + DWORD cnt = GetTickCount(); + memcpy(&zBuf[n], &cnt, sizeof(cnt)); + n += sizeof(cnt); + } + if( sizeof(LARGE_INTEGER)<=nBuf-n ){ + LARGE_INTEGER i; + QueryPerformanceCounter(&i); + memcpy(&zBuf[n], &i, sizeof(i)); + n += sizeof(i); + } + return n; +} + + +/* +** Sleep for a little while. Return the amount of time slept. +*/ +static int winSleep(sqlite3_vfs *pVfs, int microsec){ + Sleep((microsec+999)/1000); + return ((microsec+999)/1000)*1000; +} + +/* +** The following variable, if set to a non-zero value, becomes the result +** returned from sqlite3OsCurrentTime(). This is used for testing. +*/ +#ifdef SQLITE_TEST +int sqlite3_current_time = 0; +#endif + +/* +** Find the current time (in Universal Coordinated Time). Write the +** 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 winCurrentTime(sqlite3_vfs *pVfs, 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 SQLITE_OS_WINCE + SYSTEMTIME time; + GetSystemTime(&time); + /* if SystemTimeToFileTime() fails, it returns zero. */ + if (!SystemTimeToFileTime(&time,&ft)){ + return 1; + } +#else + GetSystemTimeAsFileTime( &ft ); +#endif + now = ((double)ft.dwHighDateTime) * 4294967296.0; + *prNow = (now + ft.dwLowDateTime)/864000000000.0 + 2305813.5; +#ifdef SQLITE_TEST + if( sqlite3_current_time ){ + *prNow = sqlite3_current_time/86400.0 + 2440587.5; + } +#endif + return 0; +} + +/* +** The idea is that this function works like a combination of +** GetLastError() and FormatMessage() on windows (or errno and +** strerror_r() on unix). After an error is returned by an OS +** function, SQLite calls this function with zBuf pointing to +** a buffer of nBuf bytes. The OS layer should populate the +** buffer with a nul-terminated UTF-8 encoded error message +** describing the last IO error to have occured within the calling +** thread. +** +** If the error message is too large for the supplied buffer, +** it should be truncated. The return value of xGetLastError +** is zero if the error message fits in the buffer, or non-zero +** otherwise (if the message was truncated). If non-zero is returned, +** then it is not necessary to include the nul-terminator character +** in the output buffer. +** +** Not supplying an error message will have no adverse effect +** on SQLite. It is fine to have an implementation that never +** returns an error message: +** +** int xGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ +** assert(zBuf[0]=='\0'); +** return 0; +** } +** +** However if an error message is supplied, it will be incorporated +** by sqlite into the error message available to the user using +** sqlite3_errmsg(), possibly making IO errors easier to debug. +*/ +static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ + return getLastErrorMsg(nBuf, zBuf); +} + +/* +** Initialize and deinitialize the operating system interface. +*/ +int sqlite3_os_init(void){ + static sqlite3_vfs winVfs = { + 1, /* iVersion */ + sizeof(winFile), /* szOsFile */ + MAX_PATH, /* mxPathname */ + 0, /* pNext */ + "win32", /* zName */ + 0, /* pAppData */ + + winOpen, /* xOpen */ + winDelete, /* xDelete */ + winAccess, /* xAccess */ + winFullPathname, /* xFullPathname */ + winDlOpen, /* xDlOpen */ + winDlError, /* xDlError */ + winDlSym, /* xDlSym */ + winDlClose, /* xDlClose */ + winRandomness, /* xRandomness */ + winSleep, /* xSleep */ + winCurrentTime, /* xCurrentTime */ + winGetLastError /* xGetLastError */ + }; + sqlite3_vfs_register(&winVfs, 1); + return SQLITE_OK; +} +int sqlite3_os_end(void){ + return SQLITE_OK; +} + +#endif /* SQLITE_OS_WIN */ diff --git a/third_party/sqlite/src/pager.c b/third_party/sqlite/src/pager.c new file mode 100755 index 0000000..b9f50a4 --- /dev/null +++ b/third_party/sqlite/src/pager.c @@ -0,0 +1,5494 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This is the implementation of the page cache subsystem or "pager". +** +** The pager is used to access a database disk file. It implements +** atomic commit and rollback through the use of a journal file that +** is separate from the database file. The pager also implements file +** locking to prevent two processes from writing the same database +** file simultaneously, or one process from reading the database while +** another is writing. +** +** @(#) $Id: pager.c,v 1.469 2008/08/02 03:50:39 drh Exp $ +*/ +#ifndef SQLITE_OMIT_DISKIO +#include "sqliteInt.h" +#include <assert.h> +#include <string.h> + +/* +** Macros for troubleshooting. Normally turned off +*/ +#if 0 +#define sqlite3DebugPrintf printf +#define PAGERTRACE1(X) sqlite3DebugPrintf(X) +#define PAGERTRACE2(X,Y) sqlite3DebugPrintf(X,Y) +#define PAGERTRACE3(X,Y,Z) sqlite3DebugPrintf(X,Y,Z) +#define PAGERTRACE4(X,Y,Z,W) sqlite3DebugPrintf(X,Y,Z,W) +#define PAGERTRACE5(X,Y,Z,W,V) sqlite3DebugPrintf(X,Y,Z,W,V) +#else +#define PAGERTRACE1(X) +#define PAGERTRACE2(X,Y) +#define PAGERTRACE3(X,Y,Z) +#define PAGERTRACE4(X,Y,Z,W) +#define PAGERTRACE5(X,Y,Z,W,V) +#endif + +/* +** The following two macros are used within the PAGERTRACEX() macros above +** to print out file-descriptors. +** +** PAGERID() takes a pointer to a Pager struct as its argument. The +** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file +** struct as its argument. +*/ +#define PAGERID(p) ((int)(p->fd)) +#define FILEHANDLEID(fd) ((int)fd) + +/* +** The page cache as a whole is always in one of the following +** states: +** +** PAGER_UNLOCK The page cache is not currently reading or +** writing the database file. There is no +** data held in memory. This is the initial +** state. +** +** PAGER_SHARED The page cache is reading the database. +** Writing is not permitted. There can be +** multiple readers accessing the same database +** file at the same time. +** +** PAGER_RESERVED This process has reserved the database for writing +** but has not yet made any changes. Only one process +** at a time can reserve the database. The original +** database file has not been modified so other +** processes may still be reading the on-disk +** database file. +** +** PAGER_EXCLUSIVE The page cache is writing the database. +** Access is exclusive. No other processes or +** threads can be reading or writing while one +** process is writing. +** +** PAGER_SYNCED The pager moves to this state from PAGER_EXCLUSIVE +** after all dirty pages have been written to the +** database file and the file has been synced to +** disk. All that remains to do is to remove or +** truncate the journal file and the transaction +** will be committed. +** +** The page cache comes up in PAGER_UNLOCK. The first time a +** sqlite3PagerGet() occurs, the state transitions to PAGER_SHARED. +** After all pages have been released using sqlite_page_unref(), +** the state transitions back to PAGER_UNLOCK. The first time +** that sqlite3PagerWrite() is called, the state transitions to +** PAGER_RESERVED. (Note that sqlite3PagerWrite() can only be +** called on an outstanding page which means that the pager must +** be in PAGER_SHARED before it transitions to PAGER_RESERVED.) +** PAGER_RESERVED means that there is an open rollback journal. +** The transition to PAGER_EXCLUSIVE occurs before any changes +** are made to the database file, though writes to the rollback +** journal occurs with just PAGER_RESERVED. After an sqlite3PagerRollback() +** or sqlite3PagerCommitPhaseTwo(), the state can go back to PAGER_SHARED, +** or it can stay at PAGER_EXCLUSIVE if we are in exclusive access mode. +*/ +#define PAGER_UNLOCK 0 +#define PAGER_SHARED 1 /* same as SHARED_LOCK */ +#define PAGER_RESERVED 2 /* same as RESERVED_LOCK */ +#define PAGER_EXCLUSIVE 4 /* same as EXCLUSIVE_LOCK */ +#define PAGER_SYNCED 5 + +/* +** If the SQLITE_BUSY_RESERVED_LOCK macro is set to true at compile-time, +** then failed attempts to get a reserved lock will invoke the busy callback. +** This is off by default. To see why, consider the following scenario: +** +** Suppose thread A already has a shared lock and wants a reserved lock. +** Thread B already has a reserved lock and wants an exclusive lock. If +** both threads are using their busy callbacks, it might be a long time +** be for one of the threads give up and allows the other to proceed. +** But if the thread trying to get the reserved lock gives up quickly +** (if it never invokes its busy callback) then the contention will be +** resolved quickly. +*/ +#ifndef SQLITE_BUSY_RESERVED_LOCK +# define SQLITE_BUSY_RESERVED_LOCK 0 +#endif + +/* +** This macro rounds values up so that if the value is an address it +** is guaranteed to be an address that is aligned to an 8-byte boundary. +*/ +#define FORCE_ALIGNMENT(X) (((X)+7)&~7) + +typedef struct PgHdr PgHdr; + +/* +** Each pager stores all currently unreferenced pages in a list sorted +** in least-recently-used (LRU) order (i.e. the first item on the list has +** not been referenced in a long time, the last item has been recently +** used). An instance of this structure is included as part of each +** pager structure for this purpose (variable Pager.lru). +** +** Additionally, if memory-management is enabled, all unreferenced pages +** are stored in a global LRU list (global variable sqlite3LruPageList). +** +** In both cases, the PagerLruList.pFirstSynced variable points to +** the first page in the corresponding list that does not require an +** fsync() operation before its memory can be reclaimed. If no such +** page exists, PagerLruList.pFirstSynced is set to NULL. +*/ +typedef struct PagerLruList PagerLruList; +struct PagerLruList { + PgHdr *pFirst; /* First page in LRU list */ + PgHdr *pLast; /* Last page in LRU list (the most recently used) */ + PgHdr *pFirstSynced; /* First page in list with PgHdr.needSync==0 */ +}; + +/* +** The following structure contains the next and previous pointers used +** to link a PgHdr structure into a PagerLruList linked list. +*/ +typedef struct PagerLruLink PagerLruLink; +struct PagerLruLink { + PgHdr *pNext; + PgHdr *pPrev; +}; + +/* +** Each in-memory image of a page begins with the following header. +** This header is only visible to this pager module. The client +** code that calls pager sees only the data that follows the header. +** +** Client code should call sqlite3PagerWrite() on a page prior to making +** any modifications to that page. The first time sqlite3PagerWrite() +** is called, the original page contents are written into the rollback +** journal and PgHdr.inJournal and PgHdr.needSync are set. Later, once +** the journal page has made it onto the disk surface, PgHdr.needSync +** is cleared. The modified page cannot be written back into the original +** database file until the journal pages has been synced to disk and the +** PgHdr.needSync has been cleared. +** +** The PgHdr.dirty flag is set when sqlite3PagerWrite() is called and +** is cleared again when the page content is written back to the original +** database file. +** +** Details of important structure elements: +** +** needSync +** +** If this is true, this means that it is not safe to write the page +** content to the database because the original content needed +** for rollback has not by synced to the main rollback journal. +** The original content may have been written to the rollback journal +** but it has not yet been synced. So we cannot write to the database +** file because power failure might cause the page in the journal file +** to never reach the disk. It is as if the write to the journal file +** does not occur until the journal file is synced. +** +** This flag is false if the page content exactly matches what +** currently exists in the database file. The needSync flag is also +** false if the original content has been written to the main rollback +** journal and synced. If the page represents a new page that has +** been added onto the end of the database during the current +** transaction, the needSync flag is true until the original database +** size in the journal header has been synced to disk. +** +** inJournal +** +** This is true if the original page has been written into the main +** rollback journal. This is always false for new pages added to +** the end of the database file during the current transaction. +** And this flag says nothing about whether or not the journal +** has been synced to disk. For pages that are in the original +** database file, the following expression should always be true: +** +** inJournal = sqlite3BitvecTest(pPager->pInJournal, pgno) +** +** The pPager->pInJournal object is only valid for the original +** pages of the database, not new pages that are added to the end +** of the database, so obviously the above expression cannot be +** valid for new pages. For new pages inJournal is always 0. +** +** dirty +** +** When true, this means that the content of the page has been +** modified and needs to be written back to the database file. +** If false, it means that either the content of the page is +** unchanged or else the content is unimportant and we do not +** care whether or not it is preserved. +** +** alwaysRollback +** +** This means that the sqlite3PagerDontRollback() API should be +** ignored for this page. The DontRollback() API attempts to say +** that the content of the page on disk is unimportant (it is an +** unused page on the freelist) so that it is unnecessary to +** rollback changes to this page because the content of the page +** can change without changing the meaning of the database. This +** flag overrides any DontRollback() attempt. This flag is set +** when a page that originally contained valid data is added to +** the freelist. Later in the same transaction, this page might +** be pulled from the freelist and reused for something different +** and at that point the DontRollback() API will be called because +** pages taken from the freelist do not need to be protected by +** the rollback journal. But this flag says that the page was +** not originally part of the freelist so that it still needs to +** be rolled back in spite of any subsequent DontRollback() calls. +** +** needRead +** +** This flag means (when true) that the content of the page has +** not yet been loaded from disk. The in-memory content is just +** garbage. (Actually, we zero the content, but you should not +** make any assumptions about the content nevertheless.) If the +** content is needed in the future, it should be read from the +** original database file. +*/ +struct PgHdr { + Pager *pPager; /* The pager to which this page belongs */ + Pgno pgno; /* The page number for this page */ + PgHdr *pNextHash, *pPrevHash; /* Hash collision chain for PgHdr.pgno */ + PagerLruLink free; /* Next and previous free pages */ + PgHdr *pNextAll; /* A list of all pages */ + u8 inJournal; /* TRUE if has been written to journal */ + u8 dirty; /* TRUE if we need to write back changes */ + u8 needSync; /* Sync journal before writing this page */ + u8 alwaysRollback; /* Disable DontRollback() for this page */ + u8 needRead; /* Read content if PagerWrite() is called */ + short int nRef; /* Number of users of this page */ + PgHdr *pDirty, *pPrevDirty; /* Dirty pages */ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + PgHdr *pPrevAll; /* A list of all pages */ + PagerLruLink gfree; /* Global list of nRef==0 pages */ +#endif +#ifdef SQLITE_CHECK_PAGES + u32 pageHash; +#endif + void *pData; /* Page data */ + /* Pager.nExtra bytes of local data appended to this header */ +}; + +/* +** For an in-memory only database, some extra information is recorded about +** each page so that changes can be rolled back. (Journal files are not +** used for in-memory databases.) The following information is added to +** the end of every EXTRA block for in-memory databases. +** +** This information could have been added directly to the PgHdr structure. +** But then it would take up an extra 8 bytes of storage on every PgHdr +** even for disk-based databases. Splitting it out saves 8 bytes. This +** is only a savings of 0.8% but those percentages add up. +*/ +typedef struct PgHistory PgHistory; +struct PgHistory { + u8 *pOrig; /* Original page text. Restore to this on a full rollback */ + u8 *pStmt; /* Text as it was at the beginning of the current statement */ + PgHdr *pNextStmt, *pPrevStmt; /* List of pages in the statement journal */ + u8 inStmt; /* TRUE if in the statement subjournal */ +}; + +/* +** A macro used for invoking the codec if there is one +*/ +#ifdef SQLITE_HAS_CODEC +# define CODEC1(P,D,N,X) if( P->xCodec!=0 ){ P->xCodec(P->pCodecArg,D,N,X); } +# define CODEC2(P,D,N,X) ((char*)(P->xCodec!=0?P->xCodec(P->pCodecArg,D,N,X):D)) +#else +# define CODEC1(P,D,N,X) /* NO-OP */ +# define CODEC2(P,D,N,X) ((char*)D) +#endif + +/* +** Convert a pointer to a PgHdr into a pointer to its data +** and back again. +*/ +#define PGHDR_TO_DATA(P) ((P)->pData) +#define PGHDR_TO_EXTRA(G,P) ((void*)&((G)[1])) +#define PGHDR_TO_HIST(P,PGR) \ + ((PgHistory*)&((char*)(&(P)[1]))[(PGR)->nExtra]) + +/* +** A open page cache is an instance of the following structure. +** +** Pager.errCode may be set to SQLITE_IOERR, SQLITE_CORRUPT, or +** 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 sqlite3PagerGet() and sqlite3PagerLookup() +** APIs, they may still be used successfully. +*/ +struct Pager { + sqlite3_vfs *pVfs; /* OS functions to use for IO */ + u8 journalOpen; /* True if journal file descriptors is valid */ + u8 journalStarted; /* True if header of journal is synced */ + u8 useJournal; /* Use a rollback journal on this file */ + u8 noReadlock; /* Do not bother to obtain readlocks */ + u8 stmtOpen; /* True if the statement subjournal is open */ + u8 stmtInUse; /* True we are in a statement subtransaction */ + u8 stmtAutoopen; /* Open stmt journal when main journal is opened*/ + u8 noSync; /* Do not sync the journal if true */ + u8 fullSync; /* Do extra syncs of the journal for robustness */ + u8 sync_flags; /* One of SYNC_NORMAL or SYNC_FULL */ + u8 state; /* PAGER_UNLOCK, _SHARED, _RESERVED, etc. */ + 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 */ + u8 dirtyCache; /* True if cached pages have changed */ + u8 alwaysRollback; /* Disable DontRollback() for all pages */ + u8 memDb; /* True to inhibit all file I/O */ + u8 setMaster; /* True if a m-j name has been written to jrnl */ + u8 doNotSync; /* Boolean. While true, do not spill the cache */ + u8 exclusiveMode; /* Boolean. True if locking_mode==EXCLUSIVE */ + u8 journalMode; /* On of the PAGER_JOURNALMODE_* values */ + u8 dbModified; /* True if there are any changes to the Db */ + u8 changeCountDone; /* Set after incrementing the change-counter */ + u32 vfsFlags; /* Flags for sqlite3_vfs.xOpen() */ + int errCode; /* One of several kinds of errors */ + int dbSize; /* Number of pages in the file */ + int origDbSize; /* dbSize before the current change */ + int stmtSize; /* Size of database (in pages) at stmt_begin() */ + int nRec; /* Number of pages written to the journal */ + u32 cksumInit; /* Quasi-random value added to every checksum */ + int stmtNRec; /* Number of records in stmt subjournal */ + int nExtra; /* Add this many bytes to each in-memory page */ + int pageSize; /* Number of bytes in a page */ + int nPage; /* Total number of in-memory pages */ + int nRef; /* Number of in-memory pages with PgHdr.nRef>0 */ + int mxPage; /* Maximum number of pages to hold in cache */ + Pgno mxPgno; /* Maximum allowed size of the database */ + Bitvec *pInJournal; /* One bit for each page in the database file */ + Bitvec *pInStmt; /* One bit for each page in the database */ + char *zFilename; /* Name of the database file */ + char *zJournal; /* Name of the journal file */ + char *zDirectory; /* Directory hold database and journal files */ + sqlite3_file *fd, *jfd; /* File descriptors for database and journal */ + sqlite3_file *stfd; /* File descriptor for the statement subjournal*/ + BusyHandler *pBusyHandler; /* Pointer to sqlite.busyHandler */ + PagerLruList lru; /* LRU list of free pages */ + PgHdr *pAll; /* List of all pages */ + PgHdr *pStmt; /* List of pages in the statement subjournal */ + PgHdr *pDirty; /* List of all dirty pages */ + i64 journalOff; /* Current byte offset in the journal file */ + i64 journalHdr; /* Byte offset to previous journal header */ + i64 stmtHdrOff; /* First journal header written this statement */ + i64 stmtCksum; /* cksumInit when statement was started */ + i64 stmtJSize; /* Size of journal at stmt_begin() */ + int sectorSize; /* Assumed sector size during rollback */ +#ifdef SQLITE_TEST + int nHit, nMiss; /* Cache hits and missing */ + int nRead, nWrite; /* Database pages read/written */ +#endif + void (*xDestructor)(DbPage*,int); /* Call this routine when freeing pages */ + void (*xReiniter)(DbPage*,int); /* Call this routine when reloading pages */ +#ifdef SQLITE_HAS_CODEC + void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */ + void *pCodecArg; /* First argument to xCodec() */ +#endif + int nHash; /* Size of the pager hash table */ + PgHdr **aHash; /* Hash table to map page number to PgHdr */ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + Pager *pNext; /* Doubly linked list of pagers on which */ + Pager *pPrev; /* sqlite3_release_memory() will work */ + volatile int iInUseMM; /* Non-zero if unavailable to MM */ + volatile int iInUseDB; /* Non-zero if in sqlite3_release_memory() */ +#endif + char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */ + char dbFileVers[16]; /* Changes whenever database file changes */ + i64 journalSizeLimit; /* Size limit for persistent journal files */ +}; + +/* +** The following global variables hold counters used for +** testing purposes only. These variables do not exist in +** a non-testing build. These variables are not thread-safe. +*/ +#ifdef SQLITE_TEST +int sqlite3_pager_readdb_count = 0; /* Number of full pages read from DB */ +int sqlite3_pager_writedb_count = 0; /* Number of full pages written to DB */ +int sqlite3_pager_writej_count = 0; /* Number of pages written to journal */ +int sqlite3_pager_pgfree_count = 0; /* Number of cache pages freed */ +# define PAGER_INCR(v) v++ +#else +# define PAGER_INCR(v) +#endif + +/* +** The following variable points to the head of a double-linked list +** of all pagers that are eligible for page stealing by the +** sqlite3_release_memory() interface. Access to this list is +** protected by the SQLITE_MUTEX_STATIC_MEM2 mutex. +*/ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +static Pager *sqlite3PagerList = 0; +static PagerLruList sqlite3LruPageList = {0, 0, 0}; +#endif + + +/* +** Journal files begin with the following magic string. The data +** was obtained from /dev/random. It is used only as a sanity check. +** +** Since version 2.8.0, the journal format contains additional sanity +** checking information. If the power fails while the journal is begin +** written, semi-random garbage data might appear in the journal +** file after power is restored. If an attempt is then made +** to roll the journal back, the database could be corrupted. The additional +** sanity checking data is an attempt to discover the garbage in the +** journal and ignore it. +** +** The sanity checking information for the new journal format consists +** of a 32-bit checksum on each page of data. The checksum covers both +** the page number and the pPager->pageSize bytes of data for the page. +** This cksum is initialized to a 32-bit random value that appears in the +** journal file right after the header. The random initializer is important, +** because garbage data that appears at the end of a journal is likely +** data that was once in other files that have now been deleted. If the +** garbage data came from an obsolete journal file, the checksums might +** be correct. But by initializing the checksum to random value which +** is different for every journal, we minimize that risk. +*/ +static const unsigned char aJournalMagic[] = { + 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd7, +}; + +/* +** The size of the header and of each page in the journal is determined +** by the following macros. +*/ +#define JOURNAL_PG_SZ(pPager) ((pPager->pageSize) + 8) + +/* +** The journal header size for this pager. In the future, this could be +** set to some value read from the disk controller. The important +** characteristic is that it is the same size as a disk sector. +*/ +#define JOURNAL_HDR_SZ(pPager) (pPager->sectorSize) + +/* +** The macro MEMDB is true if we are dealing with an in-memory database. +** We do this as a macro so that if the SQLITE_OMIT_MEMORYDB macro is set, +** the value of MEMDB will be a constant and the compiler will optimize +** out code that would never execute. +*/ +#ifdef SQLITE_OMIT_MEMORYDB +# define MEMDB 0 +#else +# define MEMDB pPager->memDb +#endif + +/* +** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is +** reserved for working around a windows/posix incompatibility). It is +** used in the journal to signify that the remainder of the journal file +** is devoted to storing a master journal name - there are no more pages to +** roll back. See comments for function writeMasterJournal() for details. +*/ +/* #define PAGER_MJ_PGNO(x) (PENDING_BYTE/((x)->pageSize)) */ +#define PAGER_MJ_PGNO(x) ((PENDING_BYTE/((x)->pageSize))+1) + +/* +** The maximum legal page number is (2^31 - 1). +*/ +#define PAGER_MAX_PGNO 2147483647 + +/* Begin preload-cache.patch for Chromium */ +/* See comments above the definition. */ +int sqlite3PagerAcquire2( + Pager *pPager, + Pgno pgno, + DbPage **ppPage, + int noContent, + unsigned char *pDataToFill); +/* End preload-cache.patch for Chromium */ + +/* +** The pagerEnter() and pagerLeave() routines acquire and release +** a mutex on each pager. The mutex is recursive. +** +** This is a special-purpose mutex. It only provides mutual exclusion +** between the Btree and the Memory Management sqlite3_release_memory() +** function. It does not prevent, for example, two Btrees from accessing +** the same pager at the same time. Other general-purpose mutexes in +** the btree layer handle that chore. +*/ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + static void pagerEnter(Pager *p){ + p->iInUseDB++; + if( p->iInUseMM && p->iInUseDB==1 ){ +#ifndef SQLITE_MUTEX_NOOP + sqlite3_mutex *mutex; + mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM2); +#endif + p->iInUseDB = 0; + sqlite3_mutex_enter(mutex); + p->iInUseDB = 1; + sqlite3_mutex_leave(mutex); + } + assert( p->iInUseMM==0 ); + } + static void pagerLeave(Pager *p){ + p->iInUseDB--; + assert( p->iInUseDB>=0 ); + } +#else +# define pagerEnter(X) +# define pagerLeave(X) +#endif + +/* +** Add page pPg to the end of the linked list managed by structure +** pList (pPg becomes the last entry in the list - the most recently +** used). Argument pLink should point to either pPg->free or pPg->gfree, +** depending on whether pPg is being added to the pager-specific or +** global LRU list. +*/ +static void listAdd(PagerLruList *pList, PagerLruLink *pLink, PgHdr *pPg){ + pLink->pNext = 0; + pLink->pPrev = pList->pLast; + +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + assert(pLink==&pPg->free || pLink==&pPg->gfree); + assert(pLink==&pPg->gfree || pList!=&sqlite3LruPageList); +#endif + + if( pList->pLast ){ + int iOff = (char *)pLink - (char *)pPg; + PagerLruLink *pLastLink = (PagerLruLink *)(&((u8 *)pList->pLast)[iOff]); + pLastLink->pNext = pPg; + }else{ + assert(!pList->pFirst); + pList->pFirst = pPg; + } + + pList->pLast = pPg; + if( !pList->pFirstSynced && pPg->needSync==0 ){ + pList->pFirstSynced = pPg; + } +} + +/* +** Remove pPg from the list managed by the structure pointed to by pList. +** +** Argument pLink should point to either pPg->free or pPg->gfree, depending +** on whether pPg is being added to the pager-specific or global LRU list. +*/ +static void listRemove(PagerLruList *pList, PagerLruLink *pLink, PgHdr *pPg){ + int iOff = (char *)pLink - (char *)pPg; + +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + assert(pLink==&pPg->free || pLink==&pPg->gfree); + assert(pLink==&pPg->gfree || pList!=&sqlite3LruPageList); +#endif + + if( pPg==pList->pFirst ){ + pList->pFirst = pLink->pNext; + } + if( pPg==pList->pLast ){ + pList->pLast = pLink->pPrev; + } + if( pLink->pPrev ){ + PagerLruLink *pPrevLink = (PagerLruLink *)(&((u8 *)pLink->pPrev)[iOff]); + pPrevLink->pNext = pLink->pNext; + } + if( pLink->pNext ){ + PagerLruLink *pNextLink = (PagerLruLink *)(&((u8 *)pLink->pNext)[iOff]); + pNextLink->pPrev = pLink->pPrev; + } + if( pPg==pList->pFirstSynced ){ + PgHdr *p = pLink->pNext; + while( p && p->needSync ){ + PagerLruLink *pL = (PagerLruLink *)(&((u8 *)p)[iOff]); + p = pL->pNext; + } + pList->pFirstSynced = p; + } + + pLink->pNext = pLink->pPrev = 0; +} + +/* +** Add page pPg to the list of free pages for the pager. If +** memory-management is enabled, also add the page to the global +** list of free pages. +*/ +static void lruListAdd(PgHdr *pPg){ + listAdd(&pPg->pPager->lru, &pPg->free, pPg); +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + if( !pPg->pPager->memDb ){ + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU)); + listAdd(&sqlite3LruPageList, &pPg->gfree, pPg); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU)); + } +#endif +} + +/* +** Remove page pPg from the list of free pages for the associated pager. +** If memory-management is enabled, also remove pPg from the global list +** of free pages. +*/ +static void lruListRemove(PgHdr *pPg){ + listRemove(&pPg->pPager->lru, &pPg->free, pPg); +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + if( !pPg->pPager->memDb ){ + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU)); + listRemove(&sqlite3LruPageList, &pPg->gfree, pPg); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU)); + } +#endif +} + +/* +** This function is called just after the needSync flag has been cleared +** from all pages managed by pPager (usually because the journal file +** has just been synced). It updates the pPager->lru.pFirstSynced variable +** and, if memory-management is enabled, the sqlite3LruPageList.pFirstSynced +** variable also. +*/ +static void lruListSetFirstSynced(Pager *pPager){ + pPager->lru.pFirstSynced = pPager->lru.pFirst; +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + if( !pPager->memDb ){ + PgHdr *p; + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU)); + for(p=sqlite3LruPageList.pFirst; p && p->needSync; p=p->gfree.pNext); + assert(p==pPager->lru.pFirstSynced || p==sqlite3LruPageList.pFirstSynced); + sqlite3LruPageList.pFirstSynced = p; + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU)); + } +#endif +} + +/* +** Return true if page *pPg has already been written to the statement +** journal (or statement snapshot has been created, if *pPg is part +** of an in-memory database). +*/ +static int pageInStatement(PgHdr *pPg){ + Pager *pPager = pPg->pPager; + if( MEMDB ){ + return PGHDR_TO_HIST(pPg, pPager)->inStmt; + }else{ + return sqlite3BitvecTest(pPager->pInStmt, pPg->pgno); + } +} + +/* +** Change the size of the pager hash table to N. N must be a power +** of two. +*/ +static void pager_resize_hash_table(Pager *pPager, int N){ + PgHdr **aHash, *pPg; + assert( N>0 && (N&(N-1))==0 ); +#ifdef SQLITE_MALLOC_SOFT_LIMIT + if( N*sizeof(aHash[0])>SQLITE_MALLOC_SOFT_LIMIT ){ + N = SQLITE_MALLOC_SOFT_LIMIT/sizeof(aHash[0]); + } + if( N==pPager->nHash ) return; +#endif + pagerLeave(pPager); + if( pPager->aHash!=0 ) sqlite3BeginBenignMalloc(); + aHash = sqlite3MallocZero( sizeof(aHash[0])*N ); + if( pPager->aHash!=0 ) sqlite3EndBenignMalloc(); + pagerEnter(pPager); + if( aHash==0 ){ + /* Failure to rehash is not an error. It is only a performance hit. */ + return; + } + sqlite3_free(pPager->aHash); + pPager->nHash = N; + pPager->aHash = aHash; + for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ + int h; + if( pPg->pgno==0 ){ + assert( pPg->pNextHash==0 && pPg->pPrevHash==0 ); + continue; + } + h = pPg->pgno & (N-1); + pPg->pNextHash = aHash[h]; + if( aHash[h] ){ + aHash[h]->pPrevHash = pPg; + } + aHash[h] = pPg; + pPg->pPrevHash = 0; + } +} + +/* +** Read a 32-bit integer from the given file descriptor. Store the integer +** that is read in *pRes. Return SQLITE_OK if everything worked, or an +** error code is something goes wrong. +** +** All values are stored on disk as big-endian. +*/ +static int read32bits(sqlite3_file *fd, i64 offset, u32 *pRes){ + unsigned char ac[4]; + int rc = sqlite3OsRead(fd, ac, sizeof(ac), offset); + if( rc==SQLITE_OK ){ + *pRes = sqlite3Get4byte(ac); + } + return rc; +} + +/* +** Write a 32-bit integer into a string buffer in big-endian byte order. +*/ +#define put32bits(A,B) sqlite3Put4byte((u8*)A,B) + +/* +** 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(sqlite3_file *fd, i64 offset, u32 val){ + char ac[4]; + put32bits(ac, val); + return sqlite3OsWrite(fd, ac, 4, offset); +} + +/* +** If file pFd is open, call sqlite3OsUnlock() on it. +*/ +static int osUnlock(sqlite3_file *pFd, int eLock){ + if( !pFd->pMethods ){ + return SQLITE_OK; + } + return sqlite3OsUnlock(pFd, eLock); +} + +/* +** This function determines whether or not the atomic-write optimization +** can be used with this pager. The optimization can be used if: +** +** (a) the value returned by OsDeviceCharacteristics() indicates that +** a database page may be written atomically, and +** (b) the value returned by OsSectorSize() is less than or equal +** to the page size. +** +** If the optimization cannot be used, 0 is returned. If it can be used, +** then the value returned is the size of the journal file when it +** contains rollback data for exactly one page. +*/ +#ifdef SQLITE_ENABLE_ATOMIC_WRITE +static int jrnlBufferSize(Pager *pPager){ + int dc; /* Device characteristics */ + int nSector; /* Sector size */ + int szPage; /* Page size */ + sqlite3_file *fd = pPager->fd; + + if( fd->pMethods ){ + dc = sqlite3OsDeviceCharacteristics(fd); + nSector = sqlite3OsSectorSize(fd); + szPage = pPager->pageSize; + } + + assert(SQLITE_IOCAP_ATOMIC512==(512>>8)); + assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8)); + + if( !fd->pMethods || + (dc & (SQLITE_IOCAP_ATOMIC|(szPage>>8)) && nSector<=szPage) ){ + return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager); + } + return 0; +} +#endif + +/* +** 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_FULL +** the error becomes persistent. Until the persisten error is cleared, +** subsequent API calls on this Pager will immediately return the same +** error code. +** +** A persistent error indicates that the contents of the pager-cache +** cannot be trusted. This state can be cleared by completely discarding +** the contents of the pager-cache. If a transaction was active when +** the persistent error occured, then the rollback journal may need +** to be replayed. +*/ +static void pager_unlock(Pager *pPager); +static int pager_error(Pager *pPager, int rc){ + int rc2 = rc & 0xff; + assert( + pPager->errCode==SQLITE_FULL || + pPager->errCode==SQLITE_OK || + (pPager->errCode & 0xff)==SQLITE_IOERR + ); + if( + rc2==SQLITE_FULL || + rc2==SQLITE_IOERR || + rc2==SQLITE_CORRUPT + ){ + pPager->errCode = rc; + if( pPager->state==PAGER_UNLOCK && pPager->nRef==0 ){ + /* If the pager is already unlocked, call pager_unlock() now to + ** clear the error state and ensure that the pager-cache is + ** completely empty. + */ + pager_unlock(pPager); + } + } + return rc; +} + +/* +** If SQLITE_CHECK_PAGES is defined then we do some sanity checking +** on the cache using a hash function. This is used for testing +** and debugging only. +*/ +#ifdef SQLITE_CHECK_PAGES +/* +** Return a 32-bit hash of the page data for pPage. +*/ +static u32 pager_datahash(int nByte, unsigned char *pData){ + u32 hash = 0; + int i; + for(i=0; i<nByte; i++){ + hash = (hash*1039) + pData[i]; + } + return hash; +} +static u32 pager_pagehash(PgHdr *pPage){ + return pager_datahash(pPage->pPager->pageSize, + (unsigned char *)PGHDR_TO_DATA(pPage)); +} + +/* +** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES +** is defined, and NDEBUG is not defined, an assert() statement checks +** that the page is either dirty or still matches the calculated page-hash. +*/ +#define CHECK_PAGE(x) checkPage(x) +static void checkPage(PgHdr *pPg){ + Pager *pPager = pPg->pPager; + assert( !pPg->pageHash || pPager->errCode || MEMDB || pPg->dirty || + pPg->pageHash==pager_pagehash(pPg) ); +} + +#else +#define pager_datahash(X,Y) 0 +#define pager_pagehash(X) 0 +#define CHECK_PAGE(x) +#endif + +/* +** When this is called the journal file for pager pPager must be open. +** The master journal file name is read from the end of the file and +** written into memory supplied by the caller. +** +** zMaster must point to a buffer of at least nMaster bytes allocated by +** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is +** enough space to write the master journal name). If the master journal +** name in the journal is longer than nMaster bytes (including a +** nul-terminator), then this is handled as if no master journal name +** were present in the journal. +** +** If no master journal file name is present zMaster[0] is set to 0 and +** SQLITE_OK returned. +*/ +static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, int nMaster){ + int rc; + u32 len; + i64 szJ; + u32 cksum; + u32 u; /* Unsigned loop counter */ + unsigned char aMagic[8]; /* A buffer to hold the magic header */ + + zMaster[0] = '\0'; + + rc = sqlite3OsFileSize(pJrnl, &szJ); + if( rc!=SQLITE_OK || szJ<16 ) return rc; + + rc = read32bits(pJrnl, szJ-16, &len); + if( rc!=SQLITE_OK ) return rc; + + if( len>=nMaster ){ + return SQLITE_OK; + } + + rc = read32bits(pJrnl, szJ-12, &cksum); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8); + if( rc!=SQLITE_OK || memcmp(aMagic, aJournalMagic, 8) ) return rc; + + rc = sqlite3OsRead(pJrnl, zMaster, len, szJ-16-len); + if( rc!=SQLITE_OK ){ + return rc; + } + zMaster[len] = '\0'; + + /* See if the checksum matches the master journal name */ + for(u=0; u<len; u++){ + cksum -= zMaster[u]; + } + if( cksum ){ + /* If the checksum doesn't add up, then one or more of the disk sectors + ** containing the master journal filename is corrupted. This means + ** definitely roll back, so just return SQLITE_OK and report a (nul) + ** master-journal filename. + */ + zMaster[0] = '\0'; + } + + return SQLITE_OK; +} + +/* +** Seek the journal file descriptor to the next sector boundary where a +** journal header may be read or written. Pager.journalOff is updated with +** the new seek offset. +** +** i.e for a sector size of 512: +** +** Input Offset Output Offset +** --------------------------------------- +** 0 0 +** 512 512 +** 100 512 +** 2000 2048 +** +*/ +static void seekJournalHdr(Pager *pPager){ + i64 offset = 0; + i64 c = pPager->journalOff; + if( c ){ + offset = ((c-1)/JOURNAL_HDR_SZ(pPager) + 1) * JOURNAL_HDR_SZ(pPager); + } + assert( offset%JOURNAL_HDR_SZ(pPager)==0 ); + assert( offset>=c ); + assert( (offset-c)<JOURNAL_HDR_SZ(pPager) ); + pPager->journalOff = offset; +} + +/* +** Write zeros over the header of the journal file. This has the +** effect of invalidating the journal file and committing the +** transaction. +*/ +static int zeroJournalHdr(Pager *pPager, int doTruncate){ + int rc = SQLITE_OK; + static const char zeroHdr[28]; + + if( pPager->journalOff ){ + i64 iLimit = pPager->journalSizeLimit; + + IOTRACE(("JZEROHDR %p\n", pPager)) + if( doTruncate || iLimit==0 ){ + rc = sqlite3OsTruncate(pPager->jfd, 0); + }else{ + rc = sqlite3OsWrite(pPager->jfd, zeroHdr, sizeof(zeroHdr), 0); + } + if( rc==SQLITE_OK && !pPager->noSync ){ + rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_DATAONLY|pPager->sync_flags); + } + + /* At this point the transaction is committed but the write lock + ** is still held on the file. If there is a size limit configured for + ** the persistent journal and the journal file currently consumes more + ** space than that limit allows for, truncate it now. There is no need + ** to sync the file following this operation. + */ + if( rc==SQLITE_OK && iLimit>0 ){ + i64 sz; + rc = sqlite3OsFileSize(pPager->jfd, &sz); + if( rc==SQLITE_OK && sz>iLimit ){ + rc = sqlite3OsTruncate(pPager->jfd, iLimit); + } + } + } + return rc; +} + +/* +** The journal file must be open when this routine is called. A journal +** header (JOURNAL_HDR_SZ bytes) is written into the journal file at the +** current location. +** +** The format for the journal header is as follows: +** - 8 bytes: Magic identifying journal format. +** - 4 bytes: Number of records in journal, or -1 no-sync mode is on. +** - 4 bytes: Random number used for page hash. +** - 4 bytes: Initial database page count. +** - 4 bytes: Sector size used by the process that wrote this journal. +** - 4 bytes: Database page size. +** +** Followed by (JOURNAL_HDR_SZ - 28) bytes of unused space. +*/ +static int writeJournalHdr(Pager *pPager){ + int rc = SQLITE_OK; + char *zHeader = pPager->pTmpSpace; + int nHeader = pPager->pageSize; + int nWrite; + + if( nHeader>JOURNAL_HDR_SZ(pPager) ){ + nHeader = JOURNAL_HDR_SZ(pPager); + } + + if( pPager->stmtHdrOff==0 ){ + pPager->stmtHdrOff = pPager->journalOff; + } + + seekJournalHdr(pPager); + pPager->journalHdr = pPager->journalOff; + + memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic)); + + /* + ** Write the nRec Field - the number of page records that follow this + ** journal header. Normally, zero is written to this value at this time. + ** After the records are added to the journal (and the journal synced, + ** if in full-sync mode), the zero is overwritten with the true number + ** of records (see syncJournal()). + ** + ** A faster alternative is to write 0xFFFFFFFF to the nRec field. When + ** reading the journal this value tells SQLite to assume that the + ** rest of the journal file contains valid page records. This assumption + ** is dangerous, as if a failure occured whilst writing to the journal + ** file it may contain some garbage data. There are two scenarios + ** where this risk can be ignored: + ** + ** * When the pager is in no-sync mode. Corruption can follow a + ** power failure in this case anyway. + ** + ** * When the SQLITE_IOCAP_SAFE_APPEND flag is set. This guarantees + ** that garbage data is never appended to the journal file. + */ + assert(pPager->fd->pMethods||pPager->noSync); + if( (pPager->noSync) + || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND) + ){ + put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff); + }else{ + put32bits(&zHeader[sizeof(aJournalMagic)], 0); + } + + /* The random check-hash initialiser */ + sqlite3_randomness(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); + if( pPager->journalHdr==0 ){ + /* The page size */ + put32bits(&zHeader[sizeof(aJournalMagic)+16], pPager->pageSize); + } + + for(nWrite=0; rc==SQLITE_OK&&nWrite<JOURNAL_HDR_SZ(pPager); nWrite+=nHeader){ + IOTRACE(("JHDR %p %lld %d\n", pPager, pPager->journalHdr, nHeader)) + rc = sqlite3OsWrite(pPager->jfd, zHeader, nHeader, pPager->journalOff); + pPager->journalOff += nHeader; + } + + return rc; +} + +/* +** The journal file must be open when this is called. A journal header file +** (JOURNAL_HDR_SZ bytes) is read from the current location in the journal +** file. See comments above function writeJournalHdr() for a description of +** the journal header format. +** +** If the header is read successfully, *nRec is set to the number of +** page records following this header and *dbSize is set to the size of the +** database before the transaction began, in pages. Also, pPager->cksumInit +** is set to the value read from the journal header. SQLITE_OK is returned +** in this case. +** +** If the journal header file appears to be corrupted, SQLITE_DONE is +** returned and *nRec and *dbSize are not set. If JOURNAL_HDR_SZ bytes +** cannot be read from the journal file an error code is returned. +*/ +static int readJournalHdr( + Pager *pPager, + i64 journalSize, + u32 *pNRec, + u32 *pDbSize +){ + int rc; + unsigned char aMagic[8]; /* A buffer to hold the magic header */ + i64 jrnlOff; + int iPageSize; + + seekJournalHdr(pPager); + if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){ + return SQLITE_DONE; + } + jrnlOff = pPager->journalOff; + + rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic), jrnlOff); + if( rc ) return rc; + jrnlOff += sizeof(aMagic); + + if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){ + return SQLITE_DONE; + } + + rc = read32bits(pPager->jfd, jrnlOff, pNRec); + if( rc ) return rc; + + rc = read32bits(pPager->jfd, jrnlOff+4, &pPager->cksumInit); + if( rc ) return rc; + + rc = read32bits(pPager->jfd, jrnlOff+8, pDbSize); + if( rc ) return rc; + + rc = read32bits(pPager->jfd, jrnlOff+16, (u32 *)&iPageSize); + if( rc==SQLITE_OK + && iPageSize>=512 + && iPageSize<=SQLITE_MAX_PAGE_SIZE + && ((iPageSize-1)&iPageSize)==0 + ){ + u16 pagesize = iPageSize; + rc = sqlite3PagerSetPagesize(pPager, &pagesize); + } + if( rc ) return rc; + + /* Update the assumed sector-size to match the value used by + ** the process that created this journal. If this journal was + ** created by a process other than this one, then this routine + ** 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, jrnlOff+12, (u32 *)&pPager->sectorSize); + if( rc ) return rc; + + pPager->journalOff += JOURNAL_HDR_SZ(pPager); + return SQLITE_OK; +} + + +/* +** Write the supplied master journal name into the journal file for pager +** pPager at the current location. The master journal name must be the last +** thing written to a journal file. If the pager is in full-sync mode, the +** journal file descriptor is advanced to the next sector boundary before +** anything is written. The format is: +** +** + 4 bytes: PAGER_MJ_PGNO. +** + N bytes: length of master journal name. +** + 4 bytes: N +** + 4 bytes: Master journal name checksum. +** + 8 bytes: aJournalMagic[]. +** +** 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; + i64 jrnlOff; + i64 jrnlSize; + u32 cksum = 0; + char zBuf[sizeof(aJournalMagic)+2*4]; + + if( !zMaster || pPager->setMaster) return SQLITE_OK; + pPager->setMaster = 1; + + len = strlen(zMaster); + for(i=0; i<len; i++){ + cksum += zMaster[i]; + } + + /* If in full-sync mode, advance to the next disk sector before writing + ** the master journal name. This is in case the previous page written to + ** the journal has already been synced. + */ + if( pPager->fullSync ){ + seekJournalHdr(pPager); + } + jrnlOff = pPager->journalOff; + pPager->journalOff += (len+20); + + rc = write32bits(pPager->jfd, jrnlOff, PAGER_MJ_PGNO(pPager)); + if( rc!=SQLITE_OK ) return rc; + jrnlOff += 4; + + rc = sqlite3OsWrite(pPager->jfd, zMaster, len, jrnlOff); + if( rc!=SQLITE_OK ) return rc; + jrnlOff += len; + + put32bits(zBuf, len); + put32bits(&zBuf[4], cksum); + memcpy(&zBuf[8], aJournalMagic, sizeof(aJournalMagic)); + rc = sqlite3OsWrite(pPager->jfd, zBuf, 8+sizeof(aJournalMagic), jrnlOff); + jrnlOff += 8+sizeof(aJournalMagic); + pPager->needSync = !pPager->noSync; + + /* If the pager is in peristent-journal mode, then the physical + ** journal-file may extend past the end of the master-journal name + ** and 8 bytes of magic data just written to the file. This is + ** dangerous because the code to rollback a hot-journal file + ** will not be able to find the master-journal name to determine + ** whether or not the journal is hot. + ** + ** Easiest thing to do in this scenario is to truncate the journal + ** file to the required size. + */ + if( (rc==SQLITE_OK) + && (rc = sqlite3OsFileSize(pPager->jfd, &jrnlSize))==SQLITE_OK + && jrnlSize>jrnlOff + ){ + rc = sqlite3OsTruncate(pPager->jfd, jrnlOff); + } + return rc; +} + +/* +** Add or remove a page from the list of all pages that are in the +** statement journal. +** +** The Pager keeps a separate list of pages that are currently in +** the statement journal. This helps the sqlite3PagerStmtCommit() +** routine run MUCH faster for the common case where there are many +** pages in memory but only a few are in the statement journal. +*/ +static void page_add_to_stmt_list(PgHdr *pPg){ + Pager *pPager = pPg->pPager; + PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); + assert( MEMDB ); + if( !pHist->inStmt ){ + assert( pHist->pPrevStmt==0 && pHist->pNextStmt==0 ); + if( pPager->pStmt ){ + PGHDR_TO_HIST(pPager->pStmt, pPager)->pPrevStmt = pPg; + } + pHist->pNextStmt = pPager->pStmt; + pPager->pStmt = pPg; + pHist->inStmt = 1; + } +} + +/* +** Find a page in the hash table given its page number. Return +** a pointer to the page or NULL if not found. +*/ +static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){ + PgHdr *p; + if( pPager->aHash==0 ) return 0; + p = pPager->aHash[pgno & (pPager->nHash-1)]; + while( p && p->pgno!=pgno ){ + p = p->pNextHash; + } + return p; +} + +/* +** Clear the in-memory cache. This routine +** sets the state of the pager back to what it was when it was first +** opened. Any outstanding pages are invalidated and subsequent attempts +** to access those pages will likely result in a coredump. +*/ +static void pager_reset(Pager *pPager){ + PgHdr *pPg, *pNext; + if( pPager->errCode ) return; + for(pPg=pPager->pAll; pPg; pPg=pNext){ + IOTRACE(("PGFREE %p %d\n", pPager, pPg->pgno)); + PAGER_INCR(sqlite3_pager_pgfree_count); + pNext = pPg->pNextAll; + lruListRemove(pPg); + sqlite3PageFree(pPg->pData); + sqlite3_free(pPg); + } + assert(pPager->lru.pFirst==0); + assert(pPager->lru.pFirstSynced==0); + assert(pPager->lru.pLast==0); + pPager->pStmt = 0; + pPager->pAll = 0; + pPager->pDirty = 0; + pPager->nHash = 0; + sqlite3_free(pPager->aHash); + pPager->nPage = 0; + pPager->aHash = 0; + pPager->nRef = 0; +} + +/* +** Unlock the database file. +** +** If the pager is currently in error state, discard the contents of +** the cache and reset the Pager structure internal state. If there is +** an open journal-file, then the next time a shared-lock is obtained +** on the pager file (by this or any other process), it will be +** treated as a hot-journal and rolled back. +*/ +static void pager_unlock(Pager *pPager){ + if( !pPager->exclusiveMode ){ + if( !MEMDB ){ + int rc = osUnlock(pPager->fd, NO_LOCK); + if( rc ) pPager->errCode = rc; + pPager->dbSize = -1; + IOTRACE(("UNLOCK %p\n", pPager)) + + /* Always close the journal file when dropping the database lock. + ** Otherwise, another connection with journal_mode=delete might + ** delete the file out from under us. + */ + if( pPager->journalOpen ){ + sqlite3OsClose(pPager->jfd); + pPager->journalOpen = 0; + sqlite3BitvecDestroy(pPager->pInJournal); + pPager->pInJournal = 0; + } + + /* If Pager.errCode is set, the contents of the pager cache cannot be + ** trusted. Now that the pager file is unlocked, the contents of the + ** cache can be discarded and the error code safely cleared. + */ + if( pPager->errCode ){ + if( rc==SQLITE_OK ) pPager->errCode = SQLITE_OK; + pager_reset(pPager); + if( pPager->stmtOpen ){ + sqlite3OsClose(pPager->stfd); + sqlite3BitvecDestroy(pPager->pInStmt); + pPager->pInStmt = 0; + } + pPager->stmtOpen = 0; + pPager->stmtInUse = 0; + pPager->journalOff = 0; + pPager->journalStarted = 0; + pPager->stmtAutoopen = 0; + pPager->origDbSize = 0; + } + } + + if( !MEMDB || pPager->errCode==SQLITE_OK ){ + pPager->state = PAGER_UNLOCK; + pPager->changeCountDone = 0; + } + } +} + +/* +** Execute a rollback if a transaction is active and unlock the +** database file. If the pager has already entered the error state, +** do not attempt the rollback. +*/ +static void pagerUnlockAndRollback(Pager *p){ + /* assert( p->state>=PAGER_RESERVED || p->journalOpen==0 ); */ + if( p->errCode==SQLITE_OK && p->state>=PAGER_RESERVED ){ + sqlite3BeginBenignMalloc(); + sqlite3PagerRollback(p); + sqlite3EndBenignMalloc(); + } + pager_unlock(p); +#if 0 + assert( p->errCode || !p->journalOpen || (p->exclusiveMode&&!p->journalOff) ); + assert( p->errCode || !p->stmtOpen || p->exclusiveMode ); +#endif +} + +/* +** This routine ends a transaction. A transaction is ended by either +** a COMMIT or a ROLLBACK. +** +** When this routine is called, the pager has the journal file open and +** a RESERVED or EXCLUSIVE lock on the database. This routine will release +** the database lock and acquires a SHARED lock in its place if that is +** the appropriate thing to do. Release locks usually is appropriate, +** unless we are in exclusive access mode or unless this is a +** COMMIT AND BEGIN or ROLLBACK AND BEGIN operation. +** +** The journal file is either deleted or truncated. +** +** TODO: Consider keeping the journal file open for temporary databases. +** This might give a performance improvement on windows where opening +** a file is an expensive operation. +*/ +static int pager_end_transaction(Pager *pPager, int hasMaster){ + PgHdr *pPg; + int rc = SQLITE_OK; + int rc2 = SQLITE_OK; + assert( !MEMDB ); + if( pPager->state<PAGER_RESERVED ){ + return SQLITE_OK; + } + sqlite3PagerStmtCommit(pPager); + if( pPager->stmtOpen && !pPager->exclusiveMode ){ + sqlite3OsClose(pPager->stfd); + pPager->stmtOpen = 0; + } + if( pPager->journalOpen ){ + if( pPager->exclusiveMode + || pPager->journalMode==PAGER_JOURNALMODE_PERSIST + ){ + rc = zeroJournalHdr(pPager, hasMaster); + pager_error(pPager, rc); + pPager->journalOff = 0; + pPager->journalStarted = 0; + }else{ + sqlite3OsClose(pPager->jfd); + pPager->journalOpen = 0; + if( rc==SQLITE_OK && !pPager->tempFile ){ + rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); + } + } + sqlite3BitvecDestroy(pPager->pInJournal); + pPager->pInJournal = 0; + for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ + pPg->inJournal = 0; + pPg->dirty = 0; + pPg->needSync = 0; + pPg->alwaysRollback = 0; +#ifdef SQLITE_CHECK_PAGES + pPg->pageHash = pager_pagehash(pPg); +#endif + } + pPager->pDirty = 0; + pPager->dirtyCache = 0; + pPager->nRec = 0; + }else{ + assert( pPager->pInJournal==0 ); + } + + if( !pPager->exclusiveMode ){ + rc2 = osUnlock(pPager->fd, SHARED_LOCK); + pPager->state = PAGER_SHARED; + }else if( pPager->state==PAGER_SYNCED ){ + pPager->state = PAGER_EXCLUSIVE; + } + pPager->origDbSize = 0; + pPager->setMaster = 0; + pPager->needSync = 0; + lruListSetFirstSynced(pPager); + pPager->dbSize = -1; + pPager->dbModified = 0; + + return (rc==SQLITE_OK?rc2:rc); +} + +/* +** Compute and return a checksum for the page of data. +** +** This is not a real checksum. It is really just the sum of the +** random initial value and the page number. We experimented with +** a checksum of the entire data, but that was found to be too slow. +** +** Note that the page number is stored at the beginning of data and +** the checksum is stored at the end. This is important. If journal +** corruption occurs due to a power failure, the most likely scenario +** is that one end or the other of the record will be changed. It is +** much less likely that the two ends of the journal record will be +** correct and the middle be corrupt. Thus, this "checksum" scheme, +** though fast and simple, catches the mostly likely kind of corruption. +** +** FIX ME: Consider adding every 200th (or so) byte of the data to the +** checksum. That way if a single page spans 3 or more disk sectors and +** 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, const u8 *aData){ + u32 cksum = pPager->cksumInit; + int i = pPager->pageSize-200; + while( i>0 ){ + cksum += aData[i]; + i -= 200; + } + return cksum; +} + +/* Forward declaration */ +static void makeClean(PgHdr*); + +/* +** Read a single page from the journal file opened on file descriptor +** jfd. Playback this one page. +** +** If useCksum==0 it means this journal does not use checksums. Checksums +** are not used in statement journals because statement journals do not +** need to survive power failures. +*/ +static int pager_playback_one_page( + Pager *pPager, + sqlite3_file *jfd, + i64 offset, + int useCksum +){ + int rc; + PgHdr *pPg; /* An existing page in the cache */ + Pgno pgno; /* The page number of a page in journal */ + u32 cksum; /* Checksum used for sanity checking */ + u8 *aData = (u8 *)pPager->pTmpSpace; /* Temp storage for a page */ + + /* 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( aData ); + + rc = read32bits(jfd, offset, &pgno); + if( rc!=SQLITE_OK ) return rc; + rc = sqlite3OsRead(jfd, aData, pPager->pageSize, offset+4); + if( rc!=SQLITE_OK ) return rc; + pPager->journalOff += pPager->pageSize + 4; + + /* Sanity checking on the page. This is more important that I originally + ** thought. If a power failure occurs while the journal is being written, + ** it could cause invalid data to be written into the journal. We need to + ** detect this invalid data (with high probability) and ignore it. + */ + if( pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){ + return SQLITE_DONE; + } + if( pgno>(unsigned)pPager->dbSize ){ + return SQLITE_OK; + } + if( useCksum ){ + rc = read32bits(jfd, offset+pPager->pageSize+4, &cksum); + if( rc ) return rc; + pPager->journalOff += 4; + if( pager_cksum(pPager, aData)!=cksum ){ + return SQLITE_DONE; + } + } + + assert( pPager->state==PAGER_RESERVED || pPager->state>=PAGER_EXCLUSIVE ); + + /* If the pager is in RESERVED state, then there must be a copy of this + ** page in the pager cache. In this case just update the pager cache, + ** not the database file. The page is left marked dirty in this case. + ** + ** An exception to the above rule: If the database is in no-sync mode + ** and a page is moved during an incremental vacuum then the page may + ** not be in the pager cache. Later: if a malloc() or IO error occurs + ** during a Movepage() call, then the page may not be in the cache + ** either. So the condition described in the above paragraph is not + ** assert()able. + ** + ** If in EXCLUSIVE state, then we update the pager cache if it exists + ** and the main file. The page is then marked not dirty. + ** + ** Ticket #1171: The statement journal might contain page content that is + ** different from the page content at the start of the transaction. + ** This occurs when a page is changed prior to the start of a statement + ** then changed again within the statement. When rolling back such a + ** statement we must not write to the original database unless we know + ** for certain that original page contents are synced into the main rollback + ** journal. Otherwise, a power loss might leave modified data in the + ** database file without an entry in the rollback journal that can + ** restore the database to its original form. Two conditions must be + ** met before writing to the database files. (1) the database must be + ** locked. (2) we know that the original page content is fully synced + ** in the main journal either because the page is not in cache or else + ** the page is marked as needSync==0. + ** + ** 2008-04-14: When attempting to vacuum a corrupt database file, it + ** is possible to fail a statement on a database that does not yet exist. + ** Do not attempt to write if database file has never been opened. + */ + pPg = pager_lookup(pPager, pgno); + PAGERTRACE4("PLAYBACK %d page %d hash(%08x)\n", + PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, aData)); + if( pPager->state>=PAGER_EXCLUSIVE && (pPg==0 || pPg->needSync==0) + && pPager->fd->pMethods ){ + i64 offset = (pgno-1)*(i64)pPager->pageSize; + rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize, offset); + if( pPg ){ + makeClean(pPg); + } + } + if( pPg ){ + /* No page should ever be explicitly rolled back that is in use, except + ** for page 1 which is held in use in order to keep the lock on the + ** database active. However such a page may be rolled back as a result + ** of an internal error resulting in an automatic call to + ** sqlite3PagerRollback(). + */ + void *pData; + /* assert( pPg->nRef==0 || pPg->pgno==1 ); */ + pData = PGHDR_TO_DATA(pPg); + memcpy(pData, aData, pPager->pageSize); + if( pPager->xReiniter ){ + pPager->xReiniter(pPg, pPager->pageSize); + } +#ifdef SQLITE_CHECK_PAGES + pPg->pageHash = pager_pagehash(pPg); +#endif + /* If this was page 1, then restore the value of Pager.dbFileVers. + ** Do this before any decoding. */ + if( pgno==1 ){ + memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers)); + } + + /* Decode the page just read from disk */ + CODEC1(pPager, pData, pPg->pgno, 3); + } + return rc; +} + +/* +** Parameter zMaster is the name of a master journal file. A single journal +** file that referred to the master journal file has just been rolled back. +** This routine checks if it is possible to delete the master journal file, +** and does so if it is. +** +** Argument zMaster may point to Pager.pTmpSpace. So that buffer is not +** available for use within this function. +** +** +** The master journal file contains the names of all child journals. +** To tell if a master journal can be deleted, check to each of the +** children. If all children are either missing or do not refer to +** a different master journal, then this master journal can be deleted. +*/ +static int pager_delmaster(Pager *pPager, const char *zMaster){ + sqlite3_vfs *pVfs = pPager->pVfs; + int rc; + int master_open = 0; + sqlite3_file *pMaster; + sqlite3_file *pJournal; + 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. + */ + pMaster = (sqlite3_file *)sqlite3Malloc(pVfs->szOsFile * 2); + pJournal = (sqlite3_file *)(((u8 *)pMaster) + pVfs->szOsFile); + if( !pMaster ){ + rc = SQLITE_NOMEM; + }else{ + int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MASTER_JOURNAL); + rc = sqlite3OsOpen(pVfs, zMaster, pMaster, flags, 0); + } + if( rc!=SQLITE_OK ) goto delmaster_out; + master_open = 1; + + rc = sqlite3OsFileSize(pMaster, &nMasterJournal); + if( rc!=SQLITE_OK ) goto delmaster_out; + + if( nMasterJournal>0 ){ + char *zJournal; + char *zMasterPtr = 0; + int nMasterPtr = pPager->pVfs->mxPathname+1; + + /* Load the entire master journal file into space obtained from + ** sqlite3_malloc() and pointed to by zMasterJournal. + */ + zMasterJournal = (char *)sqlite3Malloc(nMasterJournal + nMasterPtr); + if( !zMasterJournal ){ + rc = SQLITE_NOMEM; + goto delmaster_out; + } + zMasterPtr = &zMasterJournal[nMasterJournal]; + rc = sqlite3OsRead(pMaster, zMasterJournal, nMasterJournal, 0); + if( rc!=SQLITE_OK ) goto delmaster_out; + + zJournal = zMasterJournal; + while( (zJournal-zMasterJournal)<nMasterJournal ){ + int exists; + rc = sqlite3OsAccess(pVfs, zJournal, SQLITE_ACCESS_EXISTS, &exists); + if( rc!=SQLITE_OK ){ + goto delmaster_out; + } + if( exists ){ + /* One of the journals pointed to by the master journal exists. + ** Open it and check if it points at the master journal. If + ** so, return without deleting the master journal file. + */ + int c; + int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL); + rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0); + if( rc!=SQLITE_OK ){ + goto delmaster_out; + } + + rc = readMasterJournal(pJournal, zMasterPtr, nMasterPtr); + sqlite3OsClose(pJournal); + if( rc!=SQLITE_OK ){ + goto delmaster_out; + } + + c = zMasterPtr[0]!=0 && strcmp(zMasterPtr, zMaster)==0; + if( c ){ + /* We have a match. Do not delete the master journal file. */ + goto delmaster_out; + } + } + zJournal += (strlen(zJournal)+1); + } + } + + rc = sqlite3OsDelete(pVfs, zMaster, 0); + +delmaster_out: + if( zMasterJournal ){ + sqlite3_free(zMasterJournal); + } + if( master_open ){ + sqlite3OsClose(pMaster); + } + sqlite3_free(pMaster); + return rc; +} + + +static void pager_truncate_cache(Pager *pPager); + +/* +** Truncate the main file of the given pager to the number of pages +** indicated. Also truncate the cached representation of the file. +** +** Might might be the case that the file on disk is smaller than nPage. +** This can happen, for example, if we are in the middle of a transaction +** which has extended the file size and the new pages are still all held +** in cache, then an INSERT or UPDATE does a statement rollback. Some +** operating system implementations can get confused if you try to +** truncate a file to some size that is larger than it currently is, +** so detect this case and write a single zero byte to the end of the new +** file instead. +*/ +static int pager_truncate(Pager *pPager, int nPage){ + int rc = SQLITE_OK; + if( pPager->state>=PAGER_EXCLUSIVE && pPager->fd->pMethods ){ + i64 currentSize, newSize; + rc = sqlite3OsFileSize(pPager->fd, ¤tSize); + newSize = pPager->pageSize*(i64)nPage; + if( rc==SQLITE_OK && currentSize!=newSize ){ + if( currentSize>newSize ){ + rc = sqlite3OsTruncate(pPager->fd, newSize); + }else{ + rc = sqlite3OsWrite(pPager->fd, "", 1, newSize-1); + } + } + } + if( rc==SQLITE_OK ){ + pPager->dbSize = nPage; + pager_truncate_cache(pPager); + } + return rc; +} + +/* +** Set the sectorSize for the given pager. +** +** The sector size is at least as big as the sector size reported +** by sqlite3OsSectorSize(). The minimum sector size is 512. +*/ +static void setSectorSize(Pager *pPager){ + assert(pPager->fd->pMethods||pPager->tempFile); + if( !pPager->tempFile ){ + /* Sector size doesn't matter for temporary files. Also, the file + ** may not have been opened yet, in whcih case the OsSectorSize() + ** call will segfault. + */ + pPager->sectorSize = sqlite3OsSectorSize(pPager->fd); + } + if( pPager->sectorSize<512 ){ + pPager->sectorSize = 512; + } +} + +/* +** Playback the journal and thus restore the database file to +** the state it was in before we started making changes. +** +** The journal file format is as follows: +** +** (1) 8 byte prefix. A copy of aJournalMagic[]. +** (2) 4 byte big-endian integer which is the number of valid page records +** in the journal. If this value is 0xffffffff, then compute the +** number of page records from the journal size. +** (3) 4 byte big-endian integer which is the initial value for the +** sanity checksum. +** (4) 4 byte integer which is the number of pages to truncate the +** database to during a rollback. +** (5) 4 byte big-endian integer which is the sector size. The header +** is this many bytes in size. +** (6) 4 byte big-endian integer which is the page case. +** (7) 4 byte integer which is the number of bytes in the master journal +** name. The value may be zero (indicate that there is no master +** journal.) +** (8) N bytes of the master journal name. The name will be nul-terminated +** and might be shorter than the value read from (5). If the first byte +** of the name is \000 then there is no master journal. The master +** journal name is stored in UTF-8. +** (9) Zero or more pages instances, each as follows: +** + 4 byte page number. +** + pPager->pageSize bytes of data. +** + 4 byte checksum +** +** When we speak of the journal header, we mean the first 8 items above. +** Each entry in the journal is an instance of the 9th item. +** +** Call the value from the second bullet "nRec". nRec is the number of +** valid page entries in the journal. In most cases, you can compute the +** value of nRec from the size of the journal file. But if a power +** failure occurred while the journal was being written, it could be the +** case that the size of the journal file had already been increased but +** the extra entries had not yet made it safely to disk. In such a case, +** the value of nRec computed from the file size would be too large. For +** that reason, we always use the nRec value in the header. +** +** If the nRec value is 0xffffffff it means that nRec should be computed +** from the file size. This value is used when the user selects the +** no-sync option for the journal. A power failure could lead to corruption +** in this case. But for things like temporary table (which will be +** deleted when the power is restored) we don't care. +** +** If the file opened as the journal file is not a well-formed +** journal file then all pages up to the first corrupted page are rolled +** back (or no pages if the journal header is corrupted). The journal file +** is then deleted and SQLITE_OK returned, just as if no corruption had +** been encountered. +** +** If an I/O or malloc() error occurs, the journal-file is not deleted +** and an error code is returned. +*/ +static int pager_playback(Pager *pPager, int isHot){ + sqlite3_vfs *pVfs = pPager->pVfs; + i64 szJ; /* Size of the journal file in bytes */ + u32 nRec; /* Number of Records in the journal */ + u32 u; /* Unsigned loop counter */ + Pgno mxPg = 0; /* Size of the original file in pages */ + int rc; /* Result code of a subroutine */ + int res = 1; /* Value returned by sqlite3OsAccess() */ + char *zMaster = 0; /* Name of master journal file if any */ + + /* Figure out how many records are in the journal. Abort early if + ** the journal is empty. + */ + assert( pPager->journalOpen ); + rc = sqlite3OsFileSize(pPager->jfd, &szJ); + if( rc!=SQLITE_OK || szJ==0 ){ + goto end_playback; + } + + /* Read the master journal name from the journal, if it is present. + ** If a master journal file name is specified, but the file is not + ** present on disk, then the journal is not hot and does not need to be + ** played back. + */ + zMaster = pPager->pTmpSpace; + rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1); + if( rc==SQLITE_OK && zMaster[0] ){ + rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res); + } + zMaster = 0; + if( rc!=SQLITE_OK || !res ){ + goto end_playback; + } + pPager->journalOff = 0; + + /* This loop terminates either when the readJournalHdr() call returns + ** SQLITE_DONE or an IO error occurs. */ + while( 1 ){ + + /* Read the next journal header from the journal file. If there are + ** not enough bytes left in the journal file for a complete header, or + ** it is corrupted, then a process must of failed while writing it. + ** This indicates nothing more needs to be rolled back. + */ + rc = readJournalHdr(pPager, szJ, &nRec, &mxPg); + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_DONE ){ + rc = SQLITE_OK; + } + goto end_playback; + } + + /* If nRec is 0xffffffff, then this journal was created by a process + ** working in no-sync mode. This means that the rest of the journal + ** file consists of pages, there are no more journal headers. Compute + ** the value of nRec based on this assumption. + */ + if( nRec==0xffffffff ){ + assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ); + nRec = (szJ - JOURNAL_HDR_SZ(pPager))/JOURNAL_PG_SZ(pPager); + } + + /* If nRec is 0 and this rollback is of a transaction created by this + ** process and if this is the final header in the journal, then it means + ** that this part of the journal was being filled but has not yet been + ** synced to disk. Compute the number of pages based on the remaining + ** size of the file. + ** + ** The third term of the test was added to fix ticket #2565. + */ + if( nRec==0 && !isHot && + pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff ){ + nRec = (szJ - pPager->journalOff) / JOURNAL_PG_SZ(pPager); + } + + /* If this is the first header read from the journal, truncate the + ** database file back to its original size. + */ + if( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){ + rc = pager_truncate(pPager, mxPg); + if( rc!=SQLITE_OK ){ + goto end_playback; + } + } + + /* Copy original pages out of the journal and back into the database file. + */ + for(u=0; u<nRec; u++){ + rc = pager_playback_one_page(pPager, pPager->jfd, pPager->journalOff, 1); + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_DONE ){ + rc = SQLITE_OK; + pPager->journalOff = szJ; + break; + }else{ + goto end_playback; + } + } + } + } + /*NOTREACHED*/ + assert( 0 ); + +end_playback: + if( rc==SQLITE_OK ){ + zMaster = pPager->pTmpSpace; + rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1); + } + if( rc==SQLITE_OK ){ + rc = pager_end_transaction(pPager, zMaster[0]!='\0'); + } + if( rc==SQLITE_OK && zMaster[0] ){ + /* If there was a master journal and this routine will return success, + ** see if it is possible to delete the master journal. + */ + rc = pager_delmaster(pPager, zMaster); + } + + /* The Pager.sectorSize variable may have been updated while rolling + ** back a journal created by a process with a different sector size + ** value. Reset it to the correct value for this process. + */ + setSectorSize(pPager); + return rc; +} + +/* +** Playback the statement journal. +** +** This is similar to playing back the transaction journal but with +** a few extra twists. +** +** (1) The number of pages in the database file at the start of +** the statement is stored in pPager->stmtSize, not in the +** journal file itself. +** +** (2) In addition to playing back the statement journal, also +** playback all pages of the transaction journal beginning +** at offset pPager->stmtJSize. +*/ +static int pager_stmt_playback(Pager *pPager){ + i64 szJ; /* Size of the full journal */ + i64 hdrOff; + int nRec; /* Number of Records */ + int i; /* Loop counter */ + int rc; + + szJ = pPager->journalOff; + + /* Set hdrOff to be the offset just after the end of the last journal + ** page written before the first journal-header for this statement + ** transaction was written, or the end of the file if no journal + ** header was written. + */ + hdrOff = pPager->stmtHdrOff; + assert( pPager->fullSync || !hdrOff ); + if( !hdrOff ){ + hdrOff = szJ; + } + + /* Truncate the database back to its original size. + */ + rc = pager_truncate(pPager, pPager->stmtSize); + assert( pPager->state>=PAGER_SHARED ); + + /* Figure out how many records are in the statement journal. + */ + assert( pPager->stmtInUse && pPager->journalOpen ); + nRec = pPager->stmtNRec; + + /* Copy original pages out of the statement journal and back into the + ** database file. Note that the statement journal omits checksums from + ** each record since power-failure recovery is not important to statement + ** journals. + */ + for(i=0; i<nRec; i++){ + i64 offset = i*(4+pPager->pageSize); + rc = pager_playback_one_page(pPager, pPager->stfd, offset, 0); + assert( rc!=SQLITE_DONE ); + if( rc!=SQLITE_OK ) goto end_stmt_playback; + } + + /* Now roll some pages back from the transaction journal. Pager.stmtJSize + ** was the size of the journal file when this statement was started, so + ** everything after that needs to be rolled back, either into the + ** database, the memory cache, or both. + ** + ** If it is not zero, then Pager.stmtHdrOff is the offset to the start + ** of the first journal header written during this statement transaction. + */ + pPager->journalOff = pPager->stmtJSize; + pPager->cksumInit = pPager->stmtCksum; + while( pPager->journalOff < hdrOff ){ + rc = pager_playback_one_page(pPager, pPager->jfd, pPager->journalOff, 1); + assert( rc!=SQLITE_DONE ); + if( rc!=SQLITE_OK ) goto end_stmt_playback; + } + + while( pPager->journalOff < szJ ){ + u32 nJRec; /* Number of Journal Records */ + u32 dummy; + rc = readJournalHdr(pPager, szJ, &nJRec, &dummy); + if( rc!=SQLITE_OK ){ + assert( rc!=SQLITE_DONE ); + goto end_stmt_playback; + } + if( nJRec==0 ){ + nJRec = (szJ - pPager->journalOff) / (pPager->pageSize+8); + } + for(i=nJRec-1; i>=0 && pPager->journalOff < szJ; i--){ + rc = pager_playback_one_page(pPager, pPager->jfd, pPager->journalOff, 1); + assert( rc!=SQLITE_DONE ); + if( rc!=SQLITE_OK ) goto end_stmt_playback; + } + } + + pPager->journalOff = szJ; + +end_stmt_playback: + if( rc==SQLITE_OK) { + pPager->journalOff = szJ; + /* pager_reload_cache(pPager); */ + } + return rc; +} + +/* +** Change the maximum number of in-memory pages that are allowed. +*/ +void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){ + if( mxPage>10 ){ + pPager->mxPage = mxPage; + }else{ + pPager->mxPage = 10; + } +} + +/* +** Adjust the robustness of the database to damage due to OS crashes +** or power failures by changing the number of syncs()s when writing +** the rollback journal. There are three levels: +** +** OFF sqlite3OsSync() is never called. This is the default +** for temporary and transient files. +** +** NORMAL The journal is synced once before writes begin on the +** database. This is normally adequate protection, but +** it is theoretically possible, though very unlikely, +** that an inopertune power failure could leave the journal +** in a state which would cause damage to the database +** when it is rolled back. +** +** FULL The journal is synced twice before writes begin on the +** database (with some additional information - the nRec field +** of the journal header - being written in between the two +** syncs). If we assume that writing a +** single disk sector is atomic, then this mode provides +** assurance that the journal will not be corrupted to the +** point of causing damage to the database during rollback. +** +** Numeric values associated with these states are OFF==1, NORMAL=2, +** and FULL=3. +*/ +#ifndef SQLITE_OMIT_PAGER_PRAGMAS +void sqlite3PagerSetSafetyLevel(Pager *pPager, int level, int full_fsync){ + pPager->noSync = level==1 || pPager->tempFile; + pPager->fullSync = level==3 && !pPager->tempFile; + pPager->sync_flags = (full_fsync?SQLITE_SYNC_FULL:SQLITE_SYNC_NORMAL); + if( pPager->noSync ) pPager->needSync = 0; +} +#endif + +/* +** The following global variable is incremented whenever the library +** attempts to open a temporary file. This information is used for +** testing and analysis only. +*/ +#ifdef SQLITE_TEST +int sqlite3_opentemp_count = 0; +#endif + +/* +** Open a temporary file. +** +** Write the file descriptor into *fd. Return SQLITE_OK on success or some +** other error code if we fail. The OS will automatically delete the temporary +** file when it is closed. +*/ +static int sqlite3PagerOpentemp( + Pager *pPager, /* The pager object */ + sqlite3_file *pFile, /* Write the file descriptor here */ + int vfsFlags /* Flags passed through to the VFS */ +){ + int rc; + +#ifdef SQLITE_TEST + sqlite3_opentemp_count++; /* Used for testing and analysis only */ +#endif + + vfsFlags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | + SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE; + rc = sqlite3OsOpen(pPager->pVfs, 0, pFile, vfsFlags, 0); + assert( rc!=SQLITE_OK || pFile->pMethods ); + return rc; +} + +/* +** Create a new page cache and put a pointer to the page cache in *ppPager. +** The file to be cached need not exist. The file is not locked until +** the first call to sqlite3PagerGet() and is only held open until the +** last page is released using sqlite3PagerUnref(). +** +** If zFilename is NULL then a randomly-named temporary file is created +** and used as the file to be cached. The file will be deleted +** automatically when it is closed. +** +** If zFilename is ":memory:" then all information is held in cache. +** It is never written to disk. This can be used to implement an +** in-memory database. +*/ +int sqlite3PagerOpen( + sqlite3_vfs *pVfs, /* The virtual file system to use */ + Pager **ppPager, /* Return the Pager structure here */ + const char *zFilename, /* Name of the database file to open */ + int nExtra, /* Extra bytes append to each in-memory page */ + int flags, /* flags controlling this file */ + int vfsFlags /* flags passed through to sqlite3_vfs.xOpen() */ +){ + u8 *pPtr; + Pager *pPager = 0; + int rc = SQLITE_OK; + int i; + int tempFile = 0; + int memDb = 0; + int readOnly = 0; + int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; + int noReadlock = (flags & PAGER_NO_READLOCK)!=0; + int journalFileSize = sqlite3JournalSize(pVfs); + int szPageDflt = SQLITE_DEFAULT_PAGE_SIZE; + char *zPathname = 0; + int nPathname = 0; + + /* The default return is a NULL pointer */ + *ppPager = 0; + + /* Compute and store the full pathname in an allocated buffer pointed + ** to by zPathname, length nPathname. Or, if this is a temporary file, + ** leave both nPathname and zPathname set to 0. + */ + if( zFilename && zFilename[0] ){ + nPathname = pVfs->mxPathname+1; + zPathname = sqlite3Malloc(nPathname*2); + if( zPathname==0 ){ + return SQLITE_NOMEM; + } +#ifndef SQLITE_OMIT_MEMORYDB + if( strcmp(zFilename,":memory:")==0 ){ + memDb = 1; + zPathname[0] = 0; + }else +#endif + { + rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname); + } + if( rc!=SQLITE_OK ){ + sqlite3_free(zPathname); + return rc; + } + nPathname = strlen(zPathname); + } + + /* Allocate memory for the pager structure */ + pPager = sqlite3MallocZero( + sizeof(*pPager) + /* Pager structure */ + journalFileSize + /* The journal file structure */ + pVfs->szOsFile * 3 + /* The main db and two journal files */ + 3*nPathname + 40 /* zFilename, zDirectory, zJournal */ + ); + if( !pPager ){ + sqlite3_free(zPathname); + return SQLITE_NOMEM; + } + pPtr = (u8 *)&pPager[1]; + pPager->vfsFlags = vfsFlags; + pPager->fd = (sqlite3_file*)&pPtr[pVfs->szOsFile*0]; + pPager->stfd = (sqlite3_file*)&pPtr[pVfs->szOsFile*1]; + pPager->jfd = (sqlite3_file*)&pPtr[pVfs->szOsFile*2]; + pPager->zFilename = (char*)&pPtr[pVfs->szOsFile*2+journalFileSize]; + pPager->zDirectory = &pPager->zFilename[nPathname+1]; + pPager->zJournal = &pPager->zDirectory[nPathname+1]; + pPager->pVfs = pVfs; + if( zPathname ){ + memcpy(pPager->zFilename, zPathname, nPathname+1); + sqlite3_free(zPathname); + } + + /* Open the pager file. + */ + if( zFilename && zFilename[0] && !memDb ){ + if( nPathname>(pVfs->mxPathname - sizeof("-journal")) ){ + rc = SQLITE_CANTOPEN; + }else{ + int fout = 0; + rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, + pPager->vfsFlags, &fout); + readOnly = (fout&SQLITE_OPEN_READONLY); + + /* If the file was successfully opened for read/write access, + ** choose a default page size in case we have to create the + ** database file. The default page size is the maximum of: + ** + ** + SQLITE_DEFAULT_PAGE_SIZE, + ** + The value returned by sqlite3OsSectorSize() + ** + The largest page size that can be written atomically. + */ + if( rc==SQLITE_OK && !readOnly ){ + int iSectorSize = sqlite3OsSectorSize(pPager->fd); + if( szPageDflt<iSectorSize ){ + szPageDflt = iSectorSize; + } +#ifdef SQLITE_ENABLE_ATOMIC_WRITE + { + int iDc = sqlite3OsDeviceCharacteristics(pPager->fd); + int ii; + assert(SQLITE_IOCAP_ATOMIC512==(512>>8)); + assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8)); + assert(SQLITE_MAX_DEFAULT_PAGE_SIZE<=65536); + for(ii=szPageDflt; ii<=SQLITE_MAX_DEFAULT_PAGE_SIZE; ii=ii*2){ + if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ) szPageDflt = ii; + } + } +#endif + if( szPageDflt>SQLITE_MAX_DEFAULT_PAGE_SIZE ){ + szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE; + } + } + } + }else if( !memDb ){ + /* If a temporary file is requested, it is not opened immediately. + ** In this case we accept the default page size and delay actually + ** opening the file until the first call to OsWrite(). + */ + tempFile = 1; + pPager->state = PAGER_EXCLUSIVE; + } + + if( pPager && rc==SQLITE_OK ){ + pPager->pTmpSpace = sqlite3PageMalloc(szPageDflt); + } + + /* If an error occured in either of the blocks above. + ** 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 || !pPager->pTmpSpace ){ + sqlite3OsClose(pPager->fd); + sqlite3_free(pPager); + return ((rc==SQLITE_OK)?SQLITE_NOMEM:rc); + } + + PAGERTRACE3("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename); + IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename)) + + /* Fill in Pager.zDirectory[] */ + memcpy(pPager->zDirectory, pPager->zFilename, nPathname+1); + for(i=strlen(pPager->zDirectory); i>0 && pPager->zDirectory[i-1]!='/'; i--){} + if( i>0 ) pPager->zDirectory[i-1] = 0; + + /* Fill in Pager.zJournal[] */ + if( zPathname ){ + memcpy(pPager->zJournal, pPager->zFilename, nPathname); + memcpy(&pPager->zJournal[nPathname], "-journal", 9); + }else{ + pPager->zJournal = 0; + } + + /* pPager->journalOpen = 0; */ + pPager->useJournal = useJournal && !memDb; + pPager->noReadlock = noReadlock && readOnly; + /* pPager->stmtOpen = 0; */ + /* pPager->stmtInUse = 0; */ + /* pPager->nRef = 0; */ + pPager->dbSize = memDb-1; + pPager->pageSize = szPageDflt; + /* pPager->stmtSize = 0; */ + /* pPager->stmtJSize = 0; */ + /* pPager->nPage = 0; */ + pPager->mxPage = 100; + pPager->mxPgno = SQLITE_MAX_PAGE_COUNT; + /* pPager->state = PAGER_UNLOCK; */ + assert( pPager->state == (tempFile ? PAGER_EXCLUSIVE : PAGER_UNLOCK) ); + /* pPager->errMask = 0; */ + pPager->tempFile = tempFile; + assert( tempFile==PAGER_LOCKINGMODE_NORMAL + || tempFile==PAGER_LOCKINGMODE_EXCLUSIVE ); + assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 ); + pPager->exclusiveMode = tempFile; + pPager->memDb = memDb; + pPager->readOnly = readOnly; + /* pPager->needSync = 0; */ + pPager->noSync = pPager->tempFile || !useJournal; + pPager->fullSync = (pPager->noSync?0:1); + pPager->sync_flags = SQLITE_SYNC_NORMAL; + /* pPager->pFirst = 0; */ + /* pPager->pFirstSynced = 0; */ + /* pPager->pLast = 0; */ + pPager->nExtra = FORCE_ALIGNMENT(nExtra); + pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT; + assert(pPager->fd->pMethods||memDb||tempFile); + if( !memDb ){ + setSectorSize(pPager); + } + /* pPager->pBusyHandler = 0; */ + /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */ + *ppPager = pPager; +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + pPager->iInUseMM = 0; + pPager->iInUseDB = 0; + if( !memDb ){ +#ifndef SQLITE_MUTEX_NOOP + sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM2); +#endif + sqlite3_mutex_enter(mutex); + pPager->pNext = sqlite3PagerList; + if( sqlite3PagerList ){ + assert( sqlite3PagerList->pPrev==0 ); + sqlite3PagerList->pPrev = pPager; + } + pPager->pPrev = 0; + sqlite3PagerList = pPager; + sqlite3_mutex_leave(mutex); + } +#endif + return SQLITE_OK; +} + +/* +** Set the busy handler function. +*/ +void sqlite3PagerSetBusyhandler(Pager *pPager, BusyHandler *pBusyHandler){ + pPager->pBusyHandler = pBusyHandler; +} + +/* +** Set the destructor for this pager. If not NULL, the destructor is called +** when the reference count on each page reaches zero. The destructor can +** be used to clean up information in the extra segment appended to each page. +** +** The destructor is not called as a result sqlite3PagerClose(). +** Destructors are only called by sqlite3PagerUnref(). +*/ +void sqlite3PagerSetDestructor(Pager *pPager, void (*xDesc)(DbPage*,int)){ + pPager->xDestructor = xDesc; +} + +/* +** Set the reinitializer for this pager. If not NULL, the reinitializer +** is called when the content of a page in cache is restored to its original +** value as a result of a rollback. The callback gives higher-level code +** an opportunity to restore the EXTRA section to agree with the restored +** page data. +*/ +void sqlite3PagerSetReiniter(Pager *pPager, void (*xReinit)(DbPage*,int)){ + pPager->xReiniter = xReinit; +} + +/* +** Set the page size to *pPageSize. If the suggest new page size is +** inappropriate, then an alternative page size is set to that +** value before returning. +*/ +int sqlite3PagerSetPagesize(Pager *pPager, u16 *pPageSize){ + int rc = SQLITE_OK; + u16 pageSize = *pPageSize; + assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) ); + if( pageSize && pageSize!=pPager->pageSize + && !pPager->memDb && pPager->nRef==0 + ){ + char *pNew = (char *)sqlite3PageMalloc(pageSize); + if( !pNew ){ + rc = SQLITE_NOMEM; + }else{ + pagerEnter(pPager); + pager_reset(pPager); + pPager->pageSize = pageSize; + setSectorSize(pPager); + sqlite3PageFree(pPager->pTmpSpace); + pPager->pTmpSpace = pNew; + pagerLeave(pPager); + } + } + *pPageSize = pPager->pageSize; + return rc; +} + +/* +** Return a pointer to the "temporary page" buffer held internally +** by the pager. This is a buffer that is big enough to hold the +** entire content of a database page. This buffer is used internally +** during rollback and will be overwritten whenever a rollback +** occurs. But other modules are free to use it too, as long as +** no rollbacks are happening. +*/ +void *sqlite3PagerTempSpace(Pager *pPager){ + return pPager->pTmpSpace; +} + +/* +** Attempt to set the maximum database page count if mxPage is positive. +** Make no changes if mxPage is zero or negative. And never reduce the +** maximum page count below the current size of the database. +** +** Regardless of mxPage, return the current maximum page count. +*/ +int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){ + if( mxPage>0 ){ + pPager->mxPgno = mxPage; + } + sqlite3PagerPagecount(pPager, 0); + return pPager->mxPgno; +} + +/* +** 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 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 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. 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). +*/ +int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned char *pDest){ + int rc = SQLITE_OK; + memset(pDest, 0, N); + assert(MEMDB||pPager->fd->pMethods||pPager->tempFile); + if( pPager->fd->pMethods ){ + IOTRACE(("DBHDR %p 0 %d\n", pPager, N)) + rc = sqlite3OsRead(pPager->fd, pDest, N, 0); + if( rc==SQLITE_IOERR_SHORT_READ ){ + rc = SQLITE_OK; + } + } + return rc; +} + +/* +** Return the total number of pages in the disk file associated with +** pPager. +** +** If the PENDING_BYTE lies on the page directly after the end of the +** file, then consider this page part of the file too. For example, if +** PENDING_BYTE is byte 4096 (the first byte of page 5) and the size of the +** file is 4096 bytes, 5 is returned instead of 4. +*/ +int sqlite3PagerPagecount(Pager *pPager, int *pnPage){ + i64 n = 0; + int rc; + assert( pPager!=0 ); + if( pPager->errCode ){ + return pPager->errCode; + } + if( pPager->dbSize>=0 ){ + n = pPager->dbSize; + } else { + assert(pPager->fd->pMethods||pPager->tempFile); + if( (pPager->fd->pMethods) + && (rc = sqlite3OsFileSize(pPager->fd, &n))!=SQLITE_OK ){ + pPager->nRef++; + pager_error(pPager, rc); + pPager->nRef--; + return rc; + } + if( n>0 && n<pPager->pageSize ){ + n = 1; + }else{ + n /= pPager->pageSize; + } + if( pPager->state!=PAGER_UNLOCK ){ + pPager->dbSize = n; + } + } + if( n==(PENDING_BYTE/pPager->pageSize) ){ + n++; + } + if( n>pPager->mxPgno ){ + pPager->mxPgno = n; + } + if( pnPage ){ + *pnPage = n; + } + return SQLITE_OK; +} + + +#ifndef SQLITE_OMIT_MEMORYDB +/* +** Clear a PgHistory block +*/ +static void clearHistory(PgHistory *pHist){ + sqlite3PageFree(pHist->pOrig); + sqlite3PageFree(pHist->pStmt); + pHist->pOrig = 0; + pHist->pStmt = 0; +} +#else +#define clearHistory(x) +#endif + +/* +** Forward declaration +*/ +static int syncJournal(Pager*); + +/* +** Unlink pPg from its hash chain. Also set the page number to 0 to indicate +** that the page is not part of any hash chain. This is required because the +** sqlite3PagerMovepage() routine can leave a page in the +** pNextFree/pPrevFree list that is not a part of any hash-chain. +*/ +static void unlinkHashChain(Pager *pPager, PgHdr *pPg){ + if( pPg->pgno==0 ){ + assert( pPg->pNextHash==0 && pPg->pPrevHash==0 ); + return; + } + if( pPg->pNextHash ){ + pPg->pNextHash->pPrevHash = pPg->pPrevHash; + } + if( pPg->pPrevHash ){ + assert( pPager->aHash[pPg->pgno & (pPager->nHash-1)]!=pPg ); + pPg->pPrevHash->pNextHash = pPg->pNextHash; + }else{ + int h = pPg->pgno & (pPager->nHash-1); + pPager->aHash[h] = pPg->pNextHash; + } + if( MEMDB ){ + clearHistory(PGHDR_TO_HIST(pPg, pPager)); + } + pPg->pgno = 0; + pPg->pNextHash = pPg->pPrevHash = 0; +} + +/* +** Unlink a page from the free list (the list of all pages where nRef==0) +** and from its hash collision chain. +*/ +static void unlinkPage(PgHdr *pPg){ + Pager *pPager = pPg->pPager; + + /* Unlink from free page list */ + lruListRemove(pPg); + + /* Unlink from the pgno hash table */ + unlinkHashChain(pPager, pPg); +} + +/* +** This routine is used to truncate the cache when a database +** is truncated. Drop from the cache all pages whose pgno is +** larger than pPager->dbSize and is unreferenced. +** +** Referenced pages larger than pPager->dbSize are zeroed. +** +** Actually, at the point this routine is called, it would be +** an error to have a referenced page. But rather than delete +** that page and guarantee a subsequent segfault, it seems better +** to zero it and hope that we error out sanely. +*/ +static void pager_truncate_cache(Pager *pPager){ + PgHdr *pPg; + PgHdr **ppPg; + int dbSize = pPager->dbSize; + + ppPg = &pPager->pAll; + while( (pPg = *ppPg)!=0 ){ + if( pPg->pgno<=dbSize ){ + ppPg = &pPg->pNextAll; + }else if( pPg->nRef>0 ){ + memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); + ppPg = &pPg->pNextAll; + }else{ + *ppPg = pPg->pNextAll; +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + if( *ppPg ){ + (*ppPg)->pPrevAll = pPg->pPrevAll; + } +#endif + IOTRACE(("PGFREE %p %d\n", pPager, pPg->pgno)); + PAGER_INCR(sqlite3_pager_pgfree_count); + unlinkPage(pPg); + makeClean(pPg); + sqlite3PageFree(pPg->pData); + sqlite3_free(pPg); + pPager->nPage--; + } + } +} + +/* +** Try to obtain a lock on a file. Invoke the busy callback if the lock +** is currently not available. Repeat until the busy callback returns +** false or until the lock succeeds. +** +** Return SQLITE_OK on success and an error code if we cannot obtain +** the lock. +*/ +static int pager_wait_on_lock(Pager *pPager, int locktype){ + int rc; + + /* The OS lock values must be the same as the Pager lock values */ + assert( PAGER_SHARED==SHARED_LOCK ); + assert( PAGER_RESERVED==RESERVED_LOCK ); + assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK ); + + /* If the file is currently unlocked then the size must be unknown */ + assert( pPager->state>=PAGER_SHARED || pPager->dbSize<0 || MEMDB ); + + if( pPager->state>=locktype ){ + rc = SQLITE_OK; + }else{ + if( pPager->pBusyHandler ) pPager->pBusyHandler->nBusy = 0; + do { + rc = sqlite3OsLock(pPager->fd, locktype); + }while( rc==SQLITE_BUSY && sqlite3InvokeBusyHandler(pPager->pBusyHandler) ); + if( rc==SQLITE_OK ){ + pPager->state = locktype; + IOTRACE(("LOCK %p %d\n", pPager, locktype)) + } + } + return rc; +} + +/* +** Truncate the file to the number of pages specified. +*/ +int sqlite3PagerTruncate(Pager *pPager, Pgno nPage){ + int rc; + assert( pPager->state>=PAGER_SHARED || MEMDB ); + sqlite3PagerPagecount(pPager, 0); + if( pPager->errCode ){ + rc = pPager->errCode; + return rc; + } + if( nPage>=(unsigned)pPager->dbSize ){ + return SQLITE_OK; + } + if( MEMDB ){ + pPager->dbSize = nPage; + pager_truncate_cache(pPager); + return SQLITE_OK; + } + pagerEnter(pPager); + rc = syncJournal(pPager); + pagerLeave(pPager); + if( rc!=SQLITE_OK ){ + return rc; + } + + /* Get an exclusive lock on the database before truncating. */ + pagerEnter(pPager); + rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); + pagerLeave(pPager); + if( rc!=SQLITE_OK ){ + return rc; + } + + rc = pager_truncate(pPager, nPage); + return rc; +} + +/* +** Shutdown the page cache. Free all memory and close all files. +** +** If a transaction was in progress when this routine is called, that +** transaction is rolled back. All outstanding pages are invalidated +** 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 sqlite3PagerClose(Pager *pPager){ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + if( !MEMDB ){ +#ifndef SQLITE_MUTEX_NOOP + sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM2); +#endif + sqlite3_mutex_enter(mutex); + if( pPager->pPrev ){ + pPager->pPrev->pNext = pPager->pNext; + }else{ + sqlite3PagerList = pPager->pNext; + } + if( pPager->pNext ){ + pPager->pNext->pPrev = pPager->pPrev; + } + sqlite3_mutex_leave(mutex); + } +#endif + + disable_simulated_io_errors(); + sqlite3BeginBenignMalloc(); + pPager->errCode = 0; + pPager->exclusiveMode = 0; + pager_reset(pPager); + pagerUnlockAndRollback(pPager); + enable_simulated_io_errors(); + sqlite3EndBenignMalloc(); + PAGERTRACE2("CLOSE %d\n", PAGERID(pPager)); + IOTRACE(("CLOSE %p\n", pPager)) + if( pPager->journalOpen ){ + sqlite3OsClose(pPager->jfd); + } + sqlite3BitvecDestroy(pPager->pInJournal); + if( pPager->stmtOpen ){ + sqlite3OsClose(pPager->stfd); + } + sqlite3OsClose(pPager->fd); + /* Temp files are automatically deleted by the OS + ** if( pPager->tempFile ){ + ** sqlite3OsDelete(pPager->zFilename); + ** } + */ + + sqlite3_free(pPager->aHash); + sqlite3PageFree(pPager->pTmpSpace); + sqlite3_free(pPager); + return SQLITE_OK; +} + +#if !defined(NDEBUG) || defined(SQLITE_TEST) +/* +** Return the page number for the given page data. +*/ +Pgno sqlite3PagerPagenumber(DbPage *p){ + return p->pgno; +} +#endif + +/* +** The page_ref() function increments the reference count for a page. +** If the page is currently on the freelist (the reference count is zero) then +** remove it from the freelist. +** +** For non-test systems, page_ref() is a macro that calls _page_ref() +** online of the reference count is zero. For test systems, page_ref() +** is a real function so that we can set breakpoints and trace it. +*/ +static void _page_ref(PgHdr *pPg){ + if( pPg->nRef==0 ){ + /* The page is currently on the freelist. Remove it. */ + lruListRemove(pPg); + pPg->pPager->nRef++; + } + pPg->nRef++; +} +#ifdef SQLITE_DEBUG + static void page_ref(PgHdr *pPg){ + if( pPg->nRef==0 ){ + _page_ref(pPg); + }else{ + pPg->nRef++; + } + } +#else +# define page_ref(P) ((P)->nRef==0?_page_ref(P):(void)(P)->nRef++) +#endif + +/* +** Increment the reference count for a page. The input pointer is +** a reference to the page data. +*/ +int sqlite3PagerRef(DbPage *pPg){ + pagerEnter(pPg->pPager); + page_ref(pPg); + pagerLeave(pPg->pPager); + return SQLITE_OK; +} + +/* +** Sync the journal. In other words, make sure all the pages that have +** been written to the journal have actually reached the surface of the +** disk. It is not safe to modify the original database file until after +** the journal has been synced. If the original database is modified before +** the journal is synced and a power failure occurs, the unsynced journal +** data would be lost and we would be unable to completely rollback the +** database changes. Database corruption would occur. +** +** This routine also updates the nRec field in the header of the journal. +** (See comments on the pager_playback() routine for additional information.) +** If the sync mode is FULL, two syncs will occur. First the whole journal +** is synced, then the nRec field is updated, then a second sync occurs. +** +** For temporary databases, we do not care if we are able to rollback +** after a power failure, so no sync occurs. +** +** If the IOCAP_SEQUENTIAL flag is set for the persistent media on which +** the database is stored, then OsSync() is never called on the journal +** file. In this case all that is required is to update the nRec field in +** the journal header. +** +** This routine clears the needSync field of every page current held in +** memory. +*/ +static int syncJournal(Pager *pPager){ + PgHdr *pPg; + int rc = SQLITE_OK; + + /* Sync the journal before modifying the main database + ** (assuming there is a journal and it needs to be synced.) + */ + if( pPager->needSync ){ + if( !pPager->tempFile ){ + int iDc = sqlite3OsDeviceCharacteristics(pPager->fd); + assert( pPager->journalOpen ); + + if( 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){ + /* Write the nRec value into the journal file header. If in + ** full-synchronous mode, sync the journal first. This ensures that + ** all data has really hit the disk before nRec is updated to mark + ** it as a candidate for rollback. + ** + ** This is not required if the persistent media supports the + ** SAFE_APPEND property. Because in this case it is not possible + ** for garbage data to be appended to the file, the nRec field + ** is populated with 0xFFFFFFFF when the journal header is written + ** and never needs to be updated. + */ + i64 jrnlOff; + if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){ + PAGERTRACE2("SYNC journal of %d\n", PAGERID(pPager)); + IOTRACE(("JSYNC %p\n", pPager)) + rc = sqlite3OsSync(pPager->jfd, pPager->sync_flags); + if( rc!=0 ) return rc; + } + + jrnlOff = pPager->journalHdr + sizeof(aJournalMagic); + IOTRACE(("JHDR %p %lld %d\n", pPager, jrnlOff, 4)); + rc = write32bits(pPager->jfd, jrnlOff, pPager->nRec); + if( rc ) return rc; + } + if( 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){ + PAGERTRACE2("SYNC journal of %d\n", PAGERID(pPager)); + IOTRACE(("JSYNC %p\n", pPager)) + rc = sqlite3OsSync(pPager->jfd, pPager->sync_flags| + (pPager->sync_flags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0) + ); + if( rc!=0 ) return rc; + } + pPager->journalStarted = 1; + } + pPager->needSync = 0; + + /* Erase the needSync flag from every page. + */ + for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ + pPg->needSync = 0; + } + lruListSetFirstSynced(pPager); + } + +#ifndef NDEBUG + /* If the Pager.needSync flag is clear then the PgHdr.needSync + ** flag must also be clear for all pages. Verify that this + ** invariant is true. + */ + else{ + for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ + assert( pPg->needSync==0 ); + } + assert( pPager->lru.pFirstSynced==pPager->lru.pFirst ); + } +#endif + + return rc; +} + +/* +** Merge two lists of pages connected by pDirty and in pgno order. +** Do not both fixing the pPrevDirty pointers. +*/ +static PgHdr *merge_pagelist(PgHdr *pA, PgHdr *pB){ + PgHdr result, *pTail; + pTail = &result; + while( pA && pB ){ + if( pA->pgno<pB->pgno ){ + pTail->pDirty = pA; + pTail = pA; + pA = pA->pDirty; + }else{ + pTail->pDirty = pB; + pTail = pB; + pB = pB->pDirty; + } + } + if( pA ){ + pTail->pDirty = pA; + }else if( pB ){ + pTail->pDirty = pB; + }else{ + pTail->pDirty = 0; + } + return result.pDirty; +} + +/* +** Sort the list of pages in accending order by pgno. Pages are +** connected by pDirty pointers. The pPrevDirty pointers are +** corrupted by this sort. +*/ +#define N_SORT_BUCKET_ALLOC 25 +#define N_SORT_BUCKET 25 +#ifdef SQLITE_TEST + int sqlite3_pager_n_sort_bucket = 0; + #undef N_SORT_BUCKET + #define N_SORT_BUCKET \ + (sqlite3_pager_n_sort_bucket?sqlite3_pager_n_sort_bucket:N_SORT_BUCKET_ALLOC) +#endif +static PgHdr *sort_pagelist(PgHdr *pIn){ + PgHdr *a[N_SORT_BUCKET_ALLOC], *p; + int i; + memset(a, 0, sizeof(a)); + while( pIn ){ + p = pIn; + pIn = p->pDirty; + p->pDirty = 0; + for(i=0; i<N_SORT_BUCKET-1; i++){ + if( a[i]==0 ){ + a[i] = p; + break; + }else{ + p = merge_pagelist(a[i], p); + a[i] = 0; + } + } + if( i==N_SORT_BUCKET-1 ){ + /* Coverage: To get here, there need to be 2^(N_SORT_BUCKET) + ** elements in the input list. This is possible, but impractical. + ** Testing this line is the point of global variable + ** sqlite3_pager_n_sort_bucket. + */ + a[i] = merge_pagelist(a[i], p); + } + } + p = a[0]; + for(i=1; i<N_SORT_BUCKET; i++){ + p = merge_pagelist(p, a[i]); + } + return p; +} + +/* +** Given a list of pages (connected by the PgHdr.pDirty pointer) write +** every one of those pages out to the database file and mark them all +** as clean. +*/ +static int pager_write_pagelist(PgHdr *pList){ + Pager *pPager; + PgHdr *p; + int rc; + + if( pList==0 ) return SQLITE_OK; + pPager = pList->pPager; + + /* At this point there may be either a RESERVED or EXCLUSIVE lock on the + ** database file. If there is already an EXCLUSIVE lock, the following + ** calls to sqlite3OsLock() are no-ops. + ** + ** Moving the lock from RESERVED to EXCLUSIVE actually involves going + ** through an intermediate state PENDING. A PENDING lock prevents new + ** readers from attaching to the database but is unsufficient for us to + ** write. The idea of a PENDING lock is to prevent new readers from + ** coming in while we wait for existing readers to clear. + ** + ** While the pager is in the RESERVED state, the original database file + ** is unchanged and we can rollback without having to playback the + ** journal into the original database file. Once we transition to + ** EXCLUSIVE, it means the database file has been changed and any rollback + ** will require a journal playback. + */ + rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); + if( rc!=SQLITE_OK ){ + return rc; + } + + pList = sort_pagelist(pList); + for(p=pList; p; p=p->pDirty){ + assert( p->dirty ); + p->dirty = 0; + } + while( pList ){ + + /* If the file has not yet been opened, open it now. */ + if( !pPager->fd->pMethods ){ + assert(pPager->tempFile); + rc = sqlite3PagerOpentemp(pPager, pPager->fd, pPager->vfsFlags); + if( rc ) return rc; + } + + /* If there are dirty pages in the page cache with page numbers greater + ** than Pager.dbSize, this means sqlite3PagerTruncate() was called to + ** make the file smaller (presumably by auto-vacuum code). Do not write + ** any such pages to the file. + */ + if( pList->pgno<=pPager->dbSize ){ + i64 offset = (pList->pgno-1)*(i64)pPager->pageSize; + char *pData = CODEC2(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6); + PAGERTRACE4("STORE %d page %d hash(%08x)\n", + PAGERID(pPager), pList->pgno, pager_pagehash(pList)); + IOTRACE(("PGOUT %p %d\n", pPager, pList->pgno)); + rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset); + PAGER_INCR(sqlite3_pager_writedb_count); + PAGER_INCR(pPager->nWrite); + if( pList->pgno==1 ){ + memcpy(&pPager->dbFileVers, &pData[24], sizeof(pPager->dbFileVers)); + } + } +#ifndef NDEBUG + else{ + PAGERTRACE3("NOSTORE %d page %d\n", PAGERID(pPager), pList->pgno); + } +#endif + if( rc ) return rc; +#ifdef SQLITE_CHECK_PAGES + pList->pageHash = pager_pagehash(pList); +#endif + pList = pList->pDirty; + } + return SQLITE_OK; +} + +/* +** Collect every dirty page into a dirty list and +** return a pointer to the head of that list. All pages are +** collected even if they are still in use. +*/ +static PgHdr *pager_get_all_dirty_pages(Pager *pPager){ + +#ifndef NDEBUG + /* Verify the sanity of the dirty list when we are running + ** in debugging mode. This is expensive, so do not + ** do this on a normal build. */ + int n1 = 0; + int n2 = 0; + PgHdr *p; + for(p=pPager->pAll; p; p=p->pNextAll){ if( p->dirty ) n1++; } + for(p=pPager->pDirty; p; p=p->pDirty){ n2++; } + assert( n1==n2 ); +#endif + + return pPager->pDirty; +} + +/* +** Return 1 if there is a hot journal on the given pager. +** A hot journal is one that needs to be played back. +** +** If the current size of the database file is 0 but a journal file +** exists, that is probably an old journal left over from a prior +** database with the same name. Just delete the journal. +** +** Return negative if unable to determine the status of the journal. +** +** This routine does not open the journal file to examine its +** content. Hence, the journal might contain the name of a master +** journal file that has been deleted, and hence not be hot. Or +** the header of the journal might be zeroed out. This routine +** does not discover these cases of a non-hot journal - if the +** journal file exists and is not empty this routine assumes it +** is hot. The pager_playback() routine will discover that the +** journal file is not really hot and will no-op. +*/ +static int hasHotJournal(Pager *pPager, int *pExists){ + sqlite3_vfs *pVfs = pPager->pVfs; + int rc = SQLITE_OK; + *pExists = 0; + if( pPager->useJournal && pPager->fd->pMethods ){ + int exists; + int locked; + + rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &exists); + if( rc==SQLITE_OK && exists ){ + rc = sqlite3OsCheckReservedLock(pPager->fd, &locked); + } + + if( rc==SQLITE_OK && exists && !locked ){ + int nPage; + rc = sqlite3PagerPagecount(pPager, &nPage); + if( rc==SQLITE_OK ){ + if( nPage==0 ){ + sqlite3OsDelete(pVfs, pPager->zJournal, 0); + }else{ + *pExists = 1; + } + } + } + } + + return rc; +} + +/* +** 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, PgHdr **ppPg){ + PgHdr *pPg; + *ppPg = 0; + + /* It is illegal to call this function unless the pager object + ** pointed to by pPager has at least one free page (page with nRef==0). + */ + assert(!MEMDB); + assert(pPager->lru.pFirst); + + /* Find a page to recycle. Try to locate a page that does not + ** require us to do an fsync() on the journal. + */ + pPg = pPager->lru.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->lru.pFirst ){ + if( !pPager->errCode ){ + int iDc = sqlite3OsDeviceCharacteristics(pPager->fd); + int rc = syncJournal(pPager); + if( rc!=0 ){ + return rc; + } + if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){ + /* 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 ); + assert( pPager->doNotSync==0 ); + rc = writeJournalHdr(pPager); + if( rc!=0 ){ + return rc; + } + } + } + pPg = pPager->lru.pFirst; + } + + assert( pPg->nRef==0 ); + + /* Write the page to the database file if it is dirty. + */ + if( pPg->dirty && !pPager->errCode ){ + int rc; + assert( pPg->needSync==0 ); + makeClean(pPg); + pPg->dirty = 1; + pPg->pDirty = 0; + rc = pager_write_pagelist( pPg ); + pPg->dirty = 0; + if( rc!=SQLITE_OK ){ + return rc; + } + } + assert( pPg->dirty==0 || pPager->errCode ); + + /* If the page we are recycling is marked as alwaysRollback, then + ** set the global alwaysRollback flag, thus disabling the + ** sqlite3PagerDontRollback() 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 ){ + IOTRACE(("ALWAYS_ROLLBACK %p\n", pPager)) + pPager->alwaysRollback = 1; + } + + /* Unlink the old page from the free list and the hash table + */ + unlinkPage(pPg); + assert( pPg->pgno==0 ); + + *ppPg = pPg; + return SQLITE_OK; +} + +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +/* +** 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 sqlite3_free()ed. +** +** nReq is the number of bytes of memory required. Once this much has +** been released, the function returns. The return value is the total number +** of bytes of memory released. +*/ +int sqlite3PagerReleaseMemory(int nReq){ + int nReleased = 0; /* Bytes of memory released so far */ + Pager *pPager; /* For looping over pagers */ + BusyHandler *savedBusy; /* Saved copy of the busy handler */ + int rc = SQLITE_OK; + + /* Acquire the memory-management mutex + */ +#ifndef SQLITE_MUTEX_NOOP + sqlite3_mutex *mutex; /* The MEM2 mutex */ + mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM2); +#endif + sqlite3_mutex_enter(mutex); + + /* Signal all database connections that memory management wants + ** to have access to the pagers. + */ + for(pPager=sqlite3PagerList; pPager; pPager=pPager->pNext){ + pPager->iInUseMM = 1; + } + + while( rc==SQLITE_OK && (nReq<0 || nReleased<nReq) ){ + PgHdr *pPg; + PgHdr *pRecycled; + + /* Try to find a page to recycle that does not require a sync(). If + ** this is not possible, find one that does require a sync(). + */ + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU)); + pPg = sqlite3LruPageList.pFirstSynced; + while( pPg && (pPg->needSync || pPg->pPager->iInUseDB) ){ + pPg = pPg->gfree.pNext; + } + if( !pPg ){ + pPg = sqlite3LruPageList.pFirst; + while( pPg && pPg->pPager->iInUseDB ){ + pPg = pPg->gfree.pNext; + } + } + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU)); + + /* If pPg==0, then the block above has failed to find a page to + ** recycle. In this case return early - no further memory will + ** be released. + */ + if( !pPg ) break; + + pPager = pPg->pPager; + assert(!pPg->needSync || pPg==pPager->lru.pFirst); + assert(pPg->needSync || pPg==pPager->lru.pFirstSynced); + + savedBusy = pPager->pBusyHandler; + pPager->pBusyHandler = 0; + rc = pager_recycle(pPager, &pRecycled); + pPager->pBusyHandler = savedBusy; + assert(pRecycled==pPg || rc!=SQLITE_OK); + if( rc==SQLITE_OK ){ + /* 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 ); + if( pPg==pPager->pAll ){ + assert(pPg->pPrevAll==0); + assert(pPg->pNextAll==0 || pPg->pNextAll->pPrevAll==pPg); + pPager->pAll = pPg->pNextAll; + if( pPager->pAll ){ + pPager->pAll->pPrevAll = 0; + } + }else{ + assert(pPg->pPrevAll); + assert(pPg->pPrevAll->pNextAll==pPg); + pTmp = pPg->pPrevAll; + pTmp->pNextAll = pPg->pNextAll; + if( pTmp->pNextAll ){ + pTmp->pNextAll->pPrevAll = pTmp; + } + } + nReleased += ( + sizeof(*pPg) + pPager->pageSize + + sizeof(u32) + pPager->nExtra + + MEMDB*sizeof(PgHistory) + ); + IOTRACE(("PGFREE %p %d *\n", pPager, pPg->pgno)); + PAGER_INCR(sqlite3_pager_pgfree_count); + sqlite3PageFree(pPg->pData); + sqlite3_free(pPg); + pPager->nPage--; + }else{ + /* 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&0xff)==SQLITE_IOERR || + rc==SQLITE_FULL || + rc==SQLITE_BUSY + ); + assert( pPager->state>=PAGER_RESERVED ); + pager_error(pPager, rc); + } + } + + /* Clear the memory management flags and release the mutex + */ + for(pPager=sqlite3PagerList; pPager; pPager=pPager->pNext){ + pPager->iInUseMM = 0; + } + sqlite3_mutex_leave(mutex); + + /* Return the number of bytes released + */ + return nReleased; +} +#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */ + +/* +** Read the content of page pPg out of the database file. +*/ +static int readDbPage(Pager *pPager, PgHdr *pPg, Pgno pgno){ + int rc; + i64 offset; + assert( MEMDB==0 ); + assert(pPager->fd->pMethods||pPager->tempFile); + if( !pPager->fd->pMethods ){ + return SQLITE_IOERR_SHORT_READ; + } + offset = (pgno-1)*(i64)pPager->pageSize; + rc = sqlite3OsRead(pPager->fd, PGHDR_TO_DATA(pPg), pPager->pageSize, offset); + PAGER_INCR(sqlite3_pager_readdb_count); + PAGER_INCR(pPager->nRead); + IOTRACE(("PGIN %p %d\n", pPager, pgno)); + if( pgno==1 ){ + memcpy(&pPager->dbFileVers, &((u8*)PGHDR_TO_DATA(pPg))[24], + sizeof(pPager->dbFileVers)); + } + CODEC1(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3); + PAGERTRACE4("FETCH %d page %d hash(%08x)\n", + PAGERID(pPager), pPg->pgno, pager_pagehash(pPg)); + return rc; +} + + +/* +** This function is called to obtain the shared lock required before +** data may be read from the pager cache. If the shared lock has already +** been obtained, this function is a no-op. +** +** Immediately after obtaining the shared lock (if required), this function +** checks for a hot-journal file. If one is found, an emergency rollback +** is performed immediately. +*/ +static int pagerSharedLock(Pager *pPager){ + int rc = SQLITE_OK; + int isErrorReset = 0; + + /* If this database is opened for exclusive access, has no outstanding + ** page references and is in an error-state, now is the chance to clear + ** the error. Discard the contents of the pager-cache and treat any + ** open journal file as a hot-journal. + */ + if( !MEMDB && pPager->exclusiveMode && pPager->nRef==0 && pPager->errCode ){ + if( pPager->journalOpen ){ + isErrorReset = 1; + } + pPager->errCode = SQLITE_OK; + pager_reset(pPager); + } + + /* If the pager is still in an error state, do not proceed. The error + ** state will be cleared at some point in the future when all page + ** references are dropped and the cache can be discarded. + */ + if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ + return pPager->errCode; + } + + if( pPager->state==PAGER_UNLOCK || isErrorReset ){ + sqlite3_vfs *pVfs = pPager->pVfs; + if( !MEMDB ){ + int isHotJournal; + assert( pPager->nRef==0 ); + if( !pPager->noReadlock ){ + rc = pager_wait_on_lock(pPager, SHARED_LOCK); + if( rc!=SQLITE_OK ){ + assert( pPager->state==PAGER_UNLOCK ); + return pager_error(pPager, rc); + } + assert( pPager->state>=SHARED_LOCK ); + } + + /* If a journal file exists, and there is no RESERVED lock on the + ** database file, then it either needs to be played back or deleted. + */ + if( !isErrorReset ){ + rc = hasHotJournal(pPager, &isHotJournal); + if( rc!=SQLITE_OK ){ + goto failed; + } + } + if( isErrorReset || isHotJournal ){ + /* 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 + ** database file, detect the RESERVED lock, and conclude that the + ** database is safe to read while this process is still rolling it + ** back. + ** + ** Because the intermediate RESERVED lock is not requested, the + ** second process will get to this point in the code and fail to + ** obtain its own EXCLUSIVE lock on the database file. + */ + if( pPager->state<EXCLUSIVE_LOCK ){ + rc = sqlite3OsLock(pPager->fd, EXCLUSIVE_LOCK); + if( rc!=SQLITE_OK ){ + rc = pager_error(pPager, rc); + goto failed; + } + pPager->state = PAGER_EXCLUSIVE; + } + + /* Open the journal for read/write access. This is because in + ** exclusive-access mode the file descriptor will be kept open and + ** possibly used for a transaction later on. On some systems, the + ** OsTruncate() call used in exclusive-access mode also requires + ** a read/write file handle. + */ + if( !isErrorReset && pPager->journalOpen==0 ){ + int res; + rc = sqlite3OsAccess(pVfs,pPager->zJournal,SQLITE_ACCESS_EXISTS,&res); + if( rc==SQLITE_OK ){ + if( res ){ + int fout = 0; + int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL; + assert( !pPager->tempFile ); + rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout); + assert( rc!=SQLITE_OK || pPager->jfd->pMethods ); + if( fout&SQLITE_OPEN_READONLY ){ + rc = SQLITE_BUSY; + sqlite3OsClose(pPager->jfd); + } + }else{ + /* If the journal does not exist, that means some other process + ** has already rolled it back */ + rc = SQLITE_BUSY; + } + } + } + if( rc!=SQLITE_OK ){ + if( rc!=SQLITE_NOMEM && rc!=SQLITE_IOERR_UNLOCK + && rc!=SQLITE_IOERR_NOMEM + ){ + rc = SQLITE_BUSY; + } + goto failed; + } + pPager->journalOpen = 1; + pPager->journalStarted = 0; + pPager->journalOff = 0; + pPager->setMaster = 0; + pPager->journalHdr = 0; + + /* Playback and delete the journal. Drop the database write + ** lock and reacquire the read lock. + */ + rc = pager_playback(pPager, 1); + if( rc!=SQLITE_OK ){ + rc = pager_error(pPager, rc); + goto failed; + } + assert(pPager->state==PAGER_SHARED || + (pPager->exclusiveMode && pPager->state>PAGER_SHARED) + ); + } + + if( pPager->pAll ){ + /* The shared-lock has just been acquired on the database file + ** and there are already pages in the cache (from a previous + ** read or write transaction). Check to see if the database + ** has been modified. If the database has changed, flush the + ** cache. + ** + ** Database changes is detected by looking at 15 bytes beginning + ** at offset 24 into the file. The first 4 of these 16 bytes are + ** a 32-bit counter that is incremented with each change. The + ** other bytes change randomly with each file change when + ** a codec is in use. + ** + ** There is a vanishingly small chance that a change will not be + ** detected. The chance of an undetected change is so small that + ** it can be neglected. + */ + char dbFileVers[sizeof(pPager->dbFileVers)]; + sqlite3PagerPagecount(pPager, 0); + + if( pPager->errCode ){ + rc = pPager->errCode; + goto failed; + } + + if( pPager->dbSize>0 ){ + IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers))); + rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24); + if( rc!=SQLITE_OK ){ + goto failed; + } + }else{ + memset(dbFileVers, 0, sizeof(dbFileVers)); + } + + if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){ + pager_reset(pPager); + } + } + } + assert( pPager->exclusiveMode || pPager->state<=PAGER_SHARED ); + if( pPager->state==PAGER_UNLOCK ){ + pPager->state = PAGER_SHARED; + } + } + + failed: + if( rc!=SQLITE_OK ){ + /* pager_unlock() is a no-op for exclusive mode and in-memory databases. */ + pager_unlock(pPager); + } + return rc; +} + +/* +** Allocate a PgHdr object. Either create a new one or reuse +** an existing one that is not otherwise in use. +** +** A new PgHdr structure is created if any of the following are +** true: +** +** (1) We have not exceeded our maximum allocated cache size +** as set by the "PRAGMA cache_size" command. +** +** (2) There are no unused PgHdr objects available at this time. +** +** (3) This is an in-memory database. +** +** (4) There are no PgHdr objects that do not require a journal +** file sync and a sync of the journal file is currently +** prohibited. +** +** Otherwise, reuse an existing PgHdr. In other words, reuse an +** existing PgHdr if all of the following are true: +** +** (1) We have reached or exceeded the maximum cache size +** allowed by "PRAGMA cache_size". +** +** (2) There is a PgHdr available with PgHdr->nRef==0 +** +** (3) We are not in an in-memory database +** +** (4) Either there is an available PgHdr that does not need +** to be synced to disk or else disk syncing is currently +** allowed. +*/ +static int pagerAllocatePage(Pager *pPager, PgHdr **ppPg){ + int rc = SQLITE_OK; + PgHdr *pPg; + int nByteHdr; + + /* Create a new PgHdr if any of the four conditions defined + ** above are met: */ + if( pPager->nPage<pPager->mxPage + || pPager->lru.pFirst==0 + || MEMDB + || (pPager->lru.pFirstSynced==0 && pPager->doNotSync) + ){ + void *pData; + if( pPager->nPage>=pPager->nHash ){ + pager_resize_hash_table(pPager, + pPager->nHash<256 ? 256 : pPager->nHash*2); + if( pPager->nHash==0 ){ + rc = SQLITE_NOMEM; + goto pager_allocate_out; + } + } + pagerLeave(pPager); + nByteHdr = sizeof(*pPg) + sizeof(u32) + pPager->nExtra + + MEMDB*sizeof(PgHistory); + pPg = sqlite3Malloc( nByteHdr ); + if( pPg ){ + pData = sqlite3PageMalloc( pPager->pageSize ); + if( pData==0 ){ + sqlite3_free(pPg); + pPg = 0; + } + } + pagerEnter(pPager); + if( pPg==0 ){ + rc = SQLITE_NOMEM; + goto pager_allocate_out; + } + memset(pPg, 0, nByteHdr); + pPg->pData = pData; + pPg->pPager = pPager; + pPg->pNextAll = pPager->pAll; +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + if( pPg->pNextAll ){ + pPg->pNextAll->pPrevAll = pPg; + } +#endif + pPager->pAll = pPg; + pPager->nPage++; + }else{ + /* Recycle an existing page with a zero ref-count. */ + rc = pager_recycle(pPager, &pPg); + if( rc==SQLITE_BUSY ){ + rc = SQLITE_IOERR_BLOCKED; + } + if( rc!=SQLITE_OK ){ + goto pager_allocate_out; + } + assert( pPager->state>=SHARED_LOCK ); + assert(pPg); + } + *ppPg = pPg; + +pager_allocate_out: + return rc; +} + +/* +** Make sure we have the content for a page. If the page was +** previously acquired with noContent==1, then the content was +** just initialized to zeros instead of being read from disk. +** But now we need the real data off of disk. So make sure we +** have it. Read it in if we do not have it already. +*/ +static int pager_get_content(PgHdr *pPg){ + if( pPg->needRead ){ + int rc = readDbPage(pPg->pPager, pPg, pPg->pgno); + if( rc==SQLITE_OK ){ + pPg->needRead = 0; + }else{ + return rc; + } + } + return SQLITE_OK; +} + +/* +** Acquire a page. +** +** A read lock on the disk file is obtained when the first page is acquired. +** This read lock is dropped when the last page is released. +** +** This routine works for any page number greater than 0. If the database +** file is smaller than the requested page, then no actual disk +** read occurs and the memory image of the page is initialized to +** all zeros. The extra data appended to a page is always initialized +** to zeros the first time a page is loaded into memory. +** +** The acquisition might fail for several reasons. In all cases, +** an appropriate error code is returned and *ppPage is set to NULL. +** +** See also sqlite3PagerLookup(). Both this routine and Lookup() attempt +** to find a page in the in-memory cache first. If the page is not already +** in memory, this routine goes to disk to read it in whereas Lookup() +** just returns 0. This routine acquires a read-lock the first time it +** has to go to disk, and could also playback an old journal if necessary. +** Since Lookup() never goes to disk, it never has to deal with locks +** or journal files. +** +** If noContent is false, the page contents are actually read from disk. +** If noContent is true, it means that we do not care about the contents +** of the page at this time, so do not do a disk read. Just fill in the +** page content with zeros. But mark the fact that we have not read the +** content by setting the PgHdr.needRead flag. Later on, if +** sqlite3PagerWrite() is called on this page or if this routine is +** called again with noContent==0, that means that the content is needed +** and the disk read should occur at that point. +*/ +static int pagerAcquire( + Pager *pPager, /* The pager open on the database file */ + Pgno pgno, /* Page number to fetch */ + DbPage **ppPage, /* Write a pointer to the page here */ + int noContent /* Do not bother reading content from disk if true */ +){ + /* This just passes through to our modified version with NULL data. */ + return sqlite3PagerAcquire2(pPager, pgno, ppPage, noContent, 0); +} + +/* +** This is an internal version of sqlite3PagerAcquire that takes an extra +** parameter of data to use to fill the page with. This allows more efficient +** filling for preloaded data. If this extra parameter is NULL, we'll go to +** the file. +** +** See sqlite3PagerLoadall which uses this function. +*/ +int sqlite3PagerAcquire2( + Pager *pPager, /* The pager open on the database file */ + Pgno pgno, /* Page number to fetch */ + DbPage **ppPage, /* Write a pointer to the page here */ + int noContent, /* Do not bother reading content from disk if true */ + unsigned char* pDataToFill +){ + PgHdr *pPg; + int rc; + + assert( pPager->state==PAGER_UNLOCK || pPager->nRef>0 || pgno==1 ); + + /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page + ** number greater than this, or zero, is requested. + */ + if( pgno>PAGER_MAX_PGNO || pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){ + return SQLITE_CORRUPT_BKPT; + } + + /* Make sure we have not hit any critical errors. + */ + assert( pPager!=0 ); + *ppPage = 0; + + /* If this is the first page accessed, then get a SHARED lock + ** on the database file. pagerSharedLock() is a no-op if + ** a database lock is already held. + */ + rc = pagerSharedLock(pPager); + if( rc!=SQLITE_OK ){ + return rc; + } + assert( pPager->state!=PAGER_UNLOCK ); + + pPg = pager_lookup(pPager, pgno); + if( pPg==0 ){ + /* The requested page is not in the page cache. */ + int nMax; + int h; + PAGER_INCR(pPager->nMiss); + rc = pagerAllocatePage(pPager, &pPg); + if( rc!=SQLITE_OK ){ + return rc; + } + + pPg->pgno = pgno; + assert( !MEMDB || pgno>pPager->stmtSize ); + pPg->inJournal = sqlite3BitvecTest(pPager->pInJournal, pgno); + pPg->needSync = 0; + + makeClean(pPg); + pPg->nRef = 1; + + pPager->nRef++; + if( pPager->nExtra>0 ){ + memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra); + } + rc = sqlite3PagerPagecount(pPager, &nMax); + if( rc!=SQLITE_OK ){ + sqlite3PagerUnref(pPg); + return rc; + } + + /* Populate the page with data, either by reading from the database + ** file, or by setting the entire page to zero. + */ + if( nMax<(int)pgno || MEMDB || (noContent && !pPager->alwaysRollback) ){ + if( pgno>pPager->mxPgno ){ + sqlite3PagerUnref(pPg); + return SQLITE_FULL; + } + memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); + pPg->needRead = noContent && !pPager->alwaysRollback; + IOTRACE(("ZERO %p %d\n", pPager, pgno)); + }else{ + if (pDataToFill) { + /* Just copy from the given memory. */ + memcpy(PGHDR_TO_DATA(pPg), pDataToFill, pPager->pageSize); + CODEC1(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3); + } else { + /* Load from disk (old regular sqlite code path). */ + rc = readDbPage(pPager, pPg, pgno); + if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){ + pPg->pgno = 0; + sqlite3PagerUnref(pPg); + return rc; + } + } + pPg->needRead = 0; + } + + /* Link the page into the page hash table */ + h = pgno & (pPager->nHash-1); + assert( pgno!=0 ); + pPg->pNextHash = pPager->aHash[h]; + pPager->aHash[h] = pPg; + if( pPg->pNextHash ){ + assert( pPg->pNextHash->pPrevHash==0 ); + pPg->pNextHash->pPrevHash = pPg; + } + +#ifdef SQLITE_CHECK_PAGES + pPg->pageHash = pager_pagehash(pPg); +#endif + }else{ + /* The requested page is in the page cache. */ + assert(pPager->nRef>0 || pgno==1); + PAGER_INCR(pPager->nHit); + if( !noContent ){ + rc = pager_get_content(pPg); + if( rc ){ + return rc; + } + } + page_ref(pPg); + } + *ppPage = pPg; + return SQLITE_OK; +} +int sqlite3PagerAcquire( + Pager *pPager, /* The pager open on the database file */ + Pgno pgno, /* Page number to fetch */ + DbPage **ppPage, /* Write a pointer to the page here */ + int noContent /* Do not bother reading content from disk if true */ +){ + int rc; + pagerEnter(pPager); + rc = pagerAcquire(pPager, pgno, ppPage, noContent); + pagerLeave(pPager); + return rc; +} + + +/* +** Acquire a page if it is already in the in-memory cache. Do +** not read the page from disk. Return a pointer to the page, +** or 0 if the page is not in cache. +** +** See also sqlite3PagerGet(). The difference between this routine +** and sqlite3PagerGet() is that _get() will go to the disk and read +** in the page if the page is not already in cache. This routine +** returns NULL if the page is not in cache or if a disk I/O error +** has ever happened. +*/ +DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){ + PgHdr *pPg = 0; + + assert( pPager!=0 ); + assert( pgno!=0 ); + + pagerEnter(pPager); + if( pPager->state==PAGER_UNLOCK ){ + assert( !pPager->pAll || pPager->exclusiveMode ); + }else if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ + /* Do nothing */ + }else if( (pPg = pager_lookup(pPager, pgno))!=0 ){ + page_ref(pPg); + } + pagerLeave(pPager); + return pPg; +} + +/* +** Release a page. +** +** If the number of references to the page drop to zero, then the +** page is added to the LRU list. When all references to all pages +** are released, a rollback occurs and the lock on the database is +** removed. +*/ +int sqlite3PagerUnref(DbPage *pPg){ + Pager *pPager; + + if( pPg==0 ) return SQLITE_OK; + pPager = pPg->pPager; + + /* Decrement the reference count for this page + */ + assert( pPg->nRef>0 ); + pagerEnter(pPg->pPager); + pPg->nRef--; + + CHECK_PAGE(pPg); + + /* When the number of references to a page reach 0, call the + ** destructor and add the page to the freelist. + */ + if( pPg->nRef==0 ){ + + lruListAdd(pPg); + if( pPager->xDestructor ){ + pPager->xDestructor(pPg, pPager->pageSize); + } + + /* When all pages reach the freelist, drop the read lock from + ** the database file. + */ + pPager->nRef--; + assert( pPager->nRef>=0 ); + if( pPager->nRef==0 && (!pPager->exclusiveMode || pPager->journalOff>0) ){ + pagerUnlockAndRollback(pPager); + } + } + pagerLeave(pPager); + return SQLITE_OK; +} + +/* +** Create a journal file for pPager. There should already be a RESERVED +** or EXCLUSIVE lock on the database file when this routine is called. +** +** Return SQLITE_OK if everything. Return an error code and release the +** write lock if anything goes wrong. +*/ +static int pager_open_journal(Pager *pPager){ + sqlite3_vfs *pVfs = pPager->pVfs; + int flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_CREATE); + + int rc; + assert( !MEMDB ); + assert( pPager->state>=PAGER_RESERVED ); + assert( pPager->useJournal ); + assert( pPager->pInJournal==0 ); + sqlite3PagerPagecount(pPager, 0); + pagerLeave(pPager); + pPager->pInJournal = sqlite3BitvecCreate(pPager->dbSize); + pagerEnter(pPager); + if( pPager->pInJournal==0 ){ + rc = SQLITE_NOMEM; + goto failed_to_open_journal; + } + + if( pPager->journalOpen==0 ){ + if( pPager->tempFile ){ + flags |= (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL); + }else{ + flags |= (SQLITE_OPEN_MAIN_JOURNAL); + } +#ifdef SQLITE_ENABLE_ATOMIC_WRITE + rc = sqlite3JournalOpen( + pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager) + ); +#else + rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0); +#endif + assert( rc!=SQLITE_OK || pPager->jfd->pMethods ); + pPager->journalOff = 0; + pPager->setMaster = 0; + pPager->journalHdr = 0; + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_NOMEM ){ + sqlite3OsDelete(pVfs, pPager->zJournal, 0); + } + goto failed_to_open_journal; + } + } + pPager->journalOpen = 1; + pPager->journalStarted = 0; + pPager->needSync = 0; + pPager->alwaysRollback = 0; + pPager->nRec = 0; + if( pPager->errCode ){ + rc = pPager->errCode; + goto failed_to_open_journal; + } + pPager->origDbSize = pPager->dbSize; + + rc = writeJournalHdr(pPager); + + if( pPager->stmtAutoopen && rc==SQLITE_OK ){ + rc = sqlite3PagerStmtBegin(pPager); + } + if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM && rc!=SQLITE_IOERR_NOMEM ){ + rc = pager_end_transaction(pPager, 0); + if( rc==SQLITE_OK ){ + rc = SQLITE_FULL; + } + } + return rc; + +failed_to_open_journal: + sqlite3BitvecDestroy(pPager->pInJournal); + pPager->pInJournal = 0; + return rc; +} + +/* +** Acquire a write-lock on the database. The lock is removed when +** the any of the following happen: +** +** * sqlite3PagerCommitPhaseTwo() is called. +** * sqlite3PagerRollback() is called. +** * sqlite3PagerClose() is called. +** * sqlite3PagerUnref() is called to on every outstanding page. +** +** The first parameter to this routine is a pointer to any open page of the +** database file. Nothing changes about the page - it is used merely to +** acquire a pointer to the Pager structure and as proof that there is +** already a read-lock on the database. +** +** The second parameter indicates how much space in bytes to reserve for a +** master journal file-name at the start of the journal when it is created. +** +** A journal file is opened if this is not a temporary file. For temporary +** files, the opening of the journal file is deferred until there is an +** actual need to write to the journal. +** +** If the database is already reserved for writing, this routine is a no-op. +** +** If exFlag is true, go ahead and get an EXCLUSIVE lock on the file +** immediately instead of waiting until we try to flush the cache. The +** exFlag is ignored if a transaction is already active. +*/ +int sqlite3PagerBegin(DbPage *pPg, int exFlag){ + Pager *pPager = pPg->pPager; + int rc = SQLITE_OK; + pagerEnter(pPager); + assert( pPg->nRef>0 ); + assert( pPager->state!=PAGER_UNLOCK ); + if( pPager->state==PAGER_SHARED ){ + assert( pPager->pInJournal==0 ); + if( MEMDB ){ + pPager->state = PAGER_EXCLUSIVE; + pPager->origDbSize = pPager->dbSize; + }else{ + rc = sqlite3OsLock(pPager->fd, RESERVED_LOCK); + if( rc==SQLITE_OK ){ + pPager->state = PAGER_RESERVED; + if( exFlag ){ + rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); + } + } + if( rc!=SQLITE_OK ){ + pagerLeave(pPager); + return rc; + } + pPager->dirtyCache = 0; + PAGERTRACE2("TRANSACTION %d\n", PAGERID(pPager)); + if( pPager->useJournal && !pPager->tempFile + && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){ + rc = pager_open_journal(pPager); + } + } + }else if( pPager->journalOpen && pPager->journalOff==0 ){ + /* This happens when the pager was in exclusive-access mode the last + ** time a (read or write) transaction was successfully concluded + ** by this connection. Instead of deleting the journal file it was + ** kept open and either was truncated to 0 bytes or its header was + ** overwritten with zeros. + */ + assert( pPager->nRec==0 ); + assert( pPager->origDbSize==0 ); + assert( pPager->pInJournal==0 ); + sqlite3PagerPagecount(pPager, 0); + pagerLeave(pPager); + pPager->pInJournal = sqlite3BitvecCreate( pPager->dbSize ); + pagerEnter(pPager); + if( !pPager->pInJournal ){ + rc = SQLITE_NOMEM; + }else{ + pPager->origDbSize = pPager->dbSize; + rc = writeJournalHdr(pPager); + } + } + assert( !pPager->journalOpen || pPager->journalOff>0 || rc!=SQLITE_OK ); + pagerLeave(pPager); + return rc; +} + +/* +** Make a page dirty. Set its dirty flag and add it to the dirty +** page list. +*/ +static void makeDirty(PgHdr *pPg){ + if( pPg->dirty==0 ){ + Pager *pPager = pPg->pPager; + pPg->dirty = 1; + pPg->pDirty = pPager->pDirty; + if( pPager->pDirty ){ + pPager->pDirty->pPrevDirty = pPg; + } + pPg->pPrevDirty = 0; + pPager->pDirty = pPg; + } +} + +/* +** Make a page clean. Clear its dirty bit and remove it from the +** dirty page list. +*/ +static void makeClean(PgHdr *pPg){ + if( pPg->dirty ){ + pPg->dirty = 0; + if( pPg->pDirty ){ + assert( pPg->pDirty->pPrevDirty==pPg ); + pPg->pDirty->pPrevDirty = pPg->pPrevDirty; + } + if( pPg->pPrevDirty ){ + assert( pPg->pPrevDirty->pDirty==pPg ); + pPg->pPrevDirty->pDirty = pPg->pDirty; + }else{ + assert( pPg->pPager->pDirty==pPg ); + pPg->pPager->pDirty = pPg->pDirty; + } + } +} + + +/* +** Mark a data page as writeable. The page is written into the journal +** if it is not there already. This routine must be called before making +** changes to a page. +** +** The first time this routine is called, the pager creates a new +** journal and acquires a RESERVED lock on the database. If the RESERVED +** lock could not be acquired, this routine returns SQLITE_BUSY. The +** calling routine must check for that return value and be careful not to +** change any page data until this routine returns SQLITE_OK. +** +** If the journal file could not be written because the disk is full, +** then this routine returns SQLITE_FULL and does an immediate rollback. +** All subsequent write attempts also return SQLITE_FULL until there +** is a call to sqlite3PagerCommit() or sqlite3PagerRollback() to +** reset. +*/ +static int pager_write(PgHdr *pPg){ + void *pData = PGHDR_TO_DATA(pPg); + Pager *pPager = pPg->pPager; + int rc = SQLITE_OK; + + /* Check for errors + */ + if( pPager->errCode ){ + return pPager->errCode; + } + if( pPager->readOnly ){ + return SQLITE_PERM; + } + + assert( !pPager->setMaster ); + + CHECK_PAGE(pPg); + + /* If this page was previously acquired with noContent==1, that means + ** we didn't really read in the content of the page. This can happen + ** (for example) when the page is being moved to the freelist. But + ** now we are (perhaps) moving the page off of the freelist for + ** reuse and we need to know its original content so that content + ** can be stored in the rollback journal. So do the read at this + ** time. + */ + rc = pager_get_content(pPg); + if( rc ){ + return rc; + } + + /* Mark the page as dirty. If the page has already been written + ** to the journal then we can return right away. + */ + makeDirty(pPg); + if( pPg->inJournal && (pageInStatement(pPg) || pPager->stmtInUse==0) ){ + pPager->dirtyCache = 1; + pPager->dbModified = 1; + }else{ + + /* If we get this far, it means that the page needs to be + ** written to the transaction journal or the ckeckpoint journal + ** or both. + ** + ** First check to see that the transaction journal exists and + ** create it if it does not. + */ + assert( pPager->state!=PAGER_UNLOCK ); + rc = sqlite3PagerBegin(pPg, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + assert( pPager->state>=PAGER_RESERVED ); + if( !pPager->journalOpen && pPager->useJournal + && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){ + rc = pager_open_journal(pPager); + if( rc!=SQLITE_OK ) return rc; + } + pPager->dirtyCache = 1; + pPager->dbModified = 1; + + /* The transaction journal now exists and we have a RESERVED or an + ** EXCLUSIVE lock on the main database file. Write the current page to + ** the transaction journal if it is not there already. + */ + if( !pPg->inJournal && (pPager->journalOpen || MEMDB) ){ + if( (int)pPg->pgno <= pPager->origDbSize ){ + if( MEMDB ){ + PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); + PAGERTRACE3("JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); + assert( pHist->pOrig==0 ); + pHist->pOrig = sqlite3PageMalloc( pPager->pageSize ); + if( !pHist->pOrig ){ + return SQLITE_NOMEM; + } + memcpy(pHist->pOrig, PGHDR_TO_DATA(pPg), pPager->pageSize); + }else{ + u32 cksum; + char *pData2; + + /* We should never write to the journal file the page that + ** contains the database locks. The following assert verifies + ** that we do not. */ + assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) ); + pData2 = CODEC2(pPager, pData, pPg->pgno, 7); + cksum = pager_cksum(pPager, (u8*)pData2); + rc = write32bits(pPager->jfd, pPager->journalOff, pPg->pgno); + if( rc==SQLITE_OK ){ + rc = sqlite3OsWrite(pPager->jfd, pData2, pPager->pageSize, + pPager->journalOff + 4); + pPager->journalOff += pPager->pageSize+4; + } + if( rc==SQLITE_OK ){ + rc = write32bits(pPager->jfd, pPager->journalOff, cksum); + pPager->journalOff += 4; + } + IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno, + pPager->journalOff, pPager->pageSize)); + PAGER_INCR(sqlite3_pager_writej_count); + PAGERTRACE5("JOURNAL %d page %d needSync=%d hash(%08x)\n", + PAGERID(pPager), pPg->pgno, pPg->needSync, pager_pagehash(pPg)); + + /* An error has occured writing to the journal file. The + ** transaction will be rolled back by the layer above. + */ + if( rc!=SQLITE_OK ){ + return rc; + } + + pPager->nRec++; + assert( pPager->pInJournal!=0 ); + sqlite3BitvecSet(pPager->pInJournal, pPg->pgno); + pPg->needSync = !pPager->noSync; + if( pPager->stmtInUse ){ + sqlite3BitvecSet(pPager->pInStmt, pPg->pgno); + } + } + }else{ + pPg->needSync = !pPager->journalStarted && !pPager->noSync; + PAGERTRACE4("APPEND %d page %d needSync=%d\n", + PAGERID(pPager), pPg->pgno, pPg->needSync); + } + if( pPg->needSync ){ + pPager->needSync = 1; + } + pPg->inJournal = 1; + } + + /* If the statement journal is open and the page is not in it, + ** then write the current page to the statement journal. Note that + ** the statement journal format differs from the standard journal format + ** in that it omits the checksums and the header. + */ + if( pPager->stmtInUse + && !pageInStatement(pPg) + && (int)pPg->pgno<=pPager->stmtSize + ){ + assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize ); + if( MEMDB ){ + PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); + assert( pHist->pStmt==0 ); + pHist->pStmt = sqlite3PageMalloc( pPager->pageSize ); + if( pHist->pStmt ){ + memcpy(pHist->pStmt, PGHDR_TO_DATA(pPg), pPager->pageSize); + } + PAGERTRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); + page_add_to_stmt_list(pPg); + }else{ + i64 offset = pPager->stmtNRec*(4+pPager->pageSize); + char *pData2 = CODEC2(pPager, pData, pPg->pgno, 7); + rc = write32bits(pPager->stfd, offset, pPg->pgno); + if( rc==SQLITE_OK ){ + rc = sqlite3OsWrite(pPager->stfd, pData2, pPager->pageSize, offset+4); + } + PAGERTRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); + if( rc!=SQLITE_OK ){ + return rc; + } + pPager->stmtNRec++; + assert( pPager->pInStmt!=0 ); + sqlite3BitvecSet(pPager->pInStmt, pPg->pgno); + } + } + } + + /* Update the database size and return. + */ + assert( pPager->state>=PAGER_SHARED ); + if( pPager->dbSize<(int)pPg->pgno ){ + pPager->dbSize = pPg->pgno; + if( !MEMDB && pPager->dbSize==PENDING_BYTE/pPager->pageSize ){ + pPager->dbSize++; + } + } + return rc; +} + +/* +** This function is used to mark a data-page as writable. It uses +** pager_write() to open a journal file (if it is not already open) +** and write the page *pData to the journal. +** +** The difference between this function and pager_write() is that this +** function also deals with the special case where 2 or more pages +** fit on a single disk sector. In this case all co-resident pages +** must have been written to the journal file before returning. +*/ +int sqlite3PagerWrite(DbPage *pDbPage){ + int rc = SQLITE_OK; + + PgHdr *pPg = pDbPage; + Pager *pPager = pPg->pPager; + Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); + + pagerEnter(pPager); + if( !MEMDB && nPagePerSector>1 ){ + Pgno nPageCount; /* Total number of pages in database file */ + Pgno pg1; /* First page of the sector pPg is located on. */ + int nPage; /* Number of pages starting at pg1 to journal */ + int ii; + int needSync = 0; + + /* Set the doNotSync flag to 1. This is because we cannot allow a journal + ** header to be written between the pages journaled by this function. + */ + assert( pPager->doNotSync==0 ); + pPager->doNotSync = 1; + + /* This trick assumes that both the page-size and sector-size are + ** an integer power of 2. It sets variable pg1 to the identifier + ** of the first page of the sector pPg is located on. + */ + pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1; + + sqlite3PagerPagecount(pPager, (int *)&nPageCount); + if( pPg->pgno>nPageCount ){ + nPage = (pPg->pgno - pg1)+1; + }else if( (pg1+nPagePerSector-1)>nPageCount ){ + nPage = nPageCount+1-pg1; + }else{ + nPage = nPagePerSector; + } + assert(nPage>0); + assert(pg1<=pPg->pgno); + assert((pg1+nPage)>pPg->pgno); + + for(ii=0; ii<nPage && rc==SQLITE_OK; ii++){ + Pgno pg = pg1+ii; + PgHdr *pPage; + if( pg==pPg->pgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){ + if( pg!=PAGER_MJ_PGNO(pPager) ){ + rc = sqlite3PagerGet(pPager, pg, &pPage); + if( rc==SQLITE_OK ){ + rc = pager_write(pPage); + if( pPage->needSync ){ + needSync = 1; + } + sqlite3PagerUnref(pPage); + } + } + }else if( (pPage = pager_lookup(pPager, pg))!=0 ){ + if( pPage->needSync ){ + needSync = 1; + } + } + } + + /* If the PgHdr.needSync flag is set for any of the nPage pages + ** starting at pg1, then it needs to be set for all of them. Because + ** writing to any of these nPage pages may damage the others, the + ** journal file must contain sync()ed copies of all of them + ** before any of them can be written out to the database file. + */ + if( needSync ){ + for(ii=0; ii<nPage && needSync; ii++){ + PgHdr *pPage = pager_lookup(pPager, pg1+ii); + if( pPage ) pPage->needSync = 1; + } + assert(pPager->needSync); + } + + assert( pPager->doNotSync==1 ); + pPager->doNotSync = 0; + }else{ + rc = pager_write(pDbPage); + } + pagerLeave(pPager); + return rc; +} + +/* +** Return TRUE if the page given in the argument was previously passed +** to sqlite3PagerWrite(). In other words, return TRUE if it is ok +** to change the content of the page. +*/ +#ifndef NDEBUG +int sqlite3PagerIswriteable(DbPage *pPg){ + return pPg->dirty; +} +#endif + +/* +** A call to this routine tells the pager that it is not necessary to +** write the information on page pPg back to the disk, even though +** that page might be marked as dirty. +** +** The overlying software layer calls this routine when all of the data +** on the given page is unused. The pager marks the page as clean so +** that it does not get written to disk. +** +** Tests show that this optimization, together with the +** sqlite3PagerDontRollback() below, more than double the speed +** of large INSERT operations and quadruple the speed of large DELETEs. +** +** When this routine is called, set the alwaysRollback flag to true. +** Subsequent calls to sqlite3PagerDontRollback() for the same page +** will thereafter be ignored. This is necessary to avoid a problem +** where a page with data is added to the freelist during one part of +** a transaction then removed from the freelist during a later part +** of the same transaction and reused for some other purpose. When it +** is first added to the freelist, this routine is called. When reused, +** the sqlite3PagerDontRollback() routine is called. But because the +** page contains critical data, we still need to be sure it gets +** rolled back in spite of the sqlite3PagerDontRollback() call. +*/ +void sqlite3PagerDontWrite(DbPage *pDbPage){ + PgHdr *pPg = pDbPage; + Pager *pPager = pPg->pPager; + + if( MEMDB ) return; + pagerEnter(pPager); + pPg->alwaysRollback = 1; + if( pPg->dirty && !pPager->stmtInUse ){ + assert( pPager->state>=PAGER_SHARED ); + if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSize<pPager->dbSize ){ + /* 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. + ** When the database file grows, we must make sure that the last page + ** gets written at least once so that the disk file will be the correct + ** size. If you do not write this page and the size of the file + ** on the disk ends up being too small, that can lead to database + ** corruption during the next transaction. + */ + }else{ + PAGERTRACE3("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager)); + IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno)) + makeClean(pPg); +#ifdef SQLITE_CHECK_PAGES + pPg->pageHash = pager_pagehash(pPg); +#endif + } + } + pagerLeave(pPager); +} + +/* +** A call to this routine tells the pager that if a rollback occurs, +** it is not necessary to restore the data on the given page. This +** means that the pager does not have to record the given page in the +** rollback journal. +** +** If we have not yet actually read the content of this page (if +** the PgHdr.needRead flag is set) then this routine acts as a promise +** that we will never need to read the page content in the future. +** so the needRead flag can be cleared at this point. +*/ +void sqlite3PagerDontRollback(DbPage *pPg){ + Pager *pPager = pPg->pPager; + + pagerEnter(pPager); + assert( pPager->state>=PAGER_RESERVED ); + + /* If the journal file is not open, or DontWrite() has been called on + ** this page (DontWrite() sets the alwaysRollback flag), then this + ** function is a no-op. + */ + if( pPager->journalOpen==0 || pPg->alwaysRollback || pPager->alwaysRollback ){ + pagerLeave(pPager); + return; + } + assert( !MEMDB ); /* For a memdb, pPager->journalOpen is always 0 */ + +#ifdef SQLITE_SECURE_DELETE + if( pPg->inJournal || (int)pPg->pgno > pPager->origDbSize ){ + return; + } +#endif + + /* If SECURE_DELETE is disabled, then there is no way that this + ** routine can be called on a page for which sqlite3PagerDontWrite() + ** has not been previously called during the same transaction. + ** And if DontWrite() has previously been called, the following + ** conditions must be met. + ** + ** (Later:) Not true. If the database is corrupted by having duplicate + ** pages on the freelist (ex: corrupt9.test) then the following is not + ** necessarily true: + */ + /* assert( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ); */ + + assert( pPager->pInJournal!=0 ); + sqlite3BitvecSet(pPager->pInJournal, pPg->pgno); + pPg->inJournal = 1; + pPg->needRead = 0; + if( pPager->stmtInUse ){ + assert( pPager->stmtSize >= pPager->origDbSize ); + sqlite3BitvecSet(pPager->pInStmt, pPg->pgno); + } + PAGERTRACE3("DONT_ROLLBACK page %d of %d\n", pPg->pgno, PAGERID(pPager)); + IOTRACE(("GARBAGE %p %d\n", pPager, pPg->pgno)) + pagerLeave(pPager); +} + + +/* +** This routine is called to increment the database file change-counter, +** stored at byte 24 of the pager file. +*/ +static int pager_incr_changecounter(Pager *pPager, int isDirect){ + PgHdr *pPgHdr; + u32 change_counter; + int rc = SQLITE_OK; + +#ifndef SQLITE_ENABLE_ATOMIC_WRITE + assert( isDirect==0 ); /* isDirect is only true for atomic writes */ +#endif + if( !pPager->changeCountDone ){ + /* Open page 1 of the file for writing. */ + rc = sqlite3PagerGet(pPager, 1, &pPgHdr); + if( rc!=SQLITE_OK ) return rc; + + if( !isDirect ){ + rc = sqlite3PagerWrite(pPgHdr); + if( rc!=SQLITE_OK ){ + sqlite3PagerUnref(pPgHdr); + return rc; + } + } + + /* Increment the value just read and write it back to byte 24. */ + change_counter = sqlite3Get4byte((u8*)pPager->dbFileVers); + change_counter++; + put32bits(((char*)PGHDR_TO_DATA(pPgHdr))+24, change_counter); + +#ifdef SQLITE_ENABLE_ATOMIC_WRITE + if( isDirect && pPager->fd->pMethods ){ + const void *zBuf = PGHDR_TO_DATA(pPgHdr); + rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0); + } +#endif + + /* Release the page reference. */ + sqlite3PagerUnref(pPgHdr); + pPager->changeCountDone = 1; + } + return rc; +} + +/* +** Sync the pager file to disk. +*/ +int sqlite3PagerSync(Pager *pPager){ + int rc; + pagerEnter(pPager); + rc = sqlite3OsSync(pPager->fd, pPager->sync_flags); + pagerLeave(pPager); + return rc; +} + +/* +** Sync the database file for the pager pPager. zMaster points to the name +** of a master journal file that should be written into the individual +** journal file. zMaster may be NULL, which is interpreted as no master +** journal (a single database transaction). +** +** This routine ensures that the journal is synced, all dirty pages written +** to the database file and the database file synced. The only thing that +** remains to commit the transaction is to delete the journal file (or +** master journal file if specified). +** +** Note that if zMaster==NULL, this does not overwrite a previous value +** passed to an sqlite3PagerCommitPhaseOne() call. +** +** If parameter nTrunc is non-zero, then the pager file is truncated to +** nTrunc pages (this is used by auto-vacuum databases). +** +** If the final parameter - noSync - is true, then the database file itself +** is not synced. The caller must call sqlite3PagerSync() directly to +** sync the database file before calling CommitPhaseTwo() to delete the +** journal file in this case. +*/ +int sqlite3PagerCommitPhaseOne( + Pager *pPager, + const char *zMaster, + Pgno nTrunc, + int noSync +){ + int rc = SQLITE_OK; + + if( pPager->errCode ){ + return pPager->errCode; + } + + /* If no changes have been made, we can leave the transaction early. + */ + if( pPager->dbModified==0 && + (pPager->journalMode!=PAGER_JOURNALMODE_DELETE || + pPager->exclusiveMode!=0) ){ + assert( pPager->dirtyCache==0 || pPager->journalOpen==0 ); + return SQLITE_OK; + } + + PAGERTRACE4("DATABASE SYNC: File=%s zMaster=%s nTrunc=%d\n", + pPager->zFilename, zMaster, nTrunc); + pagerEnter(pPager); + + /* If this is an in-memory db, or no pages have been written to, or this + ** function has already been called, it is a no-op. + */ + if( pPager->state!=PAGER_SYNCED && !MEMDB && pPager->dirtyCache ){ + PgHdr *pPg; + +#ifdef SQLITE_ENABLE_ATOMIC_WRITE + /* The atomic-write optimization can be used if all of the + ** following are true: + ** + ** + The file-system supports the atomic-write property for + ** blocks of size page-size, and + ** + This commit is not part of a multi-file transaction, and + ** + Exactly one page has been modified and store in the journal file. + ** + ** If the optimization can be used, then the journal file will never + ** be created for this transaction. + */ + int useAtomicWrite = ( + !zMaster && + pPager->journalOpen && + pPager->journalOff==jrnlBufferSize(pPager) && + nTrunc==0 && + (0==pPager->pDirty || 0==pPager->pDirty->pDirty) + ); + assert( pPager->journalOpen || pPager->journalMode==PAGER_JOURNALMODE_OFF ); + if( useAtomicWrite ){ + /* Update the nRec field in the journal file. */ + int offset = pPager->journalHdr + sizeof(aJournalMagic); + assert(pPager->nRec==1); + rc = write32bits(pPager->jfd, offset, pPager->nRec); + + /* Update the db file change counter. The following call will modify + ** the in-memory representation of page 1 to include the updated + ** change counter and then write page 1 directly to the database + ** file. Because of the atomic-write property of the host file-system, + ** this is safe. + */ + if( rc==SQLITE_OK ){ + rc = pager_incr_changecounter(pPager, 1); + } + }else{ + rc = sqlite3JournalCreate(pPager->jfd); + } + + if( !useAtomicWrite && rc==SQLITE_OK ) +#endif + + /* If a master journal file name has already been written to the + ** journal file, then no sync is required. This happens when it is + ** written, then the process fails to upgrade from a RESERVED to an + ** EXCLUSIVE lock. The next time the process tries to commit the + ** transaction the m-j name will have already been written. + */ + if( !pPager->setMaster ){ + rc = pager_incr_changecounter(pPager, 0); + if( rc!=SQLITE_OK ) goto sync_exit; + if( pPager->journalMode!=PAGER_JOURNALMODE_OFF ){ +#ifndef SQLITE_OMIT_AUTOVACUUM + if( nTrunc!=0 ){ + /* If this transaction has made the database smaller, then all pages + ** being discarded by the truncation must be written to the journal + ** file. + */ + Pgno i; + int iSkip = PAGER_MJ_PGNO(pPager); + for( i=nTrunc+1; i<=pPager->origDbSize; i++ ){ + if( !sqlite3BitvecTest(pPager->pInJournal, i) && i!=iSkip ){ + rc = sqlite3PagerGet(pPager, i, &pPg); + if( rc!=SQLITE_OK ) goto sync_exit; + rc = sqlite3PagerWrite(pPg); + sqlite3PagerUnref(pPg); + if( rc!=SQLITE_OK ) goto sync_exit; + } + } + } +#endif + rc = writeMasterJournal(pPager, zMaster); + if( rc!=SQLITE_OK ) goto sync_exit; + rc = syncJournal(pPager); + } + } + if( rc!=SQLITE_OK ) goto sync_exit; + +#ifndef SQLITE_OMIT_AUTOVACUUM + if( nTrunc!=0 ){ + rc = sqlite3PagerTruncate(pPager, nTrunc); + if( rc!=SQLITE_OK ) goto sync_exit; + } +#endif + + /* Write all dirty pages to the database file */ + pPg = pager_get_all_dirty_pages(pPager); + rc = pager_write_pagelist(pPg); + if( rc!=SQLITE_OK ){ + assert( rc!=SQLITE_IOERR_BLOCKED ); + /* The error might have left the dirty list all fouled up here, + ** but that does not matter because if the if the dirty list did + ** get corrupted, then the transaction will roll back and + ** discard the dirty list. There is an assert in + ** pager_get_all_dirty_pages() that verifies that no attempt + ** is made to use an invalid dirty list. + */ + goto sync_exit; + } + pPager->pDirty = 0; + + /* Sync the database file. */ + if( !pPager->noSync && !noSync ){ + rc = sqlite3OsSync(pPager->fd, pPager->sync_flags); + } + IOTRACE(("DBSYNC %p\n", pPager)) + + pPager->state = PAGER_SYNCED; + }else if( MEMDB && nTrunc!=0 ){ + rc = sqlite3PagerTruncate(pPager, nTrunc); + } + +sync_exit: + if( rc==SQLITE_IOERR_BLOCKED ){ + /* pager_incr_changecounter() may attempt to obtain an exclusive + * lock to spill the cache and return IOERR_BLOCKED. But since + * there is no chance the cache is inconsistent, it is + * better to return SQLITE_BUSY. + */ + rc = SQLITE_BUSY; + } + pagerLeave(pPager); + return rc; +} + + +/* +** Commit all changes to the database and release the write lock. +** +** If the commit fails for any reason, a rollback attempt is made +** and an error code is returned. If the commit worked, SQLITE_OK +** is returned. +*/ +int sqlite3PagerCommitPhaseTwo(Pager *pPager){ + int rc; + PgHdr *pPg; + + if( pPager->errCode ){ + return pPager->errCode; + } + if( pPager->state<PAGER_RESERVED ){ + return SQLITE_ERROR; + } + if( pPager->dbModified==0 && + (pPager->journalMode!=PAGER_JOURNALMODE_DELETE || + pPager->exclusiveMode!=0) ){ + assert( pPager->dirtyCache==0 || pPager->journalOpen==0 ); + return SQLITE_OK; + } + pagerEnter(pPager); + PAGERTRACE2("COMMIT %d\n", PAGERID(pPager)); + if( MEMDB ){ + pPg = pager_get_all_dirty_pages(pPager); + while( pPg ){ + PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); + clearHistory(pHist); + pPg->dirty = 0; + pPg->inJournal = 0; + pHist->inStmt = 0; + pPg->needSync = 0; + pHist->pPrevStmt = pHist->pNextStmt = 0; + pPg = pPg->pDirty; + } + pPager->pDirty = 0; +#ifndef NDEBUG + for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ + PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); + assert( !pPg->alwaysRollback ); + assert( !pHist->pOrig ); + assert( !pHist->pStmt ); + } +#endif + pPager->pStmt = 0; + pPager->state = PAGER_SHARED; + pagerLeave(pPager); + return SQLITE_OK; + } + assert( pPager->state==PAGER_SYNCED || !pPager->dirtyCache ); + rc = pager_end_transaction(pPager, pPager->setMaster); + rc = pager_error(pPager, rc); + pagerLeave(pPager); + return rc; +} + +/* +** Rollback all changes. The database falls back to PAGER_SHARED mode. +** All in-memory cache pages revert to their original data contents. +** The journal is deleted. +** +** This routine cannot fail unless some other process is not following +** the correct locking protocol or unless some other +** process is writing trash into the journal file (SQLITE_CORRUPT) or +** unless a prior malloc() failed (SQLITE_NOMEM). Appropriate error +** codes are returned for all these occasions. Otherwise, +** SQLITE_OK is returned. +*/ +int sqlite3PagerRollback(Pager *pPager){ + int rc; + PAGERTRACE2("ROLLBACK %d\n", PAGERID(pPager)); + if( MEMDB ){ + PgHdr *p; + for(p=pPager->pAll; p; p=p->pNextAll){ + PgHistory *pHist; + assert( !p->alwaysRollback ); + if( !p->dirty ){ + assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pOrig ); + assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pStmt ); + continue; + } + + pHist = PGHDR_TO_HIST(p, pPager); + if( pHist->pOrig ){ + memcpy(PGHDR_TO_DATA(p), pHist->pOrig, pPager->pageSize); + PAGERTRACE3("ROLLBACK-PAGE %d of %d\n", p->pgno, PAGERID(pPager)); + }else{ + PAGERTRACE3("PAGE %d is clean on %d\n", p->pgno, PAGERID(pPager)); + } + clearHistory(pHist); + p->dirty = 0; + p->inJournal = 0; + pHist->inStmt = 0; + pHist->pPrevStmt = pHist->pNextStmt = 0; + if( pPager->xReiniter ){ + pPager->xReiniter(p, pPager->pageSize); + } + } + pPager->pDirty = 0; + pPager->pStmt = 0; + pPager->dbSize = pPager->origDbSize; + pager_truncate_cache(pPager); + pPager->stmtInUse = 0; + pPager->state = PAGER_SHARED; + return SQLITE_OK; + } + + pagerEnter(pPager); + if( !pPager->dirtyCache || !pPager->journalOpen ){ + rc = pager_end_transaction(pPager, pPager->setMaster); + pagerLeave(pPager); + return rc; + } + + if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ + if( pPager->state>=PAGER_EXCLUSIVE ){ + pager_playback(pPager, 0); + } + pagerLeave(pPager); + return pPager->errCode; + } + if( pPager->state==PAGER_RESERVED ){ + int rc2; + rc = pager_playback(pPager, 0); + rc2 = pager_end_transaction(pPager, pPager->setMaster); + if( rc==SQLITE_OK ){ + rc = rc2; + } + }else{ + rc = pager_playback(pPager, 0); + } + /* pager_reset(pPager); */ + pPager->dbSize = -1; + + /* 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. + */ + rc = pager_error(pPager, rc); + pagerLeave(pPager); + return rc; +} + +/* +** Return TRUE if the database file is opened read-only. Return FALSE +** if the database is (in theory) writable. +*/ +int sqlite3PagerIsreadonly(Pager *pPager){ + return pPager->readOnly; +} + +/* +** Return the number of references to the pager. +*/ +int sqlite3PagerRefcount(Pager *pPager){ + return pPager->nRef; +} + +#ifdef SQLITE_TEST +/* +** This routine is used for testing and analysis only. +*/ +int *sqlite3PagerStats(Pager *pPager){ + static int a[11]; + a[0] = pPager->nRef; + a[1] = pPager->nPage; + a[2] = pPager->mxPage; + a[3] = pPager->dbSize; + a[4] = pPager->state; + a[5] = pPager->errCode; + a[6] = pPager->nHit; + a[7] = pPager->nMiss; + a[8] = 0; /* Used to be pPager->nOvfl */ + a[9] = pPager->nRead; + a[10] = pPager->nWrite; + return a; +} +int sqlite3PagerIsMemdb(Pager *pPager){ + return MEMDB; +} +#endif + +/* +** Set the statement rollback point. +** +** This routine should be called with the transaction journal already +** open. A new statement journal is created that can be used to rollback +** changes of a single SQL command within a larger transaction. +*/ +static int pagerStmtBegin(Pager *pPager){ + int rc; + assert( !pPager->stmtInUse ); + assert( pPager->state>=PAGER_SHARED ); + assert( pPager->dbSize>=0 ); + PAGERTRACE2("STMT-BEGIN %d\n", PAGERID(pPager)); + if( MEMDB ){ + pPager->stmtInUse = 1; + pPager->stmtSize = pPager->dbSize; + return SQLITE_OK; + } + if( !pPager->journalOpen ){ + pPager->stmtAutoopen = 1; + return SQLITE_OK; + } + assert( pPager->journalOpen ); + pagerLeave(pPager); + assert( pPager->pInStmt==0 ); + pPager->pInStmt = sqlite3BitvecCreate(pPager->dbSize); + pagerEnter(pPager); + if( pPager->pInStmt==0 ){ + /* sqlite3OsLock(pPager->fd, SHARED_LOCK); */ + return SQLITE_NOMEM; + } + pPager->stmtJSize = pPager->journalOff; + pPager->stmtSize = pPager->dbSize; + pPager->stmtHdrOff = 0; + pPager->stmtCksum = pPager->cksumInit; + if( !pPager->stmtOpen ){ + rc = sqlite3PagerOpentemp(pPager, pPager->stfd, SQLITE_OPEN_SUBJOURNAL); + if( rc ){ + goto stmt_begin_failed; + } + pPager->stmtOpen = 1; + pPager->stmtNRec = 0; + } + pPager->stmtInUse = 1; + return SQLITE_OK; + +stmt_begin_failed: + if( pPager->pInStmt ){ + sqlite3BitvecDestroy(pPager->pInStmt); + pPager->pInStmt = 0; + } + return rc; +} +int sqlite3PagerStmtBegin(Pager *pPager){ + int rc; + pagerEnter(pPager); + rc = pagerStmtBegin(pPager); + pagerLeave(pPager); + return rc; +} + +/* +** Commit a statement. +*/ +int sqlite3PagerStmtCommit(Pager *pPager){ + pagerEnter(pPager); + if( pPager->stmtInUse ){ + PgHdr *pPg, *pNext; + PAGERTRACE2("STMT-COMMIT %d\n", PAGERID(pPager)); + if( !MEMDB ){ + /* sqlite3OsTruncate(pPager->stfd, 0); */ + sqlite3BitvecDestroy(pPager->pInStmt); + pPager->pInStmt = 0; + }else{ + for(pPg=pPager->pStmt; pPg; pPg=pNext){ + PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); + pNext = pHist->pNextStmt; + assert( pHist->inStmt ); + pHist->inStmt = 0; + pHist->pPrevStmt = pHist->pNextStmt = 0; + sqlite3PageFree(pHist->pStmt); + pHist->pStmt = 0; + } + } + pPager->stmtNRec = 0; + pPager->stmtInUse = 0; + pPager->pStmt = 0; + } + pPager->stmtAutoopen = 0; + pagerLeave(pPager); + return SQLITE_OK; +} + +/* +** Rollback a statement. +*/ +int sqlite3PagerStmtRollback(Pager *pPager){ + int rc; + pagerEnter(pPager); + if( pPager->stmtInUse ){ + PAGERTRACE2("STMT-ROLLBACK %d\n", PAGERID(pPager)); + if( MEMDB ){ + PgHdr *pPg; + PgHistory *pHist; + for(pPg=pPager->pStmt; pPg; pPg=pHist->pNextStmt){ + pHist = PGHDR_TO_HIST(pPg, pPager); + if( pHist->pStmt ){ + memcpy(PGHDR_TO_DATA(pPg), pHist->pStmt, pPager->pageSize); + sqlite3PageFree(pHist->pStmt); + pHist->pStmt = 0; + } + } + pPager->dbSize = pPager->stmtSize; + pager_truncate_cache(pPager); + rc = SQLITE_OK; + }else{ + rc = pager_stmt_playback(pPager); + } + sqlite3PagerStmtCommit(pPager); + }else{ + rc = SQLITE_OK; + } + pPager->stmtAutoopen = 0; + pagerLeave(pPager); + return rc; +} + +/* +** Return the full pathname of the database file. +*/ +const char *sqlite3PagerFilename(Pager *pPager){ + return pPager->zFilename; +} + +/* +** Return the VFS structure for the pager. +*/ +const sqlite3_vfs *sqlite3PagerVfs(Pager *pPager){ + return pPager->pVfs; +} + +/* +** Return the file handle for the database file associated +** with the pager. This might return NULL if the file has +** not yet been opened. +*/ +sqlite3_file *sqlite3PagerFile(Pager *pPager){ + return pPager->fd; +} + +/* +** Return the directory of the database file. +*/ +const char *sqlite3PagerDirname(Pager *pPager){ + return pPager->zDirectory; +} + +/* +** Return the full pathname of the journal file. +*/ +const char *sqlite3PagerJournalname(Pager *pPager){ + return pPager->zJournal; +} + +/* +** Return true if fsync() calls are disabled for this pager. Return FALSE +** if fsync()s are executed normally. +*/ +int sqlite3PagerNosync(Pager *pPager){ + return pPager->noSync; +} + +#ifdef SQLITE_HAS_CODEC +/* +** Set the codec for this pager +*/ +void sqlite3PagerSetCodec( + Pager *pPager, + void *(*xCodec)(void*,void*,Pgno,int), + void *pCodecArg +){ + pPager->xCodec = xCodec; + pPager->pCodecArg = pCodecArg; +} +#endif + +#ifndef SQLITE_OMIT_AUTOVACUUM +/* +** Move the page pPg to location pgno in the file. +** +** There must be no references to the page previously located at +** pgno (which we call pPgOld) though that page is allowed to be +** in cache. If the page previous located at pgno is not already +** in the rollback journal, it is not put there by by this routine. +** +** References to the page pPg remain valid. Updating any +** meta-data associated with pPg (i.e. data stored in the nExtra bytes +** allocated along with the page) is the responsibility of the caller. +** +** A transaction must be active when this routine is called. It used to be +** required that a statement transaction was not active, but this restriction +** has been removed (CREATE INDEX needs to move a page when a statement +** transaction is active). +** +** If the fourth argument, isCommit, is non-zero, then this page is being +** moved as part of a database reorganization just before the transaction +** is being committed. In this case, it is guaranteed that the database page +** pPg refers to will not be written to again within this transaction. +*/ +int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){ + PgHdr *pPgOld; /* The page being overwritten. */ + int h; + Pgno needSyncPgno = 0; + + pagerEnter(pPager); + assert( pPg->nRef>0 ); + + PAGERTRACE5("MOVE %d page %d (needSync=%d) moves to %d\n", + PAGERID(pPager), pPg->pgno, pPg->needSync, pgno); + IOTRACE(("MOVE %p %d %d\n", pPager, pPg->pgno, pgno)) + + pager_get_content(pPg); + + /* If the journal needs to be sync()ed before page pPg->pgno can + ** be written to, store pPg->pgno in local variable needSyncPgno. + ** + ** If the isCommit flag is set, there is no need to remember that + ** the journal needs to be sync()ed before database page pPg->pgno + ** can be written to. The caller has already promised not to write to it. + */ + if( pPg->needSync && !isCommit ){ + needSyncPgno = pPg->pgno; + assert( pPg->inJournal || (int)pgno>pPager->origDbSize ); + assert( pPg->dirty ); + assert( pPager->needSync ); + } + + /* Unlink pPg from its hash-chain */ + unlinkHashChain(pPager, pPg); + + /* If the cache contains a page with page-number pgno, remove it + ** from its hash chain. Also, if the PgHdr.needSync was set for + ** page pgno before the 'move' operation, it needs to be retained + ** for the page moved there. + */ + pPg->needSync = 0; + pPgOld = pager_lookup(pPager, pgno); + if( pPgOld ){ + assert( pPgOld->nRef==0 ); + unlinkHashChain(pPager, pPgOld); + makeClean(pPgOld); + pPg->needSync = pPgOld->needSync; + }else{ + pPg->needSync = 0; + } + pPg->inJournal = sqlite3BitvecTest(pPager->pInJournal, pgno); + + /* Change the page number for pPg and insert it into the new hash-chain. */ + assert( pgno!=0 ); + pPg->pgno = pgno; + h = pgno & (pPager->nHash-1); + if( pPager->aHash[h] ){ + assert( pPager->aHash[h]->pPrevHash==0 ); + pPager->aHash[h]->pPrevHash = pPg; + } + pPg->pNextHash = pPager->aHash[h]; + pPager->aHash[h] = pPg; + pPg->pPrevHash = 0; + + makeDirty(pPg); + pPager->dirtyCache = 1; + pPager->dbModified = 1; + + if( needSyncPgno ){ + /* If needSyncPgno is non-zero, then the journal file needs to be + ** sync()ed before any data is written to database file page needSyncPgno. + ** Currently, no such page exists in the page-cache and the + ** "is journaled" bitvec flag has been set. This needs to be remedied by + ** loading the page into the pager-cache and setting the PgHdr.needSync + ** flag. + ** + ** If the attempt to load the page into the page-cache fails, (due + ** to a malloc() or IO failure), clear the bit in the pInJournal[] + ** array. Otherwise, if the page is loaded and written again in + ** this transaction, it may be written to the database file before + ** it is synced into the journal file. This way, it may end up in + ** the journal file twice, but that is not a problem. + ** + ** The sqlite3PagerGet() call may cause the journal to sync. So make + ** sure the Pager.needSync flag is set too. + */ + int rc; + PgHdr *pPgHdr; + assert( pPager->needSync ); + rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr); + if( rc!=SQLITE_OK ){ + if( pPager->pInJournal && (int)needSyncPgno<=pPager->origDbSize ){ + sqlite3BitvecClear(pPager->pInJournal, needSyncPgno); + } + pagerLeave(pPager); + return rc; + } + pPager->needSync = 1; + pPgHdr->needSync = 1; + pPgHdr->inJournal = 1; + makeDirty(pPgHdr); + sqlite3PagerUnref(pPgHdr); + } + + pagerLeave(pPager); + return SQLITE_OK; +} +#endif + +/* Begin preload-cache.patch for Chromium */ +/** +** When making large allocations, there is no need to stress the heap and +** potentially hold its lock while we allocate a bunch of memory. If we know +** the allocation will be large, go directly to the OS instead of the heap. +**/ +static void* allocLarge(size_t size) { +#if SQLITE_OS_WIN + return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); +#else + return sqlite3Malloc(size); +#endif +} + +static void freeLarge(void* ptr) { +#if SQLITE_OS_WIN + VirtualFree(ptr, 0, MEM_RELEASE); +#else + sqlite3_free(ptr); +#endif +} + +/** +** Addition: This will attempt to populate the database cache with +** the first N bytes of the file, where N is the total size of the cache. +** Because we can load this as one chunk from the disk, this is much faster +** than loading a subset of the pages one at a time in random order. +** +** The pager must be initialized before this function is called. This means a +* statement must be open that has initialized the pager and is keeping the +** cache in memory. +**/ +int sqlite3PagerLoadall(Pager* pPager) +{ + int i; + int rc; + int loadSize; + int loadPages; + unsigned char *fileData; + + if (pPager->dbSize < 0 || pPager->pageSize < 0) { + /* pager not initialized, this means a statement is not open */ + return SQLITE_MISUSE; + } + + /* compute sizes */ + if (pPager->mxPage < pPager->dbSize) + loadPages = pPager->mxPage; + else + loadPages = pPager->dbSize; + loadSize = loadPages * pPager->pageSize; + + /* load the file as one chunk */ + fileData = allocLarge(loadSize); + if (! fileData) + return SQLITE_NOMEM; + rc = sqlite3OsRead(pPager->fd, fileData, loadSize, 0); + if (rc != SQLITE_OK) { + freeLarge(fileData); + return rc; + } + + /* Copy the data to each page. Note that the page numbers we pass to _get + * are one-based, 0 is a marker for no page. We also need to check that we + * haven't loaded more pages than the cache can hold total. There may have + * already been a few pages loaded before, so we may fill the cache before + * loading all of the pages we want to. + */ + for(i=1; i <= loadPages && pPager->nPage < pPager->mxPage; i++) { + DbPage *pPage; + rc = sqlite3PagerAcquire2(pPager, i, &pPage, 0, + &fileData[(i-1)*(i64)pPager->pageSize]); + if (rc != SQLITE_OK) + break; + sqlite3PagerUnref(pPage); + } + freeLarge(fileData); + return SQLITE_OK; +} +/* End preload-cache.patch for Chromium */ + +/* +** Return a pointer to the data for the specified page. +*/ +void *sqlite3PagerGetData(DbPage *pPg){ + return PGHDR_TO_DATA(pPg); +} + +/* +** Return a pointer to the Pager.nExtra bytes of "extra" space +** allocated along with the specified page. +*/ +void *sqlite3PagerGetExtra(DbPage *pPg){ + Pager *pPager = pPg->pPager; + return (pPager?PGHDR_TO_EXTRA(pPg, pPager):0); +} + +/* +** Get/set the locking-mode for this pager. Parameter eMode must be one +** of PAGER_LOCKINGMODE_QUERY, PAGER_LOCKINGMODE_NORMAL or +** PAGER_LOCKINGMODE_EXCLUSIVE. If the parameter is not _QUERY, then +** the locking-mode is set to the value specified. +** +** The returned value is either PAGER_LOCKINGMODE_NORMAL or +** PAGER_LOCKINGMODE_EXCLUSIVE, indicating the current (possibly updated) +** locking-mode. +*/ +int sqlite3PagerLockingMode(Pager *pPager, int eMode){ + assert( eMode==PAGER_LOCKINGMODE_QUERY + || eMode==PAGER_LOCKINGMODE_NORMAL + || eMode==PAGER_LOCKINGMODE_EXCLUSIVE ); + assert( PAGER_LOCKINGMODE_QUERY<0 ); + assert( PAGER_LOCKINGMODE_NORMAL>=0 && PAGER_LOCKINGMODE_EXCLUSIVE>=0 ); + if( eMode>=0 && !pPager->tempFile ){ + pPager->exclusiveMode = eMode; + } + return (int)pPager->exclusiveMode; +} + +/* +** Get/set the journal-mode for this pager. Parameter eMode must be one +** of PAGER_JOURNALMODE_QUERY, PAGER_JOURNALMODE_DELETE or +** PAGER_JOURNALMODE_PERSIST. If the parameter is not _QUERY, then +** the journal-mode is set to the value specified. +** +** The returned value is either PAGER_JOURNALMODE_DELETE or +** PAGER_JOURNALMODE_PERSIST, indicating the current (possibly updated) +** journal-mode. +*/ +int sqlite3PagerJournalMode(Pager *pPager, int eMode){ + assert( eMode==PAGER_JOURNALMODE_QUERY + || eMode==PAGER_JOURNALMODE_DELETE + || eMode==PAGER_JOURNALMODE_PERSIST + || eMode==PAGER_JOURNALMODE_OFF ); + assert( PAGER_JOURNALMODE_QUERY<0 ); + assert( PAGER_JOURNALMODE_DELETE>=0 && PAGER_JOURNALMODE_PERSIST>=0 ); + if( eMode>=0 ){ + pPager->journalMode = eMode; + } + return (int)pPager->journalMode; +} + +/* +** Get/set the size-limit used for persistent journal files. +*/ +i64 sqlite3PagerJournalSizeLimit(Pager *pPager, i64 iLimit){ + if( iLimit>=-1 ){ + pPager->journalSizeLimit = iLimit; + } + return pPager->journalSizeLimit; +} + +#endif /* SQLITE_OMIT_DISKIO */ diff --git a/third_party/sqlite/src/pager.h b/third_party/sqlite/src/pager.h new file mode 100755 index 0000000..9c989c3 --- /dev/null +++ b/third_party/sqlite/src/pager.h @@ -0,0 +1,146 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This header file defines the interface that the sqlite page cache +** 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.77 2008/07/16 18:17:56 danielk1977 Exp $ +*/ + +#ifndef _PAGER_H_ +#define _PAGER_H_ + +/* +** If defined as non-zero, auto-vacuum is enabled by default. Otherwise +** it must be turned on for each database using "PRAGMA auto_vacuum = 1". +*/ +#ifndef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT + #define SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT -1 +#endif + +/* +** The type used to represent a page number. The first page in a file +** is called page 1. 0 is used to represent "not a page". +*/ +typedef u32 Pgno; + +/* +** Each open file is managed by a separate instance of the "Pager" structure. +*/ +typedef struct Pager Pager; + +/* +** Handle type for pages. +*/ +typedef struct PgHdr DbPage; + +/* +** Allowed values for the flags parameter to sqlite3PagerOpen(). +** +** NOTE: This values must match the corresponding BTREE_ values in btree.h. +*/ +#define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */ +#define PAGER_NO_READLOCK 0x0002 /* Omit readlocks on readonly files */ + +/* +** Valid values for the second argument to sqlite3PagerLockingMode(). +*/ +#define PAGER_LOCKINGMODE_QUERY -1 +#define PAGER_LOCKINGMODE_NORMAL 0 +#define PAGER_LOCKINGMODE_EXCLUSIVE 1 + +/* +** Valid values for the second argument to sqlite3PagerJournalMode(). +*/ +#define PAGER_JOURNALMODE_QUERY -1 +#define PAGER_JOURNALMODE_DELETE 0 /* Commit by deleting journal file */ +#define PAGER_JOURNALMODE_PERSIST 1 /* Commit by zeroing journal header */ +#define PAGER_JOURNALMODE_OFF 2 /* Journal omitted. */ + +/* +** See source code comments for a detailed description of the following +** routines: +*/ +int sqlite3PagerOpen(sqlite3_vfs *, Pager **ppPager, const char*, int,int,int); +void sqlite3PagerSetBusyhandler(Pager*, BusyHandler *pBusyHandler); +void sqlite3PagerSetDestructor(Pager*, void(*)(DbPage*,int)); +void sqlite3PagerSetReiniter(Pager*, void(*)(DbPage*,int)); +int sqlite3PagerSetPagesize(Pager*, u16*); +int sqlite3PagerMaxPageCount(Pager*, int); +int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); +void sqlite3PagerSetCachesize(Pager*, int); +int sqlite3PagerClose(Pager *pPager); +int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag); +#define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0) +DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno); +int sqlite3PagerRef(DbPage*); +int sqlite3PagerUnref(DbPage*); +int sqlite3PagerWrite(DbPage*); +int sqlite3PagerPagecount(Pager*, int*); +int sqlite3PagerTruncate(Pager*,Pgno); +int sqlite3PagerBegin(DbPage*, int exFlag); +int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, Pgno, int); +int sqlite3PagerCommitPhaseTwo(Pager*); +int sqlite3PagerRollback(Pager*); +int sqlite3PagerIsreadonly(Pager*); +int sqlite3PagerStmtBegin(Pager*); +int sqlite3PagerStmtCommit(Pager*); +int sqlite3PagerStmtRollback(Pager*); +void sqlite3PagerDontRollback(DbPage*); +void sqlite3PagerDontWrite(DbPage*); +int sqlite3PagerRefcount(Pager*); +void sqlite3PagerSetSafetyLevel(Pager*,int,int); +const char *sqlite3PagerFilename(Pager*); +const sqlite3_vfs *sqlite3PagerVfs(Pager*); +sqlite3_file *sqlite3PagerFile(Pager*); +const char *sqlite3PagerDirname(Pager*); +const char *sqlite3PagerJournalname(Pager*); +int sqlite3PagerNosync(Pager*); +int sqlite3PagerMovepage(Pager*,DbPage*,Pgno,int); +void *sqlite3PagerGetData(DbPage *); +void *sqlite3PagerGetExtra(DbPage *); +int sqlite3PagerLockingMode(Pager *, int); +/* This function is for preload-cache.patch for Chromium: */ +int sqlite3PagerLoadall(Pager*); +int sqlite3PagerJournalMode(Pager *, int); +i64 sqlite3PagerJournalSizeLimit(Pager *, i64); +void *sqlite3PagerTempSpace(Pager*); +int sqlite3PagerSync(Pager *pPager); + +#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO) + int sqlite3PagerReleaseMemory(int); +#endif + +#ifdef SQLITE_HAS_CODEC + void sqlite3PagerSetCodec(Pager*,void*(*)(void*,void*,Pgno,int),void*); +#endif + +#if !defined(NDEBUG) || defined(SQLITE_TEST) + Pgno sqlite3PagerPagenumber(DbPage*); + int sqlite3PagerIswriteable(DbPage*); +#endif + +#ifdef SQLITE_TEST + int *sqlite3PagerStats(Pager*); + void sqlite3PagerRefdump(Pager*); + int sqlite3PagerIsMemdb(Pager*); +#endif + +#ifdef SQLITE_TEST +void disable_simulated_io_errors(void); +void enable_simulated_io_errors(void); +#else +# define disable_simulated_io_errors() +# define enable_simulated_io_errors() +#endif + +#endif /* _PAGER_H_ */ diff --git a/third_party/sqlite/src/parse.y b/third_party/sqlite/src/parse.y new file mode 100755 index 0000000..3ff8d65 --- /dev/null +++ b/third_party/sqlite/src/parse.y @@ -0,0 +1,1122 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains SQLite's grammar for SQL. Process this file +** using the lemon parser generator to generate C code that runs +** the parser. Lemon will also generate a header file containing +** numeric codes for all of the tokens. +** +** @(#) $Id: parse.y,v 1.248 2008/07/31 01:40:42 shane Exp $ +*/ + +// All token codes are small integers with #defines that begin with "TK_" +%token_prefix TK_ + +// The type of the data attached to each token is Token. This is also the +// default type for non-terminals. +// +%token_type {Token} +%default_type {Token} + +// The generated parser function takes a 4th argument as follows: +%extra_argument {Parse *pParse} + +// This code runs whenever there is a syntax error +// +%syntax_error { + assert( TOKEN.z[0] ); /* The tokenizer always gives us a token */ + sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN); + pParse->parseError = 1; +} +%stack_overflow { + sqlite3ErrorMsg(pParse, "parser stack overflow"); + pParse->parseError = 1; +} + +// The name of the generated procedure that implements the parser +// is as follows: +%name sqlite3Parser + +// The following text is included near the beginning of the C source +// code file that implements the parser. +// +%include { +#include "sqliteInt.h" + +/* +** An instance of this structure holds information about the +** LIMIT clause of a SELECT statement. +*/ +struct LimitVal { + Expr *pLimit; /* The LIMIT expression. NULL if there is no limit */ + Expr *pOffset; /* The OFFSET expression. NULL if there is none */ +}; + +/* +** An instance of this structure is used to store the LIKE, +** GLOB, NOT LIKE, and NOT GLOB operators. +*/ +struct LikeOp { + Token eOperator; /* "like" or "glob" or "regexp" */ + int not; /* True if the NOT keyword is present */ +}; + +/* +** An instance of the following structure describes the event of a +** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT, +** TK_DELETE, or TK_INSTEAD. If the event is of the form +** +** UPDATE ON (a,b,c) +** +** Then the "b" IdList records the list "a,b,c". +*/ +struct TrigEvent { int a; IdList * b; }; + +/* +** An instance of this structure holds the ATTACH key and the key type. +*/ +struct AttachKey { int type; Token key; }; + +} // end %include + +// Input is a single SQL command +input ::= cmdlist. +cmdlist ::= cmdlist ecmd. +cmdlist ::= ecmd. +cmdx ::= cmd. { sqlite3FinishCoding(pParse); } +ecmd ::= SEMI. +ecmd ::= explain cmdx SEMI. +explain ::= . { sqlite3BeginParse(pParse, 0); } +%ifndef SQLITE_OMIT_EXPLAIN +explain ::= EXPLAIN. { sqlite3BeginParse(pParse, 1); } +explain ::= EXPLAIN QUERY PLAN. { sqlite3BeginParse(pParse, 2); } +%endif SQLITE_OMIT_EXPLAIN + +///////////////////// Begin and end transactions. //////////////////////////// +// + +cmd ::= BEGIN transtype(Y) trans_opt. {sqlite3BeginTransaction(pParse, Y);} +trans_opt ::= . +trans_opt ::= TRANSACTION. +trans_opt ::= TRANSACTION nm. +%type transtype {int} +%ifdef SQLITE_TRANSACTION_DEFAULT_IMMEDIATE +transtype(A) ::= . {A = TK_IMMEDIATE;} +%endif SQLITE_TRANSACTION_DEFAULT_IMMEDIATE +%ifndef SQLITE_TRANSACTION_DEFAULT_IMMEDIATE +transtype(A) ::= . {A = TK_DEFERRED;} +%endif SQLITE_TRANSACTION_DEFAULT_IMMEDIATE +transtype(A) ::= DEFERRED(X). {A = @X;} +transtype(A) ::= IMMEDIATE(X). {A = @X;} +transtype(A) ::= EXCLUSIVE(X). {A = @X;} +cmd ::= COMMIT trans_opt. {sqlite3CommitTransaction(pParse);} +cmd ::= END trans_opt. {sqlite3CommitTransaction(pParse);} +cmd ::= ROLLBACK trans_opt. {sqlite3RollbackTransaction(pParse);} + +///////////////////// The CREATE TABLE statement //////////////////////////// +// +cmd ::= create_table create_table_args. +create_table ::= CREATE temp(T) TABLE ifnotexists(E) nm(Y) dbnm(Z). { + sqlite3StartTable(pParse,&Y,&Z,T,0,0,E); +} +%type ifnotexists {int} +ifnotexists(A) ::= . {A = 0;} +ifnotexists(A) ::= IF NOT EXISTS. {A = 1;} +%type temp {int} +%ifndef SQLITE_OMIT_TEMPDB +temp(A) ::= TEMP. {A = 1;} +%endif SQLITE_OMIT_TEMPDB +temp(A) ::= . {A = 0;} +create_table_args ::= LP columnlist conslist_opt(X) RP(Y). { + sqlite3EndTable(pParse,&X,&Y,0); +} +create_table_args ::= AS select(S). { + sqlite3EndTable(pParse,0,0,S); + sqlite3SelectDelete(pParse->db, S); +} +columnlist ::= columnlist COMMA column. +columnlist ::= column. + +// A "column" is a complete description of a single column in a +// CREATE TABLE statement. This includes the column name, its +// datatype, and other keywords such as PRIMARY KEY, UNIQUE, REFERENCES, +// NOT NULL and so forth. +// +column(A) ::= columnid(X) type carglist. { + A.z = X.z; + A.n = (pParse->sLastToken.z-X.z) + pParse->sLastToken.n; +} +columnid(A) ::= nm(X). { + sqlite3AddColumn(pParse,&X); + A = X; +} + + +// An IDENTIFIER can be a generic identifier, or one of several +// keywords. Any non-standard keyword can also be an identifier. +// +%type id {Token} +id(A) ::= ID(X). {A = X;} + +// The following directive causes tokens ABORT, AFTER, ASC, etc. to +// fallback to ID if they will not parse as their original value. +// This obviates the need for the "id" nonterminal. +// +%fallback ID + ABORT AFTER ANALYZE ASC ATTACH BEFORE BEGIN CASCADE CAST CONFLICT + DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR + IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH PLAN + QUERY KEY OF OFFSET PRAGMA RAISE REPLACE RESTRICT ROW + TEMP TRIGGER VACUUM VIEW VIRTUAL +%ifdef SQLITE_OMIT_COMPOUND_SELECT + EXCEPT INTERSECT UNION +%endif SQLITE_OMIT_COMPOUND_SELECT + REINDEX RENAME CTIME_KW IF + . +%wildcard ANY. + +// Define operator precedence early so that this is the first occurance +// of the operator tokens in the grammer. Keeping the operators together +// causes them to be assigned integer values that are close together, +// which keeps parser tables smaller. +// +// The token values assigned to these symbols is determined by the order +// in which lemon first sees them. It must be the case that ISNULL/NOTNULL, +// NE/EQ, GT/LE, and GE/LT are separated by only a single value. See +// the sqlite3ExprIfFalse() routine for additional information on this +// constraint. +// +%left OR. +%left AND. +%right NOT. +%left IS MATCH LIKE_KW BETWEEN IN ISNULL NOTNULL NE EQ. +%left GT LE LT GE. +%right ESCAPE. +%left BITAND BITOR LSHIFT RSHIFT. +%left PLUS MINUS. +%left STAR SLASH REM. +%left CONCAT. +%left COLLATE. +%right UMINUS UPLUS BITNOT. + +// And "ids" is an identifer-or-string. +// +%type ids {Token} +ids(A) ::= ID|STRING(X). {A = X;} + +// The name of a column or table can be any of the following: +// +%type nm {Token} +nm(A) ::= ID(X). {A = X;} +nm(A) ::= STRING(X). {A = X;} +nm(A) ::= JOIN_KW(X). {A = X;} + +// A typetoken is really one or more tokens that form a type name such +// as can be found after the column name in a CREATE TABLE statement. +// Multiple tokens are concatenated to form the value of the typetoken. +// +%type typetoken {Token} +type ::= . +type ::= typetoken(X). {sqlite3AddColumnType(pParse,&X);} +typetoken(A) ::= typename(X). {A = X;} +typetoken(A) ::= typename(X) LP signed RP(Y). { + A.z = X.z; + A.n = &Y.z[Y.n] - X.z; +} +typetoken(A) ::= typename(X) LP signed COMMA signed RP(Y). { + A.z = X.z; + A.n = &Y.z[Y.n] - X.z; +} +%type typename {Token} +typename(A) ::= ids(X). {A = X;} +typename(A) ::= typename(X) ids(Y). {A.z=X.z; A.n=Y.n+(Y.z-X.z);} +signed ::= plus_num. +signed ::= minus_num. + +// "carglist" is a list of additional constraints that come after the +// column name and column type in a CREATE TABLE statement. +// +carglist ::= carglist carg. +carglist ::= . +carg ::= CONSTRAINT nm ccons. +carg ::= ccons. +ccons ::= DEFAULT term(X). {sqlite3AddDefaultValue(pParse,X);} +ccons ::= DEFAULT LP expr(X) RP. {sqlite3AddDefaultValue(pParse,X);} +ccons ::= DEFAULT PLUS term(X). {sqlite3AddDefaultValue(pParse,X);} +ccons ::= DEFAULT MINUS term(X). { + Expr *p = sqlite3PExpr(pParse, TK_UMINUS, X, 0, 0); + sqlite3AddDefaultValue(pParse,p); +} +ccons ::= DEFAULT id(X). { + Expr *p = sqlite3PExpr(pParse, TK_STRING, 0, 0, &X); + sqlite3AddDefaultValue(pParse,p); +} + +// In addition to the type name, we also care about the primary key and +// UNIQUE constraints. +// +ccons ::= NULL onconf. +ccons ::= NOT NULL onconf(R). {sqlite3AddNotNull(pParse, R);} +ccons ::= PRIMARY KEY sortorder(Z) onconf(R) autoinc(I). + {sqlite3AddPrimaryKey(pParse,0,R,I,Z);} +ccons ::= UNIQUE onconf(R). {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0,0,0);} +ccons ::= CHECK LP expr(X) RP. {sqlite3AddCheckConstraint(pParse,X);} +ccons ::= REFERENCES nm(T) idxlist_opt(TA) refargs(R). + {sqlite3CreateForeignKey(pParse,0,&T,TA,R);} +ccons ::= defer_subclause(D). {sqlite3DeferForeignKey(pParse,D);} +ccons ::= COLLATE ids(C). {sqlite3AddCollateType(pParse, &C);} + +// The optional AUTOINCREMENT keyword +%type autoinc {int} +autoinc(X) ::= . {X = 0;} +autoinc(X) ::= AUTOINCR. {X = 1;} + +// The next group of rules parses the arguments to a REFERENCES clause +// that determine if the referential integrity checking is deferred or +// or immediate and which determine what action to take if a ref-integ +// check fails. +// +%type refargs {int} +refargs(A) ::= . { A = OE_Restrict * 0x010101; } +refargs(A) ::= refargs(X) refarg(Y). { A = (X & Y.mask) | Y.value; } +%type refarg {struct {int value; int mask;}} +refarg(A) ::= MATCH nm. { A.value = 0; A.mask = 0x000000; } +refarg(A) ::= ON DELETE refact(X). { A.value = X; A.mask = 0x0000ff; } +refarg(A) ::= ON UPDATE refact(X). { A.value = X<<8; A.mask = 0x00ff00; } +refarg(A) ::= ON INSERT refact(X). { A.value = X<<16; A.mask = 0xff0000; } +%type refact {int} +refact(A) ::= SET NULL. { A = OE_SetNull; } +refact(A) ::= SET DEFAULT. { A = OE_SetDflt; } +refact(A) ::= CASCADE. { A = OE_Cascade; } +refact(A) ::= RESTRICT. { A = OE_Restrict; } +%type defer_subclause {int} +defer_subclause(A) ::= NOT DEFERRABLE init_deferred_pred_opt(X). {A = X;} +defer_subclause(A) ::= DEFERRABLE init_deferred_pred_opt(X). {A = X;} +%type init_deferred_pred_opt {int} +init_deferred_pred_opt(A) ::= . {A = 0;} +init_deferred_pred_opt(A) ::= INITIALLY DEFERRED. {A = 1;} +init_deferred_pred_opt(A) ::= INITIALLY IMMEDIATE. {A = 0;} + +// For the time being, the only constraint we care about is the primary +// key and UNIQUE. Both create indices. +// +conslist_opt(A) ::= . {A.n = 0; A.z = 0;} +conslist_opt(A) ::= COMMA(X) conslist. {A = X;} +conslist ::= conslist COMMA tcons. +conslist ::= conslist tcons. +conslist ::= tcons. +tcons ::= CONSTRAINT nm. +tcons ::= PRIMARY KEY LP idxlist(X) autoinc(I) RP onconf(R). + {sqlite3AddPrimaryKey(pParse,X,R,I,0);} +tcons ::= UNIQUE LP idxlist(X) RP onconf(R). + {sqlite3CreateIndex(pParse,0,0,0,X,R,0,0,0,0);} +tcons ::= CHECK LP expr(E) RP onconf. {sqlite3AddCheckConstraint(pParse,E);} +tcons ::= FOREIGN KEY LP idxlist(FA) RP + REFERENCES nm(T) idxlist_opt(TA) refargs(R) defer_subclause_opt(D). { + sqlite3CreateForeignKey(pParse, FA, &T, TA, R); + sqlite3DeferForeignKey(pParse, D); +} +%type defer_subclause_opt {int} +defer_subclause_opt(A) ::= . {A = 0;} +defer_subclause_opt(A) ::= defer_subclause(X). {A = X;} + +// The following is a non-standard extension that allows us to declare the +// default behavior when there is a constraint conflict. +// +%type onconf {int} +%type orconf {int} +%type resolvetype {int} +onconf(A) ::= . {A = OE_Default;} +onconf(A) ::= ON CONFLICT resolvetype(X). {A = X;} +orconf(A) ::= . {A = OE_Default;} +orconf(A) ::= OR resolvetype(X). {A = X;} +resolvetype(A) ::= raisetype(X). {A = X;} +resolvetype(A) ::= IGNORE. {A = OE_Ignore;} +resolvetype(A) ::= REPLACE. {A = OE_Replace;} + +////////////////////////// The DROP TABLE ///////////////////////////////////// +// +cmd ::= DROP TABLE ifexists(E) fullname(X). { + sqlite3DropTable(pParse, X, 0, E); +} +%type ifexists {int} +ifexists(A) ::= IF EXISTS. {A = 1;} +ifexists(A) ::= . {A = 0;} + +///////////////////// The CREATE VIEW statement ///////////////////////////// +// +%ifndef SQLITE_OMIT_VIEW +cmd ::= CREATE(X) temp(T) VIEW ifnotexists(E) nm(Y) dbnm(Z) AS select(S). { + sqlite3CreateView(pParse, &X, &Y, &Z, S, T, E); +} +cmd ::= DROP VIEW ifexists(E) fullname(X). { + sqlite3DropTable(pParse, X, 1, E); +} +%endif SQLITE_OMIT_VIEW + +//////////////////////// The SELECT statement ///////////////////////////////// +// +cmd ::= select(X). { + SelectDest dest = {SRT_Callback, 0, 0, 0, 0}; + sqlite3Select(pParse, X, &dest, 0, 0, 0); + sqlite3SelectDelete(pParse->db, X); +} + +%type select {Select*} +%destructor select {sqlite3SelectDelete(pParse->db, $$);} +%type oneselect {Select*} +%destructor oneselect {sqlite3SelectDelete(pParse->db, $$);} + +select(A) ::= oneselect(X). {A = X;} +%ifndef SQLITE_OMIT_COMPOUND_SELECT +select(A) ::= select(X) multiselect_op(Y) oneselect(Z). { + if( Z ){ + Z->op = Y; + Z->pPrior = X; + }else{ + sqlite3SelectDelete(pParse->db, X); + } + A = Z; +} +%type multiselect_op {int} +multiselect_op(A) ::= UNION(OP). {A = @OP;} +multiselect_op(A) ::= UNION ALL. {A = TK_ALL;} +multiselect_op(A) ::= EXCEPT|INTERSECT(OP). {A = @OP;} +%endif SQLITE_OMIT_COMPOUND_SELECT +oneselect(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y) + groupby_opt(P) having_opt(Q) orderby_opt(Z) limit_opt(L). { + A = sqlite3SelectNew(pParse,W,X,Y,P,Q,Z,D,L.pLimit,L.pOffset); +} + +// The "distinct" nonterminal is true (1) if the DISTINCT keyword is +// present and false (0) if it is not. +// +%type distinct {int} +distinct(A) ::= DISTINCT. {A = 1;} +distinct(A) ::= ALL. {A = 0;} +distinct(A) ::= . {A = 0;} + +// selcollist is a list of expressions that are to become the return +// values of the SELECT statement. The "*" in statements like +// "SELECT * FROM ..." is encoded as a special expression with an +// opcode of TK_ALL. +// +%type selcollist {ExprList*} +%destructor selcollist {sqlite3ExprListDelete(pParse->db, $$);} +%type sclp {ExprList*} +%destructor sclp {sqlite3ExprListDelete(pParse->db, $$);} +sclp(A) ::= selcollist(X) COMMA. {A = X;} +sclp(A) ::= . {A = 0;} +selcollist(A) ::= sclp(P) expr(X) as(Y). { + A = sqlite3ExprListAppend(pParse,P,X,Y.n?&Y:0); +} +selcollist(A) ::= sclp(P) STAR. { + Expr *p = sqlite3PExpr(pParse, TK_ALL, 0, 0, 0); + A = sqlite3ExprListAppend(pParse, P, p, 0); +} +selcollist(A) ::= sclp(P) nm(X) DOT STAR(Y). { + Expr *pRight = sqlite3PExpr(pParse, TK_ALL, 0, 0, &Y); + Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &X); + Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); + A = sqlite3ExprListAppend(pParse,P, pDot, 0); +} + +// An option "AS <id>" phrase that can follow one of the expressions that +// define the result set, or one of the tables in the FROM clause. +// +%type as {Token} +as(X) ::= AS nm(Y). {X = Y;} +as(X) ::= ids(Y). {X = Y;} +as(X) ::= . {X.n = 0;} + + +%type seltablist {SrcList*} +%destructor seltablist {sqlite3SrcListDelete(pParse->db, $$);} +%type stl_prefix {SrcList*} +%destructor stl_prefix {sqlite3SrcListDelete(pParse->db, $$);} +%type from {SrcList*} +%destructor from {sqlite3SrcListDelete(pParse->db, $$);} + +// A complete FROM clause. +// +from(A) ::= . {A = sqlite3DbMallocZero(pParse->db, sizeof(*A));} +from(A) ::= FROM seltablist(X). { + A = X; + sqlite3SrcListShiftJoinType(A); +} + +// "seltablist" is a "Select Table List" - the content of the FROM clause +// in a SELECT statement. "stl_prefix" is a prefix of this list. +// +stl_prefix(A) ::= seltablist(X) joinop(Y). { + A = X; + if( A && A->nSrc>0 ) A->a[A->nSrc-1].jointype = Y; +} +stl_prefix(A) ::= . {A = 0;} +seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) as(Z) on_opt(N) using_opt(U). { + A = sqlite3SrcListAppendFromTerm(pParse,X,&Y,&D,&Z,0,N,U); +} +%ifndef SQLITE_OMIT_SUBQUERY + seltablist(A) ::= stl_prefix(X) LP seltablist_paren(S) RP + as(Z) on_opt(N) using_opt(U). { + A = sqlite3SrcListAppendFromTerm(pParse,X,0,0,&Z,S,N,U); + } + + // A seltablist_paren nonterminal represents anything in a FROM that + // is contained inside parentheses. This can be either a subquery or + // a grouping of table and subqueries. + // + %type seltablist_paren {Select*} + %destructor seltablist_paren {sqlite3SelectDelete(pParse->db, $$);} + seltablist_paren(A) ::= select(S). {A = S;} + seltablist_paren(A) ::= seltablist(F). { + sqlite3SrcListShiftJoinType(F); + A = sqlite3SelectNew(pParse,0,F,0,0,0,0,0,0,0); + } +%endif SQLITE_OMIT_SUBQUERY + +%type dbnm {Token} +dbnm(A) ::= . {A.z=0; A.n=0;} +dbnm(A) ::= DOT nm(X). {A = X;} + +%type fullname {SrcList*} +%destructor fullname {sqlite3SrcListDelete(pParse->db, $$);} +fullname(A) ::= nm(X) dbnm(Y). {A = sqlite3SrcListAppend(pParse->db,0,&X,&Y);} + +%type joinop {int} +%type joinop2 {int} +joinop(X) ::= COMMA|JOIN. { X = JT_INNER; } +joinop(X) ::= JOIN_KW(A) JOIN. { X = sqlite3JoinType(pParse,&A,0,0); } +joinop(X) ::= JOIN_KW(A) nm(B) JOIN. { X = sqlite3JoinType(pParse,&A,&B,0); } +joinop(X) ::= JOIN_KW(A) nm(B) nm(C) JOIN. + { X = sqlite3JoinType(pParse,&A,&B,&C); } + +%type on_opt {Expr*} +%destructor on_opt {sqlite3ExprDelete(pParse->db, $$);} +on_opt(N) ::= ON expr(E). {N = E;} +on_opt(N) ::= . {N = 0;} + +%type using_opt {IdList*} +%destructor using_opt {sqlite3IdListDelete(pParse->db, $$);} +using_opt(U) ::= USING LP inscollist(L) RP. {U = L;} +using_opt(U) ::= . {U = 0;} + + +%type orderby_opt {ExprList*} +%destructor orderby_opt {sqlite3ExprListDelete(pParse->db, $$);} +%type sortlist {ExprList*} +%destructor sortlist {sqlite3ExprListDelete(pParse->db, $$);} +%type sortitem {Expr*} +%destructor sortitem {sqlite3ExprDelete(pParse->db, $$);} + +orderby_opt(A) ::= . {A = 0;} +orderby_opt(A) ::= ORDER BY sortlist(X). {A = X;} +sortlist(A) ::= sortlist(X) COMMA sortitem(Y) sortorder(Z). { + A = sqlite3ExprListAppend(pParse,X,Y,0); + if( A ) A->a[A->nExpr-1].sortOrder = Z; +} +sortlist(A) ::= sortitem(Y) sortorder(Z). { + A = sqlite3ExprListAppend(pParse,0,Y,0); + if( A && A->a ) A->a[0].sortOrder = Z; +} +sortitem(A) ::= expr(X). {A = X;} + +%type sortorder {int} + +sortorder(A) ::= ASC. {A = SQLITE_SO_ASC;} +sortorder(A) ::= DESC. {A = SQLITE_SO_DESC;} +sortorder(A) ::= . {A = SQLITE_SO_ASC;} + +%type groupby_opt {ExprList*} +%destructor groupby_opt {sqlite3ExprListDelete(pParse->db, $$);} +groupby_opt(A) ::= . {A = 0;} +groupby_opt(A) ::= GROUP BY nexprlist(X). {A = X;} + +%type having_opt {Expr*} +%destructor having_opt {sqlite3ExprDelete(pParse->db, $$);} +having_opt(A) ::= . {A = 0;} +having_opt(A) ::= HAVING expr(X). {A = X;} + +%type limit_opt {struct LimitVal} + +// The destructor for limit_opt will never fire in the current grammar. +// The limit_opt non-terminal only occurs at the end of a single production +// rule for SELECT statements. As soon as the rule that create the +// limit_opt non-terminal reduces, the SELECT statement rule will also +// reduce. So there is never a limit_opt non-terminal on the stack +// except as a transient. So there is never anything to destroy. +// +//%destructor limit_opt { +// sqlite3ExprDelete(pParse->db, $$.pLimit); +// sqlite3ExprDelete(pParse->db, $$.pOffset); +//} +limit_opt(A) ::= . {A.pLimit = 0; A.pOffset = 0;} +limit_opt(A) ::= LIMIT expr(X). {A.pLimit = X; A.pOffset = 0;} +limit_opt(A) ::= LIMIT expr(X) OFFSET expr(Y). + {A.pLimit = X; A.pOffset = Y;} +limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y). + {A.pOffset = X; A.pLimit = Y;} + +/////////////////////////// The DELETE statement ///////////////////////////// +// +cmd ::= DELETE FROM fullname(X) where_opt(Y). {sqlite3DeleteFrom(pParse,X,Y);} + +%type where_opt {Expr*} +%destructor where_opt {sqlite3ExprDelete(pParse->db, $$);} + +where_opt(A) ::= . {A = 0;} +where_opt(A) ::= WHERE expr(X). {A = X;} + +////////////////////////// The UPDATE command //////////////////////////////// +// +cmd ::= UPDATE orconf(R) fullname(X) SET setlist(Y) where_opt(Z). { + sqlite3ExprListCheckLength(pParse,Y,"set list"); + sqlite3Update(pParse,X,Y,Z,R); +} + +%type setlist {ExprList*} +%destructor setlist {sqlite3ExprListDelete(pParse->db, $$);} + +setlist(A) ::= setlist(Z) COMMA nm(X) EQ expr(Y). + {A = sqlite3ExprListAppend(pParse,Z,Y,&X);} +setlist(A) ::= nm(X) EQ expr(Y). + {A = sqlite3ExprListAppend(pParse,0,Y,&X);} + +////////////////////////// The INSERT command ///////////////////////////////// +// +cmd ::= insert_cmd(R) INTO fullname(X) inscollist_opt(F) + VALUES LP itemlist(Y) RP. + {sqlite3Insert(pParse, X, Y, 0, F, R);} +cmd ::= insert_cmd(R) INTO fullname(X) inscollist_opt(F) select(S). + {sqlite3Insert(pParse, X, 0, S, F, R);} +cmd ::= insert_cmd(R) INTO fullname(X) inscollist_opt(F) DEFAULT VALUES. + {sqlite3Insert(pParse, X, 0, 0, F, R);} + +%type insert_cmd {int} +insert_cmd(A) ::= INSERT orconf(R). {A = R;} +insert_cmd(A) ::= REPLACE. {A = OE_Replace;} + + +%type itemlist {ExprList*} +%destructor itemlist {sqlite3ExprListDelete(pParse->db, $$);} + +itemlist(A) ::= itemlist(X) COMMA expr(Y). + {A = sqlite3ExprListAppend(pParse,X,Y,0);} +itemlist(A) ::= expr(X). + {A = sqlite3ExprListAppend(pParse,0,X,0);} + +%type inscollist_opt {IdList*} +%destructor inscollist_opt {sqlite3IdListDelete(pParse->db, $$);} +%type inscollist {IdList*} +%destructor inscollist {sqlite3IdListDelete(pParse->db, $$);} + +inscollist_opt(A) ::= . {A = 0;} +inscollist_opt(A) ::= LP inscollist(X) RP. {A = X;} +inscollist(A) ::= inscollist(X) COMMA nm(Y). + {A = sqlite3IdListAppend(pParse->db,X,&Y);} +inscollist(A) ::= nm(Y). + {A = sqlite3IdListAppend(pParse->db,0,&Y);} + +/////////////////////////// Expression Processing ///////////////////////////// +// + +%type expr {Expr*} +%destructor expr {sqlite3ExprDelete(pParse->db, $$);} +%type term {Expr*} +%destructor term {sqlite3ExprDelete(pParse->db, $$);} + +expr(A) ::= term(X). {A = X;} +expr(A) ::= LP(B) expr(X) RP(E). {A = X; sqlite3ExprSpan(A,&B,&E); } +term(A) ::= NULL(X). {A = sqlite3PExpr(pParse, @X, 0, 0, &X);} +expr(A) ::= ID(X). {A = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);} +expr(A) ::= JOIN_KW(X). {A = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);} +expr(A) ::= nm(X) DOT nm(Y). { + Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &X); + Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Y); + A = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0); +} +expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). { + Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &X); + Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Y); + Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Z); + Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0); + A = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0); +} +term(A) ::= INTEGER|FLOAT|BLOB(X). {A = sqlite3PExpr(pParse, @X, 0, 0, &X);} +term(A) ::= STRING(X). {A = sqlite3PExpr(pParse, @X, 0, 0, &X);} +expr(A) ::= REGISTER(X). {A = sqlite3RegisterExpr(pParse, &X);} +expr(A) ::= VARIABLE(X). { + Token *pToken = &X; + Expr *pExpr = A = sqlite3PExpr(pParse, TK_VARIABLE, 0, 0, pToken); + sqlite3ExprAssignVarNumber(pParse, pExpr); +} +expr(A) ::= expr(E) COLLATE ids(C). { + A = sqlite3ExprSetColl(pParse, E, &C); +} +%ifndef SQLITE_OMIT_CAST +expr(A) ::= CAST(X) LP expr(E) AS typetoken(T) RP(Y). { + A = sqlite3PExpr(pParse, TK_CAST, E, 0, &T); + sqlite3ExprSpan(A,&X,&Y); +} +%endif SQLITE_OMIT_CAST +expr(A) ::= ID(X) LP distinct(D) exprlist(Y) RP(E). { + if( Y && Y->nExpr>SQLITE_MAX_FUNCTION_ARG ){ + sqlite3ErrorMsg(pParse, "too many arguments on function %T", &X); + } + A = sqlite3ExprFunction(pParse, Y, &X); + sqlite3ExprSpan(A,&X,&E); + if( D && A ){ + A->flags |= EP_Distinct; + } +} +expr(A) ::= ID(X) LP STAR RP(E). { + A = sqlite3ExprFunction(pParse, 0, &X); + sqlite3ExprSpan(A,&X,&E); +} +term(A) ::= CTIME_KW(OP). { + /* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are + ** treated as functions that return constants */ + A = sqlite3ExprFunction(pParse, 0,&OP); + if( A ){ + A->op = TK_CONST_FUNC; + A->span = OP; + } +} +expr(A) ::= expr(X) AND(OP) expr(Y). {A = sqlite3PExpr(pParse,@OP,X,Y,0);} +expr(A) ::= expr(X) OR(OP) expr(Y). {A = sqlite3PExpr(pParse,@OP,X,Y,0);} +expr(A) ::= expr(X) LT|GT|GE|LE(OP) expr(Y). + {A = sqlite3PExpr(pParse,@OP,X,Y,0);} +expr(A) ::= expr(X) EQ|NE(OP) expr(Y). {A = sqlite3PExpr(pParse,@OP,X,Y,0);} +expr(A) ::= expr(X) BITAND|BITOR|LSHIFT|RSHIFT(OP) expr(Y). + {A = sqlite3PExpr(pParse,@OP,X,Y,0);} +expr(A) ::= expr(X) PLUS|MINUS(OP) expr(Y).{A = sqlite3PExpr(pParse,@OP,X,Y,0);} +expr(A) ::= expr(X) STAR|SLASH|REM(OP) expr(Y). + {A = sqlite3PExpr(pParse,@OP,X,Y,0);} +expr(A) ::= expr(X) CONCAT(OP) expr(Y). {A = sqlite3PExpr(pParse,@OP,X,Y,0);} +%type likeop {struct LikeOp} +likeop(A) ::= LIKE_KW(X). {A.eOperator = X; A.not = 0;} +likeop(A) ::= NOT LIKE_KW(X). {A.eOperator = X; A.not = 1;} +likeop(A) ::= MATCH(X). {A.eOperator = X; A.not = 0;} +likeop(A) ::= NOT MATCH(X). {A.eOperator = X; A.not = 1;} +%type escape {Expr*} +%destructor escape {sqlite3ExprDelete(pParse->db, $$);} +escape(X) ::= ESCAPE expr(A). [ESCAPE] {X = A;} +escape(X) ::= . [ESCAPE] {X = 0;} +expr(A) ::= expr(X) likeop(OP) expr(Y) escape(E). [LIKE_KW] { + ExprList *pList; + pList = sqlite3ExprListAppend(pParse,0, Y, 0); + pList = sqlite3ExprListAppend(pParse,pList, X, 0); + if( E ){ + pList = sqlite3ExprListAppend(pParse,pList, E, 0); + } + A = sqlite3ExprFunction(pParse, pList, &OP.eOperator); + if( OP.not ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0); + sqlite3ExprSpan(A, &X->span, &Y->span); + if( A ) A->flags |= EP_InfixFunc; +} + +expr(A) ::= expr(X) ISNULL|NOTNULL(E). { + A = sqlite3PExpr(pParse, @E, X, 0, 0); + sqlite3ExprSpan(A,&X->span,&E); +} +expr(A) ::= expr(X) IS NULL(E). { + A = sqlite3PExpr(pParse, TK_ISNULL, X, 0, 0); + sqlite3ExprSpan(A,&X->span,&E); +} +expr(A) ::= expr(X) NOT NULL(E). { + A = sqlite3PExpr(pParse, TK_NOTNULL, X, 0, 0); + sqlite3ExprSpan(A,&X->span,&E); +} +expr(A) ::= expr(X) IS NOT NULL(E). { + A = sqlite3PExpr(pParse, TK_NOTNULL, X, 0, 0); + sqlite3ExprSpan(A,&X->span,&E); +} +expr(A) ::= NOT(B) expr(X). { + A = sqlite3PExpr(pParse, @B, X, 0, 0); + sqlite3ExprSpan(A,&B,&X->span); +} +expr(A) ::= BITNOT(B) expr(X). { + A = sqlite3PExpr(pParse, @B, X, 0, 0); + sqlite3ExprSpan(A,&B,&X->span); +} +expr(A) ::= MINUS(B) expr(X). [UMINUS] { + A = sqlite3PExpr(pParse, TK_UMINUS, X, 0, 0); + sqlite3ExprSpan(A,&B,&X->span); +} +expr(A) ::= PLUS(B) expr(X). [UPLUS] { + A = sqlite3PExpr(pParse, TK_UPLUS, X, 0, 0); + sqlite3ExprSpan(A,&B,&X->span); +} +%type between_op {int} +between_op(A) ::= BETWEEN. {A = 0;} +between_op(A) ::= NOT BETWEEN. {A = 1;} +expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { + ExprList *pList = sqlite3ExprListAppend(pParse,0, X, 0); + pList = sqlite3ExprListAppend(pParse,pList, Y, 0); + A = sqlite3PExpr(pParse, TK_BETWEEN, W, 0, 0); + if( A ){ + A->pList = pList; + }else{ + sqlite3ExprListDelete(pParse->db, pList); + } + if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0); + sqlite3ExprSpan(A,&W->span,&Y->span); +} +%ifndef SQLITE_OMIT_SUBQUERY + %type in_op {int} + in_op(A) ::= IN. {A = 0;} + in_op(A) ::= NOT IN. {A = 1;} + expr(A) ::= expr(X) in_op(N) LP exprlist(Y) RP(E). [IN] { + A = sqlite3PExpr(pParse, TK_IN, X, 0, 0); + if( A ){ + A->pList = Y; + sqlite3ExprSetHeight(pParse, A); + }else{ + sqlite3ExprListDelete(pParse->db, Y); + } + if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0); + sqlite3ExprSpan(A,&X->span,&E); + } + expr(A) ::= LP(B) select(X) RP(E). { + A = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); + if( A ){ + A->pSelect = X; + sqlite3ExprSetHeight(pParse, A); + }else{ + sqlite3SelectDelete(pParse->db, X); + } + sqlite3ExprSpan(A,&B,&E); + } + expr(A) ::= expr(X) in_op(N) LP select(Y) RP(E). [IN] { + A = sqlite3PExpr(pParse, TK_IN, X, 0, 0); + if( A ){ + A->pSelect = Y; + sqlite3ExprSetHeight(pParse, A); + }else{ + sqlite3SelectDelete(pParse->db, Y); + } + if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0); + sqlite3ExprSpan(A,&X->span,&E); + } + expr(A) ::= expr(X) in_op(N) nm(Y) dbnm(Z). [IN] { + SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&Y,&Z); + A = sqlite3PExpr(pParse, TK_IN, X, 0, 0); + if( A ){ + A->pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); + sqlite3ExprSetHeight(pParse, A); + }else{ + sqlite3SrcListDelete(pParse->db, pSrc); + } + if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0); + sqlite3ExprSpan(A,&X->span,Z.z?&Z:&Y); + } + expr(A) ::= EXISTS(B) LP select(Y) RP(E). { + Expr *p = A = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); + if( p ){ + p->pSelect = Y; + sqlite3ExprSpan(p,&B,&E); + sqlite3ExprSetHeight(pParse, A); + }else{ + sqlite3SelectDelete(pParse->db, Y); + } + } +%endif SQLITE_OMIT_SUBQUERY + +/* CASE expressions */ +expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). { + A = sqlite3PExpr(pParse, TK_CASE, X, Z, 0); + if( A ){ + A->pList = Y; + sqlite3ExprSetHeight(pParse, A); + }else{ + sqlite3ExprListDelete(pParse->db, Y); + } + sqlite3ExprSpan(A, &C, &E); +} +%type case_exprlist {ExprList*} +%destructor case_exprlist {sqlite3ExprListDelete(pParse->db, $$);} +case_exprlist(A) ::= case_exprlist(X) WHEN expr(Y) THEN expr(Z). { + A = sqlite3ExprListAppend(pParse,X, Y, 0); + A = sqlite3ExprListAppend(pParse,A, Z, 0); +} +case_exprlist(A) ::= WHEN expr(Y) THEN expr(Z). { + A = sqlite3ExprListAppend(pParse,0, Y, 0); + A = sqlite3ExprListAppend(pParse,A, Z, 0); +} +%type case_else {Expr*} +%destructor case_else {sqlite3ExprDelete(pParse->db, $$);} +case_else(A) ::= ELSE expr(X). {A = X;} +case_else(A) ::= . {A = 0;} +%type case_operand {Expr*} +%destructor case_operand {sqlite3ExprDelete(pParse->db, $$);} +case_operand(A) ::= expr(X). {A = X;} +case_operand(A) ::= . {A = 0;} + +%type exprlist {ExprList*} +%destructor exprlist {sqlite3ExprListDelete(pParse->db, $$);} +%type nexprlist {ExprList*} +%destructor nexprlist {sqlite3ExprListDelete(pParse->db, $$);} + +exprlist(A) ::= nexprlist(X). {A = X;} +exprlist(A) ::= . {A = 0;} +nexprlist(A) ::= nexprlist(X) COMMA expr(Y). + {A = sqlite3ExprListAppend(pParse,X,Y,0);} +nexprlist(A) ::= expr(Y). + {A = sqlite3ExprListAppend(pParse,0,Y,0);} + + +///////////////////////////// The CREATE INDEX command /////////////////////// +// +cmd ::= CREATE(S) uniqueflag(U) INDEX ifnotexists(NE) nm(X) dbnm(D) + ON nm(Y) LP idxlist(Z) RP(E). { + sqlite3CreateIndex(pParse, &X, &D, + sqlite3SrcListAppend(pParse->db,0,&Y,0), Z, U, + &S, &E, SQLITE_SO_ASC, NE); +} + +%type uniqueflag {int} +uniqueflag(A) ::= UNIQUE. {A = OE_Abort;} +uniqueflag(A) ::= . {A = OE_None;} + +%type idxlist {ExprList*} +%destructor idxlist {sqlite3ExprListDelete(pParse->db, $$);} +%type idxlist_opt {ExprList*} +%destructor idxlist_opt {sqlite3ExprListDelete(pParse->db, $$);} +%type idxitem {Token} + +idxlist_opt(A) ::= . {A = 0;} +idxlist_opt(A) ::= LP idxlist(X) RP. {A = X;} +idxlist(A) ::= idxlist(X) COMMA idxitem(Y) collate(C) sortorder(Z). { + Expr *p = 0; + if( C.n>0 ){ + p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0); + sqlite3ExprSetColl(pParse, p, &C); + } + A = sqlite3ExprListAppend(pParse,X, p, &Y); + sqlite3ExprListCheckLength(pParse, A, "index"); + if( A ) A->a[A->nExpr-1].sortOrder = Z; +} +idxlist(A) ::= idxitem(Y) collate(C) sortorder(Z). { + Expr *p = 0; + if( C.n>0 ){ + p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0); + sqlite3ExprSetColl(pParse, p, &C); + } + A = sqlite3ExprListAppend(pParse,0, p, &Y); + sqlite3ExprListCheckLength(pParse, A, "index"); + if( A ) A->a[A->nExpr-1].sortOrder = Z; +} +idxitem(A) ::= nm(X). {A = X;} + +%type collate {Token} +collate(C) ::= . {C.z = 0; C.n = 0;} +collate(C) ::= COLLATE ids(X). {C = X;} + + +///////////////////////////// The DROP INDEX command ///////////////////////// +// +cmd ::= DROP INDEX ifexists(E) fullname(X). {sqlite3DropIndex(pParse, X, E);} + +///////////////////////////// The VACUUM command ///////////////////////////// +// +%ifndef SQLITE_OMIT_VACUUM +%ifndef SQLITE_OMIT_ATTACH +cmd ::= VACUUM. {sqlite3Vacuum(pParse);} +cmd ::= VACUUM nm. {sqlite3Vacuum(pParse);} +%endif SQLITE_OMIT_ATTACH +%endif SQLITE_OMIT_VACUUM + +///////////////////////////// The PRAGMA command ///////////////////////////// +// +%ifndef SQLITE_OMIT_PARSER +%ifndef SQLITE_OMIT_PRAGMA +cmd ::= PRAGMA nm(X) dbnm(Z) EQ nmnum(Y). {sqlite3Pragma(pParse,&X,&Z,&Y,0);} +cmd ::= PRAGMA nm(X) dbnm(Z) EQ ON(Y). {sqlite3Pragma(pParse,&X,&Z,&Y,0);} +cmd ::= PRAGMA nm(X) dbnm(Z) EQ DELETE(Y). {sqlite3Pragma(pParse,&X,&Z,&Y,0);} +cmd ::= PRAGMA nm(X) dbnm(Z) EQ minus_num(Y). { + sqlite3Pragma(pParse,&X,&Z,&Y,1); +} +cmd ::= PRAGMA nm(X) dbnm(Z) LP nmnum(Y) RP. {sqlite3Pragma(pParse,&X,&Z,&Y,0);} +cmd ::= PRAGMA nm(X) dbnm(Z). {sqlite3Pragma(pParse,&X,&Z,0,0);} +nmnum(A) ::= plus_num(X). {A = X;} +nmnum(A) ::= nm(X). {A = X;} +%endif SQLITE_OMIT_PRAGMA +%endif SQLITE_OMIT_PARSER +plus_num(A) ::= plus_opt number(X). {A = X;} +minus_num(A) ::= MINUS number(X). {A = X;} +number(A) ::= INTEGER|FLOAT(X). {A = X;} +plus_opt ::= PLUS. +plus_opt ::= . + +//////////////////////////// The CREATE TRIGGER command ///////////////////// + +%ifndef SQLITE_OMIT_TRIGGER + +cmd ::= CREATE trigger_decl(A) BEGIN trigger_cmd_list(S) END(Z). { + Token all; + all.z = A.z; + all.n = (Z.z - A.z) + Z.n; + sqlite3FinishTrigger(pParse, S, &all); +} + +trigger_decl(A) ::= temp(T) TRIGGER ifnotexists(NOERR) nm(B) dbnm(Z) + trigger_time(C) trigger_event(D) + ON fullname(E) foreach_clause when_clause(G). { + sqlite3BeginTrigger(pParse, &B, &Z, C, D.a, D.b, E, G, T, NOERR); + A = (Z.n==0?B:Z); +} + +%type trigger_time {int} +trigger_time(A) ::= BEFORE. { A = TK_BEFORE; } +trigger_time(A) ::= AFTER. { A = TK_AFTER; } +trigger_time(A) ::= INSTEAD OF. { A = TK_INSTEAD;} +trigger_time(A) ::= . { A = TK_BEFORE; } + +%type trigger_event {struct TrigEvent} +%destructor trigger_event {sqlite3IdListDelete(pParse->db, $$.b);} +trigger_event(A) ::= DELETE|INSERT(OP). {A.a = @OP; A.b = 0;} +trigger_event(A) ::= UPDATE(OP). {A.a = @OP; A.b = 0;} +trigger_event(A) ::= UPDATE OF inscollist(X). {A.a = TK_UPDATE; A.b = X;} + +foreach_clause ::= . +foreach_clause ::= FOR EACH ROW. + +%type when_clause {Expr*} +%destructor when_clause {sqlite3ExprDelete(pParse->db, $$);} +when_clause(A) ::= . { A = 0; } +when_clause(A) ::= WHEN expr(X). { A = X; } + +%type trigger_cmd_list {TriggerStep*} +%destructor trigger_cmd_list {sqlite3DeleteTriggerStep(pParse->db, $$);} +trigger_cmd_list(A) ::= trigger_cmd_list(Y) trigger_cmd(X) SEMI. { + if( Y ){ + Y->pLast->pNext = X; + }else{ + Y = X; + } + Y->pLast = X; + A = Y; +} +trigger_cmd_list(A) ::= . { A = 0; } + +%type trigger_cmd {TriggerStep*} +%destructor trigger_cmd {sqlite3DeleteTriggerStep(pParse->db, $$);} +// UPDATE +trigger_cmd(A) ::= UPDATE orconf(R) nm(X) SET setlist(Y) where_opt(Z). + { A = sqlite3TriggerUpdateStep(pParse->db, &X, Y, Z, R); } + +// INSERT +trigger_cmd(A) ::= insert_cmd(R) INTO nm(X) inscollist_opt(F) + VALUES LP itemlist(Y) RP. + {A = sqlite3TriggerInsertStep(pParse->db, &X, F, Y, 0, R);} + +trigger_cmd(A) ::= insert_cmd(R) INTO nm(X) inscollist_opt(F) select(S). + {A = sqlite3TriggerInsertStep(pParse->db, &X, F, 0, S, R);} + +// DELETE +trigger_cmd(A) ::= DELETE FROM nm(X) where_opt(Y). + {A = sqlite3TriggerDeleteStep(pParse->db, &X, Y);} + +// SELECT +trigger_cmd(A) ::= select(X). {A = sqlite3TriggerSelectStep(pParse->db, X); } + +// The special RAISE expression that may occur in trigger programs +expr(A) ::= RAISE(X) LP IGNORE RP(Y). { + A = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); + if( A ){ + A->iColumn = OE_Ignore; + sqlite3ExprSpan(A, &X, &Y); + } +} +expr(A) ::= RAISE(X) LP raisetype(T) COMMA nm(Z) RP(Y). { + A = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &Z); + if( A ) { + A->iColumn = T; + sqlite3ExprSpan(A, &X, &Y); + } +} +%endif !SQLITE_OMIT_TRIGGER + +%type raisetype {int} +raisetype(A) ::= ROLLBACK. {A = OE_Rollback;} +raisetype(A) ::= ABORT. {A = OE_Abort;} +raisetype(A) ::= FAIL. {A = OE_Fail;} + + +//////////////////////// DROP TRIGGER statement ////////////////////////////// +%ifndef SQLITE_OMIT_TRIGGER +cmd ::= DROP TRIGGER ifexists(NOERR) fullname(X). { + sqlite3DropTrigger(pParse,X,NOERR); +} +%endif !SQLITE_OMIT_TRIGGER + +//////////////////////// ATTACH DATABASE file AS name ///////////////////////// +%ifndef SQLITE_OMIT_ATTACH +cmd ::= ATTACH database_kw_opt expr(F) AS expr(D) key_opt(K). { + sqlite3Attach(pParse, F, D, K); +} +cmd ::= DETACH database_kw_opt expr(D). { + sqlite3Detach(pParse, D); +} + +%type key_opt {Expr*} +%destructor key_opt {sqlite3ExprDelete(pParse->db, $$);} +key_opt(A) ::= . { A = 0; } +key_opt(A) ::= KEY expr(X). { A = X; } + +database_kw_opt ::= DATABASE. +database_kw_opt ::= . +%endif SQLITE_OMIT_ATTACH + +////////////////////////// REINDEX collation ////////////////////////////////// +%ifndef SQLITE_OMIT_REINDEX +cmd ::= REINDEX. {sqlite3Reindex(pParse, 0, 0);} +cmd ::= REINDEX nm(X) dbnm(Y). {sqlite3Reindex(pParse, &X, &Y);} +%endif SQLITE_OMIT_REINDEX + +/////////////////////////////////// ANALYZE /////////////////////////////////// +%ifndef SQLITE_OMIT_ANALYZE +cmd ::= ANALYZE. {sqlite3Analyze(pParse, 0, 0);} +cmd ::= ANALYZE nm(X) dbnm(Y). {sqlite3Analyze(pParse, &X, &Y);} +%endif + +//////////////////////// ALTER TABLE table ... //////////////////////////////// +%ifndef SQLITE_OMIT_ALTERTABLE +cmd ::= ALTER TABLE fullname(X) RENAME TO nm(Z). { + sqlite3AlterRenameTable(pParse,X,&Z); +} +cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column(Y). { + sqlite3AlterFinishAddColumn(pParse, &Y); +} +add_column_fullname ::= fullname(X). { + sqlite3AlterBeginAddColumn(pParse, X); +} +kwcolumn_opt ::= . +kwcolumn_opt ::= COLUMNKW. +%endif SQLITE_OMIT_ALTERTABLE + +//////////////////////// CREATE VIRTUAL TABLE ... ///////////////////////////// +%ifndef SQLITE_OMIT_VIRTUALTABLE +cmd ::= create_vtab. {sqlite3VtabFinishParse(pParse,0);} +cmd ::= create_vtab LP vtabarglist RP(X). {sqlite3VtabFinishParse(pParse,&X);} +create_vtab ::= CREATE VIRTUAL TABLE nm(X) dbnm(Y) USING nm(Z). { + sqlite3VtabBeginParse(pParse, &X, &Y, &Z); +} +vtabarglist ::= vtabarg. +vtabarglist ::= vtabarglist COMMA vtabarg. +vtabarg ::= . {sqlite3VtabArgInit(pParse);} +vtabarg ::= vtabarg vtabargtoken. +vtabargtoken ::= ANY(X). {sqlite3VtabArgExtend(pParse,&X);} +vtabargtoken ::= lp anylist RP(X). {sqlite3VtabArgExtend(pParse,&X);} +lp ::= LP(X). {sqlite3VtabArgExtend(pParse,&X);} +anylist ::= . +anylist ::= anylist ANY(X). {sqlite3VtabArgExtend(pParse,&X);} +%endif SQLITE_OMIT_VIRTUALTABLE diff --git a/third_party/sqlite/src/pragma.c b/third_party/sqlite/src/pragma.c new file mode 100755 index 0000000..6ffc60d --- /dev/null +++ b/third_party/sqlite/src/pragma.c @@ -0,0 +1,1329 @@ +/* +** 2003 April 6 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains code used to implement the PRAGMA command. +** +** $Id: pragma.c,v 1.183 2008/07/28 19:34:53 drh Exp $ +*/ +#include "sqliteInt.h" +#include <ctype.h> + +/* Ignore this whole file if pragmas are disabled +*/ +#if !defined(SQLITE_OMIT_PRAGMA) && !defined(SQLITE_OMIT_PARSER) + +/* +** Interpret the given string as a safety level. Return 0 for OFF, +** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or +** unrecognized string argument. +** +** Note that the values returned are one less that the values that +** should be passed into sqlite3BtreeSetSafetyLevel(). The is done +** 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 char *z){ + /* 123456789 123456789 */ + static const char zText[] = "onoffalseyestruefull"; + static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16}; + static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 4}; + static const u8 iValue[] = {1, 0, 0, 0, 1, 1, 2}; + int i, n; + if( isdigit(*z) ){ + return atoi(z); + } + n = strlen(z); + for(i=0; i<sizeof(iLength); i++){ + if( iLength[i]==n && sqlite3StrNICmp(&zText[iOffset[i]],z,n)==0 ){ + return iValue[i]; + } + } + return 1; +} + +/* +** Interpret the given string as a boolean value. +*/ +static int getBoolean(const char *z){ + return getSafetyLevel(z)&1; +} + +/* +** Interpret the given string as a locking mode value. +*/ +static int getLockingMode(const char *z){ + if( z ){ + if( 0==sqlite3StrICmp(z, "exclusive") ) return PAGER_LOCKINGMODE_EXCLUSIVE; + if( 0==sqlite3StrICmp(z, "normal") ) return PAGER_LOCKINGMODE_NORMAL; + } + return PAGER_LOCKINGMODE_QUERY; +} + +#ifndef SQLITE_OMIT_AUTOVACUUM +/* +** Interpret the given string as an auto-vacuum mode value. +** +** The following strings, "none", "full" and "incremental" are +** acceptable, as are their numeric equivalents: 0, 1 and 2 respectively. +*/ +static int getAutoVacuum(const char *z){ + int i; + if( 0==sqlite3StrICmp(z, "none") ) return BTREE_AUTOVACUUM_NONE; + if( 0==sqlite3StrICmp(z, "full") ) return BTREE_AUTOVACUUM_FULL; + if( 0==sqlite3StrICmp(z, "incremental") ) return BTREE_AUTOVACUUM_INCR; + i = atoi(z); + return ((i>=0&&i<=2)?i:0); +} +#endif /* ifndef SQLITE_OMIT_AUTOVACUUM */ + +#ifndef SQLITE_OMIT_PAGER_PRAGMAS +/* +** Interpret the given string as a temp db location. Return 1 for file +** backed temporary databases, 2 for the Red-Black tree in memory database +** and 0 to use the compile-time default. +*/ +static int getTempStore(const char *z){ + if( z[0]>='0' && z[0]<='2' ){ + return z[0] - '0'; + }else if( sqlite3StrICmp(z, "file")==0 ){ + return 1; + }else if( sqlite3StrICmp(z, "memory")==0 ){ + return 2; + }else{ + return 0; + } +} +#endif /* SQLITE_PAGER_PRAGMAS */ + +#ifndef SQLITE_OMIT_PAGER_PRAGMAS +/* +** Invalidate temp storage, either when the temp storage is changed +** from default, or when 'file' and the temp_store_directory has changed +*/ +static int invalidateTempStorage(Parse *pParse){ + sqlite3 *db = pParse->db; + if( db->aDb[1].pBt!=0 ){ + if( !db->autoCommit || sqlite3BtreeIsInReadTrans(db->aDb[1].pBt) ){ + sqlite3ErrorMsg(pParse, "temporary storage cannot be changed " + "from within a transaction"); + return SQLITE_ERROR; + } + sqlite3BtreeClose(db->aDb[1].pBt); + db->aDb[1].pBt = 0; + sqlite3ResetInternalSchema(db, 0); + } + return SQLITE_OK; +} +#endif /* SQLITE_PAGER_PRAGMAS */ + +#ifndef SQLITE_OMIT_PAGER_PRAGMAS +/* +** If the TEMP database is open, close it and mark the database schema +** as needing reloading. This must be done when using the SQLITE_TEMP_STORE +** or DEFAULT_TEMP_STORE pragmas. +*/ +static int changeTempStorage(Parse *pParse, const char *zStorageType){ + int ts = getTempStore(zStorageType); + sqlite3 *db = pParse->db; + if( db->temp_store==ts ) return SQLITE_OK; + if( invalidateTempStorage( pParse ) != SQLITE_OK ){ + return SQLITE_ERROR; + } + db->temp_store = ts; + return SQLITE_OK; +} +#endif /* SQLITE_PAGER_PRAGMAS */ + +/* +** Generate code to return a single integer value. +*/ +static void returnSingleInt(Parse *pParse, const char *zLabel, int value){ + Vdbe *v = sqlite3GetVdbe(pParse); + int mem = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Integer, value, mem); + if( pParse->explain==0 ){ + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, P4_STATIC); + } + sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1); +} + +#ifndef SQLITE_OMIT_FLAG_PRAGMAS +/* +** Check to see if zRight and zLeft refer to a pragma that queries +** or changes one of the flags in db->flags. Return 1 if so and 0 if not. +** Also, implement the pragma. +*/ +static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){ + static const struct sPragmaType { + const char *zName; /* Name of the pragma */ + int mask; /* Mask for the db->flags value */ + } aPragma[] = { + { "full_column_names", SQLITE_FullColNames }, + { "short_column_names", SQLITE_ShortColNames }, + { "count_changes", SQLITE_CountRows }, + { "empty_result_callbacks", SQLITE_NullCallback }, + { "legacy_file_format", SQLITE_LegacyFileFmt }, + { "fullfsync", SQLITE_FullFSync }, +#ifdef SQLITE_DEBUG + { "sql_trace", SQLITE_SqlTrace }, + { "vdbe_listing", SQLITE_VdbeListing }, + { "vdbe_trace", SQLITE_VdbeTrace }, +#endif +#ifndef SQLITE_OMIT_CHECK + { "ignore_check_constraints", SQLITE_IgnoreChecks }, +#endif + /* The following is VERY experimental */ + { "writable_schema", SQLITE_WriteSchema|SQLITE_RecoveryMode }, + { "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; + for(i=0, p=aPragma; i<sizeof(aPragma)/sizeof(aPragma[0]); i++, p++){ + if( sqlite3StrICmp(zLeft, p->zName)==0 ){ + sqlite3 *db = pParse->db; + Vdbe *v; + v = sqlite3GetVdbe(pParse); + if( v ){ + if( zRight==0 ){ + returnSingleInt(pParse, p->zName, (db->flags & p->mask)!=0 ); + }else{ + if( getBoolean(zRight) ){ + db->flags |= p->mask; + }else{ + db->flags &= ~p->mask; + } + + /* Many of the flag-pragmas modify the code generated by the SQL + ** compiler (eg. count_changes). So add an opcode to expire all + ** compiled SQL statements after modifying a pragma value. + */ + sqlite3VdbeAddOp2(v, OP_Expire, 0, 0); + } + } + + return 1; + } + } + return 0; +} +#endif /* SQLITE_OMIT_FLAG_PRAGMAS */ + +/* +** Process a pragma statement. +** +** Pragmas are of this form: +** +** PRAGMA [database.]id [= value] +** +** The identifier might also be a string. The value is a string, and +** identifier, or a number. If minusFlag is true, then the value is +** a number that was preceded by a minus sign. +** +** If the left side is "database.id" then pId1 is the database name +** and pId2 is the id. If the left side is just "id" then pId1 is the +** id and pId2 is any empty string. +*/ +void sqlite3Pragma( + Parse *pParse, + Token *pId1, /* First part of [database.]id field */ + Token *pId2, /* Second part of [database.]id field, or NULL */ + Token *pValue, /* Token for <value>, or NULL */ + int minusFlag /* True if a '-' sign preceded <value> */ +){ + char *zLeft = 0; /* Nul-terminated UTF-8 string <id> */ + char *zRight = 0; /* Nul-terminated UTF-8 string <value>, or NULL */ + const char *zDb = 0; /* The database name */ + Token *pId; /* Pointer to <id> token */ + int iDb; /* Database index for <database> */ + sqlite3 *db = pParse->db; + Db *pDb; + Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db); + if( v==0 ) return; + pParse->nMem = 2; + + /* Interpret the [database.] part of the pragma statement. iDb is the + ** index of the database this pragma is being applied to in db.aDb[]. */ + iDb = sqlite3TwoPartName(pParse, pId1, pId2, &pId); + if( iDb<0 ) return; + pDb = &db->aDb[iDb]; + + /* If the temp database has been explicitly named as part of the + ** pragma, make sure it is open. + */ + if( iDb==1 && sqlite3OpenTempDatabase(pParse) ){ + return; + } + + zLeft = sqlite3NameFromToken(db, pId); + if( !zLeft ) return; + if( minusFlag ){ + zRight = sqlite3MPrintf(db, "-%T", pValue); + }else{ + zRight = sqlite3NameFromToken(db, pValue); + } + + zDb = ((iDb>0)?pDb->zName:0); + if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){ + goto pragma_out; + } + +#ifndef SQLITE_OMIT_PAGER_PRAGMAS + /* + ** PRAGMA [database.]default_cache_size + ** PRAGMA [database.]default_cache_size=N + ** + ** The first form reports the current persistent setting for the + ** page cache size. The value returned is the maximum number of + ** pages in the page cache. The second form sets both the current + ** page cache size value and the persistent page cache size value + ** stored in the database file. + ** + ** The default cache size is stored in meta-value 2 of page 1 of the + ** database file. The cache size is actually the absolute value of + ** this memory location. The sign of meta-value 2 determines the + ** synchronous setting. A negative value means synchronous is off + ** and a positive value means synchronous is on. + */ + if( sqlite3StrICmp(zLeft,"default_cache_size")==0 ){ + static const VdbeOpList getCacheSize[] = { + { OP_ReadCookie, 0, 1, 2}, /* 0 */ + { OP_IfPos, 1, 6, 0}, + { OP_Integer, 0, 2, 0}, + { OP_Subtract, 1, 2, 1}, + { OP_IfPos, 1, 6, 0}, + { OP_Integer, 0, 1, 0}, /* 5 */ + { OP_ResultRow, 1, 1, 0}, + }; + int addr; + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + sqlite3VdbeUsesBtree(v, iDb); + if( !zRight ){ + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", P4_STATIC); + pParse->nMem += 2; + addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); + sqlite3VdbeChangeP1(v, addr, iDb); + sqlite3VdbeChangeP1(v, addr+5, SQLITE_DEFAULT_CACHE_SIZE); + }else{ + int size = atoi(zRight); + if( size<0 ) size = -size; + sqlite3BeginWriteOperation(pParse, 0, iDb); + sqlite3VdbeAddOp2(v, OP_Integer, size, 1); + sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, 2, 2); + addr = sqlite3VdbeAddOp2(v, OP_IfPos, 2, 0); + sqlite3VdbeAddOp2(v, OP_Integer, -size, 1); + sqlite3VdbeJumpHere(v, addr); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 2, 1); + pDb->pSchema->cache_size = size; + sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); + } + }else + + /* + ** PRAGMA [database.]page_size + ** PRAGMA [database.]page_size=N + ** + ** The first form reports the current setting for the + ** database page size in bytes. The second form sets the + ** database page size value. The value can only be set if + ** the database has not yet been created. + */ + if( sqlite3StrICmp(zLeft,"page_size")==0 ){ + Btree *pBt = pDb->pBt; + if( !zRight ){ + int size = pBt ? sqlite3BtreeGetPageSize(pBt) : 0; + returnSingleInt(pParse, "page_size", size); + }else{ + /* Malloc may fail when setting the page-size, as there is an internal + ** buffer that the pager module resizes using sqlite3_realloc(). + */ + db->nextPagesize = atoi(zRight); + if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1) ){ + db->mallocFailed = 1; + } + } + }else + + /* + ** PRAGMA [database.]max_page_count + ** PRAGMA [database.]max_page_count=N + ** + ** The first form reports the current setting for the + ** maximum number of pages in the database file. The + ** second form attempts to change this setting. Both + ** forms return the current setting. + */ + if( sqlite3StrICmp(zLeft,"max_page_count")==0 ){ + Btree *pBt = pDb->pBt; + int newMax = 0; + if( zRight ){ + newMax = atoi(zRight); + } + if( pBt ){ + newMax = sqlite3BtreeMaxPageCount(pBt, newMax); + } + returnSingleInt(pParse, "max_page_count", newMax); + }else + + /* + ** PRAGMA [database.]page_count + ** + ** Return the number of pages in the specified database. + */ + if( sqlite3StrICmp(zLeft,"page_count")==0 ){ + Vdbe *v; + int iReg; + v = sqlite3GetVdbe(pParse); + if( !v || sqlite3ReadSchema(pParse) ) goto pragma_out; + sqlite3CodeVerifySchema(pParse, iDb); + iReg = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg); + sqlite3VdbeAddOp2(v, OP_ResultRow, iReg, 1); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "page_count", P4_STATIC); + }else + + /* + ** PRAGMA [database.]locking_mode + ** PRAGMA [database.]locking_mode = (normal|exclusive) + */ + if( sqlite3StrICmp(zLeft,"locking_mode")==0 ){ + const char *zRet = "normal"; + int eMode = getLockingMode(zRight); + + if( pId2->n==0 && eMode==PAGER_LOCKINGMODE_QUERY ){ + /* Simple "PRAGMA locking_mode;" statement. This is a query for + ** the current default locking mode (which may be different to + ** the locking-mode of the main database). + */ + eMode = db->dfltLockMode; + }else{ + Pager *pPager; + if( pId2->n==0 ){ + /* This indicates that no database name was specified as part + ** of the PRAGMA command. In this case the locking-mode must be + ** set on all attached databases, as well as the main db file. + ** + ** Also, the sqlite3.dfltLockMode variable is set so that + ** any subsequently attached databases also use the specified + ** locking mode. + */ + int ii; + assert(pDb==&db->aDb[0]); + for(ii=2; ii<db->nDb; ii++){ + pPager = sqlite3BtreePager(db->aDb[ii].pBt); + sqlite3PagerLockingMode(pPager, eMode); + } + db->dfltLockMode = eMode; + } + pPager = sqlite3BtreePager(pDb->pBt); + eMode = sqlite3PagerLockingMode(pPager, eMode); + } + + assert(eMode==PAGER_LOCKINGMODE_NORMAL||eMode==PAGER_LOCKINGMODE_EXCLUSIVE); + if( eMode==PAGER_LOCKINGMODE_EXCLUSIVE ){ + zRet = "exclusive"; + } + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "locking_mode", P4_STATIC); + sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zRet, 0); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); + }else + + /* + ** PRAGMA [database.]journal_mode + ** PRAGMA [database.]journal_mode = (delete|persist|off) + */ + if( sqlite3StrICmp(zLeft,"journal_mode")==0 ){ + int eMode; + static const char *azModeName[] = {"delete", "persist", "off"}; + + if( zRight==0 ){ + eMode = PAGER_JOURNALMODE_QUERY; + }else{ + int n = strlen(zRight); + eMode = 2; + while( eMode>=0 && sqlite3StrNICmp(zRight, azModeName[eMode], n)!=0 ){ + eMode--; + } + } + if( pId2->n==0 && eMode==PAGER_JOURNALMODE_QUERY ){ + /* Simple "PRAGMA journal_mode;" statement. This is a query for + ** the current default journal mode (which may be different to + ** the journal-mode of the main database). + */ + eMode = db->dfltJournalMode; + }else{ + Pager *pPager; + if( pId2->n==0 ){ + /* This indicates that no database name was specified as part + ** of the PRAGMA command. In this case the journal-mode must be + ** set on all attached databases, as well as the main db file. + ** + ** Also, the sqlite3.dfltJournalMode variable is set so that + ** any subsequently attached databases also use the specified + ** journal mode. + */ + int ii; + assert(pDb==&db->aDb[0]); + for(ii=1; ii<db->nDb; ii++){ + if( db->aDb[ii].pBt ){ + pPager = sqlite3BtreePager(db->aDb[ii].pBt); + sqlite3PagerJournalMode(pPager, eMode); + } + } + db->dfltJournalMode = eMode; + } + pPager = sqlite3BtreePager(pDb->pBt); + eMode = sqlite3PagerJournalMode(pPager, eMode); + } + assert( eMode==PAGER_JOURNALMODE_DELETE + || eMode==PAGER_JOURNALMODE_PERSIST + || eMode==PAGER_JOURNALMODE_OFF ); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", P4_STATIC); + sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, + azModeName[eMode], P4_STATIC); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); + }else + + /* + ** PRAGMA [database.]journal_size_limit + ** PRAGMA [database.]journal_size_limit=N + ** + ** Get or set the (boolean) value of the database 'auto-vacuum' parameter. + */ + if( sqlite3StrICmp(zLeft,"journal_size_limit")==0 ){ + Pager *pPager = sqlite3BtreePager(pDb->pBt); + i64 iLimit = -2; + if( zRight ){ + int iLimit32 = atoi(zRight); + if( iLimit32<-1 ){ + iLimit32 = -1; + } + iLimit = iLimit32; + } + iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit); + returnSingleInt(pParse, "journal_size_limit", (int)iLimit); + }else + +#endif /* SQLITE_OMIT_PAGER_PRAGMAS */ + + /* + ** PRAGMA [database.]auto_vacuum + ** PRAGMA [database.]auto_vacuum=N + ** + ** Get or set the (boolean) value of the database 'auto-vacuum' parameter. + */ +#ifndef SQLITE_OMIT_AUTOVACUUM + if( sqlite3StrICmp(zLeft,"auto_vacuum")==0 ){ + Btree *pBt = pDb->pBt; + if( sqlite3ReadSchema(pParse) ){ + goto pragma_out; + } + if( !zRight ){ + int auto_vacuum = + pBt ? sqlite3BtreeGetAutoVacuum(pBt) : SQLITE_DEFAULT_AUTOVACUUM; + returnSingleInt(pParse, "auto_vacuum", auto_vacuum); + }else{ + int eAuto = getAutoVacuum(zRight); + db->nextAutovac = eAuto; + if( eAuto>=0 ){ + /* Call SetAutoVacuum() to set initialize the internal auto and + ** incr-vacuum flags. This is required in case this connection + ** creates the database file. It is important that it is created + ** as an auto-vacuum capable db. + */ + int rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto); + if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){ + /* When setting the auto_vacuum mode to either "full" or + ** "incremental", write the value of meta[6] in the database + ** file. Before writing to meta[6], check that meta[3] indicates + ** that this really is an auto-vacuum capable database. + */ + static const VdbeOpList setMeta6[] = { + { OP_Transaction, 0, 1, 0}, /* 0 */ + { OP_ReadCookie, 0, 1, 3}, /* 1 */ + { OP_If, 1, 0, 0}, /* 2 */ + { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */ + { OP_Integer, 0, 1, 0}, /* 4 */ + { OP_SetCookie, 0, 6, 1}, /* 5 */ + }; + int iAddr; + iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6); + sqlite3VdbeChangeP1(v, iAddr, iDb); + sqlite3VdbeChangeP1(v, iAddr+1, iDb); + sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4); + sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1); + sqlite3VdbeChangeP1(v, iAddr+5, iDb); + sqlite3VdbeUsesBtree(v, iDb); + } + } + } + }else +#endif + + /* + ** PRAGMA [database.]incremental_vacuum(N) + ** + ** Do N steps of incremental vacuuming on a database. + */ +#ifndef SQLITE_OMIT_AUTOVACUUM + if( sqlite3StrICmp(zLeft,"incremental_vacuum")==0 ){ + int iLimit, addr; + if( sqlite3ReadSchema(pParse) ){ + goto pragma_out; + } + if( zRight==0 || !sqlite3GetInt32(zRight, &iLimit) || iLimit<=0 ){ + iLimit = 0x7fffffff; + } + sqlite3BeginWriteOperation(pParse, 0, iDb); + sqlite3VdbeAddOp2(v, OP_Integer, iLimit, 1); + addr = sqlite3VdbeAddOp1(v, OP_IncrVacuum, iDb); + sqlite3VdbeAddOp1(v, OP_ResultRow, 1); + sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); + sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr); + sqlite3VdbeJumpHere(v, addr); + }else +#endif + +#ifndef SQLITE_OMIT_PAGER_PRAGMAS + /* + ** PRAGMA [database.]cache_size + ** PRAGMA [database.]cache_size=N + ** + ** The first form reports the current local setting for the + ** page cache size. The local setting can be different from + ** the persistent cache size value that is stored in the database + ** file itself. The value returned is the maximum number of + ** pages in the page cache. The second form sets the local + ** page cache size value. It does not change the persistent + ** cache size stored on the disk so the cache size will revert + ** to its default value when the database is closed and reopened. + ** N should be a positive integer. + */ + if( sqlite3StrICmp(zLeft,"cache_size")==0 ){ + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + if( !zRight ){ + returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size); + }else{ + int size = atoi(zRight); + if( size<0 ) size = -size; + pDb->pSchema->cache_size = size; + sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); + } + }else + + /* + ** PRAGMA temp_store + ** PRAGMA temp_store = "default"|"memory"|"file" + ** + ** Return or set the local value of the temp_store flag. Changing + ** the local value does not make changes to the disk file and the default + ** value will be restored the next time the database is opened. + ** + ** Note that it is possible for the library compile-time options to + ** override this setting + */ + if( sqlite3StrICmp(zLeft, "temp_store")==0 ){ + if( !zRight ){ + returnSingleInt(pParse, "temp_store", db->temp_store); + }else{ + changeTempStorage(pParse, zRight); + } + }else + + /* + ** PRAGMA temp_store_directory + ** PRAGMA temp_store_directory = ""|"directory_name" + ** + ** Return or set the local value of the temp_store_directory flag. Changing + ** the value sets a specific directory to be used for temporary files. + ** Setting to a null string reverts to the default temporary directory search. + ** If temporary directory is changed, then invalidateTempStorage. + ** + */ + if( sqlite3StrICmp(zLeft, "temp_store_directory")==0 ){ + if( !zRight ){ + if( sqlite3_temp_directory ){ + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, + "temp_store_directory", P4_STATIC); + sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, sqlite3_temp_directory, 0); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); + } + }else{ + if( zRight[0] ){ + int res; + sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res); + if( res==0 ){ + sqlite3ErrorMsg(pParse, "not a writable directory"); + goto pragma_out; + } + } + if( SQLITE_TEMP_STORE==0 + || (SQLITE_TEMP_STORE==1 && db->temp_store<=1) + || (SQLITE_TEMP_STORE==2 && db->temp_store==1) + ){ + invalidateTempStorage(pParse); + } + sqlite3_free(sqlite3_temp_directory); + if( zRight[0] ){ + sqlite3_temp_directory = sqlite3DbStrDup(0, zRight); + }else{ + sqlite3_temp_directory = 0; + } + } + }else + + /* + ** PRAGMA [database.]synchronous + ** PRAGMA [database.]synchronous=OFF|ON|NORMAL|FULL + ** + ** Return or set the local value of the synchronous flag. Changing + ** the local value does not make changes to the disk file and the + ** default value will be restored the next time the database is + ** opened. + */ + if( sqlite3StrICmp(zLeft,"synchronous")==0 ){ + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + if( !zRight ){ + returnSingleInt(pParse, "synchronous", pDb->safety_level-1); + }else{ + if( !db->autoCommit ){ + sqlite3ErrorMsg(pParse, + "Safety level may not be changed inside a transaction"); + }else{ + pDb->safety_level = getSafetyLevel(zRight)+1; + } + } + }else +#endif /* SQLITE_OMIT_PAGER_PRAGMAS */ + +#ifndef SQLITE_OMIT_FLAG_PRAGMAS + if( flagPragma(pParse, zLeft, zRight) ){ + /* The flagPragma() subroutine also generates any necessary code + ** there is nothing more to do here */ + }else +#endif /* SQLITE_OMIT_FLAG_PRAGMAS */ + +#ifndef SQLITE_OMIT_SCHEMA_PRAGMAS + /* + ** PRAGMA table_info(<table>) + ** + ** Return a single row for each column of the named table. The columns of + ** the returned data set are: + ** + ** cid: Column id (numbered from left to right, starting at 0) + ** name: Column name + ** type: Column declaration type. + ** notnull: True if 'NOT NULL' is part of column declaration + ** dflt_value: The default value for the column, if any. + */ + if( sqlite3StrICmp(zLeft, "table_info")==0 && zRight ){ + Table *pTab; + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + pTab = sqlite3FindTable(db, zRight, zDb); + if( pTab ){ + int i; + int nHidden = 0; + Column *pCol; + sqlite3VdbeSetNumCols(v, 6); + pParse->nMem = 6; + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", P4_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P4_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", P4_STATIC); + sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "notnull", P4_STATIC); + sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "dflt_value", P4_STATIC); + sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "pk", P4_STATIC); + sqlite3ViewGetColumnNames(pParse, pTab); + for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){ + const Token *pDflt; + if( IsHiddenColumn(pCol) ){ + nHidden++; + continue; + } + sqlite3VdbeAddOp2(v, OP_Integer, i-nHidden, 1); + sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pCol->zName, 0); + sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, + pCol->zType ? pCol->zType : "", 0); + sqlite3VdbeAddOp2(v, OP_Integer, pCol->notNull, 4); + if( pCol->pDflt && (pDflt = &pCol->pDflt->span)->z ){ + sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pDflt->z, pDflt->n); + }else{ + sqlite3VdbeAddOp2(v, OP_Null, 0, 5); + } + sqlite3VdbeAddOp2(v, OP_Integer, pCol->isPrimKey, 6); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); + } + } + }else + + if( sqlite3StrICmp(zLeft, "index_info")==0 && zRight ){ + Index *pIdx; + Table *pTab; + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + pIdx = sqlite3FindIndex(db, zRight, zDb); + if( pIdx ){ + int i; + pTab = pIdx->pTable; + sqlite3VdbeSetNumCols(v, 3); + pParse->nMem = 3; + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", P4_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", P4_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", P4_STATIC); + for(i=0; i<pIdx->nColumn; i++){ + int cnum = pIdx->aiColumn[i]; + sqlite3VdbeAddOp2(v, OP_Integer, i, 1); + sqlite3VdbeAddOp2(v, OP_Integer, cnum, 2); + assert( pTab->nCol>cnum ); + sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pTab->aCol[cnum].zName, 0); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); + } + } + }else + + if( sqlite3StrICmp(zLeft, "index_list")==0 && zRight ){ + Index *pIdx; + Table *pTab; + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + pTab = sqlite3FindTable(db, zRight, zDb); + if( pTab ){ + v = sqlite3GetVdbe(pParse); + pIdx = pTab->pIndex; + if( pIdx ){ + int i = 0; + sqlite3VdbeSetNumCols(v, 3); + pParse->nMem = 3; + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P4_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P4_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", P4_STATIC); + while(pIdx){ + sqlite3VdbeAddOp2(v, OP_Integer, i, 1); + sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0); + sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); + ++i; + pIdx = pIdx->pNext; + } + } + } + }else + + if( sqlite3StrICmp(zLeft, "database_list")==0 ){ + int i; + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + sqlite3VdbeSetNumCols(v, 3); + pParse->nMem = 3; + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P4_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P4_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "file", P4_STATIC); + for(i=0; i<db->nDb; i++){ + if( db->aDb[i].pBt==0 ) continue; + assert( db->aDb[i].zName!=0 ); + sqlite3VdbeAddOp2(v, OP_Integer, i, 1); + sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, db->aDb[i].zName, 0); + sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, + sqlite3BtreeGetFilename(db->aDb[i].pBt), 0); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); + } + }else + + if( sqlite3StrICmp(zLeft, "collation_list")==0 ){ + int i = 0; + HashElem *p; + sqlite3VdbeSetNumCols(v, 2); + pParse->nMem = 2; + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P4_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P4_STATIC); + for(p=sqliteHashFirst(&db->aCollSeq); p; p=sqliteHashNext(p)){ + CollSeq *pColl = (CollSeq *)sqliteHashData(p); + sqlite3VdbeAddOp2(v, OP_Integer, i++, 1); + sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pColl->zName, 0); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2); + } + }else +#endif /* SQLITE_OMIT_SCHEMA_PRAGMAS */ + +#ifndef SQLITE_OMIT_FOREIGN_KEY + if( sqlite3StrICmp(zLeft, "foreign_key_list")==0 && zRight ){ + FKey *pFK; + Table *pTab; + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + pTab = sqlite3FindTable(db, zRight, zDb); + if( pTab ){ + v = sqlite3GetVdbe(pParse); + pFK = pTab->pFKey; + if( pFK ){ + int i = 0; + sqlite3VdbeSetNumCols(v, 5); + pParse->nMem = 5; + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "id", P4_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "seq", P4_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "table", P4_STATIC); + sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "from", P4_STATIC); + sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "to", P4_STATIC); + while(pFK){ + int j; + for(j=0; j<pFK->nCol; j++){ + char *zCol = pFK->aCol[j].zCol; + sqlite3VdbeAddOp2(v, OP_Integer, i, 1); + sqlite3VdbeAddOp2(v, OP_Integer, j, 2); + sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pFK->zTo, 0); + sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0, + pTab->aCol[pFK->aCol[j].iFrom].zName, 0); + sqlite3VdbeAddOp4(v, zCol ? OP_String8 : OP_Null, 0, 5, 0, zCol, 0); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5); + } + ++i; + pFK = pFK->pNextFrom; + } + } + } + }else +#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ + +#ifndef NDEBUG + if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){ + if( zRight ){ + if( getBoolean(zRight) ){ + sqlite3ParserTrace(stderr, "parser: "); + }else{ + sqlite3ParserTrace(0, 0); + } + } + }else +#endif + + /* Reinstall the LIKE and GLOB functions. The variant of LIKE + ** used will be case sensitive or not depending on the RHS. + */ + if( sqlite3StrICmp(zLeft, "case_sensitive_like")==0 ){ + if( zRight ){ + sqlite3RegisterLikeFunctions(db, getBoolean(zRight)); + } + }else + +#ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX +# define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100 +#endif + +#ifndef SQLITE_OMIT_INTEGRITY_CHECK + /* Pragma "quick_check" is an experimental reduced version of + ** integrity_check designed to detect most database corruption + ** without most of the overhead of a full integrity-check. + */ + if( sqlite3StrICmp(zLeft, "integrity_check")==0 + || sqlite3StrICmp(zLeft, "quick_check")==0 + ){ + int i, j, addr, mxErr; + + /* Code that appears at the end of the integrity check. If no error + ** messages have been generated, output OK. Otherwise output the + ** error message + */ + static const VdbeOpList endCode[] = { + { OP_AddImm, 1, 0, 0}, /* 0 */ + { OP_IfNeg, 1, 0, 0}, /* 1 */ + { OP_String8, 0, 3, 0}, /* 2 */ + { OP_ResultRow, 3, 1, 0}, + }; + + int isQuick = (zLeft[0]=='q'); + + /* Initialize the VDBE program */ + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + pParse->nMem = 6; + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", P4_STATIC); + + /* Set the maximum error count */ + mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; + if( zRight ){ + mxErr = atoi(zRight); + if( mxErr<=0 ){ + mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; + } + } + sqlite3VdbeAddOp2(v, OP_Integer, mxErr, 1); /* reg[1] holds errors left */ + + /* Do an integrity check on each database file */ + for(i=0; i<db->nDb; i++){ + HashElem *x; + Hash *pTbls; + int cnt = 0; + + if( OMIT_TEMPDB && i==1 ) continue; + + sqlite3CodeVerifySchema(pParse, i); + addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Halt if out of errors */ + sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); + sqlite3VdbeJumpHere(v, addr); + + /* Do an integrity check of the B-Tree + ** + ** Begin by filling registers 2, 3, ... with the root pages numbers + ** for all tables and indices in the database. + */ + pTbls = &db->aDb[i].pSchema->tblHash; + for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ + Table *pTab = sqliteHashData(x); + Index *pIdx; + sqlite3VdbeAddOp2(v, OP_Integer, pTab->tnum, 2+cnt); + cnt++; + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + sqlite3VdbeAddOp2(v, OP_Integer, pIdx->tnum, 2+cnt); + cnt++; + } + } + if( cnt==0 ) continue; + + /* Make sure sufficient number of registers have been allocated */ + if( pParse->nMem < cnt+4 ){ + pParse->nMem = cnt+4; + } + + /* Do the b-tree integrity checks */ + sqlite3VdbeAddOp3(v, OP_IntegrityCk, 2, cnt, 1); + sqlite3VdbeChangeP5(v, i); + addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); + sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, + sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName), + P4_DYNAMIC); + sqlite3VdbeAddOp3(v, OP_Move, 2, 4, 1); + sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2); + sqlite3VdbeAddOp2(v, OP_ResultRow, 2, 1); + sqlite3VdbeJumpHere(v, addr); + + /* Make sure all the indices are constructed correctly. + */ + for(x=sqliteHashFirst(pTbls); x && !isQuick; x=sqliteHashNext(x)){ + Table *pTab = sqliteHashData(x); + Index *pIdx; + int loopTop; + + if( pTab->pIndex==0 ) continue; + addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Stop if out of errors */ + sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); + sqlite3VdbeJumpHere(v, addr); + sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead); + sqlite3VdbeAddOp2(v, OP_Integer, 0, 2); /* reg(2) will count entries */ + loopTop = sqlite3VdbeAddOp2(v, OP_Rewind, 1, 0); + sqlite3VdbeAddOp2(v, OP_AddImm, 2, 1); /* increment entry count */ + for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ + int jmp2; + static const VdbeOpList idxErr[] = { + { OP_AddImm, 1, -1, 0}, + { OP_String8, 0, 3, 0}, /* 1 */ + { OP_Rowid, 1, 4, 0}, + { OP_String8, 0, 5, 0}, /* 3 */ + { OP_String8, 0, 6, 0}, /* 4 */ + { OP_Concat, 4, 3, 3}, + { OP_Concat, 5, 3, 3}, + { OP_Concat, 6, 3, 3}, + { OP_ResultRow, 3, 1, 0}, + { OP_IfPos, 1, 0, 0}, /* 9 */ + { OP_Halt, 0, 0, 0}, + }; + sqlite3GenerateIndexKey(pParse, pIdx, 1, 3, 1); + jmp2 = sqlite3VdbeAddOp3(v, OP_Found, j+2, 0, 3); + addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr); + sqlite3VdbeChangeP4(v, addr+1, "rowid ", P4_STATIC); + sqlite3VdbeChangeP4(v, addr+3, " missing from index ", P4_STATIC); + sqlite3VdbeChangeP4(v, addr+4, pIdx->zName, P4_STATIC); + sqlite3VdbeJumpHere(v, addr+9); + sqlite3VdbeJumpHere(v, jmp2); + } + sqlite3VdbeAddOp2(v, OP_Next, 1, loopTop+1); + sqlite3VdbeJumpHere(v, loopTop); + for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ + static const VdbeOpList cntIdx[] = { + { OP_Integer, 0, 3, 0}, + { OP_Rewind, 0, 0, 0}, /* 1 */ + { OP_AddImm, 3, 1, 0}, + { OP_Next, 0, 0, 0}, /* 3 */ + { OP_Eq, 2, 0, 3}, /* 4 */ + { OP_AddImm, 1, -1, 0}, + { OP_String8, 0, 2, 0}, /* 6 */ + { OP_String8, 0, 3, 0}, /* 7 */ + { OP_Concat, 3, 2, 2}, + { OP_ResultRow, 2, 1, 0}, + }; + if( pIdx->tnum==0 ) continue; + addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); + sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); + sqlite3VdbeJumpHere(v, addr); + addr = sqlite3VdbeAddOpList(v, ArraySize(cntIdx), cntIdx); + sqlite3VdbeChangeP1(v, addr+1, j+2); + sqlite3VdbeChangeP2(v, addr+1, addr+4); + sqlite3VdbeChangeP1(v, addr+3, j+2); + sqlite3VdbeChangeP2(v, addr+3, addr+2); + sqlite3VdbeJumpHere(v, addr+4); + sqlite3VdbeChangeP4(v, addr+6, + "wrong # of entries in index ", P4_STATIC); + sqlite3VdbeChangeP4(v, addr+7, pIdx->zName, P4_STATIC); + } + } + } + addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode); + sqlite3VdbeChangeP2(v, addr, -mxErr); + sqlite3VdbeJumpHere(v, addr+1); + sqlite3VdbeChangeP4(v, addr+2, "ok", P4_STATIC); + }else +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ + +#ifndef SQLITE_OMIT_UTF16 + /* + ** PRAGMA encoding + ** PRAGMA encoding = "utf-8"|"utf-16"|"utf-16le"|"utf-16be" + ** + ** In its first form, this pragma returns the encoding of the main + ** database. If the database is not initialized, it is initialized now. + ** + ** The second form of this pragma is a no-op if the main database file + ** has not already been initialized. In this case it sets the default + ** encoding that will be used for the main database file if a new file + ** is created. If an existing main database file is opened, then the + ** default text encoding for the existing database is used. + ** + ** In all cases new databases created using the ATTACH command are + ** created to use the same default text encoding as the main database. If + ** the main database has not been initialized and/or created when ATTACH + ** is executed, this is done before the ATTACH operation. + ** + ** In the second form this pragma sets the text encoding to be used in + ** new database files created using this database handle. It is only + ** useful if invoked immediately after the main database i + */ + if( sqlite3StrICmp(zLeft, "encoding")==0 ){ + static const struct EncName { + char *zName; + u8 enc; + } encnames[] = { + { "UTF-8", SQLITE_UTF8 }, + { "UTF8", SQLITE_UTF8 }, + { "UTF-16le", SQLITE_UTF16LE }, + { "UTF16le", SQLITE_UTF16LE }, + { "UTF-16be", SQLITE_UTF16BE }, + { "UTF16be", SQLITE_UTF16BE }, + { "UTF-16", 0 }, /* SQLITE_UTF16NATIVE */ + { "UTF16", 0 }, /* SQLITE_UTF16NATIVE */ + { 0, 0 } + }; + const struct EncName *pEnc; + if( !zRight ){ /* "PRAGMA encoding" */ + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "encoding", P4_STATIC); + sqlite3VdbeAddOp2(v, OP_String8, 0, 1); + for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ + if( pEnc->enc==ENC(pParse->db) ){ + sqlite3VdbeChangeP4(v, -1, pEnc->zName, P4_STATIC); + break; + } + } + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); + }else{ /* "PRAGMA encoding = XXX" */ + /* Only change the value of sqlite.enc if the database handle is not + ** initialized. If the main database exists, the new sqlite.enc value + ** 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( + !(DbHasProperty(db, 0, DB_SchemaLoaded)) || + DbHasProperty(db, 0, DB_Empty) + ){ + for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ + if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){ + ENC(pParse->db) = pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE; + break; + } + } + if( !pEnc->zName ){ + sqlite3ErrorMsg(pParse, "unsupported encoding: %s", zRight); + } + } + } + }else +#endif /* SQLITE_OMIT_UTF16 */ + +#ifndef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS + /* + ** PRAGMA [database.]schema_version + ** PRAGMA [database.]schema_version = <integer> + ** + ** PRAGMA [database.]user_version + ** PRAGMA [database.]user_version = <integer> + ** + ** The pragma's schema_version and user_version are used to set or get + ** the value of the schema-version and user-version, respectively. Both + ** the schema-version and the user-version are 32-bit signed integers + ** stored in the database header. + ** + ** The schema-cookie is usually only manipulated internally by SQLite. It + ** is incremented by SQLite whenever the database schema is modified (by + ** creating or dropping a table or index). The schema version is used by + ** SQLite each time a query is executed to ensure that the internal cache + ** of the schema used when compiling the SQL query matches the schema of + ** the database against which the compiled query is actually executed. + ** Subverting this mechanism by using "PRAGMA schema_version" to modify + ** the schema-version is potentially dangerous and may lead to program + ** crashes or database corruption. Use with caution! + ** + ** The user-version is not used internally by SQLite. It may be used by + ** applications for any purpose. + */ + if( sqlite3StrICmp(zLeft, "schema_version")==0 + || sqlite3StrICmp(zLeft, "user_version")==0 + || sqlite3StrICmp(zLeft, "freelist_count")==0 + ){ + + int iCookie; /* Cookie index. 0 for schema-cookie, 6 for user-cookie. */ + sqlite3VdbeUsesBtree(v, iDb); + switch( zLeft[0] ){ + case 's': case 'S': + iCookie = 0; + break; + case 'f': case 'F': + iCookie = 1; + iDb = (-1*(iDb+1)); + assert(iDb<=0); + break; + default: + iCookie = 5; + break; + } + + if( zRight && iDb>=0 ){ + /* Write the specified cookie value */ + static const VdbeOpList setCookie[] = { + { OP_Transaction, 0, 1, 0}, /* 0 */ + { OP_Integer, 0, 1, 0}, /* 1 */ + { OP_SetCookie, 0, 0, 1}, /* 2 */ + }; + int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie); + sqlite3VdbeChangeP1(v, addr, iDb); + sqlite3VdbeChangeP1(v, addr+1, atoi(zRight)); + sqlite3VdbeChangeP1(v, addr+2, iDb); + sqlite3VdbeChangeP2(v, addr+2, iCookie); + }else{ + /* Read the specified cookie value */ + static const VdbeOpList readCookie[] = { + { OP_ReadCookie, 0, 1, 0}, /* 0 */ + { OP_ResultRow, 1, 1, 0} + }; + int addr = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie); + sqlite3VdbeChangeP1(v, addr, iDb); + sqlite3VdbeChangeP3(v, addr, iCookie); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, P4_TRANSIENT); + } + }else +#endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */ + +#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) + /* + ** Report the current state of file logs for all databases + */ + if( sqlite3StrICmp(zLeft, "lock_status")==0 ){ + static const char *const azLockName[] = { + "unlocked", "shared", "reserved", "pending", "exclusive" + }; + int i; + Vdbe *v = sqlite3GetVdbe(pParse); + sqlite3VdbeSetNumCols(v, 2); + pParse->nMem = 2; + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "database", P4_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "status", P4_STATIC); + for(i=0; i<db->nDb; i++){ + Btree *pBt; + Pager *pPager; + const char *zState = "unknown"; + int j; + if( db->aDb[i].zName==0 ) continue; + sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, db->aDb[i].zName, P4_STATIC); + pBt = db->aDb[i].pBt; + if( pBt==0 || (pPager = sqlite3BtreePager(pBt))==0 ){ + zState = "closed"; + }else if( sqlite3_file_control(db, i ? db->aDb[i].zName : 0, + SQLITE_FCNTL_LOCKSTATE, &j)==SQLITE_OK ){ + zState = azLockName[j]; + } + sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, zState, P4_STATIC); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2); + } + }else +#endif + +#ifdef SQLITE_SSE + /* + ** Check to see if the sqlite_statements table exists. Create it + ** if it does not. + */ + if( sqlite3StrICmp(zLeft, "create_sqlite_statement_table")==0 ){ + extern int sqlite3CreateStatementsTable(Parse*); + sqlite3CreateStatementsTable(pParse); + }else +#endif + +#if SQLITE_HAS_CODEC + if( sqlite3StrICmp(zLeft, "key")==0 ){ + sqlite3_key(db, zRight, strlen(zRight)); + }else +#endif +#if SQLITE_HAS_CODEC || defined(SQLITE_ENABLE_CEROD) + if( sqlite3StrICmp(zLeft, "activate_extensions")==0 ){ +#if SQLITE_HAS_CODEC + if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){ + extern void sqlite3_activate_see(const char*); + sqlite3_activate_see(&zRight[4]); + } +#endif +#ifdef SQLITE_ENABLE_CEROD + if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){ + extern void sqlite3_activate_cerod(const char*); + sqlite3_activate_cerod(&zRight[6]); + } +#endif + } +#endif + + {} + + if( v ){ + /* Code an OP_Expire at the end of each PRAGMA program to cause + ** the VDBE implementing the pragma to expire. Most (all?) pragmas + ** are only valid for a single execution. + */ + sqlite3VdbeAddOp2(v, OP_Expire, 1, 0); + + /* + ** Reset the safety level, in case the fullfsync flag or synchronous + ** setting changed. + */ +#ifndef SQLITE_OMIT_PAGER_PRAGMAS + if( db->autoCommit ){ + sqlite3BtreeSetSafetyLevel(pDb->pBt, pDb->safety_level, + (db->flags&SQLITE_FullFSync)!=0); + } +#endif + } +pragma_out: + sqlite3DbFree(db, zLeft); + sqlite3DbFree(db, zRight); +} + +#endif /* SQLITE_OMIT_PRAGMA || SQLITE_OMIT_PARSER */ diff --git a/third_party/sqlite/src/prepare.c b/third_party/sqlite/src/prepare.c new file mode 100755 index 0000000..ef49f0a --- /dev/null +++ b/third_party/sqlite/src/prepare.c @@ -0,0 +1,813 @@ +/* +** 2005 May 25 +** +** 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 the implementation of the sqlite3_prepare() +** interface, and routines that contribute to loading the database schema +** from disk. +** +** $Id: prepare.c,v 1.91 2008/08/02 03:50:39 drh Exp $ +*/ +#include "sqliteInt.h" +#include <ctype.h> + +/* +** Fill the InitData structure with an error message that indicates +** that the database is corrupt. +*/ +static void corruptSchema( + InitData *pData, /* Initialization context */ + const char *zObj, /* Object being parsed at the point of error */ + const char *zExtra /* Error information */ +){ + if( !pData->db->mallocFailed ){ + if( zObj==0 ) zObj = "?"; + sqlite3SetString(pData->pzErrMsg, pData->db, + "malformed database schema (%s)", zObj); + if( zExtra && zExtra[0] ){ + *pData->pzErrMsg = sqlite3MAppendf(pData->db, *pData->pzErrMsg, "%s - %s", + *pData->pzErrMsg, zExtra); + } + } + pData->rc = SQLITE_CORRUPT; +} + +/* +** This is the callback routine for the code that initializes the +** database. See sqlite3Init() below for additional information. +** This routine is also called from the OP_ParseSchema opcode of the VDBE. +** +** Each callback contains the following information: +** +** argv[0] = name of thing being created +** argv[1] = root page number for table or index. 0 for trigger or view. +** argv[2] = SQL text for the CREATE statement. +** +*/ +int sqlite3InitCallback(void *pInit, int argc, char **argv, char **azColName){ + InitData *pData = (InitData*)pInit; + sqlite3 *db = pData->db; + int iDb = pData->iDb; + + assert( sqlite3_mutex_held(db->mutex) ); + pData->rc = SQLITE_OK; + DbClearProperty(db, iDb, DB_Empty); + if( db->mallocFailed ){ + corruptSchema(pData, argv[0], 0); + return SQLITE_NOMEM; + } + + assert( argc==3 ); + if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */ + if( argv[1]==0 ){ + corruptSchema(pData, argv[0], 0); + return 1; + } + assert( iDb>=0 && iDb<db->nDb ); + if( argv[2] && argv[2][0] ){ + /* Call the parser to process a CREATE TABLE, INDEX or VIEW. + ** But because db->init.busy is set to 1, no VDBE code is generated + ** or executed. All the parser does is build the internal data + ** structures that describe the table, index, or view. + */ + char *zErr; + int rc; + u8 lookasideEnabled; + assert( db->init.busy ); + db->init.iDb = iDb; + db->init.newTnum = atoi(argv[1]); + lookasideEnabled = db->lookaside.bEnabled; + db->lookaside.bEnabled = 0; + rc = sqlite3_exec(db, argv[2], 0, 0, &zErr); + db->init.iDb = 0; + db->lookaside.bEnabled = lookasideEnabled; + assert( rc!=SQLITE_OK || zErr==0 ); + if( SQLITE_OK!=rc ){ + pData->rc = rc; + if( rc==SQLITE_NOMEM ){ + db->mallocFailed = 1; + }else if( rc!=SQLITE_INTERRUPT ){ + corruptSchema(pData, argv[0], zErr); + } + sqlite3DbFree(db, zErr); + return 1; + } + }else if( argv[0]==0 ){ + corruptSchema(pData, 0, 0); + }else{ + /* If the SQL column is blank it means this is an index that + ** was created to be the PRIMARY KEY or to fulfill a UNIQUE + ** constraint for a CREATE TABLE. The index should have already + ** been created when we processed the CREATE TABLE. All we have + ** to do here is record the root page number for that index. + */ + Index *pIndex; + pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zName); + if( pIndex==0 || pIndex->tnum!=0 ){ + /* This can occur if there exists an index on a TEMP table which + ** has the same name as another index on a permanent index. Since + ** the permanent table is hidden by the TEMP table, we can also + ** safely ignore the index on the permanent table. + */ + /* Do Nothing */; + }else{ + pIndex->tnum = atoi(argv[1]); + } + } + return 0; +} + +/* +** Attempt to read the database schema and initialize internal +** data structures for a single database file. The index of the +** database file is given by iDb. iDb==0 is used for the main +** database. iDb==1 should never be used. iDb>=2 is used for +** auxiliary databases. Return one of the SQLITE_ error codes to +** indicate success or failure. +*/ +static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ + int rc; + BtCursor *curMain; + int size; + Table *pTab; + Db *pDb; + char const *azArg[4]; + int meta[10]; + InitData initData; + char const *zMasterSchema; + char const *zMasterName = SCHEMA_TABLE(iDb); + + /* + ** The master database table has a structure like this + */ + static const char master_schema[] = + "CREATE TABLE sqlite_master(\n" + " type text,\n" + " name text,\n" + " tbl_name text,\n" + " rootpage integer,\n" + " sql text\n" + ")" + ; +#ifndef SQLITE_OMIT_TEMPDB + static const char temp_master_schema[] = + "CREATE TEMP TABLE sqlite_temp_master(\n" + " type text,\n" + " name text,\n" + " tbl_name text,\n" + " rootpage integer,\n" + " sql text\n" + ")" + ; +#else + #define temp_master_schema 0 +#endif + + assert( iDb>=0 && iDb<db->nDb ); + assert( db->aDb[iDb].pSchema ); + assert( sqlite3_mutex_held(db->mutex) ); + assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); + + /* zMasterSchema and zInitScript are set to point at the master schema + ** and initialisation script appropriate for the database being + ** initialised. zMasterName is the name of the master table. + */ + if( !OMIT_TEMPDB && iDb==1 ){ + zMasterSchema = temp_master_schema; + }else{ + zMasterSchema = master_schema; + } + zMasterName = SCHEMA_TABLE(iDb); + + /* Construct the schema tables. */ + azArg[0] = zMasterName; + azArg[1] = "1"; + azArg[2] = zMasterSchema; + azArg[3] = 0; + initData.db = db; + initData.iDb = iDb; + initData.pzErrMsg = pzErrMsg; + (void)sqlite3SafetyOff(db); + rc = sqlite3InitCallback(&initData, 3, (char **)azArg, 0); + (void)sqlite3SafetyOn(db); + if( rc ){ + rc = initData.rc; + goto error_out; + } + pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName); + if( pTab ){ + pTab->readOnly = 1; + } + + /* Create a cursor to hold the database open + */ + pDb = &db->aDb[iDb]; + if( pDb->pBt==0 ){ + if( !OMIT_TEMPDB && iDb==1 ){ + DbSetProperty(db, 1, DB_SchemaLoaded); + } + return SQLITE_OK; + } + curMain = sqlite3MallocZero(sqlite3BtreeCursorSize()); + if( !curMain ){ + rc = SQLITE_NOMEM; + goto error_out; + } + sqlite3BtreeEnter(pDb->pBt); + rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, curMain); + if( rc!=SQLITE_OK && rc!=SQLITE_EMPTY ){ + sqlite3SetString(pzErrMsg, db, "%s", sqlite3ErrStr(rc)); + goto initone_error_out; + } + + /* Get the database meta information. + ** + ** Meta values are as follows: + ** meta[0] Schema cookie. Changes with each schema change. + ** meta[1] File format of schema layer. + ** meta[2] Size of the page cache. + ** meta[3] Use freelist if 0. Autovacuum if greater than zero. + ** meta[4] Db text encoding. 1:UTF-8 2:UTF-16LE 3:UTF-16BE + ** meta[5] The user cookie. Used by the application. + ** meta[6] Incremental-vacuum flag. + ** meta[7] + ** meta[8] + ** meta[9] + ** + ** 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; i<sizeof(meta)/sizeof(meta[0]); i++){ + rc = sqlite3BtreeGetMeta(pDb->pBt, i+1, (u32 *)&meta[i]); + if( rc ){ + sqlite3SetString(pzErrMsg, db, "%s", sqlite3ErrStr(rc)); + goto initone_error_out; + } + } + }else{ + memset(meta, 0, sizeof(meta)); + } + 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. + ** For an attached db, it is an error if the encoding is not the same + ** as sqlite3.enc. + */ + if( meta[4] ){ /* text encoding */ + if( iDb==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 ENC(db) */ + if( meta[4]!=ENC(db) ){ + sqlite3SetString(pzErrMsg, db, "attached databases must use the same" + " text encoding as main database"); + rc = SQLITE_ERROR; + goto initone_error_out; + } + } + }else{ + DbSetProperty(db, iDb, DB_Empty); + } + pDb->pSchema->enc = ENC(db); + + if( pDb->pSchema->cache_size==0 ){ + size = meta[2]; + if( size==0 ){ size = SQLITE_DEFAULT_CACHE_SIZE; } + if( size<0 ) size = -size; + 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. // 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 + */ + 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 ){ + sqlite3SetString(pzErrMsg, db, "unsupported file format"); + rc = SQLITE_ERROR; + goto initone_error_out; + } + + /* Ticket #2804: When we open a database in the newer file format, + ** clear the legacy_file_format pragma flag so that a VACUUM will + ** not downgrade the database and thus invalidate any descending + ** indices that the user might have created. + */ + if( iDb==0 && meta[1]>=4 ){ + db->flags &= ~SQLITE_LegacyFileFmt; + } + + /* Read the schema information out of the schema tables + */ + assert( db->init.busy ); + if( rc==SQLITE_EMPTY ){ + /* For an empty database, there is nothing to read */ + rc = SQLITE_OK; + }else{ + char *zSql; + zSql = sqlite3MPrintf(db, + "SELECT name, rootpage, sql FROM '%q'.%s", + db->aDb[iDb].zName, zMasterName); + (void)sqlite3SafetyOff(db); +#ifndef SQLITE_OMIT_AUTHORIZATION + { + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); + xAuth = db->xAuth; + db->xAuth = 0; +#endif + rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); +#ifndef SQLITE_OMIT_AUTHORIZATION + db->xAuth = xAuth; + } +#endif + if( rc==SQLITE_ABORT ) rc = initData.rc; + (void)sqlite3SafetyOn(db); + sqlite3DbFree(db, zSql); +#ifndef SQLITE_OMIT_ANALYZE + if( rc==SQLITE_OK ){ + sqlite3AnalysisLoad(db, iDb); + } +#endif + } + if( db->mallocFailed ){ + rc = SQLITE_NOMEM; + sqlite3ResetInternalSchema(db, 0); + } + if( rc==SQLITE_OK || (db->flags&SQLITE_RecoveryMode)){ + /* Black magic: If the SQLITE_RecoveryMode flag is set, then consider + ** the schema loaded, even if errors occured. In this situation the + ** current sqlite3_prepare() operation will fail, but the following one + ** will attempt to compile the supplied statement against whatever subset + ** of the schema was loaded before the error occured. The primary + ** purpose of this is to allow access to the sqlite_master table + ** even when its contents have been corrupted. + */ + DbSetProperty(db, iDb, DB_SchemaLoaded); + rc = SQLITE_OK; + } + + /* Jump here for an error that occurs after successfully allocating + ** curMain and calling sqlite3BtreeEnter(). For an error that occurs + ** before that point, jump to error_out. + */ +initone_error_out: + sqlite3BtreeCloseCursor(curMain); + sqlite3_free(curMain); + sqlite3BtreeLeave(pDb->pBt); + +error_out: + if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ + db->mallocFailed = 1; + } + return rc; +} + +/* +** Initialize all database files - the main database file, the file +** used to store temporary tables, and any additional database files +** created using ATTACH statements. Return a success code. If an +** error occurs, write an error message into *pzErrMsg. +** +** 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 commit_internal = !(db->flags&SQLITE_InternChanges); + + assert( sqlite3_mutex_held(db->mutex) ); + if( db->init.busy ) return SQLITE_OK; + rc = SQLITE_OK; + db->init.busy = 1; + for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ + if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue; + rc = sqlite3InitOne(db, i, pzErrMsg); + if( rc ){ + sqlite3ResetInternalSchema(db, i); + } + } + + /* Once all the other databases have been initialised, load the schema + ** for the TEMP database. This is loaded last, as the TEMP database + ** schema may contain references to objects in other databases. + */ +#ifndef SQLITE_OMIT_TEMPDB + if( rc==SQLITE_OK && db->nDb>1 && !DbHasProperty(db, 1, DB_SchemaLoaded) ){ + rc = sqlite3InitOne(db, 1, pzErrMsg); + if( rc ){ + sqlite3ResetInternalSchema(db, 1); + } + } +#endif + + db->init.busy = 0; + if( rc==SQLITE_OK && commit_internal ){ + sqlite3CommitInternalChanges(db); + } + + return rc; +} + +/* +** This routine is a no-op if the database schema is already initialised. +** Otherwise, the schema is loaded. An error code is returned. +*/ +int sqlite3ReadSchema(Parse *pParse){ + int rc = SQLITE_OK; + sqlite3 *db = pParse->db; + assert( sqlite3_mutex_held(db->mutex) ); + if( !db->init.busy ){ + rc = sqlite3Init(db, &pParse->zErrMsg); + } + if( rc!=SQLITE_OK ){ + pParse->rc = rc; + pParse->nErr++; + } + return rc; +} + + +/* +** Check schema cookies in all databases. If any cookie is out +** of date, return 0. If all schema cookies are current, return 1. +*/ +static int schemaIsValid(sqlite3 *db){ + int iDb; + int rc; + BtCursor *curTemp; + int cookie; + int allOk = 1; + + curTemp = (BtCursor *)sqlite3Malloc(sqlite3BtreeCursorSize()); + if( curTemp ){ + assert( sqlite3_mutex_held(db->mutex) ); + for(iDb=0; allOk && iDb<db->nDb; iDb++){ + Btree *pBt; + pBt = db->aDb[iDb].pBt; + if( pBt==0 ) continue; + memset(curTemp, 0, sqlite3BtreeCursorSize()); + rc = sqlite3BtreeCursor(pBt, MASTER_ROOT, 0, 0, curTemp); + if( rc==SQLITE_OK ){ + rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&cookie); + if( rc==SQLITE_OK && cookie!=db->aDb[iDb].pSchema->schema_cookie ){ + allOk = 0; + } + sqlite3BtreeCloseCursor(curTemp); + } + if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ + db->mallocFailed = 1; + } + } + sqlite3_free(curTemp); + }else{ + allOk = 0; + db->mallocFailed = 1; + } + + return allOk; +} + +/* +** 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). + */ + assert( sqlite3_mutex_held(db->mutex) ); + if( pSchema ){ + for(i=0; i<db->nDb; i++){ + if( db->aDb[i].pSchema==pSchema ){ + break; + } + } + assert( i>=0 &&i>=0 && i<db->nDb ); + } + return i; +} + +/* +** Compile the UTF-8 encoded SQL statement zSql into a statement handle. +*/ +static int sqlite3Prepare( + sqlite3 *db, /* Database handle. */ + const char *zSql, /* UTF-8 encoded SQL statement. */ + int nBytes, /* Length of zSql in bytes. */ + int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */ + sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ + const char **pzTail /* OUT: End of parsed string */ +){ + Parse sParse; + char *zErrMsg = 0; + int rc = SQLITE_OK; + int i; + + assert( ppStmt ); + *ppStmt = 0; + if( sqlite3SafetyOn(db) ){ + return SQLITE_MISUSE; + } + assert( !db->mallocFailed ); + assert( sqlite3_mutex_held(db->mutex) ); + + /* If any attached database schemas are locked, do not proceed with + ** compilation. Instead return SQLITE_LOCKED immediately. + */ + for(i=0; i<db->nDb; i++) { + Btree *pBt = db->aDb[i].pBt; + if( pBt ){ + int rc; + rc = sqlite3BtreeSchemaLocked(pBt); + if( rc ){ + const char *zDb = db->aDb[i].zName; + sqlite3Error(db, SQLITE_LOCKED, "database schema is locked: %s", zDb); + (void)sqlite3SafetyOff(db); + return sqlite3ApiExit(db, SQLITE_LOCKED); + } + } + } + + memset(&sParse, 0, sizeof(sParse)); + sParse.db = db; + if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){ + char *zSqlCopy; + int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; + if( nBytes>mxLen ){ + sqlite3Error(db, SQLITE_TOOBIG, "statement too long"); + (void)sqlite3SafetyOff(db); + return sqlite3ApiExit(db, SQLITE_TOOBIG); + } + zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes); + if( zSqlCopy ){ + sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg); + sqlite3DbFree(db, zSqlCopy); + sParse.zTail = &zSql[sParse.zTail-zSqlCopy]; + }else{ + sParse.zTail = &zSql[nBytes]; + } + }else{ + sqlite3RunParser(&sParse, zSql, &zErrMsg); + } + + if( db->mallocFailed ){ + sParse.rc = SQLITE_NOMEM; + } + if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK; + if( sParse.checkSchema && !schemaIsValid(db) ){ + sParse.rc = SQLITE_SCHEMA; + } + if( sParse.rc==SQLITE_SCHEMA ){ + sqlite3ResetInternalSchema(db, 0); + } + if( db->mallocFailed ){ + sParse.rc = SQLITE_NOMEM; + } + if( pzTail ){ + *pzTail = sParse.zTail; + } + rc = sParse.rc; + +#ifndef SQLITE_OMIT_EXPLAIN + if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){ + if( sParse.explain==2 ){ + sqlite3VdbeSetNumCols(sParse.pVdbe, 3); + sqlite3VdbeSetColName(sParse.pVdbe, 0, COLNAME_NAME, "order", P4_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 1, COLNAME_NAME, "from", P4_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 2, COLNAME_NAME, "detail", P4_STATIC); + }else{ + sqlite3VdbeSetNumCols(sParse.pVdbe, 8); + sqlite3VdbeSetColName(sParse.pVdbe, 0, COLNAME_NAME, "addr", P4_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 1, COLNAME_NAME, "opcode", P4_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 2, COLNAME_NAME, "p1", P4_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 3, COLNAME_NAME, "p2", P4_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 4, COLNAME_NAME, "p3", P4_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 5, COLNAME_NAME, "p4", P4_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 6, COLNAME_NAME, "p5", P4_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 7, COLNAME_NAME, "comment",P4_STATIC); + } + } +#endif + + if( sqlite3SafetyOff(db) ){ + rc = SQLITE_MISUSE; + } + + if( saveSqlFlag ){ + sqlite3VdbeSetSql(sParse.pVdbe, zSql, sParse.zTail - zSql); + } + if( rc!=SQLITE_OK || db->mallocFailed ){ + sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe); + assert(!(*ppStmt)); + }else{ + *ppStmt = (sqlite3_stmt*)sParse.pVdbe; + } + + if( zErrMsg ){ + sqlite3Error(db, rc, "%s", zErrMsg); + sqlite3DbFree(db, zErrMsg); + }else{ + sqlite3Error(db, rc, 0); + } + + rc = sqlite3ApiExit(db, rc); + assert( (rc&db->errMask)==rc ); + return rc; +} +static int sqlite3LockAndPrepare( + sqlite3 *db, /* Database handle. */ + const char *zSql, /* UTF-8 encoded SQL statement. */ + int nBytes, /* Length of zSql in bytes. */ + int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */ + sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ + const char **pzTail /* OUT: End of parsed string */ +){ + int rc; + if( !sqlite3SafetyCheckOk(db) ){ + return SQLITE_MISUSE; + } + sqlite3_mutex_enter(db->mutex); + sqlite3BtreeEnterAll(db); + rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, ppStmt, pzTail); + sqlite3BtreeLeaveAll(db); + sqlite3_mutex_leave(db->mutex); + return rc; +} + +/* +** Rerun the compilation of a statement after a schema change. +** Return true if the statement was recompiled successfully. +** Return false if there is an error of some kind. +*/ +int sqlite3Reprepare(Vdbe *p){ + int rc; + sqlite3_stmt *pNew; + const char *zSql; + sqlite3 *db; + + assert( sqlite3_mutex_held(sqlite3VdbeDb(p)->mutex) ); + zSql = sqlite3_sql((sqlite3_stmt *)p); + assert( zSql!=0 ); /* Reprepare only called for prepare_v2() statements */ + db = sqlite3VdbeDb(p); + assert( sqlite3_mutex_held(db->mutex) ); + rc = sqlite3LockAndPrepare(db, zSql, -1, 0, &pNew, 0); + if( rc ){ + if( rc==SQLITE_NOMEM ){ + db->mallocFailed = 1; + } + assert( pNew==0 ); + return 0; + }else{ + assert( pNew!=0 ); + } + sqlite3VdbeSwap((Vdbe*)pNew, p); + sqlite3_transfer_bindings(pNew, (sqlite3_stmt*)p); + sqlite3VdbeResetStepResult((Vdbe*)pNew); + sqlite3VdbeFinalize((Vdbe*)pNew); + return 1; +} + + +/* +** Two versions of the official API. Legacy and new use. In the legacy +** version, the original SQL text is not saved in the prepared statement +** and so if a schema change occurs, SQLITE_SCHEMA is returned by +** sqlite3_step(). In the new version, the original SQL text is retained +** and the statement is automatically recompiled if an schema change +** occurs. +*/ +int sqlite3_prepare( + sqlite3 *db, /* Database handle. */ + const char *zSql, /* UTF-8 encoded SQL statement. */ + int nBytes, /* Length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ + const char **pzTail /* OUT: End of parsed string */ +){ + int rc; + rc = sqlite3LockAndPrepare(db,zSql,nBytes,0,ppStmt,pzTail); + assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ + return rc; +} +int sqlite3_prepare_v2( + sqlite3 *db, /* Database handle. */ + const char *zSql, /* UTF-8 encoded SQL statement. */ + int nBytes, /* Length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ + const char **pzTail /* OUT: End of parsed string */ +){ + int rc; + rc = sqlite3LockAndPrepare(db,zSql,nBytes,1,ppStmt,pzTail); + assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ + return rc; +} + + +#ifndef SQLITE_OMIT_UTF16 +/* +** Compile the UTF-16 encoded SQL statement zSql into a statement handle. +*/ +static int sqlite3Prepare16( + sqlite3 *db, /* Database handle. */ + const void *zSql, /* UTF-8 encoded SQL statement. */ + int nBytes, /* Length of zSql in bytes. */ + int saveSqlFlag, /* True to save SQL text into the sqlite3_stmt */ + sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ + const void **pzTail /* OUT: End of parsed string */ +){ + /* This function currently works by first transforming the UTF-16 + ** encoded string to UTF-8, then invoking sqlite3_prepare(). The + ** tricky bit is figuring out the pointer to return in *pzTail. + */ + char *zSql8; + const char *zTail8 = 0; + int rc = SQLITE_OK; + + if( !sqlite3SafetyCheckOk(db) ){ + return SQLITE_MISUSE; + } + sqlite3_mutex_enter(db->mutex); + zSql8 = sqlite3Utf16to8(db, zSql, nBytes); + if( zSql8 ){ + rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, ppStmt, &zTail8); + } + + if( zTail8 && pzTail ){ + /* If sqlite3_prepare returns a tail pointer, we calculate the + ** equivalent pointer into the UTF-16 string by counting the unicode + ** characters between zSql8 and zTail8, and then returning a pointer + ** the same number of characters into the UTF-16 string. + */ + int chars_parsed = sqlite3Utf8CharLen(zSql8, zTail8-zSql8); + *pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, chars_parsed); + } + sqlite3DbFree(db, zSql8); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; +} + +/* +** Two versions of the official API. Legacy and new use. In the legacy +** version, the original SQL text is not saved in the prepared statement +** and so if a schema change occurs, SQLITE_SCHEMA is returned by +** sqlite3_step(). In the new version, the original SQL text is retained +** and the statement is automatically recompiled if an schema change +** occurs. +*/ +int sqlite3_prepare16( + sqlite3 *db, /* Database handle. */ + const void *zSql, /* UTF-8 encoded SQL statement. */ + int nBytes, /* Length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ + const void **pzTail /* OUT: End of parsed string */ +){ + int rc; + rc = sqlite3Prepare16(db,zSql,nBytes,0,ppStmt,pzTail); + assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ + return rc; +} +int sqlite3_prepare16_v2( + sqlite3 *db, /* Database handle. */ + const void *zSql, /* UTF-8 encoded SQL statement. */ + int nBytes, /* Length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ + const void **pzTail /* OUT: End of parsed string */ +){ + int rc; + rc = sqlite3Prepare16(db,zSql,nBytes,1,ppStmt,pzTail); + assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ + return rc; +} + +#endif /* SQLITE_OMIT_UTF16 */ diff --git a/third_party/sqlite/src/printf.c b/third_party/sqlite/src/printf.c new file mode 100755 index 0000000..b88a7d8 --- /dev/null +++ b/third_party/sqlite/src/printf.c @@ -0,0 +1,934 @@ +/* +** The "printf" code that follows dates from the 1980's. It is in +** the public domain. The original comments are included here for +** completeness. They are very out-of-date but might be useful as +** an historical reference. Most of the "enhancements" have been backed +** out so that the functionality is now the same as standard printf(). +** +** $Id: printf.c,v 1.93 2008/07/28 19:34:53 drh Exp $ +** +************************************************************************** +** +** The following modules is an enhanced replacement for the "printf" subroutines +** found in the standard C library. The following enhancements are +** supported: +** +** + Additional functions. The standard set of "printf" functions +** includes printf, fprintf, sprintf, vprintf, vfprintf, and +** vsprintf. This module adds the following: +** +** * snprintf -- Works like sprintf, but has an extra argument +** which is the size of the buffer written to. +** +** * mprintf -- Similar to sprintf. Writes output to memory +** obtained from malloc. +** +** * xprintf -- Calls a function to dispose of output. +** +** * nprintf -- No output, but returns the number of characters +** that would have been output by printf. +** +** * A v- version (ex: vsnprintf) of every function is also +** supplied. +** +** + A few extensions to the formatting notation are supported: +** +** * The "=" flag (similar to "-") causes the output to be +** be centered in the appropriately sized field. +** +** * The %b field outputs an integer in binary notation. +** +** * The %c field now accepts a precision. The character output +** is repeated by the number of times the precision specifies. +** +** * The %' field works like %c, but takes as its character the +** next character of the format string, instead of the next +** argument. For example, printf("%.78'-") prints 78 minus +** signs, the same as printf("%.78c",'-'). +** +** + When compiled using GCC on a SPARC, this version of printf is +** faster than the library printf for SUN OS 4.1. +** +** + All functions are fully reentrant. +** +*/ +#include "sqliteInt.h" + +/* +** Conversion types fall into various categories as defined by the +** following enumeration. +*/ +#define etRADIX 1 /* Integer types. %d, %x, %o, and so forth */ +#define etFLOAT 2 /* Floating point. %f */ +#define etEXP 3 /* Exponentional notation. %e and %E */ +#define etGENERIC 4 /* Floating or exponential, depending on exponent. %g */ +#define etSIZE 5 /* Return number of characters processed so far. %n */ +#define etSTRING 6 /* Strings. %s */ +#define etDYNSTRING 7 /* Dynamically allocated strings. %z */ +#define etPERCENT 8 /* Percent symbol. %% */ +#define etCHARX 9 /* Characters. %c */ +/* The rest are extensions, not normally found in printf() */ +#define etSQLESCAPE 10 /* Strings with '\'' doubled. %q */ +#define etSQLESCAPE2 11 /* Strings with '\'' doubled and enclosed in '', + NULL pointers replaced by SQL NULL. %Q */ +#define etTOKEN 12 /* a pointer to a Token structure */ +#define etSRCLIST 13 /* a pointer to a SrcList */ +#define etPOINTER 14 /* The %p conversion */ +#define etSQLESCAPE3 15 /* %w -> Strings with '\"' doubled */ +#define etORDINAL 16 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */ + + +/* +** An "etByte" is an 8-bit unsigned value. +*/ +typedef unsigned char etByte; + +/* +** Each builtin conversion character (ex: the 'd' in "%d") is described +** by an instance of the following structure +*/ +typedef struct et_info { /* Information about each format field */ + char fmttype; /* The format field code letter */ + etByte base; /* The base for radix conversion */ + etByte flags; /* One or more of FLAG_ constants below */ + etByte type; /* Conversion paradigm */ + etByte charset; /* Offset into aDigits[] of the digits string */ + etByte prefix; /* Offset into aPrefix[] of the prefix string */ +} et_info; + +/* +** Allowed values for et_info.flags +*/ +#define FLAG_SIGNED 1 /* True if the value to convert is signed */ +#define FLAG_INTERN 2 /* True if for internal use only */ +#define FLAG_STRING 4 /* Allow infinity precision */ + + +/* +** The following table is searched linearly, so it is good to put the +** most frequently used conversion types first. +*/ +static const char aDigits[] = "0123456789ABCDEF0123456789abcdef"; +static const char aPrefix[] = "-x0\000X0"; +static const et_info fmtinfo[] = { + { 'd', 10, 1, etRADIX, 0, 0 }, + { 's', 0, 4, etSTRING, 0, 0 }, + { 'g', 0, 1, etGENERIC, 30, 0 }, + { 'z', 0, 4, etDYNSTRING, 0, 0 }, + { 'q', 0, 4, etSQLESCAPE, 0, 0 }, + { 'Q', 0, 4, etSQLESCAPE2, 0, 0 }, + { 'w', 0, 4, etSQLESCAPE3, 0, 0 }, + { 'c', 0, 0, etCHARX, 0, 0 }, + { 'o', 8, 0, etRADIX, 0, 2 }, + { '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 }, + { 'p', 16, 0, etPOINTER, 0, 1 }, + { 'T', 0, 2, etTOKEN, 0, 0 }, + { 'S', 0, 2, etSRCLIST, 0, 0 }, + { 'r', 10, 3, etORDINAL, 0, 0 }, +}; +#define etNINFO (sizeof(fmtinfo)/sizeof(fmtinfo[0])) + +/* +** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point +** conversions will work. +*/ +#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 +** multiply "*val" by 10.0 to renormalize. +** +** Example: +** input: *val = 3.14159 +** output: *val = 1.4159 function return = '3' +** +** The counter *cnt is incremented each time. After counter exceeds +** 16 (the number of significant digits in a 64-bit float) '0' is +** always returned. +*/ +static int et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){ + int digit; + LONGDOUBLE_TYPE d; + if( (*cnt)++ >= 16 ) return '0'; + digit = (int)*val; + d = digit; + digit += '0'; + *val = (*val - d)*10.0; + return digit; +} +#endif /* SQLITE_OMIT_FLOATING_POINT */ + +/* +** Append N space characters to the given string buffer. +*/ +static void appendSpace(StrAccum *pAccum, int N){ + static const char zSpaces[] = " "; + while( N>=sizeof(zSpaces)-1 ){ + sqlite3StrAccumAppend(pAccum, zSpaces, sizeof(zSpaces)-1); + N -= sizeof(zSpaces)-1; + } + if( N>0 ){ + sqlite3StrAccumAppend(pAccum, zSpaces, N); + } +} + +/* +** On machines with a small stack size, you can redefine the +** SQLITE_PRINT_BUF_SIZE to be less than 350. But beware - for +** smaller values some %f conversions may go into an infinite loop. +*/ +#ifndef SQLITE_PRINT_BUF_SIZE +# define SQLITE_PRINT_BUF_SIZE 350 +#endif +#define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */ + +/* +** The root program. All variations call this core. +** +** INPUTS: +** func This is a pointer to a function taking three arguments +** 1. A pointer to anything. Same as the "arg" parameter. +** 2. A pointer to the list of characters to be output +** (Note, this list is NOT null terminated.) +** 3. An integer number of characters to be output. +** (Note: This number might be zero.) +** +** arg This is the pointer to anything which will be passed as the +** first argument to "func". Use it for whatever you like. +** +** fmt This is the format string, as in the usual print. +** +** ap This is a pointer to a list of arguments. Same as in +** vfprint. +** +** OUTPUTS: +** The return value is the total number of characters sent to +** the function "func". Returns -1 on a error. +** +** Note that the order in which automatic variables are declared below +** seems to make a big difference in determining how fast this beast +** will run. +*/ +void sqlite3VXPrintf( + StrAccum *pAccum, /* Accumulate results here */ + int useExtended, /* Allow extended %-conversions */ + const char *fmt, /* Format string */ + va_list ap /* arguments */ +){ + int c; /* Next character in the format string */ + char *bufpt; /* Pointer to the conversion buffer */ + int precision; /* Precision of the current field */ + int length; /* Length of the field */ + int idx; /* A general purpose loop counter */ + int width; /* Width of the current field */ + etByte flag_leftjustify; /* True if "-" flag is present */ + etByte flag_plussign; /* True if "+" flag is present */ + etByte flag_blanksign; /* True if " " flag is present */ + etByte flag_alternateform; /* True if "#" flag is present */ + etByte flag_altform2; /* True if "!" flag is present */ + etByte flag_zeropad; /* True if field width constant starts with zero */ + etByte flag_long; /* True if "l" flag is present */ + etByte flag_longlong; /* True if the "ll" flag is present */ + etByte done; /* Loop termination flag */ + sqlite_uint64 longvalue; /* Value for integer types */ + LONGDOUBLE_TYPE realvalue; /* Value for real types */ + const et_info *infop; /* Pointer to the appropriate info structure */ + char buf[etBUFSIZE]; /* Conversion buffer */ + char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */ + etByte errorflag = 0; /* True if an error is encountered */ + etByte xtype; /* Conversion paradigm */ + char *zExtra; /* Extra memory used for etTCLESCAPE conversions */ +#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 */ + etByte flag_rtz; /* True if trailing zeros should be removed */ + etByte flag_exp; /* True to force display of the exponent */ + int nsd; /* Number of significant digits returned */ +#endif + + length = 0; + bufpt = 0; + for(; (c=(*fmt))!=0; ++fmt){ + if( c!='%' ){ + int amt; + bufpt = (char *)fmt; + amt = 1; + while( (c=(*++fmt))!='%' && c!=0 ) amt++; + sqlite3StrAccumAppend(pAccum, bufpt, amt); + if( c==0 ) break; + } + if( (c=(*++fmt))==0 ){ + errorflag = 1; + sqlite3StrAccumAppend(pAccum, "%", 1); + break; + } + /* Find out what flags are present */ + flag_leftjustify = flag_plussign = flag_blanksign = + flag_alternateform = flag_altform2 = flag_zeropad = 0; + done = 0; + do{ + switch( c ){ + case '-': flag_leftjustify = 1; break; + case '+': flag_plussign = 1; break; + case ' ': flag_blanksign = 1; break; + case '#': flag_alternateform = 1; break; + case '!': flag_altform2 = 1; break; + case '0': flag_zeropad = 1; break; + default: done = 1; break; + } + }while( !done && (c=(*++fmt))!=0 ); + /* Get the field width */ + width = 0; + if( c=='*' ){ + width = va_arg(ap,int); + if( width<0 ){ + flag_leftjustify = 1; + width = -width; + } + c = *++fmt; + }else{ + while( c>='0' && c<='9' ){ + width = width*10 + c - '0'; + c = *++fmt; + } + } + if( width > etBUFSIZE-10 ){ + width = etBUFSIZE-10; + } + /* Get the precision */ + if( c=='.' ){ + precision = 0; + c = *++fmt; + if( c=='*' ){ + precision = va_arg(ap,int); + if( precision<0 ) precision = -precision; + c = *++fmt; + }else{ + while( c>='0' && c<='9' ){ + precision = precision*10 + c - '0'; + c = *++fmt; + } + } + }else{ + precision = -1; + } + /* Get the conversion type modifier */ + if( c=='l' ){ + flag_long = 1; + c = *++fmt; + if( c=='l' ){ + flag_longlong = 1; + c = *++fmt; + }else{ + flag_longlong = 0; + } + }else{ + flag_long = flag_longlong = 0; + } + /* Fetch the info entry for the field */ + infop = 0; + for(idx=0; idx<etNINFO; idx++){ + if( c==fmtinfo[idx].fmttype ){ + infop = &fmtinfo[idx]; + if( useExtended || (infop->flags & FLAG_INTERN)==0 ){ + xtype = infop->type; + }else{ + return; + } + break; + } + } + zExtra = 0; + if( infop==0 ){ + return; + } + + + /* Limit the precision to prevent overflowing buf[] during conversion */ + if( precision>etBUFSIZE-40 && (infop->flags & FLAG_STRING)==0 ){ + precision = etBUFSIZE-40; + } + + /* + ** At this point, variables are initialized as follows: + ** + ** flag_alternateform TRUE if a '#' is present. + ** flag_altform2 TRUE if a '!' is present. + ** flag_plussign TRUE if a '+' is present. + ** flag_leftjustify TRUE if a '-' is present or if the + ** field width was negative. + ** flag_zeropad TRUE if the width began with 0. + ** flag_long TRUE if the letter 'l' (ell) prefixed + ** the conversion character. + ** flag_longlong TRUE if the letter 'll' (ell ell) prefixed + ** the conversion character. + ** flag_blanksign TRUE if a ' ' is present. + ** width The specified field width. This is + ** always non-negative. Zero is the default. + ** precision The specified precision. The default + ** is -1. + ** xtype The class of the conversion. + ** infop Pointer to the appropriate info struct. + */ + switch( xtype ){ + case etPOINTER: + flag_longlong = sizeof(char*)==sizeof(i64); + flag_long = sizeof(char*)==sizeof(long int); + /* Fall through into the next case */ + case etORDINAL: + case etRADIX: + if( infop->flags & FLAG_SIGNED ){ + i64 v; + if( flag_longlong ) v = va_arg(ap,i64); + else if( flag_long ) v = va_arg(ap,long int); + else v = va_arg(ap,int); + if( v<0 ){ + longvalue = -v; + prefix = '-'; + }else{ + longvalue = v; + if( flag_plussign ) prefix = '+'; + else if( flag_blanksign ) prefix = ' '; + else prefix = 0; + } + }else{ + if( flag_longlong ) longvalue = va_arg(ap,u64); + else if( flag_long ) longvalue = va_arg(ap,unsigned long int); + else longvalue = va_arg(ap,unsigned int); + prefix = 0; + } + if( longvalue==0 ) flag_alternateform = 0; + if( flag_zeropad && precision<width-(prefix!=0) ){ + precision = width-(prefix!=0); + } + bufpt = &buf[etBUFSIZE-1]; + if( xtype==etORDINAL ){ + static const char zOrd[] = "thstndrd"; + int x = longvalue % 10; + if( x>=4 || (longvalue/10)%10==1 ){ + x = 0; + } + buf[etBUFSIZE-3] = zOrd[x*2]; + buf[etBUFSIZE-2] = zOrd[x*2+1]; + bufpt -= 2; + } + { + register const char *cset; /* Use registers for speed */ + register int base; + cset = &aDigits[infop->charset]; + base = infop->base; + do{ /* Convert to ascii */ + *(--bufpt) = cset[longvalue%base]; + longvalue = longvalue/base; + }while( longvalue>0 ); + } + length = &buf[etBUFSIZE-1]-bufpt; + for(idx=precision-length; idx>0; idx--){ + *(--bufpt) = '0'; /* Zero pad */ + } + if( prefix ) *(--bufpt) = prefix; /* Add sign */ + if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */ + const char *pre; + char x; + pre = &aPrefix[infop->prefix]; + for(; (x=(*pre))!=0; pre++) *(--bufpt) = x; + } + length = &buf[etBUFSIZE-1]-bufpt; + break; + case etFLOAT: + case etEXP: + case etGENERIC: + realvalue = va_arg(ap,double); +#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 ){ + realvalue = -realvalue; + prefix = '-'; + }else{ + if( flag_plussign ) prefix = '+'; + else if( flag_blanksign ) prefix = ' '; + else prefix = 0; + } + if( xtype==etGENERIC && precision>0 ) precision--; +#if 0 + /* Rounding works like BSD when the constant 0.4999 is used. Wierd! */ + for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1); +#else + /* It makes more sense to use 0.5 */ + for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1){} +#endif + if( xtype==etFLOAT ) realvalue += rounder; + /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ + exp = 0; + if( sqlite3IsNaN(realvalue) ){ + bufpt = "NaN"; + length = 3; + break; + } + if( realvalue>0.0 ){ + while( realvalue>=1e32 && exp<=350 ){ realvalue *= 1e-32; exp+=32; } + while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; } + while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; } + while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; } + while( realvalue<1.0 ){ realvalue *= 10.0; exp--; } + if( exp>350 ){ + if( prefix=='-' ){ + bufpt = "-Inf"; + }else if( prefix=='+' ){ + bufpt = "+Inf"; + }else{ + bufpt = "Inf"; + } + length = strlen(bufpt); + break; + } + } + bufpt = buf; + /* + ** If the field type is etGENERIC, then convert to either etEXP + ** or etFLOAT, as appropriate. + */ + flag_exp = xtype==etEXP; + if( xtype!=etFLOAT ){ + realvalue += rounder; + if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; } + } + if( xtype==etGENERIC ){ + flag_rtz = !flag_alternateform; + if( exp<-4 || exp>precision ){ + xtype = etEXP; + }else{ + precision = precision - exp; + xtype = etFLOAT; + } + }else{ + flag_rtz = 0; + } + if( xtype==etEXP ){ + e2 = 0; + }else{ + e2 = exp; + } + nsd = 0; + flag_dp = (precision>0) | flag_alternateform | flag_altform2; + /* The sign in front of the number */ + if( prefix ){ + *(bufpt++) = prefix; + } + /* Digits prior to the decimal point */ + if( e2<0 ){ + *(bufpt++) = '0'; + }else{ + for(; e2>=0; e2--){ + *(bufpt++) = et_getdigit(&realvalue,&nsd); + } + } + /* The decimal point */ + if( flag_dp ){ + *(bufpt++) = '.'; + } + /* "0" digits after the decimal point but before the first + ** significant digit of the number */ + for(e2++; e2<0; precision--, e2++){ + assert( precision>0 ); + *(bufpt++) = '0'; + } + /* Significant digits after the decimal point */ + while( (precision--)>0 ){ + *(bufpt++) = et_getdigit(&realvalue,&nsd); + } + /* Remove trailing zeros and the "." if no digits follow the "." */ + if( flag_rtz && flag_dp ){ + while( bufpt[-1]=='0' ) *(--bufpt) = 0; + assert( bufpt>buf ); + if( bufpt[-1]=='.' ){ + if( flag_altform2 ){ + *(bufpt++) = '0'; + }else{ + *(--bufpt) = 0; + } + } + } + /* Add the "eNNN" suffix */ + if( flag_exp || xtype==etEXP ){ + *(bufpt++) = aDigits[infop->charset]; + if( exp<0 ){ + *(bufpt++) = '-'; exp = -exp; + }else{ + *(bufpt++) = '+'; + } + if( exp>=100 ){ + *(bufpt++) = (exp/100)+'0'; /* 100's digit */ + exp %= 100; + } + *(bufpt++) = exp/10+'0'; /* 10's digit */ + *(bufpt++) = exp%10+'0'; /* 1's digit */ + } + *bufpt = 0; + + /* The converted number is in buf[] and zero terminated. Output it. + ** Note that the number is in the usual order, not reversed as with + ** integer conversions. */ + length = bufpt-buf; + bufpt = buf; + + /* Special case: Add leading zeros if the flag_zeropad flag is + ** set and we are not left justified */ + if( flag_zeropad && !flag_leftjustify && length < width){ + int i; + int nPad = width - length; + for(i=width; i>=nPad; i--){ + bufpt[i] = bufpt[i-nPad]; + } + i = prefix!=0; + while( nPad-- ) bufpt[i++] = '0'; + length = width; + } +#endif + break; + case etSIZE: + *(va_arg(ap,int*)) = pAccum->nChar; + length = width = 0; + break; + case etPERCENT: + buf[0] = '%'; + bufpt = buf; + length = 1; + break; + case etCHARX: + c = buf[0] = va_arg(ap,int); + if( precision>=0 ){ + for(idx=1; idx<precision; idx++) buf[idx] = c; + length = precision; + }else{ + length =1; + } + bufpt = buf; + break; + case etSTRING: + case etDYNSTRING: + bufpt = va_arg(ap,char*); + if( bufpt==0 ){ + bufpt = ""; + }else if( xtype==etDYNSTRING ){ + zExtra = bufpt; + } + if( precision>=0 ){ + for(length=0; length<precision && bufpt[length]; length++){} + }else{ + length = strlen(bufpt); + } + break; + case etSQLESCAPE: + case etSQLESCAPE2: + case etSQLESCAPE3: { + int i, j, n, ch, isnull; + int needQuote; + char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */ + 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==q ) n++; + } + needQuote = !isnull && xtype==etSQLESCAPE2; + n += i + 1 + needQuote*2; + if( n>etBUFSIZE ){ + bufpt = zExtra = sqlite3Malloc( n ); + if( bufpt==0 ) return; + }else{ + bufpt = buf; + } + j = 0; + if( needQuote ) bufpt[j++] = q; + for(i=0; (ch=escarg[i])!=0; i++){ + bufpt[j++] = ch; + if( ch==q ) bufpt[j++] = ch; + } + if( needQuote ) bufpt[j++] = q; + bufpt[j] = 0; + length = j; + /* The precision is ignored on %q and %Q */ + /* if( precision>=0 && precision<length ) length = precision; */ + break; + } + case etTOKEN: { + Token *pToken = va_arg(ap, Token*); + if( pToken ){ + sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n); + } + length = width = 0; + break; + } + case etSRCLIST: { + SrcList *pSrc = va_arg(ap, SrcList*); + int k = va_arg(ap, int); + struct SrcList_item *pItem = &pSrc->a[k]; + assert( k>=0 && k<pSrc->nSrc ); + if( pItem->zDatabase ){ + sqlite3StrAccumAppend(pAccum, pItem->zDatabase, -1); + sqlite3StrAccumAppend(pAccum, ".", 1); + } + sqlite3StrAccumAppend(pAccum, pItem->zName, -1); + length = width = 0; + break; + } + }/* End switch over the format type */ + /* + ** The text of the conversion is pointed to by "bufpt" and is + ** "length" characters long. The field width is "width". Do + ** the output. + */ + if( !flag_leftjustify ){ + register int nspace; + nspace = width-length; + if( nspace>0 ){ + appendSpace(pAccum, nspace); + } + } + if( length>0 ){ + sqlite3StrAccumAppend(pAccum, bufpt, length); + } + if( flag_leftjustify ){ + register int nspace; + nspace = width-length; + if( nspace>0 ){ + appendSpace(pAccum, nspace); + } + } + if( zExtra ){ + sqlite3_free(zExtra); + } + }/* End for loop over the format string */ +} /* End of function */ + +/* +** Append N bytes of text from z to the StrAccum object. +*/ +void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){ + if( p->tooBig | p->mallocFailed ){ + return; + } + if( N<0 ){ + N = strlen(z); + } + if( N==0 ){ + return; + } + if( p->nChar+N >= p->nAlloc ){ + char *zNew; + if( !p->useMalloc ){ + p->tooBig = 1; + N = p->nAlloc - p->nChar - 1; + if( N<=0 ){ + return; + } + }else{ + i64 szNew = p->nChar; + szNew += N + 1; + if( szNew > p->mxAlloc ){ + sqlite3StrAccumReset(p); + p->tooBig = 1; + return; + }else{ + p->nAlloc = szNew; + } + zNew = sqlite3DbMallocRaw(p->db, p->nAlloc ); + if( zNew ){ + memcpy(zNew, p->zText, p->nChar); + sqlite3StrAccumReset(p); + p->zText = zNew; + }else{ + p->mallocFailed = 1; + sqlite3StrAccumReset(p); + return; + } + } + } + memcpy(&p->zText[p->nChar], z, N); + p->nChar += N; +} + +/* +** Finish off a string by making sure it is zero-terminated. +** Return a pointer to the resulting string. Return a NULL +** pointer if any kind of error was encountered. +*/ +char *sqlite3StrAccumFinish(StrAccum *p){ + if( p->zText ){ + p->zText[p->nChar] = 0; + if( p->useMalloc && p->zText==p->zBase ){ + p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); + if( p->zText ){ + memcpy(p->zText, p->zBase, p->nChar+1); + }else{ + p->mallocFailed = 1; + } + } + } + return p->zText; +} + +/* +** Reset an StrAccum string. Reclaim all malloced memory. +*/ +void sqlite3StrAccumReset(StrAccum *p){ + if( p->zText!=p->zBase ){ + sqlite3DbFree(p->db, p->zText); + } + p->zText = 0; +} + +/* +** Initialize a string accumulator +*/ +void sqlite3StrAccumInit(StrAccum *p, char *zBase, int n, int mx){ + p->zText = p->zBase = zBase; + p->db = 0; + p->nChar = 0; + p->nAlloc = n; + p->mxAlloc = mx; + p->useMalloc = 1; + p->tooBig = 0; + p->mallocFailed = 0; +} + +/* +** Print into memory obtained from sqliteMalloc(). Use the internal +** %-conversion extensions. +*/ +char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){ + char *z; + char zBase[SQLITE_PRINT_BUF_SIZE]; + StrAccum acc; + sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), + db ? db->aLimit[SQLITE_LIMIT_LENGTH] : SQLITE_MAX_LENGTH); + acc.db = db; + sqlite3VXPrintf(&acc, 1, zFormat, ap); + z = sqlite3StrAccumFinish(&acc); + if( acc.mallocFailed && db ){ + db->mallocFailed = 1; + } + return z; +} + +/* +** Print into memory obtained from sqliteMalloc(). Use the internal +** %-conversion extensions. +*/ +char *sqlite3MPrintf(sqlite3 *db, const char *zFormat, ...){ + va_list ap; + char *z; + va_start(ap, zFormat); + z = sqlite3VMPrintf(db, zFormat, ap); + va_end(ap); + return z; +} + +/* +** Like sqlite3MPrintf(), but call sqlite3DbFree() on zStr after formatting +** the string and before returnning. This routine is intended to be used +** to modify an existing string. For example: +** +** x = sqlite3MPrintf(db, x, "prefix %s suffix", x); +** +*/ +char *sqlite3MAppendf(sqlite3 *db, char *zStr, const char *zFormat, ...){ + va_list ap; + char *z; + va_start(ap, zFormat); + z = sqlite3VMPrintf(db, zFormat, ap); + va_end(ap); + sqlite3DbFree(db, zStr); + return z; +} + +/* +** Print into memory obtained from sqlite3_malloc(). Omit the internal +** %-conversion extensions. +*/ +char *sqlite3_vmprintf(const char *zFormat, va_list ap){ + char *z; + char zBase[SQLITE_PRINT_BUF_SIZE]; + StrAccum acc; +#ifndef SQLITE_OMIT_AUTOINIT + if( sqlite3_initialize() ) return 0; +#endif + sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), SQLITE_MAX_LENGTH); + sqlite3VXPrintf(&acc, 0, zFormat, ap); + z = sqlite3StrAccumFinish(&acc); + return z; +} + +/* +** Print into memory obtained from sqlite3_malloc()(). Omit the internal +** %-conversion extensions. +*/ +char *sqlite3_mprintf(const char *zFormat, ...){ + va_list ap; + char *z; +#ifndef SQLITE_OMIT_AUTOINIT + if( sqlite3_initialize() ) return 0; +#endif + va_start(ap, zFormat); + z = sqlite3_vmprintf(zFormat, ap); + va_end(ap); + return z; +} + +/* +** sqlite3_snprintf() works like snprintf() except that it ignores the +** current locale settings. This is important for SQLite because we +** are not able to use a "," as the decimal point in place of "." as +** specified by some locales. +*/ +char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ + char *z; + va_list ap; + StrAccum acc; + + if( n<=0 ){ + return zBuf; + } + sqlite3StrAccumInit(&acc, zBuf, n, 0); + acc.useMalloc = 0; + va_start(ap,zFormat); + sqlite3VXPrintf(&acc, 0, zFormat, ap); + va_end(ap); + z = sqlite3StrAccumFinish(&acc); + return z; +} + +#if defined(SQLITE_DEBUG) +/* +** A version of printf() that understands %lld. Used for debugging. +** The printf() built into some versions of windows does not understand %lld +** and segfaults if you give it a long long int. +*/ +void sqlite3DebugPrintf(const char *zFormat, ...){ + va_list ap; + StrAccum acc; + char zBuf[500]; + sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf), 0); + acc.useMalloc = 0; + va_start(ap,zFormat); + sqlite3VXPrintf(&acc, 0, zFormat, ap); + va_end(ap); + sqlite3StrAccumFinish(&acc); + fprintf(stdout,"%s", zBuf); + fflush(stdout); +} +#endif diff --git a/third_party/sqlite/src/random.c b/third_party/sqlite/src/random.c new file mode 100755 index 0000000..f328232 --- /dev/null +++ b/third_party/sqlite/src/random.c @@ -0,0 +1,122 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains code to implement a pseudo-random number +** generator (PRNG) for SQLite. +** +** 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.25 2008/06/19 01:03:18 drh Exp $ +*/ +#include "sqliteInt.h" + + +/* All threads share a single random number generator. +** This structure is the current state of the generator. +*/ +static struct sqlite3PrngType { + unsigned char isInit; /* True if initialized */ + unsigned char i, j; /* State variables */ + unsigned char s[256]; /* State variables */ +} sqlite3Prng; + +/* +** Get a single 8-bit random value from the RC4 PRNG. The Mutex +** must be held while executing this routine. +** +** Why not just use a library random generator like lrand48() for this? +** Because the OP_NewRowid opcode in the VDBE depends on having a very +** good source of random numbers. The lrand48() library function may +** well be good enough. But maybe not. Or maybe lrand48() has some +** subtle problems on some systems that could cause problems. It is hard +** to know. To minimize the risk of problems due to bad lrand48() +** implementations, SQLite uses this random number generator based +** on RC4, which we know works very well. +** +** (Later): Actually, OP_NewRowid does not depend on a good source of +** randomness any more. But we will leave this code in all the same. +*/ +static int randomByte(void){ + unsigned char t; + + + /* Initialize the state of the random number generator once, + ** the first time this routine is called. The seed value does + ** not need to contain a lot of randomness since we are not + ** trying to do secure encryption or anything like that... + ** + ** Nothing in this file or anywhere else in SQLite does any kind of + ** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random + ** number generator) not as an encryption device. + */ + if( !sqlite3Prng.isInit ){ + int i; + char k[256]; + sqlite3Prng.j = 0; + sqlite3Prng.i = 0; + sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k); + for(i=0; i<256; i++){ + sqlite3Prng.s[i] = i; + } + for(i=0; i<256; i++){ + sqlite3Prng.j += sqlite3Prng.s[i] + k[i]; + t = sqlite3Prng.s[sqlite3Prng.j]; + sqlite3Prng.s[sqlite3Prng.j] = sqlite3Prng.s[i]; + sqlite3Prng.s[i] = t; + } + sqlite3Prng.isInit = 1; + } + + /* Generate and return single random byte + */ + sqlite3Prng.i++; + t = sqlite3Prng.s[sqlite3Prng.i]; + sqlite3Prng.j += t; + sqlite3Prng.s[sqlite3Prng.i] = sqlite3Prng.s[sqlite3Prng.j]; + sqlite3Prng.s[sqlite3Prng.j] = t; + t += sqlite3Prng.s[sqlite3Prng.i]; + return sqlite3Prng.s[t]; +} + +/* +** Return N random bytes. +*/ +void sqlite3_randomness(int N, void *pBuf){ + unsigned char *zBuf = pBuf; +#ifndef SQLITE_MUTEX_NOOP + sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG); +#endif + sqlite3_mutex_enter(mutex); + while( N-- ){ + *(zBuf++) = randomByte(); + } + sqlite3_mutex_leave(mutex); +} + +#ifndef SQLITE_OMIT_BUILTIN_TEST +/* +** For testing purposes, we sometimes want to preserve the state of +** PRNG and restore the PRNG to its saved state at a later time. +** The sqlite3_test_control() interface calls these routines to +** control the PRNG. +*/ +static struct sqlite3PrngType sqlite3SavedPrng; +void sqlite3PrngSaveState(void){ + memcpy(&sqlite3SavedPrng, &sqlite3Prng, sizeof(sqlite3Prng)); +} +void sqlite3PrngRestoreState(void){ + memcpy(&sqlite3Prng, &sqlite3SavedPrng, sizeof(sqlite3Prng)); +} +void sqlite3PrngResetState(void){ + sqlite3Prng.isInit = 0; +} +#endif /* SQLITE_OMIT_BUILTIN_TEST */ diff --git a/third_party/sqlite/src/select.c b/third_party/sqlite/src/select.c new file mode 100755 index 0000000..5a8ddf0 --- /dev/null +++ b/third_party/sqlite/src/select.c @@ -0,0 +1,4292 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains C code routines that are called by the parser +** to handle SELECT statements in SQLite. +** +** $Id: select.c,v 1.463 2008/08/04 03:51:24 danielk1977 Exp $ +*/ +#include "sqliteInt.h" + + +/* +** Delete all the content of a Select structure but do not deallocate +** the select structure itself. +*/ +static void clearSelect(sqlite3 *db, Select *p){ + sqlite3ExprListDelete(db, p->pEList); + sqlite3SrcListDelete(db, p->pSrc); + sqlite3ExprDelete(db, p->pWhere); + sqlite3ExprListDelete(db, p->pGroupBy); + sqlite3ExprDelete(db, p->pHaving); + sqlite3ExprListDelete(db, p->pOrderBy); + sqlite3SelectDelete(db, p->pPrior); + sqlite3ExprDelete(db, p->pLimit); + sqlite3ExprDelete(db, p->pOffset); +} + +/* +** Initialize a SelectDest structure. +*/ +void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){ + pDest->eDest = eDest; + pDest->iParm = iParm; + pDest->affinity = 0; + pDest->iMem = 0; + pDest->nMem = 0; +} + + +/* +** Allocate a new Select structure and return a pointer to that +** structure. +*/ +Select *sqlite3SelectNew( + Parse *pParse, /* Parsing context */ + ExprList *pEList, /* which columns to include in the result */ + SrcList *pSrc, /* the FROM clause -- which tables to scan */ + Expr *pWhere, /* the WHERE clause */ + ExprList *pGroupBy, /* the GROUP BY clause */ + Expr *pHaving, /* the HAVING clause */ + ExprList *pOrderBy, /* the ORDER BY clause */ + int isDistinct, /* true if the DISTINCT keyword is present */ + Expr *pLimit, /* LIMIT value. NULL means not used */ + Expr *pOffset /* OFFSET value. NULL means no offset */ +){ + Select *pNew; + Select standin; + sqlite3 *db = pParse->db; + pNew = sqlite3DbMallocZero(db, sizeof(*pNew) ); + assert( !pOffset || pLimit ); /* Can't have OFFSET without LIMIT. */ + if( pNew==0 ){ + pNew = &standin; + memset(pNew, 0, sizeof(*pNew)); + } + if( pEList==0 ){ + pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,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; + assert( pOffset==0 || pLimit!=0 ); + pNew->pLimit = pLimit; + pNew->pOffset = pOffset; + pNew->addrOpenEphm[0] = -1; + pNew->addrOpenEphm[1] = -1; + pNew->addrOpenEphm[2] = -1; + if( pNew==&standin) { + clearSelect(db, pNew); + pNew = 0; + } + return pNew; +} + +/* +** Delete the given Select structure and all of its substructures. +*/ +void sqlite3SelectDelete(sqlite3 *db, Select *p){ + if( p ){ + clearSelect(db, p); + sqlite3DbFree(db, p); + } +} + +/* +** Given 1 to 3 identifiers preceeding the JOIN keyword, determine the +** type of join. Return an integer constant that expresses that type +** in terms of the following bit values: +** +** JT_INNER +** JT_CROSS +** JT_OUTER +** JT_NATURAL +** JT_LEFT +** JT_RIGHT +** +** A full outer join is the combination of JT_LEFT and JT_RIGHT. +** +** If an illegal or unsupported join type is seen, then still return +** a join type, but put an error in the pParse structure. +*/ +int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){ + int jointype = 0; + Token *apAll[3]; + Token *p; + static const struct { + const char zKeyword[8]; + u8 nChar; + u8 code; + } keywords[] = { + { "natural", 7, JT_NATURAL }, + { "left", 4, JT_LEFT|JT_OUTER }, + { "right", 5, JT_RIGHT|JT_OUTER }, + { "full", 4, JT_LEFT|JT_RIGHT|JT_OUTER }, + { "outer", 5, JT_OUTER }, + { "inner", 5, JT_INNER }, + { "cross", 5, JT_INNER|JT_CROSS }, + }; + int i, j; + apAll[0] = pA; + apAll[1] = pB; + apAll[2] = pC; + for(i=0; i<3 && apAll[i]; i++){ + p = apAll[i]; + for(j=0; j<sizeof(keywords)/sizeof(keywords[0]); j++){ + if( p->n==keywords[j].nChar + && sqlite3StrNICmp((char*)p->z, keywords[j].zKeyword, p->n)==0 ){ + jointype |= keywords[j].code; + break; + } + } + if( j>=sizeof(keywords)/sizeof(keywords[0]) ){ + jointype |= JT_ERROR; + break; + } + } + if( + (jointype & (JT_INNER|JT_OUTER))==(JT_INNER|JT_OUTER) || + (jointype & JT_ERROR)!=0 + ){ + const char *zSp = " "; + assert( pB!=0 ); + if( pC==0 ){ zSp++; } + sqlite3ErrorMsg(pParse, "unknown or unsupported join type: " + "%T %T%s%T", pA, pB, zSp, pC); + jointype = JT_INNER; + }else if( jointype & JT_RIGHT ){ + sqlite3ErrorMsg(pParse, + "RIGHT and FULL OUTER JOINs are not currently supported"); + jointype = JT_INNER; + } + return jointype; +} + +/* +** Return the index of a column in a table. Return -1 if the column +** is not contained in the table. +*/ +static int columnIndex(Table *pTab, const char *zCol){ + int i; + for(i=0; i<pTab->nCol; i++){ + if( sqlite3StrICmp(pTab->aCol[i].zName, zCol)==0 ) return i; + } + return -1; +} + +/* +** Set the value of a token to a '\000'-terminated string. +*/ +static void setToken(Token *p, const char *z){ + p->z = (u8*)z; + p->n = z ? strlen(z) : 0; + p->dyn = 0; +} + +/* +** Set the token to the double-quoted and escaped version of the string pointed +** to by z. For example; +** +** {a"bc} -> {"a""bc"} +*/ +static void setQuotedToken(Parse *pParse, Token *p, const char *z){ + + /* Check if the string contains any " characters. If it does, then + ** this function will malloc space to create a quoted version of + ** the string in. Otherwise, save a call to sqlite3MPrintf() by + ** just copying the pointer to the string. + */ + const char *z2 = z; + while( *z2 ){ + if( *z2=='"' ) break; + z2++; + } + + if( *z2 ){ + /* String contains " characters - copy and quote the string. */ + p->z = (u8 *)sqlite3MPrintf(pParse->db, "\"%w\"", z); + if( p->z ){ + p->n = strlen((char *)p->z); + p->dyn = 1; + } + }else{ + /* String contains no " characters - copy the pointer. */ + p->z = (u8*)z; + p->n = (z2 - z); + p->dyn = 0; + } +} + +/* +** Create an expression node for an identifier with the name of zName +*/ +Expr *sqlite3CreateIdExpr(Parse *pParse, const char *zName){ + Token dummy; + setToken(&dummy, zName); + return sqlite3PExpr(pParse, TK_ID, 0, 0, &dummy); +} + +/* +** Add a term to the WHERE expression in *ppExpr that requires the +** zCol column to be equal in the two tables pTab1 and pTab2. +*/ +static void addWhereTerm( + Parse *pParse, /* Parsing context */ + const char *zCol, /* Name of the column */ + const Table *pTab1, /* First table */ + const char *zAlias1, /* Alias for first table. May be NULL */ + const Table *pTab2, /* Second table */ + const char *zAlias2, /* Alias for second table. May be NULL */ + int iRightJoinTable, /* VDBE cursor for the right table */ + Expr **ppExpr, /* Add the equality term to this expression */ + int isOuterJoin /* True if dealing with an OUTER join */ +){ + Expr *pE1a, *pE1b, *pE1c; + Expr *pE2a, *pE2b, *pE2c; + Expr *pE; + + pE1a = sqlite3CreateIdExpr(pParse, zCol); + pE2a = sqlite3CreateIdExpr(pParse, zCol); + if( zAlias1==0 ){ + zAlias1 = pTab1->zName; + } + pE1b = sqlite3CreateIdExpr(pParse, zAlias1); + if( zAlias2==0 ){ + zAlias2 = pTab2->zName; + } + pE2b = sqlite3CreateIdExpr(pParse, zAlias2); + pE1c = sqlite3PExpr(pParse, TK_DOT, pE1b, pE1a, 0); + pE2c = sqlite3PExpr(pParse, TK_DOT, pE2b, pE2a, 0); + pE = sqlite3PExpr(pParse, TK_EQ, pE1c, pE2c, 0); + if( pE && isOuterJoin ){ + ExprSetProperty(pE, EP_FromJoin); + pE->iRightJoinTable = iRightJoinTable; + } + *ppExpr = sqlite3ExprAnd(pParse->db,*ppExpr, pE); +} + +/* +** Set the EP_FromJoin property on all terms of the given expression. +** And set the Expr.iRightJoinTable to iTable for every term in the +** expression. +** +** The EP_FromJoin property is used on terms of an expression to tell +** the LEFT OUTER JOIN processing logic that this term is part of the +** join restriction specified in the ON or USING clause and not a part +** of the more general WHERE clause. These terms are moved over to the +** WHERE clause during join processing but we need to remember that they +** originated in the ON or USING clause. +** +** The Expr.iRightJoinTable tells the WHERE clause processing that the +** expression depends on table iRightJoinTable even if that table is not +** explicitly mentioned in the expression. That information is needed +** for cases like this: +** +** SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.b AND t1.x=5 +** +** The where clause needs to defer the handling of the t1.x=5 +** term until after the t2 loop of the join. In that way, a +** NULL t2 row will be inserted whenever t1.x!=5. If we do not +** defer the handling of t1.x=5, it will be processed immediately +** after the t1 loop and rows with t1.x!=5 will never appear in +** the output, which is incorrect. +*/ +static void setJoinExpr(Expr *p, int iTable){ + while( p ){ + ExprSetProperty(p, EP_FromJoin); + p->iRightJoinTable = iTable; + setJoinExpr(p->pLeft, iTable); + p = p->pRight; + } +} + +/* +** This routine processes the join information for a SELECT statement. +** ON and USING clauses are converted into extra terms of the WHERE clause. +** NATURAL joins also create extra WHERE clause terms. +** +** The terms of a FROM clause are contained in the Select.pSrc structure. +** The left most table is the first entry in Select.pSrc. The right-most +** table is the last entry. The join operator is held in the entry to +** the left. Thus entry 0 contains the join operator for the join between +** entries 0 and 1. Any ON or USING clauses associated with the join are +** also attached to the left entry. +** +** This routine returns the number of errors encountered. +*/ +static int sqliteProcessJoin(Parse *pParse, Select *p){ + SrcList *pSrc; /* All tables in the FROM clause */ + int i, j; /* Loop counters */ + struct SrcList_item *pLeft; /* Left table being joined */ + struct SrcList_item *pRight; /* Right table being joined */ + + pSrc = p->pSrc; + pLeft = &pSrc->a[0]; + pRight = &pLeft[1]; + for(i=0; i<pSrc->nSrc-1; i++, pRight++, pLeft++){ + Table *pLeftTab = pLeft->pTab; + Table *pRightTab = pRight->pTab; + int isOuter; + + if( pLeftTab==0 || pRightTab==0 ) continue; + isOuter = (pRight->jointype & JT_OUTER)!=0; + + /* When the NATURAL keyword is present, add WHERE clause terms for + ** every column that the two tables have in common. + */ + if( pRight->jointype & JT_NATURAL ){ + if( pRight->pOn || pRight->pUsing ){ + sqlite3ErrorMsg(pParse, "a NATURAL join may not have " + "an ON or USING clause", 0); + return 1; + } + for(j=0; j<pLeftTab->nCol; j++){ + char *zName = pLeftTab->aCol[j].zName; + if( columnIndex(pRightTab, zName)>=0 ){ + addWhereTerm(pParse, zName, pLeftTab, pLeft->zAlias, + pRightTab, pRight->zAlias, + pRight->iCursor, &p->pWhere, isOuter); + + } + } + } + + /* Disallow both ON and USING clauses in the same join + */ + if( pRight->pOn && pRight->pUsing ){ + sqlite3ErrorMsg(pParse, "cannot have both ON and USING " + "clauses in the same join"); + return 1; + } + + /* Add the ON clause to the end of the WHERE clause, connected by + ** an AND operator. + */ + if( pRight->pOn ){ + if( isOuter ) setJoinExpr(pRight->pOn, pRight->iCursor); + p->pWhere = sqlite3ExprAnd(pParse->db, p->pWhere, pRight->pOn); + pRight->pOn = 0; + } + + /* Create extra terms on the WHERE clause for each column named + ** in the USING clause. Example: If the two tables to be joined are + ** A and B and the USING clause names X, Y, and Z, then add this + ** to the WHERE clause: A.X=B.X AND A.Y=B.Y AND A.Z=B.Z + ** Report an error if any column mentioned in the USING clause is + ** not contained in both tables to be joined. + */ + if( pRight->pUsing ){ + IdList *pList = pRight->pUsing; + for(j=0; j<pList->nId; j++){ + char *zName = pList->a[j].zName; + if( columnIndex(pLeftTab, zName)<0 || columnIndex(pRightTab, zName)<0 ){ + sqlite3ErrorMsg(pParse, "cannot join using column %s - column " + "not present in both tables", zName); + return 1; + } + addWhereTerm(pParse, zName, pLeftTab, pLeft->zAlias, + pRightTab, pRight->zAlias, + pRight->iCursor, &p->pWhere, isOuter); + } + } + } + return 0; +} + +/* +** Insert code into "v" that will push the record on the top of the +** stack into the sorter. +*/ +static void pushOntoSorter( + Parse *pParse, /* Parser context */ + ExprList *pOrderBy, /* The ORDER BY clause */ + Select *pSelect, /* The whole SELECT statement */ + int regData /* Register holding data to be sorted */ +){ + Vdbe *v = pParse->pVdbe; + int nExpr = pOrderBy->nExpr; + int regBase = sqlite3GetTempRange(pParse, nExpr+2); + int regRecord = sqlite3GetTempReg(pParse); + sqlite3ExprCodeExprList(pParse, pOrderBy, regBase, 0); + sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr); + sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1, 1); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord); + sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy->iECursor, regRecord); + sqlite3ReleaseTempReg(pParse, regRecord); + sqlite3ReleaseTempRange(pParse, regBase, nExpr+2); + if( pSelect->iLimit ){ + int addr1, addr2; + int iLimit; + if( pSelect->iOffset ){ + iLimit = pSelect->iOffset+1; + }else{ + iLimit = pSelect->iLimit; + } + addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit); + sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1); + addr2 = sqlite3VdbeAddOp0(v, OP_Goto); + sqlite3VdbeJumpHere(v, addr1); + sqlite3VdbeAddOp1(v, OP_Last, pOrderBy->iECursor); + sqlite3VdbeAddOp1(v, OP_Delete, pOrderBy->iECursor); + sqlite3VdbeJumpHere(v, addr2); + pSelect->iLimit = 0; + } +} + +/* +** Add code to implement the OFFSET +*/ +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 */ +){ + if( p->iOffset && iContinue!=0 ){ + int addr; + sqlite3VdbeAddOp2(v, OP_AddImm, p->iOffset, -1); + addr = sqlite3VdbeAddOp1(v, OP_IfNeg, p->iOffset); + sqlite3VdbeAddOp2(v, OP_Goto, 0, iContinue); + VdbeComment((v, "skip OFFSET records")); + sqlite3VdbeJumpHere(v, addr); + } +} + +/* +** Add code that will check to make sure the N registers starting at iMem +** form a distinct entry. iTab is a sorting index that holds previously +** seen combinations of the N values. A new entry is made in iTab +** if the current N values are new. +** +** A jump to addrRepeat is made and the N+1 values are popped from the +** stack if the top N elements are not distinct. +*/ +static void codeDistinct( + Parse *pParse, /* Parsing and code generating context */ + int iTab, /* A sorting index used to test for distinctness */ + int addrRepeat, /* Jump to here if not distinct */ + int N, /* Number of elements */ + int iMem /* First element */ +){ + Vdbe *v; + int r1; + + v = pParse->pVdbe; + r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1); + sqlite3VdbeAddOp3(v, OP_Found, iTab, addrRepeat, r1); + sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, r1); + sqlite3ReleaseTempReg(pParse, r1); +} + +/* +** Generate an error message when a SELECT is used within a subexpression +** (example: "a IN (SELECT * FROM table)") but it has more than 1 result +** column. We do this in a subroutine because the error occurs in multiple +** places. +*/ +static int checkForMultiColumnSelectError( + Parse *pParse, /* Parse context. */ + SelectDest *pDest, /* Destination of SELECT results */ + int nExpr /* Number of result columns returned by SELECT */ +){ + int eDest = pDest->eDest; + if( nExpr>1 && (eDest==SRT_Mem || eDest==SRT_Set) ){ + sqlite3ErrorMsg(pParse, "only a single result allowed for " + "a SELECT that is part of an expression"); + return 1; + }else{ + return 0; + } +} + +/* +** This routine generates the code for the inside of the inner loop +** of a SELECT. +** +** If srcTab and nColumn are both zero, then the pEList expressions +** are evaluated in order to get the data for this row. If nColumn>0 +** then data is pulled from srcTab and pEList is used only to get the +** datatypes for each column. +*/ +static void selectInnerLoop( + Parse *pParse, /* The parser context */ + Select *p, /* The complete select statement being coded */ + ExprList *pEList, /* List of values being extracted */ + int srcTab, /* Pull data from this table */ + int nColumn, /* Number of columns in the source table */ + ExprList *pOrderBy, /* If not NULL, sort results using this key */ + int distinct, /* If >=0, make sure results are distinct */ + SelectDest *pDest, /* How to dispose of the results */ + int iContinue, /* Jump here to continue with next row */ + int iBreak /* Jump here to break out of the inner loop */ +){ + Vdbe *v = pParse->pVdbe; + int i; + int hasDistinct; /* True if the DISTINCT keyword is present */ + int regResult; /* Start of memory holding result set */ + int eDest = pDest->eDest; /* How to dispose of results */ + int iParm = pDest->iParm; /* First argument to disposal method */ + int nResultCol; /* Number of result columns */ + + if( v==0 ) return; + assert( pEList!=0 ); + hasDistinct = distinct>=0; + if( pOrderBy==0 && !hasDistinct ){ + codeOffset(v, p, iContinue); + } + + /* Pull the requested columns. + */ + if( nColumn>0 ){ + nResultCol = nColumn; + }else{ + nResultCol = pEList->nExpr; + } + if( pDest->iMem==0 ){ + pDest->iMem = pParse->nMem+1; + pDest->nMem = nResultCol; + pParse->nMem += nResultCol; + }else if( pDest->nMem!=nResultCol ){ + /* This happens when two SELECTs of a compound SELECT have differing + ** numbers of result columns. The error message will be generated by + ** a higher-level routine. */ + return; + } + regResult = pDest->iMem; + if( nColumn>0 ){ + for(i=0; i<nColumn; i++){ + sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i); + } + }else if( eDest!=SRT_Exists ){ + /* If the destination is an EXISTS(...) expression, the actual + ** values returned by the SELECT are not required. + */ + sqlite3ExprCodeExprList(pParse, pEList, regResult, eDest==SRT_Callback); + } + nColumn = nResultCol; + + /* If the DISTINCT keyword was present on the SELECT statement + ** and this row has been seen before, then do not make this row + ** part of the result. + */ + if( hasDistinct ){ + assert( pEList!=0 ); + assert( pEList->nExpr==nColumn ); + codeDistinct(pParse, distinct, iContinue, nColumn, regResult); + if( pOrderBy==0 ){ + codeOffset(v, p, iContinue); + } + } + + if( checkForMultiColumnSelectError(pParse, pDest, pEList->nExpr) ){ + return; + } + + switch( eDest ){ + /* In this mode, write each query result to the key of the temporary + ** table iParm. + */ +#ifndef SQLITE_OMIT_COMPOUND_SELECT + case SRT_Union: { + int r1; + r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); + sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1); + sqlite3ReleaseTempReg(pParse, r1); + break; + } + + /* Construct a record from the query result, but instead of + ** saving that record, use it as a key to delete elements from + ** the temporary table iParm. + */ + case SRT_Except: { + sqlite3VdbeAddOp3(v, OP_IdxDelete, iParm, regResult, nColumn); + break; + } +#endif + + /* Store the result as data using a unique key. + */ + case SRT_Table: + case SRT_EphemTab: { + int r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); + if( pOrderBy ){ + pushOntoSorter(pParse, pOrderBy, p, r1); + }else{ + int r2 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2); + sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, r2); + sqlite3VdbeChangeP5(v, OPFLAG_APPEND); + sqlite3ReleaseTempReg(pParse, r2); + } + sqlite3ReleaseTempReg(pParse, r1); + break; + } + +#ifndef SQLITE_OMIT_SUBQUERY + /* If we are creating a set for an "expr IN (SELECT ...)" construct, + ** then there should be a single item on the stack. Write this + ** item into the set table with bogus data. + */ + case SRT_Set: { + assert( nColumn==1 ); + p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affinity); + if( pOrderBy ){ + /* At first glance you would think we could optimize out the + ** 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, pOrderBy, p, regResult); + }else{ + int r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, 1, r1, &p->affinity, 1); + sqlite3ExprCacheAffinityChange(pParse, regResult, 1); + sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1); + sqlite3ReleaseTempReg(pParse, r1); + } + break; + } + + /* If any row exist in the result set, record that fact and abort. + */ + case SRT_Exists: { + sqlite3VdbeAddOp2(v, OP_Integer, 1, iParm); + /* 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_Mem: { + assert( nColumn==1 ); + if( pOrderBy ){ + pushOntoSorter(pParse, pOrderBy, p, regResult); + }else{ + sqlite3ExprCodeMove(pParse, regResult, iParm, 1); + /* The LIMIT clause will jump out of the loop for us */ + } + break; + } +#endif /* #ifndef SQLITE_OMIT_SUBQUERY */ + + /* Send the data to the callback function or to a subroutine. In the + ** case of a subroutine, the subroutine itself is responsible for + ** popping the data from the stack. + */ + case SRT_Coroutine: + case SRT_Callback: { + if( pOrderBy ){ + int r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); + pushOntoSorter(pParse, pOrderBy, p, r1); + sqlite3ReleaseTempReg(pParse, r1); + }else if( eDest==SRT_Coroutine ){ + sqlite3VdbeAddOp1(v, OP_Yield, pDest->iParm); + }else{ + sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nColumn); + sqlite3ExprCacheAffinityChange(pParse, regResult, nColumn); + } + break; + } + +#if !defined(SQLITE_OMIT_TRIGGER) + /* Discard the results. This is used for SELECT statements inside + ** the body of a TRIGGER. The purpose of such selects is to call + ** user-defined functions that have side effects. We do not care + ** about the actual results of the select. + */ + default: { + assert( eDest==SRT_Discard ); + break; + } +#endif + } + + /* Jump to the end of the loop if the LIMIT is reached. + */ + if( p->iLimit ){ + assert( pOrderBy==0 ); /* If there is an ORDER BY, the call to + ** pushOntoSorter() would have cleared p->iLimit */ + sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1); + sqlite3VdbeAddOp2(v, OP_IfZero, p->iLimit, iBreak); + } +} + +/* +** Given an expression list, generate a KeyInfo structure that records +** the collating sequence for each expression in that expression list. +** +** If the ExprList is an ORDER BY or GROUP BY clause then the resulting +** KeyInfo structure is appropriate for initializing a virtual index to +** implement that clause. If the ExprList is the result set of a SELECT +** then the KeyInfo structure is appropriate for initializing a virtual +** index to implement a DISTINCT test. +** +** Space to hold the KeyInfo structure is obtain from malloc. The calling +** function is responsible for seeing that this structure is eventually +** freed. Add the KeyInfo structure to the P4 field of an opcode using +** P4_KEYINFO_HANDOFF is the usual way of dealing with this. +*/ +static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList){ + sqlite3 *db = pParse->db; + int nExpr; + KeyInfo *pInfo; + struct ExprList_item *pItem; + int i; + + nExpr = pList->nExpr; + pInfo = sqlite3DbMallocZero(db, sizeof(*pInfo) + nExpr*(sizeof(CollSeq*)+1) ); + if( pInfo ){ + pInfo->aSortOrder = (u8*)&pInfo->aColl[nExpr]; + pInfo->nField = nExpr; + pInfo->enc = ENC(db); + for(i=0, pItem=pList->a; i<nExpr; i++, pItem++){ + CollSeq *pColl; + pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr); + if( !pColl ){ + pColl = db->pDfltColl; + } + pInfo->aColl[i] = pColl; + pInfo->aSortOrder[i] = pItem->sortOrder; + } + } + return pInfo; +} + + +/* +** If the inner loop was generated using a non-null pOrderBy argument, +** then the results were placed in a sorter. After the loop is terminated +** we need to run the sorter and output the results. The following +** routine generates the code needed to do that. +*/ +static void generateSortTail( + Parse *pParse, /* Parsing context */ + Select *p, /* The SELECT statement */ + Vdbe *v, /* Generate code into this VDBE */ + int nColumn, /* Number of columns of data */ + SelectDest *pDest /* Write the sorted results here */ +){ + int brk = sqlite3VdbeMakeLabel(v); + int cont = sqlite3VdbeMakeLabel(v); + int addr; + int iTab; + int pseudoTab = 0; + ExprList *pOrderBy = p->pOrderBy; + + int eDest = pDest->eDest; + int iParm = pDest->iParm; + + int regRow; + int regRowid; + + iTab = pOrderBy->iECursor; + if( eDest==SRT_Callback || eDest==SRT_Coroutine ){ + pseudoTab = pParse->nTab++; + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, nColumn); + sqlite3VdbeAddOp2(v, OP_OpenPseudo, pseudoTab, eDest==SRT_Callback); + } + addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, brk); + codeOffset(v, p, cont); + regRow = sqlite3GetTempReg(pParse); + regRowid = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr + 1, regRow); + switch( eDest ){ + case SRT_Table: + case SRT_EphemTab: { + sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid); + sqlite3VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid); + sqlite3VdbeChangeP5(v, OPFLAG_APPEND); + break; + } +#ifndef SQLITE_OMIT_SUBQUERY + case SRT_Set: { + assert( nColumn==1 ); + sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid, &p->affinity, 1); + sqlite3ExprCacheAffinityChange(pParse, regRow, 1); + sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRowid); + break; + } + case SRT_Mem: { + assert( nColumn==1 ); + sqlite3ExprCodeMove(pParse, regRow, iParm, 1); + /* The LIMIT clause will terminate the loop for us */ + break; + } +#endif + case SRT_Callback: + case SRT_Coroutine: { + int i; + sqlite3VdbeAddOp2(v, OP_Integer, 1, regRowid); + sqlite3VdbeAddOp3(v, OP_Insert, pseudoTab, regRow, regRowid); + for(i=0; i<nColumn; i++){ + assert( regRow!=pDest->iMem+i ); + sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iMem+i); + } + if( eDest==SRT_Callback ){ + sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iMem, nColumn); + sqlite3ExprCacheAffinityChange(pParse, pDest->iMem, nColumn); + }else{ + sqlite3VdbeAddOp1(v, OP_Yield, pDest->iParm); + } + break; + } + default: { + /* Do nothing */ + break; + } + } + sqlite3ReleaseTempReg(pParse, regRow); + sqlite3ReleaseTempReg(pParse, regRowid); + + /* LIMIT has been implemented by the pushOntoSorter() routine. + */ + assert( p->iLimit==0 ); + + /* The bottom of the loop + */ + sqlite3VdbeResolveLabel(v, cont); + sqlite3VdbeAddOp2(v, OP_Next, iTab, addr); + sqlite3VdbeResolveLabel(v, brk); + if( eDest==SRT_Callback || eDest==SRT_Coroutine ){ + sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0); + } + +} + +/* +** Return a pointer to a string containing the 'declaration type' of the +** expression pExpr. The string may be treated as static by the caller. +** +** The declaration type is the exact datatype definition extracted from the +** original CREATE TABLE statement if the expression is a column. The +** declaration type for a ROWID field is INTEGER. Exactly when an expression +** is considered a column can be complex in the presence of subqueries. The +** result-set expression in all of the following SELECT statements is +** considered a column by this function. +** +** SELECT col FROM tbl; +** SELECT (SELECT col FROM tbl; +** SELECT (SELECT col FROM tbl); +** SELECT abc FROM (SELECT col AS abc FROM tbl); +** +** The declaration type for any expression other than a column is NULL. +*/ +static const char *columnType( + NameContext *pNC, + Expr *pExpr, + const char **pzOriginDb, + const char **pzOriginTab, + const char **pzOriginCol +){ + char const *zType = 0; + char const *zOriginDb = 0; + char const *zOriginTab = 0; + char const *zOriginCol = 0; + int j; + if( pExpr==0 || pNC->pSrcList==0 ) return 0; + + switch( pExpr->op ){ + case TK_AGG_COLUMN: + case TK_COLUMN: { + /* The expression is a column. Locate the table the column is being + ** extracted from in NameContext.pSrcList. This table may be real + ** database table or a subquery. + */ + Table *pTab = 0; /* Table structure column is extracted from */ + Select *pS = 0; /* Select the column is extracted from */ + int iCol = pExpr->iColumn; /* Index of column in pTab */ + while( pNC && !pTab ){ + SrcList *pTabList = pNC->pSrcList; + for(j=0;j<pTabList->nSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++); + if( j<pTabList->nSrc ){ + pTab = pTabList->a[j].pTab; + pS = pTabList->a[j].pSelect; + }else{ + pNC = pNC->pNext; + } + } + + if( pTab==0 ){ + /* FIX ME: + ** This can occurs if you have something like "SELECT new.x;" inside + ** a trigger. In other words, if you reference the special "new" + ** table in the result set of a select. We do not have a good way + ** to find the actual table type, so call it "TEXT". This is really + ** something of a bug, but I do not know how to fix it. + ** + ** This code does not produce the correct answer - it just prevents + ** a segfault. See ticket #1229. + */ + zType = "TEXT"; + break; + } + + assert( pTab ); + if( pS ){ + /* The "table" is actually a sub-select or a view in the FROM clause + ** of the SELECT statement. Return the declaration type and origin + ** data for the result-set column of the sub-select. + */ + if( iCol>=0 && iCol<pS->pEList->nExpr ){ + /* If iCol is less than zero, then the expression requests the + ** rowid of the sub-select or view. This expression is legal (see + ** test case misc2.2.2) - it always evaluates to NULL. + */ + NameContext sNC; + Expr *p = pS->pEList->a[iCol].pExpr; + sNC.pSrcList = pS->pSrc; + sNC.pNext = 0; + sNC.pParse = pNC->pParse; + zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol); + } + }else if( pTab->pSchema ){ + /* A real table */ + assert( !pS ); + if( iCol<0 ) iCol = pTab->iPKey; + assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) ); + if( iCol<0 ){ + zType = "INTEGER"; + zOriginCol = "rowid"; + }else{ + zType = pTab->aCol[iCol].zType; + zOriginCol = pTab->aCol[iCol].zName; + } + zOriginTab = pTab->zName; + if( pNC->pParse ){ + int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema); + zOriginDb = pNC->pParse->db->aDb[iDb].zName; + } + } + break; + } +#ifndef SQLITE_OMIT_SUBQUERY + case TK_SELECT: { + /* The expression is a sub-select. Return the declaration type and + ** origin info for the single column in the result set of the SELECT + ** statement. + */ + NameContext sNC; + Select *pS = pExpr->pSelect; + Expr *p = pS->pEList->a[0].pExpr; + sNC.pSrcList = pS->pSrc; + sNC.pNext = pNC; + sNC.pParse = pNC->pParse; + zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol); + break; + } +#endif + } + + if( pzOriginDb ){ + assert( pzOriginTab && pzOriginCol ); + *pzOriginDb = zOriginDb; + *pzOriginTab = zOriginTab; + *pzOriginCol = zOriginCol; + } + return zType; +} + +/* +** Generate code that will tell the VDBE the declaration types of columns +** in the result set. +*/ +static void generateColumnTypes( + Parse *pParse, /* Parser context */ + SrcList *pTabList, /* List of tables */ + ExprList *pEList /* Expressions defining the result set */ +){ +#ifndef SQLITE_OMIT_DECLTYPE + Vdbe *v = pParse->pVdbe; + int i; + NameContext sNC; + sNC.pSrcList = pTabList; + sNC.pParse = pParse; + for(i=0; i<pEList->nExpr; i++){ + Expr *p = pEList->a[i].pExpr; + const char *zType; +#ifdef SQLITE_ENABLE_COLUMN_METADATA + const char *zOrigDb = 0; + const char *zOrigTab = 0; + const char *zOrigCol = 0; + zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol); + + /* The vdbe must make its own copy of the column-type and other + ** column specific strings, in case the schema is reset before this + ** virtual machine is deleted. + */ + sqlite3VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, P4_TRANSIENT); + sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, P4_TRANSIENT); + sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, P4_TRANSIENT); +#else + zType = columnType(&sNC, p, 0, 0, 0); +#endif + sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, P4_TRANSIENT); + } +#endif /* SQLITE_OMIT_DECLTYPE */ +} + +/* +** Generate code that will tell the VDBE the names of columns +** in the result set. This information is used to provide the +** azCol[] values in the callback. +*/ +static void generateColumnNames( + Parse *pParse, /* Parser context */ + SrcList *pTabList, /* List of tables */ + ExprList *pEList /* Expressions defining the result set */ +){ + Vdbe *v = pParse->pVdbe; + int i, j; + sqlite3 *db = pParse->db; + int fullNames, shortNames; + +#ifndef SQLITE_OMIT_EXPLAIN + /* If this is an EXPLAIN, skip this step */ + if( pParse->explain ){ + return; + } +#endif + + assert( v!=0 ); + if( pParse->colNamesSet || v==0 || db->mallocFailed ) return; + pParse->colNamesSet = 1; + fullNames = (db->flags & SQLITE_FullColNames)!=0; + shortNames = (db->flags & SQLITE_ShortColNames)!=0; + sqlite3VdbeSetNumCols(v, pEList->nExpr); + for(i=0; i<pEList->nExpr; i++){ + Expr *p; + p = pEList->a[i].pExpr; + if( p==0 ) continue; + if( pEList->a[i].zName ){ + char *zName = pEList->a[i].zName; + sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, strlen(zName)); + }else if( p->op==TK_COLUMN && pTabList ){ + Table *pTab; + char *zCol; + int iCol = p->iColumn; + for(j=0; j<pTabList->nSrc && pTabList->a[j].iCursor!=p->iTable; j++){} + assert( j<pTabList->nSrc ); + pTab = pTabList->a[j].pTab; + if( iCol<0 ) iCol = pTab->iPKey; + assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) ); + if( iCol<0 ){ + zCol = "rowid"; + }else{ + zCol = pTab->aCol[iCol].zName; + } + if( !shortNames && !fullNames ){ + sqlite3VdbeSetColName(v, i, COLNAME_NAME, (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; + zName = sqlite3MPrintf(db, "%s.%s", zTab, zCol); + sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, P4_DYNAMIC); + }else{ + sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, strlen(zCol)); + } + }else{ + sqlite3VdbeSetColName(v, i, COLNAME_NAME, (char*)p->span.z, p->span.n); + } + } + generateColumnTypes(pParse, pTabList, pEList); +} + +#ifndef SQLITE_OMIT_COMPOUND_SELECT +/* +** Name of the connection operator, used for error messages. +*/ +static const char *selectOpName(int id){ + char *z; + switch( id ){ + case TK_ALL: z = "UNION ALL"; break; + case TK_INTERSECT: z = "INTERSECT"; break; + case TK_EXCEPT: z = "EXCEPT"; break; + default: z = "UNION"; break; + } + return z; +} +#endif /* SQLITE_OMIT_COMPOUND_SELECT */ + +/* +** Forward declaration +*/ +static int prepSelectStmt(Parse*, Select*); + +/* +** Given a SELECT statement, generate a Table structure that describes +** the result set of that SELECT. +*/ +Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ + Table *pTab; + int i, j, rc; + ExprList *pEList; + Column *aCol, *pCol; + sqlite3 *db = pParse->db; + int savedFlags; + + savedFlags = db->flags; + db->flags &= ~SQLITE_FullColNames; + db->flags |= SQLITE_ShortColNames; + rc = sqlite3SelectResolve(pParse, pSelect, 0); + if( rc==SQLITE_OK ){ + while( pSelect->pPrior ) pSelect = pSelect->pPrior; + rc = prepSelectStmt(pParse, pSelect); + if( rc==SQLITE_OK ){ + rc = sqlite3SelectResolve(pParse, pSelect, 0); + } + } + db->flags = savedFlags; + if( rc ){ + return 0; + } + pTab = sqlite3DbMallocZero(db, sizeof(Table) ); + if( pTab==0 ){ + return 0; + } + pTab->db = db; + pTab->nRef = 1; + pTab->zName = zTabName ? sqlite3DbStrDup(db, zTabName) : 0; + pEList = pSelect->pEList; + pTab->nCol = pEList->nExpr; + assert( pTab->nCol>0 ); + pTab->aCol = aCol = sqlite3DbMallocZero(db, sizeof(pTab->aCol[0])*pTab->nCol); + testcase( aCol==0 ); + for(i=0, pCol=aCol; i<pTab->nCol; i++, pCol++){ + Expr *p; + char *zType; + char *zName; + int nName; + CollSeq *pColl; + int cnt; + NameContext sNC; + + /* Get an appropriate name for the column + */ + p = pEList->a[i].pExpr; + assert( p->pRight==0 || p->pRight->token.z==0 || p->pRight->token.z[0]!=0 ); + if( (zName = pEList->a[i].zName)!=0 ){ + /* If the column contains an "AS <name>" phrase, use <name> as the name */ + zName = sqlite3DbStrDup(db, zName); + }else if( p->op==TK_COLUMN && p->pTab ){ + /* For columns use the column name name */ + int iCol = p->iColumn; + if( iCol<0 ) iCol = p->pTab->iPKey; + zName = sqlite3MPrintf(db, "%s", p->pTab->aCol[iCol].zName); + }else{ + /* Use the original text of the column expression as its name */ + zName = sqlite3MPrintf(db, "%T", &p->span); + } + if( db->mallocFailed ){ + sqlite3DbFree(db, zName); + break; + } + sqlite3Dequote(zName); + + /* Make sure the column name is unique. If the name is not unique, + ** append a integer to the name so that it becomes unique. + */ + nName = strlen(zName); + for(j=cnt=0; j<i; j++){ + if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){ + char *zNewName; + zName[nName] = 0; + zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt); + sqlite3DbFree(db, zName); + zName = zNewName; + j = -1; + if( zName==0 ) break; + } + } + pCol->zName = zName; + + /* Get the typename, type affinity, and collating sequence for the + ** column. + */ + memset(&sNC, 0, sizeof(sNC)); + sNC.pSrcList = pSelect->pSrc; + zType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0)); + pCol->zType = zType; + pCol->affinity = sqlite3ExprAffinity(p); + pColl = sqlite3ExprCollSeq(pParse, p); + if( pColl ){ + pCol->zColl = sqlite3DbStrDup(db, pColl->zName); + } + } + pTab->iPKey = -1; + if( db->mallocFailed ){ + sqlite3DeleteTable(pTab); + return 0; + } + return pTab; +} + +/* +** Prepare a SELECT statement for processing by doing the following +** things: +** +** (1) Make sure VDBE cursor numbers have been assigned to every +** element of the FROM clause. +** +** (2) Fill in the pTabList->a[].pTab fields in the SrcList that +** defines FROM clause. When views appear in the FROM clause, +** fill pTabList->a[].pSelect with a copy of the SELECT statement +** that implements the view. A copy is made of the view's SELECT +** statement so that we can freely modify or delete that statement +** without worrying about messing up the presistent representation +** of the view. +** +** (3) Add terms to the WHERE clause to accomodate the NATURAL keyword +** on joins and the ON and USING clause of joins. +** +** (4) Scan the list of columns in the result set (pEList) looking +** for instances of the "*" operator or the TABLE.* operator. +** If found, expand each "*" to be every column in every table +** and TABLE.* to be every column in TABLE. +** +** Return 0 on success. If there are problems, leave an error message +** in pParse and return non-zero. +*/ +static int prepSelectStmt(Parse *pParse, Select *p){ + int i, j, k, rc; + SrcList *pTabList; + ExprList *pEList; + struct SrcList_item *pFrom; + sqlite3 *db = pParse->db; + + if( p==0 || p->pSrc==0 || db->mallocFailed ){ + return 1; + } + pTabList = p->pSrc; + pEList = p->pEList; + + /* Make sure cursor numbers have been assigned to all entries in + ** the FROM clause of the SELECT statement. + */ + sqlite3SrcListAssignCursors(pParse, p->pSrc); + + /* Look up every table named in the FROM clause of the select. If + ** an entry of the FROM clause is a subquery instead of a table or view, + ** then create a transient table structure to describe the subquery. + */ + for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ + Table *pTab; + if( pFrom->pTab!=0 ){ + /* This statement has already been prepared. There is no need + ** to go further. */ + assert( i==0 ); + return 0; + } + if( pFrom->zName==0 ){ +#ifndef SQLITE_OMIT_SUBQUERY + /* A sub-query in the FROM clause of a SELECT */ + assert( pFrom->pSelect!=0 ); + if( pFrom->zAlias==0 ){ + pFrom->zAlias = + sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pFrom->pSelect); + } + assert( pFrom->pTab==0 ); + pFrom->pTab = pTab = + sqlite3ResultSetOfSelect(pParse, pFrom->zAlias, pFrom->pSelect); + if( pTab==0 ){ + return 1; + } + /* The isEphem flag indicates that the Table structure has been + ** dynamically allocated and may be freed at any time. In other words, + ** pTab is not pointing to a persistent table structure that defines + ** part of the schema. */ + pTab->isEphem = 1; +#endif + }else{ + /* An ordinary table or view name in the FROM clause */ + assert( pFrom->pTab==0 ); + pFrom->pTab = pTab = + sqlite3LocateTable(pParse,0,pFrom->zName,pFrom->zDatabase); + if( pTab==0 ){ + return 1; + } + pTab->nRef++; +#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE) + if( pTab->pSelect || IsVirtual(pTab) ){ + /* We reach here if the named table is a really a view */ + if( sqlite3ViewGetColumnNames(pParse, pTab) ){ + return 1; + } + /* If pFrom->pSelect!=0 it means we are dealing with a + ** view within a view. The SELECT structure has already been + ** copied by the outer view so we can skip the copy step here + ** in the inner view. + */ + if( pFrom->pSelect==0 ){ + pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect); + } + } +#endif + } + } + + /* Process NATURAL keywords, and ON and USING clauses of joins. + */ + if( sqliteProcessJoin(pParse, p) ) return 1; + + /* For every "*" that occurs in the column list, insert the names of + ** all columns in all tables. And for every TABLE.* insert the names + ** of all columns in TABLE. The parser inserted a special expression + ** with the TK_ALL operator for each "*" that it found in the column list. + ** The following code just has to locate the TK_ALL expressions and expand + ** each one to the list of all columns in all tables. + ** + ** The first loop just checks to see if there are any "*" operators + ** that need expanding. + */ + for(k=0; k<pEList->nExpr; k++){ + Expr *pE = pEList->a[k].pExpr; + if( pE->op==TK_ALL ) break; + if( pE->op==TK_DOT && pE->pRight && pE->pRight->op==TK_ALL + && pE->pLeft && pE->pLeft->op==TK_ID ) break; + } + rc = 0; + if( k<pEList->nExpr ){ + /* + ** If we get here it means the result set contains one or more "*" + ** operators that need to be expanded. Loop through each expression + ** in the result set and expand them one by one. + */ + struct ExprList_item *a = pEList->a; + ExprList *pNew = 0; + int flags = pParse->db->flags; + int longNames = (flags & SQLITE_FullColNames)!=0 + && (flags & SQLITE_ShortColNames)==0; + + for(k=0; k<pEList->nExpr; k++){ + Expr *pE = a[k].pExpr; + if( pE->op!=TK_ALL && + (pE->op!=TK_DOT || pE->pRight==0 || pE->pRight->op!=TK_ALL) ){ + /* This particular expression does not need to be expanded. + */ + pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr, 0); + if( pNew ){ + pNew->a[pNew->nExpr-1].zName = a[k].zName; + }else{ + rc = 1; + } + a[k].pExpr = 0; + a[k].zName = 0; + }else{ + /* This expression is a "*" or a "TABLE.*" and needs to be + ** expanded. */ + int tableSeen = 0; /* Set to 1 when TABLE matches */ + char *zTName; /* text of name of TABLE */ + if( pE->op==TK_DOT && pE->pLeft ){ + zTName = sqlite3NameFromToken(db, &pE->pLeft->token); + }else{ + zTName = 0; + } + for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ + Table *pTab = pFrom->pTab; + char *zTabName = pFrom->zAlias; + if( zTabName==0 || zTabName[0]==0 ){ + zTabName = pTab->zName; + } + assert( zTabName ); + if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ + continue; + } + tableSeen = 1; + for(j=0; j<pTab->nCol; j++){ + Expr *pExpr, *pRight; + char *zName = pTab->aCol[j].zName; + + /* If a column is marked as 'hidden' (currently only possible + ** for virtual tables), do not include it in the expanded + ** result-set list. + */ + if( IsHiddenColumn(&pTab->aCol[j]) ){ + assert(IsVirtual(pTab)); + continue; + } + + if( i>0 ){ + struct SrcList_item *pLeft = &pTabList->a[i-1]; + if( (pLeft[1].jointype & JT_NATURAL)!=0 && + columnIndex(pLeft->pTab, zName)>=0 ){ + /* In a NATURAL join, omit the join columns from the + ** table on the right */ + continue; + } + if( sqlite3IdListIndex(pLeft[1].pUsing, zName)>=0 ){ + /* In a join with a USING clause, omit columns in the + ** using clause from the table on the right. */ + continue; + } + } + pRight = sqlite3PExpr(pParse, TK_ID, 0, 0, 0); + if( pRight==0 ) break; + setQuotedToken(pParse, &pRight->token, zName); + if( longNames || pTabList->nSrc>1 ){ + Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, 0); + pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); + if( pExpr==0 ) break; + setQuotedToken(pParse, &pLeft->token, zTabName); +#if 1 + setToken(&pExpr->span, + sqlite3MPrintf(db, "%s.%s", zTabName, zName)); + pExpr->span.dyn = 1; +#else + pExpr->span = pRight->token; + pExpr->span.dyn = 0; +#endif + pExpr->token.z = 0; + pExpr->token.n = 0; + pExpr->token.dyn = 0; + }else{ + pExpr = pRight; + pExpr->span = pExpr->token; + pExpr->span.dyn = 0; + } + if( longNames ){ + pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pExpr->span); + }else{ + pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pRight->token); + } + } + } + if( !tableSeen ){ + if( zTName ){ + sqlite3ErrorMsg(pParse, "no such table: %s", zTName); + }else{ + sqlite3ErrorMsg(pParse, "no tables specified"); + } + rc = 1; + } + sqlite3DbFree(db, zTName); + } + } + sqlite3ExprListDelete(db, pEList); + p->pEList = pNew; + } +#if SQLITE_MAX_COLUMN + if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ + sqlite3ErrorMsg(pParse, "too many columns in result set"); + rc = SQLITE_ERROR; + } +#endif + if( db->mallocFailed ){ + rc = SQLITE_NOMEM; + } + return rc; +} + +/* +** pE is a pointer to an expression which is a single term in +** ORDER BY or GROUP BY clause. +** +** At the point this routine is called, we already know that the +** ORDER BY term is not an integer index into the result set. That +** casee is handled by the calling routine. +** +** If pE is a well-formed expression and the SELECT statement +** is not compound, then return 0. This indicates to the +** caller that it should sort by the value of the ORDER BY +** expression. +** +** If the SELECT is compound, then attempt to match pE against +** result set columns in the left-most SELECT statement. Return +** the index i of the matching column, as an indication to the +** caller that it should sort by the i-th column. If there is +** no match, return -1 and leave an error message in pParse. +*/ +static int matchOrderByTermToExprList( + Parse *pParse, /* Parsing context for error messages */ + Select *pSelect, /* The SELECT statement with the ORDER BY clause */ + Expr *pE, /* The specific ORDER BY term */ + int idx, /* When ORDER BY term is this */ + int isCompound, /* True if this is a compound SELECT */ + u8 *pHasAgg /* True if expression contains aggregate functions */ +){ + int i; /* Loop counter */ + ExprList *pEList; /* The columns of the result set */ + NameContext nc; /* Name context for resolving pE */ + + assert( sqlite3ExprIsInteger(pE, &i)==0 ); + pEList = pSelect->pEList; + + /* If the term is a simple identifier that try to match that identifier + ** against a column name in the result set. + */ + if( pE->op==TK_ID || (pE->op==TK_STRING && pE->token.z[0]!='\'') ){ + sqlite3 *db = pParse->db; + char *zCol = sqlite3NameFromToken(db, &pE->token); + if( zCol==0 ){ + return -1; + } + for(i=0; i<pEList->nExpr; i++){ + char *zAs = pEList->a[i].zName; + if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ + sqlite3DbFree(db, zCol); + return i+1; + } + } + sqlite3DbFree(db, zCol); + } + + /* Resolve all names in the ORDER BY term expression + */ + memset(&nc, 0, sizeof(nc)); + nc.pParse = pParse; + nc.pSrcList = pSelect->pSrc; + nc.pEList = pEList; + nc.allowAgg = 1; + nc.nErr = 0; + if( sqlite3ExprResolveNames(&nc, pE) ){ + if( isCompound ){ + sqlite3ErrorClear(pParse); + return 0; + }else{ + return -1; + } + } + if( nc.hasAgg && pHasAgg ){ + *pHasAgg = 1; + } + + /* For a compound SELECT, we need to try to match the ORDER BY + ** expression against an expression in the result set + */ + if( isCompound ){ + for(i=0; i<pEList->nExpr; i++){ + if( sqlite3ExprCompare(pEList->a[i].pExpr, pE) ){ + return i+1; + } + } + } + return 0; +} + + +/* +** Analyze and ORDER BY or GROUP BY clause in a simple SELECT statement. +** Return the number of errors seen. +** +** Every term of the ORDER BY or GROUP BY clause needs to be an +** expression. If any expression is an integer constant, then +** that expression is replaced by the corresponding +** expression from the result set. +*/ +static int processOrderGroupBy( + Parse *pParse, /* Parsing context. Leave error messages here */ + Select *pSelect, /* The SELECT statement containing the clause */ + ExprList *pOrderBy, /* The ORDER BY or GROUP BY clause to be processed */ + int isOrder, /* 1 for ORDER BY. 0 for GROUP BY */ + u8 *pHasAgg /* Set to TRUE if any term contains an aggregate */ +){ + int i; + sqlite3 *db = pParse->db; + ExprList *pEList; + + if( pOrderBy==0 || pParse->db->mallocFailed ) return 0; +#if SQLITE_MAX_COLUMN + if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ + const char *zType = isOrder ? "ORDER" : "GROUP"; + sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType); + return 1; + } +#endif + pEList = pSelect->pEList; + if( pEList==0 ){ + return 0; + } + for(i=0; i<pOrderBy->nExpr; i++){ + int iCol; + Expr *pE = pOrderBy->a[i].pExpr; + if( sqlite3ExprIsInteger(pE, &iCol) ){ + if( iCol<=0 || iCol>pEList->nExpr ){ + const char *zType = isOrder ? "ORDER" : "GROUP"; + sqlite3ErrorMsg(pParse, + "%r %s BY term out of range - should be " + "between 1 and %d", i+1, zType, pEList->nExpr); + return 1; + } + }else{ + iCol = matchOrderByTermToExprList(pParse, pSelect, pE, i+1, 0, pHasAgg); + if( iCol<0 ){ + return 1; + } + } + if( iCol>0 ){ + CollSeq *pColl = pE->pColl; + int flags = pE->flags & EP_ExpCollate; + sqlite3ExprDelete(db, pE); + pE = sqlite3ExprDup(db, pEList->a[iCol-1].pExpr); + pOrderBy->a[i].pExpr = pE; + if( pE && pColl && flags ){ + pE->pColl = pColl; + pE->flags |= flags; + } + } + } + return 0; +} + +/* +** Analyze and ORDER BY or GROUP BY clause in a SELECT statement. Return +** the number of errors seen. +** +** If iTable>0 then make the N-th term of the ORDER BY clause refer to +** the N-th column of table iTable. +** +** If iTable==0 then transform each term of the ORDER BY clause to refer +** to a column of the result set by number. +*/ +static int processCompoundOrderBy( + Parse *pParse, /* Parsing context. Leave error messages here */ + Select *pSelect /* The SELECT statement containing the ORDER BY */ +){ + int i; + ExprList *pOrderBy; + ExprList *pEList; + sqlite3 *db; + int moreToDo = 1; + + pOrderBy = pSelect->pOrderBy; + if( pOrderBy==0 ) return 0; + db = pParse->db; +#if SQLITE_MAX_COLUMN + if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ + sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause"); + return 1; + } +#endif + for(i=0; i<pOrderBy->nExpr; i++){ + pOrderBy->a[i].done = 0; + } + while( pSelect->pPrior ){ + pSelect = pSelect->pPrior; + } + while( pSelect && moreToDo ){ + moreToDo = 0; + pEList = pSelect->pEList; + if( pEList==0 ){ + return 1; + } + for(i=0; i<pOrderBy->nExpr; i++){ + int iCol = -1; + Expr *pE, *pDup; + if( pOrderBy->a[i].done ) continue; + pE = pOrderBy->a[i].pExpr; + if( sqlite3ExprIsInteger(pE, &iCol) ){ + if( iCol<0 || iCol>pEList->nExpr ){ + sqlite3ErrorMsg(pParse, + "%r ORDER BY term out of range - should be " + "between 1 and %d", i+1, pEList->nExpr); + return 1; + } + }else{ + pDup = sqlite3ExprDup(db, pE); + if( !db->mallocFailed ){ + assert(pDup); + iCol = matchOrderByTermToExprList(pParse, pSelect, pDup, i+1, 1, 0); + } + sqlite3ExprDelete(db, pDup); + if( iCol<0 ){ + return 1; + } + } + if( iCol>0 ){ + pE->op = TK_INTEGER; + pE->flags |= EP_IntValue; + pE->iTable = iCol; + pOrderBy->a[i].done = 1; + }else{ + moreToDo = 1; + } + } + pSelect = pSelect->pNext; + } + for(i=0; i<pOrderBy->nExpr; i++){ + if( pOrderBy->a[i].done==0 ){ + sqlite3ErrorMsg(pParse, "%r ORDER BY term does not match any " + "column in the result set", i+1); + return 1; + } + } + return 0; +} + +/* +** Get a VDBE for the given parser context. Create a new one if necessary. +** If an error occurs, return NULL and leave a message in pParse. +*/ +Vdbe *sqlite3GetVdbe(Parse *pParse){ + Vdbe *v = pParse->pVdbe; + if( v==0 ){ + v = pParse->pVdbe = sqlite3VdbeCreate(pParse->db); +#ifndef SQLITE_OMIT_TRACE + if( v ){ + sqlite3VdbeAddOp0(v, OP_Trace); + } +#endif + } + return v; +} + + +/* +** Compute the iLimit and iOffset fields of the SELECT based on the +** 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 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 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, int iBreak){ + Vdbe *v = 0; + int iLimit = 0; + int iOffset; + int addr1; + if( p->iLimit ) return; + + /* + ** "LIMIT -1" always shows all rows. There is some + ** contraversy about what the correct behavior should be. + ** The current implementation interprets "LIMIT 0" to mean + ** no rows. + */ + if( p->pLimit ){ + p->iLimit = iLimit = ++pParse->nMem; + v = sqlite3GetVdbe(pParse); + if( v==0 ) return; + sqlite3ExprCode(pParse, p->pLimit, iLimit); + sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); + VdbeComment((v, "LIMIT counter")); + sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak); + } + if( p->pOffset ){ + p->iOffset = iOffset = ++pParse->nMem; + if( p->pLimit ){ + pParse->nMem++; /* Allocate an extra register for limit+offset */ + } + v = sqlite3GetVdbe(pParse); + if( v==0 ) return; + sqlite3ExprCode(pParse, p->pOffset, iOffset); + sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); + VdbeComment((v, "OFFSET counter")); + addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset); + sqlite3VdbeAddOp2(v, OP_Integer, 0, iOffset); + sqlite3VdbeJumpHere(v, addr1); + if( p->pLimit ){ + sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1); + VdbeComment((v, "LIMIT+OFFSET")); + addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit); + sqlite3VdbeAddOp2(v, OP_Integer, -1, iOffset+1); + sqlite3VdbeJumpHere(v, addr1); + } + } +} + +#ifndef SQLITE_OMIT_COMPOUND_SELECT +/* +** Return the appropriate collating sequence for the iCol-th column of +** the result set for the compound-select statement "p". Return NULL if +** the column has no default collating sequence. +** +** The collating sequence for the compound select is taken from the +** left-most term of the select that has a collating sequence. +*/ +static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){ + CollSeq *pRet; + if( p->pPrior ){ + pRet = multiSelectCollSeq(pParse, p->pPrior, iCol); + }else{ + pRet = 0; + } + if( pRet==0 ){ + pRet = sqlite3ExprCollSeq(pParse, p->pEList->a[iCol].pExpr); + } + return pRet; +} +#endif /* SQLITE_OMIT_COMPOUND_SELECT */ + +/* Forward reference */ +static int multiSelectOrderBy( + Parse *pParse, /* Parsing context */ + Select *p, /* The right-most of SELECTs to be coded */ + SelectDest *pDest /* What to do with query results */ +); + + +#ifndef SQLITE_OMIT_COMPOUND_SELECT +/* +** This routine is called to process a compound query form from +** two or more separate queries using UNION, UNION ALL, EXCEPT, or +** INTERSECT +** +** "p" points to the right-most of the two queries. the query on the +** left is p->pPrior. The left query could also be a compound query +** in which case this routine will be called recursively. +** +** The results of the total query are to be written into a destination +** of type eDest with parameter iParm. +** +** Example 1: Consider a three-way compound SQL statement. +** +** SELECT a FROM t1 UNION SELECT b FROM t2 UNION SELECT c FROM t3 +** +** This statement is parsed up as follows: +** +** SELECT c FROM t3 +** | +** `-----> SELECT b FROM t2 +** | +** `------> SELECT a FROM t1 +** +** The arrows in the diagram above represent the Select.pPrior pointer. +** So if this routine is called with p equal to the t3 query, then +** pPrior will be the t2 query. p->op will be TK_UNION in this case. +** +** Notice that because of the way SQLite parses compound SELECTs, the +** individual selects always group from left to right. +*/ +static int multiSelect( + Parse *pParse, /* Parsing context */ + Select *p, /* The right-most of SELECTs to be coded */ + SelectDest *pDest /* What to do with query results */ +){ + int rc = SQLITE_OK; /* Success code from a subroutine */ + Select *pPrior; /* Another SELECT immediately to our left */ + Vdbe *v; /* Generate code to this VDBE */ + SelectDest dest; /* Alternative data destination */ + Select *pDelete = 0; /* Chain of simple selects to delete */ + sqlite3 *db; /* Database connection */ + + /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only + ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT. + */ + assert( p && p->pPrior ); /* Calling function guarantees this much */ + db = pParse->db; + pPrior = p->pPrior; + assert( pPrior->pRightmost!=pPrior ); + assert( pPrior->pRightmost==p->pRightmost ); + if( pPrior->pOrderBy ){ + sqlite3ErrorMsg(pParse,"ORDER BY clause should come after %s not before", + selectOpName(p->op)); + rc = 1; + goto multi_select_end; + } + if( pPrior->pLimit ){ + sqlite3ErrorMsg(pParse,"LIMIT clause should come after %s not before", + selectOpName(p->op)); + rc = 1; + goto multi_select_end; + } + + v = sqlite3GetVdbe(pParse); + assert( v!=0 ); /* The VDBE already created by calling function */ + + /* Create the destination temporary table if necessary + */ + dest = *pDest; + if( dest.eDest==SRT_EphemTab ){ + assert( p->pEList ); + sqlite3VdbeAddOp2(v, OP_OpenEphemeral, dest.iParm, p->pEList->nExpr); + dest.eDest = SRT_Table; + } + + /* Make sure all SELECTs in the statement have the same number of elements + ** in their result sets. + */ + assert( p->pEList && pPrior->pEList ); + if( p->pEList->nExpr!=pPrior->pEList->nExpr ){ + sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s" + " do not have the same number of result columns", selectOpName(p->op)); + rc = 1; + goto multi_select_end; + } + + /* Compound SELECTs that have an ORDER BY clause are handled separately. + */ + if( p->pOrderBy ){ + return multiSelectOrderBy(pParse, p, pDest); + } + + /* Generate code for the left and right SELECT statements. + */ + switch( p->op ){ + case TK_ALL: { + int addr = 0; + assert( !pPrior->pLimit ); + pPrior->pLimit = p->pLimit; + pPrior->pOffset = p->pOffset; + rc = sqlite3Select(pParse, pPrior, &dest, 0, 0, 0); + p->pLimit = 0; + p->pOffset = 0; + if( rc ){ + goto multi_select_end; + } + p->pPrior = 0; + p->iLimit = pPrior->iLimit; + p->iOffset = pPrior->iOffset; + if( p->iLimit ){ + addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit); + VdbeComment((v, "Jump ahead if LIMIT reached")); + } + rc = sqlite3Select(pParse, p, &dest, 0, 0, 0); + pDelete = p->pPrior; + p->pPrior = pPrior; + if( rc ){ + goto multi_select_end; + } + if( addr ){ + sqlite3VdbeJumpHere(v, addr); + } + break; + } + case TK_EXCEPT: + case TK_UNION: { + int unionTab; /* Cursor number of the temporary table holding result */ + int op = 0; /* One of the SRT_ operations to apply to self */ + int priorOp; /* The SRT_ operation to apply to prior selects */ + Expr *pLimit, *pOffset; /* Saved values of p->nLimit and p->nOffset */ + int addr; + SelectDest uniondest; + + priorOp = SRT_Union; + if( dest.eDest==priorOp && !p->pLimit && !p->pOffset ){ + /* We can reuse a temporary table generated by a SELECT to our + ** right. + */ + unionTab = dest.iParm; + }else{ + /* We will need to create our own temporary table to hold the + ** intermediate results. + */ + unionTab = pParse->nTab++; + assert( p->pOrderBy==0 ); + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0); + assert( p->addrOpenEphm[0] == -1 ); + p->addrOpenEphm[0] = addr; + p->pRightmost->usesEphm = 1; + assert( p->pEList ); + } + + /* Code the SELECT statements to our left + */ + assert( !pPrior->pOrderBy ); + sqlite3SelectDestInit(&uniondest, priorOp, unionTab); + rc = sqlite3Select(pParse, pPrior, &uniondest, 0, 0, 0); + if( rc ){ + goto multi_select_end; + } + + /* Code the current SELECT statement + */ + if( p->op==TK_EXCEPT ){ + op = SRT_Except; + }else{ + assert( p->op==TK_UNION ); + op = SRT_Union; + } + p->pPrior = 0; + p->disallowOrderBy = 0; + pLimit = p->pLimit; + p->pLimit = 0; + pOffset = p->pOffset; + p->pOffset = 0; + uniondest.eDest = op; + rc = sqlite3Select(pParse, p, &uniondest, 0, 0, 0); + /* Query flattening in sqlite3Select() might refill p->pOrderBy. + ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */ + sqlite3ExprListDelete(db, p->pOrderBy); + pDelete = p->pPrior; + p->pPrior = pPrior; + p->pOrderBy = 0; + sqlite3ExprDelete(db, p->pLimit); + p->pLimit = pLimit; + p->pOffset = pOffset; + p->iLimit = 0; + p->iOffset = 0; + if( rc ){ + goto multi_select_end; + } + + + /* Convert the data in the temporary table into whatever form + ** it is that we currently need. + */ + if( dest.eDest!=priorOp || unionTab!=dest.iParm ){ + int iCont, iBreak, iStart; + assert( p->pEList ); + if( dest.eDest==SRT_Callback ){ + Select *pFirst = p; + while( pFirst->pPrior ) pFirst = pFirst->pPrior; + generateColumnNames(pParse, 0, pFirst->pEList); + } + iBreak = sqlite3VdbeMakeLabel(v); + iCont = sqlite3VdbeMakeLabel(v); + computeLimitRegisters(pParse, p, iBreak); + sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); + iStart = sqlite3VdbeCurrentAddr(v); + selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr, + 0, -1, &dest, iCont, iBreak); + sqlite3VdbeResolveLabel(v, iCont); + sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); + sqlite3VdbeResolveLabel(v, iBreak); + sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0); + } + break; + } + case TK_INTERSECT: { + int tab1, tab2; + int iCont, iBreak, iStart; + Expr *pLimit, *pOffset; + int addr; + SelectDest intersectdest; + int r1; + + /* INTERSECT is different from the others since it requires + ** two temporary tables. Hence it has its own case. Begin + ** by allocating the tables we will need. + */ + tab1 = pParse->nTab++; + tab2 = pParse->nTab++; + assert( p->pOrderBy==0 ); + + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0); + assert( p->addrOpenEphm[0] == -1 ); + p->addrOpenEphm[0] = addr; + p->pRightmost->usesEphm = 1; + assert( p->pEList ); + + /* Code the SELECTs to our left into temporary table "tab1". + */ + sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1); + rc = sqlite3Select(pParse, pPrior, &intersectdest, 0, 0, 0); + if( rc ){ + goto multi_select_end; + } + + /* Code the current SELECT into temporary table "tab2" + */ + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0); + assert( p->addrOpenEphm[1] == -1 ); + p->addrOpenEphm[1] = addr; + p->pPrior = 0; + pLimit = p->pLimit; + p->pLimit = 0; + pOffset = p->pOffset; + p->pOffset = 0; + intersectdest.iParm = tab2; + rc = sqlite3Select(pParse, p, &intersectdest, 0, 0, 0); + pDelete = p->pPrior; + p->pPrior = pPrior; + sqlite3ExprDelete(db, p->pLimit); + p->pLimit = pLimit; + p->pOffset = pOffset; + if( rc ){ + goto multi_select_end; + } + + /* Generate code to take the intersection of the two temporary + ** tables. + */ + assert( p->pEList ); + if( dest.eDest==SRT_Callback ){ + Select *pFirst = p; + while( pFirst->pPrior ) pFirst = pFirst->pPrior; + generateColumnNames(pParse, 0, pFirst->pEList); + } + iBreak = sqlite3VdbeMakeLabel(v); + iCont = sqlite3VdbeMakeLabel(v); + computeLimitRegisters(pParse, p, iBreak); + sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); + r1 = sqlite3GetTempReg(pParse); + iStart = sqlite3VdbeAddOp2(v, OP_RowKey, tab1, r1); + sqlite3VdbeAddOp3(v, OP_NotFound, tab2, iCont, r1); + sqlite3ReleaseTempReg(pParse, r1); + selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr, + 0, -1, &dest, iCont, iBreak); + sqlite3VdbeResolveLabel(v, iCont); + sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); + sqlite3VdbeResolveLabel(v, iBreak); + sqlite3VdbeAddOp2(v, OP_Close, tab2, 0); + sqlite3VdbeAddOp2(v, OP_Close, tab1, 0); + break; + } + } + + /* Compute collating sequences used by + ** temporary tables needed to implement the compound select. + ** Attach the KeyInfo structure to all temporary tables. + ** + ** This section is run by the right-most SELECT statement only. + ** SELECT statements to the left always skip this part. The right-most + ** SELECT might also skip this part if it has no ORDER BY clause and + ** no temp tables are required. + */ + if( p->usesEphm ){ + int i; /* Loop counter */ + KeyInfo *pKeyInfo; /* Collating sequence for the result set */ + Select *pLoop; /* For looping through SELECT statements */ + CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */ + int nCol; /* Number of columns in result set */ + + assert( p->pRightmost==p ); + nCol = p->pEList->nExpr; + pKeyInfo = sqlite3DbMallocZero(db, + sizeof(*pKeyInfo)+nCol*(sizeof(CollSeq*) + 1)); + if( !pKeyInfo ){ + rc = SQLITE_NOMEM; + goto multi_select_end; + } + + pKeyInfo->enc = ENC(db); + pKeyInfo->nField = nCol; + + for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){ + *apColl = multiSelectCollSeq(pParse, p, i); + if( 0==*apColl ){ + *apColl = db->pDfltColl; + } + } + + for(pLoop=p; pLoop; pLoop=pLoop->pPrior){ + for(i=0; i<2; i++){ + int addr = pLoop->addrOpenEphm[i]; + if( addr<0 ){ + /* If [0] is unused then [1] is also unused. So we can + ** always safely abort as soon as the first unused slot is found */ + assert( pLoop->addrOpenEphm[1]<0 ); + break; + } + sqlite3VdbeChangeP2(v, addr, nCol); + sqlite3VdbeChangeP4(v, addr, (char*)pKeyInfo, P4_KEYINFO); + pLoop->addrOpenEphm[i] = -1; + } + } + sqlite3DbFree(db, pKeyInfo); + } + +multi_select_end: + pDest->iMem = dest.iMem; + pDest->nMem = dest.nMem; + sqlite3SelectDelete(db, pDelete); + return rc; +} +#endif /* SQLITE_OMIT_COMPOUND_SELECT */ + +/* +** Code an output subroutine for a coroutine implementation of a +** SELECT statment. +** +** The data to be output is contained in pIn->iMem. There are +** pIn->nMem columns to be output. pDest is where the output should +** be sent. +** +** regReturn is the number of the register holding the subroutine +** return address. +** +** If regPrev>0 then it is a the first register in a vector that +** records the previous output. mem[regPrev] is a flag that is false +** if there has been no previous output. If regPrev>0 then code is +** generated to suppress duplicates. pKeyInfo is used for comparing +** keys. +** +** If the LIMIT found in p->iLimit is reached, jump immediately to +** iBreak. +*/ +static int generateOutputSubroutine( + Parse *pParse, /* Parsing context */ + Select *p, /* The SELECT statement */ + SelectDest *pIn, /* Coroutine supplying data */ + SelectDest *pDest, /* Where to send the data */ + int regReturn, /* The return address register */ + int regPrev, /* Previous result register. No uniqueness if 0 */ + KeyInfo *pKeyInfo, /* For comparing with previous entry */ + int p4type, /* The p4 type for pKeyInfo */ + int iBreak /* Jump here if we hit the LIMIT */ +){ + Vdbe *v = pParse->pVdbe; + int iContinue; + int addr; + + addr = sqlite3VdbeCurrentAddr(v); + iContinue = sqlite3VdbeMakeLabel(v); + + /* Suppress duplicates for UNION, EXCEPT, and INTERSECT + */ + if( regPrev ){ + int j1, j2; + j1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev); + j2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iMem, regPrev+1, pIn->nMem, + (char*)pKeyInfo, p4type); + sqlite3VdbeAddOp3(v, OP_Jump, j2+2, iContinue, j2+2); + sqlite3VdbeJumpHere(v, j1); + sqlite3ExprCodeCopy(pParse, pIn->iMem, regPrev+1, pIn->nMem); + sqlite3VdbeAddOp2(v, OP_Integer, 1, regPrev); + } + if( pParse->db->mallocFailed ) return 0; + + /* Suppress the the first OFFSET entries if there is an OFFSET clause + */ + codeOffset(v, p, iContinue); + + switch( pDest->eDest ){ + /* Store the result as data using a unique key. + */ + case SRT_Table: + case SRT_EphemTab: { + int r1 = sqlite3GetTempReg(pParse); + int r2 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iMem, pIn->nMem, r1); + sqlite3VdbeAddOp2(v, OP_NewRowid, pDest->iParm, r2); + sqlite3VdbeAddOp3(v, OP_Insert, pDest->iParm, r1, r2); + sqlite3VdbeChangeP5(v, OPFLAG_APPEND); + sqlite3ReleaseTempReg(pParse, r2); + sqlite3ReleaseTempReg(pParse, r1); + break; + } + +#ifndef SQLITE_OMIT_SUBQUERY + /* If we are creating a set for an "expr IN (SELECT ...)" construct, + ** then there should be a single item on the stack. Write this + ** item into the set table with bogus data. + */ + case SRT_Set: { + int r1; + assert( pIn->nMem==1 ); + p->affinity = + sqlite3CompareAffinity(p->pEList->a[0].pExpr, pDest->affinity); + r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iMem, 1, r1, &p->affinity, 1); + sqlite3ExprCacheAffinityChange(pParse, pIn->iMem, 1); + sqlite3VdbeAddOp2(v, OP_IdxInsert, pDest->iParm, r1); + sqlite3ReleaseTempReg(pParse, r1); + break; + } + +#if 0 /* Never occurs on an ORDER BY query */ + /* If any row exist in the result set, record that fact and abort. + */ + case SRT_Exists: { + sqlite3VdbeAddOp2(v, OP_Integer, 1, pDest->iParm); + /* The LIMIT clause will terminate the loop for us */ + break; + } +#endif + + /* 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_Mem: { + assert( pIn->nMem==1 ); + sqlite3ExprCodeMove(pParse, pIn->iMem, pDest->iParm, 1); + /* The LIMIT clause will jump out of the loop for us */ + break; + } +#endif /* #ifndef SQLITE_OMIT_SUBQUERY */ + + /* Send the data to the callback function or to a subroutine. In the + ** case of a subroutine, the subroutine itself is responsible for + ** popping the data from the stack. + */ + case SRT_Coroutine: { + if( pDest->iMem==0 ){ + pDest->iMem = sqlite3GetTempRange(pParse, pIn->nMem); + pDest->nMem = pIn->nMem; + } + sqlite3ExprCodeMove(pParse, pIn->iMem, pDest->iMem, pDest->nMem); + sqlite3VdbeAddOp1(v, OP_Yield, pDest->iParm); + break; + } + + case SRT_Callback: { + sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iMem, pIn->nMem); + sqlite3ExprCacheAffinityChange(pParse, pIn->iMem, pIn->nMem); + break; + } + +#if !defined(SQLITE_OMIT_TRIGGER) + /* Discard the results. This is used for SELECT statements inside + ** the body of a TRIGGER. The purpose of such selects is to call + ** user-defined functions that have side effects. We do not care + ** about the actual results of the select. + */ + default: { + break; + } +#endif + } + + /* Jump to the end of the loop if the LIMIT is reached. + */ + if( p->iLimit ){ + sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1); + sqlite3VdbeAddOp2(v, OP_IfZero, p->iLimit, iBreak); + } + + /* Generate the subroutine return + */ + sqlite3VdbeResolveLabel(v, iContinue); + sqlite3VdbeAddOp1(v, OP_Return, regReturn); + + return addr; +} + +/* +** Alternative compound select code generator for cases when there +** is an ORDER BY clause. +** +** We assume a query of the following form: +** +** <selectA> <operator> <selectB> ORDER BY <orderbylist> +** +** <operator> is one of UNION ALL, UNION, EXCEPT, or INTERSECT. The idea +** is to code both <selectA> and <selectB> with the ORDER BY clause as +** co-routines. Then run the co-routines in parallel and merge the results +** into the output. In addition to the two coroutines (called selectA and +** selectB) there are 7 subroutines: +** +** outA: Move the output of the selectA coroutine into the output +** of the compound query. +** +** outB: Move the output of the selectB coroutine into the output +** of the compound query. (Only generated for UNION and +** UNION ALL. EXCEPT and INSERTSECT never output a row that +** appears only in B.) +** +** AltB: Called when there is data from both coroutines and A<B. +** +** AeqB: Called when there is data from both coroutines and A==B. +** +** AgtB: Called when there is data from both coroutines and A>B. +** +** EofA: Called when data is exhausted from selectA. +** +** EofB: Called when data is exhausted from selectB. +** +** The implementation of the latter five subroutines depend on which +** <operator> is used: +** +** +** UNION ALL UNION EXCEPT INTERSECT +** ------------- ----------------- -------------- ----------------- +** AltB: outA, nextA outA, nextA outA, nextA nextA +** +** AeqB: outA, nextA nextA nextA outA, nextA +** +** AgtB: outB, nextB outB, nextB nextB nextB +** +** EofA: outB, nextB outB, nextB halt halt +** +** EofB: outA, nextA outA, nextA outA, nextA halt +** +** In the AltB, AeqB, and AgtB subroutines, an EOF on A following nextA +** causes an immediate jump to EofA and an EOF on B following nextB causes +** an immediate jump to EofB. Within EofA and EofB, and EOF on entry or +** following nextX causes a jump to the end of the select processing. +** +** Duplicate removal in the UNION, EXCEPT, and INTERSECT cases is handled +** within the output subroutine. The regPrev register set holds the previously +** output value. A comparison is made against this value and the output +** is skipped if the next results would be the same as the previous. +** +** The implementation plan is to implement the two coroutines and seven +** subroutines first, then put the control logic at the bottom. Like this: +** +** goto Init +** coA: coroutine for left query (A) +** coB: coroutine for right query (B) +** outA: output one row of A +** outB: output one row of B (UNION and UNION ALL only) +** EofA: ... +** EofB: ... +** AltB: ... +** AeqB: ... +** AgtB: ... +** Init: initialize coroutine registers +** yield coA +** if eof(A) goto EofA +** yield coB +** if eof(B) goto EofB +** Cmpr: Compare A, B +** Jump AltB, AeqB, AgtB +** End: ... +** +** We call AltB, AeqB, AgtB, EofA, and EofB "subroutines" but they are not +** actually called using Gosub and they do not Return. EofA and EofB loop +** until all data is exhausted then jump to the "end" labe. AltB, AeqB, +** and AgtB jump to either L2 or to one of EofA or EofB. +*/ +#ifndef SQLITE_OMIT_COMPOUND_SELECT +static int multiSelectOrderBy( + Parse *pParse, /* Parsing context */ + Select *p, /* The right-most of SELECTs to be coded */ + SelectDest *pDest /* What to do with query results */ +){ + int i, j; /* Loop counters */ + Select *pPrior; /* Another SELECT immediately to our left */ + Vdbe *v; /* Generate code to this VDBE */ + SelectDest destA; /* Destination for coroutine A */ + SelectDest destB; /* Destination for coroutine B */ + int regAddrA; /* Address register for select-A coroutine */ + int regEofA; /* Flag to indicate when select-A is complete */ + int regAddrB; /* Address register for select-B coroutine */ + int regEofB; /* Flag to indicate when select-B is complete */ + int addrSelectA; /* Address of the select-A coroutine */ + int addrSelectB; /* Address of the select-B coroutine */ + int regOutA; /* Address register for the output-A subroutine */ + int regOutB; /* Address register for the output-B subroutine */ + int addrOutA; /* Address of the output-A subroutine */ + int addrOutB; /* Address of the output-B subroutine */ + int addrEofA; /* Address of the select-A-exhausted subroutine */ + int addrEofB; /* Address of the select-B-exhausted subroutine */ + int addrAltB; /* Address of the A<B subroutine */ + int addrAeqB; /* Address of the A==B subroutine */ + int addrAgtB; /* Address of the A>B subroutine */ + int regLimitA; /* Limit register for select-A */ + int regLimitB; /* Limit register for select-A */ + int regPrev; /* A range of registers to hold previous output */ + int savedLimit; /* Saved value of p->iLimit */ + int savedOffset; /* Saved value of p->iOffset */ + int labelCmpr; /* Label for the start of the merge algorithm */ + int labelEnd; /* Label for the end of the overall SELECT stmt */ + int j1; /* Jump instructions that get retargetted */ + int op; /* One of TK_ALL, TK_UNION, TK_EXCEPT, TK_INTERSECT */ + KeyInfo *pKeyDup; /* Comparison information for duplicate removal */ + KeyInfo *pKeyMerge; /* Comparison information for merging rows */ + sqlite3 *db; /* Database connection */ + ExprList *pOrderBy; /* The ORDER BY clause */ + int nOrderBy; /* Number of terms in the ORDER BY clause */ + int *aPermute; /* Mapping from ORDER BY terms to result set columns */ + u8 NotUsed; /* Dummy variables */ + + assert( p->pOrderBy!=0 ); + db = pParse->db; + v = pParse->pVdbe; + if( v==0 ) return SQLITE_NOMEM; + labelEnd = sqlite3VdbeMakeLabel(v); + labelCmpr = sqlite3VdbeMakeLabel(v); + + + /* Patch up the ORDER BY clause + */ + op = p->op; + pPrior = p->pPrior; + assert( pPrior->pOrderBy==0 ); + pOrderBy = p->pOrderBy; + assert( pOrderBy ); + if( processCompoundOrderBy(pParse, p) ){ + return SQLITE_ERROR; + } + nOrderBy = pOrderBy->nExpr; + + /* For operators other than UNION ALL we have to make sure that + ** the ORDER BY clause covers every term of the result set. Add + ** terms to the ORDER BY clause as necessary. + */ + if( op!=TK_ALL ){ + for(i=1; db->mallocFailed==0 && i<=p->pEList->nExpr; i++){ + for(j=0; j<nOrderBy; j++){ + Expr *pTerm = pOrderBy->a[j].pExpr; + assert( pTerm->op==TK_INTEGER ); + assert( (pTerm->flags & EP_IntValue)!=0 ); + if( pTerm->iTable==i ) break; + } + if( j==nOrderBy ){ + Expr *pNew = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, 0); + if( pNew==0 ) return SQLITE_NOMEM; + pNew->flags |= EP_IntValue; + pNew->iTable = i; + pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew, 0); + nOrderBy++; + } + } + } + + /* Compute the comparison permutation and keyinfo that is used with + ** the permutation in order to comparisons to determine if the next + ** row of results comes from selectA or selectB. Also add explicit + ** collations to the ORDER BY clause terms so that when the subqueries + ** to the right and the left are evaluated, they use the correct + ** collation. + */ + aPermute = sqlite3DbMallocRaw(db, sizeof(int)*nOrderBy); + if( aPermute ){ + for(i=0; i<nOrderBy; i++){ + Expr *pTerm = pOrderBy->a[i].pExpr; + assert( pTerm->op==TK_INTEGER ); + assert( (pTerm->flags & EP_IntValue)!=0 ); + aPermute[i] = pTerm->iTable-1; + assert( aPermute[i]>=0 && aPermute[i]<p->pEList->nExpr ); + } + pKeyMerge = + sqlite3DbMallocRaw(db, sizeof(*pKeyMerge)+nOrderBy*(sizeof(CollSeq*)+1)); + if( pKeyMerge ){ + pKeyMerge->aSortOrder = (u8*)&pKeyMerge->aColl[nOrderBy]; + pKeyMerge->nField = nOrderBy; + pKeyMerge->enc = ENC(db); + for(i=0; i<nOrderBy; i++){ + CollSeq *pColl; + Expr *pTerm = pOrderBy->a[i].pExpr; + if( pTerm->flags & EP_ExpCollate ){ + pColl = pTerm->pColl; + }else{ + pColl = multiSelectCollSeq(pParse, p, aPermute[i]); + pTerm->flags |= EP_ExpCollate; + pTerm->pColl = pColl; + } + pKeyMerge->aColl[i] = pColl; + pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder; + } + } + }else{ + pKeyMerge = 0; + } + + /* Reattach the ORDER BY clause to the query. + */ + p->pOrderBy = pOrderBy; + pPrior->pOrderBy = sqlite3ExprListDup(pParse->db, pOrderBy); + + /* Allocate a range of temporary registers and the KeyInfo needed + ** for the logic that removes duplicate result rows when the + ** operator is UNION, EXCEPT, or INTERSECT (but not UNION ALL). + */ + if( op==TK_ALL ){ + regPrev = 0; + }else{ + int nExpr = p->pEList->nExpr; + assert( nOrderBy>=nExpr ); + regPrev = sqlite3GetTempRange(pParse, nExpr+1); + sqlite3VdbeAddOp2(v, OP_Integer, 0, regPrev); + pKeyDup = sqlite3DbMallocZero(db, + sizeof(*pKeyDup) + nExpr*(sizeof(CollSeq*)+1) ); + if( pKeyDup ){ + pKeyDup->aSortOrder = (u8*)&pKeyDup->aColl[nExpr]; + pKeyDup->nField = nExpr; + pKeyDup->enc = ENC(db); + for(i=0; i<nExpr; i++){ + pKeyDup->aColl[i] = multiSelectCollSeq(pParse, p, i); + pKeyDup->aSortOrder[i] = 0; + } + } + } + + /* Separate the left and the right query from one another + */ + p->pPrior = 0; + pPrior->pRightmost = 0; + processOrderGroupBy(pParse, p, p->pOrderBy, 1, &NotUsed); + if( pPrior->pPrior==0 ){ + processOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, 1, &NotUsed); + } + + /* Compute the limit registers */ + computeLimitRegisters(pParse, p, labelEnd); + if( p->iLimit && op==TK_ALL ){ + regLimitA = ++pParse->nMem; + regLimitB = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Copy, p->iOffset ? p->iOffset+1 : p->iLimit, + regLimitA); + sqlite3VdbeAddOp2(v, OP_Copy, regLimitA, regLimitB); + }else{ + regLimitA = regLimitB = 0; + } + sqlite3ExprDelete(db, p->pLimit); + p->pLimit = 0; + sqlite3ExprDelete(db, p->pOffset); + p->pOffset = 0; + + regAddrA = ++pParse->nMem; + regEofA = ++pParse->nMem; + regAddrB = ++pParse->nMem; + regEofB = ++pParse->nMem; + regOutA = ++pParse->nMem; + regOutB = ++pParse->nMem; + sqlite3SelectDestInit(&destA, SRT_Coroutine, regAddrA); + sqlite3SelectDestInit(&destB, SRT_Coroutine, regAddrB); + + /* Jump past the various subroutines and coroutines to the main + ** merge loop + */ + j1 = sqlite3VdbeAddOp0(v, OP_Goto); + addrSelectA = sqlite3VdbeCurrentAddr(v); + + + /* Generate a coroutine to evaluate the SELECT statement to the + ** left of the compound operator - the "A" select. + */ + VdbeNoopComment((v, "Begin coroutine for left SELECT")); + pPrior->iLimit = regLimitA; + sqlite3Select(pParse, pPrior, &destA, 0, 0, 0); + sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofA); + sqlite3VdbeAddOp1(v, OP_Yield, regAddrA); + VdbeNoopComment((v, "End coroutine for left SELECT")); + + /* Generate a coroutine to evaluate the SELECT statement on + ** the right - the "B" select + */ + addrSelectB = sqlite3VdbeCurrentAddr(v); + VdbeNoopComment((v, "Begin coroutine for right SELECT")); + savedLimit = p->iLimit; + savedOffset = p->iOffset; + p->iLimit = regLimitB; + p->iOffset = 0; + sqlite3Select(pParse, p, &destB, 0, 0, 0); + p->iLimit = savedLimit; + p->iOffset = savedOffset; + sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofB); + sqlite3VdbeAddOp1(v, OP_Yield, regAddrB); + VdbeNoopComment((v, "End coroutine for right SELECT")); + + /* Generate a subroutine that outputs the current row of the A + ** select as the next output row of the compound select. + */ + VdbeNoopComment((v, "Output routine for A")); + addrOutA = generateOutputSubroutine(pParse, + p, &destA, pDest, regOutA, + regPrev, pKeyDup, P4_KEYINFO_HANDOFF, labelEnd); + + /* Generate a subroutine that outputs the current row of the B + ** select as the next output row of the compound select. + */ + if( op==TK_ALL || op==TK_UNION ){ + VdbeNoopComment((v, "Output routine for B")); + addrOutB = generateOutputSubroutine(pParse, + p, &destB, pDest, regOutB, + regPrev, pKeyDup, P4_KEYINFO_STATIC, labelEnd); + } + + /* Generate a subroutine to run when the results from select A + ** are exhausted and only data in select B remains. + */ + VdbeNoopComment((v, "eof-A subroutine")); + if( op==TK_EXCEPT || op==TK_INTERSECT ){ + addrEofA = sqlite3VdbeAddOp2(v, OP_Goto, 0, labelEnd); + }else{ + addrEofA = sqlite3VdbeAddOp2(v, OP_If, regEofB, labelEnd); + sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); + sqlite3VdbeAddOp1(v, OP_Yield, regAddrB); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofA); + } + + /* Generate a subroutine to run when the results from select B + ** are exhausted and only data in select A remains. + */ + if( op==TK_INTERSECT ){ + addrEofB = addrEofA; + }else{ + VdbeNoopComment((v, "eof-B subroutine")); + addrEofB = sqlite3VdbeAddOp2(v, OP_If, regEofA, labelEnd); + sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); + sqlite3VdbeAddOp1(v, OP_Yield, regAddrA); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofB); + } + + /* Generate code to handle the case of A<B + */ + VdbeNoopComment((v, "A-lt-B subroutine")); + addrAltB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); + sqlite3VdbeAddOp1(v, OP_Yield, regAddrA); + sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA); + sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr); + + /* Generate code to handle the case of A==B + */ + if( op==TK_ALL ){ + addrAeqB = addrAltB; + }else if( op==TK_INTERSECT ){ + addrAeqB = addrAltB; + addrAltB++; + }else{ + VdbeNoopComment((v, "A-eq-B subroutine")); + addrAeqB = + sqlite3VdbeAddOp1(v, OP_Yield, regAddrA); + sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA); + sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr); + } + + /* Generate code to handle the case of A>B + */ + VdbeNoopComment((v, "A-gt-B subroutine")); + addrAgtB = sqlite3VdbeCurrentAddr(v); + if( op==TK_ALL || op==TK_UNION ){ + sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); + } + sqlite3VdbeAddOp1(v, OP_Yield, regAddrB); + sqlite3VdbeAddOp2(v, OP_If, regEofB, addrEofB); + sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr); + + /* This code runs once to initialize everything. + */ + sqlite3VdbeJumpHere(v, j1); + sqlite3VdbeAddOp2(v, OP_Integer, 0, regEofA); + sqlite3VdbeAddOp2(v, OP_Integer, 0, regEofB); + sqlite3VdbeAddOp2(v, OP_Gosub, regAddrA, addrSelectA); + sqlite3VdbeAddOp2(v, OP_Gosub, regAddrB, addrSelectB); + sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA); + sqlite3VdbeAddOp2(v, OP_If, regEofB, addrEofB); + + /* Implement the main merge loop + */ + sqlite3VdbeResolveLabel(v, labelCmpr); + sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); + sqlite3VdbeAddOp4(v, OP_Compare, destA.iMem, destB.iMem, nOrderBy, + (char*)pKeyMerge, P4_KEYINFO_HANDOFF); + sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); + + /* Release temporary registers + */ + if( regPrev ){ + sqlite3ReleaseTempRange(pParse, regPrev, nOrderBy+1); + } + + /* Jump to the this point in order to terminate the query. + */ + sqlite3VdbeResolveLabel(v, labelEnd); + + /* Set the number of output columns + */ + if( pDest->eDest==SRT_Callback ){ + Select *pFirst = pPrior; + while( pFirst->pPrior ) pFirst = pFirst->pPrior; + generateColumnNames(pParse, 0, pFirst->pEList); + } + + /* Reassembly the compound query so that it will be freed correctly + ** by the calling function */ + if( p->pPrior ){ + sqlite3SelectDelete(db, p->pPrior); + } + p->pPrior = pPrior; + + /*** TBD: Insert subroutine calls to close cursors on incomplete + **** subqueries ****/ + return SQLITE_OK; +} +#endif + +#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) +/* Forward Declarations */ +static void substExprList(sqlite3*, ExprList*, int, ExprList*); +static void substSelect(sqlite3*, Select *, int, ExprList *); + +/* +** Scan through the expression pExpr. Replace every reference to +** a column in table number iTable with a copy of the iColumn-th +** entry in pEList. (But leave references to the ROWID column +** unchanged.) +** +** This routine is part of the flattening procedure. A subquery +** whose result set is defined by pEList appears as entry in the +** FROM clause of a SELECT such that the VDBE cursor assigned to that +** FORM clause entry is iTable. This routine make the necessary +** changes to pExpr so that it refers directly to the source table +** of the subquery rather the result set of the subquery. +*/ +static void substExpr( + sqlite3 *db, /* Report malloc errors to this connection */ + Expr *pExpr, /* Expr in which substitution occurs */ + int iTable, /* Table to be substituted */ + ExprList *pEList /* Substitute expressions */ +){ + if( pExpr==0 ) return; + if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){ + if( pExpr->iColumn<0 ){ + pExpr->op = TK_NULL; + }else{ + Expr *pNew; + assert( pEList!=0 && pExpr->iColumn<pEList->nExpr ); + assert( pExpr->pLeft==0 && pExpr->pRight==0 && pExpr->pList==0 ); + pNew = pEList->a[pExpr->iColumn].pExpr; + assert( pNew!=0 ); + pExpr->op = pNew->op; + assert( pExpr->pLeft==0 ); + pExpr->pLeft = sqlite3ExprDup(db, pNew->pLeft); + assert( pExpr->pRight==0 ); + pExpr->pRight = sqlite3ExprDup(db, pNew->pRight); + assert( pExpr->pList==0 ); + pExpr->pList = sqlite3ExprListDup(db, pNew->pList); + pExpr->iTable = pNew->iTable; + pExpr->pTab = pNew->pTab; + pExpr->iColumn = pNew->iColumn; + pExpr->iAgg = pNew->iAgg; + sqlite3TokenCopy(db, &pExpr->token, &pNew->token); + sqlite3TokenCopy(db, &pExpr->span, &pNew->span); + pExpr->pSelect = sqlite3SelectDup(db, pNew->pSelect); + pExpr->flags = pNew->flags; + } + }else{ + substExpr(db, pExpr->pLeft, iTable, pEList); + substExpr(db, pExpr->pRight, iTable, pEList); + substSelect(db, pExpr->pSelect, iTable, pEList); + substExprList(db, pExpr->pList, iTable, pEList); + } +} +static void substExprList( + sqlite3 *db, /* Report malloc errors here */ + ExprList *pList, /* List to scan and in which to make substitutes */ + int iTable, /* Table to be substituted */ + ExprList *pEList /* Substitute values */ +){ + int i; + if( pList==0 ) return; + for(i=0; i<pList->nExpr; i++){ + substExpr(db, pList->a[i].pExpr, iTable, pEList); + } +} +static void substSelect( + sqlite3 *db, /* Report malloc errors here */ + Select *p, /* SELECT statement in which to make substitutions */ + int iTable, /* Table to be replaced */ + ExprList *pEList /* Substitute values */ +){ + if( !p ) return; + substExprList(db, p->pEList, iTable, pEList); + substExprList(db, p->pGroupBy, iTable, pEList); + substExprList(db, p->pOrderBy, iTable, pEList); + substExpr(db, p->pHaving, iTable, pEList); + substExpr(db, p->pWhere, iTable, pEList); + substSelect(db, p->pPrior, iTable, pEList); +} +#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ + +#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) +/* +** This routine attempts to flatten subqueries in order to speed +** execution. It returns 1 if it makes changes and 0 if no flattening +** occurs. +** +** To understand the concept of flattening, consider the following +** query: +** +** SELECT a FROM (SELECT x+y AS a FROM t1 WHERE z<100) WHERE a>5 +** +** The default way of implementing this query is to execute the +** subquery first and store the results in a temporary table, then +** run the outer query on that temporary table. This requires two +** passes over the data. Furthermore, because the temporary table +** has no indices, the WHERE clause on the outer query cannot be +** optimized. +** +** This routine attempts to rewrite queries such as the above into +** a single flat select, like this: +** +** SELECT x+y AS a FROM t1 WHERE z<100 AND a>5 +** +** The code generated for this simpification gives the same result +** but only has to scan the data once. And because indices might +** exist on the table t1, a complete scan of the data might be +** avoided. +** +** Flattening is only attempted if all of the following are true: +** +** (1) The subquery and the outer query do not both use aggregates. +** +** (2) The subquery is not an aggregate or the outer query is not a join. +** +** (3) The subquery is not the right operand of a left outer join, or +** the subquery is not itself a join. (Ticket #306) +** +** (4) The subquery is not DISTINCT or the outer query is not a join. +** +** (5) The subquery is not DISTINCT or the outer query does not use +** aggregates. +** +** (6) The subquery does not use aggregates or the outer query is not +** DISTINCT. +** +** (7) The subquery has a FROM clause. +** +** (8) The subquery does not use LIMIT or the outer query is not a join. +** +** (9) The subquery does not use LIMIT or the outer query does not use +** aggregates. +** +** (10) The subquery does not use aggregates or the outer query does not +** use LIMIT. +** +** (11) The subquery and the outer query do not both have ORDER BY clauses. +** +** (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 +** +** (15) The outer query is not part of a compound select or the +** subquery does not have both an ORDER BY and a LIMIT clause. +** (See ticket #2339) +** +** (16) The outer query is not an aggregate or the subquery does +** not contain ORDER BY. (Ticket #2942) This used to not matter +** until we introduced the group_concat() function. +** +** (17) The sub-query is not a compound select, or it is a UNION ALL +** compound clause made up entirely of non-aggregate queries, and +** the parent query: +** +** * is not itself part of a compound select, +** * is not an aggregate or DISTINCT query, and +** * has no other tables or sub-selects in the FROM clause. +** +** The parent and sub-query may contain WHERE clauses. Subject to +** rules (11), (13) and (14), they may also contain ORDER BY, +** LIMIT and OFFSET clauses. +** +** (18) If the sub-query is a compound select, then all terms of the +** ORDER by clause of the parent must be simple references to +** columns of the sub-query. +** +** 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. +** +** If flattening is not attempted, this routine is a no-op and returns 0. +** If flattening is attempted this routine returns 1. +** +** All of the expression analysis must occur on both the outer query and +** the subquery before this routine runs. +*/ +static int flattenSubquery( + Parse *pParse, /* Parsing context */ + Select *p, /* The parent or outer SELECT statement */ + int iFrom, /* Index in p->pSrc->a[] of the inner subquery */ + int isAgg, /* True if outer SELECT uses aggregate functions */ + int subqueryIsAgg /* True if the subquery uses aggregate functions */ +){ + const char *zSavedAuthContext = pParse->zAuthContext; + Select *pParent; + Select *pSub; /* The inner query or "subquery" */ + Select *pSub1; /* Pointer to the rightmost select in sub-query */ + SrcList *pSrc; /* The FROM clause of the outer query */ + SrcList *pSubSrc; /* The FROM clause of the subquery */ + ExprList *pList; /* The result set of the outer query */ + int iParent; /* VDBE cursor number of the pSub result set temp table */ + int i; /* Loop counter */ + Expr *pWhere; /* The WHERE clause */ + struct SrcList_item *pSubitem; /* The subquery */ + sqlite3 *db = pParse->db; + + /* Check to see if flattening is permitted. Return 0 if not. + */ + if( p==0 ) return 0; + pSrc = p->pSrc; + assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc ); + pSubitem = &pSrc->a[iFrom]; + iParent = pSubitem->iCursor; + pSub = pSubitem->pSelect; + assert( pSub!=0 ); + if( isAgg && subqueryIsAgg ) return 0; /* Restriction (1) */ + if( subqueryIsAgg && pSrc->nSrc>1 ) return 0; /* Restriction (2) */ + pSubSrc = pSub->pSrc; + assert( pSubSrc ); + /* 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( p->pRightmost && pSub->pLimit && pSub->pOrderBy ){ + return 0; /* Restriction (15) */ + } + 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( isAgg && pSub->pOrderBy ) return 0; /* Restriction (16) */ + + /* 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 + ** is not allowed: + ** + ** t1 LEFT OUTER JOIN (t2 JOIN t3) + ** + ** If we flatten the above, we would get + ** + ** (t1 LEFT OUTER JOIN t2) JOIN t3 + ** + ** which is not at all the same thing. + */ + if( pSubSrc->nSrc>1 && (pSubitem->jointype & JT_OUTER)!=0 ){ + return 0; + } + + /* Restriction 12: If the subquery is the right operand of a left outer + ** join, make sure the subquery has no WHERE clause. + ** An examples of why this is not allowed: + ** + ** t1 LEFT OUTER JOIN (SELECT * FROM t2 WHERE t2.x>0) + ** + ** If we flatten the above, we would get + ** + ** (t1 LEFT OUTER JOIN t2) WHERE t2.x>0 + ** + ** But the t2.x>0 test will always fail on a NULL row of t2, which + ** effectively converts the OUTER JOIN into an INNER JOIN. + */ + if( (pSubitem->jointype & JT_OUTER)!=0 && pSub->pWhere!=0 ){ + return 0; + } + + /* Restriction 17: If the sub-query is a compound SELECT, then it must + ** use only the UNION ALL operator. And none of the simple select queries + ** that make up the compound SELECT are allowed to be aggregate or distinct + ** queries. + */ + if( pSub->pPrior ){ + if( p->pPrior || isAgg || p->isDistinct || pSrc->nSrc!=1 ){ + return 0; + } + for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){ + if( pSub1->isAgg || pSub1->isDistinct + || (pSub1->pPrior && pSub1->op!=TK_ALL) + || !pSub1->pSrc || pSub1->pSrc->nSrc!=1 + ){ + return 0; + } + } + + /* Restriction 18. */ + if( p->pOrderBy ){ + int ii; + for(ii=0; ii<p->pOrderBy->nExpr; ii++){ + Expr *pExpr = p->pOrderBy->a[ii].pExpr; + if( pExpr->op!=TK_COLUMN || pExpr->iTable!=iParent ){ + return 0; + } + } + } + } + + pParse->zAuthContext = pSubitem->zName; + sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0); + pParse->zAuthContext = zSavedAuthContext; + + /* If the sub-query is a compound SELECT statement, then it must be + ** a UNION ALL and the parent query must be of the form: + ** + ** SELECT <expr-list> FROM (<sub-query>) <where-clause> + ** + ** followed by any ORDER BY, LIMIT and/or OFFSET clauses. This block + ** creates N copies of the parent query without any ORDER BY, LIMIT or + ** OFFSET clauses and joins them to the left-hand-side of the original + ** using UNION ALL operators. In this case N is the number of simple + ** select statements in the compound sub-query. + */ + for(pSub=pSub->pPrior; pSub; pSub=pSub->pPrior){ + Select *pNew; + ExprList *pOrderBy = p->pOrderBy; + Expr *pLimit = p->pLimit; + Expr *pOffset = p->pOffset; + Select *pPrior = p->pPrior; + p->pOrderBy = 0; + p->pSrc = 0; + p->pPrior = 0; + p->pLimit = 0; + pNew = sqlite3SelectDup(db, p); + pNew->pPrior = pPrior; + p->pPrior = pNew; + p->pOrderBy = pOrderBy; + p->op = TK_ALL; + p->pSrc = pSrc; + p->pLimit = pLimit; + p->pOffset = pOffset; + p->pRightmost = 0; + pNew->pRightmost = 0; + } + + /* If we reach this point, it means flattening is permitted for the + ** iFrom-th entry of the FROM clause in the outer query. + */ + pSub = pSub1 = pSubitem->pSelect; + for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){ + int nSubSrc = pSubSrc->nSrc; + int jointype = 0; + pSubSrc = pSub->pSrc; + pSrc = pParent->pSrc; + + /* Move all of the FROM elements of the subquery into the + ** the FROM clause of the outer query. Before doing this, remember + ** the cursor number for the original outer query FROM element in + ** iParent. The iParent cursor will never be used. Subsequent code + ** will scan expressions looking for iParent references and replace + ** those references with expressions that resolve to the subquery FROM + ** elements we are now copying in. + */ + if( pSrc ){ + pSubitem = &pSrc->a[iFrom]; + nSubSrc = pSubSrc->nSrc; + jointype = pSubitem->jointype; + sqlite3DeleteTable(pSubitem->pTab); + sqlite3DbFree(db, pSubitem->zDatabase); + sqlite3DbFree(db, pSubitem->zName); + sqlite3DbFree(db, pSubitem->zAlias); + pSubitem->pTab = 0; + pSubitem->zDatabase = 0; + pSubitem->zName = 0; + pSubitem->zAlias = 0; + } + if( nSubSrc!=1 || !pSrc ){ + int extra = nSubSrc - 1; + for(i=(pSrc?1:0); i<nSubSrc; i++){ + pSrc = sqlite3SrcListAppend(db, pSrc, 0, 0); + if( pSrc==0 ){ + pParent->pSrc = 0; + return 1; + } + } + pParent->pSrc = pSrc; + for(i=pSrc->nSrc-1; i-extra>=iFrom; i--){ + pSrc->a[i] = pSrc->a[i-extra]; + } + } + for(i=0; i<nSubSrc; i++){ + pSrc->a[i+iFrom] = pSubSrc->a[i]; + memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i])); + } + pSrc->a[iFrom].jointype = jointype; + + /* Now begin substituting subquery result set expressions for + ** references to the iParent in the outer query. + ** + ** Example: + ** + ** SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b; + ** \ \_____________ subquery __________/ / + ** \_____________________ outer query ______________________________/ + ** + ** We look at every expression in the outer query and every place we see + ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10". + */ + pList = pParent->pEList; + for(i=0; i<pList->nExpr; i++){ + Expr *pExpr; + if( pList->a[i].zName==0 && (pExpr = pList->a[i].pExpr)->span.z!=0 ){ + pList->a[i].zName = + sqlite3DbStrNDup(db, (char*)pExpr->span.z, pExpr->span.n); + } + } + substExprList(db, pParent->pEList, iParent, pSub->pEList); + if( isAgg ){ + substExprList(db, pParent->pGroupBy, iParent, pSub->pEList); + substExpr(db, pParent->pHaving, iParent, pSub->pEList); + } + if( pSub->pOrderBy ){ + assert( pParent->pOrderBy==0 ); + pParent->pOrderBy = pSub->pOrderBy; + pSub->pOrderBy = 0; + }else if( pParent->pOrderBy ){ + substExprList(db, pParent->pOrderBy, iParent, pSub->pEList); + } + if( pSub->pWhere ){ + pWhere = sqlite3ExprDup(db, pSub->pWhere); + }else{ + pWhere = 0; + } + if( subqueryIsAgg ){ + assert( pParent->pHaving==0 ); + pParent->pHaving = pParent->pWhere; + pParent->pWhere = pWhere; + substExpr(db, pParent->pHaving, iParent, pSub->pEList); + pParent->pHaving = sqlite3ExprAnd(db, pParent->pHaving, + sqlite3ExprDup(db, pSub->pHaving)); + assert( pParent->pGroupBy==0 ); + pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy); + }else{ + substExpr(db, pParent->pWhere, iParent, pSub->pEList); + pParent->pWhere = sqlite3ExprAnd(db, pParent->pWhere, pWhere); + } + + /* The flattened query is distinct if either the inner or the + ** outer query is distinct. + */ + pParent->isDistinct = pParent->isDistinct || pSub->isDistinct; + + /* + ** 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 ){ + pParent->pLimit = pSub->pLimit; + pSub->pLimit = 0; + } + } + + /* Finially, delete what is left of the subquery and return + ** success. + */ + sqlite3SelectDelete(db, pSub1); + + return 1; +} +#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ + +/* +** Analyze the SELECT statement passed as an argument to see if it +** is a min() or max() query. Return WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX if +** it is, or 0 otherwise. At present, a query is considered to be +** a min()/max() query if: +** +** 1. There is a single object in the FROM clause. +** +** 2. There is a single expression in the result set, and it is +** either min(x) or max(x), where x is a column reference. +*/ +static int minMaxQuery(Parse *pParse, Select *p){ + Expr *pExpr; + ExprList *pEList = p->pEList; + + if( pEList->nExpr!=1 ) return WHERE_ORDERBY_NORMAL; + pExpr = pEList->a[0].pExpr; + pEList = pExpr->pList; + if( pExpr->op!=TK_AGG_FUNCTION || pEList==0 || pEList->nExpr!=1 ) return 0; + if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return WHERE_ORDERBY_NORMAL; + if( pExpr->token.n!=3 ) return WHERE_ORDERBY_NORMAL; + if( sqlite3StrNICmp((char*)pExpr->token.z,"min",3)==0 ){ + return WHERE_ORDERBY_MIN; + }else if( sqlite3StrNICmp((char*)pExpr->token.z,"max",3)==0 ){ + return WHERE_ORDERBY_MAX; + } + return WHERE_ORDERBY_NORMAL; +} + +/* +** This routine resolves any names used in the result set of the +** supplied SELECT statement. If the SELECT statement being resolved +** is a sub-select, then pOuterNC is a pointer to the NameContext +** of the parent SELECT. +*/ +int sqlite3SelectResolve( + Parse *pParse, /* The parser context */ + Select *p, /* The SELECT statement being coded. */ + NameContext *pOuterNC /* The outer name context. May be NULL. */ +){ + ExprList *pEList; /* Result set. */ + int i; /* For-loop variable used in multiple places */ + NameContext sNC; /* Local name-context */ + ExprList *pGroupBy; /* The group by clause */ + + /* If this routine has run before, return immediately. */ + if( p->isResolved ){ + assert( !pOuterNC ); + return SQLITE_OK; + } + p->isResolved = 1; + + /* If there have already been errors, do nothing. */ + if( pParse->nErr>0 ){ + return SQLITE_ERROR; + } + + /* Prepare the select statement. This call will allocate all cursors + ** required to handle the tables and subqueries in the FROM clause. + */ + if( prepSelectStmt(pParse, p) ){ + return SQLITE_ERROR; + } + + /* Resolve the expressions in the LIMIT and OFFSET clauses. These + ** are not allowed to refer to any names, so pass an empty NameContext. + */ + memset(&sNC, 0, sizeof(sNC)); + sNC.pParse = pParse; + if( sqlite3ExprResolveNames(&sNC, p->pLimit) || + sqlite3ExprResolveNames(&sNC, p->pOffset) ){ + return SQLITE_ERROR; + } + + /* Set up the local name-context to pass to ExprResolveNames() to + ** resolve the expression-list. + */ + sNC.allowAgg = 1; + sNC.pSrcList = p->pSrc; + sNC.pNext = pOuterNC; + + /* Resolve names in the result set. */ + pEList = p->pEList; + if( !pEList ) return SQLITE_ERROR; + for(i=0; i<pEList->nExpr; i++){ + Expr *pX = pEList->a[i].pExpr; + if( sqlite3ExprResolveNames(&sNC, pX) ){ + return SQLITE_ERROR; + } + } + + /* If there are no aggregate functions in the result-set, and no GROUP BY + ** expression, do not allow aggregates in any of the other expressions. + */ + assert( !p->isAgg ); + pGroupBy = p->pGroupBy; + if( pGroupBy || sNC.hasAgg ){ + p->isAgg = 1; + }else{ + sNC.allowAgg = 0; + } + + /* If a HAVING clause is present, then there must be a GROUP BY clause. + */ + if( p->pHaving && !pGroupBy ){ + sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING"); + return SQLITE_ERROR; + } + + /* Add the expression list to the name-context before parsing the + ** other expressions in the SELECT statement. This is so that + ** expressions in the WHERE clause (etc.) can refer to expressions by + ** aliases in the result set. + ** + ** Minor point: If this is the case, then the expression will be + ** re-evaluated for each reference to it. + */ + sNC.pEList = p->pEList; + if( sqlite3ExprResolveNames(&sNC, p->pWhere) || + sqlite3ExprResolveNames(&sNC, p->pHaving) ){ + return SQLITE_ERROR; + } + if( p->pPrior==0 ){ + if( processOrderGroupBy(pParse, p, p->pOrderBy, 1, &sNC.hasAgg) ){ + return SQLITE_ERROR; + } + } + if( processOrderGroupBy(pParse, p, pGroupBy, 0, &sNC.hasAgg) ){ + return SQLITE_ERROR; + } + + if( pParse->db->mallocFailed ){ + return SQLITE_NOMEM; + } + + /* Make sure the GROUP BY clause does not contain aggregate functions. + */ + if( pGroupBy ){ + struct ExprList_item *pItem; + + for(i=0, pItem=pGroupBy->a; i<pGroupBy->nExpr; i++, pItem++){ + if( ExprHasProperty(pItem->pExpr, EP_Agg) ){ + sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in " + "the GROUP BY clause"); + return SQLITE_ERROR; + } + } + } + + /* If this is one SELECT of a compound, be sure to resolve names + ** in the other SELECTs. + */ + if( p->pPrior ){ + return sqlite3SelectResolve(pParse, p->pPrior, pOuterNC); + }else{ + return SQLITE_OK; + } +} + +/* +** Reset the aggregate accumulator. +** +** The aggregate accumulator is a set of memory cells that hold +** intermediate results while calculating an aggregate. This +** routine simply stores NULLs in all of those memory cells. +*/ +static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){ + Vdbe *v = pParse->pVdbe; + int i; + struct AggInfo_func *pFunc; + if( pAggInfo->nFunc+pAggInfo->nColumn==0 ){ + return; + } + for(i=0; i<pAggInfo->nColumn; i++){ + sqlite3VdbeAddOp2(v, OP_Null, 0, pAggInfo->aCol[i].iMem); + } + for(pFunc=pAggInfo->aFunc, i=0; i<pAggInfo->nFunc; i++, pFunc++){ + sqlite3VdbeAddOp2(v, OP_Null, 0, pFunc->iMem); + if( pFunc->iDistinct>=0 ){ + Expr *pE = pFunc->pExpr; + if( pE->pList==0 || pE->pList->nExpr!=1 ){ + sqlite3ErrorMsg(pParse, "DISTINCT in aggregate must be followed " + "by an expression"); + pFunc->iDistinct = -1; + }else{ + KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->pList); + sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 0, + (char*)pKeyInfo, P4_KEYINFO_HANDOFF); + } + } + } +} + +/* +** Invoke the OP_AggFinalize opcode for every aggregate function +** in the AggInfo structure. +*/ +static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){ + Vdbe *v = pParse->pVdbe; + int i; + struct AggInfo_func *pF; + for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){ + ExprList *pList = pF->pExpr->pList; + sqlite3VdbeAddOp4(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0, 0, + (void*)pF->pFunc, P4_FUNCDEF); + } +} + +/* +** Update the accumulator memory cells for an aggregate based on +** the current cursor position. +*/ +static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ + Vdbe *v = pParse->pVdbe; + int i; + struct AggInfo_func *pF; + struct AggInfo_col *pC; + + pAggInfo->directMode = 1; + for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){ + int nArg; + int addrNext = 0; + int regAgg; + ExprList *pList = pF->pExpr->pList; + if( pList ){ + nArg = pList->nExpr; + regAgg = sqlite3GetTempRange(pParse, nArg); + sqlite3ExprCodeExprList(pParse, pList, regAgg, 0); + }else{ + nArg = 0; + regAgg = 0; + } + if( pF->iDistinct>=0 ){ + addrNext = sqlite3VdbeMakeLabel(v); + assert( nArg==1 ); + codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg); + } + if( pF->pFunc->needCollSeq ){ + CollSeq *pColl = 0; + struct ExprList_item *pItem; + int j; + assert( pList!=0 ); /* pList!=0 if pF->pFunc->needCollSeq is true */ + for(j=0, pItem=pList->a; !pColl && j<nArg; j++, pItem++){ + pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr); + } + if( !pColl ){ + pColl = pParse->db->pDfltColl; + } + sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); + } + sqlite3VdbeAddOp4(v, OP_AggStep, 0, regAgg, pF->iMem, + (void*)pF->pFunc, P4_FUNCDEF); + sqlite3VdbeChangeP5(v, nArg); + sqlite3ReleaseTempRange(pParse, regAgg, nArg); + sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg); + if( addrNext ){ + sqlite3VdbeResolveLabel(v, addrNext); + } + } + for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){ + sqlite3ExprCode(pParse, pC->pExpr, pC->iMem); + } + pAggInfo->directMode = 0; +} + +/* +** Generate code for the given SELECT statement. +** +** The results are distributed in various ways depending on the +** contents of the SelectDest structure pointed to by argument pDest +** as follows: +** +** pDest->eDest Result +** ------------ ------------------------------------------- +** SRT_Callback Invoke the callback for each row of the result. +** +** SRT_Mem Store first result in memory cell pDest->iParm +** +** SRT_Set Store results as keys of table pDest->iParm. +** Apply the affinity pDest->affinity before storing them. +** +** SRT_Union Store results as a key in a temporary table pDest->iParm. +** +** SRT_Except Remove results from the temporary table pDest->iParm. +** +** SRT_Table Store results in temporary table pDest->iParm +** +** SRT_EphemTab Create an temporary table pDest->iParm and store +** the result there. The cursor is left open after +** returning. +** +** SRT_Coroutine Invoke a co-routine to compute a single row of +** the result +** +** SRT_Exists Store a 1 in memory cell pDest->iParm if the result +** set is not empty. +** +** SRT_Discard Throw the results away. +** +** See the selectInnerLoop() function for a canonical listing of the +** allowed values of eDest and their meanings. +** +** This routine returns the number of errors. If any errors are +** encountered, then an appropriate error message is left in +** pParse->zErrMsg. +** +** This routine does NOT free the Select structure passed in. The +** calling function needs to do that. +** +** The pParent, parentTab, and *pParentAgg fields are filled in if this +** SELECT is a subquery. This routine may try to combine this SELECT +** with its parent to form a single flat query. In so doing, it might +** change the parent query from a non-aggregate to an aggregate query. +** For that reason, the pParentAgg flag is passed as a pointer, so it +** can be changed. +** +** Example 1: The meaning of the pParent parameter. +** +** SELECT * FROM t1 JOIN (SELECT x, count(*) FROM t2) JOIN t3; +** \ \_______ subquery _______/ / +** \ / +** \____________________ outer query ___________________/ +** +** This routine is called for the outer query first. For that call, +** pParent will be NULL. During the processing of the outer query, this +** routine is called recursively to handle the subquery. For the recursive +** call, pParent will point to the outer query. Because the subquery is +** the second element in a three-way join, the parentTab parameter will +** be 1 (the 2nd value of a 0-indexed array.) +*/ +int sqlite3Select( + Parse *pParse, /* The parser context */ + Select *p, /* The SELECT statement being coded. */ + SelectDest *pDest, /* What to do with the query results */ + Select *pParent, /* Another SELECT for which this is a sub-query */ + int parentTab, /* Index in pParent->pSrc of this query */ + int *pParentAgg /* True if pParent uses aggregate functions */ +){ + int i, j; /* Loop counters */ + WhereInfo *pWInfo; /* Return from sqlite3WhereBegin() */ + Vdbe *v; /* The virtual machine under construction */ + int isAgg; /* True for select lists like "count(*)" */ + ExprList *pEList; /* List of columns to extract. */ + SrcList *pTabList; /* List of tables to select from */ + Expr *pWhere; /* The WHERE clause. May be NULL */ + ExprList *pOrderBy; /* The ORDER BY clause. May be NULL */ + ExprList *pGroupBy; /* The GROUP BY clause. May be NULL */ + Expr *pHaving; /* The HAVING clause. May be NULL */ + int isDistinct; /* True if the DISTINCT keyword is present */ + int distinct; /* Table to use for the distinct set */ + int rc = 1; /* Value to return from this function */ + int addrSortIndex; /* Address of an OP_OpenEphemeral instruction */ + AggInfo sAggInfo; /* Information used by aggregate queries */ + int iEnd; /* Address of the end of the query */ + sqlite3 *db; /* The database connection */ + + db = pParse->db; + if( p==0 || db->mallocFailed || pParse->nErr ){ + return 1; + } + if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; + memset(&sAggInfo, 0, sizeof(sAggInfo)); + + pOrderBy = p->pOrderBy; + if( IgnorableOrderby(pDest) ){ + p->pOrderBy = 0; + + /* In these cases the DISTINCT operator makes no difference to the + ** results, so remove it if it were specified. + */ + assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union || + pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard); + p->isDistinct = 0; + } + if( sqlite3SelectResolve(pParse, p, 0) ){ + goto select_end; + } + p->pOrderBy = pOrderBy; + + + /* Make local copies of the parameters for this query. + */ + pTabList = p->pSrc; + isAgg = p->isAgg; + pEList = p->pEList; + if( pEList==0 ) goto select_end; + + /* + ** Do not even attempt to generate any code if we have already seen + ** errors before this routine starts. + */ + if( pParse->nErr>0 ) goto select_end; + + /* ORDER BY is ignored for some destinations. + */ + if( IgnorableOrderby(pDest) ){ + pOrderBy = 0; + } + + /* Begin generating code. + */ + v = sqlite3GetVdbe(pParse); + if( v==0 ) goto select_end; + + /* Generate code for all sub-queries in the FROM clause + */ +#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) + for(i=0; !p->pPrior && i<pTabList->nSrc; i++){ + struct SrcList_item *pItem = &pTabList->a[i]; + SelectDest dest; + Select *pSub = pItem->pSelect; + int isAggSub; + char *zName = pItem->zName; + + if( pSub==0 || pItem->isPopulated ) continue; + if( zName!=0 ){ /* An sql view */ + const char *zSavedAuthContext = pParse->zAuthContext; + pParse->zAuthContext = zName; + rc = sqlite3SelectResolve(pParse, pSub, 0); + pParse->zAuthContext = zSavedAuthContext; + if( rc ){ + goto select_end; + } + } + + /* Increment Parse.nHeight by the height of the largest expression + ** tree refered to by this, the parent select. The child select + ** may contain expression trees of at most + ** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit + ** more conservative than necessary, but much easier than enforcing + ** an exact limit. + */ + pParse->nHeight += sqlite3SelectExprHeight(p); + + /* Check to see if the subquery can be absorbed into the parent. */ + isAggSub = pSub->isAgg; + if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){ + if( isAggSub ){ + p->isAgg = isAgg = 1; + } + i = -1; + }else{ + sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); + sqlite3Select(pParse, pSub, &dest, p, i, &isAgg); + } + if( pParse->nErr || db->mallocFailed ){ + goto select_end; + } + pParse->nHeight -= sqlite3SelectExprHeight(p); + pTabList = p->pSrc; + if( !IgnorableOrderby(pDest) ){ + pOrderBy = p->pOrderBy; + } + } + pEList = p->pEList; +#endif + pWhere = p->pWhere; + pGroupBy = p->pGroupBy; + pHaving = p->pHaving; + isDistinct = p->isDistinct; + +#ifndef SQLITE_OMIT_COMPOUND_SELECT + /* If there is are a sequence of queries, do the earlier ones first. + */ + if( p->pPrior ){ + if( p->pRightmost==0 ){ + Select *pLoop, *pRight = 0; + int cnt = 0; + int mxSelect; + for(pLoop=p; pLoop; pLoop=pLoop->pPrior, cnt++){ + pLoop->pRightmost = p; + pLoop->pNext = pRight; + pRight = pLoop; + } + mxSelect = db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT]; + if( mxSelect && cnt>mxSelect ){ + sqlite3ErrorMsg(pParse, "too many terms in compound SELECT"); + return 1; + } + } + return multiSelect(pParse, p, pDest); + } +#endif + + /* If writing to memory or generating a set + ** only a single column may be output. + */ +#ifndef SQLITE_OMIT_SUBQUERY + if( checkForMultiColumnSelectError(pParse, pDest, pEList->nExpr) ){ + goto select_end; + } +#endif + + /* If possible, rewrite the query to use GROUP BY instead of DISTINCT. + ** GROUP BY may use an index, DISTINCT never does. + */ + if( p->isDistinct && !p->isAgg && !p->pGroupBy ){ + p->pGroupBy = sqlite3ExprListDup(db, p->pEList); + pGroupBy = p->pGroupBy; + p->isDistinct = 0; + isDistinct = 0; + } + + /* If there is an ORDER BY clause, then this sorting + ** index might end up being unused if the data can be + ** extracted in pre-sorted order. If that is the case, then the + ** OP_OpenEphemeral instruction will be changed to an OP_Noop once + ** we figure out that the sorting index is not needed. The addrSortIndex + ** variable is used to facilitate that change. + */ + if( pOrderBy ){ + KeyInfo *pKeyInfo; + pKeyInfo = keyInfoFromExprList(pParse, pOrderBy); + pOrderBy->iECursor = pParse->nTab++; + p->addrOpenEphm[2] = addrSortIndex = + sqlite3VdbeAddOp4(v, OP_OpenEphemeral, + pOrderBy->iECursor, pOrderBy->nExpr+2, 0, + (char*)pKeyInfo, P4_KEYINFO_HANDOFF); + }else{ + addrSortIndex = -1; + } + + /* If the output is destined for a temporary table, open that table. + */ + if( pDest->eDest==SRT_EphemTab ){ + sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest->iParm, pEList->nExpr); + } + + /* Set the limiter. + */ + iEnd = sqlite3VdbeMakeLabel(v); + computeLimitRegisters(pParse, p, iEnd); + + /* Open a virtual index to use for the distinct set. + */ + if( isDistinct ){ + KeyInfo *pKeyInfo; + assert( isAgg || pGroupBy ); + distinct = pParse->nTab++; + pKeyInfo = keyInfoFromExprList(pParse, p->pEList); + sqlite3VdbeAddOp4(v, OP_OpenEphemeral, distinct, 0, 0, + (char*)pKeyInfo, P4_KEYINFO_HANDOFF); + }else{ + distinct = -1; + } + + /* Aggregate and non-aggregate queries are handled differently */ + if( !isAgg && pGroupBy==0 ){ + /* This case is for non-aggregate queries + ** Begin the database scan + */ + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, 0); + if( pWInfo==0 ) goto select_end; + + /* If sorting index that was created by a prior OP_OpenEphemeral + ** instruction ended up not being needed, then change the OP_OpenEphemeral + ** into an OP_Noop. + */ + if( addrSortIndex>=0 && pOrderBy==0 ){ + sqlite3VdbeChangeToNoop(v, addrSortIndex, 1); + p->addrOpenEphm[2] = -1; + } + + /* Use the standard inner loop + */ + assert(!isDistinct); + selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, -1, pDest, + pWInfo->iContinue, pWInfo->iBreak); + + /* End the database scan loop. + */ + sqlite3WhereEnd(pWInfo); + }else{ + /* This is the processing for aggregate queries */ + NameContext sNC; /* Name context for processing aggregate information */ + int iAMem; /* First Mem address for storing current GROUP BY */ + int iBMem; /* First Mem address for previous GROUP BY */ + int iUseFlag; /* Mem address holding flag indicating that at least + ** one row of the input to the aggregator has been + ** processed */ + int iAbortFlag; /* Mem address which causes query abort if positive */ + int groupBySort; /* Rows come from source in GROUP BY order */ + + + /* The following variables hold addresses or labels for parts of the + ** virtual machine program we are putting together */ + int addrOutputRow; /* Start of subroutine that outputs a result row */ + int regOutputRow; /* Return address register for output subroutine */ + int addrSetAbort; /* Set the abort flag and return */ + int addrInitializeLoop; /* Start of code that initializes the input loop */ + int addrTopOfLoop; /* Top of the input loop */ + int addrEnd; /* End of all processing */ + int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */ + int addrReset; /* Subroutine for resetting the accumulator */ + int regReset; /* Return address register for reset subroutine */ + + addrEnd = sqlite3VdbeMakeLabel(v); + + /* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in + ** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the + ** SELECT statement. + */ + memset(&sNC, 0, sizeof(sNC)); + sNC.pParse = pParse; + sNC.pSrcList = pTabList; + sNC.pAggInfo = &sAggInfo; + sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr+1 : 0; + sAggInfo.pGroupBy = pGroupBy; + sqlite3ExprAnalyzeAggList(&sNC, pEList); + sqlite3ExprAnalyzeAggList(&sNC, pOrderBy); + if( pHaving ){ + sqlite3ExprAnalyzeAggregates(&sNC, pHaving); + } + sAggInfo.nAccumulator = sAggInfo.nColumn; + for(i=0; i<sAggInfo.nFunc; i++){ + sqlite3ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->pList); + } + if( db->mallocFailed ) goto select_end; + + /* Processing for aggregates with GROUP BY is very different and + ** much more complex than aggregates without a GROUP BY. + */ + if( pGroupBy ){ + KeyInfo *pKeyInfo; /* Keying information for the group by clause */ + int j1; + + /* Create labels that we will be needing + */ + addrInitializeLoop = sqlite3VdbeMakeLabel(v); + + /* If there is a GROUP BY clause we might need a sorting index to + ** implement it. Allocate that sorting index now. If it turns out + ** that we do not need it after all, the OpenEphemeral instruction + ** will be converted into a Noop. + */ + sAggInfo.sortingIdx = pParse->nTab++; + pKeyInfo = keyInfoFromExprList(pParse, pGroupBy); + addrSortingIdx = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, + sAggInfo.sortingIdx, sAggInfo.nSortingColumn, + 0, (char*)pKeyInfo, P4_KEYINFO_HANDOFF); + + /* Initialize memory locations used by GROUP BY aggregate processing + */ + iUseFlag = ++pParse->nMem; + iAbortFlag = ++pParse->nMem; + iAMem = pParse->nMem + 1; + pParse->nMem += pGroupBy->nExpr; + iBMem = pParse->nMem + 1; + pParse->nMem += pGroupBy->nExpr; + sqlite3VdbeAddOp2(v, OP_Integer, 0, iAbortFlag); + VdbeComment((v, "clear abort flag")); + sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag); + VdbeComment((v, "indicate accumulator empty")); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrInitializeLoop); + + /* Generate a subroutine that outputs a single row of the result + ** set. This subroutine first looks at the iUseFlag. If iUseFlag + ** is less than or equal to zero, the subroutine is a no-op. If + ** the processing calls for the query to abort, this subroutine + ** increments the iAbortFlag memory location before returning in + ** order to signal the caller to abort. + */ + addrSetAbort = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp2(v, OP_Integer, 1, iAbortFlag); + VdbeComment((v, "set abort flag")); + regOutputRow = ++pParse->nMem; + sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); + addrOutputRow = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2); + VdbeComment((v, "Groupby result generator entry point")); + sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); + finalizeAggFunctions(pParse, &sAggInfo); + if( pHaving ){ + sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL); + } + selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy, + distinct, pDest, + addrOutputRow+1, addrSetAbort); + sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); + VdbeComment((v, "end groupby result generator")); + + /* Generate a subroutine that will reset the group-by accumulator + */ + addrReset = sqlite3VdbeCurrentAddr(v); + regReset = ++pParse->nMem; + resetAccumulator(pParse, &sAggInfo); + sqlite3VdbeAddOp1(v, OP_Return, regReset); + + /* Begin a loop that will extract all source rows in GROUP BY order. + ** This might involve two separate loops with an OP_Sort in between, or + ** it might be a single loop that uses an index to extract information + ** in the right order to begin with. + */ + sqlite3VdbeResolveLabel(v, addrInitializeLoop); + sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0); + if( pWInfo==0 ) goto select_end; + if( pGroupBy==0 ){ + /* The optimizer is able to deliver rows in group by order so + ** we do not have to sort. The OP_OpenEphemeral table will be + ** cancelled later because we still need to use the pKeyInfo + */ + pGroupBy = p->pGroupBy; + groupBySort = 0; + }else{ + /* Rows are coming out in undetermined order. We have to push + ** each row into a sorting index, terminate the first loop, + ** then loop over the sorting index in order to get the output + ** in sorted order + */ + int regBase; + int regRecord; + int nCol; + int nGroupBy; + + groupBySort = 1; + nGroupBy = pGroupBy->nExpr; + nCol = nGroupBy + 1; + j = nGroupBy+1; + for(i=0; i<sAggInfo.nColumn; i++){ + if( sAggInfo.aCol[i].iSorterColumn>=j ){ + nCol++; + j++; + } + } + regBase = sqlite3GetTempRange(pParse, nCol); + sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0); + sqlite3VdbeAddOp2(v, OP_Sequence, sAggInfo.sortingIdx,regBase+nGroupBy); + j = nGroupBy+1; + for(i=0; i<sAggInfo.nColumn; i++){ + struct AggInfo_col *pCol = &sAggInfo.aCol[i]; + if( pCol->iSorterColumn>=j ){ + int r1 = j + regBase; +#ifndef NDEBUG + int r2 = +#endif + sqlite3ExprCodeGetColumn(pParse, + pCol->pTab, pCol->iColumn, pCol->iTable, r1, 0); + j++; + + /* sAggInfo.aCol[] only contains one entry per column. So + ** The reference to pCol->iColumn,pCol->iTable must have been + ** the first reference to that column. Hence, + ** sqliteExprCodeGetColumn is guaranteed to put the result in + ** the column requested. + */ + assert( r1==r2 ); + } + } + regRecord = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord); + sqlite3VdbeAddOp2(v, OP_IdxInsert, sAggInfo.sortingIdx, regRecord); + sqlite3ReleaseTempReg(pParse, regRecord); + sqlite3ReleaseTempRange(pParse, regBase, nCol); + sqlite3WhereEnd(pWInfo); + sqlite3VdbeAddOp2(v, OP_Sort, sAggInfo.sortingIdx, addrEnd); + VdbeComment((v, "GROUP BY sort")); + sAggInfo.useSortingIdx = 1; + } + + /* Evaluate the current GROUP BY terms and store in b0, b1, b2... + ** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth) + ** Then compare the current GROUP BY terms against the GROUP BY terms + ** from the previous row currently stored in a0, a1, a2... + */ + addrTopOfLoop = sqlite3VdbeCurrentAddr(v); + for(j=0; j<pGroupBy->nExpr; j++){ + if( groupBySort ){ + sqlite3VdbeAddOp3(v, OP_Column, sAggInfo.sortingIdx, j, iBMem+j); + }else{ + sAggInfo.directMode = 1; + sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j); + } + } + sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr, + (char*)pKeyInfo, P4_KEYINFO); + j1 = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp3(v, OP_Jump, j1+1, 0, j1+1); + + /* Generate code that runs whenever the GROUP BY changes. + ** Changes in the GROUP BY are detected by the previous code + ** block. If there were no changes, this block is skipped. + ** + ** This code copies current group by terms in b0,b1,b2,... + ** over to a0,a1,a2. It then calls the output subroutine + ** and resets the aggregate accumulator registers in preparation + ** for the next GROUP BY batch. + */ + sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr); + sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow); + VdbeComment((v, "output one row")); + sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd); + VdbeComment((v, "check abort flag")); + sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); + VdbeComment((v, "reset accumulator")); + + /* Update the aggregate accumulators based on the content of + ** the current row + */ + sqlite3VdbeJumpHere(v, j1); + updateAccumulator(pParse, &sAggInfo); + sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag); + VdbeComment((v, "indicate data in accumulator")); + + /* End of the loop + */ + if( groupBySort ){ + sqlite3VdbeAddOp2(v, OP_Next, sAggInfo.sortingIdx, addrTopOfLoop); + }else{ + sqlite3WhereEnd(pWInfo); + sqlite3VdbeChangeToNoop(v, addrSortingIdx, 1); + } + + /* Output the final row of result + */ + sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow); + VdbeComment((v, "output final row")); + + } /* endif pGroupBy */ + else { + ExprList *pMinMax = 0; + ExprList *pDel = 0; + u8 flag; + + /* Check if the query is of one of the following forms: + ** + ** SELECT min(x) FROM ... + ** SELECT max(x) FROM ... + ** + ** If it is, then ask the code in where.c to attempt to sort results + ** as if there was an "ORDER ON x" or "ORDER ON x DESC" clause. + ** If where.c is able to produce results sorted in this order, then + ** add vdbe code to break out of the processing loop after the + ** first iteration (since the first iteration of the loop is + ** guaranteed to operate on the row with the minimum or maximum + ** value of x, the only row required). + ** + ** A special flag must be passed to sqlite3WhereBegin() to slightly + ** modify behaviour as follows: + ** + ** + If the query is a "SELECT min(x)", then the loop coded by + ** where.c should not iterate over any values with a NULL value + ** for x. + ** + ** + The optimizer code in where.c (the thing that decides which + ** index or indices to use) should place a different priority on + ** satisfying the 'ORDER BY' clause than it does in other cases. + ** Refer to code and comments in where.c for details. + */ + flag = minMaxQuery(pParse, p); + if( flag ){ + pDel = pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->pList); + if( pMinMax && !db->mallocFailed ){ + pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN; + pMinMax->a[0].pExpr->op = TK_COLUMN; + } + } + + /* This case runs if the aggregate has no GROUP BY clause. The + ** processing is much simpler since there is only a single row + ** of output. + */ + resetAccumulator(pParse, &sAggInfo); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, flag); + if( pWInfo==0 ){ + sqlite3ExprListDelete(db, pDel); + goto select_end; + } + updateAccumulator(pParse, &sAggInfo); + if( !pMinMax && flag ){ + sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iBreak); + VdbeComment((v, "%s() by index",(flag==WHERE_ORDERBY_MIN?"min":"max"))); + } + sqlite3WhereEnd(pWInfo); + finalizeAggFunctions(pParse, &sAggInfo); + pOrderBy = 0; + if( pHaving ){ + sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL); + } + selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, -1, + pDest, addrEnd, addrEnd); + + sqlite3ExprListDelete(db, pDel); + } + sqlite3VdbeResolveLabel(v, addrEnd); + + } /* endif aggregate query */ + + /* If there is an ORDER BY clause, then we need to sort the results + ** and send them to the callback one by one. + */ + if( pOrderBy ){ + generateSortTail(pParse, p, v, pEList->nExpr, pDest); + } + +#ifndef SQLITE_OMIT_SUBQUERY + /* If this was a subquery, we have now converted the subquery into a + ** temporary table. So set the SrcList_item.isPopulated flag to prevent + ** this subquery from being evaluated again and to force the use of + ** the temporary table. + */ + if( pParent ){ + assert( pParent->pSrc->nSrc>parentTab ); + assert( pParent->pSrc->a[parentTab].pSelect==p ); + pParent->pSrc->a[parentTab].isPopulated = 1; + } +#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. + */ + rc = 0; + + /* Control jumps to here if an error is encountered above, or upon + ** successful coding of the SELECT. + */ +select_end: + + /* Identify column names if we will be using them in a callback. This + ** step is skipped if the output is going to some other destination. + */ + if( rc==SQLITE_OK && pDest->eDest==SRT_Callback ){ + generateColumnNames(pParse, pTabList, pEList); + } + + sqlite3DbFree(db, sAggInfo.aCol); + sqlite3DbFree(db, sAggInfo.aFunc); + return rc; +} + +#if defined(SQLITE_DEBUG) +/* +******************************************************************************* +** The following code is used for testing and debugging only. The code +** that follows does not appear in normal builds. +** +** These routines are used to print out the content of all or part of a +** parse structures such as Select or Expr. Such printouts are useful +** for helping to understand what is happening inside the code generator +** during the execution of complex SELECT statements. +** +** These routine are not called anywhere from within the normal +** code base. Then are intended to be called from within the debugger +** or from temporary "printf" statements inserted for debugging. +*/ +void sqlite3PrintExpr(Expr *p){ + if( p->token.z && p->token.n>0 ){ + sqlite3DebugPrintf("(%.*s", p->token.n, p->token.z); + }else{ + sqlite3DebugPrintf("(%d", p->op); + } + if( p->pLeft ){ + sqlite3DebugPrintf(" "); + sqlite3PrintExpr(p->pLeft); + } + if( p->pRight ){ + sqlite3DebugPrintf(" "); + sqlite3PrintExpr(p->pRight); + } + sqlite3DebugPrintf(")"); +} +void sqlite3PrintExprList(ExprList *pList){ + int i; + for(i=0; i<pList->nExpr; i++){ + sqlite3PrintExpr(pList->a[i].pExpr); + if( i<pList->nExpr-1 ){ + sqlite3DebugPrintf(", "); + } + } +} +void sqlite3PrintSelect(Select *p, int indent){ + sqlite3DebugPrintf("%*sSELECT(%p) ", indent, "", p); + sqlite3PrintExprList(p->pEList); + sqlite3DebugPrintf("\n"); + if( p->pSrc ){ + char *zPrefix; + int i; + zPrefix = "FROM"; + for(i=0; i<p->pSrc->nSrc; i++){ + struct SrcList_item *pItem = &p->pSrc->a[i]; + sqlite3DebugPrintf("%*s ", indent+6, zPrefix); + zPrefix = ""; + if( pItem->pSelect ){ + sqlite3DebugPrintf("(\n"); + sqlite3PrintSelect(pItem->pSelect, indent+10); + sqlite3DebugPrintf("%*s)", indent+8, ""); + }else if( pItem->zName ){ + sqlite3DebugPrintf("%s", pItem->zName); + } + if( pItem->pTab ){ + sqlite3DebugPrintf("(table: %s)", pItem->pTab->zName); + } + if( pItem->zAlias ){ + sqlite3DebugPrintf(" AS %s", pItem->zAlias); + } + if( i<p->pSrc->nSrc-1 ){ + sqlite3DebugPrintf(","); + } + sqlite3DebugPrintf("\n"); + } + } + if( p->pWhere ){ + sqlite3DebugPrintf("%*s WHERE ", indent, ""); + sqlite3PrintExpr(p->pWhere); + sqlite3DebugPrintf("\n"); + } + if( p->pGroupBy ){ + sqlite3DebugPrintf("%*s GROUP BY ", indent, ""); + sqlite3PrintExprList(p->pGroupBy); + sqlite3DebugPrintf("\n"); + } + if( p->pHaving ){ + sqlite3DebugPrintf("%*s HAVING ", indent, ""); + sqlite3PrintExpr(p->pHaving); + sqlite3DebugPrintf("\n"); + } + if( p->pOrderBy ){ + sqlite3DebugPrintf("%*s ORDER BY ", indent, ""); + sqlite3PrintExprList(p->pOrderBy); + sqlite3DebugPrintf("\n"); + } +} +/* End of the structure debug printing code +*****************************************************************************/ +#endif /* defined(SQLITE_TEST) || defined(SQLITE_DEBUG) */ diff --git a/third_party/sqlite/src/shell.c b/third_party/sqlite/src/shell.c new file mode 100755 index 0000000..77ec143 --- /dev/null +++ b/third_party/sqlite/src/shell.c @@ -0,0 +1,2106 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains code to implement the "sqlite" command line +** utility for accessing SQLite databases. +** +** $Id: shell.c,v 1.184 2008/07/11 17:23:25 drh Exp $ +*/ +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <assert.h> +#include "sqlite3.h" +#include <ctype.h> +#include <stdarg.h> + +#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) +# include <signal.h> +# include <pwd.h> +# include <unistd.h> +# include <sys/types.h> +#endif + +#ifdef __OS2__ +# include <unistd.h> +#endif + +#if defined(HAVE_READLINE) && HAVE_READLINE==1 +# include <readline/readline.h> +# include <readline/history.h> +#else +# define readline(p) local_getline(p,stdin) +# define add_history(X) +# define read_history(X) +# define write_history(X) +# define stifle_history(X) +#endif + +#if defined(_WIN32) || defined(WIN32) +# include <io.h> +#else +/* Make sure isatty() has a prototype. +*/ +extern int isatty(); +#endif + +#if defined(_WIN32_WCE) +/* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty() + * thus we always assume that we have a console. That can be + * overridden with the -batch command line option. + */ +#define isatty(x) 1 +#endif + +#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) +#include <sys/time.h> +#include <sys/resource.h> + +/* Saved resource information for the beginning of an operation */ +static struct rusage sBegin; + +/* True if the timer is enabled */ +static int enableTimer = 0; + +/* +** Begin timing an operation +*/ +static void beginTimer(void){ + if( enableTimer ){ + getrusage(RUSAGE_SELF, &sBegin); + } +} + +/* Return the difference of two time_structs in seconds */ +static double timeDiff(struct timeval *pStart, struct timeval *pEnd){ + return (pEnd->tv_usec - pStart->tv_usec)*0.000001 + + (double)(pEnd->tv_sec - pStart->tv_sec); +} + +/* +** Print the timing results. +*/ +static void endTimer(void){ + if( enableTimer ){ + struct rusage sEnd; + getrusage(RUSAGE_SELF, &sEnd); + printf("CPU Time: user %f sys %f\n", + timeDiff(&sBegin.ru_utime, &sEnd.ru_utime), + timeDiff(&sBegin.ru_stime, &sEnd.ru_stime)); + } +} +#define BEGIN_TIMER beginTimer() +#define END_TIMER endTimer() +#define HAS_TIMER 1 +#else +#define BEGIN_TIMER +#define END_TIMER +#define HAS_TIMER 0 +#endif + + +/* +** If the following flag is set, then command execution stops +** at an error if we are not interactive. +*/ +static int bail_on_error = 0; + +/* +** Threat stdin as an interactive input if the following variable +** is true. Otherwise, assume stdin is connected to a file or pipe. +*/ +static int stdin_is_interactive = 1; + +/* +** The following is the open SQLite database. We make a pointer +** to this database a static variable so that it can be accessed +** by the SIGINT handler to interrupt database processing. +*/ +static sqlite3 *db = 0; + +/* +** True if an interrupt (Control-C) has been received. +*/ +static volatile int seenInterrupt = 0; + +/* +** This is the name of our program. It is set in main(), used +** in a number of other places, mostly for error messages. +*/ +static char *Argv0; + +/* +** Prompt strings. Initialized in main. Settable with +** .prompt main continue +*/ +static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/ +static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */ + +/* +** Write I/O traces to the following stream. +*/ +#ifdef SQLITE_ENABLE_IOTRACE +static FILE *iotrace = 0; +#endif + +/* +** This routine works like printf in that its first argument is a +** format string and subsequent arguments are values to be substituted +** in place of % fields. The result of formatting this string +** is written to iotrace. +*/ +#ifdef SQLITE_ENABLE_IOTRACE +static void iotracePrintf(const char *zFormat, ...){ + va_list ap; + char *z; + if( iotrace==0 ) return; + va_start(ap, zFormat); + z = sqlite3_vmprintf(zFormat, ap); + va_end(ap); + fprintf(iotrace, "%s", z); + sqlite3_free(z); +} +#endif + + +/* +** Determines if a string is a number of not. +*/ +static int isNumber(const char *z, int *realnum){ + if( *z=='-' || *z=='+' ) z++; + if( !isdigit(*z) ){ + return 0; + } + z++; + if( realnum ) *realnum = 0; + while( isdigit(*z) ){ z++; } + if( *z=='.' ){ + z++; + if( !isdigit(*z) ) return 0; + while( isdigit(*z) ){ z++; } + if( realnum ) *realnum = 1; + } + if( *z=='e' || *z=='E' ){ + z++; + if( *z=='+' || *z=='-' ) z++; + if( !isdigit(*z) ) return 0; + while( isdigit(*z) ){ z++; } + if( realnum ) *realnum = 1; + } + return *z==0; +} + +/* +** A global char* and an SQL function to access its current value +** from within an SQL statement. This program used to use the +** sqlite_exec_printf() API to substitue a string into an SQL statement. +** The correct way to do this with sqlite3 is to use the bind API, but +** since the shell is built around the callback paradigm it would be a lot +** of work. Instead just use this hack, which is quite harmless. +*/ +static const char *zShellStatic = 0; +static void shellstaticFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + assert( 0==argc ); + assert( zShellStatic ); + sqlite3_result_text(context, zShellStatic, -1, SQLITE_STATIC); +} + + +/* +** This routine reads a line of text from FILE in, stores +** the text in memory obtained from malloc() and returns a pointer +** to the text. NULL is returned at end of file, or if malloc() +** fails. +** +** The interface is like "readline" but no command-line editing +** is done. +*/ +static char *local_getline(char *zPrompt, FILE *in){ + char *zLine; + int nLine; + int n; + int eol; + + if( zPrompt && *zPrompt ){ + printf("%s",zPrompt); + fflush(stdout); + } + nLine = 100; + zLine = malloc( nLine ); + if( zLine==0 ) return 0; + n = 0; + eol = 0; + while( !eol ){ + if( n+100>nLine ){ + nLine = nLine*2 + 100; + zLine = realloc(zLine, nLine); + if( zLine==0 ) return 0; + } + if( fgets(&zLine[n], nLine - n, in)==0 ){ + if( n==0 ){ + free(zLine); + return 0; + } + zLine[n] = 0; + eol = 1; + break; + } + while( zLine[n] ){ n++; } + if( n>0 && zLine[n-1]=='\n' ){ + n--; + zLine[n] = 0; + eol = 1; + } + } + zLine = realloc( zLine, n+1 ); + return zLine; +} + +/* +** Retrieve a single line of input text. +** +** zPrior is a string of prior text retrieved. If not the empty +** string, then issue a continuation prompt. +*/ +static char *one_input_line(const char *zPrior, FILE *in){ + char *zPrompt; + char *zResult; + if( in!=0 ){ + return local_getline(0, in); + } + if( zPrior && zPrior[0] ){ + zPrompt = continuePrompt; + }else{ + zPrompt = mainPrompt; + } + zResult = readline(zPrompt); +#if defined(HAVE_READLINE) && HAVE_READLINE==1 + if( zResult && *zResult ) add_history(zResult); +#endif + return zResult; +} + +struct previous_mode_data { + int valid; /* Is there legit data in here? */ + int mode; + int showHeader; + int colWidth[100]; +}; + +/* +** An pointer to an instance of this structure is passed from +** the main program to the callback. This is used to communicate +** state and mode information. +*/ +struct callback_data { + sqlite3 *db; /* The database */ + int echoOn; /* True to echo input commands */ + int cnt; /* Number of records displayed so far */ + FILE *out; /* Write results here */ + int mode; /* An output mode setting */ + int writableSchema; /* True if PRAGMA writable_schema=ON */ + int showHeader; /* True to show column names in List or Column mode */ + char *zDestTable; /* Name of destination table when MODE_Insert */ + char separator[20]; /* Separator character for MODE_List */ + int colWidth[100]; /* Requested width of each column when in column mode*/ + int actualWidth[100]; /* Actual width of each column */ + char nullvalue[20]; /* The text to print when a NULL comes back from + ** the database */ + struct previous_mode_data explainPrev; + /* Holds the mode information just before + ** .explain ON */ + char outfile[FILENAME_MAX]; /* Filename for *out */ + const char *zDbFilename; /* name of the database file */ +}; + +/* +** These are the allowed modes. +*/ +#define MODE_Line 0 /* One column per line. Blank line between records */ +#define MODE_Column 1 /* One record per line in neat columns */ +#define MODE_List 2 /* One record per line with a separator */ +#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */ +#define MODE_Html 4 /* Generate an XHTML table */ +#define MODE_Insert 5 /* Generate SQL "insert" statements */ +#define MODE_Tcl 6 /* Generate ANSI-C or TCL quoted elements */ +#define MODE_Csv 7 /* Quote strings, numbers are plain */ +#define MODE_Explain 8 /* Like MODE_Column, but do not truncate data */ + +static const char *modeDescr[] = { + "line", + "column", + "list", + "semi", + "html", + "insert", + "tcl", + "csv", + "explain", +}; + +/* +** Number of elements in an array +*/ +#define ArraySize(X) (sizeof(X)/sizeof(X[0])) + +/* +** Output the given string as a quoted string using SQL quoting conventions. +*/ +static void output_quoted_string(FILE *out, const char *z){ + int i; + int nSingle = 0; + for(i=0; z[i]; i++){ + if( z[i]=='\'' ) nSingle++; + } + if( nSingle==0 ){ + fprintf(out,"'%s'",z); + }else{ + fprintf(out,"'"); + while( *z ){ + for(i=0; z[i] && z[i]!='\''; i++){} + if( i==0 ){ + fprintf(out,"''"); + z++; + }else if( z[i]=='\'' ){ + fprintf(out,"%.*s''",i,z); + z += i+1; + }else{ + fprintf(out,"%s",z); + break; + } + } + fprintf(out,"'"); + } +} + +/* +** Output the given string as a quoted according to C or TCL quoting rules. +*/ +static void output_c_string(FILE *out, const char *z){ + unsigned int c; + fputc('"', out); + while( (c = *(z++))!=0 ){ + if( c=='\\' ){ + fputc(c, out); + fputc(c, out); + }else if( c=='\t' ){ + fputc('\\', out); + fputc('t', out); + }else if( c=='\n' ){ + fputc('\\', out); + fputc('n', out); + }else if( c=='\r' ){ + fputc('\\', out); + fputc('r', out); + }else if( !isprint(c) ){ + fprintf(out, "\\%03o", c&0xff); + }else{ + fputc(c, out); + } + } + fputc('"', out); +} + +/* +** Output the given string with characters that are special to +** HTML escaped. +*/ +static void output_html_string(FILE *out, const char *z){ + int i; + while( *z ){ + for(i=0; z[i] && z[i]!='<' && z[i]!='&'; i++){} + if( i>0 ){ + fprintf(out,"%.*s",i,z); + } + if( z[i]=='<' ){ + fprintf(out,"<"); + }else if( z[i]=='&' ){ + fprintf(out,"&"); + }else{ + break; + } + z += i + 1; + } +} + +/* +** If a field contains any character identified by a 1 in the following +** array, then the string must be quoted for CSV. +*/ +static const char needCsvQuote[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +}; + +/* +** Output a single term of CSV. Actually, p->separator is used for +** the separator, which may or may not be a comma. p->nullvalue is +** the null value. Strings are quoted using ANSI-C rules. Numbers +** appear outside of quotes. +*/ +static void output_csv(struct callback_data *p, const char *z, int bSep){ + FILE *out = p->out; + if( z==0 ){ + fprintf(out,"%s",p->nullvalue); + }else{ + int i; + int nSep = strlen(p->separator); + for(i=0; z[i]; i++){ + if( needCsvQuote[((unsigned char*)z)[i]] + || (z[i]==p->separator[0] && + (nSep==1 || memcmp(z, p->separator, nSep)==0)) ){ + i = 0; + break; + } + } + if( i==0 ){ + putc('"', out); + for(i=0; z[i]; i++){ + if( z[i]=='"' ) putc('"', out); + putc(z[i], out); + } + putc('"', out); + }else{ + fprintf(out, "%s", z); + } + } + if( bSep ){ + fprintf(p->out, "%s", p->separator); + } +} + +#ifdef SIGINT +/* +** This routine runs when the user presses Ctrl-C +*/ +static void interrupt_handler(int NotUsed){ + seenInterrupt = 1; + if( db ) sqlite3_interrupt(db); +} +#endif + +/* +** This is the callback routine that the SQLite library +** invokes for each row of a query result. +*/ +static int callback(void *pArg, int nArg, char **azArg, char **azCol){ + int i; + struct callback_data *p = (struct callback_data*)pArg; + switch( p->mode ){ + case MODE_Line: { + int w = 5; + if( azArg==0 ) break; + for(i=0; i<nArg; i++){ + int len = strlen(azCol[i] ? azCol[i] : ""); + if( len>w ) w = len; + } + if( p->cnt++>0 ) fprintf(p->out,"\n"); + for(i=0; i<nArg; i++){ + fprintf(p->out,"%*s = %s\n", w, azCol[i], + azArg[i] ? azArg[i] : p->nullvalue); + } + break; + } + case MODE_Explain: + case MODE_Column: { + if( p->cnt++==0 ){ + for(i=0; i<nArg; i++){ + int w, n; + if( i<ArraySize(p->colWidth) ){ + w = p->colWidth[i]; + }else{ + w = 0; + } + if( w<=0 ){ + w = strlen(azCol[i] ? azCol[i] : ""); + if( w<10 ) w = 10; + n = strlen(azArg && azArg[i] ? azArg[i] : p->nullvalue); + if( w<n ) w = n; + } + if( i<ArraySize(p->actualWidth) ){ + p->actualWidth[i] = w; + } + if( p->showHeader ){ + fprintf(p->out,"%-*.*s%s",w,w,azCol[i], i==nArg-1 ? "\n": " "); + } + } + if( p->showHeader ){ + for(i=0; i<nArg; i++){ + int w; + if( i<ArraySize(p->actualWidth) ){ + w = p->actualWidth[i]; + }else{ + w = 10; + } + fprintf(p->out,"%-*.*s%s",w,w,"-----------------------------------" + "----------------------------------------------------------", + i==nArg-1 ? "\n": " "); + } + } + } + if( azArg==0 ) break; + for(i=0; i<nArg; i++){ + int w; + if( i<ArraySize(p->actualWidth) ){ + w = p->actualWidth[i]; + }else{ + w = 10; + } + if( p->mode==MODE_Explain && azArg[i] && strlen(azArg[i])>w ){ + w = strlen(azArg[i]); + } + fprintf(p->out,"%-*.*s%s",w,w, + azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": " "); + } + break; + } + case MODE_Semi: + case MODE_List: { + if( p->cnt++==0 && p->showHeader ){ + for(i=0; i<nArg; i++){ + fprintf(p->out,"%s%s",azCol[i], i==nArg-1 ? "\n" : p->separator); + } + } + if( azArg==0 ) break; + for(i=0; i<nArg; i++){ + char *z = azArg[i]; + if( z==0 ) z = p->nullvalue; + fprintf(p->out, "%s", z); + if( i<nArg-1 ){ + fprintf(p->out, "%s", p->separator); + }else if( p->mode==MODE_Semi ){ + fprintf(p->out, ";\n"); + }else{ + fprintf(p->out, "\n"); + } + } + break; + } + case MODE_Html: { + if( p->cnt++==0 && p->showHeader ){ + fprintf(p->out,"<TR>"); + for(i=0; i<nArg; i++){ + fprintf(p->out,"<TH>%s</TH>",azCol[i]); + } + fprintf(p->out,"</TR>\n"); + } + if( azArg==0 ) break; + fprintf(p->out,"<TR>"); + for(i=0; i<nArg; i++){ + fprintf(p->out,"<TD>"); + output_html_string(p->out, azArg[i] ? azArg[i] : p->nullvalue); + fprintf(p->out,"</TD>\n"); + } + fprintf(p->out,"</TR>\n"); + break; + } + case MODE_Tcl: { + if( p->cnt++==0 && p->showHeader ){ + for(i=0; i<nArg; i++){ + output_c_string(p->out,azCol[i] ? azCol[i] : ""); + fprintf(p->out, "%s", p->separator); + } + fprintf(p->out,"\n"); + } + if( azArg==0 ) break; + for(i=0; i<nArg; i++){ + output_c_string(p->out, azArg[i] ? azArg[i] : p->nullvalue); + fprintf(p->out, "%s", p->separator); + } + fprintf(p->out,"\n"); + break; + } + case MODE_Csv: { + if( p->cnt++==0 && p->showHeader ){ + for(i=0; i<nArg; i++){ + output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1); + } + fprintf(p->out,"\n"); + } + if( azArg==0 ) break; + for(i=0; i<nArg; i++){ + output_csv(p, azArg[i], i<nArg-1); + } + fprintf(p->out,"\n"); + break; + } + case MODE_Insert: { + if( azArg==0 ) break; + fprintf(p->out,"INSERT INTO %s VALUES(",p->zDestTable); + for(i=0; i<nArg; i++){ + char *zSep = i>0 ? ",": ""; + if( azArg[i]==0 ){ + fprintf(p->out,"%sNULL",zSep); + }else if( isNumber(azArg[i], 0) ){ + fprintf(p->out,"%s%s",zSep, azArg[i]); + }else{ + if( zSep[0] ) fprintf(p->out,"%s",zSep); + output_quoted_string(p->out, azArg[i]); + } + } + fprintf(p->out,");\n"); + break; + } + } + return 0; +} + +/* +** Set the destination table field of the callback_data structure to +** the name of the table given. Escape any quote characters in the +** table name. +*/ +static void set_table_name(struct callback_data *p, const char *zName){ + int i, n; + int needQuote; + char *z; + + if( p->zDestTable ){ + free(p->zDestTable); + p->zDestTable = 0; + } + if( zName==0 ) return; + needQuote = !isalpha((unsigned char)*zName) && *zName!='_'; + for(i=n=0; zName[i]; i++, n++){ + if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ){ + needQuote = 1; + if( zName[i]=='\'' ) n++; + } + } + if( needQuote ) n += 2; + z = p->zDestTable = malloc( n+1 ); + if( z==0 ){ + fprintf(stderr,"Out of memory!\n"); + exit(1); + } + n = 0; + if( needQuote ) z[n++] = '\''; + for(i=0; zName[i]; i++){ + z[n++] = zName[i]; + if( zName[i]=='\'' ) z[n++] = '\''; + } + if( needQuote ) z[n++] = '\''; + z[n] = 0; +} + +/* zIn is either a pointer to a NULL-terminated string in memory obtained +** from malloc(), or a NULL pointer. The string pointed to by zAppend is +** added to zIn, and the result returned in memory obtained from malloc(). +** zIn, if it was not NULL, is freed. +** +** If the third argument, quote, is not '\0', then it is used as a +** quote character for zAppend. +*/ +static char *appendText(char *zIn, char const *zAppend, char quote){ + int len; + int i; + int nAppend = strlen(zAppend); + int nIn = (zIn?strlen(zIn):0); + + len = nAppend+nIn+1; + if( quote ){ + len += 2; + for(i=0; i<nAppend; i++){ + if( zAppend[i]==quote ) len++; + } + } + + zIn = (char *)realloc(zIn, len); + if( !zIn ){ + return 0; + } + + if( quote ){ + char *zCsr = &zIn[nIn]; + *zCsr++ = quote; + for(i=0; i<nAppend; i++){ + *zCsr++ = zAppend[i]; + if( zAppend[i]==quote ) *zCsr++ = quote; + } + *zCsr++ = quote; + *zCsr++ = '\0'; + assert( (zCsr-zIn)==len ); + }else{ + memcpy(&zIn[nIn], zAppend, nAppend); + zIn[len-1] = '\0'; + } + + return zIn; +} + + +/* +** Execute a query statement that has a single result column. Print +** that result column on a line by itself with a semicolon terminator. +** +** This is used, for example, to show the schema of the database by +** querying the SQLITE_MASTER table. +*/ +static int run_table_dump_query(FILE *out, sqlite3 *db, const char *zSelect){ + sqlite3_stmt *pSelect; + int rc; + rc = sqlite3_prepare(db, zSelect, -1, &pSelect, 0); + if( rc!=SQLITE_OK || !pSelect ){ + return rc; + } + rc = sqlite3_step(pSelect); + while( rc==SQLITE_ROW ){ + fprintf(out, "%s;\n", sqlite3_column_text(pSelect, 0)); + rc = sqlite3_step(pSelect); + } + return sqlite3_finalize(pSelect); +} + + +/* +** This is a different callback routine used for dumping the database. +** Each row received by this callback consists of a table name, +** the table type ("index" or "table") and SQL to create the table. +** This routine should print text sufficient to recreate the table. +*/ +static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){ + int rc; + const char *zTable; + const char *zType; + const char *zSql; + struct callback_data *p = (struct callback_data *)pArg; + + if( nArg!=3 ) return 1; + zTable = azArg[0]; + zType = azArg[1]; + zSql = azArg[2]; + + if( strcmp(zTable, "sqlite_sequence")==0 ){ + fprintf(p->out, "DELETE FROM sqlite_sequence;\n"); + }else if( strcmp(zTable, "sqlite_stat1")==0 ){ + fprintf(p->out, "ANALYZE sqlite_master;\n"); + }else if( strncmp(zTable, "sqlite_", 7)==0 ){ + return 0; + }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){ + char *zIns; + if( !p->writableSchema ){ + fprintf(p->out, "PRAGMA writable_schema=ON;\n"); + p->writableSchema = 1; + } + zIns = sqlite3_mprintf( + "INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)" + "VALUES('table','%q','%q',0,'%q');", + zTable, zTable, zSql); + fprintf(p->out, "%s\n", zIns); + sqlite3_free(zIns); + return 0; + }else{ + fprintf(p->out, "%s;\n", zSql); + } + + if( strcmp(zType, "table")==0 ){ + sqlite3_stmt *pTableInfo = 0; + char *zSelect = 0; + char *zTableInfo = 0; + char *zTmp = 0; + + zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0); + zTableInfo = appendText(zTableInfo, zTable, '"'); + zTableInfo = appendText(zTableInfo, ");", 0); + + rc = sqlite3_prepare(p->db, zTableInfo, -1, &pTableInfo, 0); + if( zTableInfo ) free(zTableInfo); + if( rc!=SQLITE_OK || !pTableInfo ){ + return 1; + } + + zSelect = appendText(zSelect, "SELECT 'INSERT INTO ' || ", 0); + zTmp = appendText(zTmp, zTable, '"'); + if( zTmp ){ + zSelect = appendText(zSelect, zTmp, '\''); + } + 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, zText, '"'); + rc = sqlite3_step(pTableInfo); + if( rc==SQLITE_ROW ){ + zSelect = appendText(zSelect, ") || ',' || ", 0); + }else{ + zSelect = appendText(zSelect, ") ", 0); + } + } + rc = sqlite3_finalize(pTableInfo); + if( rc!=SQLITE_OK ){ + if( zSelect ) free(zSelect); + return 1; + } + zSelect = appendText(zSelect, "|| ')' FROM ", 0); + zSelect = appendText(zSelect, zTable, '"'); + + rc = run_table_dump_query(p->out, p->db, zSelect); + if( rc==SQLITE_CORRUPT ){ + zSelect = appendText(zSelect, " ORDER BY rowid DESC", 0); + rc = run_table_dump_query(p->out, p->db, zSelect); + } + if( zSelect ) free(zSelect); + } + return 0; +} + +/* +** Run zQuery. Use dump_callback() as the callback routine so that +** the contents of the query are output as SQL statements. +** +** If we get a SQLITE_CORRUPT error, rerun the query after appending +** "ORDER BY rowid DESC" to the end. +*/ +static int run_schema_dump_query( + struct callback_data *p, + const char *zQuery, + char **pzErrMsg +){ + int rc; + rc = sqlite3_exec(p->db, zQuery, dump_callback, p, pzErrMsg); + if( rc==SQLITE_CORRUPT ){ + char *zQ2; + int len = strlen(zQuery); + if( pzErrMsg ) sqlite3_free(*pzErrMsg); + zQ2 = malloc( len+100 ); + if( zQ2==0 ) return rc; + sqlite3_snprintf(sizeof(zQ2), zQ2, "%s ORDER BY rowid DESC", zQuery); + rc = sqlite3_exec(p->db, zQ2, dump_callback, p, pzErrMsg); + free(zQ2); + } + return rc; +} + +/* +** Text of a help message +*/ +static char zHelp[] = + ".bail ON|OFF Stop after hitting an error. Default OFF\n" + ".databases List names and files of attached databases\n" + ".dump ?TABLE? ... Dump the database in an SQL text format\n" + ".echo ON|OFF Turn command echo on or off\n" + ".exit Exit this program\n" + ".explain ON|OFF Turn output mode suitable for EXPLAIN on or off.\n" + ".header(s) ON|OFF Turn display of headers on or off\n" + ".help Show this message\n" + ".import FILE TABLE Import data from FILE into TABLE\n" + ".indices TABLE Show names of all indices on TABLE\n" +#ifdef SQLITE_ENABLE_IOTRACE + ".iotrace FILE Enable I/O diagnostic logging to FILE\n" +#endif +#ifndef SQLITE_OMIT_LOAD_EXTENSION + ".load FILE ?ENTRY? Load an extension library\n" +#endif + ".mode MODE ?TABLE? Set output mode where MODE is one of:\n" + " csv Comma-separated values\n" + " column Left-aligned columns. (See .width)\n" + " html HTML <table> code\n" + " insert SQL insert statements for TABLE\n" + " line One value per line\n" + " list Values delimited by .separator string\n" + " tabs Tab-separated values\n" + " tcl TCL list elements\n" + ".nullvalue STRING Print STRING in place of NULL values\n" + ".output FILENAME Send output to FILENAME\n" + ".output stdout Send output to the screen\n" + ".prompt MAIN CONTINUE Replace the standard prompts\n" + ".quit Exit this program\n" + ".read FILENAME Execute SQL in FILENAME\n" + ".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" + ".tables ?PATTERN? List names of tables matching a LIKE pattern\n" + ".timeout MS Try opening locked tables for MS milliseconds\n" +#if HAS_TIMER + ".timer ON|OFF Turn the CPU timer measurement on or off\n" +#endif + ".width NUM NUM ... Set column widths for \"column\" mode\n" +; + +/* Forward reference */ +static int process_input(struct callback_data *p, FILE *in); + +/* +** Make sure the database is open. If it is not, then open it. If +** the database fails to open, print an error message and exit. +*/ +static void open_db(struct callback_data *p){ + if( p->db==0 ){ + sqlite3_open(p->zDbFilename, &p->db); + db = p->db; + if( db && sqlite3_errcode(db)==SQLITE_OK ){ + sqlite3_create_function(db, "shellstatic", 0, SQLITE_UTF8, 0, + shellstaticFunc, 0, 0); + } + if( db==0 || SQLITE_OK!=sqlite3_errcode(db) ){ + fprintf(stderr,"Unable to open database \"%s\": %s\n", + p->zDbFilename, sqlite3_errmsg(db)); + exit(1); + } +#ifndef SQLITE_OMIT_LOAD_EXTENSION + sqlite3_enable_load_extension(p->db, 1); +#endif + } +} + +/* +** Do C-language style dequoting. +** +** \t -> tab +** \n -> newline +** \r -> carriage return +** \NNN -> ascii character NNN in octal +** \\ -> backslash +*/ +static void resolve_backslashes(char *z){ + int i, j, c; + for(i=j=0; (c = z[i])!=0; i++, j++){ + if( c=='\\' ){ + c = z[++i]; + if( c=='n' ){ + c = '\n'; + }else if( c=='t' ){ + c = '\t'; + }else if( c=='r' ){ + c = '\r'; + }else if( c>='0' && c<='7' ){ + c -= '0'; + if( z[i+1]>='0' && z[i+1]<='7' ){ + i++; + c = (c<<3) + z[i] - '0'; + if( z[i+1]>='0' && z[i+1]<='7' ){ + i++; + c = (c<<3) + z[i] - '0'; + } + } + } + } + z[j] = c; + } + z[j] = 0; +} + +/* +** Interpret zArg as a boolean value. Return either 0 or 1. +*/ +static int booleanValue(char *zArg){ + int val = atoi(zArg); + int j; + for(j=0; zArg[j]; j++){ + zArg[j] = tolower(zArg[j]); + } + if( strcmp(zArg,"on")==0 ){ + val = 1; + }else if( strcmp(zArg,"yes")==0 ){ + val = 1; + } + return val; +} + +/* +** If an input line begins with "." then invoke this routine to +** process that line. +** +** Return 1 on error, 2 to exit, and 0 otherwise. +*/ +static int do_meta_command(char *zLine, struct callback_data *p){ + int i = 1; + int nArg = 0; + int n, c; + int rc = 0; + char *azArg[50]; + + /* Parse the input line into tokens. + */ + while( zLine[i] && nArg<ArraySize(azArg) ){ + while( isspace((unsigned char)zLine[i]) ){ i++; } + if( zLine[i]==0 ) break; + if( zLine[i]=='\'' || zLine[i]=='"' ){ + int delim = zLine[i++]; + azArg[nArg++] = &zLine[i]; + while( zLine[i] && zLine[i]!=delim ){ i++; } + if( zLine[i]==delim ){ + zLine[i++] = 0; + } + if( delim=='"' ) resolve_backslashes(azArg[nArg-1]); + }else{ + azArg[nArg++] = &zLine[i]; + while( zLine[i] && !isspace((unsigned char)zLine[i]) ){ i++; } + if( zLine[i] ) zLine[i++] = 0; + resolve_backslashes(azArg[nArg-1]); + } + } + + /* Process the input line. + */ + if( nArg==0 ) return rc; + n = strlen(azArg[0]); + c = azArg[0][0]; + if( c=='b' && n>1 && strncmp(azArg[0], "bail", n)==0 && nArg>1 ){ + bail_on_error = booleanValue(azArg[1]); + }else + + if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){ + struct callback_data data; + char *zErrMsg = 0; + open_db(p); + memcpy(&data, p, sizeof(data)); + data.showHeader = 1; + data.mode = MODE_Column; + data.colWidth[0] = 3; + data.colWidth[1] = 15; + data.colWidth[2] = 58; + data.cnt = 0; + sqlite3_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg); + if( zErrMsg ){ + fprintf(stderr,"Error: %s\n", zErrMsg); + sqlite3_free(zErrMsg); + } + }else + + if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){ + char *zErrMsg = 0; + open_db(p); + fprintf(p->out, "BEGIN TRANSACTION;\n"); + p->writableSchema = 0; + if( nArg==1 ){ + run_schema_dump_query(p, + "SELECT name, type, sql FROM sqlite_master " + "WHERE sql NOT NULL AND type=='table'", 0 + ); + run_table_dump_query(p->out, p->db, + "SELECT sql FROM sqlite_master " + "WHERE sql NOT NULL AND type IN ('index','trigger','view')" + ); + }else{ + int i; + for(i=1; i<nArg; i++){ + zShellStatic = azArg[i]; + run_schema_dump_query(p, + "SELECT name, type, sql FROM sqlite_master " + "WHERE tbl_name LIKE shellstatic() AND type=='table'" + " AND sql NOT NULL", 0); + run_table_dump_query(p->out, p->db, + "SELECT sql FROM sqlite_master " + "WHERE sql NOT NULL" + " AND type IN ('index','trigger','view')" + " AND tbl_name LIKE shellstatic()" + ); + zShellStatic = 0; + } + } + if( p->writableSchema ){ + fprintf(p->out, "PRAGMA writable_schema=OFF;\n"); + p->writableSchema = 0; + } + if( zErrMsg ){ + fprintf(stderr,"Error: %s\n", zErrMsg); + sqlite3_free(zErrMsg); + }else{ + fprintf(p->out, "COMMIT;\n"); + } + }else + + if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 ){ + p->echoOn = booleanValue(azArg[1]); + }else + + if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){ + rc = 2; + }else + + if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){ + int val = nArg>=2 ? booleanValue(azArg[1]) : 1; + if(val == 1) { + if(!p->explainPrev.valid) { + p->explainPrev.valid = 1; + p->explainPrev.mode = p->mode; + p->explainPrev.showHeader = p->showHeader; + memcpy(p->explainPrev.colWidth,p->colWidth,sizeof(p->colWidth)); + } + /* We could put this code under the !p->explainValid + ** condition so that it does not execute if we are already in + ** explain mode. However, always executing it allows us an easy + ** was to reset to explain mode in case the user previously + ** did an .explain followed by a .width, .mode or .header + ** command. + */ + p->mode = MODE_Explain; + p->showHeader = 1; + memset(p->colWidth,0,ArraySize(p->colWidth)); + p->colWidth[0] = 4; /* addr */ + p->colWidth[1] = 13; /* opcode */ + p->colWidth[2] = 4; /* P1 */ + p->colWidth[3] = 4; /* P2 */ + p->colWidth[4] = 4; /* P3 */ + p->colWidth[5] = 13; /* P4 */ + p->colWidth[6] = 2; /* P5 */ + p->colWidth[7] = 13; /* Comment */ + }else if (p->explainPrev.valid) { + p->explainPrev.valid = 0; + p->mode = p->explainPrev.mode; + p->showHeader = p->explainPrev.showHeader; + memcpy(p->colWidth,p->explainPrev.colWidth,sizeof(p->colWidth)); + } + }else + + if( c=='h' && (strncmp(azArg[0], "header", n)==0 || + strncmp(azArg[0], "headers", n)==0 )&& nArg>1 ){ + p->showHeader = booleanValue(azArg[1]); + }else + + if( c=='h' && strncmp(azArg[0], "help", n)==0 ){ + fprintf(stderr,zHelp); + }else + + if( c=='i' && strncmp(azArg[0], "import", n)==0 && nArg>=3 ){ + char *zTable = azArg[2]; /* Insert data into this table */ + char *zFile = azArg[1]; /* The file from which to extract data */ + sqlite3_stmt *pStmt; /* A statement */ + int rc; /* Result code */ + int nCol; /* Number of columns in the table */ + int nByte; /* Number of bytes in an SQL string */ + int i, j; /* Loop counters */ + int nSep; /* Number of bytes in p->separator[] */ + char *zSql; /* An SQL statement */ + char *zLine; /* A single line of input from the file */ + char **azCol; /* zLine[] broken up into columns */ + char *zCommit; /* How to commit changes */ + FILE *in; /* The input file */ + int lineno = 0; /* Line number of input file */ + + open_db(p); + nSep = strlen(p->separator); + if( nSep==0 ){ + fprintf(stderr, "non-null separator required for import\n"); + return 0; + } + zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable); + if( zSql==0 ) return 0; + nByte = strlen(zSql); + rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + if( rc ){ + fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db)); + nCol = 0; + rc = 1; + }else{ + nCol = sqlite3_column_count(pStmt); + } + sqlite3_finalize(pStmt); + if( nCol==0 ) return 0; + zSql = malloc( nByte + 20 + nCol*2 ); + if( zSql==0 ) return 0; + sqlite3_snprintf(nByte+20, zSql, "INSERT INTO '%q' VALUES(?", zTable); + j = strlen(zSql); + for(i=1; i<nCol; i++){ + zSql[j++] = ','; + zSql[j++] = '?'; + } + zSql[j++] = ')'; + zSql[j] = 0; + rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0); + free(zSql); + if( rc ){ + fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db)); + sqlite3_finalize(pStmt); + return 1; + } + in = fopen(zFile, "rb"); + if( in==0 ){ + fprintf(stderr, "cannot open file: %s\n", zFile); + sqlite3_finalize(pStmt); + return 0; + } + azCol = malloc( sizeof(azCol[0])*(nCol+1) ); + if( azCol==0 ){ + fclose(in); + return 0; + } + sqlite3_exec(p->db, "BEGIN", 0, 0, 0); + zCommit = "COMMIT"; + while( (zLine = local_getline(0, in))!=0 ){ + char *z; + i = 0; + lineno++; + azCol[0] = zLine; + for(i=0, z=zLine; *z && *z!='\n' && *z!='\r'; z++){ + if( *z==p->separator[0] && strncmp(z, p->separator, nSep)==0 ){ + *z = 0; + i++; + if( i<nCol ){ + azCol[i] = &z[nSep]; + z += nSep-1; + } + } + } + *z = 0; + if( i+1!=nCol ){ + fprintf(stderr,"%s line %d: expected %d columns of data but found %d\n", + zFile, lineno, nCol, i+1); + zCommit = "ROLLBACK"; + break; + } + for(i=0; i<nCol; i++){ + sqlite3_bind_text(pStmt, i+1, azCol[i], -1, SQLITE_STATIC); + } + sqlite3_step(pStmt); + rc = sqlite3_reset(pStmt); + free(zLine); + if( rc!=SQLITE_OK ){ + fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db)); + zCommit = "ROLLBACK"; + rc = 1; + break; + } + } + free(azCol); + fclose(in); + sqlite3_finalize(pStmt); + sqlite3_exec(p->db, zCommit, 0, 0, 0); + }else + + if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg>1 ){ + struct callback_data data; + char *zErrMsg = 0; + open_db(p); + memcpy(&data, p, sizeof(data)); + data.showHeader = 0; + data.mode = MODE_List; + zShellStatic = azArg[1]; + sqlite3_exec(p->db, + "SELECT name FROM sqlite_master " + "WHERE type='index' AND tbl_name LIKE shellstatic() " + "UNION ALL " + "SELECT name FROM sqlite_temp_master " + "WHERE type='index' AND tbl_name LIKE shellstatic() " + "ORDER BY 1", + callback, &data, &zErrMsg + ); + zShellStatic = 0; + if( zErrMsg ){ + fprintf(stderr,"Error: %s\n", zErrMsg); + sqlite3_free(zErrMsg); + } + }else + +#ifdef SQLITE_ENABLE_IOTRACE + if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){ + extern void (*sqlite3IoTrace)(const char*, ...); + if( iotrace && iotrace!=stdout ) fclose(iotrace); + iotrace = 0; + if( nArg<2 ){ + sqlite3IoTrace = 0; + }else if( strcmp(azArg[1], "-")==0 ){ + sqlite3IoTrace = iotracePrintf; + iotrace = stdout; + }else{ + iotrace = fopen(azArg[1], "w"); + if( iotrace==0 ){ + fprintf(stderr, "cannot open \"%s\"\n", azArg[1]); + sqlite3IoTrace = 0; + }else{ + sqlite3IoTrace = iotracePrintf; + } + } + }else +#endif + +#ifndef SQLITE_OMIT_LOAD_EXTENSION + if( c=='l' && strncmp(azArg[0], "load", n)==0 && nArg>=2 ){ + const char *zFile, *zProc; + char *zErrMsg = 0; + int rc; + zFile = azArg[1]; + zProc = nArg>=3 ? azArg[2] : 0; + open_db(p); + rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg); + if( rc!=SQLITE_OK ){ + fprintf(stderr, "%s\n", zErrMsg); + sqlite3_free(zErrMsg); + rc = 1; + } + }else +#endif + + if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg>=2 ){ + int n2 = strlen(azArg[1]); + if( strncmp(azArg[1],"line",n2)==0 + || + strncmp(azArg[1],"lines",n2)==0 ){ + p->mode = MODE_Line; + }else if( strncmp(azArg[1],"column",n2)==0 + || + strncmp(azArg[1],"columns",n2)==0 ){ + p->mode = MODE_Column; + }else if( strncmp(azArg[1],"list",n2)==0 ){ + p->mode = MODE_List; + }else if( strncmp(azArg[1],"html",n2)==0 ){ + p->mode = MODE_Html; + }else if( strncmp(azArg[1],"tcl",n2)==0 ){ + p->mode = MODE_Tcl; + }else if( strncmp(azArg[1],"csv",n2)==0 ){ + p->mode = MODE_Csv; + sqlite3_snprintf(sizeof(p->separator), p->separator, ","); + }else if( strncmp(azArg[1],"tabs",n2)==0 ){ + p->mode = MODE_List; + sqlite3_snprintf(sizeof(p->separator), p->separator, "\t"); + }else if( strncmp(azArg[1],"insert",n2)==0 ){ + p->mode = MODE_Insert; + if( nArg>=3 ){ + set_table_name(p, azArg[2]); + }else{ + set_table_name(p, "table"); + } + }else { + fprintf(stderr,"mode should be one of: " + "column csv html insert line list tabs tcl\n"); + } + }else + + if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 && nArg==2 ) { + sqlite3_snprintf(sizeof(p->nullvalue), p->nullvalue, + "%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]); + }else + + if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){ + if( p->out!=stdout ){ + fclose(p->out); + } + if( strcmp(azArg[1],"stdout")==0 ){ + p->out = stdout; + sqlite3_snprintf(sizeof(p->outfile), p->outfile, "stdout"); + }else{ + p->out = fopen(azArg[1], "wb"); + if( p->out==0 ){ + fprintf(stderr,"can't write to \"%s\"\n", azArg[1]); + p->out = stdout; + } else { + sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", azArg[1]); + } + } + }else + + if( c=='p' && strncmp(azArg[0], "prompt", n)==0 && (nArg==2 || nArg==3)){ + if( nArg >= 2) { + strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1); + } + if( nArg >= 3) { + strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1); + } + }else + + if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){ + rc = 2; + }else + + if( c=='r' && strncmp(azArg[0], "read", n)==0 && nArg==2 ){ + FILE *alt = fopen(azArg[1], "rb"); + if( alt==0 ){ + fprintf(stderr,"can't open \"%s\"\n", azArg[1]); + }else{ + process_input(p, alt); + fclose(alt); + } + }else + + if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ + struct callback_data data; + char *zErrMsg = 0; + open_db(p); + memcpy(&data, p, sizeof(data)); + data.showHeader = 0; + data.mode = MODE_Semi; + if( nArg>1 ){ + int i; + for(i=0; azArg[1][i]; i++) azArg[1][i] = tolower(azArg[1][i]); + if( strcmp(azArg[1],"sqlite_master")==0 ){ + char *new_argv[2], *new_colv[2]; + new_argv[0] = "CREATE TABLE sqlite_master (\n" + " type text,\n" + " name text,\n" + " tbl_name text,\n" + " rootpage integer,\n" + " sql text\n" + ")"; + new_argv[1] = 0; + new_colv[0] = "sql"; + new_colv[1] = 0; + callback(&data, 1, new_argv, new_colv); + }else if( strcmp(azArg[1],"sqlite_temp_master")==0 ){ + char *new_argv[2], *new_colv[2]; + new_argv[0] = "CREATE TEMP TABLE sqlite_temp_master (\n" + " type text,\n" + " name text,\n" + " tbl_name text,\n" + " rootpage integer,\n" + " sql text\n" + ")"; + new_argv[1] = 0; + new_colv[0] = "sql"; + new_colv[1] = 0; + callback(&data, 1, new_argv, new_colv); + }else{ + zShellStatic = azArg[1]; + sqlite3_exec(p->db, + "SELECT sql FROM " + " (SELECT * FROM sqlite_master UNION ALL" + " SELECT * FROM sqlite_temp_master) " + "WHERE tbl_name LIKE shellstatic() AND type!='meta' AND sql NOTNULL " + "ORDER BY substr(type,2,1), name", + callback, &data, &zErrMsg); + zShellStatic = 0; + } + }else{ + sqlite3_exec(p->db, + "SELECT sql FROM " + " (SELECT * FROM sqlite_master UNION ALL" + " SELECT * FROM sqlite_temp_master) " + "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%'" + "ORDER BY substr(type,2,1), name", + callback, &data, &zErrMsg + ); + } + if( zErrMsg ){ + fprintf(stderr,"Error: %s\n", zErrMsg); + sqlite3_free(zErrMsg); + } + }else + + if( c=='s' && strncmp(azArg[0], "separator", n)==0 && nArg==2 ){ + sqlite3_snprintf(sizeof(p->separator), p->separator, + "%.*s", (int)sizeof(p->separator)-1, azArg[1]); + }else + + if( c=='s' && strncmp(azArg[0], "show", n)==0){ + int i; + fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off"); + fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off"); + fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off"); + fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]); + fprintf(p->out,"%9.9s: ", "nullvalue"); + output_c_string(p->out, p->nullvalue); + fprintf(p->out, "\n"); + fprintf(p->out,"%9.9s: %s\n","output", + strlen(p->outfile) ? p->outfile : "stdout"); + fprintf(p->out,"%9.9s: ", "separator"); + output_c_string(p->out, p->separator); + fprintf(p->out, "\n"); + fprintf(p->out,"%9.9s: ","width"); + for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) { + fprintf(p->out,"%d ",p->colWidth[i]); + } + fprintf(p->out,"\n"); + }else + + if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){ + char **azResult; + int nRow, rc; + char *zErrMsg; + open_db(p); + if( nArg==1 ){ + rc = sqlite3_get_table(p->db, + "SELECT name FROM sqlite_master " + "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%'" + "UNION ALL " + "SELECT name FROM sqlite_temp_master " + "WHERE type IN ('table','view') " + "ORDER BY 1", + &azResult, &nRow, 0, &zErrMsg + ); + }else{ + zShellStatic = azArg[1]; + rc = sqlite3_get_table(p->db, + "SELECT name FROM sqlite_master " + "WHERE type IN ('table','view') AND name LIKE '%'||shellstatic()||'%' " + "UNION ALL " + "SELECT name FROM sqlite_temp_master " + "WHERE type IN ('table','view') AND name LIKE '%'||shellstatic()||'%' " + "ORDER BY 1", + &azResult, &nRow, 0, &zErrMsg + ); + zShellStatic = 0; + } + if( zErrMsg ){ + fprintf(stderr,"Error: %s\n", zErrMsg); + sqlite3_free(zErrMsg); + } + if( rc==SQLITE_OK ){ + int len, maxlen = 0; + int i, j; + int nPrintCol, nPrintRow; + for(i=1; i<=nRow; i++){ + if( azResult[i]==0 ) continue; + len = strlen(azResult[i]); + if( len>maxlen ) maxlen = len; + } + nPrintCol = 80/(maxlen+2); + if( nPrintCol<1 ) nPrintCol = 1; + nPrintRow = (nRow + nPrintCol - 1)/nPrintCol; + for(i=0; i<nPrintRow; i++){ + for(j=i+1; j<=nRow; j+=nPrintRow){ + char *zSp = j<=nPrintRow ? "" : " "; + printf("%s%-*s", zSp, maxlen, azResult[j] ? azResult[j] : ""); + } + printf("\n"); + } + }else{ + rc = 1; + } + sqlite3_free_table(azResult); + }else + + if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 && nArg>=2 ){ + open_db(p); + sqlite3_busy_timeout(p->db, atoi(azArg[1])); + }else + +#if HAS_TIMER + if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 && nArg>1 ){ + enableTimer = booleanValue(azArg[1]); + }else +#endif + + if( c=='w' && strncmp(azArg[0], "width", n)==0 ){ + int j; + assert( nArg<=ArraySize(azArg) ); + for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){ + p->colWidth[j-1] = atoi(azArg[j]); + } + }else + + + { + fprintf(stderr, "unknown command or invalid arguments: " + " \"%s\". Enter \".help\" for help\n", azArg[0]); + } + + return rc; +} + +/* +** Return TRUE if a semicolon occurs anywhere in the first N characters +** of string z[]. +*/ +static int _contains_semicolon(const char *z, int N){ + int i; + for(i=0; i<N; i++){ if( z[i]==';' ) return 1; } + return 0; +} + +/* +** Test to see if a line consists entirely of whitespace. +*/ +static int _all_whitespace(const char *z){ + for(; *z; z++){ + if( isspace(*(unsigned char*)z) ) continue; + if( *z=='/' && z[1]=='*' ){ + z += 2; + while( *z && (*z!='*' || z[1]!='/') ){ z++; } + if( *z==0 ) return 0; + z++; + continue; + } + if( *z=='-' && z[1]=='-' ){ + z += 2; + while( *z && *z!='\n' ){ z++; } + if( *z==0 ) return 1; + continue; + } + return 0; + } + return 1; +} + +/* +** Return TRUE if the line typed in is an SQL command terminator other +** than a semi-colon. The SQL Server style "go" command is understood +** as is the Oracle "/". +*/ +static int _is_command_terminator(const char *zLine){ + while( isspace(*(unsigned char*)zLine) ){ zLine++; }; + if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ) return 1; /* Oracle */ + if( tolower(zLine[0])=='g' && tolower(zLine[1])=='o' + && _all_whitespace(&zLine[2]) ){ + return 1; /* SQL Server */ + } + return 0; +} + +/* +** Read input from *in and process it. If *in==0 then input +** is interactive - the user is typing it it. Otherwise, input +** is coming from a file or device. A prompt is issued and history +** is saved only if input is interactive. An interrupt signal will +** cause this routine to exit immediately, unless input is interactive. +** +** Return the number of errors. +*/ +static int process_input(struct callback_data *p, FILE *in){ + char *zLine = 0; + char *zSql = 0; + int nSql = 0; + int nSqlPrior = 0; + char *zErrMsg; + int rc; + int errCnt = 0; + int lineno = 0; + int startline = 0; + + while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){ + fflush(p->out); + free(zLine); + zLine = one_input_line(zSql, in); + if( zLine==0 ){ + break; /* We have reached EOF */ + } + if( seenInterrupt ){ + if( in!=0 ) break; + seenInterrupt = 0; + } + lineno++; + if( p->echoOn ) printf("%s\n", zLine); + if( (zSql==0 || zSql[0]==0) && _all_whitespace(zLine) ) continue; + if( zLine && zLine[0]=='.' && nSql==0 ){ + rc = do_meta_command(zLine, p); + if( rc==2 ){ + break; + }else if( rc ){ + errCnt++; + } + continue; + } + if( _is_command_terminator(zLine) ){ + memcpy(zLine,";",2); + } + nSqlPrior = nSql; + if( zSql==0 ){ + int i; + for(i=0; zLine[i] && isspace((unsigned char)zLine[i]); i++){} + if( zLine[i]!=0 ){ + nSql = strlen(zLine); + zSql = malloc( nSql+1 ); + if( zSql==0 ){ + fprintf(stderr, "out of memory\n"); + exit(1); + } + memcpy(zSql, zLine, nSql+1); + startline = lineno; + } + }else{ + int len = strlen(zLine); + zSql = realloc( zSql, nSql + len + 2 ); + if( zSql==0 ){ + fprintf(stderr,"%s: out of memory!\n", Argv0); + exit(1); + } + zSql[nSql++] = '\n'; + memcpy(&zSql[nSql], zLine, len+1); + nSql += len; + } + if( zSql && _contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior) + && sqlite3_complete(zSql) ){ + p->cnt = 0; + open_db(p); + BEGIN_TIMER; + rc = sqlite3_exec(p->db, zSql, callback, p, &zErrMsg); + END_TIMER; + if( rc || zErrMsg ){ + char zPrefix[100]; + if( in!=0 || !stdin_is_interactive ){ + sqlite3_snprintf(sizeof(zPrefix), zPrefix, + "SQL error near line %d:", startline); + }else{ + sqlite3_snprintf(sizeof(zPrefix), zPrefix, "SQL error:"); + } + if( zErrMsg!=0 ){ + printf("%s %s\n", zPrefix, zErrMsg); + sqlite3_free(zErrMsg); + zErrMsg = 0; + }else{ + printf("%s %s\n", zPrefix, sqlite3_errmsg(p->db)); + } + errCnt++; + } + free(zSql); + zSql = 0; + nSql = 0; + } + } + if( zSql ){ + if( !_all_whitespace(zSql) ) printf("Incomplete SQL: %s\n", zSql); + free(zSql); + } + free(zLine); + return errCnt; +} + +/* +** Return a pathname which is the user's home directory. A +** 0 return indicates an error of some kind. Space to hold the +** resulting string is obtained from malloc(). The calling +** function should free the result. +*/ +static char *find_home_dir(void){ + char *home_dir = NULL; + +#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) && !defined(_WIN32_WCE) + struct passwd *pwent; + uid_t uid = getuid(); + if( (pwent=getpwuid(uid)) != NULL) { + home_dir = pwent->pw_dir; + } +#endif + +#if defined(_WIN32_WCE) + /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv() + */ + home_dir = strdup("/"); +#else + +#if defined(_WIN32) || defined(WIN32) || defined(__OS2__) + if (!home_dir) { + home_dir = getenv("USERPROFILE"); + } +#endif + + if (!home_dir) { + home_dir = getenv("HOME"); + } + +#if defined(_WIN32) || defined(WIN32) || defined(__OS2__) + if (!home_dir) { + char *zDrive, *zPath; + int n; + zDrive = getenv("HOMEDRIVE"); + zPath = getenv("HOMEPATH"); + if( zDrive && zPath ){ + n = strlen(zDrive) + strlen(zPath) + 1; + home_dir = malloc( n ); + if( home_dir==0 ) return 0; + sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath); + return home_dir; + } + home_dir = "c:\\"; + } +#endif + +#endif /* !_WIN32_WCE */ + + if( home_dir ){ + int n = strlen(home_dir) + 1; + char *z = malloc( n ); + if( z ) memcpy(z, home_dir, n); + home_dir = z; + } + + return home_dir; +} + +/* +** Read input from the file given by sqliterc_override. Or if that +** parameter is NULL, take input from ~/.sqliterc +*/ +static void process_sqliterc( + struct callback_data *p, /* Configuration data */ + const char *sqliterc_override /* Name of config file. NULL to use default */ +){ + char *home_dir = NULL; + const char *sqliterc = sqliterc_override; + char *zBuf = 0; + FILE *in = NULL; + int nBuf; + + if (sqliterc == NULL) { + home_dir = find_home_dir(); + if( home_dir==0 ){ + fprintf(stderr,"%s: cannot locate your home directory!\n", Argv0); + return; + } + nBuf = strlen(home_dir) + 16; + zBuf = malloc( nBuf ); + if( zBuf==0 ){ + fprintf(stderr,"%s: out of memory!\n", Argv0); + exit(1); + } + sqlite3_snprintf(nBuf, zBuf,"%s/.sqliterc",home_dir); + free(home_dir); + sqliterc = (const char*)zBuf; + } + in = fopen(sqliterc,"rb"); + if( in ){ + if( stdin_is_interactive ){ + printf("-- Loading resources from %s\n",sqliterc); + } + process_input(p,in); + fclose(in); + } + free(zBuf); + return; +} + +/* +** Show available command line options +*/ +static const char zOptions[] = + " -init filename read/process named file\n" + " -echo print commands before execution\n" + " -[no]header turn headers on or off\n" + " -bail stop after hitting an error\n" + " -interactive force interactive I/O\n" + " -batch force batch I/O\n" + " -column set output mode to 'column'\n" + " -csv set output mode to 'csv'\n" + " -html set output mode to HTML\n" + " -line set output mode to 'line'\n" + " -list set output mode to 'list'\n" + " -separator 'x' set output field separator (|)\n" + " -nullvalue 'text' set text string for NULL values\n" + " -version show SQLite version\n" +; +static void usage(int showDetail){ + fprintf(stderr, + "Usage: %s [OPTIONS] FILENAME [SQL]\n" + "FILENAME is the name of an SQLite database. A new database is created\n" + "if the file does not previously exist.\n", Argv0); + if( showDetail ){ + fprintf(stderr, "OPTIONS include:\n%s", zOptions); + }else{ + fprintf(stderr, "Use the -help option for additional information\n"); + } + exit(1); +} + +/* +** Initialize the state information in data +*/ +static void main_init(struct callback_data *data) { + memset(data, 0, sizeof(*data)); + data->mode = MODE_List; + memcpy(data->separator,"|", 2); + data->showHeader = 0; + sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> "); + sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> "); +} + +int main(int argc, char **argv){ + char *zErrMsg = 0; + struct callback_data data; + const char *zInitFile = 0; + char *zFirstCmd = 0; + int i; + int rc = 0; + + /* Begin evanm patch. */ +#ifdef SQLITE_GEARS_DISABLE_SHELL_ICU + /* Gears doesn't use this. */ +#else + extern int sqlite_shell_init_icu(); + if( !sqlite_shell_init_icu() ){ + fprintf(stderr, "%s: warning: couldn't find icudt38.dll; " + "queries against ICU FTS tables will fail.\n", argv[0]); + } +#endif + /* End evanm patch. */ + + Argv0 = argv[0]; + main_init(&data); + stdin_is_interactive = isatty(0); + + /* Make sure we have a valid signal handler early, before anything + ** else is done. + */ +#ifdef SIGINT + signal(SIGINT, interrupt_handler); +#endif + + /* Do an initial pass through the command-line argument to locate + ** the name of the database file, the name of the initialization file, + ** and the first command to execute. + */ + for(i=1; i<argc-1; i++){ + char *z; + if( argv[i][0]!='-' ) break; + z = argv[i]; + if( z[0]=='-' && z[1]=='-' ) z++; + if( strcmp(argv[i],"-separator")==0 || strcmp(argv[i],"-nullvalue")==0 ){ + i++; + }else if( strcmp(argv[i],"-init")==0 ){ + i++; + zInitFile = argv[i]; + } + } + if( i<argc ){ +#if defined(SQLITE_OS_OS2) && SQLITE_OS_OS2 + data.zDbFilename = (const char *)convertCpPathToUtf8( argv[i++] ); +#else + data.zDbFilename = argv[i++]; +#endif + }else{ +#ifndef SQLITE_OMIT_MEMORYDB + data.zDbFilename = ":memory:"; +#else + data.zDbFilename = 0; +#endif + } + if( i<argc ){ + zFirstCmd = argv[i++]; + } + data.out = stdout; + +#ifdef SQLITE_OMIT_MEMORYDB + if( data.zDbFilename==0 ){ + fprintf(stderr,"%s: no database filename specified\n", argv[0]); + exit(1); + } +#endif + + /* Go ahead and open the database file if it already exists. If the + ** file does not exist, delay opening it. This prevents empty database + ** files from being created if a user mistypes the database name argument + ** to the sqlite command-line tool. + */ + if( access(data.zDbFilename, 0)==0 ){ + open_db(&data); + } + + /* Process the initialization file if there is one. If no -init option + ** is given on the command line, look for a file named ~/.sqliterc and + ** try to process it. + */ + process_sqliterc(&data,zInitFile); + + /* Make a second pass through the command-line argument and set + ** options. This second pass is delayed until after the initialization + ** file is processed so that the command-line arguments will override + ** settings in the initialization file. + */ + for(i=1; i<argc && argv[i][0]=='-'; i++){ + char *z = argv[i]; + if( z[1]=='-' ){ z++; } + if( strcmp(z,"-init")==0 ){ + i++; + }else if( strcmp(z,"-html")==0 ){ + data.mode = MODE_Html; + }else if( strcmp(z,"-list")==0 ){ + data.mode = MODE_List; + }else if( strcmp(z,"-line")==0 ){ + data.mode = MODE_Line; + }else if( strcmp(z,"-column")==0 ){ + data.mode = MODE_Column; + }else if( strcmp(z,"-csv")==0 ){ + data.mode = MODE_Csv; + memcpy(data.separator,",",2); + }else if( strcmp(z,"-separator")==0 ){ + i++; + sqlite3_snprintf(sizeof(data.separator), data.separator, + "%.*s",(int)sizeof(data.separator)-1,argv[i]); + }else if( strcmp(z,"-nullvalue")==0 ){ + i++; + sqlite3_snprintf(sizeof(data.nullvalue), data.nullvalue, + "%.*s",(int)sizeof(data.nullvalue)-1,argv[i]); + }else if( strcmp(z,"-header")==0 ){ + data.showHeader = 1; + }else if( strcmp(z,"-noheader")==0 ){ + data.showHeader = 0; + }else if( strcmp(z,"-echo")==0 ){ + data.echoOn = 1; + }else if( strcmp(z,"-bail")==0 ){ + bail_on_error = 1; + }else if( strcmp(z,"-version")==0 ){ + printf("%s\n", sqlite3_libversion()); + return 0; + }else if( strcmp(z,"-interactive")==0 ){ + stdin_is_interactive = 1; + }else if( strcmp(z,"-batch")==0 ){ + stdin_is_interactive = 0; + }else if( strcmp(z,"-help")==0 || strcmp(z, "--help")==0 ){ + usage(1); + }else{ + fprintf(stderr,"%s: unknown option: %s\n", Argv0, z); + fprintf(stderr,"Use -help for a list of options.\n"); + return 1; + } + } + + if( zFirstCmd ){ + /* Run just the command that follows the database name + */ + if( zFirstCmd[0]=='.' ){ + do_meta_command(zFirstCmd, &data); + exit(0); + }else{ + int rc; + open_db(&data); + rc = sqlite3_exec(data.db, zFirstCmd, callback, &data, &zErrMsg); + if( rc!=0 && zErrMsg!=0 ){ + fprintf(stderr,"SQL error: %s\n", zErrMsg); + exit(1); + } + } + }else{ + /* Run commands received from standard input + */ + if( stdin_is_interactive ){ + char *zHome; + char *zHistory = 0; + int nHistory; + printf( + "SQLite version %s\n" + "Enter \".help\" for instructions\n" + "Enter SQL statements terminated with a \";\"\n", + sqlite3_libversion() + ); + zHome = find_home_dir(); + if( zHome && (zHistory = malloc(nHistory = strlen(zHome)+20))!=0 ){ + sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome); + } +#if defined(HAVE_READLINE) && HAVE_READLINE==1 + if( zHistory ) read_history(zHistory); +#endif + rc = process_input(&data, 0); + if( zHistory ){ + stifle_history(100); + write_history(zHistory); + free(zHistory); + } + free(zHome); + }else{ + rc = process_input(&data, stdin); + } + } + set_table_name(&data, 0); + if( db ){ + if( sqlite3_close(db)!=SQLITE_OK ){ + fprintf(stderr,"error closing database: %s\n", sqlite3_errmsg(db)); + } + } + return rc; +} diff --git a/third_party/sqlite/src/shell_icu.c b/third_party/sqlite/src/shell_icu.c new file mode 100755 index 0000000..d68cf8f --- /dev/null +++ b/third_party/sqlite/src/shell_icu.c @@ -0,0 +1,29 @@ +/* Copyright 2007 Google Inc. All Rights Reserved. +**/ + +#include <windows.h> +#include "unicode/udata.h" + +/* +** This function attempts to load the ICU data tables from a DLL. +** Returns 0 on failure, nonzero on success. +** This a hack job of icu_utils.cc:Initialize(). It's Chrome-specific code. +*/ +int sqlite_shell_init_icu() { + HMODULE module; + FARPROC addr; + UErrorCode err; + + module = LoadLibrary(L"icudt38.dll"); + if (!module) + return 0; + + addr = GetProcAddress(module, "icudt38_dat"); + if (!addr) + return 0; + + err = U_ZERO_ERROR; + udata_setCommonData(addr, &err); + + return 1; +} diff --git a/third_party/sqlite/src/sqlite.h.in b/third_party/sqlite/src/sqlite.h.in new file mode 100755 index 0000000..d37b251 --- /dev/null +++ b/third_party/sqlite/src/sqlite.h.in @@ -0,0 +1,6294 @@ +/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This header file defines the interface that the SQLite library
+** presents to client programs. If a C-function, structure, datatype,
+** or constant definition does not appear in this file, then it is
+** not a published API of SQLite, is subject to change without
+** notice, and should not be referenced by programs that use SQLite.
+**
+** Some of the definitions that are in this file are marked as
+** "experimental". Experimental interfaces are normally new
+** features recently added to SQLite. We do not anticipate changes
+** to experimental interfaces but reserve to make minor changes if
+** experience from use "in the wild" suggest such changes are prudent.
+**
+** The official C-language API documentation for SQLite is derived
+** from comments in this file. This file is the authoritative source
+** on how SQLite interfaces are suppose to operate.
+**
+** The name of this file under configuration management is "sqlite.h.in".
+** The makefile makes some minor changes to this file (such as inserting
+** the version number) and changes its name to "sqlite3.h" as
+** part of the build process.
+**
+** @(#) $Id: sqlite.h.in,v 1.388 2008/08/06 13:40:13 danielk1977 Exp $
+*/
+#ifndef _SQLITE3_H_
+#define _SQLITE3_H_
+#include <stdarg.h> /* Needed for the definition of va_list */
+
+/*
+** Make sure we can call this stuff from C++.
+*/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*
+** Add the ability to override 'extern'
+*/
+#ifndef SQLITE_EXTERN
+# define SQLITE_EXTERN extern
+#endif
+
+/*
+** Ensure these symbols were not defined by some previous header file.
+*/
+#ifdef SQLITE_VERSION
+# undef SQLITE_VERSION
+#endif
+#ifdef SQLITE_VERSION_NUMBER
+# undef SQLITE_VERSION_NUMBER
+#endif
+
+/*
+** CAPI3REF: Compile-Time Library Version Numbers {H10010} <S60100>
+**
+** The SQLITE_VERSION and SQLITE_VERSION_NUMBER #defines in
+** the sqlite3.h file specify the version of SQLite with which
+** that header file is associated.
+**
+** The "version" of SQLite is a string of the form "X.Y.Z".
+** The phrase "alpha" or "beta" might be appended after the Z.
+** The X value is major version number always 3 in SQLite3.
+** The X value only changes when backwards compatibility is
+** broken and we intend to never break backwards compatibility.
+** The Y value is the minor version number and only changes when
+** there are major feature enhancements that are forwards compatible
+** but not backwards compatible.
+** The Z value is the release number and is incremented with
+** each release but resets back to 0 whenever Y is incremented.
+**
+** See also: [sqlite3_libversion()] and [sqlite3_libversion_number()].
+**
+** INVARIANTS:
+**
+** {H10011} The SQLITE_VERSION #define in the sqlite3.h header file shall
+** evaluate to a string literal that is the SQLite version
+** with which the header file is associated.
+**
+** {H10014} The SQLITE_VERSION_NUMBER #define shall resolve to an integer
+** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z
+** are the major version, minor version, and release number.
+*/
+#define SQLITE_VERSION "--VERS--"
+#define SQLITE_VERSION_NUMBER --VERSION-NUMBER--
+
+/*
+** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100>
+** KEYWORDS: sqlite3_version
+**
+** These features provide the same information as the [SQLITE_VERSION]
+** and [SQLITE_VERSION_NUMBER] #defines in the header, but are associated
+** with the library instead of the header file. Cautious programmers might
+** include a check in their application to verify that
+** sqlite3_libversion_number() always returns the value
+** [SQLITE_VERSION_NUMBER].
+**
+** The sqlite3_libversion() function returns the same information as is
+** in the sqlite3_version[] string constant. The function is provided
+** for use in DLLs since DLL users usually do not have direct access to string
+** constants within the DLL.
+**
+** INVARIANTS:
+**
+** {H10021} The [sqlite3_libversion_number()] interface shall return
+** an integer equal to [SQLITE_VERSION_NUMBER].
+**
+** {H10022} The [sqlite3_version] string constant shall contain
+** the text of the [SQLITE_VERSION] string.
+**
+** {H10023} The [sqlite3_libversion()] function shall return
+** a pointer to the [sqlite3_version] string constant.
+*/
+SQLITE_EXTERN const char sqlite3_version[];
+const char *sqlite3_libversion(void);
+int sqlite3_libversion_number(void);
+
+/*
+** CAPI3REF: Test To See If The Library Is Threadsafe {H10100} <S60100>
+**
+** SQLite can be compiled with or without mutexes. When
+** the [SQLITE_THREADSAFE] C preprocessor macro is true, mutexes
+** are enabled and SQLite is threadsafe. When that macro is false,
+** the mutexes are omitted. Without the mutexes, it is not safe
+** to use SQLite concurrently from more than one thread.
+**
+** Enabling mutexes incurs a measurable performance penalty.
+** So if speed is of utmost importance, it makes sense to disable
+** the mutexes. But for maximum safety, mutexes should be enabled.
+** The default behavior is for mutexes to be enabled.
+**
+** This interface can be used by a program to make sure that the
+** version of SQLite that it is linking against was compiled with
+** the desired setting of the [SQLITE_THREADSAFE] macro.
+**
+** This interface only reports on the compile-time mutex setting
+** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with
+** SQLITE_THREADSAFE=1 then mutexes are enabled by default but
+** can be fully or partially disabled using a call to [sqlite3_config()]
+** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD],
+** or [SQLITE_CONFIG_MUTEX]. The return value of this function shows
+** only the default compile-time setting, not any run-time changes
+** to that setting.
+**
+** INVARIANTS:
+**
+** {H10101} The [sqlite3_threadsafe()] function shall return nonzero if
+** SQLite was compiled with the its mutexes enabled by default
+** or zero if SQLite was compiled such that mutexes are
+** permanently disabled.
+**
+** {H10102} The value returned by the [sqlite3_threadsafe()] function
+** shall not change when mutex setting are modified at
+** runtime using the [sqlite3_config()] interface and
+** especially the [SQLITE_CONFIG_SINGLETHREAD],
+** [SQLITE_CONFIG_MULTITHREAD], [SQLITE_CONFIG_SERIALIZED],
+** and [SQLITE_CONFIG_MUTEX] verbs.
+*/
+int sqlite3_threadsafe(void);
+
+/*
+** CAPI3REF: Database Connection Handle {H12000} <S40200>
+** KEYWORDS: {database connection} {database connections}
+**
+** Each open SQLite database is represented by a pointer to an instance of
+** the opaque structure named "sqlite3". It is useful to think of an sqlite3
+** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and
+** [sqlite3_open_v2()] interfaces are its constructors, and [sqlite3_close()]
+** is its destructor. There are many other interfaces (such as
+** [sqlite3_prepare_v2()], [sqlite3_create_function()], and
+** [sqlite3_busy_timeout()] to name but three) that are methods on an
+** sqlite3 object.
+*/
+typedef struct sqlite3 sqlite3;
+
+/*
+** CAPI3REF: 64-Bit Integer Types {H10200} <S10110>
+** KEYWORDS: sqlite_int64 sqlite_uint64
+**
+** Because there is no cross-platform way to specify 64-bit integer types
+** SQLite includes typedefs for 64-bit signed and unsigned integers.
+**
+** The sqlite3_int64 and sqlite3_uint64 are the preferred type definitions.
+** The sqlite_int64 and sqlite_uint64 types are supported for backwards
+** compatibility only.
+**
+** INVARIANTS:
+**
+** {H10201} The [sqlite_int64] and [sqlite3_int64] type shall specify
+** a 64-bit signed integer.
+**
+** {H10202} The [sqlite_uint64] and [sqlite3_uint64] type shall specify
+** a 64-bit unsigned integer.
+*/
+#ifdef SQLITE_INT64_TYPE
+ typedef SQLITE_INT64_TYPE sqlite_int64;
+ typedef unsigned SQLITE_INT64_TYPE sqlite_uint64;
+#elif defined(_MSC_VER) || defined(__BORLANDC__)
+ typedef __int64 sqlite_int64;
+ typedef unsigned __int64 sqlite_uint64;
+#else
+ typedef long long int sqlite_int64;
+ typedef unsigned long long int sqlite_uint64;
+#endif
+typedef sqlite_int64 sqlite3_int64;
+typedef sqlite_uint64 sqlite3_uint64;
+
+/*
+** If compiling for a processor that lacks floating point support,
+** substitute integer for floating-point.
+*/
+#ifdef SQLITE_OMIT_FLOATING_POINT
+# define double sqlite3_int64
+#endif
+
+/*
+** CAPI3REF: Closing A Database Connection {H12010} <S30100><S40200>
+**
+** This routine is the destructor for the [sqlite3] object.
+**
+** Applications should [sqlite3_finalize | finalize] all [prepared statements]
+** and [sqlite3_blob_close | close] all [BLOB handles] associated with
+** the [sqlite3] object prior to attempting to close the object.
+** The [sqlite3_next_stmt()] interface can be used to locate all
+** [prepared statements] associated with a [database connection] if desired.
+** Typical code might look like this:
+**
+** <blockquote><pre>
+** sqlite3_stmt *pStmt;
+** while( (pStmt = sqlite3_next_stmt(db, 0))!=0 ){
+** sqlite3_finalize(pStmt);
+** }
+** </pre></blockquote>
+**
+** If [sqlite3_close()] is invoked while a transaction is open,
+** the transaction is automatically rolled back.
+**
+** INVARIANTS:
+**
+** {H12011} A successful call to [sqlite3_close(C)] shall destroy the
+** [database connection] object C.
+**
+** {H12012} A successful call to [sqlite3_close(C)] shall return SQLITE_OK.
+**
+** {H12013} A successful call to [sqlite3_close(C)] shall release all
+** memory and system resources associated with [database connection]
+** C.
+**
+** {H12014} A call to [sqlite3_close(C)] on a [database connection] C that
+** has one or more open [prepared statements] shall fail with
+** an [SQLITE_BUSY] error code.
+**
+** {H12015} A call to [sqlite3_close(C)] where C is a NULL pointer shall
+** return SQLITE_OK.
+**
+** {H12019} When [sqlite3_close(C)] is invoked on a [database connection] C
+** that has a pending transaction, the transaction shall be
+** rolled back.
+**
+** ASSUMPTIONS:
+**
+** {A12016} The C parameter to [sqlite3_close(C)] must be either a NULL
+** pointer or an [sqlite3] object pointer obtained
+** from [sqlite3_open()], [sqlite3_open16()], or
+** [sqlite3_open_v2()], and not previously closed.
+*/
+int sqlite3_close(sqlite3 *);
+
+/*
+** The type for a callback function.
+** This is legacy and deprecated. It is included for historical
+** compatibility and is not documented.
+*/
+typedef int (*sqlite3_callback)(void*,int,char**, char**);
+
+/*
+** CAPI3REF: One-Step Query Execution Interface {H12100} <S10000>
+**
+** The sqlite3_exec() interface is a convenient way of running one or more
+** SQL statements without having to write a lot of C code. The UTF-8 encoded
+** SQL statements are passed in as the second parameter to sqlite3_exec().
+** The statements are evaluated one by one until either an error or
+** an interrupt is encountered, or until they are all done. The 3rd parameter
+** is an optional callback that is invoked once for each row of any query
+** results produced by the SQL statements. The 5th parameter tells where
+** to write any error messages.
+**
+** The error message passed back through the 5th parameter is held
+** in memory obtained from [sqlite3_malloc()]. To avoid a memory leak,
+** the calling application should call [sqlite3_free()] on any error
+** message returned through the 5th parameter when it has finished using
+** the error message.
+**
+** If the SQL statement in the 2nd parameter is NULL or an empty string
+** or a string containing only whitespace and comments, then no SQL
+** statements are evaluated and the database is not changed.
+**
+** The sqlite3_exec() interface is implemented in terms of
+** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()].
+** The sqlite3_exec() routine does nothing to the database that cannot be done
+** by [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()].
+**
+** INVARIANTS:
+**
+** {H12101} A successful invocation of [sqlite3_exec(D,S,C,A,E)]
+** shall sequentially evaluate all of the UTF-8 encoded,
+** semicolon-separated SQL statements in the zero-terminated
+** string S within the context of the [database connection] D.
+**
+** {H12102} If the S parameter to [sqlite3_exec(D,S,C,A,E)] is NULL then
+** the actions of the interface shall be the same as if the
+** S parameter were an empty string.
+**
+** {H12104} The return value of [sqlite3_exec()] shall be [SQLITE_OK] if all
+** SQL statements run successfully and to completion.
+**
+** {H12105} The return value of [sqlite3_exec()] shall be an appropriate
+** non-zero [error code] if any SQL statement fails.
+**
+** {H12107} If one or more of the SQL statements handed to [sqlite3_exec()]
+** return results and the 3rd parameter is not NULL, then
+** the callback function specified by the 3rd parameter shall be
+** invoked once for each row of result.
+**
+** {H12110} If the callback returns a non-zero value then [sqlite3_exec()]
+** shall abort the SQL statement it is currently evaluating,
+** skip all subsequent SQL statements, and return [SQLITE_ABORT].
+**
+** {H12113} The [sqlite3_exec()] routine shall pass its 4th parameter through
+** as the 1st parameter of the callback.
+**
+** {H12116} The [sqlite3_exec()] routine shall set the 2nd parameter of its
+** callback to be the number of columns in the current row of
+** result.
+**
+** {H12119} The [sqlite3_exec()] routine shall set the 3rd parameter of its
+** callback to be an array of pointers to strings holding the
+** values for each column in the current result set row as
+** obtained from [sqlite3_column_text()].
+**
+** {H12122} The [sqlite3_exec()] routine shall set the 4th parameter of its
+** callback to be an array of pointers to strings holding the
+** names of result columns as obtained from [sqlite3_column_name()].
+**
+** {H12125} If the 3rd parameter to [sqlite3_exec()] is NULL then
+** [sqlite3_exec()] shall silently discard query results.
+**
+** {H12131} If an error occurs while parsing or evaluating any of the SQL
+** statements in the S parameter of [sqlite3_exec(D,S,C,A,E)] and if
+** the E parameter is not NULL, then [sqlite3_exec()] shall store
+** in *E an appropriate error message written into memory obtained
+** from [sqlite3_malloc()].
+**
+** {H12134} The [sqlite3_exec(D,S,C,A,E)] routine shall set the value of
+** *E to NULL if E is not NULL and there are no errors.
+**
+** {H12137} The [sqlite3_exec(D,S,C,A,E)] function shall set the [error code]
+** and message accessible via [sqlite3_errcode()],
+** [sqlite3_errmsg()], and [sqlite3_errmsg16()].
+**
+** {H12138} If the S parameter to [sqlite3_exec(D,S,C,A,E)] is NULL or an
+** empty string or contains nothing other than whitespace, comments,
+** and/or semicolons, then results of [sqlite3_errcode()],
+** [sqlite3_errmsg()], and [sqlite3_errmsg16()]
+** shall reset to indicate no errors.
+**
+** ASSUMPTIONS:
+**
+** {A12141} The first parameter to [sqlite3_exec()] must be an valid and open
+** [database connection].
+**
+** {A12142} The database connection must not be closed while
+** [sqlite3_exec()] is running.
+**
+** {A12143} The calling function should use [sqlite3_free()] to free
+** the memory that *errmsg is left pointing at once the error
+** message is no longer needed.
+**
+** {A12145} The SQL statement text in the 2nd parameter to [sqlite3_exec()]
+** must remain unchanged while [sqlite3_exec()] is running.
+*/
+int sqlite3_exec(
+ sqlite3*, /* An open database */
+ const char *sql, /* SQL to be evaluated */
+ int (*callback)(void*,int,char**,char**), /* Callback function */
+ void *, /* 1st argument to callback */
+ char **errmsg /* Error msg written here */
+);
+
+/*
+** CAPI3REF: Result Codes {H10210} <S10700>
+** KEYWORDS: SQLITE_OK {error code} {error codes}
+** KEYWORDS: {result code} {result codes}
+**
+** Many SQLite functions return an integer result code from the set shown
+** here in order to indicates success or failure.
+**
+** New error codes may be added in future versions of SQLite.
+**
+** See also: [SQLITE_IOERR_READ | extended result codes]
+*/
+#define SQLITE_OK 0 /* Successful result */
+/* beginning-of-error-codes */
+#define SQLITE_ERROR 1 /* SQL error or missing database */
+#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */
+#define SQLITE_PERM 3 /* Access permission denied */
+#define SQLITE_ABORT 4 /* Callback routine requested an abort */
+#define SQLITE_BUSY 5 /* The database file is locked */
+#define SQLITE_LOCKED 6 /* A table in the database is locked */
+#define SQLITE_NOMEM 7 /* A malloc() failed */
+#define SQLITE_READONLY 8 /* Attempt to write a readonly database */
+#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/
+#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */
+#define SQLITE_CORRUPT 11 /* The database disk image is malformed */
+#define SQLITE_NOTFOUND 12 /* NOT USED. Table or record not found */
+#define SQLITE_FULL 13 /* Insertion failed because database is full */
+#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
+#define SQLITE_PROTOCOL 15 /* NOT USED. Database lock protocol error */
+#define SQLITE_EMPTY 16 /* Database is empty */
+#define SQLITE_SCHEMA 17 /* The database schema changed */
+#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */
+#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */
+#define SQLITE_MISMATCH 20 /* Data type mismatch */
+#define SQLITE_MISUSE 21 /* Library used incorrectly */
+#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */
+#define SQLITE_AUTH 23 /* Authorization denied */
+#define SQLITE_FORMAT 24 /* Auxiliary database format error */
+#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */
+#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-error-codes */
+
+/*
+** CAPI3REF: Extended Result Codes {H10220} <S10700>
+** KEYWORDS: {extended error code} {extended error codes}
+** KEYWORDS: {extended result code} {extended result codes}
+**
+** In its default configuration, SQLite API routines return one of 26 integer
+** [SQLITE_OK | result codes]. However, experience has shown that many of
+** these result codes are too coarse-grained. They do not provide as
+** much information about problems as programmers might like. In an effort to
+** address this, newer versions of SQLite (version 3.3.8 and later) include
+** support for additional result codes that provide more detailed information
+** about errors. The extended result codes are enabled or disabled
+** on a per database connection basis using the
+** [sqlite3_extended_result_codes()] API.
+**
+** Some of the available extended result codes are listed here.
+** One may expect the number of extended result codes will be expand
+** over time. Software that uses extended result codes should expect
+** to see new result codes in future releases of SQLite.
+**
+** The SQLITE_OK result code will never be extended. It will always
+** be exactly zero.
+**
+** INVARIANTS:
+**
+** {H10223} The symbolic name for an extended result code shall contains
+** a related primary result code as a prefix.
+**
+** {H10224} Primary result code names shall contain a single "_" character.
+**
+** {H10225} Extended result code names shall contain two or more "_" characters.
+**
+** {H10226} The numeric value of an extended result code shall contain the
+** numeric value of its corresponding primary result code in
+** its least significant 8 bits.
+*/
+#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
+#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
+#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8))
+#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8))
+#define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8))
+#define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8))
+#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8))
+#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8))
+#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8))
+#define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10<<8))
+#define SQLITE_IOERR_BLOCKED (SQLITE_IOERR | (11<<8))
+#define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12<<8))
+#define SQLITE_IOERR_ACCESS (SQLITE_IOERR | (13<<8))
+#define SQLITE_IOERR_CHECKRESERVEDLOCK (SQLITE_IOERR | (14<<8))
+
+/*
+** CAPI3REF: Flags For File Open Operations {H10230} <H11120> <H12700>
+**
+** These bit values are intended for use in the
+** 3rd parameter to the [sqlite3_open_v2()] interface and
+** in the 4th parameter to the xOpen method of the
+** [sqlite3_vfs] object.
+*/
+#define SQLITE_OPEN_READONLY 0x00000001
+#define SQLITE_OPEN_READWRITE 0x00000002
+#define SQLITE_OPEN_CREATE 0x00000004
+#define SQLITE_OPEN_DELETEONCLOSE 0x00000008
+#define SQLITE_OPEN_EXCLUSIVE 0x00000010
+#define SQLITE_OPEN_MAIN_DB 0x00000100
+#define SQLITE_OPEN_TEMP_DB 0x00000200
+#define SQLITE_OPEN_TRANSIENT_DB 0x00000400
+#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800
+#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000
+#define SQLITE_OPEN_SUBJOURNAL 0x00002000
+#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000
+#define SQLITE_OPEN_NOMUTEX 0x00008000
+
+/*
+** CAPI3REF: Device Characteristics {H10240} <H11120>
+**
+** The xDeviceCapabilities method of the [sqlite3_io_methods]
+** object returns an integer which is a vector of the these
+** bit values expressing I/O characteristics of the mass storage
+** device that holds the file that the [sqlite3_io_methods]
+** refers to.
+**
+** The SQLITE_IOCAP_ATOMIC property means that all writes of
+** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values
+** mean that writes of blocks that are nnn bytes in size and
+** are aligned to an address which is an integer multiple of
+** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means
+** that when data is appended to a file, the data is appended
+** first then the size of the file is extended, never the other
+** way around. The SQLITE_IOCAP_SEQUENTIAL property means that
+** information is written to disk in the same order as calls
+** to xWrite().
+*/
+#define SQLITE_IOCAP_ATOMIC 0x00000001
+#define SQLITE_IOCAP_ATOMIC512 0x00000002
+#define SQLITE_IOCAP_ATOMIC1K 0x00000004
+#define SQLITE_IOCAP_ATOMIC2K 0x00000008
+#define SQLITE_IOCAP_ATOMIC4K 0x00000010
+#define SQLITE_IOCAP_ATOMIC8K 0x00000020
+#define SQLITE_IOCAP_ATOMIC16K 0x00000040
+#define SQLITE_IOCAP_ATOMIC32K 0x00000080
+#define SQLITE_IOCAP_ATOMIC64K 0x00000100
+#define SQLITE_IOCAP_SAFE_APPEND 0x00000200
+#define SQLITE_IOCAP_SEQUENTIAL 0x00000400
+
+/*
+** CAPI3REF: File Locking Levels {H10250} <H11120> <H11310>
+**
+** SQLite uses one of these integer values as the second
+** argument to calls it makes to the xLock() and xUnlock() methods
+** of an [sqlite3_io_methods] object.
+*/
+#define SQLITE_LOCK_NONE 0
+#define SQLITE_LOCK_SHARED 1
+#define SQLITE_LOCK_RESERVED 2
+#define SQLITE_LOCK_PENDING 3
+#define SQLITE_LOCK_EXCLUSIVE 4
+
+/*
+** CAPI3REF: Synchronization Type Flags {H10260} <H11120>
+**
+** When SQLite invokes the xSync() method of an
+** [sqlite3_io_methods] object it uses a combination of
+** these integer values as the second argument.
+**
+** When the SQLITE_SYNC_DATAONLY flag is used, it means that the
+** sync operation only needs to flush data to mass storage. Inode
+** information need not be flushed. The SQLITE_SYNC_NORMAL flag means
+** to use normal fsync() semantics. The SQLITE_SYNC_FULL flag means
+** to use Mac OS-X style fullsync instead of fsync().
+*/
+#define SQLITE_SYNC_NORMAL 0x00002
+#define SQLITE_SYNC_FULL 0x00003
+#define SQLITE_SYNC_DATAONLY 0x00010
+
+/*
+** CAPI3REF: OS Interface Open File Handle {H11110} <S20110>
+**
+** An [sqlite3_file] object represents an open file in the OS
+** interface layer. Individual OS interface implementations will
+** want to subclass this object by appending additional fields
+** for their own use. The pMethods entry is a pointer to an
+** [sqlite3_io_methods] object that defines methods for performing
+** I/O operations on the open file.
+*/
+typedef struct sqlite3_file sqlite3_file;
+struct sqlite3_file {
+ const struct sqlite3_io_methods *pMethods; /* Methods for an open file */
+};
+
+/*
+** CAPI3REF: OS Interface File Virtual Methods Object {H11120} <S20110>
+**
+** Every file opened by the [sqlite3_vfs] xOpen method populates an
+** [sqlite3_file] object (or, more commonly, a subclass of the
+** [sqlite3_file] object) with a pointer to an instance of this object.
+** This object defines the methods used to perform various operations
+** against the open file represented by the [sqlite3_file] object.
+**
+** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or
+** [SQLITE_SYNC_FULL]. The first choice is the normal fsync().
+** The second choice is a Mac OS-X style fullsync. The [SQLITE_SYNC_DATAONLY]
+** flag may be ORed in to indicate that only the data of the file
+** and not its inode needs to be synced.
+**
+** The integer values to xLock() and xUnlock() are one of
+** <ul>
+** <li> [SQLITE_LOCK_NONE],
+** <li> [SQLITE_LOCK_SHARED],
+** <li> [SQLITE_LOCK_RESERVED],
+** <li> [SQLITE_LOCK_PENDING], or
+** <li> [SQLITE_LOCK_EXCLUSIVE].
+** </ul>
+** xLock() increases the lock. xUnlock() decreases the lock.
+** The xCheckReservedLock() method checks whether any database connection,
+** either in this process or in some other process, is holding a RESERVED,
+** PENDING, or EXCLUSIVE lock on the file. It returns true
+** if such a lock exists and false otherwise.
+**
+** The xFileControl() method is a generic interface that allows custom
+** VFS implementations to directly control an open file using the
+** [sqlite3_file_control()] interface. The second "op" argument is an
+** integer opcode. The third argument is a generic pointer intended to
+** point to a structure that may contain arguments or space in which to
+** write return values. Potential uses for xFileControl() might be
+** functions to enable blocking locks with timeouts, to change the
+** locking strategy (for example to use dot-file locks), to inquire
+** about the status of a lock, or to break stale locks. The SQLite
+** core reserves all opcodes less than 100 for its own use.
+** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available.
+** Applications that define a custom xFileControl method should use opcodes
+** greater than 100 to avoid conflicts.
+**
+** The xSectorSize() method returns the sector size of the
+** device that underlies the file. The sector size is the
+** minimum write that can be performed without disturbing
+** other bytes in the file. The xDeviceCharacteristics()
+** method returns a bit vector describing behaviors of the
+** underlying device:
+**
+** <ul>
+** <li> [SQLITE_IOCAP_ATOMIC]
+** <li> [SQLITE_IOCAP_ATOMIC512]
+** <li> [SQLITE_IOCAP_ATOMIC1K]
+** <li> [SQLITE_IOCAP_ATOMIC2K]
+** <li> [SQLITE_IOCAP_ATOMIC4K]
+** <li> [SQLITE_IOCAP_ATOMIC8K]
+** <li> [SQLITE_IOCAP_ATOMIC16K]
+** <li> [SQLITE_IOCAP_ATOMIC32K]
+** <li> [SQLITE_IOCAP_ATOMIC64K]
+** <li> [SQLITE_IOCAP_SAFE_APPEND]
+** <li> [SQLITE_IOCAP_SEQUENTIAL]
+** </ul>
+**
+** The SQLITE_IOCAP_ATOMIC property means that all writes of
+** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values
+** mean that writes of blocks that are nnn bytes in size and
+** are aligned to an address which is an integer multiple of
+** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means
+** that when data is appended to a file, the data is appended
+** first then the size of the file is extended, never the other
+** way around. The SQLITE_IOCAP_SEQUENTIAL property means that
+** information is written to disk in the same order as calls
+** to xWrite().
+*/
+typedef struct sqlite3_io_methods sqlite3_io_methods;
+struct sqlite3_io_methods {
+ int iVersion;
+ int (*xClose)(sqlite3_file*);
+ int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
+ int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);
+ int (*xTruncate)(sqlite3_file*, sqlite3_int64 size);
+ int (*xSync)(sqlite3_file*, int flags);
+ int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize);
+ int (*xLock)(sqlite3_file*, int);
+ int (*xUnlock)(sqlite3_file*, int);
+ int (*xCheckReservedLock)(sqlite3_file*, int *pResOut);
+ int (*xFileControl)(sqlite3_file*, int op, void *pArg);
+ int (*xSectorSize)(sqlite3_file*);
+ int (*xDeviceCharacteristics)(sqlite3_file*);
+ /* Additional methods may be added in future releases */
+};
+
+/*
+** CAPI3REF: Standard File Control Opcodes {H11310} <S30800>
+**
+** These integer constants are opcodes for the xFileControl method
+** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
+** interface.
+**
+** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This
+** opcode causes the xFileControl method to write the current state of
+** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED],
+** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE])
+** into an integer that the pArg argument points to. This capability
+** is used during testing and only needs to be supported when SQLITE_TEST
+** is defined.
+*/
+#define SQLITE_FCNTL_LOCKSTATE 1
+
+/*
+** CAPI3REF: Mutex Handle {H17110} <S20130>
+**
+** The mutex module within SQLite defines [sqlite3_mutex] to be an
+** abstract type for a mutex object. The SQLite core never looks
+** at the internal representation of an [sqlite3_mutex]. It only
+** deals with pointers to the [sqlite3_mutex] object.
+**
+** Mutexes are created using [sqlite3_mutex_alloc()].
+*/
+typedef struct sqlite3_mutex sqlite3_mutex;
+
+/*
+** CAPI3REF: OS Interface Object {H11140} <S20100>
+**
+** An instance of the sqlite3_vfs object defines the interface between
+** the SQLite core and the underlying operating system. The "vfs"
+** in the name of the object stands for "virtual file system".
+**
+** The value of the iVersion field is initially 1 but may be larger in
+** future versions of SQLite. Additional fields may be appended to this
+** object when the iVersion value is increased. Note that the structure
+** of the sqlite3_vfs object changes in the transaction between
+** SQLite version 3.5.9 and 3.6.0 and yet the iVersion field was not
+** modified.
+**
+** The szOsFile field is the size of the subclassed [sqlite3_file]
+** structure used by this VFS. mxPathname is the maximum length of
+** a pathname in this VFS.
+**
+** Registered sqlite3_vfs objects are kept on a linked list formed by
+** the pNext pointer. The [sqlite3_vfs_register()]
+** and [sqlite3_vfs_unregister()] interfaces manage this list
+** in a thread-safe way. The [sqlite3_vfs_find()] interface
+** searches the list. Neither the application code nor the VFS
+** implementation should use the pNext pointer.
+**
+** The pNext field is the only field in the sqlite3_vfs
+** structure that SQLite will ever modify. SQLite will only access
+** or modify this field while holding a particular static mutex.
+** The application should never modify anything within the sqlite3_vfs
+** object once the object has been registered.
+**
+** The zName field holds the name of the VFS module. The name must
+** be unique across all VFS modules.
+**
+** {H11141} SQLite will guarantee that the zFilename parameter to xOpen
+** is either a NULL pointer or string obtained
+** from xFullPathname(). SQLite further guarantees that
+** the string will be valid and unchanged until xClose() is
+** called. {END} Because of the previous sentense,
+** the [sqlite3_file] can safely store a pointer to the
+** filename if it needs to remember the filename for some reason.
+** If the zFilename parameter is xOpen is a NULL pointer then xOpen
+** must invite its own temporary name for the file. Whenever the
+** xFilename parameter is NULL it will also be the case that the
+** flags parameter will include [SQLITE_OPEN_DELETEONCLOSE].
+**
+** {H11142} The flags argument to xOpen() includes all bits set in
+** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()]
+** or [sqlite3_open16()] is used, then flags includes at least
+** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. {END}
+** If xOpen() opens a file read-only then it sets *pOutFlags to
+** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be set.
+**
+** {H11143} SQLite will also add one of the following flags to the xOpen()
+** call, depending on the object being opened:
+**
+** <ul>
+** <li> [SQLITE_OPEN_MAIN_DB]
+** <li> [SQLITE_OPEN_MAIN_JOURNAL]
+** <li> [SQLITE_OPEN_TEMP_DB]
+** <li> [SQLITE_OPEN_TEMP_JOURNAL]
+** <li> [SQLITE_OPEN_TRANSIENT_DB]
+** <li> [SQLITE_OPEN_SUBJOURNAL]
+** <li> [SQLITE_OPEN_MASTER_JOURNAL]
+** </ul> {END}
+**
+** The file I/O implementation can use the object type flags to
+** change the way it deals with files. For example, an application
+** that does not care about crash recovery or rollback might make
+** the open of a journal file a no-op. Writes to this journal would
+** also be no-ops, and any attempt to read the journal would return
+** SQLITE_IOERR. Or the implementation might recognize that a database
+** file will be doing page-aligned sector reads and writes in a random
+** order and set up its I/O subsystem accordingly.
+**
+** SQLite might also add one of the following flags to the xOpen method:
+**
+** <ul>
+** <li> [SQLITE_OPEN_DELETEONCLOSE]
+** <li> [SQLITE_OPEN_EXCLUSIVE]
+** </ul>
+**
+** {H11145} The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be
+** deleted when it is closed. {H11146} The [SQLITE_OPEN_DELETEONCLOSE]
+** will be set for TEMP databases, journals and for subjournals.
+**
+** {H11147} The [SQLITE_OPEN_EXCLUSIVE] flag means the file should be opened
+** for exclusive access. This flag is set for all files except
+** for the main database file.
+**
+** {H11148} At least szOsFile bytes of memory are allocated by SQLite
+** to hold the [sqlite3_file] structure passed as the third
+** argument to xOpen. {END} The xOpen method does not have to
+** allocate the structure; it should just fill it in.
+**
+** {H11149} The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS]
+** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to
+** test whether a file is readable and writable, or [SQLITE_ACCESS_READ]
+** to test whether a file is at least readable. {END} The file can be a
+** directory.
+**
+** {H11150} SQLite will always allocate at least mxPathname+1 bytes for the
+** output buffer xFullPathname. {H11151} The exact size of the output buffer
+** is also passed as a parameter to both methods. {END} If the output buffer
+** is not large enough, [SQLITE_CANTOPEN] should be returned. Since this is
+** handled as a fatal error by SQLite, vfs implementations should endeavor
+** to prevent this by setting mxPathname to a sufficiently large value.
+**
+** The xRandomness(), xSleep(), and xCurrentTime() interfaces
+** are not strictly a part of the filesystem, but they are
+** included in the VFS structure for completeness.
+** The xRandomness() function attempts to return nBytes bytes
+** of good-quality randomness into zOut. The return value is
+** the actual number of bytes of randomness obtained.
+** The xSleep() method causes the calling thread to sleep for at
+** least the number of microseconds given. The xCurrentTime()
+** method returns a Julian Day Number for the current date and time.
+*/
+typedef struct sqlite3_vfs sqlite3_vfs;
+struct sqlite3_vfs {
+ int iVersion; /* Structure version number */
+ int szOsFile; /* Size of subclassed sqlite3_file */
+ int mxPathname; /* Maximum file pathname length */
+ sqlite3_vfs *pNext; /* Next registered VFS */
+ const char *zName; /* Name of this virtual file system */
+ void *pAppData; /* Pointer to application-specific data */
+ int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*,
+ int flags, int *pOutFlags);
+ int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir);
+ int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut);
+ int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut);
+ void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename);
+ void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg);
+ void *(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol);
+ void (*xDlClose)(sqlite3_vfs*, void*);
+ int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut);
+ int (*xSleep)(sqlite3_vfs*, int microseconds);
+ int (*xCurrentTime)(sqlite3_vfs*, double*);
+ int (*xGetLastError)(sqlite3_vfs*, int, char *);
+ /* New fields may be appended in figure versions. The iVersion
+ ** value will increment whenever this happens. */
+};
+
+/*
+** CAPI3REF: Flags for the xAccess VFS method {H11190} <H11140>
+**
+** {H11191} These integer constants can be used as the third parameter to
+** the xAccess method of an [sqlite3_vfs] object. {END} They determine
+** what kind of permissions the xAccess method is looking for.
+** {H11192} With SQLITE_ACCESS_EXISTS, the xAccess method
+** simply checks whether the file exists.
+** {H11193} With SQLITE_ACCESS_READWRITE, the xAccess method
+** checks whether the file is both readable and writable.
+** {H11194} With SQLITE_ACCESS_READ, the xAccess method
+** checks whether the file is readable.
+*/
+#define SQLITE_ACCESS_EXISTS 0
+#define SQLITE_ACCESS_READWRITE 1
+#define SQLITE_ACCESS_READ 2
+
+/*
+** CAPI3REF: Initialize The SQLite Library {H10130} <S20000><S30100>
+**
+** The sqlite3_initialize() routine initializes the
+** SQLite library. The sqlite3_shutdown() routine
+** deallocates any resources that were allocated by sqlite3_initialize().
+**
+** A call to sqlite3_initialize() is an "effective" call if it is
+** the first time sqlite3_initialize() is invoked during the lifetime of
+** the process, or if it is the first time sqlite3_initialize() is invoked
+** following a call to sqlite3_shutdown(). Only an effective call
+** of sqlite3_initialize() does any initialization. All other calls
+** are harmless no-ops.
+**
+** Among other things, sqlite3_initialize() shall invoke
+** sqlite3_os_init(). Similarly, sqlite3_shutdown()
+** shall invoke sqlite3_os_end().
+**
+** The sqlite3_initialize() routine returns SQLITE_OK on success.
+** If for some reason, sqlite3_initialize() is unable to initialize
+** the library (perhaps it is unable to allocate a needed resource such
+** as a mutex) it returns an [error code] other than SQLITE_OK.
+**
+** The sqlite3_initialize() routine is called internally by many other
+** SQLite interfaces so that an application usually does not need to
+** invoke sqlite3_initialize() directly. For example, [sqlite3_open()]
+** calls sqlite3_initialize() so the SQLite library will be automatically
+** initialized when [sqlite3_open()] is called if it has not be initialized
+** already. However, if SQLite is compiled with the SQLITE_OMIT_AUTOINIT
+** compile-time option, then the automatic calls to sqlite3_initialize()
+** are omitted and the application must call sqlite3_initialize() directly
+** prior to using any other SQLite interface. For maximum portability,
+** it is recommended that applications always invoke sqlite3_initialize()
+** directly prior to using any other SQLite interface. Future releases
+** of SQLite may require this. In other words, the behavior exhibited
+** when SQLite is compiled with SQLITE_OMIT_AUTOINIT might become the
+** default behavior in some future release of SQLite.
+**
+** The sqlite3_os_init() routine does operating-system specific
+** initialization of the SQLite library. The sqlite3_os_end()
+** routine undoes the effect of sqlite3_os_init(). Typical tasks
+** performed by these routines include allocation or deallocation
+** of static resources, initialization of global variables,
+** setting up a default [sqlite3_vfs] module, or setting up
+** a default configuration using [sqlite3_config()].
+**
+** The application should never invoke either sqlite3_os_init()
+** or sqlite3_os_end() directly. The application should only invoke
+** sqlite3_initialize() and sqlite3_shutdown(). The sqlite3_os_init()
+** interface is called automatically by sqlite3_initialize() and
+** sqlite3_os_end() is called by sqlite3_shutdown(). Appropriate
+** implementations for sqlite3_os_init() and sqlite3_os_end()
+** are built into SQLite when it is compiled for unix, windows, or os/2.
+** When built for other platforms (using the SQLITE_OS_OTHER=1 compile-time
+** option) the application must supply a suitable implementation for
+** sqlite3_os_init() and sqlite3_os_end(). An application-supplied
+** implementation of sqlite3_os_init() or sqlite3_os_end()
+** must return SQLITE_OK on success and some other [error code] upon
+** failure.
+*/
+int sqlite3_initialize(void);
+int sqlite3_shutdown(void);
+int sqlite3_os_init(void);
+int sqlite3_os_end(void);
+
+/*
+** CAPI3REF: Configuring The SQLite Library {H10145} <S20000><S30200>
+** EXPERIMENTAL
+**
+** The sqlite3_config() interface is used to make global configuration
+** changes to SQLite in order to tune SQLite to the specific needs of
+** the application. The default configuration is recommended for most
+** applications and so this routine is usually not necessary. It is
+** provided to support rare applications with unusual needs.
+**
+** The sqlite3_config() interface is not threadsafe. The application
+** must insure that no other SQLite interfaces are invoked by other
+** threads while sqlite3_config() is running. Furthermore, sqlite3_config()
+** may only be invoked prior to library initialization using
+** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()].
+** Note, however, that sqlite3_config() can be called as part of the
+** implementation of an application-defined [sqlite3_os_init()].
+**
+** The first argument to sqlite3_config() is an integer
+** [SQLITE_CONFIG_SINGLETHREAD | configuration option] that determines
+** what property of SQLite is to be configured. Subsequent arguments
+** vary depending on the [SQLITE_CONFIG_SINGLETHREAD | configuration option]
+** in the first argument.
+**
+** When a configuration option is set, sqlite3_config() returns SQLITE_OK.
+** If the option is unknown or SQLite is unable to set the option
+** then this routine returns a non-zero [error code].
+*/
+int sqlite3_config(int, ...);
+
+/*
+** CAPI3REF: Configure database connections {H10180} <S20000>
+** EXPERIMENTAL
+**
+** The sqlite3_db_config() interface is used to make configuration
+** changes to a [database connection]. The interface is similar to
+** [sqlite3_config()] except that the changes apply to a single
+** [database connection] (specified in the first argument). The
+** sqlite3_db_config() interface can only be used immediately after
+** the database connection is created using [sqlite3_open()],
+** [sqlite3_open16()], or [sqlite3_open_v2()].
+**
+** The second argument to sqlite3_db_config(D,V,...) is the
+** configuration verb - an integer code that indicates what
+** aspect of the [database connection] is being configured.
+** The only choice for this value is [SQLITE_DBCONFIG_LOOKASIDE].
+** New verbs are likely to be added in future releases of SQLite.
+** Additional arguments depend on the verb.
+*/
+int sqlite3_db_config(sqlite3*, int op, ...);
+
+/*
+** CAPI3REF: Memory Allocation Routines {H10155} <S20120>
+** EXPERIMENTAL
+**
+** An instance of this object defines the interface between SQLite
+** and low-level memory allocation routines.
+**
+** This object is used in only one place in the SQLite interface.
+** A pointer to an instance of this object is the argument to
+** [sqlite3_config()] when the configuration option is
+** [SQLITE_CONFIG_MALLOC]. By creating an instance of this object
+** and passing it to [sqlite3_config()] during configuration, an
+** application can specify an alternative memory allocation subsystem
+** for SQLite to use for all of its dynamic memory needs.
+**
+** Note that SQLite comes with a built-in memory allocator that is
+** perfectly adequate for the overwhelming majority of applications
+** and that this object is only useful to a tiny minority of applications
+** with specialized memory allocation requirements. This object is
+** also used during testing of SQLite in order to specify an alternative
+** memory allocator that simulates memory out-of-memory conditions in
+** order to verify that SQLite recovers gracefully from such
+** conditions.
+**
+** The xMalloc, xFree, and xRealloc methods must work like the
+** malloc(), free(), and realloc() functions from the standard library.
+**
+** xSize should return the allocated size of a memory allocation
+** previously obtained from xMalloc or xRealloc. The allocated size
+** is always at least as big as the requested size but may be larger.
+**
+** The xRoundup method returns what would be the allocated size of
+** a memory allocation given a particular requested size. Most memory
+** allocators round up memory allocations at least to the next multiple
+** of 8. Some allocators round up to a larger multiple or to a power of 2.
+**
+** The xInit method initializes the memory allocator. (For example,
+** it might allocate any require mutexes or initialize internal data
+** structures. The xShutdown method is invoked (indirectly) by
+** [sqlite3_shutdown()] and should deallocate any resources acquired
+** by xInit. The pAppData pointer is used as the only parameter to
+** xInit and xShutdown.
+*/
+typedef struct sqlite3_mem_methods sqlite3_mem_methods;
+struct sqlite3_mem_methods {
+ void *(*xMalloc)(int); /* Memory allocation function */
+ void (*xFree)(void*); /* Free a prior allocation */
+ void *(*xRealloc)(void*,int); /* Resize an allocation */
+ int (*xSize)(void*); /* Return the size of an allocation */
+ int (*xRoundup)(int); /* Round up request size to allocation size */
+ int (*xInit)(void*); /* Initialize the memory allocator */
+ void (*xShutdown)(void*); /* Deinitialize the memory allocator */
+ void *pAppData; /* Argument to xInit() and xShutdown() */
+};
+
+/*
+** CAPI3REF: Configuration Options {H10160} <S20000>
+** EXPERIMENTAL
+**
+** These constants are the available integer configuration options that
+** can be passed as the first argument to the [sqlite3_config()] interface.
+**
+** New configuration options may be added in future releases of SQLite.
+** Existing configuration options might be discontinued. Applications
+** should check the return code from [sqlite3_config()] to make sure that
+** the call worked. The [sqlite3_config()] interface will return a
+** non-zero [error code] if a discontinued or unsupported configuration option
+** is invoked.
+**
+** <dl>
+** <dt>SQLITE_CONFIG_SINGLETHREAD</dt>
+** <dd>There are no arguments to this option. This option disables
+** all mutexing and puts SQLite into a mode where it can only be used
+** by a single thread.</dd>
+**
+** <dt>SQLITE_CONFIG_MULTITHREAD</dt>
+** <dd>There are no arguments to this option. This option disables
+** mutexing on [database connection] and [prepared statement] objects.
+** The application is responsible for serializing access to
+** [database connections] and [prepared statements]. But other mutexes
+** are enabled so that SQLite will be safe to use in a multi-threaded
+** environment.</dd>
+**
+** <dt>SQLITE_CONFIG_SERIALIZED</dt>
+** <dd>There are no arguments to this option. This option enables
+** all mutexes including the recursive
+** mutexes on [database connection] and [prepared statement] objects.
+** In this mode (which is the default when SQLite is compiled with
+** [SQLITE_THREADSAFE=1]) the SQLite library will itself serialize access
+** to [database connections] and [prepared statements] so that the
+** application is free to use the same [database connection] or the
+** same [prepared statement] in different threads at the same time.
+**
+** <p>This configuration option merely sets the default mutex
+** behavior to serialize access to [database connections]. Individual
+** [database connections] can override this setting
+** using the [SQLITE_OPEN_NOMUTEX] flag to [sqlite3_open_v2()].</p></dd>
+**
+** <dt>SQLITE_CONFIG_MALLOC</dt>
+** <dd>This option takes a single argument which is a pointer to an
+** instance of the [sqlite3_mem_methods] structure. The argument specifies
+** alternative low-level memory allocation routines to be used in place of
+** the memory allocation routines built into SQLite.</dd>
+**
+** <dt>SQLITE_CONFIG_GETMALLOC</dt>
+** <dd>This option takes a single argument which is a pointer to an
+** instance of the [sqlite3_mem_methods] structure. The [sqlite3_mem_methods]
+** structure is filled with the currently defined memory allocation routines.
+** This option can be used to overload the default memory allocation
+** routines with a wrapper that simulations memory allocation failure or
+** tracks memory usage, for example.</dd>
+**
+** <dt>SQLITE_CONFIG_MEMSTATUS</dt>
+** <dd>This option takes single argument of type int, interpreted as a
+** boolean, which enables or disables the collection of memory allocation
+** statistics. When disabled, the following SQLite interfaces become
+** non-operational:
+** <ul>
+** <li> [sqlite3_memory_used()]
+** <li> [sqlite3_memory_highwater()]
+** <li> [sqlite3_soft_heap_limit()]
+** <li> [sqlite3_status()]
+** </ul>
+** </dd>
+**
+** <dt>SQLITE_CONFIG_SCRATCH</dt>
+** <dd>This option specifies a static memory buffer that SQLite can use for
+** scratch memory. There are three arguments: A pointer to the memory, the
+** size of each scratch buffer (sz), and the number of buffers (N). The sz
+** argument must be a multiple of 16. The sz parameter should be a few bytes
+** larger than the actual scratch space required due internal overhead.
+** The first
+** argument should point to an allocation of at least sz*N bytes of memory.
+** SQLite will use no more than one scratch buffer at once per thread, so
+** N should be set to the expected maximum number of threads. The sz
+** parameter should be 6 times the size of the largest database page size.
+** Scratch buffers are used as part of the btree balance operation. If
+** The btree balancer needs additional memory beyond what is provided by
+** scratch buffers or if no scratch buffer space is specified, then SQLite
+** goes to [sqlite3_malloc()] to obtain the memory it needs.</dd>
+**
+** <dt>SQLITE_CONFIG_PAGECACHE</dt>
+** <dd>This option specifies a static memory buffer that SQLite can use for
+** the database page cache. There are three arguments: A pointer to the
+** memory, the size of each page buffer (sz), and the number of pages (N).
+** The sz argument must be a power of two between 512 and 32768. The first
+** argument should point to an allocation of at least sz*N bytes of memory.
+** SQLite will use the memory provided by the first argument to satisfy its
+** memory needs for the first N pages that it adds to cache. If additional
+** page cache memory is needed beyond what is provided by this option, then
+** SQLite goes to [sqlite3_malloc()] for the additional storage space.
+** The implementation might use one or more of the N buffers to hold
+** memory accounting information. </dd>
+**
+** <dt>SQLITE_CONFIG_HEAP</dt>
+** <dd>This option specifies a static memory buffer that SQLite will use
+** for all of its dynamic memory allocation needs beyond those provided
+** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE].
+** There are three arguments: A pointer to the memory, the number of
+** bytes in the memory buffer, and the minimum allocation size. If
+** the first pointer (the memory pointer) is NULL, then SQLite reverts
+** to using its default memory allocator (the system malloc() implementation),
+** undoing any prior invocation of [SQLITE_CONFIG_MALLOC]. If the
+** memory pointer is not NULL and either [SQLITE_ENABLE_MEMSYS3] or
+** [SQLITE_ENABLE_MEMSYS5] are defined, then the alternative memory
+** allocator is engaged to handle all of SQLites memory allocation needs.</dd>
+**
+** <dt>SQLITE_CONFIG_MUTEX</dt>
+** <dd>This option takes a single argument which is a pointer to an
+** instance of the [sqlite3_mutex_methods] structure. The argument specifies
+** alternative low-level mutex routines to be used in place
+** the mutex routines built into SQLite.</dd>
+**
+** <dt>SQLITE_CONFIG_GETMUTEX</dt>
+** <dd>This option takes a single argument which is a pointer to an
+** instance of the [sqlite3_mutex_methods] structure. The
+** [sqlite3_mutex_methods]
+** structure is filled with the currently defined mutex routines.
+** This option can be used to overload the default mutex allocation
+** routines with a wrapper used to track mutex usage for performance
+** profiling or testing, for example.</dd>
+**
+** <dt>SQLITE_CONFIG_LOOKASIDE</dt>
+** <dd>This option takes two arguments that determine the default
+** memory allcation lookaside optimization. The first argument is the
+** size of each lookaside buffer slot and the second is the number of
+** slots allocated to each database connection.</dd>
+**
+** </dl>
+*/
+#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
+#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
+#define SQLITE_CONFIG_SERIALIZED 3 /* nil */
+#define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */
+#define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */
+#define SQLITE_CONFIG_SCRATCH 6 /* void*, int sz, int N */
+#define SQLITE_CONFIG_PAGECACHE 7 /* void*, int sz, int N */
+#define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */
+#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */
+#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */
+#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */
+#define SQLITE_CONFIG_CHUNKALLOC 12 /* int threshold */
+#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */
+
+/*
+** CAPI3REF: Configuration Options {H10170} <S20000>
+** EXPERIMENTAL
+**
+** These constants are the available integer configuration options that
+** can be passed as the second argument to the [sqlite3_db_config()] interface.
+**
+** New configuration options may be added in future releases of SQLite.
+** Existing configuration options might be discontinued. Applications
+** should check the return code from [sqlite3_db_config()] to make sure that
+** the call worked. The [sqlite3_db_config()] interface will return a
+** non-zero [error code] if a discontinued or unsupported configuration option
+** is invoked.
+**
+** <dl>
+** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt>
+** <dd>This option takes three additional arguments that determine the
+** [lookaside memory allocator] configuration for the [database connection].
+** The first argument (the third parameter to [sqlite3_db_config()] is a
+** pointer to a memory buffer to use for lookaside memory. The first
+** argument may be NULL in which case SQLite will allocate the lookaside
+** buffer itself using [sqlite3_malloc()]. The second argument is the
+** size of each lookaside buffer slot and the third argument is the number of
+** slots. The size of the buffer in the first argument must be greater than
+** or equal to the product of the second and third arguments.</dd>
+**
+** </dl>
+*/
+#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
+
+
+/*
+** CAPI3REF: Enable Or Disable Extended Result Codes {H12200} <S10700>
+**
+** The sqlite3_extended_result_codes() routine enables or disables the
+** [extended result codes] feature of SQLite. The extended result
+** codes are disabled by default for historical compatibility considerations.
+**
+** INVARIANTS:
+**
+** {H12201} Each new [database connection] shall have the
+** [extended result codes] feature disabled by default.
+**
+** {H12202} The [sqlite3_extended_result_codes(D,F)] interface shall enable
+** [extended result codes] for the [database connection] D
+** if the F parameter is true, or disable them if F is false.
+*/
+int sqlite3_extended_result_codes(sqlite3*, int onoff);
+
+/*
+** CAPI3REF: Last Insert Rowid {H12220} <S10700>
+**
+** Each entry in an SQLite table has a unique 64-bit signed
+** integer key called the "rowid". The rowid is always available
+** as an undeclared column named ROWID, OID, or _ROWID_ as long as those
+** names are not also used by explicitly declared columns. If
+** the table has a column of type INTEGER PRIMARY KEY then that column
+** is another alias for the rowid.
+**
+** This routine returns the rowid of the most recent
+** successful INSERT into the database from the [database connection]
+** in the first argument. If no successful INSERTs
+** have ever occurred on that database connection, zero is returned.
+**
+** If an INSERT occurs within a trigger, then the rowid of the inserted
+** row is returned by this routine as long as the trigger is running.
+** But once the trigger terminates, the value returned by this routine
+** reverts to the last value inserted before the trigger fired.
+**
+** An INSERT that fails due to a constraint violation is not a
+** successful INSERT and does not change the value returned by this
+** routine. Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK,
+** and INSERT OR ABORT make no changes to the return value of this
+** routine when their insertion fails. When INSERT OR REPLACE
+** encounters a constraint violation, it does not fail. The
+** INSERT continues to completion after deleting rows that caused
+** the constraint problem so INSERT OR REPLACE will always change
+** the return value of this interface.
+**
+** For the purposes of this routine, an INSERT is considered to
+** be successful even if it is subsequently rolled back.
+**
+** INVARIANTS:
+**
+** {H12221} The [sqlite3_last_insert_rowid()] function returns the rowid
+** of the most recent successful INSERT performed on the same
+** [database connection] and within the same or higher level
+** trigger context, or zero if there have been no qualifying inserts.
+**
+** {H12223} The [sqlite3_last_insert_rowid()] function returns the
+** same value when called from the same trigger context
+** immediately before and after a ROLLBACK.
+**
+** ASSUMPTIONS:
+**
+** {A12232} If a separate thread performs a new INSERT on the same
+** database connection while the [sqlite3_last_insert_rowid()]
+** function is running and thus changes the last insert rowid,
+** then the value returned by [sqlite3_last_insert_rowid()] is
+** unpredictable and might not equal either the old or the new
+** last insert rowid.
+*/
+sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
+
+/*
+** CAPI3REF: Count The Number Of Rows Modified {H12240} <S10600>
+**
+** This function returns the number of database rows that were changed
+** or inserted or deleted by the most recently completed SQL statement
+** on the [database connection] specified by the first parameter.
+** Only changes that are directly specified by the INSERT, UPDATE,
+** or DELETE statement are counted. Auxiliary changes caused by
+** triggers are not counted. Use the [sqlite3_total_changes()] function
+** to find the total number of changes including changes caused by triggers.
+**
+** A "row change" is a change to a single row of a single table
+** caused by an INSERT, DELETE, or UPDATE statement. Rows that
+** are changed as side effects of REPLACE constraint resolution,
+** rollback, ABORT processing, DROP TABLE, or by any other
+** mechanisms do not count as direct row changes.
+**
+** A "trigger context" is a scope of execution that begins and
+** ends with the script of a trigger. Most SQL statements are
+** evaluated outside of any trigger. This is the "top level"
+** trigger context. If a trigger fires from the top level, a
+** new trigger context is entered for the duration of that one
+** trigger. Subtriggers create subcontexts for their duration.
+**
+** Calling [sqlite3_exec()] or [sqlite3_step()] recursively does
+** not create a new trigger context.
+**
+** This function returns the number of direct row changes in the
+** most recent INSERT, UPDATE, or DELETE statement within the same
+** trigger context.
+**
+** Thus, when called from the top level, this function returns the
+** number of changes in the most recent INSERT, UPDATE, or DELETE
+** that also occurred at the top level. Within the body of a trigger,
+** the sqlite3_changes() interface can be called to find the number of
+** changes in the most recently completed INSERT, UPDATE, or DELETE
+** statement within the body of the same trigger.
+** However, the number returned does not include changes
+** caused by subtriggers since those have their own context.
+**
+** SQLite implements the command "DELETE FROM table" without a WHERE clause
+** by dropping and recreating the table. (This is much faster than going
+** through and deleting individual elements from the table.) Because of this
+** optimization, the deletions in "DELETE FROM table" are not row changes and
+** will not be counted by the sqlite3_changes() or [sqlite3_total_changes()]
+** functions, regardless of the number of elements that were originally
+** in the table. To get an accurate count of the number of rows deleted, use
+** "DELETE FROM table WHERE 1" instead.
+**
+** INVARIANTS:
+**
+** {H12241} The [sqlite3_changes()] function shall return the number of
+** row changes caused by the most recent INSERT, UPDATE,
+** or DELETE statement on the same database connection and
+** within the same or higher trigger context, or zero if there have
+** not been any qualifying row changes.
+**
+** {H12243} Statements of the form "DELETE FROM tablename" with no
+** WHERE clause shall cause subsequent calls to
+** [sqlite3_changes()] to return zero, regardless of the
+** number of rows originally in the table.
+**
+** ASSUMPTIONS:
+**
+** {A12252} If a separate thread makes changes on the same database connection
+** while [sqlite3_changes()] is running then the value returned
+** is unpredictable and not meaningful.
+*/
+int sqlite3_changes(sqlite3*);
+
+/*
+** CAPI3REF: Total Number Of Rows Modified {H12260} <S10600>
+**
+** This function returns the number of row changes caused by INSERT,
+** UPDATE or DELETE statements since the [database connection] was opened.
+** The count includes all changes from all trigger contexts. However,
+** the count does not include changes used to implement REPLACE constraints,
+** do rollbacks or ABORT processing, or DROP table processing.
+** The changes are counted as soon as the statement that makes them is
+** completed (when the statement handle is passed to [sqlite3_reset()] or
+** [sqlite3_finalize()]).
+**
+** SQLite implements the command "DELETE FROM table" without a WHERE clause
+** by dropping and recreating the table. (This is much faster than going
+** through and deleting individual elements from the table.) Because of this
+** optimization, the deletions in "DELETE FROM table" are not row changes and
+** will not be counted by the sqlite3_changes() or [sqlite3_total_changes()]
+** functions, regardless of the number of elements that were originally
+** in the table. To get an accurate count of the number of rows deleted, use
+** "DELETE FROM table WHERE 1" instead.
+**
+** See also the [sqlite3_changes()] interface.
+**
+** INVARIANTS:
+**
+** {H12261} The [sqlite3_total_changes()] returns the total number
+** of row changes caused by INSERT, UPDATE, and/or DELETE
+** statements on the same [database connection], in any
+** trigger context, since the database connection was created.
+**
+** {H12263} Statements of the form "DELETE FROM tablename" with no
+** WHERE clause shall not change the value returned
+** by [sqlite3_total_changes()].
+**
+** ASSUMPTIONS:
+**
+** {A12264} If a separate thread makes changes on the same database connection
+** while [sqlite3_total_changes()] is running then the value
+** returned is unpredictable and not meaningful.
+*/
+int sqlite3_total_changes(sqlite3*);
+
+/*
+** CAPI3REF: Interrupt A Long-Running Query {H12270} <S30500>
+**
+** This function causes any pending database operation to abort and
+** return at its earliest opportunity. This routine is typically
+** called in response to a user action such as pressing "Cancel"
+** or Ctrl-C where the user wants a long query operation to halt
+** immediately.
+**
+** It is safe to call this routine from a thread different from the
+** thread that is currently running the database operation. But it
+** is not safe to call this routine with a [database connection] that
+** is closed or might close before sqlite3_interrupt() returns.
+**
+** If an SQL operation is very nearly finished at the time when
+** sqlite3_interrupt() is called, then it might not have an opportunity
+** to be interrupted and might continue to completion.
+**
+** An SQL operation that is interrupted will return [SQLITE_INTERRUPT].
+** If the interrupted SQL operation is an INSERT, UPDATE, or DELETE
+** that is inside an explicit transaction, then the entire transaction
+** will be rolled back automatically.
+**
+** A call to sqlite3_interrupt() has no effect on SQL statements
+** that are started after sqlite3_interrupt() returns.
+**
+** INVARIANTS:
+**
+** {H12271} The [sqlite3_interrupt()] interface will force all running
+** SQL statements associated with the same database connection
+** to halt after processing at most one additional row of data.
+**
+** {H12272} Any SQL statement that is interrupted by [sqlite3_interrupt()]
+** will return [SQLITE_INTERRUPT].
+**
+** ASSUMPTIONS:
+**
+** {A12279} If the database connection closes while [sqlite3_interrupt()]
+** is running then bad things will likely happen.
+*/
+void sqlite3_interrupt(sqlite3*);
+
+/*
+** CAPI3REF: Determine If An SQL Statement Is Complete {H10510} <S70200>
+**
+** These routines are useful for command-line input to determine if the
+** currently entered text seems to form complete a SQL statement or
+** if additional input is needed before sending the text into
+** SQLite for parsing. These routines return true if the input string
+** appears to be a complete SQL statement. A statement is judged to be
+** complete if it ends with a semicolon token and is not a fragment of a
+** CREATE TRIGGER statement. Semicolons that are embedded within
+** string literals or quoted identifier names or comments are not
+** independent tokens (they are part of the token in which they are
+** embedded) and thus do not count as a statement terminator.
+**
+** These routines do not parse the SQL statements thus
+** will not detect syntactically incorrect SQL.
+**
+** INVARIANTS:
+**
+** {H10511} A successful evaluation of [sqlite3_complete()] or
+** [sqlite3_complete16()] functions shall
+** return a numeric 1 if and only if the last non-whitespace
+** token in their input is a semicolon that is not in between
+** the BEGIN and END of a CREATE TRIGGER statement.
+**
+** {H10512} If a memory allocation error occurs during an invocation
+** of [sqlite3_complete()] or [sqlite3_complete16()] then the
+** routine shall return [SQLITE_NOMEM].
+**
+** ASSUMPTIONS:
+**
+** {A10512} The input to [sqlite3_complete()] must be a zero-terminated
+** UTF-8 string.
+**
+** {A10513} The input to [sqlite3_complete16()] must be a zero-terminated
+** UTF-16 string in native byte order.
+*/
+int sqlite3_complete(const char *sql);
+int sqlite3_complete16(const void *sql);
+
+/*
+** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors {H12310} <S40400>
+**
+** This routine sets a callback function that might be invoked whenever
+** an attempt is made to open a database table that another thread
+** or process has locked.
+**
+** If the busy callback is NULL, then [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]
+** is returned immediately upon encountering the lock. If the busy callback
+** is not NULL, then the callback will be invoked with two arguments.
+**
+** The first argument to the handler is a copy of the void* pointer which
+** is the third argument to sqlite3_busy_handler(). The second argument to
+** the handler callback is the number of times that the busy handler has
+** been invoked for this locking event. If the
+** busy callback returns 0, then no additional attempts are made to
+** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned.
+** If the callback returns non-zero, then another attempt
+** is made to open the database for reading and the cycle repeats.
+**
+** The presence of a busy handler does not guarantee that it will be invoked
+** when there is lock contention. If SQLite determines that invoking the busy
+** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY]
+** or [SQLITE_IOERR_BLOCKED] instead of invoking the busy handler.
+** Consider a scenario where one process is holding a read lock that
+** it is trying to promote to a reserved lock and
+** a second process is holding a reserved lock that it is trying
+** to promote to an exclusive lock. The first process cannot proceed
+** because it is blocked by the second and the second process cannot
+** proceed because it is blocked by the first. If both processes
+** invoke the busy handlers, neither will make any progress. Therefore,
+** SQLite returns [SQLITE_BUSY] for the first process, hoping that this
+** will induce the first process to release its read lock and allow
+** the second process to proceed.
+**
+** The default busy callback is NULL.
+**
+** The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED]
+** when SQLite is in the middle of a large transaction where all the
+** changes will not fit into the in-memory cache. SQLite will
+** already hold a RESERVED lock on the database file, but it needs
+** to promote this lock to EXCLUSIVE so that it can spill cache
+** pages into the database file without harm to concurrent
+** readers. If it is unable to promote the lock, then the in-memory
+** cache will be left in an inconsistent state and so the error
+** code is promoted from the relatively benign [SQLITE_BUSY] to
+** the more severe [SQLITE_IOERR_BLOCKED]. This error code promotion
+** forces an automatic rollback of the changes. See the
+** <a href="/cvstrac/wiki?p=CorruptionFollowingBusyError">
+** CorruptionFollowingBusyError</a> wiki page for a discussion of why
+** this is important.
+**
+** There can only be a single busy handler defined for each
+** [database connection]. Setting a new busy handler clears any
+** previously set handler. Note that calling [sqlite3_busy_timeout()]
+** will also set or clear the busy handler.
+**
+** INVARIANTS:
+**
+** {H12311} The [sqlite3_busy_handler(D,C,A)] function shall replace
+** busy callback in the [database connection] D with a new
+** a new busy handler C and application data pointer A.
+**
+** {H12312} Newly created [database connections] shall have a busy
+** handler of NULL.
+**
+** {H12314} When two or more [database connections] share a
+** [sqlite3_enable_shared_cache | common cache],
+** the busy handler for the database connection currently using
+** the cache shall be invoked when the cache encounters a lock.
+**
+** {H12316} If a busy handler callback returns zero, then the SQLite interface
+** that provoked the locking event shall return [SQLITE_BUSY].
+**
+** {H12318} SQLite shall invokes the busy handler with two arguments which
+** are a copy of the pointer supplied by the 3rd parameter to
+** [sqlite3_busy_handler()] and a count of the number of prior
+** invocations of the busy handler for the same locking event.
+**
+** ASSUMPTIONS:
+**
+** {A12319} A busy handler must not close the database connection
+** or [prepared statement] that invoked the busy handler.
+*/
+int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
+
+/*
+** CAPI3REF: Set A Busy Timeout {H12340} <S40410>
+**
+** This routine sets a [sqlite3_busy_handler | busy handler] that sleeps
+** for a specified amount of time when a table is locked. The handler
+** will sleep multiple times until at least "ms" milliseconds of sleeping
+** have accumulated. {H12343} After "ms" milliseconds of sleeping,
+** the handler returns 0 which causes [sqlite3_step()] to return
+** [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED].
+**
+** Calling this routine with an argument less than or equal to zero
+** turns off all busy handlers.
+**
+** There can only be a single busy handler for a particular
+** [database connection] any any given moment. If another busy handler
+** was defined (using [sqlite3_busy_handler()]) prior to calling
+** this routine, that other busy handler is cleared.
+**
+** INVARIANTS:
+**
+** {H12341} The [sqlite3_busy_timeout()] function shall override any prior
+** [sqlite3_busy_timeout()] or [sqlite3_busy_handler()] setting
+** on the same [database connection].
+**
+** {H12343} If the 2nd parameter to [sqlite3_busy_timeout()] is less than
+** or equal to zero, then the busy handler shall be cleared so that
+** all subsequent locking events immediately return [SQLITE_BUSY].
+**
+** {H12344} If the 2nd parameter to [sqlite3_busy_timeout()] is a positive
+** number N, then a busy handler shall be set that repeatedly calls
+** the xSleep() method in the [sqlite3_vfs | VFS interface] until
+** either the lock clears or until the cumulative sleep time
+** reported back by xSleep() exceeds N milliseconds.
+*/
+int sqlite3_busy_timeout(sqlite3*, int ms);
+
+/*
+** CAPI3REF: Convenience Routines For Running Queries {H12370} <S10000>
+**
+** Definition: A <b>result table</b> is memory data structure created by the
+** [sqlite3_get_table()] interface. A result table records the
+** complete query results from one or more queries.
+**
+** The table conceptually has a number of rows and columns. But
+** these numbers are not part of the result table itself. These
+** numbers are obtained separately. Let N be the number of rows
+** and M be the number of columns.
+**
+** A result table is an array of pointers to zero-terminated UTF-8 strings.
+** There are (N+1)*M elements in the array. The first M pointers point
+** to zero-terminated strings that contain the names of the columns.
+** The remaining entries all point to query results. NULL values result
+** in NULL pointers. All other values are in their UTF-8 zero-terminated
+** string representation as returned by [sqlite3_column_text()].
+**
+** A result table might consist of one or more memory allocations.
+** It is not safe to pass a result table directly to [sqlite3_free()].
+** A result table should be deallocated using [sqlite3_free_table()].
+**
+** As an example of the result table format, suppose a query result
+** is as follows:
+**
+** <blockquote><pre>
+** Name | Age
+** -----------------------
+** Alice | 43
+** Bob | 28
+** Cindy | 21
+** </pre></blockquote>
+**
+** There are two column (M==2) and three rows (N==3). Thus the
+** result table has 8 entries. Suppose the result table is stored
+** in an array names azResult. Then azResult holds this content:
+**
+** <blockquote><pre>
+** azResult[0] = "Name";
+** azResult[1] = "Age";
+** azResult[2] = "Alice";
+** azResult[3] = "43";
+** azResult[4] = "Bob";
+** azResult[5] = "28";
+** azResult[6] = "Cindy";
+** azResult[7] = "21";
+** </pre></blockquote>
+**
+** The sqlite3_get_table() function evaluates one or more
+** semicolon-separated SQL statements in the zero-terminated UTF-8
+** string of its 2nd parameter. It returns a result table to the
+** pointer given in its 3rd parameter.
+**
+** After the calling function has finished using the result, it should
+** pass the pointer to the result table to sqlite3_free_table() in order to
+** release the memory that was malloced. Because of the way the
+** [sqlite3_malloc()] happens within sqlite3_get_table(), the calling
+** function must not try to call [sqlite3_free()] directly. Only
+** [sqlite3_free_table()] is able to release the memory properly and safely.
+**
+** The sqlite3_get_table() interface is implemented as a wrapper around
+** [sqlite3_exec()]. The sqlite3_get_table() routine does not have access
+** to any internal data structures of SQLite. It uses only the public
+** interface defined here. As a consequence, errors that occur in the
+** wrapper layer outside of the internal [sqlite3_exec()] call are not
+** reflected in subsequent calls to [sqlite3_errcode()] or [sqlite3_errmsg()].
+**
+** INVARIANTS:
+**
+** {H12371} If a [sqlite3_get_table()] fails a memory allocation, then
+** it shall free the result table under construction, abort the
+** query in process, skip any subsequent queries, set the
+** *pazResult output pointer to NULL and return [SQLITE_NOMEM].
+**
+** {H12373} If the pnColumn parameter to [sqlite3_get_table()] is not NULL
+** then a successful invocation of [sqlite3_get_table()] shall
+** write the number of columns in the
+** result set of the query into *pnColumn.
+**
+** {H12374} If the pnRow parameter to [sqlite3_get_table()] is not NULL
+** then a successful invocation of [sqlite3_get_table()] shall
+** writes the number of rows in the
+** result set of the query into *pnRow.
+**
+** {H12376} A successful invocation of [sqlite3_get_table()] that computes
+** N rows of result with C columns per row shall make *pazResult
+** point to an array of pointers to (N+1)*C strings where the first
+** C strings are column names as obtained from
+** [sqlite3_column_name()] and the rest are column result values
+** obtained from [sqlite3_column_text()].
+**
+** {H12379} The values in the pazResult array returned by [sqlite3_get_table()]
+** shall remain valid until cleared by [sqlite3_free_table()].
+**
+** {H12382} When an error occurs during evaluation of [sqlite3_get_table()]
+** the function shall set *pazResult to NULL, write an error message
+** into memory obtained from [sqlite3_malloc()], make
+** **pzErrmsg point to that error message, and return a
+** appropriate [error code].
+*/
+int sqlite3_get_table(
+ sqlite3 *db, /* An open database */
+ const char *zSql, /* SQL to be evaluated */
+ char ***pazResult, /* Results of the query */
+ int *pnRow, /* Number of result rows written here */
+ int *pnColumn, /* Number of result columns written here */
+ char **pzErrmsg /* Error msg written here */
+);
+void sqlite3_free_table(char **result);
+
+/*
+** CAPI3REF: Formatted String Printing Functions {H17400} <S70000><S20000>
+**
+** These routines are workalikes of the "printf()" family of functions
+** from the standard C library.
+**
+** The sqlite3_mprintf() and sqlite3_vmprintf() routines write their
+** results into memory obtained from [sqlite3_malloc()].
+** The strings returned by these two routines should be
+** released by [sqlite3_free()]. Both routines return a
+** NULL pointer if [sqlite3_malloc()] is unable to allocate enough
+** memory to hold the resulting string.
+**
+** In sqlite3_snprintf() routine is similar to "snprintf()" from
+** the standard C library. The result is written into the
+** buffer supplied as the second parameter whose size is given by
+** the first parameter. Note that the order of the
+** first two parameters is reversed from snprintf(). This is an
+** historical accident that cannot be fixed without breaking
+** backwards compatibility. Note also that sqlite3_snprintf()
+** returns a pointer to its buffer instead of the number of
+** characters actually written into the buffer. We admit that
+** the number of characters written would be a more useful return
+** value but we cannot change the implementation of sqlite3_snprintf()
+** now without breaking compatibility.
+**
+** As long as the buffer size is greater than zero, sqlite3_snprintf()
+** guarantees that the buffer is always zero-terminated. The first
+** parameter "n" is the total size of the buffer, including space for
+** the zero terminator. So the longest string that can be completely
+** written will be n-1 characters.
+**
+** These routines all implement some additional formatting
+** options that are useful for constructing SQL statements.
+** All of the usual printf() formatting options apply. In addition, there
+** is are "%q", "%Q", and "%z" options.
+**
+** The %q option works like %s in that it substitutes a null-terminated
+** string from the argument list. But %q also doubles every '\'' character.
+** %q is designed for use inside a string literal. By doubling each '\''
+** character it escapes that character and allows it to be inserted into
+** the string.
+**
+** For example, assume the string variable zText contains text as follows:
+**
+** <blockquote><pre>
+** char *zText = "It's a happy day!";
+** </pre></blockquote>
+**
+** One can use this text in an SQL statement as follows:
+**
+** <blockquote><pre>
+** char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
+** sqlite3_exec(db, zSQL, 0, 0, 0);
+** sqlite3_free(zSQL);
+** </pre></blockquote>
+**
+** Because the %q format string is used, the '\'' character in zText
+** is escaped and the SQL generated is as follows:
+**
+** <blockquote><pre>
+** INSERT INTO table1 VALUES('It''s a happy day!')
+** </pre></blockquote>
+**
+** This is correct. Had we used %s instead of %q, the generated SQL
+** would have looked like this:
+**
+** <blockquote><pre>
+** INSERT INTO table1 VALUES('It's a happy day!');
+** </pre></blockquote>
+**
+** This second example is an SQL syntax error. As a general rule you should
+** always use %q instead of %s when inserting text into a string literal.
+**
+** The %Q option works like %q except it also adds single quotes around
+** the outside of the total string. Additionally, if the parameter in the
+** argument list is a NULL pointer, %Q substitutes the text "NULL" (without
+** single quotes) in place of the %Q option. So, for example, one could say:
+**
+** <blockquote><pre>
+** char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
+** sqlite3_exec(db, zSQL, 0, 0, 0);
+** sqlite3_free(zSQL);
+** </pre></blockquote>
+**
+** The code above will render a correct SQL statement in the zSQL
+** variable even if the zText variable is a NULL pointer.
+**
+** The "%z" formatting option works exactly like "%s" with the
+** addition that after the string has been read and copied into
+** the result, [sqlite3_free()] is called on the input string. {END}
+**
+** INVARIANTS:
+**
+** {H17403} The [sqlite3_mprintf()] and [sqlite3_vmprintf()] interfaces
+** return either pointers to zero-terminated UTF-8 strings held in
+** memory obtained from [sqlite3_malloc()] or NULL pointers if
+** a call to [sqlite3_malloc()] fails.
+**
+** {H17406} The [sqlite3_snprintf()] interface writes a zero-terminated
+** UTF-8 string into the buffer pointed to by the second parameter
+** provided that the first parameter is greater than zero.
+**
+** {H17407} The [sqlite3_snprintf()] interface does not write slots of
+** its output buffer (the second parameter) outside the range
+** of 0 through N-1 (where N is the first parameter)
+** regardless of the length of the string
+** requested by the format specification.
+*/
+char *sqlite3_mprintf(const char*,...);
+char *sqlite3_vmprintf(const char*, va_list);
+char *sqlite3_snprintf(int,char*,const char*, ...);
+
+/*
+** CAPI3REF: Memory Allocation Subsystem {H17300} <S20000>
+**
+** The SQLite core uses these three routines for all of its own
+** internal memory allocation needs. "Core" in the previous sentence
+** does not include operating-system specific VFS implementation. The
+** Windows VFS uses native malloc() and free() for some operations.
+**
+** The sqlite3_malloc() routine returns a pointer to a block
+** of memory at least N bytes in length, where N is the parameter.
+** If sqlite3_malloc() is unable to obtain sufficient free
+** memory, it returns a NULL pointer. If the parameter N to
+** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns
+** a NULL pointer.
+**
+** Calling sqlite3_free() with a pointer previously returned
+** by sqlite3_malloc() or sqlite3_realloc() releases that memory so
+** that it might be reused. The sqlite3_free() routine is
+** a no-op if is called with a NULL pointer. Passing a NULL pointer
+** to sqlite3_free() is harmless. After being freed, memory
+** should neither be read nor written. Even reading previously freed
+** memory might result in a segmentation fault or other severe error.
+** Memory corruption, a segmentation fault, or other severe error
+** might result if sqlite3_free() is called with a non-NULL pointer that
+** was not obtained from sqlite3_malloc() or sqlite3_free().
+**
+** The sqlite3_realloc() interface attempts to resize a
+** prior memory allocation to be at least N bytes, where N is the
+** second parameter. The memory allocation to be resized is the first
+** parameter. If the first parameter to sqlite3_realloc()
+** is a NULL pointer then its behavior is identical to calling
+** sqlite3_malloc(N) where N is the second parameter to sqlite3_realloc().
+** If the second parameter to sqlite3_realloc() is zero or
+** negative then the behavior is exactly the same as calling
+** sqlite3_free(P) where P is the first parameter to sqlite3_realloc().
+** sqlite3_realloc() returns a pointer to a memory allocation
+** of at least N bytes in size or NULL if sufficient memory is unavailable.
+** If M is the size of the prior allocation, then min(N,M) bytes
+** of the prior allocation are copied into the beginning of buffer returned
+** by sqlite3_realloc() and the prior allocation is freed.
+** If sqlite3_realloc() returns NULL, then the prior allocation
+** is not freed.
+**
+** The memory returned by sqlite3_malloc() and sqlite3_realloc()
+** is always aligned to at least an 8 byte boundary. {END}
+**
+** The default implementation of the memory allocation subsystem uses
+** the malloc(), realloc() and free() provided by the standard C library.
+** {H17382} However, if SQLite is compiled with the
+** SQLITE_MEMORY_SIZE=<i>NNN</i> C preprocessor macro (where <i>NNN</i>
+** is an integer), then SQLite create a static array of at least
+** <i>NNN</i> bytes in size and uses that array for all of its dynamic
+** memory allocation needs. {END} Additional memory allocator options
+** may be added in future releases.
+**
+** In SQLite version 3.5.0 and 3.5.1, it was possible to define
+** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in
+** implementation of these routines to be omitted. That capability
+** is no longer provided. Only built-in memory allocators can be used.
+**
+** The Windows OS interface layer calls
+** the system malloc() and free() directly when converting
+** filenames between the UTF-8 encoding used by SQLite
+** and whatever filename encoding is used by the particular Windows
+** installation. Memory allocation errors are detected, but
+** they are reported back as [SQLITE_CANTOPEN] or
+** [SQLITE_IOERR] rather than [SQLITE_NOMEM].
+**
+** INVARIANTS:
+**
+** {H17303} The [sqlite3_malloc(N)] interface returns either a pointer to
+** a newly checked-out block of at least N bytes of memory
+** that is 8-byte aligned, or it returns NULL if it is unable
+** to fulfill the request.
+**
+** {H17304} The [sqlite3_malloc(N)] interface returns a NULL pointer if
+** N is less than or equal to zero.
+**
+** {H17305} The [sqlite3_free(P)] interface releases memory previously
+** returned from [sqlite3_malloc()] or [sqlite3_realloc()],
+** making it available for reuse.
+**
+** {H17306} A call to [sqlite3_free(NULL)] is a harmless no-op.
+**
+** {H17310} A call to [sqlite3_realloc(0,N)] is equivalent to a call
+** to [sqlite3_malloc(N)].
+**
+** {H17312} A call to [sqlite3_realloc(P,0)] is equivalent to a call
+** to [sqlite3_free(P)].
+**
+** {H17315} The SQLite core uses [sqlite3_malloc()], [sqlite3_realloc()],
+** and [sqlite3_free()] for all of its memory allocation and
+** deallocation needs.
+**
+** {H17318} The [sqlite3_realloc(P,N)] interface returns either a pointer
+** to a block of checked-out memory of at least N bytes in size
+** that is 8-byte aligned, or a NULL pointer.
+**
+** {H17321} When [sqlite3_realloc(P,N)] returns a non-NULL pointer, it first
+** copies the first K bytes of content from P into the newly
+** allocated block, where K is the lesser of N and the size of
+** the buffer P.
+**
+** {H17322} When [sqlite3_realloc(P,N)] returns a non-NULL pointer, it first
+** releases the buffer P.
+**
+** {H17323} When [sqlite3_realloc(P,N)] returns NULL, the buffer P is
+** not modified or released.
+**
+** ASSUMPTIONS:
+**
+** {A17350} The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()]
+** must be either NULL or else pointers obtained from a prior
+** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have
+** not yet been released.
+**
+** {A17351} The application must not read or write any part of
+** a block of memory after it has been released using
+** [sqlite3_free()] or [sqlite3_realloc()].
+*/
+void *sqlite3_malloc(int);
+void *sqlite3_realloc(void*, int);
+void sqlite3_free(void*);
+
+/*
+** CAPI3REF: Memory Allocator Statistics {H17370} <S30210>
+**
+** SQLite provides these two interfaces for reporting on the status
+** of the [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()]
+** routines, which form the built-in memory allocation subsystem.
+**
+** INVARIANTS:
+**
+** {H17371} The [sqlite3_memory_used()] routine returns the number of bytes
+** of memory currently outstanding (malloced but not freed).
+**
+** {H17373} The [sqlite3_memory_highwater()] routine returns the maximum
+** value of [sqlite3_memory_used()] since the high-water mark
+** was last reset.
+**
+** {H17374} The values returned by [sqlite3_memory_used()] and
+** [sqlite3_memory_highwater()] include any overhead
+** added by SQLite in its implementation of [sqlite3_malloc()],
+** but not overhead added by the any underlying system library
+** routines that [sqlite3_malloc()] may call.
+**
+** {H17375} The memory high-water mark is reset to the current value of
+** [sqlite3_memory_used()] if and only if the parameter to
+** [sqlite3_memory_highwater()] is true. The value returned
+** by [sqlite3_memory_highwater(1)] is the high-water mark
+** prior to the reset.
+*/
+sqlite3_int64 sqlite3_memory_used(void);
+sqlite3_int64 sqlite3_memory_highwater(int resetFlag);
+
+/*
+** CAPI3REF: Pseudo-Random Number Generator {H17390} <S20000>
+**
+** SQLite contains a high-quality pseudo-random number generator (PRNG) used to
+** select random ROWIDs when inserting new records into a table that
+** already uses the largest possible ROWID. The PRNG is also used for
+** the build-in random() and randomblob() SQL functions. This interface allows
+** applications to access the same PRNG for other purposes.
+**
+** A call to this routine stores N bytes of randomness into buffer P.
+**
+** The first time this routine is invoked (either internally or by
+** the application) the PRNG is seeded using randomness obtained
+** from the xRandomness method of the default [sqlite3_vfs] object.
+** On all subsequent invocations, the pseudo-randomness is generated
+** internally and without recourse to the [sqlite3_vfs] xRandomness
+** method.
+**
+** INVARIANTS:
+**
+** {H17392} The [sqlite3_randomness(N,P)] interface writes N bytes of
+** high-quality pseudo-randomness into buffer P.
+*/
+void sqlite3_randomness(int N, void *P);
+
+/*
+** CAPI3REF: Compile-Time Authorization Callbacks {H12500} <S70100>
+**
+** This routine registers a authorizer callback with a particular
+** [database connection], supplied in the first argument.
+** The authorizer callback is invoked as SQL statements are being compiled
+** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()],
+** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()]. At various
+** points during the compilation process, as logic is being created
+** to perform various actions, the authorizer callback is invoked to
+** see if those actions are allowed. The authorizer callback should
+** return [SQLITE_OK] to allow the action, [SQLITE_IGNORE] to disallow the
+** specific action but allow the SQL statement to continue to be
+** compiled, or [SQLITE_DENY] to cause the entire SQL statement to be
+** rejected with an error. If the authorizer callback returns
+** any value other than [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY]
+** then the [sqlite3_prepare_v2()] or equivalent call that triggered
+** the authorizer will fail with an error message.
+**
+** When the callback returns [SQLITE_OK], that means the operation
+** requested is ok. When the callback returns [SQLITE_DENY], the
+** [sqlite3_prepare_v2()] or equivalent call that triggered the
+** authorizer will fail with an error message explaining that
+** access is denied. If the authorizer code is [SQLITE_READ]
+** and the callback returns [SQLITE_IGNORE] then the
+** [prepared statement] statement is constructed to substitute
+** a NULL value in place of the table column that would have
+** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE]
+** return can be used to deny an untrusted user access to individual
+** columns of a table.
+**
+** The first parameter to the authorizer callback is a copy of the third
+** parameter to the sqlite3_set_authorizer() interface. The second parameter
+** to the callback is an integer [SQLITE_COPY | action code] that specifies
+** the particular action to be authorized. The third through sixth parameters
+** to the callback are zero-terminated strings that contain additional
+** details about the action to be authorized.
+**
+** An authorizer is used when [sqlite3_prepare | preparing]
+** SQL statements from an untrusted source, to ensure that the SQL statements
+** do not try to access data they are not allowed to see, or that they do not
+** try to execute malicious statements that damage the database. For
+** example, an application may allow a user to enter arbitrary
+** SQL queries for evaluation by a database. But the application does
+** not want the user to be able to make arbitrary changes to the
+** database. An authorizer could then be put in place while the
+** user-entered SQL is being [sqlite3_prepare | prepared] that
+** disallows everything except [SELECT] statements.
+**
+** Applications that need to process SQL from untrusted sources
+** might also consider lowering resource limits using [sqlite3_limit()]
+** and limiting database size using the [max_page_count] [PRAGMA]
+** in addition to using an authorizer.
+**
+** Only a single authorizer can be in place on a database connection
+** at a time. Each call to sqlite3_set_authorizer overrides the
+** previous call. Disable the authorizer by installing a NULL callback.
+** The authorizer is disabled by default.
+**
+** Note that the authorizer callback is invoked only during
+** [sqlite3_prepare()] or its variants. Authorization is not
+** performed during statement evaluation in [sqlite3_step()].
+**
+** INVARIANTS:
+**
+** {H12501} The [sqlite3_set_authorizer(D,...)] interface registers a
+** authorizer callback with database connection D.
+**
+** {H12502} The authorizer callback is invoked as SQL statements are
+** being compiled.
+**
+** {H12503} If the authorizer callback returns any value other than
+** [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY], then
+** the [sqlite3_prepare_v2()] or equivalent call that caused
+** the authorizer callback to run shall fail with an
+** [SQLITE_ERROR] error code and an appropriate error message.
+**
+** {H12504} When the authorizer callback returns [SQLITE_OK], the operation
+** described is processed normally.
+**
+** {H12505} When the authorizer callback returns [SQLITE_DENY], the
+** [sqlite3_prepare_v2()] or equivalent call that caused the
+** authorizer callback to run shall fail
+** with an [SQLITE_ERROR] error code and an error message
+** explaining that access is denied.
+**
+** {H12506} If the authorizer code (the 2nd parameter to the authorizer
+** callback) is [SQLITE_READ] and the authorizer callback returns
+** [SQLITE_IGNORE], then the prepared statement is constructed to
+** insert a NULL value in place of the table column that would have
+** been read if [SQLITE_OK] had been returned.
+**
+** {H12507} If the authorizer code (the 2nd parameter to the authorizer
+** callback) is anything other than [SQLITE_READ], then
+** a return of [SQLITE_IGNORE] has the same effect as [SQLITE_DENY].
+**
+** {H12510} The first parameter to the authorizer callback is a copy of
+** the third parameter to the [sqlite3_set_authorizer()] interface.
+**
+** {H12511} The second parameter to the callback is an integer
+** [SQLITE_COPY | action code] that specifies the particular action
+** to be authorized.
+**
+** {H12512} The third through sixth parameters to the callback are
+** zero-terminated strings that contain
+** additional details about the action to be authorized.
+**
+** {H12520} Each call to [sqlite3_set_authorizer()] overrides
+** any previously installed authorizer.
+**
+** {H12521} A NULL authorizer means that no authorization
+** callback is invoked.
+**
+** {H12522} The default authorizer is NULL.
+*/
+int sqlite3_set_authorizer(
+ sqlite3*,
+ int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
+ void *pUserData
+);
+
+/*
+** CAPI3REF: Authorizer Return Codes {H12590} <H12500>
+**
+** The [sqlite3_set_authorizer | authorizer callback function] must
+** return either [SQLITE_OK] or one of these two constants in order
+** to signal SQLite whether or not the action is permitted. See the
+** [sqlite3_set_authorizer | authorizer documentation] for additional
+** information.
+*/
+#define SQLITE_DENY 1 /* Abort the SQL statement with an error */
+#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
+
+/*
+** CAPI3REF: Authorizer Action Codes {H12550} <H12500>
+**
+** The [sqlite3_set_authorizer()] interface registers a callback function
+** that is invoked to authorize certain SQL statement actions. The
+** second parameter to the callback is an integer code that specifies
+** what action is being authorized. These are the integer action codes that
+** the authorizer callback may be passed.
+**
+** These action code values signify what kind of operation is to be
+** authorized. The 3rd and 4th parameters to the authorization
+** callback function will be parameters or NULL depending on which of these
+** codes is used as the second parameter. The 5th parameter to the
+** authorizer callback is the name of the database ("main", "temp",
+** etc.) if applicable. The 6th parameter to the authorizer callback
+** is the name of the inner-most trigger or view that is responsible for
+** the access attempt or NULL if this access attempt is directly from
+** top-level SQL code.
+**
+** INVARIANTS:
+**
+** {H12551} The second parameter to an
+** [sqlite3_set_authorizer | authorizer callback] is always an integer
+** [SQLITE_COPY | authorizer code] that specifies what action
+** is being authorized.
+**
+** {H12552} The 3rd and 4th parameters to the
+** [sqlite3_set_authorizer | authorization callback]
+** will be parameters or NULL depending on which
+** [SQLITE_COPY | authorizer code] is used as the second parameter.
+**
+** {H12553} The 5th parameter to the
+** [sqlite3_set_authorizer | authorizer callback] is the name
+** of the database (example: "main", "temp", etc.) if applicable.
+**
+** {H12554} The 6th parameter to the
+** [sqlite3_set_authorizer | authorizer callback] is the name
+** of the inner-most trigger or view that is responsible for
+** the access attempt or NULL if this access attempt is directly from
+** top-level SQL code.
+*/
+/******************************************* 3rd ************ 4th ***********/
+#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */
+#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */
+#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */
+#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */
+#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */
+#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */
+#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */
+#define SQLITE_CREATE_VIEW 8 /* View Name NULL */
+#define SQLITE_DELETE 9 /* Table Name NULL */
+#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */
+#define SQLITE_DROP_TABLE 11 /* Table Name NULL */
+#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */
+#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */
+#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */
+#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */
+#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */
+#define SQLITE_DROP_VIEW 17 /* View Name NULL */
+#define SQLITE_INSERT 18 /* Table Name NULL */
+#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */
+#define SQLITE_READ 20 /* Table Name Column Name */
+#define SQLITE_SELECT 21 /* NULL NULL */
+#define SQLITE_TRANSACTION 22 /* NULL NULL */
+#define SQLITE_UPDATE 23 /* Table Name Column Name */
+#define SQLITE_ATTACH 24 /* Filename NULL */
+#define SQLITE_DETACH 25 /* Database Name NULL */
+#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */
+#define SQLITE_REINDEX 27 /* Index Name NULL */
+#define SQLITE_ANALYZE 28 /* Table Name NULL */
+#define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */
+#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */
+#define SQLITE_FUNCTION 31 /* Function Name NULL */
+#define SQLITE_COPY 0 /* No longer used */
+
+/*
+** CAPI3REF: Tracing And Profiling Functions {H12280} <S60400>
+** EXPERIMENTAL
+**
+** These routines register callback functions that can be used for
+** tracing and profiling the execution of SQL statements.
+**
+** The callback function registered by sqlite3_trace() is invoked at
+** various times when an SQL statement is being run by [sqlite3_step()].
+** The callback returns a UTF-8 rendering of the SQL statement text
+** as the statement first begins executing. Additional callbacks occur
+** as each triggered subprogram is entered. The callbacks for triggers
+** contain a UTF-8 SQL comment that identifies the trigger.
+**
+** The callback function registered by sqlite3_profile() is invoked
+** as each SQL statement finishes. The profile callback contains
+** the original statement text and an estimate of wall-clock time
+** of how long that statement took to run.
+**
+** INVARIANTS:
+**
+** {H12281} The callback function registered by [sqlite3_trace()] is
+** whenever an SQL statement first begins to execute and
+** whenever a trigger subprogram first begins to run.
+**
+** {H12282} Each call to [sqlite3_trace()] overrides the previously
+** registered trace callback.
+**
+** {H12283} A NULL trace callback disables tracing.
+**
+** {H12284} The first argument to the trace callback is a copy of
+** the pointer which was the 3rd argument to [sqlite3_trace()].
+**
+** {H12285} The second argument to the trace callback is a
+** zero-terminated UTF-8 string containing the original text
+** of the SQL statement as it was passed into [sqlite3_prepare_v2()]
+** or the equivalent, or an SQL comment indicating the beginning
+** of a trigger subprogram.
+**
+** {H12287} The callback function registered by [sqlite3_profile()] is invoked
+** as each SQL statement finishes.
+**
+** {H12288} The first parameter to the profile callback is a copy of
+** the 3rd parameter to [sqlite3_profile()].
+**
+** {H12289} The second parameter to the profile callback is a
+** zero-terminated UTF-8 string that contains the complete text of
+** the SQL statement as it was processed by [sqlite3_prepare_v2()]
+** or the equivalent.
+**
+** {H12290} The third parameter to the profile callback is an estimate
+** of the number of nanoseconds of wall-clock time required to
+** run the SQL statement from start to finish.
+*/
+void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
+void *sqlite3_profile(sqlite3*,
+ void(*xProfile)(void*,const char*,sqlite3_uint64), void*);
+
+/*
+** CAPI3REF: Query Progress Callbacks {H12910} <S60400>
+**
+** This routine configures a callback function - the
+** progress callback - that is invoked periodically during long
+** running calls to [sqlite3_exec()], [sqlite3_step()] and
+** [sqlite3_get_table()]. An example use for this
+** interface is to keep a GUI updated during a large query.
+**
+** If the progress callback returns non-zero, the operation is
+** interrupted. This feature can be used to implement a
+** "Cancel" button on a GUI dialog box.
+**
+** INVARIANTS:
+**
+** {H12911} The callback function registered by sqlite3_progress_handler()
+** is invoked periodically during long running calls to
+** [sqlite3_step()].
+**
+** {H12912} The progress callback is invoked once for every N virtual
+** machine opcodes, where N is the second argument to
+** the [sqlite3_progress_handler()] call that registered
+** the callback. If N is less than 1, sqlite3_progress_handler()
+** acts as if a NULL progress handler had been specified.
+**
+** {H12913} The progress callback itself is identified by the third
+** argument to sqlite3_progress_handler().
+**
+** {H12914} The fourth argument to sqlite3_progress_handler() is a
+** void pointer passed to the progress callback
+** function each time it is invoked.
+**
+** {H12915} If a call to [sqlite3_step()] results in fewer than N opcodes
+** being executed, then the progress callback is never invoked.
+**
+** {H12916} Every call to [sqlite3_progress_handler()]
+** overwrites any previously registered progress handler.
+**
+** {H12917} If the progress handler callback is NULL then no progress
+** handler is invoked.
+**
+** {H12918} If the progress callback returns a result other than 0, then
+** the behavior is a if [sqlite3_interrupt()] had been called.
+** <S30500>
+*/
+void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
+
+/*
+** CAPI3REF: Opening A New Database Connection {H12700} <S40200>
+**
+** These routines open an SQLite database file whose name is given by the
+** filename argument. The filename argument is interpreted as UTF-8 for
+** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte
+** order for sqlite3_open16(). A [database connection] handle is usually
+** returned in *ppDb, even if an error occurs. The only exception is that
+** if SQLite is unable to allocate memory to hold the [sqlite3] object,
+** a NULL will be written into *ppDb instead of a pointer to the [sqlite3]
+** object. If the database is opened (and/or created) successfully, then
+** [SQLITE_OK] is returned. Otherwise an [error code] is returned. The
+** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain
+** an English language description of the error.
+**
+** The default encoding for the database will be UTF-8 if
+** sqlite3_open() or sqlite3_open_v2() is called and
+** UTF-16 in the native byte order if sqlite3_open16() is used.
+**
+** Whether or not an error occurs when it is opened, resources
+** associated with the [database connection] handle should be released by
+** passing it to [sqlite3_close()] when it is no longer required.
+**
+** The sqlite3_open_v2() interface works like sqlite3_open()
+** except that it accepts two additional parameters for additional control
+** over the new database connection. The flags parameter can take one of
+** the following three values, optionally combined with the
+** [SQLITE_OPEN_NOMUTEX] flag:
+**
+** <dl>
+** <dt>[SQLITE_OPEN_READONLY]</dt>
+** <dd>The database is opened in read-only mode. If the database does not
+** already exist, an error is returned.</dd>
+**
+** <dt>[SQLITE_OPEN_READWRITE]</dt>
+** <dd>The database is opened for reading and writing if possible, or reading
+** only if the file is write protected by the operating system. In either
+** case the database must already exist, otherwise an error is returned.</dd>
+**
+** <dt>[SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]</dt>
+** <dd>The database is opened for reading and writing, and is creates it if
+** it does not already exist. This is the behavior that is always used for
+** sqlite3_open() and sqlite3_open16().</dd>
+** </dl>
+**
+** If the 3rd parameter to sqlite3_open_v2() is not one of the
+** combinations shown above or one of the combinations shown above combined
+** with the [SQLITE_OPEN_NOMUTEX] flag, then the behavior is undefined.
+**
+** If the [SQLITE_OPEN_NOMUTEX] flag is set, then mutexes on the
+** opened [database connection] are disabled and the appliation must
+** insure that access to the [database connection] and its associated
+** [prepared statements] is serialized. The [SQLITE_OPEN_NOMUTEX] flag
+** is the default behavior is SQLite is configured using the
+** [SQLITE_CONFIG_MULTITHREAD] or [SQLITE_CONFIG_SINGLETHREAD] options
+** to [sqlite3_config()]. The [SQLITE_OPEN_NOMUTEX] flag only makes a
+** difference when SQLite is in its default [SQLITE_CONFIG_SERIALIZED] mode.
+**
+** If the filename is ":memory:", then a private, temporary in-memory database
+** is created for the connection. This in-memory database will vanish when
+** the database connection is closed. Future versions of SQLite might
+** make use of additional special filenames that begin with the ":" character.
+** It is recommended that when a database filename actually does begin with
+** a ":" character you should prefix the filename with a pathname such as
+** "./" to avoid ambiguity.
+**
+** If the filename is an empty string, then a private, temporary
+** on-disk database will be created. This private database will be
+** automatically deleted as soon as the database connection is closed.
+**
+** The fourth parameter to sqlite3_open_v2() is the name of the
+** [sqlite3_vfs] object that defines the operating system interface that
+** the new database connection should use. If the fourth parameter is
+** a NULL pointer then the default [sqlite3_vfs] object is used.
+**
+** <b>Note to Windows users:</b> The encoding used for the filename argument
+** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever
+** codepage is currently defined. Filenames containing international
+** characters must be converted to UTF-8 prior to passing them into
+** sqlite3_open() or sqlite3_open_v2().
+**
+** INVARIANTS:
+**
+** {H12701} The [sqlite3_open()], [sqlite3_open16()], and
+** [sqlite3_open_v2()] interfaces create a new
+** [database connection] associated with
+** the database file given in their first parameter.
+**
+** {H12702} The filename argument is interpreted as UTF-8
+** for [sqlite3_open()] and [sqlite3_open_v2()] and as UTF-16
+** in the native byte order for [sqlite3_open16()].
+**
+** {H12703} A successful invocation of [sqlite3_open()], [sqlite3_open16()],
+** or [sqlite3_open_v2()] writes a pointer to a new
+** [database connection] into *ppDb.
+**
+** {H12704} The [sqlite3_open()], [sqlite3_open16()], and
+** [sqlite3_open_v2()] interfaces return [SQLITE_OK] upon success,
+** or an appropriate [error code] on failure.
+**
+** {H12706} The default text encoding for a new database created using
+** [sqlite3_open()] or [sqlite3_open_v2()] will be UTF-8.
+**
+** {H12707} The default text encoding for a new database created using
+** [sqlite3_open16()] will be UTF-16.
+**
+** {H12709} The [sqlite3_open(F,D)] interface is equivalent to
+** [sqlite3_open_v2(F,D,G,0)] where the G parameter is
+** [SQLITE_OPEN_READWRITE]|[SQLITE_OPEN_CREATE].
+**
+** {H12711} If the G parameter to [sqlite3_open_v2(F,D,G,V)] contains the
+** bit value [SQLITE_OPEN_READONLY] then the database is opened
+** for reading only.
+**
+** {H12712} If the G parameter to [sqlite3_open_v2(F,D,G,V)] contains the
+** bit value [SQLITE_OPEN_READWRITE] then the database is opened
+** reading and writing if possible, or for reading only if the
+** file is write protected by the operating system.
+**
+** {H12713} If the G parameter to [sqlite3_open_v2(F,D,G,V)] omits the
+** bit value [SQLITE_OPEN_CREATE] and the database does not
+** previously exist, an error is returned.
+**
+** {H12714} If the G parameter to [sqlite3_open_v2(F,D,G,V)] contains the
+** bit value [SQLITE_OPEN_CREATE] and the database does not
+** previously exist, then an attempt is made to create and
+** initialize the database.
+**
+** {H12717} If the filename argument to [sqlite3_open()], [sqlite3_open16()],
+** or [sqlite3_open_v2()] is ":memory:", then an private,
+** ephemeral, in-memory database is created for the connection.
+** <todo>Is SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE required
+** in sqlite3_open_v2()?</todo>
+**
+** {H12719} If the filename is NULL or an empty string, then a private,
+** ephemeral on-disk database will be created.
+** <todo>Is SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE required
+** in sqlite3_open_v2()?</todo>
+**
+** {H12721} The [database connection] created by [sqlite3_open_v2(F,D,G,V)]
+** will use the [sqlite3_vfs] object identified by the V parameter,
+** or the default [sqlite3_vfs] object if V is a NULL pointer.
+**
+** {H12723} Two [database connections] will share a common cache if both were
+** opened with the same VFS while [shared cache mode] was enabled and
+** if both filenames compare equal using memcmp() after having been
+** processed by the [sqlite3_vfs | xFullPathname] method of the VFS.
+*/
+int sqlite3_open(
+ const char *filename, /* Database filename (UTF-8) */
+ sqlite3 **ppDb /* OUT: SQLite db handle */
+);
+int sqlite3_open16(
+ const void *filename, /* Database filename (UTF-16) */
+ sqlite3 **ppDb /* OUT: SQLite db handle */
+);
+int sqlite3_open_v2(
+ const char *filename, /* Database filename (UTF-8) */
+ sqlite3 **ppDb, /* OUT: SQLite db handle */
+ int flags, /* Flags */
+ const char *zVfs /* Name of VFS module to use */
+);
+
+/*
+** CAPI3REF: Error Codes And Messages {H12800} <S60200>
+**
+** The sqlite3_errcode() interface returns the numeric [result code] or
+** [extended result code] for the most recent failed sqlite3_* API call
+** associated with a [database connection]. If a prior API call failed
+** but the most recent API call succeeded, the return value from
+** sqlite3_errcode() is undefined.
+**
+** The sqlite3_errmsg() and sqlite3_errmsg16() return English-language
+** text that describes the error, as either UTF-8 or UTF-16 respectively.
+** Memory to hold the error message string is managed internally.
+** The application does not need to worry about freeing the result.
+** However, the error string might be overwritten or deallocated by
+** subsequent calls to other SQLite interface functions.
+**
+** If an interface fails with SQLITE_MISUSE, that means the interface
+** was invoked incorrectly by the application. In that case, the
+** error code and message may or may not be set.
+**
+** INVARIANTS:
+**
+** {H12801} The [sqlite3_errcode(D)] interface returns the numeric
+** [result code] or [extended result code] for the most recently
+** failed interface call associated with the [database connection] D.
+**
+** {H12803} The [sqlite3_errmsg(D)] and [sqlite3_errmsg16(D)]
+** interfaces return English-language text that describes
+** the error in the mostly recently failed interface call,
+** encoded as either UTF-8 or UTF-16 respectively.
+**
+** {H12807} The strings returned by [sqlite3_errmsg()] and [sqlite3_errmsg16()]
+** are valid until the next SQLite interface call.
+**
+** {H12808} Calls to API routines that do not return an error code
+** (example: [sqlite3_data_count()]) do not
+** change the error code or message returned by
+** [sqlite3_errcode()], [sqlite3_errmsg()], or [sqlite3_errmsg16()].
+**
+** {H12809} Interfaces that are not associated with a specific
+** [database connection] (examples:
+** [sqlite3_mprintf()] or [sqlite3_enable_shared_cache()]
+** do not change the values returned by
+** [sqlite3_errcode()], [sqlite3_errmsg()], or [sqlite3_errmsg16()].
+*/
+int sqlite3_errcode(sqlite3 *db);
+const char *sqlite3_errmsg(sqlite3*);
+const void *sqlite3_errmsg16(sqlite3*);
+
+/*
+** CAPI3REF: SQL Statement Object {H13000} <H13010>
+** KEYWORDS: {prepared statement} {prepared statements}
+**
+** An instance of this object represents a single SQL statement.
+** This object is variously known as a "prepared statement" or a
+** "compiled SQL statement" or simply as a "statement".
+**
+** The life of a statement object goes something like this:
+**
+** <ol>
+** <li> Create the object using [sqlite3_prepare_v2()] or a related
+** function.
+** <li> Bind values to [host parameters] using the sqlite3_bind_*()
+** interfaces.
+** <li> Run the SQL by calling [sqlite3_step()] one or more times.
+** <li> Reset the statement using [sqlite3_reset()] then go back
+** to step 2. Do this zero or more times.
+** <li> Destroy the object using [sqlite3_finalize()].
+** </ol>
+**
+** Refer to documentation on individual methods above for additional
+** information.
+*/
+typedef struct sqlite3_stmt sqlite3_stmt;
+
+/*
+** CAPI3REF: Run-time Limits {H12760} <S20600>
+**
+** This interface allows the size of various constructs to be limited
+** on a connection by connection basis. The first parameter is the
+** [database connection] whose limit is to be set or queried. The
+** second parameter is one of the [limit categories] that define a
+** class of constructs to be size limited. The third parameter is the
+** new limit for that construct. The function returns the old limit.
+**
+** If the new limit is a negative number, the limit is unchanged.
+** For the limit category of SQLITE_LIMIT_XYZ there is a hard upper
+** bound set by a compile-time C preprocessor macro named SQLITE_MAX_XYZ.
+** (The "_LIMIT_" in the name is changed to "_MAX_".)
+** Attempts to increase a limit above its hard upper bound are
+** silently truncated to the hard upper limit.
+**
+** Run time limits are intended for use in applications that manage
+** both their own internal database and also databases that are controlled
+** by untrusted external sources. An example application might be a
+** webbrowser that has its own databases for storing history and
+** separate databases controlled by JavaScript applications downloaded
+** off the Internet. The internal databases can be given the
+** large, default limits. Databases managed by external sources can
+** be given much smaller limits designed to prevent a denial of service
+** attack. Developers might also want to use the [sqlite3_set_authorizer()]
+** interface to further control untrusted SQL. The size of the database
+** created by an untrusted script can be contained using the
+** [max_page_count] [PRAGMA].
+**
+** New run-time limit categories may be added in future releases.
+**
+** INVARIANTS:
+**
+** {H12762} A successful call to [sqlite3_limit(D,C,V)] where V is
+** positive changes the limit on the size of construct C in the
+** [database connection] D to the lesser of V and the hard upper
+** bound on the size of C that is set at compile-time.
+**
+** {H12766} A successful call to [sqlite3_limit(D,C,V)] where V is negative
+** leaves the state of the [database connection] D unchanged.
+**
+** {H12769} A successful call to [sqlite3_limit(D,C,V)] returns the
+** value of the limit on the size of construct C in the
+** [database connection] D as it was prior to the call.
+*/
+int sqlite3_limit(sqlite3*, int id, int newVal);
+
+/*
+** CAPI3REF: Run-Time Limit Categories {H12790} <H12760>
+** KEYWORDS: {limit category} {limit categories}
+**
+** These constants define various aspects of a [database connection]
+** that can be limited in size by calls to [sqlite3_limit()].
+** The meanings of the various limits are as follows:
+**
+** <dl>
+** <dt>SQLITE_LIMIT_LENGTH</dt>
+** <dd>The maximum size of any string or BLOB or table row.<dd>
+**
+** <dt>SQLITE_LIMIT_SQL_LENGTH</dt>
+** <dd>The maximum length of an SQL statement.</dd>
+**
+** <dt>SQLITE_LIMIT_COLUMN</dt>
+** <dd>The maximum number of columns in a table definition or in the
+** result set of a SELECT or the maximum number of columns in an index
+** or in an ORDER BY or GROUP BY clause.</dd>
+**
+** <dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
+** <dd>The maximum depth of the parse tree on any expression.</dd>
+**
+** <dt>SQLITE_LIMIT_COMPOUND_SELECT</dt>
+** <dd>The maximum number of terms in a compound SELECT statement.</dd>
+**
+** <dt>SQLITE_LIMIT_VDBE_OP</dt>
+** <dd>The maximum number of instructions in a virtual machine program
+** used to implement an SQL statement.</dd>
+**
+** <dt>SQLITE_LIMIT_FUNCTION_ARG</dt>
+** <dd>The maximum number of arguments on a function.</dd>
+**
+** <dt>SQLITE_LIMIT_ATTACHED</dt>
+** <dd>The maximum number of attached databases.</dd>
+**
+** <dt>SQLITE_LIMIT_LIKE_PATTERN_LENGTH</dt>
+** <dd>The maximum length of the pattern argument to the LIKE or
+** GLOB operators.</dd>
+**
+** <dt>SQLITE_LIMIT_VARIABLE_NUMBER</dt>
+** <dd>The maximum number of variables in an SQL statement that can
+** be bound.</dd>
+** </dl>
+*/
+#define SQLITE_LIMIT_LENGTH 0
+#define SQLITE_LIMIT_SQL_LENGTH 1
+#define SQLITE_LIMIT_COLUMN 2
+#define SQLITE_LIMIT_EXPR_DEPTH 3
+#define SQLITE_LIMIT_COMPOUND_SELECT 4
+#define SQLITE_LIMIT_VDBE_OP 5
+#define SQLITE_LIMIT_FUNCTION_ARG 6
+#define SQLITE_LIMIT_ATTACHED 7
+#define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8
+#define SQLITE_LIMIT_VARIABLE_NUMBER 9
+
+/*
+** CAPI3REF: Compiling An SQL Statement {H13010} <S10000>
+** KEYWORDS: {SQL statement compiler}
+**
+** To execute an SQL query, it must first be compiled into a byte-code
+** program using one of these routines.
+**
+** The first argument, "db", is a [database connection] obtained from a
+** prior call to [sqlite3_open()], [sqlite3_open_v2()] or [sqlite3_open16()].
+**
+** The second argument, "zSql", is the statement to be compiled, encoded
+** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2()
+** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2()
+** use UTF-16.
+**
+** If the nByte argument is less than zero, then zSql is read up to the
+** first zero terminator. If nByte is non-negative, then it is the maximum
+** number of bytes read from zSql. When nByte is non-negative, the
+** zSql string ends at either the first '\000' or '\u0000' character or
+** the nByte-th byte, whichever comes first. If the caller knows
+** that the supplied string is nul-terminated, then there is a small
+** performance advantage to be gained by passing an nByte parameter that
+** is equal to the number of bytes in the input string <i>including</i>
+** the nul-terminator bytes.
+**
+** *pzTail is made to point to the first byte past the end of the
+** first SQL statement in zSql. These routines only compile the first
+** statement in zSql, so *pzTail is left pointing to what remains
+** uncompiled.
+**
+** *ppStmt is left pointing to a compiled [prepared statement] that can be
+** executed using [sqlite3_step()]. If there is an error, *ppStmt is set
+** to NULL. If the input text contains no SQL (if the input is an empty
+** string or a comment) then *ppStmt is set to NULL.
+** {A13018} The calling procedure is responsible for deleting the compiled
+** SQL statement using [sqlite3_finalize()] after it has finished with it.
+**
+** On success, [SQLITE_OK] is returned, otherwise an [error code] is returned.
+**
+** The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are
+** recommended for all new programs. The two older interfaces are retained
+** for backwards compatibility, but their use is discouraged.
+** In the "v2" interfaces, the prepared statement
+** that is returned (the [sqlite3_stmt] object) contains a copy of the
+** original SQL text. This causes the [sqlite3_step()] interface to
+** behave a differently in two ways:
+**
+** <ol>
+** <li>
+** If the database schema changes, instead of returning [SQLITE_SCHEMA] as it
+** always used to do, [sqlite3_step()] will automatically recompile the SQL
+** statement and try to run it again. If the schema has changed in
+** a way that makes the statement no longer valid, [sqlite3_step()] will still
+** return [SQLITE_SCHEMA]. But unlike the legacy behavior, [SQLITE_SCHEMA] is
+** now a fatal error. Calling [sqlite3_prepare_v2()] again will not make the
+** error go away. Note: use [sqlite3_errmsg()] to find the text
+** of the parsing error that results in an [SQLITE_SCHEMA] return.
+** </li>
+**
+** <li>
+** When an error occurs, [sqlite3_step()] will return one of the detailed
+** [error codes] or [extended error codes]. The legacy behavior was that
+** [sqlite3_step()] would only return a generic [SQLITE_ERROR] result code
+** and you would have to make a second call to [sqlite3_reset()] in order
+** to find the underlying cause of the problem. With the "v2" prepare
+** interfaces, the underlying reason for the error is returned immediately.
+** </li>
+** </ol>
+**
+** INVARIANTS:
+**
+** {H13011} The [sqlite3_prepare(db,zSql,...)] and
+** [sqlite3_prepare_v2(db,zSql,...)] interfaces interpret the
+** text in their zSql parameter as UTF-8.
+**
+** {H13012} The [sqlite3_prepare16(db,zSql,...)] and
+** [sqlite3_prepare16_v2(db,zSql,...)] interfaces interpret the
+** text in their zSql parameter as UTF-16 in the native byte order.
+**
+** {H13013} If the nByte argument to [sqlite3_prepare_v2(db,zSql,nByte,...)]
+** and its variants is less than zero, the SQL text is
+** read from zSql is read up to the first zero terminator.
+**
+** {H13014} If the nByte argument to [sqlite3_prepare_v2(db,zSql,nByte,...)]
+** and its variants is non-negative, then at most nBytes bytes of
+** SQL text is read from zSql.
+**
+** {H13015} In [sqlite3_prepare_v2(db,zSql,N,P,pzTail)] and its variants
+** if the zSql input text contains more than one SQL statement
+** and pzTail is not NULL, then *pzTail is made to point to the
+** first byte past the end of the first SQL statement in zSql.
+** <todo>What does *pzTail point to if there is one statement?</todo>
+**
+** {H13016} A successful call to [sqlite3_prepare_v2(db,zSql,N,ppStmt,...)]
+** or one of its variants writes into *ppStmt a pointer to a new
+** [prepared statement] or a pointer to NULL if zSql contains
+** nothing other than whitespace or comments.
+**
+** {H13019} The [sqlite3_prepare_v2()] interface and its variants return
+** [SQLITE_OK] or an appropriate [error code] upon failure.
+**
+** {H13021} Before [sqlite3_prepare(db,zSql,nByte,ppStmt,pzTail)] or its
+** variants returns an error (any value other than [SQLITE_OK]),
+** they first set *ppStmt to NULL.
+*/
+int sqlite3_prepare(
+ sqlite3 *db, /* Database handle */
+ const char *zSql, /* SQL statement, UTF-8 encoded */
+ int nByte, /* Maximum length of zSql in bytes. */
+ sqlite3_stmt **ppStmt, /* OUT: Statement handle */
+ const char **pzTail /* OUT: Pointer to unused portion of zSql */
+);
+int sqlite3_prepare_v2(
+ sqlite3 *db, /* Database handle */
+ const char *zSql, /* SQL statement, UTF-8 encoded */
+ int nByte, /* Maximum length of zSql in bytes. */
+ sqlite3_stmt **ppStmt, /* OUT: Statement handle */
+ const char **pzTail /* OUT: Pointer to unused portion of zSql */
+);
+int sqlite3_prepare16(
+ sqlite3 *db, /* Database handle */
+ const void *zSql, /* SQL statement, UTF-16 encoded */
+ int nByte, /* Maximum length of zSql in bytes. */
+ sqlite3_stmt **ppStmt, /* OUT: Statement handle */
+ const void **pzTail /* OUT: Pointer to unused portion of zSql */
+);
+int sqlite3_prepare16_v2(
+ sqlite3 *db, /* Database handle */
+ const void *zSql, /* SQL statement, UTF-16 encoded */
+ int nByte, /* Maximum length of zSql in bytes. */
+ sqlite3_stmt **ppStmt, /* OUT: Statement handle */
+ const void **pzTail /* OUT: Pointer to unused portion of zSql */
+);
+
+/*
+** CAPIREF: Retrieving Statement SQL {H13100} <H13000>
+**
+** This interface can be used to retrieve a saved copy of the original
+** SQL text used to create a [prepared statement] if that statement was
+** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()].
+**
+** INVARIANTS:
+**
+** {H13101} If the [prepared statement] passed as the argument to
+** [sqlite3_sql()] was compiled using either [sqlite3_prepare_v2()] or
+** [sqlite3_prepare16_v2()], then [sqlite3_sql()] returns
+** a pointer to a zero-terminated string containing a UTF-8 rendering
+** of the original SQL statement.
+**
+** {H13102} If the [prepared statement] passed as the argument to
+** [sqlite3_sql()] was compiled using either [sqlite3_prepare()] or
+** [sqlite3_prepare16()], then [sqlite3_sql()] returns a NULL pointer.
+**
+** {H13103} The string returned by [sqlite3_sql(S)] is valid until the
+** [prepared statement] S is deleted using [sqlite3_finalize(S)].
+*/
+const char *sqlite3_sql(sqlite3_stmt *pStmt);
+
+/*
+** CAPI3REF: Dynamically Typed Value Object {H15000} <S20200>
+** KEYWORDS: {protected sqlite3_value} {unprotected sqlite3_value}
+**
+** SQLite uses the sqlite3_value object to represent all values
+** that can be stored in a database table. SQLite uses dynamic typing
+** for the values it stores. Values stored in sqlite3_value objects
+** can be integers, floating point values, strings, BLOBs, or NULL.
+**
+** An sqlite3_value object may be either "protected" or "unprotected".
+** Some interfaces require a protected sqlite3_value. Other interfaces
+** will accept either a protected or an unprotected sqlite3_value.
+** Every interface that accepts sqlite3_value arguments specifies
+** whether or not it requires a protected sqlite3_value.
+**
+** The terms "protected" and "unprotected" refer to whether or not
+** a mutex is held. A internal mutex is held for a protected
+** sqlite3_value object but no mutex is held for an unprotected
+** sqlite3_value object. If SQLite is compiled to be single-threaded
+** (with [SQLITE_THREADSAFE=0] and with [sqlite3_threadsafe()] returning 0)
+** or if SQLite is run in one of reduced mutex modes
+** [SQLITE_CONFIG_SINGLETHREAD] or [SQLITE_CONFIG_MULTITHREAD]
+** then there is no distinction between protected and unprotected
+** sqlite3_value objects and they can be used interchangeably. However,
+** for maximum code portability it is recommended that applications
+** still make the distinction between between protected and unprotected
+** sqlite3_value objects even when not strictly required.
+**
+** The sqlite3_value objects that are passed as parameters into the
+** implementation of [application-defined SQL functions] are protected.
+** The sqlite3_value object returned by
+** [sqlite3_column_value()] is unprotected.
+** Unprotected sqlite3_value objects may only be used with
+** [sqlite3_result_value()] and [sqlite3_bind_value()].
+** The [sqlite3_value_blob | sqlite3_value_type()] family of
+** interfaces require protected sqlite3_value objects.
+*/
+typedef struct Mem sqlite3_value;
+
+/*
+** CAPI3REF: SQL Function Context Object {H16001} <S20200>
+**
+** The context in which an SQL function executes is stored in an
+** sqlite3_context object. A pointer to an sqlite3_context object
+** is always first parameter to [application-defined SQL functions].
+** The application-defined SQL function implementation will pass this
+** pointer through into calls to [sqlite3_result_int | sqlite3_result()],
+** [sqlite3_aggregate_context()], [sqlite3_user_data()],
+** [sqlite3_context_db_handle()], [sqlite3_get_auxdata()],
+** and/or [sqlite3_set_auxdata()].
+*/
+typedef struct sqlite3_context sqlite3_context;
+
+/*
+** CAPI3REF: Binding Values To Prepared Statements {H13500} <S70300>
+** KEYWORDS: {host parameter} {host parameters} {host parameter name}
+** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding}
+**
+** In the SQL strings input to [sqlite3_prepare_v2()] and its variants,
+** literals may be replaced by a parameter in one of these forms:
+**
+** <ul>
+** <li> ?
+** <li> ?NNN
+** <li> :VVV
+** <li> @VVV
+** <li> $VVV
+** </ul>
+**
+** In the parameter forms shown above NNN is an integer literal,
+** and VVV is an alpha-numeric parameter name. The values of these
+** parameters (also called "host parameter names" or "SQL parameters")
+** can be set using the sqlite3_bind_*() routines defined here.
+**
+** The first argument to the sqlite3_bind_*() routines is always
+** a pointer to the [sqlite3_stmt] object returned from
+** [sqlite3_prepare_v2()] or its variants.
+**
+** The second argument is the index of the SQL parameter to be set.
+** The leftmost SQL parameter has an index of 1. When the same named
+** SQL parameter is used more than once, second and subsequent
+** occurrences have the same index as the first occurrence.
+** The index for named parameters can be looked up using the
+** [sqlite3_bind_parameter_index()] API if desired. The index
+** for "?NNN" parameters is the value of NNN.
+** The NNN value must be between 1 and the [sqlite3_limit()]
+** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999).
+**
+** The third argument is the value to bind to the parameter.
+**
+** In those routines that have a fourth argument, its value is the
+** number of bytes in the parameter. To be clear: the value is the
+** number of <u>bytes</u> in the value, not the number of characters.
+** If the fourth parameter is negative, the length of the string is
+** the number of bytes up to the first zero terminator.
+**
+** The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and
+** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or
+** string after SQLite has finished with it. If the fifth argument is
+** the special value [SQLITE_STATIC], then SQLite assumes that the
+** information is in static, unmanaged space and does not need to be freed.
+** If the fifth argument has the value [SQLITE_TRANSIENT], then
+** SQLite makes its own private copy of the data immediately, before
+** the sqlite3_bind_*() routine returns.
+**
+** The sqlite3_bind_zeroblob() routine binds a BLOB of length N that
+** is filled with zeroes. A zeroblob uses a fixed amount of memory
+** (just an integer to hold its size) while it is being processed.
+** Zeroblobs are intended to serve as placeholders for BLOBs whose
+** content is later written using
+** [sqlite3_blob_open | incremental BLOB I/O] routines.
+** A negative value for the zeroblob results in a zero-length BLOB.
+**
+** The sqlite3_bind_*() routines must be called after
+** [sqlite3_prepare_v2()] (and its variants) or [sqlite3_reset()] and
+** before [sqlite3_step()].
+** Bindings are not cleared by the [sqlite3_reset()] routine.
+** Unbound parameters are interpreted as NULL.
+**
+** These routines return [SQLITE_OK] on success or an error code if
+** anything goes wrong. [SQLITE_RANGE] is returned if the parameter
+** index is out of range. [SQLITE_NOMEM] is returned if malloc() fails.
+** [SQLITE_MISUSE] might be returned if these routines are called on a
+** virtual machine that is the wrong state or which has already been finalized.
+** Detection of misuse is unreliable. Applications should not depend
+** on SQLITE_MISUSE returns. SQLITE_MISUSE is intended to indicate a
+** a logic error in the application. Future versions of SQLite might
+** panic rather than return SQLITE_MISUSE.
+**
+** See also: [sqlite3_bind_parameter_count()],
+** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()].
+**
+** INVARIANTS:
+**
+** {H13506} The [SQL statement compiler] recognizes tokens of the forms
+** "?", "?NNN", "$VVV", ":VVV", and "@VVV" as SQL parameters,
+** where NNN is any sequence of one or more digits
+** and where VVV is any sequence of one or more alphanumeric
+** characters or "::" optionally followed by a string containing
+** no spaces and contained within parentheses.
+**
+** {H13509} The initial value of an SQL parameter is NULL.
+**
+** {H13512} The index of an "?" SQL parameter is one larger than the
+** largest index of SQL parameter to the left, or 1 if
+** the "?" is the leftmost SQL parameter.
+**
+** {H13515} The index of an "?NNN" SQL parameter is the integer NNN.
+**
+** {H13518} The index of an ":VVV", "$VVV", or "@VVV" SQL parameter is
+** the same as the index of leftmost occurrences of the same
+** parameter, or one more than the largest index over all
+** parameters to the left if this is the first occurrence
+** of this parameter, or 1 if this is the leftmost parameter.
+**
+** {H13521} The [SQL statement compiler] fails with an [SQLITE_RANGE]
+** error if the index of an SQL parameter is less than 1
+** or greater than the compile-time SQLITE_MAX_VARIABLE_NUMBER
+** parameter.
+**
+** {H13524} Calls to [sqlite3_bind_text | sqlite3_bind(S,N,V,...)]
+** associate the value V with all SQL parameters having an
+** index of N in the [prepared statement] S.
+**
+** {H13527} Calls to [sqlite3_bind_text | sqlite3_bind(S,N,...)]
+** override prior calls with the same values of S and N.
+**
+** {H13530} Bindings established by [sqlite3_bind_text | sqlite3_bind(S,...)]
+** persist across calls to [sqlite3_reset(S)].
+**
+** {H13533} In calls to [sqlite3_bind_blob(S,N,V,L,D)],
+** [sqlite3_bind_text(S,N,V,L,D)], or
+** [sqlite3_bind_text16(S,N,V,L,D)] SQLite binds the first L
+** bytes of the BLOB or string pointed to by V, when L
+** is non-negative.
+**
+** {H13536} In calls to [sqlite3_bind_text(S,N,V,L,D)] or
+** [sqlite3_bind_text16(S,N,V,L,D)] SQLite binds characters
+** from V through the first zero character when L is negative.
+**
+** {H13539} In calls to [sqlite3_bind_blob(S,N,V,L,D)],
+** [sqlite3_bind_text(S,N,V,L,D)], or
+** [sqlite3_bind_text16(S,N,V,L,D)] when D is the special
+** constant [SQLITE_STATIC], SQLite assumes that the value V
+** is held in static unmanaged space that will not change
+** during the lifetime of the binding.
+**
+** {H13542} In calls to [sqlite3_bind_blob(S,N,V,L,D)],
+** [sqlite3_bind_text(S,N,V,L,D)], or
+** [sqlite3_bind_text16(S,N,V,L,D)] when D is the special
+** constant [SQLITE_TRANSIENT], the routine makes a
+** private copy of the value V before it returns.
+**
+** {H13545} In calls to [sqlite3_bind_blob(S,N,V,L,D)],
+** [sqlite3_bind_text(S,N,V,L,D)], or
+** [sqlite3_bind_text16(S,N,V,L,D)] when D is a pointer to
+** a function, SQLite invokes that function to destroy the
+** value V after it has finished using the value V.
+**
+** {H13548} In calls to [sqlite3_bind_zeroblob(S,N,V,L)] the value bound
+** is a BLOB of L bytes, or a zero-length BLOB if L is negative.
+**
+** {H13551} In calls to [sqlite3_bind_value(S,N,V)] the V argument may
+** be either a [protected sqlite3_value] object or an
+** [unprotected sqlite3_value] object.
+*/
+int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
+int sqlite3_bind_double(sqlite3_stmt*, int, double);
+int sqlite3_bind_int(sqlite3_stmt*, int, int);
+int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
+int sqlite3_bind_null(sqlite3_stmt*, int);
+int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*));
+int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
+int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
+int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
+
+/*
+** CAPI3REF: Number Of SQL Parameters {H13600} <S70300>
+**
+** This routine can be used to find the number of [SQL parameters]
+** in a [prepared statement]. SQL parameters are tokens of the
+** form "?", "?NNN", ":AAA", "$AAA", or "@AAA" that serve as
+** placeholders for values that are [sqlite3_bind_blob | bound]
+** to the parameters at a later time.
+**
+** This routine actually returns the index of the largest (rightmost)
+** parameter. For all forms except ?NNN, this will correspond to the
+** number of unique parameters. If parameters of the ?NNN are used,
+** there may be gaps in the list.
+**
+** See also: [sqlite3_bind_blob|sqlite3_bind()],
+** [sqlite3_bind_parameter_name()], and
+** [sqlite3_bind_parameter_index()].
+**
+** INVARIANTS:
+**
+** {H13601} The [sqlite3_bind_parameter_count(S)] interface returns
+** the largest index of all SQL parameters in the
+** [prepared statement] S, or 0 if S contains no SQL parameters.
+*/
+int sqlite3_bind_parameter_count(sqlite3_stmt*);
+
+/*
+** CAPI3REF: Name Of A Host Parameter {H13620} <S70300>
+**
+** This routine returns a pointer to the name of the n-th
+** [SQL parameter] in a [prepared statement].
+** SQL parameters of the form "?NNN" or ":AAA" or "@AAA" or "$AAA"
+** have a name which is the string "?NNN" or ":AAA" or "@AAA" or "$AAA"
+** respectively.
+** In other words, the initial ":" or "$" or "@" or "?"
+** is included as part of the name.
+** Parameters of the form "?" without a following integer have no name
+** and are also referred to as "anonymous parameters".
+**
+** The first host parameter has an index of 1, not 0.
+**
+** If the value n is out of range or if the n-th parameter is
+** nameless, then NULL is returned. The returned string is
+** always in UTF-8 encoding even if the named parameter was
+** originally specified as UTF-16 in [sqlite3_prepare16()] or
+** [sqlite3_prepare16_v2()].
+**
+** See also: [sqlite3_bind_blob|sqlite3_bind()],
+** [sqlite3_bind_parameter_count()], and
+** [sqlite3_bind_parameter_index()].
+**
+** INVARIANTS:
+**
+** {H13621} The [sqlite3_bind_parameter_name(S,N)] interface returns
+** a UTF-8 rendering of the name of the SQL parameter in
+** the [prepared statement] S having index N, or
+** NULL if there is no SQL parameter with index N or if the
+** parameter with index N is an anonymous parameter "?".
+*/
+const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
+
+/*
+** CAPI3REF: Index Of A Parameter With A Given Name {H13640} <S70300>
+**
+** Return the index of an SQL parameter given its name. The
+** index value returned is suitable for use as the second
+** parameter to [sqlite3_bind_blob|sqlite3_bind()]. A zero
+** is returned if no matching parameter is found. The parameter
+** name must be given in UTF-8 even if the original statement
+** was prepared from UTF-16 text using [sqlite3_prepare16_v2()].
+**
+** See also: [sqlite3_bind_blob|sqlite3_bind()],
+** [sqlite3_bind_parameter_count()], and
+** [sqlite3_bind_parameter_index()].
+**
+** INVARIANTS:
+**
+** {H13641} The [sqlite3_bind_parameter_index(S,N)] interface returns
+** the index of SQL parameter in the [prepared statement]
+** S whose name matches the UTF-8 string N, or 0 if there is
+** no match.
+*/
+int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName);
+
+/*
+** CAPI3REF: Reset All Bindings On A Prepared Statement {H13660} <S70300>
+**
+** Contrary to the intuition of many, [sqlite3_reset()] does not reset
+** the [sqlite3_bind_blob | bindings] on a [prepared statement].
+** Use this routine to reset all host parameters to NULL.
+**
+** INVARIANTS:
+**
+** {H13661} The [sqlite3_clear_bindings(S)] interface resets all SQL
+** parameter bindings in the [prepared statement] S back to NULL.
+*/
+int sqlite3_clear_bindings(sqlite3_stmt*);
+
+/*
+** CAPI3REF: Number Of Columns In A Result Set {H13710} <S10700>
+**
+** Return the number of columns in the result set returned by the
+** [prepared statement]. This routine returns 0 if pStmt is an SQL
+** statement that does not return data (for example an [UPDATE]).
+**
+** INVARIANTS:
+**
+** {H13711} The [sqlite3_column_count(S)] interface returns the number of
+** columns in the result set generated by the [prepared statement] S,
+** or 0 if S does not generate a result set.
+*/
+int sqlite3_column_count(sqlite3_stmt *pStmt);
+
+/*
+** CAPI3REF: Column Names In A Result Set {H13720} <S10700>
+**
+** These routines return the name assigned to a particular column
+** in the result set of a [SELECT] statement. The sqlite3_column_name()
+** interface returns a pointer to a zero-terminated UTF-8 string
+** and sqlite3_column_name16() returns a pointer to a zero-terminated
+** UTF-16 string. The first parameter is the [prepared statement]
+** that implements the [SELECT] statement. The second parameter is the
+** column number. The leftmost column is number 0.
+**
+** The returned string pointer is valid until either the [prepared statement]
+** is destroyed by [sqlite3_finalize()] or until the next call to
+** sqlite3_column_name() or sqlite3_column_name16() on the same column.
+**
+** If sqlite3_malloc() fails during the processing of either routine
+** (for example during a conversion from UTF-8 to UTF-16) then a
+** NULL pointer is returned.
+**
+** The name of a result column is the value of the "AS" clause for
+** that column, if there is an AS clause. If there is no AS clause
+** then the name of the column is unspecified and may change from
+** one release of SQLite to the next.
+**
+** INVARIANTS:
+**
+** {H13721} A successful invocation of the [sqlite3_column_name(S,N)]
+** interface returns the name of the Nth column (where 0 is
+** the leftmost column) for the result set of the
+** [prepared statement] S as a zero-terminated UTF-8 string.
+**
+** {H13723} A successful invocation of the [sqlite3_column_name16(S,N)]
+** interface returns the name of the Nth column (where 0 is
+** the leftmost column) for the result set of the
+** [prepared statement] S as a zero-terminated UTF-16 string
+** in the native byte order.
+**
+** {H13724} The [sqlite3_column_name()] and [sqlite3_column_name16()]
+** interfaces return a NULL pointer if they are unable to
+** allocate memory to hold their normal return strings.
+**
+** {H13725} If the N parameter to [sqlite3_column_name(S,N)] or
+** [sqlite3_column_name16(S,N)] is out of range, then the
+** interfaces return a NULL pointer.
+**
+** {H13726} The strings returned by [sqlite3_column_name(S,N)] and
+** [sqlite3_column_name16(S,N)] are valid until the next
+** call to either routine with the same S and N parameters
+** or until [sqlite3_finalize(S)] is called.
+**
+** {H13727} When a result column of a [SELECT] statement contains
+** an AS clause, the name of that column is the identifier
+** to the right of the AS keyword.
+*/
+const char *sqlite3_column_name(sqlite3_stmt*, int N);
+const void *sqlite3_column_name16(sqlite3_stmt*, int N);
+
+/*
+** CAPI3REF: Source Of Data In A Query Result {H13740} <S10700>
+**
+** These routines provide a means to determine what column of what
+** table in which database a result of a [SELECT] statement comes from.
+** The name of the database or table or column can be returned as
+** either a UTF-8 or UTF-16 string. The _database_ routines return
+** the database name, the _table_ routines return the table name, and
+** the origin_ routines return the column name.
+** The returned string is valid until the [prepared statement] is destroyed
+** using [sqlite3_finalize()] or until the same information is requested
+** again in a different encoding.
+**
+** The names returned are the original un-aliased names of the
+** database, table, and column.
+**
+** The first argument to the following calls is a [prepared statement].
+** These functions return information about the Nth column returned by
+** the statement, where N is the second function argument.
+**
+** If the Nth column returned by the statement is an expression or
+** subquery and is not a column value, then all of these functions return
+** NULL. These routine might also return NULL if a memory allocation error
+** occurs. Otherwise, they return the name of the attached database, table
+** and column that query result column was extracted from.
+**
+** As with all other SQLite APIs, those postfixed with "16" return
+** UTF-16 encoded strings, the other functions return UTF-8. {END}
+**
+** These APIs are only available if the library was compiled with the
+** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined.
+**
+** {A13751}
+** If two or more threads call one or more of these routines against the same
+** prepared statement and column at the same time then the results are
+** undefined.
+**
+** INVARIANTS:
+**
+** {H13741} The [sqlite3_column_database_name(S,N)] interface returns either
+** the UTF-8 zero-terminated name of the database from which the
+** Nth result column of the [prepared statement] S is extracted,
+** or NULL if the Nth column of S is a general expression
+** or if unable to allocate memory to store the name.
+**
+** {H13742} The [sqlite3_column_database_name16(S,N)] interface returns either
+** the UTF-16 native byte order zero-terminated name of the database
+** from which the Nth result column of the [prepared statement] S is
+** extracted, or NULL if the Nth column of S is a general expression
+** or if unable to allocate memory to store the name.
+**
+** {H13743} The [sqlite3_column_table_name(S,N)] interface returns either
+** the UTF-8 zero-terminated name of the table from which the
+** Nth result column of the [prepared statement] S is extracted,
+** or NULL if the Nth column of S is a general expression
+** or if unable to allocate memory to store the name.
+**
+** {H13744} The [sqlite3_column_table_name16(S,N)] interface returns either
+** the UTF-16 native byte order zero-terminated name of the table
+** from which the Nth result column of the [prepared statement] S is
+** extracted, or NULL if the Nth column of S is a general expression
+** or if unable to allocate memory to store the name.
+**
+** {H13745} The [sqlite3_column_origin_name(S,N)] interface returns either
+** the UTF-8 zero-terminated name of the table column from which the
+** Nth result column of the [prepared statement] S is extracted,
+** or NULL if the Nth column of S is a general expression
+** or if unable to allocate memory to store the name.
+**
+** {H13746} The [sqlite3_column_origin_name16(S,N)] interface returns either
+** the UTF-16 native byte order zero-terminated name of the table
+** column from which the Nth result column of the
+** [prepared statement] S is extracted, or NULL if the Nth column
+** of S is a general expression or if unable to allocate memory
+** to store the name.
+**
+** {H13748} The return values from
+** [sqlite3_column_database_name | column metadata interfaces]
+** are valid for the lifetime of the [prepared statement]
+** or until the encoding is changed by another metadata
+** interface call for the same prepared statement and column.
+**
+** ASSUMPTIONS:
+**
+** {A13751} If two or more threads call one or more
+** [sqlite3_column_database_name | column metadata interfaces]
+** for the same [prepared statement] and result column
+** at the same time then the results are undefined.
+*/
+const char *sqlite3_column_database_name(sqlite3_stmt*,int);
+const void *sqlite3_column_database_name16(sqlite3_stmt*,int);
+const char *sqlite3_column_table_name(sqlite3_stmt*,int);
+const void *sqlite3_column_table_name16(sqlite3_stmt*,int);
+const char *sqlite3_column_origin_name(sqlite3_stmt*,int);
+const void *sqlite3_column_origin_name16(sqlite3_stmt*,int);
+
+/*
+** CAPI3REF: Declared Datatype Of A Query Result {H13760} <S10700>
+**
+** The first parameter is a [prepared statement].
+** If this statement is a [SELECT] statement and the Nth column of the
+** returned result set of that [SELECT] is a table column (not an
+** expression or subquery) then the declared type of the table
+** column is returned. If the Nth column of the result set is an
+** expression or subquery, then a NULL pointer is returned.
+** The returned string is always UTF-8 encoded. {END}
+**
+** For example, given the database schema:
+**
+** CREATE TABLE t1(c1 VARIANT);
+**
+** and the following statement to be compiled:
+**
+** SELECT c1 + 1, c1 FROM t1;
+**
+** this routine would return the string "VARIANT" for the second result
+** column (i==1), and a NULL pointer for the first result column (i==0).
+**
+** SQLite uses dynamic run-time typing. So just because a column
+** is declared to contain a particular type does not mean that the
+** data stored in that column is of the declared type. SQLite is
+** strongly typed, but the typing is dynamic not static. Type
+** is associated with individual values, not with the containers
+** used to hold those values.
+**
+** INVARIANTS:
+**
+** {H13761} A successful call to [sqlite3_column_decltype(S,N)] returns a
+** zero-terminated UTF-8 string containing the declared datatype
+** of the table column that appears as the Nth column (numbered
+** from 0) of the result set to the [prepared statement] S.
+**
+** {H13762} A successful call to [sqlite3_column_decltype16(S,N)]
+** returns a zero-terminated UTF-16 native byte order string
+** containing the declared datatype of the table column that appears
+** as the Nth column (numbered from 0) of the result set to the
+** [prepared statement] S.
+**
+** {H13763} If N is less than 0 or N is greater than or equal to
+** the number of columns in the [prepared statement] S,
+** or if the Nth column of S is an expression or subquery rather
+** than a table column, or if a memory allocation failure
+** occurs during encoding conversions, then
+** calls to [sqlite3_column_decltype(S,N)] or
+** [sqlite3_column_decltype16(S,N)] return NULL.
+*/
+const char *sqlite3_column_decltype(sqlite3_stmt*,int);
+const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
+
+/*
+** CAPI3REF: Evaluate An SQL Statement {H13200} <S10000>
+**
+** After a [prepared statement] has been prepared using either
+** [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or one of the legacy
+** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this function
+** must be called one or more times to evaluate the statement.
+**
+** The details of the behavior of the sqlite3_step() interface depend
+** on whether the statement was prepared using the newer "v2" interface
+** [sqlite3_prepare_v2()] and [sqlite3_prepare16_v2()] or the older legacy
+** interface [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the
+** new "v2" interface is recommended for new applications but the legacy
+** interface will continue to be supported.
+**
+** In the legacy interface, the return value will be either [SQLITE_BUSY],
+** [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE].
+** With the "v2" interface, any of the other [result codes] or
+** [extended result codes] might be returned as well.
+**
+** [SQLITE_BUSY] means that the database engine was unable to acquire the
+** database locks it needs to do its job. If the statement is a [COMMIT]
+** or occurs outside of an explicit transaction, then you can retry the
+** statement. If the statement is not a [COMMIT] and occurs within a
+** explicit transaction then you should rollback the transaction before
+** continuing.
+**
+** [SQLITE_DONE] means that the statement has finished executing
+** successfully. sqlite3_step() should not be called again on this virtual
+** machine without first calling [sqlite3_reset()] to reset the virtual
+** machine back to its initial state.
+**
+** If the SQL statement being executed returns any data, then [SQLITE_ROW]
+** is returned each time a new row of data is ready for processing by the
+** caller. The values may be accessed using the [column access functions].
+** sqlite3_step() is called again to retrieve the next row of data.
+**
+** [SQLITE_ERROR] means that a run-time error (such as a constraint
+** violation) has occurred. sqlite3_step() should not be called again on
+** the VM. More information may be found by calling [sqlite3_errmsg()].
+** With the legacy interface, a more specific error code (for example,
+** [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth)
+** can be obtained by calling [sqlite3_reset()] on the
+** [prepared statement]. In the "v2" interface,
+** the more specific error code is returned directly by sqlite3_step().
+**
+** [SQLITE_MISUSE] means that the this routine was called inappropriately.
+** Perhaps it was called on a [prepared statement] that has
+** already been [sqlite3_finalize | finalized] or on one that had
+** previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could
+** be the case that the same database connection is being used by two or
+** more threads at the same moment in time.
+**
+** <b>Goofy Interface Alert:</b> In the legacy interface, the sqlite3_step()
+** API always returns a generic error code, [SQLITE_ERROR], following any
+** error other than [SQLITE_BUSY] and [SQLITE_MISUSE]. You must call
+** [sqlite3_reset()] or [sqlite3_finalize()] in order to find one of the
+** specific [error codes] that better describes the error.
+** We admit that this is a goofy design. The problem has been fixed
+** with the "v2" interface. If you prepare all of your SQL statements
+** using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead
+** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()] interfaces,
+** then the more specific [error codes] are returned directly
+** by sqlite3_step(). The use of the "v2" interface is recommended.
+**
+** INVARIANTS:
+**
+** {H13202} If the [prepared statement] S is ready to be run, then
+** [sqlite3_step(S)] advances that prepared statement until
+** completion or until it is ready to return another row of the
+** result set, or until an [sqlite3_interrupt | interrupt]
+** or a run-time error occurs.
+**
+** {H15304} When a call to [sqlite3_step(S)] causes the [prepared statement]
+** S to run to completion, the function returns [SQLITE_DONE].
+**
+** {H15306} When a call to [sqlite3_step(S)] stops because it is ready to
+** return another row of the result set, it returns [SQLITE_ROW].
+**
+** {H15308} If a call to [sqlite3_step(S)] encounters an
+** [sqlite3_interrupt | interrupt] or a run-time error,
+** it returns an appropriate error code that is not one of
+** [SQLITE_OK], [SQLITE_ROW], or [SQLITE_DONE].
+**
+** {H15310} If an [sqlite3_interrupt | interrupt] or a run-time error
+** occurs during a call to [sqlite3_step(S)]
+** for a [prepared statement] S created using
+** legacy interfaces [sqlite3_prepare()] or
+** [sqlite3_prepare16()], then the function returns either
+** [SQLITE_ERROR], [SQLITE_BUSY], or [SQLITE_MISUSE].
+*/
+int sqlite3_step(sqlite3_stmt*);
+
+/*
+** CAPI3REF: Number of columns in a result set {H13770} <S10700>
+**
+** Returns the number of values in the current row of the result set.
+**
+** INVARIANTS:
+**
+** {H13771} After a call to [sqlite3_step(S)] that returns [SQLITE_ROW],
+** the [sqlite3_data_count(S)] routine will return the same value
+** as the [sqlite3_column_count(S)] function.
+**
+** {H13772} After [sqlite3_step(S)] has returned any value other than
+** [SQLITE_ROW] or before [sqlite3_step(S)] has been called on the
+** [prepared statement] for the first time since it was
+** [sqlite3_prepare | prepared] or [sqlite3_reset | reset],
+** the [sqlite3_data_count(S)] routine returns zero.
+*/
+int sqlite3_data_count(sqlite3_stmt *pStmt);
+
+/*
+** CAPI3REF: Fundamental Datatypes {H10265} <S10110><S10120>
+** KEYWORDS: SQLITE_TEXT
+**
+** {H10266} Every value in SQLite has one of five fundamental datatypes:
+**
+** <ul>
+** <li> 64-bit signed integer
+** <li> 64-bit IEEE floating point number
+** <li> string
+** <li> BLOB
+** <li> NULL
+** </ul> {END}
+**
+** These constants are codes for each of those types.
+**
+** Note that the SQLITE_TEXT constant was also used in SQLite version 2
+** for a completely different meaning. Software that links against both
+** SQLite version 2 and SQLite version 3 should use SQLITE3_TEXT, not
+** SQLITE_TEXT.
+*/
+#define SQLITE_INTEGER 1
+#define SQLITE_FLOAT 2
+#define SQLITE_BLOB 4
+#define SQLITE_NULL 5
+#ifdef SQLITE_TEXT
+# undef SQLITE_TEXT
+#else
+# define SQLITE_TEXT 3
+#endif
+#define SQLITE3_TEXT 3
+
+/*
+** CAPI3REF: Result Values From A Query {H13800} <S10700>
+** KEYWORDS: {column access functions}
+**
+** These routines form the "result set query" interface.
+**
+** These routines return information about a single column of the current
+** result row of a query. In every case the first argument is a pointer
+** to the [prepared statement] that is being evaluated (the [sqlite3_stmt*]
+** that was returned from [sqlite3_prepare_v2()] or one of its variants)
+** and the second argument is the index of the column for which information
+** should be returned. The leftmost column of the result set has the index 0.
+**
+** If the SQL statement does not currently point to a valid row, or if the
+** column index is out of range, the result is undefined.
+** These routines may only be called when the most recent call to
+** [sqlite3_step()] has returned [SQLITE_ROW] and neither
+** [sqlite3_reset()] nor [sqlite3_finalize()] have been called subsequently.
+** If any of these routines are called after [sqlite3_reset()] or
+** [sqlite3_finalize()] or after [sqlite3_step()] has returned
+** something other than [SQLITE_ROW], the results are undefined.
+** If [sqlite3_step()] or [sqlite3_reset()] or [sqlite3_finalize()]
+** are called from a different thread while any of these routines
+** are pending, then the results are undefined.
+**
+** The sqlite3_column_type() routine returns the
+** [SQLITE_INTEGER | datatype code] for the initial data type
+** of the result column. The returned value is one of [SQLITE_INTEGER],
+** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. The value
+** returned by sqlite3_column_type() is only meaningful if no type
+** conversions have occurred as described below. After a type conversion,
+** the value returned by sqlite3_column_type() is undefined. Future
+** versions of SQLite may change the behavior of sqlite3_column_type()
+** following a type conversion.
+**
+** If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes()
+** routine returns the number of bytes in that BLOB or string.
+** If the result is a UTF-16 string, then sqlite3_column_bytes() converts
+** the string to UTF-8 and then returns the number of bytes.
+** If the result is a numeric value then sqlite3_column_bytes() uses
+** [sqlite3_snprintf()] to convert that value to a UTF-8 string and returns
+** the number of bytes in that string.
+** The value returned does not include the zero terminator at the end
+** of the string. For clarity: the value returned is the number of
+** bytes in the string, not the number of characters.
+**
+** Strings returned by sqlite3_column_text() and sqlite3_column_text16(),
+** even empty strings, are always zero terminated. The return
+** value from sqlite3_column_blob() for a zero-length BLOB is an arbitrary
+** pointer, possibly even a NULL pointer.
+**
+** The sqlite3_column_bytes16() routine is similar to sqlite3_column_bytes()
+** but leaves the result in UTF-16 in native byte order instead of UTF-8.
+** The zero terminator is not included in this count.
+**
+** The object returned by [sqlite3_column_value()] is an
+** [unprotected sqlite3_value] object. An unprotected sqlite3_value object
+** may only be used with [sqlite3_bind_value()] and [sqlite3_result_value()].
+** If the [unprotected sqlite3_value] object returned by
+** [sqlite3_column_value()] is used in any other way, including calls
+** to routines like [sqlite3_value_int()], [sqlite3_value_text()],
+** or [sqlite3_value_bytes()], then the behavior is undefined.
+**
+** These routines attempt to convert the value where appropriate. For
+** example, if the internal representation is FLOAT and a text result
+** is requested, [sqlite3_snprintf()] is used internally to perform the
+** conversion automatically. The following table details the conversions
+** that are applied:
+**
+** <blockquote>
+** <table border="1">
+** <tr><th> Internal<br>Type <th> Requested<br>Type <th> Conversion
+**
+** <tr><td> NULL <td> INTEGER <td> Result is 0
+** <tr><td> NULL <td> FLOAT <td> Result is 0.0
+** <tr><td> NULL <td> TEXT <td> Result is NULL pointer
+** <tr><td> NULL <td> BLOB <td> Result is NULL pointer
+** <tr><td> INTEGER <td> FLOAT <td> Convert from integer to float
+** <tr><td> INTEGER <td> TEXT <td> ASCII rendering of the integer
+** <tr><td> INTEGER <td> BLOB <td> Same as INTEGER->TEXT
+** <tr><td> FLOAT <td> INTEGER <td> Convert from float to integer
+** <tr><td> FLOAT <td> TEXT <td> ASCII rendering of the float
+** <tr><td> FLOAT <td> BLOB <td> Same as FLOAT->TEXT
+** <tr><td> TEXT <td> INTEGER <td> Use atoi()
+** <tr><td> TEXT <td> FLOAT <td> Use atof()
+** <tr><td> TEXT <td> BLOB <td> No change
+** <tr><td> BLOB <td> INTEGER <td> Convert to TEXT then use atoi()
+** <tr><td> BLOB <td> FLOAT <td> Convert to TEXT then use atof()
+** <tr><td> BLOB <td> TEXT <td> Add a zero terminator if needed
+** </table>
+** </blockquote>
+**
+** The table above makes reference to standard C library functions atoi()
+** and atof(). SQLite does not really use these functions. It has its
+** own equivalent internal routines. The atoi() and atof() names are
+** used in the table for brevity and because they are familiar to most
+** C programmers.
+**
+** Note that when type conversions occur, pointers returned by prior
+** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or
+** sqlite3_column_text16() may be invalidated.
+** Type conversions and pointer invalidations might occur
+** in the following cases:
+**
+** <ul>
+** <li> The initial content is a BLOB and sqlite3_column_text() or
+** sqlite3_column_text16() is called. A zero-terminator might
+** need to be added to the string.</li>
+** <li> The initial content is UTF-8 text and sqlite3_column_bytes16() or
+** sqlite3_column_text16() is called. The content must be converted
+** to UTF-16.</li>
+** <li> The initial content is UTF-16 text and sqlite3_column_bytes() or
+** sqlite3_column_text() is called. The content must be converted
+** to UTF-8.</li>
+** </ul>
+**
+** Conversions between UTF-16be and UTF-16le are always done in place and do
+** not invalidate a prior pointer, though of course the content of the buffer
+** that the prior pointer points to will have been modified. Other kinds
+** of conversion are done in place when it is possible, but sometimes they
+** are not possible and in those cases prior pointers are invalidated.
+**
+** The safest and easiest to remember policy is to invoke these routines
+** in one of the following ways:
+**
+** <ul>
+** <li>sqlite3_column_text() followed by sqlite3_column_bytes()</li>
+** <li>sqlite3_column_blob() followed by sqlite3_column_bytes()</li>
+** <li>sqlite3_column_text16() followed by sqlite3_column_bytes16()</li>
+** </ul>
+**
+** In other words, you should call sqlite3_column_text(),
+** sqlite3_column_blob(), or sqlite3_column_text16() first to force the result
+** into the desired format, then invoke sqlite3_column_bytes() or
+** sqlite3_column_bytes16() to find the size of the result. Do not mix calls
+** to sqlite3_column_text() or sqlite3_column_blob() with calls to
+** sqlite3_column_bytes16(), and do not mix calls to sqlite3_column_text16()
+** with calls to sqlite3_column_bytes().
+**
+** The pointers returned are valid until a type conversion occurs as
+** described above, or until [sqlite3_step()] or [sqlite3_reset()] or
+** [sqlite3_finalize()] is called. The memory space used to hold strings
+** and BLOBs is freed automatically. Do <b>not</b> pass the pointers returned
+** [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
+** [sqlite3_free()].
+**
+** If a memory allocation error occurs during the evaluation of any
+** of these routines, a default value is returned. The default value
+** is either the integer 0, the floating point number 0.0, or a NULL
+** pointer. Subsequent calls to [sqlite3_errcode()] will return
+** [SQLITE_NOMEM].
+**
+** INVARIANTS:
+**
+** {H13803} The [sqlite3_column_blob(S,N)] interface converts the
+** Nth column in the current row of the result set for
+** the [prepared statement] S into a BLOB and then returns a
+** pointer to the converted value.
+**
+** {H13806} The [sqlite3_column_bytes(S,N)] interface returns the
+** number of bytes in the BLOB or string (exclusive of the
+** zero terminator on the string) that was returned by the
+** most recent call to [sqlite3_column_blob(S,N)] or
+** [sqlite3_column_text(S,N)].
+**
+** {H13809} The [sqlite3_column_bytes16(S,N)] interface returns the
+** number of bytes in the string (exclusive of the
+** zero terminator on the string) that was returned by the
+** most recent call to [sqlite3_column_text16(S,N)].
+**
+** {H13812} The [sqlite3_column_double(S,N)] interface converts the
+** Nth column in the current row of the result set for the
+** [prepared statement] S into a floating point value and
+** returns a copy of that value.
+**
+** {H13815} The [sqlite3_column_int(S,N)] interface converts the
+** Nth column in the current row of the result set for the
+** [prepared statement] S into a 64-bit signed integer and
+** returns the lower 32 bits of that integer.
+**
+** {H13818} The [sqlite3_column_int64(S,N)] interface converts the
+** Nth column in the current row of the result set for the
+** [prepared statement] S into a 64-bit signed integer and
+** returns a copy of that integer.
+**
+** {H13821} The [sqlite3_column_text(S,N)] interface converts the
+** Nth column in the current row of the result set for
+** the [prepared statement] S into a zero-terminated UTF-8
+** string and returns a pointer to that string.
+**
+** {H13824} The [sqlite3_column_text16(S,N)] interface converts the
+** Nth column in the current row of the result set for the
+** [prepared statement] S into a zero-terminated 2-byte
+** aligned UTF-16 native byte order string and returns
+** a pointer to that string.
+**
+** {H13827} The [sqlite3_column_type(S,N)] interface returns
+** one of [SQLITE_NULL], [SQLITE_INTEGER], [SQLITE_FLOAT],
+** [SQLITE_TEXT], or [SQLITE_BLOB] as appropriate for
+** the Nth column in the current row of the result set for
+** the [prepared statement] S.
+**
+** {H13830} The [sqlite3_column_value(S,N)] interface returns a
+** pointer to an [unprotected sqlite3_value] object for the
+** Nth column in the current row of the result set for
+** the [prepared statement] S.
+*/
+const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
+int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
+int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
+double sqlite3_column_double(sqlite3_stmt*, int iCol);
+int sqlite3_column_int(sqlite3_stmt*, int iCol);
+sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);
+const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
+const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
+int sqlite3_column_type(sqlite3_stmt*, int iCol);
+sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
+
+/*
+** CAPI3REF: Destroy A Prepared Statement Object {H13300} <S70300><S30100>
+**
+** The sqlite3_finalize() function is called to delete a [prepared statement].
+** If the statement was executed successfully or not executed at all, then
+** SQLITE_OK is returned. If execution of the statement failed then an
+** [error code] or [extended error code] is returned.
+**
+** This routine can be called at any point during the execution of the
+** [prepared statement]. If the virtual machine has not
+** completed execution when this routine is called, that is like
+** encountering an error or an [sqlite3_interrupt | interrupt].
+** Incomplete updates may be rolled back and transactions canceled,
+** depending on the circumstances, and the
+** [error code] returned will be [SQLITE_ABORT].
+**
+** INVARIANTS:
+**
+** {H11302} The [sqlite3_finalize(S)] interface destroys the
+** [prepared statement] S and releases all
+** memory and file resources held by that object.
+**
+** {H11304} If the most recent call to [sqlite3_step(S)] for the
+** [prepared statement] S returned an error,
+** then [sqlite3_finalize(S)] returns that same error.
+*/
+int sqlite3_finalize(sqlite3_stmt *pStmt);
+
+/*
+** CAPI3REF: Reset A Prepared Statement Object {H13330} <S70300>
+**
+** The sqlite3_reset() function is called to reset a [prepared statement]
+** object back to its initial state, ready to be re-executed.
+** Any SQL statement variables that had values bound to them using
+** the [sqlite3_bind_blob | sqlite3_bind_*() API] retain their values.
+** Use [sqlite3_clear_bindings()] to reset the bindings.
+**
+** {H11332} The [sqlite3_reset(S)] interface resets the [prepared statement] S
+** back to the beginning of its program.
+**
+** {H11334} If the most recent call to [sqlite3_step(S)] for the
+** [prepared statement] S returned [SQLITE_ROW] or [SQLITE_DONE],
+** or if [sqlite3_step(S)] has never before been called on S,
+** then [sqlite3_reset(S)] returns [SQLITE_OK].
+**
+** {H11336} If the most recent call to [sqlite3_step(S)] for the
+** [prepared statement] S indicated an error, then
+** [sqlite3_reset(S)] returns an appropriate [error code].
+**
+** {H11338} The [sqlite3_reset(S)] interface does not change the values
+** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S.
+*/
+int sqlite3_reset(sqlite3_stmt *pStmt);
+
+/*
+** CAPI3REF: Create Or Redefine SQL Functions {H16100} <S20200>
+** KEYWORDS: {function creation routines}
+** KEYWORDS: {application-defined SQL function}
+** KEYWORDS: {application-defined SQL functions}
+**
+** These two functions (collectively known as "function creation routines")
+** are used to add SQL functions or aggregates or to redefine the behavior
+** of existing SQL functions or aggregates. The only difference between the
+** two is that the second parameter, the name of the (scalar) function or
+** aggregate, is encoded in UTF-8 for sqlite3_create_function() and UTF-16
+** for sqlite3_create_function16().
+**
+** The first parameter is the [database connection] to which the SQL
+** function is to be added. If a single program uses more than one database
+** connection internally, then SQL functions must be added individually to
+** each database connection.
+**
+** The second parameter is the name of the SQL function to be created or
+** redefined. The length of the name is limited to 255 bytes, exclusive of
+** the zero-terminator. Note that the name length limit is in bytes, not
+** characters. Any attempt to create a function with a longer name
+** will result in [SQLITE_ERROR] being returned.
+**
+** The third parameter is the number of arguments that the SQL function or
+** aggregate takes. If this parameter is negative, then the SQL function or
+** aggregate may take any number of arguments.
+**
+** The fourth parameter, eTextRep, specifies what
+** [SQLITE_UTF8 | text encoding] this SQL function prefers for
+** its parameters. Any SQL function implementation should be able to work
+** work with UTF-8, UTF-16le, or UTF-16be. But some implementations may be
+** more efficient with one encoding than another. It is allowed to
+** invoke sqlite3_create_function() or sqlite3_create_function16() multiple
+** times with the same function but with different values of eTextRep.
+** When multiple implementations of the same function are available, SQLite
+** will pick the one that involves the least amount of data conversion.
+** If there is only a single implementation which does not care what text
+** encoding is used, then the fourth argument should be [SQLITE_ANY].
+**
+** The fifth parameter is an arbitrary pointer. The implementation of the
+** function can gain access to this pointer using [sqlite3_user_data()].
+**
+** The seventh, eighth and ninth parameters, xFunc, xStep and xFinal, are
+** pointers to C-language functions that implement the SQL function or
+** aggregate. A scalar SQL function requires an implementation of the xFunc
+** callback only, NULL pointers should be passed as the xStep and xFinal
+** parameters. An aggregate SQL function requires an implementation of xStep
+** and xFinal and NULL should be passed for xFunc. To delete an existing
+** SQL function or aggregate, pass NULL for all three function callbacks.
+**
+** It is permitted to register multiple implementations of the same
+** functions with the same name but with either differing numbers of
+** arguments or differing preferred text encodings. SQLite will use
+** the implementation most closely matches the way in which the
+** SQL function is used.
+**
+** INVARIANTS:
+**
+** {H16103} The [sqlite3_create_function16()] interface behaves exactly
+** like [sqlite3_create_function()] in every way except that it
+** interprets the zFunctionName argument as zero-terminated UTF-16
+** native byte order instead of as zero-terminated UTF-8.
+**
+** {H16106} A successful invocation of
+** the [sqlite3_create_function(D,X,N,E,...)] interface registers
+** or replaces callback functions in the [database connection] D
+** used to implement the SQL function named X with N parameters
+** and having a preferred text encoding of E.
+**
+** {H16109} A successful call to [sqlite3_create_function(D,X,N,E,P,F,S,L)]
+** replaces the P, F, S, and L values from any prior calls with
+** the same D, X, N, and E values.
+**
+** {H16112} The [sqlite3_create_function(D,X,...)] interface fails with
+** a return code of [SQLITE_ERROR] if the SQL function name X is
+** longer than 255 bytes exclusive of the zero terminator.
+**
+** {H16118} Either F must be NULL and S and L are non-NULL or else F
+** is non-NULL and S and L are NULL, otherwise
+** [sqlite3_create_function(D,X,N,E,P,F,S,L)] returns [SQLITE_ERROR].
+**
+** {H16121} The [sqlite3_create_function(D,...)] interface fails with an
+** error code of [SQLITE_BUSY] if there exist [prepared statements]
+** associated with the [database connection] D.
+**
+** {H16124} The [sqlite3_create_function(D,X,N,...)] interface fails with an
+** error code of [SQLITE_ERROR] if parameter N (specifying the number
+** of arguments to the SQL function being registered) is less
+** than -1 or greater than 127.
+**
+** {H16127} When N is non-negative, the [sqlite3_create_function(D,X,N,...)]
+** interface causes callbacks to be invoked for the SQL function
+** named X when the number of arguments to the SQL function is
+** exactly N.
+**
+** {H16130} When N is -1, the [sqlite3_create_function(D,X,N,...)]
+** interface causes callbacks to be invoked for the SQL function
+** named X with any number of arguments.
+**
+** {H16133} When calls to [sqlite3_create_function(D,X,N,...)]
+** specify multiple implementations of the same function X
+** and when one implementation has N>=0 and the other has N=(-1)
+** the implementation with a non-zero N is preferred.
+**
+** {H16136} When calls to [sqlite3_create_function(D,X,N,E,...)]
+** specify multiple implementations of the same function X with
+** the same number of arguments N but with different
+** encodings E, then the implementation where E matches the
+** database encoding is preferred.
+**
+** {H16139} For an aggregate SQL function created using
+** [sqlite3_create_function(D,X,N,E,P,0,S,L)] the finalizer
+** function L will always be invoked exactly once if the
+** step function S is called one or more times.
+**
+** {H16142} When SQLite invokes either the xFunc or xStep function of
+** an application-defined SQL function or aggregate created
+** by [sqlite3_create_function()] or [sqlite3_create_function16()],
+** then the array of [sqlite3_value] objects passed as the
+** third parameter are always [protected sqlite3_value] objects.
+*/
+int sqlite3_create_function(
+ sqlite3 *db,
+ const char *zFunctionName,
+ int nArg,
+ int eTextRep,
+ void *pApp,
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**),
+ void (*xFinal)(sqlite3_context*)
+);
+int sqlite3_create_function16(
+ sqlite3 *db,
+ const void *zFunctionName,
+ int nArg,
+ int eTextRep,
+ void *pApp,
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**),
+ void (*xFinal)(sqlite3_context*)
+);
+
+/*
+** CAPI3REF: Text Encodings {H10267} <S50200> <H16100>
+**
+** These constant define integer codes that represent the various
+** text encodings supported by SQLite.
+*/
+#define SQLITE_UTF8 1
+#define SQLITE_UTF16LE 2
+#define SQLITE_UTF16BE 3
+#define SQLITE_UTF16 4 /* Use native byte order */
+#define SQLITE_ANY 5 /* sqlite3_create_function only */
+#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */
+
+/*
+** CAPI3REF: Deprecated Functions
+** DEPRECATED
+**
+** These functions are [deprecated]. In order to maintain
+** backwards compatibility with older code, these functions continue
+** to be supported. However, new applications should avoid
+** the use of these functions. To help encourage people to avoid
+** using these functions, we are not going to tell you want they do.
+*/
+int sqlite3_aggregate_count(sqlite3_context*);
+int sqlite3_expired(sqlite3_stmt*);
+int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
+int sqlite3_global_recover(void);
+void sqlite3_thread_cleanup(void);
+int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64);
+
+/*
+** CAPI3REF: Obtaining SQL Function Parameter Values {H15100} <S20200>
+**
+** The C-language implementation of SQL functions and aggregates uses
+** this set of interface routines to access the parameter values on
+** the function or aggregate.
+**
+** The xFunc (for scalar functions) or xStep (for aggregates) parameters
+** to [sqlite3_create_function()] and [sqlite3_create_function16()]
+** define callbacks that implement the SQL functions and aggregates.
+** The 4th parameter to these callbacks is an array of pointers to
+** [protected sqlite3_value] objects. There is one [sqlite3_value] object for
+** each parameter to the SQL function. These routines are used to
+** extract values from the [sqlite3_value] objects.
+**
+** These routines work only with [protected sqlite3_value] objects.
+** Any attempt to use these routines on an [unprotected sqlite3_value]
+** object results in undefined behavior.
+**
+** These routines work just like the corresponding [column access functions]
+** except that these routines take a single [protected sqlite3_value] object
+** pointer instead of a [sqlite3_stmt*] pointer and an integer column number.
+**
+** The sqlite3_value_text16() interface extracts a UTF-16 string
+** in the native byte-order of the host machine. The
+** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces
+** extract UTF-16 strings as big-endian and little-endian respectively.
+**
+** The sqlite3_value_numeric_type() interface attempts to apply
+** numeric affinity to the value. This means that an attempt is
+** made to convert the value to an integer or floating point. If
+** such a conversion is possible without loss of information (in other
+** words, if the value is a string that looks like a number)
+** then the conversion is performed. Otherwise no conversion occurs.
+** The [SQLITE_INTEGER | datatype] after conversion is returned.
+**
+** Please pay particular attention to the fact that the pointer returned
+** from [sqlite3_value_blob()], [sqlite3_value_text()], or
+** [sqlite3_value_text16()] can be invalidated by a subsequent call to
+** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()],
+** or [sqlite3_value_text16()].
+**
+** These routines must be called from the same thread as
+** the SQL function that supplied the [sqlite3_value*] parameters.
+**
+** INVARIANTS:
+**
+** {H15103} The [sqlite3_value_blob(V)] interface converts the
+** [protected sqlite3_value] object V into a BLOB and then
+** returns a pointer to the converted value.
+**
+** {H15106} The [sqlite3_value_bytes(V)] interface returns the
+** number of bytes in the BLOB or string (exclusive of the
+** zero terminator on the string) that was returned by the
+** most recent call to [sqlite3_value_blob(V)] or
+** [sqlite3_value_text(V)].
+**
+** {H15109} The [sqlite3_value_bytes16(V)] interface returns the
+** number of bytes in the string (exclusive of the
+** zero terminator on the string) that was returned by the
+** most recent call to [sqlite3_value_text16(V)],
+** [sqlite3_value_text16be(V)], or [sqlite3_value_text16le(V)].
+**
+** {H15112} The [sqlite3_value_double(V)] interface converts the
+** [protected sqlite3_value] object V into a floating point value and
+** returns a copy of that value.
+**
+** {H15115} The [sqlite3_value_int(V)] interface converts the
+** [protected sqlite3_value] object V into a 64-bit signed integer and
+** returns the lower 32 bits of that integer.
+**
+** {H15118} The [sqlite3_value_int64(V)] interface converts the
+** [protected sqlite3_value] object V into a 64-bit signed integer and
+** returns a copy of that integer.
+**
+** {H15121} The [sqlite3_value_text(V)] interface converts the
+** [protected sqlite3_value] object V into a zero-terminated UTF-8
+** string and returns a pointer to that string.
+**
+** {H15124} The [sqlite3_value_text16(V)] interface converts the
+** [protected sqlite3_value] object V into a zero-terminated 2-byte
+** aligned UTF-16 native byte order
+** string and returns a pointer to that string.
+**
+** {H15127} The [sqlite3_value_text16be(V)] interface converts the
+** [protected sqlite3_value] object V into a zero-terminated 2-byte
+** aligned UTF-16 big-endian
+** string and returns a pointer to that string.
+**
+** {H15130} The [sqlite3_value_text16le(V)] interface converts the
+** [protected sqlite3_value] object V into a zero-terminated 2-byte
+** aligned UTF-16 little-endian
+** string and returns a pointer to that string.
+**
+** {H15133} The [sqlite3_value_type(V)] interface returns
+** one of [SQLITE_NULL], [SQLITE_INTEGER], [SQLITE_FLOAT],
+** [SQLITE_TEXT], or [SQLITE_BLOB] as appropriate for
+** the [sqlite3_value] object V.
+**
+** {H15136} The [sqlite3_value_numeric_type(V)] interface converts
+** the [protected sqlite3_value] object V into either an integer or
+** a floating point value if it can do so without loss of
+** information, and returns one of [SQLITE_NULL],
+** [SQLITE_INTEGER], [SQLITE_FLOAT], [SQLITE_TEXT], or
+** [SQLITE_BLOB] as appropriate for the
+** [protected sqlite3_value] object V after the conversion attempt.
+*/
+const void *sqlite3_value_blob(sqlite3_value*);
+int sqlite3_value_bytes(sqlite3_value*);
+int sqlite3_value_bytes16(sqlite3_value*);
+double sqlite3_value_double(sqlite3_value*);
+int sqlite3_value_int(sqlite3_value*);
+sqlite3_int64 sqlite3_value_int64(sqlite3_value*);
+const unsigned char *sqlite3_value_text(sqlite3_value*);
+const void *sqlite3_value_text16(sqlite3_value*);
+const void *sqlite3_value_text16le(sqlite3_value*);
+const void *sqlite3_value_text16be(sqlite3_value*);
+int sqlite3_value_type(sqlite3_value*);
+int sqlite3_value_numeric_type(sqlite3_value*);
+
+/*
+** CAPI3REF: Obtain Aggregate Function Context {H16210} <S20200>
+**
+** The implementation of aggregate SQL functions use this routine to allocate
+** a structure for storing their state.
+**
+** The first time the sqlite3_aggregate_context() routine is called for a
+** particular aggregate, SQLite allocates nBytes of memory, zeroes out that
+** memory, and returns a pointer to it. On second and subsequent calls to
+** sqlite3_aggregate_context() for the same aggregate function index,
+** the same buffer is returned. The implementation of the aggregate can use
+** the returned buffer to accumulate data.
+**
+** SQLite automatically frees the allocated buffer when the aggregate
+** query concludes.
+**
+** The first parameter should be a copy of the
+** [sqlite3_context | SQL function context] that is the first parameter
+** to the callback routine that implements the aggregate function.
+**
+** This routine must be called from the same thread in which
+** the aggregate SQL function is running.
+**
+** INVARIANTS:
+**
+** {H16211} The first invocation of [sqlite3_aggregate_context(C,N)] for
+** a particular instance of an aggregate function (for a particular
+** context C) causes SQLite to allocate N bytes of memory,
+** zero that memory, and return a pointer to the allocated memory.
+**
+** {H16213} If a memory allocation error occurs during
+** [sqlite3_aggregate_context(C,N)] then the function returns 0.
+**
+** {H16215} Second and subsequent invocations of
+** [sqlite3_aggregate_context(C,N)] for the same context pointer C
+** ignore the N parameter and return a pointer to the same
+** block of memory returned by the first invocation.
+**
+** {H16217} The memory allocated by [sqlite3_aggregate_context(C,N)] is
+** automatically freed on the next call to [sqlite3_reset()]
+** or [sqlite3_finalize()] for the [prepared statement] containing
+** the aggregate function associated with context C.
+*/
+void *sqlite3_aggregate_context(sqlite3_context*, int nBytes);
+
+/*
+** CAPI3REF: User Data For Functions {H16240} <S20200>
+**
+** The sqlite3_user_data() interface returns a copy of
+** the pointer that was the pUserData parameter (the 5th parameter)
+** of the [sqlite3_create_function()]
+** and [sqlite3_create_function16()] routines that originally
+** registered the application defined function. {END}
+**
+** This routine must be called from the same thread in which
+** the application-defined function is running.
+**
+** INVARIANTS:
+**
+** {H16243} The [sqlite3_user_data(C)] interface returns a copy of the
+** P pointer from the [sqlite3_create_function(D,X,N,E,P,F,S,L)]
+** or [sqlite3_create_function16(D,X,N,E,P,F,S,L)] call that
+** registered the SQL function associated with [sqlite3_context] C.
+*/
+void *sqlite3_user_data(sqlite3_context*);
+
+/*
+** CAPI3REF: Database Connection For Functions {H16250} <S60600><S20200>
+**
+** The sqlite3_context_db_handle() interface returns a copy of
+** the pointer to the [database connection] (the 1st parameter)
+** of the [sqlite3_create_function()]
+** and [sqlite3_create_function16()] routines that originally
+** registered the application defined function.
+**
+** INVARIANTS:
+**
+** {H16253} The [sqlite3_context_db_handle(C)] interface returns a copy of the
+** D pointer from the [sqlite3_create_function(D,X,N,E,P,F,S,L)]
+** or [sqlite3_create_function16(D,X,N,E,P,F,S,L)] call that
+** registered the SQL function associated with [sqlite3_context] C.
+*/
+sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
+
+/*
+** CAPI3REF: Function Auxiliary Data {H16270} <S20200>
+**
+** The following two functions may be used by scalar SQL functions to
+** associate metadata with argument values. If the same value is passed to
+** multiple invocations of the same SQL function during query execution, under
+** some circumstances the associated metadata may be preserved. This may
+** be used, for example, to add a regular-expression matching scalar
+** function. The compiled version of the regular expression is stored as
+** metadata associated with the SQL value passed as the regular expression
+** pattern. The compiled regular expression can be reused on multiple
+** invocations of the same function so that the original pattern string
+** does not need to be recompiled on each invocation.
+**
+** The sqlite3_get_auxdata() interface returns a pointer to the metadata
+** associated by the sqlite3_set_auxdata() function with the Nth argument
+** value to the application-defined function. If no metadata has been ever
+** been set for the Nth argument of the function, or if the corresponding
+** function parameter has changed since the meta-data was set,
+** then sqlite3_get_auxdata() returns a NULL pointer.
+**
+** The sqlite3_set_auxdata() interface saves the metadata
+** pointed to by its 3rd parameter as the metadata for the N-th
+** argument of the application-defined function. Subsequent
+** calls to sqlite3_get_auxdata() might return this data, if it has
+** not been destroyed.
+** If it is not NULL, SQLite will invoke the destructor
+** function given by the 4th parameter to sqlite3_set_auxdata() on
+** the metadata when the corresponding function parameter changes
+** or when the SQL statement completes, whichever comes first.
+**
+** SQLite is free to call the destructor and drop metadata on any
+** parameter of any function at any time. The only guarantee is that
+** the destructor will be called before the metadata is dropped.
+**
+** In practice, metadata is preserved between function calls for
+** expressions that are constant at compile time. This includes literal
+** values and SQL variables.
+**
+** These routines must be called from the same thread in which
+** the SQL function is running.
+**
+** INVARIANTS:
+**
+** {H16272} The [sqlite3_get_auxdata(C,N)] interface returns a pointer
+** to metadata associated with the Nth parameter of the SQL function
+** whose context is C, or NULL if there is no metadata associated
+** with that parameter.
+**
+** {H16274} The [sqlite3_set_auxdata(C,N,P,D)] interface assigns a metadata
+** pointer P to the Nth parameter of the SQL function with context C.
+**
+** {H16276} SQLite will invoke the destructor D with a single argument
+** which is the metadata pointer P following a call to
+** [sqlite3_set_auxdata(C,N,P,D)] when SQLite ceases to hold
+** the metadata.
+**
+** {H16277} SQLite ceases to hold metadata for an SQL function parameter
+** when the value of that parameter changes.
+**
+** {H16278} When [sqlite3_set_auxdata(C,N,P,D)] is invoked, the destructor
+** is called for any prior metadata associated with the same function
+** context C and parameter N.
+**
+** {H16279} SQLite will call destructors for any metadata it is holding
+** in a particular [prepared statement] S when either
+** [sqlite3_reset(S)] or [sqlite3_finalize(S)] is called.
+*/
+void *sqlite3_get_auxdata(sqlite3_context*, int N);
+void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*));
+
+
+/*
+** CAPI3REF: Constants Defining Special Destructor Behavior {H10280} <S30100>
+**
+** These are special values for the destructor that is passed in as the
+** final argument to routines like [sqlite3_result_blob()]. If the destructor
+** argument is SQLITE_STATIC, it means that the content pointer is constant
+** and will never change. It does not need to be destroyed. The
+** SQLITE_TRANSIENT value means that the content will likely change in
+** the near future and that SQLite should make its own private copy of
+** the content before returning.
+**
+** The typedef is necessary to work around problems in certain
+** C++ compilers. See ticket #2191.
+*/
+typedef void (*sqlite3_destructor_type)(void*);
+#define SQLITE_STATIC ((sqlite3_destructor_type)0)
+#define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1)
+
+/*
+** CAPI3REF: Setting The Result Of An SQL Function {H16400} <S20200>
+**
+** These routines are used by the xFunc or xFinal callbacks that
+** implement SQL functions and aggregates. See
+** [sqlite3_create_function()] and [sqlite3_create_function16()]
+** for additional information.
+**
+** These functions work very much like the [parameter binding] family of
+** functions used to bind values to host parameters in prepared statements.
+** Refer to the [SQL parameter] documentation for additional information.
+**
+** The sqlite3_result_blob() interface sets the result from
+** an application-defined function to be the BLOB whose content is pointed
+** to by the second parameter and which is N bytes long where N is the
+** third parameter.
+**
+** The sqlite3_result_zeroblob() interfaces set the result of
+** the application-defined function to be a BLOB containing all zero
+** bytes and N bytes in size, where N is the value of the 2nd parameter.
+**
+** The sqlite3_result_double() interface sets the result from
+** an application-defined function to be a floating point value specified
+** by its 2nd argument.
+**
+** The sqlite3_result_error() and sqlite3_result_error16() functions
+** cause the implemented SQL function to throw an exception.
+** SQLite uses the string pointed to by the
+** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16()
+** as the text of an error message. SQLite interprets the error
+** message string from sqlite3_result_error() as UTF-8. SQLite
+** interprets the string from sqlite3_result_error16() as UTF-16 in native
+** byte order. If the third parameter to sqlite3_result_error()
+** or sqlite3_result_error16() is negative then SQLite takes as the error
+** message all text up through the first zero character.
+** If the third parameter to sqlite3_result_error() or
+** sqlite3_result_error16() is non-negative then SQLite takes that many
+** bytes (not characters) from the 2nd parameter as the error message.
+** The sqlite3_result_error() and sqlite3_result_error16()
+** routines make a private copy of the error message text before
+** they return. Hence, the calling function can deallocate or
+** modify the text after they return without harm.
+** The sqlite3_result_error_code() function changes the error code
+** returned by SQLite as a result of an error in a function. By default,
+** the error code is SQLITE_ERROR. A subsequent call to sqlite3_result_error()
+** or sqlite3_result_error16() resets the error code to SQLITE_ERROR.
+**
+** The sqlite3_result_toobig() interface causes SQLite to throw an error
+** indicating that a string or BLOB is to long to represent.
+**
+** The sqlite3_result_nomem() interface causes SQLite to throw an error
+** indicating that a memory allocation failed.
+**
+** The sqlite3_result_int() interface sets the return value
+** of the application-defined function to be the 32-bit signed integer
+** value given in the 2nd argument.
+** The sqlite3_result_int64() interface sets the return value
+** of the application-defined function to be the 64-bit signed integer
+** value given in the 2nd argument.
+**
+** The sqlite3_result_null() interface sets the return value
+** of the application-defined function to be NULL.
+**
+** The sqlite3_result_text(), sqlite3_result_text16(),
+** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces
+** set the return value of the application-defined function to be
+** a text string which is represented as UTF-8, UTF-16 native byte order,
+** UTF-16 little endian, or UTF-16 big endian, respectively.
+** SQLite takes the text result from the application from
+** the 2nd parameter of the sqlite3_result_text* interfaces.
+** If the 3rd parameter to the sqlite3_result_text* interfaces
+** is negative, then SQLite takes result text from the 2nd parameter
+** through the first zero character.
+** If the 3rd parameter to the sqlite3_result_text* interfaces
+** is non-negative, then as many bytes (not characters) of the text
+** pointed to by the 2nd parameter are taken as the application-defined
+** function result.
+** If the 4th parameter to the sqlite3_result_text* interfaces
+** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that
+** function as the destructor on the text or BLOB result when it has
+** finished using that result.
+** If the 4th parameter to the sqlite3_result_text* interfaces or
+** sqlite3_result_blob is the special constant SQLITE_STATIC, then SQLite
+** assumes that the text or BLOB result is in constant space and does not
+** copy the it or call a destructor when it has finished using that result.
+** If the 4th parameter to the sqlite3_result_text* interfaces
+** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT
+** then SQLite makes a copy of the result into space obtained from
+** from [sqlite3_malloc()] before it returns.
+**
+** The sqlite3_result_value() interface sets the result of
+** the application-defined function to be a copy the
+** [unprotected sqlite3_value] object specified by the 2nd parameter. The
+** sqlite3_result_value() interface makes a copy of the [sqlite3_value]
+** so that the [sqlite3_value] specified in the parameter may change or
+** be deallocated after sqlite3_result_value() returns without harm.
+** A [protected sqlite3_value] object may always be used where an
+** [unprotected sqlite3_value] object is required, so either
+** kind of [sqlite3_value] object can be used with this interface.
+**
+** If these routines are called from within the different thread
+** than the one containing the application-defined function that received
+** the [sqlite3_context] pointer, the results are undefined.
+**
+** INVARIANTS:
+**
+** {H16403} The default return value from any SQL function is NULL.
+**
+** {H16406} The [sqlite3_result_blob(C,V,N,D)] interface changes the
+** return value of function C to be a BLOB that is N bytes
+** in length and with content pointed to by V.
+**
+** {H16409} The [sqlite3_result_double(C,V)] interface changes the
+** return value of function C to be the floating point value V.
+**
+** {H16412} The [sqlite3_result_error(C,V,N)] interface changes the return
+** value of function C to be an exception with error code
+** [SQLITE_ERROR] and a UTF-8 error message copied from V up to the
+** first zero byte or until N bytes are read if N is positive.
+**
+** {H16415} The [sqlite3_result_error16(C,V,N)] interface changes the return
+** value of function C to be an exception with error code
+** [SQLITE_ERROR] and a UTF-16 native byte order error message
+** copied from V up to the first zero terminator or until N bytes
+** are read if N is positive.
+**
+** {H16418} The [sqlite3_result_error_toobig(C)] interface changes the return
+** value of the function C to be an exception with error code
+** [SQLITE_TOOBIG] and an appropriate error message.
+**
+** {H16421} The [sqlite3_result_error_nomem(C)] interface changes the return
+** value of the function C to be an exception with error code
+** [SQLITE_NOMEM] and an appropriate error message.
+**
+** {H16424} The [sqlite3_result_error_code(C,E)] interface changes the return
+** value of the function C to be an exception with error code E.
+** The error message text is unchanged.
+**
+** {H16427} The [sqlite3_result_int(C,V)] interface changes the
+** return value of function C to be the 32-bit integer value V.
+**
+** {H16430} The [sqlite3_result_int64(C,V)] interface changes the
+** return value of function C to be the 64-bit integer value V.
+**
+** {H16433} The [sqlite3_result_null(C)] interface changes the
+** return value of function C to be NULL.
+**
+** {H16436} The [sqlite3_result_text(C,V,N,D)] interface changes the
+** return value of function C to be the UTF-8 string
+** V up to the first zero if N is negative
+** or the first N bytes of V if N is non-negative.
+**
+** {H16439} The [sqlite3_result_text16(C,V,N,D)] interface changes the
+** return value of function C to be the UTF-16 native byte order
+** string V up to the first zero if N is negative
+** or the first N bytes of V if N is non-negative.
+**
+** {H16442} The [sqlite3_result_text16be(C,V,N,D)] interface changes the
+** return value of function C to be the UTF-16 big-endian
+** string V up to the first zero if N is negative
+** or the first N bytes or V if N is non-negative.
+**
+** {H16445} The [sqlite3_result_text16le(C,V,N,D)] interface changes the
+** return value of function C to be the UTF-16 little-endian
+** string V up to the first zero if N is negative
+** or the first N bytes of V if N is non-negative.
+**
+** {H16448} The [sqlite3_result_value(C,V)] interface changes the
+** return value of function C to be the [unprotected sqlite3_value]
+** object V.
+**
+** {H16451} The [sqlite3_result_zeroblob(C,N)] interface changes the
+** return value of function C to be an N-byte BLOB of all zeros.
+**
+** {H16454} The [sqlite3_result_error()] and [sqlite3_result_error16()]
+** interfaces make a copy of their error message strings before
+** returning.
+**
+** {H16457} If the D destructor parameter to [sqlite3_result_blob(C,V,N,D)],
+** [sqlite3_result_text(C,V,N,D)], [sqlite3_result_text16(C,V,N,D)],
+** [sqlite3_result_text16be(C,V,N,D)], or
+** [sqlite3_result_text16le(C,V,N,D)] is the constant [SQLITE_STATIC]
+** then no destructor is ever called on the pointer V and SQLite
+** assumes that V is immutable.
+**
+** {H16460} If the D destructor parameter to [sqlite3_result_blob(C,V,N,D)],
+** [sqlite3_result_text(C,V,N,D)], [sqlite3_result_text16(C,V,N,D)],
+** [sqlite3_result_text16be(C,V,N,D)], or
+** [sqlite3_result_text16le(C,V,N,D)] is the constant
+** [SQLITE_TRANSIENT] then the interfaces makes a copy of the
+** content of V and retains the copy.
+**
+** {H16463} If the D destructor parameter to [sqlite3_result_blob(C,V,N,D)],
+** [sqlite3_result_text(C,V,N,D)], [sqlite3_result_text16(C,V,N,D)],
+** [sqlite3_result_text16be(C,V,N,D)], or
+** [sqlite3_result_text16le(C,V,N,D)] is some value other than
+** the constants [SQLITE_STATIC] and [SQLITE_TRANSIENT] then
+** SQLite will invoke the destructor D with V as its only argument
+** when it has finished with the V value.
+*/
+void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
+void sqlite3_result_double(sqlite3_context*, double);
+void sqlite3_result_error(sqlite3_context*, const char*, int);
+void sqlite3_result_error16(sqlite3_context*, const void*, int);
+void sqlite3_result_error_toobig(sqlite3_context*);
+void sqlite3_result_error_nomem(sqlite3_context*);
+void sqlite3_result_error_code(sqlite3_context*, int);
+void sqlite3_result_int(sqlite3_context*, int);
+void sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
+void sqlite3_result_null(sqlite3_context*);
+void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
+void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
+void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
+void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
+void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
+void sqlite3_result_zeroblob(sqlite3_context*, int n);
+
+/*
+** CAPI3REF: Define New Collating Sequences {H16600} <S20300>
+**
+** These functions are used to add new collation sequences to the
+** [database connection] specified as the first argument.
+**
+** The name of the new collation sequence is specified as a UTF-8 string
+** for sqlite3_create_collation() and sqlite3_create_collation_v2()
+** and a UTF-16 string for sqlite3_create_collation16(). In all cases
+** the name is passed as the second function argument.
+**
+** The third argument may be one of the constants [SQLITE_UTF8],
+** [SQLITE_UTF16LE] or [SQLITE_UTF16BE], indicating that the user-supplied
+** routine expects to be passed pointers to strings encoded using UTF-8,
+** UTF-16 little-endian, or UTF-16 big-endian, respectively. The
+** third argument might also be [SQLITE_UTF16_ALIGNED] to indicate that
+** the routine expects pointers to 16-bit word aligned strings
+** of UTF-16 in the native byte order of the host computer.
+**
+** A pointer to the user supplied routine must be passed as the fifth
+** argument. If it is NULL, this is the same as deleting the collation
+** sequence (so that SQLite cannot call it anymore).
+** Each time the application supplied function is invoked, it is passed
+** as its first parameter a copy of the void* passed as the fourth argument
+** to sqlite3_create_collation() or sqlite3_create_collation16().
+**
+** The remaining arguments to the application-supplied routine are two strings,
+** each represented by a (length, data) pair and encoded in the encoding
+** that was passed as the third argument when the collation sequence was
+** registered. {END} The application defined collation routine should
+** return negative, zero or positive if the first string is less than,
+** equal to, or greater than the second string. i.e. (STRING1 - STRING2).
+**
+** The sqlite3_create_collation_v2() works like sqlite3_create_collation()
+** except that it takes an extra argument which is a destructor for
+** the collation. The destructor is called when the collation is
+** destroyed and is passed a copy of the fourth parameter void* pointer
+** of the sqlite3_create_collation_v2().
+** Collations are destroyed when they are overridden by later calls to the
+** collation creation functions or when the [database connection] is closed
+** using [sqlite3_close()].
+**
+** INVARIANTS:
+**
+** {H16603} A successful call to the
+** [sqlite3_create_collation_v2(B,X,E,P,F,D)] interface
+** registers function F as the comparison function used to
+** implement collation X on the [database connection] B for
+** databases having encoding E.
+**
+** {H16604} SQLite understands the X parameter to
+** [sqlite3_create_collation_v2(B,X,E,P,F,D)] as a zero-terminated
+** UTF-8 string in which case is ignored for ASCII characters and
+** is significant for non-ASCII characters.
+**
+** {H16606} Successive calls to [sqlite3_create_collation_v2(B,X,E,P,F,D)]
+** with the same values for B, X, and E, override prior values
+** of P, F, and D.
+**
+** {H16609} If the destructor D in [sqlite3_create_collation_v2(B,X,E,P,F,D)]
+** is not NULL then it is called with argument P when the
+** collating function is dropped by SQLite.
+**
+** {H16612} A collating function is dropped when it is overloaded.
+**
+** {H16615} A collating function is dropped when the database connection
+** is closed using [sqlite3_close()].
+**
+** {H16618} The pointer P in [sqlite3_create_collation_v2(B,X,E,P,F,D)]
+** is passed through as the first parameter to the comparison
+** function F for all subsequent invocations of F.
+**
+** {H16621} A call to [sqlite3_create_collation(B,X,E,P,F)] is exactly
+** the same as a call to [sqlite3_create_collation_v2()] with
+** the same parameters and a NULL destructor.
+**
+** {H16624} Following a [sqlite3_create_collation_v2(B,X,E,P,F,D)],
+** SQLite uses the comparison function F for all text comparison
+** operations on the [database connection] B on text values that
+** use the collating sequence named X.
+**
+** {H16627} The [sqlite3_create_collation16(B,X,E,P,F)] works the same
+** as [sqlite3_create_collation(B,X,E,P,F)] except that the
+** collation name X is understood as UTF-16 in native byte order
+** instead of UTF-8.
+**
+** {H16630} When multiple comparison functions are available for the same
+** collating sequence, SQLite chooses the one whose text encoding
+** requires the least amount of conversion from the default
+** text encoding of the database.
+*/
+int sqlite3_create_collation(
+ sqlite3*,
+ const char *zName,
+ int eTextRep,
+ void*,
+ int(*xCompare)(void*,int,const void*,int,const void*)
+);
+int sqlite3_create_collation_v2(
+ sqlite3*,
+ const char *zName,
+ int eTextRep,
+ void*,
+ int(*xCompare)(void*,int,const void*,int,const void*),
+ void(*xDestroy)(void*)
+);
+int sqlite3_create_collation16(
+ sqlite3*,
+ const void *zName,
+ int eTextRep,
+ void*,
+ int(*xCompare)(void*,int,const void*,int,const void*)
+);
+
+/*
+** CAPI3REF: Collation Needed Callbacks {H16700} <S20300>
+**
+** To avoid having to register all collation sequences before a database
+** can be used, a single callback function may be registered with the
+** [database connection] to be called whenever an undefined collation
+** sequence is required.
+**
+** If the function is registered using the sqlite3_collation_needed() API,
+** then it is passed the names of undefined collation sequences as strings
+** encoded in UTF-8. {H16703} If sqlite3_collation_needed16() is used,
+** the names are passed as UTF-16 in machine native byte order.
+** A call to either function replaces any existing callback.
+**
+** When the callback is invoked, the first argument passed is a copy
+** of the second argument to sqlite3_collation_needed() or
+** sqlite3_collation_needed16(). The second argument is the database
+** connection. The third argument is one of [SQLITE_UTF8], [SQLITE_UTF16BE],
+** or [SQLITE_UTF16LE], indicating the most desirable form of the collation
+** sequence function required. The fourth parameter is the name of the
+** required collation sequence.
+**
+** The callback function should register the desired collation using
+** [sqlite3_create_collation()], [sqlite3_create_collation16()], or
+** [sqlite3_create_collation_v2()].
+**
+** INVARIANTS:
+**
+** {H16702} A successful call to [sqlite3_collation_needed(D,P,F)]
+** or [sqlite3_collation_needed16(D,P,F)] causes
+** the [database connection] D to invoke callback F with first
+** parameter P whenever it needs a comparison function for a
+** collating sequence that it does not know about.
+**
+** {H16704} Each successful call to [sqlite3_collation_needed()] or
+** [sqlite3_collation_needed16()] overrides the callback registered
+** on the same [database connection] by prior calls to either
+** interface.
+**
+** {H16706} The name of the requested collating function passed in the
+** 4th parameter to the callback is in UTF-8 if the callback
+** was registered using [sqlite3_collation_needed()] and
+** is in UTF-16 native byte order if the callback was
+** registered using [sqlite3_collation_needed16()].
+*/
+int sqlite3_collation_needed(
+ sqlite3*,
+ void*,
+ void(*)(void*,sqlite3*,int eTextRep,const char*)
+);
+int sqlite3_collation_needed16(
+ sqlite3*,
+ void*,
+ void(*)(void*,sqlite3*,int eTextRep,const void*)
+);
+
+/*
+** Specify the key for an encrypted database. This routine should be
+** called right after sqlite3_open().
+**
+** The code to implement this API is not available in the public release
+** of SQLite.
+*/
+int sqlite3_key(
+ sqlite3 *db, /* Database to be rekeyed */
+ const void *pKey, int nKey /* The key */
+);
+
+/*
+** Change the key on an open database. If the current database is not
+** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the
+** database is decrypted.
+**
+** The code to implement this API is not available in the public release
+** of SQLite.
+*/
+int sqlite3_rekey(
+ sqlite3 *db, /* Database to be rekeyed */
+ const void *pKey, int nKey /* The new key */
+);
+
+/*
+** CAPI3REF: Suspend Execution For A Short Time {H10530} <S40410>
+**
+** The sqlite3_sleep() function causes the current thread to suspend execution
+** for at least a number of milliseconds specified in its parameter.
+**
+** If the operating system does not support sleep requests with
+** millisecond time resolution, then the time will be rounded up to
+** the nearest second. The number of milliseconds of sleep actually
+** requested from the operating system is returned.
+**
+** SQLite implements this interface by calling the xSleep()
+** method of the default [sqlite3_vfs] object.
+**
+** INVARIANTS:
+**
+** {H10533} The [sqlite3_sleep(M)] interface invokes the xSleep
+** method of the default [sqlite3_vfs|VFS] in order to
+** suspend execution of the current thread for at least
+** M milliseconds.
+**
+** {H10536} The [sqlite3_sleep(M)] interface returns the number of
+** milliseconds of sleep actually requested of the operating
+** system, which might be larger than the parameter M.
+*/
+int sqlite3_sleep(int);
+
+/*
+** CAPI3REF: Name Of The Folder Holding Temporary Files {H10310} <S20000>
+**
+** If this global variable is made to point to a string which is
+** the name of a folder (a.k.a. directory), then all temporary files
+** created by SQLite will be placed in that directory. If this variable
+** is a NULL pointer, then SQLite performs a search for an appropriate
+** temporary file directory.
+**
+** It is not safe to modify this variable once a [database connection]
+** has been opened. It is intended that this variable be set once
+** as part of process initialization and before any SQLite interface
+** routines have been call and remain unchanged thereafter.
+*/
+SQLITE_EXTERN char *sqlite3_temp_directory;
+
+/*
+** CAPI3REF: Test For Auto-Commit Mode {H12930} <S60200>
+** KEYWORDS: {autocommit mode}
+**
+** The sqlite3_get_autocommit() interface returns non-zero or
+** zero if the given database connection is or is not in autocommit mode,
+** respectively. Autocommit mode is on by default.
+** Autocommit mode is disabled by a [BEGIN] statement.
+** Autocommit mode is re-enabled by a [COMMIT] or [ROLLBACK].
+**
+** If certain kinds of errors occur on a statement within a multi-statement
+** transaction (errors including [SQLITE_FULL], [SQLITE_IOERR],
+** [SQLITE_NOMEM], [SQLITE_BUSY], and [SQLITE_INTERRUPT]) then the
+** transaction might be rolled back automatically. The only way to
+** find out whether SQLite automatically rolled back the transaction after
+** an error is to use this function.
+**
+** INVARIANTS:
+**
+** {H12931} The [sqlite3_get_autocommit(D)] interface returns non-zero or
+** zero if the [database connection] D is or is not in autocommit
+** mode, respectively.
+**
+** {H12932} Autocommit mode is on by default.
+**
+** {H12933} Autocommit mode is disabled by a successful [BEGIN] statement.
+**
+** {H12934} Autocommit mode is enabled by a successful [COMMIT] or [ROLLBACK]
+** statement.
+**
+** ASSUMPTIONS:
+**
+** {A12936} If another thread changes the autocommit status of the database
+** connection while this routine is running, then the return value
+** is undefined.
+*/
+int sqlite3_get_autocommit(sqlite3*);
+
+/*
+** CAPI3REF: Find The Database Handle Of A Prepared Statement {H13120} <S60600>
+**
+** The sqlite3_db_handle interface returns the [database connection] handle
+** to which a [prepared statement] belongs. The database handle returned by
+** sqlite3_db_handle is the same database handle that was the first argument
+** to the [sqlite3_prepare_v2()] call (or its variants) that was used to
+** create the statement in the first place.
+**
+** INVARIANTS:
+**
+** {H13123} The [sqlite3_db_handle(S)] interface returns a pointer
+** to the [database connection] associated with the
+** [prepared statement] S.
+*/
+sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
+
+/*
+** CAPI3REF: Find the next prepared statement {H13140} <S60600>
+**
+** This interface returns a pointer to the next [prepared statement] after
+** pStmt associated with the [database connection] pDb. If pStmt is NULL
+** then this interface returns a pointer to the first prepared statement
+** associated with the database connection pDb. If no prepared statement
+** satisfies the conditions of this routine, it returns NULL.
+**
+** INVARIANTS:
+**
+** {H13143} If D is a [database connection] that holds one or more
+** unfinalized [prepared statements] and S is a NULL pointer,
+** then [sqlite3_next_stmt(D, S)] routine shall return a pointer
+** to one of the prepared statements associated with D.
+**
+** {H13146} If D is a [database connection] that holds no unfinalized
+** [prepared statements] and S is a NULL pointer, then
+** [sqlite3_next_stmt(D, S)] routine shall return a NULL pointer.
+**
+** {H13149} If S is a [prepared statement] in the [database connection] D
+** and S is not the last prepared statement in D, then
+** [sqlite3_next_stmt(D, S)] routine shall return a pointer
+** to the next prepared statement in D after S.
+**
+** {H13152} If S is the last [prepared statement] in the
+** [database connection] D then the [sqlite3_next_stmt(D, S)]
+** routine shall return a NULL pointer.
+**
+** ASSUMPTIONS:
+**
+** {A13154} The [database connection] pointer D in a call to
+** [sqlite3_next_stmt(D,S)] must refer to an open database
+** connection and in particular must not be a NULL pointer.
+*/
+sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);
+
+/*
+** CAPI3REF: Commit And Rollback Notification Callbacks {H12950} <S60400>
+**
+** The sqlite3_commit_hook() interface registers a callback
+** function to be invoked whenever a transaction is committed.
+** Any callback set by a previous call to sqlite3_commit_hook()
+** for the same database connection is overridden.
+** The sqlite3_rollback_hook() interface registers a callback
+** function to be invoked whenever a transaction is committed.
+** Any callback set by a previous call to sqlite3_commit_hook()
+** for the same database connection is overridden.
+** The pArg argument is passed through to the callback.
+** If the callback on a commit hook function returns non-zero,
+** then the commit is converted into a rollback.
+**
+** If another function was previously registered, its
+** pArg value is returned. Otherwise NULL is returned.
+**
+** Registering a NULL function disables the callback.
+**
+** 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 rollback callback is not invoked if a transaction is
+** automatically rolled back because the database connection is closed.
+** The rollback callback is not invoked if a transaction is
+** rolled back because a commit callback returned non-zero.
+** <todo> Check on this </todo>
+**
+** INVARIANTS:
+**
+** {H12951} The [sqlite3_commit_hook(D,F,P)] interface registers the
+** callback function F to be invoked with argument P whenever
+** a transaction commits on the [database connection] D.
+**
+** {H12952} The [sqlite3_commit_hook(D,F,P)] interface returns the P argument
+** from the previous call with the same [database connection] D,
+** or NULL on the first call for a particular database connection D.
+**
+** {H12953} Each call to [sqlite3_commit_hook()] overwrites the callback
+** registered by prior calls.
+**
+** {H12954} If the F argument to [sqlite3_commit_hook(D,F,P)] is NULL
+** then the commit hook callback is canceled and no callback
+** is invoked when a transaction commits.
+**
+** {H12955} If the commit callback returns non-zero then the commit is
+** converted into a rollback.
+**
+** {H12961} The [sqlite3_rollback_hook(D,F,P)] interface registers the
+** callback function F to be invoked with argument P whenever
+** a transaction rolls back on the [database connection] D.
+**
+** {H12962} The [sqlite3_rollback_hook(D,F,P)] interface returns the P
+** argument from the previous call with the same
+** [database connection] D, or NULL on the first call
+** for a particular database connection D.
+**
+** {H12963} Each call to [sqlite3_rollback_hook()] overwrites the callback
+** registered by prior calls.
+**
+** {H12964} If the F argument to [sqlite3_rollback_hook(D,F,P)] is NULL
+** then the rollback hook callback is canceled and no callback
+** is invoked when a transaction rolls back.
+*/
+void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*);
+void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
+
+/*
+** CAPI3REF: Data Change Notification Callbacks {H12970} <S60400>
+**
+** The sqlite3_update_hook() interface registers 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.
+**
+** INVARIANTS:
+**
+** {H12971} The [sqlite3_update_hook(D,F,P)] interface causes the callback
+** function F to be invoked with first parameter P whenever
+** a table row is modified, inserted, or deleted on
+** the [database connection] D.
+**
+** {H12973} The [sqlite3_update_hook(D,F,P)] interface returns the value
+** of P for the previous call on the same [database connection] D,
+** or NULL for the first call.
+**
+** {H12975} If the update hook callback F in [sqlite3_update_hook(D,F,P)]
+** is NULL then the no update callbacks are made.
+**
+** {H12977} Each call to [sqlite3_update_hook(D,F,P)] overrides prior calls
+** to the same interface on the same [database connection] D.
+**
+** {H12979} The update hook callback is not invoked when internal system
+** tables such as sqlite_master and sqlite_sequence are modified.
+**
+** {H12981} The second parameter to the update callback
+** is one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE],
+** depending on the operation that caused the callback to be invoked.
+**
+** {H12983} The third and fourth arguments to the callback contain pointers
+** to zero-terminated UTF-8 strings which are the names of the
+** database and table that is being updated.
+
+** {H12985} The final callback parameter is the rowid of the row after
+** the change occurs.
+*/
+void *sqlite3_update_hook(
+ sqlite3*,
+ void(*)(void *,int ,char const *,char const *,sqlite3_int64),
+ void*
+);
+
+/*
+** CAPI3REF: Enable Or Disable Shared Pager Cache {H10330} <S30900>
+** KEYWORDS: {shared cache} {shared cache mode}
+**
+** This routine enables or disables the sharing of the database cache
+** and schema data structures between [database connection | connections]
+** to the same database. Sharing is enabled if the argument is true
+** and disabled if the argument is false.
+**
+** Cache sharing is enabled and disabled for an entire process. {END}
+** This is a change as of SQLite version 3.5.0. In prior versions of SQLite,
+** sharing was enabled or disabled for each thread separately.
+**
+** The cache sharing mode set by this interface effects all subsequent
+** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()].
+** Existing database connections continue use the sharing mode
+** that was in effect at the time they were opened.
+**
+** Virtual tables cannot be used with a shared cache. When shared
+** cache is enabled, the [sqlite3_create_module()] API used to register
+** virtual tables will always return an error.
+**
+** This routine returns [SQLITE_OK] if shared cache was enabled or disabled
+** successfully. An [error code] is returned otherwise.
+**
+** Shared cache is disabled by default. But this might change in
+** future releases of SQLite. Applications that care about shared
+** cache setting should set it explicitly.
+**
+** INVARIANTS:
+**
+** {H10331} A successful invocation of [sqlite3_enable_shared_cache(B)]
+** will enable or disable shared cache mode for any subsequently
+** created [database connection] in the same process.
+**
+** {H10336} When shared cache is enabled, the [sqlite3_create_module()]
+** interface will always return an error.
+**
+** {H10337} The [sqlite3_enable_shared_cache(B)] interface returns
+** [SQLITE_OK] if shared cache was enabled or disabled successfully.
+**
+** {H10339} Shared cache is disabled by default.
+*/
+int sqlite3_enable_shared_cache(int);
+
+/*
+** CAPI3REF: Attempt To Free Heap Memory {H17340} <S30220>
+**
+** The sqlite3_release_memory() interface attempts to free N bytes
+** of heap memory by deallocating non-essential memory allocations
+** held by the database library. {END} Memory used to cache database
+** pages to improve performance is an example of non-essential memory.
+** sqlite3_release_memory() returns the number of bytes actually freed,
+** which might be more or less than the amount requested.
+**
+** INVARIANTS:
+**
+** {H17341} The [sqlite3_release_memory(N)] interface attempts to
+** free N bytes of heap memory by deallocating non-essential
+** memory allocations held by the database library.
+**
+** {H16342} The [sqlite3_release_memory(N)] returns the number
+** of bytes actually freed, which might be more or less
+** than the amount requested.
+*/
+int sqlite3_release_memory(int);
+
+/*
+** CAPI3REF: Impose A Limit On Heap Size {H17350} <S30220>
+**
+** The sqlite3_soft_heap_limit() interface places a "soft" limit
+** on the amount of heap memory that may be allocated by SQLite.
+** If an internal allocation is requested that would exceed the
+** soft heap limit, [sqlite3_release_memory()] is invoked one or
+** more times to free up some space before the allocation is performed.
+**
+** 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.
+**
+** A negative or zero value for N means that there is no soft heap limit and
+** [sqlite3_release_memory()] will only be called when memory is exhausted.
+** The default value for the soft heap limit is zero.
+**
+** SQLite makes a best effort to honor the soft heap limit.
+** But if the soft heap limit cannot be honored, execution will
+** continue without error or notification. This is why the limit is
+** called a "soft" limit. It is advisory only.
+**
+** Prior to SQLite version 3.5.0, this routine only constrained the memory
+** allocated by a single thread - the same thread in which this routine
+** runs. Beginning with SQLite version 3.5.0, the soft heap limit is
+** applied to all threads. The value specified for the soft heap limit
+** is an upper bound on the total memory allocation for all threads. In
+** version 3.5.0 there is no mechanism for limiting the heap usage for
+** individual threads.
+**
+** INVARIANTS:
+**
+** {H16351} The [sqlite3_soft_heap_limit(N)] interface places a soft limit
+** of N bytes on the amount of heap memory that may be allocated
+** using [sqlite3_malloc()] or [sqlite3_realloc()] at any point
+** in time.
+**
+** {H16352} If a call to [sqlite3_malloc()] or [sqlite3_realloc()] would
+** cause the total amount of allocated memory to exceed the
+** soft heap limit, then [sqlite3_release_memory()] is invoked
+** in an attempt to reduce the memory usage prior to proceeding
+** with the memory allocation attempt.
+**
+** {H16353} Calls to [sqlite3_malloc()] or [sqlite3_realloc()] that trigger
+** attempts to reduce memory usage through the soft heap limit
+** mechanism continue even if the attempt to reduce memory
+** usage is unsuccessful.
+**
+** {H16354} A negative or zero value for N in a call to
+** [sqlite3_soft_heap_limit(N)] means that there is no soft
+** heap limit and [sqlite3_release_memory()] will only be
+** called when memory is completely exhausted.
+**
+** {H16355} The default value for the soft heap limit is zero.
+**
+** {H16358} Each call to [sqlite3_soft_heap_limit(N)] overrides the
+** values set by all prior calls.
+*/
+void sqlite3_soft_heap_limit(int);
+
+/*
+** CAPI3REF: Extract Metadata About A Column Of A Table {H12850} <S60300>
+**
+** This routine returns metadata about a specific column of a specific
+** database table accessible using the [database connection] handle
+** passed as the first function argument.
+**
+** The column is identified by the second, third and fourth parameters to
+** this function. The second parameter is either the name of the database
+** (i.e. "main", "temp" or an attached database) containing the specified
+** table or NULL. If it is NULL, then all attached databases are searched
+** for the table using the same algorithm used by the database engine to
+** resolve unqualified table references.
+**
+** The third and fourth parameters to this function are the table and column
+** name of the desired column, respectively. Neither of these parameters
+** may be NULL.
+**
+** Metadata is returned by writing to the memory locations passed as the 5th
+** and subsequent parameters to this function. Any of these arguments may be
+** NULL, in which case the corresponding element of metadata is omitted.
+**
+** <blockquote>
+** <table border="1">
+** <tr><th> Parameter <th> Output<br>Type <th> Description
+**
+** <tr><td> 5th <td> const char* <td> Data type
+** <tr><td> 6th <td> const char* <td> Name of default collation sequence
+** <tr><td> 7th <td> int <td> True if column has a NOT NULL constraint
+** <tr><td> 8th <td> int <td> True if column is part of the PRIMARY KEY
+** <tr><td> 9th <td> int <td> True if column is AUTOINCREMENT
+** </table>
+** </blockquote>
+**
+** The memory pointed to by the character pointers returned for the
+** declaration type and collation sequence is valid only until the next
+** call to any SQLite API function.
+**
+** If the specified table is actually a view, an [error code] is returned.
+**
+** If the specified column is "rowid", "oid" or "_rowid_" and an
+** INTEGER PRIMARY KEY column has been explicitly declared, then the output
+** parameters are set for the explicitly declared column. If there is no
+** explicitly declared INTEGER PRIMARY KEY column, then the output
+** parameters are set as follows:
+**
+** <pre>
+** data type: "INTEGER"
+** collation sequence: "BINARY"
+** not null: 0
+** primary key: 1
+** auto increment: 0
+** </pre>
+**
+** This function may load one or more schemas from database files. If an
+** error occurs during this process, or if the requested table or column
+** cannot be found, an [error code] is returned and an error message left
+** in the [database connection] (to be retrieved using sqlite3_errmsg()).
+**
+** This API is only available if the library was compiled with the
+** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined.
+*/
+int sqlite3_table_column_metadata(
+ sqlite3 *db, /* Connection handle */
+ const char *zDbName, /* Database name or NULL */
+ const char *zTableName, /* Table name */
+ const char *zColumnName, /* Column name */
+ char const **pzDataType, /* OUTPUT: Declared data type */
+ char const **pzCollSeq, /* OUTPUT: Collation sequence name */
+ int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */
+ int *pPrimaryKey, /* OUTPUT: True if column part of PK */
+ int *pAutoinc /* OUTPUT: True if column is auto-increment */
+);
+
+/*
+** CAPI3REF: Load An Extension {H12600} <S20500>
+**
+** This interface loads an SQLite extension library from the named file.
+**
+** {H12601} The sqlite3_load_extension() interface attempts to load an
+** SQLite extension library contained in the file zFile.
+**
+** {H12602} The entry point is zProc.
+**
+** {H12603} zProc may be 0, in which case the name of the entry point
+** defaults to "sqlite3_extension_init".
+**
+** {H12604} The sqlite3_load_extension() interface shall return
+** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong.
+**
+** {H12605} If an error occurs and pzErrMsg is not 0, then the
+** [sqlite3_load_extension()] interface shall attempt to
+** fill *pzErrMsg with error message text stored in memory
+** obtained from [sqlite3_malloc()]. {END} The calling function
+** should free this memory by calling [sqlite3_free()].
+**
+** {H12606} Extension loading must be enabled using
+** [sqlite3_enable_load_extension()] prior to calling this API,
+** otherwise an error will be returned.
+*/
+int sqlite3_load_extension(
+ sqlite3 *db, /* Load the extension into this database connection */
+ const char *zFile, /* Name of the shared library containing extension */
+ const char *zProc, /* Entry point. Derived from zFile if 0 */
+ char **pzErrMsg /* Put error message here if not 0 */
+);
+
+/*
+** CAPI3REF: Enable Or Disable Extension Loading {H12620} <S20500>
+**
+** So as not to open security holes in older applications that are
+** unprepared to deal with extension loading, and as a means of disabling
+** extension loading while evaluating user-entered SQL, the following API
+** is provided to turn the [sqlite3_load_extension()] mechanism on and off.
+**
+** Extension loading is off by default. See ticket #1863.
+**
+** {H12621} Call the sqlite3_enable_load_extension() routine with onoff==1
+** to turn extension loading on and call it with onoff==0 to turn
+** it back off again.
+**
+** {H12622} Extension loading is off by default.
+*/
+int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
+
+/*
+** CAPI3REF: Automatically Load An Extensions {H12640} <S20500>
+**
+** This API can be invoked at program startup in order to register
+** one or more statically linked extensions that will be available
+** to all new [database connections]. {END}
+**
+** This routine stores a pointer to the extension in an array that is
+** obtained from [sqlite3_malloc()]. If you run a memory leak checker
+** on your program and it reports a leak because of this array, invoke
+** [sqlite3_reset_auto_extension()] prior to shutdown to free the memory.
+**
+** {H12641} This function registers an extension entry point that is
+** automatically invoked whenever a new [database connection]
+** is opened using [sqlite3_open()], [sqlite3_open16()],
+** or [sqlite3_open_v2()].
+**
+** {H12642} Duplicate extensions are detected so calling this routine
+** multiple times with the same extension is harmless.
+**
+** {H12643} This routine stores a pointer to the extension in an array
+** that is obtained from [sqlite3_malloc()].
+**
+** {H12644} Automatic extensions apply across all threads.
+*/
+int sqlite3_auto_extension(void *xEntryPoint);
+
+/*
+** CAPI3REF: Reset Automatic Extension Loading {H12660} <S20500>
+**
+** This function disables all previously registered automatic
+** extensions. {END} It undoes the effect of all prior
+** [sqlite3_auto_extension()] calls.
+**
+** {H12661} This function disables all previously registered
+** automatic extensions.
+**
+** {H12662} This function disables automatic extensions in all threads.
+*/
+void sqlite3_reset_auto_extension(void);
+
+/*
+****** EXPERIMENTAL - subject to change without notice **************
+**
+** The interface to the virtual-table mechanism is currently considered
+** to be experimental. The interface might change in incompatible ways.
+** If this is a problem for you, do not use the interface at this time.
+**
+** When the virtual-table mechanism stabilizes, we will declare the
+** interface fixed, support it indefinitely, and remove this comment.
+*/
+
+/*
+** Structures used by the virtual table interface
+*/
+typedef struct sqlite3_vtab sqlite3_vtab;
+typedef struct sqlite3_index_info sqlite3_index_info;
+typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor;
+typedef struct sqlite3_module sqlite3_module;
+
+/*
+** CAPI3REF: Virtual Table Object {H18000} <S20400>
+** KEYWORDS: sqlite3_module
+** EXPERIMENTAL
+**
+** A module is a class of virtual tables. Each module is defined
+** by an instance of the following structure. This structure consists
+** mostly of methods for the module.
+**
+** This interface is experimental and is subject to change or
+** removal in future releases of SQLite.
+*/
+struct sqlite3_module {
+ int iVersion;
+ int (*xCreate)(sqlite3*, void *pAux,
+ int argc, const char *const*argv,
+ sqlite3_vtab **ppVTab, char**);
+ int (*xConnect)(sqlite3*, void *pAux,
+ int argc, const char *const*argv,
+ sqlite3_vtab **ppVTab, char**);
+ int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*);
+ int (*xDisconnect)(sqlite3_vtab *pVTab);
+ int (*xDestroy)(sqlite3_vtab *pVTab);
+ int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);
+ int (*xClose)(sqlite3_vtab_cursor*);
+ int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr,
+ int argc, sqlite3_value **argv);
+ int (*xNext)(sqlite3_vtab_cursor*);
+ int (*xEof)(sqlite3_vtab_cursor*);
+ int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int);
+ int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid);
+ int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *);
+ int (*xBegin)(sqlite3_vtab *pVTab);
+ int (*xSync)(sqlite3_vtab *pVTab);
+ int (*xCommit)(sqlite3_vtab *pVTab);
+ int (*xRollback)(sqlite3_vtab *pVTab);
+ int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
+ void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
+ void **ppArg);
+ int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
+};
+
+/*
+** CAPI3REF: Virtual Table Indexing Information {H18100} <S20400>
+** KEYWORDS: sqlite3_index_info
+** EXPERIMENTAL
+**
+** The sqlite3_index_info structure and its substructures is used to
+** pass information into and receive the reply from the xBestIndex
+** method of an sqlite3_module. The fields under **Inputs** are the
+** inputs to xBestIndex and are read-only. xBestIndex inserts its
+** results into the **Outputs** fields.
+**
+** The aConstraint[] array records WHERE clause constraints of the form:
+**
+** <pre>column OP expr</pre>
+**
+** where OP is =, <, <=, >, or >=. The particular operator is
+** stored in aConstraint[].op. The index of the column is stored in
+** aConstraint[].iColumn. aConstraint[].usable is TRUE if the
+** expr on the right-hand side can be evaluated (and thus the constraint
+** is usable) and false if it cannot.
+**
+** The optimizer automatically inverts terms of the form "expr OP column"
+** and makes other simplifications to the WHERE clause in an attempt to
+** get as many WHERE clause terms into the form shown above as possible.
+** The aConstraint[] array only reports WHERE clause terms in the correct
+** form that refer to the particular virtual table being queried.
+**
+** Information about the ORDER BY clause is stored in aOrderBy[].
+** Each term of aOrderBy records a column of the ORDER BY clause.
+**
+** The xBestIndex method must fill aConstraintUsage[] with information
+** about what parameters to pass to xFilter. If argvIndex>0 then
+** the right-hand side of the corresponding aConstraint[] is evaluated
+** and becomes the argvIndex-th entry in argv. If aConstraintUsage[].omit
+** is true, then the constraint is assumed to be fully handled by the
+** virtual table and is not checked again by SQLite.
+**
+** The idxNum and idxPtr values are recorded and passed into xFilter.
+** sqlite3_free() is used to free idxPtr if needToFreeIdxPtr is true.
+**
+** The orderByConsumed means that output from xFilter will occur in
+** the correct order to satisfy the ORDER BY clause so that no separate
+** sorting step is required.
+**
+** The estimatedCost value is an estimate of the cost of doing the
+** particular lookup. A full scan of a table with N entries should have
+** a cost of N. A binary search of a table of N entries should have a
+** cost of approximately log(N).
+**
+** This interface is experimental and is subject to change or
+** removal in future releases of SQLite.
+*/
+struct sqlite3_index_info {
+ /* Inputs */
+ int nConstraint; /* Number of entries in aConstraint */
+ struct sqlite3_index_constraint {
+ int iColumn; /* Column on left-hand side of constraint */
+ unsigned char op; /* Constraint operator */
+ unsigned char usable; /* True if this constraint is usable */
+ int iTermOffset; /* Used internally - xBestIndex should ignore */
+ } *aConstraint; /* Table of WHERE clause constraints */
+ int nOrderBy; /* Number of terms in the ORDER BY clause */
+ struct sqlite3_index_orderby {
+ int iColumn; /* Column number */
+ unsigned char desc; /* True for DESC. False for ASC. */
+ } *aOrderBy; /* The ORDER BY clause */
+ /* Outputs */
+ struct sqlite3_index_constraint_usage {
+ int argvIndex; /* if >0, constraint is part of argv to xFilter */
+ unsigned char omit; /* Do not code a test for this constraint */
+ } *aConstraintUsage;
+ int idxNum; /* Number used to identify the index */
+ char *idxStr; /* String, possibly obtained from sqlite3_malloc */
+ int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */
+ int orderByConsumed; /* True if output is already ordered */
+ double estimatedCost; /* Estimated cost of using this index */
+};
+#define SQLITE_INDEX_CONSTRAINT_EQ 2
+#define SQLITE_INDEX_CONSTRAINT_GT 4
+#define SQLITE_INDEX_CONSTRAINT_LE 8
+#define SQLITE_INDEX_CONSTRAINT_LT 16
+#define SQLITE_INDEX_CONSTRAINT_GE 32
+#define SQLITE_INDEX_CONSTRAINT_MATCH 64
+
+/*
+** CAPI3REF: Register A Virtual Table Implementation {H18200} <S20400>
+** EXPERIMENTAL
+**
+** This routine is used to register a new module name with a
+** [database connection]. Module names must be registered before
+** creating new virtual tables on the module, or before using
+** preexisting virtual tables of the module.
+**
+** This interface is experimental and is subject to change or
+** removal in future releases of SQLite.
+*/
+int sqlite3_create_module(
+ sqlite3 *db, /* SQLite connection to register module with */
+ const char *zName, /* Name of the module */
+ const sqlite3_module *, /* Methods for the module */
+ void * /* Client data for xCreate/xConnect */
+);
+
+/*
+** CAPI3REF: Register A Virtual Table Implementation {H18210} <S20400>
+** EXPERIMENTAL
+**
+** This routine is identical to the [sqlite3_create_module()] method above,
+** except that it allows a destructor function to be specified. It is
+** even more experimental than the rest of the virtual tables API.
+*/
+int sqlite3_create_module_v2(
+ sqlite3 *db, /* SQLite connection to register module with */
+ const char *zName, /* Name of the module */
+ const sqlite3_module *, /* Methods for the module */
+ void *, /* Client data for xCreate/xConnect */
+ void(*xDestroy)(void*) /* Module destructor function */
+);
+
+/*
+** CAPI3REF: Virtual Table Instance Object {H18010} <S20400>
+** KEYWORDS: sqlite3_vtab
+** EXPERIMENTAL
+**
+** Every module implementation uses a subclass of the following structure
+** to describe a particular instance of the module. Each subclass will
+** be tailored to the specific needs of the module implementation.
+** The purpose of this superclass is to define certain fields that are
+** common to all module implementations.
+**
+** Virtual tables methods can set an error message by assigning a
+** string obtained from [sqlite3_mprintf()] to zErrMsg. The method should
+** take care that any prior string is freed by a call to [sqlite3_free()]
+** prior to assigning a new string to zErrMsg. After the error message
+** is delivered up to the client application, the string will be automatically
+** freed by sqlite3_free() and the zErrMsg field will be zeroed. Note
+** that sqlite3_mprintf() and sqlite3_free() are used on the zErrMsg field
+** since virtual tables are commonly implemented in loadable extensions which
+** do not have access to sqlite3MPrintf() or sqlite3Free().
+**
+** This interface is experimental and is subject to change or
+** removal in future releases of SQLite.
+*/
+struct sqlite3_vtab {
+ const sqlite3_module *pModule; /* The module for this virtual table */
+ int nRef; /* Used internally */
+ char *zErrMsg; /* Error message from sqlite3_mprintf() */
+ /* Virtual table implementations will typically add additional fields */
+};
+
+/*
+** CAPI3REF: Virtual Table Cursor Object {H18020} <S20400>
+** KEYWORDS: sqlite3_vtab_cursor
+** EXPERIMENTAL
+**
+** Every module implementation uses a subclass of the following structure
+** to describe cursors that point into the virtual table and are used
+** to loop through the virtual table. Cursors are created using the
+** xOpen method of the module. Each module implementation will define
+** the content of a cursor structure to suit its own needs.
+**
+** This superclass exists in order to define fields of the cursor that
+** are common to all implementations.
+**
+** This interface is experimental and is subject to change or
+** removal in future releases of SQLite.
+*/
+struct sqlite3_vtab_cursor {
+ sqlite3_vtab *pVtab; /* Virtual table of this cursor */
+ /* Virtual table implementations will typically add additional fields */
+};
+
+/*
+** CAPI3REF: Declare The Schema Of A Virtual Table {H18280} <S20400>
+** EXPERIMENTAL
+**
+** The xCreate and xConnect methods of a module use the following API
+** to declare the format (the names and datatypes of the columns) of
+** the virtual tables they implement.
+**
+** This interface is experimental and is subject to change or
+** removal in future releases of SQLite.
+*/
+int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable);
+
+/*
+** CAPI3REF: Overload A Function For A Virtual Table {H18300} <S20400>
+** EXPERIMENTAL
+**
+** Virtual tables can provide alternative implementations of functions
+** using the xFindFunction method. But global versions of those functions
+** must exist in order to be overloaded.
+**
+** This API makes sure a global version of a function with a particular
+** name and number of parameters exists. If no such function exists
+** before this API is called, a new function is created. The implementation
+** of the new function always causes an exception to be thrown. So
+** the new function is not good for anything by itself. Its only
+** purpose is to be a placeholder function that can be overloaded
+** by virtual tables.
+**
+** This API should be considered part of the virtual table interface,
+** which is experimental and subject to change.
+*/
+int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
+
+/*
+** The interface to the virtual-table mechanism defined above (back up
+** to a comment remarkably similar to this one) is currently considered
+** to be experimental. The interface might change in incompatible ways.
+** If this is a problem for you, do not use the interface at this time.
+**
+** When the virtual-table mechanism stabilizes, we will declare the
+** interface fixed, support it indefinitely, and remove this comment.
+**
+****** EXPERIMENTAL - subject to change without notice **************
+*/
+
+/*
+** CAPI3REF: A Handle To An Open BLOB {H17800} <S30230>
+** KEYWORDS: {BLOB handle} {BLOB handles}
+**
+** An instance of this object represents an open BLOB on which
+** [sqlite3_blob_open | incremental BLOB I/O] can be performed.
+** Objects of this type are created by [sqlite3_blob_open()]
+** and destroyed by [sqlite3_blob_close()].
+** The [sqlite3_blob_read()] and [sqlite3_blob_write()] interfaces
+** can be used to read or write small subsections of the BLOB.
+** The [sqlite3_blob_bytes()] interface returns the size of the BLOB in bytes.
+*/
+typedef struct sqlite3_blob sqlite3_blob;
+
+/*
+** CAPI3REF: Open A BLOB For Incremental I/O {H17810} <S30230>
+**
+** This interfaces opens a [BLOB handle | handle] to the BLOB located
+** in row iRow, column zColumn, table zTable in database zDb;
+** in other words, the same BLOB that would be selected by:
+**
+** <pre>
+** SELECT zColumn FROM zDb.zTable WHERE rowid = iRow;
+** </pre> {END}
+**
+** If the flags parameter is non-zero, the the BLOB is opened for read
+** and write access. If it is zero, the BLOB is opened for read access.
+**
+** Note that the database name is not the filename that contains
+** the database but rather the symbolic name of the database that
+** is assigned when the database is connected using [ATTACH].
+** For the main database file, the database name is "main".
+** For TEMP tables, the database name is "temp".
+**
+** On success, [SQLITE_OK] is returned and the new [BLOB handle] is written
+** to *ppBlob. Otherwise an [error code] is returned and any value written
+** to *ppBlob should not be used by the caller.
+** This function sets the [database connection] error code and message
+** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()].
+**
+** If the row that a BLOB handle points to is modified by an
+** [UPDATE], [DELETE], or by [ON CONFLICT] side-effects
+** then the BLOB handle is marked as "expired".
+** This is true if any column of the row is changed, even a column
+** other than the one the BLOB handle is open on.
+** Calls to [sqlite3_blob_read()] and [sqlite3_blob_write()] for
+** a expired BLOB handle fail with an return code of [SQLITE_ABORT].
+** Changes written into a BLOB prior to the BLOB expiring are not
+** rollback by the expiration of the BLOB. Such changes will eventually
+** commit if the transaction continues to completion.
+**
+** INVARIANTS:
+**
+** {H17813} A successful invocation of the [sqlite3_blob_open(D,B,T,C,R,F,P)]
+** interface shall open an [sqlite3_blob] object P on the BLOB
+** in column C of the table T in the database B on
+** the [database connection] D.
+**
+** {H17814} A successful invocation of [sqlite3_blob_open(D,...)] shall start
+** a new transaction on the [database connection] D if that
+** connection is not already in a transaction.
+**
+** {H17816} The [sqlite3_blob_open(D,B,T,C,R,F,P)] interface shall open
+** the BLOB for read and write access if and only if the F
+** parameter is non-zero.
+**
+** {H17819} The [sqlite3_blob_open()] interface shall return [SQLITE_OK] on
+** success and an appropriate [error code] on failure.
+**
+** {H17821} If an error occurs during evaluation of [sqlite3_blob_open(D,...)]
+** then subsequent calls to [sqlite3_errcode(D)],
+** [sqlite3_errmsg(D)], and [sqlite3_errmsg16(D)] shall return
+** information appropriate for that error.
+**
+** {H17824} If any column in the row that a [sqlite3_blob] has open is
+** changed by a separate [UPDATE] or [DELETE] statement or by
+** an [ON CONFLICT] side effect, then the [sqlite3_blob] shall
+** be marked as invalid.
+*/
+int sqlite3_blob_open(
+ sqlite3*,
+ const char *zDb,
+ const char *zTable,
+ const char *zColumn,
+ sqlite3_int64 iRow,
+ int flags,
+ sqlite3_blob **ppBlob
+);
+
+/*
+** CAPI3REF: Close A BLOB Handle {H17830} <S30230>
+**
+** Closes an open [BLOB handle].
+**
+** Closing a BLOB shall cause the current transaction to commit
+** if there are no other BLOBs, no pending prepared statements, and the
+** database connection is in [autocommit mode].
+** If any writes were made to the BLOB, they might be held in cache
+** until the close operation if they will fit. {END}
+**
+** Closing the BLOB often forces the changes
+** out to disk and so if any I/O errors occur, they will likely occur
+** at the time when the BLOB is closed. {H17833} Any errors that occur during
+** closing are reported as a non-zero return value.
+**
+** The BLOB is closed unconditionally. Even if this routine returns
+** an error code, the BLOB is still closed.
+**
+** INVARIANTS:
+**
+** {H17833} The [sqlite3_blob_close(P)] interface closes an [sqlite3_blob]
+** object P previously opened using [sqlite3_blob_open()].
+**
+** {H17836} Closing an [sqlite3_blob] object using
+** [sqlite3_blob_close()] shall cause the current transaction to
+** commit if there are no other open [sqlite3_blob] objects
+** or [prepared statements] on the same [database connection] and
+** the database connection is in [autocommit mode].
+**
+** {H17839} The [sqlite3_blob_close(P)] interfaces shall close the
+** [sqlite3_blob] object P unconditionally, even if
+** [sqlite3_blob_close(P)] returns something other than [SQLITE_OK].
+*/
+int sqlite3_blob_close(sqlite3_blob *);
+
+/*
+** CAPI3REF: Return The Size Of An Open BLOB {H17840} <S30230>
+**
+** Returns the size in bytes of the BLOB accessible via the open
+** []BLOB handle] in its only argument.
+**
+** INVARIANTS:
+**
+** {H17843} The [sqlite3_blob_bytes(P)] interface returns the size
+** in bytes of the BLOB that the [sqlite3_blob] object P
+** refers to.
+*/
+int sqlite3_blob_bytes(sqlite3_blob *);
+
+/*
+** CAPI3REF: Read Data From A BLOB Incrementally {H17850} <S30230>
+**
+** This function is used to read data from an open [BLOB handle] into a
+** caller-supplied buffer. N bytes of data are copied into buffer Z
+** from the open BLOB, starting at offset iOffset.
+**
+** If offset iOffset is less than N bytes from the end of the BLOB,
+** [SQLITE_ERROR] is returned and no data is read. If N or iOffset is
+** less than zero, [SQLITE_ERROR] is returned and no data is read.
+**
+** An attempt to read from an expired [BLOB handle] fails with an
+** error code of [SQLITE_ABORT].
+**
+** On success, SQLITE_OK is returned.
+** Otherwise, an [error code] or an [extended error code] is returned.
+**
+** INVARIANTS:
+**
+** {H17853} A successful invocation of [sqlite3_blob_read(P,Z,N,X)]
+** shall reads N bytes of data out of the BLOB referenced by
+** [BLOB handle] P beginning at offset X and store those bytes
+** into buffer Z.
+**
+** {H17856} In [sqlite3_blob_read(P,Z,N,X)] if the size of the BLOB
+** is less than N+X bytes, then the function shall leave the
+** Z buffer unchanged and return [SQLITE_ERROR].
+**
+** {H17859} In [sqlite3_blob_read(P,Z,N,X)] if X or N is less than zero
+** then the function shall leave the Z buffer unchanged
+** and return [SQLITE_ERROR].
+**
+** {H17862} The [sqlite3_blob_read(P,Z,N,X)] interface shall return [SQLITE_OK]
+** if N bytes are successfully read into buffer Z.
+**
+** {H17863} If the [BLOB handle] P is expired and X and N are within bounds
+** then [sqlite3_blob_read(P,Z,N,X)] shall leave the Z buffer
+** unchanged and return [SQLITE_ABORT].
+**
+** {H17865} If the requested read could not be completed,
+** the [sqlite3_blob_read(P,Z,N,X)] interface shall return an
+** appropriate [error code] or [extended error code].
+**
+** {H17868} If an error occurs during evaluation of [sqlite3_blob_read(P,...)]
+** then subsequent calls to [sqlite3_errcode(D)],
+** [sqlite3_errmsg(D)], and [sqlite3_errmsg16(D)] shall return
+** information appropriate for that error, where D is the
+** [database connection] that was used to open the [BLOB handle] P.
+*/
+int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
+
+/*
+** CAPI3REF: Write Data Into A BLOB Incrementally {H17870} <S30230>
+**
+** This function is used to write data into an open [BLOB handle] from a
+** caller-supplied buffer. N bytes of data are copied from the buffer Z
+** into the open BLOB, starting at offset iOffset.
+**
+** If the [BLOB handle] passed as the first argument was not opened for
+** writing (the flags parameter to [sqlite3_blob_open()] was zero),
+** this function returns [SQLITE_READONLY].
+**
+** This function may only modify the contents of the BLOB; it is
+** not possible to increase the size of a BLOB using this API.
+** If offset iOffset is less than N bytes from the end of the BLOB,
+** [SQLITE_ERROR] is returned and no data is written. If N is
+** less than zero [SQLITE_ERROR] is returned and no data is written.
+**
+** An attempt to write to an expired [BLOB handle] fails with an
+** error code of [SQLITE_ABORT]. Writes to the BLOB that occurred
+** before the [BLOB handle] expired are not rolled back by the
+** expiration of the handle, though of course those changes might
+** have been overwritten by the statement that expired the BLOB handle
+** or by other independent statements.
+**
+** On success, SQLITE_OK is returned.
+** Otherwise, an [error code] or an [extended error code] is returned.
+**
+** INVARIANTS:
+**
+** {H17873} A successful invocation of [sqlite3_blob_write(P,Z,N,X)]
+** shall write N bytes of data from buffer Z into the BLOB
+** referenced by [BLOB handle] P beginning at offset X into
+** the BLOB.
+**
+** {H17874} In the absence of other overridding changes, the changes
+** written to a BLOB by [sqlite3_blob_write()] shall
+** remain in effect after the associated [BLOB handle] expires.
+**
+** {H17875} If the [BLOB handle] P was opened for reading only then
+** an invocation of [sqlite3_blob_write(P,Z,N,X)] shall leave
+** the referenced BLOB unchanged and return [SQLITE_READONLY].
+**
+** {H17876} If the size of the BLOB referenced by [BLOB handle] P is
+** less than N+X bytes then [sqlite3_blob_write(P,Z,N,X)] shall
+** leave the BLOB unchanged and return [SQLITE_ERROR].
+**
+** {H17877} If the [BLOB handle] P is expired and X and N are within bounds
+** then [sqlite3_blob_read(P,Z,N,X)] shall leave the BLOB
+** unchanged and return [SQLITE_ABORT].
+**
+** {H17879} If X or N are less than zero then [sqlite3_blob_write(P,Z,N,X)]
+** shall leave the BLOB referenced by [BLOB handle] P unchanged
+** and return [SQLITE_ERROR].
+**
+** {H17882} The [sqlite3_blob_write(P,Z,N,X)] interface shall return
+** [SQLITE_OK] if N bytes where successfully written into the BLOB.
+**
+** {H17885} If the requested write could not be completed,
+** the [sqlite3_blob_write(P,Z,N,X)] interface shall return an
+** appropriate [error code] or [extended error code].
+**
+** {H17888} If an error occurs during evaluation of [sqlite3_blob_write(D,...)]
+** then subsequent calls to [sqlite3_errcode(D)],
+** [sqlite3_errmsg(D)], and [sqlite3_errmsg16(D)] shall return
+** information appropriate for that error.
+*/
+int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset);
+
+/* Begin preload-cache.patch for Chromium */
+/*
+** Preload the databases into the pager cache, up to the maximum size of the
+** pager cache.
+**
+** For a database to be loaded successfully, the pager must be active. That is,
+** there must be an open statement on that database. See sqlite3pager_loadall
+**
+** There might be many databases attached to the given connection. We iterate
+** them all and try to load them. If none are loadable successfully, we return
+** an error. Otherwise, we return OK.
+*/
+int sqlite3Preload(sqlite3 *db);
+/* End preload-cache.patch for Chromium */
+
+/*
+** CAPI3REF: Virtual File System Objects {H11200} <S20100>
+**
+** A virtual filesystem (VFS) is an [sqlite3_vfs] object
+** that SQLite uses to interact
+** with the underlying operating system. Most SQLite builds come with a
+** single default VFS that is appropriate for the host computer.
+** New VFSes can be registered and existing VFSes can be unregistered.
+** The following interfaces are provided.
+**
+** The sqlite3_vfs_find() interface returns a pointer to a VFS given its name.
+** Names are case sensitive.
+** Names are zero-terminated UTF-8 strings.
+** If there is no match, a NULL pointer is returned.
+** If zVfsName is NULL then the default VFS is returned.
+**
+** New VFSes are registered with sqlite3_vfs_register().
+** Each new VFS becomes the default VFS if the makeDflt flag is set.
+** The same VFS can be registered multiple times without injury.
+** To make an existing VFS into the default VFS, register it again
+** with the makeDflt flag set. If two different VFSes with the
+** same name are registered, the behavior is undefined. If a
+** VFS is registered with a name that is NULL or an empty string,
+** then the behavior is undefined.
+**
+** Unregister a VFS with the sqlite3_vfs_unregister() interface.
+** If the default VFS is unregistered, another VFS is chosen as
+** the default. The choice for the new VFS is arbitrary.
+**
+** INVARIANTS:
+**
+** {H11203} The [sqlite3_vfs_find(N)] interface returns a pointer to the
+** registered [sqlite3_vfs] object whose name exactly matches
+** the zero-terminated UTF-8 string N, or it returns NULL if
+** there is no match.
+**
+** {H11206} If the N parameter to [sqlite3_vfs_find(N)] is NULL then
+** the function returns a pointer to the default [sqlite3_vfs]
+** object if there is one, or NULL if there is no default
+** [sqlite3_vfs] object.
+**
+** {H11209} The [sqlite3_vfs_register(P,F)] interface registers the
+** well-formed [sqlite3_vfs] object P using the name given
+** by the zName field of the object.
+**
+** {H11212} Using the [sqlite3_vfs_register(P,F)] interface to register
+** the same [sqlite3_vfs] object multiple times is a harmless no-op.
+**
+** {H11215} The [sqlite3_vfs_register(P,F)] interface makes the [sqlite3_vfs]
+** object P the default [sqlite3_vfs] object if F is non-zero.
+**
+** {H11218} The [sqlite3_vfs_unregister(P)] interface unregisters the
+** [sqlite3_vfs] object P so that it is no longer returned by
+** subsequent calls to [sqlite3_vfs_find()].
+*/
+sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName);
+int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt);
+int sqlite3_vfs_unregister(sqlite3_vfs*);
+
+/*
+** CAPI3REF: Mutexes {H17000} <S20000>
+**
+** The SQLite core uses these routines for thread
+** synchronization. Though they are intended for internal
+** use by SQLite, code that links against SQLite is
+** permitted to use any of these routines.
+**
+** The SQLite source code contains multiple implementations
+** of these mutex routines. An appropriate implementation
+** is selected automatically at compile-time. The following
+** implementations are available in the SQLite core:
+**
+** <ul>
+** <li> SQLITE_MUTEX_OS2
+** <li> SQLITE_MUTEX_PTHREAD
+** <li> SQLITE_MUTEX_W32
+** <li> SQLITE_MUTEX_NOOP
+** </ul>
+**
+** The SQLITE_MUTEX_NOOP implementation is a set of routines
+** that does no real locking and is appropriate for use in
+** a single-threaded application. The SQLITE_MUTEX_OS2,
+** SQLITE_MUTEX_PTHREAD, and SQLITE_MUTEX_W32 implementations
+** are appropriate for use on OS/2, Unix, and Windows.
+**
+** If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor
+** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex
+** implementation is included with the library. In this case the
+** application must supply a custom mutex implementation using the
+** [SQLITE_CONFIG_MUTEX] option of the sqlite3_config() function
+** before calling sqlite3_initialize() or any other public sqlite3_
+** function that calls sqlite3_initialize().
+**
+** {H17011} The sqlite3_mutex_alloc() routine allocates a new
+** mutex and returns a pointer to it. {H17012} If it returns NULL
+** that means that a mutex could not be allocated. {H17013} SQLite
+** will unwind its stack and return an error. {H17014} The argument
+** to sqlite3_mutex_alloc() is one of these integer constants:
+**
+** <ul>
+** <li> SQLITE_MUTEX_FAST
+** <li> SQLITE_MUTEX_RECURSIVE
+** <li> SQLITE_MUTEX_STATIC_MASTER
+** <li> SQLITE_MUTEX_STATIC_MEM
+** <li> SQLITE_MUTEX_STATIC_MEM2
+** <li> SQLITE_MUTEX_STATIC_PRNG
+** <li> SQLITE_MUTEX_STATIC_LRU
+** <li> SQLITE_MUTEX_STATIC_LRU2
+** </ul>
+**
+** {H17015} The first two constants cause sqlite3_mutex_alloc() to create
+** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
+** is used but not necessarily so when SQLITE_MUTEX_FAST is used. {END}
+** The mutex implementation does not need to make a distinction
+** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
+** not want to. {H17016} But SQLite will only request a recursive mutex in
+** cases where it really needs one. {END} If a faster non-recursive mutex
+** implementation is available on the host platform, the mutex subsystem
+** might return such a mutex in response to SQLITE_MUTEX_FAST.
+**
+** {H17017} The other allowed parameters to sqlite3_mutex_alloc() each return
+** a pointer to a static preexisting mutex. {END} Four static mutexes are
+** used by the current version of SQLite. Future versions of SQLite
+** may add additional static mutexes. Static mutexes are for internal
+** use by SQLite only. Applications that use SQLite mutexes should
+** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
+** SQLITE_MUTEX_RECURSIVE.
+**
+** {H17018} Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
+** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
+** returns a different mutex on every call. {H17034} But for the static
+** mutex types, the same mutex is returned on every call that has
+** the same type number.
+**
+** {H17019} The sqlite3_mutex_free() routine deallocates a previously
+** allocated dynamic mutex. {H17020} SQLite is careful to deallocate every
+** dynamic mutex that it allocates. {A17021} The dynamic mutexes must not be in
+** use when they are deallocated. {A17022} Attempting to deallocate a static
+** mutex results in undefined behavior. {H17023} SQLite never deallocates
+** a static mutex. {END}
+**
+** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
+** to enter a mutex. {H17024} If another thread is already within the mutex,
+** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
+** SQLITE_BUSY. {H17025} The sqlite3_mutex_try() interface returns [SQLITE_OK]
+** upon successful entry. {H17026} Mutexes created using
+** SQLITE_MUTEX_RECURSIVE can be entered multiple times by the same thread.
+** {H17027} In such cases the,
+** mutex must be exited an equal number of times before another thread
+** can enter. {A17028} If the same thread tries to enter any other
+** kind of mutex more than once, the behavior is undefined.
+** {H17029} SQLite will never exhibit
+** such behavior in its own use of mutexes.
+**
+** Some systems (for example, Windows 95) do not support the operation
+** implemented by sqlite3_mutex_try(). On those systems, sqlite3_mutex_try()
+** will always return SQLITE_BUSY. {H17030} The SQLite core only ever uses
+** sqlite3_mutex_try() as an optimization so this is acceptable behavior.
+**
+** {H17031} The sqlite3_mutex_leave() routine exits a mutex that was
+** previously entered by the same thread. {A17032} The behavior
+** is undefined if the mutex is not currently entered by the
+** calling thread or is not currently allocated. {H17033} SQLite will
+** never do either. {END}
+**
+** If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or
+** sqlite3_mutex_leave() is a NULL pointer, then all three routines
+** behave as no-ops.
+**
+** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()].
+*/
+sqlite3_mutex *sqlite3_mutex_alloc(int);
+void sqlite3_mutex_free(sqlite3_mutex*);
+void sqlite3_mutex_enter(sqlite3_mutex*);
+int sqlite3_mutex_try(sqlite3_mutex*);
+void sqlite3_mutex_leave(sqlite3_mutex*);
+
+/*
+** CAPI3REF: Mutex Methods Object {H17120} <S20130>
+** EXPERIMENTAL
+**
+** An instance of this structure defines the low-level routines
+** used to allocate and use mutexes.
+**
+** Usually, the default mutex implementations provided by SQLite are
+** sufficient, however the user has the option of substituting a custom
+** implementation for specialized deployments or systems for which SQLite
+** does not provide a suitable implementation. In this case, the user
+** creates and populates an instance of this structure to pass
+** to sqlite3_config() along with the [SQLITE_CONFIG_MUTEX] option.
+** Additionally, an instance of this structure can be used as an
+** output variable when querying the system for the current mutex
+** implementation, using the [SQLITE_CONFIG_GETMUTEX] option.
+**
+** The xMutexInit method defined by this structure is invoked as
+** part of system initialization by the sqlite3_initialize() function.
+** {H17001} The xMutexInit routine shall be called by SQLite once for each
+** effective call to [sqlite3_initialize()].
+**
+** The xMutexEnd method defined by this structure is invoked as
+** part of system shutdown by the sqlite3_shutdown() function. The
+** implementation of this method is expected to release all outstanding
+** resources obtained by the mutex methods implementation, especially
+** those obtained by the xMutexInit method. {H17003} The xMutexEnd()
+** interface shall be invoked once for each call to [sqlite3_shutdown()].
+**
+** The remaining seven methods defined by this structure (xMutexAlloc,
+** xMutexFree, xMutexEnter, xMutexTry, xMutexLeave, xMutexHeld and
+** xMutexNotheld) implement the following interfaces (respectively):
+**
+** <ul>
+** <li> [sqlite3_mutex_alloc()] </li>
+** <li> [sqlite3_mutex_free()] </li>
+** <li> [sqlite3_mutex_enter()] </li>
+** <li> [sqlite3_mutex_try()] </li>
+** <li> [sqlite3_mutex_leave()] </li>
+** <li> [sqlite3_mutex_held()] </li>
+** <li> [sqlite3_mutex_notheld()] </li>
+** </ul>
+**
+** The only difference is that the public sqlite3_XXX functions enumerated
+** above silently ignore any invocations that pass a NULL pointer instead
+** of a valid mutex handle. The implementations of the methods defined
+** by this structure are not required to handle this case, the results
+** of passing a NULL pointer instead of a valid mutex handle are undefined
+** (i.e. it is acceptable to provide an implementation that segfaults if
+** it is passed a NULL pointer).
+*/
+typedef struct sqlite3_mutex_methods sqlite3_mutex_methods;
+struct sqlite3_mutex_methods {
+ int (*xMutexInit)(void);
+ int (*xMutexEnd)(void);
+ sqlite3_mutex *(*xMutexAlloc)(int);
+ void (*xMutexFree)(sqlite3_mutex *);
+ void (*xMutexEnter)(sqlite3_mutex *);
+ int (*xMutexTry)(sqlite3_mutex *);
+ void (*xMutexLeave)(sqlite3_mutex *);
+ int (*xMutexHeld)(sqlite3_mutex *);
+ int (*xMutexNotheld)(sqlite3_mutex *);
+};
+
+/*
+** CAPI3REF: Mutex Verification Routines {H17080} <S20130> <S30800>
+**
+** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines
+** are intended for use inside assert() statements. {H17081} The SQLite core
+** never uses these routines except inside an assert() and applications
+** are advised to follow the lead of the core. {H17082} The core only
+** provides implementations for these routines when it is compiled
+** with the SQLITE_DEBUG flag. {A17087} External mutex implementations
+** are only required to provide these routines if SQLITE_DEBUG is
+** defined and if NDEBUG is not defined.
+**
+** {H17083} These routines should return true if the mutex in their argument
+** is held or not held, respectively, by the calling thread.
+**
+** {X17084} The implementation is not required to provided versions of these
+** routines that actually work. If the implementation does not provide working
+** versions of these routines, it should at least provide stubs that always
+** return true so that one does not get spurious assertion failures.
+**
+** {H17085} If the argument to sqlite3_mutex_held() is a NULL pointer then
+** the routine should return 1. {END} This seems counter-intuitive since
+** clearly the mutex cannot be held if it does not exist. But the
+** the reason the mutex does not exist is because the build is not
+** using mutexes. And we do not want the assert() containing the
+** call to sqlite3_mutex_held() to fail, so a non-zero return is
+** the appropriate thing to do. {H17086} The sqlite3_mutex_notheld()
+** interface should also return 1 when given a NULL pointer.
+*/
+int sqlite3_mutex_held(sqlite3_mutex*);
+int sqlite3_mutex_notheld(sqlite3_mutex*);
+
+/*
+** CAPI3REF: Mutex Types {H17001} <H17000>
+**
+** The [sqlite3_mutex_alloc()] interface takes a single argument
+** which is one of these integer constants.
+**
+** The set of static mutexes may change from one SQLite release to the
+** next. Applications that override the built-in mutex logic must be
+** prepared to accommodate additional static mutexes.
+*/
+#define SQLITE_MUTEX_FAST 0
+#define SQLITE_MUTEX_RECURSIVE 1
+#define SQLITE_MUTEX_STATIC_MASTER 2
+#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */
+#define SQLITE_MUTEX_STATIC_MEM2 4 /* sqlite3_release_memory() */
+#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */
+#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */
+#define SQLITE_MUTEX_STATIC_LRU2 7 /* lru page list */
+
+/*
+** CAPI3REF: Low-Level Control Of Database Files {H11300} <S30800>
+**
+** {H11301} The [sqlite3_file_control()] interface makes a direct call to the
+** xFileControl method for the [sqlite3_io_methods] object associated
+** with a particular database identified by the second argument. {H11302} The
+** name of the database is the name assigned to the database by the
+** <a href="lang_attach.html">ATTACH</a> SQL command that opened the
+** database. {H11303} To control the main database file, use the name "main"
+** or a NULL pointer. {H11304} The third and fourth parameters to this routine
+** are passed directly through to the second and third parameters of
+** the xFileControl method. {H11305} The return value of the xFileControl
+** method becomes the return value of this routine.
+**
+** {H11306} If the second parameter (zDbName) does not match the name of any
+** open database file, then SQLITE_ERROR is returned. {H11307} This error
+** code is not remembered and will not be recalled by [sqlite3_errcode()]
+** or [sqlite3_errmsg()]. {A11308} The underlying xFileControl method might
+** also return SQLITE_ERROR. {A11309} There is no way to distinguish between
+** an incorrect zDbName and an SQLITE_ERROR return from the underlying
+** xFileControl method. {END}
+**
+** See also: [SQLITE_FCNTL_LOCKSTATE]
+*/
+int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*);
+
+/*
+** CAPI3REF: Testing Interface {H11400} <S30800>
+**
+** The sqlite3_test_control() interface is used to read out internal
+** state of SQLite and to inject faults into SQLite for testing
+** purposes. The first parameter is an operation code that determines
+** the number, meaning, and operation of all subsequent parameters.
+**
+** This interface is not for use by applications. It exists solely
+** for verifying the correct operation of the SQLite library. Depending
+** on how the SQLite library is compiled, this interface might not exist.
+**
+** The details of the operation codes, their meanings, the parameters
+** they take, and what they do are all subject to change without notice.
+** Unlike most of the SQLite API, this function is not guaranteed to
+** operate consistently from one release to the next.
+*/
+int sqlite3_test_control(int op, ...);
+
+/*
+** CAPI3REF: Testing Interface Operation Codes {H11410} <H11400>
+**
+** These constants are the valid operation code parameters used
+** as the first argument to [sqlite3_test_control()].
+**
+** These parameters and their meanings are subject to change
+** without notice. These values are for testing purposes only.
+** Applications should not use any of these parameters or the
+** [sqlite3_test_control()] interface.
+*/
+#define SQLITE_TESTCTRL_PRNG_SAVE 5
+#define SQLITE_TESTCTRL_PRNG_RESTORE 6
+#define SQLITE_TESTCTRL_PRNG_RESET 7
+#define SQLITE_TESTCTRL_BITVEC_TEST 8
+#define SQLITE_TESTCTRL_FAULT_INSTALL 9
+#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10
+
+/*
+** CAPI3REF: SQLite Runtime Status {H17200} <S60200>
+** EXPERIMENTAL
+**
+** This interface is used to retrieve runtime status information
+** about the preformance of SQLite, and optionally to reset various
+** highwater marks. The first argument is an integer code for
+** the specific parameter to measure. Recognized integer codes
+** are of the form [SQLITE_STATUS_MEMORY_USED | SQLITE_STATUS_...].
+** The current value of the parameter is returned into *pCurrent.
+** The highest recorded value is returned in *pHighwater. If the
+** resetFlag is true, then the highest record value is reset after
+** *pHighwater is written. Some parameters do not record the highest
+** value. For those parameters
+** nothing is written into *pHighwater and the resetFlag is ignored.
+** Other parameters record only the highwater mark and not the current
+** value. For these latter parameters nothing is written into *pCurrent.
+**
+** This routine returns SQLITE_OK on success and a non-zero
+** [error code] on failure.
+**
+** This routine is threadsafe but is not atomic. This routine can
+** called while other threads are running the same or different SQLite
+** interfaces. However the values returned in *pCurrent and
+** *pHighwater reflect the status of SQLite at different points in time
+** and it is possible that another thread might change the parameter
+** in between the times when *pCurrent and *pHighwater are written.
+**
+** See also: [sqlite3_db_status()]
+*/
+int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
+
+/*
+** CAPI3REF: Database Connection Status {H17201} <S60200>
+** EXPERIMENTAL
+**
+** This interface is used to retrieve runtime status information
+** about a single [database connection]. The first argument is the
+** database connection object to be interrogated. The second argument
+** is the parameter to interrogate. Currently, the only allowed value
+** for the second parameter is [SQLITE_DBSTATUS_LOOKASIDE_USED].
+** Additional options will likely appear in future releases of SQLite.
+**
+** The current value of the request parameter is written into *pCur
+** and the highest instantaneous value is written into *pHiwtr. If
+** the resetFlg is true, then the highest instantaneous value is
+** reset back down to the current value.
+**
+** See also: [sqlite3_status()].
+*/
+int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
+
+/*
+** CAPI3REF: Status Parameters {H17250} <H17200>
+** EXPERIMENTAL
+**
+** These integer constants designate various run-time status parameters
+** that can be returned by [sqlite3_status()].
+**
+** <dl>
+** <dt>SQLITE_STATUS_MEMORY_USED</dt>
+** <dd>This parameter is the current amount of memory checked out
+** using [sqlite3_malloc()], either directly or indirectly. The
+** figure includes calls made to [sqlite3_malloc()] by the application
+** and internal memory usage by the SQLite library. Scratch memory
+** controlled by [SQLITE_CONFIG_SCRATCH] and auxiliary page-cache
+** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in
+** this parameter. The amount returned is the sum of the allocation
+** sizes as reported by the xSize method in [sqlite3_mem_methods].</dd>
+**
+** <dt>SQLITE_STATUS_MALLOC_SIZE</dt>
+** <dd>This parameter records the largest memory allocation request
+** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their
+** internal equivalents). Only the value returned in the
+** *pHighwater parameter to [sqlite3_status()] is of interest.
+** The value written into the *pCurrent parameter is undefined.</dd>
+**
+** <dt>SQLITE_STATUS_PAGECACHE_USED</dt>
+** <dd>This parameter returns the number of pages used out of the
+** [pagecache memory allocator] that was configured using
+** [SQLITE_CONFIG_PAGECACHE]. The
+** value returned is in pages, not in bytes.</dd>
+**
+** <dt>SQLITE_STATUS_PAGECACHE_OVERFLOW</dt>
+** <dd>This parameter returns the number of bytes of page cache
+** allocation which could not be statisfied by the [SQLITE_CONFIG_PAGECACHE]
+** buffer and where forced to overflow to [sqlite3_malloc()]. The
+** returned value includes allocations that overflowed because they
+** where too large (they were larger than the "sz" parameter to
+** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because
+** no space was left in the page cache.</dd>
+**
+** <dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
+** <dd>This parameter records the largest memory allocation request
+** handed to [pagecache memory allocator]. Only the value returned in the
+** *pHighwater parameter to [sqlite3_status()] is of interest.
+** The value written into the *pCurrent parameter is undefined.</dd>
+**
+** <dt>SQLITE_STATUS_SCRATCH_USED</dt>
+** <dd>This parameter returns the number of allocations used out of the
+** [scratch memory allocator] configured using
+** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not
+** in bytes. Since a single thread may only have one scratch allocation
+** outstanding at time, this parameter also reports the number of threads
+** using scratch memory at the same time.</dd>
+**
+** <dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt>
+** <dd>This parameter returns the number of bytes of scratch memory
+** allocation which could not be statisfied by the [SQLITE_CONFIG_SCRATCH]
+** buffer and where forced to overflow to [sqlite3_malloc()]. The values
+** returned include overflows because the requested allocation was too
+** larger (that is, because the requested allocation was larger than the
+** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer
+** slots were available.
+** </dd>
+**
+** <dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
+** <dd>This parameter records the largest memory allocation request
+** handed to [scratch memory allocator]. Only the value returned in the
+** *pHighwater parameter to [sqlite3_status()] is of interest.
+** The value written into the *pCurrent parameter is undefined.</dd>
+**
+** <dt>SQLITE_STATUS_PARSER_STACK</dt>
+** <dd>This parameter records the deepest parser stack. It is only
+** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].</dd>
+** </dl>
+**
+** New status parameters may be added from time to time.
+*/
+#define SQLITE_STATUS_MEMORY_USED 0
+#define SQLITE_STATUS_PAGECACHE_USED 1
+#define SQLITE_STATUS_PAGECACHE_OVERFLOW 2
+#define SQLITE_STATUS_SCRATCH_USED 3
+#define SQLITE_STATUS_SCRATCH_OVERFLOW 4
+#define SQLITE_STATUS_MALLOC_SIZE 5
+#define SQLITE_STATUS_PARSER_STACK 6
+#define SQLITE_STATUS_PAGECACHE_SIZE 7
+#define SQLITE_STATUS_SCRATCH_SIZE 8
+
+/*
+** CAPI3REF: Status Parameters for database connections {H17275} <H17200>
+** EXPERIMENTAL
+**
+** Status verbs for [sqlite3_db_status()].
+**
+** <dl>
+** <dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
+** <dd>This parameter returns the number of lookaside memory slots currently
+** checked out.</dd>
+** </dl>
+*/
+#define SQLITE_DBSTATUS_LOOKASIDE_USED 0
+
+/*
+** 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
+
+#ifdef __cplusplus
+} /* End of the 'extern "C"' block */
+#endif
+#endif
diff --git a/third_party/sqlite/src/sqlite3ext.h b/third_party/sqlite/src/sqlite3ext.h new file mode 100755 index 0000000..a4da1d9 --- /dev/null +++ b/third_party/sqlite/src/sqlite3ext.h @@ -0,0 +1,378 @@ +/* +** 2006 June 7 +** +** 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 header file defines the SQLite interface for use by +** shared libraries that want to be imported as extensions into +** an SQLite instance. Shared libraries that intend to be loaded +** as extensions by SQLite should #include this file instead of +** sqlite3.h. +** +** @(#) $Id: sqlite3ext.h,v 1.24 2008/06/30 15:09:29 danielk1977 Exp $ +*/ +#ifndef _SQLITE3EXT_H_ +#define _SQLITE3EXT_H_ +#include "sqlite3.h" + +typedef struct sqlite3_api_routines sqlite3_api_routines; + +/* +** The following structure holds pointers to all of the SQLite API +** routines. +** +** WARNING: In order to maintain backwards compatibility, add new +** interfaces to the end of this structure only. If you insert new +** interfaces in the middle of this structure, then older different +** versions of SQLite will not be able to load each others' shared +** libraries! +*/ +struct sqlite3_api_routines { + void * (*aggregate_context)(sqlite3_context*,int nBytes); + int (*aggregate_count)(sqlite3_context*); + int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*)); + int (*bind_double)(sqlite3_stmt*,int,double); + int (*bind_int)(sqlite3_stmt*,int,int); + int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64); + int (*bind_null)(sqlite3_stmt*,int); + int (*bind_parameter_count)(sqlite3_stmt*); + int (*bind_parameter_index)(sqlite3_stmt*,const char*zName); + const char * (*bind_parameter_name)(sqlite3_stmt*,int); + int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*)); + int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*)); + int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*); + int (*busy_handler)(sqlite3*,int(*)(void*,int),void*); + int (*busy_timeout)(sqlite3*,int ms); + int (*changes)(sqlite3*); + int (*close)(sqlite3*); + int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,int eTextRep,const char*)); + int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,int eTextRep,const void*)); + const void * (*column_blob)(sqlite3_stmt*,int iCol); + int (*column_bytes)(sqlite3_stmt*,int iCol); + int (*column_bytes16)(sqlite3_stmt*,int iCol); + int (*column_count)(sqlite3_stmt*pStmt); + const char * (*column_database_name)(sqlite3_stmt*,int); + const void * (*column_database_name16)(sqlite3_stmt*,int); + const char * (*column_decltype)(sqlite3_stmt*,int i); + const void * (*column_decltype16)(sqlite3_stmt*,int); + double (*column_double)(sqlite3_stmt*,int iCol); + int (*column_int)(sqlite3_stmt*,int iCol); + sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol); + const char * (*column_name)(sqlite3_stmt*,int); + const void * (*column_name16)(sqlite3_stmt*,int); + const char * (*column_origin_name)(sqlite3_stmt*,int); + const void * (*column_origin_name16)(sqlite3_stmt*,int); + const char * (*column_table_name)(sqlite3_stmt*,int); + const void * (*column_table_name16)(sqlite3_stmt*,int); + const unsigned char * (*column_text)(sqlite3_stmt*,int iCol); + const void * (*column_text16)(sqlite3_stmt*,int iCol); + int (*column_type)(sqlite3_stmt*,int iCol); + sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol); + void * (*commit_hook)(sqlite3*,int(*)(void*),void*); + int (*complete)(const char*sql); + int (*complete16)(const void*sql); + int (*create_collation)(sqlite3*,const char*,int,void*,int(*)(void*,int,const void*,int,const void*)); + int (*create_collation16)(sqlite3*,const void*,int,void*,int(*)(void*,int,const void*,int,const void*)); + int (*create_function)(sqlite3*,const char*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*)); + int (*create_function16)(sqlite3*,const void*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*)); + int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*); + int (*data_count)(sqlite3_stmt*pStmt); + sqlite3 * (*db_handle)(sqlite3_stmt*); + int (*declare_vtab)(sqlite3*,const char*); + int (*enable_shared_cache)(int); + int (*errcode)(sqlite3*db); + const char * (*errmsg)(sqlite3*); + const void * (*errmsg16)(sqlite3*); + int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**); + int (*expired)(sqlite3_stmt*); + int (*finalize)(sqlite3_stmt*pStmt); + void (*free)(void*); + void (*free_table)(char**result); + int (*get_autocommit)(sqlite3*); + void * (*get_auxdata)(sqlite3_context*,int); + int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**); + int (*global_recover)(void); + void (*interruptx)(sqlite3*); + sqlite_int64 (*last_insert_rowid)(sqlite3*); + const char * (*libversion)(void); + int (*libversion_number)(void); + void *(*malloc)(int); + char * (*mprintf)(const char*,...); + int (*open)(const char*,sqlite3**); + int (*open16)(const void*,sqlite3**); + int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**); + int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**); + void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*); + void (*progress_handler)(sqlite3*,int,int(*)(void*),void*); + void *(*realloc)(void*,int); + int (*reset)(sqlite3_stmt*pStmt); + void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*)); + void (*result_double)(sqlite3_context*,double); + void (*result_error)(sqlite3_context*,const char*,int); + void (*result_error16)(sqlite3_context*,const void*,int); + void (*result_int)(sqlite3_context*,int); + void (*result_int64)(sqlite3_context*,sqlite_int64); + void (*result_null)(sqlite3_context*); + void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*)); + void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*)); + void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*)); + void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*)); + void (*result_value)(sqlite3_context*,sqlite3_value*); + void * (*rollback_hook)(sqlite3*,void(*)(void*),void*); + int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,const char*,const char*),void*); + void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*)); + char * (*snprintf)(int,char*,const char*,...); + int (*step)(sqlite3_stmt*); + int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,char const**,char const**,int*,int*,int*); + void (*thread_cleanup)(void); + int (*total_changes)(sqlite3*); + void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*); + int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*); + void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,sqlite_int64),void*); + void * (*user_data)(sqlite3_context*); + const void * (*value_blob)(sqlite3_value*); + int (*value_bytes)(sqlite3_value*); + int (*value_bytes16)(sqlite3_value*); + double (*value_double)(sqlite3_value*); + int (*value_int)(sqlite3_value*); + sqlite_int64 (*value_int64)(sqlite3_value*); + int (*value_numeric_type)(sqlite3_value*); + const unsigned char * (*value_text)(sqlite3_value*); + const void * (*value_text16)(sqlite3_value*); + const void * (*value_text16be)(sqlite3_value*); + const void * (*value_text16le)(sqlite3_value*); + int (*value_type)(sqlite3_value*); + char *(*vmprintf)(const char*,va_list); + /* Added ??? */ + int (*overload_function)(sqlite3*, const char *zFuncName, int nArg); + /* Added by 3.3.13 */ + int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**); + int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**); + int (*clear_bindings)(sqlite3_stmt*); + /* Added by 3.4.1 */ + int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,void (*xDestroy)(void *)); + /* Added by 3.5.0 */ + int (*bind_zeroblob)(sqlite3_stmt*,int,int); + int (*blob_bytes)(sqlite3_blob*); + int (*blob_close)(sqlite3_blob*); + int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,int,sqlite3_blob**); + int (*blob_read)(sqlite3_blob*,void*,int,int); + int (*blob_write)(sqlite3_blob*,const void*,int,int); + int (*create_collation_v2)(sqlite3*,const char*,int,void*,int(*)(void*,int,const void*,int,const void*),void(*)(void*)); + int (*file_control)(sqlite3*,const char*,int,void*); + sqlite3_int64 (*memory_highwater)(int); + sqlite3_int64 (*memory_used)(void); + sqlite3_mutex *(*mutex_alloc)(int); + void (*mutex_enter)(sqlite3_mutex*); + void (*mutex_free)(sqlite3_mutex*); + void (*mutex_leave)(sqlite3_mutex*); + int (*mutex_try)(sqlite3_mutex*); + int (*open_v2)(const char*,sqlite3**,int,const char*); + int (*release_memory)(int); + void (*result_error_nomem)(sqlite3_context*); + void (*result_error_toobig)(sqlite3_context*); + int (*sleep)(int); + void (*soft_heap_limit)(int); + sqlite3_vfs *(*vfs_find)(const char*); + int (*vfs_register)(sqlite3_vfs*,int); + int (*vfs_unregister)(sqlite3_vfs*); + int (*xthreadsafe)(void); + void (*result_zeroblob)(sqlite3_context*,int); + void (*result_error_code)(sqlite3_context*,int); + int (*test_control)(int, ...); + void (*randomness)(int,void*); + sqlite3 *(*context_db_handle)(sqlite3_context*); + int (*extended_result_codes)(sqlite3*,int); + int (*limit)(sqlite3*,int,int); + sqlite3_stmt *(*next_stmt)(sqlite3*,sqlite3_stmt*); + const char *(*sql)(sqlite3_stmt*); + int (*status)(int,int*,int*,int); +}; + +/* +** The following macros redefine the API routines so that they are +** redirected throught the global sqlite3_api structure. +** +** This header file is also used by the loadext.c source file +** (part of the main SQLite library - not an extension) so that +** it can get access to the sqlite3_api_routines structure +** definition. But the main library does not want to redefine +** the API. So the redefinition macros are only valid if the +** SQLITE_CORE macros is undefined. +*/ +#ifndef SQLITE_CORE +#define sqlite3_aggregate_context sqlite3_api->aggregate_context +#define sqlite3_aggregate_count sqlite3_api->aggregate_count +#define sqlite3_bind_blob sqlite3_api->bind_blob +#define sqlite3_bind_double sqlite3_api->bind_double +#define sqlite3_bind_int sqlite3_api->bind_int +#define sqlite3_bind_int64 sqlite3_api->bind_int64 +#define sqlite3_bind_null sqlite3_api->bind_null +#define sqlite3_bind_parameter_count sqlite3_api->bind_parameter_count +#define sqlite3_bind_parameter_index sqlite3_api->bind_parameter_index +#define sqlite3_bind_parameter_name sqlite3_api->bind_parameter_name +#define sqlite3_bind_text sqlite3_api->bind_text +#define sqlite3_bind_text16 sqlite3_api->bind_text16 +#define sqlite3_bind_value sqlite3_api->bind_value +#define sqlite3_busy_handler sqlite3_api->busy_handler +#define sqlite3_busy_timeout sqlite3_api->busy_timeout +#define sqlite3_changes sqlite3_api->changes +#define sqlite3_close sqlite3_api->close +#define sqlite3_collation_needed sqlite3_api->collation_needed +#define sqlite3_collation_needed16 sqlite3_api->collation_needed16 +#define sqlite3_column_blob sqlite3_api->column_blob +#define sqlite3_column_bytes sqlite3_api->column_bytes +#define sqlite3_column_bytes16 sqlite3_api->column_bytes16 +#define sqlite3_column_count sqlite3_api->column_count +#define sqlite3_column_database_name sqlite3_api->column_database_name +#define sqlite3_column_database_name16 sqlite3_api->column_database_name16 +#define sqlite3_column_decltype sqlite3_api->column_decltype +#define sqlite3_column_decltype16 sqlite3_api->column_decltype16 +#define sqlite3_column_double sqlite3_api->column_double +#define sqlite3_column_int sqlite3_api->column_int +#define sqlite3_column_int64 sqlite3_api->column_int64 +#define sqlite3_column_name sqlite3_api->column_name +#define sqlite3_column_name16 sqlite3_api->column_name16 +#define sqlite3_column_origin_name sqlite3_api->column_origin_name +#define sqlite3_column_origin_name16 sqlite3_api->column_origin_name16 +#define sqlite3_column_table_name sqlite3_api->column_table_name +#define sqlite3_column_table_name16 sqlite3_api->column_table_name16 +#define sqlite3_column_text sqlite3_api->column_text +#define sqlite3_column_text16 sqlite3_api->column_text16 +#define sqlite3_column_type sqlite3_api->column_type +#define sqlite3_column_value sqlite3_api->column_value +#define sqlite3_commit_hook sqlite3_api->commit_hook +#define sqlite3_complete sqlite3_api->complete +#define sqlite3_complete16 sqlite3_api->complete16 +#define sqlite3_create_collation sqlite3_api->create_collation +#define sqlite3_create_collation16 sqlite3_api->create_collation16 +#define sqlite3_create_function sqlite3_api->create_function +#define sqlite3_create_function16 sqlite3_api->create_function16 +#define sqlite3_create_module sqlite3_api->create_module +#define sqlite3_create_module_v2 sqlite3_api->create_module_v2 +#define sqlite3_data_count sqlite3_api->data_count +#define sqlite3_db_handle sqlite3_api->db_handle +#define sqlite3_declare_vtab sqlite3_api->declare_vtab +#define sqlite3_enable_shared_cache sqlite3_api->enable_shared_cache +#define sqlite3_errcode sqlite3_api->errcode +#define sqlite3_errmsg sqlite3_api->errmsg +#define sqlite3_errmsg16 sqlite3_api->errmsg16 +#define sqlite3_exec sqlite3_api->exec +#define sqlite3_expired sqlite3_api->expired +#define sqlite3_finalize sqlite3_api->finalize +#define sqlite3_free sqlite3_api->free +#define sqlite3_free_table sqlite3_api->free_table +#define sqlite3_get_autocommit sqlite3_api->get_autocommit +#define sqlite3_get_auxdata sqlite3_api->get_auxdata +#define sqlite3_get_table sqlite3_api->get_table +#define sqlite3_global_recover sqlite3_api->global_recover +#define sqlite3_interrupt sqlite3_api->interruptx +#define sqlite3_last_insert_rowid sqlite3_api->last_insert_rowid +#define sqlite3_libversion sqlite3_api->libversion +#define sqlite3_libversion_number sqlite3_api->libversion_number +#define sqlite3_malloc sqlite3_api->malloc +#define sqlite3_mprintf sqlite3_api->mprintf +#define sqlite3_open sqlite3_api->open +#define sqlite3_open16 sqlite3_api->open16 +#define sqlite3_prepare sqlite3_api->prepare +#define sqlite3_prepare16 sqlite3_api->prepare16 +#define sqlite3_prepare_v2 sqlite3_api->prepare_v2 +#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 +#define sqlite3_profile sqlite3_api->profile +#define sqlite3_progress_handler sqlite3_api->progress_handler +#define sqlite3_realloc sqlite3_api->realloc +#define sqlite3_reset sqlite3_api->reset +#define sqlite3_result_blob sqlite3_api->result_blob +#define sqlite3_result_double sqlite3_api->result_double +#define sqlite3_result_error sqlite3_api->result_error +#define sqlite3_result_error16 sqlite3_api->result_error16 +#define sqlite3_result_int sqlite3_api->result_int +#define sqlite3_result_int64 sqlite3_api->result_int64 +#define sqlite3_result_null sqlite3_api->result_null +#define sqlite3_result_text sqlite3_api->result_text +#define sqlite3_result_text16 sqlite3_api->result_text16 +#define sqlite3_result_text16be sqlite3_api->result_text16be +#define sqlite3_result_text16le sqlite3_api->result_text16le +#define sqlite3_result_value sqlite3_api->result_value +#define sqlite3_rollback_hook sqlite3_api->rollback_hook +#define sqlite3_set_authorizer sqlite3_api->set_authorizer +#define sqlite3_set_auxdata sqlite3_api->set_auxdata +#define sqlite3_snprintf sqlite3_api->snprintf +#define sqlite3_step sqlite3_api->step +#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata +#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup +#define sqlite3_total_changes sqlite3_api->total_changes +#define sqlite3_trace sqlite3_api->trace +#define sqlite3_transfer_bindings sqlite3_api->transfer_bindings +#define sqlite3_update_hook sqlite3_api->update_hook +#define sqlite3_user_data sqlite3_api->user_data +#define sqlite3_value_blob sqlite3_api->value_blob +#define sqlite3_value_bytes sqlite3_api->value_bytes +#define sqlite3_value_bytes16 sqlite3_api->value_bytes16 +#define sqlite3_value_double sqlite3_api->value_double +#define sqlite3_value_int sqlite3_api->value_int +#define sqlite3_value_int64 sqlite3_api->value_int64 +#define sqlite3_value_numeric_type sqlite3_api->value_numeric_type +#define sqlite3_value_text sqlite3_api->value_text +#define sqlite3_value_text16 sqlite3_api->value_text16 +#define sqlite3_value_text16be sqlite3_api->value_text16be +#define sqlite3_value_text16le sqlite3_api->value_text16le +#define sqlite3_value_type sqlite3_api->value_type +#define sqlite3_vmprintf sqlite3_api->vmprintf +#define sqlite3_overload_function sqlite3_api->overload_function +#define sqlite3_prepare_v2 sqlite3_api->prepare_v2 +#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 +#define sqlite3_clear_bindings sqlite3_api->clear_bindings +#define sqlite3_bind_zeroblob sqlite3_api->bind_zeroblob +#define sqlite3_blob_bytes sqlite3_api->blob_bytes +#define sqlite3_blob_close sqlite3_api->blob_close +#define sqlite3_blob_open sqlite3_api->blob_open +#define sqlite3_blob_read sqlite3_api->blob_read +#define sqlite3_blob_write sqlite3_api->blob_write +#define sqlite3_create_collation_v2 sqlite3_api->create_collation_v2 +#define sqlite3_file_control sqlite3_api->file_control +#define sqlite3_memory_highwater sqlite3_api->memory_highwater +#define sqlite3_memory_used sqlite3_api->memory_used +#define sqlite3_mutex_alloc sqlite3_api->mutex_alloc +#define sqlite3_mutex_enter sqlite3_api->mutex_enter +#define sqlite3_mutex_free sqlite3_api->mutex_free +#define sqlite3_mutex_leave sqlite3_api->mutex_leave +#define sqlite3_mutex_try sqlite3_api->mutex_try +#define sqlite3_open_v2 sqlite3_api->open_v2 +#define sqlite3_release_memory sqlite3_api->release_memory +#define sqlite3_result_error_nomem sqlite3_api->result_error_nomem +#define sqlite3_result_error_toobig sqlite3_api->result_error_toobig +#define sqlite3_sleep sqlite3_api->sleep +#define sqlite3_soft_heap_limit sqlite3_api->soft_heap_limit +#define sqlite3_vfs_find sqlite3_api->vfs_find +#define sqlite3_vfs_register sqlite3_api->vfs_register +#define sqlite3_vfs_unregister sqlite3_api->vfs_unregister +#define sqlite3_threadsafe sqlite3_api->xthreadsafe +#define sqlite3_result_zeroblob sqlite3_api->result_zeroblob +#define sqlite3_result_error_code sqlite3_api->result_error_code +#define sqlite3_test_control sqlite3_api->test_control +#define sqlite3_randomness sqlite3_api->randomness +#define sqlite3_context_db_handle sqlite3_api->context_db_handle +#define sqlite3_extended_result_codes sqlite3_api->extended_result_codes +#define sqlite3_limit sqlite3_api->limit +#define sqlite3_next_stmt sqlite3_api->next_stmt +#define sqlite3_sql sqlite3_api->sql +#define sqlite3_status sqlite3_api->status + +#define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api = 0; +#define SQLITE_EXTENSION_INIT2(v) sqlite3_api = v; + +#else + +#define SQLITE_EXTENSION_INIT1 +#define SQLITE_EXTENSION_INIT2(v) + +#endif /* SQLITE_CORE */ + +#endif /* _SQLITE3EXT_H_ */ diff --git a/third_party/sqlite/src/sqliteInt.h b/third_party/sqlite/src/sqliteInt.h new file mode 100755 index 0000000..68de4a1 --- /dev/null +++ b/third_party/sqlite/src/sqliteInt.h @@ -0,0 +1,2357 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** Internal interface definitions for SQLite. +** +** @(#) $Id: sqliteInt.h,v 1.752 2008/08/04 20:13:27 drh Exp $ +*/ +#ifndef _SQLITEINT_H_ +#define _SQLITEINT_H_ + +/* +** Include the configuration header output by 'configure' if we're using the +** autoconf-based build +*/ +#ifdef _HAVE_SQLITE_CONFIG_H +#include "config.h" +#endif + +#include "sqliteLimit.h" + +/* Disable nuisance warnings on Borland compilers */ +#if defined(__BORLANDC__) +#pragma warn -rch /* unreachable code */ +#pragma warn -ccc /* Condition is always true or false */ +#pragma warn -aus /* Assigned value is never used */ +#pragma warn -csu /* Comparing signed and unsigned */ +#pragma warn -spa /* Suspicous pointer arithmetic */ +#endif + +/* Needed for various definitions... */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + +/* +** Include standard header files as necessary +*/ +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#endif + +/* +** A macro used to aid in coverage testing. When doing coverage +** testing, the condition inside the argument must be evaluated +** both true and false in order to get full branch coverage. +** This macro can be inserted to ensure adequate test coverage +** in places where simple condition/decision coverage is inadequate. +*/ +#ifdef SQLITE_COVERAGE_TEST + void sqlite3Coverage(int); +# define testcase(X) if( X ){ sqlite3Coverage(__LINE__); } +#else +# define testcase(X) +#endif + +/* +** The ALWAYS and NEVER macros surround boolean expressions which +** are intended to always be true or false, respectively. Such +** expressions could be omitted from the code completely. But they +** are included in a few cases in order to enhance the resilience +** of SQLite to unexpected behavior - to make the code "self-healing" +** or "ductile" rather than being "brittle" and crashing at the first +** hint of unplanned behavior. +** +** When doing coverage testing ALWAYS and NEVER are hard-coded to +** be true and false so that the unreachable code then specify will +** not be counted as untested code. +*/ +#ifdef SQLITE_COVERAGE_TEST +# define ALWAYS(X) (1) +# define NEVER(X) (0) +#else +# define ALWAYS(X) (X) +# define NEVER(X) (X) +#endif + +/* +** The macro unlikely() is a hint that surrounds a boolean +** expression that is usually false. Macro likely() surrounds +** a boolean expression that is usually true. GCC is able to +** use these hints to generate better code, sometimes. +*/ +#if defined(__GNUC__) && 0 +# define likely(X) __builtin_expect((X),1) +# define unlikely(X) __builtin_expect((X),0) +#else +# define likely(X) !!(X) +# define unlikely(X) !!(X) +#endif + +/* + * This macro is used to "hide" some ugliness in casting an int + * value to a ptr value under the MSVC 64-bit compiler. Casting + * non 64-bit values to ptr types results in a "hard" error with + * the MSVC 64-bit compiler which this attempts to avoid. + * + * A simple compiler pragma or casting sequence could not be found + * to correct this in all situations, so this macro was introduced. + * + * It could be argued that the intptr_t type could be used in this + * case, but that type is not available on all compilers, or + * requires the #include of specific headers which differs between + * platforms. + */ +#define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X]) +#define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0)) + +/* +** These #defines should enable >2GB file support on Posix if the +** underlying operating system supports it. If the OS lacks +** large file support, or if the OS is windows, these should be no-ops. +** +** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any +** system #includes. Hence, this block of code must be the very first +** code in all source files. +** +** 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. +** +** Similar is true for MacOS. LFS is only supported on MacOS 9 and later. +*/ +#ifndef SQLITE_DISABLE_LFS +# define _LARGE_FILE 1 +# ifndef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 +# endif +# define _LARGEFILE_SOURCE 1 +#endif + + +/* +** The SQLITE_THREADSAFE macro must be defined as either 0 or 1. +** Older versions of SQLite used an optional THREADSAFE macro. +** We support that for legacy +*/ +#if !defined(SQLITE_THREADSAFE) +#if defined(THREADSAFE) +# define SQLITE_THREADSAFE THREADSAFE +#else +# define SQLITE_THREADSAFE 1 +#endif +#endif + +/* +** Exactly one of the following macros must be defined in order to +** specify which memory allocation subsystem to use. +** +** SQLITE_SYSTEM_MALLOC // Use normal system malloc() +** SQLITE_MEMDEBUG // Debugging version of system malloc() +** SQLITE_MEMORY_SIZE // internal allocator #1 +** SQLITE_MMAP_HEAP_SIZE // internal mmap() allocator +** SQLITE_POW2_MEMORY_SIZE // internal power-of-two allocator +** +** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as +** the default. +*/ +#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+\ + defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+\ + defined(SQLITE_POW2_MEMORY_SIZE)>1 +# error "At most one of the following compile-time configuration options\ + is allows: SQLITE_SYSTEM_MALLOC, SQLITE_MEMDEBUG, SQLITE_MEMORY_SIZE,\ + SQLITE_MMAP_HEAP_SIZE, SQLITE_POW2_MEMORY_SIZE" +#endif +#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+\ + defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+\ + defined(SQLITE_POW2_MEMORY_SIZE)==0 +# define SQLITE_SYSTEM_MALLOC 1 +#endif + +/* +** If SQLITE_MALLOC_SOFT_LIMIT is defined, then try to keep the +** sizes of memory allocations below this value where possible. +*/ +#if defined(SQLITE_POW2_MEMORY_SIZE) && !defined(SQLITE_MALLOC_SOFT_LIMIT) +# define SQLITE_MALLOC_SOFT_LIMIT 1024 +#endif + +/* +** We need to define _XOPEN_SOURCE as follows in order to enable +** recursive mutexes on most unix systems. But Mac OS X is different. +** The _XOPEN_SOURCE define causes problems for Mac OS X we are told, +** so it is omitted there. See ticket #2673. +** +** Later we learn that _XOPEN_SOURCE is poorly or incorrectly +** implemented on some systems. So we avoid defining it at all +** if it is already defined or if it is unneeded because we are +** not doing a threadsafe build. Ticket #2681. +** +** See also ticket #2741. +*/ +#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) && !defined(__APPLE__) && SQLITE_THREADSAFE +# define _XOPEN_SOURCE 500 /* Needed to enable pthread recursive mutexes */ +#endif + +#if defined(SQLITE_TCL) || defined(TCLSH) +# include <tcl.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 +** lines are added to automatically set NDEBUG unless the -DSQLITE_DEBUG=1 +** option is set. Thus NDEBUG becomes an opt-in rather than an opt-out +** feature. +*/ +#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) +# define NDEBUG 1 +#endif + +#include "sqlite3.h" +#include "hash.h" +#include "parse.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <stddef.h> + +/* +** 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 +# undef SQLITE_MIXED_ENDIAN_64BIT_FLOAT +#endif +#ifndef SQLITE_BIG_DBL +# define SQLITE_BIG_DBL (1e99) +#endif + +/* +** OMIT_TEMPDB is set to 1 if SQLITE_OMIT_TEMPDB is defined, or 0 +** afterward. Having this macro allows us to cause the C compiler +** to omit code used by TEMP tables without messy #ifndef statements. +*/ +#ifdef SQLITE_OMIT_TEMPDB +#define OMIT_TEMPDB 1 +#else +#define OMIT_TEMPDB 0 +#endif + +/* +** If the following macro is set to 1, then NULL values are considered +** distinct when determining whether or not two entries are the same +** in a UNIQUE index. This is the way PostgreSQL, Oracle, DB2, MySQL, +** OCELOT, and Firebird all work. The SQL92 spec explicitly says this +** is the way things are suppose to work. +** +** If the following macro is set to 0, the NULLs are indistinct for +** a UNIQUE index. In this mode, you can only have a single NULL entry +** for a column declared UNIQUE. This is the way Informix and SQL Server +** work. +*/ +#define NULL_DISTINCT_FOR_UNIQUE 1 + +/* +** 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_MAX_FILE_FORMAT 4 +#ifndef SQLITE_DEFAULT_FILE_FORMAT +# define SQLITE_DEFAULT_FILE_FORMAT 1 +#endif + +/* +** Provide a default value for SQLITE_TEMP_STORE in case it is not specified +** on the command-line +*/ +#ifndef SQLITE_TEMP_STORE +# define SQLITE_TEMP_STORE 1 +#endif + +/* +** GCC does not define the offsetof() macro so we'll have to do it +** ourselves. +*/ +#ifndef offsetof +#define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD)) +#endif + +/* +** Check to see if this machine uses EBCDIC. (Yes, believe it or +** not, there are still machines out there that use EBCDIC.) +*/ +#if 'A' == '\301' +# define SQLITE_EBCDIC 1 +#else +# define SQLITE_ASCII 1 +#endif + +/* +** Integers of known sizes. These typedefs might change for architectures +** where the sizes very. Preprocessor macros are available so that the +** types can be conveniently redefined at compile-type. Like this: +** +** cc '-DUINTPTR_TYPE=long long int' ... +*/ +#ifndef UINT32_TYPE +# ifdef HAVE_UINT32_T +# define UINT32_TYPE uint32_t +# else +# define UINT32_TYPE unsigned int +# endif +#endif +#ifndef UINT16_TYPE +# ifdef HAVE_UINT16_T +# define UINT16_TYPE uint16_t +# else +# define UINT16_TYPE unsigned short int +# endif +#endif +#ifndef INT16_TYPE +# ifdef HAVE_INT16_T +# define INT16_TYPE int16_t +# else +# define INT16_TYPE short int +# endif +#endif +#ifndef UINT8_TYPE +# ifdef HAVE_UINT8_T +# define UINT8_TYPE uint8_t +# else +# define UINT8_TYPE unsigned char +# endif +#endif +#ifndef INT8_TYPE +# ifdef HAVE_INT8_T +# define INT8_TYPE int8_t +# else +# define INT8_TYPE signed char +# endif +#endif +#ifndef LONGDOUBLE_TYPE +# define LONGDOUBLE_TYPE long double +#endif +typedef sqlite_int64 i64; /* 8-byte signed integer */ +typedef sqlite_uint64 u64; /* 8-byte unsigned integer */ +typedef UINT32_TYPE u32; /* 4-byte unsigned integer */ +typedef UINT16_TYPE u16; /* 2-byte unsigned integer */ +typedef INT16_TYPE i16; /* 2-byte signed integer */ +typedef UINT8_TYPE u8; /* 1-byte unsigned integer */ +typedef UINT8_TYPE i8; /* 1-byte signed integer */ + +/* +** Macros to determine whether the machine is big or little endian, +** evaluated at runtime. +*/ +#ifdef SQLITE_AMALGAMATION +const int sqlite3one; +#else +extern const int sqlite3one; +#endif +#if defined(i386) || defined(__i386__) || defined(_M_IX86) +# define SQLITE_BIGENDIAN 0 +# define SQLITE_LITTLEENDIAN 1 +# define SQLITE_UTF16NATIVE SQLITE_UTF16LE +#else +# define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0) +# define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1) +# define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE) +#endif + +/* +** Constants for the largest and smallest possible 64-bit signed integers. +** These macros are designed to work correctly on both 32-bit and 64-bit +** compilers. +*/ +#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32)) +#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64) + +/* +** An instance of the following structure is used to store the busy-handler +** callback for a given sqlite handle. +** +** The sqlite.busyHandler member of the sqlite struct contains the busy +** callback for the database handle. Each pager opened via the sqlite +** handle is passed a pointer to sqlite.busyHandler. The busy-handler +** callback is currently invoked only from within pager.c. +*/ +typedef struct BusyHandler BusyHandler; +struct BusyHandler { + int (*xFunc)(void *,int); /* The busy callback */ + void *pArg; /* First arg to busy callback */ + int nBusy; /* Incremented with each busy call */ +}; + +/* +** Name of the master database table. The master database table +** is a special table that holds the names and attributes of all +** user tables and indices. +*/ +#define MASTER_NAME "sqlite_master" +#define TEMP_MASTER_NAME "sqlite_temp_master" + +/* +** The root-page of the master database table. +*/ +#define MASTER_ROOT 1 + +/* +** The name of the schema table. +*/ +#define SCHEMA_TABLE(x) ((!OMIT_TEMPDB)&&(x==1)?TEMP_MASTER_NAME:MASTER_NAME) + +/* +** A convenience macro that returns the number of elements in +** an array. +*/ +#define ArraySize(X) (sizeof(X)/sizeof(X[0])) + +/* +** The following value as a destructor means to use sqlite3DbFree(). +** This is an internal extension to SQLITE_STATIC and SQLITE_TRANSIENT. +*/ +#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3DbFree) + +/* +** Forward references to structures +*/ +typedef struct AggInfo AggInfo; +typedef struct AuthContext AuthContext; +typedef struct Bitvec Bitvec; +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; +typedef struct FuncDef FuncDef; +typedef struct IdList IdList; +typedef struct Index Index; +typedef struct KeyClass KeyClass; +typedef struct KeyInfo KeyInfo; +typedef struct Lookaside Lookaside; +typedef struct LookasideSlot LookasideSlot; +typedef struct Module Module; +typedef struct NameContext NameContext; +typedef struct Parse Parse; +typedef struct Select Select; +typedef struct SrcList SrcList; +typedef struct StrAccum StrAccum; +typedef struct Table Table; +typedef struct TableLock TableLock; +typedef struct Token Token; +typedef struct TriggerStack TriggerStack; +typedef struct TriggerStep TriggerStep; +typedef struct Trigger Trigger; +typedef struct WhereInfo WhereInfo; +typedef struct WhereLevel WhereLevel; + +/* +** Defer sourcing vdbe.h and btree.h until after the "u8" and +** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque +** pointer types (i.e. FuncDef) defined above. +*/ +#include "btree.h" +#include "vdbe.h" +#include "pager.h" + +#include "os.h" +#include "mutex.h" + + +/* +** Each database file to be accessed by the system is an instance +** of the following structure. There are normally two of these structures +** in the sqlite.aDb[] array. aDb[0] is the main database file and +** aDb[1] is the database file used to hold temporary tables. Additional +** databases may be attached. +*/ +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. +** +** If there are no virtual tables configured in this schema, the +** Schema.db variable is set to NULL. After the first virtual table +** has been added, it is set to point to the database connection +** used to create the connection. Once a virtual table has been +** added to the Schema structure and the Schema.db variable populated, +** only that database connection may use the Schema to prepare +** statements. +*/ +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 */ + Table *pSeqTab; /* The sqlite_sequence table used by AUTOINCREMENT */ + 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 */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + sqlite3 *db; /* "Owner" connection. See comment above */ +#endif +}; + +/* +** These macros can be used to test, set, or clear bits in the +** Db.flags field. +*/ +#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. +** +** The DB_SchemaLoaded flag is set after the database schema has been +** read into internal hash tables. +** +** DB_UnresetViews means that one or more views have column names that +** have been filled out. If the schema changes, these column names might +** changes and so the view will need to be reset. +*/ +#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) */ + +/* +** The number of different kinds of things that can be limited +** using the sqlite3_limit() interface. +*/ +#define SQLITE_N_LIMIT (SQLITE_LIMIT_VARIABLE_NUMBER+1) + +/* +** Lookaside malloc is a set of fixed-size buffers that can be used +** to satisify small transient memory allocation requests for objects +** associated with a particular database connection. The use of +** lookaside malloc provides a significant performance enhancement +** (approx 10%) by avoiding numerous malloc/free requests while parsing +** SQL statements. +** +** The Lookaside structure holds configuration information about the +** lookaside malloc subsystem. Each available memory allocation in +** the lookaside subsystem is stored on a linked list of LookasideSlot +** objects. +*/ +struct Lookaside { + u16 sz; /* Size of each buffer in bytes */ + u8 bEnabled; /* True if use lookaside. False to ignore it */ + u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */ + int nOut; /* Number of buffers currently checked out */ + int mxOut; /* Highwater mark for nOut */ + LookasideSlot *pFree; /* List if available buffers */ + void *pStart; /* First byte of available memory space */ + void *pEnd; /* First byte past end of available space */ +}; +struct LookasideSlot { + LookasideSlot *pNext; /* Next buffer in the list of free buffers */ +}; + +/* +** Each database is an instance of the following structure. +** +** The sqlite.lastRowid records the last insert rowid generated by an +** insert statement. Inserts on views do not affect its value. Each +** trigger has its own context, so that lastRowid can be updated inside +** triggers as usual. The previous value will be restored once the trigger +** exits. Upon entering a before or instead of trigger, lastRowid is no +** longer (since after version 2.8.12) reset to -1. +** +** The sqlite.nChange does not count changes within triggers and keeps no +** context. It is reset at start of sqlite3_exec. +** The sqlite.lsChange represents the number of changes made by the last +** insert, update, or delete statement. It remains constant throughout the +** length of a statement and is then updated by OP_SetCounts. It keeps a +** context stack just like lastRowid so that the count of changes +** within a trigger is not seen outside the trigger. Changes to views do not +** affect the value of lsChange. +** The sqlite.csChange keeps track of the number of current changes (since +** the last statement) and is used to update sqlite_lsChange. +** +** The member variables sqlite.errCode, sqlite.zErrMsg and sqlite.zErrMsg16 +** store the most recent error code and, if applicable, string. The +** internal function sqlite3Error() is used to set these variables +** consistently. +*/ +struct sqlite3 { + sqlite3_vfs *pVfs; /* OS Interface */ + int nDb; /* Number of backends currently in use */ + Db *aDb; /* All backends */ + int flags; /* Miscellanous flags. See below */ + int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */ + int errCode; /* Most recent error code (SQLITE_*) */ + int errMask; /* & result codes with this before returning */ + u8 autoCommit; /* The auto-commit flag. */ + u8 temp_store; /* 1: file 2: memory 0: default */ + u8 mallocFailed; /* True if we have seen a malloc failure */ + u8 dfltLockMode; /* Default locking-mode for attached dbs */ + u8 dfltJournalMode; /* Default journal mode for attached dbs */ + signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ + int nextPagesize; /* Pagesize after VACUUM if >0 */ + int nTable; /* Number of tables in the database */ + CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ + i64 lastRowid; /* ROWID of most recent insert (see above) */ + i64 priorNewRowid; /* Last randomly generated ROWID */ + int magic; /* Magic number for detect library misuse */ + int nChange; /* Value returned by sqlite3_changes() */ + int nTotalChange; /* Value returned by sqlite3_total_changes() */ + sqlite3_mutex *mutex; /* Connection mutex */ + int aLimit[SQLITE_N_LIMIT]; /* Limits */ + struct sqlite3InitInfo { /* Information used during initialization */ + int iDb; /* When back is being initialized */ + int newTnum; /* Rootpage of table being initialized */ + u8 busy; /* TRUE if currently initializing */ + } init; + int nExtension; /* Number of loaded extensions */ + void **aExtension; /* Array of shared libraray handles */ + struct Vdbe *pVdbe; /* List of active virtual machines */ + int activeVdbeCnt; /* Number of vdbes currently executing */ + void (*xTrace)(void*,const char*); /* Trace function */ + 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 *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 *pErr; /* Most recent error message */ + char *zErrMsg; /* Most recent error message (UTF-8 encoded) */ + char *zErrMsg16; /* Most recent error message (UTF-16 encoded) */ + union { + int isInterrupted; /* True if sqlite3_interrupt has been called */ + double notUsed1; /* Spacer */ + } u1; + Lookaside lookaside; /* Lookaside malloc configuration */ +#ifndef SQLITE_OMIT_AUTHORIZATION + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); + /* Access authorization function */ + void *pAuthArg; /* 1st argument to the access auth function */ +#endif +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK + int (*xProgress)(void *); /* The progress callback */ + void *pProgressArg; /* Argument to the progress callback */ + int nProgressOps; /* Number of opcodes for progress callback */ +#endif +#ifndef SQLITE_OMIT_VIRTUALTABLE + Hash aModule; /* populated by sqlite3_create_module() */ + Table *pVTab; /* vtab with active Connect/Create method */ + sqlite3_vtab **aVTrans; /* Virtual tables with open transactions */ + int nVTrans; /* Allocated size of aVTrans */ +#endif + Hash aFunc; /* All functions that can be in SQL exprs */ + Hash aCollSeq; /* All collating sequences */ + BusyHandler busyHandler; /* Busy callback */ + int busyTimeout; /* Busy handler timeout, in msec */ + Db aDbStatic[2]; /* Static space for the 2 default backends */ +#ifdef SQLITE_SSE + sqlite3_stmt *pFetch; /* Used by SSE to fetch stored statements */ +#endif +}; + +/* +** A macro to discover the encoding of a database. +*/ +#define ENC(db) ((db)->aDb[0].pSchema->enc) + +/* +** Possible values for the sqlite.flags and or Db.flags fields. +** +** On sqlite.flags, the SQLITE_InTrans value means that we have +** executed a BEGIN. On Db.flags, SQLITE_InTrans means a statement +** transaction is active on that particular database file. +*/ +#define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ +#define SQLITE_InTrans 0x00000008 /* True if in a transaction */ +#define SQLITE_InternChanges 0x00000010 /* Uncommitted Hash table changes */ +#define SQLITE_FullColNames 0x00000020 /* Show full column names on SELECT */ +#define SQLITE_ShortColNames 0x00000040 /* Show short columns names */ +#define SQLITE_CountRows 0x00000080 /* Count rows changed by INSERT, */ + /* DELETE, or UPDATE and return */ + /* the count using a callback. */ +#define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */ + /* result set is empty */ +#define SQLITE_SqlTrace 0x00000200 /* Debug print SQL as it executes */ +#define SQLITE_VdbeListing 0x00000400 /* Debug listings of VDBE programs */ +#define SQLITE_WriteSchema 0x00000800 /* OK to update SQLITE_MASTER */ +#define SQLITE_NoReadlock 0x00001000 /* Readlocks are omitted when + ** accessing read-only databases */ +#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 */ +#define SQLITE_FullFSync 0x00010000 /* Use full fsync on the backend */ +#define SQLITE_LoadExtension 0x00020000 /* Enable load_extension */ + +#define SQLITE_RecoveryMode 0x00040000 /* Ignore schema errors */ +#define SQLITE_SharedCache 0x00080000 /* Cache sharing is enabled */ +#define SQLITE_Vtab 0x00100000 /* There exists a virtual table */ + +/* +** Possible values for the sqlite.magic field. +** The numbers are obtained at random and have no special meaning, other +** than being distinct from one another. +*/ +#define SQLITE_MAGIC_OPEN 0xa029a697 /* Database is open */ +#define SQLITE_MAGIC_CLOSED 0x9f3c2d33 /* Database is closed */ +#define SQLITE_MAGIC_SICK 0x4b771290 /* Error and awaiting close */ +#define SQLITE_MAGIC_BUSY 0xf03b7906 /* Database currently in use */ +#define SQLITE_MAGIC_ERROR 0xb5357930 /* An SQLITE_MISUSE error occurred */ + +/* +** Each SQL function is defined by an instance of the following +** structure. A pointer to this structure is stored in the sqlite.aFunc +** hash table. When multiple functions have the same name, the hash table +** points to a linked list of these structures. +*/ +struct FuncDef { + i16 nArg; /* Number of arguments. -1 means unlimited */ + u8 iPrefEnc; /* Preferred text encoding (SQLITE_UTF8, 16LE, 16BE) */ + u8 needCollSeq; /* True if sqlite3GetFuncCollSeq() might be called */ + u8 flags; /* Some combination of SQLITE_FUNC_* */ + void *pUserData; /* User data parameter */ + FuncDef *pNext; /* Next function with same name */ + void (*xFunc)(sqlite3_context*,int,sqlite3_value**); /* Regular function */ + void (*xStep)(sqlite3_context*,int,sqlite3_value**); /* Aggregate step */ + void (*xFinalize)(sqlite3_context*); /* Aggregate finializer */ + char zName[1]; /* SQL name of the function. MUST BE LAST */ +}; + +/* +** Each SQLite module (virtual table definition) is defined by an +** instance of the following structure, stored in the sqlite3.aModule +** hash table. +*/ +struct Module { + const sqlite3_module *pModule; /* Callback pointers */ + const char *zName; /* Name passed to create_module() */ + void *pAux; /* pAux passed to create_module() */ + void (*xDestroy)(void *); /* Module destructor function */ +}; + +/* +** Possible values for FuncDef.flags +*/ +#define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */ +#define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */ +#define SQLITE_FUNC_EPHEM 0x04 /* Ephermeral. Delete with VDBE */ + +/* +** information about each column of an SQL table is held in an instance +** of this structure. +*/ +struct Column { + char *zName; /* Name of this column */ + Expr *pDflt; /* Default value of this column */ + char *zType; /* Data type for this column */ + 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 */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + u8 isHidden; /* True if this column is 'hidden' */ +#endif +}; + +/* +** A "Collating Sequence" is defined by an instance of the following +** structure. Conceptually, a collating sequence consists of a name and +** a comparison routine that defines the order of that sequence. +** +** There may two seperate implementations of the collation function, one +** that processes text in UTF-8 encoding (CollSeq.xCmp) and another that +** 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 +** 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. +** CollSeq.pUser16 is the equivalent for the UTF-16 comparison function, +** xCmp16. +** +** If both CollSeq.xCmp and CollSeq.xCmp16 are NULL, it means that the +** collating sequence is undefined. Indices built on an undefined +** collating sequence may not be read or written. +*/ +struct CollSeq { + char *zName; /* Name of the collating sequence, UTF-8 encoded */ + u8 enc; /* Text encoding handled by xCmp() */ + u8 type; /* One of the SQLITE_COLL_... values below */ + void *pUser; /* First argument to xCmp() */ + int (*xCmp)(void*,int, const void*, int, const void*); + void (*xDel)(void*); /* Destructor for pUser */ +}; + +/* +** Allowed values of CollSeq flags: +*/ +#define SQLITE_COLL_BINARY 1 /* The default memcmp() collating sequence */ +#define SQLITE_COLL_NOCASE 2 /* The built-in NOCASE collating sequence */ +#define SQLITE_COLL_REVERSE 3 /* The built-in REVERSE collating sequence */ +#define SQLITE_COLL_USER 0 /* Any other user-defined collating sequence */ + +/* +** A sort order can be either ASC or DESC. +*/ +#define SQLITE_SO_ASC 0 /* Sort in ascending order */ +#define SQLITE_SO_DESC 1 /* Sort in ascending order */ + +/* +** 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 P4 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_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) + +/* +** The SQLITE_AFF_MASK values masks off the significant bits of an +** affinity value. +*/ +#define SQLITE_AFF_MASK 0x67 + +/* +** Additional bit values that can be ORed with an affinity without +** changing the affinity. +*/ +#define SQLITE_JUMPIFNULL 0x08 /* jumps if either operand is NULL */ +#define SQLITE_STOREP2 0x10 /* Store result in reg[P2] rather than jump */ + +/* +** Each SQL table is represented in memory by an instance of the +** following structure. +** +** Table.zName is the name of the table. The case of the original +** CREATE TABLE statement is stored, but case is not significant for +** comparisons. +** +** Table.nCol is the number of columns in this table. Table.aCol is a +** pointer to an array of Column structures, one for each column. +** +** If the table has an INTEGER PRIMARY KEY, then Table.iPKey is the index of +** the column that is that key. Otherwise Table.iPKey is negative. Note +** that the datatype of the PRIMARY KEY must be INTEGER for this field to +** be set. An INTEGER PRIMARY KEY is used as the rowid for each row of +** the table. If a table has no INTEGER PRIMARY KEY, then a random rowid +** is generated for each row of the table. Table.hasPrimKey is true if +** the table has any PRIMARY KEY, INTEGER or otherwise. +** +** Table.tnum is the page number for the root BTree page of the table in the +** database file. If Table.iDb is the index of the database table backend +** in sqlite.aDb[]. 0 is for the main database and 1 is for the file that +** holds temporary tables and indices. If Table.isEphem +** is true, then the table is stored in a file that is automatically deleted +** when the VDBE cursor to the table is closed. In this case Table.tnum +** refers VDBE cursor number that holds the table open, not to the root +** page number. Transient tables are used to hold the results of a +** sub-query that appears instead of a real table name in the FROM clause +** of a SELECT statement. +*/ +struct Table { + sqlite3 *db; /* Associated database connection. Might be NULL. */ + char *zName; /* Name of the table */ + int nCol; /* Number of columns in this table */ + Column *aCol; /* Information about each column */ + int iPKey; /* If not less then 0, use aCol[iPKey] as the primary key */ + Index *pIndex; /* List of SQL indexes on this table. */ + int tnum; /* Root BTree node for this table (see note above) */ + Select *pSelect; /* NULL for tables. Points to definition if a view. */ + int nRef; /* Number of pointers to this 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 + u8 readOnly; /* True if this table should not be written by the user */ + u8 isEphem; /* True if created using OP_OpenEphermeral */ + u8 hasPrimKey; /* True if there exists a primary key */ + u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ + u8 autoInc; /* True if the integer primary key is autoincrement */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + u8 isVirtual; /* True if this is a virtual table */ + u8 isCommit; /* True once the CREATE TABLE has been committed */ + Module *pMod; /* Pointer to the implementation of the module */ + sqlite3_vtab *pVtab; /* Pointer to the module instance */ + int nModuleArg; /* Number of arguments to the module */ + char **azModuleArg; /* Text of all module args. [0] is module name */ +#endif + Schema *pSchema; /* Schema that contains this table */ +}; + +/* +** Test to see whether or not a table is a virtual table. This is +** done as a macro so that it will be optimized out when virtual +** table support is omitted from the build. +*/ +#ifndef SQLITE_OMIT_VIRTUALTABLE +# define IsVirtual(X) ((X)->isVirtual) +# define IsHiddenColumn(X) ((X)->isHidden) +#else +# define IsVirtual(X) 0 +# define IsHiddenColumn(X) 0 +#endif + +/* +** Each foreign key constraint is an instance of the following structure. +** +** A foreign key is associated with two tables. The "from" table is +** the table that contains the REFERENCES clause that creates the foreign +** key. The "to" table is the table that is named in the REFERENCES clause. +** Consider this example: +** +** CREATE TABLE ex1( +** a INTEGER PRIMARY KEY, +** b INTEGER CONSTRAINT fk1 REFERENCES ex2(x) +** ); +** +** For foreign key "fk1", the from-table is "ex1" and the to-table is "ex2". +** +** Each REFERENCES clause generates an instance of the following structure +** which is attached to the from-table. The to-table need not exist when +** the from-table is created. The existance of the to-table is not checked +** until an attempt is made to insert data into the from-table. +** +** The sqlite.aFKey hash table stores pointers to this structure +** given the name of a to-table. For each to-table, all foreign keys +** associated with that table are on a linked list using the FKey.pNextTo +** field. +*/ +struct FKey { + Table *pFrom; /* The table that constains the REFERENCES clause */ + FKey *pNextFrom; /* Next foreign key in pFrom */ + char *zTo; /* Name of table that the key points to */ + FKey *pNextTo; /* Next foreign key that points to zTo */ + int nCol; /* Number of columns in this key */ + struct sColMap { /* Mapping of columns in pFrom to columns in zTo */ + int iFrom; /* Index of column in pFrom */ + char *zCol; /* Name of column in zTo. If 0 use PRIMARY KEY */ + } *aCol; /* One entry for each of nCol column s */ + u8 isDeferred; /* True if constraint checking is deferred till COMMIT */ + u8 updateConf; /* How to resolve conflicts that occur on UPDATE */ + u8 deleteConf; /* How to resolve conflicts that occur on DELETE */ + u8 insertConf; /* How to resolve conflicts that occur on INSERT */ +}; + +/* +** SQLite supports many different ways to resolve a constraint +** error. ROLLBACK processing means that a constraint violation +** causes the operation in process to fail and for the current transaction +** to be rolled back. ABORT processing means the operation in process +** fails and any prior changes from that one operation are backed out, +** but the transaction is not rolled back. FAIL processing means that +** the operation in progress stops and returns an error code. But prior +** changes due to the same operation are not backed out and no rollback +** occurs. IGNORE means that the particular row that caused the constraint +** error is not inserted or updated. Processing continues and no error +** is returned. REPLACE means that preexisting database rows that caused +** a UNIQUE constraint violation are removed so that the new insert or +** update can proceed. Processing continues and no error is reported. +** +** RESTRICT, SETNULL, and CASCADE actions apply only to foreign keys. +** RESTRICT is the same as ABORT for IMMEDIATE foreign keys and the +** same as ROLLBACK for DEFERRED keys. SETNULL means that the foreign +** key is set to NULL. CASCADE means that a DELETE or UPDATE of the +** referenced table row is propagated into the row that holds the +** foreign key. +** +** The following symbolic values are used to record which type +** of action to take. +*/ +#define OE_None 0 /* There is no constraint to check */ +#define OE_Rollback 1 /* Fail the operation and rollback the transaction */ +#define OE_Abort 2 /* Back out changes but do no rollback transaction */ +#define OE_Fail 3 /* Stop the operation but leave all prior changes */ +#define OE_Ignore 4 /* Ignore the error. Do not do the INSERT or UPDATE */ +#define OE_Replace 5 /* Delete existing record, then do INSERT or UPDATE */ + +#define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */ +#define OE_SetNull 7 /* Set the foreign key value to NULL */ +#define OE_SetDflt 8 /* Set the foreign key value to its default */ +#define OE_Cascade 9 /* Cascade the changes */ + +#define OE_Default 99 /* Do whatever the default action is */ + + +/* +** An instance of the following structure is passed as the first +** argument to sqlite3VdbeKeyCompare and is used to control the +** comparison of the two index keys. +** +** If the KeyInfo.incrKey value is true and the comparison would +** otherwise be equal, then return a result as if the second key +** were larger. +*/ +struct KeyInfo { + sqlite3 *db; /* The database connection */ + u8 enc; /* Text encoding - one of the TEXT_Utf* values */ + u8 incrKey; /* Increase 2nd key by epsilon before comparison */ + u8 prefixIsEqual; /* Treat a prefix as equal */ + int nField; /* Number of entries in aColl[] */ + u8 *aSortOrder; /* If defined an aSortOrder[i] is true, sort DESC */ + CollSeq *aColl[1]; /* Collating sequence for each term of the key */ +}; + +/* +** Each SQL index is represented in memory by an +** instance of the following structure. +** +** The columns of the table that are to be indexed are described +** by the aiColumn[] field of this structure. For example, suppose +** we have the following table and index: +** +** CREATE TABLE Ex1(c1 int, c2 int, c3 text); +** CREATE INDEX Ex2 ON Ex1(c3,c1); +** +** In the Table structure describing Ex1, nCol==3 because there are +** three columns in the table. In the Index structure describing +** Ex2, nColumn==2 since 2 of the 3 columns of Ex1 are indexed. +** The value of aiColumn is {2, 0}. aiColumn[0]==2 because the +** first column to be indexed (c3) has an index of 2 in Ex1.aCol[]. +** The second column to be indexed (c1) has an index of 0 in +** Ex1.aCol[], hence Ex2.aiColumn[1]==0. +** +** The Index.onError field determines whether or not the indexed columns +** must be unique and what to do if they are not. When Index.onError=OE_None, +** it means this is not a unique index. Otherwise it is a unique index +** and the value of Index.onError indicate the which conflict resolution +** algorithm to employ whenever an attempt is made to insert a non-unique +** element. +*/ +struct Index { + char *zName; /* Name of this index */ + int nColumn; /* Number of columns in the table used by this index */ + int *aiColumn; /* Which columns are used by this index. 1st is 0 */ + unsigned *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */ + Table *pTable; /* The SQL table being indexed */ + 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) */ + char *zColAff; /* String defining the affinity of each column */ + Index *pNext; /* The next index associated with the same table */ + 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 */ +}; + +/* +** Each token coming out of the lexer is an instance of +** this structure. Tokens are also used as part of an expression. +** +** Note if Token.z==0 then Token.dyn and Token.n are undefined and +** may contain random values. Do not make any assuptions about Token.dyn +** and Token.n when Token.z==0. +*/ +struct Token { + const unsigned char *z; /* Text of the token. Not NULL-terminated! */ + unsigned dyn : 1; /* True for malloced memory, false for static */ + unsigned n : 31; /* Number of characters in this token */ +}; + +/* +** An instance of this structure contains information needed to generate +** code for a SELECT that contains aggregate functions. +** +** If Expr.op==TK_AGG_COLUMN or TK_AGG_FUNCTION then Expr.pAggInfo is a +** pointer to this structure. The Expr.iColumn field is the index in +** AggInfo.aCol[] or AggInfo.aFunc[] of information needed to generate +** code for that node. +** +** AggInfo.pGroupBy and AggInfo.aFunc.pExpr point to fields within the +** original Select structure that describes the SELECT statement. These +** fields do not need to be freed when deallocating the AggInfo structure. +*/ +struct AggInfo { + u8 directMode; /* Direct rendering mode means take data directly + ** from source tables rather than from accumulators */ + u8 useSortingIdx; /* In direct mode, reference the sorting index rather + ** than the source table */ + int sortingIdx; /* Cursor number of the sorting index */ + ExprList *pGroupBy; /* The group by clause */ + int nSortingColumn; /* Number of columns in the sorting index */ + struct AggInfo_col { /* For each column used in source tables */ + Table *pTab; /* Source table */ + int iTable; /* Cursor number of the source table */ + int iColumn; /* Column number within the source table */ + int iSorterColumn; /* Column number in the sorting index */ + int iMem; /* Memory location that acts as accumulator */ + Expr *pExpr; /* The original expression */ + } *aCol; + int nColumn; /* Number of used entries in aCol[] */ + int nColumnAlloc; /* Number of slots allocated for aCol[] */ + int nAccumulator; /* Number of columns that show through to the output. + ** Additional columns are used only as parameters to + ** aggregate functions */ + struct AggInfo_func { /* For each aggregate function */ + Expr *pExpr; /* Expression encoding the function */ + FuncDef *pFunc; /* The aggregate function implementation */ + int iMem; /* Memory location that acts as accumulator */ + int iDistinct; /* Ephermeral table used to enforce DISTINCT */ + } *aFunc; + int nFunc; /* Number of entries in aFunc[] */ + int nFuncAlloc; /* Number of slots allocated for aFunc[] */ +}; + +/* +** Each node of an expression in the parse tree is an instance +** of this structure. +** +** Expr.op is the opcode. The integer parser token codes are reused +** as opcodes here. For example, the parser defines TK_GE to be an integer +** code representing the ">=" operator. This same integer code is reused +** to represent the greater-than-or-equal-to operator in the expression +** tree. +** +** Expr.pRight and Expr.pLeft are subexpressions. Expr.pList is a list +** of argument if the expression is a function. +** +** Expr.token is the operator token for this node. For some expressions +** that have subexpressions, Expr.token can be the complete text that gave +** rise to the Expr. In the latter case, the token is marked as being +** a compound token. +** +** An expression of the form ID or ID.ID refers to a column in a table. +** For such expressions, Expr.op is set to TK_COLUMN and Expr.iTable is +** the integer cursor number of a VDBE cursor pointing to that table and +** Expr.iColumn is the column number for the specific column. If the +** expression is used as a result in an aggregate SELECT, then the +** value is also stored in the Expr.iAgg column in the aggregate so that +** it can be accessed after all aggregates are computed. +** +** If the expression is a function, the Expr.iTable is an integer code +** representing which function. If the expression is an unbound variable +** marker (a question mark character '?' in the original SQL) then the +** Expr.iTable holds the index number for that variable. +** +** If the expression is a subquery then Expr.iColumn holds an integer +** register number containing the result of the subquery. If the +** subquery gives a constant result, then iTable is -1. If the subquery +** gives a different answer at different times during statement processing +** then iTable is the address of a subroutine that computes the subquery. +** +** The Expr.pSelect field points to a SELECT statement. The SELECT might +** be the right operand of an IN operator. Or, if a scalar SELECT appears +** in an expression the opcode is TK_SELECT and Expr.pSelect is the only +** operand. +** +** If the Expr is of type OP_Column, and the table it is selecting from +** is a disk table or the "old.*" pseudo-table, then pTab points to the +** corresponding table definition. +*/ +struct Expr { + u8 op; /* Operation performed by this node */ + char affinity; /* The affinity of the column or 0 if not a column */ + u16 flags; /* Various flags. See below */ + CollSeq *pColl; /* The collation type of the column or 0 */ + Expr *pLeft, *pRight; /* Left and right subnodes */ + ExprList *pList; /* A list of expressions used as function arguments + ** or in "<expr> IN (<expr-list)" */ + Token token; /* An operand token */ + Token span; /* Complete text of the expression */ + int iTable, iColumn; /* When op==TK_COLUMN, then this expr node means the + ** iColumn-th field of the iTable-th table. */ + AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ + int iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */ + int iRightJoinTable; /* If EP_FromJoin, the right table of the join */ + Select *pSelect; /* When the expression is a sub-select. Also the + ** right side of "<expr> IN (<select>)" */ + Table *pTab; /* Table for OP_Column expressions. */ +#if SQLITE_MAX_EXPR_DEPTH>0 + int nHeight; /* Height of the tree headed by this node */ +#endif +}; + +/* +** The following are the meanings of bits in the Expr.flags field. +*/ +#define EP_FromJoin 0x0001 /* Originated in ON or USING clause of a join */ +#define EP_Agg 0x0002 /* Contains one or more aggregate functions */ +#define EP_Resolved 0x0004 /* IDs have been resolved to COLUMNs */ +#define EP_Error 0x0008 /* Expression contains one or more errors */ +#define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */ +#define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */ +#define EP_Dequoted 0x0040 /* True if the string has been dequoted */ +#define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */ +#define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */ +#define EP_AnyAff 0x0200 /* Can take a cached column of any affinity */ +#define EP_FixedDest 0x0400 /* Result needed in a specific register */ +#define EP_IntValue 0x0800 /* Integer value contained in iTable */ +/* +** These macros can be used to test, set, or clear bits in the +** Expr.flags field. +*/ +#define ExprHasProperty(E,P) (((E)->flags&(P))==(P)) +#define ExprHasAnyProperty(E,P) (((E)->flags&(P))!=0) +#define ExprSetProperty(E,P) (E)->flags|=(P) +#define ExprClearProperty(E,P) (E)->flags&=~(P) + +/* +** A list of expressions. Each expression may optionally have a +** name. An expr/name combination can be used in several ways, such +** as the list of "expr AS ID" fields following a "SELECT" or in the +** list of "ID = expr" items in an UPDATE. A list of expressions can +** also be used as the argument to a function, in which case the a.zName +** field is not used. +*/ +struct ExprList { + int nExpr; /* Number of expressions on the list */ + int nAlloc; /* Number of entries allocated below */ + int iECursor; /* VDBE Cursor associated with this ExprList */ + struct ExprList_item { + Expr *pExpr; /* The list of expressions */ + char *zName; /* Token associated with this expression */ + u8 sortOrder; /* 1 for DESC or 0 for ASC */ + u8 isAgg; /* True if this is an aggregate like count(*) */ + u8 done; /* A flag to indicate when processing is finished */ + } *a; /* One entry for each expression */ +}; + +/* +** An instance of this structure can hold a simple list of identifiers, +** such as the list "a,b,c" in the following statements: +** +** INSERT INTO t(a,b,c) VALUES ...; +** CREATE INDEX idx ON t(a,b,c); +** CREATE TRIGGER trig BEFORE UPDATE ON t(a,b,c) ...; +** +** The IdList.a.idx field is used when the IdList represents the list of +** column names after a table name in an INSERT statement. In the statement +** +** INSERT INTO t(a,b,c) ... +** +** If "a" is the k-th column of table "t", then IdList.a[0].idx==k. +*/ +struct IdList { + struct IdList_item { + char *zName; /* Name of the identifier */ + int idx; /* Index in some Table.aCol[] of a column named zName */ + } *a; + int nId; /* Number of identifiers on the list */ + int nAlloc; /* Number of entries allocated for a[] below */ +}; + +/* +** The bitmask datatype defined below is used for various optimizations. +** +** Changing this from a 64-bit to a 32-bit type limits the number of +** tables in a join to 32 instead of 64. But it also reduces the size +** of the library by 738 bytes on ix86. +*/ +typedef u64 Bitmask; + +/* +** The following structure describes the FROM clause of a SELECT statement. +** Each table or subquery in the FROM clause is a separate element of +** the SrcList.a[] array. +** +** With the addition of multiple database support, the following structure +** can also be used to describe a particular table such as the table that +** is modified by an INSERT, DELETE, or UPDATE statement. In standard SQL, +** such a table must be a simple name: ID. But in SQLite, the table can +** now be identified by a database name, a dot, then the table name: ID.ID. +** +** The jointype starts out showing the join type between the current table +** and the next table on the list. The parser builds the list this way. +** But sqlite3SrcListShiftJoinType() later shifts the jointypes so that each +** jointype expresses the join between the table and the previous table. +*/ +struct SrcList { + i16 nSrc; /* Number of tables or subqueries in the FROM clause */ + i16 nAlloc; /* Number of entries allocated in a[] below */ + struct SrcList_item { + char *zDatabase; /* Name of database holding this table */ + char *zName; /* Name of the table */ + char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */ + Table *pTab; /* An SQL table corresponding to zName */ + Select *pSelect; /* A SELECT statement used in place of a table name */ + u8 isPopulated; /* Temporary table associated with SELECT is populated */ + u8 jointype; /* Type of join between this able and the previous */ + int iCursor; /* The VDBE cursor number used to access this table */ + Expr *pOn; /* The ON clause of a join */ + IdList *pUsing; /* The USING clause of a join */ + Bitmask colUsed; /* Bit N (1<<N) set if column N or pTab is used */ + } a[1]; /* One entry for each identifier on the list */ +}; + +/* +** Permitted values of the SrcList.a.jointype field +*/ +#define JT_INNER 0x0001 /* Any kind of inner or cross join */ +#define JT_CROSS 0x0002 /* Explicit use of the CROSS keyword */ +#define JT_NATURAL 0x0004 /* True for a "natural" join */ +#define JT_LEFT 0x0008 /* Left outer join */ +#define JT_RIGHT 0x0010 /* Right outer join */ +#define JT_OUTER 0x0020 /* The "OUTER" keyword is present */ +#define JT_ERROR 0x0040 /* unknown or unsupported join type */ + +/* +** For each nested loop in a WHERE clause implementation, the WhereInfo +** structure contains a single instance of this structure. This structure +** is intended to be private the the where.c module and should not be +** access or modified by other modules. +** +** The pIdxInfo and pBestIdx fields are used to help pick the best +** index on a virtual table. The pIdxInfo pointer contains indexing +** information for the i-th table in the FROM clause before reordering. +** All the pIdxInfo pointers are freed by whereInfoFree() in where.c. +** The pBestIdx pointer is a copy of pIdxInfo for the i-th table after +** FROM clause ordering. This is a little confusing so I will repeat +** it in different words. WhereInfo.a[i].pIdxInfo is index information +** for WhereInfo.pTabList.a[i]. WhereInfo.a[i].pBestInfo is the +** index information for the i-th loop of the join. pBestInfo is always +** either NULL or a copy of some pIdxInfo. So for cleanup it is +** sufficient to free all of the pIdxInfo pointers. +** +*/ +struct WhereLevel { + int iFrom; /* Which entry in the FROM clause */ + int flags; /* Flags associated with this level */ + int iMem; /* First memory cell used by this level */ + int iLeftJoin; /* Memory cell used to implement LEFT OUTER JOIN */ + Index *pIdx; /* Index used. NULL if no index */ + int iTabCur; /* The VDBE cursor used to access the table */ + int iIdxCur; /* The VDBE cursor used to acesss pIdx */ + int brk; /* Jump here to break out of the loop */ + int nxt; /* Jump here to start the next IN combination */ + int cont; /* Jump here to continue with the next loop cycle */ + int top; /* First instruction of interior of the loop */ + int op, p1, p2; /* Opcode used to terminate the loop */ + int nEq; /* Number of == or IN constraints on this loop */ + int nIn; /* Number of IN operators constraining this loop */ + struct InLoop { + int iCur; /* The VDBE cursor used by this IN operator */ + int topAddr; /* Top of the IN loop */ + } *aInLoop; /* Information about each nested IN operator */ + sqlite3_index_info *pBestIdx; /* Index information for this level */ + + /* The following field is really not part of the current level. But + ** we need a place to cache index information for each table in the + ** FROM clause and the WhereLevel structure is a convenient place. + */ + sqlite3_index_info *pIdxInfo; /* Index info for n-th source table */ +}; + +/* +** Flags appropriate for the wflags parameter of sqlite3WhereBegin(). +*/ +#define WHERE_ORDERBY_NORMAL 0 /* No-op */ +#define WHERE_ORDERBY_MIN 1 /* ORDER BY processing for min() func */ +#define WHERE_ORDERBY_MAX 2 /* ORDER BY processing for max() func */ +#define WHERE_ONEPASS_DESIRED 4 /* Want to do one-pass UPDATE/DELETE */ + +/* +** The WHERE clause processing routine has two halves. The +** first part does the start of the WHERE loop and the second +** half does the tail of the WHERE loop. An instance of +** this structure is returned by the first half and passed +** into the second half to give some continuity. +*/ +struct WhereInfo { + Parse *pParse; /* Parsing and code generating context */ + u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE or DELETE */ + SrcList *pTabList; /* List of tables in the join */ + int iTop; /* The very beginning of the WHERE loop */ + int iContinue; /* Jump here to continue with next record */ + int iBreak; /* Jump here to break out of the loop */ + int nLevel; /* Number of nested loop */ + sqlite3_index_info **apInfo; /* Array of pointers to index info structures */ + WhereLevel a[1]; /* Information about each nest loop in the WHERE */ +}; + +/* +** A NameContext defines a context in which to resolve table and column +** names. The context consists of a list of tables (the pSrcList) field and +** a list of named expression (pEList). The named expression list may +** be NULL. The pSrc corresponds to the FROM clause of a SELECT or +** to the table being operated on by INSERT, UPDATE, or DELETE. The +** pEList corresponds to the result set of a SELECT and is NULL for +** other statements. +** +** NameContexts can be nested. When resolving names, the inner-most +** context is searched first. If no match is found, the next outer +** context is checked. If there is still no match, the next context +** is checked. This process continues until either a match is found +** or all contexts are check. When a match is found, the nRef member of +** the context containing the match is incremented. +** +** Each subquery gets a new NameContext. The pNext field points to the +** NameContext in the parent query. Thus the process of scanning the +** NameContext list corresponds to searching through successively outer +** subqueries looking for a match. +*/ +struct NameContext { + Parse *pParse; /* The parser */ + SrcList *pSrcList; /* One or more tables used to resolve names */ + ExprList *pEList; /* Optional list of named expressions */ + int nRef; /* Number of names resolved by this context */ + int nErr; /* Number of errors encountered while resolving names */ + u8 allowAgg; /* Aggregate functions allowed here */ + u8 hasAgg; /* True if aggregates are seen */ + u8 isCheck; /* True if resolving names in a CHECK constraint */ + int nDepth; /* Depth of subquery recursion. 1 for no recursion */ + AggInfo *pAggInfo; /* Information about aggregates at this level */ + NameContext *pNext; /* Next outer name context. NULL for outermost */ +}; + +/* +** An instance of the following structure contains all information +** needed to generate code for a single SELECT statement. +** +** nLimit is set to -1 if there is no LIMIT clause. nOffset is set to 0. +** If there is a LIMIT clause, the parser sets nLimit to the value of the +** limit and nOffset to the value of the offset (or 0 if there is not +** offset). But later on, nLimit and nOffset become the memory locations +** in the VDBE that record the limit and offset counters. +** +** addrOpenEphm[] entries contain the address of OP_OpenEphemeral opcodes. +** These addresses must be stored so that we can go back and fill in +** the P4_KEYINFO and P2 parameters later. Neither the KeyInfo nor +** the number of columns in P2 can be computed at the same time +** as the OP_OpenEphm instruction is coded because not +** enough information about the compound query is known at that point. +** The KeyInfo for addrOpenTran[0] and [1] contains collating sequences +** for the result set. The KeyInfo for addrOpenTran[2] contains collating +** sequences for the ORDER BY clause. +*/ +struct Select { + ExprList *pEList; /* The fields of the result */ + u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */ + u8 isDistinct; /* True if the DISTINCT keyword is present */ + u8 isResolved; /* True once sqlite3SelectResolve() has run. */ + u8 isAgg; /* True if this is an aggregate query */ + u8 usesEphm; /* True if uses an OpenEphemeral opcode */ + u8 disallowOrderBy; /* Do not allow an ORDER BY to be attached if TRUE */ + char affinity; /* MakeRecord with this affinity for SRT_Set */ + SrcList *pSrc; /* The FROM clause */ + Expr *pWhere; /* The WHERE clause */ + ExprList *pGroupBy; /* The GROUP BY clause */ + Expr *pHaving; /* The HAVING clause */ + ExprList *pOrderBy; /* The ORDER BY clause */ + Select *pPrior; /* Prior select in a compound select statement */ + Select *pNext; /* Next select to the left in a compound */ + Select *pRightmost; /* Right-most select in a compound select statement */ + Expr *pLimit; /* LIMIT expression. NULL means not used. */ + Expr *pOffset; /* OFFSET expression. NULL means not used. */ + int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */ + int addrOpenEphm[3]; /* OP_OpenEphem opcodes related to this select */ +}; + +/* +** The results of a select can be distributed in several ways. +*/ +#define SRT_Union 1 /* Store result as keys in an index */ +#define SRT_Except 2 /* Remove result from a UNION index */ +#define SRT_Exists 3 /* Store 1 if the result is not empty */ +#define SRT_Discard 4 /* Do not save the results anywhere */ + +/* The ORDER BY clause is ignored for all of the above */ +#define IgnorableOrderby(X) ((X->eDest)<=SRT_Discard) + +#define SRT_Callback 5 /* Invoke a callback with each row of result */ +#define SRT_Mem 6 /* Store result in a memory cell */ +#define SRT_Set 7 /* Store results as keys in an index */ +#define SRT_Table 8 /* Store result as data with an automatic rowid */ +#define SRT_EphemTab 9 /* Create transient tab and store like SRT_Table */ +#define SRT_Coroutine 10 /* Generate a single row of result */ + +/* +** A structure used to customize the behaviour of sqlite3Select(). See +** comments above sqlite3Select() for details. +*/ +typedef struct SelectDest SelectDest; +struct SelectDest { + u8 eDest; /* How to dispose of the results */ + u8 affinity; /* Affinity used when eDest==SRT_Set */ + int iParm; /* A parameter used by the eDest disposal method */ + int iMem; /* Base register where results are written */ + int nMem; /* Number of registers allocated */ +}; + +/* +** An SQL parser context. A copy of this structure is passed through +** the parser and down into all the parser action routine in order to +** carry around information that is global to the entire parse. +** +** The structure is divided into two parts. When the parser and code +** generate call themselves recursively, the first part of the structure +** is constant but the second part is reset at the beginning and end of +** each recursion. +** +** The nTableLock and aTableLock variables are only used if the shared-cache +** feature is enabled (if sqlite3Tsd()->useSharedData is true). They are +** used to store the set of table-locks required by the statement being +** compiled. Function sqlite3TableLock() is used to add entries to the +** list. +*/ +struct Parse { + sqlite3 *db; /* The main database structure */ + int rc; /* Return code from execution */ + char *zErrMsg; /* An error message */ + Vdbe *pVdbe; /* An engine for executing database bytecode */ + u8 colNamesSet; /* TRUE after OP_ColumnName has been issued to pVdbe */ + u8 nameClash; /* A permanent table name clashes with temp table name */ + u8 checkSchema; /* Causes schema cookie check after an error */ + u8 nested; /* Number of nested calls to the parser/code generator */ + u8 parseError; /* True after a parsing error. Ticket #1794 */ + u8 nTempReg; /* Number of temporary registers in aTempReg[] */ + u8 nTempInUse; /* Number of aTempReg[] currently checked out */ + int aTempReg[8]; /* Holding area for temporary registers */ + int nRangeReg; /* Size of the temporary register block */ + int iRangeReg; /* First register in temporary register block */ + int nErr; /* Number of errors seen */ + int nTab; /* Number of previously allocated VDBE cursors */ + int nMem; /* Number of memory cells used so far */ + int nSet; /* Number of sets used so far */ + int ckBase; /* Base register of data during check constraints */ + int disableColCache; /* True to disable adding to column cache */ + int nColCache; /* Number of entries in the column cache */ + int iColCache; /* Next entry of the cache to replace */ + struct yColCache { + int iTable; /* Table cursor number */ + int iColumn; /* Table column number */ + char affChange; /* True if this register has had an affinity change */ + int iReg; /* Register holding value of this column */ + } aColCache[10]; /* One for each valid column cache entry */ + u32 writeMask; /* Start a write transaction on these databases */ + u32 cookieMask; /* Bitmask of schema verified databases */ + int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */ + int cookieValue[SQLITE_MAX_ATTACHED+2]; /* Values of cookies to verify */ +#ifndef SQLITE_OMIT_SHARED_CACHE + int nTableLock; /* Number of locks in aTableLock */ + TableLock *aTableLock; /* Required table locks for shared-cache mode */ +#endif + int regRowid; /* Register holding rowid of CREATE TABLE entry */ + int regRoot; /* Register holding root page number for new objects */ + + /* Above is constant between recursions. Below is reset before and after + ** each recursion */ + + int nVar; /* Number of '?' variables seen in the SQL so far */ + int nVarExpr; /* Number of used slots in apVarExpr[] */ + int nVarExprAlloc; /* Number of allocated slots in apVarExpr[] */ + Expr **apVarExpr; /* Pointers to :aaa and $aaaa wildcard expressions */ + u8 explain; /* True if the EXPLAIN flag is found on the query */ + Token sErrToken; /* The token at which the error occurred */ + Token sNameToken; /* Token with unqualified schema object name */ + Token sLastToken; /* The last token parsed */ + const char *zSql; /* All SQL text */ + const char *zTail; /* All SQL text past the last semicolon parsed */ + Table *pNewTable; /* A table being constructed by CREATE TABLE */ + Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */ + TriggerStack *trigStack; /* Trigger actions being coded */ + const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + Token sArg; /* Complete text of a module argument */ + u8 declareVtab; /* True if inside sqlite3_declare_vtab() */ + int nVtabLock; /* Number of virtual tables to lock */ + Table **apVtabLock; /* Pointer to virtual tables needing locking */ +#endif + int nHeight; /* Expression tree height of current sub-select */ +}; + +#ifdef SQLITE_OMIT_VIRTUALTABLE + #define IN_DECLARE_VTAB 0 +#else + #define IN_DECLARE_VTAB (pParse->declareVtab) +#endif + +/* +** An instance of the following structure can be declared on a stack and used +** to save the Parse.zAuthContext value so that it can be restored later. +*/ +struct AuthContext { + const char *zAuthContext; /* Put saved Parse.zAuthContext here */ + Parse *pParse; /* The Parse structure */ +}; + +/* +** Bitfield flags for P2 value in OP_Insert and OP_Delete +*/ +#define OPFLAG_NCHANGE 1 /* Set to update db->nChange */ +#define OPFLAG_LASTROWID 2 /* Set to update db->lastRowid */ +#define OPFLAG_ISUPDATE 4 /* This OP_Insert is an sql UPDATE */ +#define OPFLAG_APPEND 8 /* This is likely to be an append */ + +/* + * Each trigger present in the database schema is stored as an instance of + * struct Trigger. + * + * Pointers to instances of struct Trigger are stored in two ways. + * 1. In the "trigHash" hash table (part of the sqlite3* that represents the + * database). This allows Trigger structures to be retrieved by name. + * 2. All triggers associated with a single table form a linked list, using the + * pNext member of struct Trigger. A pointer to the first element of the + * linked list is stored as the "pTrigger" member of the associated + * struct Table. + * + * The "step_list" member points to the first element of a linked list + * containing the SQL statements specified as the trigger program. + */ +struct Trigger { + char *name; /* The name of the trigger */ + char *table; /* The table or view to which the trigger applies */ + u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT */ + u8 tr_tm; /* One of TRIGGER_BEFORE, TRIGGER_AFTER */ + Expr *pWhen; /* The WHEN clause of the expresion (may be NULL) */ + IdList *pColumns; /* If this is an UPDATE OF <column-list> trigger, + the <column-list> is stored here */ + Token nameToken; /* Token containing zName. Use during parsing only */ + Schema *pSchema; /* Schema containing the trigger */ + Schema *pTabSchema; /* Schema containing the table */ + TriggerStep *step_list; /* Link list of trigger program steps */ + Trigger *pNext; /* Next trigger associated with the table */ +}; + +/* +** A trigger is either a BEFORE or an AFTER trigger. The following constants +** determine which. +** +** If there are multiple triggers, you might of some BEFORE and some AFTER. +** In that cases, the constants below can be ORed together. +*/ +#define TRIGGER_BEFORE 1 +#define TRIGGER_AFTER 2 + +/* + * An instance of struct TriggerStep is used to store a single SQL statement + * that is a part of a trigger-program. + * + * Instances of struct TriggerStep are stored in a singly linked list (linked + * using the "pNext" member) referenced by the "step_list" member of the + * associated struct Trigger instance. The first element of the linked list is + * the first step of the trigger-program. + * + * The "op" member indicates whether this is a "DELETE", "INSERT", "UPDATE" or + * "SELECT" statement. The meanings of the other members is determined by the + * value of "op" as follows: + * + * (op == TK_INSERT) + * orconf -> stores the ON CONFLICT algorithm + * pSelect -> If this is an INSERT INTO ... SELECT ... statement, then + * this stores a pointer to the SELECT statement. Otherwise NULL. + * target -> A token holding the name of the table to insert into. + * pExprList -> If this is an INSERT INTO ... VALUES ... statement, then + * this stores values to be inserted. Otherwise NULL. + * pIdList -> If this is an INSERT INTO ... (<column-names>) VALUES ... + * statement, then this stores the column-names to be + * inserted into. + * + * (op == TK_DELETE) + * target -> A token holding the name of the table to delete from. + * pWhere -> The WHERE clause of the DELETE statement if one is specified. + * Otherwise NULL. + * + * (op == TK_UPDATE) + * target -> A token holding the name of the table to update rows of. + * pWhere -> The WHERE clause of the UPDATE statement if one is specified. + * Otherwise NULL. + * pExprList -> A list of the columns to update and the expressions to update + * them to. See sqlite3Update() documentation of "pChanges" + * argument. + * + */ +struct TriggerStep { + int op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */ + int orconf; /* OE_Rollback etc. */ + Trigger *pTrig; /* The trigger that this step is a part of */ + + Select *pSelect; /* Valid for SELECT and sometimes + INSERT steps (when pExprList == 0) */ + Token target; /* Valid for DELETE, UPDATE, INSERT steps */ + Expr *pWhere; /* Valid for DELETE, UPDATE steps */ + ExprList *pExprList; /* Valid for UPDATE statements and sometimes + INSERT steps (when pSelect == 0) */ + IdList *pIdList; /* Valid for INSERT statements only */ + TriggerStep *pNext; /* Next in the link-list */ + TriggerStep *pLast; /* Last element in link-list. Valid for 1st elem only */ +}; + +/* + * An instance of struct TriggerStack stores information required during code + * generation of a single trigger program. While the trigger program is being + * coded, its associated TriggerStack instance is pointed to by the + * "pTriggerStack" member of the Parse structure. + * + * The pTab member points to the table that triggers are being coded on. The + * newIdx member contains the index of the vdbe cursor that points at the temp + * table that stores the new.* references. If new.* references are not valid + * for the trigger being coded (for example an ON DELETE trigger), then newIdx + * is set to -1. The oldIdx member is analogous to newIdx, for old.* references. + * + * The ON CONFLICT policy to be used for the trigger program steps is stored + * as the orconf member. If this is OE_Default, then the ON CONFLICT clause + * specified for individual triggers steps is used. + * + * struct TriggerStack has a "pNext" member, to allow linked lists to be + * constructed. When coding nested triggers (triggers fired by other triggers) + * each nested trigger stores its parent trigger's TriggerStack as the "pNext" + * pointer. Once the nested trigger has been coded, the pNext value is restored + * to the pTriggerStack member of the Parse stucture and coding of the parent + * trigger continues. + * + * Before a nested trigger is coded, the linked list pointed to by the + * pTriggerStack is scanned to ensure that the trigger is not about to be coded + * recursively. If this condition is detected, the nested trigger is not coded. + */ +struct TriggerStack { + Table *pTab; /* Table that triggers are currently being coded on */ + int newIdx; /* Index of vdbe cursor to "new" temp table */ + int oldIdx; /* Index of vdbe cursor to "old" temp table */ + u32 newColMask; + u32 oldColMask; + int orconf; /* Current orconf policy */ + int ignoreJump; /* where to jump to for a RAISE(IGNORE) */ + Trigger *pTrigger; /* The trigger currently being coded */ + TriggerStack *pNext; /* Next trigger down on the trigger stack */ +}; + +/* +** The following structure contains information used by the sqliteFix... +** routines as they walk the parse tree to make database references +** explicit. +*/ +typedef struct DbFixer DbFixer; +struct DbFixer { + Parse *pParse; /* The parsing context. Error messages written here */ + const char *zDb; /* Make sure all objects are contained in this database */ + const char *zType; /* Type of the container - used for error messages */ + const Token *pName; /* Name of the container - used for error messages */ +}; + +/* +** An objected used to accumulate the text of a string where we +** do not necessarily know how big the string will be in the end. +*/ +struct StrAccum { + sqlite3 *db; /* Optional database for lookaside. Can be NULL */ + char *zBase; /* A base allocation. Not from malloc. */ + char *zText; /* The string collected so far */ + int nChar; /* Length of the string so far */ + int nAlloc; /* Amount of space allocated in zText */ + int mxAlloc; /* Maximum allowed string length */ + u8 mallocFailed; /* Becomes true if any memory allocation fails */ + u8 useMalloc; /* True if zText is enlargable using realloc */ + u8 tooBig; /* Becomes true if string size exceeds limits */ +}; + +/* +** A pointer to this structure is used to communicate information +** from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback. +*/ +typedef struct { + sqlite3 *db; /* The database being initialized */ + int iDb; /* 0 for main database. 1 for TEMP, 2.. for ATTACHed */ + char **pzErrMsg; /* Error message stored here */ + int rc; /* Result code stored here */ +} InitData; + +/* +** Structure containing global configuration data for the SQLite library. +** +** This structure also contains some state information. +*/ +struct Sqlite3Config { + int bMemstat; /* True to enable memory status */ + int bCoreMutex; /* True to enable core mutexing */ + int bFullMutex; /* True to enable full mutexing */ + int mxStrlen; /* Maximum string length */ + int szLookaside; /* Default lookaside buffer size */ + int nLookaside; /* Default lookaside buffer count */ + sqlite3_mem_methods m; /* Low-level memory allocation interface */ + sqlite3_mutex_methods mutex; /* Low-level mutex interface */ + void *pHeap; /* Heap storage space */ + int nHeap; /* Size of pHeap[] */ + int mnReq, mxReq; /* Min and max heap requests sizes */ + void *pScratch; /* Scratch memory */ + int szScratch; /* Size of each scratch buffer */ + int nScratch; /* Number of scratch buffers */ + void *pPage; /* Page cache memory */ + int szPage; /* Size of each page in pPage[] */ + int nPage; /* Number of pages in pPage[] */ + int isInit; /* True after initialization has finished */ + int isMallocInit; /* True after malloc is initialized */ + sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */ + int nSmall; /* alloc size threshold used by mem6.c */ + int mxParserStack; /* maximum depth of the parser stack */ +}; + +/* +** Assuming zIn points to the first byte of a UTF-8 character, +** advance zIn to point to the first byte of the next UTF-8 character. +*/ +#define SQLITE_SKIP_UTF8(zIn) { \ + if( (*(zIn++))>=0xc0 ){ \ + while( (*zIn & 0xc0)==0x80 ){ zIn++; } \ + } \ +} + +/* +** The SQLITE_CORRUPT_BKPT macro can be either a constant (for production +** builds) or a function call (for debugging). If it is a function call, +** it allows the operator to set a breakpoint at the spot where database +** corruption is first detected. +*/ +#ifdef SQLITE_DEBUG + int sqlite3Corrupt(void); +# define SQLITE_CORRUPT_BKPT sqlite3Corrupt() +#else +# define SQLITE_CORRUPT_BKPT SQLITE_CORRUPT +#endif + +/* +** Internal function prototypes +*/ +int sqlite3StrICmp(const char *, const char *); +int sqlite3StrNICmp(const char *, const char *, int); +int sqlite3IsNumber(const char*, int*, u8); +int sqlite3Strlen(sqlite3*, const char*); + +int sqlite3MallocInit(void); +void sqlite3MallocEnd(void); +void *sqlite3Malloc(int); +void *sqlite3MallocZero(int); +void *sqlite3DbMallocZero(sqlite3*, int); +void *sqlite3DbMallocRaw(sqlite3*, int); +char *sqlite3DbStrDup(sqlite3*,const char*); +char *sqlite3DbStrNDup(sqlite3*,const char*, int); +void *sqlite3Realloc(void*, int); +void *sqlite3DbReallocOrFree(sqlite3 *, void *, int); +void *sqlite3DbRealloc(sqlite3 *, void *, int); +void sqlite3DbFree(sqlite3*, void*); +int sqlite3MallocSize(void*); +int sqlite3DbMallocSize(sqlite3*, void*); +void *sqlite3ScratchMalloc(int); +void sqlite3ScratchFree(void*); +void *sqlite3PageMalloc(int); +void sqlite3PageFree(void*); +void sqlite3MemSetDefault(void); +const sqlite3_mem_methods *sqlite3MemGetDefault(void); +const sqlite3_mem_methods *sqlite3MemGetMemsys5(void); +const sqlite3_mem_methods *sqlite3MemGetMemsys3(void); +const sqlite3_mem_methods *sqlite3MemGetMemsys6(void); +void sqlite3BenignMallocHooks(void (*)(void), void (*)(void)); + +#ifndef SQLITE_MUTEX_NOOP + sqlite3_mutex_methods *sqlite3DefaultMutex(void); + sqlite3_mutex *sqlite3MutexAlloc(int); + int sqlite3MutexInit(void); + int sqlite3MutexEnd(void); +#endif + +void sqlite3StatusReset(void); +int sqlite3StatusValue(int); +void sqlite3StatusAdd(int, int); +void sqlite3StatusSet(int, int); + +int sqlite3IsNaN(double); + +void sqlite3VXPrintf(StrAccum*, int, const char*, va_list); +char *sqlite3MPrintf(sqlite3*,const char*, ...); +char *sqlite3VMPrintf(sqlite3*,const char*, va_list); +char *sqlite3MAppendf(sqlite3*,char*,const char*,...); +#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) + void sqlite3DebugPrintf(const char*, ...); +#endif +#if defined(SQLITE_TEST) + void *sqlite3TestTextToPtr(const char*); +#endif +void sqlite3SetString(char **, sqlite3*, const char*, ...); +void sqlite3ErrorMsg(Parse*, const char*, ...); +void sqlite3ErrorClear(Parse*); +void sqlite3Dequote(char*); +void sqlite3DequoteExpr(sqlite3*, Expr*); +int sqlite3KeywordCode(const unsigned char*, int); +int sqlite3RunParser(Parse*, const char*, char **); +void sqlite3FinishCoding(Parse*); +int sqlite3GetTempReg(Parse*); +void sqlite3ReleaseTempReg(Parse*,int); +int sqlite3GetTempRange(Parse*,int); +void sqlite3ReleaseTempRange(Parse*,int,int); +Expr *sqlite3Expr(sqlite3*, int, Expr*, Expr*, const Token*); +Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*, const Token*); +Expr *sqlite3RegisterExpr(Parse*,Token*); +Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*); +void sqlite3ExprSpan(Expr*,Token*,Token*); +Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*); +void sqlite3ExprAssignVarNumber(Parse*, Expr*); +void sqlite3ExprDelete(sqlite3*, Expr*); +ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*,Token*); +void sqlite3ExprListDelete(sqlite3*, ExprList*); +int sqlite3Init(sqlite3*, char**); +int sqlite3InitCallback(void*, int, char**, char**); +void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); +void sqlite3ResetInternalSchema(sqlite3*, int); +void sqlite3BeginParse(Parse*,int); +void sqlite3CommitInternalChanges(sqlite3*); +Table *sqlite3ResultSetOfSelect(Parse*,char*,Select*); +void sqlite3OpenMasterTable(Parse *, int); +void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int); +void sqlite3AddColumn(Parse*,Token*); +void sqlite3AddNotNull(Parse*, int); +void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int); +void sqlite3AddCheckConstraint(Parse*, Expr*); +void sqlite3AddColumnType(Parse*,Token*); +void sqlite3AddDefaultValue(Parse*,Expr*); +void sqlite3AddCollateType(Parse*, Token*); +void sqlite3EndTable(Parse*,Token*,Token*,Select*); + +Bitvec *sqlite3BitvecCreate(u32); +int sqlite3BitvecTest(Bitvec*, u32); +int sqlite3BitvecSet(Bitvec*, u32); +void sqlite3BitvecClear(Bitvec*, u32); +void sqlite3BitvecDestroy(Bitvec*); +int sqlite3BitvecBuiltinTest(int,int*); + +void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int); + +#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) + int sqlite3ViewGetColumnNames(Parse*,Table*); +#else +# define sqlite3ViewGetColumnNames(A,B) 0 +#endif + +void sqlite3DropTable(Parse*, SrcList*, int, int); +void sqlite3DeleteTable(Table*); +void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int); +void *sqlite3ArrayAllocate(sqlite3*,void*,int,int,int*,int*,int*); +IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*); +int sqlite3IdListIndex(IdList*,const char*); +SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*); +SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*, Token*, + Select*, Expr*, IdList*); +void sqlite3SrcListShiftJoinType(SrcList*); +void sqlite3SrcListAssignCursors(Parse*, SrcList*); +void sqlite3IdListDelete(sqlite3*, IdList*); +void sqlite3SrcListDelete(sqlite3*, SrcList*); +void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, + Token*, int, int); +void sqlite3DropIndex(Parse*, SrcList*, int); +int sqlite3Select(Parse*, Select*, SelectDest*, Select*, int, int*); +Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, + Expr*,ExprList*,int,Expr*,Expr*); +void sqlite3SelectDelete(sqlite3*, Select*); +Table *sqlite3SrcListLookup(Parse*, SrcList*); +int sqlite3IsReadOnly(Parse*, Table*, int); +void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); +void sqlite3DeleteFrom(Parse*, SrcList*, Expr*); +void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); +WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u8); +void sqlite3WhereEnd(WhereInfo*); +int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, int); +void sqlite3ExprCodeMove(Parse*, int, int, int); +void sqlite3ExprCodeCopy(Parse*, int, int, int); +void sqlite3ExprClearColumnCache(Parse*, int); +void sqlite3ExprCacheAffinityChange(Parse*, int, int); +int sqlite3ExprWritableRegister(Parse*,int,int); +void sqlite3ExprHardCopy(Parse*,int,int); +int sqlite3ExprCode(Parse*, Expr*, int); +int sqlite3ExprCodeTemp(Parse*, Expr*, int*); +int sqlite3ExprCodeTarget(Parse*, Expr*, int); +int sqlite3ExprCodeAndCache(Parse*, Expr*, int); +void sqlite3ExprCodeConstants(Parse*, Expr*); +int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int); +void sqlite3ExprIfTrue(Parse*, Expr*, int, int); +void sqlite3ExprIfFalse(Parse*, Expr*, int, int); +Table *sqlite3FindTable(sqlite3*,const char*, const char*); +Table *sqlite3LocateTable(Parse*,int isView,const char*, const char*); +Index *sqlite3FindIndex(sqlite3*,const char*, const char*); +void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*); +void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*); +void sqlite3Vacuum(Parse*); +int sqlite3RunVacuum(char**, sqlite3*); +char *sqlite3NameFromToken(sqlite3*, Token*); +int sqlite3ExprCompare(Expr*, Expr*); +int sqlite3ExprResolveNames(NameContext *, Expr *); +void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*); +void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); +Vdbe *sqlite3GetVdbe(Parse*); +Expr *sqlite3CreateIdExpr(Parse *, const char*); +void sqlite3PrngSaveState(void); +void sqlite3PrngRestoreState(void); +void sqlite3PrngResetState(void); +void sqlite3RollbackAll(sqlite3*); +void sqlite3CodeVerifySchema(Parse*, int); +void sqlite3BeginTransaction(Parse*, int); +void sqlite3CommitTransaction(Parse*); +void sqlite3RollbackTransaction(Parse*); +int sqlite3ExprIsConstant(Expr*); +int sqlite3ExprIsConstantNotJoin(Expr*); +int sqlite3ExprIsConstantOrFunction(Expr*); +int sqlite3ExprIsInteger(Expr*, int*); +int sqlite3IsRowid(const char*); +void sqlite3GenerateRowDelete(Parse*, Table*, int, int, int); +void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int*); +int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int); +void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int, + int*,int,int,int,int); +void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*,int,int,int,int); +int sqlite3OpenTableAndIndices(Parse*, Table*, int, int); +void sqlite3BeginWriteOperation(Parse*, int, int); +Expr *sqlite3ExprDup(sqlite3*,Expr*); +void sqlite3TokenCopy(sqlite3*,Token*, Token*); +ExprList *sqlite3ExprListDup(sqlite3*,ExprList*); +SrcList *sqlite3SrcListDup(sqlite3*,SrcList*); +IdList *sqlite3IdListDup(sqlite3*,IdList*); +Select *sqlite3SelectDup(sqlite3*,Select*); +FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,int); +void sqlite3RegisterBuiltinFunctions(sqlite3*); +void sqlite3RegisterDateTimeFunctions(sqlite3*); +#ifdef SQLITE_DEBUG + int sqlite3SafetyOn(sqlite3*); + int sqlite3SafetyOff(sqlite3*); +#else +# define sqlite3SafetyOn(A) 0 +# define sqlite3SafetyOff(A) 0 +#endif +int sqlite3SafetyCheckOk(sqlite3*); +int sqlite3SafetyCheckSickOrOk(sqlite3*); +void sqlite3ChangeCookie(Parse*, int); +void sqlite3MaterializeView(Parse*, Select*, Expr*, int); + +#ifndef SQLITE_OMIT_TRIGGER + void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*, + Expr*,int, int); + void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*); + void sqlite3DropTrigger(Parse*, SrcList*, int); + void sqlite3DropTriggerPtr(Parse*, Trigger*); + int sqlite3TriggersExist(Parse*, Table*, int, ExprList*); + int sqlite3CodeRowTrigger(Parse*, int, ExprList*, int, Table *, int, int, + int, int, u32*, u32*); + void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*); + void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*); + TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*); + TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*, + ExprList*,Select*,int); + TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, int); + TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*); + void sqlite3DeleteTrigger(sqlite3*, Trigger*); + void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); +#else +# define sqlite3TriggersExist(A,B,C,D,E,F) 0 +# define sqlite3DeleteTrigger(A,B) +# define sqlite3DropTriggerPtr(A,B) +# define sqlite3UnlinkAndDeleteTrigger(A,B,C) +# define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I,J,K) 0 +#endif + +int sqlite3JoinType(Parse*, Token*, Token*, Token*); +void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int); +void sqlite3DeferForeignKey(Parse*, int); +#ifndef SQLITE_OMIT_AUTHORIZATION + void sqlite3AuthRead(Parse*,Expr*,Schema*,SrcList*); + int sqlite3AuthCheck(Parse*,int, const char*, const char*, const char*); + void sqlite3AuthContextPush(Parse*, AuthContext*, const char*); + void sqlite3AuthContextPop(AuthContext*); +#else +# define sqlite3AuthRead(a,b,c,d) +# define sqlite3AuthCheck(a,b,c,d,e) SQLITE_OK +# define sqlite3AuthContextPush(a,b,c) +# define sqlite3AuthContextPop(a) ((void)(a)) +#endif +void sqlite3Attach(Parse*, Expr*, Expr*, Expr*); +void sqlite3Detach(Parse*, Expr*); +int sqlite3BtreeFactory(const sqlite3 *db, const char *zFilename, + int omitJournal, int nCache, int flags, Btree **ppBtree); +int sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*); +int sqlite3FixSrcList(DbFixer*, SrcList*); +int sqlite3FixSelect(DbFixer*, Select*); +int sqlite3FixExpr(DbFixer*, Expr*); +int sqlite3FixExprList(DbFixer*, ExprList*); +int sqlite3FixTriggerStep(DbFixer*, TriggerStep*); +int sqlite3AtoF(const char *z, double*); +char *sqlite3_snprintf(int,char*,const char*,...); +int sqlite3GetInt32(const char *, int*); +int sqlite3FitsIn64Bits(const char *, int); +int sqlite3Utf16ByteLen(const void *pData, int nChar); +int sqlite3Utf8CharLen(const char *pData, int nByte); +int sqlite3Utf8Read(const u8*, const u8*, const u8**); + +/* +** Routines to read and write variable-length integers. These used to +** be defined locally, but now we use the varint routines in the util.c +** file. Code should use the MACRO forms below, as the Varint32 versions +** are coded to assume the single byte case is already handled (which +** the MACRO form does). +*/ +int sqlite3PutVarint(unsigned char*, u64); +int sqlite3PutVarint32(unsigned char*, u32); +int sqlite3GetVarint(const unsigned char *, u64 *); +int sqlite3GetVarint32(const unsigned char *, u32 *); +int sqlite3VarintLen(u64 v); + +/* +** The header of a record consists of a sequence variable-length integers. +** These integers are almost always small and are encoded as a single byte. +** The following macros take advantage this fact to provide a fast encode +** and decode of the integers in a record header. It is faster for the common +** case where the integer is a single byte. It is a little slower when the +** integer is two or more bytes. But overall it is faster. +** +** The following expressions are equivalent: +** +** x = sqlite3GetVarint32( A, &B ); +** x = sqlite3PutVarint32( A, B ); +** +** x = getVarint32( A, B ); +** x = putVarint32( A, B ); +** +*/ +#define getVarint32(A,B) ((*(A)<(unsigned char)0x80) ? ((B) = (u32)*(A)),1 : sqlite3GetVarint32((A), &(B))) +#define putVarint32(A,B) (((B)<(u32)0x80) ? (*(A) = (unsigned char)(B)),1 : sqlite3PutVarint32((A), (B))) +#define getVarint sqlite3GetVarint +#define putVarint sqlite3PutVarint + + +void sqlite3IndexAffinityStr(Vdbe *, Index *); +void sqlite3TableAffinityStr(Vdbe *, Table *); +char sqlite3CompareAffinity(Expr *pExpr, char aff2); +int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity); +char sqlite3ExprAffinity(Expr *pExpr); +int sqlite3Atoi64(const char*, i64*); +void sqlite3Error(sqlite3*, int, const char*,...); +void *sqlite3HexToBlob(sqlite3*, const char *z, int n); +int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); +const char *sqlite3ErrStr(int); +int sqlite3ReadSchema(Parse *pParse); +CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char *,int,int); +CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName); +CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); +Expr *sqlite3ExprSetColl(Parse *pParse, Expr *, Token *); +int sqlite3CheckCollSeq(Parse *, CollSeq *); +int sqlite3CheckObjectName(Parse *, const char *); +void sqlite3VdbeSetChanges(sqlite3 *, int); + +const void *sqlite3ValueText(sqlite3_value*, u8); +int sqlite3ValueBytes(sqlite3_value*, u8); +void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, + void(*)(void*)); +void sqlite3ValueFree(sqlite3_value*); +sqlite3_value *sqlite3ValueNew(sqlite3 *); +char *sqlite3Utf16to8(sqlite3 *, const void*, int); +int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **); +void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8); +#ifndef SQLITE_AMALGAMATION +extern const unsigned char sqlite3UpperToLower[]; +extern struct Sqlite3Config sqlite3Config; +#endif +void sqlite3RootPageMoved(Db*, int, int); +void sqlite3Reindex(Parse*, Token*, Token*); +void sqlite3AlterFunctions(sqlite3*); +void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); +int sqlite3GetToken(const unsigned char *, int *); +void sqlite3NestedParse(Parse*, const char*, ...); +void sqlite3ExpirePreparedStatements(sqlite3*); +void sqlite3CodeSubselect(Parse *, Expr *, int); +int sqlite3SelectResolve(Parse *, Select *, NameContext *); +void sqlite3ColumnDefault(Vdbe *, Table *, int); +void sqlite3AlterFinishAddColumn(Parse *, Token *); +void sqlite3AlterBeginAddColumn(Parse *, SrcList *); +CollSeq *sqlite3GetCollSeq(sqlite3*, CollSeq *, const char *, int); +char sqlite3AffinityType(const Token*); +void sqlite3Analyze(Parse*, Token*, Token*); +int sqlite3InvokeBusyHandler(BusyHandler*); +int sqlite3FindDb(sqlite3*, Token*); +int sqlite3AnalysisLoad(sqlite3*,int iDB); +void sqlite3DefaultRowEst(Index*); +void sqlite3RegisterLikeFunctions(sqlite3*, int); +int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*); +void sqlite3AttachFunctions(sqlite3 *); +void sqlite3MinimumFileFormat(Parse*, int, int); +void sqlite3SchemaFree(void *); +Schema *sqlite3SchemaGet(sqlite3 *, Btree *); +int sqlite3SchemaToIndex(sqlite3 *db, Schema *); +KeyInfo *sqlite3IndexKeyinfo(Parse *, Index *); +int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, + void (*)(sqlite3_context*,int,sqlite3_value **), + void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*)); +int sqlite3ApiExit(sqlite3 *db, int); +int sqlite3OpenTempDatabase(Parse *); + +void sqlite3StrAccumInit(StrAccum*, char*, int, int); +void sqlite3StrAccumAppend(StrAccum*,const char*,int); +char *sqlite3StrAccumFinish(StrAccum*); +void sqlite3StrAccumReset(StrAccum*); +void sqlite3SelectDestInit(SelectDest*,int,int); + +/* +** The interface to the LEMON-generated parser +*/ +void *sqlite3ParserAlloc(void*(*)(size_t)); +void sqlite3ParserFree(void*, void(*)(void*)); +void sqlite3Parser(void*, int, Token, Parse*); +#ifdef YYTRACKMAXSTACKDEPTH + int sqlite3ParserStackPeak(void*); +#endif + +int sqlite3AutoLoadExtensions(sqlite3*); +#ifndef SQLITE_OMIT_LOAD_EXTENSION + void sqlite3CloseExtensions(sqlite3*); +#else +# define sqlite3CloseExtensions(X) +#endif + +#ifndef SQLITE_OMIT_SHARED_CACHE + void sqlite3TableLock(Parse *, int, int, u8, const char *); +#else + #define sqlite3TableLock(v,w,x,y,z) +#endif + +#ifdef SQLITE_TEST + int sqlite3Utf8To8(unsigned char*); +#endif + +#ifdef SQLITE_OMIT_VIRTUALTABLE +# define sqlite3VtabClear(X) +# define sqlite3VtabSync(X,Y) SQLITE_OK +# define sqlite3VtabRollback(X) +# define sqlite3VtabCommit(X) +#else + void sqlite3VtabClear(Table*); + int sqlite3VtabSync(sqlite3 *db, char **); + int sqlite3VtabRollback(sqlite3 *db); + int sqlite3VtabCommit(sqlite3 *db); +#endif +void sqlite3VtabMakeWritable(Parse*,Table*); +void sqlite3VtabLock(sqlite3_vtab*); +void sqlite3VtabUnlock(sqlite3*, sqlite3_vtab*); +void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*); +void sqlite3VtabFinishParse(Parse*, Token*); +void sqlite3VtabArgInit(Parse*); +void sqlite3VtabArgExtend(Parse*, Token*); +int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **); +int sqlite3VtabCallConnect(Parse*, Table*); +int sqlite3VtabCallDestroy(sqlite3*, int, const char *); +int sqlite3VtabBegin(sqlite3 *, sqlite3_vtab *); +FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*); +void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**); +int sqlite3Reprepare(Vdbe*); +void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*); +CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *); + + +/* +** Available fault injectors. Should be numbered beginning with 0. +*/ +#define SQLITE_FAULTINJECTOR_MALLOC 0 +#define SQLITE_FAULTINJECTOR_COUNT 1 + +/* +** The interface to the code in fault.c used for identifying "benign" +** malloc failures. This is only present if SQLITE_OMIT_BUILTIN_TEST +** is not defined. +*/ +#ifndef SQLITE_OMIT_BUILTIN_TEST + void sqlite3BeginBenignMalloc(void); + void sqlite3EndBenignMalloc(void); +#else + #define sqlite3BeginBenignMalloc() + #define sqlite3EndBenignMalloc() +#endif + +#define IN_INDEX_ROWID 1 +#define IN_INDEX_EPH 2 +#define IN_INDEX_INDEX 3 +int sqlite3FindInIndex(Parse *, Expr *, int*); + +#ifdef SQLITE_ENABLE_ATOMIC_WRITE + int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int); + int sqlite3JournalSize(sqlite3_vfs *); + int sqlite3JournalCreate(sqlite3_file *); +#else + #define sqlite3JournalSize(pVfs) ((pVfs)->szOsFile) +#endif + +#if SQLITE_MAX_EXPR_DEPTH>0 + void sqlite3ExprSetHeight(Parse *pParse, Expr *p); + int sqlite3SelectExprHeight(Select *); +#else + #define sqlite3ExprSetHeight(x,y) + #define sqlite3SelectExprHeight(x) 0 +#endif + +u32 sqlite3Get4byte(const u8*); +void sqlite3Put4byte(u8*, u32); + +#ifdef SQLITE_SSE +#include "sseInt.h" +#endif + +#ifdef SQLITE_DEBUG + void sqlite3ParserTrace(FILE*, char *); +#endif + +/* +** If the SQLITE_ENABLE IOTRACE exists then the global variable +** sqlite3IoTrace is a pointer to a printf-like routine used to +** print I/O tracing messages. +*/ +#ifdef SQLITE_ENABLE_IOTRACE +# define IOTRACE(A) if( sqlite3IoTrace ){ sqlite3IoTrace A; } + void sqlite3VdbeIOTraceSql(Vdbe*); +SQLITE_EXTERN void (*sqlite3IoTrace)(const char*,...); +#else +# define IOTRACE(A) +# define sqlite3VdbeIOTraceSql(X) +#endif + +#endif diff --git a/third_party/sqlite/src/sqliteLimit.h b/third_party/sqlite/src/sqliteLimit.h new file mode 100755 index 0000000..a1307de --- /dev/null +++ b/third_party/sqlite/src/sqliteLimit.h @@ -0,0 +1,183 @@ +/* +** 2007 May 7 +** +** 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 defines various limits of what SQLite can process. +** +** @(#) $Id: sqliteLimit.h,v 1.8 2008/03/26 15:56:22 drh Exp $ +*/ + +/* +** The maximum length of a TEXT or BLOB in bytes. This also +** limits the size of a row in a table or index. +** +** The hard limit is the ability of a 32-bit signed integer +** to count the size: 2^31-1 or 2147483647. +*/ +#ifndef SQLITE_MAX_LENGTH +# define SQLITE_MAX_LENGTH 1000000000 +#endif + +/* +** This is the maximum number of +** +** * Columns in a table +** * Columns in an index +** * Columns in a view +** * Terms in the SET clause of an UPDATE statement +** * Terms in the result set of a SELECT statement +** * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement. +** * Terms in the VALUES clause of an INSERT statement +** +** The hard upper limit here is 32676. Most database people will +** tell you that in a well-normalized database, you usually should +** not have more than a dozen or so columns in any table. And if +** that is the case, there is no point in having more than a few +** dozen values in any of the other situations described above. +*/ +#ifndef SQLITE_MAX_COLUMN +# define SQLITE_MAX_COLUMN 2000 +#endif + +/* +** The maximum length of a single SQL statement in bytes. +** +** It used to be the case that setting this value to zero would +** turn the limit off. That is no longer true. It is not possible +** to turn this limit off. +*/ +#ifndef SQLITE_MAX_SQL_LENGTH +# define SQLITE_MAX_SQL_LENGTH 1000000000 +#endif + +/* +** The maximum depth of an expression tree. This is limited to +** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might +** want to place more severe limits on the complexity of an +** expression. +** +** A value of 0 used to mean that the limit was not enforced. +** But that is no longer true. The limit is now strictly enforced +** at all times. +*/ +#ifndef SQLITE_MAX_EXPR_DEPTH +# define SQLITE_MAX_EXPR_DEPTH 1000 +#endif + +/* +** The maximum number of terms in a compound SELECT statement. +** The code generator for compound SELECT statements does one +** level of recursion for each term. A stack overflow can result +** if the number of terms is too large. In practice, most SQL +** never has more than 3 or 4 terms. Use a value of 0 to disable +** any limit on the number of terms in a compount SELECT. +*/ +#ifndef SQLITE_MAX_COMPOUND_SELECT +# define SQLITE_MAX_COMPOUND_SELECT 500 +#endif + +/* +** The maximum number of opcodes in a VDBE program. +** Not currently enforced. +*/ +#ifndef SQLITE_MAX_VDBE_OP +# define SQLITE_MAX_VDBE_OP 25000 +#endif + +/* +** The maximum number of arguments to an SQL function. +*/ +#ifndef SQLITE_MAX_FUNCTION_ARG +# define SQLITE_MAX_FUNCTION_ARG 100 +#endif + +/* +** The maximum number of in-memory pages to use for the main database +** table and for temporary tables. The SQLITE_DEFAULT_CACHE_SIZE +*/ +#ifndef SQLITE_DEFAULT_CACHE_SIZE +# define SQLITE_DEFAULT_CACHE_SIZE 2000 +#endif +#ifndef SQLITE_DEFAULT_TEMP_CACHE_SIZE +# define SQLITE_DEFAULT_TEMP_CACHE_SIZE 500 +#endif + +/* +** The maximum number of attached databases. This must be between 0 +** and 30. The upper bound on 30 is because a 32-bit integer bitmap +** is used internally to track attached databases. +*/ +#ifndef SQLITE_MAX_ATTACHED +# define SQLITE_MAX_ATTACHED 10 +#endif + + +/* +** The maximum value of a ?nnn wildcard that the parser will accept. +*/ +#ifndef SQLITE_MAX_VARIABLE_NUMBER +# define SQLITE_MAX_VARIABLE_NUMBER 999 +#endif + +/* Maximum page size. The upper bound on this value is 32768. This a limit +** imposed by the necessity of storing the value in a 2-byte unsigned integer +** and the fact that the page size must be a power of 2. +*/ +#ifndef SQLITE_MAX_PAGE_SIZE +# define SQLITE_MAX_PAGE_SIZE 32768 +#endif + + +/* +** The default size of a database page. +*/ +#ifndef SQLITE_DEFAULT_PAGE_SIZE +# define SQLITE_DEFAULT_PAGE_SIZE 1024 +#endif +#if SQLITE_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE +# undef SQLITE_DEFAULT_PAGE_SIZE +# define SQLITE_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE +#endif + +/* +** Ordinarily, if no value is explicitly provided, SQLite creates databases +** with page size SQLITE_DEFAULT_PAGE_SIZE. However, based on certain +** device characteristics (sector-size and atomic write() support), +** SQLite may choose a larger value. This constant is the maximum value +** SQLite will choose on its own. +*/ +#ifndef SQLITE_MAX_DEFAULT_PAGE_SIZE +# define SQLITE_MAX_DEFAULT_PAGE_SIZE 8192 +#endif +#if SQLITE_MAX_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE +# undef SQLITE_MAX_DEFAULT_PAGE_SIZE +# define SQLITE_MAX_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE +#endif + + +/* +** Maximum number of pages in one database file. +** +** This is really just the default value for the max_page_count pragma. +** This value can be lowered (or raised) at run-time using that the +** max_page_count macro. +*/ +#ifndef SQLITE_MAX_PAGE_COUNT +# define SQLITE_MAX_PAGE_COUNT 1073741823 +#endif + +/* +** Maximum length (in bytes) of the pattern in a LIKE or GLOB +** operator. +*/ +#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH +# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000 +#endif diff --git a/third_party/sqlite/src/status.c b/third_party/sqlite/src/status.c new file mode 100755 index 0000000..a60a853 --- /dev/null +++ b/third_party/sqlite/src/status.c @@ -0,0 +1,111 @@ +/* +** 2008 June 18 +** +** 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 module implements the sqlite3_status() interface and related +** functionality. +** +** $Id: status.c,v 1.7 2008/08/05 17:53:23 drh Exp $ +*/ +#include "sqliteInt.h" + +/* +** Variables in which to record status information. +*/ +static struct { + int nowValue[9]; /* Current value */ + int mxValue[9]; /* Maximum value */ +} sqlite3Stat; + + +/* +** Reset the status records. This routine is called by +** sqlite3_initialize(). +*/ +void sqlite3StatusReset(void){ + memset(&sqlite3Stat, 0, sizeof(sqlite3Stat)); +} + +/* +** Return the current value of a status parameter. +*/ +int sqlite3StatusValue(int op){ + assert( op>=0 && op<ArraySize(sqlite3Stat.nowValue) ); + return sqlite3Stat.nowValue[op]; +} + +/* +** Add N to the value of a status record. It is assumed that the +** caller holds appropriate locks. +*/ +void sqlite3StatusAdd(int op, int N){ + assert( op>=0 && op<ArraySize(sqlite3Stat.nowValue) ); + sqlite3Stat.nowValue[op] += N; + if( sqlite3Stat.nowValue[op]>sqlite3Stat.mxValue[op] ){ + sqlite3Stat.mxValue[op] = sqlite3Stat.nowValue[op]; + } +} + +/* +** Set the value of a status to X. +*/ +void sqlite3StatusSet(int op, int X){ + assert( op>=0 && op<ArraySize(sqlite3Stat.nowValue) ); + sqlite3Stat.nowValue[op] = X; + if( sqlite3Stat.nowValue[op]>sqlite3Stat.mxValue[op] ){ + sqlite3Stat.mxValue[op] = sqlite3Stat.nowValue[op]; + } +} + +/* +** Query status information. +** +** This implementation assumes that reading or writing an aligned +** 32-bit integer is an atomic operation. If that assumption is not true, +** then this routine is not threadsafe. +*/ +int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){ + if( op<0 || op>=ArraySize(sqlite3Stat.nowValue) ){ + return SQLITE_MISUSE; + } + *pCurrent = sqlite3Stat.nowValue[op]; + *pHighwater = sqlite3Stat.mxValue[op]; + if( resetFlag ){ + sqlite3Stat.mxValue[op] = sqlite3Stat.nowValue[op]; + } + return SQLITE_OK; +} + +/* +** Query status information for a single database connection +*/ +int sqlite3_db_status( + sqlite3 *db, /* The database connection whose status is desired */ + int op, /* Status verb */ + int *pCurrent, /* Write current value here */ + int *pHighwater, /* Write high-water mark here */ + int resetFlag /* Reset high-water mark if true */ +){ + switch( op ){ + case SQLITE_DBSTATUS_LOOKASIDE_USED: { + *pCurrent = db->lookaside.nOut; + *pHighwater = db->lookaside.mxOut; + if( resetFlag ){ + db->lookaside.mxOut = db->lookaside.nOut; + } + break; + } + default: { + return SQLITE_ERROR; + } + } + return SQLITE_OK; +} diff --git a/third_party/sqlite/src/table.c b/third_party/sqlite/src/table.c new file mode 100755 index 0000000..1bd1bd1 --- /dev/null +++ b/third_party/sqlite/src/table.c @@ -0,0 +1,201 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains the sqlite3_get_table() and sqlite3_free_table() +** interface routines. These are just wrappers around the main +** interface routine of sqlite3_exec(). +** +** These routines are in a separate files so that they will not be linked +** if they are not used. +** +** $Id: table.c,v 1.36 2008/07/08 22:28:49 shane Exp $ +*/ +#include "sqliteInt.h" +#include <stdlib.h> +#include <string.h> + +#ifndef SQLITE_OMIT_GET_TABLE + +/* +** This structure is used to pass data from sqlite3_get_table() through +** to the callback function is uses to build the result. +*/ +typedef struct TabResult { + char **azResult; + char *zErrMsg; + int nResult; + int nAlloc; + int nRow; + int nColumn; + int nData; + int rc; +} TabResult; + +/* +** This routine is called once for each row in the result table. Its job +** is to fill in the TabResult structure appropriately, allocating new +** memory as necessary. +*/ +static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){ + TabResult *p = (TabResult*)pArg; + int need; + int i; + char *z; + + /* Make sure there is enough space in p->azResult to hold everything + ** we need to remember from this invocation of the callback. + */ + if( p->nRow==0 && argv!=0 ){ + need = nCol*2; + }else{ + need = nCol; + } + if( p->nData + need >= p->nAlloc ){ + char **azNew; + p->nAlloc = p->nAlloc*2 + need + 1; + azNew = sqlite3_realloc( p->azResult, sizeof(char*)*p->nAlloc ); + if( azNew==0 ) goto malloc_failed; + p->azResult = azNew; + } + + /* If this is the first row, then generate an extra row containing + ** the names of all columns. + */ + if( p->nRow==0 ){ + p->nColumn = nCol; + for(i=0; i<nCol; i++){ + z = sqlite3_mprintf("%s", colv[i]); + if( z==0 ) goto malloc_failed; + p->azResult[p->nData++] = z; + } + }else if( p->nColumn!=nCol ){ + sqlite3_free(p->zErrMsg); + p->zErrMsg = sqlite3_mprintf( + "sqlite3_get_table() called with two or more incompatible queries" + ); + p->rc = SQLITE_ERROR; + return 1; + } + + /* Copy over the row data + */ + if( argv!=0 ){ + for(i=0; i<nCol; i++){ + if( argv[i]==0 ){ + z = 0; + }else{ + int n = strlen(argv[i])+1; + z = sqlite3_malloc( n ); + if( z==0 ) goto malloc_failed; + memcpy(z, argv[i], n); + } + p->azResult[p->nData++] = z; + } + p->nRow++; + } + return 0; + +malloc_failed: + p->rc = SQLITE_NOMEM; + return 1; +} + +/* +** Query the database. But instead of invoking a callback for each row, +** malloc() for space to hold the result and return the entire results +** at the conclusion of the call. +** +** The result that is written to ***pazResult is held in memory obtained +** from malloc(). But the caller cannot free this memory directly. +** Instead, the entire table should be passed to sqlite3_free_table() when +** the calling procedure is finished using it. +*/ +int sqlite3_get_table( + sqlite3 *db, /* The database on which the SQL executes */ + const char *zSql, /* The SQL to be executed */ + char ***pazResult, /* Write the result table here */ + int *pnRow, /* Write the number of rows in the result here */ + int *pnColumn, /* Write the number of columns of result here */ + char **pzErrMsg /* Write error messages here */ +){ + int rc; + TabResult res; + + *pazResult = 0; + if( pnColumn ) *pnColumn = 0; + if( pnRow ) *pnRow = 0; + res.zErrMsg = 0; + res.nResult = 0; + res.nRow = 0; + res.nColumn = 0; + res.nData = 1; + res.nAlloc = 20; + res.rc = SQLITE_OK; + res.azResult = sqlite3_malloc(sizeof(char*)*res.nAlloc ); + if( res.azResult==0 ){ + db->errCode = SQLITE_NOMEM; + return SQLITE_NOMEM; + } + res.azResult[0] = 0; + rc = sqlite3_exec(db, zSql, sqlite3_get_table_cb, &res, pzErrMsg); + assert( sizeof(res.azResult[0])>= sizeof(res.nData) ); + res.azResult[0] = SQLITE_INT_TO_PTR(res.nData); + if( (rc&0xff)==SQLITE_ABORT ){ + sqlite3_free_table(&res.azResult[1]); + if( res.zErrMsg ){ + if( pzErrMsg ){ + sqlite3_free(*pzErrMsg); + *pzErrMsg = sqlite3_mprintf("%s",res.zErrMsg); + } + sqlite3_free(res.zErrMsg); + } + db->errCode = res.rc; /* Assume 32-bit assignment is atomic */ + return res.rc; + } + sqlite3_free(res.zErrMsg); + if( rc!=SQLITE_OK ){ + sqlite3_free_table(&res.azResult[1]); + return rc; + } + if( res.nAlloc>res.nData ){ + char **azNew; + azNew = sqlite3_realloc( res.azResult, sizeof(char*)*(res.nData+1) ); + if( azNew==0 ){ + sqlite3_free_table(&res.azResult[1]); + db->errCode = SQLITE_NOMEM; + return SQLITE_NOMEM; + } + res.nAlloc = res.nData+1; + res.azResult = azNew; + } + *pazResult = &res.azResult[1]; + if( pnColumn ) *pnColumn = res.nColumn; + if( pnRow ) *pnRow = res.nRow; + return rc; +} + +/* +** This routine frees the space the sqlite3_get_table() malloced. +*/ +void sqlite3_free_table( + char **azResult /* Result returned from from sqlite3_get_table() */ +){ + if( azResult ){ + int i, n; + azResult--; + assert( azResult!=0 ); + n = SQLITE_PTR_TO_INT(azResult[0]); + for(i=1; i<n; i++){ if( azResult[i] ) sqlite3_free(azResult[i]); } + sqlite3_free(azResult); + } +} + +#endif /* SQLITE_OMIT_GET_TABLE */ diff --git a/third_party/sqlite/src/tclsqlite.c b/third_party/sqlite/src/tclsqlite.c new file mode 100755 index 0000000..35a69b8 --- /dev/null +++ b/third_party/sqlite/src/tclsqlite.c @@ -0,0 +1,2599 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** A TCL Interface to SQLite. Append this file to sqlite3.c and +** compile the whole thing to build a TCL-enabled version of SQLite. +** +** $Id: tclsqlite.c,v 1.219 2008/07/10 17:52:49 danielk1977 Exp $ +*/ +#include "tcl.h" +#include <errno.h> + +/* +** Some additional include files are needed if this file is not +** appended to the amalgamation. +*/ +#ifndef SQLITE_AMALGAMATION +# include "sqliteInt.h" +# include <stdlib.h> +# include <string.h> +# include <assert.h> +# include <ctype.h> +#endif + +/* + * Windows needs to know which symbols to export. Unix does not. + * BUILD_sqlite should be undefined for Unix. + */ +#ifdef BUILD_sqlite +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLEXPORT +#endif /* BUILD_sqlite */ + +#define NUM_PREPARED_STMTS 10 +#define MAX_PREPARED_STMTS 100 + +/* +** If TCL uses UTF-8 and SQLite is configured to use iso8859, then we +** have to do a translation when going between the two. Set the +** UTF_TRANSLATION_NEEDED macro to indicate that we need to do +** this translation. +*/ +#if defined(TCL_UTF_MAX) && !defined(SQLITE_UTF8) +# define UTF_TRANSLATION_NEEDED 1 +#endif + +/* +** New SQL functions can be created as TCL scripts. Each such function +** is described by an instance of the following structure. +*/ +typedef struct SqlFunc SqlFunc; +struct SqlFunc { + Tcl_Interp *interp; /* The TCL interpret to execute the function */ + Tcl_Obj *pScript; /* The Tcl_Obj representation of the script */ + int useEvalObjv; /* True if it is safe to use Tcl_EvalObjv */ + char *zName; /* Name of this function */ + SqlFunc *pNext; /* Next function on the list of them all */ +}; + +/* +** New collation sequences function can be created as TCL scripts. Each such +** function is described by an instance of the following structure. +*/ +typedef struct SqlCollate SqlCollate; +struct SqlCollate { + Tcl_Interp *interp; /* The TCL interpret to execute the function */ + char *zScript; /* The script to be run */ + SqlCollate *pNext; /* Next function on the list of them all */ +}; + +/* +** Prepared statements are cached for faster execution. Each prepared +** statement is described by an instance of the following structure. +*/ +typedef struct SqlPreparedStmt SqlPreparedStmt; +struct SqlPreparedStmt { + SqlPreparedStmt *pNext; /* Next in linked list */ + SqlPreparedStmt *pPrev; /* Previous on the list */ + sqlite3_stmt *pStmt; /* The prepared statement */ + int nSql; /* chars in zSql[] */ + const char *zSql; /* Text of the SQL statement */ +}; + +typedef struct IncrblobChannel IncrblobChannel; + +/* +** There is one instance of this structure for each SQLite database +** that has been opened by the SQLite TCL interface. +*/ +typedef struct SqliteDb SqliteDb; +struct SqliteDb { + sqlite3 *db; /* The "real" database structure. MUST BE FIRST */ + Tcl_Interp *interp; /* The interpreter used for this database */ + char *zBusy; /* The busy callback routine */ + char *zCommit; /* The commit hook callback routine */ + char *zTrace; /* The trace callback routine */ + char *zProfile; /* The profile callback routine */ + char *zProgress; /* The progress callback routine */ + char *zAuth; /* The authorization callback routine */ + char *zNull; /* Text to substitute for an SQL NULL value */ + SqlFunc *pFunc; /* List of SQL functions */ + Tcl_Obj *pUpdateHook; /* Update hook script (if any) */ + Tcl_Obj *pRollbackHook; /* Rollback hook script (if any) */ + SqlCollate *pCollate; /* List of SQL collation functions */ + int rc; /* Return code of most recent sqlite3_exec() */ + Tcl_Obj *pCollateNeeded; /* Collation needed script */ + SqlPreparedStmt *stmtList; /* List of prepared statements*/ + SqlPreparedStmt *stmtLast; /* Last statement in the list */ + int maxStmt; /* The next maximum number of stmtList */ + int nStmt; /* Number of statements in stmtList */ + IncrblobChannel *pIncrblob;/* Linked list of open incrblob channels */ +}; + +struct IncrblobChannel { + sqlite3_blob *pBlob; /* sqlite3 blob handle */ + SqliteDb *pDb; /* Associated database connection */ + int iSeek; /* Current seek offset */ + Tcl_Channel channel; /* Channel identifier */ + IncrblobChannel *pNext; /* Linked list of all open incrblob channels */ + IncrblobChannel *pPrev; /* Linked list of all open incrblob channels */ +}; + +#ifndef SQLITE_OMIT_INCRBLOB +/* +** Close all incrblob channels opened using database connection pDb. +** This is called when shutting down the database connection. +*/ +static void closeIncrblobChannels(SqliteDb *pDb){ + IncrblobChannel *p; + IncrblobChannel *pNext; + + for(p=pDb->pIncrblob; p; p=pNext){ + pNext = p->pNext; + + /* Note: Calling unregister here call Tcl_Close on the incrblob channel, + ** which deletes the IncrblobChannel structure at *p. So do not + ** call Tcl_Free() here. + */ + Tcl_UnregisterChannel(pDb->interp, p->channel); + } +} + +/* +** Close an incremental blob channel. +*/ +static int incrblobClose(ClientData instanceData, Tcl_Interp *interp){ + IncrblobChannel *p = (IncrblobChannel *)instanceData; + int rc = sqlite3_blob_close(p->pBlob); + sqlite3 *db = p->pDb->db; + + /* Remove the channel from the SqliteDb.pIncrblob list. */ + if( p->pNext ){ + p->pNext->pPrev = p->pPrev; + } + if( p->pPrev ){ + p->pPrev->pNext = p->pNext; + } + if( p->pDb->pIncrblob==p ){ + p->pDb->pIncrblob = p->pNext; + } + + /* Free the IncrblobChannel structure */ + Tcl_Free((char *)p); + + if( rc!=SQLITE_OK ){ + Tcl_SetResult(interp, (char *)sqlite3_errmsg(db), TCL_VOLATILE); + return TCL_ERROR; + } + return TCL_OK; +} + +/* +** Read data from an incremental blob channel. +*/ +static int incrblobInput( + ClientData instanceData, + char *buf, + int bufSize, + int *errorCodePtr +){ + IncrblobChannel *p = (IncrblobChannel *)instanceData; + int nRead = bufSize; /* Number of bytes to read */ + int nBlob; /* Total size of the blob */ + int rc; /* sqlite error code */ + + nBlob = sqlite3_blob_bytes(p->pBlob); + if( (p->iSeek+nRead)>nBlob ){ + nRead = nBlob-p->iSeek; + } + if( nRead<=0 ){ + return 0; + } + + rc = sqlite3_blob_read(p->pBlob, (void *)buf, nRead, p->iSeek); + if( rc!=SQLITE_OK ){ + *errorCodePtr = rc; + return -1; + } + + p->iSeek += nRead; + return nRead; +} + +/* +** Write data to an incremental blob channel. +*/ +static int incrblobOutput( + ClientData instanceData, + CONST char *buf, + int toWrite, + int *errorCodePtr +){ + IncrblobChannel *p = (IncrblobChannel *)instanceData; + int nWrite = toWrite; /* Number of bytes to write */ + int nBlob; /* Total size of the blob */ + int rc; /* sqlite error code */ + + nBlob = sqlite3_blob_bytes(p->pBlob); + if( (p->iSeek+nWrite)>nBlob ){ + *errorCodePtr = EINVAL; + return -1; + } + if( nWrite<=0 ){ + return 0; + } + + rc = sqlite3_blob_write(p->pBlob, (void *)buf, nWrite, p->iSeek); + if( rc!=SQLITE_OK ){ + *errorCodePtr = EIO; + return -1; + } + + p->iSeek += nWrite; + return nWrite; +} + +/* +** Seek an incremental blob channel. +*/ +static int incrblobSeek( + ClientData instanceData, + long offset, + int seekMode, + int *errorCodePtr +){ + IncrblobChannel *p = (IncrblobChannel *)instanceData; + + switch( seekMode ){ + case SEEK_SET: + p->iSeek = offset; + break; + case SEEK_CUR: + p->iSeek += offset; + break; + case SEEK_END: + p->iSeek = sqlite3_blob_bytes(p->pBlob) + offset; + break; + + default: assert(!"Bad seekMode"); + } + + return p->iSeek; +} + + +static void incrblobWatch(ClientData instanceData, int mode){ + /* NO-OP */ +} +static int incrblobHandle(ClientData instanceData, int dir, ClientData *hPtr){ + return TCL_ERROR; +} + +static Tcl_ChannelType IncrblobChannelType = { + "incrblob", /* typeName */ + TCL_CHANNEL_VERSION_2, /* version */ + incrblobClose, /* closeProc */ + incrblobInput, /* inputProc */ + incrblobOutput, /* outputProc */ + incrblobSeek, /* seekProc */ + 0, /* setOptionProc */ + 0, /* getOptionProc */ + incrblobWatch, /* watchProc (this is a no-op) */ + incrblobHandle, /* getHandleProc (always returns error) */ + 0, /* close2Proc */ + 0, /* blockModeProc */ + 0, /* flushProc */ + 0, /* handlerProc */ + 0, /* wideSeekProc */ +}; + +/* +** Create a new incrblob channel. +*/ +static int createIncrblobChannel( + Tcl_Interp *interp, + SqliteDb *pDb, + const char *zDb, + const char *zTable, + const char *zColumn, + sqlite_int64 iRow, + int isReadonly +){ + IncrblobChannel *p; + sqlite3 *db = pDb->db; + sqlite3_blob *pBlob; + int rc; + int flags = TCL_READABLE|(isReadonly ? 0 : TCL_WRITABLE); + + /* This variable is used to name the channels: "incrblob_[incr count]" */ + static int count = 0; + char zChannel[64]; + + rc = sqlite3_blob_open(db, zDb, zTable, zColumn, iRow, !isReadonly, &pBlob); + if( rc!=SQLITE_OK ){ + Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE); + return TCL_ERROR; + } + + p = (IncrblobChannel *)Tcl_Alloc(sizeof(IncrblobChannel)); + p->iSeek = 0; + p->pBlob = pBlob; + + sqlite3_snprintf(sizeof(zChannel), zChannel, "incrblob_%d", ++count); + p->channel = Tcl_CreateChannel(&IncrblobChannelType, zChannel, p, flags); + Tcl_RegisterChannel(interp, p->channel); + + /* Link the new channel into the SqliteDb.pIncrblob list. */ + p->pNext = pDb->pIncrblob; + p->pPrev = 0; + if( p->pNext ){ + p->pNext->pPrev = p; + } + pDb->pIncrblob = p; + p->pDb = pDb; + + Tcl_SetResult(interp, (char *)Tcl_GetChannelName(p->channel), TCL_VOLATILE); + return TCL_OK; +} +#else /* else clause for "#ifndef SQLITE_OMIT_INCRBLOB" */ + #define closeIncrblobChannels(pDb) +#endif + +/* +** Look at the script prefix in pCmd. We will be executing this script +** after first appending one or more arguments. This routine analyzes +** the script to see if it is safe to use Tcl_EvalObjv() on the script +** rather than the more general Tcl_EvalEx(). Tcl_EvalObjv() is much +** faster. +** +** Scripts that are safe to use with Tcl_EvalObjv() consists of a +** command name followed by zero or more arguments with no [...] or $ +** or {...} or ; to be seen anywhere. Most callback scripts consist +** of just a single procedure name and they meet this requirement. +*/ +static int safeToUseEvalObjv(Tcl_Interp *interp, Tcl_Obj *pCmd){ + /* We could try to do something with Tcl_Parse(). But we will instead + ** just do a search for forbidden characters. If any of the forbidden + ** characters appear in pCmd, we will report the string as unsafe. + */ + const char *z; + int n; + z = Tcl_GetStringFromObj(pCmd, &n); + while( n-- > 0 ){ + int c = *(z++); + if( c=='$' || c=='[' || c==';' ) return 0; + } + return 1; +} + +/* +** Find an SqlFunc structure with the given name. Or create a new +** one if an existing one cannot be found. Return a pointer to the +** structure. +*/ +static SqlFunc *findSqlFunc(SqliteDb *pDb, const char *zName){ + SqlFunc *p, *pNew; + int i; + pNew = (SqlFunc*)Tcl_Alloc( sizeof(*pNew) + strlen(zName) + 1 ); + pNew->zName = (char*)&pNew[1]; + for(i=0; zName[i]; i++){ pNew->zName[i] = tolower(zName[i]); } + pNew->zName[i] = 0; + for(p=pDb->pFunc; p; p=p->pNext){ + if( strcmp(p->zName, pNew->zName)==0 ){ + Tcl_Free((char*)pNew); + return p; + } + } + pNew->interp = pDb->interp; + pNew->pScript = 0; + pNew->pNext = pDb->pFunc; + pDb->pFunc = pNew; + return pNew; +} + +/* +** Finalize and free a list of prepared statements +*/ +static void flushStmtCache( SqliteDb *pDb ){ + SqlPreparedStmt *pPreStmt; + + while( pDb->stmtList ){ + sqlite3_finalize( pDb->stmtList->pStmt ); + pPreStmt = pDb->stmtList; + pDb->stmtList = pDb->stmtList->pNext; + Tcl_Free( (char*)pPreStmt ); + } + pDb->nStmt = 0; + pDb->stmtLast = 0; +} + +/* +** TCL calls this procedure when an sqlite3 database command is +** deleted. +*/ +static void DbDeleteCmd(void *db){ + SqliteDb *pDb = (SqliteDb*)db; + flushStmtCache(pDb); + closeIncrblobChannels(pDb); + sqlite3_close(pDb->db); + while( pDb->pFunc ){ + SqlFunc *pFunc = pDb->pFunc; + pDb->pFunc = pFunc->pNext; + Tcl_DecrRefCount(pFunc->pScript); + Tcl_Free((char*)pFunc); + } + while( pDb->pCollate ){ + SqlCollate *pCollate = pDb->pCollate; + pDb->pCollate = pCollate->pNext; + Tcl_Free((char*)pCollate); + } + if( pDb->zBusy ){ + Tcl_Free(pDb->zBusy); + } + if( pDb->zTrace ){ + Tcl_Free(pDb->zTrace); + } + if( pDb->zProfile ){ + Tcl_Free(pDb->zProfile); + } + if( pDb->zAuth ){ + Tcl_Free(pDb->zAuth); + } + if( pDb->zNull ){ + Tcl_Free(pDb->zNull); + } + if( pDb->pUpdateHook ){ + Tcl_DecrRefCount(pDb->pUpdateHook); + } + if( pDb->pRollbackHook ){ + Tcl_DecrRefCount(pDb->pRollbackHook); + } + if( pDb->pCollateNeeded ){ + Tcl_DecrRefCount(pDb->pCollateNeeded); + } + Tcl_Free((char*)pDb); +} + +/* +** This routine is called when a database file is locked while trying +** to execute SQL. +*/ +static int DbBusyHandler(void *cd, int nTries){ + SqliteDb *pDb = (SqliteDb*)cd; + int rc; + char zVal[30]; + + sqlite3_snprintf(sizeof(zVal), zVal, "%d", nTries); + rc = Tcl_VarEval(pDb->interp, pDb->zBusy, " ", zVal, (char*)0); + if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){ + return 0; + } + return 1; +} + +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK +/* +** This routine is invoked as the 'progress callback' for the database. +*/ +static int DbProgressHandler(void *cd){ + SqliteDb *pDb = (SqliteDb*)cd; + int rc; + + assert( pDb->zProgress ); + rc = Tcl_Eval(pDb->interp, pDb->zProgress); + if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){ + return 1; + } + return 0; +} +#endif + +#ifndef SQLITE_OMIT_TRACE +/* +** This routine is called by the SQLite trace handler whenever a new +** block of SQL is executed. The TCL script in pDb->zTrace is executed. +*/ +static void DbTraceHandler(void *cd, const char *zSql){ + SqliteDb *pDb = (SqliteDb*)cd; + Tcl_DString str; + + Tcl_DStringInit(&str); + Tcl_DStringAppend(&str, pDb->zTrace, -1); + Tcl_DStringAppendElement(&str, zSql); + Tcl_Eval(pDb->interp, Tcl_DStringValue(&str)); + Tcl_DStringFree(&str); + Tcl_ResetResult(pDb->interp); +} +#endif + +#ifndef SQLITE_OMIT_TRACE +/* +** This routine is called by the SQLite profile handler after a statement +** SQL has executed. The TCL script in pDb->zProfile is evaluated. +*/ +static void DbProfileHandler(void *cd, const char *zSql, sqlite_uint64 tm){ + SqliteDb *pDb = (SqliteDb*)cd; + Tcl_DString str; + char zTm[100]; + + sqlite3_snprintf(sizeof(zTm)-1, zTm, "%lld", tm); + Tcl_DStringInit(&str); + Tcl_DStringAppend(&str, pDb->zProfile, -1); + Tcl_DStringAppendElement(&str, zSql); + Tcl_DStringAppendElement(&str, zTm); + Tcl_Eval(pDb->interp, Tcl_DStringValue(&str)); + Tcl_DStringFree(&str); + Tcl_ResetResult(pDb->interp); +} +#endif + +/* +** This routine is called when a transaction is committed. The +** TCL script in pDb->zCommit is executed. If it returns non-zero or +** if it throws an exception, the transaction is rolled back instead +** of being committed. +*/ +static int DbCommitHandler(void *cd){ + SqliteDb *pDb = (SqliteDb*)cd; + int rc; + + rc = Tcl_Eval(pDb->interp, pDb->zCommit); + if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){ + return 1; + } + return 0; +} + +static void DbRollbackHandler(void *clientData){ + SqliteDb *pDb = (SqliteDb*)clientData; + assert(pDb->pRollbackHook); + if( TCL_OK!=Tcl_EvalObjEx(pDb->interp, pDb->pRollbackHook, 0) ){ + Tcl_BackgroundError(pDb->interp); + } +} + +static void DbUpdateHandler( + void *p, + int op, + const char *zDb, + const char *zTbl, + sqlite_int64 rowid +){ + SqliteDb *pDb = (SqliteDb *)p; + Tcl_Obj *pCmd; + + assert( pDb->pUpdateHook ); + assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE ); + + pCmd = Tcl_DuplicateObj(pDb->pUpdateHook); + Tcl_IncrRefCount(pCmd); + Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj( + ( (op==SQLITE_INSERT)?"INSERT":(op==SQLITE_UPDATE)?"UPDATE":"DELETE"), -1)); + Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zDb, -1)); + Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zTbl, -1)); + Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(rowid)); + Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT); +} + +static void tclCollateNeeded( + void *pCtx, + sqlite3 *db, + int enc, + const char *zName +){ + SqliteDb *pDb = (SqliteDb *)pCtx; + Tcl_Obj *pScript = Tcl_DuplicateObj(pDb->pCollateNeeded); + Tcl_IncrRefCount(pScript); + Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj(zName, -1)); + Tcl_EvalObjEx(pDb->interp, pScript, 0); + Tcl_DecrRefCount(pScript); +} + +/* +** This routine is called to evaluate an SQL collation function implemented +** using TCL script. +*/ +static int tclSqlCollate( + void *pCtx, + int nA, + const void *zA, + int nB, + const void *zB +){ + SqlCollate *p = (SqlCollate *)pCtx; + Tcl_Obj *pCmd; + + pCmd = Tcl_NewStringObj(p->zScript, -1); + Tcl_IncrRefCount(pCmd); + Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zA, nA)); + Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zB, nB)); + Tcl_EvalObjEx(p->interp, pCmd, TCL_EVAL_DIRECT); + Tcl_DecrRefCount(pCmd); + return (atoi(Tcl_GetStringResult(p->interp))); +} + +/* +** This routine is called to evaluate an SQL function implemented +** using TCL script. +*/ +static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){ + SqlFunc *p = sqlite3_user_data(context); + Tcl_Obj *pCmd; + int i; + int rc; + + if( argc==0 ){ + /* If there are no arguments to the function, call Tcl_EvalObjEx on the + ** script object directly. This allows the TCL compiler to generate + ** bytecode for the command on the first invocation and thus make + ** subsequent invocations much faster. */ + pCmd = p->pScript; + Tcl_IncrRefCount(pCmd); + rc = Tcl_EvalObjEx(p->interp, pCmd, 0); + Tcl_DecrRefCount(pCmd); + }else{ + /* If there are arguments to the function, make a shallow copy of the + ** script object, lappend the arguments, then evaluate the copy. + ** + ** By "shallow" copy, we mean a only the outer list Tcl_Obj is duplicated. + ** The new Tcl_Obj contains pointers to the original list elements. + ** That way, when Tcl_EvalObjv() is run and shimmers the first element + ** of the list to tclCmdNameType, that alternate representation will + ** be preserved and reused on the next invocation. + */ + Tcl_Obj **aArg; + int nArg; + if( Tcl_ListObjGetElements(p->interp, p->pScript, &nArg, &aArg) ){ + sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1); + return; + } + pCmd = Tcl_NewListObj(nArg, aArg); + Tcl_IncrRefCount(pCmd); + for(i=0; i<argc; i++){ + sqlite3_value *pIn = argv[i]; + Tcl_Obj *pVal; + + /* Set pVal to contain the i'th column of this row. */ + switch( sqlite3_value_type(pIn) ){ + case SQLITE_BLOB: { + int bytes = sqlite3_value_bytes(pIn); + pVal = Tcl_NewByteArrayObj(sqlite3_value_blob(pIn), bytes); + break; + } + case SQLITE_INTEGER: { + sqlite_int64 v = sqlite3_value_int64(pIn); + if( v>=-2147483647 && v<=2147483647 ){ + pVal = Tcl_NewIntObj(v); + }else{ + pVal = Tcl_NewWideIntObj(v); + } + break; + } + case SQLITE_FLOAT: { + double r = sqlite3_value_double(pIn); + pVal = Tcl_NewDoubleObj(r); + break; + } + case SQLITE_NULL: { + pVal = Tcl_NewStringObj("", 0); + break; + } + default: { + int bytes = sqlite3_value_bytes(pIn); + pVal = Tcl_NewStringObj((char *)sqlite3_value_text(pIn), bytes); + break; + } + } + rc = Tcl_ListObjAppendElement(p->interp, pCmd, pVal); + if( rc ){ + Tcl_DecrRefCount(pCmd); + sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1); + return; + } + } + if( !p->useEvalObjv ){ + /* Tcl_EvalObjEx() will automatically call Tcl_EvalObjv() if pCmd + ** is a list without a string representation. To prevent this from + ** happening, make sure pCmd has a valid string representation */ + Tcl_GetString(pCmd); + } + rc = Tcl_EvalObjEx(p->interp, pCmd, TCL_EVAL_DIRECT); + Tcl_DecrRefCount(pCmd); + } + + if( rc && rc!=TCL_RETURN ){ + sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1); + }else{ + Tcl_Obj *pVar = Tcl_GetObjResult(p->interp); + int n; + u8 *data; + char *zType = pVar->typePtr ? pVar->typePtr->name : ""; + char c = zType[0]; + if( c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0 ){ + /* Only return a BLOB type if the Tcl variable is a bytearray and + ** has no string representation. */ + data = Tcl_GetByteArrayFromObj(pVar, &n); + sqlite3_result_blob(context, data, n, SQLITE_TRANSIENT); + }else if( c=='b' && strcmp(zType,"boolean")==0 ){ + Tcl_GetIntFromObj(0, pVar, &n); + sqlite3_result_int(context, n); + }else if( c=='d' && strcmp(zType,"double")==0 ){ + double r; + Tcl_GetDoubleFromObj(0, pVar, &r); + sqlite3_result_double(context, r); + }else if( (c=='w' && strcmp(zType,"wideInt")==0) || + (c=='i' && strcmp(zType,"int")==0) ){ + Tcl_WideInt v; + Tcl_GetWideIntFromObj(0, pVar, &v); + sqlite3_result_int64(context, v); + }else{ + data = (unsigned char *)Tcl_GetStringFromObj(pVar, &n); + sqlite3_result_text(context, (char *)data, n, SQLITE_TRANSIENT); + } + } +} + +#ifndef SQLITE_OMIT_AUTHORIZATION +/* +** This is the authentication function. It appends the authentication +** type code and the two arguments to zCmd[] then invokes the result +** on the interpreter. The reply is examined to determine if the +** authentication fails or succeeds. +*/ +static int auth_callback( + void *pArg, + int code, + const char *zArg1, + const char *zArg2, + const char *zArg3, + const char *zArg4 +){ + char *zCode; + Tcl_DString str; + int rc; + const char *zReply; + SqliteDb *pDb = (SqliteDb*)pArg; + + switch( code ){ + case SQLITE_COPY : zCode="SQLITE_COPY"; break; + case SQLITE_CREATE_INDEX : zCode="SQLITE_CREATE_INDEX"; break; + case SQLITE_CREATE_TABLE : zCode="SQLITE_CREATE_TABLE"; break; + case SQLITE_CREATE_TEMP_INDEX : zCode="SQLITE_CREATE_TEMP_INDEX"; break; + case SQLITE_CREATE_TEMP_TABLE : zCode="SQLITE_CREATE_TEMP_TABLE"; break; + case SQLITE_CREATE_TEMP_TRIGGER: zCode="SQLITE_CREATE_TEMP_TRIGGER"; break; + case SQLITE_CREATE_TEMP_VIEW : zCode="SQLITE_CREATE_TEMP_VIEW"; break; + case SQLITE_CREATE_TRIGGER : zCode="SQLITE_CREATE_TRIGGER"; break; + case SQLITE_CREATE_VIEW : zCode="SQLITE_CREATE_VIEW"; break; + case SQLITE_DELETE : zCode="SQLITE_DELETE"; break; + case SQLITE_DROP_INDEX : zCode="SQLITE_DROP_INDEX"; break; + case SQLITE_DROP_TABLE : zCode="SQLITE_DROP_TABLE"; break; + case SQLITE_DROP_TEMP_INDEX : zCode="SQLITE_DROP_TEMP_INDEX"; break; + case SQLITE_DROP_TEMP_TABLE : zCode="SQLITE_DROP_TEMP_TABLE"; break; + case SQLITE_DROP_TEMP_TRIGGER : zCode="SQLITE_DROP_TEMP_TRIGGER"; break; + case SQLITE_DROP_TEMP_VIEW : zCode="SQLITE_DROP_TEMP_VIEW"; break; + case SQLITE_DROP_TRIGGER : zCode="SQLITE_DROP_TRIGGER"; break; + case SQLITE_DROP_VIEW : zCode="SQLITE_DROP_VIEW"; break; + case SQLITE_INSERT : zCode="SQLITE_INSERT"; break; + case SQLITE_PRAGMA : zCode="SQLITE_PRAGMA"; break; + case SQLITE_READ : zCode="SQLITE_READ"; break; + case SQLITE_SELECT : zCode="SQLITE_SELECT"; break; + case SQLITE_TRANSACTION : zCode="SQLITE_TRANSACTION"; break; + case SQLITE_UPDATE : zCode="SQLITE_UPDATE"; break; + case SQLITE_ATTACH : zCode="SQLITE_ATTACH"; break; + case SQLITE_DETACH : zCode="SQLITE_DETACH"; break; + case SQLITE_ALTER_TABLE : zCode="SQLITE_ALTER_TABLE"; break; + case SQLITE_REINDEX : zCode="SQLITE_REINDEX"; break; + case SQLITE_ANALYZE : zCode="SQLITE_ANALYZE"; break; + case SQLITE_CREATE_VTABLE : zCode="SQLITE_CREATE_VTABLE"; break; + case SQLITE_DROP_VTABLE : zCode="SQLITE_DROP_VTABLE"; break; + case SQLITE_FUNCTION : zCode="SQLITE_FUNCTION"; break; + default : zCode="????"; break; + } + Tcl_DStringInit(&str); + Tcl_DStringAppend(&str, pDb->zAuth, -1); + Tcl_DStringAppendElement(&str, zCode); + Tcl_DStringAppendElement(&str, zArg1 ? zArg1 : ""); + Tcl_DStringAppendElement(&str, zArg2 ? zArg2 : ""); + Tcl_DStringAppendElement(&str, zArg3 ? zArg3 : ""); + Tcl_DStringAppendElement(&str, zArg4 ? zArg4 : ""); + rc = Tcl_GlobalEval(pDb->interp, Tcl_DStringValue(&str)); + Tcl_DStringFree(&str); + zReply = Tcl_GetStringResult(pDb->interp); + if( strcmp(zReply,"SQLITE_OK")==0 ){ + rc = SQLITE_OK; + }else if( strcmp(zReply,"SQLITE_DENY")==0 ){ + rc = SQLITE_DENY; + }else if( strcmp(zReply,"SQLITE_IGNORE")==0 ){ + rc = SQLITE_IGNORE; + }else{ + rc = 999; + } + return rc; +} +#endif /* SQLITE_OMIT_AUTHORIZATION */ + +/* +** zText is a pointer to text obtained via an sqlite3_result_text() +** or similar interface. This routine returns a Tcl string object, +** reference count set to 0, containing the text. If a translation +** between iso8859 and UTF-8 is required, it is preformed. +*/ +static Tcl_Obj *dbTextToObj(char const *zText){ + Tcl_Obj *pVal; +#ifdef UTF_TRANSLATION_NEEDED + Tcl_DString dCol; + Tcl_DStringInit(&dCol); + Tcl_ExternalToUtfDString(NULL, zText, -1, &dCol); + pVal = Tcl_NewStringObj(Tcl_DStringValue(&dCol), -1); + Tcl_DStringFree(&dCol); +#else + pVal = Tcl_NewStringObj(zText, -1); +#endif + return pVal; +} + +/* +** This routine reads a line of text from FILE in, stores +** the text in memory obtained from malloc() and returns a pointer +** to the text. NULL is returned at end of file, or if malloc() +** fails. +** +** The interface is like "readline" but no command-line editing +** is done. +** +** copied from shell.c from '.import' command +*/ +static char *local_getline(char *zPrompt, FILE *in){ + char *zLine; + int nLine; + int n; + int eol; + + nLine = 100; + zLine = malloc( nLine ); + if( zLine==0 ) return 0; + n = 0; + eol = 0; + while( !eol ){ + if( n+100>nLine ){ + nLine = nLine*2 + 100; + zLine = realloc(zLine, nLine); + if( zLine==0 ) return 0; + } + if( fgets(&zLine[n], nLine - n, in)==0 ){ + if( n==0 ){ + free(zLine); + return 0; + } + zLine[n] = 0; + eol = 1; + break; + } + while( zLine[n] ){ n++; } + if( n>0 && zLine[n-1]=='\n' ){ + n--; + zLine[n] = 0; + eol = 1; + } + } + zLine = realloc( zLine, n+1 ); + return zLine; +} + + +/* +** Figure out the column names for the data returned by the statement +** passed as the second argument. +** +** If parameter papColName is not NULL, then *papColName is set to point +** at an array allocated using Tcl_Alloc(). It is the callers responsibility +** to free this array using Tcl_Free(), and to decrement the reference +** count of each Tcl_Obj* member of the array. +** +** The return value of this function is the number of columns of data +** returned by pStmt (and hence the size of the *papColName array). +** +** If pArray is not NULL, then it contains the name of a Tcl array +** variable. The "*" member of this array is set to a list containing +** the names of the columns returned by the statement, in order from +** left to right. e.g. if the names of the returned columns are a, b and +** c, it does the equivalent of the tcl command: +** +** set ${pArray}(*) {a b c} +*/ +static int +computeColumnNames( + Tcl_Interp *interp, + sqlite3_stmt *pStmt, /* SQL statement */ + Tcl_Obj ***papColName, /* OUT: Array of column names */ + Tcl_Obj *pArray /* Name of array variable (may be null) */ +){ + int nCol; + + /* Compute column names */ + nCol = sqlite3_column_count(pStmt); + if( papColName ){ + int i; + Tcl_Obj **apColName = (Tcl_Obj**)Tcl_Alloc( sizeof(Tcl_Obj*)*nCol ); + for(i=0; i<nCol; i++){ + apColName[i] = dbTextToObj(sqlite3_column_name(pStmt,i)); + Tcl_IncrRefCount(apColName[i]); + } + + /* If results are being stored in an array variable, then create + ** the array(*) entry for that array + */ + if( pArray ){ + Tcl_Obj *pColList = Tcl_NewObj(); + Tcl_Obj *pStar = Tcl_NewStringObj("*", -1); + Tcl_IncrRefCount(pColList); + for(i=0; i<nCol; i++){ + Tcl_ListObjAppendElement(interp, pColList, apColName[i]); + } + Tcl_IncrRefCount(pStar); + Tcl_ObjSetVar2(interp, pArray, pStar, pColList,0); + Tcl_DecrRefCount(pColList); + Tcl_DecrRefCount(pStar); + } + *papColName = apColName; + } + + return nCol; +} + +/* +** The "sqlite" command below creates a new Tcl command for each +** connection it opens to an SQLite database. This routine is invoked +** whenever one of those connection-specific commands is executed +** in Tcl. For example, if you run Tcl code like this: +** +** sqlite3 db1 "my_database" +** db1 close +** +** The first command opens a connection to the "my_database" database +** and calls that connection "db1". The second command causes this +** subroutine to be invoked. +*/ +static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ + SqliteDb *pDb = (SqliteDb*)cd; + int choice; + int rc = TCL_OK; + static const char *DB_strs[] = { + "authorizer", "busy", "cache", + "changes", "close", "collate", + "collation_needed", "commit_hook", "complete", + "copy", "enable_load_extension","errorcode", + "eval", "exists", "function", + "incrblob", "interrupt", "last_insert_rowid", + "nullvalue", "onecolumn", "profile", + "progress", "rekey", "rollback_hook", + "timeout", "total_changes", "trace", + "transaction", "update_hook", "version", + 0 + }; + enum DB_enum { + DB_AUTHORIZER, DB_BUSY, DB_CACHE, + DB_CHANGES, DB_CLOSE, DB_COLLATE, + DB_COLLATION_NEEDED, DB_COMMIT_HOOK, DB_COMPLETE, + DB_COPY, DB_ENABLE_LOAD_EXTENSION,DB_ERRORCODE, + DB_EVAL, DB_EXISTS, DB_FUNCTION, + DB_INCRBLOB, DB_INTERRUPT, DB_LAST_INSERT_ROWID, + DB_NULLVALUE, DB_ONECOLUMN, DB_PROFILE, + DB_PROGRESS, DB_REKEY, DB_ROLLBACK_HOOK, + DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE, + DB_TRANSACTION, DB_UPDATE_HOOK, DB_VERSION + }; + /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */ + + if( objc<2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ..."); + return TCL_ERROR; + } + if( Tcl_GetIndexFromObj(interp, objv[1], DB_strs, "option", 0, &choice) ){ + return TCL_ERROR; + } + + switch( (enum DB_enum)choice ){ + + /* $db authorizer ?CALLBACK? + ** + ** Invoke the given callback to authorize each SQL operation as it is + ** compiled. 5 arguments are appended to the callback before it is + ** invoked: + ** + ** (1) The authorization type (ex: SQLITE_CREATE_TABLE, SQLITE_INSERT, ...) + ** (2) First descriptive name (depends on authorization type) + ** (3) Second descriptive name + ** (4) Name of the database (ex: "main", "temp") + ** (5) Name of trigger that is doing the access + ** + ** The callback should return on of the following strings: SQLITE_OK, + ** SQLITE_IGNORE, or SQLITE_DENY. Any other return value is an error. + ** + ** If this method is invoked with no arguments, the current authorization + ** callback string is returned. + */ + case DB_AUTHORIZER: { +#ifdef SQLITE_OMIT_AUTHORIZATION + Tcl_AppendResult(interp, "authorization not available in this build", 0); + return TCL_ERROR; +#else + if( objc>3 ){ + Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); + return TCL_ERROR; + }else if( objc==2 ){ + if( pDb->zAuth ){ + Tcl_AppendResult(interp, pDb->zAuth, 0); + } + }else{ + char *zAuth; + int len; + if( pDb->zAuth ){ + Tcl_Free(pDb->zAuth); + } + zAuth = Tcl_GetStringFromObj(objv[2], &len); + if( zAuth && len>0 ){ + pDb->zAuth = Tcl_Alloc( len + 1 ); + memcpy(pDb->zAuth, zAuth, len+1); + }else{ + pDb->zAuth = 0; + } + if( pDb->zAuth ){ + pDb->interp = interp; + sqlite3_set_authorizer(pDb->db, auth_callback, pDb); + }else{ + sqlite3_set_authorizer(pDb->db, 0, 0); + } + } +#endif + break; + } + + /* $db busy ?CALLBACK? + ** + ** Invoke the given callback if an SQL statement attempts to open + ** a locked database file. + */ + case DB_BUSY: { + if( objc>3 ){ + Tcl_WrongNumArgs(interp, 2, objv, "CALLBACK"); + return TCL_ERROR; + }else if( objc==2 ){ + if( pDb->zBusy ){ + Tcl_AppendResult(interp, pDb->zBusy, 0); + } + }else{ + char *zBusy; + int len; + if( pDb->zBusy ){ + Tcl_Free(pDb->zBusy); + } + zBusy = Tcl_GetStringFromObj(objv[2], &len); + if( zBusy && len>0 ){ + pDb->zBusy = Tcl_Alloc( len + 1 ); + memcpy(pDb->zBusy, zBusy, len+1); + }else{ + pDb->zBusy = 0; + } + if( pDb->zBusy ){ + pDb->interp = interp; + sqlite3_busy_handler(pDb->db, DbBusyHandler, pDb); + }else{ + sqlite3_busy_handler(pDb->db, 0, 0); + } + } + break; + } + + /* $db cache flush + ** $db cache size n + ** + ** Flush the prepared statement cache, or set the maximum number of + ** cached statements. + */ + case DB_CACHE: { + char *subCmd; + int n; + + if( objc<=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "cache option ?arg?"); + return TCL_ERROR; + } + subCmd = Tcl_GetStringFromObj( objv[2], 0 ); + if( *subCmd=='f' && strcmp(subCmd,"flush")==0 ){ + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 2, objv, "flush"); + return TCL_ERROR; + }else{ + flushStmtCache( pDb ); + } + }else if( *subCmd=='s' && strcmp(subCmd,"size")==0 ){ + if( objc!=4 ){ + Tcl_WrongNumArgs(interp, 2, objv, "size n"); + return TCL_ERROR; + }else{ + if( TCL_ERROR==Tcl_GetIntFromObj(interp, objv[3], &n) ){ + Tcl_AppendResult( interp, "cannot convert \"", + Tcl_GetStringFromObj(objv[3],0), "\" to integer", 0); + return TCL_ERROR; + }else{ + if( n<0 ){ + flushStmtCache( pDb ); + n = 0; + }else if( n>MAX_PREPARED_STMTS ){ + n = MAX_PREPARED_STMTS; + } + pDb->maxStmt = n; + } + } + }else{ + Tcl_AppendResult( interp, "bad option \"", + Tcl_GetStringFromObj(objv[2],0), "\": must be flush or size", 0); + return TCL_ERROR; + } + break; + } + + /* $db changes + ** + ** Return the number of rows that were modified, inserted, or deleted by + ** the most recent INSERT, UPDATE or DELETE statement, not including + ** any changes made by trigger programs. + */ + case DB_CHANGES: { + Tcl_Obj *pResult; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 2, objv, ""); + return TCL_ERROR; + } + pResult = Tcl_GetObjResult(interp); + Tcl_SetIntObj(pResult, sqlite3_changes(pDb->db)); + break; + } + + /* $db close + ** + ** Shutdown the database + */ + case DB_CLOSE: { + Tcl_DeleteCommand(interp, Tcl_GetStringFromObj(objv[0], 0)); + break; + } + + /* + ** $db collate NAME SCRIPT + ** + ** Create a new SQL collation function called NAME. Whenever + ** that function is called, invoke SCRIPT to evaluate the function. + */ + case DB_COLLATE: { + SqlCollate *pCollate; + char *zName; + char *zScript; + int nScript; + if( objc!=4 ){ + Tcl_WrongNumArgs(interp, 2, objv, "NAME SCRIPT"); + return TCL_ERROR; + } + zName = Tcl_GetStringFromObj(objv[2], 0); + zScript = Tcl_GetStringFromObj(objv[3], &nScript); + pCollate = (SqlCollate*)Tcl_Alloc( sizeof(*pCollate) + nScript + 1 ); + if( pCollate==0 ) return TCL_ERROR; + pCollate->interp = interp; + pCollate->pNext = pDb->pCollate; + pCollate->zScript = (char*)&pCollate[1]; + pDb->pCollate = pCollate; + memcpy(pCollate->zScript, zScript, nScript+1); + if( sqlite3_create_collation(pDb->db, zName, SQLITE_UTF8, + pCollate, tclSqlCollate) ){ + Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE); + return TCL_ERROR; + } + break; + } + + /* + ** $db collation_needed SCRIPT + ** + ** Create a new SQL collation function called NAME. Whenever + ** that function is called, invoke SCRIPT to evaluate the function. + */ + case DB_COLLATION_NEEDED: { + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 2, objv, "SCRIPT"); + return TCL_ERROR; + } + if( pDb->pCollateNeeded ){ + Tcl_DecrRefCount(pDb->pCollateNeeded); + } + pDb->pCollateNeeded = Tcl_DuplicateObj(objv[2]); + Tcl_IncrRefCount(pDb->pCollateNeeded); + sqlite3_collation_needed(pDb->db, pDb, tclCollateNeeded); + break; + } + + /* $db commit_hook ?CALLBACK? + ** + ** Invoke the given callback just before committing every SQL transaction. + ** If the callback throws an exception or returns non-zero, then the + ** transaction is aborted. If CALLBACK is an empty string, the callback + ** is disabled. + */ + case DB_COMMIT_HOOK: { + if( objc>3 ){ + Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); + return TCL_ERROR; + }else if( objc==2 ){ + if( pDb->zCommit ){ + Tcl_AppendResult(interp, pDb->zCommit, 0); + } + }else{ + char *zCommit; + int len; + if( pDb->zCommit ){ + Tcl_Free(pDb->zCommit); + } + zCommit = Tcl_GetStringFromObj(objv[2], &len); + if( zCommit && len>0 ){ + pDb->zCommit = Tcl_Alloc( len + 1 ); + memcpy(pDb->zCommit, zCommit, len+1); + }else{ + pDb->zCommit = 0; + } + if( pDb->zCommit ){ + pDb->interp = interp; + sqlite3_commit_hook(pDb->db, DbCommitHandler, pDb); + }else{ + sqlite3_commit_hook(pDb->db, 0, 0); + } + } + break; + } + + /* $db complete SQL + ** + ** Return TRUE if SQL is a complete SQL statement. Return FALSE if + ** additional lines of input are needed. This is similar to the + ** built-in "info complete" command of Tcl. + */ + case DB_COMPLETE: { +#ifndef SQLITE_OMIT_COMPLETE + Tcl_Obj *pResult; + int isComplete; + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 2, objv, "SQL"); + return TCL_ERROR; + } + isComplete = sqlite3_complete( Tcl_GetStringFromObj(objv[2], 0) ); + pResult = Tcl_GetObjResult(interp); + Tcl_SetBooleanObj(pResult, isComplete); +#endif + break; + } + + /* $db copy conflict-algorithm table filename ?SEPARATOR? ?NULLINDICATOR? + ** + ** Copy data into table from filename, optionally using SEPARATOR + ** as column separators. If a column contains a null string, or the + ** value of NULLINDICATOR, a NULL is inserted for the column. + ** conflict-algorithm is one of the sqlite conflict algorithms: + ** rollback, abort, fail, ignore, replace + ** On success, return the number of lines processed, not necessarily same + ** as 'db changes' due to conflict-algorithm selected. + ** + ** This code is basically an implementation/enhancement of + ** the sqlite3 shell.c ".import" command. + ** + ** This command usage is equivalent to the sqlite2.x COPY statement, + ** which imports file data into a table using the PostgreSQL COPY file format: + ** $db copy $conflit_algo $table_name $filename \t \\N + */ + case DB_COPY: { + char *zTable; /* Insert data into this table */ + char *zFile; /* The file from which to extract data */ + char *zConflict; /* The conflict algorithm to use */ + sqlite3_stmt *pStmt; /* A statement */ + int nCol; /* Number of columns in the table */ + int nByte; /* Number of bytes in an SQL string */ + int i, j; /* Loop counters */ + int nSep; /* Number of bytes in zSep[] */ + int nNull; /* Number of bytes in zNull[] */ + char *zSql; /* An SQL statement */ + char *zLine; /* A single line of input from the file */ + char **azCol; /* zLine[] broken up into columns */ + char *zCommit; /* How to commit changes */ + FILE *in; /* The input file */ + int lineno = 0; /* Line number of input file */ + char zLineNum[80]; /* Line number print buffer */ + Tcl_Obj *pResult; /* interp result */ + + char *zSep; + char *zNull; + if( objc<5 || objc>7 ){ + Tcl_WrongNumArgs(interp, 2, objv, + "CONFLICT-ALGORITHM TABLE FILENAME ?SEPARATOR? ?NULLINDICATOR?"); + return TCL_ERROR; + } + if( objc>=6 ){ + zSep = Tcl_GetStringFromObj(objv[5], 0); + }else{ + zSep = "\t"; + } + if( objc>=7 ){ + zNull = Tcl_GetStringFromObj(objv[6], 0); + }else{ + zNull = ""; + } + zConflict = Tcl_GetStringFromObj(objv[2], 0); + zTable = Tcl_GetStringFromObj(objv[3], 0); + zFile = Tcl_GetStringFromObj(objv[4], 0); + nSep = strlen(zSep); + nNull = strlen(zNull); + if( nSep==0 ){ + Tcl_AppendResult(interp,"Error: non-null separator required for copy",0); + return TCL_ERROR; + } + if(strcasecmp(zConflict, "rollback") != 0 && + strcasecmp(zConflict, "abort" ) != 0 && + strcasecmp(zConflict, "fail" ) != 0 && + strcasecmp(zConflict, "ignore" ) != 0 && + strcasecmp(zConflict, "replace" ) != 0 ) { + Tcl_AppendResult(interp, "Error: \"", zConflict, + "\", conflict-algorithm must be one of: rollback, " + "abort, fail, ignore, or replace", 0); + return TCL_ERROR; + } + zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable); + if( zSql==0 ){ + Tcl_AppendResult(interp, "Error: no such table: ", zTable, 0); + return TCL_ERROR; + } + nByte = strlen(zSql); + rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + if( rc ){ + Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), 0); + nCol = 0; + }else{ + nCol = sqlite3_column_count(pStmt); + } + sqlite3_finalize(pStmt); + if( nCol==0 ) { + return TCL_ERROR; + } + zSql = malloc( nByte + 50 + nCol*2 ); + if( zSql==0 ) { + Tcl_AppendResult(interp, "Error: can't malloc()", 0); + return TCL_ERROR; + } + sqlite3_snprintf(nByte+50, zSql, "INSERT OR %q INTO '%q' VALUES(?", + zConflict, zTable); + j = strlen(zSql); + for(i=1; i<nCol; i++){ + zSql[j++] = ','; + zSql[j++] = '?'; + } + zSql[j++] = ')'; + zSql[j] = 0; + rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0); + free(zSql); + if( rc ){ + Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), 0); + sqlite3_finalize(pStmt); + return TCL_ERROR; + } + in = fopen(zFile, "rb"); + if( in==0 ){ + Tcl_AppendResult(interp, "Error: cannot open file: ", zFile, NULL); + sqlite3_finalize(pStmt); + return TCL_ERROR; + } + azCol = malloc( sizeof(azCol[0])*(nCol+1) ); + if( azCol==0 ) { + Tcl_AppendResult(interp, "Error: can't malloc()", 0); + fclose(in); + return TCL_ERROR; + } + (void)sqlite3_exec(pDb->db, "BEGIN", 0, 0, 0); + zCommit = "COMMIT"; + while( (zLine = local_getline(0, in))!=0 ){ + char *z; + i = 0; + lineno++; + azCol[0] = zLine; + for(i=0, z=zLine; *z; z++){ + if( *z==zSep[0] && strncmp(z, zSep, nSep)==0 ){ + *z = 0; + i++; + if( i<nCol ){ + azCol[i] = &z[nSep]; + z += nSep-1; + } + } + } + if( i+1!=nCol ){ + char *zErr; + int nErr = strlen(zFile) + 200; + zErr = malloc(nErr); + if( zErr ){ + sqlite3_snprintf(nErr, zErr, + "Error: %s line %d: expected %d columns of data but found %d", + zFile, lineno, nCol, i+1); + Tcl_AppendResult(interp, zErr, 0); + free(zErr); + } + zCommit = "ROLLBACK"; + break; + } + for(i=0; i<nCol; i++){ + /* check for null data, if so, bind as null */ + if ((nNull>0 && strcmp(azCol[i], zNull)==0) || strlen(azCol[i])==0) { + sqlite3_bind_null(pStmt, i+1); + }else{ + sqlite3_bind_text(pStmt, i+1, azCol[i], -1, SQLITE_STATIC); + } + } + sqlite3_step(pStmt); + rc = sqlite3_reset(pStmt); + free(zLine); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp,"Error: ", sqlite3_errmsg(pDb->db), 0); + zCommit = "ROLLBACK"; + break; + } + } + free(azCol); + fclose(in); + sqlite3_finalize(pStmt); + (void)sqlite3_exec(pDb->db, zCommit, 0, 0, 0); + + if( zCommit[0] == 'C' ){ + /* success, set result as number of lines processed */ + pResult = Tcl_GetObjResult(interp); + Tcl_SetIntObj(pResult, lineno); + rc = TCL_OK; + }else{ + /* failure, append lineno where failed */ + sqlite3_snprintf(sizeof(zLineNum), zLineNum,"%d",lineno); + Tcl_AppendResult(interp,", failed while processing line: ",zLineNum,0); + rc = TCL_ERROR; + } + break; + } + + /* + ** $db enable_load_extension BOOLEAN + ** + ** Turn the extension loading feature on or off. It if off by + ** default. + */ + case DB_ENABLE_LOAD_EXTENSION: { +#ifndef SQLITE_OMIT_LOAD_EXTENSION + int onoff; + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 2, objv, "BOOLEAN"); + return TCL_ERROR; + } + if( Tcl_GetBooleanFromObj(interp, objv[2], &onoff) ){ + return TCL_ERROR; + } + sqlite3_enable_load_extension(pDb->db, onoff); + break; +#else + Tcl_AppendResult(interp, "extension loading is turned off at compile-time", + 0); + return TCL_ERROR; +#endif + } + + /* + ** $db errorcode + ** + ** Return the numeric error code that was returned by the most recent + ** call to sqlite3_exec(). + */ + case DB_ERRORCODE: { + Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_errcode(pDb->db))); + break; + } + + /* + ** $db eval $sql ?array? ?{ ...code... }? + ** $db onecolumn $sql + ** + ** The SQL statement in $sql is evaluated. For each row, the values are + ** placed in elements of the array named "array" and ...code... is executed. + ** If "array" and "code" are omitted, then no callback is every invoked. + ** If "array" is an empty string, then the values are placed in variables + ** that have the same name as the fields extracted by the query. + ** + ** The onecolumn method is the equivalent of: + ** lindex [$db eval $sql] 0 + */ + case DB_ONECOLUMN: + case DB_EVAL: + case DB_EXISTS: { + char const *zSql; /* Next SQL statement to execute */ + char const *zLeft; /* What is left after first stmt in zSql */ + sqlite3_stmt *pStmt; /* Compiled SQL statment */ + Tcl_Obj *pArray; /* Name of array into which results are written */ + Tcl_Obj *pScript; /* Script to run for each result set */ + Tcl_Obj **apParm; /* Parameters that need a Tcl_DecrRefCount() */ + int nParm; /* Number of entries used in apParm[] */ + Tcl_Obj *aParm[10]; /* Static space for apParm[] in the common case */ + Tcl_Obj *pRet; /* Value to be returned */ + SqlPreparedStmt *pPreStmt; /* Pointer to a prepared statement */ + int rc2; + + if( choice==DB_EVAL ){ + if( objc<3 || objc>5 ){ + Tcl_WrongNumArgs(interp, 2, objv, "SQL ?ARRAY-NAME? ?SCRIPT?"); + return TCL_ERROR; + } + pRet = Tcl_NewObj(); + Tcl_IncrRefCount(pRet); + }else{ + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 2, objv, "SQL"); + return TCL_ERROR; + } + if( choice==DB_EXISTS ){ + pRet = Tcl_NewBooleanObj(0); + Tcl_IncrRefCount(pRet); + }else{ + pRet = 0; + } + } + if( objc==3 ){ + pArray = pScript = 0; + }else if( objc==4 ){ + pArray = 0; + pScript = objv[3]; + }else{ + pArray = objv[3]; + if( Tcl_GetString(pArray)[0]==0 ) pArray = 0; + pScript = objv[4]; + } + + Tcl_IncrRefCount(objv[2]); + zSql = Tcl_GetStringFromObj(objv[2], 0); + while( rc==TCL_OK && zSql[0] ){ + int i; /* Loop counter */ + int nVar; /* Number of bind parameters in the pStmt */ + int nCol = -1; /* Number of columns in the result set */ + Tcl_Obj **apColName = 0; /* Array of column names */ + int len; /* String length of zSql */ + + /* Try to find a SQL statement that has already been compiled and + ** which matches the next sequence of SQL. + */ + pStmt = 0; + len = strlen(zSql); + for(pPreStmt = pDb->stmtList; pPreStmt; pPreStmt=pPreStmt->pNext){ + int n = pPreStmt->nSql; + if( len>=n + && memcmp(pPreStmt->zSql, zSql, n)==0 + && (zSql[n]==0 || zSql[n-1]==';') + ){ + pStmt = pPreStmt->pStmt; + zLeft = &zSql[pPreStmt->nSql]; + + /* When a prepared statement is found, unlink it from the + ** cache list. It will later be added back to the beginning + ** of the cache list in order to implement LRU replacement. + */ + if( pPreStmt->pPrev ){ + pPreStmt->pPrev->pNext = pPreStmt->pNext; + }else{ + pDb->stmtList = pPreStmt->pNext; + } + if( pPreStmt->pNext ){ + pPreStmt->pNext->pPrev = pPreStmt->pPrev; + }else{ + pDb->stmtLast = pPreStmt->pPrev; + } + pDb->nStmt--; + break; + } + } + + /* If no prepared statement was found. Compile the SQL text + */ + if( pStmt==0 ){ + if( SQLITE_OK!=sqlite3_prepare_v2(pDb->db, zSql, -1, &pStmt, &zLeft) ){ + Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db))); + rc = TCL_ERROR; + break; + } + if( pStmt==0 ){ + if( SQLITE_OK!=sqlite3_errcode(pDb->db) ){ + /* A compile-time error in the statement + */ + Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db))); + rc = TCL_ERROR; + break; + }else{ + /* The statement was a no-op. Continue to the next statement + ** in the SQL string. + */ + zSql = zLeft; + continue; + } + } + assert( pPreStmt==0 ); + } + + /* Bind values to parameters that begin with $ or : + */ + nVar = sqlite3_bind_parameter_count(pStmt); + nParm = 0; + if( nVar>sizeof(aParm)/sizeof(aParm[0]) ){ + apParm = (Tcl_Obj**)Tcl_Alloc(nVar*sizeof(apParm[0])); + }else{ + apParm = aParm; + } + for(i=1; i<=nVar; i++){ + const char *zVar = sqlite3_bind_parameter_name(pStmt, i); + if( zVar!=0 && (zVar[0]=='$' || zVar[0]==':' || zVar[0]=='@') ){ + Tcl_Obj *pVar = Tcl_GetVar2Ex(interp, &zVar[1], 0, 0); + if( pVar ){ + int n; + u8 *data; + char *zType = pVar->typePtr ? pVar->typePtr->name : ""; + char c = zType[0]; + if( zVar[0]=='@' || + (c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0) ){ + /* Load a BLOB type if the Tcl variable is a bytearray and + ** it has no string representation or the host + ** parameter name begins with "@". */ + data = Tcl_GetByteArrayFromObj(pVar, &n); + sqlite3_bind_blob(pStmt, i, data, n, SQLITE_STATIC); + Tcl_IncrRefCount(pVar); + apParm[nParm++] = pVar; + }else if( c=='b' && strcmp(zType,"boolean")==0 ){ + Tcl_GetIntFromObj(interp, pVar, &n); + sqlite3_bind_int(pStmt, i, n); + }else if( c=='d' && strcmp(zType,"double")==0 ){ + double r; + Tcl_GetDoubleFromObj(interp, pVar, &r); + sqlite3_bind_double(pStmt, i, r); + }else if( (c=='w' && strcmp(zType,"wideInt")==0) || + (c=='i' && strcmp(zType,"int")==0) ){ + Tcl_WideInt v; + Tcl_GetWideIntFromObj(interp, pVar, &v); + sqlite3_bind_int64(pStmt, i, v); + }else{ + data = (unsigned char *)Tcl_GetStringFromObj(pVar, &n); + sqlite3_bind_text(pStmt, i, (char *)data, n, SQLITE_STATIC); + Tcl_IncrRefCount(pVar); + apParm[nParm++] = pVar; + } + }else{ + sqlite3_bind_null( pStmt, i ); + } + } + } + + /* Execute the SQL + */ + while( rc==TCL_OK && pStmt && SQLITE_ROW==sqlite3_step(pStmt) ){ + + /* Compute column names. This must be done after the first successful + ** call to sqlite3_step(), in case the query is recompiled and the + ** number or names of the returned columns changes. + */ + assert(!pArray||pScript); + if (nCol < 0) { + Tcl_Obj ***ap = (pScript?&apColName:0); + nCol = computeColumnNames(interp, pStmt, ap, pArray); + } + + for(i=0; i<nCol; i++){ + Tcl_Obj *pVal; + + /* Set pVal to contain the i'th column of this row. */ + switch( sqlite3_column_type(pStmt, i) ){ + case SQLITE_BLOB: { + int bytes = sqlite3_column_bytes(pStmt, i); + const char *zBlob = sqlite3_column_blob(pStmt, i); + if( !zBlob ) bytes = 0; + pVal = Tcl_NewByteArrayObj((u8*)zBlob, bytes); + break; + } + case SQLITE_INTEGER: { + sqlite_int64 v = sqlite3_column_int64(pStmt, i); + if( v>=-2147483647 && v<=2147483647 ){ + pVal = Tcl_NewIntObj(v); + }else{ + pVal = Tcl_NewWideIntObj(v); + } + break; + } + case SQLITE_FLOAT: { + double r = sqlite3_column_double(pStmt, i); + pVal = Tcl_NewDoubleObj(r); + break; + } + case SQLITE_NULL: { + pVal = dbTextToObj(pDb->zNull); + break; + } + default: { + pVal = dbTextToObj((char *)sqlite3_column_text(pStmt, i)); + break; + } + } + + if( pScript ){ + if( pArray==0 ){ + Tcl_ObjSetVar2(interp, apColName[i], 0, pVal, 0); + }else{ + Tcl_ObjSetVar2(interp, pArray, apColName[i], pVal, 0); + } + }else if( choice==DB_ONECOLUMN ){ + assert( pRet==0 ); + if( pRet==0 ){ + pRet = pVal; + Tcl_IncrRefCount(pRet); + } + rc = TCL_BREAK; + i = nCol; + }else if( choice==DB_EXISTS ){ + Tcl_DecrRefCount(pRet); + pRet = Tcl_NewBooleanObj(1); + Tcl_IncrRefCount(pRet); + rc = TCL_BREAK; + i = nCol; + }else{ + Tcl_ListObjAppendElement(interp, pRet, pVal); + } + } + + if( pScript ){ + rc = Tcl_EvalObjEx(interp, pScript, 0); + if( rc==TCL_CONTINUE ){ + rc = TCL_OK; + } + } + } + if( rc==TCL_BREAK ){ + rc = TCL_OK; + } + + /* Free the column name objects */ + if( pScript ){ + /* If the query returned no rows, but an array variable was + ** specified, call computeColumnNames() now to populate the + ** arrayname(*) variable. + */ + if (pArray && nCol < 0) { + Tcl_Obj ***ap = (pScript?&apColName:0); + nCol = computeColumnNames(interp, pStmt, ap, pArray); + } + for(i=0; i<nCol; i++){ + Tcl_DecrRefCount(apColName[i]); + } + Tcl_Free((char*)apColName); + } + + /* Free the bound string and blob parameters */ + for(i=0; i<nParm; i++){ + Tcl_DecrRefCount(apParm[i]); + } + if( apParm!=aParm ){ + Tcl_Free((char*)apParm); + } + + /* Reset the statement. If the result code is SQLITE_SCHEMA, then + ** flush the statement cache and try the statement again. + */ + rc2 = sqlite3_reset(pStmt); + if( SQLITE_OK!=rc2 ){ + /* If a run-time error occurs, report the error and stop reading + ** the SQL + */ + Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db))); + sqlite3_finalize(pStmt); + rc = TCL_ERROR; + if( pPreStmt ) Tcl_Free((char*)pPreStmt); + break; + }else if( pDb->maxStmt<=0 ){ + /* If the cache is turned off, deallocated the statement */ + if( pPreStmt ) Tcl_Free((char*)pPreStmt); + sqlite3_finalize(pStmt); + }else{ + /* Everything worked and the cache is operational. + ** Create a new SqlPreparedStmt structure if we need one. + ** (If we already have one we can just reuse it.) + */ + if( pPreStmt==0 ){ + len = zLeft - zSql; + pPreStmt = (SqlPreparedStmt*)Tcl_Alloc( sizeof(*pPreStmt) ); + if( pPreStmt==0 ) return TCL_ERROR; + pPreStmt->pStmt = pStmt; + pPreStmt->nSql = len; + pPreStmt->zSql = sqlite3_sql(pStmt); + assert( strlen(pPreStmt->zSql)==len ); + assert( 0==memcmp(pPreStmt->zSql, zSql, len) ); + } + + /* Add the prepared statement to the beginning of the cache list + */ + pPreStmt->pNext = pDb->stmtList; + pPreStmt->pPrev = 0; + if( pDb->stmtList ){ + pDb->stmtList->pPrev = pPreStmt; + } + pDb->stmtList = pPreStmt; + if( pDb->stmtLast==0 ){ + assert( pDb->nStmt==0 ); + pDb->stmtLast = pPreStmt; + }else{ + assert( pDb->nStmt>0 ); + } + pDb->nStmt++; + + /* If we have too many statement in cache, remove the surplus from the + ** end of the cache list. + */ + while( pDb->nStmt>pDb->maxStmt ){ + sqlite3_finalize(pDb->stmtLast->pStmt); + pDb->stmtLast = pDb->stmtLast->pPrev; + Tcl_Free((char*)pDb->stmtLast->pNext); + pDb->stmtLast->pNext = 0; + pDb->nStmt--; + } + } + + /* Proceed to the next statement */ + zSql = zLeft; + } + Tcl_DecrRefCount(objv[2]); + + if( pRet ){ + if( rc==TCL_OK ){ + Tcl_SetObjResult(interp, pRet); + } + Tcl_DecrRefCount(pRet); + }else if( rc==TCL_OK ){ + Tcl_ResetResult(interp); + } + break; + } + + /* + ** $db function NAME SCRIPT + ** + ** Create a new SQL function called NAME. Whenever that function is + ** called, invoke SCRIPT to evaluate the function. + */ + case DB_FUNCTION: { + SqlFunc *pFunc; + Tcl_Obj *pScript; + char *zName; + if( objc!=4 ){ + Tcl_WrongNumArgs(interp, 2, objv, "NAME SCRIPT"); + return TCL_ERROR; + } + zName = Tcl_GetStringFromObj(objv[2], 0); + pScript = objv[3]; + pFunc = findSqlFunc(pDb, zName); + if( pFunc==0 ) return TCL_ERROR; + if( pFunc->pScript ){ + Tcl_DecrRefCount(pFunc->pScript); + } + pFunc->pScript = pScript; + Tcl_IncrRefCount(pScript); + pFunc->useEvalObjv = safeToUseEvalObjv(interp, pScript); + rc = sqlite3_create_function(pDb->db, zName, -1, SQLITE_UTF8, + pFunc, tclSqlFunc, 0, 0); + if( rc!=SQLITE_OK ){ + rc = TCL_ERROR; + Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE); + } + break; + } + + /* + ** $db incrblob ?-readonly? ?DB? TABLE COLUMN ROWID + */ + case DB_INCRBLOB: { +#ifdef SQLITE_OMIT_INCRBLOB + Tcl_AppendResult(interp, "incrblob not available in this build", 0); + return TCL_ERROR; +#else + int isReadonly = 0; + const char *zDb = "main"; + const char *zTable; + const char *zColumn; + sqlite_int64 iRow; + + /* Check for the -readonly option */ + if( objc>3 && strcmp(Tcl_GetString(objv[2]), "-readonly")==0 ){ + isReadonly = 1; + } + + if( objc!=(5+isReadonly) && objc!=(6+isReadonly) ){ + Tcl_WrongNumArgs(interp, 2, objv, "?-readonly? ?DB? TABLE COLUMN ROWID"); + return TCL_ERROR; + } + + if( objc==(6+isReadonly) ){ + zDb = Tcl_GetString(objv[2]); + } + zTable = Tcl_GetString(objv[objc-3]); + zColumn = Tcl_GetString(objv[objc-2]); + rc = Tcl_GetWideIntFromObj(interp, objv[objc-1], &iRow); + + if( rc==TCL_OK ){ + rc = createIncrblobChannel( + interp, pDb, zDb, zTable, zColumn, iRow, isReadonly + ); + } +#endif + break; + } + + /* + ** $db interrupt + ** + ** Interrupt the execution of the inner-most SQL interpreter. This + ** causes the SQL statement to return an error of SQLITE_INTERRUPT. + */ + case DB_INTERRUPT: { + sqlite3_interrupt(pDb->db); + break; + } + + /* + ** $db nullvalue ?STRING? + ** + ** Change text used when a NULL comes back from the database. If ?STRING? + ** is not present, then the current string used for NULL is returned. + ** If STRING is present, then STRING is returned. + ** + */ + case DB_NULLVALUE: { + if( objc!=2 && objc!=3 ){ + Tcl_WrongNumArgs(interp, 2, objv, "NULLVALUE"); + return TCL_ERROR; + } + if( objc==3 ){ + int len; + char *zNull = Tcl_GetStringFromObj(objv[2], &len); + if( pDb->zNull ){ + Tcl_Free(pDb->zNull); + } + if( zNull && len>0 ){ + pDb->zNull = Tcl_Alloc( len + 1 ); + strncpy(pDb->zNull, zNull, len); + pDb->zNull[len] = '\0'; + }else{ + pDb->zNull = 0; + } + } + Tcl_SetObjResult(interp, dbTextToObj(pDb->zNull)); + break; + } + + /* + ** $db last_insert_rowid + ** + ** Return an integer which is the ROWID for the most recent insert. + */ + case DB_LAST_INSERT_ROWID: { + Tcl_Obj *pResult; + Tcl_WideInt rowid; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 2, objv, ""); + return TCL_ERROR; + } + rowid = sqlite3_last_insert_rowid(pDb->db); + pResult = Tcl_GetObjResult(interp); + Tcl_SetWideIntObj(pResult, rowid); + break; + } + + /* + ** The DB_ONECOLUMN method is implemented together with DB_EVAL. + */ + + /* $db progress ?N CALLBACK? + ** + ** Invoke the given callback every N virtual machine opcodes while executing + ** queries. + */ + case DB_PROGRESS: { + if( objc==2 ){ + if( pDb->zProgress ){ + Tcl_AppendResult(interp, pDb->zProgress, 0); + } + }else if( objc==4 ){ + char *zProgress; + int len; + int N; + if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &N) ){ + return TCL_ERROR; + }; + if( pDb->zProgress ){ + Tcl_Free(pDb->zProgress); + } + zProgress = Tcl_GetStringFromObj(objv[3], &len); + if( zProgress && len>0 ){ + pDb->zProgress = Tcl_Alloc( len + 1 ); + memcpy(pDb->zProgress, zProgress, len+1); + }else{ + pDb->zProgress = 0; + } +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK + if( pDb->zProgress ){ + pDb->interp = interp; + sqlite3_progress_handler(pDb->db, N, DbProgressHandler, pDb); + }else{ + sqlite3_progress_handler(pDb->db, 0, 0, 0); + } +#endif + }else{ + Tcl_WrongNumArgs(interp, 2, objv, "N CALLBACK"); + return TCL_ERROR; + } + break; + } + + /* $db profile ?CALLBACK? + ** + ** Make arrangements to invoke the CALLBACK routine after each SQL statement + ** that has run. The text of the SQL and the amount of elapse time are + ** appended to CALLBACK before the script is run. + */ + case DB_PROFILE: { + if( objc>3 ){ + Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); + return TCL_ERROR; + }else if( objc==2 ){ + if( pDb->zProfile ){ + Tcl_AppendResult(interp, pDb->zProfile, 0); + } + }else{ + char *zProfile; + int len; + if( pDb->zProfile ){ + Tcl_Free(pDb->zProfile); + } + zProfile = Tcl_GetStringFromObj(objv[2], &len); + if( zProfile && len>0 ){ + pDb->zProfile = Tcl_Alloc( len + 1 ); + memcpy(pDb->zProfile, zProfile, len+1); + }else{ + pDb->zProfile = 0; + } +#ifndef SQLITE_OMIT_TRACE + if( pDb->zProfile ){ + pDb->interp = interp; + sqlite3_profile(pDb->db, DbProfileHandler, pDb); + }else{ + sqlite3_profile(pDb->db, 0, 0); + } +#endif + } + break; + } + + /* + ** $db rekey KEY + ** + ** Change the encryption key on the currently open database. + */ + case DB_REKEY: { + int nKey; + void *pKey; + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 2, objv, "KEY"); + return TCL_ERROR; + } + pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey); +#ifdef SQLITE_HAS_CODEC + rc = sqlite3_rekey(pDb->db, pKey, nKey); + if( rc ){ + Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0); + rc = TCL_ERROR; + } +#endif + break; + } + + /* + ** $db timeout MILLESECONDS + ** + ** Delay for the number of milliseconds specified when a file is locked. + */ + case DB_TIMEOUT: { + int ms; + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 2, objv, "MILLISECONDS"); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, objv[2], &ms) ) return TCL_ERROR; + sqlite3_busy_timeout(pDb->db, ms); + break; + } + + /* + ** $db total_changes + ** + ** Return the number of rows that were modified, inserted, or deleted + ** since the database handle was created. + */ + case DB_TOTAL_CHANGES: { + Tcl_Obj *pResult; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 2, objv, ""); + return TCL_ERROR; + } + pResult = Tcl_GetObjResult(interp); + Tcl_SetIntObj(pResult, sqlite3_total_changes(pDb->db)); + break; + } + + /* $db trace ?CALLBACK? + ** + ** Make arrangements to invoke the CALLBACK routine for each SQL statement + ** that is executed. The text of the SQL is appended to CALLBACK before + ** it is executed. + */ + case DB_TRACE: { + if( objc>3 ){ + Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); + return TCL_ERROR; + }else if( objc==2 ){ + if( pDb->zTrace ){ + Tcl_AppendResult(interp, pDb->zTrace, 0); + } + }else{ + char *zTrace; + int len; + if( pDb->zTrace ){ + Tcl_Free(pDb->zTrace); + } + zTrace = Tcl_GetStringFromObj(objv[2], &len); + if( zTrace && len>0 ){ + pDb->zTrace = Tcl_Alloc( len + 1 ); + memcpy(pDb->zTrace, zTrace, len+1); + }else{ + pDb->zTrace = 0; + } +#ifndef SQLITE_OMIT_TRACE + if( pDb->zTrace ){ + pDb->interp = interp; + sqlite3_trace(pDb->db, DbTraceHandler, pDb); + }else{ + sqlite3_trace(pDb->db, 0, 0); + } +#endif + } + break; + } + + /* $db transaction [-deferred|-immediate|-exclusive] SCRIPT + ** + ** Start a new transaction (if we are not already in the midst of a + ** transaction) and execute the TCL script SCRIPT. After SCRIPT + ** completes, either commit the transaction or roll it back if SCRIPT + ** throws an exception. Or if no new transation was started, do nothing. + ** pass the exception on up the stack. + ** + ** This command was inspired by Dave Thomas's talk on Ruby at the + ** 2005 O'Reilly Open Source Convention (OSCON). + */ + case DB_TRANSACTION: { + int inTrans; + Tcl_Obj *pScript; + const char *zBegin = "BEGIN"; + if( objc!=3 && objc!=4 ){ + Tcl_WrongNumArgs(interp, 2, objv, "[TYPE] SCRIPT"); + return TCL_ERROR; + } + if( objc==3 ){ + pScript = objv[2]; + } else { + static const char *TTYPE_strs[] = { + "deferred", "exclusive", "immediate", 0 + }; + enum TTYPE_enum { + TTYPE_DEFERRED, TTYPE_EXCLUSIVE, TTYPE_IMMEDIATE + }; + int ttype; + if( Tcl_GetIndexFromObj(interp, objv[2], TTYPE_strs, "transaction type", + 0, &ttype) ){ + return TCL_ERROR; + } + switch( (enum TTYPE_enum)ttype ){ + case TTYPE_DEFERRED: /* no-op */; break; + case TTYPE_EXCLUSIVE: zBegin = "BEGIN EXCLUSIVE"; break; + case TTYPE_IMMEDIATE: zBegin = "BEGIN IMMEDIATE"; break; + } + pScript = objv[3]; + } + inTrans = !sqlite3_get_autocommit(pDb->db); + if( !inTrans ){ + (void)sqlite3_exec(pDb->db, zBegin, 0, 0, 0); + } + rc = Tcl_EvalObjEx(interp, pScript, 0); + if( !inTrans ){ + const char *zEnd; + if( rc==TCL_ERROR ){ + zEnd = "ROLLBACK"; + } else { + zEnd = "COMMIT"; + } + if( sqlite3_exec(pDb->db, zEnd, 0, 0, 0) ){ + sqlite3_exec(pDb->db, "ROLLBACK", 0, 0, 0); + } + } + break; + } + + /* + ** $db update_hook ?script? + ** $db rollback_hook ?script? + */ + case DB_UPDATE_HOOK: + case DB_ROLLBACK_HOOK: { + + /* set ppHook to point at pUpdateHook or pRollbackHook, depending on + ** whether [$db update_hook] or [$db rollback_hook] was invoked. + */ + Tcl_Obj **ppHook; + if( choice==DB_UPDATE_HOOK ){ + ppHook = &pDb->pUpdateHook; + }else{ + ppHook = &pDb->pRollbackHook; + } + + if( objc!=2 && objc!=3 ){ + Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?"); + return TCL_ERROR; + } + if( *ppHook ){ + Tcl_SetObjResult(interp, *ppHook); + if( objc==3 ){ + Tcl_DecrRefCount(*ppHook); + *ppHook = 0; + } + } + if( objc==3 ){ + assert( !(*ppHook) ); + if( Tcl_GetCharLength(objv[2])>0 ){ + *ppHook = objv[2]; + Tcl_IncrRefCount(*ppHook); + } + } + + sqlite3_update_hook(pDb->db, (pDb->pUpdateHook?DbUpdateHandler:0), pDb); + sqlite3_rollback_hook(pDb->db,(pDb->pRollbackHook?DbRollbackHandler:0),pDb); + + break; + } + + /* $db version + ** + ** Return the version string for this database. + */ + case DB_VERSION: { + Tcl_SetResult(interp, (char *)sqlite3_libversion(), TCL_STATIC); + break; + } + + + } /* End of the SWITCH statement */ + return rc; +} + +/* +** sqlite3 DBNAME FILENAME ?-vfs VFSNAME? ?-key KEY? ?-readonly BOOLEAN? +** ?-create BOOLEAN? ?-nomutex BOOLEAN? +** +** This is the main Tcl command. When the "sqlite" Tcl command is +** invoked, this routine runs to process that command. +** +** The first argument, DBNAME, is an arbitrary name for a new +** database connection. This command creates a new command named +** DBNAME that is used to control that connection. The database +** connection is deleted when the DBNAME command is deleted. +** +** The second argument is the name of the database file. +** +*/ +static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ + SqliteDb *p; + void *pKey = 0; + int nKey = 0; + const char *zArg; + char *zErrMsg; + int i; + const char *zFile; + const char *zVfs = 0; + int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + Tcl_DString translatedFilename; + if( objc==2 ){ + zArg = Tcl_GetStringFromObj(objv[1], 0); + if( strcmp(zArg,"-version")==0 ){ + Tcl_AppendResult(interp,sqlite3_version,0); + return TCL_OK; + } + if( strcmp(zArg,"-has-codec")==0 ){ +#ifdef SQLITE_HAS_CODEC + Tcl_AppendResult(interp,"1",0); +#else + Tcl_AppendResult(interp,"0",0); +#endif + return TCL_OK; + } + } + for(i=3; i+1<objc; i+=2){ + zArg = Tcl_GetString(objv[i]); + if( strcmp(zArg,"-key")==0 ){ + pKey = Tcl_GetByteArrayFromObj(objv[i+1], &nKey); + }else if( strcmp(zArg, "-vfs")==0 ){ + i++; + zVfs = Tcl_GetString(objv[i]); + }else if( strcmp(zArg, "-readonly")==0 ){ + int b; + if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR; + if( b ){ + flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); + flags |= SQLITE_OPEN_READONLY; + }else{ + flags &= ~SQLITE_OPEN_READONLY; + flags |= SQLITE_OPEN_READWRITE; + } + }else if( strcmp(zArg, "-create")==0 ){ + int b; + if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR; + if( b && (flags & SQLITE_OPEN_READONLY)==0 ){ + flags |= SQLITE_OPEN_CREATE; + }else{ + flags &= ~SQLITE_OPEN_CREATE; + } + }else if( strcmp(zArg, "-nomutex")==0 ){ + int b; + if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR; + if( b ){ + flags |= SQLITE_OPEN_NOMUTEX; + }else{ + flags &= ~SQLITE_OPEN_NOMUTEX; + } + }else{ + Tcl_AppendResult(interp, "unknown option: ", zArg, (char*)0); + return TCL_ERROR; + } + } + if( objc<3 || (objc&1)!=1 ){ + Tcl_WrongNumArgs(interp, 1, objv, + "HANDLE FILENAME ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN?" + " ?-nomutex BOOLEAN?" +#ifdef SQLITE_HAS_CODEC + " ?-key CODECKEY?" +#endif + ); + return TCL_ERROR; + } + zErrMsg = 0; + p = (SqliteDb*)Tcl_Alloc( sizeof(*p) ); + if( p==0 ){ + Tcl_SetResult(interp, "malloc failed", TCL_STATIC); + return TCL_ERROR; + } + memset(p, 0, sizeof(*p)); + zFile = Tcl_GetStringFromObj(objv[2], 0); + zFile = Tcl_TranslateFileName(interp, zFile, &translatedFilename); + sqlite3_open_v2(zFile, &p->db, flags, zVfs); + Tcl_DStringFree(&translatedFilename); + if( SQLITE_OK!=sqlite3_errcode(p->db) ){ + zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(p->db)); + sqlite3_close(p->db); + p->db = 0; + } +#ifdef SQLITE_HAS_CODEC + if( p->db ){ + sqlite3_key(p->db, pKey, nKey); + } +#endif + if( p->db==0 ){ + Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE); + Tcl_Free((char*)p); + sqlite3_free(zErrMsg); + return TCL_ERROR; + } + p->maxStmt = NUM_PREPARED_STMTS; + p->interp = interp; + zArg = Tcl_GetStringFromObj(objv[1], 0); + Tcl_CreateObjCommand(interp, zArg, DbObjCmd, (char*)p, DbDeleteCmd); + return TCL_OK; +} + +/* +** Provide a dummy Tcl_InitStubs if we are using this as a static +** library. +*/ +#ifndef USE_TCL_STUBS +# undef Tcl_InitStubs +# define Tcl_InitStubs(a,b,c) +#endif + +/* +** Make sure we have a PACKAGE_VERSION macro defined. This will be +** defined automatically by the TEA makefile. But other makefiles +** do not define it. +*/ +#ifndef PACKAGE_VERSION +# define PACKAGE_VERSION SQLITE_VERSION +#endif + +/* +** Initialize this module. +** +** This Tcl module contains only a single new Tcl command named "sqlite". +** (Hence there is no namespace. There is no point in using a namespace +** if the extension only supplies one new name!) The "sqlite" command is +** used to open a new SQLite database. See the DbMain() routine above +** for additional information. +*/ +EXTERN int Sqlite3_Init(Tcl_Interp *interp){ + Tcl_InitStubs(interp, "8.4", 0); + Tcl_CreateObjCommand(interp, "sqlite3", (Tcl_ObjCmdProc*)DbMain, 0, 0); + Tcl_PkgProvide(interp, "sqlite3", PACKAGE_VERSION); + Tcl_CreateObjCommand(interp, "sqlite", (Tcl_ObjCmdProc*)DbMain, 0, 0); + Tcl_PkgProvide(interp, "sqlite", PACKAGE_VERSION); + return TCL_OK; +} +EXTERN int Tclsqlite3_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); } +EXTERN int Sqlite3_SafeInit(Tcl_Interp *interp){ return TCL_OK; } +EXTERN int Tclsqlite3_SafeInit(Tcl_Interp *interp){ return TCL_OK; } + +#ifndef SQLITE_3_SUFFIX_ONLY +EXTERN int Sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); } +EXTERN int Tclsqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); } +EXTERN int Sqlite_SafeInit(Tcl_Interp *interp){ return TCL_OK; } +EXTERN int Tclsqlite_SafeInit(Tcl_Interp *interp){ return TCL_OK; } +#endif + +#ifdef TCLSH +/***************************************************************************** +** The code that follows is used to build standalone TCL interpreters +** that are statically linked with SQLite. +*/ + +/* +** If the macro TCLSH is one, then put in code this for the +** "main" routine that will initialize Tcl and take input from +** standard input, or if a file is named on the command line +** the TCL interpreter reads and evaluates that file. +*/ +#if TCLSH==1 +static char zMainloop[] = + "set line {}\n" + "while {![eof stdin]} {\n" + "if {$line!=\"\"} {\n" + "puts -nonewline \"> \"\n" + "} else {\n" + "puts -nonewline \"% \"\n" + "}\n" + "flush stdout\n" + "append line [gets stdin]\n" + "if {[info complete $line]} {\n" + "if {[catch {uplevel #0 $line} result]} {\n" + "puts stderr \"Error: $result\"\n" + "} elseif {$result!=\"\"} {\n" + "puts $result\n" + "}\n" + "set line {}\n" + "} else {\n" + "append line \\n\n" + "}\n" + "}\n" +; +#endif + +/* +** If the macro TCLSH is two, then get the main loop code out of +** the separate file "spaceanal_tcl.h". +*/ +#if TCLSH==2 +static char zMainloop[] = +#include "spaceanal_tcl.h" +; +#endif + +#define TCLSH_MAIN main /* Needed to fake out mktclapp */ +int TCLSH_MAIN(int argc, char **argv){ + Tcl_Interp *interp; + Tcl_FindExecutable(argv[0]); + interp = Tcl_CreateInterp(); + Sqlite3_Init(interp); +#ifdef SQLITE_TEST + { + extern int Md5_Init(Tcl_Interp*); + extern int Sqliteconfig_Init(Tcl_Interp*); + extern int Sqlitetest1_Init(Tcl_Interp*); + extern int Sqlitetest2_Init(Tcl_Interp*); + extern int Sqlitetest3_Init(Tcl_Interp*); + extern int Sqlitetest4_Init(Tcl_Interp*); + extern int Sqlitetest5_Init(Tcl_Interp*); + extern int Sqlitetest6_Init(Tcl_Interp*); + extern int Sqlitetest7_Init(Tcl_Interp*); + extern int Sqlitetest8_Init(Tcl_Interp*); + extern int Sqlitetest9_Init(Tcl_Interp*); + extern int Sqlitetestasync_Init(Tcl_Interp*); + extern int Sqlitetest_autoext_Init(Tcl_Interp*); + extern int Sqlitetest_func_Init(Tcl_Interp*); + extern int Sqlitetest_hexio_Init(Tcl_Interp*); + extern int Sqlitetest_malloc_Init(Tcl_Interp*); + extern int Sqlitetest_mutex_Init(Tcl_Interp*); + extern int Sqlitetestschema_Init(Tcl_Interp*); + extern int Sqlitetestsse_Init(Tcl_Interp*); + extern int Sqlitetesttclvar_Init(Tcl_Interp*); + extern int SqlitetestThread_Init(Tcl_Interp*); + extern int SqlitetestOnefile_Init(); + extern int SqlitetestOsinst_Init(Tcl_Interp*); + + Md5_Init(interp); + Sqliteconfig_Init(interp); + Sqlitetest1_Init(interp); + Sqlitetest2_Init(interp); + Sqlitetest3_Init(interp); + Sqlitetest4_Init(interp); + Sqlitetest5_Init(interp); + Sqlitetest6_Init(interp); + Sqlitetest7_Init(interp); + Sqlitetest8_Init(interp); + Sqlitetest9_Init(interp); + Sqlitetestasync_Init(interp); + Sqlitetest_autoext_Init(interp); + Sqlitetest_func_Init(interp); + Sqlitetest_hexio_Init(interp); + Sqlitetest_malloc_Init(interp); + Sqlitetest_mutex_Init(interp); + Sqlitetestschema_Init(interp); + Sqlitetesttclvar_Init(interp); + SqlitetestThread_Init(interp); + SqlitetestOnefile_Init(interp); + SqlitetestOsinst_Init(interp); + +#ifdef SQLITE_SSE + Sqlitetestsse_Init(interp); +#endif + } +#endif + if( argc>=2 || TCLSH==2 ){ + int i; + char zArgc[32]; + sqlite3_snprintf(sizeof(zArgc), zArgc, "%d", argc-(3-TCLSH)); + Tcl_SetVar(interp,"argc", zArgc, TCL_GLOBAL_ONLY); + Tcl_SetVar(interp,"argv0",argv[1],TCL_GLOBAL_ONLY); + Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY); + for(i=3-TCLSH; i<argc; i++){ + Tcl_SetVar(interp, "argv", argv[i], + TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE); + } + if( TCLSH==1 && Tcl_EvalFile(interp, argv[1])!=TCL_OK ){ + const char *zInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY); + if( zInfo==0 ) zInfo = interp->result; + fprintf(stderr,"%s: %s\n", *argv, zInfo); + return 1; + } + } + if( argc<=1 || TCLSH==2 ){ + Tcl_GlobalEval(interp, zMainloop); + } + return 0; +} +#endif /* TCLSH */ diff --git a/third_party/sqlite/src/test1.c b/third_party/sqlite/src/test1.c new file mode 100755 index 0000000..f83d38f --- /dev/null +++ b/third_party/sqlite/src/test1.c @@ -0,0 +1,4784 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** Code for testing all sorts of SQLite interfaces. This code +** is not included in the SQLite library. It is used for automated +** testing of the SQLite library. +** +** $Id: test1.c,v 1.317 2008/07/31 02:05:04 shane Exp $ +*/ +#include "sqliteInt.h" +#include "tcl.h" +#include <stdlib.h> +#include <string.h> + +/* +** This is a copy of the first part of the SqliteDb structure in +** tclsqlite.c. We need it here so that the get_sqlite_pointer routine +** can extract the sqlite3* pointer from an existing Tcl SQLite +** connection. +*/ +struct SqliteDb { + sqlite3 *db; +}; + +/* +** Convert text generated by the "%p" conversion format back into +** a pointer. +*/ +static int testHexToInt(int h){ + if( h>='0' && h<='9' ){ + return h - '0'; + }else if( h>='a' && h<='f' ){ + return h - 'a' + 10; + }else{ + assert( h>='A' && h<='F' ); + return h - 'A' + 10; + } +} +void *sqlite3TestTextToPtr(const char *z){ + void *p; + u64 v; + u32 v2; + if( z[0]=='0' && z[1]=='x' ){ + z += 2; + } + v = 0; + while( *z ){ + v = (v<<4) + testHexToInt(*z); + z++; + } + if( sizeof(p)==sizeof(v) ){ + memcpy(&p, &v, sizeof(p)); + }else{ + assert( sizeof(p)==sizeof(v2) ); + v2 = (u32)v; + memcpy(&p, &v2, sizeof(p)); + } + return p; +} + + +/* +** A TCL command that returns the address of the sqlite* pointer +** for an sqlite connection instance. Bad things happen if the +** input is not an sqlite connection. +*/ +static int get_sqlite_pointer( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + struct SqliteDb *p; + Tcl_CmdInfo cmdInfo; + char zBuf[100]; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "SQLITE-CONNECTION"); + return TCL_ERROR; + } + if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){ + Tcl_AppendResult(interp, "command not found: ", + Tcl_GetString(objv[1]), (char*)0); + return TCL_ERROR; + } + p = (struct SqliteDb*)cmdInfo.objClientData; + sprintf(zBuf, "%p", p->db); + if( strncmp(zBuf,"0x",2) ){ + sprintf(zBuf, "0x%p", p->db); + } + Tcl_AppendResult(interp, zBuf, 0); + return TCL_OK; +} + +/* +** Decode a pointer to an sqlite3 object. +*/ +int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){ + struct SqliteDb *p; + Tcl_CmdInfo cmdInfo; + if( Tcl_GetCommandInfo(interp, zA, &cmdInfo) ){ + p = (struct SqliteDb*)cmdInfo.objClientData; + *ppDb = p->db; + }else{ + *ppDb = (sqlite3*)sqlite3TestTextToPtr(zA); + } + return TCL_OK; +} + + +const char *sqlite3TestErrorName(int rc){ + const char *zName = 0; + switch( rc & 0xff ){ + case SQLITE_OK: zName = "SQLITE_OK"; break; + case SQLITE_ERROR: zName = "SQLITE_ERROR"; break; + case SQLITE_PERM: zName = "SQLITE_PERM"; break; + case SQLITE_ABORT: zName = "SQLITE_ABORT"; break; + case SQLITE_BUSY: zName = "SQLITE_BUSY"; break; + case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break; + case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break; + case SQLITE_READONLY: zName = "SQLITE_READONLY"; break; + case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break; + case SQLITE_IOERR: zName = "SQLITE_IOERR"; break; + case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break; + case SQLITE_FULL: zName = "SQLITE_FULL"; break; + case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break; + case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break; + case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break; + case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break; + case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break; + case SQLITE_MISMATCH: zName = "SQLITE_MISMATCH"; break; + case SQLITE_MISUSE: zName = "SQLITE_MISUSE"; break; + case SQLITE_NOLFS: zName = "SQLITE_NOLFS"; break; + case SQLITE_AUTH: zName = "SQLITE_AUTH"; break; + case SQLITE_FORMAT: zName = "SQLITE_FORMAT"; break; + case SQLITE_RANGE: zName = "SQLITE_RANGE"; break; + case SQLITE_ROW: zName = "SQLITE_ROW"; break; + case SQLITE_DONE: zName = "SQLITE_DONE"; break; + case SQLITE_NOTADB: zName = "SQLITE_NOTADB"; break; + case SQLITE_TOOBIG: zName = "SQLITE_TOOBIG"; break; + default: zName = "SQLITE_Unknown"; break; + } + return zName; +} +#define t1ErrorName sqlite3TestErrorName + +/* +** Convert an sqlite3_stmt* into an sqlite3*. This depends on the +** fact that the sqlite3* is the first field in the Vdbe structure. +*/ +#define StmtToDb(X) sqlite3_db_handle(X) + +/* +** Check a return value to make sure it agrees with the results +** from sqlite3_errcode. +*/ +int sqlite3TestErrCode(Tcl_Interp *interp, sqlite3 *db, int rc){ + if( rc!=SQLITE_MISUSE && rc!=SQLITE_OK && sqlite3_errcode(db)!=rc ){ + char zBuf[200]; + int r2 = sqlite3_errcode(db); + sprintf(zBuf, "error code %s (%d) does not match sqlite3_errcode %s (%d)", + t1ErrorName(rc), rc, t1ErrorName(r2), r2); + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, zBuf, 0); + return 1; + } + return 0; +} + +/* +** Decode a pointer to an sqlite3_stmt object. +*/ +static int getStmtPointer( + Tcl_Interp *interp, + const char *zArg, + sqlite3_stmt **ppStmt +){ + *ppStmt = (sqlite3_stmt*)sqlite3TestTextToPtr(zArg); + return TCL_OK; +} + +/* +** Generate a text representation of a pointer that can be understood +** by the getDbPointer and getVmPointer routines above. +** +** The problem is, on some machines (Solaris) if you do a printf with +** "%p" you cannot turn around and do a scanf with the same "%p" and +** get your pointer back. You have to prepend a "0x" before it will +** work. Or at least that is what is reported to me (drh). But this +** behavior varies from machine to machine. The solution used her is +** to test the string right after it is generated to see if it can be +** understood by scanf, and if not, try prepending an "0x" to see if +** that helps. If nothing works, a fatal error is generated. +*/ +int sqlite3TestMakePointerStr(Tcl_Interp *interp, char *zPtr, void *p){ + sqlite3_snprintf(100, zPtr, "%p", p); + return TCL_OK; +} + +/* +** The callback routine for sqlite3_exec_printf(). +*/ +static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){ + Tcl_DString *str = (Tcl_DString*)pArg; + int i; + + if( Tcl_DStringLength(str)==0 ){ + for(i=0; i<argc; i++){ + Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL"); + } + } + for(i=0; i<argc; i++){ + Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL"); + } + return 0; +} + +/* +** The I/O tracing callback. +*/ +#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE) +static FILE *iotrace_file = 0; +static void io_trace_callback(const char *zFormat, ...){ + va_list ap; + va_start(ap, zFormat); + vfprintf(iotrace_file, zFormat, ap); + va_end(ap); + fflush(iotrace_file); +} +#endif + +/* +** Usage: io_trace FILENAME +** +** Turn I/O tracing on or off. If FILENAME is not an empty string, +** I/O tracing begins going into FILENAME. If FILENAME is an empty +** string, I/O tracing is turned off. +*/ +static int test_io_trace( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ +#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE) + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " FILENAME\"", 0); + return TCL_ERROR; + } + if( iotrace_file ){ + if( iotrace_file!=stdout && iotrace_file!=stderr ){ + fclose(iotrace_file); + } + iotrace_file = 0; + sqlite3IoTrace = 0; + } + if( argv[1][0] ){ + if( strcmp(argv[1],"stdout")==0 ){ + iotrace_file = stdout; + }else if( strcmp(argv[1],"stderr")==0 ){ + iotrace_file = stderr; + }else{ + iotrace_file = fopen(argv[1], "w"); + } + sqlite3IoTrace = io_trace_callback; + } +#endif + return TCL_OK; +} + + +/* +** Usage: sqlite3_exec_printf DB FORMAT STRING +** +** Invoke the sqlite3_exec_printf() interface using the open database +** DB. The SQL is the string FORMAT. The format string should contain +** one %s or %q. STRING is the value inserted into %s or %q. +*/ +static int test_exec_printf( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + sqlite3 *db; + Tcl_DString str; + int rc; + char *zErr = 0; + char *zSql; + char zBuf[30]; + if( argc!=4 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " DB FORMAT STRING", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; + Tcl_DStringInit(&str); + zSql = sqlite3_mprintf(argv[2], argv[3]); + rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr); + sqlite3_free(zSql); + sprintf(zBuf, "%d", rc); + Tcl_AppendElement(interp, zBuf); + Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); + Tcl_DStringFree(&str); + if( zErr ) sqlite3_free(zErr); + if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; + return TCL_OK; +} + +/* +** Usage: db_enter DB +** db_leave DB +** +** Enter or leave the mutex on a database connection. +*/ +static int db_enter( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + sqlite3 *db; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " DB", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; + sqlite3_mutex_enter(db->mutex); + return TCL_OK; +} +static int db_leave( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + sqlite3 *db; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " DB", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; + sqlite3_mutex_leave(db->mutex); + return TCL_OK; +} + +/* +** Usage: sqlite3_exec DB SQL +** +** Invoke the sqlite3_exec interface using the open database DB +*/ +static int test_exec( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + sqlite3 *db; + Tcl_DString str; + int rc; + char *zErr = 0; + char *zSql; + int i, j; + char zBuf[30]; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " DB SQL", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; + Tcl_DStringInit(&str); + zSql = sqlite3_mprintf("%s", argv[2]); + for(i=j=0; zSql[i];){ + if( zSql[i]=='%' ){ + zSql[j++] = (testHexToInt(zSql[i+1])<<4) + testHexToInt(zSql[i+2]); + i += 3; + }else{ + zSql[j++] = zSql[i++]; + } + } + zSql[j] = 0; + rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr); + sqlite3_free(zSql); + sprintf(zBuf, "%d", rc); + Tcl_AppendElement(interp, zBuf); + Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); + Tcl_DStringFree(&str); + if( zErr ) sqlite3_free(zErr); + if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; + return TCL_OK; +} + +/* +** Usage: sqlite3_exec_nr DB SQL +** +** Invoke the sqlite3_exec interface using the open database DB. Discard +** all results +*/ +static int test_exec_nr( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + sqlite3 *db; + int rc; + char *zErr = 0; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " DB SQL", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; + rc = sqlite3_exec(db, argv[2], 0, 0, &zErr); + if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; + return TCL_OK; +} + +/* +** Usage: sqlite3_mprintf_z_test SEPARATOR ARG0 ARG1 ... +** +** Test the %z format of sqliteMPrintf(). Use multiple mprintf() calls to +** concatenate arg0 through argn using separator as the separator. +** Return the result. +*/ +static int test_mprintf_z( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + char *zResult = 0; + int i; + + for(i=2; i<argc && (i==2 || zResult); i++){ + zResult = sqlite3MPrintf(0, "%z%s%s", zResult, argv[1], argv[i]); + } + Tcl_AppendResult(interp, zResult, 0); + sqlite3_free(zResult); + return TCL_OK; +} + +/* +** Usage: sqlite3_mprintf_n_test STRING +** +** Test the %n format of sqliteMPrintf(). Return the length of the +** input string. +*/ +static int test_mprintf_n( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + char *zStr; + int n = 0; + zStr = sqlite3MPrintf(0, "%s%n", argv[1], &n); + sqlite3_free(zStr); + Tcl_SetObjResult(interp, Tcl_NewIntObj(n)); + return TCL_OK; +} + +/* +** Usage: sqlite3_snprintf_int SIZE FORMAT INT +** +** Test the of sqlite3_snprintf() routine. SIZE is the size of the +** output buffer in bytes. The maximum size is 100. FORMAT is the +** format string. INT is a single integer argument. The FORMAT +** string must require no more than this one integer argument. If +** You pass in a format string that requires more than one argument, +** bad things will happen. +*/ +static int test_snprintf_int( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + char zStr[100]; + int n = atoi(argv[1]); + const char *zFormat = argv[2]; + int a1 = atoi(argv[3]); + if( n>sizeof(zStr) ) n = sizeof(zStr); + sqlite3_snprintf(sizeof(zStr), zStr, "abcdefghijklmnopqrstuvwxyz"); + sqlite3_snprintf(n, zStr, zFormat, a1); + Tcl_AppendResult(interp, zStr, 0); + return TCL_OK; +} + +#ifndef SQLITE_OMIT_GET_TABLE + +/* +** Usage: sqlite3_get_table_printf DB FORMAT STRING ?--no-counts? +** +** Invoke the sqlite3_get_table_printf() interface using the open database +** DB. The SQL is the string FORMAT. The format string should contain +** one %s or %q. STRING is the value inserted into %s or %q. +*/ +static int test_get_table_printf( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + sqlite3 *db; + Tcl_DString str; + int rc; + char *zErr = 0; + int nRow, nCol; + char **aResult; + int i; + char zBuf[30]; + char *zSql; + int resCount = -1; + if( argc==5 ){ + if( Tcl_GetInt(interp, argv[4], &resCount) ) return TCL_ERROR; + } + if( argc!=4 && argc!=5 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " DB FORMAT STRING ?COUNT?", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; + Tcl_DStringInit(&str); + zSql = sqlite3_mprintf(argv[2],argv[3]); + if( argc==5 ){ + rc = sqlite3_get_table(db, zSql, &aResult, 0, 0, &zErr); + }else{ + rc = sqlite3_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr); + resCount = (nRow+1)*nCol; + } + sqlite3_free(zSql); + sprintf(zBuf, "%d", rc); + Tcl_AppendElement(interp, zBuf); + if( rc==SQLITE_OK ){ + if( argc==4 ){ + sprintf(zBuf, "%d", nRow); + Tcl_AppendElement(interp, zBuf); + sprintf(zBuf, "%d", nCol); + Tcl_AppendElement(interp, zBuf); + } + for(i=0; i<resCount; i++){ + Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL"); + } + }else{ + Tcl_AppendElement(interp, zErr); + } + sqlite3_free_table(aResult); + if( zErr ) sqlite3_free(zErr); + if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; + return TCL_OK; +} + +#endif /* SQLITE_OMIT_GET_TABLE */ + + +/* +** Usage: sqlite3_last_insert_rowid DB +** +** Returns the integer ROWID of the most recent insert. +*/ +static int test_last_rowid( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + sqlite3 *db; + char zBuf[30]; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; + sprintf(zBuf, "%lld", sqlite3_last_insert_rowid(db)); + Tcl_AppendResult(interp, zBuf, 0); + return SQLITE_OK; +} + +/* +** Usage: sqlite3_key DB KEY +** +** Set the codec key. +*/ +static int test_key( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + sqlite3 *db; + const char *zKey; + int nKey; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " FILENAME\"", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; + zKey = argv[2]; + nKey = strlen(zKey); +#ifdef SQLITE_HAS_CODEC + sqlite3_key(db, zKey, nKey); +#endif + return TCL_OK; +} + +/* +** Usage: sqlite3_rekey DB KEY +** +** Change the codec key. +*/ +static int test_rekey( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + sqlite3 *db; + const char *zKey; + int nKey; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " FILENAME\"", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; + zKey = argv[2]; + nKey = strlen(zKey); +#ifdef SQLITE_HAS_CODEC + sqlite3_rekey(db, zKey, nKey); +#endif + return TCL_OK; +} + +/* +** Usage: sqlite3_close DB +** +** Closes the database opened by sqlite3_open. +*/ +static int sqlite_test_close( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + sqlite3 *db; + int rc; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " FILENAME\"", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; + rc = sqlite3_close(db); + Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); + return TCL_OK; +} + +/* +** Implementation of the x_coalesce() function. +** Return the first argument non-NULL argument. +*/ +static void t1_ifnullFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + int i; + for(i=0; i<argc; i++){ + if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){ + int n = sqlite3_value_bytes(argv[i]); + sqlite3_result_text(context, (char*)sqlite3_value_text(argv[i]), + n, SQLITE_TRANSIENT); + break; + } + } +} + +/* +** These are test functions. hex8() interprets its argument as +** UTF8 and returns a hex encoding. hex16le() interprets its argument +** as UTF16le and returns a hex encoding. +*/ +static void hex8Func(sqlite3_context *p, int argc, sqlite3_value **argv){ + const unsigned char *z; + int i; + char zBuf[200]; + z = sqlite3_value_text(argv[0]); + for(i=0; i<sizeof(zBuf)/2 - 2 && z[i]; i++){ + sprintf(&zBuf[i*2], "%02x", z[i]&0xff); + } + zBuf[i*2] = 0; + sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT); +} +#ifndef SQLITE_OMIT_UTF16 +static void hex16Func(sqlite3_context *p, int argc, sqlite3_value **argv){ + const unsigned short int *z; + int i; + char zBuf[400]; + z = sqlite3_value_text16(argv[0]); + for(i=0; i<sizeof(zBuf)/4 - 4 && z[i]; i++){ + sprintf(&zBuf[i*4], "%04x", z[i]&0xff); + } + zBuf[i*4] = 0; + sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT); +} +#endif + +/* +** A structure into which to accumulate text. +*/ +struct dstr { + int nAlloc; /* Space allocated */ + int nUsed; /* Space used */ + char *z; /* The space */ +}; + +/* +** Append text to a dstr +*/ +static void dstrAppend(struct dstr *p, const char *z, int divider){ + int n = strlen(z); + if( p->nUsed + n + 2 > p->nAlloc ){ + char *zNew; + p->nAlloc = p->nAlloc*2 + n + 200; + zNew = sqlite3_realloc(p->z, p->nAlloc); + if( zNew==0 ){ + sqlite3_free(p->z); + memset(p, 0, sizeof(*p)); + return; + } + p->z = zNew; + } + if( divider && p->nUsed>0 ){ + p->z[p->nUsed++] = divider; + } + memcpy(&p->z[p->nUsed], z, n+1); + p->nUsed += n; +} + +/* +** Invoked for each callback from sqlite3ExecFunc +*/ +static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){ + struct dstr *p = (struct dstr*)pData; + int i; + for(i=0; i<argc; i++){ + if( argv[i]==0 ){ + dstrAppend(p, "NULL", ' '); + }else{ + dstrAppend(p, argv[i], ' '); + } + } + return 0; +} + +/* +** Implementation of the x_sqlite_exec() function. This function takes +** a single argument and attempts to execute that argument as SQL code. +** This is illegal and should set the SQLITE_MISUSE flag on the database. +** +** 2004-Jan-07: We have changed this to make it legal to call sqlite3_exec() +** from within a function call. +** +** This routine simulates the effect of having two threads attempt to +** use the same database at the same time. +*/ +static void sqlite3ExecFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + struct dstr x; + memset(&x, 0, sizeof(x)); + (void)sqlite3_exec((sqlite3*)sqlite3_user_data(context), + (char*)sqlite3_value_text(argv[0]), + execFuncCallback, &x, 0); + sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT); + sqlite3_free(x.z); +} + +/* +** Implementation of tkt2213func(), a scalar function that takes exactly +** one argument. It has two interesting features: +** +** * It calls sqlite3_value_text() 3 times on the argument sqlite3_value*. +** If the three pointers returned are not the same an SQL error is raised. +** +** * Otherwise it returns a copy of the text representation of its +** argument in such a way as the VDBE representation is a Mem* cell +** with the MEM_Term flag clear. +** +** Ticket #2213 can therefore be tested by evaluating the following +** SQL expression: +** +** tkt2213func(tkt2213func('a string')); +*/ +static void tkt2213Function( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + int nText; + unsigned char const *zText1; + unsigned char const *zText2; + unsigned char const *zText3; + + nText = sqlite3_value_bytes(argv[0]); + zText1 = sqlite3_value_text(argv[0]); + zText2 = sqlite3_value_text(argv[0]); + zText3 = sqlite3_value_text(argv[0]); + + if( zText1!=zText2 || zText2!=zText3 ){ + sqlite3_result_error(context, "tkt2213 is not fixed", -1); + }else{ + char *zCopy = (char *)sqlite3_malloc(nText); + memcpy(zCopy, zText1, nText); + sqlite3_result_text(context, zCopy, nText, sqlite3_free); + } +} + +/* +** The following SQL function takes 4 arguments. The 2nd and +** 4th argument must be one of these strings: 'text', 'text16', +** or 'blob' corresponding to API functions +** +** sqlite3_value_text() +** sqlite3_value_text16() +** sqlite3_value_blob() +** +** The third argument is a string, either 'bytes' or 'bytes16' or 'noop', +** corresponding to APIs: +** +** sqlite3_value_bytes() +** sqlite3_value_bytes16() +** noop +** +** The APIs designated by the 2nd through 4th arguments are applied +** to the first argument in order. If the pointers returned by the +** second and fourth are different, this routine returns 1. Otherwise, +** this routine returns 0. +** +** This function is used to test to see when returned pointers from +** the _text(), _text16() and _blob() APIs become invalidated. +*/ +static void ptrChngFunction( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const void *p1, *p2; + const char *zCmd; + if( argc!=4 ) return; + zCmd = (const char*)sqlite3_value_text(argv[1]); + if( zCmd==0 ) return; + if( strcmp(zCmd,"text")==0 ){ + p1 = (const void*)sqlite3_value_text(argv[0]); +#ifndef SQLITE_OMIT_UTF16 + }else if( strcmp(zCmd, "text16")==0 ){ + p1 = (const void*)sqlite3_value_text16(argv[0]); +#endif + }else if( strcmp(zCmd, "blob")==0 ){ + p1 = (const void*)sqlite3_value_blob(argv[0]); + }else{ + return; + } + zCmd = (const char*)sqlite3_value_text(argv[2]); + if( zCmd==0 ) return; + if( strcmp(zCmd,"bytes")==0 ){ + sqlite3_value_bytes(argv[0]); +#ifndef SQLITE_OMIT_UTF16 + }else if( strcmp(zCmd, "bytes16")==0 ){ + sqlite3_value_bytes16(argv[0]); +#endif + }else if( strcmp(zCmd, "noop")==0 ){ + /* do nothing */ + }else{ + return; + } + zCmd = (const char*)sqlite3_value_text(argv[3]); + if( zCmd==0 ) return; + if( strcmp(zCmd,"text")==0 ){ + p2 = (const void*)sqlite3_value_text(argv[0]); +#ifndef SQLITE_OMIT_UTF16 + }else if( strcmp(zCmd, "text16")==0 ){ + p2 = (const void*)sqlite3_value_text16(argv[0]); +#endif + }else if( strcmp(zCmd, "blob")==0 ){ + p2 = (const void*)sqlite3_value_blob(argv[0]); + }else{ + return; + } + sqlite3_result_int(context, p1!=p2); +} + + +/* +** Usage: sqlite_test_create_function DB +** +** Call the sqlite3_create_function API on the given database in order +** to create a function named "x_coalesce". This function does the same thing +** as the "coalesce" function. This function also registers an SQL function +** named "x_sqlite_exec" that invokes sqlite3_exec(). Invoking sqlite3_exec() +** in this way is illegal recursion and should raise an SQLITE_MISUSE error. +** The effect is similar to trying to use the same database connection from +** two threads at the same time. +** +** The original motivation for this routine was to be able to call the +** sqlite3_create_function function while a query is in progress in order +** to test the SQLITE_MISUSE detection logic. +*/ +static int test_create_function( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + int rc; + sqlite3 *db; + extern void Md5_Register(sqlite3*); + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " DB\"", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; + rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_ANY, 0, + t1_ifnullFunc, 0, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "hex8", 1, SQLITE_ANY, 0, + hex8Func, 0, 0); + } +#ifndef SQLITE_OMIT_UTF16 + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "hex16", 1, SQLITE_ANY, 0, + hex16Func, 0, 0); + } +#endif + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "tkt2213func", 1, SQLITE_ANY, 0, + tkt2213Function, 0, 0); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "pointer_change", 4, SQLITE_ANY, 0, + ptrChngFunction, 0, 0); + } + +#ifndef SQLITE_OMIT_UTF16 + /* Use the sqlite3_create_function16() API here. Mainly for fun, but also + ** because it is not tested anywhere else. */ + if( rc==SQLITE_OK ){ + const void *zUtf16; + sqlite3_value *pVal; + sqlite3_mutex_enter(db->mutex); + pVal = sqlite3ValueNew(db); + sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC); + zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE); + if( db->mallocFailed ){ + rc = SQLITE_NOMEM; + }else{ + rc = sqlite3_create_function16(db, zUtf16, + 1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0); + } + sqlite3ValueFree(pVal); + sqlite3_mutex_leave(db->mutex); + } +#endif + + if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; + Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0); + return TCL_OK; +} + +/* +** Routines to implement the x_count() aggregate function. +** +** x_count() counts the number of non-null arguments. But there are +** some twists for testing purposes. +** +** If the argument to x_count() is 40 then a UTF-8 error is reported +** on the step function. If x_count(41) is seen, then a UTF-16 error +** is reported on the step function. If the total count is 42, then +** a UTF-8 error is reported on the finalize function. +*/ +typedef struct t1CountCtx t1CountCtx; +struct t1CountCtx { + int n; +}; +static void t1CountStep( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + t1CountCtx *p; + p = sqlite3_aggregate_context(context, sizeof(*p)); + if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){ + p->n++; + } + if( argc>0 ){ + int v = sqlite3_value_int(argv[0]); + if( v==40 ){ + sqlite3_result_error(context, "value of 40 handed to x_count", -1); +#ifndef SQLITE_OMIT_UTF16 + }else if( v==41 ){ + const char zUtf16ErrMsg[] = { 0, 0x61, 0, 0x62, 0, 0x63, 0, 0, 0}; + sqlite3_result_error16(context, &zUtf16ErrMsg[1-SQLITE_BIGENDIAN], -1); +#endif + } + } +} +static void t1CountFinalize(sqlite3_context *context){ + t1CountCtx *p; + p = sqlite3_aggregate_context(context, sizeof(*p)); + if( p ){ + if( p->n==42 ){ + sqlite3_result_error(context, "x_count totals to 42", -1); + }else{ + sqlite3_result_int(context, p ? p->n : 0); + } + } +} + +static void legacyCountStep( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + /* no-op */ +} +static void legacyCountFinalize(sqlite3_context *context){ + sqlite3_result_int(context, sqlite3_aggregate_count(context)); +} + +/* +** Usage: sqlite3_create_aggregate DB +** +** Call the sqlite3_create_function API on the given database in order +** to create a function named "x_count". This function is similar +** to the built-in count() function, with a few special quirks +** for testing the sqlite3_result_error() APIs. +** +** The original motivation for this routine was to be able to call the +** sqlite3_create_aggregate function while a query is in progress in order +** to test the SQLITE_MISUSE detection logic. See misuse.test. +** +** This routine was later extended to test the use of sqlite3_result_error() +** within aggregate functions. +** +** Later: It is now also extended to register the aggregate function +** "legacy_count()" with the supplied database handle. This is used +** to test the deprecated sqlite3_aggregate_count() API. +*/ +static int test_create_aggregate( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + sqlite3 *db; + int rc; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " FILENAME\"", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; + rc = sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0, + t1CountStep,t1CountFinalize); + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0, + t1CountStep,t1CountFinalize); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "legacy_count", 0, SQLITE_ANY, 0, 0, + legacyCountStep, legacyCountFinalize + ); + } + if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; + Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0); + return TCL_OK; +} + + +/* +** Usage: printf TEXT +** +** Send output to printf. Use this rather than puts to merge the output +** in the correct sequence with debugging printfs inserted into C code. +** Puts uses a separate buffer and debugging statements will be out of +** sequence if it is used. +*/ +static int test_printf( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " TEXT\"", 0); + return TCL_ERROR; + } + printf("%s\n", argv[1]); + return TCL_OK; +} + + + +/* +** Usage: sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER +** +** Call mprintf with three integer arguments +*/ +static int sqlite3_mprintf_int( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + int a[3], i; + char *z; + if( argc!=5 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " FORMAT INT INT INT\"", 0); + return TCL_ERROR; + } + for(i=2; i<5; i++){ + if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; + } + z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]); + Tcl_AppendResult(interp, z, 0); + sqlite3_free(z); + return TCL_OK; +} + +/* +** If zNum represents an integer that will fit in 64-bits, then set +** *pValue to that integer and return true. Otherwise return false. +*/ +static int sqlite3GetInt64(const char *zNum, i64 *pValue){ + if( sqlite3FitsIn64Bits(zNum, 0) ){ + sqlite3Atoi64(zNum, pValue); + return 1; + } + return 0; +} + +/* +** Usage: sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER +** +** Call mprintf with three 64-bit integer arguments +*/ +static int sqlite3_mprintf_int64( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + int i; + sqlite_int64 a[3]; + char *z; + if( argc!=5 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " FORMAT INT INT INT\"", 0); + return TCL_ERROR; + } + for(i=2; i<5; i++){ + if( !sqlite3GetInt64(argv[i], &a[i-2]) ){ + Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0); + return TCL_ERROR; + } + } + z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]); + Tcl_AppendResult(interp, z, 0); + sqlite3_free(z); + return TCL_OK; +} + +/* +** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING +** +** Call mprintf with two integer arguments and one string argument +*/ +static int sqlite3_mprintf_str( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + int a[3], i; + char *z; + if( argc<4 || argc>5 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " FORMAT INT INT ?STRING?\"", 0); + return TCL_ERROR; + } + for(i=2; i<4; i++){ + if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; + } + z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL); + Tcl_AppendResult(interp, z, 0); + sqlite3_free(z); + return TCL_OK; +} + +/* +** Usage: sqlite3_snprintf_str INTEGER FORMAT INTEGER INTEGER STRING +** +** Call mprintf with two integer arguments and one string argument +*/ +static int sqlite3_snprintf_str( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + int a[3], i; + int n; + char *z; + if( argc<5 || argc>6 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " INT FORMAT INT INT ?STRING?\"", 0); + return TCL_ERROR; + } + if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; + if( n<0 ){ + Tcl_AppendResult(interp, "N must be non-negative", 0); + return TCL_ERROR; + } + for(i=3; i<5; i++){ + if( Tcl_GetInt(interp, argv[i], &a[i-3]) ) return TCL_ERROR; + } + z = sqlite3_malloc( n+1 ); + sqlite3_snprintf(n, z, argv[2], a[0], a[1], argc>4 ? argv[5] : NULL); + Tcl_AppendResult(interp, z, 0); + sqlite3_free(z); + return TCL_OK; +} + +/* +** Usage: sqlite3_mprintf_double FORMAT INTEGER INTEGER DOUBLE +** +** Call mprintf with two integer arguments and one double argument +*/ +static int sqlite3_mprintf_double( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + int a[3], i; + double r; + char *z; + if( argc!=5 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " FORMAT INT INT DOUBLE\"", 0); + return TCL_ERROR; + } + for(i=2; i<4; i++){ + if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR; + } + if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR; + z = sqlite3_mprintf(argv[1], a[0], a[1], r); + Tcl_AppendResult(interp, z, 0); + sqlite3_free(z); + return TCL_OK; +} + +/* +** Usage: sqlite3_mprintf_scaled FORMAT DOUBLE DOUBLE +** +** Call mprintf with a single double argument which is the product of the +** two arguments given above. This is used to generate overflow and underflow +** doubles to test that they are converted properly. +*/ +static int sqlite3_mprintf_scaled( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + int i; + double r[2]; + char *z; + if( argc!=4 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " FORMAT DOUBLE DOUBLE\"", 0); + return TCL_ERROR; + } + for(i=2; i<4; i++){ + if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR; + } + z = sqlite3_mprintf(argv[1], r[0]*r[1]); + Tcl_AppendResult(interp, z, 0); + sqlite3_free(z); + return TCL_OK; +} + +/* +** Usage: sqlite3_mprintf_stronly FORMAT STRING +** +** Call mprintf with a single double argument which is the product of the +** two arguments given above. This is used to generate overflow and underflow +** doubles to test that they are converted properly. +*/ +static int sqlite3_mprintf_stronly( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + char *z; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " FORMAT STRING\"", 0); + return TCL_ERROR; + } + z = sqlite3_mprintf(argv[1], argv[2]); + Tcl_AppendResult(interp, z, 0); + sqlite3_free(z); + return TCL_OK; +} + +/* +** Usage: sqlite3_mprintf_hexdouble FORMAT HEX +** +** Call mprintf with a single double argument which is derived from the +** hexadecimal encoding of an IEEE double. +*/ +static int sqlite3_mprintf_hexdouble( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + char *z; + double r; + unsigned int x1, x2; + sqlite_uint64 d; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " FORMAT STRING\"", 0); + return TCL_ERROR; + } + if( sscanf(argv[2], "%08x%08x", &x2, &x1)!=2 ){ + Tcl_AppendResult(interp, "2nd argument should be 16-characters of hex", 0); + return TCL_ERROR; + } + d = x2; + d = (d<<32) + x1; + memcpy(&r, &d, sizeof(r)); + z = sqlite3_mprintf(argv[1], r); + Tcl_AppendResult(interp, z, 0); + sqlite3_free(z); + return TCL_OK; +} + +/* +** Usage: sqlite3_enable_shared_cache BOOLEAN +** +*/ +#if !defined(SQLITE_OMIT_SHARED_CACHE) +static int test_enable_shared( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + int rc; + int enable; + int ret = 0; + extern int sqlite3SharedCacheEnabled; + + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN"); + return TCL_ERROR; + } + if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ){ + return TCL_ERROR; + } + ret = sqlite3SharedCacheEnabled; + rc = sqlite3_enable_shared_cache(enable); + if( rc!=SQLITE_OK ){ + Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC); + return TCL_ERROR; + } + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(ret)); + return TCL_OK; +} +#endif + + + +/* +** Usage: sqlite3_extended_result_codes DB BOOLEAN +** +*/ +static int test_extended_result_codes( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + int enable; + sqlite3 *db; + + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB BOOLEAN"); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + if( Tcl_GetBooleanFromObj(interp, objv[2], &enable) ) return TCL_ERROR; + sqlite3_extended_result_codes(db, enable); + return TCL_OK; +} + +/* +** Usage: sqlite3_libversion_number +** +*/ +static int test_libversion_number( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_libversion_number())); + return TCL_OK; +} + +/* +** Usage: sqlite3_table_column_metadata DB dbname tblname colname +** +*/ +#ifdef SQLITE_ENABLE_COLUMN_METADATA +static int test_table_column_metadata( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + sqlite3 *db; + const char *zDb; + const char *zTbl; + const char *zCol; + int rc; + Tcl_Obj *pRet; + + const char *zDatatype; + const char *zCollseq; + int notnull; + int primarykey; + int autoincrement; + + if( objc!=5 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB dbname tblname colname"); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + zDb = Tcl_GetString(objv[2]); + zTbl = Tcl_GetString(objv[3]); + zCol = Tcl_GetString(objv[4]); + + if( strlen(zDb)==0 ) zDb = 0; + + rc = sqlite3_table_column_metadata(db, zDb, zTbl, zCol, + &zDatatype, &zCollseq, ¬null, &primarykey, &autoincrement); + + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, sqlite3_errmsg(db), 0); + return TCL_ERROR; + } + + pRet = Tcl_NewObj(); + Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zDatatype, -1)); + Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zCollseq, -1)); + Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(notnull)); + Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(primarykey)); + Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(autoincrement)); + Tcl_SetObjResult(interp, pRet); + + return TCL_OK; +} +#endif + +#ifndef SQLITE_OMIT_INCRBLOB + +/* +** sqlite3_blob_read CHANNEL OFFSET N +** +** This command is used to test the sqlite3_blob_read() in ways that +** the Tcl channel interface does not. The first argument should +** be the name of a valid channel created by the [incrblob] method +** of a database handle. This function calls sqlite3_blob_read() +** to read N bytes from offset OFFSET from the underlying SQLite +** blob handle. +** +** On success, a byte-array object containing the read data is +** returned. On failure, the interpreter result is set to the +** text representation of the returned error code (i.e. "SQLITE_NOMEM") +** and a Tcl exception is thrown. +*/ +static int test_blob_read( + ClientData clientData, /* Not used */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + Tcl_Channel channel; + ClientData instanceData; + sqlite3_blob *pBlob; + int notUsed; + int nByte; + int iOffset; + unsigned char *zBuf; + int rc; + + if( objc!=4 ){ + Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL OFFSET N"); + return TCL_ERROR; + } + + channel = Tcl_GetChannel(interp, Tcl_GetString(objv[1]), ¬Used); + if( !channel + || TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset) + || TCL_OK!=Tcl_GetIntFromObj(interp, objv[3], &nByte) + || nByte<0 || iOffset<0 + ){ + return TCL_ERROR; + } + + instanceData = Tcl_GetChannelInstanceData(channel); + pBlob = *((sqlite3_blob **)instanceData); + + zBuf = (unsigned char *)Tcl_Alloc(nByte); + rc = sqlite3_blob_read(pBlob, zBuf, nByte, iOffset); + if( rc==SQLITE_OK ){ + Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zBuf, nByte)); + }else{ + Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE); + } + Tcl_Free((char *)zBuf); + + return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR); +} + +/* +** sqlite3_blob_write CHANNEL OFFSET DATA +** +** This command is used to test the sqlite3_blob_write() in ways that +** the Tcl channel interface does not. The first argument should +** be the name of a valid channel created by the [incrblob] method +** of a database handle. This function calls sqlite3_blob_write() +** to write the DATA byte-array to the underlying SQLite blob handle. +** at offset OFFSET. +** +** On success, an empty string is returned. On failure, the interpreter +** result is set to the text representation of the returned error code +** (i.e. "SQLITE_NOMEM") and a Tcl exception is thrown. +*/ +static int test_blob_write( + ClientData clientData, /* Not used */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + Tcl_Channel channel; + ClientData instanceData; + sqlite3_blob *pBlob; + int notUsed; + int iOffset; + int rc; + + unsigned char *zBuf; + int nBuf; + + if( objc!=4 ){ + Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL OFFSET DATA"); + return TCL_ERROR; + } + + channel = Tcl_GetChannel(interp, Tcl_GetString(objv[1]), ¬Used); + if( !channel + || TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset) + || iOffset<0 + ){ + return TCL_ERROR; + } + + instanceData = Tcl_GetChannelInstanceData(channel); + pBlob = *((sqlite3_blob **)instanceData); + + zBuf = Tcl_GetByteArrayFromObj(objv[3], &nBuf); + rc = sqlite3_blob_write(pBlob, zBuf, nBuf, iOffset); + if( rc!=SQLITE_OK ){ + Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE); + } + + return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR); +} +#endif + +/* +** Usage: sqlite3_create_collation_v2 DB-HANDLE NAME CMP-PROC DEL-PROC +** +** This Tcl proc is used for testing the experimental +** sqlite3_create_collation_v2() interface. +*/ +struct TestCollationX { + Tcl_Interp *interp; + Tcl_Obj *pCmp; + Tcl_Obj *pDel; +}; +typedef struct TestCollationX TestCollationX; +static void testCreateCollationDel(void *pCtx){ + TestCollationX *p = (TestCollationX *)pCtx; + + int rc = Tcl_EvalObjEx(p->interp, p->pDel, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL); + if( rc!=TCL_OK ){ + Tcl_BackgroundError(p->interp); + } + + Tcl_DecrRefCount(p->pCmp); + Tcl_DecrRefCount(p->pDel); + sqlite3_free((void *)p); +} +static int testCreateCollationCmp( + void *pCtx, + int nLeft, + const void *zLeft, + int nRight, + const void *zRight +){ + TestCollationX *p = (TestCollationX *)pCtx; + Tcl_Obj *pScript = Tcl_DuplicateObj(p->pCmp); + int iRes = 0; + + Tcl_IncrRefCount(pScript); + Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj((char *)zLeft, nLeft)); + Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj((char *)zRight,nRight)); + + if( TCL_OK!=Tcl_EvalObjEx(p->interp, pScript, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL) + || TCL_OK!=Tcl_GetIntFromObj(p->interp, Tcl_GetObjResult(p->interp), &iRes) + ){ + Tcl_BackgroundError(p->interp); + } + Tcl_DecrRefCount(pScript); + + return iRes; +} +static int test_create_collation_v2( + ClientData clientData, /* Not used */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + TestCollationX *p; + sqlite3 *db; + int rc; + + if( objc!=5 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE NAME CMP-PROC DEL-PROC"); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + + p = (TestCollationX *)sqlite3_malloc(sizeof(TestCollationX)); + p->pCmp = objv[3]; + p->pDel = objv[4]; + p->interp = interp; + Tcl_IncrRefCount(p->pCmp); + Tcl_IncrRefCount(p->pDel); + + rc = sqlite3_create_collation_v2(db, Tcl_GetString(objv[2]), 16, + (void *)p, testCreateCollationCmp, testCreateCollationDel + ); + if( rc!=SQLITE_MISUSE ){ + Tcl_AppendResult(interp, "sqlite3_create_collate_v2() failed to detect " + "an invalid encoding", (char*)0); + return TCL_ERROR; + } + rc = sqlite3_create_collation_v2(db, Tcl_GetString(objv[2]), SQLITE_UTF8, + (void *)p, testCreateCollationCmp, testCreateCollationDel + ); + return TCL_OK; +} + +/* +** Usage: sqlite3_load_extension DB-HANDLE FILE ?PROC? +*/ +static int test_load_extension( + ClientData clientData, /* Not used */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + Tcl_CmdInfo cmdInfo; + sqlite3 *db; + int rc; + char *zDb; + char *zFile; + char *zProc = 0; + char *zErr = 0; + + if( objc!=4 && objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE FILE ?PROC?"); + return TCL_ERROR; + } + zDb = Tcl_GetString(objv[1]); + zFile = Tcl_GetString(objv[2]); + if( objc==4 ){ + zProc = Tcl_GetString(objv[3]); + } + + /* Extract the C database handle from the Tcl command name */ + if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){ + Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0); + return TCL_ERROR; + } + db = ((struct SqliteDb*)cmdInfo.objClientData)->db; + assert(db); + + /* Call the underlying C function. If an error occurs, set rc to + ** TCL_ERROR and load any error string into the interpreter. If no + ** error occurs, set rc to TCL_OK. + */ +#ifdef SQLITE_OMIT_LOAD_EXTENSION + rc = SQLITE_ERROR; + zErr = sqlite3_mprintf("this build omits sqlite3_load_extension()"); +#else + rc = sqlite3_load_extension(db, zFile, zProc, &zErr); +#endif + if( rc!=SQLITE_OK ){ + Tcl_SetResult(interp, zErr ? zErr : "", TCL_VOLATILE); + rc = TCL_ERROR; + }else{ + rc = TCL_OK; + } + sqlite3_free(zErr); + + return rc; +} + +/* +** Usage: sqlite3_enable_load_extension DB-HANDLE ONOFF +*/ +static int test_enable_load( + ClientData clientData, /* Not used */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + Tcl_CmdInfo cmdInfo; + sqlite3 *db; + char *zDb; + int onoff; + + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE ONOFF"); + return TCL_ERROR; + } + zDb = Tcl_GetString(objv[1]); + + /* Extract the C database handle from the Tcl command name */ + if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){ + Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0); + return TCL_ERROR; + } + db = ((struct SqliteDb*)cmdInfo.objClientData)->db; + assert(db); + + /* Get the onoff parameter */ + if( Tcl_GetBooleanFromObj(interp, objv[2], &onoff) ){ + return TCL_ERROR; + } + +#ifdef SQLITE_OMIT_LOAD_EXTENSION + Tcl_AppendResult(interp, "this build omits sqlite3_load_extension()"); + return TCL_ERROR; +#else + sqlite3_enable_load_extension(db, onoff); + return TCL_OK; +#endif +} + +/* +** Usage: sqlite_abort +** +** Shutdown the process immediately. This is not a clean shutdown. +** This command is used to test the recoverability of a database in +** the event of a program crash. +*/ +static int sqlite_abort( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + assert( interp==0 ); /* This will always fail */ + return TCL_OK; +} + +/* +** The following routine is a user-defined SQL function whose purpose +** is to test the sqlite_set_result() API. +*/ +static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + while( argc>=2 ){ + const char *zArg0 = (char*)sqlite3_value_text(argv[0]); + if( zArg0 ){ + if( 0==sqlite3StrICmp(zArg0, "int") ){ + sqlite3_result_int(context, sqlite3_value_int(argv[1])); + }else if( sqlite3StrICmp(zArg0,"int64")==0 ){ + sqlite3_result_int64(context, sqlite3_value_int64(argv[1])); + }else if( sqlite3StrICmp(zArg0,"string")==0 ){ + sqlite3_result_text(context, (char*)sqlite3_value_text(argv[1]), -1, + SQLITE_TRANSIENT); + }else if( sqlite3StrICmp(zArg0,"double")==0 ){ + sqlite3_result_double(context, sqlite3_value_double(argv[1])); + }else if( sqlite3StrICmp(zArg0,"null")==0 ){ + sqlite3_result_null(context); + }else if( sqlite3StrICmp(zArg0,"value")==0 ){ + sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]); + }else{ + goto error_out; + } + }else{ + goto error_out; + } + argc -= 2; + argv += 2; + } + return; + +error_out: + sqlite3_result_error(context,"first argument should be one of: " + "int int64 string double null value", -1); +} + +/* +** Usage: sqlite_register_test_function DB NAME +** +** Register the test SQL function on the database DB under the name NAME. +*/ +static int test_register_func( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + sqlite3 *db; + int rc; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " DB FUNCTION-NAME", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; + rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, + testFunc, 0, 0); + if( rc!=0 ){ + Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0); + return TCL_ERROR; + } + if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; + return TCL_OK; +} + +/* +** Usage: sqlite3_finalize STMT +** +** Finalize a statement handle. +*/ +static int test_finalize( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int rc; + sqlite3 *db = 0; + + if( objc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + + if( pStmt ){ + db = StmtToDb(pStmt); + } + rc = sqlite3_finalize(pStmt); + Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); + if( db && sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; + return TCL_OK; +} + +/* +** Usage: sqlite3_next_stmt DB STMT +** +** Return the next statment in sequence after STMT. +*/ +static int test_next_stmt( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + sqlite3 *db = 0; + char zBuf[50]; + + if( objc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), " DB STMT", 0); + return TCL_ERROR; + } + + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt) ) return TCL_ERROR; + pStmt = sqlite3_next_stmt(db, pStmt); + if( pStmt ){ + if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; + Tcl_AppendResult(interp, zBuf, 0); + } + return TCL_OK; +} + + +/* +** Usage: sqlite3_reset STMT +** +** Reset a statement handle. +*/ +static int test_reset( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int rc; + + if( objc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + + rc = sqlite3_reset(pStmt); + if( pStmt && sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ){ + return TCL_ERROR; + } + Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); +/* + if( rc ){ + return TCL_ERROR; + } +*/ + return TCL_OK; +} + +/* +** Usage: sqlite3_expired STMT +** +** Return TRUE if a recompilation of the statement is recommended. +*/ +static int test_expired( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + if( objc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0); + return TCL_ERROR; + } + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(sqlite3_expired(pStmt))); + return TCL_OK; +} + +/* +** Usage: sqlite3_transfer_bindings FROMSTMT TOSTMT +** +** Transfer all bindings from FROMSTMT over to TOSTMT +*/ +static int test_transfer_bind( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt1, *pStmt2; + if( objc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), " FROM-STMT TO-STMT", 0); + return TCL_ERROR; + } + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt1)) return TCL_ERROR; + if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt2)) return TCL_ERROR; + Tcl_SetObjResult(interp, + Tcl_NewIntObj(sqlite3_transfer_bindings(pStmt1,pStmt2))); + return TCL_OK; +} + +/* +** Usage: sqlite3_changes DB +** +** Return the number of changes made to the database by the last SQL +** execution. +*/ +static int test_changes( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3 *db; + if( objc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " DB", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db))); + return TCL_OK; +} + +/* +** This is the "static_bind_value" that variables are bound to when +** the FLAG option of sqlite3_bind is "static" +*/ +static char *sqlite_static_bind_value = 0; +static int sqlite_static_bind_nbyte = 0; + +/* +** Usage: sqlite3_bind VM IDX VALUE FLAGS +** +** Sets the value of the IDX-th occurance of "?" in the original SQL +** string. VALUE is the new value. If FLAGS=="null" then VALUE is +** ignored and the value is set to NULL. If FLAGS=="static" then +** the value is set to the value of a static variable named +** "sqlite_static_bind_value". If FLAGS=="normal" then a copy +** of the VALUE is made. If FLAGS=="blob10" then a VALUE is ignored +** an a 10-byte blob "abc\000xyz\000pq" is inserted. +*/ +static int test_bind( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + sqlite3_stmt *pStmt; + int rc; + int idx; + if( argc!=5 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " VM IDX VALUE (null|static|normal)\"", 0); + return TCL_ERROR; + } + if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR; + if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR; + if( strcmp(argv[4],"null")==0 ){ + rc = sqlite3_bind_null(pStmt, idx); + }else if( strcmp(argv[4],"static")==0 ){ + rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0); + }else if( strcmp(argv[4],"static-nbytes")==0 ){ + rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, + sqlite_static_bind_nbyte, 0); + }else if( strcmp(argv[4],"normal")==0 ){ + rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT); + }else if( strcmp(argv[4],"blob10")==0 ){ + rc = sqlite3_bind_text(pStmt, idx, "abc\000xyz\000pq", 10, SQLITE_STATIC); + }else{ + Tcl_AppendResult(interp, "4th argument should be " + "\"null\" or \"static\" or \"normal\"", 0); + return TCL_ERROR; + } + if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; + if( rc ){ + char zBuf[50]; + sprintf(zBuf, "(%d) ", rc); + Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0); + return TCL_ERROR; + } + return TCL_OK; +} + +#ifndef SQLITE_OMIT_UTF16 +/* +** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be> +** +** This function is used to test that SQLite selects the correct collation +** sequence callback when multiple versions (for different text encodings) +** are available. +** +** Calling this routine registers the collation sequence "test_collate" +** with database handle <db>. The second argument must be a list of three +** boolean values. If the first is true, then a version of test_collate is +** registered for UTF-8, if the second is true, a version is registered for +** UTF-16le, if the third is true, a UTF-16be version is available. +** Previous versions of test_collate are deleted. +** +** The collation sequence test_collate is implemented by calling the +** following TCL script: +** +** "test_collate <enc> <lhs> <rhs>" +** +** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8. +** The <enc> parameter is the encoding of the collation function that +** SQLite selected to call. The TCL test script implements the +** "test_collate" proc. +** +** Note that this will only work with one intepreter at a time, as the +** interp pointer to use when evaluating the TCL script is stored in +** pTestCollateInterp. +*/ +static Tcl_Interp* pTestCollateInterp; +static int test_collate_func( + void *pCtx, + int nA, const void *zA, + int nB, const void *zB +){ + Tcl_Interp *i = pTestCollateInterp; + int encin = (int)pCtx; + int res; + int n; + + sqlite3_value *pVal; + Tcl_Obj *pX; + + pX = Tcl_NewStringObj("test_collate", -1); + Tcl_IncrRefCount(pX); + + switch( encin ){ + case SQLITE_UTF8: + Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1)); + break; + case SQLITE_UTF16LE: + Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1)); + break; + case SQLITE_UTF16BE: + Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1)); + break; + default: + assert(0); + } + + pVal = sqlite3ValueNew(0); + sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC); + n = sqlite3_value_bytes(pVal); + Tcl_ListObjAppendElement(i,pX, + Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n)); + sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC); + n = sqlite3_value_bytes(pVal); + Tcl_ListObjAppendElement(i,pX, + Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n)); + sqlite3ValueFree(pVal); + + Tcl_EvalObjEx(i, pX, 0); + Tcl_DecrRefCount(pX); + Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res); + return res; +} +static int test_collate( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3 *db; + int val; + sqlite3_value *pVal; + int rc; + + if( objc!=5 ) goto bad_args; + pTestCollateInterp = interp; + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + + if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; + rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8, + (void *)SQLITE_UTF8, val?test_collate_func:0); + if( rc==SQLITE_OK ){ + const void *zUtf16; + if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR; + rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE, + (void *)SQLITE_UTF16LE, val?test_collate_func:0); + if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR; + +#if 0 + if( sqlite3_iMallocFail>0 ){ + sqlite3_iMallocFail++; + } +#endif + sqlite3_mutex_enter(db->mutex); + pVal = sqlite3ValueNew(db); + sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC); + zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE); + if( db->mallocFailed ){ + rc = SQLITE_NOMEM; + }else{ + rc = sqlite3_create_collation16(db, zUtf16, SQLITE_UTF16BE, + (void *)SQLITE_UTF16BE, val?test_collate_func:0); + } + sqlite3ValueFree(pVal); + sqlite3_mutex_leave(db->mutex); + } + if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; + + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0); + return TCL_ERROR; + } + return TCL_OK; + +bad_args: + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0); + return TCL_ERROR; +} + +/* +** When the collation needed callback is invoked, record the name of +** the requested collating function here. The recorded name is linked +** to a TCL variable and used to make sure that the requested collation +** name is correct. +*/ +static char zNeededCollation[200]; +static char *pzNeededCollation = zNeededCollation; + + +/* +** Called when a collating sequence is needed. Registered using +** sqlite3_collation_needed16(). +*/ +static void test_collate_needed_cb( + void *pCtx, + sqlite3 *db, + int eTextRep, + const void *pName +){ + int enc = ENC(db); + int i; + char *z; + for(z = (char*)pName, i=0; *z || z[1]; z++){ + if( *z ) zNeededCollation[i++] = *z; + } + zNeededCollation[i] = 0; + sqlite3_create_collation( + db, "test_collate", ENC(db), (void *)enc, test_collate_func); +} + +/* +** Usage: add_test_collate_needed DB +*/ +static int test_collate_needed( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3 *db; + int rc; + + if( objc!=2 ) goto bad_args; + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + rc = sqlite3_collation_needed16(db, 0, test_collate_needed_cb); + zNeededCollation[0] = 0; + if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; + return TCL_OK; + +bad_args: + Tcl_WrongNumArgs(interp, 1, objv, "DB"); + return TCL_ERROR; +} + +/* +** tclcmd: add_alignment_test_collations DB +** +** Add two new collating sequences to the database DB +** +** utf16_aligned +** utf16_unaligned +** +** Both collating sequences use the same sort order as BINARY. +** The only difference is that the utf16_aligned collating +** sequence is declared with the SQLITE_UTF16_ALIGNED flag. +** Both collating functions increment the unaligned utf16 counter +** whenever they see a string that begins on an odd byte boundary. +*/ +static int unaligned_string_counter = 0; +static int alignmentCollFunc( + void *NotUsed, + int nKey1, const void *pKey1, + int nKey2, const void *pKey2 +){ + int rc, n; + n = nKey1<nKey2 ? nKey1 : nKey2; + if( nKey1>0 && 1==(1&(int)pKey1) ) unaligned_string_counter++; + if( nKey2>0 && 1==(1&(int)pKey2) ) unaligned_string_counter++; + rc = memcmp(pKey1, pKey2, n); + if( rc==0 ){ + rc = nKey1 - nKey2; + } + return rc; +} +static int add_alignment_test_collations( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3 *db; + if( objc>=2 ){ + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + sqlite3_create_collation(db, "utf16_unaligned", + SQLITE_UTF16, + 0, alignmentCollFunc); + sqlite3_create_collation(db, "utf16_aligned", + SQLITE_UTF16 | SQLITE_UTF16_ALIGNED, + 0, alignmentCollFunc); + } + return SQLITE_OK; +} +#endif /* !defined(SQLITE_OMIT_UTF16) */ + +/* +** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be> +** +** This function is used to test that SQLite selects the correct user +** function callback when multiple versions (for different text encodings) +** are available. +** +** Calling this routine registers up to three versions of the user function +** "test_function" with database handle <db>. If the second argument is +** true, then a version of test_function is registered for UTF-8, if the +** third is true, a version is registered for UTF-16le, if the fourth is +** true, a UTF-16be version is available. Previous versions of +** test_function are deleted. +** +** The user function is implemented by calling the following TCL script: +** +** "test_function <enc> <arg>" +** +** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the +** single argument passed to the SQL function. The value returned by +** the TCL script is used as the return value of the SQL function. It +** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8 +** for a UTF-16LE test_function(), and UTF-16LE for an implementation that +** prefers UTF-16BE. +*/ +#ifndef SQLITE_OMIT_UTF16 +static void test_function_utf8( + sqlite3_context *pCtx, + int nArg, + sqlite3_value **argv +){ + Tcl_Interp *interp; + Tcl_Obj *pX; + sqlite3_value *pVal; + interp = (Tcl_Interp *)sqlite3_user_data(pCtx); + pX = Tcl_NewStringObj("test_function", -1); + Tcl_IncrRefCount(pX); + Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1)); + Tcl_ListObjAppendElement(interp, pX, + Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1)); + Tcl_EvalObjEx(interp, pX, 0); + Tcl_DecrRefCount(pX); + sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT); + pVal = sqlite3ValueNew(0); + sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), + SQLITE_UTF8, SQLITE_STATIC); + sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal), + -1, SQLITE_TRANSIENT); + sqlite3ValueFree(pVal); +} +static void test_function_utf16le( + sqlite3_context *pCtx, + int nArg, + sqlite3_value **argv +){ + Tcl_Interp *interp; + Tcl_Obj *pX; + sqlite3_value *pVal; + interp = (Tcl_Interp *)sqlite3_user_data(pCtx); + pX = Tcl_NewStringObj("test_function", -1); + Tcl_IncrRefCount(pX); + Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1)); + Tcl_ListObjAppendElement(interp, pX, + Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1)); + Tcl_EvalObjEx(interp, pX, 0); + Tcl_DecrRefCount(pX); + pVal = sqlite3ValueNew(0); + sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), + SQLITE_UTF8, SQLITE_STATIC); + sqlite3_result_text(pCtx,(char*)sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT); + sqlite3ValueFree(pVal); +} +static void test_function_utf16be( + sqlite3_context *pCtx, + int nArg, + sqlite3_value **argv +){ + Tcl_Interp *interp; + Tcl_Obj *pX; + sqlite3_value *pVal; + interp = (Tcl_Interp *)sqlite3_user_data(pCtx); + pX = Tcl_NewStringObj("test_function", -1); + Tcl_IncrRefCount(pX); + Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1)); + Tcl_ListObjAppendElement(interp, pX, + Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1)); + Tcl_EvalObjEx(interp, pX, 0); + Tcl_DecrRefCount(pX); + pVal = sqlite3ValueNew(0); + sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), + SQLITE_UTF8, SQLITE_STATIC); + sqlite3_result_text16(pCtx, sqlite3_value_text16le(pVal), + -1, SQLITE_TRANSIENT); + sqlite3_result_text16be(pCtx, sqlite3_value_text16le(pVal), + -1, SQLITE_TRANSIENT); + sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal), + -1, SQLITE_TRANSIENT); + sqlite3ValueFree(pVal); +} +#endif /* SQLITE_OMIT_UTF16 */ +static int test_function( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ +#ifndef SQLITE_OMIT_UTF16 + sqlite3 *db; + int val; + + if( objc!=5 ) goto bad_args; + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + + if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; + if( val ){ + sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8, + interp, test_function_utf8, 0, 0); + } + if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR; + if( val ){ + sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE, + interp, test_function_utf16le, 0, 0); + } + if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR; + if( val ){ + sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE, + interp, test_function_utf16be, 0, 0); + } + + return TCL_OK; +bad_args: + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0); +#endif /* SQLITE_OMIT_UTF16 */ + return TCL_ERROR; +} + +/* +** Usage: test_errstr <err code> +** +** Test that the english language string equivalents for sqlite error codes +** are sane. The parameter is an integer representing an sqlite error code. +** The result is a list of two elements, the string representation of the +** error code and the english language explanation. +*/ +static int test_errstr( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + char *zCode; + int i; + if( objc!=1 ){ + Tcl_WrongNumArgs(interp, 1, objv, "<error code>"); + } + + zCode = Tcl_GetString(objv[1]); + for(i=0; i<200; i++){ + if( 0==strcmp(t1ErrorName(i), zCode) ) break; + } + Tcl_SetResult(interp, (char *)sqlite3ErrStr(i), 0); + return TCL_OK; +} + +/* +** Usage: breakpoint +** +** This routine exists for one purpose - to provide a place to put a +** breakpoint with GDB that can be triggered using TCL code. The use +** for this is when a particular test fails on (say) the 1485th iteration. +** In the TCL test script, we can add code like this: +** +** if {$i==1485} breakpoint +** +** Then run testfixture in the debugger and wait for the breakpoint to +** fire. Then additional breakpoints can be set to trace down the bug. +*/ +static int test_breakpoint( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + return TCL_OK; /* Do nothing */ +} + +/* +** Usage: sqlite3_bind_zeroblob STMT IDX N +** +** Test the sqlite3_bind_zeroblob interface. STMT is a prepared statement. +** IDX is the index of a wildcard in the prepared statement. This command +** binds a N-byte zero-filled BLOB to the wildcard. +*/ +static int test_bind_zeroblob( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int idx; + int n; + int rc; + + if( objc!=4 ){ + Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX N"); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[3], &n) ) return TCL_ERROR; + + rc = sqlite3_bind_zeroblob(pStmt, idx, n); + if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; + if( rc!=SQLITE_OK ){ + return TCL_ERROR; + } + + return TCL_OK; +} + +/* +** Usage: sqlite3_bind_int STMT N VALUE +** +** Test the sqlite3_bind_int interface. STMT is a prepared statement. +** N is the index of a wildcard in the prepared statement. This command +** binds a 32-bit integer VALUE to that wildcard. +*/ +static int test_bind_int( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int idx; + int value; + int rc; + + if( objc!=4 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR; + + rc = sqlite3_bind_int(pStmt, idx, value); + if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; + if( rc!=SQLITE_OK ){ + return TCL_ERROR; + } + + return TCL_OK; +} + + +/* +** Usage: sqlite3_bind_int64 STMT N VALUE +** +** Test the sqlite3_bind_int64 interface. STMT is a prepared statement. +** N is the index of a wildcard in the prepared statement. This command +** binds a 64-bit integer VALUE to that wildcard. +*/ +static int test_bind_int64( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int idx; + i64 value; + int rc; + + if( objc!=4 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; + if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR; + + rc = sqlite3_bind_int64(pStmt, idx, value); + if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; + if( rc!=SQLITE_OK ){ + return TCL_ERROR; + } + + return TCL_OK; +} + + +/* +** Usage: sqlite3_bind_double STMT N VALUE +** +** Test the sqlite3_bind_double interface. STMT is a prepared statement. +** N is the index of a wildcard in the prepared statement. This command +** binds a 64-bit integer VALUE to that wildcard. +*/ +static int test_bind_double( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int idx; + double value; + int rc; + const char *zVal; + int i; + static const struct { + const char *zName; /* Name of the special floating point value */ + unsigned int iUpper; /* Upper 32 bits */ + unsigned int iLower; /* Lower 32 bits */ + } aSpecialFp[] = { + { "NaN", 0x7fffffff, 0xffffffff }, + { "SNaN", 0x7ff7ffff, 0xffffffff }, + { "-NaN", 0xffffffff, 0xffffffff }, + { "-SNaN", 0xfff7ffff, 0xffffffff }, + { "+Inf", 0x7ff00000, 0x00000000 }, + { "-Inf", 0xfff00000, 0x00000000 }, + { "Epsilon", 0x00000000, 0x00000001 }, + { "-Epsilon", 0x80000000, 0x00000001 }, + { "NaN0", 0x7ff80000, 0x00000000 }, + { "-NaN0", 0xfff80000, 0x00000000 }, + }; + + if( objc!=4 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; + + /* Intercept the string "NaN" and generate a NaN value for it. + ** All other strings are passed through to Tcl_GetDoubleFromObj(). + ** Tcl_GetDoubleFromObj() should understand "NaN" but some versions + ** contain a bug. + */ + zVal = Tcl_GetString(objv[3]); + for(i=0; i<sizeof(aSpecialFp)/sizeof(aSpecialFp[0]); i++){ + if( strcmp(aSpecialFp[i].zName, zVal)==0 ){ + sqlite3_uint64 x; + x = aSpecialFp[i].iUpper; + x <<= 32; + x |= aSpecialFp[i].iLower; + assert( sizeof(value)==8 ); + assert( sizeof(x)==8 ); + memcpy(&value, &x, 8); + break; + } + } + if( i>=sizeof(aSpecialFp)/sizeof(aSpecialFp[0]) && + Tcl_GetDoubleFromObj(interp, objv[3], &value) ){ + return TCL_ERROR; + } + rc = sqlite3_bind_double(pStmt, idx, value); + if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; + if( rc!=SQLITE_OK ){ + return TCL_ERROR; + } + + return TCL_OK; +} + +/* +** Usage: sqlite3_bind_null STMT N +** +** Test the sqlite3_bind_null interface. STMT is a prepared statement. +** N is the index of a wildcard in the prepared statement. This command +** binds a NULL to the wildcard. +*/ +static int test_bind_null( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int idx; + int rc; + + if( objc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), " STMT N", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; + + rc = sqlite3_bind_null(pStmt, idx); + if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; + if( rc!=SQLITE_OK ){ + return TCL_ERROR; + } + + return TCL_OK; +} + +/* +** Usage: sqlite3_bind_text STMT N STRING BYTES +** +** Test the sqlite3_bind_text interface. STMT is a prepared statement. +** N is the index of a wildcard in the prepared statement. This command +** binds a UTF-8 string STRING to the wildcard. The string is BYTES bytes +** long. +*/ +static int test_bind_text( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int idx; + int bytes; + char *value; + int rc; + + if( objc!=5 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; + value = (char*)Tcl_GetByteArrayFromObj(objv[3], &bytes); + if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; + + rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT); + if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0); + return TCL_ERROR; + } + + return TCL_OK; +} + +/* +** Usage: sqlite3_bind_text16 ?-static? STMT N STRING BYTES +** +** Test the sqlite3_bind_text16 interface. STMT is a prepared statement. +** N is the index of a wildcard in the prepared statement. This command +** binds a UTF-16 string STRING to the wildcard. The string is BYTES bytes +** long. +*/ +static int test_bind_text16( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ +#ifndef SQLITE_OMIT_UTF16 + sqlite3_stmt *pStmt; + int idx; + int bytes; + char *value; + int rc; + + void (*xDel)() = (objc==6?SQLITE_STATIC:SQLITE_TRANSIENT); + Tcl_Obj *oStmt = objv[objc-4]; + Tcl_Obj *oN = objv[objc-3]; + Tcl_Obj *oString = objv[objc-2]; + Tcl_Obj *oBytes = objv[objc-1]; + + if( objc!=5 && objc!=6){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(oStmt), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, oN, &idx) ) return TCL_ERROR; + value = (char*)Tcl_GetByteArrayFromObj(oString, 0); + if( Tcl_GetIntFromObj(interp, oBytes, &bytes) ) return TCL_ERROR; + + rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, xDel); + if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0); + return TCL_ERROR; + } + +#endif /* SQLITE_OMIT_UTF16 */ + return TCL_OK; +} + +/* +** Usage: sqlite3_bind_blob ?-static? STMT N DATA BYTES +** +** Test the sqlite3_bind_blob interface. STMT is a prepared statement. +** N is the index of a wildcard in the prepared statement. This command +** binds a BLOB to the wildcard. The BLOB is BYTES bytes in size. +*/ +static int test_bind_blob( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int idx; + int bytes; + char *value; + int rc; + sqlite3_destructor_type xDestructor = SQLITE_TRANSIENT; + + if( objc!=5 && objc!=6 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), " STMT N DATA BYTES", 0); + return TCL_ERROR; + } + + if( objc==6 ){ + xDestructor = SQLITE_STATIC; + objv++; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; + value = Tcl_GetString(objv[3]); + if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; + + rc = sqlite3_bind_blob(pStmt, idx, value, bytes, xDestructor); + if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR; + if( rc!=SQLITE_OK ){ + return TCL_ERROR; + } + + return TCL_OK; +} + +/* +** Usage: sqlite3_bind_parameter_count STMT +** +** Return the number of wildcards in the given statement. +*/ +static int test_bind_parameter_count( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "STMT"); + return TCL_ERROR; + } + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt))); + return TCL_OK; +} + +/* +** Usage: sqlite3_bind_parameter_name STMT N +** +** Return the name of the Nth wildcard. The first wildcard is 1. +** An empty string is returned if N is out of range or if the wildcard +** is nameless. +*/ +static int test_bind_parameter_name( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int i; + + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "STMT N"); + return TCL_ERROR; + } + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &i) ) return TCL_ERROR; + Tcl_SetObjResult(interp, + Tcl_NewStringObj(sqlite3_bind_parameter_name(pStmt,i),-1) + ); + return TCL_OK; +} + +/* +** Usage: sqlite3_bind_parameter_index STMT NAME +** +** Return the index of the wildcard called NAME. Return 0 if there is +** no such wildcard. +*/ +static int test_bind_parameter_index( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "STMT NAME"); + return TCL_ERROR; + } + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + Tcl_SetObjResult(interp, + Tcl_NewIntObj( + sqlite3_bind_parameter_index(pStmt,Tcl_GetString(objv[2])) + ) + ); + return TCL_OK; +} + +/* +** Usage: sqlite3_clear_bindings STMT +** +*/ +static int test_clear_bindings( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "STMT"); + return TCL_ERROR; + } + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt))); + return TCL_OK; +} + +/* +** Usage: sqlite3_sleep MILLISECONDS +*/ +static int test_sleep( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int ms; + + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "MILLISECONDS"); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, objv[1], &ms) ){ + return TCL_ERROR; + } + Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_sleep(ms))); + return TCL_OK; +} + +/* +** Usage: sqlite3_errcode DB +** +** Return the string representation of the most recent sqlite3_* API +** error code. e.g. "SQLITE_ERROR". +*/ +static int test_errcode( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3 *db; + int rc; + char zBuf[30]; + + if( objc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " DB", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + rc = sqlite3_errcode(db); + if( (rc&0xff)==rc ){ + zBuf[0] = 0; + }else{ + sprintf(zBuf,"+%d", rc>>8); + } + Tcl_AppendResult(interp, (char *)t1ErrorName(rc), zBuf, 0); + return TCL_OK; +} + +/* +** Usage: test_errmsg DB +** +** Returns the UTF-8 representation of the error message string for the +** most recent sqlite3_* API call. +*/ +static int test_errmsg( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3 *db; + const char *zErr; + + if( objc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " DB", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + + zErr = sqlite3_errmsg(db); + Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1)); + return TCL_OK; +} + +/* +** Usage: test_errmsg16 DB +** +** Returns the UTF-16 representation of the error message string for the +** most recent sqlite3_* API call. This is a byte array object at the TCL +** level, and it includes the 0x00 0x00 terminator bytes at the end of the +** UTF-16 string. +*/ +static int test_errmsg16( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ +#ifndef SQLITE_OMIT_UTF16 + sqlite3 *db; + const void *zErr; + int bytes = 0; + + if( objc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " DB", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + + zErr = sqlite3_errmsg16(db); + if( zErr ){ + bytes = sqlite3Utf16ByteLen(zErr, -1); + } + Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes)); +#endif /* SQLITE_OMIT_UTF16 */ + return TCL_OK; +} + +/* +** Usage: sqlite3_prepare DB sql bytes tailvar +** +** Compile up to <bytes> bytes of the supplied SQL string <sql> using +** database handle <DB>. The parameter <tailval> is the name of a global +** variable that is set to the unused portion of <sql> (if any). A +** STMT handle is returned. +*/ +static int test_prepare( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3 *db; + const char *zSql; + int bytes; + const char *zTail = 0; + sqlite3_stmt *pStmt = 0; + char zBuf[50]; + int rc; + + if( objc!=5 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + zSql = Tcl_GetString(objv[2]); + if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; + + rc = sqlite3_prepare(db, zSql, bytes, &pStmt, &zTail); + if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; + if( zTail ){ + if( bytes>=0 ){ + bytes = bytes - (zTail-zSql); + } + if( strlen(zTail)<bytes ){ + bytes = strlen(zTail); + } + Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0); + } + if( rc!=SQLITE_OK ){ + assert( pStmt==0 ); + sprintf(zBuf, "(%d) ", rc); + Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); + return TCL_ERROR; + } + + if( pStmt ){ + if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; + Tcl_AppendResult(interp, zBuf, 0); + } + return TCL_OK; +} + +/* +** Usage: sqlite3_prepare_v2 DB sql bytes tailvar +** +** Compile up to <bytes> bytes of the supplied SQL string <sql> using +** database handle <DB>. The parameter <tailval> is the name of a global +** variable that is set to the unused portion of <sql> (if any). A +** STMT handle is returned. +*/ +static int test_prepare_v2( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3 *db; + const char *zSql; + int bytes; + const char *zTail = 0; + sqlite3_stmt *pStmt = 0; + char zBuf[50]; + int rc; + + if( objc!=5 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + zSql = Tcl_GetString(objv[2]); + if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; + + rc = sqlite3_prepare_v2(db, zSql, bytes, &pStmt, &zTail); + assert(rc==SQLITE_OK || pStmt==0); + if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; + if( zTail ){ + if( bytes>=0 ){ + bytes = bytes - (zTail-zSql); + } + Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0); + } + if( rc!=SQLITE_OK ){ + assert( pStmt==0 ); + sprintf(zBuf, "(%d) ", rc); + Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); + return TCL_ERROR; + } + + if( pStmt ){ + if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; + Tcl_AppendResult(interp, zBuf, 0); + } + return TCL_OK; +} + +/* +** Usage: sqlite3_prepare_tkt3134 DB +** +** Generate a prepared statement for a zero-byte string as a test +** for ticket #3134. The string should be preceeded by a zero byte. +*/ +static int test_prepare_tkt3134( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3 *db; + static const char zSql[] = "\000SELECT 1"; + sqlite3_stmt *pStmt = 0; + char zBuf[50]; + int rc; + + if( objc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + rc = sqlite3_prepare_v2(db, &zSql[1], 0, &pStmt, 0); + assert(rc==SQLITE_OK || pStmt==0); + if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; + if( rc!=SQLITE_OK ){ + assert( pStmt==0 ); + sprintf(zBuf, "(%d) ", rc); + Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); + return TCL_ERROR; + } + + if( pStmt ){ + if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; + Tcl_AppendResult(interp, zBuf, 0); + } + return TCL_OK; +} + +/* +** Usage: sqlite3_prepare16 DB sql bytes tailvar +** +** Compile up to <bytes> bytes of the supplied SQL string <sql> using +** database handle <DB>. The parameter <tailval> is the name of a global +** variable that is set to the unused portion of <sql> (if any). A +** STMT handle is returned. +*/ +static int test_prepare16( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ +#ifndef SQLITE_OMIT_UTF16 + sqlite3 *db; + const void *zSql; + const void *zTail = 0; + Tcl_Obj *pTail = 0; + sqlite3_stmt *pStmt = 0; + char zBuf[50]; + int rc; + int bytes; /* The integer specified as arg 3 */ + int objlen; /* The byte-array length of arg 2 */ + + if( objc!=5 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen); + if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; + + rc = sqlite3_prepare16(db, zSql, bytes, &pStmt, &zTail); + if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; + if( rc ){ + return TCL_ERROR; + } + + if( zTail ){ + objlen = objlen - ((u8 *)zTail-(u8 *)zSql); + }else{ + objlen = 0; + } + pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen); + Tcl_IncrRefCount(pTail); + Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0); + Tcl_DecrRefCount(pTail); + + if( pStmt ){ + if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; + } + Tcl_AppendResult(interp, zBuf, 0); +#endif /* SQLITE_OMIT_UTF16 */ + return TCL_OK; +} + +/* +** Usage: sqlite3_prepare16_v2 DB sql bytes tailvar +** +** Compile up to <bytes> bytes of the supplied SQL string <sql> using +** database handle <DB>. The parameter <tailval> is the name of a global +** variable that is set to the unused portion of <sql> (if any). A +** STMT handle is returned. +*/ +static int test_prepare16_v2( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ +#ifndef SQLITE_OMIT_UTF16 + sqlite3 *db; + const void *zSql; + const void *zTail = 0; + Tcl_Obj *pTail = 0; + sqlite3_stmt *pStmt = 0; + char zBuf[50]; + int rc; + int bytes; /* The integer specified as arg 3 */ + int objlen; /* The byte-array length of arg 2 */ + + if( objc!=5 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen); + if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; + + rc = sqlite3_prepare16_v2(db, zSql, bytes, &pStmt, &zTail); + if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; + if( rc ){ + return TCL_ERROR; + } + + if( zTail ){ + objlen = objlen - ((u8 *)zTail-(u8 *)zSql); + }else{ + objlen = 0; + } + pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen); + Tcl_IncrRefCount(pTail); + Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0); + Tcl_DecrRefCount(pTail); + + if( pStmt ){ + if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; + } + Tcl_AppendResult(interp, zBuf, 0); +#endif /* SQLITE_OMIT_UTF16 */ + return TCL_OK; +} + +/* +** Usage: sqlite3_open filename ?options-list? +*/ +static int test_open( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + const char *zFilename; + sqlite3 *db; + int rc; + char zBuf[100]; + + if( objc!=3 && objc!=2 && objc!=1 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " filename options-list", 0); + return TCL_ERROR; + } + + zFilename = objc>1 ? Tcl_GetString(objv[1]) : 0; + rc = sqlite3_open(zFilename, &db); + + if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR; + Tcl_AppendResult(interp, zBuf, 0); + return TCL_OK; +} + +/* +** Usage: sqlite3_open16 filename options +*/ +static int test_open16( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ +#ifndef SQLITE_OMIT_UTF16 + const void *zFilename; + sqlite3 *db; + int rc; + char zBuf[100]; + + if( objc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " filename options-list", 0); + return TCL_ERROR; + } + + zFilename = Tcl_GetByteArrayFromObj(objv[1], 0); + rc = sqlite3_open16(zFilename, &db); + + if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR; + Tcl_AppendResult(interp, zBuf, 0); +#endif /* SQLITE_OMIT_UTF16 */ + return TCL_OK; +} + +/* +** Usage: sqlite3_complete16 <UTF-16 string> +** +** Return 1 if the supplied argument is a complete SQL statement, or zero +** otherwise. +*/ +static int test_complete16( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ +#if !defined(SQLITE_OMIT_COMPLETE) && !defined(SQLITE_OMIT_UTF16) + char *zBuf; + + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "<utf-16 sql>"); + return TCL_ERROR; + } + + zBuf = (char*)Tcl_GetByteArrayFromObj(objv[1], 0); + Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_complete16(zBuf))); +#endif /* SQLITE_OMIT_COMPLETE && SQLITE_OMIT_UTF16 */ + return TCL_OK; +} + +/* +** Usage: sqlite3_step STMT +** +** Advance the statement to the next row. +*/ +static int test_step( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int rc; + + if( objc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " STMT", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + rc = sqlite3_step(pStmt); + + /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */ + Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0); + return TCL_OK; +} + +/* +** Usage: sqlite3_column_count STMT +** +** Return the number of columns returned by the sql statement STMT. +*/ +static int test_column_count( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + + if( objc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " STMT column", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + + Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt))); + return TCL_OK; +} + +/* +** Usage: sqlite3_column_type STMT column +** +** Return the type of the data in column 'column' of the current row. +*/ +static int test_column_type( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int col; + int tp; + + if( objc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " STMT column", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; + + tp = sqlite3_column_type(pStmt, col); + switch( tp ){ + case SQLITE_INTEGER: + Tcl_SetResult(interp, "INTEGER", TCL_STATIC); + break; + case SQLITE_NULL: + Tcl_SetResult(interp, "NULL", TCL_STATIC); + break; + case SQLITE_FLOAT: + Tcl_SetResult(interp, "FLOAT", TCL_STATIC); + break; + case SQLITE_TEXT: + Tcl_SetResult(interp, "TEXT", TCL_STATIC); + break; + case SQLITE_BLOB: + Tcl_SetResult(interp, "BLOB", TCL_STATIC); + break; + default: + assert(0); + } + + return TCL_OK; +} + +/* +** Usage: sqlite3_column_int64 STMT column +** +** Return the data in column 'column' of the current row cast as an +** wide (64-bit) integer. +*/ +static int test_column_int64( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int col; + i64 iVal; + + if( objc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " STMT column", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; + + iVal = sqlite3_column_int64(pStmt, col); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal)); + return TCL_OK; +} + +/* +** Usage: sqlite3_column_blob STMT column +*/ +static int test_column_blob( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int col; + + int len; + const void *pBlob; + + if( objc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " STMT column", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; + + len = sqlite3_column_bytes(pStmt, col); + pBlob = sqlite3_column_blob(pStmt, col); + Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len)); + return TCL_OK; +} + +/* +** Usage: sqlite3_column_double STMT column +** +** Return the data in column 'column' of the current row cast as a double. +*/ +static int test_column_double( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int col; + double rVal; + + if( objc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " STMT column", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; + + rVal = sqlite3_column_double(pStmt, col); + Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal)); + return TCL_OK; +} + +/* +** Usage: sqlite3_data_count STMT +** +** Return the number of columns returned by the sql statement STMT. +*/ +static int test_data_count( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + + if( objc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " STMT column", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + + Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt))); + return TCL_OK; +} + +/* +** Usage: sqlite3_column_text STMT column +** +** Usage: sqlite3_column_decltype STMT column +** +** Usage: sqlite3_column_name STMT column +*/ +static int test_stmt_utf8( + void * clientData, /* Pointer to SQLite API function to be invoke */ + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int col; + const char *(*xFunc)(sqlite3_stmt*, int) = clientData; + const char *zRet; + + if( objc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " STMT column", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; + zRet = xFunc(pStmt, col); + if( zRet ){ + Tcl_SetResult(interp, (char *)zRet, 0); + } + return TCL_OK; +} + +static int test_global_recover( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ +#ifndef SQLITE_OMIT_GLOBALRECOVER + int rc; + if( objc!=1 ){ + Tcl_WrongNumArgs(interp, 1, objv, ""); + return TCL_ERROR; + } + rc = sqlite3_global_recover(); + Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); +#endif + return TCL_OK; +} + +/* +** Usage: sqlite3_column_text STMT column +** +** Usage: sqlite3_column_decltype STMT column +** +** Usage: sqlite3_column_name STMT column +*/ +static int test_stmt_utf16( + void * clientData, /* Pointer to SQLite API function to be invoked */ + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ +#ifndef SQLITE_OMIT_UTF16 + sqlite3_stmt *pStmt; + int col; + Tcl_Obj *pRet; + const void *zName16; + const void *(*xFunc)(sqlite3_stmt*, int) = clientData; + + if( objc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " STMT column", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; + + zName16 = xFunc(pStmt, col); + if( zName16 ){ + pRet = Tcl_NewByteArrayObj(zName16, sqlite3Utf16ByteLen(zName16, -1)+2); + Tcl_SetObjResult(interp, pRet); + } +#endif /* SQLITE_OMIT_UTF16 */ + + return TCL_OK; +} + +/* +** Usage: sqlite3_column_int STMT column +** +** Usage: sqlite3_column_bytes STMT column +** +** Usage: sqlite3_column_bytes16 STMT column +** +*/ +static int test_stmt_int( + void * clientData, /* Pointer to SQLite API function to be invoked */ + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int col; + int (*xFunc)(sqlite3_stmt*, int) = clientData; + + if( objc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " STMT column", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; + + Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col))); + return TCL_OK; +} + +/* +** Usage: sqlite_set_magic DB MAGIC-NUMBER +** +** Set the db->magic value. This is used to test error recovery logic. +*/ +static int sqlite_set_magic( + void * clientData, + Tcl_Interp *interp, + int argc, + char **argv +){ + sqlite3 *db; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " DB MAGIC", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; + if( strcmp(argv[2], "SQLITE_MAGIC_OPEN")==0 ){ + db->magic = SQLITE_MAGIC_OPEN; + }else if( strcmp(argv[2], "SQLITE_MAGIC_CLOSED")==0 ){ + db->magic = SQLITE_MAGIC_CLOSED; + }else if( strcmp(argv[2], "SQLITE_MAGIC_BUSY")==0 ){ + db->magic = SQLITE_MAGIC_BUSY; + }else if( strcmp(argv[2], "SQLITE_MAGIC_ERROR")==0 ){ + db->magic = SQLITE_MAGIC_ERROR; + }else if( Tcl_GetInt(interp, argv[2], &db->magic) ){ + return TCL_ERROR; + } + return TCL_OK; +} + +/* +** Usage: sqlite3_interrupt DB +** +** Trigger an interrupt on DB +*/ +static int test_interrupt( + void * clientData, + Tcl_Interp *interp, + int argc, + char **argv +){ + sqlite3 *db; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; + sqlite3_interrupt(db); + return TCL_OK; +} + +static u8 *sqlite3_stack_baseline = 0; + +/* +** Fill the stack with a known bitpattern. +*/ +static void prepStack(void){ + int i; + u32 bigBuf[65536]; + for(i=0; i<sizeof(bigBuf); i++) bigBuf[i] = 0xdeadbeef; + sqlite3_stack_baseline = (u8*)&bigBuf[65536]; +} + +/* +** Get the current stack depth. Used for debugging only. +*/ +u64 sqlite3StackDepth(void){ + u8 x; + return (u64)(sqlite3_stack_baseline - &x); +} + +/* +** Usage: sqlite3_stack_used DB SQL +** +** Try to measure the amount of stack space used by a call to sqlite3_exec +*/ +static int test_stack_used( + void * clientData, + Tcl_Interp *interp, + int argc, + char **argv +){ + sqlite3 *db; + int i; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " DB SQL", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; + prepStack(); + (void)sqlite3_exec(db, argv[2], 0, 0, 0); + for(i=65535; i>=0 && ((u32*)sqlite3_stack_baseline)[-i]==0xdeadbeef; i--){} + Tcl_SetObjResult(interp, Tcl_NewIntObj(i*4)); + return TCL_OK; +} + +/* +** Usage: sqlite_delete_function DB function-name +** +** Delete the user function 'function-name' from database handle DB. It +** is assumed that the user function was created as UTF8, any number of +** arguments (the way the TCL interface does it). +*/ +static int delete_function( + void * clientData, + Tcl_Interp *interp, + int argc, + char **argv +){ + int rc; + sqlite3 *db; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " DB function-name", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; + rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 0, 0, 0); + Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); + return TCL_OK; +} + +/* +** Usage: sqlite_delete_collation DB collation-name +** +** Delete the collation sequence 'collation-name' from database handle +** DB. It is assumed that the collation sequence was created as UTF8 (the +** way the TCL interface does it). +*/ +static int delete_collation( + void * clientData, + Tcl_Interp *interp, + int argc, + char **argv +){ + int rc; + sqlite3 *db; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " DB function-name", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; + rc = sqlite3_create_collation(db, argv[2], SQLITE_UTF8, 0, 0); + Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); + return TCL_OK; +} + +/* +** Usage: sqlite3_get_autocommit DB +** +** Return true if the database DB is currently in auto-commit mode. +** Return false if not. +*/ +static int get_autocommit( + void * clientData, + Tcl_Interp *interp, + int argc, + char **argv +){ + char zBuf[30]; + sqlite3 *db; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " DB", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; + sprintf(zBuf, "%d", sqlite3_get_autocommit(db)); + Tcl_AppendResult(interp, zBuf, 0); + return TCL_OK; +} + +/* +** Usage: sqlite3_busy_timeout DB MS +** +** Set the busy timeout. This is more easily done using the timeout +** method of the TCL interface. But we need a way to test the case +** where it returns SQLITE_MISUSE. +*/ +static int test_busy_timeout( + void * clientData, + Tcl_Interp *interp, + int argc, + char **argv +){ + int rc, ms; + sqlite3 *db; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " DB", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; + if( Tcl_GetInt(interp, argv[2], &ms) ) return TCL_ERROR; + rc = sqlite3_busy_timeout(db, ms); + Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0); + return TCL_OK; +} + +/* +** Usage: tcl_variable_type VARIABLENAME +** +** Return the name of the internal representation for the +** value of the given variable. +*/ +static int tcl_variable_type( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + Tcl_Obj *pVar; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "VARIABLE"); + return TCL_ERROR; + } + pVar = Tcl_GetVar2Ex(interp, Tcl_GetString(objv[1]), 0, TCL_LEAVE_ERR_MSG); + if( pVar==0 ) return TCL_ERROR; + if( pVar->typePtr ){ + Tcl_SetObjResult(interp, Tcl_NewStringObj(pVar->typePtr->name, -1)); + } + return TCL_OK; +} + +/* +** Usage: sqlite3_release_memory ?N? +** +** Attempt to release memory currently held but not actually required. +** The integer N is the number of bytes we are trying to release. The +** return value is the amount of memory actually released. +*/ +static int test_release_memory( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ +#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO) + int N; + int amt; + if( objc!=1 && objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "?N?"); + return TCL_ERROR; + } + if( objc==2 ){ + if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR; + }else{ + N = -1; + } + amt = sqlite3_release_memory(N); + Tcl_SetObjResult(interp, Tcl_NewIntObj(amt)); +#endif + return TCL_OK; +} + +/* +** Usage: sqlite3_soft_heap_limit ?N? +** +** Query or set the soft heap limit for the current thread. The +** limit is only changed if the N is present. The previous limit +** is returned. +*/ +static int test_soft_heap_limit( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + static int softHeapLimit = 0; + int amt; + if( objc!=1 && objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "?N?"); + return TCL_ERROR; + } + amt = softHeapLimit; + if( objc==2 ){ + int N; + if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR; + sqlite3_soft_heap_limit(N); + softHeapLimit = N; + } + Tcl_SetObjResult(interp, Tcl_NewIntObj(amt)); + return TCL_OK; +} + +/* +** Usage: sqlite3_thread_cleanup +** +** Call the sqlite3_thread_cleanup API. +*/ +static int test_thread_cleanup( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_thread_cleanup(); + return TCL_OK; +} + + +/* +** Usage: sqlite3_pager_refcounts DB +** +** Return a list of numbers which are the PagerRefcount for all +** pagers on each database connection. +*/ +static int test_pager_refcounts( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3 *db; + int i; + int v, *a; + Tcl_Obj *pResult; + + if( objc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), " DB", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + pResult = Tcl_NewObj(); + for(i=0; i<db->nDb; i++){ + if( db->aDb[i].pBt==0 ){ + v = -1; + }else{ + sqlite3_mutex_enter(db->mutex); + a = sqlite3PagerStats(sqlite3BtreePager(db->aDb[i].pBt)); + v = a[0]; + sqlite3_mutex_leave(db->mutex); + } + Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(v)); + } + Tcl_SetObjResult(interp, pResult); + return TCL_OK; +} + + +/* +** tclcmd: working_64bit_int +** +** Some TCL builds (ex: cygwin) do not support 64-bit integers. This +** leads to a number of test failures. The present command checks the +** TCL build to see whether or not it supports 64-bit integers. It +** returns TRUE if it does and FALSE if not. +** +** This command is used to warn users that their TCL build is defective +** and that the errors they are seeing in the test scripts might be +** a result of their defective TCL rather than problems in SQLite. +*/ +static int working_64bit_int( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + Tcl_Obj *pTestObj; + int working = 0; + + pTestObj = Tcl_NewWideIntObj(1000000*(i64)1234567890); + working = strcmp(Tcl_GetString(pTestObj), "1234567890000000")==0; + Tcl_DecrRefCount(pTestObj); + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(working)); + return TCL_OK; +} + + +/* +** tclcmd: vfs_unlink_test +** +** This TCL command unregisters the primary VFS and then registers +** it back again. This is used to test the ability to register a +** VFS when none are previously registered, and the ability to +** unregister the only available VFS. Ticket #2738 +*/ +static int vfs_unlink_test( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + int i; + sqlite3_vfs *pMain; + sqlite3_vfs *apVfs[20]; + sqlite3_vfs one, two; + + sqlite3_vfs_unregister(0); /* Unregister of NULL is harmless */ + one.zName = "__one"; + two.zName = "__two"; + + /* Calling sqlite3_vfs_register with 2nd argument of 0 does not + ** change the default VFS + */ + pMain = sqlite3_vfs_find(0); + sqlite3_vfs_register(&one, 0); + assert( pMain==0 || pMain==sqlite3_vfs_find(0) ); + sqlite3_vfs_register(&two, 0); + assert( pMain==0 || pMain==sqlite3_vfs_find(0) ); + + /* We can find a VFS by its name */ + assert( sqlite3_vfs_find("__one")==&one ); + assert( sqlite3_vfs_find("__two")==&two ); + + /* Calling sqlite_vfs_register with non-zero second parameter changes the + ** default VFS, even if the 1st parameter is an existig VFS that is + ** previously registered as the non-default. + */ + sqlite3_vfs_register(&one, 1); + assert( sqlite3_vfs_find("__one")==&one ); + assert( sqlite3_vfs_find("__two")==&two ); + assert( sqlite3_vfs_find(0)==&one ); + sqlite3_vfs_register(&two, 1); + assert( sqlite3_vfs_find("__one")==&one ); + assert( sqlite3_vfs_find("__two")==&two ); + assert( sqlite3_vfs_find(0)==&two ); + if( pMain ){ + sqlite3_vfs_register(pMain, 1); + assert( sqlite3_vfs_find("__one")==&one ); + assert( sqlite3_vfs_find("__two")==&two ); + assert( sqlite3_vfs_find(0)==pMain ); + } + + /* Unlink the default VFS. Repeat until there are no more VFSes + ** registered. + */ + for(i=0; i<sizeof(apVfs)/sizeof(apVfs[0]); i++){ + apVfs[i] = sqlite3_vfs_find(0); + if( apVfs[i] ){ + assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) ); + sqlite3_vfs_unregister(apVfs[i]); + assert( 0==sqlite3_vfs_find(apVfs[i]->zName) ); + } + } + assert( 0==sqlite3_vfs_find(0) ); + + /* Register the main VFS as non-default (will be made default, since + ** it'll be the only one in existence). + */ + sqlite3_vfs_register(pMain, 0); + assert( sqlite3_vfs_find(0)==pMain ); + + /* Un-register the main VFS again to restore an empty VFS list */ + sqlite3_vfs_unregister(pMain); + assert( 0==sqlite3_vfs_find(0) ); + + /* Relink all VFSes in reverse order. */ + for(i=sizeof(apVfs)/sizeof(apVfs[0])-1; i>=0; i--){ + if( apVfs[i] ){ + sqlite3_vfs_register(apVfs[i], 1); + assert( apVfs[i]==sqlite3_vfs_find(0) ); + assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) ); + } + } + + /* Unregister out sample VFSes. */ + sqlite3_vfs_unregister(&one); + sqlite3_vfs_unregister(&two); + + /* Unregistering a VFS that is not currently registered is harmless */ + sqlite3_vfs_unregister(&one); + sqlite3_vfs_unregister(&two); + assert( sqlite3_vfs_find("__one")==0 ); + assert( sqlite3_vfs_find("__two")==0 ); + + /* We should be left with the original default VFS back as the + ** original */ + assert( sqlite3_vfs_find(0)==pMain ); + + return TCL_OK; +} + +/* +** tclcmd: vfs_initfail_test +** +** This TCL command attempts to vfs_find and vfs_register when the +** sqlite3_initialize() interface is failing. All calls should fail. +*/ +static int vfs_initfail_test( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + sqlite3_vfs one; + one.zName = "__one"; + + if( sqlite3_vfs_find(0) ) return TCL_ERROR; + sqlite3_vfs_register(&one, 0); + if( sqlite3_vfs_find(0) ) return TCL_ERROR; + sqlite3_vfs_register(&one, 1); + if( sqlite3_vfs_find(0) ) return TCL_ERROR; + return TCL_OK; +} + +/* +** Saved VFSes +*/ +static sqlite3_vfs *apVfs[20]; +static int nVfs = 0; + +/* +** tclcmd: vfs_unregister_all +** +** Unregister all VFSes. +*/ +static int vfs_unregister_all( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + int i; + for(i=0; i<ArraySize(apVfs); i++){ + apVfs[i] = sqlite3_vfs_find(0); + if( apVfs[i]==0 ) break; + sqlite3_vfs_unregister(apVfs[i]); + } + nVfs = i; + return TCL_OK; +} +/* +** tclcmd: vfs_reregister_all +** +** Restore all VFSes that were removed using vfs_unregister_all +*/ +static int vfs_reregister_all( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + int i; + for(i=0; i<nVfs; i++){ + sqlite3_vfs_register(apVfs[i], i==0); + } + return TCL_OK; +} + + +/* +** tclcmd: file_control_test DB +** +** This TCL command runs the sqlite3_file_control interface and +** verifies correct operation of the same. +*/ +static int file_control_test( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + int iArg = 0; + sqlite3 *db; + int rc; + + if( objc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), " DB", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + rc = sqlite3_file_control(db, 0, 0, &iArg); + assert( rc==SQLITE_ERROR ); + rc = sqlite3_file_control(db, "notadatabase", SQLITE_FCNTL_LOCKSTATE, &iArg); + assert( rc==SQLITE_ERROR ); + rc = sqlite3_file_control(db, "main", -1, &iArg); + assert( rc==SQLITE_ERROR ); + rc = sqlite3_file_control(db, "temp", -1, &iArg); + assert( rc==SQLITE_ERROR ); + return TCL_OK; +} + +/* +** tclcmd: sqlite3_vfs_list +** +** Return a tcl list containing the names of all registered vfs's. +*/ +static int vfs_list( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + sqlite3_vfs *pVfs; + Tcl_Obj *pRet = Tcl_NewObj(); + if( objc!=1 ){ + Tcl_WrongNumArgs(interp, 1, objv, ""); + return TCL_ERROR; + } + for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){ + Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(pVfs->zName, -1)); + } + Tcl_SetObjResult(interp, pRet); + return TCL_OK; +} + +/* +** tclcmd: sqlite3_limit DB ID VALUE +** +** This TCL command runs the sqlite3_limit interface and +** verifies correct operation of the same. +*/ +static int test_limit( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + sqlite3 *db; + int rc; + static const struct { + char *zName; + int id; + } aId[] = { + { "SQLITE_LIMIT_LENGTH", SQLITE_LIMIT_LENGTH }, + { "SQLITE_LIMIT_SQL_LENGTH", SQLITE_LIMIT_SQL_LENGTH }, + { "SQLITE_LIMIT_COLUMN", SQLITE_LIMIT_COLUMN }, + { "SQLITE_LIMIT_EXPR_DEPTH", SQLITE_LIMIT_EXPR_DEPTH }, + { "SQLITE_LIMIT_COMPOUND_SELECT", SQLITE_LIMIT_COMPOUND_SELECT }, + { "SQLITE_LIMIT_VDBE_OP", SQLITE_LIMIT_VDBE_OP }, + { "SQLITE_LIMIT_FUNCTION_ARG", SQLITE_LIMIT_FUNCTION_ARG }, + { "SQLITE_LIMIT_ATTACHED", SQLITE_LIMIT_ATTACHED }, + { "SQLITE_LIMIT_LIKE_PATTERN_LENGTH", SQLITE_LIMIT_LIKE_PATTERN_LENGTH }, + { "SQLITE_LIMIT_VARIABLE_NUMBER", SQLITE_LIMIT_VARIABLE_NUMBER }, + + /* Out of range test cases */ + { "SQLITE_LIMIT_TOOSMALL", -1, }, + { "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_VARIABLE_NUMBER+1 }, + }; + int i, id; + int val; + const char *zId; + + if( objc!=4 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), " DB ID VALUE", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + zId = Tcl_GetString(objv[2]); + for(i=0; i<sizeof(aId)/sizeof(aId[0]); i++){ + if( strcmp(zId, aId[i].zName)==0 ){ + id = aId[i].id; + break; + } + } + if( i>=sizeof(aId)/sizeof(aId[0]) ){ + Tcl_AppendResult(interp, "unknown limit type: ", zId, (char*)0); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR; + rc = sqlite3_limit(db, id, val); + Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); + return TCL_OK; +} + +/* +** tclcmd: save_prng_state +** +** Save the state of the pseudo-random number generator. +** At the same time, verify that sqlite3_test_control works even when +** called with an out-of-range opcode. +*/ +static int save_prng_state( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + int rc = sqlite3_test_control(9999); + assert( rc==0 ); + rc = sqlite3_test_control(-1); + assert( rc==0 ); + sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SAVE); + return TCL_OK; +} +/* +** tclcmd: restore_prng_state +*/ +static int restore_prng_state( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESTORE); + return TCL_OK; +} +/* +** tclcmd: reset_prng_state +*/ +static int reset_prng_state( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESET); + return TCL_OK; +} + + +/* +** Register commands with the TCL interpreter. +*/ +int Sqlitetest1_Init(Tcl_Interp *interp){ + extern int sqlite3_search_count; + extern int sqlite3_interrupt_count; + extern int sqlite3_open_file_count; + extern int sqlite3_sort_count; + extern int sqlite3_current_time; + extern int sqlite3_max_blobsize; + extern int sqlite3BtreeSharedCacheReport(void*, + Tcl_Interp*,int,Tcl_Obj*CONST*); + static struct { + char *zName; + Tcl_CmdProc *xProc; + } aCmd[] = { + { "db_enter", (Tcl_CmdProc*)db_enter }, + { "db_leave", (Tcl_CmdProc*)db_leave }, + { "sqlite3_mprintf_int", (Tcl_CmdProc*)sqlite3_mprintf_int }, + { "sqlite3_mprintf_int64", (Tcl_CmdProc*)sqlite3_mprintf_int64 }, + { "sqlite3_mprintf_str", (Tcl_CmdProc*)sqlite3_mprintf_str }, + { "sqlite3_snprintf_str", (Tcl_CmdProc*)sqlite3_snprintf_str }, + { "sqlite3_mprintf_stronly", (Tcl_CmdProc*)sqlite3_mprintf_stronly}, + { "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double }, + { "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled }, + { "sqlite3_mprintf_hexdouble", (Tcl_CmdProc*)sqlite3_mprintf_hexdouble}, + { "sqlite3_mprintf_z_test", (Tcl_CmdProc*)test_mprintf_z }, + { "sqlite3_mprintf_n_test", (Tcl_CmdProc*)test_mprintf_n }, + { "sqlite3_snprintf_int", (Tcl_CmdProc*)test_snprintf_int }, + { "sqlite3_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid }, + { "sqlite3_exec_printf", (Tcl_CmdProc*)test_exec_printf }, + { "sqlite3_exec", (Tcl_CmdProc*)test_exec }, + { "sqlite3_exec_nr", (Tcl_CmdProc*)test_exec_nr }, +#ifndef SQLITE_OMIT_GET_TABLE + { "sqlite3_get_table_printf", (Tcl_CmdProc*)test_get_table_printf }, +#endif + { "sqlite3_close", (Tcl_CmdProc*)sqlite_test_close }, + { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function }, + { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate }, + { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func }, + { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort }, + { "sqlite_bind", (Tcl_CmdProc*)test_bind }, + { "breakpoint", (Tcl_CmdProc*)test_breakpoint }, + { "sqlite3_key", (Tcl_CmdProc*)test_key }, + { "sqlite3_rekey", (Tcl_CmdProc*)test_rekey }, + { "sqlite_set_magic", (Tcl_CmdProc*)sqlite_set_magic }, + { "sqlite3_interrupt", (Tcl_CmdProc*)test_interrupt }, + { "sqlite_delete_function", (Tcl_CmdProc*)delete_function }, + { "sqlite_delete_collation", (Tcl_CmdProc*)delete_collation }, + { "sqlite3_get_autocommit", (Tcl_CmdProc*)get_autocommit }, + { "sqlite3_stack_used", (Tcl_CmdProc*)test_stack_used }, + { "sqlite3_busy_timeout", (Tcl_CmdProc*)test_busy_timeout }, + { "printf", (Tcl_CmdProc*)test_printf }, + { "sqlite3IoTrace", (Tcl_CmdProc*)test_io_trace }, + }; + static struct { + char *zName; + Tcl_ObjCmdProc *xProc; + void *clientData; + } aObjCmd[] = { + { "sqlite3_connection_pointer", get_sqlite_pointer, 0 }, + { "sqlite3_bind_int", test_bind_int, 0 }, + { "sqlite3_bind_zeroblob", test_bind_zeroblob, 0 }, + { "sqlite3_bind_int64", test_bind_int64, 0 }, + { "sqlite3_bind_double", test_bind_double, 0 }, + { "sqlite3_bind_null", test_bind_null ,0 }, + { "sqlite3_bind_text", test_bind_text ,0 }, + { "sqlite3_bind_text16", test_bind_text16 ,0 }, + { "sqlite3_bind_blob", test_bind_blob ,0 }, + { "sqlite3_bind_parameter_count", test_bind_parameter_count, 0}, + { "sqlite3_bind_parameter_name", test_bind_parameter_name, 0}, + { "sqlite3_bind_parameter_index", test_bind_parameter_index, 0}, + { "sqlite3_clear_bindings", test_clear_bindings, 0}, + { "sqlite3_sleep", test_sleep, 0}, + { "sqlite3_errcode", test_errcode ,0 }, + { "sqlite3_errmsg", test_errmsg ,0 }, + { "sqlite3_errmsg16", test_errmsg16 ,0 }, + { "sqlite3_open", test_open ,0 }, + { "sqlite3_open16", test_open16 ,0 }, + { "sqlite3_complete16", test_complete16 ,0 }, + + { "sqlite3_prepare", test_prepare ,0 }, + { "sqlite3_prepare16", test_prepare16 ,0 }, + { "sqlite3_prepare_v2", test_prepare_v2 ,0 }, + { "sqlite3_prepare_tkt3134", test_prepare_tkt3134, 0}, + { "sqlite3_prepare16_v2", test_prepare16_v2 ,0 }, + { "sqlite3_finalize", test_finalize ,0 }, + { "sqlite3_reset", test_reset ,0 }, + { "sqlite3_expired", test_expired ,0 }, + { "sqlite3_transfer_bindings", test_transfer_bind ,0 }, + { "sqlite3_changes", test_changes ,0 }, + { "sqlite3_step", test_step ,0 }, + { "sqlite3_next_stmt", test_next_stmt ,0 }, + + { "sqlite3_release_memory", test_release_memory, 0}, + { "sqlite3_soft_heap_limit", test_soft_heap_limit, 0}, + { "sqlite3_thread_cleanup", test_thread_cleanup, 0}, + { "sqlite3_pager_refcounts", test_pager_refcounts, 0}, + + { "sqlite3_load_extension", test_load_extension, 0}, + { "sqlite3_enable_load_extension", test_enable_load, 0}, + { "sqlite3_extended_result_codes", test_extended_result_codes, 0}, + { "sqlite3_limit", test_limit, 0}, + + { "save_prng_state", save_prng_state, 0 }, + { "restore_prng_state", restore_prng_state, 0 }, + { "reset_prng_state", reset_prng_state, 0 }, + + /* sqlite3_column_*() API */ + { "sqlite3_column_count", test_column_count ,0 }, + { "sqlite3_data_count", test_data_count ,0 }, + { "sqlite3_column_type", test_column_type ,0 }, + { "sqlite3_column_blob", test_column_blob ,0 }, + { "sqlite3_column_double", test_column_double ,0 }, + { "sqlite3_column_int64", test_column_int64 ,0 }, + { "sqlite3_column_text", test_stmt_utf8, sqlite3_column_text }, + { "sqlite3_column_name", test_stmt_utf8, sqlite3_column_name }, + { "sqlite3_column_int", test_stmt_int, sqlite3_column_int }, + { "sqlite3_column_bytes", test_stmt_int, sqlite3_column_bytes }, +#ifndef SQLITE_OMIT_DECLTYPE + { "sqlite3_column_decltype", test_stmt_utf8, sqlite3_column_decltype }, +#endif +#ifdef SQLITE_ENABLE_COLUMN_METADATA +{ "sqlite3_column_database_name", test_stmt_utf8, sqlite3_column_database_name}, +{ "sqlite3_column_table_name", test_stmt_utf8, sqlite3_column_table_name}, +{ "sqlite3_column_origin_name", test_stmt_utf8, sqlite3_column_origin_name}, +#endif + +#ifndef SQLITE_OMIT_UTF16 + { "sqlite3_column_bytes16", test_stmt_int, sqlite3_column_bytes16 }, + { "sqlite3_column_text16", test_stmt_utf16, sqlite3_column_text16 }, + { "sqlite3_column_name16", test_stmt_utf16, sqlite3_column_name16 }, + { "add_alignment_test_collations", add_alignment_test_collations, 0 }, +#ifndef SQLITE_OMIT_DECLTYPE + { "sqlite3_column_decltype16", test_stmt_utf16, sqlite3_column_decltype16}, +#endif +#ifdef SQLITE_ENABLE_COLUMN_METADATA +{"sqlite3_column_database_name16", + test_stmt_utf16, sqlite3_column_database_name16}, +{"sqlite3_column_table_name16", test_stmt_utf16, sqlite3_column_table_name16}, +{"sqlite3_column_origin_name16", test_stmt_utf16, sqlite3_column_origin_name16}, +#endif +#endif + { "sqlite3_create_collation_v2", test_create_collation_v2, 0 }, + { "sqlite3_global_recover", test_global_recover, 0 }, + { "working_64bit_int", working_64bit_int, 0 }, + { "vfs_unlink_test", vfs_unlink_test, 0 }, + { "vfs_initfail_test", vfs_initfail_test, 0 }, + { "vfs_unregister_all", vfs_unregister_all, 0 }, + { "vfs_reregister_all", vfs_reregister_all, 0 }, + { "file_control_test", file_control_test, 0 }, + { "sqlite3_vfs_list", vfs_list, 0 }, + + /* Functions from os.h */ +#ifndef SQLITE_OMIT_UTF16 + { "add_test_collate", test_collate, 0 }, + { "add_test_collate_needed", test_collate_needed, 0 }, + { "add_test_function", test_function, 0 }, +#endif + { "sqlite3_test_errstr", test_errstr, 0 }, + { "tcl_variable_type", tcl_variable_type, 0 }, +#ifndef SQLITE_OMIT_SHARED_CACHE + { "sqlite3_enable_shared_cache", test_enable_shared, 0 }, + { "sqlite3_shared_cache_report", sqlite3BtreeSharedCacheReport, 0}, +#endif + { "sqlite3_libversion_number", test_libversion_number, 0 }, +#ifdef SQLITE_ENABLE_COLUMN_METADATA + { "sqlite3_table_column_metadata", test_table_column_metadata, 0 }, +#endif +#ifndef SQLITE_OMIT_INCRBLOB + { "sqlite3_blob_read", test_blob_read, 0 }, + { "sqlite3_blob_write", test_blob_write, 0 }, +#endif + }; + static int bitmask_size = sizeof(Bitmask)*8; + int i; + extern int sqlite3_sync_count, sqlite3_fullsync_count; + extern int sqlite3_opentemp_count; + extern int sqlite3_like_count; + extern int sqlite3_xferopt_count; + extern int sqlite3_pager_readdb_count; + extern int sqlite3_pager_writedb_count; + extern int sqlite3_pager_writej_count; + extern int sqlite3_pager_pgfree_count; +#if SQLITE_OS_UNIX && defined(SQLITE_TEST) && SQLITE_THREADSAFE + extern int threadsOverrideEachOthersLocks; +#endif +#if SQLITE_OS_WIN + extern int sqlite3_os_type; +#endif +#ifdef SQLITE_DEBUG + extern int sqlite3WhereTrace; + extern int sqlite3OSTrace; + extern int sqlite3VdbeAddopTrace; +#endif +#ifdef SQLITE_TEST + extern int sqlite3_enable_in_opt; + extern char sqlite3_query_plan[]; + static char *query_plan = sqlite3_query_plan; +#endif + + for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ + Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); + } + for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ + Tcl_CreateObjCommand(interp, aObjCmd[i].zName, + aObjCmd[i].xProc, aObjCmd[i].clientData, 0); + } + Tcl_LinkVar(interp, "sqlite_search_count", + (char*)&sqlite3_search_count, TCL_LINK_INT); + Tcl_LinkVar(interp, "sqlite_sort_count", + (char*)&sqlite3_sort_count, TCL_LINK_INT); + Tcl_LinkVar(interp, "sqlite3_max_blobsize", + (char*)&sqlite3_max_blobsize, TCL_LINK_INT); + Tcl_LinkVar(interp, "sqlite_like_count", + (char*)&sqlite3_like_count, TCL_LINK_INT); + Tcl_LinkVar(interp, "sqlite_interrupt_count", + (char*)&sqlite3_interrupt_count, TCL_LINK_INT); + Tcl_LinkVar(interp, "sqlite_open_file_count", + (char*)&sqlite3_open_file_count, TCL_LINK_INT); + Tcl_LinkVar(interp, "sqlite_current_time", + (char*)&sqlite3_current_time, TCL_LINK_INT); + Tcl_LinkVar(interp, "sqlite3_xferopt_count", + (char*)&sqlite3_xferopt_count, TCL_LINK_INT); + Tcl_LinkVar(interp, "sqlite3_pager_readdb_count", + (char*)&sqlite3_pager_readdb_count, TCL_LINK_INT); + Tcl_LinkVar(interp, "sqlite3_pager_writedb_count", + (char*)&sqlite3_pager_writedb_count, TCL_LINK_INT); + Tcl_LinkVar(interp, "sqlite3_pager_writej_count", + (char*)&sqlite3_pager_writej_count, TCL_LINK_INT); + Tcl_LinkVar(interp, "sqlite3_pager_pgfree_count", + (char*)&sqlite3_pager_pgfree_count, TCL_LINK_INT); +#ifndef SQLITE_OMIT_UTF16 + Tcl_LinkVar(interp, "unaligned_string_counter", + (char*)&unaligned_string_counter, TCL_LINK_INT); +#endif +#if SQLITE_OS_UNIX && defined(SQLITE_TEST) && SQLITE_THREADSAFE + Tcl_LinkVar(interp, "threadsOverrideEachOthersLocks", + (char*)&threadsOverrideEachOthersLocks, TCL_LINK_INT); +#endif +#ifndef SQLITE_OMIT_UTF16 + Tcl_LinkVar(interp, "sqlite_last_needed_collation", + (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY); +#endif +#if SQLITE_OS_WIN + Tcl_LinkVar(interp, "sqlite_os_type", + (char*)&sqlite3_os_type, TCL_LINK_INT); +#endif +#ifdef SQLITE_TEST + Tcl_LinkVar(interp, "sqlite_query_plan", + (char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY); +#endif +#ifdef SQLITE_DEBUG + Tcl_LinkVar(interp, "sqlite_addop_trace", + (char*)&sqlite3VdbeAddopTrace, TCL_LINK_INT); + Tcl_LinkVar(interp, "sqlite_where_trace", + (char*)&sqlite3WhereTrace, TCL_LINK_INT); + Tcl_LinkVar(interp, "sqlite_os_trace", + (char*)&sqlite3OSTrace, TCL_LINK_INT); +#endif +#ifndef SQLITE_OMIT_DISKIO + Tcl_LinkVar(interp, "sqlite_opentemp_count", + (char*)&sqlite3_opentemp_count, TCL_LINK_INT); +#endif + Tcl_LinkVar(interp, "sqlite_static_bind_value", + (char*)&sqlite_static_bind_value, TCL_LINK_STRING); + Tcl_LinkVar(interp, "sqlite_static_bind_nbyte", + (char*)&sqlite_static_bind_nbyte, TCL_LINK_INT); + Tcl_LinkVar(interp, "sqlite_temp_directory", + (char*)&sqlite3_temp_directory, TCL_LINK_STRING); + Tcl_LinkVar(interp, "bitmask_size", + (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY); + Tcl_LinkVar(interp, "sqlite_sync_count", + (char*)&sqlite3_sync_count, TCL_LINK_INT); + Tcl_LinkVar(interp, "sqlite_fullsync_count", + (char*)&sqlite3_fullsync_count, TCL_LINK_INT); +#ifdef SQLITE_TEST + Tcl_LinkVar(interp, "sqlite_enable_in_opt", + (char*)&sqlite3_enable_in_opt, TCL_LINK_INT); +#endif + return TCL_OK; +} diff --git a/third_party/sqlite/src/test2.c b/third_party/sqlite/src/test2.c new file mode 100755 index 0000000..c27a9fd --- /dev/null +++ b/third_party/sqlite/src/test2.c @@ -0,0 +1,659 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** Code for testing the pager.c module in SQLite. This code +** is not included in the SQLite library. It is used for automated +** testing of the SQLite library. +** +** $Id: test2.c,v 1.59 2008/07/12 14:52:20 drh Exp $ +*/ +#include "sqliteInt.h" +#include "tcl.h" +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +/* +** Interpret an SQLite error number +*/ +static char *errorName(int rc){ + char *zName; + switch( rc ){ + case SQLITE_OK: zName = "SQLITE_OK"; break; + case SQLITE_ERROR: zName = "SQLITE_ERROR"; break; + case SQLITE_PERM: zName = "SQLITE_PERM"; break; + case SQLITE_ABORT: zName = "SQLITE_ABORT"; break; + case SQLITE_BUSY: zName = "SQLITE_BUSY"; break; + case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break; + case SQLITE_READONLY: zName = "SQLITE_READONLY"; break; + case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break; + case SQLITE_IOERR: zName = "SQLITE_IOERR"; break; + case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break; + case SQLITE_FULL: zName = "SQLITE_FULL"; break; + case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break; + case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break; + case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break; + case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break; + case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break; + case SQLITE_MISMATCH: zName = "SQLITE_MISMATCH"; break; + case SQLITE_MISUSE: zName = "SQLITE_MISUSE"; break; + case SQLITE_NOLFS: zName = "SQLITE_NOLFS"; break; + default: zName = "SQLITE_Unknown"; break; + } + return zName; +} + +/* +** Page size and reserved size used for testing. +*/ +static int test_pagesize = 1024; + +/* +** Usage: pager_open FILENAME N-PAGE +** +** Open a new pager +*/ +static int pager_open( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + u16 pageSize; + Pager *pPager; + int nPage; + int rc; + char zBuf[100]; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " FILENAME N-PAGE\"", 0); + return TCL_ERROR; + } + if( Tcl_GetInt(interp, argv[2], &nPage) ) return TCL_ERROR; + rc = sqlite3PagerOpen(sqlite3_vfs_find(0), &pPager, argv[1], 0, 0, + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + sqlite3PagerSetCachesize(pPager, nPage); + pageSize = test_pagesize; + sqlite3PagerSetPagesize(pPager, &pageSize); + sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPager); + Tcl_AppendResult(interp, zBuf, 0); + return TCL_OK; +} + +/* +** Usage: pager_close ID +** +** Close the given pager. +*/ +static int pager_close( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Pager *pPager; + int rc; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pPager = sqlite3TestTextToPtr(argv[1]); + rc = sqlite3PagerClose(pPager); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + return TCL_OK; +} + +/* +** Usage: pager_rollback ID +** +** Rollback changes +*/ +static int pager_rollback( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Pager *pPager; + int rc; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pPager = sqlite3TestTextToPtr(argv[1]); + rc = sqlite3PagerRollback(pPager); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + return TCL_OK; +} + +/* +** Usage: pager_commit ID +** +** Commit all changes +*/ +static int pager_commit( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Pager *pPager; + int rc; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pPager = sqlite3TestTextToPtr(argv[1]); + rc = sqlite3PagerCommitPhaseOne(pPager, 0, 0, 0); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + rc = sqlite3PagerCommitPhaseTwo(pPager); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + return TCL_OK; +} + +/* +** Usage: pager_stmt_begin ID +** +** Start a new checkpoint. +*/ +static int pager_stmt_begin( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Pager *pPager; + int rc; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pPager = sqlite3TestTextToPtr(argv[1]); + rc = sqlite3PagerStmtBegin(pPager); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + return TCL_OK; +} + +/* +** Usage: pager_stmt_rollback ID +** +** Rollback changes to a checkpoint +*/ +static int pager_stmt_rollback( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Pager *pPager; + int rc; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pPager = sqlite3TestTextToPtr(argv[1]); + rc = sqlite3PagerStmtRollback(pPager); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + return TCL_OK; +} + +/* +** Usage: pager_stmt_commit ID +** +** Commit changes to a checkpoint +*/ +static int pager_stmt_commit( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Pager *pPager; + int rc; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pPager = sqlite3TestTextToPtr(argv[1]); + rc = sqlite3PagerStmtCommit(pPager); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + return TCL_OK; +} + +/* +** Usage: pager_stats ID +** +** Return pager statistics. +*/ +static int pager_stats( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Pager *pPager; + int i, *a; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pPager = sqlite3TestTextToPtr(argv[1]); + a = sqlite3PagerStats(pPager); + for(i=0; i<9; i++){ + static char *zName[] = { + "ref", "page", "max", "size", "state", "err", + "hit", "miss", "ovfl", + }; + char zBuf[100]; + Tcl_AppendElement(interp, zName[i]); + sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",a[i]); + Tcl_AppendElement(interp, zBuf); + } + return TCL_OK; +} + +/* +** Usage: pager_pagecount ID +** +** Return the size of the database file. +*/ +static int pager_pagecount( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Pager *pPager; + char zBuf[100]; + int nPage; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pPager = sqlite3TestTextToPtr(argv[1]); + sqlite3PagerPagecount(pPager, &nPage); + sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nPage); + Tcl_AppendResult(interp, zBuf, 0); + return TCL_OK; +} + +/* +** Usage: page_get ID PGNO +** +** Return a pointer to a page from the database. +*/ +static int page_get( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Pager *pPager; + char zBuf[100]; + DbPage *pPage; + int pgno; + int rc; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID PGNO\"", 0); + return TCL_ERROR; + } + pPager = sqlite3TestTextToPtr(argv[1]); + if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR; + rc = sqlite3PagerGet(pPager, pgno, &pPage); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPage); + Tcl_AppendResult(interp, zBuf, 0); + return TCL_OK; +} + +/* +** Usage: page_lookup ID PGNO +** +** Return a pointer to a page if the page is already in cache. +** If not in cache, return an empty string. +*/ +static int page_lookup( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Pager *pPager; + char zBuf[100]; + DbPage *pPage; + int pgno; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID PGNO\"", 0); + return TCL_ERROR; + } + pPager = sqlite3TestTextToPtr(argv[1]); + if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR; + pPage = sqlite3PagerLookup(pPager, pgno); + if( pPage ){ + sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPage); + Tcl_AppendResult(interp, zBuf, 0); + } + return TCL_OK; +} + +/* +** Usage: pager_truncate ID PGNO +*/ +static int pager_truncate( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Pager *pPager; + int rc; + int pgno; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID PGNO\"", 0); + return TCL_ERROR; + } + pPager = sqlite3TestTextToPtr(argv[1]); + if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR; + rc = sqlite3PagerTruncate(pPager, pgno); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + return TCL_OK; +} + + +/* +** Usage: page_unref PAGE +** +** Drop a pointer to a page. +*/ +static int page_unref( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + DbPage *pPage; + int rc; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " PAGE\"", 0); + return TCL_ERROR; + } + pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]); + rc = sqlite3PagerUnref(pPage); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + return TCL_OK; +} + +/* +** Usage: page_read PAGE +** +** Return the content of a page +*/ +static int page_read( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + char zBuf[100]; + DbPage *pPage; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " PAGE\"", 0); + return TCL_ERROR; + } + pPage = sqlite3TestTextToPtr(argv[1]); + memcpy(zBuf, sqlite3PagerGetData(pPage), sizeof(zBuf)); + Tcl_AppendResult(interp, zBuf, 0); + return TCL_OK; +} + +/* +** Usage: page_number PAGE +** +** Return the page number for a page. +*/ +static int page_number( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + char zBuf[100]; + DbPage *pPage; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " PAGE\"", 0); + return TCL_ERROR; + } + pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]); + sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", sqlite3PagerPagenumber(pPage)); + Tcl_AppendResult(interp, zBuf, 0); + return TCL_OK; +} + +/* +** Usage: page_write PAGE DATA +** +** Write something into a page. +*/ +static int page_write( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + DbPage *pPage; + char *pData; + int rc; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " PAGE DATA\"", 0); + return TCL_ERROR; + } + pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]); + rc = sqlite3PagerWrite(pPage); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + pData = sqlite3PagerGetData(pPage); + strncpy(pData, argv[2], test_pagesize-1); + pData[test_pagesize-1] = 0; + return TCL_OK; +} + +#ifndef SQLITE_OMIT_DISKIO +/* +** Usage: fake_big_file N FILENAME +** +** Write a few bytes at the N megabyte point of FILENAME. This will +** create a large file. If the file was a valid SQLite database, then +** the next time the database is opened, SQLite will begin allocating +** new pages after N. If N is 2096 or bigger, this will test the +** ability of SQLite to write to large files. +*/ +static int fake_big_file( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + sqlite3_vfs *pVfs; + sqlite3_file *fd = 0; + int rc; + int n; + i64 offset; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " N-MEGABYTES FILE\"", 0); + return TCL_ERROR; + } + if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; + + pVfs = sqlite3_vfs_find(0); + rc = sqlite3OsOpenMalloc(pVfs, argv[2], &fd, + (SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB), 0 + ); + if( rc ){ + Tcl_AppendResult(interp, "open failed: ", errorName(rc), 0); + return TCL_ERROR; + } + offset = n; + offset *= 1024*1024; + rc = sqlite3OsWrite(fd, "Hello, World!", 14, offset); + sqlite3OsCloseFree(fd); + if( rc ){ + Tcl_AppendResult(interp, "write failed: ", errorName(rc), 0); + return TCL_ERROR; + } + return TCL_OK; +} +#endif + + +/* +** sqlite3BitvecBuiltinTest SIZE PROGRAM +** +** Invoke the SQLITE_TESTCTRL_BITVEC_TEST operator on test_control. +** See comments on sqlite3BitvecBuiltinTest() for additional information. +*/ +static int testBitvecBuiltinTest( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int sz, rc; + int nProg = 0; + int aProg[100]; + const char *z; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " SIZE PROGRAM\"", (void*)0); + } + if( Tcl_GetInt(interp, argv[1], &sz) ) return TCL_ERROR; + z = argv[2]; + while( nProg<99 && *z ){ + while( *z && !isdigit(*z) ){ z++; } + if( *z==0 ) break; + aProg[nProg++] = atoi(z); + while( isdigit(*z) ){ z++; } + } + aProg[nProg] = 0; + rc = sqlite3_test_control(SQLITE_TESTCTRL_BITVEC_TEST, sz, aProg); + Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); + return TCL_OK; +} + +/* +** Register commands with the TCL interpreter. +*/ +int Sqlitetest2_Init(Tcl_Interp *interp){ + extern int sqlite3_io_error_persist; + extern int sqlite3_io_error_pending; + extern int sqlite3_io_error_hit; + extern int sqlite3_io_error_hardhit; + extern int sqlite3_diskfull_pending; + extern int sqlite3_diskfull; + extern int sqlite3_pager_n_sort_bucket; + static struct { + char *zName; + Tcl_CmdProc *xProc; + } aCmd[] = { + { "pager_open", (Tcl_CmdProc*)pager_open }, + { "pager_close", (Tcl_CmdProc*)pager_close }, + { "pager_commit", (Tcl_CmdProc*)pager_commit }, + { "pager_rollback", (Tcl_CmdProc*)pager_rollback }, + { "pager_stmt_begin", (Tcl_CmdProc*)pager_stmt_begin }, + { "pager_stmt_commit", (Tcl_CmdProc*)pager_stmt_commit }, + { "pager_stmt_rollback", (Tcl_CmdProc*)pager_stmt_rollback }, + { "pager_stats", (Tcl_CmdProc*)pager_stats }, + { "pager_pagecount", (Tcl_CmdProc*)pager_pagecount }, + { "page_get", (Tcl_CmdProc*)page_get }, + { "page_lookup", (Tcl_CmdProc*)page_lookup }, + { "page_unref", (Tcl_CmdProc*)page_unref }, + { "page_read", (Tcl_CmdProc*)page_read }, + { "page_write", (Tcl_CmdProc*)page_write }, + { "page_number", (Tcl_CmdProc*)page_number }, + { "pager_truncate", (Tcl_CmdProc*)pager_truncate }, +#ifndef SQLITE_OMIT_DISKIO + { "fake_big_file", (Tcl_CmdProc*)fake_big_file }, +#endif + { "sqlite3BitvecBuiltinTest",(Tcl_CmdProc*)testBitvecBuiltinTest}, + }; + int i; + for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ + Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); + } + Tcl_LinkVar(interp, "sqlite_io_error_pending", + (char*)&sqlite3_io_error_pending, TCL_LINK_INT); + Tcl_LinkVar(interp, "sqlite_io_error_persist", + (char*)&sqlite3_io_error_persist, TCL_LINK_INT); + Tcl_LinkVar(interp, "sqlite_io_error_hit", + (char*)&sqlite3_io_error_hit, TCL_LINK_INT); + Tcl_LinkVar(interp, "sqlite_io_error_hardhit", + (char*)&sqlite3_io_error_hardhit, TCL_LINK_INT); + Tcl_LinkVar(interp, "sqlite_diskfull_pending", + (char*)&sqlite3_diskfull_pending, TCL_LINK_INT); + Tcl_LinkVar(interp, "sqlite_diskfull", + (char*)&sqlite3_diskfull, TCL_LINK_INT); + Tcl_LinkVar(interp, "sqlite_pending_byte", + (char*)&sqlite3_pending_byte, TCL_LINK_INT); + Tcl_LinkVar(interp, "sqlite_pager_n_sort_bucket", + (char*)&sqlite3_pager_n_sort_bucket, TCL_LINK_INT); + return TCL_OK; +} diff --git a/third_party/sqlite/src/test3.c b/third_party/sqlite/src/test3.c new file mode 100755 index 0000000..6b06dfc --- /dev/null +++ b/third_party/sqlite/src/test3.c @@ -0,0 +1,1605 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** Code for testing the btree.c module in SQLite. This code +** is not included in the SQLite library. It is used for automated +** testing of the SQLite library. +** +** $Id: test3.c,v 1.100 2008/07/12 14:52:20 drh Exp $ +*/ +#include "sqliteInt.h" +#include "btreeInt.h" +#include "tcl.h" +#include <stdlib.h> +#include <string.h> + +/* +** Interpret an SQLite error number +*/ +static char *errorName(int rc){ + char *zName; + switch( rc ){ + case SQLITE_OK: zName = "SQLITE_OK"; break; + case SQLITE_ERROR: zName = "SQLITE_ERROR"; break; + case SQLITE_PERM: zName = "SQLITE_PERM"; break; + case SQLITE_ABORT: zName = "SQLITE_ABORT"; break; + case SQLITE_BUSY: zName = "SQLITE_BUSY"; break; + case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break; + case SQLITE_READONLY: zName = "SQLITE_READONLY"; break; + case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break; + case SQLITE_IOERR: zName = "SQLITE_IOERR"; break; + case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break; + case SQLITE_FULL: zName = "SQLITE_FULL"; break; + case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break; + case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break; + case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break; + case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break; + default: zName = "SQLITE_Unknown"; break; + } + return zName; +} + +/* +** A bogus sqlite3 connection structure for use in the btree +** tests. +*/ +static sqlite3 sDb; +static int nRefSqlite3 = 0; + +/* +** Usage: btree_open FILENAME NCACHE FLAGS +** +** Open a new database +*/ +static int btree_open( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Btree *pBt; + int rc, nCache, flags; + char zBuf[100]; + if( argc!=4 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " FILENAME NCACHE FLAGS\"", 0); + return TCL_ERROR; + } + if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR; + if( Tcl_GetInt(interp, argv[3], &flags) ) return TCL_ERROR; + nRefSqlite3++; + if( nRefSqlite3==1 ){ + sDb.pVfs = sqlite3_vfs_find(0); + sDb.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); + sqlite3_mutex_enter(sDb.mutex); + } + rc = sqlite3BtreeOpen(argv[1], &sDb, &pBt, flags, + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + sqlite3BtreeSetCacheSize(pBt, nCache); + sqlite3_snprintf(sizeof(zBuf), zBuf,"%p", pBt); + Tcl_AppendResult(interp, zBuf, 0); + return TCL_OK; +} + +/* +** Usage: btree_close ID +** +** Close the given database. +*/ +static int btree_close( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Btree *pBt; + int rc; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pBt = sqlite3TestTextToPtr(argv[1]); + rc = sqlite3BtreeClose(pBt); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + nRefSqlite3--; + if( nRefSqlite3==0 ){ + sqlite3_mutex_leave(sDb.mutex); + sqlite3_mutex_free(sDb.mutex); + sDb.mutex = 0; + sDb.pVfs = 0; + } + return TCL_OK; +} + + +/* +** Usage: btree_begin_transaction ID +** +** Start a new transaction +*/ +static int btree_begin_transaction( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Btree *pBt; + int rc; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pBt = sqlite3TestTextToPtr(argv[1]); + sqlite3BtreeEnter(pBt); + rc = sqlite3BtreeBeginTrans(pBt, 1); + sqlite3BtreeLeave(pBt); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + return TCL_OK; +} + +/* +** Usage: btree_rollback ID +** +** Rollback changes +*/ +static int btree_rollback( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Btree *pBt; + int rc; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pBt = sqlite3TestTextToPtr(argv[1]); + sqlite3BtreeEnter(pBt); + rc = sqlite3BtreeRollback(pBt); + sqlite3BtreeLeave(pBt); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + return TCL_OK; +} + +/* +** Usage: btree_commit ID +** +** Commit all changes +*/ +static int btree_commit( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Btree *pBt; + int rc; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pBt = sqlite3TestTextToPtr(argv[1]); + sqlite3BtreeEnter(pBt); + rc = sqlite3BtreeCommit(pBt); + sqlite3BtreeLeave(pBt); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + return TCL_OK; +} + +/* +** Usage: btree_begin_statement ID +** +** Start a new statement transaction +*/ +static int btree_begin_statement( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Btree *pBt; + int rc; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pBt = sqlite3TestTextToPtr(argv[1]); + sqlite3BtreeEnter(pBt); + rc = sqlite3BtreeBeginStmt(pBt); + sqlite3BtreeLeave(pBt); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + return TCL_OK; +} + +/* +** Usage: btree_rollback_statement ID +** +** Rollback changes +*/ +static int btree_rollback_statement( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Btree *pBt; + int rc; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pBt = sqlite3TestTextToPtr(argv[1]); + sqlite3BtreeEnter(pBt); + rc = sqlite3BtreeRollbackStmt(pBt); + sqlite3BtreeLeave(pBt); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + return TCL_OK; +} + +/* +** Usage: btree_commit_statement ID +** +** Commit all changes +*/ +static int btree_commit_statement( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Btree *pBt; + int rc; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pBt = sqlite3TestTextToPtr(argv[1]); + sqlite3BtreeEnter(pBt); + rc = sqlite3BtreeCommitStmt(pBt); + sqlite3BtreeLeave(pBt); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + return TCL_OK; +} + +/* +** Usage: btree_create_table ID FLAGS +** +** Create a new table in the database +*/ +static int btree_create_table( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Btree *pBt; + int rc, iTable, flags; + char zBuf[30]; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID FLAGS\"", 0); + return TCL_ERROR; + } + pBt = sqlite3TestTextToPtr(argv[1]); + if( Tcl_GetInt(interp, argv[2], &flags) ) return TCL_ERROR; + sqlite3BtreeEnter(pBt); + rc = sqlite3BtreeCreateTable(pBt, &iTable, flags); + sqlite3BtreeLeave(pBt); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", iTable); + Tcl_AppendResult(interp, zBuf, 0); + return TCL_OK; +} + +/* +** Usage: btree_drop_table ID TABLENUM +** +** Delete an entire table from the database +*/ +static int btree_drop_table( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Btree *pBt; + int iTable; + int rc; + int notUsed1; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID TABLENUM\"", 0); + return TCL_ERROR; + } + pBt = sqlite3TestTextToPtr(argv[1]); + if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR; + sqlite3BtreeEnter(pBt); + rc = sqlite3BtreeDropTable(pBt, iTable, ¬Used1); + sqlite3BtreeLeave(pBt); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + return TCL_OK; +} + +/* +** Usage: btree_clear_table ID TABLENUM +** +** Remove all entries from the given table but keep the table around. +*/ +static int btree_clear_table( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Btree *pBt; + int iTable; + int rc; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID TABLENUM\"", 0); + return TCL_ERROR; + } + pBt = sqlite3TestTextToPtr(argv[1]); + if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR; + sqlite3BtreeEnter(pBt); + rc = sqlite3BtreeClearTable(pBt, iTable); + sqlite3BtreeLeave(pBt); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + return TCL_OK; +} + +/* +** Usage: btree_get_meta ID +** +** Return meta data +*/ +static int btree_get_meta( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Btree *pBt; + int rc; + int i; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pBt = sqlite3TestTextToPtr(argv[1]); + for(i=0; i<SQLITE_N_BTREE_META; i++){ + char zBuf[30]; + u32 v; + sqlite3BtreeEnter(pBt); + rc = sqlite3BtreeGetMeta(pBt, i, &v); + sqlite3BtreeLeave(pBt); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + sqlite3_snprintf(sizeof(zBuf), zBuf,"%d",v); + Tcl_AppendElement(interp, zBuf); + } + return TCL_OK; +} + +/* +** Usage: btree_update_meta ID METADATA... +** +** Return meta data +*/ +static int btree_update_meta( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Btree *pBt; + int rc; + int i; + int aMeta[SQLITE_N_BTREE_META]; + + if( argc!=2+SQLITE_N_BTREE_META ){ + char zBuf[30]; + sqlite3_snprintf(sizeof(zBuf), zBuf,"%d",SQLITE_N_BTREE_META); + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID METADATA...\" (METADATA is ", zBuf, " integers)", 0); + return TCL_ERROR; + } + pBt = sqlite3TestTextToPtr(argv[1]); + for(i=1; i<SQLITE_N_BTREE_META; i++){ + if( Tcl_GetInt(interp, argv[i+2], &aMeta[i]) ) return TCL_ERROR; + } + for(i=1; i<SQLITE_N_BTREE_META; i++){ + sqlite3BtreeEnter(pBt); + rc = sqlite3BtreeUpdateMeta(pBt, i, aMeta[i]); + sqlite3BtreeLeave(pBt); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + } + return TCL_OK; +} + +/* +** Usage: btree_pager_stats ID +** +** Returns pager statistics +*/ +static int btree_pager_stats( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Btree *pBt; + int i; + int *a; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pBt = sqlite3TestTextToPtr(argv[1]); + + /* Normally in this file, with a b-tree handle opened using the + ** [btree_open] command it is safe to call sqlite3BtreeEnter() directly. + ** But this function is sometimes called with a btree handle obtained + ** from an open SQLite connection (using [btree_from_db]). In this case + ** we need to obtain the mutex for the controlling SQLite handle before + ** it is safe to call sqlite3BtreeEnter(). + */ + sqlite3_mutex_enter(pBt->db->mutex); + + sqlite3BtreeEnter(pBt); + a = sqlite3PagerStats(sqlite3BtreePager(pBt)); + for(i=0; i<11; i++){ + static char *zName[] = { + "ref", "page", "max", "size", "state", "err", + "hit", "miss", "ovfl", "read", "write" + }; + char zBuf[100]; + Tcl_AppendElement(interp, zName[i]); + sqlite3_snprintf(sizeof(zBuf), zBuf,"%d",a[i]); + Tcl_AppendElement(interp, zBuf); + } + sqlite3BtreeLeave(pBt); + + /* Release the mutex on the SQLite handle that controls this b-tree */ + sqlite3_mutex_leave(pBt->db->mutex); + return TCL_OK; +} + +/* +** Usage: btree_integrity_check ID ROOT ... +** +** Look through every page of the given BTree file to verify correct +** formatting and linkage. Return a line of text for each problem found. +** Return an empty string if everything worked. +*/ +static int btree_integrity_check( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Btree *pBt; + int nRoot; + int *aRoot; + int i; + int nErr; + char *zResult; + + if( argc<3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID ROOT ...\"", 0); + return TCL_ERROR; + } + pBt = sqlite3TestTextToPtr(argv[1]); + nRoot = argc-2; + aRoot = (int*)sqlite3_malloc( sizeof(int)*(argc-2) ); + for(i=0; i<argc-2; i++){ + if( Tcl_GetInt(interp, argv[i+2], &aRoot[i]) ) return TCL_ERROR; + } +#ifndef SQLITE_OMIT_INTEGRITY_CHECK + sqlite3BtreeEnter(pBt); + zResult = sqlite3BtreeIntegrityCheck(pBt, aRoot, nRoot, 10000, &nErr); + sqlite3BtreeLeave(pBt); +#else + zResult = 0; +#endif + sqlite3_free((void*)aRoot); + if( zResult ){ + Tcl_AppendResult(interp, zResult, 0); + sqlite3_free(zResult); + } + return TCL_OK; +} + +/* +** Usage: btree_cursor_list ID +** +** Print information about all cursors to standard output for debugging. +*/ +static int btree_cursor_list( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Btree *pBt; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pBt = sqlite3TestTextToPtr(argv[1]); + sqlite3BtreeEnter(pBt); + sqlite3BtreeCursorList(pBt); + sqlite3BtreeLeave(pBt); + return SQLITE_OK; +} + +/* +** Usage: btree_cursor ID TABLENUM WRITEABLE +** +** Create a new cursor. Return the ID for the cursor. +*/ +static int btree_cursor( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Btree *pBt; + int iTable; + BtCursor *pCur; + int rc; + int wrFlag; + char zBuf[30]; + + if( argc!=4 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID TABLENUM WRITEABLE\"", 0); + return TCL_ERROR; + } + pBt = sqlite3TestTextToPtr(argv[1]); + if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR; + if( Tcl_GetBoolean(interp, argv[3], &wrFlag) ) return TCL_ERROR; + pCur = (BtCursor *)ckalloc(sqlite3BtreeCursorSize()); + memset(pCur, 0, sqlite3BtreeCursorSize()); + sqlite3BtreeEnter(pBt); + rc = sqlite3BtreeCursor(pBt, iTable, wrFlag, 0, pCur); + sqlite3BtreeLeave(pBt); + if( rc ){ + ckfree((char *)pCur); + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + sqlite3_snprintf(sizeof(zBuf), zBuf,"%p", pCur); + Tcl_AppendResult(interp, zBuf, 0); + return SQLITE_OK; +} + +/* +** Usage: btree_close_cursor ID +** +** Close a cursor opened using btree_cursor. +*/ +static int btree_close_cursor( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + BtCursor *pCur; + Btree *pBt; + int rc; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pCur = sqlite3TestTextToPtr(argv[1]); + pBt = pCur->pBtree; + sqlite3BtreeEnter(pBt); + rc = sqlite3BtreeCloseCursor(pCur); + sqlite3BtreeLeave(pBt); + ckfree((char *)pCur); + if( rc ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + return SQLITE_OK; +} + +/* +** Usage: btree_move_to ID KEY +** +** Move the cursor to the entry with the given key. +*/ +static int btree_move_to( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + BtCursor *pCur; + int rc; + int res; + char zBuf[20]; + + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID KEY\"", 0); + return TCL_ERROR; + } + pCur = sqlite3TestTextToPtr(argv[1]); + sqlite3BtreeEnter(pCur->pBtree); + if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){ + int iKey; + if( Tcl_GetInt(interp, argv[2], &iKey) ){ + sqlite3BtreeLeave(pCur->pBtree); + return TCL_ERROR; + } + rc = sqlite3BtreeMoveto(pCur, 0, 0, iKey, 0, &res); + }else{ + rc = sqlite3BtreeMoveto(pCur, argv[2], 0, strlen(argv[2]), 0, &res); + } + sqlite3BtreeLeave(pCur->pBtree); + if( rc ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + if( res<0 ) res = -1; + if( res>0 ) res = 1; + sqlite3_snprintf(sizeof(zBuf), zBuf,"%d",res); + Tcl_AppendResult(interp, zBuf, 0); + return SQLITE_OK; +} + +/* +** Usage: btree_delete ID +** +** Delete the entry that the cursor is pointing to +*/ +static int btree_delete( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + BtCursor *pCur; + int rc; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pCur = sqlite3TestTextToPtr(argv[1]); + sqlite3BtreeEnter(pCur->pBtree); + rc = sqlite3BtreeDelete(pCur); + sqlite3BtreeLeave(pCur->pBtree); + if( rc ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + return SQLITE_OK; +} + +/* +** Usage: btree_insert ID KEY DATA ?NZERO? +** +** Create a new entry with the given key and data. If an entry already +** exists with the same key the old entry is overwritten. +*/ +static int btree_insert( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + BtCursor *pCur; + int rc; + int nZero; + + if( objc!=4 && objc!=5 ){ + Tcl_WrongNumArgs(interp, 1, objv, "ID KEY DATA ?NZERO?"); + return TCL_ERROR; + } + pCur = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); + if( objc==5 ){ + if( Tcl_GetIntFromObj(interp, objv[4], &nZero) ) return TCL_ERROR; + }else{ + nZero = 0; + } + sqlite3BtreeEnter(pCur->pBtree); + if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){ + i64 iKey; + int len; + unsigned char *pBuf; + if( Tcl_GetWideIntFromObj(interp, objv[2], &iKey) ){ + sqlite3BtreeLeave(pCur->pBtree); + return TCL_ERROR; + } + pBuf = Tcl_GetByteArrayFromObj(objv[3], &len); + rc = sqlite3BtreeInsert(pCur, 0, iKey, pBuf, len, nZero, 0); + }else{ + int keylen; + int dlen; + unsigned char *pKBuf; + unsigned char *pDBuf; + pKBuf = Tcl_GetByteArrayFromObj(objv[2], &keylen); + pDBuf = Tcl_GetByteArrayFromObj(objv[3], &dlen); + rc = sqlite3BtreeInsert(pCur, pKBuf, keylen, pDBuf, dlen, nZero, 0); + } + sqlite3BtreeLeave(pCur->pBtree); + if( rc ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + return SQLITE_OK; +} + +/* +** Usage: btree_next ID +** +** Move the cursor to the next entry in the table. Return 0 on success +** or 1 if the cursor was already on the last entry in the table or if +** the table is empty. +*/ +static int btree_next( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + BtCursor *pCur; + int rc; + int res = 0; + char zBuf[100]; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pCur = sqlite3TestTextToPtr(argv[1]); + sqlite3BtreeEnter(pCur->pBtree); + rc = sqlite3BtreeNext(pCur, &res); + sqlite3BtreeLeave(pCur->pBtree); + if( rc ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",res); + Tcl_AppendResult(interp, zBuf, 0); + return SQLITE_OK; +} + +/* +** Usage: btree_prev ID +** +** Move the cursor to the previous entry in the table. Return 0 on +** success and 1 if the cursor was already on the first entry in +** the table or if the table was empty. +*/ +static int btree_prev( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + BtCursor *pCur; + int rc; + int res = 0; + char zBuf[100]; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pCur = sqlite3TestTextToPtr(argv[1]); + sqlite3BtreeEnter(pCur->pBtree); + rc = sqlite3BtreePrevious(pCur, &res); + sqlite3BtreeLeave(pCur->pBtree); + if( rc ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",res); + Tcl_AppendResult(interp, zBuf, 0); + return SQLITE_OK; +} + +/* +** Usage: btree_first ID +** +** Move the cursor to the first entry in the table. Return 0 if the +** cursor was left point to something and 1 if the table is empty. +*/ +static int btree_first( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + BtCursor *pCur; + int rc; + int res = 0; + char zBuf[100]; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pCur = sqlite3TestTextToPtr(argv[1]); + sqlite3BtreeEnter(pCur->pBtree); + rc = sqlite3BtreeFirst(pCur, &res); + sqlite3BtreeLeave(pCur->pBtree); + if( rc ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",res); + Tcl_AppendResult(interp, zBuf, 0); + return SQLITE_OK; +} + +/* +** Usage: btree_last ID +** +** Move the cursor to the last entry in the table. Return 0 if the +** cursor was left point to something and 1 if the table is empty. +*/ +static int btree_last( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + BtCursor *pCur; + int rc; + int res = 0; + char zBuf[100]; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pCur = sqlite3TestTextToPtr(argv[1]); + sqlite3BtreeEnter(pCur->pBtree); + rc = sqlite3BtreeLast(pCur, &res); + sqlite3BtreeLeave(pCur->pBtree); + if( rc ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",res); + Tcl_AppendResult(interp, zBuf, 0); + return SQLITE_OK; +} + +/* +** Usage: btree_eof ID +** +** Return TRUE if the given cursor is not pointing at a valid entry. +** Return FALSE if the cursor does point to a valid entry. +*/ +static int btree_eof( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + BtCursor *pCur; + int rc; + char zBuf[50]; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pCur = sqlite3TestTextToPtr(argv[1]); + sqlite3BtreeEnter(pCur->pBtree); + rc = sqlite3BtreeEof(pCur); + sqlite3BtreeLeave(pCur->pBtree); + sqlite3_snprintf(sizeof(zBuf),zBuf, "%d", rc); + Tcl_AppendResult(interp, zBuf, 0); + return SQLITE_OK; +} + +/* +** Usage: btree_keysize ID +** +** Return the number of bytes of key. For an INTKEY table, this +** returns the key itself. +*/ +static int btree_keysize( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + BtCursor *pCur; + u64 n; + char zBuf[50]; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pCur = sqlite3TestTextToPtr(argv[1]); + sqlite3BtreeEnter(pCur->pBtree); + sqlite3BtreeKeySize(pCur, (i64*)&n); + sqlite3BtreeLeave(pCur->pBtree); + sqlite3_snprintf(sizeof(zBuf),zBuf, "%llu", n); + Tcl_AppendResult(interp, zBuf, 0); + return SQLITE_OK; +} + +/* +** Usage: btree_key ID +** +** Return the key for the entry at which the cursor is pointing. +*/ +static int btree_key( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + BtCursor *pCur; + int rc; + u64 n; + char *zBuf; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pCur = sqlite3TestTextToPtr(argv[1]); + sqlite3BtreeEnter(pCur->pBtree); + sqlite3BtreeKeySize(pCur, (i64*)&n); + if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){ + char zBuf2[60]; + sqlite3_snprintf(sizeof(zBuf2),zBuf2, "%llu", n); + Tcl_AppendResult(interp, zBuf2, 0); + }else{ + zBuf = sqlite3_malloc( n+1 ); + rc = sqlite3BtreeKey(pCur, 0, n, zBuf); + if( rc ){ + sqlite3BtreeLeave(pCur->pBtree); + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + zBuf[n] = 0; + Tcl_AppendResult(interp, zBuf, 0); + sqlite3_free(zBuf); + } + sqlite3BtreeLeave(pCur->pBtree); + return SQLITE_OK; +} + +/* +** Usage: btree_data ID ?N? +** +** Return the data for the entry at which the cursor is pointing. +*/ +static int btree_data( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + BtCursor *pCur; + int rc; + u32 n; + char *zBuf; + + if( argc!=2 && argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pCur = sqlite3TestTextToPtr(argv[1]); + sqlite3BtreeEnter(pCur->pBtree); + if( argc==2 ){ + sqlite3BtreeDataSize(pCur, &n); + }else{ + n = atoi(argv[2]); + } + zBuf = sqlite3_malloc( n+1 ); + rc = sqlite3BtreeData(pCur, 0, n, zBuf); + sqlite3BtreeLeave(pCur->pBtree); + if( rc ){ + Tcl_AppendResult(interp, errorName(rc), 0); + sqlite3_free(zBuf); + return TCL_ERROR; + } + zBuf[n] = 0; + Tcl_AppendResult(interp, zBuf, 0); + sqlite3_free(zBuf); + return SQLITE_OK; +} + +/* +** Usage: btree_fetch_key ID AMT +** +** Use the sqlite3BtreeKeyFetch() routine to get AMT bytes of the key. +** If sqlite3BtreeKeyFetch() fails, return an empty string. +*/ +static int btree_fetch_key( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + BtCursor *pCur; + int n; + int amt; + u64 nKey; + const char *zBuf; + char zStatic[1000]; + + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID AMT\"", 0); + return TCL_ERROR; + } + pCur = sqlite3TestTextToPtr(argv[1]); + if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR; + sqlite3BtreeEnter(pCur->pBtree); + sqlite3BtreeKeySize(pCur, (i64*)&nKey); + zBuf = sqlite3BtreeKeyFetch(pCur, &amt); + if( zBuf && amt>=n ){ + assert( nKey<sizeof(zStatic) ); + if( n>0 ) nKey = n; + memcpy(zStatic, zBuf, (int)nKey); + zStatic[nKey] = 0; + Tcl_AppendResult(interp, zStatic, 0); + } + sqlite3BtreeLeave(pCur->pBtree); + return TCL_OK; +} + +/* +** Usage: btree_fetch_data ID AMT +** +** Use the sqlite3BtreeDataFetch() routine to get AMT bytes of the key. +** If sqlite3BtreeDataFetch() fails, return an empty string. +*/ +static int btree_fetch_data( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + BtCursor *pCur; + int n; + int amt; + u32 nData; + const char *zBuf; + char zStatic[1000]; + + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID AMT\"", 0); + return TCL_ERROR; + } + pCur = sqlite3TestTextToPtr(argv[1]); + if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR; + sqlite3BtreeEnter(pCur->pBtree); + sqlite3BtreeDataSize(pCur, &nData); + zBuf = sqlite3BtreeDataFetch(pCur, &amt); + if( zBuf && amt>=n ){ + assert( nData<sizeof(zStatic) ); + if( n>0 ) nData = n; + memcpy(zStatic, zBuf, (int)nData); + zStatic[nData] = 0; + Tcl_AppendResult(interp, zStatic, 0); + } + sqlite3BtreeLeave(pCur->pBtree); + return TCL_OK; +} + +/* +** Usage: btree_payload_size ID +** +** Return the number of bytes of payload +*/ +static int btree_payload_size( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + BtCursor *pCur; + int n2; + u64 n1; + char zBuf[50]; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pCur = sqlite3TestTextToPtr(argv[1]); + sqlite3BtreeEnter(pCur->pBtree); + if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){ + n1 = 0; + }else{ + sqlite3BtreeKeySize(pCur, (i64*)&n1); + } + sqlite3BtreeDataSize(pCur, (u32*)&n2); + sqlite3BtreeLeave(pCur->pBtree); + sqlite3_snprintf(sizeof(zBuf),zBuf, "%d", (int)(n1+n2)); + Tcl_AppendResult(interp, zBuf, 0); + return SQLITE_OK; +} + +/* +** Usage: btree_cursor_info ID ?UP-CNT? +** +** Return integers containing information about the entry the +** cursor is pointing to: +** +** aResult[0] = The page number +** aResult[1] = The entry number +** aResult[2] = Total number of entries on this page +** aResult[3] = Cell size (local payload + header) +** aResult[4] = Number of free bytes on this page +** aResult[5] = Number of free blocks on the page +** aResult[6] = Total payload size (local + overflow) +** aResult[7] = Header size in bytes +** aResult[8] = Local payload size +** aResult[9] = Parent page number +** aResult[10]= Page number of the first overflow page +*/ +static int btree_cursor_info( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + BtCursor *pCur; + int rc; + int i, j; + int up; + int aResult[11]; + char zBuf[400]; + + if( argc!=2 && argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID ?UP-CNT?\"", 0); + return TCL_ERROR; + } + pCur = sqlite3TestTextToPtr(argv[1]); + if( argc==3 ){ + if( Tcl_GetInt(interp, argv[2], &up) ) return TCL_ERROR; + }else{ + up = 0; + } + sqlite3BtreeEnter(pCur->pBtree); + rc = sqlite3BtreeCursorInfo(pCur, aResult, up); + if( rc ){ + Tcl_AppendResult(interp, errorName(rc), 0); + sqlite3BtreeLeave(pCur->pBtree); + return TCL_ERROR; + } + j = 0; + for(i=0; i<sizeof(aResult)/sizeof(aResult[0]); i++){ + sqlite3_snprintf(40,&zBuf[j]," %d", aResult[i]); + j += strlen(&zBuf[j]); + } + sqlite3BtreeLeave(pCur->pBtree); + Tcl_AppendResult(interp, &zBuf[1], 0); + return SQLITE_OK; +} + +/* +** Copied from btree.c: +*/ +static u32 t4Get4byte(unsigned char *p){ + return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; +} + +/* +** btree_ovfl_info BTREE CURSOR +** +** Given a cursor, return the sequence of pages number that form the +** overflow pages for the data of the entry that the cursor is point +** to. +*/ +static int btree_ovfl_info( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Btree *pBt; + BtCursor *pCur; + Pager *pPager; + int rc; + int n; + int dataSize; + u32 pgno; + void *pPage; + int aResult[11]; + char zElem[100]; + Tcl_DString str; + + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " BTREE CURSOR", 0); + return TCL_ERROR; + } + pBt = sqlite3TestTextToPtr(argv[1]); + pCur = sqlite3TestTextToPtr(argv[2]); + if( (*(void**)pCur) != (void*)pBt ){ + Tcl_AppendResult(interp, "Cursor ", argv[2], " does not belong to btree ", + argv[1], 0); + return TCL_ERROR; + } + sqlite3BtreeEnter(pBt); + pPager = sqlite3BtreePager(pBt); + rc = sqlite3BtreeCursorInfo(pCur, aResult, 0); + if( rc ){ + Tcl_AppendResult(interp, errorName(rc), 0); + sqlite3BtreeLeave(pBt); + return TCL_ERROR; + } + dataSize = pBt->pBt->usableSize; + Tcl_DStringInit(&str); + n = aResult[6] - aResult[8]; + n = (n + dataSize - 1)/dataSize; + pgno = (u32)aResult[10]; + while( pgno && n-- ){ + DbPage *pDbPage; + sprintf(zElem, "%d", pgno); + Tcl_DStringAppendElement(&str, zElem); + if( sqlite3PagerGet(pPager, pgno, &pDbPage)!=SQLITE_OK ){ + Tcl_DStringFree(&str); + Tcl_AppendResult(interp, "unable to get page ", zElem, 0); + sqlite3BtreeLeave(pBt); + return TCL_ERROR; + } + pPage = sqlite3PagerGetData(pDbPage); + pgno = t4Get4byte((unsigned char*)pPage); + sqlite3PagerUnref(pDbPage); + } + sqlite3BtreeLeave(pBt); + Tcl_DStringResult(interp, &str); + return SQLITE_OK; +} + +/* +** The command is provided for the purpose of setting breakpoints. +** in regression test scripts. +** +** By setting a GDB breakpoint on this procedure and executing the +** btree_breakpoint command in a test script, we can stop GDB at +** the point in the script where the btree_breakpoint command is +** inserted. This is useful for debugging. +*/ +static int btree_breakpoint( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + return TCL_OK; +} + +/* +** usage: varint_test START MULTIPLIER COUNT INCREMENT +** +** This command tests the putVarint() and getVarint() +** routines, both for accuracy and for speed. +** +** An integer is written using putVarint() and read back with +** getVarint() and varified to be unchanged. This repeats COUNT +** times. The first integer is START*MULTIPLIER. Each iteration +** increases the integer by INCREMENT. +** +** This command returns nothing if it works. It returns an error message +** if something goes wrong. +*/ +static int btree_varint_test( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + u32 start, mult, count, incr; + u64 in, out; + int n1, n2, i, j; + unsigned char zBuf[100]; + if( argc!=5 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " START MULTIPLIER COUNT INCREMENT\"", 0); + return TCL_ERROR; + } + if( Tcl_GetInt(interp, argv[1], (int*)&start) ) return TCL_ERROR; + if( Tcl_GetInt(interp, argv[2], (int*)&mult) ) return TCL_ERROR; + if( Tcl_GetInt(interp, argv[3], (int*)&count) ) return TCL_ERROR; + if( Tcl_GetInt(interp, argv[4], (int*)&incr) ) return TCL_ERROR; + in = start; + in *= mult; + for(i=0; i<count; i++){ + char zErr[200]; + n1 = putVarint(zBuf, in); + if( n1>9 || n1<1 ){ + sprintf(zErr, "putVarint returned %d - should be between 1 and 9", n1); + Tcl_AppendResult(interp, zErr, 0); + return TCL_ERROR; + } + n2 = getVarint(zBuf, &out); + if( n1!=n2 ){ + sprintf(zErr, "putVarint returned %d and getVarint returned %d", n1, n2); + Tcl_AppendResult(interp, zErr, 0); + return TCL_ERROR; + } + if( in!=out ){ + sprintf(zErr, "Wrote 0x%016llx and got back 0x%016llx", in, out); + Tcl_AppendResult(interp, zErr, 0); + return TCL_ERROR; + } + if( (in & 0xffffffff)==in ){ + u32 out32; + n2 = getVarint32(zBuf, out32); + out = out32; + if( n1!=n2 ){ + sprintf(zErr, "putVarint returned %d and GetVarint32 returned %d", + n1, n2); + Tcl_AppendResult(interp, zErr, 0); + return TCL_ERROR; + } + if( in!=out ){ + sprintf(zErr, "Wrote 0x%016llx and got back 0x%016llx from GetVarint32", + in, out); + Tcl_AppendResult(interp, zErr, 0); + return TCL_ERROR; + } + } + + /* In order to get realistic timings, run getVarint 19 more times. + ** This is because getVarint is called about 20 times more often + ** than putVarint. + */ + for(j=0; j<19; j++){ + getVarint(zBuf, &out); + } + in += incr; + } + return TCL_OK; +} + +/* +** usage: btree_from_db DB-HANDLE +** +** This command returns the btree handle for the main database associated +** with the database-handle passed as the argument. Example usage: +** +** sqlite3 db test.db +** set bt [btree_from_db db] +*/ +static int btree_from_db( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + char zBuf[100]; + Tcl_CmdInfo info; + sqlite3 *db; + Btree *pBt; + int iDb = 0; + + if( argc!=2 && argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " DB-HANDLE ?N?\"", 0); + return TCL_ERROR; + } + + if( 1!=Tcl_GetCommandInfo(interp, argv[1], &info) ){ + Tcl_AppendResult(interp, "No such db-handle: \"", argv[1], "\"", 0); + return TCL_ERROR; + } + if( argc==3 ){ + iDb = atoi(argv[2]); + } + + db = *((sqlite3 **)info.objClientData); + assert( db ); + + pBt = db->aDb[iDb].pBt; + sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", pBt); + Tcl_SetResult(interp, zBuf, TCL_VOLATILE); + return TCL_OK; +} + + +/* +** usage: btree_set_cache_size ID NCACHE +** +** Set the size of the cache used by btree $ID. +*/ +static int btree_set_cache_size( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int nCache; + Btree *pBt; + + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " BT NCACHE\"", 0); + return TCL_ERROR; + } + pBt = sqlite3TestTextToPtr(argv[1]); + if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR; + + sqlite3_mutex_enter(pBt->db->mutex); + sqlite3BtreeEnter(pBt); + sqlite3BtreeSetCacheSize(pBt, nCache); + sqlite3BtreeLeave(pBt); + sqlite3_mutex_leave(pBt->db->mutex); + + return TCL_OK; +} + +/* +** Usage: btree_ismemdb ID +** +** Return true if the B-Tree is in-memory. +*/ +static int btree_ismemdb( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Btree *pBt; + int res; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + pBt = sqlite3TestTextToPtr(argv[1]); + sqlite3_mutex_enter(pBt->db->mutex); + sqlite3BtreeEnter(pBt); + res = sqlite3PagerIsMemdb(sqlite3BtreePager(pBt)); + sqlite3BtreeLeave(pBt); + sqlite3_mutex_leave(pBt->db->mutex); + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(res)); + return SQLITE_OK; +} + + +/* +** Register commands with the TCL interpreter. +*/ +int Sqlitetest3_Init(Tcl_Interp *interp){ + static struct { + char *zName; + Tcl_CmdProc *xProc; + } aCmd[] = { + { "btree_open", (Tcl_CmdProc*)btree_open }, + { "btree_close", (Tcl_CmdProc*)btree_close }, + { "btree_begin_transaction", (Tcl_CmdProc*)btree_begin_transaction }, + { "btree_commit", (Tcl_CmdProc*)btree_commit }, + { "btree_rollback", (Tcl_CmdProc*)btree_rollback }, + { "btree_create_table", (Tcl_CmdProc*)btree_create_table }, + { "btree_drop_table", (Tcl_CmdProc*)btree_drop_table }, + { "btree_clear_table", (Tcl_CmdProc*)btree_clear_table }, + { "btree_get_meta", (Tcl_CmdProc*)btree_get_meta }, + { "btree_update_meta", (Tcl_CmdProc*)btree_update_meta }, + { "btree_pager_stats", (Tcl_CmdProc*)btree_pager_stats }, + { "btree_cursor", (Tcl_CmdProc*)btree_cursor }, + { "btree_close_cursor", (Tcl_CmdProc*)btree_close_cursor }, + { "btree_move_to", (Tcl_CmdProc*)btree_move_to }, + { "btree_delete", (Tcl_CmdProc*)btree_delete }, + { "btree_next", (Tcl_CmdProc*)btree_next }, + { "btree_prev", (Tcl_CmdProc*)btree_prev }, + { "btree_eof", (Tcl_CmdProc*)btree_eof }, + { "btree_keysize", (Tcl_CmdProc*)btree_keysize }, + { "btree_key", (Tcl_CmdProc*)btree_key }, + { "btree_data", (Tcl_CmdProc*)btree_data }, + { "btree_fetch_key", (Tcl_CmdProc*)btree_fetch_key }, + { "btree_fetch_data", (Tcl_CmdProc*)btree_fetch_data }, + { "btree_payload_size", (Tcl_CmdProc*)btree_payload_size }, + { "btree_first", (Tcl_CmdProc*)btree_first }, + { "btree_last", (Tcl_CmdProc*)btree_last }, + { "btree_integrity_check", (Tcl_CmdProc*)btree_integrity_check }, + { "btree_breakpoint", (Tcl_CmdProc*)btree_breakpoint }, + { "btree_varint_test", (Tcl_CmdProc*)btree_varint_test }, + { "btree_begin_statement", (Tcl_CmdProc*)btree_begin_statement }, + { "btree_commit_statement", (Tcl_CmdProc*)btree_commit_statement }, + { "btree_rollback_statement", (Tcl_CmdProc*)btree_rollback_statement }, + { "btree_from_db", (Tcl_CmdProc*)btree_from_db }, + { "btree_set_cache_size", (Tcl_CmdProc*)btree_set_cache_size }, + { "btree_cursor_info", (Tcl_CmdProc*)btree_cursor_info }, + { "btree_ovfl_info", (Tcl_CmdProc*)btree_ovfl_info }, + { "btree_cursor_list", (Tcl_CmdProc*)btree_cursor_list }, + { "btree_ismemdb", (Tcl_CmdProc*)btree_ismemdb }, + }; + int i; + + for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ + Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); + } + + /* The btree_insert command is implemented using the tcl 'object' + ** interface, not the string interface like the other commands in this + ** file. This is so binary data can be inserted into btree tables. + */ + Tcl_CreateObjCommand(interp, "btree_insert", btree_insert, 0, 0); + return TCL_OK; +} diff --git a/third_party/sqlite/src/test4.c b/third_party/sqlite/src/test4.c new file mode 100755 index 0000000..de5d3a2 --- /dev/null +++ b/third_party/sqlite/src/test4.c @@ -0,0 +1,716 @@ +/* +** 2003 December 18 +** +** 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. +** +************************************************************************* +** Code for testing the the SQLite library in a multithreaded environment. +** +** $Id: test4.c,v 1.23 2008/07/28 19:34:54 drh Exp $ +*/ +#include "sqliteInt.h" +#include "tcl.h" +#if defined(SQLITE_OS_UNIX) && OS_UNIX==1 && SQLITE_THREADSAFE +#include <stdlib.h> +#include <string.h> +#include <pthread.h> +#include <sched.h> +#include <ctype.h> + +/* +** Each thread is controlled by an instance of the following +** structure. +*/ +typedef struct Thread Thread; +struct Thread { + /* The first group of fields are writable by the master and read-only + ** to the thread. */ + char *zFilename; /* Name of database file */ + void (*xOp)(Thread*); /* next operation to do */ + char *zArg; /* argument usable by xOp */ + int opnum; /* Operation number */ + int busy; /* True if this thread is in use */ + + /* The next group of fields are writable by the thread but read-only to the + ** master. */ + int completed; /* Number of operations completed */ + sqlite3 *db; /* Open database */ + sqlite3_stmt *pStmt; /* Pending operation */ + char *zErr; /* operation error */ + char *zStaticErr; /* Static error message */ + int rc; /* operation return code */ + int argc; /* number of columns in result */ + const char *argv[100]; /* result columns */ + const char *colv[100]; /* result column names */ +}; + +/* +** There can be as many as 26 threads running at once. Each is named +** by a capital letter: A, B, C, ..., Y, Z. +*/ +#define N_THREAD 26 +static Thread threadset[N_THREAD]; + + +/* +** The main loop for a thread. Threads use busy waiting. +*/ +static void *thread_main(void *pArg){ + Thread *p = (Thread*)pArg; + if( p->db ){ + sqlite3_close(p->db); + } + sqlite3_open(p->zFilename, &p->db); + if( SQLITE_OK!=sqlite3_errcode(p->db) ){ + p->zErr = strdup(sqlite3_errmsg(p->db)); + sqlite3_close(p->db); + p->db = 0; + } + p->pStmt = 0; + p->completed = 1; + while( p->opnum<=p->completed ) sched_yield(); + while( p->xOp ){ + if( p->zErr && p->zErr!=p->zStaticErr ){ + sqlite3_free(p->zErr); + p->zErr = 0; + } + (*p->xOp)(p); + p->completed++; + while( p->opnum<=p->completed ) sched_yield(); + } + if( p->pStmt ){ + sqlite3_finalize(p->pStmt); + p->pStmt = 0; + } + if( p->db ){ + sqlite3_close(p->db); + p->db = 0; + } + if( p->zErr && p->zErr!=p->zStaticErr ){ + sqlite3_free(p->zErr); + p->zErr = 0; + } + p->completed++; + sqlite3_thread_cleanup(); + return 0; +} + +/* +** Get a thread ID which is an upper case letter. Return the index. +** If the argument is not a valid thread ID put an error message in +** the interpreter and return -1. +*/ +static int parse_thread_id(Tcl_Interp *interp, const char *zArg){ + if( zArg==0 || zArg[0]==0 || zArg[1]!=0 || !isupper((unsigned char)zArg[0]) ){ + Tcl_AppendResult(interp, "thread ID must be an upper case letter", 0); + return -1; + } + return zArg[0] - 'A'; +} + +/* +** Usage: thread_create NAME FILENAME +** +** NAME should be an upper case letter. Start the thread running with +** an open connection to the given database. +*/ +static int tcl_thread_create( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i; + pthread_t x; + int rc; + + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID FILENAME", 0); + return TCL_ERROR; + } + i = parse_thread_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( threadset[i].busy ){ + Tcl_AppendResult(interp, "thread ", argv[1], " is already running", 0); + return TCL_ERROR; + } + threadset[i].busy = 1; + sqlite3_free(threadset[i].zFilename); + threadset[i].zFilename = sqlite3DbStrDup(0, argv[2]); + threadset[i].opnum = 1; + threadset[i].completed = 0; + rc = pthread_create(&x, 0, thread_main, &threadset[i]); + if( rc ){ + Tcl_AppendResult(interp, "failed to create the thread", 0); + sqlite3_free(threadset[i].zFilename); + threadset[i].busy = 0; + return TCL_ERROR; + } + pthread_detach(x); + return TCL_OK; +} + +/* +** Wait for a thread to reach its idle state. +*/ +static void thread_wait(Thread *p){ + while( p->opnum>p->completed ) sched_yield(); +} + +/* +** Usage: thread_wait ID +** +** Wait on thread ID to reach its idle state. +*/ +static int tcl_thread_wait( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID", 0); + return TCL_ERROR; + } + i = parse_thread_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( !threadset[i].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + thread_wait(&threadset[i]); + return TCL_OK; +} + +/* +** Stop a thread. +*/ +static void stop_thread(Thread *p){ + thread_wait(p); + p->xOp = 0; + p->opnum++; + thread_wait(p); + sqlite3_free(p->zArg); + p->zArg = 0; + sqlite3_free(p->zFilename); + p->zFilename = 0; + p->busy = 0; +} + +/* +** Usage: thread_halt ID +** +** Cause a thread to shut itself down. Wait for the shutdown to be +** completed. If ID is "*" then stop all threads. +*/ +static int tcl_thread_halt( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID", 0); + return TCL_ERROR; + } + if( argv[1][0]=='*' && argv[1][1]==0 ){ + for(i=0; i<N_THREAD; i++){ + if( threadset[i].busy ) stop_thread(&threadset[i]); + } + }else{ + i = parse_thread_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( !threadset[i].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + stop_thread(&threadset[i]); + } + return TCL_OK; +} + +/* +** Usage: thread_argc ID +** +** Wait on the most recent thread_step to complete, then return the +** number of columns in the result set. +*/ +static int tcl_thread_argc( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i; + char zBuf[100]; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID", 0); + return TCL_ERROR; + } + i = parse_thread_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( !threadset[i].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + thread_wait(&threadset[i]); + sprintf(zBuf, "%d", threadset[i].argc); + Tcl_AppendResult(interp, zBuf, 0); + return TCL_OK; +} + +/* +** Usage: thread_argv ID N +** +** Wait on the most recent thread_step to complete, then return the +** value of the N-th columns in the result set. +*/ +static int tcl_thread_argv( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i; + int n; + + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID N", 0); + return TCL_ERROR; + } + i = parse_thread_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( !threadset[i].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR; + thread_wait(&threadset[i]); + if( n<0 || n>=threadset[i].argc ){ + Tcl_AppendResult(interp, "column number out of range", 0); + return TCL_ERROR; + } + Tcl_AppendResult(interp, threadset[i].argv[n], 0); + return TCL_OK; +} + +/* +** Usage: thread_colname ID N +** +** Wait on the most recent thread_step to complete, then return the +** name of the N-th columns in the result set. +*/ +static int tcl_thread_colname( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i; + int n; + + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID N", 0); + return TCL_ERROR; + } + i = parse_thread_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( !threadset[i].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR; + thread_wait(&threadset[i]); + if( n<0 || n>=threadset[i].argc ){ + Tcl_AppendResult(interp, "column number out of range", 0); + return TCL_ERROR; + } + Tcl_AppendResult(interp, threadset[i].colv[n], 0); + return TCL_OK; +} + +/* +** Usage: thread_result ID +** +** Wait on the most recent operation to complete, then return the +** result code from that operation. +*/ +static int tcl_thread_result( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i; + const char *zName; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID", 0); + return TCL_ERROR; + } + i = parse_thread_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( !threadset[i].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + thread_wait(&threadset[i]); + switch( threadset[i].rc ){ + case SQLITE_OK: zName = "SQLITE_OK"; break; + case SQLITE_ERROR: zName = "SQLITE_ERROR"; break; + case SQLITE_PERM: zName = "SQLITE_PERM"; break; + case SQLITE_ABORT: zName = "SQLITE_ABORT"; break; + case SQLITE_BUSY: zName = "SQLITE_BUSY"; break; + case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break; + case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break; + case SQLITE_READONLY: zName = "SQLITE_READONLY"; break; + case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break; + case SQLITE_IOERR: zName = "SQLITE_IOERR"; break; + case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break; + case SQLITE_FULL: zName = "SQLITE_FULL"; break; + case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break; + case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break; + case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break; + case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break; + case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break; + case SQLITE_MISMATCH: zName = "SQLITE_MISMATCH"; break; + case SQLITE_MISUSE: zName = "SQLITE_MISUSE"; break; + case SQLITE_NOLFS: zName = "SQLITE_NOLFS"; break; + case SQLITE_AUTH: zName = "SQLITE_AUTH"; break; + case SQLITE_FORMAT: zName = "SQLITE_FORMAT"; break; + case SQLITE_RANGE: zName = "SQLITE_RANGE"; break; + case SQLITE_ROW: zName = "SQLITE_ROW"; break; + case SQLITE_DONE: zName = "SQLITE_DONE"; break; + default: zName = "SQLITE_Unknown"; break; + } + Tcl_AppendResult(interp, zName, 0); + return TCL_OK; +} + +/* +** Usage: thread_error ID +** +** Wait on the most recent operation to complete, then return the +** error string. +*/ +static int tcl_thread_error( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID", 0); + return TCL_ERROR; + } + i = parse_thread_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( !threadset[i].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + thread_wait(&threadset[i]); + Tcl_AppendResult(interp, threadset[i].zErr, 0); + return TCL_OK; +} + +/* +** This procedure runs in the thread to compile an SQL statement. +*/ +static void do_compile(Thread *p){ + if( p->db==0 ){ + p->zErr = p->zStaticErr = "no database is open"; + p->rc = SQLITE_ERROR; + return; + } + if( p->pStmt ){ + sqlite3_finalize(p->pStmt); + p->pStmt = 0; + } + p->rc = sqlite3_prepare(p->db, p->zArg, -1, &p->pStmt, 0); +} + +/* +** Usage: thread_compile ID SQL +** +** Compile a new virtual machine. +*/ +static int tcl_thread_compile( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID SQL", 0); + return TCL_ERROR; + } + i = parse_thread_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( !threadset[i].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + thread_wait(&threadset[i]); + threadset[i].xOp = do_compile; + sqlite3_free(threadset[i].zArg); + threadset[i].zArg = sqlite3DbStrDup(0, argv[2]); + threadset[i].opnum++; + return TCL_OK; +} + +/* +** This procedure runs in the thread to step the virtual machine. +*/ +static void do_step(Thread *p){ + int i; + if( p->pStmt==0 ){ + p->zErr = p->zStaticErr = "no virtual machine available"; + p->rc = SQLITE_ERROR; + return; + } + p->rc = sqlite3_step(p->pStmt); + if( p->rc==SQLITE_ROW ){ + p->argc = sqlite3_column_count(p->pStmt); + for(i=0; i<sqlite3_data_count(p->pStmt); i++){ + p->argv[i] = (char*)sqlite3_column_text(p->pStmt, i); + } + for(i=0; i<p->argc; i++){ + p->colv[i] = sqlite3_column_name(p->pStmt, i); + } + } +} + +/* +** Usage: thread_step ID +** +** Advance the virtual machine by one step +*/ +static int tcl_thread_step( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " IDL", 0); + return TCL_ERROR; + } + i = parse_thread_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( !threadset[i].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + thread_wait(&threadset[i]); + threadset[i].xOp = do_step; + threadset[i].opnum++; + return TCL_OK; +} + +/* +** This procedure runs in the thread to finalize a virtual machine. +*/ +static void do_finalize(Thread *p){ + if( p->pStmt==0 ){ + p->zErr = p->zStaticErr = "no virtual machine available"; + p->rc = SQLITE_ERROR; + return; + } + p->rc = sqlite3_finalize(p->pStmt); + p->pStmt = 0; +} + +/* +** Usage: thread_finalize ID +** +** Finalize the virtual machine. +*/ +static int tcl_thread_finalize( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " IDL", 0); + return TCL_ERROR; + } + i = parse_thread_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( !threadset[i].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + thread_wait(&threadset[i]); + threadset[i].xOp = do_finalize; + sqlite3_free(threadset[i].zArg); + threadset[i].zArg = 0; + threadset[i].opnum++; + return TCL_OK; +} + +/* +** Usage: thread_swap ID ID +** +** Interchange the sqlite* pointer between two threads. +*/ +static int tcl_thread_swap( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i, j; + sqlite3 *temp; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID1 ID2", 0); + return TCL_ERROR; + } + i = parse_thread_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( !threadset[i].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + thread_wait(&threadset[i]); + j = parse_thread_id(interp, argv[2]); + if( j<0 ) return TCL_ERROR; + if( !threadset[j].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + thread_wait(&threadset[j]); + temp = threadset[i].db; + threadset[i].db = threadset[j].db; + threadset[j].db = temp; + return TCL_OK; +} + +/* +** Usage: thread_db_get ID +** +** Return the database connection pointer for the given thread. Then +** remove the pointer from the thread itself. Afterwards, the thread +** can be stopped and the connection can be used by the main thread. +*/ +static int tcl_thread_db_get( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i; + char zBuf[100]; + extern int sqlite3TestMakePointerStr(Tcl_Interp*, char*, void*); + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID", 0); + return TCL_ERROR; + } + i = parse_thread_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( !threadset[i].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + thread_wait(&threadset[i]); + sqlite3TestMakePointerStr(interp, zBuf, threadset[i].db); + threadset[i].db = 0; + Tcl_AppendResult(interp, zBuf, (char*)0); + return TCL_OK; +} + +/* +** Usage: thread_stmt_get ID +** +** Return the database stmt pointer for the given thread. Then +** remove the pointer from the thread itself. +*/ +static int tcl_thread_stmt_get( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i; + char zBuf[100]; + extern int sqlite3TestMakePointerStr(Tcl_Interp*, char*, void*); + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID", 0); + return TCL_ERROR; + } + i = parse_thread_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( !threadset[i].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + thread_wait(&threadset[i]); + sqlite3TestMakePointerStr(interp, zBuf, threadset[i].pStmt); + threadset[i].pStmt = 0; + Tcl_AppendResult(interp, zBuf, (char*)0); + return TCL_OK; +} + +/* +** Register commands with the TCL interpreter. +*/ +int Sqlitetest4_Init(Tcl_Interp *interp){ + static struct { + char *zName; + Tcl_CmdProc *xProc; + } aCmd[] = { + { "thread_create", (Tcl_CmdProc*)tcl_thread_create }, + { "thread_wait", (Tcl_CmdProc*)tcl_thread_wait }, + { "thread_halt", (Tcl_CmdProc*)tcl_thread_halt }, + { "thread_argc", (Tcl_CmdProc*)tcl_thread_argc }, + { "thread_argv", (Tcl_CmdProc*)tcl_thread_argv }, + { "thread_colname", (Tcl_CmdProc*)tcl_thread_colname }, + { "thread_result", (Tcl_CmdProc*)tcl_thread_result }, + { "thread_error", (Tcl_CmdProc*)tcl_thread_error }, + { "thread_compile", (Tcl_CmdProc*)tcl_thread_compile }, + { "thread_step", (Tcl_CmdProc*)tcl_thread_step }, + { "thread_finalize", (Tcl_CmdProc*)tcl_thread_finalize }, + { "thread_swap", (Tcl_CmdProc*)tcl_thread_swap }, + { "thread_db_get", (Tcl_CmdProc*)tcl_thread_db_get }, + { "thread_stmt_get", (Tcl_CmdProc*)tcl_thread_stmt_get }, + }; + int i; + + for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ + Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); + } + return TCL_OK; +} +#else +int Sqlitetest4_Init(Tcl_Interp *interp){ return TCL_OK; } +#endif /* SQLITE_OS_UNIX */ diff --git a/third_party/sqlite/src/test5.c b/third_party/sqlite/src/test5.c new file mode 100755 index 0000000..cbb8840 --- /dev/null +++ b/third_party/sqlite/src/test5.c @@ -0,0 +1,217 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** Code for testing the utf.c module in SQLite. This code +** is not included in the SQLite library. It is used for automated +** testing of the SQLite library. Specifically, the code in this file +** is used for testing the SQLite routines for converting between +** the various supported unicode encodings. +** +** $Id: test5.c,v 1.21 2008/07/28 19:34:54 drh Exp $ +*/ +#include "sqliteInt.h" +#include "vdbeInt.h" +#include "tcl.h" +#include <stdlib.h> +#include <string.h> + +/* +** The first argument is a TCL UTF-8 string. Return the byte array +** object with the encoded representation of the string, including +** the NULL terminator. +*/ +static int binarize( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int len; + char *bytes; + Tcl_Obj *pRet; + assert(objc==2); + + bytes = Tcl_GetStringFromObj(objv[1], &len); + pRet = Tcl_NewByteArrayObj((u8*)bytes, len+1); + Tcl_SetObjResult(interp, pRet); + return TCL_OK; +} + +/* +** Usage: test_value_overhead <repeat-count> <do-calls>. +** +** This routine is used to test the overhead of calls to +** sqlite3_value_text(), on a value that contains a UTF-8 string. The idea +** is to figure out whether or not it is a problem to use sqlite3_value +** structures with collation sequence functions. +** +** If <do-calls> is 0, then the calls to sqlite3_value_text() are not +** actually made. +*/ +static int test_value_overhead( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int do_calls; + int repeat_count; + int i; + Mem val; + const char *zVal; + + if( objc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), " <repeat-count> <do-calls>", 0); + return TCL_ERROR; + } + + if( Tcl_GetIntFromObj(interp, objv[1], &repeat_count) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &do_calls) ) return TCL_ERROR; + + val.flags = MEM_Str|MEM_Term|MEM_Static; + val.z = "hello world"; + val.type = SQLITE_TEXT; + val.enc = SQLITE_UTF8; + + for(i=0; i<repeat_count; i++){ + if( do_calls ){ + zVal = (char*)sqlite3_value_text(&val); + } + } + + return TCL_OK; +} + +static u8 name_to_enc(Tcl_Interp *interp, Tcl_Obj *pObj){ + struct EncName { + char *zName; + u8 enc; + } encnames[] = { + { "UTF8", SQLITE_UTF8 }, + { "UTF16LE", SQLITE_UTF16LE }, + { "UTF16BE", SQLITE_UTF16BE }, + { "UTF16", SQLITE_UTF16NATIVE }, + { 0, 0 } + }; + struct EncName *pEnc; + char *z = Tcl_GetString(pObj); + for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ + if( 0==sqlite3StrICmp(z, pEnc->zName) ){ + break; + } + } + if( !pEnc->enc ){ + Tcl_AppendResult(interp, "No such encoding: ", z, 0); + } + return pEnc->enc; +} + +/* +** Usage: test_translate <string/blob> <from enc> <to enc> ?<transient>? +** +*/ +static int test_translate( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + u8 enc_from; + u8 enc_to; + sqlite3_value *pVal; + + char *z; + int len; + void (*xDel)(void *p) = SQLITE_STATIC; + + if( objc!=4 && objc!=5 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), + " <string/blob> <from enc> <to enc>", 0 + ); + return TCL_ERROR; + } + if( objc==5 ){ + xDel = sqlite3_free; + } + + enc_from = name_to_enc(interp, objv[2]); + if( !enc_from ) return TCL_ERROR; + enc_to = name_to_enc(interp, objv[3]); + if( !enc_to ) return TCL_ERROR; + + pVal = sqlite3ValueNew(0); + + if( enc_from==SQLITE_UTF8 ){ + z = Tcl_GetString(objv[1]); + if( objc==5 ){ + z = sqlite3DbStrDup(0, z); + } + sqlite3ValueSetStr(pVal, -1, z, enc_from, xDel); + }else{ + z = (char*)Tcl_GetByteArrayFromObj(objv[1], &len); + if( objc==5 ){ + char *zTmp = z; + z = sqlite3_malloc(len); + memcpy(z, zTmp, len); + } + sqlite3ValueSetStr(pVal, -1, z, enc_from, xDel); + } + + z = (char *)sqlite3ValueText(pVal, enc_to); + len = sqlite3ValueBytes(pVal, enc_to) + (enc_to==SQLITE_UTF8?1:2); + Tcl_SetObjResult(interp, Tcl_NewByteArrayObj((u8*)z, len)); + + sqlite3ValueFree(pVal); + + return TCL_OK; +} + +/* +** Usage: translate_selftest +** +** Call sqlite3UtfSelfTest() to run the internal tests for unicode +** translation. If there is a problem an assert() will fail. +**/ +void sqlite3UtfSelfTest(); +static int test_translate_selftest( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ +#ifndef SQLITE_OMIT_UTF16 + sqlite3UtfSelfTest(); +#endif + return SQLITE_OK; +} + + +/* +** Register commands with the TCL interpreter. +*/ +int Sqlitetest5_Init(Tcl_Interp *interp){ + static struct { + char *zName; + Tcl_ObjCmdProc *xProc; + } aCmd[] = { + { "binarize", (Tcl_ObjCmdProc*)binarize }, + { "test_value_overhead", (Tcl_ObjCmdProc*)test_value_overhead }, + { "test_translate", (Tcl_ObjCmdProc*)test_translate }, + { "translate_selftest", (Tcl_ObjCmdProc*)test_translate_selftest}, + }; + int i; + for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ + Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); + } + return SQLITE_OK; +} diff --git a/third_party/sqlite/src/test6.c b/third_party/sqlite/src/test6.c new file mode 100755 index 0000000..8805cb8 --- /dev/null +++ b/third_party/sqlite/src/test6.c @@ -0,0 +1,881 @@ +/* +** 2004 May 22 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains code that modified the OS layer in order to simulate +** the effect on the database file of an OS crash or power failure. This +** is used to test the ability of SQLite to recover from those situations. +** +** $Id: test6.c,v 1.39 2008/06/06 11:11:26 danielk1977 Exp $ +*/ +#if SQLITE_TEST /* This file is used for testing only */ +#include "sqliteInt.h" +#include "tcl.h" + +#ifndef SQLITE_OMIT_DISKIO /* This file is a no-op if disk I/O is disabled */ + +/* #define TRACE_CRASHTEST */ + +typedef struct CrashFile CrashFile; +typedef struct CrashGlobal CrashGlobal; +typedef struct WriteBuffer WriteBuffer; + +/* +** Method: +** +** This layer is implemented as a wrapper around the "real" +** sqlite3_file object for the host system. Each time data is +** written to the file object, instead of being written to the +** underlying file, the write operation is stored in an in-memory +** structure (type WriteBuffer). This structure is placed at the +** end of a global ordered list (the write-list). +** +** When data is read from a file object, the requested region is +** first retrieved from the real file. The write-list is then +** traversed and data copied from any overlapping WriteBuffer +** structures to the output buffer. i.e. a read() operation following +** one or more write() operations works as expected, even if no +** data has actually been written out to the real file. +** +** When a fsync() operation is performed, an operating system crash +** may be simulated, in which case exit(-1) is called (the call to +** xSync() never returns). Whether or not a crash is simulated, +** the data associated with a subset of the WriteBuffer structures +** stored in the write-list is written to the real underlying files +** and the entries removed from the write-list. If a crash is simulated, +** a subset of the buffers may be corrupted before the data is written. +** +** The exact subset of the write-list written and/or corrupted is +** determined by the simulated device characteristics and sector-size. +** +** "Normal" mode: +** +** Normal mode is used when the simulated device has none of the +** SQLITE_IOCAP_XXX flags set. +** +** In normal mode, if the fsync() is not a simulated crash, the +** write-list is traversed from beginning to end. Each WriteBuffer +** structure associated with the file handle used to call xSync() +** is written to the real file and removed from the write-list. +** +** If a crash is simulated, one of the following takes place for +** each WriteBuffer in the write-list, regardless of which +** file-handle it is associated with: +** +** 1. The buffer is correctly written to the file, just as if +** a crash were not being simulated. +** +** 2. Nothing is done. +** +** 3. Garbage data is written to all sectors of the file that +** overlap the region specified by the WriteBuffer. Or garbage +** data is written to some contiguous section within the +** overlapped sectors. +** +** Device Characteristic flag handling: +** +** If the IOCAP_ATOMIC flag is set, then option (3) above is +** never selected. +** +** If the IOCAP_ATOMIC512 flag is set, and the WriteBuffer represents +** an aligned write() of an integer number of 512 byte regions, then +** option (3) above is never selected. Instead, each 512 byte region +** is either correctly written or left completely untouched. Similar +** logic governs the behaviour if any of the other ATOMICXXX flags +** is set. +** +** If either the IOCAP_SAFEAPPEND or IOCAP_SEQUENTIAL flags are set +** and a crash is being simulated, then an entry of the write-list is +** selected at random. Everything in the list after the selected entry +** is discarded before processing begins. +** +** If IOCAP_SEQUENTIAL is set and a crash is being simulated, option +** (1) is selected for all write-list entries except the last. If a +** crash is not being simulated, then all entries in the write-list +** that occur before at least one write() on the file-handle specified +** as part of the xSync() are written to their associated real files. +** +** If IOCAP_SAFEAPPEND is set and the first byte written by the write() +** operation is one byte past the current end of the file, then option +** (1) is always selected. +*/ + +/* +** Each write operation in the write-list is represented by an instance +** of the following structure. +** +** If zBuf is 0, then this structure represents a call to xTruncate(), +** not xWrite(). In that case, iOffset is the size that the file is +** truncated to. +*/ +struct WriteBuffer { + i64 iOffset; /* Byte offset of the start of this write() */ + int nBuf; /* Number of bytes written */ + u8 *zBuf; /* Pointer to copy of written data */ + CrashFile *pFile; /* File this write() applies to */ + + WriteBuffer *pNext; /* Next in CrashGlobal.pWriteList */ +}; + +struct CrashFile { + const sqlite3_io_methods *pMethod; /* Must be first */ + sqlite3_file *pRealFile; /* Underlying "real" file handle */ + char *zName; + + /* Cache of the entire file. This is used to speed up OsRead() and + ** OsFileSize() calls. Although both could be done by traversing the + ** write-list, in practice this is impractically slow. + */ + int iSize; /* Size of file in bytes */ + int nData; /* Size of buffer allocated at zData */ + u8 *zData; /* Buffer containing file contents */ +}; + +struct CrashGlobal { + WriteBuffer *pWriteList; /* Head of write-list */ + WriteBuffer *pWriteListEnd; /* End of write-list */ + + int iSectorSize; /* Value of simulated sector size */ + int iDeviceCharacteristics; /* Value of simulated device characteristics */ + + int iCrash; /* Crash on the iCrash'th call to xSync() */ + char zCrashFile[500]; /* Crash during an xSync() on this file */ +}; + +static CrashGlobal g = {0, 0, SQLITE_DEFAULT_SECTOR_SIZE, 0, 0}; + +/* +** Set this global variable to 1 to enable crash testing. +*/ +static int sqlite3CrashTestEnable = 0; + +static void *crash_malloc(int nByte){ + return (void *)Tcl_Alloc((size_t)nByte); +} +static void crash_free(void *p){ + Tcl_Free(p); +} +static void *crash_realloc(void *p, int n){ + return (void *)Tcl_Realloc(p, (size_t)n); +} + +/* +** Flush the write-list as if xSync() had been called on file handle +** pFile. If isCrash is true, simulate a crash. +*/ +static int writeListSync(CrashFile *pFile, int isCrash){ + int rc = SQLITE_OK; + int iDc = g.iDeviceCharacteristics; + + WriteBuffer *pWrite; + WriteBuffer **ppPtr; + + /* If this is not a crash simulation, set pFinal to point to the + ** last element of the write-list that is associated with file handle + ** pFile. + ** + ** If this is a crash simulation, set pFinal to an arbitrarily selected + ** element of the write-list. + */ + WriteBuffer *pFinal = 0; + if( !isCrash ){ + for(pWrite=g.pWriteList; pWrite; pWrite=pWrite->pNext){ + if( pWrite->pFile==pFile ){ + pFinal = pWrite; + } + } + }else if( iDc&(SQLITE_IOCAP_SEQUENTIAL|SQLITE_IOCAP_SAFE_APPEND) ){ + int nWrite = 0; + int iFinal; + for(pWrite=g.pWriteList; pWrite; pWrite=pWrite->pNext) nWrite++; + sqlite3_randomness(sizeof(int), &iFinal); + iFinal = ((iFinal<0)?-1*iFinal:iFinal)%nWrite; + for(pWrite=g.pWriteList; iFinal>0; pWrite=pWrite->pNext) iFinal--; + pFinal = pWrite; + } + +#ifdef TRACE_CRASHTEST + printf("Sync %s (is %s crash)\n", pFile->zName, (isCrash?"a":"not a")); +#endif + + ppPtr = &g.pWriteList; + for(pWrite=*ppPtr; rc==SQLITE_OK && pWrite; pWrite=*ppPtr){ + sqlite3_file *pRealFile = pWrite->pFile->pRealFile; + + /* (eAction==1) -> write block out normally, + ** (eAction==2) -> do nothing, + ** (eAction==3) -> trash sectors. + */ + int eAction = 0; + if( !isCrash ){ + eAction = 2; + if( (pWrite->pFile==pFile || iDc&SQLITE_IOCAP_SEQUENTIAL) ){ + eAction = 1; + } + }else{ + char random; + sqlite3_randomness(1, &random); + + /* Do not select option 3 (sector trashing) if the IOCAP_ATOMIC flag + ** is set or this is an OsTruncate(), not an Oswrite(). + */ + if( (iDc&SQLITE_IOCAP_ATOMIC) || (pWrite->zBuf==0) ){ + random &= 0x01; + } + + /* If IOCAP_SEQUENTIAL is set and this is not the final entry + ** in the truncated write-list, always select option 1 (write + ** out correctly). + */ + if( (iDc&SQLITE_IOCAP_SEQUENTIAL && pWrite!=pFinal) ){ + random = 0; + } + + /* If IOCAP_SAFE_APPEND is set and this OsWrite() operation is + ** an append (first byte of the written region is 1 byte past the + ** current EOF), always select option 1 (write out correctly). + */ + if( iDc&SQLITE_IOCAP_SAFE_APPEND && pWrite->zBuf ){ + i64 iSize; + sqlite3OsFileSize(pRealFile, &iSize); + if( iSize==pWrite->iOffset ){ + random = 0; + } + } + + if( (random&0x06)==0x06 ){ + eAction = 3; + }else{ + eAction = ((random&0x01)?2:1); + } + } + + switch( eAction ){ + case 1: { /* Write out correctly */ + if( pWrite->zBuf ){ + rc = sqlite3OsWrite( + pRealFile, pWrite->zBuf, pWrite->nBuf, pWrite->iOffset + ); + }else{ + rc = sqlite3OsTruncate(pRealFile, pWrite->iOffset); + } + *ppPtr = pWrite->pNext; +#ifdef TRACE_CRASHTEST + if( isCrash ){ + printf("Writing %d bytes @ %d (%s)\n", + pWrite->nBuf, (int)pWrite->iOffset, pWrite->pFile->zName + ); + } +#endif + crash_free(pWrite); + break; + } + case 2: { /* Do nothing */ + ppPtr = &pWrite->pNext; +#ifdef TRACE_CRASHTEST + if( isCrash ){ + printf("Omiting %d bytes @ %d (%s)\n", + pWrite->nBuf, (int)pWrite->iOffset, pWrite->pFile->zName + ); + } +#endif + break; + } + case 3: { /* Trash sectors */ + u8 *zGarbage; + int iFirst = (pWrite->iOffset/g.iSectorSize); + int iLast = (pWrite->iOffset+pWrite->nBuf-1)/g.iSectorSize; + + assert(pWrite->zBuf); + +#ifdef TRACE_CRASHTEST + printf("Trashing %d sectors @ sector %d (%s)\n", + 1+iLast-iFirst, iFirst, pWrite->pFile->zName + ); +#endif + + zGarbage = crash_malloc(g.iSectorSize); + if( zGarbage ){ + sqlite3_int64 i; + for(i=iFirst; rc==SQLITE_OK && i<=iLast; i++){ + sqlite3_randomness(g.iSectorSize, zGarbage); + rc = sqlite3OsWrite( + pRealFile, zGarbage, g.iSectorSize, i*g.iSectorSize + ); + } + crash_free(zGarbage); + }else{ + rc = SQLITE_NOMEM; + } + + ppPtr = &pWrite->pNext; + break; + } + + default: + assert(!"Cannot happen"); + } + + if( pWrite==pFinal ) break; + } + + if( rc==SQLITE_OK && isCrash ){ + exit(-1); + } + + for(pWrite=g.pWriteList; pWrite && pWrite->pNext; pWrite=pWrite->pNext); + g.pWriteListEnd = pWrite; + + return rc; +} + +/* +** Add an entry to the end of the write-list. +*/ +static int writeListAppend( + sqlite3_file *pFile, + sqlite3_int64 iOffset, + const u8 *zBuf, + int nBuf +){ + WriteBuffer *pNew; + + assert((zBuf && nBuf) || (!nBuf && !zBuf)); + + pNew = (WriteBuffer *)crash_malloc(sizeof(WriteBuffer) + nBuf); + if( pNew==0 ){ + fprintf(stderr, "out of memory in the crash simulator\n"); + } + memset(pNew, 0, sizeof(WriteBuffer)+nBuf); + pNew->iOffset = iOffset; + pNew->nBuf = nBuf; + pNew->pFile = (CrashFile *)pFile; + if( zBuf ){ + pNew->zBuf = (u8 *)&pNew[1]; + memcpy(pNew->zBuf, zBuf, nBuf); + } + + if( g.pWriteList ){ + assert(g.pWriteListEnd); + g.pWriteListEnd->pNext = pNew; + }else{ + g.pWriteList = pNew; + } + g.pWriteListEnd = pNew; + + return SQLITE_OK; +} + +/* +** Close a crash-file. +*/ +static int cfClose(sqlite3_file *pFile){ + CrashFile *pCrash = (CrashFile *)pFile; + writeListSync(pCrash, 0); + sqlite3OsClose(pCrash->pRealFile); + return SQLITE_OK; +} + +/* +** Read data from a crash-file. +*/ +static int cfRead( + sqlite3_file *pFile, + void *zBuf, + int iAmt, + sqlite_int64 iOfst +){ + CrashFile *pCrash = (CrashFile *)pFile; + + /* Check the file-size to see if this is a short-read */ + if( pCrash->iSize<(iOfst+iAmt) ){ + return SQLITE_IOERR_SHORT_READ; + } + + memcpy(zBuf, &pCrash->zData[iOfst], iAmt); + return SQLITE_OK; +} + +/* +** Write data to a crash-file. +*/ +static int cfWrite( + sqlite3_file *pFile, + const void *zBuf, + int iAmt, + sqlite_int64 iOfst +){ + CrashFile *pCrash = (CrashFile *)pFile; + if( iAmt+iOfst>pCrash->iSize ){ + pCrash->iSize = iAmt+iOfst; + } + while( pCrash->iSize>pCrash->nData ){ + u8 *zNew; + int nNew = (pCrash->nData*2) + 4096; + zNew = crash_realloc(pCrash->zData, nNew); + if( !zNew ){ + return SQLITE_NOMEM; + } + memset(&zNew[pCrash->nData], 0, nNew-pCrash->nData); + pCrash->nData = nNew; + pCrash->zData = zNew; + } + memcpy(&pCrash->zData[iOfst], zBuf, iAmt); + return writeListAppend(pFile, iOfst, zBuf, iAmt); +} + +/* +** Truncate a crash-file. +*/ +static int cfTruncate(sqlite3_file *pFile, sqlite_int64 size){ + CrashFile *pCrash = (CrashFile *)pFile; + assert(size>=0); + if( pCrash->iSize>size ){ + pCrash->iSize = size; + } + return writeListAppend(pFile, size, 0, 0); +} + +/* +** Sync a crash-file. +*/ +static int cfSync(sqlite3_file *pFile, int flags){ + CrashFile *pCrash = (CrashFile *)pFile; + int isCrash = 0; + + const char *zName = pCrash->zName; + const char *zCrashFile = g.zCrashFile; + int nName = strlen(zName); + int nCrashFile = strlen(zCrashFile); + + if( nCrashFile>0 && zCrashFile[nCrashFile-1]=='*' ){ + nCrashFile--; + if( nName>nCrashFile ) nName = nCrashFile; + } + + if( nName==nCrashFile && 0==memcmp(zName, zCrashFile, nName) ){ + if( (--g.iCrash)==0 ) isCrash = 1; + } + + return writeListSync(pCrash, isCrash); +} + +/* +** Return the current file-size of the crash-file. +*/ +static int cfFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ + CrashFile *pCrash = (CrashFile *)pFile; + *pSize = (i64)pCrash->iSize; + return SQLITE_OK; +} + +/* +** Calls related to file-locks are passed on to the real file handle. +*/ +static int cfLock(sqlite3_file *pFile, int eLock){ + return sqlite3OsLock(((CrashFile *)pFile)->pRealFile, eLock); +} +static int cfUnlock(sqlite3_file *pFile, int eLock){ + return sqlite3OsUnlock(((CrashFile *)pFile)->pRealFile, eLock); +} +static int cfCheckReservedLock(sqlite3_file *pFile, int *pResOut){ + return sqlite3OsCheckReservedLock(((CrashFile *)pFile)->pRealFile, pResOut); +} +static int cfFileControl(sqlite3_file *pFile, int op, void *pArg){ + return sqlite3OsFileControl(((CrashFile *)pFile)->pRealFile, op, pArg); +} + +/* +** The xSectorSize() and xDeviceCharacteristics() functions return +** the global values configured by the [sqlite_crashparams] tcl +* interface. +*/ +static int cfSectorSize(sqlite3_file *pFile){ + return g.iSectorSize; +} +static int cfDeviceCharacteristics(sqlite3_file *pFile){ + return g.iDeviceCharacteristics; +} + +static const sqlite3_io_methods CrashFileVtab = { + 1, /* iVersion */ + cfClose, /* xClose */ + cfRead, /* xRead */ + cfWrite, /* xWrite */ + cfTruncate, /* xTruncate */ + cfSync, /* xSync */ + cfFileSize, /* xFileSize */ + cfLock, /* xLock */ + cfUnlock, /* xUnlock */ + cfCheckReservedLock, /* xCheckReservedLock */ + cfFileControl, /* xFileControl */ + cfSectorSize, /* xSectorSize */ + cfDeviceCharacteristics /* xDeviceCharacteristics */ +}; + +/* +** Application data for the crash VFS +*/ +struct crashAppData { + sqlite3_vfs *pOrig; /* Wrapped vfs structure */ +}; + +/* +** Open a crash-file file handle. +** +** The caller will have allocated pVfs->szOsFile bytes of space +** at pFile. This file uses this space for the CrashFile structure +** and allocates space for the "real" file structure using +** sqlite3_malloc(). The assumption here is (pVfs->szOsFile) is +** equal or greater than sizeof(CrashFile). +*/ +static int cfOpen( + sqlite3_vfs *pCfVfs, + const char *zName, + sqlite3_file *pFile, + int flags, + int *pOutFlags +){ + sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; + int rc; + CrashFile *pWrapper = (CrashFile *)pFile; + sqlite3_file *pReal = (sqlite3_file*)&pWrapper[1]; + + memset(pWrapper, 0, sizeof(CrashFile)); + rc = sqlite3OsOpen(pVfs, zName, pReal, flags, pOutFlags); + + if( rc==SQLITE_OK ){ + i64 iSize; + pWrapper->pMethod = &CrashFileVtab; + pWrapper->zName = (char *)zName; + pWrapper->pRealFile = pReal; + rc = sqlite3OsFileSize(pReal, &iSize); + pWrapper->iSize = (int)iSize; + } + if( rc==SQLITE_OK ){ + pWrapper->nData = (4096 + pWrapper->iSize); + pWrapper->zData = crash_malloc(pWrapper->nData); + if( pWrapper->zData ){ + memset(pWrapper->zData, 0, pWrapper->nData); + rc = sqlite3OsRead(pReal, pWrapper->zData, pWrapper->iSize, 0); + }else{ + rc = SQLITE_NOMEM; + } + } + if( rc!=SQLITE_OK && pWrapper->pMethod ){ + sqlite3OsClose(pFile); + } + return rc; +} + +static int cfDelete(sqlite3_vfs *pCfVfs, const char *zPath, int dirSync){ + sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; + return pVfs->xDelete(pVfs, zPath, dirSync); +} +static int cfAccess( + sqlite3_vfs *pCfVfs, + const char *zPath, + int flags, + int *pResOut +){ + sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; + return pVfs->xAccess(pVfs, zPath, flags, pResOut); +} +static int cfFullPathname( + sqlite3_vfs *pCfVfs, + const char *zPath, + int nPathOut, + char *zPathOut +){ + sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; + return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut); +} +static void *cfDlOpen(sqlite3_vfs *pCfVfs, const char *zPath){ + sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; + return pVfs->xDlOpen(pVfs, zPath); +} +static void cfDlError(sqlite3_vfs *pCfVfs, int nByte, char *zErrMsg){ + sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; + pVfs->xDlError(pVfs, nByte, zErrMsg); +} +static void *cfDlSym(sqlite3_vfs *pCfVfs, void *pHandle, const char *zSymbol){ + sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; + return pVfs->xDlSym(pVfs, pHandle, zSymbol); +} +static void cfDlClose(sqlite3_vfs *pCfVfs, void *pHandle){ + sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; + pVfs->xDlClose(pVfs, pHandle); +} +static int cfRandomness(sqlite3_vfs *pCfVfs, int nByte, char *zBufOut){ + sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; + return pVfs->xRandomness(pVfs, nByte, zBufOut); +} +static int cfSleep(sqlite3_vfs *pCfVfs, int nMicro){ + sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; + return pVfs->xSleep(pVfs, nMicro); +} +static int cfCurrentTime(sqlite3_vfs *pCfVfs, double *pTimeOut){ + sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; + return pVfs->xCurrentTime(pVfs, pTimeOut); +} + +static int processDevSymArgs( + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[], + int *piDeviceChar, + int *piSectorSize +){ + struct DeviceFlag { + char *zName; + int iValue; + } aFlag[] = { + { "atomic", SQLITE_IOCAP_ATOMIC }, + { "atomic512", SQLITE_IOCAP_ATOMIC512 }, + { "atomic1k", SQLITE_IOCAP_ATOMIC1K }, + { "atomic2k", SQLITE_IOCAP_ATOMIC2K }, + { "atomic4k", SQLITE_IOCAP_ATOMIC4K }, + { "atomic8k", SQLITE_IOCAP_ATOMIC8K }, + { "atomic16k", SQLITE_IOCAP_ATOMIC16K }, + { "atomic32k", SQLITE_IOCAP_ATOMIC32K }, + { "atomic64k", SQLITE_IOCAP_ATOMIC64K }, + { "sequential", SQLITE_IOCAP_SEQUENTIAL }, + { "safe_append", SQLITE_IOCAP_SAFE_APPEND }, + { 0, 0 } + }; + + int i; + int iDc = 0; + int iSectorSize = 0; + int setSectorsize = 0; + int setDeviceChar = 0; + + for(i=0; i<objc; i+=2){ + int nOpt; + char *zOpt = Tcl_GetStringFromObj(objv[i], &nOpt); + + if( (nOpt>11 || nOpt<2 || strncmp("-sectorsize", zOpt, nOpt)) + && (nOpt>16 || nOpt<2 || strncmp("-characteristics", zOpt, nOpt)) + ){ + Tcl_AppendResult(interp, + "Bad option: \"", zOpt, + "\" - must be \"-characteristics\" or \"-sectorsize\"", 0 + ); + return TCL_ERROR; + } + if( i==objc-1 ){ + Tcl_AppendResult(interp, "Option requires an argument: \"", zOpt, "\"",0); + return TCL_ERROR; + } + + if( zOpt[1]=='s' ){ + if( Tcl_GetIntFromObj(interp, objv[i+1], &iSectorSize) ){ + return TCL_ERROR; + } + setSectorsize = 1; + }else{ + int j; + Tcl_Obj **apObj; + int nObj; + if( Tcl_ListObjGetElements(interp, objv[i+1], &nObj, &apObj) ){ + return TCL_ERROR; + } + for(j=0; j<nObj; j++){ + int rc; + int iChoice; + Tcl_Obj *pFlag = Tcl_DuplicateObj(apObj[j]); + Tcl_IncrRefCount(pFlag); + Tcl_UtfToLower(Tcl_GetString(pFlag)); + + rc = Tcl_GetIndexFromObjStruct( + interp, pFlag, aFlag, sizeof(aFlag[0]), "no such flag", 0, &iChoice + ); + Tcl_DecrRefCount(pFlag); + if( rc ){ + return TCL_ERROR; + } + + iDc |= aFlag[iChoice].iValue; + } + setDeviceChar = 1; + } + } + + if( setDeviceChar ){ + *piDeviceChar = iDc; + } + if( setSectorsize ){ + *piSectorSize = iSectorSize; + } + + return TCL_OK; +} + +/* +** tclcmd: sqlite_crash_enable ENABLE +** +** Parameter ENABLE must be a boolean value. If true, then the "crash" +** vfs is added to the system. If false, it is removed. +*/ +static int crashEnableCmd( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int isEnable; + static sqlite3_vfs crashVfs = { + 1, /* iVersion */ + 0, /* szOsFile */ + 0, /* mxPathname */ + 0, /* pNext */ + "crash", /* zName */ + 0, /* pAppData */ + + cfOpen, /* xOpen */ + cfDelete, /* xDelete */ + cfAccess, /* xAccess */ + cfFullPathname, /* xFullPathname */ + cfDlOpen, /* xDlOpen */ + cfDlError, /* xDlError */ + cfDlSym, /* xDlSym */ + cfDlClose, /* xDlClose */ + cfRandomness, /* xRandomness */ + cfSleep, /* xSleep */ + cfCurrentTime /* xCurrentTime */ + }; + + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "ENABLE"); + return TCL_ERROR; + } + + if( Tcl_GetBooleanFromObj(interp, objv[1], &isEnable) ){ + return TCL_ERROR; + } + + if( (isEnable && crashVfs.pAppData) || (!isEnable && !crashVfs.pAppData) ){ + return TCL_OK; + } + + if( crashVfs.pAppData==0 ){ + sqlite3_vfs *pOriginalVfs = sqlite3_vfs_find(0); + crashVfs.mxPathname = pOriginalVfs->mxPathname; + crashVfs.pAppData = (void *)pOriginalVfs; + crashVfs.szOsFile = sizeof(CrashFile) + pOriginalVfs->szOsFile; + sqlite3_vfs_register(&crashVfs, 0); + }else{ + crashVfs.pAppData = 0; + sqlite3_vfs_unregister(&crashVfs); + } + + return TCL_OK; +} + +/* +** tclcmd: sqlite_crashparams ?OPTIONS? DELAY CRASHFILE +** +** This procedure implements a TCL command that enables crash testing +** in testfixture. Once enabled, crash testing cannot be disabled. +** +** Available options are "-characteristics" and "-sectorsize". Both require +** an argument. For -sectorsize, this is the simulated sector size in +** bytes. For -characteristics, the argument must be a list of io-capability +** flags to simulate. Valid flags are "atomic", "atomic512", "atomic1K", +** "atomic2K", "atomic4K", "atomic8K", "atomic16K", "atomic32K", +** "atomic64K", "sequential" and "safe_append". +** +** Example: +** +** sqlite_crashparams -sect 1024 -char {atomic sequential} ./test.db 1 +** +*/ +static int crashParamsObjCmd( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int iDelay; + const char *zCrashFile; + int nCrashFile, iDc, iSectorSize; + + iDc = -1; + iSectorSize = -1; + + if( objc<3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "?OPTIONS? DELAY CRASHFILE"); + goto error; + } + + zCrashFile = Tcl_GetStringFromObj(objv[objc-1], &nCrashFile); + if( nCrashFile>=sizeof(g.zCrashFile) ){ + Tcl_AppendResult(interp, "Filename is too long: \"", zCrashFile, "\"", 0); + goto error; + } + if( Tcl_GetIntFromObj(interp, objv[objc-2], &iDelay) ){ + goto error; + } + + if( processDevSymArgs(interp, objc-3, &objv[1], &iDc, &iSectorSize) ){ + return TCL_ERROR; + } + + if( iDc>=0 ){ + g.iDeviceCharacteristics = iDc; + } + if( iSectorSize>=0 ){ + g.iSectorSize = iSectorSize; + } + + g.iCrash = iDelay; + memcpy(g.zCrashFile, zCrashFile, nCrashFile+1); + sqlite3CrashTestEnable = 1; + return TCL_OK; + +error: + return TCL_ERROR; +} + +static int devSymObjCmd( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + void devsym_register(int iDeviceChar, int iSectorSize); + + int iDc = -1; + int iSectorSize = -1; + + if( processDevSymArgs(interp, objc-1, &objv[1], &iDc, &iSectorSize) ){ + return TCL_ERROR; + } + devsym_register(iDc, iSectorSize); + + return TCL_OK; +} + +#endif /* SQLITE_OMIT_DISKIO */ + +/* +** This procedure registers the TCL procedures defined in this file. +*/ +int Sqlitetest6_Init(Tcl_Interp *interp){ +#ifndef SQLITE_OMIT_DISKIO + Tcl_CreateObjCommand(interp, "sqlite3_crash_enable", crashEnableCmd, 0, 0); + Tcl_CreateObjCommand(interp, "sqlite3_crashparams", crashParamsObjCmd, 0, 0); + Tcl_CreateObjCommand(interp, "sqlite3_simulate_device", devSymObjCmd, 0, 0); +#endif + return TCL_OK; +} + +#endif /* SQLITE_TEST */ diff --git a/third_party/sqlite/src/test7.c b/third_party/sqlite/src/test7.c new file mode 100755 index 0000000..78754bf --- /dev/null +++ b/third_party/sqlite/src/test7.c @@ -0,0 +1,723 @@ +/* +** 2006 January 09 +** +** 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. +** +************************************************************************* +** Code for testing the client/server version of the SQLite library. +** Derived from test4.c. +** +** $Id: test7.c,v 1.12 2008/07/28 19:34:54 drh Exp $ +*/ +#include "sqliteInt.h" +#include "tcl.h" + +/* +** This test only works on UNIX with a SQLITE_THREADSAFE build that includes +** the SQLITE_SERVER option. +*/ +#if defined(SQLITE_SERVER) && !defined(SQLITE_OMIT_SHARED_CACHE) && \ + defined(SQLITE_OS_UNIX) && OS_UNIX && SQLITE_THREADSAFE + +#include <stdlib.h> +#include <string.h> +#include <pthread.h> +#include <sched.h> +#include <ctype.h> + +/* +** Interfaces defined in server.c +*/ +int sqlite3_client_open(const char*, sqlite3**); +int sqlite3_client_prepare(sqlite3*,const char*,int, + sqlite3_stmt**,const char**); +int sqlite3_client_step(sqlite3_stmt*); +int sqlite3_client_reset(sqlite3_stmt*); +int sqlite3_client_finalize(sqlite3_stmt*); +int sqlite3_client_close(sqlite3*); +int sqlite3_server_start(void); +int sqlite3_server_stop(void); + +/* +** Each thread is controlled by an instance of the following +** structure. +*/ +typedef struct Thread Thread; +struct Thread { + /* The first group of fields are writable by the supervisor thread + ** and read-only to the client threads + */ + char *zFilename; /* Name of database file */ + void (*xOp)(Thread*); /* next operation to do */ + char *zArg; /* argument usable by xOp */ + volatile int opnum; /* Operation number */ + volatile int busy; /* True if this thread is in use */ + + /* The next group of fields are writable by the client threads + ** but read-only to the superviser thread. + */ + volatile int completed; /* Number of operations completed */ + sqlite3 *db; /* Open database */ + sqlite3_stmt *pStmt; /* Pending operation */ + char *zErr; /* operation error */ + char *zStaticErr; /* Static error message */ + int rc; /* operation return code */ + int argc; /* number of columns in result */ + const char *argv[100]; /* result columns */ + const char *colv[100]; /* result column names */ +}; + +/* +** There can be as many as 26 threads running at once. Each is named +** by a capital letter: A, B, C, ..., Y, Z. +*/ +#define N_THREAD 26 +static Thread threadset[N_THREAD]; + +/* +** The main loop for a thread. Threads use busy waiting. +*/ +static void *client_main(void *pArg){ + Thread *p = (Thread*)pArg; + if( p->db ){ + sqlite3_client_close(p->db); + } + sqlite3_client_open(p->zFilename, &p->db); + if( SQLITE_OK!=sqlite3_errcode(p->db) ){ + p->zErr = strdup(sqlite3_errmsg(p->db)); + sqlite3_client_close(p->db); + p->db = 0; + } + p->pStmt = 0; + p->completed = 1; + while( p->opnum<=p->completed ) sched_yield(); + while( p->xOp ){ + if( p->zErr && p->zErr!=p->zStaticErr ){ + sqlite3_free(p->zErr); + p->zErr = 0; + } + (*p->xOp)(p); + p->completed++; + while( p->opnum<=p->completed ) sched_yield(); + } + if( p->pStmt ){ + sqlite3_client_finalize(p->pStmt); + p->pStmt = 0; + } + if( p->db ){ + sqlite3_client_close(p->db); + p->db = 0; + } + if( p->zErr && p->zErr!=p->zStaticErr ){ + sqlite3_free(p->zErr); + p->zErr = 0; + } + p->completed++; + sqlite3_thread_cleanup(); + return 0; +} + +/* +** Get a thread ID which is an upper case letter. Return the index. +** If the argument is not a valid thread ID put an error message in +** the interpreter and return -1. +*/ +static int parse_client_id(Tcl_Interp *interp, const char *zArg){ + if( zArg==0 || zArg[0]==0 || zArg[1]!=0 || !isupper((unsigned char)zArg[0]) ){ + Tcl_AppendResult(interp, "thread ID must be an upper case letter", 0); + return -1; + } + return zArg[0] - 'A'; +} + +/* +** Usage: client_create NAME FILENAME +** +** NAME should be an upper case letter. Start the thread running with +** an open connection to the given database. +*/ +static int tcl_client_create( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i; + pthread_t x; + int rc; + + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID FILENAME", 0); + return TCL_ERROR; + } + i = parse_client_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( threadset[i].busy ){ + Tcl_AppendResult(interp, "thread ", argv[1], " is already running", 0); + return TCL_ERROR; + } + threadset[i].busy = 1; + sqlite3_free(threadset[i].zFilename); + threadset[i].zFilename = sqlite3DbStrDup(0, argv[2]); + threadset[i].opnum = 1; + threadset[i].completed = 0; + rc = pthread_create(&x, 0, client_main, &threadset[i]); + if( rc ){ + Tcl_AppendResult(interp, "failed to create the thread", 0); + sqlite3_free(threadset[i].zFilename); + threadset[i].busy = 0; + return TCL_ERROR; + } + pthread_detach(x); + sqlite3_server_start(); + return TCL_OK; +} + +/* +** Wait for a thread to reach its idle state. +*/ +static void client_wait(Thread *p){ + while( p->opnum>p->completed ) sched_yield(); +} + +/* +** Usage: client_wait ID +** +** Wait on thread ID to reach its idle state. +*/ +static int tcl_client_wait( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID", 0); + return TCL_ERROR; + } + i = parse_client_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( !threadset[i].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + client_wait(&threadset[i]); + return TCL_OK; +} + +/* +** Stop a thread. +*/ +static void stop_thread(Thread *p){ + client_wait(p); + p->xOp = 0; + p->opnum++; + client_wait(p); + sqlite3_free(p->zArg); + p->zArg = 0; + sqlite3_free(p->zFilename); + p->zFilename = 0; + p->busy = 0; +} + +/* +** Usage: client_halt ID +** +** Cause a client thread to shut itself down. Wait for the shutdown to be +** completed. If ID is "*" then stop all client threads. +*/ +static int tcl_client_halt( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID", 0); + return TCL_ERROR; + } + if( argv[1][0]=='*' && argv[1][1]==0 ){ + for(i=0; i<N_THREAD; i++){ + if( threadset[i].busy ){ + stop_thread(&threadset[i]); + } + } + }else{ + i = parse_client_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( !threadset[i].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + stop_thread(&threadset[i]); + } + + /* If no client threads are still running, also stop the server */ + for(i=0; i<N_THREAD && threadset[i].busy==0; i++){} + if( i>=N_THREAD ){ + sqlite3_server_stop(); + } + return TCL_OK; +} + +/* +** Usage: client_argc ID +** +** Wait on the most recent client_step to complete, then return the +** number of columns in the result set. +*/ +static int tcl_client_argc( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i; + char zBuf[100]; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID", 0); + return TCL_ERROR; + } + i = parse_client_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( !threadset[i].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + client_wait(&threadset[i]); + sprintf(zBuf, "%d", threadset[i].argc); + Tcl_AppendResult(interp, zBuf, 0); + return TCL_OK; +} + +/* +** Usage: client_argv ID N +** +** Wait on the most recent client_step to complete, then return the +** value of the N-th columns in the result set. +*/ +static int tcl_client_argv( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i; + int n; + + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID N", 0); + return TCL_ERROR; + } + i = parse_client_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( !threadset[i].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR; + client_wait(&threadset[i]); + if( n<0 || n>=threadset[i].argc ){ + Tcl_AppendResult(interp, "column number out of range", 0); + return TCL_ERROR; + } + Tcl_AppendResult(interp, threadset[i].argv[n], 0); + return TCL_OK; +} + +/* +** Usage: client_colname ID N +** +** Wait on the most recent client_step to complete, then return the +** name of the N-th columns in the result set. +*/ +static int tcl_client_colname( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i; + int n; + + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID N", 0); + return TCL_ERROR; + } + i = parse_client_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( !threadset[i].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR; + client_wait(&threadset[i]); + if( n<0 || n>=threadset[i].argc ){ + Tcl_AppendResult(interp, "column number out of range", 0); + return TCL_ERROR; + } + Tcl_AppendResult(interp, threadset[i].colv[n], 0); + return TCL_OK; +} + +/* +** Usage: client_result ID +** +** Wait on the most recent operation to complete, then return the +** result code from that operation. +*/ +static int tcl_client_result( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i; + const char *zName; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID", 0); + return TCL_ERROR; + } + i = parse_client_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( !threadset[i].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + client_wait(&threadset[i]); + switch( threadset[i].rc ){ + case SQLITE_OK: zName = "SQLITE_OK"; break; + case SQLITE_ERROR: zName = "SQLITE_ERROR"; break; + case SQLITE_PERM: zName = "SQLITE_PERM"; break; + case SQLITE_ABORT: zName = "SQLITE_ABORT"; break; + case SQLITE_BUSY: zName = "SQLITE_BUSY"; break; + case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break; + case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break; + case SQLITE_READONLY: zName = "SQLITE_READONLY"; break; + case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break; + case SQLITE_IOERR: zName = "SQLITE_IOERR"; break; + case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break; + case SQLITE_FULL: zName = "SQLITE_FULL"; break; + case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break; + case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break; + case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break; + case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break; + case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break; + case SQLITE_MISMATCH: zName = "SQLITE_MISMATCH"; break; + case SQLITE_MISUSE: zName = "SQLITE_MISUSE"; break; + case SQLITE_NOLFS: zName = "SQLITE_NOLFS"; break; + case SQLITE_AUTH: zName = "SQLITE_AUTH"; break; + case SQLITE_FORMAT: zName = "SQLITE_FORMAT"; break; + case SQLITE_RANGE: zName = "SQLITE_RANGE"; break; + case SQLITE_ROW: zName = "SQLITE_ROW"; break; + case SQLITE_DONE: zName = "SQLITE_DONE"; break; + default: zName = "SQLITE_Unknown"; break; + } + Tcl_AppendResult(interp, zName, 0); + return TCL_OK; +} + +/* +** Usage: client_error ID +** +** Wait on the most recent operation to complete, then return the +** error string. +*/ +static int tcl_client_error( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID", 0); + return TCL_ERROR; + } + i = parse_client_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( !threadset[i].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + client_wait(&threadset[i]); + Tcl_AppendResult(interp, threadset[i].zErr, 0); + return TCL_OK; +} + +/* +** This procedure runs in the thread to compile an SQL statement. +*/ +static void do_compile(Thread *p){ + if( p->db==0 ){ + p->zErr = p->zStaticErr = "no database is open"; + p->rc = SQLITE_ERROR; + return; + } + if( p->pStmt ){ + sqlite3_client_finalize(p->pStmt); + p->pStmt = 0; + } + p->rc = sqlite3_client_prepare(p->db, p->zArg, -1, &p->pStmt, 0); +} + +/* +** Usage: client_compile ID SQL +** +** Compile a new virtual machine. +*/ +static int tcl_client_compile( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID SQL", 0); + return TCL_ERROR; + } + i = parse_client_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( !threadset[i].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + client_wait(&threadset[i]); + threadset[i].xOp = do_compile; + sqlite3_free(threadset[i].zArg); + threadset[i].zArg = sqlite3DbStrDup(0, argv[2]); + threadset[i].opnum++; + return TCL_OK; +} + +/* +** This procedure runs in the thread to step the virtual machine. +*/ +static void do_step(Thread *p){ + int i; + if( p->pStmt==0 ){ + p->zErr = p->zStaticErr = "no virtual machine available"; + p->rc = SQLITE_ERROR; + return; + } + p->rc = sqlite3_client_step(p->pStmt); + if( p->rc==SQLITE_ROW ){ + p->argc = sqlite3_column_count(p->pStmt); + for(i=0; i<sqlite3_data_count(p->pStmt); i++){ + p->argv[i] = (char*)sqlite3_column_text(p->pStmt, i); + } + for(i=0; i<p->argc; i++){ + p->colv[i] = sqlite3_column_name(p->pStmt, i); + } + } +} + +/* +** Usage: client_step ID +** +** Advance the virtual machine by one step +*/ +static int tcl_client_step( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " IDL", 0); + return TCL_ERROR; + } + i = parse_client_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( !threadset[i].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + client_wait(&threadset[i]); + threadset[i].xOp = do_step; + threadset[i].opnum++; + return TCL_OK; +} + +/* +** This procedure runs in the thread to finalize a virtual machine. +*/ +static void do_finalize(Thread *p){ + if( p->pStmt==0 ){ + p->zErr = p->zStaticErr = "no virtual machine available"; + p->rc = SQLITE_ERROR; + return; + } + p->rc = sqlite3_client_finalize(p->pStmt); + p->pStmt = 0; +} + +/* +** Usage: client_finalize ID +** +** Finalize the virtual machine. +*/ +static int tcl_client_finalize( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " IDL", 0); + return TCL_ERROR; + } + i = parse_client_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( !threadset[i].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + client_wait(&threadset[i]); + threadset[i].xOp = do_finalize; + sqlite3_free(threadset[i].zArg); + threadset[i].zArg = 0; + threadset[i].opnum++; + return TCL_OK; +} + +/* +** This procedure runs in the thread to reset a virtual machine. +*/ +static void do_reset(Thread *p){ + if( p->pStmt==0 ){ + p->zErr = p->zStaticErr = "no virtual machine available"; + p->rc = SQLITE_ERROR; + return; + } + p->rc = sqlite3_client_reset(p->pStmt); + p->pStmt = 0; +} + +/* +** Usage: client_reset ID +** +** Finalize the virtual machine. +*/ +static int tcl_client_reset( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " IDL", 0); + return TCL_ERROR; + } + i = parse_client_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( !threadset[i].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + client_wait(&threadset[i]); + threadset[i].xOp = do_reset; + sqlite3_free(threadset[i].zArg); + threadset[i].zArg = 0; + threadset[i].opnum++; + return TCL_OK; +} + +/* +** Usage: client_swap ID ID +** +** Interchange the sqlite* pointer between two threads. +*/ +static int tcl_client_swap( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + int i, j; + sqlite3 *temp; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID1 ID2", 0); + return TCL_ERROR; + } + i = parse_client_id(interp, argv[1]); + if( i<0 ) return TCL_ERROR; + if( !threadset[i].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + client_wait(&threadset[i]); + j = parse_client_id(interp, argv[2]); + if( j<0 ) return TCL_ERROR; + if( !threadset[j].busy ){ + Tcl_AppendResult(interp, "no such thread", 0); + return TCL_ERROR; + } + client_wait(&threadset[j]); + temp = threadset[i].db; + threadset[i].db = threadset[j].db; + threadset[j].db = temp; + return TCL_OK; +} + +/* +** Register commands with the TCL interpreter. +*/ +int Sqlitetest7_Init(Tcl_Interp *interp){ + static struct { + char *zName; + Tcl_CmdProc *xProc; + } aCmd[] = { + { "client_create", (Tcl_CmdProc*)tcl_client_create }, + { "client_wait", (Tcl_CmdProc*)tcl_client_wait }, + { "client_halt", (Tcl_CmdProc*)tcl_client_halt }, + { "client_argc", (Tcl_CmdProc*)tcl_client_argc }, + { "client_argv", (Tcl_CmdProc*)tcl_client_argv }, + { "client_colname", (Tcl_CmdProc*)tcl_client_colname }, + { "client_result", (Tcl_CmdProc*)tcl_client_result }, + { "client_error", (Tcl_CmdProc*)tcl_client_error }, + { "client_compile", (Tcl_CmdProc*)tcl_client_compile }, + { "client_step", (Tcl_CmdProc*)tcl_client_step }, + { "client_reset", (Tcl_CmdProc*)tcl_client_reset }, + { "client_finalize", (Tcl_CmdProc*)tcl_client_finalize }, + { "client_swap", (Tcl_CmdProc*)tcl_client_swap }, + }; + int i; + + for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ + Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); + } + return TCL_OK; +} +#else +int Sqlitetest7_Init(Tcl_Interp *interp){ return TCL_OK; } +#endif /* SQLITE_OS_UNIX */ diff --git a/third_party/sqlite/src/test8.c b/third_party/sqlite/src/test8.c new file mode 100755 index 0000000..c9b87b9 --- /dev/null +++ b/third_party/sqlite/src/test8.c @@ -0,0 +1,1344 @@ +/* +** 2006 June 10 +** +** 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. +** +************************************************************************* +** Code for testing the virtual table interfaces. This code +** is not included in the SQLite library. It is used for automated +** testing of the SQLite library. +** +** $Id: test8.c,v 1.72 2008/08/05 21:36:07 drh Exp $ +*/ +#include "sqliteInt.h" +#include "tcl.h" +#include <stdlib.h> +#include <string.h> + +#ifndef SQLITE_OMIT_VIRTUALTABLE + +typedef struct echo_vtab echo_vtab; +typedef struct echo_cursor echo_cursor; + +/* +** The test module defined in this file uses four global Tcl variables to +** commicate with test-scripts: +** +** $::echo_module +** $::echo_module_sync_fail +** $::echo_module_begin_fail +** $::echo_module_cost +** +** The variable ::echo_module is a list. Each time one of the following +** methods is called, one or more elements are appended to the list. +** This is used for automated testing of virtual table modules. +** +** The ::echo_module_sync_fail variable is set by test scripts and read +** by code in this file. If it is set to the name of a real table in the +** the database, then all xSync operations on echo virtual tables that +** use the named table as a backing store will fail. +*/ + +/* +** Errors can be provoked within the following echo virtual table methods: +** +** xBestIndex xOpen xFilter xNext +** xColumn xRowid xUpdate xSync +** xBegin xRename +** +** This is done by setting the global tcl variable: +** +** echo_module_fail($method,$tbl) +** +** where $method is set to the name of the virtual table method to fail +** (i.e. "xBestIndex") and $tbl is the name of the table being echoed (not +** the name of the virtual table, the name of the underlying real table). +*/ + +/* +** An echo virtual-table object. +** +** echo.vtab.aIndex is an array of booleans. The nth entry is true if +** the nth column of the real table is the left-most column of an index +** (implicit or otherwise). In other words, if SQLite can optimize +** a query like "SELECT * FROM real_table WHERE col = ?". +** +** Member variable aCol[] contains copies of the column names of the real +** table. +*/ +struct echo_vtab { + sqlite3_vtab base; + Tcl_Interp *interp; /* Tcl interpreter containing debug variables */ + sqlite3 *db; /* Database connection */ + + int isPattern; + int inTransaction; /* True if within a transaction */ + char *zThis; /* Name of the echo table */ + char *zTableName; /* Name of the real table */ + char *zLogName; /* Name of the log table */ + int nCol; /* Number of columns in the real table */ + int *aIndex; /* Array of size nCol. True if column has an index */ + char **aCol; /* Array of size nCol. Column names */ +}; + +/* An echo cursor object */ +struct echo_cursor { + sqlite3_vtab_cursor base; + sqlite3_stmt *pStmt; +}; + +static int simulateVtabError(echo_vtab *p, const char *zMethod){ + const char *zErr; + char zVarname[128]; + zVarname[127] = '\0'; + sqlite3_snprintf(127, zVarname, + "echo_module_fail(%s,%s)", zMethod, p->zTableName); + zErr = Tcl_GetVar(p->interp, zVarname, TCL_GLOBAL_ONLY); + if( zErr ){ + p->base.zErrMsg = sqlite3_mprintf("echo-vtab-error: %s", zErr); + } + return (zErr!=0); +} + +/* +** Convert an SQL-style quoted string into a normal string by removing +** the quote characters. The conversion is done in-place. If the +** input does not begin with a quote character, then this routine +** is a no-op. +** +** Examples: +** +** "abc" becomes abc +** 'xyz' becomes xyz +** [pqr] becomes pqr +** `mno` becomes mno +*/ +static void dequoteString(char *z){ + int quote; + int i, j; + if( z==0 ) return; + quote = z[0]; + switch( quote ){ + case '\'': break; + case '"': break; + case '`': break; /* For MySQL compatibility */ + case '[': quote = ']'; break; /* For MS SqlServer compatibility */ + default: return; + } + for(i=1, j=0; z[i]; i++){ + if( z[i]==quote ){ + if( z[i+1]==quote ){ + z[j++] = quote; + i++; + }else{ + z[j++] = 0; + break; + } + }else{ + z[j++] = z[i]; + } + } +} + +/* +** Retrieve the column names for the table named zTab via database +** connection db. SQLITE_OK is returned on success, or an sqlite error +** code otherwise. +** +** If successful, the number of columns is written to *pnCol. *paCol is +** set to point at sqlite3_malloc()'d space containing the array of +** nCol column names. The caller is responsible for calling sqlite3_free +** on *paCol. +*/ +static int getColumnNames( + sqlite3 *db, + const char *zTab, + char ***paCol, + int *pnCol +){ + char **aCol = 0; + char *zSql; + sqlite3_stmt *pStmt = 0; + int rc = SQLITE_OK; + int nCol = 0; + + /* Prepare the statement "SELECT * FROM <tbl>". The column names + ** of the result set of the compiled SELECT will be the same as + ** the column names of table <tbl>. + */ + zSql = sqlite3_mprintf("SELECT * FROM %Q", zTab); + if( !zSql ){ + rc = SQLITE_NOMEM; + goto out; + } + rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + + if( rc==SQLITE_OK ){ + int ii; + int nBytes; + char *zSpace; + nCol = sqlite3_column_count(pStmt); + + /* Figure out how much space to allocate for the array of column names + ** (including space for the strings themselves). Then allocate it. + */ + nBytes = sizeof(char *) * nCol; + for(ii=0; ii<nCol; ii++){ + const char *zName = sqlite3_column_name(pStmt, ii); + if( !zName ){ + rc = SQLITE_NOMEM; + goto out; + } + nBytes += strlen(zName)+1; + } + aCol = (char **)sqlite3MallocZero(nBytes); + if( !aCol ){ + rc = SQLITE_NOMEM; + goto out; + } + + /* Copy the column names into the allocated space and set up the + ** pointers in the aCol[] array. + */ + zSpace = (char *)(&aCol[nCol]); + for(ii=0; ii<nCol; ii++){ + aCol[ii] = zSpace; + zSpace += sprintf(zSpace, "%s", sqlite3_column_name(pStmt, ii)); + zSpace++; + } + assert( (zSpace-nBytes)==(char *)aCol ); + } + + *paCol = aCol; + *pnCol = nCol; + +out: + sqlite3_finalize(pStmt); + return rc; +} + +/* +** Parameter zTab is the name of a table in database db with nCol +** columns. This function allocates an array of integers nCol in +** size and populates it according to any implicit or explicit +** indices on table zTab. +** +** If successful, SQLITE_OK is returned and *paIndex set to point +** at the allocated array. Otherwise, an error code is returned. +** +** See comments associated with the member variable aIndex above +** "struct echo_vtab" for details of the contents of the array. +*/ +static int getIndexArray( + sqlite3 *db, /* Database connection */ + const char *zTab, /* Name of table in database db */ + int nCol, + int **paIndex +){ + sqlite3_stmt *pStmt = 0; + int *aIndex = 0; + int rc; + char *zSql; + + /* Allocate space for the index array */ + aIndex = (int *)sqlite3MallocZero(sizeof(int) * nCol); + if( !aIndex ){ + rc = SQLITE_NOMEM; + goto get_index_array_out; + } + + /* Compile an sqlite pragma to loop through all indices on table zTab */ + zSql = sqlite3MPrintf(0, "PRAGMA index_list(%s)", zTab); + if( !zSql ){ + rc = SQLITE_NOMEM; + goto get_index_array_out; + } + rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + + /* For each index, figure out the left-most column and set the + ** corresponding entry in aIndex[] to 1. + */ + while( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){ + const char *zIdx = (const char *)sqlite3_column_text(pStmt, 1); + sqlite3_stmt *pStmt2 = 0; + zSql = sqlite3MPrintf(0, "PRAGMA index_info(%s)", zIdx); + if( !zSql ){ + rc = SQLITE_NOMEM; + goto get_index_array_out; + } + rc = sqlite3_prepare(db, zSql, -1, &pStmt2, 0); + sqlite3_free(zSql); + if( pStmt2 && sqlite3_step(pStmt2)==SQLITE_ROW ){ + int cid = sqlite3_column_int(pStmt2, 1); + assert( cid>=0 && cid<nCol ); + aIndex[cid] = 1; + } + if( pStmt2 ){ + rc = sqlite3_finalize(pStmt2); + } + if( rc!=SQLITE_OK ){ + goto get_index_array_out; + } + } + + +get_index_array_out: + if( pStmt ){ + int rc2 = sqlite3_finalize(pStmt); + if( rc==SQLITE_OK ){ + rc = rc2; + } + } + if( rc!=SQLITE_OK ){ + sqlite3_free(aIndex); + aIndex = 0; + } + *paIndex = aIndex; + return rc; +} + +/* +** Global Tcl variable $echo_module is a list. This routine appends +** the string element zArg to that list in interpreter interp. +*/ +static void appendToEchoModule(Tcl_Interp *interp, const char *zArg){ + int flags = (TCL_APPEND_VALUE | TCL_LIST_ELEMENT | TCL_GLOBAL_ONLY); + Tcl_SetVar(interp, "echo_module", (zArg?zArg:""), flags); +} + +/* +** This function is called from within the echo-modules xCreate and +** xConnect methods. The argc and argv arguments are copies of those +** passed to the calling method. This function is responsible for +** calling sqlite3_declare_vtab() to declare the schema of the virtual +** table being created or connected. +** +** If the constructor was passed just one argument, i.e.: +** +** CREATE TABLE t1 AS echo(t2); +** +** Then t2 is assumed to be the name of a *real* database table. The +** schema of the virtual table is declared by passing a copy of the +** CREATE TABLE statement for the real table to sqlite3_declare_vtab(). +** Hence, the virtual table should have exactly the same column names and +** types as the real table. +*/ +static int echoDeclareVtab( + echo_vtab *pVtab, + sqlite3 *db +){ + int rc = SQLITE_OK; + + if( pVtab->zTableName ){ + sqlite3_stmt *pStmt = 0; + rc = sqlite3_prepare(db, + "SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?", + -1, &pStmt, 0); + if( rc==SQLITE_OK ){ + sqlite3_bind_text(pStmt, 1, pVtab->zTableName, -1, 0); + if( sqlite3_step(pStmt)==SQLITE_ROW ){ + int rc2; + const char *zCreateTable = (const char *)sqlite3_column_text(pStmt, 0); + rc = sqlite3_declare_vtab(db, zCreateTable); + rc2 = sqlite3_finalize(pStmt); + if( rc==SQLITE_OK ){ + rc = rc2; + } + } else { + rc = sqlite3_finalize(pStmt); + if( rc==SQLITE_OK ){ + rc = SQLITE_ERROR; + } + } + if( rc==SQLITE_OK ){ + rc = getColumnNames(db, pVtab->zTableName, &pVtab->aCol, &pVtab->nCol); + } + if( rc==SQLITE_OK ){ + rc = getIndexArray(db, pVtab->zTableName, pVtab->nCol, &pVtab->aIndex); + } + } + } + + return rc; +} + +/* +** This function frees all runtime structures associated with the virtual +** table pVtab. +*/ +static int echoDestructor(sqlite3_vtab *pVtab){ + echo_vtab *p = (echo_vtab*)pVtab; + sqlite3_free(p->aIndex); + sqlite3_free(p->aCol); + sqlite3_free(p->zThis); + sqlite3_free(p->zTableName); + sqlite3_free(p->zLogName); + sqlite3_free(p); + return 0; +} + +typedef struct EchoModule EchoModule; +struct EchoModule { + Tcl_Interp *interp; +}; + +/* +** This function is called to do the work of the xConnect() method - +** to allocate the required in-memory structures for a newly connected +** virtual table. +*/ +static int echoConstructor( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr +){ + int rc; + int i; + echo_vtab *pVtab; + + /* Allocate the sqlite3_vtab/echo_vtab structure itself */ + pVtab = sqlite3MallocZero( sizeof(*pVtab) ); + if( !pVtab ){ + return SQLITE_NOMEM; + } + pVtab->interp = ((EchoModule *)pAux)->interp; + pVtab->db = db; + + /* Allocate echo_vtab.zThis */ + pVtab->zThis = sqlite3MPrintf(0, "%s", argv[2]); + if( !pVtab->zThis ){ + echoDestructor((sqlite3_vtab *)pVtab); + return SQLITE_NOMEM; + } + + /* Allocate echo_vtab.zTableName */ + if( argc>3 ){ + pVtab->zTableName = sqlite3MPrintf(0, "%s", argv[3]); + dequoteString(pVtab->zTableName); + if( pVtab->zTableName && pVtab->zTableName[0]=='*' ){ + char *z = sqlite3MPrintf(0, "%s%s", argv[2], &(pVtab->zTableName[1])); + sqlite3_free(pVtab->zTableName); + pVtab->zTableName = z; + pVtab->isPattern = 1; + } + if( !pVtab->zTableName ){ + echoDestructor((sqlite3_vtab *)pVtab); + return SQLITE_NOMEM; + } + } + + /* Log the arguments to this function to Tcl var ::echo_module */ + for(i=0; i<argc; i++){ + appendToEchoModule(pVtab->interp, argv[i]); + } + + /* Invoke sqlite3_declare_vtab and set up other members of the echo_vtab + ** structure. If an error occurs, delete the sqlite3_vtab structure and + ** return an error code. + */ + rc = echoDeclareVtab(pVtab, db); + if( rc!=SQLITE_OK ){ + echoDestructor((sqlite3_vtab *)pVtab); + return rc; + } + + /* Success. Set *ppVtab and return */ + *ppVtab = &pVtab->base; + return SQLITE_OK; +} + +/* +** Echo virtual table module xCreate method. +*/ +static int echoCreate( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr +){ + int rc = SQLITE_OK; + appendToEchoModule(((EchoModule *)pAux)->interp, "xCreate"); + rc = echoConstructor(db, pAux, argc, argv, ppVtab, pzErr); + + /* If there were two arguments passed to the module at the SQL level + ** (i.e. "CREATE VIRTUAL TABLE tbl USING echo(arg1, arg2)"), then + ** the second argument is used as a table name. Attempt to create + ** such a table with a single column, "logmsg". This table will + ** be used to log calls to the xUpdate method. It will be deleted + ** when the virtual table is DROPed. + ** + ** Note: The main point of this is to test that we can drop tables + ** from within an xDestroy method call. + */ + if( rc==SQLITE_OK && argc==5 ){ + char *zSql; + echo_vtab *pVtab = *(echo_vtab **)ppVtab; + pVtab->zLogName = sqlite3MPrintf(0, "%s", argv[4]); + zSql = sqlite3MPrintf(0, "CREATE TABLE %Q(logmsg)", pVtab->zLogName); + rc = sqlite3_exec(db, zSql, 0, 0, 0); + sqlite3_free(zSql); + if( rc!=SQLITE_OK ){ + *pzErr = sqlite3DbStrDup(0, sqlite3_errmsg(db)); + } + } + + if( *ppVtab && rc!=SQLITE_OK ){ + echoDestructor(*ppVtab); + *ppVtab = 0; + } + + if( rc==SQLITE_OK ){ + (*(echo_vtab**)ppVtab)->inTransaction = 1; + } + + return rc; +} + +/* +** Echo virtual table module xConnect method. +*/ +static int echoConnect( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr +){ + appendToEchoModule(((EchoModule *)pAux)->interp, "xConnect"); + return echoConstructor(db, pAux, argc, argv, ppVtab, pzErr); +} + +/* +** Echo virtual table module xDisconnect method. +*/ +static int echoDisconnect(sqlite3_vtab *pVtab){ + appendToEchoModule(((echo_vtab *)pVtab)->interp, "xDisconnect"); + return echoDestructor(pVtab); +} + +/* +** Echo virtual table module xDestroy method. +*/ +static int echoDestroy(sqlite3_vtab *pVtab){ + int rc = SQLITE_OK; + echo_vtab *p = (echo_vtab *)pVtab; + appendToEchoModule(((echo_vtab *)pVtab)->interp, "xDestroy"); + + /* Drop the "log" table, if one exists (see echoCreate() for details) */ + if( p && p->zLogName ){ + char *zSql; + zSql = sqlite3MPrintf(0, "DROP TABLE %Q", p->zLogName); + rc = sqlite3_exec(p->db, zSql, 0, 0, 0); + sqlite3_free(zSql); + } + + if( rc==SQLITE_OK ){ + rc = echoDestructor(pVtab); + } + return rc; +} + +/* +** Echo virtual table module xOpen method. +*/ +static int echoOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ + echo_cursor *pCur; + if( simulateVtabError((echo_vtab *)pVTab, "xOpen") ){ + return SQLITE_ERROR; + } + pCur = sqlite3MallocZero(sizeof(echo_cursor)); + *ppCursor = (sqlite3_vtab_cursor *)pCur; + return (pCur ? SQLITE_OK : SQLITE_NOMEM); +} + +/* +** Echo virtual table module xClose method. +*/ +static int echoClose(sqlite3_vtab_cursor *cur){ + int rc; + echo_cursor *pCur = (echo_cursor *)cur; + sqlite3_stmt *pStmt = pCur->pStmt; + pCur->pStmt = 0; + sqlite3_free(pCur); + rc = sqlite3_finalize(pStmt); + return rc; +} + +/* +** Return non-zero if the cursor does not currently point to a valid record +** (i.e if the scan has finished), or zero otherwise. +*/ +static int echoEof(sqlite3_vtab_cursor *cur){ + return (((echo_cursor *)cur)->pStmt ? 0 : 1); +} + +/* +** Echo virtual table module xNext method. +*/ +static int echoNext(sqlite3_vtab_cursor *cur){ + int rc = SQLITE_OK; + echo_cursor *pCur = (echo_cursor *)cur; + + if( simulateVtabError((echo_vtab *)(cur->pVtab), "xNext") ){ + return SQLITE_ERROR; + } + + if( pCur->pStmt ){ + rc = sqlite3_step(pCur->pStmt); + if( rc==SQLITE_ROW ){ + rc = SQLITE_OK; + }else{ + rc = sqlite3_finalize(pCur->pStmt); + pCur->pStmt = 0; + } + } + + return rc; +} + +/* +** Echo virtual table module xColumn method. +*/ +static int echoColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ + int iCol = i + 1; + sqlite3_stmt *pStmt = ((echo_cursor *)cur)->pStmt; + + if( simulateVtabError((echo_vtab *)(cur->pVtab), "xColumn") ){ + return SQLITE_ERROR; + } + + if( !pStmt ){ + sqlite3_result_null(ctx); + }else{ + assert( sqlite3_data_count(pStmt)>iCol ); + sqlite3_result_value(ctx, sqlite3_column_value(pStmt, iCol)); + } + return SQLITE_OK; +} + +/* +** Echo virtual table module xRowid method. +*/ +static int echoRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ + sqlite3_stmt *pStmt = ((echo_cursor *)cur)->pStmt; + + if( simulateVtabError((echo_vtab *)(cur->pVtab), "xRowid") ){ + return SQLITE_ERROR; + } + + *pRowid = sqlite3_column_int64(pStmt, 0); + return SQLITE_OK; +} + +/* +** Compute a simple hash of the null terminated string zString. +** +** This module uses only sqlite3_index_info.idxStr, not +** sqlite3_index_info.idxNum. So to test idxNum, when idxStr is set +** in echoBestIndex(), idxNum is set to the corresponding hash value. +** In echoFilter(), code assert()s that the supplied idxNum value is +** indeed the hash of the supplied idxStr. +*/ +static int hashString(const char *zString){ + int val = 0; + int ii; + for(ii=0; zString[ii]; ii++){ + val = (val << 3) + (int)zString[ii]; + } + return val; +} + +/* +** Echo virtual table module xFilter method. +*/ +static int echoFilter( + sqlite3_vtab_cursor *pVtabCursor, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv +){ + int rc; + int i; + + echo_cursor *pCur = (echo_cursor *)pVtabCursor; + echo_vtab *pVtab = (echo_vtab *)pVtabCursor->pVtab; + sqlite3 *db = pVtab->db; + + if( simulateVtabError(pVtab, "xFilter") ){ + return SQLITE_ERROR; + } + + /* Check that idxNum matches idxStr */ + assert( idxNum==hashString(idxStr) ); + + /* Log arguments to the ::echo_module Tcl variable */ + appendToEchoModule(pVtab->interp, "xFilter"); + appendToEchoModule(pVtab->interp, idxStr); + for(i=0; i<argc; i++){ + appendToEchoModule(pVtab->interp, (const char*)sqlite3_value_text(argv[i])); + } + + sqlite3_finalize(pCur->pStmt); + pCur->pStmt = 0; + + /* Prepare the SQL statement created by echoBestIndex and bind the + ** runtime parameters passed to this function to it. + */ + rc = sqlite3_prepare(db, idxStr, -1, &pCur->pStmt, 0); + assert( pCur->pStmt || rc!=SQLITE_OK ); + for(i=0; rc==SQLITE_OK && i<argc; i++){ + sqlite3_bind_value(pCur->pStmt, i+1, argv[i]); + } + + /* If everything was successful, advance to the first row of the scan */ + if( rc==SQLITE_OK ){ + rc = echoNext(pVtabCursor); + } + + return rc; +} + + +/* +** A helper function used by echoUpdate() and echoBestIndex() for +** manipulating strings in concert with the sqlite3_mprintf() function. +** +** Parameter pzStr points to a pointer to a string allocated with +** sqlite3_mprintf. The second parameter, zAppend, points to another +** string. The two strings are concatenated together and *pzStr +** set to point at the result. The initial buffer pointed to by *pzStr +** is deallocated via sqlite3_free(). +** +** If the third argument, doFree, is true, then sqlite3_free() is +** also called to free the buffer pointed to by zAppend. +*/ +static void string_concat(char **pzStr, char *zAppend, int doFree, int *pRc){ + char *zIn = *pzStr; + if( !zAppend && doFree && *pRc==SQLITE_OK ){ + *pRc = SQLITE_NOMEM; + } + if( *pRc!=SQLITE_OK ){ + sqlite3_free(zIn); + zIn = 0; + }else{ + if( zIn ){ + char *zTemp = zIn; + zIn = sqlite3_mprintf("%s%s", zIn, zAppend); + sqlite3_free(zTemp); + }else{ + zIn = sqlite3_mprintf("%s", zAppend); + } + if( !zIn ){ + *pRc = SQLITE_NOMEM; + } + } + *pzStr = zIn; + if( doFree ){ + sqlite3_free(zAppend); + } +} + +/* +** The echo module implements the subset of query constraints and sort +** orders that may take advantage of SQLite indices on the underlying +** real table. For example, if the real table is declared as: +** +** CREATE TABLE real(a, b, c); +** CREATE INDEX real_index ON real(b); +** +** then the echo module handles WHERE or ORDER BY clauses that refer +** to the column "b", but not "a" or "c". If a multi-column index is +** present, only its left most column is considered. +** +** This xBestIndex method encodes the proposed search strategy as +** an SQL query on the real table underlying the virtual echo module +** table and stores the query in sqlite3_index_info.idxStr. The SQL +** statement is of the form: +** +** SELECT rowid, * FROM <real-table> ?<where-clause>? ?<order-by-clause>? +** +** where the <where-clause> and <order-by-clause> are determined +** by the contents of the structure pointed to by the pIdxInfo argument. +*/ +static int echoBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ + int ii; + char *zQuery = 0; + char *zNew; + int nArg = 0; + const char *zSep = "WHERE"; + echo_vtab *pVtab = (echo_vtab *)tab; + sqlite3_stmt *pStmt = 0; + Tcl_Interp *interp = pVtab->interp; + + int nRow; + int useIdx = 0; + int rc = SQLITE_OK; + int useCost = 0; + double cost; + int isIgnoreUsable = 0; + if( Tcl_GetVar(interp, "echo_module_ignore_usable", TCL_GLOBAL_ONLY) ){ + isIgnoreUsable = 1; + } + + if( simulateVtabError(pVtab, "xBestIndex") ){ + return SQLITE_ERROR; + } + + /* Determine the number of rows in the table and store this value in local + ** variable nRow. The 'estimated-cost' of the scan will be the number of + ** rows in the table for a linear scan, or the log (base 2) of the + ** number of rows if the proposed scan uses an index. + */ + if( Tcl_GetVar(interp, "echo_module_cost", TCL_GLOBAL_ONLY) ){ + cost = atof(Tcl_GetVar(interp, "echo_module_cost", TCL_GLOBAL_ONLY)); + useCost = 1; + } else { + zQuery = sqlite3_mprintf("SELECT count(*) FROM %Q", pVtab->zTableName); + if( !zQuery ){ + return SQLITE_NOMEM; + } + rc = sqlite3_prepare(pVtab->db, zQuery, -1, &pStmt, 0); + sqlite3_free(zQuery); + if( rc!=SQLITE_OK ){ + return rc; + } + sqlite3_step(pStmt); + nRow = sqlite3_column_int(pStmt, 0); + rc = sqlite3_finalize(pStmt); + if( rc!=SQLITE_OK ){ + return rc; + } + } + + zQuery = sqlite3_mprintf("SELECT rowid, * FROM %Q", pVtab->zTableName); + if( !zQuery ){ + return SQLITE_NOMEM; + } + for(ii=0; ii<pIdxInfo->nConstraint; ii++){ + const struct sqlite3_index_constraint *pConstraint; + struct sqlite3_index_constraint_usage *pUsage; + int iCol; + + pConstraint = &pIdxInfo->aConstraint[ii]; + pUsage = &pIdxInfo->aConstraintUsage[ii]; + + if( !isIgnoreUsable && !pConstraint->usable ) continue; + + iCol = pConstraint->iColumn; + if( pVtab->aIndex[iCol] || iCol<0 ){ + char *zCol = pVtab->aCol[iCol]; + char *zOp = 0; + useIdx = 1; + if( iCol<0 ){ + zCol = "rowid"; + } + switch( pConstraint->op ){ + case SQLITE_INDEX_CONSTRAINT_EQ: + zOp = "="; break; + case SQLITE_INDEX_CONSTRAINT_LT: + zOp = "<"; break; + case SQLITE_INDEX_CONSTRAINT_GT: + zOp = ">"; break; + case SQLITE_INDEX_CONSTRAINT_LE: + zOp = "<="; break; + case SQLITE_INDEX_CONSTRAINT_GE: + zOp = ">="; break; + case SQLITE_INDEX_CONSTRAINT_MATCH: + zOp = "LIKE"; break; + } + if( zOp[0]=='L' ){ + zNew = sqlite3_mprintf(" %s %s LIKE (SELECT '%%'||?||'%%')", + zSep, zCol); + } else { + zNew = sqlite3_mprintf(" %s %s %s ?", zSep, zCol, zOp); + } + string_concat(&zQuery, zNew, 1, &rc); + + zSep = "AND"; + pUsage->argvIndex = ++nArg; + pUsage->omit = 1; + } + } + + /* If there is only one term in the ORDER BY clause, and it is + ** on a column that this virtual table has an index for, then consume + ** the ORDER BY clause. + */ + if( pIdxInfo->nOrderBy==1 && pVtab->aIndex[pIdxInfo->aOrderBy->iColumn] ){ + int iCol = pIdxInfo->aOrderBy->iColumn; + char *zCol = pVtab->aCol[iCol]; + char *zDir = pIdxInfo->aOrderBy->desc?"DESC":"ASC"; + if( iCol<0 ){ + zCol = "rowid"; + } + zNew = sqlite3_mprintf(" ORDER BY %s %s", zCol, zDir); + string_concat(&zQuery, zNew, 1, &rc); + pIdxInfo->orderByConsumed = 1; + } + + appendToEchoModule(pVtab->interp, "xBestIndex");; + appendToEchoModule(pVtab->interp, zQuery); + + if( !zQuery ){ + return rc; + } + pIdxInfo->idxNum = hashString(zQuery); + pIdxInfo->idxStr = zQuery; + pIdxInfo->needToFreeIdxStr = 1; + if (useCost) { + pIdxInfo->estimatedCost = cost; + } else if( useIdx ){ + /* Approximation of log2(nRow). */ + for( ii=0; ii<(sizeof(int)*8); ii++ ){ + if( nRow & (1<<ii) ){ + pIdxInfo->estimatedCost = (double)ii; + } + } + } else { + pIdxInfo->estimatedCost = (double)nRow; + } + return rc; +} + +/* +** The xUpdate method for echo module virtual tables. +** +** apData[0] apData[1] apData[2..] +** +** INTEGER DELETE +** +** INTEGER NULL (nCol args) UPDATE (do not set rowid) +** INTEGER INTEGER (nCol args) UPDATE (with SET rowid = <arg1>) +** +** NULL NULL (nCol args) INSERT INTO (automatic rowid value) +** NULL INTEGER (nCol args) INSERT (incl. rowid value) +** +*/ +int echoUpdate( + sqlite3_vtab *tab, + int nData, + sqlite3_value **apData, + sqlite_int64 *pRowid +){ + echo_vtab *pVtab = (echo_vtab *)tab; + sqlite3 *db = pVtab->db; + int rc = SQLITE_OK; + + sqlite3_stmt *pStmt; + char *z = 0; /* SQL statement to execute */ + int bindArgZero = 0; /* True to bind apData[0] to sql var no. nData */ + int bindArgOne = 0; /* True to bind apData[1] to sql var no. 1 */ + int i; /* Counter variable used by for loops */ + + assert( nData==pVtab->nCol+2 || nData==1 ); + + /* Ticket #3083 - make sure we always start a transaction prior to + ** making any changes to a virtual table */ + assert( pVtab->inTransaction ); + + if( simulateVtabError(pVtab, "xUpdate") ){ + return SQLITE_ERROR; + } + + /* If apData[0] is an integer and nData>1 then do an UPDATE */ + if( nData>1 && sqlite3_value_type(apData[0])==SQLITE_INTEGER ){ + char *zSep = " SET"; + z = sqlite3_mprintf("UPDATE %Q", pVtab->zTableName); + if( !z ){ + rc = SQLITE_NOMEM; + } + + bindArgOne = (apData[1] && sqlite3_value_type(apData[1])==SQLITE_INTEGER); + bindArgZero = 1; + + if( bindArgOne ){ + string_concat(&z, " SET rowid=?1 ", 0, &rc); + zSep = ","; + } + for(i=2; i<nData; i++){ + if( apData[i]==0 ) continue; + string_concat(&z, sqlite3_mprintf( + "%s %Q=?%d", zSep, pVtab->aCol[i-2], i), 1, &rc); + zSep = ","; + } + string_concat(&z, sqlite3_mprintf(" WHERE rowid=?%d", nData), 1, &rc); + } + + /* If apData[0] is an integer and nData==1 then do a DELETE */ + else if( nData==1 && sqlite3_value_type(apData[0])==SQLITE_INTEGER ){ + z = sqlite3_mprintf("DELETE FROM %Q WHERE rowid = ?1", pVtab->zTableName); + if( !z ){ + rc = SQLITE_NOMEM; + } + bindArgZero = 1; + } + + /* If the first argument is NULL and there are more than two args, INSERT */ + else if( nData>2 && sqlite3_value_type(apData[0])==SQLITE_NULL ){ + int ii; + char *zInsert = 0; + char *zValues = 0; + + zInsert = sqlite3_mprintf("INSERT INTO %Q (", pVtab->zTableName); + if( !zInsert ){ + rc = SQLITE_NOMEM; + } + if( sqlite3_value_type(apData[1])==SQLITE_INTEGER ){ + bindArgOne = 1; + zValues = sqlite3_mprintf("?"); + string_concat(&zInsert, "rowid", 0, &rc); + } + + assert((pVtab->nCol+2)==nData); + for(ii=2; ii<nData; ii++){ + string_concat(&zInsert, + sqlite3_mprintf("%s%Q", zValues?", ":"", pVtab->aCol[ii-2]), 1, &rc); + string_concat(&zValues, + sqlite3_mprintf("%s?%d", zValues?", ":"", ii), 1, &rc); + } + + string_concat(&z, zInsert, 1, &rc); + string_concat(&z, ") VALUES(", 0, &rc); + string_concat(&z, zValues, 1, &rc); + string_concat(&z, ")", 0, &rc); + } + + /* Anything else is an error */ + else{ + assert(0); + return SQLITE_ERROR; + } + + if( rc==SQLITE_OK ){ + rc = sqlite3_prepare(db, z, -1, &pStmt, 0); + } + assert( rc!=SQLITE_OK || pStmt ); + sqlite3_free(z); + if( rc==SQLITE_OK ) { + if( bindArgZero ){ + sqlite3_bind_value(pStmt, nData, apData[0]); + } + if( bindArgOne ){ + sqlite3_bind_value(pStmt, 1, apData[1]); + } + for(i=2; i<nData && rc==SQLITE_OK; i++){ + if( apData[i] ) rc = sqlite3_bind_value(pStmt, i, apData[i]); + } + if( rc==SQLITE_OK ){ + sqlite3_step(pStmt); + rc = sqlite3_finalize(pStmt); + }else{ + sqlite3_finalize(pStmt); + } + } + + if( pRowid && rc==SQLITE_OK ){ + *pRowid = sqlite3_last_insert_rowid(db); + } + if( rc!=SQLITE_OK ){ + tab->zErrMsg = sqlite3_mprintf("echo-vtab-error: %s", sqlite3_errmsg(db)); + } + + return rc; +} + +/* +** xBegin, xSync, xCommit and xRollback callbacks for echo module +** virtual tables. Do nothing other than add the name of the callback +** to the $::echo_module Tcl variable. +*/ +static int echoTransactionCall(sqlite3_vtab *tab, const char *zCall){ + char *z; + echo_vtab *pVtab = (echo_vtab *)tab; + z = sqlite3_mprintf("echo(%s)", pVtab->zTableName); + if( z==0 ) return SQLITE_NOMEM; + appendToEchoModule(pVtab->interp, zCall); + appendToEchoModule(pVtab->interp, z); + sqlite3_free(z); + return SQLITE_OK; +} +static int echoBegin(sqlite3_vtab *tab){ + int rc; + echo_vtab *pVtab = (echo_vtab *)tab; + Tcl_Interp *interp = pVtab->interp; + const char *zVal; + + /* Ticket #3083 - do not start a transaction if we are already in + ** a transaction */ + assert( !pVtab->inTransaction ); + + if( simulateVtabError(pVtab, "xBegin") ){ + return SQLITE_ERROR; + } + + rc = echoTransactionCall(tab, "xBegin"); + + if( rc==SQLITE_OK ){ + /* Check if the $::echo_module_begin_fail variable is defined. If it is, + ** and it is set to the name of the real table underlying this virtual + ** echo module table, then cause this xSync operation to fail. + */ + zVal = Tcl_GetVar(interp, "echo_module_begin_fail", TCL_GLOBAL_ONLY); + if( zVal && 0==strcmp(zVal, pVtab->zTableName) ){ + rc = SQLITE_ERROR; + } + } + if( rc==SQLITE_OK ){ + pVtab->inTransaction = 1; + } + return rc; +} +static int echoSync(sqlite3_vtab *tab){ + int rc; + echo_vtab *pVtab = (echo_vtab *)tab; + Tcl_Interp *interp = pVtab->interp; + const char *zVal; + + /* Ticket #3083 - Only call xSync if we have previously started a + ** transaction */ + assert( pVtab->inTransaction ); + + if( simulateVtabError(pVtab, "xSync") ){ + return SQLITE_ERROR; + } + + rc = echoTransactionCall(tab, "xSync"); + + if( rc==SQLITE_OK ){ + /* Check if the $::echo_module_sync_fail variable is defined. If it is, + ** and it is set to the name of the real table underlying this virtual + ** echo module table, then cause this xSync operation to fail. + */ + zVal = Tcl_GetVar(interp, "echo_module_sync_fail", TCL_GLOBAL_ONLY); + if( zVal && 0==strcmp(zVal, pVtab->zTableName) ){ + rc = -1; + } + } + return rc; +} +static int echoCommit(sqlite3_vtab *tab){ + echo_vtab *pVtab = (echo_vtab*)tab; + int rc; + + /* Ticket #3083 - Only call xCommit if we have previously started + ** a transaction */ + assert( pVtab->inTransaction ); + + if( simulateVtabError(pVtab, "xCommit") ){ + return SQLITE_ERROR; + } + + sqlite3BeginBenignMalloc(); + rc = echoTransactionCall(tab, "xCommit"); + sqlite3EndBenignMalloc(); + pVtab->inTransaction = 0; + return rc; +} +static int echoRollback(sqlite3_vtab *tab){ + int rc; + echo_vtab *pVtab = (echo_vtab*)tab; + + /* Ticket #3083 - Only call xRollback if we have previously started + ** a transaction */ + assert( pVtab->inTransaction ); + + rc = echoTransactionCall(tab, "xRollback"); + pVtab->inTransaction = 0; + return rc; +} + +/* +** Implementation of "GLOB" function on the echo module. Pass +** all arguments to the ::echo_glob_overload procedure of TCL +** and return the result of that procedure as a string. +*/ +static void overloadedGlobFunction( + sqlite3_context *pContext, + int nArg, + sqlite3_value **apArg +){ + Tcl_Interp *interp = sqlite3_user_data(pContext); + Tcl_DString str; + int i; + int rc; + Tcl_DStringInit(&str); + Tcl_DStringAppendElement(&str, "::echo_glob_overload"); + for(i=0; i<nArg; i++){ + Tcl_DStringAppendElement(&str, (char*)sqlite3_value_text(apArg[i])); + } + rc = Tcl_Eval(interp, Tcl_DStringValue(&str)); + Tcl_DStringFree(&str); + if( rc ){ + sqlite3_result_error(pContext, Tcl_GetStringResult(interp), -1); + }else{ + sqlite3_result_text(pContext, Tcl_GetStringResult(interp), + -1, SQLITE_TRANSIENT); + } + Tcl_ResetResult(interp); +} + +/* +** This is the xFindFunction implementation for the echo module. +** SQLite calls this routine when the first argument of a function +** is a column of an echo virtual table. This routine can optionally +** override the implementation of that function. It will choose to +** do so if the function is named "glob", and a TCL command named +** ::echo_glob_overload exists. +*/ +static int echoFindFunction( + sqlite3_vtab *vtab, + int nArg, + const char *zFuncName, + void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), + void **ppArg +){ + echo_vtab *pVtab = (echo_vtab *)vtab; + Tcl_Interp *interp = pVtab->interp; + Tcl_CmdInfo info; + if( strcmp(zFuncName,"glob")!=0 ){ + return 0; + } + if( Tcl_GetCommandInfo(interp, "::echo_glob_overload", &info)==0 ){ + return 0; + } + *pxFunc = overloadedGlobFunction; + *ppArg = interp; + return 1; +} + +static int echoRename(sqlite3_vtab *vtab, const char *zNewName){ + int rc = SQLITE_OK; + echo_vtab *p = (echo_vtab *)vtab; + + if( simulateVtabError(p, "xRename") ){ + return SQLITE_ERROR; + } + + if( p->isPattern ){ + int nThis = strlen(p->zThis); + char *zSql = sqlite3MPrintf(0, "ALTER TABLE %s RENAME TO %s%s", + p->zTableName, zNewName, &p->zTableName[nThis] + ); + rc = sqlite3_exec(p->db, zSql, 0, 0, 0); + sqlite3_free(zSql); + } + + return rc; +} + +/* +** A virtual table module that merely "echos" the contents of another +** table (like an SQL VIEW). +*/ +static sqlite3_module echoModule = { + 0, /* iVersion */ + echoCreate, + echoConnect, + echoBestIndex, + echoDisconnect, + echoDestroy, + echoOpen, /* xOpen - open a cursor */ + echoClose, /* xClose - close a cursor */ + echoFilter, /* xFilter - configure scan constraints */ + echoNext, /* xNext - advance a cursor */ + echoEof, /* xEof */ + echoColumn, /* xColumn - read data */ + echoRowid, /* xRowid - read data */ + echoUpdate, /* xUpdate - write data */ + echoBegin, /* xBegin - begin transaction */ + echoSync, /* xSync - sync transaction */ + echoCommit, /* xCommit - commit transaction */ + echoRollback, /* xRollback - rollback transaction */ + echoFindFunction, /* xFindFunction - function overloading */ + echoRename, /* xRename - rename the table */ +}; + +/* +** Decode a pointer to an sqlite3 object. +*/ +extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb); + +static void moduleDestroy(void *p){ + sqlite3_free(p); +} + +/* +** Register the echo virtual table module. +*/ +static int register_echo_module( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + sqlite3 *db; + EchoModule *pMod; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB"); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + pMod = sqlite3_malloc(sizeof(EchoModule)); + pMod->interp = interp; + sqlite3_create_module_v2(db, "echo", &echoModule, (void*)pMod, moduleDestroy); + return TCL_OK; +} + +/* +** Tcl interface to sqlite3_declare_vtab, invoked as follows from Tcl: +** +** sqlite3_declare_vtab DB SQL +*/ +static int declare_vtab( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + sqlite3 *db; + int rc; + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB SQL"); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + rc = sqlite3_declare_vtab(db, Tcl_GetString(objv[2])); + if( rc!=SQLITE_OK ){ + Tcl_SetResult(interp, (char *)sqlite3_errmsg(db), TCL_VOLATILE); + return TCL_ERROR; + } + return TCL_OK; +} + +#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ + +/* +** Register commands with the TCL interpreter. +*/ +int Sqlitetest8_Init(Tcl_Interp *interp){ + static struct { + char *zName; + Tcl_ObjCmdProc *xProc; + void *clientData; + } aObjCmd[] = { +#ifndef SQLITE_OMIT_VIRTUALTABLE + { "register_echo_module", register_echo_module, 0 }, + { "sqlite3_declare_vtab", declare_vtab, 0 }, +#endif + }; + int i; + for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ + Tcl_CreateObjCommand(interp, aObjCmd[i].zName, + aObjCmd[i].xProc, aObjCmd[i].clientData, 0); + } + return TCL_OK; +} diff --git a/third_party/sqlite/src/test9.c b/third_party/sqlite/src/test9.c new file mode 100755 index 0000000..2043da2 --- /dev/null +++ b/third_party/sqlite/src/test9.c @@ -0,0 +1,193 @@ +/* +** 2007 March 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 obscure tests of the C-interface required +** for completeness. Test code is written in C for these cases +** as there is not much point in binding to Tcl. +** +** $Id: test9.c,v 1.6 2008/07/11 13:53:55 drh Exp $ +*/ +#include "sqliteInt.h" +#include "tcl.h" +#include <stdlib.h> +#include <string.h> + +/* +** c_collation_test +*/ +static int c_collation_test( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + const char *zErrFunction = "N/A"; + sqlite3 *db; + + int rc; + if( objc!=1 ){ + Tcl_WrongNumArgs(interp, 1, objv, ""); + return TCL_ERROR; + } + + /* Open a database. */ + rc = sqlite3_open(":memory:", &db); + if( rc!=SQLITE_OK ){ + zErrFunction = "sqlite3_open"; + goto error_out; + } + + rc = sqlite3_create_collation(db, "collate", 456, 0, 0); + if( rc!=SQLITE_MISUSE ){ + sqlite3_close(db); + zErrFunction = "sqlite3_create_collation"; + goto error_out; + } + + sqlite3_close(db); + return TCL_OK; + +error_out: + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "Error testing function: ", zErrFunction, 0); + return TCL_ERROR; +} + +/* +** c_realloc_test +*/ +static int c_realloc_test( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + void *p; + const char *zErrFunction = "N/A"; + + if( objc!=1 ){ + Tcl_WrongNumArgs(interp, 1, objv, ""); + return TCL_ERROR; + } + + p = sqlite3_malloc(5); + if( !p ){ + zErrFunction = "sqlite3_malloc"; + goto error_out; + } + + /* Test that realloc()ing a block of memory to a negative size is + ** the same as free()ing that memory. + */ + p = sqlite3_realloc(p, -1); + if( p ){ + zErrFunction = "sqlite3_realloc"; + goto error_out; + } + + return TCL_OK; + +error_out: + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "Error testing function: ", zErrFunction, 0); + return TCL_ERROR; +} + + +/* +** c_misuse_test +*/ +static int c_misuse_test( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + const char *zErrFunction = "N/A"; + sqlite3 *db = 0; + int rc; + + if( objc!=1 ){ + Tcl_WrongNumArgs(interp, 1, objv, ""); + return TCL_ERROR; + } + + /* Open a database. Then close it again. We need to do this so that + ** we have a "closed database handle" to pass to various API functions. + */ + rc = sqlite3_open(":memory:", &db); + if( rc!=SQLITE_OK ){ + zErrFunction = "sqlite3_open"; + goto error_out; + } + sqlite3_close(db); + + + rc = sqlite3_errcode(db); + if( rc!=SQLITE_MISUSE ){ + zErrFunction = "sqlite3_errcode"; + goto error_out; + } + + rc = sqlite3_prepare(db, 0, 0, 0, 0); + if( rc!=SQLITE_MISUSE ){ + zErrFunction = "sqlite3_prepare"; + goto error_out; + } + + rc = sqlite3_prepare_v2(db, 0, 0, 0, 0); + if( rc!=SQLITE_MISUSE ){ + zErrFunction = "sqlite3_prepare_v2"; + goto error_out; + } + +#ifndef SQLITE_OMIT_UTF16 + rc = sqlite3_prepare16(db, 0, 0, 0, 0); + if( rc!=SQLITE_MISUSE ){ + zErrFunction = "sqlite3_prepare16"; + goto error_out; + } + rc = sqlite3_prepare16_v2(db, 0, 0, 0, 0); + if( rc!=SQLITE_MISUSE ){ + zErrFunction = "sqlite3_prepare16_v2"; + goto error_out; + } +#endif + + return TCL_OK; + +error_out: + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "Error testing function: ", zErrFunction, 0); + return TCL_ERROR; +} + +/* +** Register commands with the TCL interpreter. +*/ +int Sqlitetest9_Init(Tcl_Interp *interp){ + static struct { + char *zName; + Tcl_ObjCmdProc *xProc; + void *clientData; + } aObjCmd[] = { + { "c_misuse_test", c_misuse_test, 0 }, + { "c_realloc_test", c_realloc_test, 0 }, + { "c_collation_test", c_collation_test, 0 }, + }; + int i; + for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ + Tcl_CreateObjCommand(interp, aObjCmd[i].zName, + aObjCmd[i].xProc, aObjCmd[i].clientData, 0); + } + return TCL_OK; +} diff --git a/third_party/sqlite/src/test_async.c b/third_party/sqlite/src/test_async.c new file mode 100755 index 0000000..7b48afe --- /dev/null +++ b/third_party/sqlite/src/test_async.c @@ -0,0 +1,1717 @@ +/* +** 2005 December 14 +** +** 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. +** +************************************************************************* +** +** $Id: test_async.c,v 1.45 2008/06/26 10:41:19 danielk1977 Exp $ +** +** This file contains an example implementation of an asynchronous IO +** backend for SQLite. +** +** WHAT IS ASYNCHRONOUS I/O? +** +** With asynchronous I/O, write requests are handled by a separate thread +** running in the background. This means that the thread that initiates +** a database write does not have to wait for (sometimes slow) disk I/O +** to occur. The write seems to happen very quickly, though in reality +** it is happening at its usual slow pace in the background. +** +** Asynchronous I/O appears to give better responsiveness, but at a price. +** You lose the Durable property. With the default I/O backend of SQLite, +** once a write completes, you know that the information you wrote is +** safely on disk. With the asynchronous I/O, this is not the case. If +** your program crashes or if a power lose occurs after the database +** write but before the asynchronous write thread has completed, then the +** database change might never make it to disk and the next user of the +** database might not see your change. +** +** You lose Durability with asynchronous I/O, but you still retain the +** other parts of ACID: Atomic, Consistent, and Isolated. Many +** appliations get along fine without the Durablity. +** +** HOW IT WORKS +** +** Asynchronous I/O works by creating a special SQLite "vfs" structure +** and registering it with sqlite3_vfs_register(). When files opened via +** this vfs are written to (using sqlite3OsWrite()), the data is not +** written directly to disk, but is placed in the "write-queue" to be +** handled by the background thread. +** +** When files opened with the asynchronous vfs are read from +** (using sqlite3OsRead()), the data is read from the file on +** disk and the write-queue, so that from the point of view of +** the vfs reader the OsWrite() appears to have already completed. +** +** The special vfs is registered (and unregistered) by calls to +** function asyncEnable() (see below). +** +** LIMITATIONS +** +** This demonstration code is deliberately kept simple in order to keep +** the main ideas clear and easy to understand. Real applications that +** want to do asynchronous I/O might want to add additional capabilities. +** For example, in this demonstration if writes are happening at a steady +** stream that exceeds the I/O capability of the background writer thread, +** the queue of pending write operations will grow without bound until we +** run out of memory. Users of this technique may want to keep track of +** the quantity of pending writes and stop accepting new write requests +** when the buffer gets to be too big. +** +** LOCKING + CONCURRENCY +** +** Multiple connections from within a single process that use this +** implementation of asynchronous IO may access a single database +** file concurrently. From the point of view of the user, if all +** connections are from within a single process, there is no difference +** between the concurrency offered by "normal" SQLite and SQLite +** using the asynchronous backend. +** +** If connections from within multiple database files may access the +** database file, the ENABLE_FILE_LOCKING symbol (see below) must be +** defined. If it is not defined, then no locks are established on +** the database file. In this case, if multiple processes access +** the database file, corruption will quickly result. +** +** If ENABLE_FILE_LOCKING is defined (the default), then connections +** from within multiple processes may access a single database file +** without risking corruption. However concurrency is reduced as +** follows: +** +** * When a connection using asynchronous IO begins a database +** transaction, the database is locked immediately. However the +** lock is not released until after all relevant operations +** in the write-queue have been flushed to disk. This means +** (for example) that the database may remain locked for some +** time after a "COMMIT" or "ROLLBACK" is issued. +** +** * If an application using asynchronous IO executes transactions +** in quick succession, other database users may be effectively +** locked out of the database. This is because when a BEGIN +** is executed, a database lock is established immediately. But +** when the corresponding COMMIT or ROLLBACK occurs, the lock +** is not released until the relevant part of the write-queue +** has been flushed through. As a result, if a COMMIT is followed +** by a BEGIN before the write-queue is flushed through, the database +** is never unlocked,preventing other processes from accessing +** the database. +** +** Defining ENABLE_FILE_LOCKING when using an NFS or other remote +** file-system may slow things down, as synchronous round-trips to the +** server may be required to establish database file locks. +*/ +#define ENABLE_FILE_LOCKING + +#ifndef SQLITE_AMALGAMATION +# include "sqliteInt.h" +#endif +#include <tcl.h> + +/* +** This test uses pthreads and hence only works on unix and with +** a threadsafe build of SQLite. +*/ +#if SQLITE_OS_UNIX && SQLITE_THREADSAFE + +/* +** This demo uses pthreads. If you do not have a pthreads implementation +** for your operating system, you will need to recode the threading +** logic. +*/ +#include <pthread.h> +#include <sched.h> + +/* Useful macros used in several places */ +#define MIN(x,y) ((x)<(y)?(x):(y)) +#define MAX(x,y) ((x)>(y)?(x):(y)) + +/* Forward references */ +typedef struct AsyncWrite AsyncWrite; +typedef struct AsyncFile AsyncFile; +typedef struct AsyncFileData AsyncFileData; +typedef struct AsyncFileLock AsyncFileLock; +typedef struct AsyncLock AsyncLock; + +/* Enable for debugging */ +static int sqlite3async_trace = 0; +# define ASYNC_TRACE(X) if( sqlite3async_trace ) asyncTrace X +static void asyncTrace(const char *zFormat, ...){ + char *z; + va_list ap; + va_start(ap, zFormat); + z = sqlite3_vmprintf(zFormat, ap); + va_end(ap); + fprintf(stderr, "[%d] %s", (int)pthread_self(), z); + sqlite3_free(z); +} + +/* +** THREAD SAFETY NOTES +** +** Basic rules: +** +** * Both read and write access to the global write-op queue must be +** protected by the async.queueMutex. As are the async.ioError and +** async.nFile variables. +** +** * The async.aLock hash-table and all AsyncLock and AsyncFileLock +** structures must be protected by the async.lockMutex mutex. +** +** * The file handles from the underlying system are assumed not to +** be thread safe. +** +** * See the last two paragraphs under "The Writer Thread" for +** an assumption to do with file-handle synchronization by the Os. +** +** Deadlock prevention: +** +** There are three mutex used by the system: the "writer" mutex, +** the "queue" mutex and the "lock" mutex. Rules are: +** +** * It is illegal to block on the writer mutex when any other mutex +** are held, and +** +** * It is illegal to block on the queue mutex when the lock mutex +** is held. +** +** i.e. mutex's must be grabbed in the order "writer", "queue", "lock". +** +** File system operations (invoked by SQLite thread): +** +** xOpen +** xDelete +** xFileExists +** +** File handle operations (invoked by SQLite thread): +** +** asyncWrite, asyncClose, asyncTruncate, asyncSync +** +** The operations above add an entry to the global write-op list. They +** prepare the entry, acquire the async.queueMutex momentarily while +** list pointers are manipulated to insert the new entry, then release +** the mutex and signal the writer thread to wake up in case it happens +** to be asleep. +** +** +** asyncRead, asyncFileSize. +** +** Read operations. Both of these read from both the underlying file +** first then adjust their result based on pending writes in the +** write-op queue. So async.queueMutex is held for the duration +** of these operations to prevent other threads from changing the +** queue in mid operation. +** +** +** asyncLock, asyncUnlock, asyncCheckReservedLock +** +** These primitives implement in-process locking using a hash table +** on the file name. Files are locked correctly for connections coming +** from the same process. But other processes cannot see these locks +** and will therefore not honor them. +** +** +** The writer thread: +** +** The async.writerMutex is used to make sure only there is only +** a single writer thread running at a time. +** +** Inside the writer thread is a loop that works like this: +** +** WHILE (write-op list is not empty) +** Do IO operation at head of write-op list +** Remove entry from head of write-op list +** END WHILE +** +** The async.queueMutex is always held during the <write-op list is +** not empty> test, and when the entry is removed from the head +** of the write-op list. Sometimes it is held for the interim +** period (while the IO is performed), and sometimes it is +** relinquished. It is relinquished if (a) the IO op is an +** ASYNC_CLOSE or (b) when the file handle was opened, two of +** the underlying systems handles were opened on the same +** file-system entry. +** +** If condition (b) above is true, then one file-handle +** (AsyncFile.pBaseRead) is used exclusively by sqlite threads to read the +** file, the other (AsyncFile.pBaseWrite) by sqlite3_async_flush() +** threads to perform write() operations. This means that read +** operations are not blocked by asynchronous writes (although +** asynchronous writes may still be blocked by reads). +** +** This assumes that the OS keeps two handles open on the same file +** properly in sync. That is, any read operation that starts after a +** write operation on the same file system entry has completed returns +** data consistent with the write. We also assume that if one thread +** reads a file while another is writing it all bytes other than the +** ones actually being written contain valid data. +** +** If the above assumptions are not true, set the preprocessor symbol +** SQLITE_ASYNC_TWO_FILEHANDLES to 0. +*/ + +#ifndef SQLITE_ASYNC_TWO_FILEHANDLES +/* #define SQLITE_ASYNC_TWO_FILEHANDLES 0 */ +#define SQLITE_ASYNC_TWO_FILEHANDLES 1 +#endif + +/* +** State information is held in the static variable "async" defined +** as the following structure. +** +** Both async.ioError and async.nFile are protected by async.queueMutex. +*/ +static struct TestAsyncStaticData { + pthread_mutex_t lockMutex; /* For access to aLock hash table */ + pthread_mutex_t queueMutex; /* Mutex for access to write operation queue */ + pthread_mutex_t writerMutex; /* Prevents multiple writer threads */ + pthread_cond_t queueSignal; /* For waking up sleeping writer thread */ + pthread_cond_t emptySignal; /* Notify when the write queue is empty */ + AsyncWrite *pQueueFirst; /* Next write operation to be processed */ + AsyncWrite *pQueueLast; /* Last write operation on the list */ + Hash aLock; /* Files locked */ + volatile int ioDelay; /* Extra delay between write operations */ + volatile int writerHaltWhenIdle; /* Writer thread halts when queue empty */ + volatile int writerHaltNow; /* Writer thread halts after next op */ + int ioError; /* True if an IO error has occured */ + int nFile; /* Number of open files (from sqlite pov) */ +} async = { + PTHREAD_MUTEX_INITIALIZER, + PTHREAD_MUTEX_INITIALIZER, + PTHREAD_MUTEX_INITIALIZER, + PTHREAD_COND_INITIALIZER, + PTHREAD_COND_INITIALIZER, +}; + +/* Possible values of AsyncWrite.op */ +#define ASYNC_NOOP 0 +#define ASYNC_WRITE 1 +#define ASYNC_SYNC 2 +#define ASYNC_TRUNCATE 3 +#define ASYNC_CLOSE 4 +#define ASYNC_DELETE 5 +#define ASYNC_OPENEXCLUSIVE 6 +#define ASYNC_UNLOCK 7 + +/* Names of opcodes. Used for debugging only. +** Make sure these stay in sync with the macros above! +*/ +static const char *azOpcodeName[] = { + "NOOP", "WRITE", "SYNC", "TRUNCATE", "CLOSE", "DELETE", "OPENEX", "UNLOCK" +}; + +/* +** Entries on the write-op queue are instances of the AsyncWrite +** structure, defined here. +** +** The interpretation of the iOffset and nByte variables varies depending +** on the value of AsyncWrite.op: +** +** ASYNC_NOOP: +** No values used. +** +** ASYNC_WRITE: +** iOffset -> Offset in file to write to. +** nByte -> Number of bytes of data to write (pointed to by zBuf). +** +** ASYNC_SYNC: +** nByte -> flags to pass to sqlite3OsSync(). +** +** ASYNC_TRUNCATE: +** iOffset -> Size to truncate file to. +** nByte -> Unused. +** +** ASYNC_CLOSE: +** iOffset -> Unused. +** nByte -> Unused. +** +** ASYNC_DELETE: +** iOffset -> Contains the "syncDir" flag. +** nByte -> Number of bytes of zBuf points to (file name). +** +** ASYNC_OPENEXCLUSIVE: +** iOffset -> Value of "delflag". +** nByte -> Number of bytes of zBuf points to (file name). +** +** ASYNC_UNLOCK: +** nByte -> Argument to sqlite3OsUnlock(). +** +** +** For an ASYNC_WRITE operation, zBuf points to the data to write to the file. +** This space is sqlite3_malloc()d along with the AsyncWrite structure in a +** single blob, so is deleted when sqlite3_free() is called on the parent +** structure. +*/ +struct AsyncWrite { + AsyncFileData *pFileData; /* File to write data to or sync */ + int op; /* One of ASYNC_xxx etc. */ + i64 iOffset; /* See above */ + int nByte; /* See above */ + char *zBuf; /* Data to write to file (or NULL if op!=ASYNC_WRITE) */ + AsyncWrite *pNext; /* Next write operation (to any file) */ +}; + +/* +** An instance of this structure is created for each distinct open file +** (i.e. if two handles are opened on the one file, only one of these +** structures is allocated) and stored in the async.aLock hash table. The +** keys for async.aLock are the full pathnames of the opened files. +** +** AsyncLock.pList points to the head of a linked list of AsyncFileLock +** structures, one for each handle currently open on the file. +** +** If the opened file is not a main-database (the SQLITE_OPEN_MAIN_DB is +** not passed to the sqlite3OsOpen() call), or if ENABLE_FILE_LOCKING is +** not defined at compile time, variables AsyncLock.pFile and +** AsyncLock.eLock are never used. Otherwise, pFile is a file handle +** opened on the file in question and used to obtain the file-system +** locks required by database connections within this process. +** +** See comments above the asyncLock() function for more details on +** the implementation of database locking used by this backend. +*/ +struct AsyncLock { + sqlite3_file *pFile; + int eLock; + AsyncFileLock *pList; +}; + +/* +** An instance of the following structure is allocated along with each +** AsyncFileData structure (see AsyncFileData.lock), but is only used if the +** file was opened with the SQLITE_OPEN_MAIN_DB. +*/ +struct AsyncFileLock { + int eLock; /* Internally visible lock state (sqlite pov) */ + int eAsyncLock; /* Lock-state with write-queue unlock */ + AsyncFileLock *pNext; +}; + +/* +** The AsyncFile structure is a subclass of sqlite3_file used for +** asynchronous IO. +** +** All of the actual data for the structure is stored in the structure +** pointed to by AsyncFile.pData, which is allocated as part of the +** sqlite3OsOpen() using sqlite3_malloc(). The reason for this is that the +** lifetime of the AsyncFile structure is ended by the caller after OsClose() +** is called, but the data in AsyncFileData may be required by the +** writer thread after that point. +*/ +struct AsyncFile { + sqlite3_io_methods *pMethod; + AsyncFileData *pData; +}; +struct AsyncFileData { + char *zName; /* Underlying OS filename - used for debugging */ + int nName; /* Number of characters in zName */ + sqlite3_file *pBaseRead; /* Read handle to the underlying Os file */ + sqlite3_file *pBaseWrite; /* Write handle to the underlying Os file */ + AsyncFileLock lock; + AsyncWrite close; +}; + +/* +** The following async_XXX functions are debugging wrappers around the +** corresponding pthread_XXX functions: +** +** pthread_mutex_lock(); +** pthread_mutex_unlock(); +** pthread_mutex_trylock(); +** pthread_cond_wait(); +** +** It is illegal to pass any mutex other than those stored in the +** following global variables of these functions. +** +** async.queueMutex +** async.writerMutex +** async.lockMutex +** +** If NDEBUG is defined, these wrappers do nothing except call the +** corresponding pthreads function. If NDEBUG is not defined, then the +** following variables are used to store the thread-id (as returned +** by pthread_self()) currently holding the mutex, or 0 otherwise: +** +** asyncdebug.queueMutexHolder +** asyncdebug.writerMutexHolder +** asyncdebug.lockMutexHolder +** +** These variables are used by some assert() statements that verify +** the statements made in the "Deadlock Prevention" notes earlier +** in this file. +*/ +#ifndef NDEBUG + +static struct TestAsyncDebugData { + pthread_t lockMutexHolder; + pthread_t queueMutexHolder; + pthread_t writerMutexHolder; +} asyncdebug = {0, 0, 0}; + +/* +** Wrapper around pthread_mutex_lock(). Checks that we have not violated +** the anti-deadlock rules (see "Deadlock prevention" above). +*/ +static int async_mutex_lock(pthread_mutex_t *pMutex){ + int iIdx; + int rc; + pthread_mutex_t *aMutex = (pthread_mutex_t *)(&async); + pthread_t *aHolder = (pthread_t *)(&asyncdebug); + + /* The code in this 'ifndef NDEBUG' block depends on a certain alignment + * of the variables in TestAsyncStaticData and TestAsyncDebugData. The + * following assert() statements check that this has not been changed. + * + * Really, these only need to be run once at startup time. + */ + assert(&(aMutex[0])==&async.lockMutex); + assert(&(aMutex[1])==&async.queueMutex); + assert(&(aMutex[2])==&async.writerMutex); + assert(&(aHolder[0])==&asyncdebug.lockMutexHolder); + assert(&(aHolder[1])==&asyncdebug.queueMutexHolder); + assert(&(aHolder[2])==&asyncdebug.writerMutexHolder); + + assert( pthread_self()!=0 ); + + for(iIdx=0; iIdx<3; iIdx++){ + if( pMutex==&aMutex[iIdx] ) break; + + /* This is the key assert(). Here we are checking that if the caller + * is trying to block on async.writerMutex, neither of the other two + * mutex are held. If the caller is trying to block on async.queueMutex, + * lockMutex is not held. + */ + assert(!pthread_equal(aHolder[iIdx], pthread_self())); + } + assert(iIdx<3); + + rc = pthread_mutex_lock(pMutex); + if( rc==0 ){ + assert(aHolder[iIdx]==0); + aHolder[iIdx] = pthread_self(); + } + return rc; +} + +/* +** Wrapper around pthread_mutex_unlock(). +*/ +static int async_mutex_unlock(pthread_mutex_t *pMutex){ + int iIdx; + int rc; + pthread_mutex_t *aMutex = (pthread_mutex_t *)(&async); + pthread_t *aHolder = (pthread_t *)(&asyncdebug); + + for(iIdx=0; iIdx<3; iIdx++){ + if( pMutex==&aMutex[iIdx] ) break; + } + assert(iIdx<3); + + assert(pthread_equal(aHolder[iIdx], pthread_self())); + aHolder[iIdx] = 0; + rc = pthread_mutex_unlock(pMutex); + assert(rc==0); + + return 0; +} + +/* +** Wrapper around pthread_mutex_trylock(). +*/ +static int async_mutex_trylock(pthread_mutex_t *pMutex){ + int iIdx; + int rc; + pthread_mutex_t *aMutex = (pthread_mutex_t *)(&async); + pthread_t *aHolder = (pthread_t *)(&asyncdebug); + + for(iIdx=0; iIdx<3; iIdx++){ + if( pMutex==&aMutex[iIdx] ) break; + } + assert(iIdx<3); + + rc = pthread_mutex_trylock(pMutex); + if( rc==0 ){ + assert(aHolder[iIdx]==0); + aHolder[iIdx] = pthread_self(); + } + return rc; +} + +/* +** Wrapper around pthread_cond_wait(). +*/ +static int async_cond_wait(pthread_cond_t *pCond, pthread_mutex_t *pMutex){ + int iIdx; + int rc; + pthread_mutex_t *aMutex = (pthread_mutex_t *)(&async); + pthread_t *aHolder = (pthread_t *)(&asyncdebug); + + for(iIdx=0; iIdx<3; iIdx++){ + if( pMutex==&aMutex[iIdx] ) break; + } + assert(iIdx<3); + + assert(pthread_equal(aHolder[iIdx],pthread_self())); + aHolder[iIdx] = 0; + rc = pthread_cond_wait(pCond, pMutex); + if( rc==0 ){ + aHolder[iIdx] = pthread_self(); + } + return rc; +} + +/* Call our async_XX wrappers instead of selected pthread_XX functions */ +#define pthread_mutex_lock async_mutex_lock +#define pthread_mutex_unlock async_mutex_unlock +#define pthread_mutex_trylock async_mutex_trylock +#define pthread_cond_wait async_cond_wait + +#endif /* !defined(NDEBUG) */ + +/* +** Add an entry to the end of the global write-op list. pWrite should point +** to an AsyncWrite structure allocated using sqlite3_malloc(). The writer +** thread will call sqlite3_free() to free the structure after the specified +** operation has been completed. +** +** Once an AsyncWrite structure has been added to the list, it becomes the +** property of the writer thread and must not be read or modified by the +** caller. +*/ +static void addAsyncWrite(AsyncWrite *pWrite){ + /* We must hold the queue mutex in order to modify the queue pointers */ + pthread_mutex_lock(&async.queueMutex); + + /* Add the record to the end of the write-op queue */ + assert( !pWrite->pNext ); + if( async.pQueueLast ){ + assert( async.pQueueFirst ); + async.pQueueLast->pNext = pWrite; + }else{ + async.pQueueFirst = pWrite; + } + async.pQueueLast = pWrite; + ASYNC_TRACE(("PUSH %p (%s %s %d)\n", pWrite, azOpcodeName[pWrite->op], + pWrite->pFileData ? pWrite->pFileData->zName : "-", pWrite->iOffset)); + + if( pWrite->op==ASYNC_CLOSE ){ + async.nFile--; + } + + /* Drop the queue mutex */ + pthread_mutex_unlock(&async.queueMutex); + + /* The writer thread might have been idle because there was nothing + ** on the write-op queue for it to do. So wake it up. */ + pthread_cond_signal(&async.queueSignal); +} + +/* +** Increment async.nFile in a thread-safe manner. +*/ +static void incrOpenFileCount(){ + /* We must hold the queue mutex in order to modify async.nFile */ + pthread_mutex_lock(&async.queueMutex); + if( async.nFile==0 ){ + async.ioError = SQLITE_OK; + } + async.nFile++; + pthread_mutex_unlock(&async.queueMutex); +} + +/* +** This is a utility function to allocate and populate a new AsyncWrite +** structure and insert it (via addAsyncWrite() ) into the global list. +*/ +static int addNewAsyncWrite( + AsyncFileData *pFileData, + int op, + i64 iOffset, + int nByte, + const char *zByte +){ + AsyncWrite *p; + if( op!=ASYNC_CLOSE && async.ioError ){ + return async.ioError; + } + p = sqlite3_malloc(sizeof(AsyncWrite) + (zByte?nByte:0)); + if( !p ){ + /* The upper layer does not expect operations like OsWrite() to + ** return SQLITE_NOMEM. This is partly because under normal conditions + ** SQLite is required to do rollback without calling malloc(). So + ** if malloc() fails here, treat it as an I/O error. The above + ** layer knows how to handle that. + */ + return SQLITE_IOERR; + } + p->op = op; + p->iOffset = iOffset; + p->nByte = nByte; + p->pFileData = pFileData; + p->pNext = 0; + if( zByte ){ + p->zBuf = (char *)&p[1]; + memcpy(p->zBuf, zByte, nByte); + }else{ + p->zBuf = 0; + } + addAsyncWrite(p); + return SQLITE_OK; +} + +/* +** Close the file. This just adds an entry to the write-op list, the file is +** not actually closed. +*/ +static int asyncClose(sqlite3_file *pFile){ + AsyncFileData *p = ((AsyncFile *)pFile)->pData; + + /* Unlock the file, if it is locked */ + pthread_mutex_lock(&async.lockMutex); + p->lock.eLock = 0; + pthread_mutex_unlock(&async.lockMutex); + + addAsyncWrite(&p->close); + return SQLITE_OK; +} + +/* +** Implementation of sqlite3OsWrite() for asynchronous files. Instead of +** writing to the underlying file, this function adds an entry to the end of +** the global AsyncWrite list. Either SQLITE_OK or SQLITE_NOMEM may be +** returned. +*/ +static int asyncWrite(sqlite3_file *pFile, const void *pBuf, int amt, i64 iOff){ + AsyncFileData *p = ((AsyncFile *)pFile)->pData; + return addNewAsyncWrite(p, ASYNC_WRITE, iOff, amt, pBuf); +} + +/* +** Read data from the file. First we read from the filesystem, then adjust +** the contents of the buffer based on ASYNC_WRITE operations in the +** write-op queue. +** +** This method holds the mutex from start to finish. +*/ +static int asyncRead(sqlite3_file *pFile, void *zOut, int iAmt, i64 iOffset){ + AsyncFileData *p = ((AsyncFile *)pFile)->pData; + int rc = SQLITE_OK; + i64 filesize; + int nRead; + sqlite3_file *pBase = p->pBaseRead; + + /* Grab the write queue mutex for the duration of the call */ + pthread_mutex_lock(&async.queueMutex); + + /* If an I/O error has previously occurred in this virtual file + ** system, then all subsequent operations fail. + */ + if( async.ioError!=SQLITE_OK ){ + rc = async.ioError; + goto asyncread_out; + } + + if( pBase->pMethods ){ + rc = sqlite3OsFileSize(pBase, &filesize); + if( rc!=SQLITE_OK ){ + goto asyncread_out; + } + nRead = MIN(filesize - iOffset, iAmt); + if( nRead>0 ){ + rc = sqlite3OsRead(pBase, zOut, nRead, iOffset); + ASYNC_TRACE(("READ %s %d bytes at %d\n", p->zName, nRead, iOffset)); + } + } + + if( rc==SQLITE_OK ){ + AsyncWrite *pWrite; + char *zName = p->zName; + + for(pWrite=async.pQueueFirst; pWrite; pWrite = pWrite->pNext){ + if( pWrite->op==ASYNC_WRITE && pWrite->pFileData->zName==zName ){ + int iBeginOut = (pWrite->iOffset-iOffset); + int iBeginIn = -iBeginOut; + int nCopy; + + if( iBeginIn<0 ) iBeginIn = 0; + if( iBeginOut<0 ) iBeginOut = 0; + nCopy = MIN(pWrite->nByte-iBeginIn, iAmt-iBeginOut); + + if( nCopy>0 ){ + memcpy(&((char *)zOut)[iBeginOut], &pWrite->zBuf[iBeginIn], nCopy); + ASYNC_TRACE(("OVERREAD %d bytes at %d\n", nCopy, iBeginOut+iOffset)); + } + } + } + } + +asyncread_out: + pthread_mutex_unlock(&async.queueMutex); + return rc; +} + +/* +** Truncate the file to nByte bytes in length. This just adds an entry to +** the write-op list, no IO actually takes place. +*/ +static int asyncTruncate(sqlite3_file *pFile, i64 nByte){ + AsyncFileData *p = ((AsyncFile *)pFile)->pData; + return addNewAsyncWrite(p, ASYNC_TRUNCATE, nByte, 0, 0); +} + +/* +** Sync the file. This just adds an entry to the write-op list, the +** sync() is done later by sqlite3_async_flush(). +*/ +static int asyncSync(sqlite3_file *pFile, int flags){ + AsyncFileData *p = ((AsyncFile *)pFile)->pData; + return addNewAsyncWrite(p, ASYNC_SYNC, 0, flags, 0); +} + +/* +** Read the size of the file. First we read the size of the file system +** entry, then adjust for any ASYNC_WRITE or ASYNC_TRUNCATE operations +** currently in the write-op list. +** +** This method holds the mutex from start to finish. +*/ +int asyncFileSize(sqlite3_file *pFile, i64 *piSize){ + AsyncFileData *p = ((AsyncFile *)pFile)->pData; + int rc = SQLITE_OK; + i64 s = 0; + sqlite3_file *pBase; + + pthread_mutex_lock(&async.queueMutex); + + /* Read the filesystem size from the base file. If pBaseRead is NULL, this + ** means the file hasn't been opened yet. In this case all relevant data + ** must be in the write-op queue anyway, so we can omit reading from the + ** file-system. + */ + pBase = p->pBaseRead; + if( pBase->pMethods ){ + rc = sqlite3OsFileSize(pBase, &s); + } + + if( rc==SQLITE_OK ){ + AsyncWrite *pWrite; + for(pWrite=async.pQueueFirst; pWrite; pWrite = pWrite->pNext){ + if( pWrite->op==ASYNC_DELETE && strcmp(p->zName, pWrite->zBuf)==0 ){ + s = 0; + }else if( pWrite->pFileData && pWrite->pFileData->zName==p->zName){ + switch( pWrite->op ){ + case ASYNC_WRITE: + s = MAX(pWrite->iOffset + (i64)(pWrite->nByte), s); + break; + case ASYNC_TRUNCATE: + s = MIN(s, pWrite->iOffset); + break; + } + } + } + *piSize = s; + } + pthread_mutex_unlock(&async.queueMutex); + return rc; +} + +/* +** Lock or unlock the actual file-system entry. +*/ +static int getFileLock(AsyncLock *pLock){ + int rc = SQLITE_OK; + AsyncFileLock *pIter; + int eRequired = 0; + + if( pLock->pFile ){ + for(pIter=pLock->pList; pIter; pIter=pIter->pNext){ + assert(pIter->eAsyncLock>=pIter->eLock); + if( pIter->eAsyncLock>eRequired ){ + eRequired = pIter->eAsyncLock; + assert(eRequired>=0 && eRequired<=SQLITE_LOCK_EXCLUSIVE); + } + } + + if( eRequired>pLock->eLock ){ + rc = sqlite3OsLock(pLock->pFile, eRequired); + if( rc==SQLITE_OK ){ + pLock->eLock = eRequired; + } + } + else if( eRequired<pLock->eLock && eRequired<=SQLITE_LOCK_SHARED ){ + rc = sqlite3OsUnlock(pLock->pFile, eRequired); + if( rc==SQLITE_OK ){ + pLock->eLock = eRequired; + } + } + } + + return rc; +} + +/* +** The following two methods - asyncLock() and asyncUnlock() - are used +** to obtain and release locks on database files opened with the +** asynchronous backend. +*/ +static int asyncLock(sqlite3_file *pFile, int eLock){ + int rc = SQLITE_OK; + AsyncFileData *p = ((AsyncFile *)pFile)->pData; + + pthread_mutex_lock(&async.lockMutex); + if( p->lock.eLock<eLock ){ + AsyncLock *pLock; + AsyncFileLock *pIter; + pLock = (AsyncLock *)sqlite3HashFind(&async.aLock, p->zName, p->nName); + assert(pLock && pLock->pList); + for(pIter=pLock->pList; pIter; pIter=pIter->pNext){ + if( pIter!=&p->lock && ( + (eLock==SQLITE_LOCK_EXCLUSIVE && pIter->eLock>=SQLITE_LOCK_SHARED) || + (eLock==SQLITE_LOCK_PENDING && pIter->eLock>=SQLITE_LOCK_RESERVED) || + (eLock==SQLITE_LOCK_RESERVED && pIter->eLock>=SQLITE_LOCK_RESERVED) || + (eLock==SQLITE_LOCK_SHARED && pIter->eLock>=SQLITE_LOCK_PENDING) + )){ + rc = SQLITE_BUSY; + } + } + if( rc==SQLITE_OK ){ + p->lock.eLock = eLock; + p->lock.eAsyncLock = MAX(p->lock.eAsyncLock, eLock); + } + assert(p->lock.eAsyncLock>=p->lock.eLock); + if( rc==SQLITE_OK ){ + rc = getFileLock(pLock); + } + } + pthread_mutex_unlock(&async.lockMutex); + + ASYNC_TRACE(("LOCK %d (%s) rc=%d\n", eLock, p->zName, rc)); + return rc; +} +static int asyncUnlock(sqlite3_file *pFile, int eLock){ + AsyncFileData *p = ((AsyncFile *)pFile)->pData; + AsyncFileLock *pLock = &p->lock; + pthread_mutex_lock(&async.lockMutex); + pLock->eLock = MIN(pLock->eLock, eLock); + pthread_mutex_unlock(&async.lockMutex); + return addNewAsyncWrite(p, ASYNC_UNLOCK, 0, eLock, 0); +} + +/* +** This function is called when the pager layer first opens a database file +** and is checking for a hot-journal. +*/ +static int asyncCheckReservedLock(sqlite3_file *pFile, int *pResOut){ + int ret = 0; + AsyncFileLock *pIter; + AsyncLock *pLock; + AsyncFileData *p = ((AsyncFile *)pFile)->pData; + + pthread_mutex_lock(&async.lockMutex); + pLock = (AsyncLock *)sqlite3HashFind(&async.aLock, p->zName, p->nName); + for(pIter=pLock->pList; pIter; pIter=pIter->pNext){ + if( pIter->eLock>=SQLITE_LOCK_RESERVED ){ + ret = 1; + } + } + pthread_mutex_unlock(&async.lockMutex); + + ASYNC_TRACE(("CHECK-LOCK %d (%s)\n", ret, p->zName)); + *pResOut = ret; + return SQLITE_OK; +} + +/* +** This is a no-op, as the asynchronous backend does not support locking. +*/ +static int asyncFileControl(sqlite3_file *id, int op, void *pArg){ + switch( op ){ + case SQLITE_FCNTL_LOCKSTATE: { + pthread_mutex_lock(&async.lockMutex); + *(int*)pArg = ((AsyncFile*)id)->pData->lock.eLock; + pthread_mutex_unlock(&async.lockMutex); + return SQLITE_OK; + } + } + return SQLITE_ERROR; +} + +/* +** Return the device characteristics and sector-size of the device. It +** is not tricky to implement these correctly, as this backend might +** not have an open file handle at this point. +*/ +static int asyncSectorSize(sqlite3_file *pFile){ + return 512; +} +static int asyncDeviceCharacteristics(sqlite3_file *pFile){ + return 0; +} + +static int unlinkAsyncFile(AsyncFileData *pData){ + AsyncLock *pLock; + AsyncFileLock **ppIter; + int rc = SQLITE_OK; + + pLock = sqlite3HashFind(&async.aLock, pData->zName, pData->nName); + for(ppIter=&pLock->pList; *ppIter; ppIter=&((*ppIter)->pNext)){ + if( (*ppIter)==&pData->lock ){ + *ppIter = pData->lock.pNext; + break; + } + } + if( !pLock->pList ){ + if( pLock->pFile ){ + sqlite3OsClose(pLock->pFile); + } + sqlite3_free(pLock); + sqlite3HashInsert(&async.aLock, pData->zName, pData->nName, 0); + if( !sqliteHashFirst(&async.aLock) ){ + sqlite3HashClear(&async.aLock); + } + }else{ + rc = getFileLock(pLock); + } + + return rc; +} + +/* +** Open a file. +*/ +static int asyncOpen( + sqlite3_vfs *pAsyncVfs, + const char *zName, + sqlite3_file *pFile, + int flags, + int *pOutFlags +){ + static sqlite3_io_methods async_methods = { + 1, /* iVersion */ + asyncClose, /* xClose */ + asyncRead, /* xRead */ + asyncWrite, /* xWrite */ + asyncTruncate, /* xTruncate */ + asyncSync, /* xSync */ + asyncFileSize, /* xFileSize */ + asyncLock, /* xLock */ + asyncUnlock, /* xUnlock */ + asyncCheckReservedLock, /* xCheckReservedLock */ + asyncFileControl, /* xFileControl */ + asyncSectorSize, /* xSectorSize */ + asyncDeviceCharacteristics /* xDeviceCharacteristics */ + }; + + sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData; + AsyncFile *p = (AsyncFile *)pFile; + int nName = strlen(zName)+1; + int rc = SQLITE_OK; + int nByte; + AsyncFileData *pData; + AsyncLock *pLock = 0; + char *z; + int isExclusive = (flags&SQLITE_OPEN_EXCLUSIVE); + + nByte = ( + sizeof(AsyncFileData) + /* AsyncFileData structure */ + 2 * pVfs->szOsFile + /* AsyncFileData.pBaseRead and pBaseWrite */ + nName /* AsyncFileData.zName */ + ); + z = sqlite3_malloc(nByte); + if( !z ){ + return SQLITE_NOMEM; + } + memset(z, 0, nByte); + pData = (AsyncFileData*)z; + z += sizeof(pData[0]); + pData->pBaseRead = (sqlite3_file*)z; + z += pVfs->szOsFile; + pData->pBaseWrite = (sqlite3_file*)z; + z += pVfs->szOsFile; + pData->zName = z; + pData->nName = nName; + pData->close.pFileData = pData; + pData->close.op = ASYNC_CLOSE; + memcpy(pData->zName, zName, nName); + + if( !isExclusive ){ + rc = sqlite3OsOpen(pVfs, zName, pData->pBaseRead, flags, pOutFlags); + if( rc==SQLITE_OK && ((*pOutFlags)&SQLITE_OPEN_READWRITE) ){ + rc = sqlite3OsOpen(pVfs, zName, pData->pBaseWrite, flags, 0); + } + } + + pthread_mutex_lock(&async.lockMutex); + + if( rc==SQLITE_OK ){ + pLock = sqlite3HashFind(&async.aLock, pData->zName, pData->nName); + if( !pLock ){ + pLock = sqlite3MallocZero(pVfs->szOsFile + sizeof(AsyncLock)); + if( pLock ){ + AsyncLock *pDelete; +#ifdef ENABLE_FILE_LOCKING + if( flags&SQLITE_OPEN_MAIN_DB ){ + pLock->pFile = (sqlite3_file *)&pLock[1]; + rc = sqlite3OsOpen(pVfs, zName, pLock->pFile, flags, 0); + if( rc!=SQLITE_OK ){ + sqlite3_free(pLock); + pLock = 0; + } + } +#endif + pDelete = sqlite3HashInsert( + &async.aLock, pData->zName, pData->nName, (void *)pLock + ); + if( pDelete ){ + rc = SQLITE_NOMEM; + sqlite3_free(pLock); + } + }else{ + rc = SQLITE_NOMEM; + } + } + } + + if( rc==SQLITE_OK ){ + HashElem *pElem; + p->pMethod = &async_methods; + p->pData = pData; + + /* Link AsyncFileData.lock into the linked list of + ** AsyncFileLock structures for this file. + */ + pData->lock.pNext = pLock->pList; + pLock->pList = &pData->lock; + + pElem = sqlite3HashFindElem(&async.aLock, pData->zName, pData->nName); + pData->zName = (char *)sqliteHashKey(pElem); + }else{ + sqlite3OsClose(pData->pBaseRead); + sqlite3OsClose(pData->pBaseWrite); + sqlite3_free(pData); + } + + pthread_mutex_unlock(&async.lockMutex); + + if( rc==SQLITE_OK ){ + incrOpenFileCount(); + } + + if( rc==SQLITE_OK && isExclusive ){ + rc = addNewAsyncWrite(pData, ASYNC_OPENEXCLUSIVE, (i64)flags, 0, 0); + if( rc==SQLITE_OK ){ + if( pOutFlags ) *pOutFlags = flags; + }else{ + pthread_mutex_lock(&async.lockMutex); + unlinkAsyncFile(pData); + pthread_mutex_unlock(&async.lockMutex); + sqlite3_free(pData); + } + } + return rc; +} + +/* +** Implementation of sqlite3OsDelete. Add an entry to the end of the +** write-op queue to perform the delete. +*/ +static int asyncDelete(sqlite3_vfs *pAsyncVfs, const char *z, int syncDir){ + return addNewAsyncWrite(0, ASYNC_DELETE, syncDir, strlen(z)+1, z); +} + +/* +** Implementation of sqlite3OsAccess. This method holds the mutex from +** start to finish. +*/ +static int asyncAccess( + sqlite3_vfs *pAsyncVfs, + const char *zName, + int flags, + int *pResOut +){ + int rc; + int ret; + AsyncWrite *p; + sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData; + + assert(flags==SQLITE_ACCESS_READWRITE + || flags==SQLITE_ACCESS_READ + || flags==SQLITE_ACCESS_EXISTS + ); + + pthread_mutex_lock(&async.queueMutex); + rc = sqlite3OsAccess(pVfs, zName, flags, &ret); + if( rc==SQLITE_OK && flags==SQLITE_ACCESS_EXISTS ){ + for(p=async.pQueueFirst; p; p = p->pNext){ + if( p->op==ASYNC_DELETE && 0==strcmp(p->zBuf, zName) ){ + ret = 0; + }else if( p->op==ASYNC_OPENEXCLUSIVE + && 0==strcmp(p->pFileData->zName, zName) + ){ + ret = 1; + } + } + } + ASYNC_TRACE(("ACCESS(%s): %s = %d\n", + flags==SQLITE_ACCESS_READWRITE?"read-write": + flags==SQLITE_ACCESS_READ?"read":"exists" + , zName, ret) + ); + pthread_mutex_unlock(&async.queueMutex); + *pResOut = ret; + return rc; +} + +/* +** Fill in zPathOut with the full path to the file identified by zPath. +*/ +static int asyncFullPathname( + sqlite3_vfs *pAsyncVfs, + const char *zPath, + int nPathOut, + char *zPathOut +){ + int rc; + sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData; + rc = sqlite3OsFullPathname(pVfs, zPath, nPathOut, zPathOut); + + /* Because of the way intra-process file locking works, this backend + ** needs to return a canonical path. The following block assumes the + ** file-system uses unix style paths. + */ + if( rc==SQLITE_OK ){ + int iIn; + int iOut = 0; + int nPathOut = strlen(zPathOut); + + for(iIn=0; iIn<nPathOut; iIn++){ + + /* Replace any occurences of "//" with "/" */ + if( iIn<=(nPathOut-2) && zPathOut[iIn]=='/' && zPathOut[iIn+1]=='/' + ){ + continue; + } + + /* Replace any occurences of "/./" with "/" */ + if( iIn<=(nPathOut-3) + && zPathOut[iIn]=='/' && zPathOut[iIn+1]=='.' && zPathOut[iIn+2]=='/' + ){ + iIn++; + continue; + } + + /* Replace any occurences of "<path-component>/../" with "" */ + if( iOut>0 && iIn<=(nPathOut-4) + && zPathOut[iIn]=='/' && zPathOut[iIn+1]=='.' + && zPathOut[iIn+2]=='.' && zPathOut[iIn+3]=='/' + ){ + iIn += 3; + iOut--; + for( ; iOut>0 && zPathOut[iOut-1]!='/'; iOut--); + continue; + } + + zPathOut[iOut++] = zPathOut[iIn]; + } + zPathOut[iOut] = '\0'; + } + + return rc; +} +static void *asyncDlOpen(sqlite3_vfs *pAsyncVfs, const char *zPath){ + sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData; + return pVfs->xDlOpen(pVfs, zPath); +} +static void asyncDlError(sqlite3_vfs *pAsyncVfs, int nByte, char *zErrMsg){ + sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData; + pVfs->xDlError(pVfs, nByte, zErrMsg); +} +static void *asyncDlSym( + sqlite3_vfs *pAsyncVfs, + void *pHandle, + const char *zSymbol +){ + sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData; + return pVfs->xDlSym(pVfs, pHandle, zSymbol); +} +static void asyncDlClose(sqlite3_vfs *pAsyncVfs, void *pHandle){ + sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData; + pVfs->xDlClose(pVfs, pHandle); +} +static int asyncRandomness(sqlite3_vfs *pAsyncVfs, int nByte, char *zBufOut){ + sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData; + return pVfs->xRandomness(pVfs, nByte, zBufOut); +} +static int asyncSleep(sqlite3_vfs *pAsyncVfs, int nMicro){ + sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData; + return pVfs->xSleep(pVfs, nMicro); +} +static int asyncCurrentTime(sqlite3_vfs *pAsyncVfs, double *pTimeOut){ + sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData; + return pVfs->xCurrentTime(pVfs, pTimeOut); +} + +static sqlite3_vfs async_vfs = { + 1, /* iVersion */ + sizeof(AsyncFile), /* szOsFile */ + 0, /* mxPathname */ + 0, /* pNext */ + "async", /* zName */ + 0, /* pAppData */ + asyncOpen, /* xOpen */ + asyncDelete, /* xDelete */ + asyncAccess, /* xAccess */ + asyncFullPathname, /* xFullPathname */ + asyncDlOpen, /* xDlOpen */ + asyncDlError, /* xDlError */ + asyncDlSym, /* xDlSym */ + asyncDlClose, /* xDlClose */ + asyncRandomness, /* xDlError */ + asyncSleep, /* xDlSym */ + asyncCurrentTime /* xDlClose */ +}; + +/* +** Call this routine to enable or disable the +** asynchronous IO features implemented in this file. +** +** This routine is not even remotely threadsafe. Do not call +** this routine while any SQLite database connections are open. +*/ +static void asyncEnable(int enable){ + if( enable ){ + if( !async_vfs.pAppData ){ + static int hashTableInit = 0; + async_vfs.pAppData = (void *)sqlite3_vfs_find(0); + async_vfs.mxPathname = ((sqlite3_vfs *)async_vfs.pAppData)->mxPathname; + sqlite3_vfs_register(&async_vfs, 1); + if( !hashTableInit ){ + sqlite3HashInit(&async.aLock, SQLITE_HASH_BINARY, 1); + hashTableInit = 1; + } + } + }else{ + if( async_vfs.pAppData ){ + sqlite3_vfs_unregister(&async_vfs); + async_vfs.pAppData = 0; + } + } +} + +/* +** This procedure runs in a separate thread, reading messages off of the +** write queue and processing them one by one. +** +** If async.writerHaltNow is true, then this procedure exits +** after processing a single message. +** +** If async.writerHaltWhenIdle is true, then this procedure exits when +** the write queue is empty. +** +** If both of the above variables are false, this procedure runs +** indefinately, waiting for operations to be added to the write queue +** and processing them in the order in which they arrive. +** +** An artifical delay of async.ioDelay milliseconds is inserted before +** each write operation in order to simulate the effect of a slow disk. +** +** Only one instance of this procedure may be running at a time. +*/ +static void *asyncWriterThread(void *pIsStarted){ + sqlite3_vfs *pVfs = (sqlite3_vfs *)(async_vfs.pAppData); + AsyncWrite *p = 0; + int rc = SQLITE_OK; + int holdingMutex = 0; + + if( pthread_mutex_trylock(&async.writerMutex) ){ + return 0; + } + (*(int *)pIsStarted) = 1; + while( async.writerHaltNow==0 ){ + int doNotFree = 0; + sqlite3_file *pBase = 0; + + if( !holdingMutex ){ + pthread_mutex_lock(&async.queueMutex); + } + while( (p = async.pQueueFirst)==0 ){ + pthread_cond_broadcast(&async.emptySignal); + if( async.writerHaltWhenIdle ){ + pthread_mutex_unlock(&async.queueMutex); + break; + }else{ + ASYNC_TRACE(("IDLE\n")); + pthread_cond_wait(&async.queueSignal, &async.queueMutex); + ASYNC_TRACE(("WAKEUP\n")); + } + } + if( p==0 ) break; + holdingMutex = 1; + + /* Right now this thread is holding the mutex on the write-op queue. + ** Variable 'p' points to the first entry in the write-op queue. In + ** the general case, we hold on to the mutex for the entire body of + ** the loop. + ** + ** However in the cases enumerated below, we relinquish the mutex, + ** perform the IO, and then re-request the mutex before removing 'p' from + ** the head of the write-op queue. The idea is to increase concurrency with + ** sqlite threads. + ** + ** * An ASYNC_CLOSE operation. + ** * An ASYNC_OPENEXCLUSIVE operation. For this one, we relinquish + ** the mutex, call the underlying xOpenExclusive() function, then + ** re-aquire the mutex before seting the AsyncFile.pBaseRead + ** variable. + ** * ASYNC_SYNC and ASYNC_WRITE operations, if + ** SQLITE_ASYNC_TWO_FILEHANDLES was set at compile time and two + ** file-handles are open for the particular file being "synced". + */ + if( async.ioError!=SQLITE_OK && p->op!=ASYNC_CLOSE ){ + p->op = ASYNC_NOOP; + } + if( p->pFileData ){ + pBase = p->pFileData->pBaseWrite; + if( + p->op==ASYNC_CLOSE || + p->op==ASYNC_OPENEXCLUSIVE || + (pBase->pMethods && (p->op==ASYNC_SYNC || p->op==ASYNC_WRITE) ) + ){ + pthread_mutex_unlock(&async.queueMutex); + holdingMutex = 0; + } + if( !pBase->pMethods ){ + pBase = p->pFileData->pBaseRead; + } + } + + switch( p->op ){ + case ASYNC_NOOP: + break; + + case ASYNC_WRITE: + assert( pBase ); + ASYNC_TRACE(("WRITE %s %d bytes at %d\n", + p->pFileData->zName, p->nByte, p->iOffset)); + rc = sqlite3OsWrite(pBase, (void *)(p->zBuf), p->nByte, p->iOffset); + break; + + case ASYNC_SYNC: + assert( pBase ); + ASYNC_TRACE(("SYNC %s\n", p->pFileData->zName)); + rc = sqlite3OsSync(pBase, p->nByte); + break; + + case ASYNC_TRUNCATE: + assert( pBase ); + ASYNC_TRACE(("TRUNCATE %s to %d bytes\n", + p->pFileData->zName, p->iOffset)); + rc = sqlite3OsTruncate(pBase, p->iOffset); + break; + + case ASYNC_CLOSE: { + AsyncFileData *pData = p->pFileData; + ASYNC_TRACE(("CLOSE %s\n", p->pFileData->zName)); + sqlite3OsClose(pData->pBaseWrite); + sqlite3OsClose(pData->pBaseRead); + + /* Unlink AsyncFileData.lock from the linked list of AsyncFileLock + ** structures for this file. Obtain the async.lockMutex mutex + ** before doing so. + */ + pthread_mutex_lock(&async.lockMutex); + rc = unlinkAsyncFile(pData); + pthread_mutex_unlock(&async.lockMutex); + + async.pQueueFirst = p->pNext; + sqlite3_free(pData); + doNotFree = 1; + break; + } + + case ASYNC_UNLOCK: { + AsyncLock *pLock; + AsyncFileData *pData = p->pFileData; + int eLock = p->nByte; + pthread_mutex_lock(&async.lockMutex); + pData->lock.eAsyncLock = MIN( + pData->lock.eAsyncLock, MAX(pData->lock.eLock, eLock) + ); + assert(pData->lock.eAsyncLock>=pData->lock.eLock); + pLock = sqlite3HashFind(&async.aLock, pData->zName, pData->nName); + rc = getFileLock(pLock); + pthread_mutex_unlock(&async.lockMutex); + break; + } + + case ASYNC_DELETE: + ASYNC_TRACE(("DELETE %s\n", p->zBuf)); + rc = sqlite3OsDelete(pVfs, p->zBuf, (int)p->iOffset); + break; + + case ASYNC_OPENEXCLUSIVE: { + int flags = (int)p->iOffset; + AsyncFileData *pData = p->pFileData; + ASYNC_TRACE(("OPEN %s flags=%d\n", p->zBuf, (int)p->iOffset)); + assert(pData->pBaseRead->pMethods==0 && pData->pBaseWrite->pMethods==0); + rc = sqlite3OsOpen(pVfs, pData->zName, pData->pBaseRead, flags, 0); + assert( holdingMutex==0 ); + pthread_mutex_lock(&async.queueMutex); + holdingMutex = 1; + break; + } + + default: assert(!"Illegal value for AsyncWrite.op"); + } + + /* If we didn't hang on to the mutex during the IO op, obtain it now + ** so that the AsyncWrite structure can be safely removed from the + ** global write-op queue. + */ + if( !holdingMutex ){ + pthread_mutex_lock(&async.queueMutex); + holdingMutex = 1; + } + /* ASYNC_TRACE(("UNLINK %p\n", p)); */ + if( p==async.pQueueLast ){ + async.pQueueLast = 0; + } + if( !doNotFree ){ + async.pQueueFirst = p->pNext; + sqlite3_free(p); + } + assert( holdingMutex ); + + /* An IO error has occured. We cannot report the error back to the + ** connection that requested the I/O since the error happened + ** asynchronously. The connection has already moved on. There + ** really is nobody to report the error to. + ** + ** The file for which the error occured may have been a database or + ** journal file. Regardless, none of the currently queued operations + ** associated with the same database should now be performed. Nor should + ** any subsequently requested IO on either a database or journal file + ** handle for the same database be accepted until the main database + ** file handle has been closed and reopened. + ** + ** Furthermore, no further IO should be queued or performed on any file + ** handle associated with a database that may have been part of a + ** multi-file transaction that included the database associated with + ** the IO error (i.e. a database ATTACHed to the same handle at some + ** point in time). + */ + if( rc!=SQLITE_OK ){ + async.ioError = rc; + } + + if( async.ioError && !async.pQueueFirst ){ + pthread_mutex_lock(&async.lockMutex); + if( 0==sqliteHashFirst(&async.aLock) ){ + async.ioError = SQLITE_OK; + } + pthread_mutex_unlock(&async.lockMutex); + } + + /* Drop the queue mutex before continuing to the next write operation + ** in order to give other threads a chance to work with the write queue. + */ + if( !async.pQueueFirst || !async.ioError ){ + pthread_mutex_unlock(&async.queueMutex); + holdingMutex = 0; + if( async.ioDelay>0 ){ + sqlite3OsSleep(pVfs, async.ioDelay); + }else{ + sched_yield(); + } + } + } + + pthread_mutex_unlock(&async.writerMutex); + return 0; +} + +/************************************************************************** +** The remaining code defines a Tcl interface for testing the asynchronous +** IO implementation in this file. +** +** To adapt the code to a non-TCL environment, delete or comment out +** the code that follows. +*/ + +/* +** sqlite3async_enable ?YES/NO? +** +** Enable or disable the asynchronous I/O backend. This command is +** not thread-safe. Do not call it while any database connections +** are open. +*/ +static int testAsyncEnable( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + if( objc!=1 && objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "?YES/NO?"); + return TCL_ERROR; + } + if( objc==1 ){ + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(async_vfs.pAppData!=0)); + }else{ + int en; + if( Tcl_GetBooleanFromObj(interp, objv[1], &en) ) return TCL_ERROR; + asyncEnable(en); + } + return TCL_OK; +} + +/* +** sqlite3async_halt "now"|"idle"|"never" +** +** Set the conditions at which the writer thread will halt. +*/ +static int testAsyncHalt( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + const char *zCond; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "\"now\"|\"idle\"|\"never\""); + return TCL_ERROR; + } + zCond = Tcl_GetString(objv[1]); + if( strcmp(zCond, "now")==0 ){ + async.writerHaltNow = 1; + pthread_cond_broadcast(&async.queueSignal); + }else if( strcmp(zCond, "idle")==0 ){ + async.writerHaltWhenIdle = 1; + async.writerHaltNow = 0; + pthread_cond_broadcast(&async.queueSignal); + }else if( strcmp(zCond, "never")==0 ){ + async.writerHaltWhenIdle = 0; + async.writerHaltNow = 0; + }else{ + Tcl_AppendResult(interp, + "should be one of: \"now\", \"idle\", or \"never\"", (char*)0); + return TCL_ERROR; + } + return TCL_OK; +} + +/* +** sqlite3async_delay ?MS? +** +** Query or set the number of milliseconds of delay in the writer +** thread after each write operation. The default is 0. By increasing +** the memory delay we can simulate the effect of slow disk I/O. +*/ +static int testAsyncDelay( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + if( objc!=1 && objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "?MS?"); + return TCL_ERROR; + } + if( objc==1 ){ + Tcl_SetObjResult(interp, Tcl_NewIntObj(async.ioDelay)); + }else{ + int ioDelay; + if( Tcl_GetIntFromObj(interp, objv[1], &ioDelay) ) return TCL_ERROR; + async.ioDelay = ioDelay; + } + return TCL_OK; +} + +/* +** sqlite3async_start +** +** Start a new writer thread. +*/ +static int testAsyncStart( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + pthread_t x; + int rc; + volatile int isStarted = 0; + rc = pthread_create(&x, 0, asyncWriterThread, (void *)&isStarted); + if( rc ){ + Tcl_AppendResult(interp, "failed to create the thread", 0); + return TCL_ERROR; + } + pthread_detach(x); + while( isStarted==0 ){ + sched_yield(); + } + return TCL_OK; +} + +/* +** sqlite3async_wait +** +** Wait for the current writer thread to terminate. +** +** If the current writer thread is set to run forever then this +** command would block forever. To prevent that, an error is returned. +*/ +static int testAsyncWait( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int cnt = 10; + if( async.writerHaltNow==0 && async.writerHaltWhenIdle==0 ){ + Tcl_AppendResult(interp, "would block forever", (char*)0); + return TCL_ERROR; + } + + while( cnt-- && !pthread_mutex_trylock(&async.writerMutex) ){ + pthread_mutex_unlock(&async.writerMutex); + sched_yield(); + } + if( cnt>=0 ){ + ASYNC_TRACE(("WAIT\n")); + pthread_mutex_lock(&async.queueMutex); + pthread_cond_broadcast(&async.queueSignal); + pthread_mutex_unlock(&async.queueMutex); + pthread_mutex_lock(&async.writerMutex); + pthread_mutex_unlock(&async.writerMutex); + }else{ + ASYNC_TRACE(("NO-WAIT\n")); + } + return TCL_OK; +} + + +#endif /* SQLITE_OS_UNIX and SQLITE_THREADSAFE */ + +/* +** This routine registers the custom TCL commands defined in this +** module. This should be the only procedure visible from outside +** of this module. +*/ +int Sqlitetestasync_Init(Tcl_Interp *interp){ +#if SQLITE_OS_UNIX && SQLITE_THREADSAFE + Tcl_CreateObjCommand(interp,"sqlite3async_enable",testAsyncEnable,0,0); + Tcl_CreateObjCommand(interp,"sqlite3async_halt",testAsyncHalt,0,0); + Tcl_CreateObjCommand(interp,"sqlite3async_delay",testAsyncDelay,0,0); + Tcl_CreateObjCommand(interp,"sqlite3async_start",testAsyncStart,0,0); + Tcl_CreateObjCommand(interp,"sqlite3async_wait",testAsyncWait,0,0); + Tcl_LinkVar(interp, "sqlite3async_trace", + (char*)&sqlite3async_trace, TCL_LINK_INT); +#endif /* SQLITE_OS_UNIX and SQLITE_THREADSAFE */ + return TCL_OK; +} diff --git a/third_party/sqlite/src/test_autoext.c b/third_party/sqlite/src/test_autoext.c new file mode 100755 index 0000000..11f5413 --- /dev/null +++ b/third_party/sqlite/src/test_autoext.c @@ -0,0 +1,169 @@ +/* +** 2006 August 23 +** +** 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. +** +************************************************************************* +** Test extension for testing the sqlite3_auto_extension() function. +** +** $Id: test_autoext.c,v 1.5 2008/07/08 02:12:37 drh Exp $ +*/ +#include "tcl.h" +#include "sqlite3ext.h" + +#ifndef SQLITE_OMIT_LOAD_EXTENSION +static SQLITE_EXTENSION_INIT1 + +/* +** The sqr() SQL function returns the square of its input value. +*/ +static void sqrFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + double r = sqlite3_value_double(argv[0]); + sqlite3_result_double(context, r*r); +} + +/* +** This is the entry point to register the extension for the sqr() function. +*/ +static int sqr_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + SQLITE_EXTENSION_INIT2(pApi); + sqlite3_create_function(db, "sqr", 1, SQLITE_ANY, 0, sqrFunc, 0, 0); + return 0; +} + +/* +** The cube() SQL function returns the cube of its input value. +*/ +static void cubeFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + double r = sqlite3_value_double(argv[0]); + sqlite3_result_double(context, r*r*r); +} + +/* +** This is the entry point to register the extension for the cube() function. +*/ +static int cube_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + SQLITE_EXTENSION_INIT2(pApi); + sqlite3_create_function(db, "cube", 1, SQLITE_ANY, 0, cubeFunc, 0, 0); + return 0; +} + +/* +** This is a broken extension entry point +*/ +static int broken_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + char *zErr; + SQLITE_EXTENSION_INIT2(pApi); + zErr = sqlite3_mprintf("broken autoext!"); + *pzErrMsg = zErr; + return 1; +} + +/* +** tclcmd: sqlite3_auto_extension_sqr +** +** Register the "sqr" extension to be loaded automatically. +*/ +static int autoExtSqrObjCmd( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int rc = sqlite3_auto_extension((void*)sqr_init); + Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); + return SQLITE_OK; +} + +/* +** tclcmd: sqlite3_auto_extension_cube +** +** Register the "cube" extension to be loaded automatically. +*/ +static int autoExtCubeObjCmd( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int rc = sqlite3_auto_extension((void*)cube_init); + Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); + return SQLITE_OK; +} + +/* +** tclcmd: sqlite3_auto_extension_broken +** +** Register the broken extension to be loaded automatically. +*/ +static int autoExtBrokenObjCmd( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int rc = sqlite3_auto_extension((void*)broken_init); + Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); + return SQLITE_OK; +} + +#endif /* SQLITE_OMIT_LOAD_EXTENSION */ + + +/* +** tclcmd: sqlite3_reset_auto_extension +** +** Reset all auto-extensions +*/ +static int resetAutoExtObjCmd( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_reset_auto_extension(); + return SQLITE_OK; +} + + +/* +** This procedure registers the TCL procs defined in this file. +*/ +int Sqlitetest_autoext_Init(Tcl_Interp *interp){ +#ifndef SQLITE_OMIT_LOAD_EXTENSION + Tcl_CreateObjCommand(interp, "sqlite3_auto_extension_sqr", + autoExtSqrObjCmd, 0, 0); + Tcl_CreateObjCommand(interp, "sqlite3_auto_extension_cube", + autoExtCubeObjCmd, 0, 0); + Tcl_CreateObjCommand(interp, "sqlite3_auto_extension_broken", + autoExtBrokenObjCmd, 0, 0); +#endif + Tcl_CreateObjCommand(interp, "sqlite3_reset_auto_extension", + resetAutoExtObjCmd, 0, 0); + return TCL_OK; +} diff --git a/third_party/sqlite/src/test_btree.c b/third_party/sqlite/src/test_btree.c new file mode 100755 index 0000000..006df81 --- /dev/null +++ b/third_party/sqlite/src/test_btree.c @@ -0,0 +1,140 @@ +/* +** 2007 May 05 +** +** 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. +** +************************************************************************* +** Code for testing the btree.c module in SQLite. This code +** is not included in the SQLite library. It is used for automated +** testing of the SQLite library. +** +** $Id: test_btree.c,v 1.6 2008/07/15 00:27:35 drh Exp $ +*/ +#include "btreeInt.h" +#include <tcl.h> + +/* +** Usage: sqlite3_shared_cache_report +** +** Return a list of file that are shared and the number of +** references to each file. +*/ +int sqlite3BtreeSharedCacheReport( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ +#ifndef SQLITE_OMIT_SHARED_CACHE + extern BtShared *sqlite3SharedCacheList; + BtShared *pBt; + Tcl_Obj *pRet = Tcl_NewObj(); + for(pBt=sqlite3SharedCacheList; pBt; pBt=pBt->pNext){ + const char *zFile = sqlite3PagerFilename(pBt->pPager); + Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(zFile, -1)); + Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(pBt->nRef)); + } + Tcl_SetObjResult(interp, pRet); +#endif + return TCL_OK; +} + +/* +** Print debugging information about all cursors to standard output. +*/ +void sqlite3BtreeCursorList(Btree *p){ +#ifdef SQLITE_DEBUG + 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->eState==CURSOR_VALID) ? "" : " eof" + ); + } +#endif +} + + +/* +** Fill aResult[] with information about the entry and page that the +** cursor is pointing to. +** +** aResult[0] = The page number +** aResult[1] = The entry number +** aResult[2] = Total number of entries on this page +** aResult[3] = Cell size (local payload + header) +** aResult[4] = Number of free bytes on this page +** aResult[5] = Number of free blocks on the page +** aResult[6] = Total payload size (local + overflow) +** aResult[7] = Header size in bytes +** aResult[8] = Local payload size +** aResult[9] = Parent page number +** aResult[10]= Page number of the first overflow page +** +** This routine is used for testing and debugging only. +*/ +int sqlite3BtreeCursorInfo(BtCursor *pCur, int *aResult, int upCnt){ + int cnt, idx; + MemPage *pPage = pCur->pPage; + BtCursor tmpCur; + int rc; + + if( pCur->eState==CURSOR_REQUIRESEEK ){ + rc = sqlite3BtreeRestoreCursorPosition(pCur); + if( rc!=SQLITE_OK ){ + return rc; + } + } + + assert( pPage->isInit ); + sqlite3BtreeGetTempCursor(pCur, &tmpCur); + while( upCnt-- ){ + sqlite3BtreeMoveToParent(&tmpCur); + } + pPage = tmpCur.pPage; + aResult[0] = sqlite3PagerPagenumber(pPage->pDbPage); + assert( aResult[0]==pPage->pgno ); + aResult[1] = tmpCur.idx; + aResult[2] = pPage->nCell; + if( tmpCur.idx>=0 && tmpCur.idx<pPage->nCell ){ + sqlite3BtreeParseCell(tmpCur.pPage, tmpCur.idx, &tmpCur.info); + aResult[3] = tmpCur.info.nSize; + aResult[6] = tmpCur.info.nData; + aResult[7] = tmpCur.info.nHeader; + aResult[8] = tmpCur.info.nLocal; + }else{ + aResult[3] = 0; + aResult[6] = 0; + aResult[7] = 0; + aResult[8] = 0; + } + aResult[4] = pPage->nFree; + cnt = 0; + idx = get2byte(&pPage->aData[pPage->hdrOffset+1]); + while( idx>0 && idx<pPage->pBt->usableSize ){ + cnt++; + idx = get2byte(&pPage->aData[idx]); + } + aResult[5] = cnt; + if( pPage->pParent==0 || sqlite3BtreeIsRootPage(pPage) ){ + aResult[9] = 0; + }else{ + aResult[9] = pPage->pParent->pgno; + } + if( tmpCur.info.iOverflow ){ + aResult[10] = get4byte(&tmpCur.info.pCell[tmpCur.info.iOverflow]); + }else{ + aResult[10] = 0; + } + sqlite3BtreeReleaseTempCursor(&tmpCur); + return SQLITE_OK; +} diff --git a/third_party/sqlite/src/test_config.c b/third_party/sqlite/src/test_config.c new file mode 100755 index 0000000..fe96b29 --- /dev/null +++ b/third_party/sqlite/src/test_config.c @@ -0,0 +1,488 @@ +/* +** 2007 May 7 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file contains code used for testing the SQLite system. +** None of the code in this file goes into a deliverable build. +** +** The focus of this file is providing the TCL testing layer +** access to compile-time constants. +** +** $Id: test_config.c,v 1.33 2008/07/31 02:05:05 shane Exp $ +*/ + +#include "sqliteLimit.h" + +#include "sqliteInt.h" +#include "tcl.h" +#include <stdlib.h> +#include <string.h> + +/* +** This routine sets entries in the global ::sqlite_options() array variable +** according to the compile-time configuration of the database. Test +** procedures use this to determine when tests should be omitted. +*/ +static void set_options(Tcl_Interp *interp){ + int rc = 0; + +#ifdef SQLITE_32BIT_ROWID + Tcl_SetVar2(interp, "sqlite_options", "rowid32", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "rowid32", "0", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_CASE_SENSITIVE_LIKE + Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","1",TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","0",TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_DEBUG + Tcl_SetVar2(interp, "sqlite_options", "debug", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "debug", "0", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_DISABLE_DIRSYNC + Tcl_SetVar2(interp, "sqlite_options", "dirsync", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "dirsync", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_DISABLE_LFS + Tcl_SetVar2(interp, "sqlite_options", "lfs", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "lfs", "1", TCL_GLOBAL_ONLY); +#endif + +#if 1 /* def SQLITE_MEMDEBUG */ + Tcl_SetVar2(interp, "sqlite_options", "memdebug", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "memdebug", "0", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_ENABLE_MEMSYS3 + Tcl_SetVar2(interp, "sqlite_options", "mem3", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "mem3", "0", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_ENABLE_MEMSYS5 + Tcl_SetVar2(interp, "sqlite_options", "mem5", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "mem5", "0", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_ALTERTABLE + Tcl_SetVar2(interp, "sqlite_options", "altertable", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "altertable", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_ANALYZE + Tcl_SetVar2(interp, "sqlite_options", "analyze", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "analyze", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_ENABLE_ATOMIC_WRITE + Tcl_SetVar2(interp, "sqlite_options", "atomicwrite", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "atomicwrite", "0", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_ATTACH + Tcl_SetVar2(interp, "sqlite_options", "attach", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "attach", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_AUTHORIZATION + Tcl_SetVar2(interp, "sqlite_options", "auth", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "auth", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_AUTOINCREMENT + Tcl_SetVar2(interp, "sqlite_options", "autoinc", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "autoinc", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_AUTOVACUUM + Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "1", TCL_GLOBAL_ONLY); +#endif /* SQLITE_OMIT_AUTOVACUUM */ +#if !defined(SQLITE_DEFAULT_AUTOVACUUM) || SQLITE_DEFAULT_AUTOVACUUM==0 + Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","0",TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","1",TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION + Tcl_SetVar2(interp, "sqlite_options", "between_opt", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "between_opt", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_BUILTIN_TEST + Tcl_SetVar2(interp, "sqlite_options", "builtin_test", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "builtin_test", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_BLOB_LITERAL + Tcl_SetVar2(interp, "sqlite_options", "bloblit", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "bloblit", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_CAST + Tcl_SetVar2(interp, "sqlite_options", "cast", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "cast", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_CHECK + Tcl_SetVar2(interp, "sqlite_options", "check", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "check", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_ENABLE_COLUMN_METADATA + Tcl_SetVar2(interp, "sqlite_options", "columnmetadata", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "columnmetadata", "0", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_COMPLETE + Tcl_SetVar2(interp, "sqlite_options", "complete", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "complete", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_COMPOUND_SELECT + Tcl_SetVar2(interp, "sqlite_options", "compound", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "compound", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_CONFLICT_CLAUSE + Tcl_SetVar2(interp, "sqlite_options", "conflict", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "conflict", "1", TCL_GLOBAL_ONLY); +#endif + +#if SQLITE_OS_UNIX + Tcl_SetVar2(interp, "sqlite_options", "crashtest", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "crashtest", "0", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_DATETIME_FUNCS + Tcl_SetVar2(interp, "sqlite_options", "datetime", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "datetime", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_DECLTYPE + Tcl_SetVar2(interp, "sqlite_options", "decltype", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "decltype", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_DISKIO + Tcl_SetVar2(interp, "sqlite_options", "diskio", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "diskio", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_EXPLAIN + Tcl_SetVar2(interp, "sqlite_options", "explain", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "explain", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_FLOATING_POINT + Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_FOREIGN_KEY + Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_ENABLE_FTS1 + Tcl_SetVar2(interp, "sqlite_options", "fts1", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "fts1", "0", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_ENABLE_FTS2 + Tcl_SetVar2(interp, "sqlite_options", "fts2", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "fts2", "0", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_ENABLE_FTS3 + Tcl_SetVar2(interp, "sqlite_options", "fts3", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "fts3", "0", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_GET_TABLE + Tcl_SetVar2(interp, "sqlite_options", "gettable", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "gettable", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_GLOBALRECOVER + Tcl_SetVar2(interp, "sqlite_options", "globalrecover", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "globalrecover", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_ENABLE_ICU + Tcl_SetVar2(interp, "sqlite_options", "icu", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "icu", "0", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_INCRBLOB + Tcl_SetVar2(interp, "sqlite_options", "incrblob", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "incrblob", "1", TCL_GLOBAL_ONLY); +#endif /* SQLITE_OMIT_AUTOVACUUM */ + +#ifdef SQLITE_OMIT_INTEGRITY_CHECK + Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "integrityck", "1", TCL_GLOBAL_ONLY); +#endif + +#if defined(SQLITE_DEFAULT_FILE_FORMAT) && SQLITE_DEFAULT_FILE_FORMAT==1 + Tcl_SetVar2(interp, "sqlite_options", "legacyformat", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "legacyformat", "0", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION + Tcl_SetVar2(interp, "sqlite_options", "like_opt", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "like_opt", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_LOAD_EXTENSION + Tcl_SetVar2(interp, "sqlite_options", "load_ext", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "load_ext", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_LOCALTIME + Tcl_SetVar2(interp, "sqlite_options", "localtime", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "localtime", "1", TCL_GLOBAL_ONLY); +#endif + +Tcl_SetVar2(interp, "sqlite_options", "long_double", + sizeof(LONGDOUBLE_TYPE)>sizeof(double) ? "1" : "0", + TCL_GLOBAL_ONLY); + +#ifdef SQLITE_OMIT_MEMORYDB + Tcl_SetVar2(interp, "sqlite_options", "memorydb", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "memorydb", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + Tcl_SetVar2(interp, "sqlite_options", "memorymanage", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "memorymanage", "0", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_OR_OPTIMIZATION + Tcl_SetVar2(interp, "sqlite_options", "or_opt", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "or_opt", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_PAGER_PRAGMAS + Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_PARSER + Tcl_SetVar2(interp, "sqlite_options", "parser", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "parser", "1", TCL_GLOBAL_ONLY); +#endif + +#if defined(SQLITE_OMIT_PRAGMA) || defined(SQLITE_OMIT_FLAG_PRAGMAS) + Tcl_SetVar2(interp, "sqlite_options", "pragma", "0", TCL_GLOBAL_ONLY); + Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "pragma", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_PROGRESS_CALLBACK + Tcl_SetVar2(interp, "sqlite_options", "progress", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "progress", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_REINDEX + Tcl_SetVar2(interp, "sqlite_options", "reindex", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "reindex", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_ENABLE_RTREE + Tcl_SetVar2(interp, "sqlite_options", "rtree", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "rtree", "0", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS + Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS + Tcl_SetVar2(interp, "sqlite_options", "schema_version", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "schema_version", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_SHARED_CACHE + Tcl_SetVar2(interp, "sqlite_options", "shared_cache", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "shared_cache", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_SUBQUERY + Tcl_SetVar2(interp, "sqlite_options", "subquery", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "subquery", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_TCL_VARIABLE + Tcl_SetVar2(interp, "sqlite_options", "tclvar", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "tclvar", "1", TCL_GLOBAL_ONLY); +#endif + + rc = sqlite3_threadsafe(); +#if SQLITE_THREADSAFE + Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "1", TCL_GLOBAL_ONLY); + assert( rc ); +#else + Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "0", TCL_GLOBAL_ONLY); + assert( !rc ); +#endif + +#ifdef SQLITE_OMIT_TRACE + Tcl_SetVar2(interp, "sqlite_options", "trace", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "trace", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_TRIGGER + Tcl_SetVar2(interp, "sqlite_options", "trigger", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "trigger", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_TEMPDB + Tcl_SetVar2(interp, "sqlite_options", "tempdb", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "tempdb", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_UTF16 + Tcl_SetVar2(interp, "sqlite_options", "utf16", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "utf16", "1", TCL_GLOBAL_ONLY); +#endif + +#if defined(SQLITE_OMIT_VACUUM) || defined(SQLITE_OMIT_ATTACH) + Tcl_SetVar2(interp, "sqlite_options", "vacuum", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "vacuum", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_VIEW + Tcl_SetVar2(interp, "sqlite_options", "view", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "view", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_OMIT_VIRTUALTABLE + Tcl_SetVar2(interp, "sqlite_options", "vtab", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "vtab", "1", TCL_GLOBAL_ONLY); +#endif + +#ifdef SQLITE_SECURE_DELETE + Tcl_SetVar2(interp, "sqlite_options", "secure_delete", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "secure_delete", "0", TCL_GLOBAL_ONLY); +#endif + +#ifdef YYTRACKMAXSTACKDEPTH + Tcl_SetVar2(interp, "sqlite_options", "yytrackmaxstackdepth", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "yytrackmaxstackdepth", "0", TCL_GLOBAL_ONLY); +#endif + +#define LINKVAR(x) { \ + static const int cv_ ## x = SQLITE_ ## x; \ + Tcl_LinkVar(interp, "SQLITE_" #x, (char *)&(cv_ ## x), \ + TCL_LINK_INT | TCL_LINK_READ_ONLY); } + + LINKVAR( MAX_LENGTH ); + LINKVAR( MAX_COLUMN ); + LINKVAR( MAX_SQL_LENGTH ); + LINKVAR( MAX_EXPR_DEPTH ); + LINKVAR( MAX_COMPOUND_SELECT ); + LINKVAR( MAX_VDBE_OP ); + LINKVAR( MAX_FUNCTION_ARG ); + LINKVAR( MAX_VARIABLE_NUMBER ); + LINKVAR( MAX_PAGE_SIZE ); + LINKVAR( MAX_PAGE_COUNT ); + LINKVAR( MAX_LIKE_PATTERN_LENGTH ); + LINKVAR( DEFAULT_TEMP_CACHE_SIZE ); + LINKVAR( DEFAULT_CACHE_SIZE ); + LINKVAR( DEFAULT_PAGE_SIZE ); + LINKVAR( DEFAULT_FILE_FORMAT ); + LINKVAR( MAX_ATTACHED ); + + { + static const int cv_TEMP_STORE = SQLITE_TEMP_STORE; + Tcl_LinkVar(interp, "TEMP_STORE", (char *)&(cv_TEMP_STORE), + TCL_LINK_INT | TCL_LINK_READ_ONLY); + } +} + + +/* +** Register commands with the TCL interpreter. +*/ +int Sqliteconfig_Init(Tcl_Interp *interp){ + set_options(interp); + return TCL_OK; +} diff --git a/third_party/sqlite/src/test_devsym.c b/third_party/sqlite/src/test_devsym.c new file mode 100755 index 0000000..0314804 --- /dev/null +++ b/third_party/sqlite/src/test_devsym.c @@ -0,0 +1,353 @@ +/* +** 2008 Jan 22 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains code that modified the OS layer in order to simulate +** different device types (by overriding the return values of the +** xDeviceCharacteristics() and xSectorSize() methods). +** +** $Id: test_devsym.c,v 1.7 2008/06/06 11:11:26 danielk1977 Exp $ +*/ +#if SQLITE_TEST /* This file is used for testing only */ + +#include "sqlite3.h" +#include "sqliteInt.h" + +/* +** Maximum pathname length supported by the devsym backend. +*/ +#define DEVSYM_MAX_PATHNAME 512 + +/* +** Name used to identify this VFS. +*/ +#define DEVSYM_VFS_NAME "devsym" + +typedef struct devsym_file devsym_file; +struct devsym_file { + sqlite3_file base; + sqlite3_file *pReal; +}; + +/* +** Method declarations for devsym_file. +*/ +static int devsymClose(sqlite3_file*); +static int devsymRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); +static int devsymWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst); +static int devsymTruncate(sqlite3_file*, sqlite3_int64 size); +static int devsymSync(sqlite3_file*, int flags); +static int devsymFileSize(sqlite3_file*, sqlite3_int64 *pSize); +static int devsymLock(sqlite3_file*, int); +static int devsymUnlock(sqlite3_file*, int); +static int devsymCheckReservedLock(sqlite3_file*, int *); +static int devsymFileControl(sqlite3_file*, int op, void *pArg); +static int devsymSectorSize(sqlite3_file*); +static int devsymDeviceCharacteristics(sqlite3_file*); + +/* +** Method declarations for devsym_vfs. +*/ +static int devsymOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); +static int devsymDelete(sqlite3_vfs*, const char *zName, int syncDir); +static int devsymAccess(sqlite3_vfs*, const char *zName, int flags, int *); +static int devsymFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut); +#ifndef SQLITE_OMIT_LOAD_EXTENSION +static void *devsymDlOpen(sqlite3_vfs*, const char *zFilename); +static void devsymDlError(sqlite3_vfs*, int nByte, char *zErrMsg); +static void *devsymDlSym(sqlite3_vfs*,void*, const char *zSymbol); +static void devsymDlClose(sqlite3_vfs*, void*); +#endif /* SQLITE_OMIT_LOAD_EXTENSION */ +static int devsymRandomness(sqlite3_vfs*, int nByte, char *zOut); +static int devsymSleep(sqlite3_vfs*, int microseconds); +static int devsymCurrentTime(sqlite3_vfs*, double*); + +static sqlite3_vfs devsym_vfs = { + 1, /* iVersion */ + sizeof(devsym_file), /* szOsFile */ + DEVSYM_MAX_PATHNAME, /* mxPathname */ + 0, /* pNext */ + DEVSYM_VFS_NAME, /* zName */ + 0, /* pAppData */ + devsymOpen, /* xOpen */ + devsymDelete, /* xDelete */ + devsymAccess, /* xAccess */ + devsymFullPathname, /* xFullPathname */ +#ifndef SQLITE_OMIT_LOAD_EXTENSION + devsymDlOpen, /* xDlOpen */ + devsymDlError, /* xDlError */ + devsymDlSym, /* xDlSym */ + devsymDlClose, /* xDlClose */ +#else + 0, /* xDlOpen */ + 0, /* xDlError */ + 0, /* xDlSym */ + 0, /* xDlClose */ +#endif /* SQLITE_OMIT_LOAD_EXTENSION */ + devsymRandomness, /* xRandomness */ + devsymSleep, /* xSleep */ + devsymCurrentTime /* xCurrentTime */ +}; + +static sqlite3_io_methods devsym_io_methods = { + 1, /* iVersion */ + devsymClose, /* xClose */ + devsymRead, /* xRead */ + devsymWrite, /* xWrite */ + devsymTruncate, /* xTruncate */ + devsymSync, /* xSync */ + devsymFileSize, /* xFileSize */ + devsymLock, /* xLock */ + devsymUnlock, /* xUnlock */ + devsymCheckReservedLock, /* xCheckReservedLock */ + devsymFileControl, /* xFileControl */ + devsymSectorSize, /* xSectorSize */ + devsymDeviceCharacteristics /* xDeviceCharacteristics */ +}; + +struct DevsymGlobal { + sqlite3_vfs *pVfs; + int iDeviceChar; + int iSectorSize; +}; +struct DevsymGlobal g = {0, 0, 512}; + +/* +** Close an devsym-file. +*/ +static int devsymClose(sqlite3_file *pFile){ + devsym_file *p = (devsym_file *)pFile; + return sqlite3OsClose(p->pReal); +} + +/* +** Read data from an devsym-file. +*/ +static int devsymRead( + sqlite3_file *pFile, + void *zBuf, + int iAmt, + sqlite_int64 iOfst +){ + devsym_file *p = (devsym_file *)pFile; + return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst); +} + +/* +** Write data to an devsym-file. +*/ +static int devsymWrite( + sqlite3_file *pFile, + const void *zBuf, + int iAmt, + sqlite_int64 iOfst +){ + devsym_file *p = (devsym_file *)pFile; + return sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst); +} + +/* +** Truncate an devsym-file. +*/ +static int devsymTruncate(sqlite3_file *pFile, sqlite_int64 size){ + devsym_file *p = (devsym_file *)pFile; + return sqlite3OsTruncate(p->pReal, size); +} + +/* +** Sync an devsym-file. +*/ +static int devsymSync(sqlite3_file *pFile, int flags){ + devsym_file *p = (devsym_file *)pFile; + return sqlite3OsSync(p->pReal, flags); +} + +/* +** Return the current file-size of an devsym-file. +*/ +static int devsymFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ + devsym_file *p = (devsym_file *)pFile; + return sqlite3OsFileSize(p->pReal, pSize); +} + +/* +** Lock an devsym-file. +*/ +static int devsymLock(sqlite3_file *pFile, int eLock){ + devsym_file *p = (devsym_file *)pFile; + return sqlite3OsLock(p->pReal, eLock); +} + +/* +** Unlock an devsym-file. +*/ +static int devsymUnlock(sqlite3_file *pFile, int eLock){ + devsym_file *p = (devsym_file *)pFile; + return sqlite3OsUnlock(p->pReal, eLock); +} + +/* +** Check if another file-handle holds a RESERVED lock on an devsym-file. +*/ +static int devsymCheckReservedLock(sqlite3_file *pFile, int *pResOut){ + devsym_file *p = (devsym_file *)pFile; + return sqlite3OsCheckReservedLock(p->pReal, pResOut); +} + +/* +** File control method. For custom operations on an devsym-file. +*/ +static int devsymFileControl(sqlite3_file *pFile, int op, void *pArg){ + devsym_file *p = (devsym_file *)pFile; + return sqlite3OsFileControl(p->pReal, op, pArg); +} + +/* +** Return the sector-size in bytes for an devsym-file. +*/ +static int devsymSectorSize(sqlite3_file *pFile){ + return g.iSectorSize; +} + +/* +** Return the device characteristic flags supported by an devsym-file. +*/ +static int devsymDeviceCharacteristics(sqlite3_file *pFile){ + return g.iDeviceChar; +} + +/* +** Open an devsym file handle. +*/ +static int devsymOpen( + sqlite3_vfs *pVfs, + const char *zName, + sqlite3_file *pFile, + int flags, + int *pOutFlags +){ + devsym_file *p = (devsym_file *)pFile; + pFile->pMethods = &devsym_io_methods; + p->pReal = (sqlite3_file *)&p[1]; + return sqlite3OsOpen(g.pVfs, zName, p->pReal, flags, pOutFlags); +} + +/* +** Delete the file located at zPath. If the dirSync argument is true, +** ensure the file-system modifications are synced to disk before +** returning. +*/ +static int devsymDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ + return sqlite3OsDelete(g.pVfs, zPath, dirSync); +} + +/* +** Test for access permissions. Return true if the requested permission +** is available, or false otherwise. +*/ +static int devsymAccess( + sqlite3_vfs *pVfs, + const char *zPath, + int flags, + int *pResOut +){ + return sqlite3OsAccess(g.pVfs, zPath, flags, pResOut); +} + +/* +** Populate buffer zOut with the full canonical pathname corresponding +** to the pathname in zPath. zOut is guaranteed to point to a buffer +** of at least (DEVSYM_MAX_PATHNAME+1) bytes. +*/ +static int devsymFullPathname( + sqlite3_vfs *pVfs, + const char *zPath, + int nOut, + char *zOut +){ + return sqlite3OsFullPathname(g.pVfs, zPath, nOut, zOut); +} + +#ifndef SQLITE_OMIT_LOAD_EXTENSION +/* +** Open the dynamic library located at zPath and return a handle. +*/ +static void *devsymDlOpen(sqlite3_vfs *pVfs, const char *zPath){ + return sqlite3OsDlOpen(g.pVfs, zPath); +} + +/* +** Populate the buffer zErrMsg (size nByte bytes) with a human readable +** utf-8 string describing the most recent error encountered associated +** with dynamic libraries. +*/ +static void devsymDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ + sqlite3OsDlError(g.pVfs, nByte, zErrMsg); +} + +/* +** Return a pointer to the symbol zSymbol in the dynamic library pHandle. +*/ +static void *devsymDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){ + return sqlite3OsDlSym(g.pVfs, pHandle, zSymbol); +} + +/* +** Close the dynamic library handle pHandle. +*/ +static void devsymDlClose(sqlite3_vfs *pVfs, void *pHandle){ + sqlite3OsDlClose(g.pVfs, pHandle); +} +#endif /* SQLITE_OMIT_LOAD_EXTENSION */ + +/* +** Populate the buffer pointed to by zBufOut with nByte bytes of +** random data. +*/ +static int devsymRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ + return sqlite3OsRandomness(g.pVfs, nByte, zBufOut); +} + +/* +** Sleep for nMicro microseconds. Return the number of microseconds +** actually slept. +*/ +static int devsymSleep(sqlite3_vfs *pVfs, int nMicro){ + return sqlite3OsSleep(g.pVfs, nMicro); +} + +/* +** Return the current time as a Julian Day number in *pTimeOut. +*/ +static int devsymCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ + return sqlite3OsCurrentTime(g.pVfs, pTimeOut); +} + +/* +** This procedure registers the devsym vfs with SQLite. If the argument is +** true, the devsym vfs becomes the new default vfs. It is the only publicly +** available function in this file. +*/ +void devsym_register(int iDeviceChar, int iSectorSize){ + if( g.pVfs==0 ){ + g.pVfs = sqlite3_vfs_find(0); + devsym_vfs.szOsFile += g.pVfs->szOsFile; + sqlite3_vfs_register(&devsym_vfs, 0); + } + if( iDeviceChar>=0 ){ + g.iDeviceChar = iDeviceChar; + } + if( iSectorSize>=0 ){ + g.iSectorSize = iSectorSize; + } +} + +#endif diff --git a/third_party/sqlite/src/test_func.c b/third_party/sqlite/src/test_func.c new file mode 100755 index 0000000..eaafc23 --- /dev/null +++ b/third_party/sqlite/src/test_func.c @@ -0,0 +1,431 @@ +/* +** 2008 March 19 +** +** 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. +** +************************************************************************* +** Code for testing all sorts of SQLite interfaces. This code +** implements new SQL functions used by the test scripts. +** +** $Id: test_func.c,v 1.10 2008/08/02 03:50:39 drh Exp $ +*/ +#include "sqlite3.h" +#include "tcl.h" +#include <stdlib.h> +#include <string.h> +#include <assert.h> + + +/* +** Allocate nByte bytes of space using sqlite3_malloc(). If the +** allocation fails, call sqlite3_result_error_nomem() to notify +** the database handle that malloc() has failed. +*/ +static void *testContextMalloc(sqlite3_context *context, int nByte){ + char *z = sqlite3_malloc(nByte); + if( !z && nByte>0 ){ + sqlite3_result_error_nomem(context); + } + return z; +} + +/* +** This function generates a string of random characters. Used for +** generating test data. +*/ +static void randStr(sqlite3_context *context, int argc, sqlite3_value **argv){ + static const unsigned char zSrc[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" + ".-!,:*^+=_|?/<> "; + int iMin, iMax, n, r, i; + unsigned char zBuf[1000]; + + /* It used to be possible to call randstr() with any number of arguments, + ** but now it is registered with SQLite as requiring exactly 2. + */ + assert(argc==2); + + iMin = sqlite3_value_int(argv[0]); + if( iMin<0 ) iMin = 0; + if( iMin>=sizeof(zBuf) ) iMin = sizeof(zBuf)-1; + iMax = sqlite3_value_int(argv[1]); + if( iMax<iMin ) iMax = iMin; + if( iMax>=sizeof(zBuf) ) iMax = sizeof(zBuf)-1; + n = iMin; + if( iMax>iMin ){ + sqlite3_randomness(sizeof(r), &r); + r &= 0x7fffffff; + n += r%(iMax + 1 - iMin); + } + assert( n<sizeof(zBuf) ); + sqlite3_randomness(n, zBuf); + for(i=0; i<n; i++){ + zBuf[i] = zSrc[zBuf[i]%(sizeof(zSrc)-1)]; + } + zBuf[n] = 0; + sqlite3_result_text(context, (char*)zBuf, n, SQLITE_TRANSIENT); +} + +/* +** The following two SQL functions are used to test returning a text +** result with a destructor. Function 'test_destructor' takes one argument +** and returns the same argument interpreted as TEXT. A destructor is +** passed with the sqlite3_result_text() call. +** +** SQL function 'test_destructor_count' returns the number of outstanding +** allocations made by 'test_destructor'; +** +** WARNING: Not threadsafe. +*/ +static int test_destructor_count_var = 0; +static void destructor(void *p){ + char *zVal = (char *)p; + assert(zVal); + zVal--; + sqlite3_free(zVal); + test_destructor_count_var--; +} +static void test_destructor( + sqlite3_context *pCtx, + int nArg, + sqlite3_value **argv +){ + char *zVal; + int len; + + test_destructor_count_var++; + assert( nArg==1 ); + if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; + len = sqlite3_value_bytes(argv[0]); + zVal = testContextMalloc(pCtx, len+3); + if( !zVal ){ + return; + } + zVal[len+1] = 0; + zVal[len+2] = 0; + zVal++; + memcpy(zVal, sqlite3_value_text(argv[0]), len); + sqlite3_result_text(pCtx, zVal, -1, destructor); +} +#ifndef SQLITE_OMIT_UTF16 +static void test_destructor16( + sqlite3_context *pCtx, + int nArg, + sqlite3_value **argv +){ + char *zVal; + int len; + + test_destructor_count_var++; + assert( nArg==1 ); + if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; + len = sqlite3_value_bytes16(argv[0]); + zVal = testContextMalloc(pCtx, len+3); + if( !zVal ){ + return; + } + zVal[len+1] = 0; + zVal[len+2] = 0; + zVal++; + memcpy(zVal, sqlite3_value_text16(argv[0]), len); + sqlite3_result_text16(pCtx, zVal, -1, destructor); +} +#endif +static void test_destructor_count( + sqlite3_context *pCtx, + int nArg, + sqlite3_value **argv +){ + sqlite3_result_int(pCtx, test_destructor_count_var); +} + +/* +** Routines for testing the sqlite3_get_auxdata() and sqlite3_set_auxdata() +** interface. +** +** The test_auxdata() SQL function attempts to register each of its arguments +** as auxiliary data. If there are no prior registrations of aux data for +** that argument (meaning the argument is not a constant or this is its first +** call) then the result for that argument is 0. If there is a prior +** registration, the result for that argument is 1. The overall result +** is the individual argument results separated by spaces. +*/ +static void free_test_auxdata(void *p) {sqlite3_free(p);} +static void test_auxdata( + sqlite3_context *pCtx, + int nArg, + sqlite3_value **argv +){ + int i; + char *zRet = testContextMalloc(pCtx, nArg*2); + if( !zRet ) return; + memset(zRet, 0, nArg*2); + for(i=0; i<nArg; i++){ + char const *z = (char*)sqlite3_value_text(argv[i]); + if( z ){ + int n; + char *zAux = sqlite3_get_auxdata(pCtx, i); + if( zAux ){ + zRet[i*2] = '1'; + assert( strcmp(zAux,z)==0 ); + }else { + zRet[i*2] = '0'; + } + n = strlen(z) + 1; + zAux = testContextMalloc(pCtx, n); + if( zAux ){ + memcpy(zAux, z, n); + sqlite3_set_auxdata(pCtx, i, zAux, free_test_auxdata); + } + zRet[i*2+1] = ' '; + } + } + sqlite3_result_text(pCtx, zRet, 2*nArg-1, free_test_auxdata); +} + +/* +** A function to test error reporting from user functions. This function +** returns a copy of its first argument as the error message. If the +** second argument exists, it becomes the error code. +*/ +static void test_error( + sqlite3_context *pCtx, + int nArg, + sqlite3_value **argv +){ + sqlite3_result_error(pCtx, (char*)sqlite3_value_text(argv[0]), -1); + if( nArg==2 ){ + sqlite3_result_error_code(pCtx, sqlite3_value_int(argv[1])); + } +} + +/* +** This function takes two arguments. It performance UTF-8/16 type +** conversions on the first argument then returns a copy of the second +** argument. +** +** This function is used in cases such as the following: +** +** SELECT test_isolation(x,x) FROM t1; +** +** We want to verify that the type conversions that occur on the +** first argument do not invalidate the second argument. +*/ +static void test_isolation( + sqlite3_context *pCtx, + int nArg, + sqlite3_value **argv +){ +#ifndef SQLITE_OMIT_UTF16 + sqlite3_value_text16(argv[0]); + sqlite3_value_text(argv[0]); + sqlite3_value_text16(argv[0]); + sqlite3_value_text(argv[0]); +#endif + sqlite3_result_value(pCtx, argv[1]); +} + +/* +** Invoke an SQL statement recursively. The function result is the +** first column of the first row of the result set. +*/ +static void test_eval( + sqlite3_context *pCtx, + int nArg, + sqlite3_value **argv +){ + sqlite3_stmt *pStmt; + int rc; + sqlite3 *db = sqlite3_context_db_handle(pCtx); + const char *zSql; + + zSql = (char*)sqlite3_value_text(argv[0]); + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3_step(pStmt); + if( rc==SQLITE_ROW ){ + sqlite3_result_value(pCtx, sqlite3_column_value(pStmt, 0)); + } + rc = sqlite3_finalize(pStmt); + } + if( rc ){ + char *zErr; + assert( pStmt==0 ); + zErr = sqlite3_mprintf("sqlite3_prepare_v2() error: %s",sqlite3_errmsg(db)); + sqlite3_result_text(pCtx, zErr, -1, sqlite3_free); + sqlite3_result_error_code(pCtx, rc); + } +} + + +static int registerTestFunctions(sqlite3 *db){ + static const struct { + char *zName; + signed char nArg; + unsigned char eTextRep; /* 1: UTF-16. 0: UTF-8 */ + void (*xFunc)(sqlite3_context*,int,sqlite3_value **); + } aFuncs[] = { + { "randstr", 2, SQLITE_UTF8, randStr }, + { "test_destructor", 1, SQLITE_UTF8, test_destructor}, +#ifndef SQLITE_OMIT_UTF16 + { "test_destructor16", 1, SQLITE_UTF8, test_destructor16}, +#endif + { "test_destructor_count", 0, SQLITE_UTF8, test_destructor_count}, + { "test_auxdata", -1, SQLITE_UTF8, test_auxdata}, + { "test_error", 1, SQLITE_UTF8, test_error}, + { "test_error", 2, SQLITE_UTF8, test_error}, + { "test_eval", 1, SQLITE_UTF8, test_eval}, + { "test_isolation", 2, SQLITE_UTF8, test_isolation}, + }; + int i; + extern int Md5_Register(sqlite3*); + + for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ + sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg, + aFuncs[i].eTextRep, 0, aFuncs[i].xFunc, 0, 0); + } + Md5_Register(db); + return SQLITE_OK; +} + +/* +** TCLCMD: autoinstall_test_functions +** +** Invoke this TCL command to use sqlite3_auto_extension() to cause +** the standard set of test functions to be loaded into each new +** database connection. +*/ +static int autoinstall_test_funcs( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int rc = sqlite3_auto_extension((void*)registerTestFunctions); + Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); + return TCL_OK; +} + +/* +** A bogus step function and finalizer function. +*/ +static void tStep(sqlite3_context *a, int b, sqlite3_value **c){} +static void tFinal(sqlite3_context *a){} + + +/* +** tclcmd: abuse_create_function +** +** Make various calls to sqlite3_create_function that do not have valid +** parameters. Verify that the error condition is detected and reported. +*/ +static int abuse_create_function( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**); + sqlite3 *db; + int rc; + int mxArg; + + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + + rc = sqlite3_create_function(db, "tx", 1, SQLITE_UTF8, 0, tStep,tStep,tFinal); + if( rc!=SQLITE_ERROR ) goto abuse_err; + if( sqlite3_errcode(db)!=SQLITE_ERROR ) goto abuse_err; + if( strcmp(sqlite3_errmsg(db), "bad parameters")!=0 ) goto abuse_err; + + rc = sqlite3_create_function(db, "tx", 1, SQLITE_UTF8, 0, tStep, tStep, 0); + if( rc!=SQLITE_ERROR ) goto abuse_err; + if( sqlite3_errcode(db)!=SQLITE_ERROR ) goto abuse_err; + if( strcmp(sqlite3_errmsg(db), "bad parameters")!=0 ) goto abuse_err; + + rc = sqlite3_create_function(db, "tx", 1, SQLITE_UTF8, 0, tStep, 0, tFinal); + if( rc!=SQLITE_ERROR ) goto abuse_err; + if( sqlite3_errcode(db)!=SQLITE_ERROR ) goto abuse_err; + if( strcmp(sqlite3_errmsg(db), "bad parameters")!=0 ) goto abuse_err; + + rc = sqlite3_create_function(db, "tx", 1, SQLITE_UTF8, 0, 0, 0, tFinal); + if( rc!=SQLITE_ERROR ) goto abuse_err; + if( sqlite3_errcode(db)!=SQLITE_ERROR ) goto abuse_err; + if( strcmp(sqlite3_errmsg(db), "bad parameters")!=0 ) goto abuse_err; + + rc = sqlite3_create_function(db, "tx", 1, SQLITE_UTF8, 0, 0, tStep, 0); + if( rc!=SQLITE_ERROR ) goto abuse_err; + if( sqlite3_errcode(db)!=SQLITE_ERROR ) goto abuse_err; + if( strcmp(sqlite3_errmsg(db), "bad parameters")!=0 ) goto abuse_err; + + rc = sqlite3_create_function(db, "tx", -2, SQLITE_UTF8, 0, tStep, 0, 0); + if( rc!=SQLITE_ERROR ) goto abuse_err; + if( sqlite3_errcode(db)!=SQLITE_ERROR ) goto abuse_err; + if( strcmp(sqlite3_errmsg(db), "bad parameters")!=0 ) goto abuse_err; + + rc = sqlite3_create_function(db, "tx", 128, SQLITE_UTF8, 0, tStep, 0, 0); + if( rc!=SQLITE_ERROR ) goto abuse_err; + if( sqlite3_errcode(db)!=SQLITE_ERROR ) goto abuse_err; + if( strcmp(sqlite3_errmsg(db), "bad parameters")!=0 ) goto abuse_err; + + rc = sqlite3_create_function(db, "funcxx" + "_123456789_123456789_123456789_123456789_123456789" + "_123456789_123456789_123456789_123456789_123456789" + "_123456789_123456789_123456789_123456789_123456789" + "_123456789_123456789_123456789_123456789_123456789" + "_123456789_123456789_123456789_123456789_123456789", + 1, SQLITE_UTF8, 0, tStep, 0, 0); + if( rc!=SQLITE_ERROR ) goto abuse_err; + if( sqlite3_errcode(db)!=SQLITE_ERROR ) goto abuse_err; + if( strcmp(sqlite3_errmsg(db), "bad parameters")!=0 ) goto abuse_err; + + /* This last function registration should actually work. Generate + ** a no-op function (that always returns NULL) and which has the + ** maximum-length function name and the maximum number of parameters. + */ + sqlite3_limit(db, SQLITE_LIMIT_FUNCTION_ARG, 10000); + mxArg = sqlite3_limit(db, SQLITE_LIMIT_FUNCTION_ARG, -1); + rc = sqlite3_create_function(db, "nullx" + "_123456789_123456789_123456789_123456789_123456789" + "_123456789_123456789_123456789_123456789_123456789" + "_123456789_123456789_123456789_123456789_123456789" + "_123456789_123456789_123456789_123456789_123456789" + "_123456789_123456789_123456789_123456789_123456789", + mxArg, SQLITE_UTF8, 0, tStep, 0, 0); + if( rc!=SQLITE_OK ) goto abuse_err; + + return TCL_OK; + +abuse_err: + Tcl_AppendResult(interp, "sqlite3_create_function abused test failed", + (char*)0); + return TCL_ERROR; +} + + + +/* +** Register commands with the TCL interpreter. +*/ +int Sqlitetest_func_Init(Tcl_Interp *interp){ + static struct { + char *zName; + Tcl_ObjCmdProc *xProc; + } aObjCmd[] = { + { "autoinstall_test_functions", autoinstall_test_funcs }, + { "abuse_create_function", abuse_create_function }, + }; + int i; + for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ + Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0); + } + sqlite3_initialize(); + sqlite3_auto_extension((void*)registerTestFunctions); + return TCL_OK; +} diff --git a/third_party/sqlite/src/test_hexio.c b/third_party/sqlite/src/test_hexio.c new file mode 100755 index 0000000..9e1e8de --- /dev/null +++ b/third_party/sqlite/src/test_hexio.c @@ -0,0 +1,342 @@ +/* +** 2007 April 6 +** +** 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. +** +************************************************************************* +** Code for testing all sorts of SQLite interfaces. This code +** implements TCL commands for reading and writing the binary +** database files and displaying the content of those files as +** hexadecimal. We could, in theory, use the built-in "binary" +** command of TCL to do a lot of this, but there are some issues +** with historical versions of the "binary" command. So it seems +** easier and safer to build our own mechanism. +** +** $Id: test_hexio.c,v 1.7 2008/05/12 16:17:42 drh Exp $ +*/ +#include "sqliteInt.h" +#include "tcl.h" +#include <stdlib.h> +#include <string.h> +#include <assert.h> + + +/* +** Convert binary to hex. The input zBuf[] contains N bytes of +** binary data. zBuf[] is 2*n+1 bytes long. Overwrite zBuf[] +** with a hexadecimal representation of its original binary input. +*/ +void sqlite3TestBinToHex(unsigned char *zBuf, int N){ + const unsigned char zHex[] = "0123456789ABCDEF"; + int i, j; + unsigned char c; + i = N*2; + zBuf[i--] = 0; + for(j=N-1; j>=0; j--){ + c = zBuf[j]; + zBuf[i--] = zHex[c&0xf]; + zBuf[i--] = zHex[c>>4]; + } + assert( i==-1 ); +} + +/* +** Convert hex to binary. The input zIn[] contains N bytes of +** hexadecimal. Convert this into binary and write aOut[] with +** the binary data. Spaces in the original input are ignored. +** Return the number of bytes of binary rendered. +*/ +int sqlite3TestHexToBin(const unsigned char *zIn, int N, unsigned char *aOut){ + const unsigned char aMap[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 0, 0, 0, 0, 0, 0, + 0,11,12,13,14,15,16, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,11,12,13,14,15,16, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }; + int i, j; + int hi=1; + unsigned char c; + + for(i=j=0; i<N; i++){ + c = aMap[zIn[i]]; + if( c==0 ) continue; + if( hi ){ + aOut[j] = (c-1)<<4; + hi = 0; + }else{ + aOut[j++] |= c-1; + hi = 1; + } + } + return j; +} + + +/* +** Usage: hexio_read FILENAME OFFSET AMT +** +** Read AMT bytes from file FILENAME beginning at OFFSET from the +** beginning of the file. Convert that information to hexadecimal +** and return the resulting HEX string. +*/ +static int hexio_read( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int offset; + int amt, got; + const char *zFile; + unsigned char *zBuf; + FILE *in; + + if( objc!=4 ){ + Tcl_WrongNumArgs(interp, 1, objv, "FILENAME OFFSET AMT"); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, objv[2], &offset) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[3], &amt) ) return TCL_ERROR; + zFile = Tcl_GetString(objv[1]); + zBuf = sqlite3_malloc( amt*2+1 ); + if( zBuf==0 ){ + return TCL_ERROR; + } + in = fopen(zFile, "rb"); + if( in==0 ){ + in = fopen(zFile, "r"); + } + if( in==0 ){ + Tcl_AppendResult(interp, "cannot open input file ", zFile, 0); + return TCL_ERROR; + } + fseek(in, offset, SEEK_SET); + got = fread(zBuf, 1, amt, in); + fclose(in); + if( got<0 ){ + got = 0; + } + sqlite3TestBinToHex(zBuf, got); + Tcl_AppendResult(interp, zBuf, 0); + sqlite3_free(zBuf); + return TCL_OK; +} + + +/* +** Usage: hexio_write FILENAME OFFSET DATA +** +** Write DATA into file FILENAME beginning at OFFSET from the +** beginning of the file. DATA is expressed in hexadecimal. +*/ +static int hexio_write( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int offset; + int nIn, nOut, written; + const char *zFile; + const unsigned char *zIn; + unsigned char *aOut; + FILE *out; + + if( objc!=4 ){ + Tcl_WrongNumArgs(interp, 1, objv, "FILENAME OFFSET HEXDATA"); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, objv[2], &offset) ) return TCL_ERROR; + zFile = Tcl_GetString(objv[1]); + zIn = (const unsigned char *)Tcl_GetStringFromObj(objv[3], &nIn); + aOut = sqlite3_malloc( nIn/2 ); + if( aOut==0 ){ + return TCL_ERROR; + } + nOut = sqlite3TestHexToBin(zIn, nIn, aOut); + out = fopen(zFile, "r+b"); + if( out==0 ){ + out = fopen(zFile, "r+"); + } + if( out==0 ){ + Tcl_AppendResult(interp, "cannot open output file ", zFile, 0); + return TCL_ERROR; + } + fseek(out, offset, SEEK_SET); + written = fwrite(aOut, 1, nOut, out); + sqlite3_free(aOut); + fclose(out); + Tcl_SetObjResult(interp, Tcl_NewIntObj(written)); + return TCL_OK; +} + +/* +** USAGE: hexio_get_int HEXDATA +** +** Interpret the HEXDATA argument as a big-endian integer. Return +** the value of that integer. HEXDATA can contain between 2 and 8 +** hexadecimal digits. +*/ +static int hexio_get_int( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int val; + int nIn, nOut; + const unsigned char *zIn; + unsigned char *aOut; + unsigned char aNum[4]; + + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "HEXDATA"); + return TCL_ERROR; + } + zIn = (const unsigned char *)Tcl_GetStringFromObj(objv[1], &nIn); + aOut = sqlite3_malloc( nIn/2 ); + if( aOut==0 ){ + return TCL_ERROR; + } + nOut = sqlite3TestHexToBin(zIn, nIn, aOut); + if( nOut>=4 ){ + memcpy(aNum, aOut, 4); + }else{ + memset(aNum, 0, sizeof(aNum)); + memcpy(&aNum[4-nOut], aOut, nOut); + } + sqlite3_free(aOut); + val = (aNum[0]<<24) | (aNum[1]<<16) | (aNum[2]<<8) | aNum[3]; + Tcl_SetObjResult(interp, Tcl_NewIntObj(val)); + return TCL_OK; +} + + +/* +** USAGE: hexio_render_int16 INTEGER +** +** Render INTEGER has a 16-bit big-endian integer in hexadecimal. +*/ +static int hexio_render_int16( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int val; + unsigned char aNum[10]; + + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "INTEGER"); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, objv[1], &val) ) return TCL_ERROR; + aNum[0] = val>>8; + aNum[1] = val; + sqlite3TestBinToHex(aNum, 2); + Tcl_SetObjResult(interp, Tcl_NewStringObj((char*)aNum, 4)); + return TCL_OK; +} + + +/* +** USAGE: hexio_render_int32 INTEGER +** +** Render INTEGER has a 32-bit big-endian integer in hexadecimal. +*/ +static int hexio_render_int32( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int val; + unsigned char aNum[10]; + + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "INTEGER"); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, objv[1], &val) ) return TCL_ERROR; + aNum[0] = val>>24; + aNum[1] = val>>16; + aNum[2] = val>>8; + aNum[3] = val; + sqlite3TestBinToHex(aNum, 4); + Tcl_SetObjResult(interp, Tcl_NewStringObj((char*)aNum, 8)); + return TCL_OK; +} + +/* +** USAGE: utf8_to_utf8 HEX +** +** The argument is a UTF8 string represented in hexadecimal. +** The UTF8 might not be well-formed. Run this string through +** sqlite3Utf8to8() convert it back to hex and return the result. +*/ +static int utf8_to_utf8( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ +#ifdef SQLITE_DEBUG + int n; + int nOut; + const unsigned char *zOrig; + unsigned char *z; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "HEX"); + return TCL_ERROR; + } + zOrig = (unsigned char *)Tcl_GetStringFromObj(objv[1], &n); + z = sqlite3_malloc( n+3 ); + n = sqlite3TestHexToBin(zOrig, n, z); + z[n] = 0; + nOut = sqlite3Utf8To8(z); + sqlite3TestBinToHex(z,nOut); + Tcl_AppendResult(interp, (char*)z, 0); + sqlite3_free(z); +#endif + return TCL_OK; +} + + +/* +** Register commands with the TCL interpreter. +*/ +int Sqlitetest_hexio_Init(Tcl_Interp *interp){ + static struct { + char *zName; + Tcl_ObjCmdProc *xProc; + } aObjCmd[] = { + { "hexio_read", hexio_read }, + { "hexio_write", hexio_write }, + { "hexio_get_int", hexio_get_int }, + { "hexio_render_int16", hexio_render_int16 }, + { "hexio_render_int32", hexio_render_int32 }, + { "utf8_to_utf8", utf8_to_utf8 }, + }; + int i; + for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ + Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0); + } + return TCL_OK; +} diff --git a/third_party/sqlite/src/test_loadext.c b/third_party/sqlite/src/test_loadext.c new file mode 100755 index 0000000..e973566 --- /dev/null +++ b/third_party/sqlite/src/test_loadext.c @@ -0,0 +1,124 @@ +/* +** 2006 June 14 +** +** 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. +** +************************************************************************* +** Test extension for testing the sqlite3_load_extension() function. +** +** $Id: test_loadext.c,v 1.3 2008/08/02 03:50:39 drh Exp $ +*/ +#include <string.h> +#include "sqlite3ext.h" +SQLITE_EXTENSION_INIT1 + +/* +** The half() SQL function returns half of its input value. +*/ +static void halfFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + sqlite3_result_double(context, 0.5*sqlite3_value_double(argv[0])); +} + +/* +** SQL functions to call the sqlite3_status function and return results. +*/ +static void statusFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + int op, mx, cur, resetFlag, rc; + if( sqlite3_value_type(argv[0])==SQLITE_INTEGER ){ + op = sqlite3_value_int(argv[0]); + }else if( sqlite3_value_type(argv[0])==SQLITE_TEXT ){ + int i; + const char *zName; + static const struct { + const char *zName; + int op; + } aOp[] = { + { "MEMORY_USED", SQLITE_STATUS_MEMORY_USED }, + { "PAGECACHE_USED", SQLITE_STATUS_PAGECACHE_USED }, + { "PAGECACHE_OVERFLOW", SQLITE_STATUS_PAGECACHE_OVERFLOW }, + { "SCRATCH_USED", SQLITE_STATUS_SCRATCH_USED }, + { "SCRATCH_OVERFLOW", SQLITE_STATUS_SCRATCH_OVERFLOW }, + { "MALLOC_SIZE", SQLITE_STATUS_MALLOC_SIZE }, + }; + int nOp = sizeof(aOp)/sizeof(aOp[0]); + zName = (const char*)sqlite3_value_text(argv[0]); + for(i=0; i<nOp; i++){ + if( strcmp(aOp[i].zName, zName)==0 ){ + op = aOp[i].op; + break; + } + } + if( i>=nOp ){ + char *zMsg = sqlite3_mprintf("unknown status property: %s", zName); + sqlite3_result_error(context, zMsg, -1); + sqlite3_free(zMsg); + return; + } + }else{ + sqlite3_result_error(context, "unknown status type", -1); + return; + } + if( argc==2 ){ + resetFlag = sqlite3_value_int(argv[1]); + }else{ + resetFlag = 0; + } + rc = sqlite3_status(op, &cur, &mx, resetFlag); + if( rc!=SQLITE_OK ){ + char *zMsg = sqlite3_mprintf("sqlite3_status(%d,...) returns %d", op, rc); + sqlite3_result_error(context, zMsg, -1); + sqlite3_free(zMsg); + return; + } + if( argc==2 ){ + sqlite3_result_int(context, mx); + }else{ + sqlite3_result_int(context, cur); + } +} + +/* +** Extension load function. +*/ +int testloadext_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + int nErr = 0; + SQLITE_EXTENSION_INIT2(pApi); + nErr |= sqlite3_create_function(db, "half", 1, SQLITE_ANY, 0, halfFunc, 0, 0); + nErr |= sqlite3_create_function(db, "sqlite3_status", 1, SQLITE_ANY, 0, + statusFunc, 0, 0); + nErr |= sqlite3_create_function(db, "sqlite3_status", 2, SQLITE_ANY, 0, + statusFunc, 0, 0); + return nErr ? SQLITE_ERROR : SQLITE_OK; +} + +/* +** Another extension entry point. This one always fails. +*/ +int testbrokenext_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + char *zErr; + SQLITE_EXTENSION_INIT2(pApi); + zErr = sqlite3_mprintf("broken!"); + *pzErrMsg = zErr; + return 1; +} diff --git a/third_party/sqlite/src/test_malloc.c b/third_party/sqlite/src/test_malloc.c new file mode 100755 index 0000000..24d2389 --- /dev/null +++ b/third_party/sqlite/src/test_malloc.c @@ -0,0 +1,1339 @@ +/* +** 2007 August 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file contains code used to implement test interfaces to the +** memory allocation subsystem. +** +** $Id: test_malloc.c,v 1.47 2008/08/05 17:53:24 drh Exp $ +*/ +#include "sqliteInt.h" +#include "tcl.h" +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +/* +** This structure is used to encapsulate the global state variables used +** by malloc() fault simulation. +*/ +static struct MemFault { + int iCountdown; /* Number of pending successes before a failure */ + int nRepeat; /* Number of times to repeat the failure */ + int nBenign; /* Number of benign failures seen since last config */ + int nFail; /* Number of failures seen since last config */ + u8 enable; /* True if enabled */ + int isInstalled; /* True if the fault simulation layer is installed */ + int isBenignMode; /* True if malloc failures are considered benign */ + sqlite3_mem_methods m; /* 'Real' malloc implementation */ +} memfault; + +/* +** This routine exists as a place to set a breakpoint that will +** fire on any simulated malloc() failure. +*/ +static void sqlite3Fault(void){ + static int cnt = 0; + cnt++; +} + +/* +** Check to see if a fault should be simulated. Return true to simulate +** the fault. Return false if the fault should not be simulated. +*/ +static int faultsimStep(){ + if( likely(!memfault.enable) ){ + return 0; + } + if( memfault.iCountdown>0 ){ + memfault.iCountdown--; + return 0; + } + sqlite3Fault(); + memfault.nFail++; + if( memfault.isBenignMode>0 ){ + memfault.nBenign++; + } + memfault.nRepeat--; + if( memfault.nRepeat<=0 ){ + memfault.enable = 0; + } + return 1; +} + +/* +** A version of sqlite3_mem_methods.xMalloc() that includes fault simulation +** logic. +*/ +static void *faultsimMalloc(int n){ + void *p = 0; + if( !faultsimStep() ){ + p = memfault.m.xMalloc(n); + } + return p; +} + + +/* +** A version of sqlite3_mem_methods.xRealloc() that includes fault simulation +** logic. +*/ +static void *faultsimRealloc(void *pOld, int n){ + void *p = 0; + if( !faultsimStep() ){ + p = memfault.m.xRealloc(pOld, n); + } + return p; +} + +/* +** The following method calls are passed directly through to the underlying +** malloc system: +** +** xFree +** xSize +** xRoundup +** xInit +** xShutdown +*/ +static void faultsimFree(void *p){ + memfault.m.xFree(p); +} +static int faultsimSize(void *p){ + return memfault.m.xSize(p); +} +static int faultsimRoundup(int n){ + return memfault.m.xRoundup(n); +} +static int faultsimInit(void *p){ + return memfault.m.xInit(memfault.m.pAppData); +} +static void faultsimShutdown(void *p){ + memfault.m.xShutdown(memfault.m.pAppData); +} + +/* +** This routine configures the malloc failure simulation. After +** calling this routine, the next nDelay mallocs will succeed, followed +** by a block of nRepeat failures, after which malloc() calls will begin +** to succeed again. +*/ +static void faultsimConfig(int nDelay, int nRepeat){ + memfault.iCountdown = nDelay; + memfault.nRepeat = nRepeat; + memfault.nBenign = 0; + memfault.nFail = 0; + memfault.enable = nDelay>=0; +} + +/* +** Return the number of faults (both hard and benign faults) that have +** occurred since the injector was last configured. +*/ +static int faultsimFailures(void){ + return memfault.nFail; +} + +/* +** Return the number of benign faults that have occurred since the +** injector was last configured. +*/ +static int faultsimBenignFailures(void){ + return memfault.nBenign; +} + +/* +** Return the number of successes that will occur before the next failure. +** If no failures are scheduled, return -1. +*/ +static int faultsimPending(void){ + if( memfault.enable ){ + return memfault.iCountdown; + }else{ + return -1; + } +} + + +static void faultsimBeginBenign(void){ + memfault.isBenignMode++; +} +static void faultsimEndBenign(void){ + memfault.isBenignMode--; +} + +/* +** Add or remove the fault-simulation layer using sqlite3_config(). If +** the argument is non-zero, the +*/ +static int faultsimInstall(int install){ + static struct sqlite3_mem_methods m = { + faultsimMalloc, /* xMalloc */ + faultsimFree, /* xFree */ + faultsimRealloc, /* xRealloc */ + faultsimSize, /* xSize */ + faultsimRoundup, /* xRoundup */ + faultsimInit, /* xInit */ + faultsimShutdown, /* xShutdown */ + 0 /* pAppData */ + }; + int rc; + + install = (install ? 1 : 0); + assert(memfault.isInstalled==1 || memfault.isInstalled==0); + + if( install==memfault.isInstalled ){ + return SQLITE_ERROR; + } + + if( install ){ + rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memfault.m); + assert(memfault.m.xMalloc); + if( rc==SQLITE_OK ){ + rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &m); + } + sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, + faultsimBeginBenign, faultsimEndBenign + ); + }else{ + assert(memfault.m.xMalloc); + rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memfault.m); + sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, 0, 0); + } + + if( rc==SQLITE_OK ){ + memfault.isInstalled = 1; + } + return rc; +} + +#ifdef SQLITE_TEST + +/* +** This function is implemented in test1.c. Returns a pointer to a static +** buffer containing the symbolic SQLite error code that corresponds to +** the least-significant 8-bits of the integer passed as an argument. +** For example: +** +** sqlite3TestErrorName(1) -> "SQLITE_ERROR" +*/ +const char *sqlite3TestErrorName(int); + +/* +** Transform pointers to text and back again +*/ +static void pointerToText(void *p, char *z){ + static const char zHex[] = "0123456789abcdef"; + int i, k; + unsigned int u; + sqlite3_uint64 n; + if( p==0 ){ + strcpy(z, "0"); + return; + } + if( sizeof(n)==sizeof(p) ){ + memcpy(&n, &p, sizeof(p)); + }else if( sizeof(u)==sizeof(p) ){ + memcpy(&u, &p, sizeof(u)); + n = u; + }else{ + assert( 0 ); + } + for(i=0, k=sizeof(p)*2-1; i<sizeof(p)*2; i++, k--){ + z[k] = zHex[n&0xf]; + n >>= 4; + } + z[sizeof(p)*2] = 0; +} +static int hexToInt(int h){ + if( h>='0' && h<='9' ){ + return h - '0'; + }else if( h>='a' && h<='f' ){ + return h - 'a' + 10; + }else{ + return -1; + } +} +static int textToPointer(const char *z, void **pp){ + sqlite3_uint64 n = 0; + int i; + unsigned int u; + for(i=0; i<sizeof(void*)*2 && z[0]; i++){ + int v; + v = hexToInt(*z++); + if( v<0 ) return TCL_ERROR; + n = n*16 + v; + } + if( *z!=0 ) return TCL_ERROR; + if( sizeof(n)==sizeof(*pp) ){ + memcpy(pp, &n, sizeof(n)); + }else if( sizeof(u)==sizeof(*pp) ){ + u = (unsigned int)n; + memcpy(pp, &u, sizeof(u)); + }else{ + assert( 0 ); + } + return TCL_OK; +} + +/* +** Usage: sqlite3_malloc NBYTES +** +** Raw test interface for sqlite3_malloc(). +*/ +static int test_malloc( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int nByte; + void *p; + char zOut[100]; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "NBYTES"); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, objv[1], &nByte) ) return TCL_ERROR; + p = sqlite3_malloc((unsigned)nByte); + pointerToText(p, zOut); + Tcl_AppendResult(interp, zOut, NULL); + return TCL_OK; +} + +/* +** Usage: sqlite3_realloc PRIOR NBYTES +** +** Raw test interface for sqlite3_realloc(). +*/ +static int test_realloc( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int nByte; + void *pPrior, *p; + char zOut[100]; + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "PRIOR NBYTES"); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, objv[2], &nByte) ) return TCL_ERROR; + if( textToPointer(Tcl_GetString(objv[1]), &pPrior) ){ + Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0); + return TCL_ERROR; + } + p = sqlite3_realloc(pPrior, (unsigned)nByte); + pointerToText(p, zOut); + Tcl_AppendResult(interp, zOut, NULL); + return TCL_OK; +} + +/* +** Usage: sqlite3_free PRIOR +** +** Raw test interface for sqlite3_free(). +*/ +static int test_free( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + void *pPrior; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "PRIOR"); + return TCL_ERROR; + } + if( textToPointer(Tcl_GetString(objv[1]), &pPrior) ){ + Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0); + return TCL_ERROR; + } + sqlite3_free(pPrior); + return TCL_OK; +} + +/* +** These routines are in test_hexio.c +*/ +int sqlite3TestHexToBin(const char *, int, char *); +int sqlite3TestBinToHex(char*,int); + +/* +** Usage: memset ADDRESS SIZE HEX +** +** Set a chunk of memory (obtained from malloc, probably) to a +** specified hex pattern. +*/ +static int test_memset( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + void *p; + int size, n, i; + char *zHex; + char *zOut; + char zBin[100]; + + if( objc!=4 ){ + Tcl_WrongNumArgs(interp, 1, objv, "ADDRESS SIZE HEX"); + return TCL_ERROR; + } + if( textToPointer(Tcl_GetString(objv[1]), &p) ){ + Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, objv[2], &size) ){ + return TCL_ERROR; + } + if( size<=0 ){ + Tcl_AppendResult(interp, "size must be positive", (char*)0); + return TCL_ERROR; + } + zHex = Tcl_GetStringFromObj(objv[3], &n); + if( n>sizeof(zBin)*2 ) n = sizeof(zBin)*2; + n = sqlite3TestHexToBin(zHex, n, zBin); + if( n==0 ){ + Tcl_AppendResult(interp, "no data", (char*)0); + return TCL_ERROR; + } + zOut = p; + for(i=0; i<size; i++){ + zOut[i] = zBin[i%n]; + } + return TCL_OK; +} + +/* +** Usage: memget ADDRESS SIZE +** +** Return memory as hexadecimal text. +*/ +static int test_memget( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + void *p; + int size, n; + char *zBin; + char zHex[100]; + + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "ADDRESS SIZE"); + return TCL_ERROR; + } + if( textToPointer(Tcl_GetString(objv[1]), &p) ){ + Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, objv[2], &size) ){ + return TCL_ERROR; + } + if( size<=0 ){ + Tcl_AppendResult(interp, "size must be positive", (char*)0); + return TCL_ERROR; + } + zBin = p; + while( size>0 ){ + if( size>(sizeof(zHex)-1)/2 ){ + n = (sizeof(zHex)-1)/2; + }else{ + n = size; + } + memcpy(zHex, zBin, n); + zBin += n; + size -= n; + sqlite3TestBinToHex(zHex, n); + Tcl_AppendResult(interp, zHex, (char*)0); + } + return TCL_OK; +} + +/* +** Usage: sqlite3_memory_used +** +** Raw test interface for sqlite3_memory_used(). +*/ +static int test_memory_used( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sqlite3_memory_used())); + return TCL_OK; +} + +/* +** Usage: sqlite3_memory_highwater ?RESETFLAG? +** +** Raw test interface for sqlite3_memory_highwater(). +*/ +static int test_memory_highwater( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int resetFlag = 0; + if( objc!=1 && objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "?RESET?"); + return TCL_ERROR; + } + if( objc==2 ){ + if( Tcl_GetBooleanFromObj(interp, objv[1], &resetFlag) ) return TCL_ERROR; + } + Tcl_SetObjResult(interp, + Tcl_NewWideIntObj(sqlite3_memory_highwater(resetFlag))); + return TCL_OK; +} + +/* +** Usage: sqlite3_memdebug_backtrace DEPTH +** +** Set the depth of backtracing. If SQLITE_MEMDEBUG is not defined +** then this routine is a no-op. +*/ +static int test_memdebug_backtrace( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int depth; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DEPT"); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, objv[1], &depth) ) return TCL_ERROR; +#ifdef SQLITE_MEMDEBUG + { + extern void sqlite3MemdebugBacktrace(int); + sqlite3MemdebugBacktrace(depth); + } +#endif + return TCL_OK; +} + +/* +** Usage: sqlite3_memdebug_dump FILENAME +** +** Write a summary of unfreed memory to FILENAME. +*/ +static int test_memdebug_dump( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "FILENAME"); + return TCL_ERROR; + } +#if defined(SQLITE_MEMDEBUG) || defined(SQLITE_MEMORY_SIZE) \ + || defined(SQLITE_POW2_MEMORY_SIZE) + { + extern void sqlite3MemdebugDump(const char*); + sqlite3MemdebugDump(Tcl_GetString(objv[1])); + } +#endif + return TCL_OK; +} + +/* +** Usage: sqlite3_memdebug_malloc_count +** +** Return the total number of times malloc() has been called. +*/ +static int test_memdebug_malloc_count( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int nMalloc = -1; + if( objc!=1 ){ + Tcl_WrongNumArgs(interp, 1, objv, ""); + return TCL_ERROR; + } +#if defined(SQLITE_MEMDEBUG) + { + extern int sqlite3MemdebugMallocCount(); + nMalloc = sqlite3MemdebugMallocCount(); + } +#endif + Tcl_SetObjResult(interp, Tcl_NewIntObj(nMalloc)); + return TCL_OK; +} + + +/* +** Usage: sqlite3_memdebug_fail COUNTER ?OPTIONS? +** +** where options are: +** +** -repeat <count> +** -benigncnt <varname> +** +** Arrange for a simulated malloc() failure after COUNTER successes. +** If a repeat count is specified, the fault is repeated that many +** times. +** +** Each call to this routine overrides the prior counter value. +** This routine returns the number of simulated failures that have +** happened since the previous call to this routine. +** +** To disable simulated failures, use a COUNTER of -1. +*/ +static int test_memdebug_fail( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int ii; + int iFail; + int nRepeat = 1; + Tcl_Obj *pBenignCnt = 0; + int nBenign; + int nFail = 0; + + if( objc<2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "COUNTER ?OPTIONS?"); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, objv[1], &iFail) ) return TCL_ERROR; + + for(ii=2; ii<objc; ii+=2){ + int nOption; + char *zOption = Tcl_GetStringFromObj(objv[ii], &nOption); + char *zErr = 0; + + if( nOption>1 && strncmp(zOption, "-repeat", nOption)==0 ){ + if( ii==(objc-1) ){ + zErr = "option requires an argument: "; + }else{ + if( Tcl_GetIntFromObj(interp, objv[ii+1], &nRepeat) ){ + return TCL_ERROR; + } + } + }else if( nOption>1 && strncmp(zOption, "-benigncnt", nOption)==0 ){ + if( ii==(objc-1) ){ + zErr = "option requires an argument: "; + }else{ + pBenignCnt = objv[ii+1]; + } + }else{ + zErr = "unknown option: "; + } + + if( zErr ){ + Tcl_AppendResult(interp, zErr, zOption, 0); + return TCL_ERROR; + } + } + + nBenign = faultsimBenignFailures(); + nFail = faultsimFailures(); + faultsimConfig(iFail, nRepeat); + + if( pBenignCnt ){ + Tcl_ObjSetVar2(interp, pBenignCnt, 0, Tcl_NewIntObj(nBenign), 0); + } + Tcl_SetObjResult(interp, Tcl_NewIntObj(nFail)); + return TCL_OK; +} + +/* +** Usage: sqlite3_memdebug_pending +** +** Return the number of malloc() calls that will succeed before a +** simulated failure occurs. A negative return value indicates that +** no malloc() failure is scheduled. +*/ +static int test_memdebug_pending( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int nPending; + if( objc!=1 ){ + Tcl_WrongNumArgs(interp, 1, objv, ""); + return TCL_ERROR; + } + nPending = faultsimPending(); + Tcl_SetObjResult(interp, Tcl_NewIntObj(nPending)); + return TCL_OK; +} + + +/* +** Usage: sqlite3_memdebug_settitle TITLE +** +** Set a title string stored with each allocation. The TITLE is +** typically the name of the test that was running when the +** allocation occurred. The TITLE is stored with the allocation +** and can be used to figure out which tests are leaking memory. +** +** Each title overwrite the previous. +*/ +static int test_memdebug_settitle( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + const char *zTitle; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "TITLE"); + return TCL_ERROR; + } + zTitle = Tcl_GetString(objv[1]); +#ifdef SQLITE_MEMDEBUG + { + extern int sqlite3MemdebugSettitle(const char*); + sqlite3MemdebugSettitle(zTitle); + } +#endif + return TCL_OK; +} + +#define MALLOC_LOG_FRAMES 10 +static Tcl_HashTable aMallocLog; +static int mallocLogEnabled = 0; + +typedef struct MallocLog MallocLog; +struct MallocLog { + int nCall; + int nByte; +}; + +#ifdef SQLITE_MEMDEBUG +static void test_memdebug_callback(int nByte, int nFrame, void **aFrame){ + if( mallocLogEnabled ){ + MallocLog *pLog; + Tcl_HashEntry *pEntry; + int isNew; + + int aKey[MALLOC_LOG_FRAMES]; + int nKey = sizeof(int)*MALLOC_LOG_FRAMES; + + memset(aKey, 0, nKey); + if( (sizeof(void*)*nFrame)<nKey ){ + nKey = nFrame*sizeof(void*); + } + memcpy(aKey, aFrame, nKey); + + pEntry = Tcl_CreateHashEntry(&aMallocLog, (const char *)aKey, &isNew); + if( isNew ){ + pLog = (MallocLog *)Tcl_Alloc(sizeof(MallocLog)); + memset(pLog, 0, sizeof(MallocLog)); + Tcl_SetHashValue(pEntry, (ClientData)pLog); + }else{ + pLog = (MallocLog *)Tcl_GetHashValue(pEntry); + } + + pLog->nCall++; + pLog->nByte += nByte; + } +} +#endif /* SQLITE_MEMDEBUG */ + +static void test_memdebug_log_clear(){ + Tcl_HashSearch search; + Tcl_HashEntry *pEntry; + for( + pEntry=Tcl_FirstHashEntry(&aMallocLog, &search); + pEntry; + pEntry=Tcl_NextHashEntry(&search) + ){ + MallocLog *pLog = (MallocLog *)Tcl_GetHashValue(pEntry); + Tcl_Free((char *)pLog); + } + Tcl_DeleteHashTable(&aMallocLog); + Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_FRAMES); +} + +static int test_memdebug_log( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + static int isInit = 0; + int iSub; + + static const char *MB_strs[] = { "start", "stop", "dump", "clear", "sync" }; + enum MB_enum { + MB_LOG_START, MB_LOG_STOP, MB_LOG_DUMP, MB_LOG_CLEAR, MB_LOG_SYNC + }; + + if( !isInit ){ +#ifdef SQLITE_MEMDEBUG + extern void sqlite3MemdebugBacktraceCallback( + void (*xBacktrace)(int, int, void **)); + sqlite3MemdebugBacktraceCallback(test_memdebug_callback); +#endif + Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_FRAMES); + isInit = 1; + } + + if( objc<2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ..."); + } + if( Tcl_GetIndexFromObj(interp, objv[1], MB_strs, "sub-command", 0, &iSub) ){ + return TCL_ERROR; + } + + switch( (enum MB_enum)iSub ){ + case MB_LOG_START: + mallocLogEnabled = 1; + break; + case MB_LOG_STOP: + mallocLogEnabled = 0; + break; + case MB_LOG_DUMP: { + Tcl_HashSearch search; + Tcl_HashEntry *pEntry; + Tcl_Obj *pRet = Tcl_NewObj(); + + assert(sizeof(int)==sizeof(void*)); + + for( + pEntry=Tcl_FirstHashEntry(&aMallocLog, &search); + pEntry; + pEntry=Tcl_NextHashEntry(&search) + ){ + Tcl_Obj *apElem[MALLOC_LOG_FRAMES+2]; + MallocLog *pLog = (MallocLog *)Tcl_GetHashValue(pEntry); + int *aKey = (int *)Tcl_GetHashKey(&aMallocLog, pEntry); + int ii; + + apElem[0] = Tcl_NewIntObj(pLog->nCall); + apElem[1] = Tcl_NewIntObj(pLog->nByte); + for(ii=0; ii<MALLOC_LOG_FRAMES; ii++){ + apElem[ii+2] = Tcl_NewIntObj(aKey[ii]); + } + + Tcl_ListObjAppendElement(interp, pRet, + Tcl_NewListObj(MALLOC_LOG_FRAMES+2, apElem) + ); + } + + Tcl_SetObjResult(interp, pRet); + break; + } + case MB_LOG_CLEAR: { + test_memdebug_log_clear(); + break; + } + + case MB_LOG_SYNC: { +#ifdef SQLITE_MEMDEBUG + extern void sqlite3MemdebugSync(); + test_memdebug_log_clear(); + mallocLogEnabled = 1; + sqlite3MemdebugSync(); +#endif + break; + } + } + + return TCL_OK; +} + +/* +** Usage: sqlite3_config_scratch SIZE N +** +** Set the scratch memory buffer using SQLITE_CONFIG_SCRATCH. +** The buffer is static and is of limited size. N might be +** adjusted downward as needed to accomodate the requested size. +** The revised value of N is returned. +** +** A negative SIZE causes the buffer pointer to be NULL. +*/ +static int test_config_scratch( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int sz, N, rc; + Tcl_Obj *pResult; + static char *buf = 0; + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "SIZE N"); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &N) ) return TCL_ERROR; + free(buf); + if( sz<0 ){ + buf = 0; + rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, 0, 0, 0); + }else{ + buf = malloc( sz*N + 1 ); + rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, buf, sz, N); + } + pResult = Tcl_NewObj(); + Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc)); + Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(N)); + Tcl_SetObjResult(interp, pResult); + return TCL_OK; +} + +/* +** Usage: sqlite3_config_pagecache SIZE N +** +** Set the page-cache memory buffer using SQLITE_CONFIG_PAGECACHE. +** The buffer is static and is of limited size. N might be +** adjusted downward as needed to accomodate the requested size. +** The revised value of N is returned. +** +** A negative SIZE causes the buffer pointer to be NULL. +*/ +static int test_config_pagecache( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int sz, N, rc; + Tcl_Obj *pResult; + static char *buf = 0; + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "SIZE N"); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &N) ) return TCL_ERROR; + free(buf); + if( sz<0 ){ + buf = 0; + rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, 0, 0, 0); + }else{ + buf = malloc( sz*N ); + rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, buf, sz, N); + } + pResult = Tcl_NewObj(); + Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc)); + Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(N)); + Tcl_SetObjResult(interp, pResult); + return TCL_OK; +} + +/* +** Usage: sqlite3_config_memstatus BOOLEAN +** +** Enable or disable memory status reporting using SQLITE_CONFIG_MEMSTATUS. +*/ +static int test_config_memstatus( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int enable, rc; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN"); + return TCL_ERROR; + } + if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ) return TCL_ERROR; + rc = sqlite3_config(SQLITE_CONFIG_MEMSTATUS, enable); + Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); + return TCL_OK; +} + +/* +** Usage: sqlite3_config_chunkalloc +** +*/ +static int test_config_chunkalloc( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int rc; + int nThreshold; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "THRESHOLD"); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, objv[1], &nThreshold) ) return TCL_ERROR; + rc = sqlite3_config(SQLITE_CONFIG_CHUNKALLOC, nThreshold); + Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); + return TCL_OK; +} + +/* +** Usage: sqlite3_config_lookaside SIZE COUNT +** +*/ +static int test_config_lookaside( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int rc; + int sz, cnt; + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "SIZE COUNT"); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &cnt) ) return TCL_ERROR; + rc = sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, cnt); + Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); + return TCL_OK; +} + + +/* +** Usage: sqlite3_db_config_lookaside CONNECTION BUFID SIZE COUNT +** +** There are two static buffers with BUFID 1 and 2. Each static buffer +** is 10KB in size. A BUFID of 0 indicates that the buffer should be NULL +** which will cause sqlite3_db_config() to allocate space on its own. +*/ +static int test_db_config_lookaside( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int rc; + int sz, cnt; + sqlite3 *db; + int bufid; + static char azBuf[2][10000]; + int getDbPointer(Tcl_Interp*, const char*, sqlite3**); + if( objc!=5 ){ + Tcl_WrongNumArgs(interp, 1, objv, "BUFID SIZE COUNT"); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &bufid) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[3], &sz) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[4], &cnt) ) return TCL_ERROR; + if( bufid==0 ){ + rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, 0, sz, cnt); + }else if( bufid>=1 && bufid<=2 && sz*cnt<=sizeof(azBuf[0]) ){ + rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, azBuf[bufid], sz,cnt); + }else{ + Tcl_AppendResult(interp, "illegal arguments - see documentation", (char*)0); + return TCL_ERROR; + } + Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); + return TCL_OK; +} + +/* +** Usage: +** +** sqlite3_config_heap NBYTE NMINALLOC +*/ +static int test_config_heap( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + static char *zBuf; /* Use this memory */ + static int szBuf; /* Bytes allocated for zBuf */ + int nByte; /* Size of buffer to pass to sqlite3_config() */ + int nMinAlloc; /* Size of minimum allocation */ + int rc; /* Return code of sqlite3_config() */ + + Tcl_Obj * CONST *aArg = &objv[1]; + int nArg = objc-1; + + if( nArg!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "NBYTE NMINALLOC"); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, aArg[0], &nByte) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, aArg[1], &nMinAlloc) ) return TCL_ERROR; + + if( nByte==0 ){ + free( zBuf ); + zBuf = 0; + szBuf = 0; + rc = sqlite3_config(SQLITE_CONFIG_HEAP, (void*)0, 0, 0); + }else{ + zBuf = realloc(zBuf, nByte); + szBuf = nByte; + rc = sqlite3_config(SQLITE_CONFIG_HEAP, zBuf, nByte, nMinAlloc); + } + + Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE); + return TCL_OK; +} + +/* +** tclcmd: sqlite3_config_error [DB] +** +** Invoke sqlite3_config() or sqlite3_db_config() with invalid +** opcodes and verify that they return errors. +*/ +static int test_config_error( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3 *db; + int getDbPointer(Tcl_Interp*, const char*, sqlite3**); + + if( objc!=2 && objc!=1 ){ + Tcl_WrongNumArgs(interp, 1, objv, "[DB]"); + return TCL_ERROR; + } + if( objc==2 ){ + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + if( sqlite3_db_config(db, 99999)!=SQLITE_ERROR ){ + Tcl_AppendResult(interp, + "sqlite3_db_config(db, 99999) does not return SQLITE_ERROR", + (char*)0); + return TCL_ERROR; + } + }else{ + if( sqlite3_config(99999)!=SQLITE_ERROR ){ + Tcl_AppendResult(interp, + "sqlite3_config(99999) does not return SQLITE_ERROR", + (char*)0); + return TCL_ERROR; + } + } + return TCL_OK; +} + +/* +** Usage: +** +** sqlite3_dump_memsys3 FILENAME +** sqlite3_dump_memsys5 FILENAME +** +** Write a summary of unfreed memsys3 allocations to FILENAME. +*/ +static int test_dump_memsys3( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "FILENAME"); + return TCL_ERROR; + } + + switch( (int)clientData ){ + case 3: { +#ifdef SQLITE_ENABLE_MEMSYS3 + extern void sqlite3Memsys3Dump(const char*); + sqlite3Memsys3Dump(Tcl_GetString(objv[1])); + break; +#endif + } + case 5: { +#ifdef SQLITE_ENABLE_MEMSYS5 + extern void sqlite3Memsys5Dump(const char*); + sqlite3Memsys5Dump(Tcl_GetString(objv[1])); + break; +#endif + } + } + return TCL_OK; +} + +/* +** Usage: sqlite3_status OPCODE RESETFLAG +** +** Return a list of three elements which are the sqlite3_status() return +** code, the current value, and the high-water mark value. +*/ +static int test_status( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int rc, iValue, mxValue; + int i, op, resetFlag; + const char *zOpName; + static const struct { + const char *zName; + int op; + } aOp[] = { + { "SQLITE_STATUS_MEMORY_USED", SQLITE_STATUS_MEMORY_USED }, + { "SQLITE_STATUS_MALLOC_SIZE", SQLITE_STATUS_MALLOC_SIZE }, + { "SQLITE_STATUS_PAGECACHE_USED", SQLITE_STATUS_PAGECACHE_USED }, + { "SQLITE_STATUS_PAGECACHE_OVERFLOW", SQLITE_STATUS_PAGECACHE_OVERFLOW }, + { "SQLITE_STATUS_PAGECACHE_SIZE", SQLITE_STATUS_PAGECACHE_SIZE }, + { "SQLITE_STATUS_SCRATCH_USED", SQLITE_STATUS_SCRATCH_USED }, + { "SQLITE_STATUS_SCRATCH_OVERFLOW", SQLITE_STATUS_SCRATCH_OVERFLOW }, + { "SQLITE_STATUS_SCRATCH_SIZE", SQLITE_STATUS_SCRATCH_SIZE }, + { "SQLITE_STATUS_PARSER_STACK", SQLITE_STATUS_PARSER_STACK }, + }; + Tcl_Obj *pResult; + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "PARAMETER RESETFLAG"); + return TCL_ERROR; + } + zOpName = Tcl_GetString(objv[1]); + for(i=0; i<ArraySize(aOp); i++){ + if( strcmp(aOp[i].zName, zOpName)==0 ){ + op = aOp[i].op; + break; + } + } + if( i>=ArraySize(aOp) ){ + if( Tcl_GetIntFromObj(interp, objv[1], &op) ) return TCL_ERROR; + } + if( Tcl_GetBooleanFromObj(interp, objv[2], &resetFlag) ) return TCL_ERROR; + iValue = 0; + mxValue = 0; + rc = sqlite3_status(op, &iValue, &mxValue, resetFlag); + pResult = Tcl_NewObj(); + Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc)); + Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(iValue)); + Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(mxValue)); + Tcl_SetObjResult(interp, pResult); + return TCL_OK; +} + +/* +** Usage: sqlite3_db_status DATABASE OPCODE RESETFLAG +** +** Return a list of three elements which are the sqlite3_db_status() return +** code, the current value, and the high-water mark value. +*/ +static int test_db_status( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int rc, iValue, mxValue; + int i, op, resetFlag; + const char *zOpName; + sqlite3 *db; + int getDbPointer(Tcl_Interp*, const char*, sqlite3**); + static const struct { + const char *zName; + int op; + } aOp[] = { + { "SQLITE_DBSTATUS_LOOKASIDE_USED", SQLITE_DBSTATUS_LOOKASIDE_USED }, + }; + Tcl_Obj *pResult; + if( objc!=4 ){ + Tcl_WrongNumArgs(interp, 1, objv, "PARAMETER RESETFLAG"); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + zOpName = Tcl_GetString(objv[2]); + for(i=0; i<ArraySize(aOp); i++){ + if( strcmp(aOp[i].zName, zOpName)==0 ){ + op = aOp[i].op; + break; + } + } + if( i>=ArraySize(aOp) ){ + if( Tcl_GetIntFromObj(interp, objv[2], &op) ) return TCL_ERROR; + } + if( Tcl_GetBooleanFromObj(interp, objv[3], &resetFlag) ) return TCL_ERROR; + iValue = 0; + mxValue = 0; + rc = sqlite3_db_status(db, op, &iValue, &mxValue, resetFlag); + pResult = Tcl_NewObj(); + Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc)); + Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(iValue)); + Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(mxValue)); + Tcl_SetObjResult(interp, pResult); + return TCL_OK; +} + +/* +** install_malloc_faultsim BOOLEAN +*/ +static int test_install_malloc_faultsim( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int rc; + int isInstall; + + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN"); + return TCL_ERROR; + } + if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[1], &isInstall) ){ + return TCL_ERROR; + } + rc = faultsimInstall(isInstall); + Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE); + return TCL_OK; +} + +/* +** Register commands with the TCL interpreter. +*/ +int Sqlitetest_malloc_Init(Tcl_Interp *interp){ + static struct { + char *zName; + Tcl_ObjCmdProc *xProc; + int clientData; + } aObjCmd[] = { + { "sqlite3_malloc", test_malloc ,0 }, + { "sqlite3_realloc", test_realloc ,0 }, + { "sqlite3_free", test_free ,0 }, + { "memset", test_memset ,0 }, + { "memget", test_memget ,0 }, + { "sqlite3_memory_used", test_memory_used ,0 }, + { "sqlite3_memory_highwater", test_memory_highwater ,0 }, + { "sqlite3_memdebug_backtrace", test_memdebug_backtrace ,0 }, + { "sqlite3_memdebug_dump", test_memdebug_dump ,0 }, + { "sqlite3_memdebug_fail", test_memdebug_fail ,0 }, + { "sqlite3_memdebug_pending", test_memdebug_pending ,0 }, + { "sqlite3_memdebug_settitle", test_memdebug_settitle ,0 }, + { "sqlite3_memdebug_malloc_count", test_memdebug_malloc_count ,0 }, + { "sqlite3_memdebug_log", test_memdebug_log ,0 }, + { "sqlite3_config_scratch", test_config_scratch ,0 }, + { "sqlite3_config_pagecache", test_config_pagecache ,0 }, + { "sqlite3_status", test_status ,0 }, + { "sqlite3_db_status", test_db_status ,0 }, + { "install_malloc_faultsim", test_install_malloc_faultsim ,0 }, + { "sqlite3_config_heap", test_config_heap ,0 }, + { "sqlite3_config_memstatus", test_config_memstatus ,0 }, + { "sqlite3_config_chunkalloc", test_config_chunkalloc ,0 }, + { "sqlite3_config_lookaside", test_config_lookaside ,0 }, + { "sqlite3_config_error", test_config_error ,0 }, + { "sqlite3_db_config_lookaside",test_db_config_lookaside ,0 }, + { "sqlite3_dump_memsys3", test_dump_memsys3 ,3 }, + { "sqlite3_dump_memsys5", test_dump_memsys3 ,5 } + }; + int i; + for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ + ClientData c = (ClientData)aObjCmd[i].clientData; + Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, c, 0); + } + return TCL_OK; +} +#endif diff --git a/third_party/sqlite/src/test_md5.c b/third_party/sqlite/src/test_md5.c new file mode 100755 index 0000000..0470d9f --- /dev/null +++ b/third_party/sqlite/src/test_md5.c @@ -0,0 +1,392 @@ +/* +** SQLite uses this code for testing only. It is not a part of +** the SQLite library. This file implements two new TCL commands +** "md5" and "md5file" that compute md5 checksums on arbitrary text +** and on complete files. These commands are used by the "testfixture" +** program to help verify the correct operation of the SQLite library. +** +** The original use of these TCL commands was to test the ROLLBACK +** feature of SQLite. First compute the MD5-checksum of the database. +** Then make some changes but rollback the changes rather than commit +** them. Compute a second MD5-checksum of the file and verify that the +** two checksums are the same. Such is the original use of this code. +** New uses may have been added since this comment was written. +** +** $Id: test_md5.c,v 1.8 2008/05/16 04:51:55 danielk1977 Exp $ +*/ +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ +#include <tcl.h> +#include <string.h> +#include "sqlite3.h" + +/* + * If compiled on a machine that doesn't have a 32-bit integer, + * you just set "uint32" to the appropriate datatype for an + * unsigned 32-bit integer. For example: + * + * cc -Duint32='unsigned long' md5.c + * + */ +#ifndef uint32 +# define uint32 unsigned int +#endif + +struct Context { + int isInit; + uint32 buf[4]; + uint32 bits[2]; + unsigned char in[64]; +}; +typedef struct Context MD5Context; + +/* + * Note: this code is harmless on little-endian machines. + */ +static void byteReverse (unsigned char *buf, unsigned longs){ + uint32 t; + do { + t = (uint32)((unsigned)buf[3]<<8 | buf[2]) << 16 | + ((unsigned)buf[1]<<8 | buf[0]); + *(uint32 *)buf = t; + buf += 4; + } while (--longs); +} +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +static void MD5Transform(uint32 buf[4], const uint32 in[16]){ + register uint32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +static void MD5Init(MD5Context *ctx){ + ctx->isInit = 1; + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +static +void MD5Update(MD5Context *pCtx, const unsigned char *buf, unsigned int len){ + struct Context *ctx = (struct Context *)pCtx; + uint32 t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((uint32)len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if ( t ) { + unsigned char *p = (unsigned char *)ctx->in + t; + + t = 64-t; + if (len < t) { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *)ctx->in); + buf += t; + len -= t; + } + + /* Process data in 64-byte chunks */ + + while (len >= 64) { + memcpy(ctx->in, buf, 64); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *)ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memcpy(ctx->in, buf, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +static void MD5Final(unsigned char digest[16], MD5Context *pCtx){ + struct Context *ctx = (struct Context *)pCtx; + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *)ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset(p, 0, count-8); + } + byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + ((uint32 *)ctx->in)[ 14 ] = ctx->bits[0]; + ((uint32 *)ctx->in)[ 15 ] = ctx->bits[1]; + + MD5Transform(ctx->buf, (uint32 *)ctx->in); + byteReverse((unsigned char *)ctx->buf, 4); + memcpy(digest, ctx->buf, 16); + memset(ctx, 0, sizeof(ctx)); /* In case it is sensitive */ +} + +/* +** Convert a digest into base-16. digest should be declared as +** "unsigned char digest[16]" in the calling function. The MD5 +** digest is stored in the first 16 bytes. zBuf should +** be "char zBuf[33]". +*/ +static void DigestToBase16(unsigned char *digest, char *zBuf){ + static char const zEncode[] = "0123456789abcdef"; + int i, j; + + for(j=i=0; i<16; i++){ + int a = digest[i]; + zBuf[j++] = zEncode[(a>>4)&0xf]; + zBuf[j++] = zEncode[a & 0xf]; + } + zBuf[j] = 0; +} + +/* +** A TCL command for md5. The argument is the text to be hashed. The +** Result is the hash in base64. +*/ +static int md5_cmd(void*cd, Tcl_Interp *interp, int argc, const char **argv){ + MD5Context ctx; + unsigned char digest[16]; + + if( argc!=2 ){ + Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0], + " TEXT\"", 0); + return TCL_ERROR; + } + MD5Init(&ctx); + MD5Update(&ctx, (unsigned char*)argv[1], (unsigned)strlen(argv[1])); + MD5Final(digest, &ctx); + DigestToBase16(digest, interp->result); + return TCL_OK; +} + +/* +** A TCL command to take the md5 hash of a file. The argument is the +** name of the file. +*/ +static int md5file_cmd(void*cd, Tcl_Interp*interp, int argc, const char **argv){ + FILE *in; + MD5Context ctx; + unsigned char digest[16]; + char zBuf[10240]; + + if( argc!=2 ){ + Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0], + " FILENAME\"", 0); + return TCL_ERROR; + } + in = fopen(argv[1],"rb"); + if( in==0 ){ + Tcl_AppendResult(interp,"unable to open file \"", argv[1], + "\" for reading", 0); + return TCL_ERROR; + } + MD5Init(&ctx); + for(;;){ + int n; + n = fread(zBuf, 1, sizeof(zBuf), in); + if( n<=0 ) break; + MD5Update(&ctx, (unsigned char*)zBuf, (unsigned)n); + } + fclose(in); + MD5Final(digest, &ctx); + DigestToBase16(digest, interp->result); + return TCL_OK; +} + +/* +** Register the two TCL commands above with the TCL interpreter. +*/ +int Md5_Init(Tcl_Interp *interp){ + Tcl_CreateCommand(interp, "md5", (Tcl_CmdProc*)md5_cmd, 0, 0); + Tcl_CreateCommand(interp, "md5file", (Tcl_CmdProc*)md5file_cmd, 0, 0); + return TCL_OK; +} + +/* +** During testing, the special md5sum() aggregate function is available. +** inside SQLite. The following routines implement that function. +*/ +static void md5step(sqlite3_context *context, int argc, sqlite3_value **argv){ + MD5Context *p; + int i; + if( argc<1 ) return; + p = sqlite3_aggregate_context(context, sizeof(*p)); + if( p==0 ) return; + if( !p->isInit ){ + MD5Init(p); + } + for(i=0; i<argc; i++){ + const char *zData = (char*)sqlite3_value_text(argv[i]); + if( zData ){ + MD5Update(p, (unsigned char*)zData, strlen(zData)); + } + } +} +static void md5finalize(sqlite3_context *context){ + MD5Context *p; + unsigned char digest[16]; + char zBuf[33]; + p = sqlite3_aggregate_context(context, sizeof(*p)); + MD5Final(digest,p); + DigestToBase16(digest, zBuf); + sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); +} +int Md5_Register(sqlite3 *db){ + int rc = sqlite3_create_function(db, "md5sum", -1, SQLITE_UTF8, 0, 0, + md5step, md5finalize); + sqlite3_overload_function(db, "md5sum", -1); /* To exercise this API */ + return rc; +} diff --git a/third_party/sqlite/src/test_mutex.c b/third_party/sqlite/src/test_mutex.c new file mode 100755 index 0000000..571f81a --- /dev/null +++ b/third_party/sqlite/src/test_mutex.c @@ -0,0 +1,387 @@ +/* +** 2008 June 18 +** +** 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. +** +************************************************************************* +** +** $Id: test_mutex.c,v 1.11 2008/07/19 13:43:24 danielk1977 Exp $ +*/ + +#include "tcl.h" +#include "sqlite3.h" +#include "sqliteInt.h" +#include <stdlib.h> +#include <assert.h> +#include <string.h> + +/* defined in test1.c */ +const char *sqlite3TestErrorName(int); + +/* A countable mutex */ +struct sqlite3_mutex { + sqlite3_mutex *pReal; + int eType; +}; + +/* State variables */ +static struct test_mutex_globals { + int isInstalled; /* True if installed */ + int disableInit; /* True to cause sqlite3_initalize() to fail */ + int disableTry; /* True to force sqlite3_mutex_try() to fail */ + int isInit; /* True if initialized */ + sqlite3_mutex_methods m; /* Interface to "real" mutex system */ + int aCounter[8]; /* Number of grabs of each type of mutex */ + sqlite3_mutex aStatic[6]; /* The six static mutexes */ +} g; + +/* Return true if the countable mutex is currently held */ +static int counterMutexHeld(sqlite3_mutex *p){ + return g.m.xMutexHeld(p->pReal); +} + +/* Return true if the countable mutex is not currently held */ +static int counterMutexNotheld(sqlite3_mutex *p){ + return g.m.xMutexNotheld(p->pReal); +} + +/* Initialize the countable mutex interface +** Or, if g.disableInit is non-zero, then do not initialize but instead +** return the value of g.disableInit as the result code. This can be used +** to simulate an initialization failure. +*/ +static int counterMutexInit(void){ + int rc; + if( g.disableInit ) return g.disableInit; + rc = g.m.xMutexInit(); + g.isInit = 1; + return rc; +} + +/* +** Uninitialize the mutex subsystem +*/ +static int counterMutexEnd(void){ + g.isInit = 0; + return g.m.xMutexEnd(); +} + +/* +** Allocate a countable mutex +*/ +static sqlite3_mutex *counterMutexAlloc(int eType){ + sqlite3_mutex *pReal; + sqlite3_mutex *pRet = 0; + + assert( g.isInit ); + assert(eType<8 && eType>=0); + + pReal = g.m.xMutexAlloc(eType); + if( !pReal ) return 0; + + if( eType==SQLITE_MUTEX_FAST || eType==SQLITE_MUTEX_RECURSIVE ){ + pRet = (sqlite3_mutex *)malloc(sizeof(sqlite3_mutex)); + }else{ + pRet = &g.aStatic[eType-2]; + } + + pRet->eType = eType; + pRet->pReal = pReal; + return pRet; +} + +/* +** Free a countable mutex +*/ +static void counterMutexFree(sqlite3_mutex *p){ + assert( g.isInit ); + g.m.xMutexFree(p->pReal); + if( p->eType==SQLITE_MUTEX_FAST || p->eType==SQLITE_MUTEX_RECURSIVE ){ + free(p); + } +} + +/* +** Enter a countable mutex. Block until entry is safe. +*/ +static void counterMutexEnter(sqlite3_mutex *p){ + assert( g.isInit ); + g.aCounter[p->eType]++; + g.m.xMutexEnter(p->pReal); +} + +/* +** Try to enter a mutex. Return true on success. +*/ +static int counterMutexTry(sqlite3_mutex *p){ + assert( g.isInit ); + g.aCounter[p->eType]++; + if( g.disableTry ) return SQLITE_BUSY; + return g.m.xMutexTry(p->pReal); +} + +/* Leave a mutex +*/ +static void counterMutexLeave(sqlite3_mutex *p){ + assert( g.isInit ); + g.m.xMutexLeave(p->pReal); +} + +/* +** sqlite3_shutdown +*/ +static int test_shutdown( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int rc; + + if( objc!=1 ){ + Tcl_WrongNumArgs(interp, 1, objv, ""); + return TCL_ERROR; + } + + rc = sqlite3_shutdown(); + Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE); + return TCL_OK; +} + +/* +** sqlite3_initialize +*/ +static int test_initialize( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int rc; + + if( objc!=1 ){ + Tcl_WrongNumArgs(interp, 1, objv, ""); + return TCL_ERROR; + } + + rc = sqlite3_initialize(); + Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE); + return TCL_OK; +} + +/* +** install_mutex_counters BOOLEAN +*/ +static int test_install_mutex_counters( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int rc = SQLITE_OK; + int isInstall; + + sqlite3_mutex_methods counter_methods = { + counterMutexInit, + counterMutexEnd, + counterMutexAlloc, + counterMutexFree, + counterMutexEnter, + counterMutexTry, + counterMutexLeave, + counterMutexHeld, + counterMutexNotheld + }; + + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN"); + return TCL_ERROR; + } + if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[1], &isInstall) ){ + return TCL_ERROR; + } + + assert(isInstall==0 || isInstall==1); + assert(g.isInstalled==0 || g.isInstalled==1); + if( isInstall==g.isInstalled ){ + Tcl_AppendResult(interp, "mutex counters are ", 0); + Tcl_AppendResult(interp, isInstall?"already installed":"not installed", 0); + return TCL_ERROR; + } + + if( isInstall ){ + assert( g.m.xMutexAlloc==0 ); + rc = sqlite3_config(SQLITE_CONFIG_GETMUTEX, &g.m); + if( rc==SQLITE_OK ){ + sqlite3_config(SQLITE_CONFIG_MUTEX, &counter_methods); + } + g.disableTry = 0; + }else{ + assert( g.m.xMutexAlloc ); + rc = sqlite3_config(SQLITE_CONFIG_MUTEX, &g.m); + memset(&g.m, 0, sizeof(sqlite3_mutex_methods)); + } + + if( rc==SQLITE_OK ){ + g.isInstalled = isInstall; + } + + Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE); + return TCL_OK; +} + +/* +** read_mutex_counters +*/ +static int test_read_mutex_counters( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + Tcl_Obj *pRet; + int ii; + char *aName[8] = { + "fast", "recursive", "static_master", "static_mem", + "static_mem2", "static_prng", "static_lru", "static_lru2" + }; + + if( objc!=1 ){ + Tcl_WrongNumArgs(interp, 1, objv, ""); + return TCL_ERROR; + } + + pRet = Tcl_NewObj(); + Tcl_IncrRefCount(pRet); + for(ii=0; ii<8; ii++){ + Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(aName[ii], -1)); + Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(g.aCounter[ii])); + } + Tcl_SetObjResult(interp, pRet); + Tcl_DecrRefCount(pRet); + + return TCL_OK; +} + +/* +** clear_mutex_counters +*/ +static int test_clear_mutex_counters( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int ii; + + if( objc!=1 ){ + Tcl_WrongNumArgs(interp, 1, objv, ""); + return TCL_ERROR; + } + + for(ii=0; ii<8; ii++){ + g.aCounter[ii] = 0; + } + return TCL_OK; +} + +/* +** Create and free a mutex. Return the mutex pointer. The pointer +** will be invalid since the mutex has already been freed. The +** return pointer just checks to see if the mutex really was allocated. +*/ +static int test_alloc_mutex( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ +#if SQLITE_THREADSAFE + sqlite3_mutex *p = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); + char zBuf[100]; + sqlite3_mutex_free(p); + sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", p); + Tcl_AppendResult(interp, zBuf, (char*)0); +#endif + return TCL_OK; +} + +/* +** sqlite3_config OPTION +** +** OPTION can be either one of the keywords: +** +** SQLITE_CONFIG_SINGLETHREAD +** SQLITE_CONFIG_MULTITHREAD +** SQLITE_CONFIG_SERIALIZED +** +** Or OPTION can be an raw integer. +*/ +static int test_config( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + struct ConfigOption { + const char *zName; + int iValue; + } aOpt[] = { + {"singlethread", SQLITE_CONFIG_SINGLETHREAD}, + {"multithread", SQLITE_CONFIG_MULTITHREAD}, + {"serialized", SQLITE_CONFIG_SERIALIZED}, + {0, 0} + }; + int s = sizeof(struct ConfigOption); + int i; + int rc; + + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, ""); + return TCL_ERROR; + } + + if( Tcl_GetIndexFromObjStruct(interp, objv[1], aOpt, s, "flag", 0, &i) ){ + if( Tcl_GetIntFromObj(interp, objv[1], &i) ){ + return TCL_ERROR; + } + }else{ + i = aOpt[i].iValue; + } + + rc = sqlite3_config(i); + Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE); + return TCL_OK; +} + +int Sqlitetest_mutex_Init(Tcl_Interp *interp){ + static struct { + char *zName; + Tcl_ObjCmdProc *xProc; + } aCmd[] = { + { "sqlite3_shutdown", (Tcl_ObjCmdProc*)test_shutdown }, + { "sqlite3_initialize", (Tcl_ObjCmdProc*)test_initialize }, + { "sqlite3_config", (Tcl_ObjCmdProc*)test_config }, + + { "alloc_dealloc_mutex", (Tcl_ObjCmdProc*)test_alloc_mutex }, + { "install_mutex_counters", (Tcl_ObjCmdProc*)test_install_mutex_counters }, + { "read_mutex_counters", (Tcl_ObjCmdProc*)test_read_mutex_counters }, + { "clear_mutex_counters", (Tcl_ObjCmdProc*)test_clear_mutex_counters }, + }; + int i; + for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ + Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); + } + memset(&g, 0, sizeof(g)); + + Tcl_LinkVar(interp, "disable_mutex_init", + (char*)&g.disableInit, TCL_LINK_INT); + Tcl_LinkVar(interp, "disable_mutex_try", + (char*)&g.disableTry, TCL_LINK_INT); + return SQLITE_OK; +} diff --git a/third_party/sqlite/src/test_onefile.c b/third_party/sqlite/src/test_onefile.c new file mode 100755 index 0000000..c8cc43c --- /dev/null +++ b/third_party/sqlite/src/test_onefile.c @@ -0,0 +1,822 @@ +/* +** 2007 September 14 +** +** 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. +** +************************************************************************* +** +** $Id: test_onefile.c,v 1.9 2008/06/26 10:54:12 danielk1977 Exp $ +** +** OVERVIEW: +** +** This file contains some example code demonstrating how the SQLite +** vfs feature can be used to have SQLite operate directly on an +** embedded media, without using an intermediate file system. +** +** Because this is only a demo designed to run on a workstation, the +** underlying media is simulated using a regular file-system file. The +** size of the file is fixed when it is first created (default size 10 MB). +** From SQLite's point of view, this space is used to store a single +** database file and the journal file. +** +** Any statement journal created is stored in volatile memory obtained +** from sqlite3_malloc(). Any attempt to create a temporary database file +** will fail (SQLITE_IOERR). To prevent SQLite from attempting this, +** it should be configured to store all temporary database files in +** main memory (see pragma "temp_store" or the SQLITE_TEMP_STORE compile +** time option). +** +** ASSUMPTIONS: +** +** After it has been created, the blob file is accessed using the +** following three functions only: +** +** mediaRead(); - Read a 512 byte block from the file. +** mediaWrite(); - Write a 512 byte block to the file. +** mediaSync(); - Tell the media hardware to sync. +** +** It is assumed that these can be easily implemented by any "real" +** media vfs driver adapting this code. +** +** FILE FORMAT: +** +** The basic principle is that the "database file" is stored at the +** beginning of the 10 MB blob and grows in a forward direction. The +** "journal file" is stored at the end of the 10MB blob and grows +** in the reverse direction. If, during a transaction, insufficient +** space is available to expand either the journal or database file, +** an SQLITE_FULL error is returned. The database file is never allowed +** to consume more than 90% of the blob space. If SQLite tries to +** create a file larger than this, SQLITE_FULL is returned. +** +** No allowance is made for "wear-leveling", as is required by. +** embedded devices in the absence of equivalent hardware features. +** +** The first 512 block byte of the file is reserved for storing the +** size of the "database file". It is updated as part of the sync() +** operation. On startup, it can only be trusted if no journal file +** exists. If a journal-file does exist, then it stores the real size +** of the database region. The second and subsequent blocks store the +** actual database content. +** +** The size of the "journal file" is not stored persistently in the +** file. When the system is running, the size of the journal file is +** stored in volatile memory. When recovering from a crash, this vfs +** reports a very large size for the journal file. The normal journal +** header and checksum mechanisms serve to prevent SQLite from +** processing any data that lies past the logical end of the journal. +** +** When SQLite calls OsDelete() to delete the journal file, the final +** 512 bytes of the blob (the area containing the first journal header) +** are zeroed. +** +** LOCKING: +** +** File locking is a no-op. Only one connection may be open at any one +** time using this demo vfs. +*/ + +#include "sqlite3.h" +#include <assert.h> +#include <string.h> + +/* +** Maximum pathname length supported by the fs backend. +*/ +#define BLOCKSIZE 512 +#define BLOBSIZE 10485760 + +/* +** Name used to identify this VFS. +*/ +#define FS_VFS_NAME "fs" + +typedef struct fs_real_file fs_real_file; +struct fs_real_file { + sqlite3_file *pFile; + const char *zName; + int nDatabase; /* Current size of database region */ + int nJournal; /* Current size of journal region */ + int nBlob; /* Total size of allocated blob */ + int nRef; /* Number of pointers to this structure */ + fs_real_file *pNext; + fs_real_file **ppThis; +}; + +typedef struct fs_file fs_file; +struct fs_file { + sqlite3_file base; + int eType; + fs_real_file *pReal; +}; + +typedef struct tmp_file tmp_file; +struct tmp_file { + sqlite3_file base; + int nSize; + int nAlloc; + char *zAlloc; +}; + +/* Values for fs_file.eType. */ +#define DATABASE_FILE 1 +#define JOURNAL_FILE 2 + +/* +** Method declarations for fs_file. +*/ +static int fsClose(sqlite3_file*); +static int fsRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); +static int fsWrite(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); +static int fsTruncate(sqlite3_file*, sqlite3_int64 size); +static int fsSync(sqlite3_file*, int flags); +static int fsFileSize(sqlite3_file*, sqlite3_int64 *pSize); +static int fsLock(sqlite3_file*, int); +static int fsUnlock(sqlite3_file*, int); +static int fsCheckReservedLock(sqlite3_file*, int *pResOut); +static int fsFileControl(sqlite3_file*, int op, void *pArg); +static int fsSectorSize(sqlite3_file*); +static int fsDeviceCharacteristics(sqlite3_file*); + +/* +** Method declarations for tmp_file. +*/ +static int tmpClose(sqlite3_file*); +static int tmpRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); +static int tmpWrite(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); +static int tmpTruncate(sqlite3_file*, sqlite3_int64 size); +static int tmpSync(sqlite3_file*, int flags); +static int tmpFileSize(sqlite3_file*, sqlite3_int64 *pSize); +static int tmpLock(sqlite3_file*, int); +static int tmpUnlock(sqlite3_file*, int); +static int tmpCheckReservedLock(sqlite3_file*, int *pResOut); +static int tmpFileControl(sqlite3_file*, int op, void *pArg); +static int tmpSectorSize(sqlite3_file*); +static int tmpDeviceCharacteristics(sqlite3_file*); + +/* +** Method declarations for fs_vfs. +*/ +static int fsOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); +static int fsDelete(sqlite3_vfs*, const char *zName, int syncDir); +static int fsAccess(sqlite3_vfs*, const char *zName, int flags, int *); +static int fsFullPathname(sqlite3_vfs*, const char *zName, int nOut,char *zOut); +static void *fsDlOpen(sqlite3_vfs*, const char *zFilename); +static void fsDlError(sqlite3_vfs*, int nByte, char *zErrMsg); +static void *fsDlSym(sqlite3_vfs*,void*, const char *zSymbol); +static void fsDlClose(sqlite3_vfs*, void*); +static int fsRandomness(sqlite3_vfs*, int nByte, char *zOut); +static int fsSleep(sqlite3_vfs*, int microseconds); +static int fsCurrentTime(sqlite3_vfs*, double*); + + +typedef struct fs_vfs_t fs_vfs_t; +struct fs_vfs_t { + sqlite3_vfs base; + fs_real_file *pFileList; + sqlite3_vfs *pParent; +}; + +static fs_vfs_t fs_vfs = { + { + 1, /* iVersion */ + 0, /* szOsFile */ + 0, /* mxPathname */ + 0, /* pNext */ + FS_VFS_NAME, /* zName */ + 0, /* pAppData */ + fsOpen, /* xOpen */ + fsDelete, /* xDelete */ + fsAccess, /* xAccess */ + fsFullPathname, /* xFullPathname */ + fsDlOpen, /* xDlOpen */ + fsDlError, /* xDlError */ + fsDlSym, /* xDlSym */ + fsDlClose, /* xDlClose */ + fsRandomness, /* xRandomness */ + fsSleep, /* xSleep */ + fsCurrentTime /* xCurrentTime */ + }, + 0, /* pFileList */ + 0 /* pParent */ +}; + +static sqlite3_io_methods fs_io_methods = { + 1, /* iVersion */ + fsClose, /* xClose */ + fsRead, /* xRead */ + fsWrite, /* xWrite */ + fsTruncate, /* xTruncate */ + fsSync, /* xSync */ + fsFileSize, /* xFileSize */ + fsLock, /* xLock */ + fsUnlock, /* xUnlock */ + fsCheckReservedLock, /* xCheckReservedLock */ + fsFileControl, /* xFileControl */ + fsSectorSize, /* xSectorSize */ + fsDeviceCharacteristics /* xDeviceCharacteristics */ +}; + + +static sqlite3_io_methods tmp_io_methods = { + 1, /* iVersion */ + tmpClose, /* xClose */ + tmpRead, /* xRead */ + tmpWrite, /* xWrite */ + tmpTruncate, /* xTruncate */ + tmpSync, /* xSync */ + tmpFileSize, /* xFileSize */ + tmpLock, /* xLock */ + tmpUnlock, /* xUnlock */ + tmpCheckReservedLock, /* xCheckReservedLock */ + tmpFileControl, /* xFileControl */ + tmpSectorSize, /* xSectorSize */ + tmpDeviceCharacteristics /* xDeviceCharacteristics */ +}; + +/* Useful macros used in several places */ +#define MIN(x,y) ((x)<(y)?(x):(y)) +#define MAX(x,y) ((x)>(y)?(x):(y)) + + +/* +** Close a tmp-file. +*/ +static int tmpClose(sqlite3_file *pFile){ + tmp_file *pTmp = (tmp_file *)pFile; + sqlite3_free(pTmp->zAlloc); + return SQLITE_OK; +} + +/* +** Read data from a tmp-file. +*/ +static int tmpRead( + sqlite3_file *pFile, + void *zBuf, + int iAmt, + sqlite_int64 iOfst +){ + tmp_file *pTmp = (tmp_file *)pFile; + if( (iAmt+iOfst)>pTmp->nSize ){ + return SQLITE_IOERR_SHORT_READ; + } + memcpy(zBuf, &pTmp->zAlloc[iOfst], iAmt); + return SQLITE_OK; +} + +/* +** Write data to a tmp-file. +*/ +static int tmpWrite( + sqlite3_file *pFile, + const void *zBuf, + int iAmt, + sqlite_int64 iOfst +){ + tmp_file *pTmp = (tmp_file *)pFile; + if( (iAmt+iOfst)>pTmp->nAlloc ){ + int nNew = 2*(iAmt+iOfst+pTmp->nAlloc); + char *zNew = sqlite3_realloc(pTmp->zAlloc, nNew); + if( !zNew ){ + return SQLITE_NOMEM; + } + pTmp->zAlloc = zNew; + pTmp->nAlloc = nNew; + } + memcpy(&pTmp->zAlloc[iOfst], zBuf, iAmt); + pTmp->nSize = MAX(pTmp->nSize, iOfst+iAmt); + return SQLITE_OK; +} + +/* +** Truncate a tmp-file. +*/ +static int tmpTruncate(sqlite3_file *pFile, sqlite_int64 size){ + tmp_file *pTmp = (tmp_file *)pFile; + pTmp->nSize = MIN(pTmp->nSize, size); + return SQLITE_OK; +} + +/* +** Sync a tmp-file. +*/ +static int tmpSync(sqlite3_file *pFile, int flags){ + return SQLITE_OK; +} + +/* +** Return the current file-size of a tmp-file. +*/ +static int tmpFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ + tmp_file *pTmp = (tmp_file *)pFile; + *pSize = pTmp->nSize; + return SQLITE_OK; +} + +/* +** Lock a tmp-file. +*/ +static int tmpLock(sqlite3_file *pFile, int eLock){ + return SQLITE_OK; +} + +/* +** Unlock a tmp-file. +*/ +static int tmpUnlock(sqlite3_file *pFile, int eLock){ + return SQLITE_OK; +} + +/* +** Check if another file-handle holds a RESERVED lock on a tmp-file. +*/ +static int tmpCheckReservedLock(sqlite3_file *pFile, int *pResOut){ + *pResOut = 0; + return SQLITE_OK; +} + +/* +** File control method. For custom operations on a tmp-file. +*/ +static int tmpFileControl(sqlite3_file *pFile, int op, void *pArg){ + return SQLITE_OK; +} + +/* +** Return the sector-size in bytes for a tmp-file. +*/ +static int tmpSectorSize(sqlite3_file *pFile){ + return 0; +} + +/* +** Return the device characteristic flags supported by a tmp-file. +*/ +static int tmpDeviceCharacteristics(sqlite3_file *pFile){ + return 0; +} + +/* +** Close an fs-file. +*/ +static int fsClose(sqlite3_file *pFile){ + int rc = SQLITE_OK; + fs_file *p = (fs_file *)pFile; + fs_real_file *pReal = p->pReal; + + /* Decrement the real_file ref-count. */ + pReal->nRef--; + assert(pReal->nRef>=0); + + /* When the ref-count reaches 0, destroy the structure */ + if( pReal->nRef==0 ){ + *pReal->ppThis = pReal->pNext; + if( pReal->pNext ){ + pReal->pNext->ppThis = pReal->ppThis; + } + rc = pReal->pFile->pMethods->xClose(pReal->pFile); + sqlite3_free(pReal); + } + + return rc; +} + +/* +** Read data from an fs-file. +*/ +static int fsRead( + sqlite3_file *pFile, + void *zBuf, + int iAmt, + sqlite_int64 iOfst +){ + int rc = SQLITE_OK; + fs_file *p = (fs_file *)pFile; + fs_real_file *pReal = p->pReal; + sqlite3_file *pF = pReal->pFile; + + if( (p->eType==DATABASE_FILE && (iAmt+iOfst)>pReal->nDatabase) + || (p->eType==JOURNAL_FILE && (iAmt+iOfst)>pReal->nJournal) + ){ + rc = SQLITE_IOERR_SHORT_READ; + }else if( p->eType==DATABASE_FILE ){ + rc = pF->pMethods->xRead(pF, zBuf, iAmt, iOfst+BLOCKSIZE); + }else{ + /* Journal file. */ + int iRem = iAmt; + int iBuf = 0; + int ii = iOfst; + while( iRem>0 && rc==SQLITE_OK ){ + int iRealOff = pReal->nBlob - BLOCKSIZE*((ii/BLOCKSIZE)+1) + ii%BLOCKSIZE; + int iRealAmt = MIN(iRem, BLOCKSIZE - (iRealOff%BLOCKSIZE)); + + rc = pF->pMethods->xRead(pF, &((char *)zBuf)[iBuf], iRealAmt, iRealOff); + ii += iRealAmt; + iBuf += iRealAmt; + iRem -= iRealAmt; + } + } + + return rc; +} + +/* +** Write data to an fs-file. +*/ +static int fsWrite( + sqlite3_file *pFile, + const void *zBuf, + int iAmt, + sqlite_int64 iOfst +){ + int rc = SQLITE_OK; + fs_file *p = (fs_file *)pFile; + fs_real_file *pReal = p->pReal; + sqlite3_file *pF = pReal->pFile; + + if( p->eType==DATABASE_FILE ){ + if( (iAmt+iOfst+BLOCKSIZE)>(pReal->nBlob-pReal->nJournal) ){ + rc = SQLITE_FULL; + }else{ + rc = pF->pMethods->xWrite(pF, zBuf, iAmt, iOfst+BLOCKSIZE); + if( rc==SQLITE_OK ){ + pReal->nDatabase = MAX(pReal->nDatabase, iAmt+iOfst); + } + } + }else{ + /* Journal file. */ + int iRem = iAmt; + int iBuf = 0; + int ii = iOfst; + while( iRem>0 && rc==SQLITE_OK ){ + int iRealOff = pReal->nBlob - BLOCKSIZE*((ii/BLOCKSIZE)+1) + ii%BLOCKSIZE; + int iRealAmt = MIN(iRem, BLOCKSIZE - (iRealOff%BLOCKSIZE)); + + if( iRealOff<(pReal->nDatabase+BLOCKSIZE) ){ + rc = SQLITE_FULL; + }else{ + rc = pF->pMethods->xWrite(pF, &((char *)zBuf)[iBuf], iRealAmt,iRealOff); + ii += iRealAmt; + iBuf += iRealAmt; + iRem -= iRealAmt; + } + } + if( rc==SQLITE_OK ){ + pReal->nJournal = MAX(pReal->nJournal, iAmt+iOfst); + } + } + + return rc; +} + +/* +** Truncate an fs-file. +*/ +static int fsTruncate(sqlite3_file *pFile, sqlite_int64 size){ + fs_file *p = (fs_file *)pFile; + fs_real_file *pReal = p->pReal; + if( p->eType==DATABASE_FILE ){ + pReal->nDatabase = MIN(pReal->nDatabase, size); + }else{ + pReal->nJournal = MIN(pReal->nJournal, size); + } + return SQLITE_OK; +} + +/* +** Sync an fs-file. +*/ +static int fsSync(sqlite3_file *pFile, int flags){ + fs_file *p = (fs_file *)pFile; + fs_real_file *pReal = p->pReal; + sqlite3_file *pRealFile = pReal->pFile; + int rc = SQLITE_OK; + + if( p->eType==DATABASE_FILE ){ + unsigned char zSize[4]; + zSize[0] = (pReal->nDatabase&0xFF000000)>>24; + zSize[1] = (pReal->nDatabase&0x00FF0000)>>16; + zSize[2] = (pReal->nDatabase&0x0000FF00)>>8; + zSize[3] = (pReal->nDatabase&0x000000FF); + rc = pRealFile->pMethods->xWrite(pRealFile, zSize, 4, 0); + } + if( rc==SQLITE_OK ){ + rc = pRealFile->pMethods->xSync(pRealFile, flags&(~SQLITE_SYNC_DATAONLY)); + } + + return rc; +} + +/* +** Return the current file-size of an fs-file. +*/ +static int fsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ + fs_file *p = (fs_file *)pFile; + fs_real_file *pReal = p->pReal; + if( p->eType==DATABASE_FILE ){ + *pSize = pReal->nDatabase; + }else{ + *pSize = pReal->nJournal; + } + return SQLITE_OK; +} + +/* +** Lock an fs-file. +*/ +static int fsLock(sqlite3_file *pFile, int eLock){ + return SQLITE_OK; +} + +/* +** Unlock an fs-file. +*/ +static int fsUnlock(sqlite3_file *pFile, int eLock){ + return SQLITE_OK; +} + +/* +** Check if another file-handle holds a RESERVED lock on an fs-file. +*/ +static int fsCheckReservedLock(sqlite3_file *pFile, int *pResOut){ + *pResOut = 0; + return SQLITE_OK; +} + +/* +** File control method. For custom operations on an fs-file. +*/ +static int fsFileControl(sqlite3_file *pFile, int op, void *pArg){ + return SQLITE_OK; +} + +/* +** Return the sector-size in bytes for an fs-file. +*/ +static int fsSectorSize(sqlite3_file *pFile){ + return BLOCKSIZE; +} + +/* +** Return the device characteristic flags supported by an fs-file. +*/ +static int fsDeviceCharacteristics(sqlite3_file *pFile){ + return 0; +} + +/* +** Open an fs file handle. +*/ +static int fsOpen( + sqlite3_vfs *pVfs, + const char *zName, + sqlite3_file *pFile, + int flags, + int *pOutFlags +){ + fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs; + fs_file *p = (fs_file *)pFile; + fs_real_file *pReal = 0; + int eType; + int nName; + int rc = SQLITE_OK; + + if( 0==(flags&(SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_MAIN_JOURNAL)) ){ + tmp_file *p = (tmp_file *)pFile; + memset(p, 0, sizeof(*p)); + p->base.pMethods = &tmp_io_methods; + return SQLITE_OK; + } + + eType = ((flags&(SQLITE_OPEN_MAIN_DB))?DATABASE_FILE:JOURNAL_FILE); + p->base.pMethods = &fs_io_methods; + p->eType = eType; + + assert(strlen("-journal")==8); + nName = strlen(zName)-((eType==JOURNAL_FILE)?8:0); + pReal=pFsVfs->pFileList; + for(; pReal && strncmp(pReal->zName, zName, nName); pReal=pReal->pNext); + + if( !pReal ){ + sqlite3_int64 size; + sqlite3_file *pRealFile; + sqlite3_vfs *pParent = pFsVfs->pParent; + assert(eType==DATABASE_FILE); + + pReal = (fs_real_file *)sqlite3_malloc(sizeof(*pReal)+pParent->szOsFile); + if( !pReal ){ + rc = SQLITE_NOMEM; + goto open_out; + } + memset(pReal, 0, sizeof(*pReal)+pParent->szOsFile); + pReal->zName = zName; + pReal->pFile = (sqlite3_file *)(&pReal[1]); + + rc = pParent->xOpen(pParent, zName, pReal->pFile, flags, pOutFlags); + if( rc!=SQLITE_OK ){ + goto open_out; + } + pRealFile = pReal->pFile; + + rc = pRealFile->pMethods->xFileSize(pRealFile, &size); + if( rc!=SQLITE_OK ){ + goto open_out; + } + if( size==0 ){ + rc = pRealFile->pMethods->xWrite(pRealFile, "\0", 1, BLOBSIZE-1); + pReal->nBlob = BLOBSIZE; + }else{ + unsigned char zS[4]; + pReal->nBlob = size; + rc = pRealFile->pMethods->xRead(pRealFile, zS, 4, 0); + pReal->nDatabase = (zS[0]<<24)+(zS[1]<<16)+(zS[2]<<8)+zS[3]; + if( rc==SQLITE_OK ){ + rc = pRealFile->pMethods->xRead(pRealFile, zS, 4, pReal->nBlob-4); + if( zS[0] || zS[1] || zS[2] || zS[3] ){ + pReal->nJournal = pReal->nBlob; + } + } + } + + if( rc==SQLITE_OK ){ + pReal->pNext = pFsVfs->pFileList; + if( pReal->pNext ){ + pReal->pNext->ppThis = &pReal->pNext; + } + pReal->ppThis = &pFsVfs->pFileList; + pFsVfs->pFileList = pReal; + } + } + +open_out: + if( pReal ){ + if( rc==SQLITE_OK ){ + p->pReal = pReal; + pReal->nRef++; + }else{ + if( pReal->pFile->pMethods ){ + pReal->pFile->pMethods->xClose(pReal->pFile); + } + sqlite3_free(pReal); + } + } + return rc; +} + +/* +** Delete the file located at zPath. If the dirSync argument is true, +** ensure the file-system modifications are synced to disk before +** returning. +*/ +static int fsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ + int rc = SQLITE_OK; + fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs; + fs_real_file *pReal; + sqlite3_file *pF; + int nName = strlen(zPath) - 8; + + assert(strlen("-journal")==8); + assert(strcmp("-journal", &zPath[nName])==0); + + pReal = pFsVfs->pFileList; + for(; pReal && strncmp(pReal->zName, zPath, nName); pReal=pReal->pNext); + if( pReal ){ + pF = pReal->pFile; + rc = pF->pMethods->xWrite(pF, "\0\0\0\0", 4, pReal->nBlob-BLOCKSIZE); + if( rc==SQLITE_OK ){ + pReal->nJournal = 0; + } + } + return rc; +} + +/* +** Test for access permissions. Return true if the requested permission +** is available, or false otherwise. +*/ +static int fsAccess( + sqlite3_vfs *pVfs, + const char *zPath, + int flags, + int *pResOut +){ + fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs; + fs_real_file *pReal; + int isJournal = 0; + int nName = strlen(zPath); + + if( flags!=SQLITE_ACCESS_EXISTS ){ + sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent; + return pParent->xAccess(pParent, zPath, flags, pResOut); + } + + assert(strlen("-journal")==8); + if( nName>8 && strcmp("-journal", &zPath[nName-8])==0 ){ + nName -= 8; + isJournal = 1; + } + + pReal = pFsVfs->pFileList; + for(; pReal && strncmp(pReal->zName, zPath, nName); pReal=pReal->pNext); + + *pResOut = (pReal && (!isJournal || pReal->nJournal>0)); + return SQLITE_OK; +} + +/* +** Populate buffer zOut with the full canonical pathname corresponding +** to the pathname in zPath. zOut is guaranteed to point to a buffer +** of at least (FS_MAX_PATHNAME+1) bytes. +*/ +static int fsFullPathname( + sqlite3_vfs *pVfs, /* Pointer to vfs object */ + const char *zPath, /* Possibly relative input path */ + int nOut, /* Size of output buffer in bytes */ + char *zOut /* Output buffer */ +){ + sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent; + return pParent->xFullPathname(pParent, zPath, nOut, zOut); +} + +/* +** Open the dynamic library located at zPath and return a handle. +*/ +static void *fsDlOpen(sqlite3_vfs *pVfs, const char *zPath){ + sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent; + return pParent->xDlOpen(pParent, zPath); +} + +/* +** Populate the buffer zErrMsg (size nByte bytes) with a human readable +** utf-8 string describing the most recent error encountered associated +** with dynamic libraries. +*/ +static void fsDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ + sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent; + pParent->xDlError(pParent, nByte, zErrMsg); +} + +/* +** Return a pointer to the symbol zSymbol in the dynamic library pHandle. +*/ +static void *fsDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){ + sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent; + return pParent->xDlSym(pParent, pHandle, zSymbol); +} + +/* +** Close the dynamic library handle pHandle. +*/ +static void fsDlClose(sqlite3_vfs *pVfs, void *pHandle){ + sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent; + pParent->xDlClose(pParent, pHandle); +} + +/* +** Populate the buffer pointed to by zBufOut with nByte bytes of +** random data. +*/ +static int fsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ + sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent; + return pParent->xRandomness(pParent, nByte, zBufOut); +} + +/* +** Sleep for nMicro microseconds. Return the number of microseconds +** actually slept. +*/ +static int fsSleep(sqlite3_vfs *pVfs, int nMicro){ + sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent; + return pParent->xSleep(pParent, nMicro); +} + +/* +** Return the current time as a Julian Day number in *pTimeOut. +*/ +static int fsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ + sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent; + return pParent->xCurrentTime(pParent, pTimeOut); +} + +/* +** This procedure registers the fs vfs with SQLite. If the argument is +** true, the fs vfs becomes the new default vfs. It is the only publicly +** available function in this file. +*/ +int fs_register(){ + if( fs_vfs.pParent ) return SQLITE_OK; + fs_vfs.pParent = sqlite3_vfs_find(0); + fs_vfs.base.mxPathname = fs_vfs.pParent->mxPathname; + fs_vfs.base.szOsFile = MAX(sizeof(tmp_file), sizeof(fs_file)); + return sqlite3_vfs_register(&fs_vfs.base, 0); +} + +#ifdef SQLITE_TEST + int SqlitetestOnefile_Init() {return fs_register();} +#endif diff --git a/third_party/sqlite/src/test_osinst.c b/third_party/sqlite/src/test_osinst.c new file mode 100755 index 0000000..a05ef7a --- /dev/null +++ b/third_party/sqlite/src/test_osinst.c @@ -0,0 +1,1069 @@ +/* +** 2008 April 10 +** +** 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 the implementation of an SQLite vfs wrapper that +** adds instrumentation to all vfs and file methods. C and Tcl interfaces +** are provided to control the instrumentation. +** +** $Id: test_osinst.c,v 1.18 2008/07/25 13:32:45 drh Exp $ +*/ + +#ifdef SQLITE_ENABLE_INSTVFS +/* +** C interface: +** +** sqlite3_instvfs_create() +** sqlite3_instvfs_destroy() +** sqlite3_instvfs_configure() +** +** sqlite3_instvfs_reset() +** sqlite3_instvfs_get() +** +** sqlite3_instvfs_binarylog +** sqlite3_instvfs_binarylog_marker +** +** Tcl interface (omitted if SQLITE_TEST is not set): +** +** sqlite3_instvfs create NAME ?PARENT? +** +** Create and register new vfs called $NAME, which is a wrapper around +** the existing vfs $PARENT. If the PARENT argument is omitted, the +** new vfs is a wrapper around the current default vfs. +** +** sqlite3_instvfs destroy NAME +** +** Deregister and destroy the vfs named $NAME, which must have been +** created by an earlier invocation of [sqlite3_instvfs create]. +** +** sqlite3_instvfs configure NAME SCRIPT +** +** Configure the callback script for the vfs $NAME, which much have +** been created by an earlier invocation of [sqlite3_instvfs create]. +** After a callback script has been configured, it is invoked each +** time a vfs or file method is called by SQLite. Before invoking +** the callback script, five arguments are appended to it: +** +** * The name of the invoked method - i.e. "xRead". +** +** * The time consumed by the method call as measured by +** sqlite3Hwtime() (an integer value) +** +** * A string value with a different meaning for different calls. +** For file methods, the name of the file being operated on. For +** other methods it is the filename argument, if any. +** +** * A 32-bit integer value with a call-specific meaning. +** +** * A 64-bit integer value. For xRead() and xWrite() calls this +** is the file offset being written to or read from. Unused by +** all other calls. +** +** sqlite3_instvfs reset NAME +** +** Zero the internal event counters associated with vfs $NAME, +** which must have been created by an earlier invocation of +** [sqlite3_instvfs create]. +** +** sqlite3_instvfs report NAME +** +** Return the values of the internal event counters associated +** with vfs $NAME. The report format is a list with one element +** for each method call (xWrite, xRead etc.). Each element is +** itself a list with three elements: +** +** * The name of the method call - i.e. "xWrite", +** * The total number of calls to the method (an integer). +** * The aggregate time consumed by all calls to the method as +** measured by sqlite3Hwtime() (an integer). +*/ + +#include "sqlite3.h" +#include <string.h> +#include <assert.h> + +/* +** Maximum pathname length supported by the inst backend. +*/ +#define INST_MAX_PATHNAME 512 + + +/* File methods */ +/* Vfs methods */ +#define OS_ACCESS 1 +#define OS_CHECKRESERVEDLOCK 2 +#define OS_CLOSE 3 +#define OS_CURRENTTIME 4 +#define OS_DELETE 5 +#define OS_DEVCHAR 6 +#define OS_FILECONTROL 7 +#define OS_FILESIZE 8 +#define OS_FULLPATHNAME 9 +#define OS_LOCK 11 +#define OS_OPEN 12 +#define OS_RANDOMNESS 13 +#define OS_READ 14 +#define OS_SECTORSIZE 15 +#define OS_SLEEP 16 +#define OS_SYNC 17 +#define OS_TRUNCATE 18 +#define OS_UNLOCK 19 +#define OS_WRITE 20 + +#define OS_NUMEVENTS 21 + +#define BINARYLOG_STRING 30 +#define BINARYLOG_MARKER 31 + +#define BINARYLOG_PREPARE_V2 64 +#define BINARYLOG_STEP 65 +#define BINARYLOG_FINALIZE 66 + +struct InstVfs { + sqlite3_vfs base; + sqlite3_vfs *pVfs; + + void *pClient; + void (*xDel)(void *); + void (*xCall)(void *, int, int, sqlite3_int64, int, const char *, int, int, sqlite3_int64); + + /* Counters */ + sqlite3_int64 aTime[OS_NUMEVENTS]; + int aCount[OS_NUMEVENTS]; + + int iNextFileId; +}; +typedef struct InstVfs InstVfs; + +#define REALVFS(p) (((InstVfs *)(p))->pVfs) + +typedef struct inst_file inst_file; +struct inst_file { + sqlite3_file base; + sqlite3_file *pReal; + InstVfs *pInstVfs; + const char *zName; + int iFileId; /* File id number */ + int flags; +}; + +/* +** Method declarations for inst_file. +*/ +static int instClose(sqlite3_file*); +static int instRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); +static int instWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst); +static int instTruncate(sqlite3_file*, sqlite3_int64 size); +static int instSync(sqlite3_file*, int flags); +static int instFileSize(sqlite3_file*, sqlite3_int64 *pSize); +static int instLock(sqlite3_file*, int); +static int instUnlock(sqlite3_file*, int); +static int instCheckReservedLock(sqlite3_file*, int *pResOut); +static int instFileControl(sqlite3_file*, int op, void *pArg); +static int instSectorSize(sqlite3_file*); +static int instDeviceCharacteristics(sqlite3_file*); + +/* +** Method declarations for inst_vfs. +*/ +static int instOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); +static int instDelete(sqlite3_vfs*, const char *zName, int syncDir); +static int instAccess(sqlite3_vfs*, const char *zName, int flags, int *); +static int instFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut); +static void *instDlOpen(sqlite3_vfs*, const char *zFilename); +static void instDlError(sqlite3_vfs*, int nByte, char *zErrMsg); +static void *instDlSym(sqlite3_vfs*,void*, const char *zSymbol); +static void instDlClose(sqlite3_vfs*, void*); +static int instRandomness(sqlite3_vfs*, int nByte, char *zOut); +static int instSleep(sqlite3_vfs*, int microseconds); +static int instCurrentTime(sqlite3_vfs*, double*); + +static void binarylog_blob(sqlite3_vfs *, const char *, int, int); + +static sqlite3_vfs inst_vfs = { + 1, /* iVersion */ + sizeof(inst_file), /* szOsFile */ + INST_MAX_PATHNAME, /* mxPathname */ + 0, /* pNext */ + 0, /* zName */ + 0, /* pAppData */ + instOpen, /* xOpen */ + instDelete, /* xDelete */ + instAccess, /* xAccess */ + instFullPathname, /* xFullPathname */ + instDlOpen, /* xDlOpen */ + instDlError, /* xDlError */ + instDlSym, /* xDlSym */ + instDlClose, /* xDlClose */ + instRandomness, /* xRandomness */ + instSleep, /* xSleep */ + instCurrentTime /* xCurrentTime */ +}; + +static sqlite3_io_methods inst_io_methods = { + 1, /* iVersion */ + instClose, /* xClose */ + instRead, /* xRead */ + instWrite, /* xWrite */ + instTruncate, /* xTruncate */ + instSync, /* xSync */ + instFileSize, /* xFileSize */ + instLock, /* xLock */ + instUnlock, /* xUnlock */ + instCheckReservedLock, /* xCheckReservedLock */ + instFileControl, /* xFileControl */ + instSectorSize, /* xSectorSize */ + instDeviceCharacteristics /* xDeviceCharacteristics */ +}; + +/* +** hwtime.h contains inline assembler code for implementing +** high-performance timing routines. +*/ +#include "hwtime.h" + +#define OS_TIME_IO(eEvent, A, B, Call) { \ + inst_file *p = (inst_file *)pFile; \ + InstVfs *pInstVfs = p->pInstVfs; \ + int rc; \ + sqlite_uint64 t = sqlite3Hwtime(); \ + rc = Call; \ + t = sqlite3Hwtime() - t; \ + pInstVfs->aTime[eEvent] += t; \ + pInstVfs->aCount[eEvent] += 1; \ + if( pInstVfs->xCall ){ \ + pInstVfs->xCall( \ + pInstVfs->pClient,eEvent,p->iFileId,t,rc,p->zName,p->flags,A,B \ + ); \ + } \ + return rc; \ +} + +#define OS_TIME_VFS(eEvent, Z, flags, A, B, Call) { \ + InstVfs *pInstVfs = (InstVfs *)pVfs; \ + int rc; \ + sqlite_uint64 t = sqlite3Hwtime(); \ + rc = Call; \ + t = sqlite3Hwtime() - t; \ + pInstVfs->aTime[eEvent] += t; \ + pInstVfs->aCount[eEvent] += 1; \ + if( pInstVfs->xCall ){ \ + pInstVfs->xCall(pInstVfs->pClient,eEvent,0, t, rc, Z, flags, A, B); \ + } \ + return rc; \ +} + +/* +** Close an inst-file. +*/ +static int instClose(sqlite3_file *pFile){ + OS_TIME_IO(OS_CLOSE, 0, 0, + (p->pReal->pMethods ? p->pReal->pMethods->xClose(p->pReal) : SQLITE_OK) + ); +} + +/* +** Read data from an inst-file. +*/ +static int instRead( + sqlite3_file *pFile, + void *zBuf, + int iAmt, + sqlite_int64 iOfst +){ + sqlite3_vfs *pVfs = (sqlite3_vfs *)(((inst_file *)pFile)->pInstVfs); + OS_TIME_IO(OS_READ, iAmt, (binarylog_blob(pVfs, zBuf, iAmt, 1), iOfst), + p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst) + ); +} + +/* +** Write data to an inst-file. +*/ +static int instWrite( + sqlite3_file *pFile, + const void *z, + int iAmt, + sqlite_int64 iOfst +){ + sqlite3_vfs *pVfs = (sqlite3_vfs *)(((inst_file *)pFile)->pInstVfs); + binarylog_blob(pVfs, z, iAmt, 1); + OS_TIME_IO(OS_WRITE, iAmt, iOfst, + p->pReal->pMethods->xWrite(p->pReal, z, iAmt, iOfst) + ); +} + +/* +** Truncate an inst-file. +*/ +static int instTruncate(sqlite3_file *pFile, sqlite_int64 size){ + OS_TIME_IO(OS_TRUNCATE, 0, (int)size, + p->pReal->pMethods->xTruncate(p->pReal, size) + ); +} + +/* +** Sync an inst-file. +*/ +static int instSync(sqlite3_file *pFile, int flags){ + OS_TIME_IO(OS_SYNC, flags, 0, p->pReal->pMethods->xSync(p->pReal, flags)); +} + +/* +** Return the current file-size of an inst-file. +*/ +static int instFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ + OS_TIME_IO(OS_FILESIZE, (int)(*pSize), 0, + p->pReal->pMethods->xFileSize(p->pReal, pSize) + ); +} + +/* +** Lock an inst-file. +*/ +static int instLock(sqlite3_file *pFile, int eLock){ + OS_TIME_IO(OS_LOCK, eLock, 0, p->pReal->pMethods->xLock(p->pReal, eLock)); +} + +/* +** Unlock an inst-file. +*/ +static int instUnlock(sqlite3_file *pFile, int eLock){ + OS_TIME_IO(OS_UNLOCK, eLock, 0, p->pReal->pMethods->xUnlock(p->pReal, eLock)); +} + +/* +** Check if another file-handle holds a RESERVED lock on an inst-file. +*/ +static int instCheckReservedLock(sqlite3_file *pFile, int *pResOut){ + OS_TIME_IO(OS_CHECKRESERVEDLOCK, 0, 0, + p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut) + ); +} + +/* +** File control method. For custom operations on an inst-file. +*/ +static int instFileControl(sqlite3_file *pFile, int op, void *pArg){ + OS_TIME_IO(OS_FILECONTROL, 0, 0, p->pReal->pMethods->xFileControl(p->pReal, op, pArg)); +} + +/* +** Return the sector-size in bytes for an inst-file. +*/ +static int instSectorSize(sqlite3_file *pFile){ + OS_TIME_IO(OS_SECTORSIZE, 0, 0, p->pReal->pMethods->xSectorSize(p->pReal)); +} + +/* +** Return the device characteristic flags supported by an inst-file. +*/ +static int instDeviceCharacteristics(sqlite3_file *pFile){ + OS_TIME_IO(OS_DEVCHAR, 0, 0, p->pReal->pMethods->xDeviceCharacteristics(p->pReal)); +} + +/* +** Open an inst file handle. +*/ +static int instOpen( + sqlite3_vfs *pVfs, + const char *zName, + sqlite3_file *pFile, + int flags, + int *pOutFlags +){ + inst_file *p = (inst_file *)pFile; + pFile->pMethods = &inst_io_methods; + p->pReal = (sqlite3_file *)&p[1]; + p->pInstVfs = (InstVfs *)pVfs; + p->zName = zName; + p->flags = flags; + p->iFileId = ++p->pInstVfs->iNextFileId; + + binarylog_blob(pVfs, zName, -1, 0); + OS_TIME_VFS(OS_OPEN, zName, flags, p->iFileId, 0, + REALVFS(pVfs)->xOpen(REALVFS(pVfs), zName, p->pReal, flags, pOutFlags) + ); +} + +/* +** Delete the file located at zPath. If the dirSync argument is true, +** ensure the file-system modifications are synced to disk before +** returning. +*/ +static int instDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ + binarylog_blob(pVfs, zPath, -1, 0); + OS_TIME_VFS(OS_DELETE, zPath, 0, dirSync, 0, + REALVFS(pVfs)->xDelete(REALVFS(pVfs), zPath, dirSync) + ); +} + +/* +** Test for access permissions. Return true if the requested permission +** is available, or false otherwise. +*/ +static int instAccess( + sqlite3_vfs *pVfs, + const char *zPath, + int flags, + int *pResOut +){ + binarylog_blob(pVfs, zPath, -1, 0); + OS_TIME_VFS(OS_ACCESS, zPath, 0, flags, *pResOut, + REALVFS(pVfs)->xAccess(REALVFS(pVfs), zPath, flags, pResOut) + ); +} + +/* +** Populate buffer zOut with the full canonical pathname corresponding +** to the pathname in zPath. zOut is guaranteed to point to a buffer +** of at least (INST_MAX_PATHNAME+1) bytes. +*/ +static int instFullPathname( + sqlite3_vfs *pVfs, + const char *zPath, + int nOut, + char *zOut +){ + OS_TIME_VFS( OS_FULLPATHNAME, zPath, 0, 0, 0, + REALVFS(pVfs)->xFullPathname(REALVFS(pVfs), zPath, nOut, zOut); + ); +} + +/* +** Open the dynamic library located at zPath and return a handle. +*/ +static void *instDlOpen(sqlite3_vfs *pVfs, const char *zPath){ + return REALVFS(pVfs)->xDlOpen(REALVFS(pVfs), zPath); +} + +/* +** Populate the buffer zErrMsg (size nByte bytes) with a human readable +** utf-8 string describing the most recent error encountered associated +** with dynamic libraries. +*/ +static void instDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ + REALVFS(pVfs)->xDlError(REALVFS(pVfs), nByte, zErrMsg); +} + +/* +** Return a pointer to the symbol zSymbol in the dynamic library pHandle. +*/ +static void *instDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){ + return REALVFS(pVfs)->xDlSym(REALVFS(pVfs), pHandle, zSymbol); +} + +/* +** Close the dynamic library handle pHandle. +*/ +static void instDlClose(sqlite3_vfs *pVfs, void *pHandle){ + REALVFS(pVfs)->xDlClose(REALVFS(pVfs), pHandle); +} + +/* +** Populate the buffer pointed to by zBufOut with nByte bytes of +** random data. +*/ +static int instRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ + OS_TIME_VFS( OS_RANDOMNESS, 0, 0, nByte, 0, + REALVFS(pVfs)->xRandomness(REALVFS(pVfs), nByte, zBufOut); + ); +} + +/* +** Sleep for nMicro microseconds. Return the number of microseconds +** actually slept. +*/ +static int instSleep(sqlite3_vfs *pVfs, int nMicro){ + OS_TIME_VFS( OS_SLEEP, 0, 0, nMicro, 0, + REALVFS(pVfs)->xSleep(REALVFS(pVfs), nMicro) + ); +} + +/* +** Return the current time as a Julian Day number in *pTimeOut. +*/ +static int instCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ + OS_TIME_VFS( OS_CURRENTTIME, 0, 0, 0, 0, + REALVFS(pVfs)->xCurrentTime(REALVFS(pVfs), pTimeOut) + ); +} + +sqlite3_vfs *sqlite3_instvfs_create(const char *zName, const char *zParent){ + int nByte; + InstVfs *p; + sqlite3_vfs *pParent; + + pParent = sqlite3_vfs_find(zParent); + if( !pParent ){ + return 0; + } + + nByte = strlen(zName) + 1 + sizeof(InstVfs); + p = (InstVfs *)sqlite3_malloc(nByte); + if( p ){ + char *zCopy = (char *)&p[1]; + memset(p, 0, nByte); + memcpy(p, &inst_vfs, sizeof(sqlite3_vfs)); + p->pVfs = pParent; + memcpy(zCopy, zName, strlen(zName)); + p->base.zName = (const char *)zCopy; + p->base.szOsFile += pParent->szOsFile; + sqlite3_vfs_register((sqlite3_vfs *)p, 0); + } + + return (sqlite3_vfs *)p; +} + +void sqlite3_instvfs_configure( + sqlite3_vfs *pVfs, + void (*xCall)( + void*, + int, /* File id */ + int, /* Event code */ + sqlite3_int64, + int, /* Return code */ + const char*, /* File name */ + int, + int, + sqlite3_int64 + ), + void *pClient, + void (*xDel)(void *) +){ + InstVfs *p = (InstVfs *)pVfs; + assert( pVfs->xOpen==instOpen ); + if( p->xDel ){ + p->xDel(p->pClient); + } + p->xCall = xCall; + p->xDel = xDel; + p->pClient = pClient; +} + +void sqlite3_instvfs_destroy(sqlite3_vfs *pVfs){ + if( pVfs ){ + sqlite3_vfs_unregister(pVfs); + sqlite3_instvfs_configure(pVfs, 0, 0, 0); + sqlite3_free(pVfs); + } +} + +void sqlite3_instvfs_reset(sqlite3_vfs *pVfs){ + InstVfs *p = (InstVfs *)pVfs; + assert( pVfs->xOpen==instOpen ); + memset(p->aTime, 0, sizeof(sqlite3_int64)*OS_NUMEVENTS); + memset(p->aCount, 0, sizeof(int)*OS_NUMEVENTS); +} + +const char *sqlite3_instvfs_name(int eEvent){ + const char *zEvent = 0; + + switch( eEvent ){ + case OS_CLOSE: zEvent = "xClose"; break; + case OS_READ: zEvent = "xRead"; break; + case OS_WRITE: zEvent = "xWrite"; break; + case OS_TRUNCATE: zEvent = "xTruncate"; break; + case OS_SYNC: zEvent = "xSync"; break; + case OS_FILESIZE: zEvent = "xFilesize"; break; + case OS_LOCK: zEvent = "xLock"; break; + case OS_UNLOCK: zEvent = "xUnlock"; break; + case OS_CHECKRESERVEDLOCK: zEvent = "xCheckReservedLock"; break; + case OS_FILECONTROL: zEvent = "xFileControl"; break; + case OS_SECTORSIZE: zEvent = "xSectorSize"; break; + case OS_DEVCHAR: zEvent = "xDeviceCharacteristics"; break; + case OS_OPEN: zEvent = "xOpen"; break; + case OS_DELETE: zEvent = "xDelete"; break; + case OS_ACCESS: zEvent = "xAccess"; break; + case OS_FULLPATHNAME: zEvent = "xFullPathname"; break; + case OS_RANDOMNESS: zEvent = "xRandomness"; break; + case OS_SLEEP: zEvent = "xSleep"; break; + case OS_CURRENTTIME: zEvent = "xCurrentTime"; break; + } + + return zEvent; +} + +void sqlite3_instvfs_get( + sqlite3_vfs *pVfs, + int eEvent, + const char **pzEvent, + sqlite3_int64 *pnClick, + int *pnCall +){ + InstVfs *p = (InstVfs *)pVfs; + assert( pVfs->xOpen==instOpen ); + if( eEvent<1 || eEvent>=OS_NUMEVENTS ){ + *pzEvent = 0; + *pnClick = 0; + *pnCall = 0; + return; + } + + *pzEvent = sqlite3_instvfs_name(eEvent); + *pnClick = p->aTime[eEvent]; + *pnCall = p->aCount[eEvent]; +} + +#define BINARYLOG_BUFFERSIZE 8192 + +struct InstVfsBinaryLog { + int nBuf; + char *zBuf; + sqlite3_int64 iOffset; + int log_data; + sqlite3_file *pOut; + char *zOut; /* Log file name */ +}; +typedef struct InstVfsBinaryLog InstVfsBinaryLog; + +static void put32bits(unsigned char *p, unsigned int v){ + p[0] = v>>24; + p[1] = v>>16; + p[2] = v>>8; + p[3] = v; +} + +static void binarylog_flush(InstVfsBinaryLog *pLog){ + sqlite3_file *pFile = pLog->pOut; + +#ifdef SQLITE_TEST + extern int sqlite3_io_error_pending; + extern int sqlite3_io_error_persist; + extern int sqlite3_diskfull_pending; + + int pending = sqlite3_io_error_pending; + int persist = sqlite3_io_error_persist; + int diskfull = sqlite3_diskfull_pending; + + sqlite3_io_error_pending = 0; + sqlite3_io_error_persist = 0; + sqlite3_diskfull_pending = 0; +#endif + + pFile->pMethods->xWrite(pFile, pLog->zBuf, pLog->nBuf, pLog->iOffset); + pLog->iOffset += pLog->nBuf; + pLog->nBuf = 0; + +#ifdef SQLITE_TEST + sqlite3_io_error_pending = pending; + sqlite3_io_error_persist = persist; + sqlite3_diskfull_pending = diskfull; +#endif +} + +static void binarylog_xcall( + void *p, + int eEvent, + int iFileId, + sqlite3_int64 nClick, + int return_code, + const char *zName, + int flags, + int nByte, + sqlite3_int64 iOffset +){ + InstVfsBinaryLog *pLog = (InstVfsBinaryLog *)p; + unsigned char *zRec; + if( (28+pLog->nBuf)>BINARYLOG_BUFFERSIZE ){ + binarylog_flush(pLog); + } + zRec = (unsigned char *)&pLog->zBuf[pLog->nBuf]; + put32bits(&zRec[0], eEvent); + put32bits(&zRec[4], (int)iFileId); + put32bits(&zRec[8], (int)nClick); + put32bits(&zRec[12], return_code); + put32bits(&zRec[16], flags); + put32bits(&zRec[20], nByte); + put32bits(&zRec[24], (int)iOffset); + pLog->nBuf += 28; +} + +static void binarylog_xdel(void *p){ + /* Close the log file and free the memory allocated for the + ** InstVfsBinaryLog structure. + */ + InstVfsBinaryLog *pLog = (InstVfsBinaryLog *)p; + sqlite3_file *pFile = pLog->pOut; + if( pLog->nBuf ){ + binarylog_flush(pLog); + } + pFile->pMethods->xClose(pFile); + sqlite3_free(pLog->pOut); + sqlite3_free(pLog->zBuf); + sqlite3_free(pLog); +} + +static void binarylog_blob( + sqlite3_vfs *pVfs, + const char *zBlob, + int nBlob, + int isBinary +){ + InstVfsBinaryLog *pLog; + InstVfs *pInstVfs = (InstVfs *)pVfs; + + if( pVfs->xOpen!=instOpen || pInstVfs->xCall!=binarylog_xcall ){ + return; + } + pLog = (InstVfsBinaryLog *)pInstVfs->pClient; + if( zBlob && (!isBinary || pLog->log_data) ){ + unsigned char *zRec; + int nWrite; + + if( nBlob<0 ){ + nBlob = strlen(zBlob); + } + nWrite = nBlob + 28; + + if( (nWrite+pLog->nBuf)>BINARYLOG_BUFFERSIZE ){ + binarylog_flush(pLog); + } + + zRec = (unsigned char *)&pLog->zBuf[pLog->nBuf]; + memset(zRec, 0, nWrite); + put32bits(&zRec[0], BINARYLOG_STRING); + put32bits(&zRec[4], (int)nBlob); + put32bits(&zRec[8], (int)isBinary); + memcpy(&zRec[28], zBlob, nBlob); + pLog->nBuf += nWrite; + } +} + +void sqlite3_instvfs_binarylog_call( + sqlite3_vfs *pVfs, + int eEvent, + sqlite3_int64 nClick, + int return_code, + const char *zString +){ + InstVfs *pInstVfs = (InstVfs *)pVfs; + InstVfsBinaryLog *pLog = (InstVfsBinaryLog *)pInstVfs->pClient; + + if( zString ){ + binarylog_blob(pVfs, zString, -1, 0); + } + binarylog_xcall(pLog, eEvent, 0, nClick, return_code, 0, 0, 0, 0); +} + +void sqlite3_instvfs_binarylog_marker( + sqlite3_vfs *pVfs, + const char *zMarker +){ + InstVfs *pInstVfs = (InstVfs *)pVfs; + InstVfsBinaryLog *pLog = (InstVfsBinaryLog *)pInstVfs->pClient; + binarylog_blob(pVfs, zMarker, -1, 0); + binarylog_xcall(pLog, BINARYLOG_MARKER, 0, 0, 0, 0, 0, 0, 0); +} + +sqlite3_vfs *sqlite3_instvfs_binarylog( + const char *zVfs, + const char *zParentVfs, + const char *zLog, + int log_data +){ + InstVfsBinaryLog *p; + sqlite3_vfs *pVfs; + sqlite3_vfs *pParent; + int nByte; + int flags; + int rc; + + pParent = sqlite3_vfs_find(zParentVfs); + if( !pParent ){ + return 0; + } + + nByte = sizeof(InstVfsBinaryLog) + pParent->mxPathname+1; + p = (InstVfsBinaryLog *)sqlite3_malloc(nByte); + memset(p, 0, nByte); + p->zBuf = sqlite3_malloc(BINARYLOG_BUFFERSIZE); + p->zOut = (char *)&p[1]; + p->pOut = (sqlite3_file *)sqlite3_malloc(pParent->szOsFile); + p->log_data = log_data; + pParent->xFullPathname(pParent, zLog, pParent->mxPathname, p->zOut); + flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MASTER_JOURNAL; + pParent->xDelete(pParent, p->zOut, 0); + rc = pParent->xOpen(pParent, p->zOut, p->pOut, flags, &flags); + if( rc==SQLITE_OK ){ + memcpy(p->zBuf, "sqlite_ostrace1.....", 20); + p->iOffset = 0; + p->nBuf = 20; + } + if( rc ){ + binarylog_xdel(p); + return 0; + } + + pVfs = sqlite3_instvfs_create(zVfs, zParentVfs); + if( pVfs ){ + sqlite3_instvfs_configure(pVfs, binarylog_xcall, p, binarylog_xdel); + } + + return pVfs; +} +#endif /* SQLITE_ENABLE_INSTVFS */ + +/************************************************************************** +*************************************************************************** +** Tcl interface starts here. +*/ +#if SQLITE_TEST + +#include <tcl.h> + +#ifdef SQLITE_ENABLE_INSTVFS +struct InstVfsCall { + Tcl_Interp *interp; + Tcl_Obj *pScript; +}; +typedef struct InstVfsCall InstVfsCall; + +static void test_instvfs_xcall( + void *p, + int eEvent, + int iFileId, + sqlite3_int64 nClick, + int return_code, + const char *zName, + int flags, + int nByte, + sqlite3_int64 iOffset +){ + int rc; + InstVfsCall *pCall = (InstVfsCall *)p; + Tcl_Obj *pObj = Tcl_DuplicateObj( pCall->pScript); + const char *zEvent = sqlite3_instvfs_name(eEvent); + + Tcl_IncrRefCount(pObj); + Tcl_ListObjAppendElement(0, pObj, Tcl_NewStringObj(zEvent, -1)); + Tcl_ListObjAppendElement(0, pObj, Tcl_NewWideIntObj(nClick)); + Tcl_ListObjAppendElement(0, pObj, Tcl_NewStringObj(zName, -1)); + Tcl_ListObjAppendElement(0, pObj, Tcl_NewIntObj(nByte)); + Tcl_ListObjAppendElement(0, pObj, Tcl_NewWideIntObj(iOffset)); + + rc = Tcl_EvalObjEx(pCall->interp, pObj, TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT); + if( rc ){ + Tcl_BackgroundError(pCall->interp); + } + Tcl_DecrRefCount(pObj); +} + +static void test_instvfs_xdel(void *p){ + InstVfsCall *pCall = (InstVfsCall *)p; + Tcl_DecrRefCount(pCall->pScript); + sqlite3_free(pCall); +} + +static int test_sqlite3_instvfs( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + static const char *IV_strs[] = + { "create", "destroy", "reset", "report", "configure", "binarylog", "marker", 0 }; + enum IV_enum { IV_CREATE, IV_DESTROY, IV_RESET, IV_REPORT, IV_CONFIGURE, IV_BINARYLOG, IV_MARKER }; + int iSub; + + if( objc<2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ..."); + } + if( Tcl_GetIndexFromObj(interp, objv[1], IV_strs, "sub-command", 0, &iSub) ){ + return TCL_ERROR; + } + + switch( (enum IV_enum)iSub ){ + case IV_CREATE: { + char *zParent = 0; + sqlite3_vfs *p; + int isDefault = 0; + if( objc>2 && 0==strcmp("-default", Tcl_GetString(objv[2])) ){ + isDefault = 1; + } + if( (objc-isDefault)!=4 && (objc-isDefault)!=3 ){ + Tcl_WrongNumArgs(interp, 2, objv, "?-default? NAME ?PARENT-VFS?"); + return TCL_ERROR; + } + if( objc==(4+isDefault) ){ + zParent = Tcl_GetString(objv[3+isDefault]); + } + p = sqlite3_instvfs_create(Tcl_GetString(objv[2+isDefault]), zParent); + if( !p ){ + Tcl_AppendResult(interp, "error creating vfs ", 0); + return TCL_ERROR; + } + if( isDefault ){ + sqlite3_vfs_register(p, 1); + } + Tcl_SetObjResult(interp, objv[2]); + break; + } + case IV_BINARYLOG: { + char *zName = 0; + char *zLog = 0; + char *zParent = 0; + sqlite3_vfs *p; + int isDefault = 0; + int isLogdata = 0; + int argbase = 2; + + for(argbase=2; argbase<(objc-2); argbase++){ + if( 0==strcmp("-default", Tcl_GetString(objv[argbase])) ){ + isDefault = 1; + } + else if( 0==strcmp("-parent", Tcl_GetString(objv[argbase])) ){ + argbase++; + zParent = Tcl_GetString(objv[argbase]); + } + else if( 0==strcmp("-logdata", Tcl_GetString(objv[argbase])) ){ + isLogdata = 1; + }else{ + break; + } + } + + if( (objc-argbase)!=2 ){ + Tcl_WrongNumArgs( + interp, 2, objv, "?-default? ?-parent VFS? ?-logdata? NAME LOGFILE" + ); + return TCL_ERROR; + } + zName = Tcl_GetString(objv[argbase]); + zLog = Tcl_GetString(objv[argbase+1]); + p = sqlite3_instvfs_binarylog(zName, zParent, zLog, isLogdata); + if( !p ){ + Tcl_AppendResult(interp, "error creating vfs ", 0); + return TCL_ERROR; + } + if( isDefault ){ + sqlite3_vfs_register(p, 1); + } + Tcl_SetObjResult(interp, objv[2]); + break; + } + + case IV_MARKER: { + sqlite3_vfs *p; + if( objc!=4 ){ + Tcl_WrongNumArgs(interp, 2, objv, "VFS MARKER"); + return TCL_ERROR; + } + p = sqlite3_vfs_find(Tcl_GetString(objv[2])); + if( !p || p->xOpen!=instOpen ){ + Tcl_AppendResult(interp, "no such vfs: ", Tcl_GetString(objv[2]), 0); + return TCL_ERROR; + } + sqlite3_instvfs_binarylog_marker(p, Tcl_GetString(objv[3])); + Tcl_ResetResult(interp); + break; + } + + case IV_CONFIGURE: { + InstVfsCall *pCall; + + sqlite3_vfs *p; + if( objc!=4 ){ + Tcl_WrongNumArgs(interp, 2, objv, "NAME SCRIPT"); + return TCL_ERROR; + } + p = sqlite3_vfs_find(Tcl_GetString(objv[2])); + if( !p || p->xOpen!=instOpen ){ + Tcl_AppendResult(interp, "no such vfs: ", Tcl_GetString(objv[2]), 0); + return TCL_ERROR; + } + + if( strlen(Tcl_GetString(objv[3])) ){ + pCall = (InstVfsCall *)sqlite3_malloc(sizeof(InstVfsCall)); + pCall->interp = interp; + pCall->pScript = Tcl_DuplicateObj(objv[3]); + Tcl_IncrRefCount(pCall->pScript); + sqlite3_instvfs_configure(p, + test_instvfs_xcall, (void *)pCall, test_instvfs_xdel + ); + }else{ + sqlite3_instvfs_configure(p, 0, 0, 0); + } + break; + } + + case IV_REPORT: + case IV_DESTROY: + case IV_RESET: { + sqlite3_vfs *p; + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 2, objv, "NAME"); + return TCL_ERROR; + } + p = sqlite3_vfs_find(Tcl_GetString(objv[2])); + if( !p || p->xOpen!=instOpen ){ + Tcl_AppendResult(interp, "no such vfs: ", Tcl_GetString(objv[2]), 0); + return TCL_ERROR; + } + + if( ((enum IV_enum)iSub)==IV_DESTROY ){ + sqlite3_instvfs_destroy(p); + } + if( ((enum IV_enum)iSub)==IV_RESET ){ + sqlite3_instvfs_reset(p); + } + if( ((enum IV_enum)iSub)==IV_REPORT ){ + int ii; + Tcl_Obj *pRet = Tcl_NewObj(); + + const char *zName = (char *)1; + sqlite3_int64 nClick; + int nCall; + for(ii=1; zName; ii++){ + sqlite3_instvfs_get(p, ii, &zName, &nClick, &nCall); + if( zName ){ + Tcl_Obj *pElem = Tcl_NewObj(); + Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj(zName, -1)); + Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(nCall)); + Tcl_ListObjAppendElement(0, pElem, Tcl_NewWideIntObj(nClick)); + Tcl_ListObjAppendElement(0, pRet, pElem); + } + } + + Tcl_SetObjResult(interp, pRet); + } + + break; + } + } + + return TCL_OK; +} +#endif /* SQLITE_ENABLE_INSTVFS */ + +/* Alternative implementation of sqlite3_instvfs when the real +** implementation is unavailable. +*/ +#ifndef SQLITE_ENABLE_INSTVFS +static int test_sqlite3_instvfs( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + Tcl_AppendResult(interp, + "not compiled with -DSQLITE_ENABLE_INSTVFS; sqlite3_instvfs is " + "unavailable", (char*)0); + return TCL_ERROR; +} +#endif /* !defined(SQLITE_ENABLE_INSTVFS) */ + +int SqlitetestOsinst_Init(Tcl_Interp *interp){ + Tcl_CreateObjCommand(interp, "sqlite3_instvfs", test_sqlite3_instvfs, 0, 0); + return TCL_OK; +} + +#endif /* SQLITE_TEST */ diff --git a/third_party/sqlite/src/test_schema.c b/third_party/sqlite/src/test_schema.c new file mode 100755 index 0000000..51099f5 --- /dev/null +++ b/third_party/sqlite/src/test_schema.c @@ -0,0 +1,361 @@ +/* +** 2006 June 10 +** +** 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. +** +************************************************************************* +** Code for testing the virtual table interfaces. This code +** is not included in the SQLite library. It is used for automated +** testing of the SQLite library. +** +** $Id: test_schema.c,v 1.15 2008/07/07 14:50:14 drh Exp $ +*/ + +/* The code in this file defines a sqlite3 virtual-table module that +** provides a read-only view of the current database schema. There is one +** row in the schema table for each column in the database schema. +*/ +#define SCHEMA \ +"CREATE TABLE x(" \ + "database," /* Name of database (i.e. main, temp etc.) */ \ + "tablename," /* Name of table */ \ + "cid," /* Column number (from left-to-right, 0 upward) */ \ + "name," /* Column name */ \ + "type," /* Specified type (i.e. VARCHAR(32)) */ \ + "not_null," /* Boolean. True if NOT NULL was specified */ \ + "dflt_value," /* Default value for this column */ \ + "pk" /* True if this column is part of the primary key */ \ +")" + +/* If SQLITE_TEST is defined this code is preprocessed for use as part +** of the sqlite test binary "testfixture". Otherwise it is preprocessed +** to be compiled into an sqlite dynamic extension. +*/ +#ifdef SQLITE_TEST + #include "sqliteInt.h" + #include "tcl.h" +#else + #include "sqlite3ext.h" + SQLITE_EXTENSION_INIT1 +#endif + +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +typedef struct schema_vtab schema_vtab; +typedef struct schema_cursor schema_cursor; + +/* A schema table object */ +struct schema_vtab { + sqlite3_vtab base; + sqlite3 *db; +}; + +/* A schema table cursor object */ +struct schema_cursor { + sqlite3_vtab_cursor base; + sqlite3_stmt *pDbList; + sqlite3_stmt *pTableList; + sqlite3_stmt *pColumnList; + int rowid; +}; + +/* +** None of this works unless we have virtual tables. +*/ +#ifndef SQLITE_OMIT_VIRTUALTABLE + +/* +** Table destructor for the schema module. +*/ +static int schemaDestroy(sqlite3_vtab *pVtab){ + sqlite3_free(pVtab); + return 0; +} + +/* +** Table constructor for the schema module. +*/ +static int schemaCreate( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr +){ + int rc = SQLITE_NOMEM; + schema_vtab *pVtab = sqlite3_malloc(sizeof(schema_vtab)); + if( pVtab ){ + memset(pVtab, 0, sizeof(schema_vtab)); + pVtab->db = db; +#ifndef SQLITE_OMIT_VIRTUALTABLE + rc = sqlite3_declare_vtab(db, SCHEMA); +#endif + } + *ppVtab = (sqlite3_vtab *)pVtab; + return rc; +} + +/* +** Open a new cursor on the schema table. +*/ +static int schemaOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ + int rc = SQLITE_NOMEM; + schema_cursor *pCur; + pCur = sqlite3_malloc(sizeof(schema_cursor)); + if( pCur ){ + memset(pCur, 0, sizeof(schema_cursor)); + *ppCursor = (sqlite3_vtab_cursor *)pCur; + rc = SQLITE_OK; + } + return rc; +} + +/* +** Close a schema table cursor. +*/ +static int schemaClose(sqlite3_vtab_cursor *cur){ + schema_cursor *pCur = (schema_cursor *)cur; + sqlite3_finalize(pCur->pDbList); + sqlite3_finalize(pCur->pTableList); + sqlite3_finalize(pCur->pColumnList); + sqlite3_free(pCur); + return SQLITE_OK; +} + +/* +** Retrieve a column of data. +*/ +static int schemaColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ + schema_cursor *pCur = (schema_cursor *)cur; + switch( i ){ + case 0: + sqlite3_result_value(ctx, sqlite3_column_value(pCur->pDbList, 1)); + break; + case 1: + sqlite3_result_value(ctx, sqlite3_column_value(pCur->pTableList, 0)); + break; + default: + sqlite3_result_value(ctx, sqlite3_column_value(pCur->pColumnList, i-2)); + break; + } + return SQLITE_OK; +} + +/* +** Retrieve the current rowid. +*/ +static int schemaRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ + schema_cursor *pCur = (schema_cursor *)cur; + *pRowid = pCur->rowid; + return SQLITE_OK; +} + +static int finalize(sqlite3_stmt **ppStmt){ + int rc = sqlite3_finalize(*ppStmt); + *ppStmt = 0; + return rc; +} + +static int schemaEof(sqlite3_vtab_cursor *cur){ + schema_cursor *pCur = (schema_cursor *)cur; + return (pCur->pDbList ? 0 : 1); +} + +/* +** Advance the cursor to the next row. +*/ +static int schemaNext(sqlite3_vtab_cursor *cur){ + int rc = SQLITE_OK; + schema_cursor *pCur = (schema_cursor *)cur; + schema_vtab *pVtab = (schema_vtab *)(cur->pVtab); + char *zSql = 0; + + while( !pCur->pColumnList || SQLITE_ROW!=sqlite3_step(pCur->pColumnList) ){ + if( SQLITE_OK!=(rc = finalize(&pCur->pColumnList)) ) goto next_exit; + + while( !pCur->pTableList || SQLITE_ROW!=sqlite3_step(pCur->pTableList) ){ + if( SQLITE_OK!=(rc = finalize(&pCur->pTableList)) ) goto next_exit; + + assert(pCur->pDbList); + while( SQLITE_ROW!=sqlite3_step(pCur->pDbList) ){ + rc = finalize(&pCur->pDbList); + goto next_exit; + } + + /* Set zSql to the SQL to pull the list of tables from the + ** sqlite_master (or sqlite_temp_master) table of the database + ** identfied by the row pointed to by the SQL statement pCur->pDbList + ** (iterating through a "PRAGMA database_list;" statement). + */ + if( sqlite3_column_int(pCur->pDbList, 0)==1 ){ + zSql = sqlite3_mprintf( + "SELECT name FROM sqlite_temp_master WHERE type='table'" + ); + }else{ + sqlite3_stmt *pDbList = pCur->pDbList; + zSql = sqlite3_mprintf( + "SELECT name FROM %Q.sqlite_master WHERE type='table'", + sqlite3_column_text(pDbList, 1) + ); + } + if( !zSql ){ + rc = SQLITE_NOMEM; + goto next_exit; + } + + rc = sqlite3_prepare(pVtab->db, zSql, -1, &pCur->pTableList, 0); + sqlite3_free(zSql); + if( rc!=SQLITE_OK ) goto next_exit; + } + + /* Set zSql to the SQL to the table_info pragma for the table currently + ** identified by the rows pointed to by statements pCur->pDbList and + ** pCur->pTableList. + */ + zSql = sqlite3_mprintf("PRAGMA %Q.table_info(%Q)", + sqlite3_column_text(pCur->pDbList, 1), + sqlite3_column_text(pCur->pTableList, 0) + ); + + if( !zSql ){ + rc = SQLITE_NOMEM; + goto next_exit; + } + rc = sqlite3_prepare(pVtab->db, zSql, -1, &pCur->pColumnList, 0); + sqlite3_free(zSql); + if( rc!=SQLITE_OK ) goto next_exit; + } + pCur->rowid++; + +next_exit: + /* TODO: Handle rc */ + return rc; +} + +/* +** Reset a schema table cursor. +*/ +static int schemaFilter( + sqlite3_vtab_cursor *pVtabCursor, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv +){ + int rc; + schema_vtab *pVtab = (schema_vtab *)(pVtabCursor->pVtab); + schema_cursor *pCur = (schema_cursor *)pVtabCursor; + pCur->rowid = 0; + finalize(&pCur->pTableList); + finalize(&pCur->pColumnList); + finalize(&pCur->pDbList); + rc = sqlite3_prepare(pVtab->db,"PRAGMA database_list", -1, &pCur->pDbList, 0); + return (rc==SQLITE_OK ? schemaNext(pVtabCursor) : rc); +} + +/* +** Analyse the WHERE condition. +*/ +static int schemaBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ + return SQLITE_OK; +} + +/* +** A virtual table module that merely echos method calls into TCL +** variables. +*/ +static sqlite3_module schemaModule = { + 0, /* iVersion */ + schemaCreate, + schemaCreate, + schemaBestIndex, + schemaDestroy, + schemaDestroy, + schemaOpen, /* xOpen - open a cursor */ + schemaClose, /* xClose - close a cursor */ + schemaFilter, /* xFilter - configure scan constraints */ + schemaNext, /* xNext - advance a cursor */ + schemaEof, /* xEof */ + schemaColumn, /* xColumn - read data */ + schemaRowid, /* xRowid - read data */ + 0, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindMethod */ + 0, /* xRename */ +}; + +#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */ + +#ifdef SQLITE_TEST + +/* +** Decode a pointer to an sqlite3 object. +*/ +extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb); + +/* +** Register the schema virtual table module. +*/ +static int register_schema_module( + ClientData clientData, /* Not used */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + sqlite3 *db; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB"); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; +#ifndef SQLITE_OMIT_VIRTUALTABLE + sqlite3_create_module(db, "schema", &schemaModule, 0); +#endif + return TCL_OK; +} + +/* +** Register commands with the TCL interpreter. +*/ +int Sqlitetestschema_Init(Tcl_Interp *interp){ + static struct { + char *zName; + Tcl_ObjCmdProc *xProc; + void *clientData; + } aObjCmd[] = { + { "register_schema_module", register_schema_module, 0 }, + }; + int i; + for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ + Tcl_CreateObjCommand(interp, aObjCmd[i].zName, + aObjCmd[i].xProc, aObjCmd[i].clientData, 0); + } + return TCL_OK; +} + +#else + +/* +** Extension load function. +*/ +int sqlite3_extension_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + SQLITE_EXTENSION_INIT2(pApi); +#ifndef SQLITE_OMIT_VIRTUALTABLE + sqlite3_create_module(db, "schema", &schemaModule, 0); +#endif + return 0; +} + +#endif diff --git a/third_party/sqlite/src/test_server.c b/third_party/sqlite/src/test_server.c new file mode 100755 index 0000000..6862d7c --- /dev/null +++ b/third_party/sqlite/src/test_server.c @@ -0,0 +1,493 @@ +/* +** 2006 January 07 +** +** 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. +** +****************************************************************************** +** +** $Id: test_server.c,v 1.8 2008/06/26 10:41:19 danielk1977 Exp $ +** +** This file contains demonstration code. Nothing in this file gets compiled +** or linked into the SQLite library unless you use a non-standard option: +** +** -DSQLITE_SERVER=1 +** +** The configure script will never generate a Makefile with the option +** above. You will need to manually modify the Makefile if you want to +** include any of the code from this file in your project. Or, at your +** option, you may copy and paste the code from this file and +** thereby avoiding a recompile of SQLite. +** +** +** This source file demonstrates how to use SQLite to create an SQL database +** server thread in a multiple-threaded program. One or more client threads +** send messages to the server thread and the server thread processes those +** messages in the order received and returns the results to the client. +** +** One might ask: "Why bother? Why not just let each thread connect +** to the database directly?" There are a several of reasons to +** prefer the client/server approach. +** +** (1) Some systems (ex: Redhat9) have broken threading implementations +** that prevent SQLite database connections from being used in +** a thread different from the one where they were created. With +** the client/server approach, all database connections are created +** and used within the server thread. Client calls to the database +** can be made from multiple threads (though not at the same time!) +** +** (2) Beginning with SQLite version 3.3.0, when two or more +** connections to the same database occur within the same thread, +** they can optionally share their database cache. This reduces +** I/O and memory requirements. Cache shared is controlled using +** the sqlite3_enable_shared_cache() API. +** +** (3) Database connections on a shared cache use table-level locking +** instead of file-level locking for improved concurrency. +** +** (4) Database connections on a shared cache can by optionally +** set to READ UNCOMMITTED isolation. (The default isolation for +** SQLite is SERIALIZABLE.) When this occurs, readers will +** never be blocked by a writer and writers will not be +** blocked by readers. There can still only be a single writer +** at a time, but multiple readers can simultaneously exist with +** that writer. This is a huge increase in concurrency. +** +** To summarize the rational for using a client/server approach: prior +** to SQLite version 3.3.0 it probably was not worth the trouble. But +** with SQLite version 3.3.0 and beyond you can get significant performance +** and concurrency improvements and memory usage reductions by going +** client/server. +** +** Note: The extra features of version 3.3.0 described by points (2) +** through (4) above are only available if you compile without the +** option -DSQLITE_OMIT_SHARED_CACHE. +** +** Here is how the client/server approach works: The database server +** thread is started on this procedure: +** +** void *sqlite3_server(void *NotUsed); +** +** The sqlite_server procedure runs as long as the g.serverHalt variable +** is false. A mutex is used to make sure no more than one server runs +** at a time. The server waits for messages to arrive on a message +** queue and processes the messages in order. +** +** Two convenience routines are provided for starting and stopping the +** server thread: +** +** void sqlite3_server_start(void); +** void sqlite3_server_stop(void); +** +** Both of the convenience routines return immediately. Neither will +** ever give an error. If a server is already started or already halted, +** then the routines are effectively no-ops. +** +** Clients use the following interfaces: +** +** sqlite3_client_open +** sqlite3_client_prepare +** sqlite3_client_step +** sqlite3_client_reset +** sqlite3_client_finalize +** sqlite3_client_close +** +** These interfaces work exactly like the standard core SQLite interfaces +** having the same names without the "_client_" infix. Many other SQLite +** interfaces can be used directly without having to send messages to the +** server as long as SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined. +** The following interfaces fall into this second category: +** +** sqlite3_bind_* +** sqlite3_changes +** sqlite3_clear_bindings +** sqlite3_column_* +** sqlite3_complete +** sqlite3_create_collation +** sqlite3_create_function +** sqlite3_data_count +** sqlite3_db_handle +** sqlite3_errcode +** sqlite3_errmsg +** sqlite3_last_insert_rowid +** sqlite3_total_changes +** sqlite3_transfer_bindings +** +** A single SQLite connection (an sqlite3* object) or an SQLite statement +** (an sqlite3_stmt* object) should only be passed to a single interface +** function at a time. The connections and statements can be passed from +** any thread to any of the functions listed in the second group above as +** long as the same connection is not in use by two threads at once and +** as long as SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined. Additional +** information about the SQLITE_ENABLE_MEMORY_MANAGEMENT constraint is +** below. +** +** The busy handler for all database connections should remain turned +** off. That means that any lock contention will cause the associated +** sqlite3_client_step() call to return immediately with an SQLITE_BUSY +** error code. If a busy handler is enabled and lock contention occurs, +** then the entire server thread will block. This will cause not only +** the requesting client to block but every other database client as +** well. It is possible to enhance the code below so that lock +** contention will cause the message to be placed back on the top of +** the queue to be tried again later. But such enhanced processing is +** not included here, in order to keep the example simple. +** +** This example code assumes the use of pthreads. Pthreads +** implementations are available for windows. (See, for example +** http://sourceware.org/pthreads-win32/announcement.html.) Or, you +** can translate the locking and thread synchronization code to use +** windows primitives easily enough. The details are left as an +** exercise to the reader. +** +**** Restrictions Associated With SQLITE_ENABLE_MEMORY_MANAGEMENT **** +** +** If you compile with SQLITE_ENABLE_MEMORY_MANAGEMENT defined, then +** SQLite includes code that tracks how much memory is being used by +** each thread. These memory counts can become confused if memory +** is allocated by one thread and then freed by another. For that +** reason, when SQLITE_ENABLE_MEMORY_MANAGEMENT is used, all operations +** that might allocate or free memory should be performanced in the same +** thread that originally created the database connection. In that case, +** many of the operations that are listed above as safe to be performed +** in separate threads would need to be sent over to the server to be +** done there. If SQLITE_ENABLE_MEMORY_MANAGEMENT is defined, then +** the following functions can be used safely from different threads +** without messing up the allocation counts: +** +** sqlite3_bind_parameter_name +** sqlite3_bind_parameter_index +** sqlite3_changes +** sqlite3_column_blob +** sqlite3_column_count +** sqlite3_complete +** sqlite3_data_count +** sqlite3_db_handle +** sqlite3_errcode +** sqlite3_errmsg +** sqlite3_last_insert_rowid +** sqlite3_total_changes +** +** The remaining functions are not thread-safe when memory management +** is enabled. So one would have to define some new interface routines +** along the following lines: +** +** sqlite3_client_bind_* +** sqlite3_client_clear_bindings +** sqlite3_client_column_* +** sqlite3_client_create_collation +** sqlite3_client_create_function +** sqlite3_client_transfer_bindings +** +** The example code in this file is intended for use with memory +** management turned off. So the implementation of these additional +** client interfaces is left as an exercise to the reader. +** +** It may seem surprising to the reader that the list of safe functions +** above does not include things like sqlite3_bind_int() or +** sqlite3_column_int(). But those routines might, in fact, allocate +** or deallocate memory. In the case of sqlite3_bind_int(), if the +** parameter was previously bound to a string that string might need +** to be deallocated before the new integer value is inserted. In +** the case of sqlite3_column_int(), the value of the column might be +** a UTF-16 string which will need to be converted to UTF-8 then into +** an integer. +*/ + +/* Include this to get the definition of SQLITE_THREADSAFE, in the +** case that default values are used. +*/ +#include "sqliteInt.h" + +/* +** Only compile the code in this file on UNIX with a SQLITE_THREADSAFE build +** and only if the SQLITE_SERVER macro is defined. +*/ +#if defined(SQLITE_SERVER) && !defined(SQLITE_OMIT_SHARED_CACHE) +#if defined(SQLITE_OS_UNIX) && OS_UNIX && SQLITE_THREADSAFE + +/* +** We require only pthreads and the public interface of SQLite. +*/ +#include <pthread.h> +#include "sqlite3.h" + +/* +** Messages are passed from client to server and back again as +** instances of the following structure. +*/ +typedef struct SqlMessage SqlMessage; +struct SqlMessage { + int op; /* Opcode for the message */ + sqlite3 *pDb; /* The SQLite connection */ + sqlite3_stmt *pStmt; /* A specific statement */ + int errCode; /* Error code returned */ + const char *zIn; /* Input filename or SQL statement */ + int nByte; /* Size of the zIn parameter for prepare() */ + const char *zOut; /* Tail of the SQL statement */ + SqlMessage *pNext; /* Next message in the queue */ + SqlMessage *pPrev; /* Previous message in the queue */ + pthread_mutex_t clientMutex; /* Hold this mutex to access the message */ + pthread_cond_t clientWakeup; /* Signal to wake up the client */ +}; + +/* +** Legal values for SqlMessage.op +*/ +#define MSG_Open 1 /* sqlite3_open(zIn, &pDb) */ +#define MSG_Prepare 2 /* sqlite3_prepare(pDb, zIn, nByte, &pStmt, &zOut) */ +#define MSG_Step 3 /* sqlite3_step(pStmt) */ +#define MSG_Reset 4 /* sqlite3_reset(pStmt) */ +#define MSG_Finalize 5 /* sqlite3_finalize(pStmt) */ +#define MSG_Close 6 /* sqlite3_close(pDb) */ +#define MSG_Done 7 /* Server has finished with this message */ + + +/* +** State information about the server is stored in a static variable +** named "g" as follows: +*/ +static struct ServerState { + pthread_mutex_t queueMutex; /* Hold this mutex to access the msg queue */ + pthread_mutex_t serverMutex; /* Held by the server while it is running */ + pthread_cond_t serverWakeup; /* Signal this condvar to wake up the server */ + volatile int serverHalt; /* Server halts itself when true */ + SqlMessage *pQueueHead; /* Head of the message queue */ + SqlMessage *pQueueTail; /* Tail of the message queue */ +} g = { + PTHREAD_MUTEX_INITIALIZER, + PTHREAD_MUTEX_INITIALIZER, + PTHREAD_COND_INITIALIZER, +}; + +/* +** Send a message to the server. Block until we get a reply. +** +** The mutex and condition variable in the message are uninitialized +** when this routine is called. This routine takes care of +** initializing them and destroying them when it has finished. +*/ +static void sendToServer(SqlMessage *pMsg){ + /* Initialize the mutex and condition variable on the message + */ + pthread_mutex_init(&pMsg->clientMutex, 0); + pthread_cond_init(&pMsg->clientWakeup, 0); + + /* Add the message to the head of the server's message queue. + */ + pthread_mutex_lock(&g.queueMutex); + pMsg->pNext = g.pQueueHead; + if( g.pQueueHead==0 ){ + g.pQueueTail = pMsg; + }else{ + g.pQueueHead->pPrev = pMsg; + } + pMsg->pPrev = 0; + g.pQueueHead = pMsg; + pthread_mutex_unlock(&g.queueMutex); + + /* Signal the server that the new message has be queued, then + ** block waiting for the server to process the message. + */ + pthread_mutex_lock(&pMsg->clientMutex); + pthread_cond_signal(&g.serverWakeup); + while( pMsg->op!=MSG_Done ){ + pthread_cond_wait(&pMsg->clientWakeup, &pMsg->clientMutex); + } + pthread_mutex_unlock(&pMsg->clientMutex); + + /* Destroy the mutex and condition variable of the message. + */ + pthread_mutex_destroy(&pMsg->clientMutex); + pthread_cond_destroy(&pMsg->clientWakeup); +} + +/* +** The following 6 routines are client-side implementations of the +** core SQLite interfaces: +** +** sqlite3_open +** sqlite3_prepare +** sqlite3_step +** sqlite3_reset +** sqlite3_finalize +** sqlite3_close +** +** Clients should use the following client-side routines instead of +** the core routines above. +** +** sqlite3_client_open +** sqlite3_client_prepare +** sqlite3_client_step +** sqlite3_client_reset +** sqlite3_client_finalize +** sqlite3_client_close +** +** Each of these routines creates a message for the desired operation, +** sends that message to the server, waits for the server to process +** then message and return a response. +*/ +int sqlite3_client_open(const char *zDatabaseName, sqlite3 **ppDb){ + SqlMessage msg; + msg.op = MSG_Open; + msg.zIn = zDatabaseName; + sendToServer(&msg); + *ppDb = msg.pDb; + return msg.errCode; +} +int sqlite3_client_prepare( + sqlite3 *pDb, + const char *zSql, + int nByte, + sqlite3_stmt **ppStmt, + const char **pzTail +){ + SqlMessage msg; + msg.op = MSG_Prepare; + msg.pDb = pDb; + msg.zIn = zSql; + msg.nByte = nByte; + sendToServer(&msg); + *ppStmt = msg.pStmt; + if( pzTail ) *pzTail = msg.zOut; + return msg.errCode; +} +int sqlite3_client_step(sqlite3_stmt *pStmt){ + SqlMessage msg; + msg.op = MSG_Step; + msg.pStmt = pStmt; + sendToServer(&msg); + return msg.errCode; +} +int sqlite3_client_reset(sqlite3_stmt *pStmt){ + SqlMessage msg; + msg.op = MSG_Reset; + msg.pStmt = pStmt; + sendToServer(&msg); + return msg.errCode; +} +int sqlite3_client_finalize(sqlite3_stmt *pStmt){ + SqlMessage msg; + msg.op = MSG_Finalize; + msg.pStmt = pStmt; + sendToServer(&msg); + return msg.errCode; +} +int sqlite3_client_close(sqlite3 *pDb){ + SqlMessage msg; + msg.op = MSG_Close; + msg.pDb = pDb; + sendToServer(&msg); + return msg.errCode; +} + +/* +** This routine implements the server. To start the server, first +** make sure g.serverHalt is false, then create a new detached thread +** on this procedure. See the sqlite3_server_start() routine below +** for an example. This procedure loops until g.serverHalt becomes +** true. +*/ +void *sqlite3_server(void *NotUsed){ + if( pthread_mutex_trylock(&g.serverMutex) ){ + return 0; /* Another server is already running */ + } + sqlite3_enable_shared_cache(1); + while( !g.serverHalt ){ + SqlMessage *pMsg; + + /* Remove the last message from the message queue. + */ + pthread_mutex_lock(&g.queueMutex); + while( g.pQueueTail==0 && g.serverHalt==0 ){ + pthread_cond_wait(&g.serverWakeup, &g.queueMutex); + } + pMsg = g.pQueueTail; + if( pMsg ){ + if( pMsg->pPrev ){ + pMsg->pPrev->pNext = 0; + }else{ + g.pQueueHead = 0; + } + g.pQueueTail = pMsg->pPrev; + } + pthread_mutex_unlock(&g.queueMutex); + if( pMsg==0 ) break; + + /* Process the message just removed + */ + pthread_mutex_lock(&pMsg->clientMutex); + switch( pMsg->op ){ + case MSG_Open: { + pMsg->errCode = sqlite3_open(pMsg->zIn, &pMsg->pDb); + break; + } + case MSG_Prepare: { + pMsg->errCode = sqlite3_prepare(pMsg->pDb, pMsg->zIn, pMsg->nByte, + &pMsg->pStmt, &pMsg->zOut); + break; + } + case MSG_Step: { + pMsg->errCode = sqlite3_step(pMsg->pStmt); + break; + } + case MSG_Reset: { + pMsg->errCode = sqlite3_reset(pMsg->pStmt); + break; + } + case MSG_Finalize: { + pMsg->errCode = sqlite3_finalize(pMsg->pStmt); + break; + } + case MSG_Close: { + pMsg->errCode = sqlite3_close(pMsg->pDb); + break; + } + } + + /* Signal the client that the message has been processed. + */ + pMsg->op = MSG_Done; + pthread_mutex_unlock(&pMsg->clientMutex); + pthread_cond_signal(&pMsg->clientWakeup); + } + sqlite3_thread_cleanup(); + pthread_mutex_unlock(&g.serverMutex); + return 0; +} + +/* +** Start a server thread if one is not already running. If there +** is aleady a server thread running, the new thread will quickly +** die and this routine is effectively a no-op. +*/ +void sqlite3_server_start(void){ + pthread_t x; + int rc; + g.serverHalt = 0; + rc = pthread_create(&x, 0, sqlite3_server, 0); + if( rc==0 ){ + pthread_detach(x); + } +} + +/* +** If a server thread is running, then stop it. If no server is +** running, this routine is effectively a no-op. +** +** This routine waits until the server has actually stopped before +** returning. +*/ +void sqlite3_server_stop(void){ + g.serverHalt = 1; + pthread_cond_broadcast(&g.serverWakeup); + pthread_mutex_lock(&g.serverMutex); + pthread_mutex_unlock(&g.serverMutex); +} + +#endif /* defined(SQLITE_OS_UNIX) && OS_UNIX && SQLITE_THREADSAFE */ +#endif /* defined(SQLITE_SERVER) */ diff --git a/third_party/sqlite/src/test_tclvar.c b/third_party/sqlite/src/test_tclvar.c new file mode 100755 index 0000000..6cbec53 --- /dev/null +++ b/third_party/sqlite/src/test_tclvar.c @@ -0,0 +1,325 @@ +/* +** 2006 June 13 +** +** 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. +** +************************************************************************* +** Code for testing the virtual table interfaces. This code +** is not included in the SQLite library. It is used for automated +** testing of the SQLite library. +** +** The emphasis of this file is a virtual table that provides +** access to TCL variables. +** +** $Id: test_tclvar.c,v 1.16 2008/07/07 14:50:14 drh Exp $ +*/ +#include "sqliteInt.h" +#include "tcl.h" +#include <stdlib.h> +#include <string.h> + +#ifndef SQLITE_OMIT_VIRTUALTABLE + +typedef struct tclvar_vtab tclvar_vtab; +typedef struct tclvar_cursor tclvar_cursor; + +/* +** A tclvar virtual-table object +*/ +struct tclvar_vtab { + sqlite3_vtab base; + Tcl_Interp *interp; +}; + +/* A tclvar cursor object */ +struct tclvar_cursor { + sqlite3_vtab_cursor base; + + Tcl_Obj *pList1; /* Result of [info vars ?pattern?] */ + Tcl_Obj *pList2; /* Result of [array names [lindex $pList1 $i1]] */ + int i1; /* Current item in pList1 */ + int i2; /* Current item (if any) in pList2 */ +}; + +/* Methods for the tclvar module */ +static int tclvarConnect( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr +){ + tclvar_vtab *pVtab; + static const char zSchema[] = + "CREATE TABLE whatever(name TEXT, arrayname TEXT, value TEXT)"; + pVtab = sqlite3MallocZero( sizeof(*pVtab) ); + if( pVtab==0 ) return SQLITE_NOMEM; + *ppVtab = &pVtab->base; + pVtab->interp = (Tcl_Interp *)pAux; + sqlite3_declare_vtab(db, zSchema); + return SQLITE_OK; +} +/* Note that for this virtual table, the xCreate and xConnect +** methods are identical. */ + +static int tclvarDisconnect(sqlite3_vtab *pVtab){ + sqlite3_free(pVtab); + return SQLITE_OK; +} +/* The xDisconnect and xDestroy methods are also the same */ + +/* +** Open a new tclvar cursor. +*/ +static int tclvarOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ + tclvar_cursor *pCur; + pCur = sqlite3MallocZero(sizeof(tclvar_cursor)); + *ppCursor = &pCur->base; + return SQLITE_OK; +} + +/* +** Close a tclvar cursor. +*/ +static int tclvarClose(sqlite3_vtab_cursor *cur){ + tclvar_cursor *pCur = (tclvar_cursor *)cur; + if( pCur->pList1 ){ + Tcl_DecrRefCount(pCur->pList1); + } + if( pCur->pList2 ){ + Tcl_DecrRefCount(pCur->pList2); + } + sqlite3_free(pCur); + return SQLITE_OK; +} + +/* +** Returns 1 if data is ready, or 0 if not. +*/ +static int next2(Tcl_Interp *interp, tclvar_cursor *pCur, Tcl_Obj *pObj){ + Tcl_Obj *p; + + if( pObj ){ + if( !pCur->pList2 ){ + p = Tcl_NewStringObj("array names", -1); + Tcl_IncrRefCount(p); + Tcl_ListObjAppendElement(0, p, pObj); + Tcl_EvalObjEx(interp, p, TCL_EVAL_GLOBAL); + Tcl_DecrRefCount(p); + pCur->pList2 = Tcl_GetObjResult(interp); + Tcl_IncrRefCount(pCur->pList2); + assert( pCur->i2==0 ); + }else{ + int n = 0; + pCur->i2++; + Tcl_ListObjLength(0, pCur->pList2, &n); + if( pCur->i2>=n ){ + Tcl_DecrRefCount(pCur->pList2); + pCur->pList2 = 0; + pCur->i2 = 0; + return 0; + } + } + } + + return 1; +} + +static int tclvarNext(sqlite3_vtab_cursor *cur){ + Tcl_Obj *pObj; + int n = 0; + int ok = 0; + + tclvar_cursor *pCur = (tclvar_cursor *)cur; + Tcl_Interp *interp = ((tclvar_vtab *)(cur->pVtab))->interp; + + Tcl_ListObjLength(0, pCur->pList1, &n); + while( !ok && pCur->i1<n ){ + Tcl_ListObjIndex(0, pCur->pList1, pCur->i1, &pObj); + ok = next2(interp, pCur, pObj); + if( !ok ){ + pCur->i1++; + } + } + + return 0; +} + +static int tclvarFilter( + sqlite3_vtab_cursor *pVtabCursor, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv +){ + tclvar_cursor *pCur = (tclvar_cursor *)pVtabCursor; + Tcl_Interp *interp = ((tclvar_vtab *)(pVtabCursor->pVtab))->interp; + + Tcl_Obj *p = Tcl_NewStringObj("info vars", -1); + Tcl_IncrRefCount(p); + + assert( argc==0 || argc==1 ); + if( argc==1 ){ + Tcl_Obj *pArg = Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1); + Tcl_ListObjAppendElement(0, p, pArg); + } + Tcl_EvalObjEx(interp, p, TCL_EVAL_GLOBAL); + pCur->pList1 = Tcl_GetObjResult(interp); + Tcl_IncrRefCount(pCur->pList1); + assert( pCur->i1==0 && pCur->i2==0 && pCur->pList2==0 ); + + Tcl_DecrRefCount(p); + return tclvarNext(pVtabCursor); +} + +static int tclvarColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ + Tcl_Obj *p1; + Tcl_Obj *p2; + const char *z1; + const char *z2 = ""; + tclvar_cursor *pCur = (tclvar_cursor*)cur; + Tcl_Interp *interp = ((tclvar_vtab *)cur->pVtab)->interp; + + Tcl_ListObjIndex(interp, pCur->pList1, pCur->i1, &p1); + Tcl_ListObjIndex(interp, pCur->pList2, pCur->i2, &p2); + z1 = Tcl_GetString(p1); + if( p2 ){ + z2 = Tcl_GetString(p2); + } + switch (i) { + case 0: { + sqlite3_result_text(ctx, z1, -1, SQLITE_TRANSIENT); + break; + } + case 1: { + sqlite3_result_text(ctx, z2, -1, SQLITE_TRANSIENT); + break; + } + case 2: { + Tcl_Obj *pVal = Tcl_GetVar2Ex(interp, z1, *z2?z2:0, TCL_GLOBAL_ONLY); + sqlite3_result_text(ctx, Tcl_GetString(pVal), -1, SQLITE_TRANSIENT); + break; + } + } + return SQLITE_OK; +} + +static int tclvarRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ + *pRowid = 0; + return SQLITE_OK; +} + +static int tclvarEof(sqlite3_vtab_cursor *cur){ + tclvar_cursor *pCur = (tclvar_cursor*)cur; + return (pCur->pList2?0:1); +} + +static int tclvarBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ + int ii; + + for(ii=0; ii<pIdxInfo->nConstraint; ii++){ + struct sqlite3_index_constraint const *pCons = &pIdxInfo->aConstraint[ii]; + if( pCons->iColumn==0 && pCons->usable + && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){ + struct sqlite3_index_constraint_usage *pUsage; + pUsage = &pIdxInfo->aConstraintUsage[ii]; + pUsage->omit = 0; + pUsage->argvIndex = 1; + return SQLITE_OK; + } + } + + for(ii=0; ii<pIdxInfo->nConstraint; ii++){ + struct sqlite3_index_constraint const *pCons = &pIdxInfo->aConstraint[ii]; + if( pCons->iColumn==0 && pCons->usable + && pCons->op==SQLITE_INDEX_CONSTRAINT_MATCH ){ + struct sqlite3_index_constraint_usage *pUsage; + pUsage = &pIdxInfo->aConstraintUsage[ii]; + pUsage->omit = 1; + pUsage->argvIndex = 1; + return SQLITE_OK; + } + } + + return SQLITE_OK; +} + +/* +** A virtual table module that provides read-only access to a +** Tcl global variable namespace. +*/ +static sqlite3_module tclvarModule = { + 0, /* iVersion */ + tclvarConnect, + tclvarConnect, + tclvarBestIndex, + tclvarDisconnect, + tclvarDisconnect, + tclvarOpen, /* xOpen - open a cursor */ + tclvarClose, /* xClose - close a cursor */ + tclvarFilter, /* xFilter - configure scan constraints */ + tclvarNext, /* xNext - advance a cursor */ + tclvarEof, /* xEof - check for end of scan */ + tclvarColumn, /* xColumn - read data */ + tclvarRowid, /* xRowid - read data */ + 0, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindMethod */ + 0, /* xRename */ +}; + +/* +** Decode a pointer to an sqlite3 object. +*/ +extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb); + +/* +** Register the echo virtual table module. +*/ +static int register_tclvar_module( + ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + sqlite3 *db; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB"); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; +#ifndef SQLITE_OMIT_VIRTUALTABLE + sqlite3_create_module(db, "tclvar", &tclvarModule, (void *)interp); +#endif + return TCL_OK; +} + +#endif + + +/* +** Register commands with the TCL interpreter. +*/ +int Sqlitetesttclvar_Init(Tcl_Interp *interp){ + static struct { + char *zName; + Tcl_ObjCmdProc *xProc; + void *clientData; + } aObjCmd[] = { +#ifndef SQLITE_OMIT_VIRTUALTABLE + { "register_tclvar_module", register_tclvar_module, 0 }, +#endif + }; + int i; + for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ + Tcl_CreateObjCommand(interp, aObjCmd[i].zName, + aObjCmd[i].xProc, aObjCmd[i].clientData, 0); + } + return TCL_OK; +} diff --git a/third_party/sqlite/src/test_thread.c b/third_party/sqlite/src/test_thread.c new file mode 100755 index 0000000..d74470e --- /dev/null +++ b/third_party/sqlite/src/test_thread.c @@ -0,0 +1,332 @@ +/* +** 2007 September 9 +** +** 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 the implementation of some Tcl commands used to +** test that sqlite3 database handles may be concurrently accessed by +** multiple threads. Right now this only works on unix. +** +** $Id: test_thread.c,v 1.6 2007/12/13 21:54:11 drh Exp $ +*/ + +#include "sqliteInt.h" +#include <tcl.h> + +#if SQLITE_THREADSAFE && defined(TCL_THREADS) + +#include <errno.h> +#include <unistd.h> + +/* +** One of these is allocated for each thread created by [sqlthread spawn]. +*/ +typedef struct SqlThread SqlThread; +struct SqlThread { + Tcl_ThreadId parent; /* Thread id of parent thread */ + Tcl_Interp *interp; /* Parent interpreter */ + char *zScript; /* The script to execute. */ + char *zVarname; /* Varname in parent script */ +}; + +/* +** A custom Tcl_Event type used by this module. When the event is +** handled, script zScript is evaluated in interpreter interp. If +** the evaluation throws an exception (returns TCL_ERROR), then the +** error is handled by Tcl_BackgroundError(). If no error occurs, +** the result is simply discarded. +*/ +typedef struct EvalEvent EvalEvent; +struct EvalEvent { + Tcl_Event base; /* Base class of type Tcl_Event */ + char *zScript; /* The script to execute. */ + Tcl_Interp *interp; /* The interpreter to execute it in. */ +}; + +static Tcl_ObjCmdProc sqlthread_proc; +int Sqlitetest1_Init(Tcl_Interp *); + +/* +** Handler for events of type EvalEvent. +*/ +static int tclScriptEvent(Tcl_Event *evPtr, int flags){ + int rc; + EvalEvent *p = (EvalEvent *)evPtr; + rc = Tcl_Eval(p->interp, p->zScript); + if( rc!=TCL_OK ){ + Tcl_BackgroundError(p->interp); + } + return 1; +} + +/* +** Register an EvalEvent to evaluate the script pScript in the +** parent interpreter/thread of SqlThread p. +*/ +static void postToParent(SqlThread *p, Tcl_Obj *pScript){ + EvalEvent *pEvent; + char *zMsg; + int nMsg; + + zMsg = Tcl_GetStringFromObj(pScript, &nMsg); + pEvent = (EvalEvent *)ckalloc(sizeof(EvalEvent)+nMsg+1); + pEvent->base.nextPtr = 0; + pEvent->base.proc = tclScriptEvent; + pEvent->zScript = (char *)&pEvent[1]; + memcpy(pEvent->zScript, zMsg, nMsg+1); + pEvent->interp = p->interp; + + Tcl_ThreadQueueEvent(p->parent, (Tcl_Event *)pEvent, TCL_QUEUE_TAIL); + Tcl_ThreadAlert(p->parent); +} + +/* +** The main function for threads created with [sqlthread spawn]. +*/ +static Tcl_ThreadCreateType tclScriptThread(ClientData pSqlThread){ + Tcl_Interp *interp; + Tcl_Obj *pRes; + Tcl_Obj *pList; + int rc; + + SqlThread *p = (SqlThread *)pSqlThread; + + interp = Tcl_CreateInterp(); + Tcl_CreateObjCommand(interp, "sqlthread", sqlthread_proc, pSqlThread, 0); + Sqlitetest1_Init(interp); + + rc = Tcl_Eval(interp, p->zScript); + pRes = Tcl_GetObjResult(interp); + pList = Tcl_NewObj(); + Tcl_IncrRefCount(pList); + Tcl_IncrRefCount(pRes); + + if( rc!=TCL_OK ){ + Tcl_ListObjAppendElement(interp, pList, Tcl_NewStringObj("error", -1)); + Tcl_ListObjAppendElement(interp, pList, pRes); + postToParent(p, pList); + Tcl_DecrRefCount(pList); + pList = Tcl_NewObj(); + } + + Tcl_ListObjAppendElement(interp, pList, Tcl_NewStringObj("set", -1)); + Tcl_ListObjAppendElement(interp, pList, Tcl_NewStringObj(p->zVarname, -1)); + Tcl_ListObjAppendElement(interp, pList, pRes); + postToParent(p, pList); + + ckfree((void *)p); + Tcl_DecrRefCount(pList); + Tcl_DecrRefCount(pRes); + Tcl_DeleteInterp(interp); + return; +} + +/* +** sqlthread spawn VARNAME SCRIPT +** +** Spawn a new thread with its own Tcl interpreter and run the +** specified SCRIPT(s) in it. The thread terminates after running +** the script. The result of the script is stored in the variable +** VARNAME. +** +** The caller can wait for the script to terminate using [vwait VARNAME]. +*/ +static int sqlthread_spawn( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + Tcl_ThreadId x; + SqlThread *pNew; + int rc; + + int nVarname; char *zVarname; + int nScript; char *zScript; + + /* Parameters for thread creation */ + const int nStack = TCL_THREAD_STACK_DEFAULT; + const int flags = TCL_THREAD_NOFLAGS; + + assert(objc==4); + + zVarname = Tcl_GetStringFromObj(objv[2], &nVarname); + zScript = Tcl_GetStringFromObj(objv[3], &nScript); + + pNew = (SqlThread *)ckalloc(sizeof(SqlThread)+nVarname+nScript+2); + pNew->zVarname = (char *)&pNew[1]; + pNew->zScript = (char *)&pNew->zVarname[nVarname+1]; + memcpy(pNew->zVarname, zVarname, nVarname+1); + memcpy(pNew->zScript, zScript, nScript+1); + pNew->parent = Tcl_GetCurrentThread(); + pNew->interp = interp; + + rc = Tcl_CreateThread(&x, tclScriptThread, (void *)pNew, nStack, flags); + if( rc!=TCL_OK ){ + Tcl_AppendResult(interp, "Error in Tcl_CreateThread()", 0); + sqlite3_free(pNew); + return TCL_ERROR; + } + + return TCL_OK; +} + +/* +** sqlthread parent SCRIPT +** +** This can be called by spawned threads only. It sends the specified +** script back to the parent thread for execution. The result of +** evaluating the SCRIPT is returned. The parent thread must enter +** the event loop for this to work - otherwise the caller will +** block indefinitely. +** +** NOTE: At the moment, this doesn't work. FIXME. +*/ +static int sqlthread_parent( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + EvalEvent *pEvent; + char *zMsg; + int nMsg; + SqlThread *p = (SqlThread *)clientData; + + assert(objc==3); + if( p==0 ){ + Tcl_AppendResult(interp, "no parent thread", 0); + return TCL_ERROR; + } + + zMsg = Tcl_GetStringFromObj(objv[2], &nMsg); + pEvent = (EvalEvent *)ckalloc(sizeof(EvalEvent)+nMsg+1); + pEvent->base.nextPtr = 0; + pEvent->base.proc = tclScriptEvent; + pEvent->zScript = (char *)&pEvent[1]; + memcpy(pEvent->zScript, zMsg, nMsg+1); + pEvent->interp = p->interp; + Tcl_ThreadQueueEvent(p->parent, (Tcl_Event *)pEvent, TCL_QUEUE_TAIL); + Tcl_ThreadAlert(p->parent); + + return TCL_OK; +} + +static int xBusy(void *pArg, int nBusy){ + sqlite3_sleep(50); + return 1; /* Try again... */ +} + +/* +** sqlthread open +** +** Open a database handle and return the string representation of +** the pointer value. +*/ +static int sqlthread_open( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int sqlite3TestMakePointerStr(Tcl_Interp *interp, char *zPtr, void *p); + + const char *zFilename; + sqlite3 *db; + int rc; + char zBuf[100]; + extern void Md5_Register(sqlite3*); + + zFilename = Tcl_GetString(objv[2]); + rc = sqlite3_open(zFilename, &db); + Md5_Register(db); + sqlite3_busy_handler(db, xBusy, 0); + + if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR; + Tcl_AppendResult(interp, zBuf, 0); + + return TCL_OK; +} + + +/* +** sqlthread open +** +** Return the current thread-id (Tcl_GetCurrentThread()) cast to +** an integer. +*/ +static int sqlthread_id( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + Tcl_ThreadId id = Tcl_GetCurrentThread(); + Tcl_SetObjResult(interp, Tcl_NewIntObj((int)id)); + return TCL_OK; +} + + +/* +** Dispatch routine for the sub-commands of [sqlthread]. +*/ +static int sqlthread_proc( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + struct SubCommand { + char *zName; + Tcl_ObjCmdProc *xProc; + int nArg; + char *zUsage; + } aSub[] = { + {"parent", sqlthread_parent, 1, "SCRIPT"}, + {"spawn", sqlthread_spawn, 2, "VARNAME SCRIPT"}, + {"open", sqlthread_open, 1, "DBNAME"}, + {"id", sqlthread_id, 0, ""}, + {0, 0, 0} + }; + struct SubCommand *pSub; + int rc; + int iIndex; + + if( objc<2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND"); + return TCL_ERROR; + } + + rc = Tcl_GetIndexFromObjStruct( + interp, objv[1], aSub, sizeof(aSub[0]), "sub-command", 0, &iIndex + ); + if( rc!=TCL_OK ) return rc; + pSub = &aSub[iIndex]; + + if( objc!=(pSub->nArg+2) ){ + Tcl_WrongNumArgs(interp, 2, objv, pSub->zUsage); + return TCL_ERROR; + } + + return pSub->xProc(clientData, interp, objc, objv); +} + +/* +** Register commands with the TCL interpreter. +*/ +int SqlitetestThread_Init(Tcl_Interp *interp){ + Tcl_CreateObjCommand(interp, "sqlthread", sqlthread_proc, 0, 0); + return TCL_OK; +} +#else +int SqlitetestThread_Init(Tcl_Interp *interp){ + return TCL_OK; +} +#endif diff --git a/third_party/sqlite/src/tokenize.c b/third_party/sqlite/src/tokenize.c new file mode 100755 index 0000000..bea8d5e --- /dev/null +++ b/third_party/sqlite/src/tokenize.c @@ -0,0 +1,508 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** An tokenizer for SQL +** +** This file contains C code that splits an SQL input string up into +** individual tokens and sends those tokens one-by-one over to the +** parser for analysis. +** +** $Id: tokenize.c,v 1.148 2008/07/28 19:34:54 drh Exp $ +*/ +#include "sqliteInt.h" +#include <ctype.h> +#include <stdlib.h> + +/* +** The charMap() macro maps alphabetic characters into their +** lower-case ASCII equivalent. On ASCII machines, this is just +** an upper-to-lower case map. On EBCDIC machines we also need +** to adjust the encoding. Only alphabetic characters and underscores +** need to be translated. +*/ +#ifdef SQLITE_ASCII +# define charMap(X) sqlite3UpperToLower[(unsigned char)X] +#endif +#ifdef SQLITE_EBCDIC +# define charMap(X) ebcdicToAscii[(unsigned char)X] +const unsigned char ebcdicToAscii[] = { +/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 0, 0, /* 6x */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */ + 0, 97, 98, 99,100,101,102,103,104,105, 0, 0, 0, 0, 0, 0, /* 8x */ + 0,106,107,108,109,110,111,112,113,114, 0, 0, 0, 0, 0, 0, /* 9x */ + 0, 0,115,116,117,118,119,120,121,122, 0, 0, 0, 0, 0, 0, /* Ax */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */ + 0, 97, 98, 99,100,101,102,103,104,105, 0, 0, 0, 0, 0, 0, /* Cx */ + 0,106,107,108,109,110,111,112,113,114, 0, 0, 0, 0, 0, 0, /* Dx */ + 0, 0,115,116,117,118,119,120,121,122, 0, 0, 0, 0, 0, 0, /* Ex */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Fx */ +}; +#endif + +/* +** The sqlite3KeywordCode function looks up an identifier to determine if +** it is a keyword. If it is a keyword, the token code of that keyword is +** returned. If the input is not a keyword, TK_ID is returned. +** +** The implementation of this routine was generated by a program, +** mkkeywordhash.h, located in the tool subdirectory of the distribution. +** The output of the mkkeywordhash.c program is written into a file +** named keywordhash.h and then included into this source file by +** the #include below. +*/ +#include "keywordhash.h" + + +/* +** If X is a character that can be used in an identifier then +** IdChar(X) will be true. Otherwise it is false. +** +** For ASCII, any character with the high-order bit set is +** allowed in an identifier. For 7-bit characters, +** sqlite3IsIdChar[X] must be 1. +** +** For EBCDIC, the rules are more complex but have the same +** end result. +** +** Ticket #1066. the SQL standard does not allow '$' in the +** middle of identfiers. But many SQL implementations do. +** SQLite will allow '$' in identifiers for compatibility. +** But the feature is undocumented. +*/ +#ifdef SQLITE_ASCII +const char sqlite3IsAsciiIdChar[] = { +/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */ +}; +#define IdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && sqlite3IsAsciiIdChar[c-0x20])) +#endif +#ifdef SQLITE_EBCDIC +const char sqlite3IsEbcdicIdChar[] = { +/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 4x */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, /* 5x */ + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, /* 6x */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, /* 7x */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, /* 8x */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, /* 9x */ + 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, /* Ax */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Cx */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Dx */ + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Ex */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, /* Fx */ +}; +#define IdChar(C) (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40])) +#endif + + +/* +** Return the length of the token that begins at z[0]. +** Store the token type in *tokenType before returning. +*/ +int sqlite3GetToken(const unsigned char *z, int *tokenType){ + int i, c; + switch( *z ){ + case ' ': case '\t': case '\n': case '\f': case '\r': { + for(i=1; isspace(z[i]); i++){} + *tokenType = TK_SPACE; + return i; + } + case '-': { + if( z[1]=='-' ){ + for(i=2; (c=z[i])!=0 && c!='\n'; i++){} + *tokenType = TK_COMMENT; + return i; + } + *tokenType = TK_MINUS; + return 1; + } + case '(': { + *tokenType = TK_LP; + return 1; + } + case ')': { + *tokenType = TK_RP; + return 1; + } + case ';': { + *tokenType = TK_SEMI; + return 1; + } + case '+': { + *tokenType = TK_PLUS; + return 1; + } + case '*': { + *tokenType = TK_STAR; + return 1; + } + case '/': { + if( z[1]!='*' || z[2]==0 ){ + *tokenType = TK_SLASH; + return 1; + } + for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){} + if( c ) i++; + *tokenType = TK_COMMENT; + return i; + } + case '%': { + *tokenType = TK_REM; + return 1; + } + case '=': { + *tokenType = TK_EQ; + return 1 + (z[1]=='='); + } + case '<': { + if( (c=z[1])=='=' ){ + *tokenType = TK_LE; + return 2; + }else if( c=='>' ){ + *tokenType = TK_NE; + return 2; + }else if( c=='<' ){ + *tokenType = TK_LSHIFT; + return 2; + }else{ + *tokenType = TK_LT; + return 1; + } + } + case '>': { + if( (c=z[1])=='=' ){ + *tokenType = TK_GE; + return 2; + }else if( c=='>' ){ + *tokenType = TK_RSHIFT; + return 2; + }else{ + *tokenType = TK_GT; + return 1; + } + } + case '!': { + if( z[1]!='=' ){ + *tokenType = TK_ILLEGAL; + return 2; + }else{ + *tokenType = TK_NE; + return 2; + } + } + case '|': { + if( z[1]!='|' ){ + *tokenType = TK_BITOR; + return 1; + }else{ + *tokenType = TK_CONCAT; + return 2; + } + } + case ',': { + *tokenType = TK_COMMA; + return 1; + } + case '&': { + *tokenType = TK_BITAND; + return 1; + } + case '~': { + *tokenType = TK_BITNOT; + return 1; + } + case '`': + case '\'': + case '"': { + int delim = z[0]; + for(i=1; (c=z[i])!=0; i++){ + if( c==delim ){ + if( z[i+1]==delim ){ + i++; + }else{ + break; + } + } + } + if( c ){ + *tokenType = TK_STRING; + return i+1; + }else{ + *tokenType = TK_ILLEGAL; + return i; + } + } + case '.': { +#ifndef SQLITE_OMIT_FLOATING_POINT + if( !isdigit(z[1]) ) +#endif + { + *tokenType = TK_DOT; + return 1; + } + /* If the next character is a digit, this is a floating point + ** number that begins with ".". Fall thru into the next case */ + } + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': { + *tokenType = TK_INTEGER; + for(i=0; isdigit(z[i]); i++){} +#ifndef SQLITE_OMIT_FLOATING_POINT + if( z[i]=='.' ){ + i++; + while( isdigit(z[i]) ){ i++; } + *tokenType = TK_FLOAT; + } + if( (z[i]=='e' || z[i]=='E') && + ( isdigit(z[i+1]) + || ((z[i+1]=='+' || z[i+1]=='-') && isdigit(z[i+2])) + ) + ){ + i += 2; + while( isdigit(z[i]) ){ i++; } + *tokenType = TK_FLOAT; + } +#endif + while( IdChar(z[i]) ){ + *tokenType = TK_ILLEGAL; + i++; + } + return i; + } + case '[': { + for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){} + *tokenType = c==']' ? TK_ID : TK_ILLEGAL; + return i; + } + case '?': { + *tokenType = TK_VARIABLE; + for(i=1; isdigit(z[i]); i++){} + return i; + } + case '#': { + for(i=1; isdigit(z[i]); i++){} + if( i>1 ){ + /* Parameters of the form #NNN (where NNN is a number) are used + ** internally by sqlite3NestedParse. */ + *tokenType = TK_REGISTER; + return i; + } + /* Fall through into the next case if the '#' is not followed by + ** a digit. Try to match #AAAA where AAAA is a parameter name. */ + } +#ifndef SQLITE_OMIT_TCL_VARIABLE + case '$': +#endif + case '@': /* For compatibility with MS SQL Server */ + case ':': { + int n = 0; + *tokenType = TK_VARIABLE; + for(i=1; (c=z[i])!=0; i++){ + if( IdChar(c) ){ + n++; +#ifndef SQLITE_OMIT_TCL_VARIABLE + }else if( c=='(' && n>0 ){ + do{ + i++; + }while( (c=z[i])!=0 && !isspace(c) && c!=')' ); + if( c==')' ){ + i++; + }else{ + *tokenType = TK_ILLEGAL; + } + break; + }else if( c==':' && z[i+1]==':' ){ + i++; +#endif + }else{ + break; + } + } + if( n==0 ) *tokenType = TK_ILLEGAL; + return i; + } +#ifndef SQLITE_OMIT_BLOB_LITERAL + case 'x': case 'X': { + if( z[1]=='\'' ){ + *tokenType = TK_BLOB; + for(i=2; (c=z[i])!=0 && c!='\''; i++){ + if( !isxdigit(c) ){ + *tokenType = TK_ILLEGAL; + } + } + if( i%2 || !c ) *tokenType = TK_ILLEGAL; + if( c ) i++; + return i; + } + /* Otherwise fall through to the next case */ + } +#endif + default: { + if( !IdChar(*z) ){ + break; + } + for(i=1; IdChar(z[i]); i++){} + *tokenType = keywordCode((char*)z, i); + return i; + } + } + *tokenType = TK_ILLEGAL; + return 1; +} + +/* +** Run the parser on the given SQL string. The parser structure is +** passed in. An SQLITE_ status code is returned. If an error occurs +** then an and attempt is made to write an error message into +** memory obtained from sqlite3_malloc() and to make *pzErrMsg point to that +** error message. +*/ +int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ + int nErr = 0; + int i; + void *pEngine; + int tokenType; + int lastTokenParsed = -1; + sqlite3 *db = pParse->db; + int mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; + + if( db->activeVdbeCnt==0 ){ + db->u1.isInterrupted = 0; + } + pParse->rc = SQLITE_OK; + pParse->zTail = pParse->zSql = zSql; + i = 0; + assert( pzErrMsg!=0 ); + pEngine = sqlite3ParserAlloc((void*(*)(size_t))sqlite3Malloc); + if( pEngine==0 ){ + db->mallocFailed = 1; + return SQLITE_NOMEM; + } + assert( pParse->sLastToken.dyn==0 ); + assert( pParse->pNewTable==0 ); + assert( pParse->pNewTrigger==0 ); + assert( pParse->nVar==0 ); + assert( pParse->nVarExpr==0 ); + assert( pParse->nVarExprAlloc==0 ); + assert( pParse->apVarExpr==0 ); + while( !db->mallocFailed && zSql[i]!=0 ){ + assert( i>=0 ); + pParse->sLastToken.z = (u8*)&zSql[i]; + assert( pParse->sLastToken.dyn==0 ); + pParse->sLastToken.n = sqlite3GetToken((unsigned char*)&zSql[i],&tokenType); + i += pParse->sLastToken.n; + if( i>mxSqlLen ){ + pParse->rc = SQLITE_TOOBIG; + break; + } + switch( tokenType ){ + case TK_SPACE: + case TK_COMMENT: { + if( db->u1.isInterrupted ){ + pParse->rc = SQLITE_INTERRUPT; + sqlite3SetString(pzErrMsg, db, "interrupt"); + goto abort_parse; + } + break; + } + case TK_ILLEGAL: { + sqlite3DbFree(db, *pzErrMsg); + *pzErrMsg = sqlite3MPrintf(db, "unrecognized token: \"%T\"", + &pParse->sLastToken); + nErr++; + goto abort_parse; + } + case TK_SEMI: { + pParse->zTail = &zSql[i]; + /* Fall thru into the default case */ + } + default: { + sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse); + lastTokenParsed = tokenType; + if( pParse->rc!=SQLITE_OK ){ + goto abort_parse; + } + break; + } + } + } +abort_parse: + if( zSql[i]==0 && nErr==0 && pParse->rc==SQLITE_OK ){ + if( lastTokenParsed!=TK_SEMI ){ + sqlite3Parser(pEngine, TK_SEMI, pParse->sLastToken, pParse); + pParse->zTail = &zSql[i]; + } + sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse); + } +#ifdef YYTRACKMAXSTACKDEPTH + sqlite3StatusSet(SQLITE_STATUS_PARSER_STACK, + sqlite3ParserStackPeak(pEngine) + ); +#endif /* YYDEBUG */ + sqlite3ParserFree(pEngine, sqlite3_free); + if( db->mallocFailed ){ + pParse->rc = SQLITE_NOMEM; + } + if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){ + sqlite3SetString(&pParse->zErrMsg, db, "%s", sqlite3ErrStr(pParse->rc)); + } + if( pParse->zErrMsg ){ + if( *pzErrMsg==0 ){ + *pzErrMsg = pParse->zErrMsg; + }else{ + sqlite3DbFree(db, pParse->zErrMsg); + } + pParse->zErrMsg = 0; + nErr++; + } + if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){ + sqlite3VdbeDelete(pParse->pVdbe); + pParse->pVdbe = 0; + } +#ifndef SQLITE_OMIT_SHARED_CACHE + if( pParse->nested==0 ){ + sqlite3DbFree(db, pParse->aTableLock); + pParse->aTableLock = 0; + pParse->nTableLock = 0; + } +#endif +#ifndef SQLITE_OMIT_VIRTUALTABLE + sqlite3DbFree(db, pParse->apVtabLock); +#endif + + if( !IN_DECLARE_VTAB ){ + /* If the pParse->declareVtab flag is set, do not delete any table + ** structure built up in pParse->pNewTable. The calling code (see vtab.c) + ** will take responsibility for freeing the Table structure. + */ + sqlite3DeleteTable(pParse->pNewTable); + } + + sqlite3DeleteTrigger(db, pParse->pNewTrigger); + sqlite3DbFree(db, pParse->apVarExpr); + if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){ + pParse->rc = SQLITE_ERROR; + } + return nErr; +} diff --git a/third_party/sqlite/src/trigger.c b/third_party/sqlite/src/trigger.c new file mode 100755 index 0000000..760c708 --- /dev/null +++ b/third_party/sqlite/src/trigger.c @@ -0,0 +1,853 @@ +/* +** +** 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. +** +************************************************************************* +** +** +** $Id: trigger.c,v 1.128 2008/07/28 19:34:54 drh Exp $ +*/ +#include "sqliteInt.h" + +#ifndef SQLITE_OMIT_TRIGGER +/* +** Delete a linked list of TriggerStep structures. +*/ +void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerStep){ + while( pTriggerStep ){ + TriggerStep * pTmp = pTriggerStep; + pTriggerStep = pTriggerStep->pNext; + + if( pTmp->target.dyn ) sqlite3DbFree(db, (char*)pTmp->target.z); + sqlite3ExprDelete(db, pTmp->pWhere); + sqlite3ExprListDelete(db, pTmp->pExprList); + sqlite3SelectDelete(db, pTmp->pSelect); + sqlite3IdListDelete(db, pTmp->pIdList); + + sqlite3DbFree(db, pTmp); + } +} + +/* +** This is called by the parser when it sees a CREATE TRIGGER statement +** up to the point of the BEGIN before the trigger actions. A Trigger +** structure is generated based on the information available and stored +** in pParse->pNewTrigger. After the trigger actions have been parsed, the +** sqlite3FinishTrigger() function is called to complete the trigger +** construction process. +*/ +void sqlite3BeginTrigger( + Parse *pParse, /* The parse context of the CREATE TRIGGER statement */ + Token *pName1, /* The name of the trigger */ + Token *pName2, /* The name of the trigger */ + int tr_tm, /* One of TK_BEFORE, TK_AFTER, TK_INSTEAD */ + int op, /* One of TK_INSERT, TK_UPDATE, TK_DELETE */ + IdList *pColumns, /* column list if this is an UPDATE OF trigger */ + SrcList *pTableName,/* The name of the table/view the trigger applies to */ + Expr *pWhen, /* WHEN clause */ + int isTemp, /* True if the TEMPORARY keyword is present */ + int noErr /* Suppress errors if the trigger already exists */ +){ + Trigger *pTrigger = 0; + Table *pTab; + char *zName = 0; /* Name of the trigger */ + sqlite3 *db = pParse->db; + int iDb; /* The database to store the trigger in */ + Token *pName; /* The unqualified db name */ + DbFixer sFix; + int iTabDb; + + assert( pName1!=0 ); /* pName1->z might be NULL, but not pName1 itself */ + assert( pName2!=0 ); + if( isTemp ){ + /* If TEMP was specified, then the trigger name may not be qualified. */ + if( pName2->n>0 ){ + sqlite3ErrorMsg(pParse, "temporary trigger may not have qualified name"); + goto trigger_cleanup; + } + iDb = 1; + pName = pName1; + }else{ + /* Figure out the db that the the trigger will be created in */ + iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); + if( iDb<0 ){ + goto trigger_cleanup; + } + } + + /* If the trigger name was unqualified, and the table is a temp table, + ** then set iDb to 1 to create the trigger in the temporary database. + ** If sqlite3SrcListLookup() returns 0, indicating the table does not + ** exist, the error is caught by the block below. + */ + if( !pTableName || db->mallocFailed ){ + goto trigger_cleanup; + } + pTab = sqlite3SrcListLookup(pParse, pTableName); + if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){ + iDb = 1; + } + + /* Ensure the table name matches database name and that the table exists */ + if( db->mallocFailed ) goto trigger_cleanup; + assert( pTableName->nSrc==1 ); + if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) && + sqlite3FixSrcList(&sFix, pTableName) ){ + goto trigger_cleanup; + } + pTab = sqlite3SrcListLookup(pParse, pTableName); + if( !pTab ){ + /* The table does not exist. */ + goto trigger_cleanup; + } + if( IsVirtual(pTab) ){ + sqlite3ErrorMsg(pParse, "cannot create triggers on virtual tables"); + goto trigger_cleanup; + } + + /* Check that the trigger name is not reserved and that no trigger of the + ** specified name exists */ + zName = sqlite3NameFromToken(db, pName); + if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ + goto trigger_cleanup; + } + if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash), zName,strlen(zName)) ){ + if( !noErr ){ + sqlite3ErrorMsg(pParse, "trigger %T already exists", pName); + } + goto trigger_cleanup; + } + + /* Do not create a trigger on a system table */ + if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){ + sqlite3ErrorMsg(pParse, "cannot create trigger on system table"); + pParse->nErr++; + goto trigger_cleanup; + } + + /* INSTEAD of triggers are only for views and views only support INSTEAD + ** of triggers. + */ + if( pTab->pSelect && tr_tm!=TK_INSTEAD ){ + sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S", + (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0); + goto trigger_cleanup; + } + if( !pTab->pSelect && tr_tm==TK_INSTEAD ){ + sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF" + " trigger on table: %S", pTableName, 0); + goto trigger_cleanup; + } + iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); + +#ifndef SQLITE_OMIT_AUTHORIZATION + { + int code = SQLITE_CREATE_TRIGGER; + const char *zDb = db->aDb[iTabDb].zName; + const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb; + if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER; + if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){ + goto trigger_cleanup; + } + if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iTabDb),0,zDb)){ + goto trigger_cleanup; + } + } +#endif + + /* INSTEAD OF triggers can only appear on views and BEFORE triggers + ** cannot appear on views. So we might as well translate every + ** INSTEAD OF trigger into a BEFORE trigger. It simplifies code + ** elsewhere. + */ + if (tr_tm == TK_INSTEAD){ + tr_tm = TK_BEFORE; + } + + /* Build the Trigger object */ + pTrigger = (Trigger*)sqlite3DbMallocZero(db, sizeof(Trigger)); + if( pTrigger==0 ) goto trigger_cleanup; + pTrigger->name = zName; + zName = 0; + pTrigger->table = sqlite3DbStrDup(db, pTableName->a[0].zName); + pTrigger->pSchema = db->aDb[iDb].pSchema; + pTrigger->pTabSchema = pTab->pSchema; + pTrigger->op = op; + pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER; + pTrigger->pWhen = sqlite3ExprDup(db, pWhen); + pTrigger->pColumns = sqlite3IdListDup(db, pColumns); + sqlite3TokenCopy(db, &pTrigger->nameToken,pName); + assert( pParse->pNewTrigger==0 ); + pParse->pNewTrigger = pTrigger; + +trigger_cleanup: + sqlite3DbFree(db, zName); + sqlite3SrcListDelete(db, pTableName); + sqlite3IdListDelete(db, pColumns); + sqlite3ExprDelete(db, pWhen); + if( !pParse->pNewTrigger ){ + sqlite3DeleteTrigger(db, pTrigger); + }else{ + assert( pParse->pNewTrigger==pTrigger ); + } +} + +/* +** This routine is called after all of the trigger actions have been parsed +** in order to complete the process of building the trigger. +*/ +void sqlite3FinishTrigger( + Parse *pParse, /* Parser context */ + TriggerStep *pStepList, /* The triggered program */ + Token *pAll /* Token that describes the complete CREATE TRIGGER */ +){ + Trigger *pTrig = 0; /* The trigger whose construction is finishing up */ + sqlite3 *db = pParse->db; /* The database */ + DbFixer sFix; + int iDb; /* Database containing the trigger */ + + pTrig = pParse->pNewTrigger; + pParse->pNewTrigger = 0; + if( pParse->nErr || !pTrig ) goto triggerfinish_cleanup; + iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); + pTrig->step_list = pStepList; + while( pStepList ){ + pStepList->pTrig = pTrig; + pStepList = pStepList->pNext; + } + if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &pTrig->nameToken) + && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){ + goto triggerfinish_cleanup; + } + + /* if we are not initializing, and this trigger is not on a TEMP table, + ** build the sqlite_master entry + */ + if( !db->init.busy ){ + Vdbe *v; + char *z; + + /* Make an entry in the sqlite_master table */ + v = sqlite3GetVdbe(pParse); + if( v==0 ) goto triggerfinish_cleanup; + sqlite3BeginWriteOperation(pParse, 0, iDb); + z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n); + sqlite3NestedParse(pParse, + "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')", + db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pTrig->name, + pTrig->table, z); + sqlite3DbFree(db, z); + sqlite3ChangeCookie(pParse, iDb); + sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, sqlite3MPrintf( + db, "type='trigger' AND name='%q'", pTrig->name), P4_DYNAMIC + ); + } + + if( db->init.busy ){ + int n; + Table *pTab; + Trigger *pDel; + pDel = sqlite3HashInsert(&db->aDb[iDb].pSchema->trigHash, + pTrig->name, strlen(pTrig->name), pTrig); + if( pDel ){ + assert( pDel==pTrig ); + db->mallocFailed = 1; + goto triggerfinish_cleanup; + } + n = strlen(pTrig->table) + 1; + pTab = sqlite3HashFind(&pTrig->pTabSchema->tblHash, pTrig->table, n); + assert( pTab!=0 ); + pTrig->pNext = pTab->pTrigger; + pTab->pTrigger = pTrig; + pTrig = 0; + } + +triggerfinish_cleanup: + sqlite3DeleteTrigger(db, pTrig); + assert( !pParse->pNewTrigger ); + sqlite3DeleteTriggerStep(db, pStepList); +} + +/* +** Make a copy of all components of the given trigger step. This has +** the effect of copying all Expr.token.z values into memory obtained +** from sqlite3_malloc(). As initially created, the Expr.token.z values +** all point to the input string that was fed to the parser. But that +** string is ephemeral - it will go away as soon as the sqlite3_exec() +** call that started the parser exits. This routine makes a persistent +** copy of all the Expr.token.z strings so that the TriggerStep structure +** will be valid even after the sqlite3_exec() call returns. +*/ +static void sqlitePersistTriggerStep(sqlite3 *db, TriggerStep *p){ + if( p->target.z ){ + p->target.z = (u8*)sqlite3DbStrNDup(db, (char*)p->target.z, p->target.n); + p->target.dyn = 1; + } + if( p->pSelect ){ + Select *pNew = sqlite3SelectDup(db, p->pSelect); + sqlite3SelectDelete(db, p->pSelect); + p->pSelect = pNew; + } + if( p->pWhere ){ + Expr *pNew = sqlite3ExprDup(db, p->pWhere); + sqlite3ExprDelete(db, p->pWhere); + p->pWhere = pNew; + } + if( p->pExprList ){ + ExprList *pNew = sqlite3ExprListDup(db, p->pExprList); + sqlite3ExprListDelete(db, p->pExprList); + p->pExprList = pNew; + } + if( p->pIdList ){ + IdList *pNew = sqlite3IdListDup(db, p->pIdList); + sqlite3IdListDelete(db, p->pIdList); + p->pIdList = pNew; + } +} + +/* +** Turn a SELECT statement (that the pSelect parameter points to) into +** a trigger step. Return a pointer to a TriggerStep structure. +** +** The parser calls this routine when it finds a SELECT statement in +** body of a TRIGGER. +*/ +TriggerStep *sqlite3TriggerSelectStep(sqlite3 *db, Select *pSelect){ + TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep)); + if( pTriggerStep==0 ) { + sqlite3SelectDelete(db, pSelect); + return 0; + } + + pTriggerStep->op = TK_SELECT; + pTriggerStep->pSelect = pSelect; + pTriggerStep->orconf = OE_Default; + sqlitePersistTriggerStep(db, pTriggerStep); + + return pTriggerStep; +} + +/* +** Build a trigger step out of an INSERT statement. Return a pointer +** to the new trigger step. +** +** The parser calls this routine when it sees an INSERT inside the +** body of a trigger. +*/ +TriggerStep *sqlite3TriggerInsertStep( + sqlite3 *db, /* The database connection */ + Token *pTableName, /* Name of the table into which we insert */ + IdList *pColumn, /* List of columns in pTableName to insert into */ + ExprList *pEList, /* The VALUE clause: a list of values to be inserted */ + Select *pSelect, /* A SELECT statement that supplies values */ + int orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ +){ + TriggerStep *pTriggerStep; + + assert(pEList == 0 || pSelect == 0); + assert(pEList != 0 || pSelect != 0 || db->mallocFailed); + + pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep)); + if( pTriggerStep ){ + pTriggerStep->op = TK_INSERT; + pTriggerStep->pSelect = pSelect; + pTriggerStep->target = *pTableName; + pTriggerStep->pIdList = pColumn; + pTriggerStep->pExprList = pEList; + pTriggerStep->orconf = orconf; + sqlitePersistTriggerStep(db, pTriggerStep); + }else{ + sqlite3IdListDelete(db, pColumn); + sqlite3ExprListDelete(db, pEList); + sqlite3SelectDelete(db, pSelect); + } + + return pTriggerStep; +} + +/* +** Construct a trigger step that implements an UPDATE statement and return +** a pointer to that trigger step. The parser calls this routine when it +** sees an UPDATE statement inside the body of a CREATE TRIGGER. +*/ +TriggerStep *sqlite3TriggerUpdateStep( + sqlite3 *db, /* The database connection */ + Token *pTableName, /* Name of the table to be updated */ + ExprList *pEList, /* The SET clause: list of column and new values */ + Expr *pWhere, /* The WHERE clause */ + int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */ +){ + TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep)); + if( pTriggerStep==0 ){ + sqlite3ExprListDelete(db, pEList); + sqlite3ExprDelete(db, pWhere); + return 0; + } + + pTriggerStep->op = TK_UPDATE; + pTriggerStep->target = *pTableName; + pTriggerStep->pExprList = pEList; + pTriggerStep->pWhere = pWhere; + pTriggerStep->orconf = orconf; + sqlitePersistTriggerStep(db, pTriggerStep); + + return pTriggerStep; +} + +/* +** Construct a trigger step that implements a DELETE statement and return +** a pointer to that trigger step. The parser calls this routine when it +** sees a DELETE statement inside the body of a CREATE TRIGGER. +*/ +TriggerStep *sqlite3TriggerDeleteStep( + sqlite3 *db, /* Database connection */ + Token *pTableName, /* The table from which rows are deleted */ + Expr *pWhere /* The WHERE clause */ +){ + TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep)); + if( pTriggerStep==0 ){ + sqlite3ExprDelete(db, pWhere); + return 0; + } + + pTriggerStep->op = TK_DELETE; + pTriggerStep->target = *pTableName; + pTriggerStep->pWhere = pWhere; + pTriggerStep->orconf = OE_Default; + sqlitePersistTriggerStep(db, pTriggerStep); + + return pTriggerStep; +} + +/* +** Recursively delete a Trigger structure +*/ +void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){ + if( pTrigger==0 ) return; + sqlite3DeleteTriggerStep(db, pTrigger->step_list); + sqlite3DbFree(db, pTrigger->name); + sqlite3DbFree(db, pTrigger->table); + sqlite3ExprDelete(db, pTrigger->pWhen); + sqlite3IdListDelete(db, pTrigger->pColumns); + if( pTrigger->nameToken.dyn ) sqlite3DbFree(db, (char*)pTrigger->nameToken.z); + sqlite3DbFree(db, pTrigger); +} + +/* +** This function is called to drop a trigger from the database schema. +** +** This may be called directly from the parser and therefore identifies +** the trigger by name. The sqlite3DropTriggerPtr() routine does the +** same job as this routine except it takes a pointer to the trigger +** instead of the trigger name. +**/ +void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){ + Trigger *pTrigger = 0; + int i; + const char *zDb; + const char *zName; + int nName; + sqlite3 *db = pParse->db; + + if( db->mallocFailed ) goto drop_trigger_cleanup; + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ + goto drop_trigger_cleanup; + } + + assert( pName->nSrc==1 ); + zDb = pName->a[0].zDatabase; + zName = pName->a[0].zName; + nName = strlen(zName); + for(i=OMIT_TEMPDB; i<db->nDb; i++){ + int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ + if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue; + pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName, nName); + if( pTrigger ) break; + } + if( !pTrigger ){ + if( !noErr ){ + sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0); + } + goto drop_trigger_cleanup; + } + sqlite3DropTriggerPtr(pParse, pTrigger); + +drop_trigger_cleanup: + sqlite3SrcListDelete(db, pName); +} + +/* +** Return a pointer to the Table structure for the table that a trigger +** is set on. +*/ +static Table *tableOfTrigger(Trigger *pTrigger){ + int n = strlen(pTrigger->table) + 1; + return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table, n); +} + + +/* +** Drop a trigger given a pointer to that trigger. +*/ +void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ + Table *pTable; + Vdbe *v; + sqlite3 *db = pParse->db; + int iDb; + + iDb = sqlite3SchemaToIndex(pParse->db, pTrigger->pSchema); + assert( iDb>=0 && iDb<db->nDb ); + pTable = tableOfTrigger(pTrigger); + assert( pTable ); + assert( pTable->pSchema==pTrigger->pSchema || iDb==1 ); +#ifndef SQLITE_OMIT_AUTHORIZATION + { + int code = SQLITE_DROP_TRIGGER; + const char *zDb = db->aDb[iDb].zName; + const char *zTab = SCHEMA_TABLE(iDb); + if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER; + if( sqlite3AuthCheck(pParse, code, pTrigger->name, pTable->zName, zDb) || + sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ + return; + } + } +#endif + + /* Generate code to destroy the database record of the trigger. + */ + assert( pTable!=0 ); + if( (v = sqlite3GetVdbe(pParse))!=0 ){ + int base; + static const VdbeOpList dropTrigger[] = { + { OP_Rewind, 0, ADDR(9), 0}, + { OP_String8, 0, 1, 0}, /* 1 */ + { OP_Column, 0, 1, 2}, + { OP_Ne, 2, ADDR(8), 1}, + { OP_String8, 0, 1, 0}, /* 4: "trigger" */ + { OP_Column, 0, 0, 2}, + { OP_Ne, 2, ADDR(8), 1}, + { OP_Delete, 0, 0, 0}, + { OP_Next, 0, ADDR(1), 0}, /* 8 */ + }; + + sqlite3BeginWriteOperation(pParse, 0, iDb); + sqlite3OpenMasterTable(pParse, iDb); + base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger); + sqlite3VdbeChangeP4(v, base+1, pTrigger->name, 0); + sqlite3VdbeChangeP4(v, base+4, "trigger", P4_STATIC); + sqlite3ChangeCookie(pParse, iDb); + sqlite3VdbeAddOp2(v, OP_Close, 0, 0); + sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->name, 0); + } +} + +/* +** Remove a trigger from the hash tables of the sqlite* pointer. +*/ +void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){ + Trigger *pTrigger; + int nName = strlen(zName); + pTrigger = sqlite3HashInsert(&(db->aDb[iDb].pSchema->trigHash), + zName, nName, 0); + if( pTrigger ){ + Table *pTable = tableOfTrigger(pTrigger); + assert( pTable!=0 ); + if( pTable->pTrigger == pTrigger ){ + pTable->pTrigger = pTrigger->pNext; + }else{ + Trigger *cc = pTable->pTrigger; + while( cc ){ + if( cc->pNext == pTrigger ){ + cc->pNext = cc->pNext->pNext; + break; + } + cc = cc->pNext; + } + assert(cc); + } + sqlite3DeleteTrigger(db, pTrigger); + db->flags |= SQLITE_InternChanges; + } +} + +/* +** pEList is the SET clause of an UPDATE statement. Each entry +** in pEList is of the format <id>=<expr>. If any of the entries +** in pEList have an <id> which matches an identifier in pIdList, +** then return TRUE. If pIdList==NULL, then it is considered a +** wildcard that matches anything. Likewise if pEList==NULL then +** it matches anything so always return true. Return false only +** if there is no match. +*/ +static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){ + int e; + if( !pIdList || !pEList ) return 1; + for(e=0; e<pEList->nExpr; e++){ + if( sqlite3IdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1; + } + return 0; +} + +/* +** Return a bit vector to indicate what kind of triggers exist for operation +** "op" on table pTab. If pChanges is not NULL then it is a list of columns +** that are being updated. Triggers only match if the ON clause of the +** trigger definition overlaps the set of columns being updated. +** +** The returned bit vector is some combination of TRIGGER_BEFORE and +** TRIGGER_AFTER. +*/ +int sqlite3TriggersExist( + Parse *pParse, /* Used to check for recursive triggers */ + Table *pTab, /* The table the contains the triggers */ + int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */ + ExprList *pChanges /* Columns that change in an UPDATE statement */ +){ + Trigger *pTrigger; + int mask = 0; + + pTrigger = IsVirtual(pTab) ? 0 : pTab->pTrigger; + while( pTrigger ){ + if( pTrigger->op==op && checkColumnOverLap(pTrigger->pColumns, pChanges) ){ + mask |= pTrigger->tr_tm; + } + pTrigger = pTrigger->pNext; + } + return mask; +} + +/* +** Convert the pStep->target token into a SrcList and return a pointer +** to that SrcList. +** +** This routine adds a specific database name, if needed, to the target when +** forming the SrcList. This prevents a trigger in one database from +** referring to a target in another database. An exception is when the +** trigger is in TEMP in which case it can refer to any other database it +** wants. +*/ +static SrcList *targetSrcList( + Parse *pParse, /* The parsing context */ + TriggerStep *pStep /* The trigger containing the target token */ +){ + Token sDb; /* Dummy database name token */ + int iDb; /* Index of the database to use */ + SrcList *pSrc; /* SrcList to be returned */ + + iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema); + if( iDb==0 || iDb>=2 ){ + assert( iDb<pParse->db->nDb ); + sDb.z = (u8*)pParse->db->aDb[iDb].zName; + sDb.n = strlen((char*)sDb.z); + pSrc = sqlite3SrcListAppend(pParse->db, 0, &sDb, &pStep->target); + } else { + pSrc = sqlite3SrcListAppend(pParse->db, 0, &pStep->target, 0); + } + return pSrc; +} + +/* +** Generate VDBE code for zero or more statements inside the body of a +** trigger. +*/ +static int codeTriggerProgram( + Parse *pParse, /* The parser context */ + TriggerStep *pStepList, /* List of statements inside the trigger body */ + int orconfin /* Conflict algorithm. (OE_Abort, etc) */ +){ + TriggerStep * pTriggerStep = pStepList; + int orconf; + Vdbe *v = pParse->pVdbe; + sqlite3 *db = pParse->db; + + assert( pTriggerStep!=0 ); + assert( v!=0 ); + sqlite3VdbeAddOp2(v, OP_ContextPush, 0, 0); + VdbeComment((v, "begin trigger %s", pStepList->pTrig->name)); + while( pTriggerStep ){ + orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin; + pParse->trigStack->orconf = orconf; + switch( pTriggerStep->op ){ + case TK_SELECT: { + Select *ss = sqlite3SelectDup(db, pTriggerStep->pSelect); + if( ss ){ + SelectDest dest; + + sqlite3SelectDestInit(&dest, SRT_Discard, 0); + sqlite3SelectResolve(pParse, ss, 0); + sqlite3Select(pParse, ss, &dest, 0, 0, 0); + sqlite3SelectDelete(db, ss); + } + break; + } + case TK_UPDATE: { + SrcList *pSrc; + pSrc = targetSrcList(pParse, pTriggerStep); + sqlite3VdbeAddOp2(v, OP_ResetCount, 0, 0); + sqlite3Update(pParse, pSrc, + sqlite3ExprListDup(db, pTriggerStep->pExprList), + sqlite3ExprDup(db, pTriggerStep->pWhere), orconf); + sqlite3VdbeAddOp2(v, OP_ResetCount, 1, 0); + break; + } + case TK_INSERT: { + SrcList *pSrc; + pSrc = targetSrcList(pParse, pTriggerStep); + sqlite3VdbeAddOp2(v, OP_ResetCount, 0, 0); + sqlite3Insert(pParse, pSrc, + sqlite3ExprListDup(db, pTriggerStep->pExprList), + sqlite3SelectDup(db, pTriggerStep->pSelect), + sqlite3IdListDup(db, pTriggerStep->pIdList), orconf); + sqlite3VdbeAddOp2(v, OP_ResetCount, 1, 0); + break; + } + case TK_DELETE: { + SrcList *pSrc; + sqlite3VdbeAddOp2(v, OP_ResetCount, 0, 0); + pSrc = targetSrcList(pParse, pTriggerStep); + sqlite3DeleteFrom(pParse, pSrc, + sqlite3ExprDup(db, pTriggerStep->pWhere)); + sqlite3VdbeAddOp2(v, OP_ResetCount, 1, 0); + break; + } + default: + assert(0); + } + pTriggerStep = pTriggerStep->pNext; + } + sqlite3VdbeAddOp2(v, OP_ContextPop, 0, 0); + VdbeComment((v, "end trigger %s", pStepList->pTrig->name)); + + return 0; +} + +/* +** This is called to code FOR EACH ROW triggers. +** +** When the code that this function generates is executed, the following +** must be true: +** +** 1. No cursors may be open in the main database. (But newIdx and oldIdx +** can be indices of cursors in temporary tables. See below.) +** +** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then +** a temporary vdbe cursor (index newIdx) must be open and pointing at +** a row containing values to be substituted for new.* expressions in the +** trigger program(s). +** +** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then +** a temporary vdbe cursor (index oldIdx) must be open and pointing at +** a row containing values to be substituted for old.* expressions in the +** trigger program(s). +** +** If they are not NULL, the piOldColMask and piNewColMask output variables +** are set to values that describe the columns used by the trigger program +** in the OLD.* and NEW.* tables respectively. If column N of the +** pseudo-table is read at least once, the corresponding bit of the output +** mask is set. If a column with an index greater than 32 is read, the +** output mask is set to the special value 0xffffffff. +** +*/ +int sqlite3CodeRowTrigger( + Parse *pParse, /* Parse context */ + int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */ + ExprList *pChanges, /* Changes list for any UPDATE OF triggers */ + int tr_tm, /* One of TRIGGER_BEFORE, TRIGGER_AFTER */ + Table *pTab, /* The table to code triggers from */ + int newIdx, /* The indice of the "new" row to access */ + int oldIdx, /* The indice of the "old" row to access */ + int orconf, /* ON CONFLICT policy */ + int ignoreJump, /* Instruction to jump to for RAISE(IGNORE) */ + u32 *piOldColMask, /* OUT: Mask of columns used from the OLD.* table */ + u32 *piNewColMask /* OUT: Mask of columns used from the NEW.* table */ +){ + Trigger *p; + sqlite3 *db = pParse->db; + TriggerStack trigStackEntry; + + trigStackEntry.oldColMask = 0; + trigStackEntry.newColMask = 0; + + assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE); + assert(tr_tm == TRIGGER_BEFORE || tr_tm == TRIGGER_AFTER ); + + assert(newIdx != -1 || oldIdx != -1); + + for(p=pTab->pTrigger; p; p=p->pNext){ + int fire_this = 0; + + /* Determine whether we should code this trigger */ + if( + p->op==op && + p->tr_tm==tr_tm && + (p->pSchema==p->pTabSchema || p->pSchema==db->aDb[1].pSchema) && + (op!=TK_UPDATE||!p->pColumns||checkColumnOverLap(p->pColumns,pChanges)) + ){ + TriggerStack *pS; /* Pointer to trigger-stack entry */ + for(pS=pParse->trigStack; pS && p!=pS->pTrigger; pS=pS->pNext){} + if( !pS ){ + fire_this = 1; + } +#if 0 /* Give no warning for recursive triggers. Just do not do them */ + else{ + sqlite3ErrorMsg(pParse, "recursive triggers not supported (%s)", + p->name); + return SQLITE_ERROR; + } +#endif + } + + if( fire_this ){ + int endTrigger; + Expr * whenExpr; + AuthContext sContext; + NameContext sNC; + +#ifndef SQLITE_OMIT_TRACE + sqlite3VdbeAddOp4(pParse->pVdbe, OP_Trace, 0, 0, 0, + sqlite3MPrintf(db, "-- TRIGGER %s", p->name), + P4_DYNAMIC); +#endif + memset(&sNC, 0, sizeof(sNC)); + sNC.pParse = pParse; + + /* Push an entry on to the trigger stack */ + trigStackEntry.pTrigger = p; + trigStackEntry.newIdx = newIdx; + trigStackEntry.oldIdx = oldIdx; + trigStackEntry.pTab = pTab; + trigStackEntry.pNext = pParse->trigStack; + trigStackEntry.ignoreJump = ignoreJump; + pParse->trigStack = &trigStackEntry; + sqlite3AuthContextPush(pParse, &sContext, p->name); + + /* code the WHEN clause */ + endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe); + whenExpr = sqlite3ExprDup(db, p->pWhen); + if( db->mallocFailed || sqlite3ExprResolveNames(&sNC, whenExpr) ){ + pParse->trigStack = trigStackEntry.pNext; + sqlite3ExprDelete(db, whenExpr); + return 1; + } + sqlite3ExprIfFalse(pParse, whenExpr, endTrigger, SQLITE_JUMPIFNULL); + sqlite3ExprDelete(db, whenExpr); + + codeTriggerProgram(pParse, p->step_list, orconf); + + /* Pop the entry off the trigger stack */ + pParse->trigStack = trigStackEntry.pNext; + sqlite3AuthContextPop(&sContext); + + sqlite3VdbeResolveLabel(pParse->pVdbe, endTrigger); + } + } + if( piOldColMask ) *piOldColMask |= trigStackEntry.oldColMask; + if( piNewColMask ) *piNewColMask |= trigStackEntry.newColMask; + return 0; +} +#endif /* !defined(SQLITE_OMIT_TRIGGER) */ diff --git a/third_party/sqlite/src/update.c b/third_party/sqlite/src/update.c new file mode 100755 index 0000000..7647d4a --- /dev/null +++ b/third_party/sqlite/src/update.c @@ -0,0 +1,678 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains C code routines that are called by the parser +** to handle UPDATE statements. +** +** $Id: update.c,v 1.181 2008/07/28 19:34:54 drh Exp $ +*/ +#include "sqliteInt.h" + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* Forward declaration */ +static void updateVirtualTable( + Parse *pParse, /* The parsing context */ + SrcList *pSrc, /* The virtual table to be modified */ + Table *pTab, /* The virtual table */ + ExprList *pChanges, /* The columns to change in the UPDATE statement */ + Expr *pRowidExpr, /* Expression used to recompute the rowid */ + int *aXRef, /* Mapping from columns of pTab to entries in pChanges */ + Expr *pWhere /* WHERE clause of the UPDATE statement */ +); +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +/* +** The most recently coded instruction was an OP_Column to retrieve the +** i-th column of table pTab. This routine sets the P4 parameter of the +** OP_Column to the default value, if any. +** +** The default value of a column is specified by a DEFAULT clause in the +** column definition. This was either supplied by the user when the table +** was created, or added later to the table definition by an ALTER TABLE +** command. If the latter, then the row-records in the table btree on disk +** may not contain a value for the column and the default value, taken +** from the P4 parameter of the OP_Column instruction, is returned instead. +** If the former, then all row-records are guaranteed to include a value +** for the column and the P4 value is not required. +** +** Column definitions created by an ALTER TABLE command may only have +** literal default values specified: a number, null or a string. (If a more +** complicated default expression value was provided, it is evaluated +** when the ALTER TABLE is executed and one of the literal values written +** into the sqlite_master table.) +** +** Therefore, the P4 parameter is only required if the default value for +** the column is a literal number, string or null. The sqlite3ValueFromExpr() +** function is capable of transforming these types of expressions into +** sqlite3_value objects. +*/ +void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i){ + if( pTab && !pTab->pSelect ){ + sqlite3_value *pValue; + u8 enc = ENC(sqlite3VdbeDb(v)); + Column *pCol = &pTab->aCol[i]; + VdbeComment((v, "%s.%s", pTab->zName, pCol->zName)); + assert( i<pTab->nCol ); + sqlite3ValueFromExpr(sqlite3VdbeDb(v), pCol->pDflt, enc, + pCol->affinity, &pValue); + if( pValue ){ + sqlite3VdbeChangeP4(v, -1, (const char *)pValue, P4_MEM); + } + } +} + +/* +** Process an UPDATE statement. +** +** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL; +** \_______/ \________/ \______/ \________________/ +* onError pTabList pChanges pWhere +*/ +void sqlite3Update( + Parse *pParse, /* The parser context */ + SrcList *pTabList, /* The table in which we should change things */ + ExprList *pChanges, /* Things to be changed */ + Expr *pWhere, /* The WHERE clause. May be null */ + int onError /* How to handle constraint errors */ +){ + int i, j; /* Loop counters */ + Table *pTab; /* The table to be updated */ + int addr = 0; /* VDBE instruction address of the start of the loop */ + WhereInfo *pWInfo; /* Information about the WHERE clause */ + Vdbe *v; /* The virtual database engine */ + Index *pIdx; /* For looping over indices */ + int nIdx; /* Number of indices that need updating */ + int iCur; /* VDBE Cursor number of pTab */ + sqlite3 *db; /* The database structure */ + int *aRegIdx = 0; /* One register assigned to each index to be updated */ + int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the + ** an expression for the i-th column of the table. + ** aXRef[i]==-1 if the i-th column is not changed. */ + int chngRowid; /* True if the record number is being changed */ + Expr *pRowidExpr = 0; /* Expression defining the new record number */ + int openAll = 0; /* True if all indices need to be opened */ + AuthContext sContext; /* The authorization context */ + NameContext sNC; /* The name-context to resolve expressions in */ + int iDb; /* Database containing the table being updated */ + int j1; /* Addresses of jump instructions */ + int okOnePass; /* True for one-pass algorithm without the FIFO */ + +#ifndef SQLITE_OMIT_TRIGGER + int isView; /* Trying to update a view */ + int triggers_exist = 0; /* True if any row triggers exist */ +#endif + int iBeginAfterTrigger; /* Address of after trigger program */ + int iEndAfterTrigger; /* Exit of after trigger program */ + int iBeginBeforeTrigger; /* Address of before trigger program */ + int iEndBeforeTrigger; /* Exit of before trigger program */ + u32 old_col_mask = 0; /* Mask of OLD.* columns in use */ + u32 new_col_mask = 0; /* Mask of NEW.* columns in use */ + + int newIdx = -1; /* index of trigger "new" temp table */ + int oldIdx = -1; /* index of trigger "old" temp table */ + + /* Register Allocations */ + int regRowCount = 0; /* A count of rows changed */ + int regOldRowid; /* The old rowid */ + int regNewRowid; /* The new rowid */ + int regData; /* New data for the row */ + + sContext.pParse = 0; + db = pParse->db; + if( pParse->nErr || db->mallocFailed ){ + goto update_cleanup; + } + assert( pTabList->nSrc==1 ); + + /* Locate the table which we want to update. + */ + pTab = sqlite3SrcListLookup(pParse, pTabList); + if( pTab==0 ) goto update_cleanup; + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + + /* Figure out if we have any triggers and if the table being + ** updated is a view + */ +#ifndef SQLITE_OMIT_TRIGGER + triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges); + isView = pTab->pSelect!=0; +#else +# define triggers_exist 0 +# define isView 0 +#endif +#ifdef SQLITE_OMIT_VIEW +# undef isView +# define isView 0 +#endif + + if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){ + goto update_cleanup; + } + if( sqlite3ViewGetColumnNames(pParse, pTab) ){ + goto update_cleanup; + } + aXRef = sqlite3DbMallocRaw(db, sizeof(int) * pTab->nCol ); + if( aXRef==0 ) goto update_cleanup; + for(i=0; i<pTab->nCol; i++) aXRef[i] = -1; + + /* If there are FOR EACH ROW triggers, allocate cursors for the + ** special OLD and NEW tables + */ + if( triggers_exist ){ + newIdx = pParse->nTab++; + oldIdx = pParse->nTab++; + } + + /* Allocate a cursors for the main database table and for all indices. + ** The index cursors might not be used, but if they are used they + ** need to occur right after the database cursor. So go ahead and + ** allocate enough space, just in case. + */ + pTabList->a[0].iCursor = iCur = pParse->nTab++; + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + pParse->nTab++; + } + + /* Initialize the name-context */ + memset(&sNC, 0, sizeof(sNC)); + sNC.pParse = pParse; + sNC.pSrcList = pTabList; + + /* Resolve the column names in all the expressions of the + ** of the UPDATE statement. Also find the column index + ** for each column to be updated in the pChanges array. For each + ** column to be updated, make sure we have authorization to change + ** that column. + */ + chngRowid = 0; + for(i=0; i<pChanges->nExpr; i++){ + if( sqlite3ExprResolveNames(&sNC, pChanges->a[i].pExpr) ){ + goto update_cleanup; + } + for(j=0; j<pTab->nCol; j++){ + if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){ + if( j==pTab->iPKey ){ + chngRowid = 1; + pRowidExpr = pChanges->a[i].pExpr; + } + aXRef[j] = i; + break; + } + } + if( j>=pTab->nCol ){ + if( sqlite3IsRowid(pChanges->a[i].zName) ){ + chngRowid = 1; + pRowidExpr = pChanges->a[i].pExpr; + }else{ + sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName); + goto update_cleanup; + } + } +#ifndef SQLITE_OMIT_AUTHORIZATION + { + int rc; + rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName, + pTab->aCol[j].zName, db->aDb[iDb].zName); + if( rc==SQLITE_DENY ){ + goto update_cleanup; + }else if( rc==SQLITE_IGNORE ){ + aXRef[j] = -1; + } + } +#endif + } + + /* Allocate memory for the array aRegIdx[]. There is one entry in the + ** array for each index associated with table being updated. Fill in + ** the value with a register number for indices that are to be used + ** and with zero for unused indices. + */ + for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){} + if( nIdx>0 ){ + aRegIdx = sqlite3DbMallocRaw(db, sizeof(Index*) * nIdx ); + if( aRegIdx==0 ) goto update_cleanup; + } + for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ + int reg; + if( chngRowid ){ + reg = ++pParse->nMem; + }else{ + reg = 0; + for(i=0; i<pIdx->nColumn; i++){ + if( aXRef[pIdx->aiColumn[i]]>=0 ){ + reg = ++pParse->nMem; + break; + } + } + } + aRegIdx[j] = reg; + } + + /* Allocate a block of register used to store the change record + ** sent to sqlite3GenerateConstraintChecks(). There are either + ** one or two registers for holding the rowid. One rowid register + ** is used if chngRowid is false and two are used if chngRowid is + ** true. Following these are pTab->nCol register holding column + ** data. + */ + regOldRowid = regNewRowid = pParse->nMem + 1; + pParse->nMem += pTab->nCol + 1; + if( chngRowid ){ + regNewRowid++; + pParse->nMem++; + } + regData = regNewRowid+1; + + + /* Begin generating code. + */ + v = sqlite3GetVdbe(pParse); + if( v==0 ) goto update_cleanup; + if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); + sqlite3BeginWriteOperation(pParse, 1, iDb); + +#ifndef SQLITE_OMIT_VIRTUALTABLE + /* Virtual tables must be handled separately */ + if( IsVirtual(pTab) ){ + updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef, + pWhere); + pWhere = 0; + pTabList = 0; + goto update_cleanup; + } +#endif + + /* Start the view context + */ + if( isView ){ + sqlite3AuthContextPush(pParse, &sContext, pTab->zName); + } + + /* Generate the code for triggers. + */ + if( triggers_exist ){ + int iGoto; + + /* Create pseudo-tables for NEW and OLD + */ + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol); + sqlite3VdbeAddOp2(v, OP_OpenPseudo, oldIdx, 0); + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol); + sqlite3VdbeAddOp2(v, OP_OpenPseudo, newIdx, 0); + + iGoto = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); + addr = sqlite3VdbeMakeLabel(v); + iBeginBeforeTrigger = sqlite3VdbeCurrentAddr(v); + if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TRIGGER_BEFORE, pTab, + newIdx, oldIdx, onError, addr, &old_col_mask, &new_col_mask) ){ + goto update_cleanup; + } + iEndBeforeTrigger = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); + iBeginAfterTrigger = sqlite3VdbeCurrentAddr(v); + if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TRIGGER_AFTER, pTab, + newIdx, oldIdx, onError, addr, &old_col_mask, &new_col_mask) ){ + goto update_cleanup; + } + iEndAfterTrigger = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); + sqlite3VdbeJumpHere(v, iGoto); + } + + /* If we are trying to update a view, realize that view into + ** a ephemeral table. + */ + if( isView ){ + sqlite3MaterializeView(pParse, pTab->pSelect, pWhere, iCur); + } + + /* Resolve the column names in all the expressions in the + ** WHERE clause. + */ + if( sqlite3ExprResolveNames(&sNC, pWhere) ){ + goto update_cleanup; + } + + /* Begin the database scan + */ + sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, + WHERE_ONEPASS_DESIRED); + if( pWInfo==0 ) goto update_cleanup; + okOnePass = pWInfo->okOnePass; + + /* Remember the rowid of every item to be updated. + */ + sqlite3VdbeAddOp2(v, IsVirtual(pTab)?OP_VRowid:OP_Rowid, iCur, regOldRowid); + if( !okOnePass ) sqlite3VdbeAddOp2(v, OP_FifoWrite, regOldRowid, 0); + + /* End the database scan loop. + */ + sqlite3WhereEnd(pWInfo); + + /* Initialize the count of updated rows + */ + if( db->flags & SQLITE_CountRows && !pParse->trigStack ){ + regRowCount = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); + } + + if( !isView && !IsVirtual(pTab) ){ + /* + ** Open every index that needs updating. Note that if any + ** index could potentially invoke a REPLACE conflict resolution + ** action, then we need to open all indices because we might need + ** to be deleting some records. + */ + if( !okOnePass ) sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite); + if( onError==OE_Replace ){ + openAll = 1; + }else{ + openAll = 0; + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + if( pIdx->onError==OE_Replace ){ + openAll = 1; + break; + } + } + } + for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ + if( openAll || aRegIdx[i]>0 ){ + KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); + sqlite3VdbeAddOp4(v, OP_OpenWrite, iCur+i+1, pIdx->tnum, iDb, + (char*)pKey, P4_KEYINFO_HANDOFF); + assert( pParse->nTab>iCur+i+1 ); + } + } + } + + /* Jump back to this point if a trigger encounters an IGNORE constraint. */ + if( triggers_exist ){ + sqlite3VdbeResolveLabel(v, addr); + } + + /* Top of the update loop */ + if( okOnePass ){ + int a1 = sqlite3VdbeAddOp1(v, OP_NotNull, regOldRowid); + addr = sqlite3VdbeAddOp0(v, OP_Goto); + sqlite3VdbeJumpHere(v, a1); + }else{ + addr = sqlite3VdbeAddOp2(v, OP_FifoRead, regOldRowid, 0); + } + + if( triggers_exist ){ + int regRowid; + int regRow; + int regCols; + + /* Make cursor iCur point to the record that is being updated. + */ + sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid); + + /* Generate the OLD table + */ + regRowid = sqlite3GetTempReg(pParse); + regRow = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regRowid); + if( !old_col_mask ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, regRow); + }else{ + sqlite3VdbeAddOp2(v, OP_RowData, iCur, regRow); + } + sqlite3VdbeAddOp3(v, OP_Insert, oldIdx, regRow, regRowid); + + /* Generate the NEW table + */ + if( chngRowid ){ + sqlite3ExprCodeAndCache(pParse, pRowidExpr, regRowid); + }else{ + sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regRowid); + } + regCols = sqlite3GetTempRange(pParse, pTab->nCol); + for(i=0; i<pTab->nCol; i++){ + if( i==pTab->iPKey ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, regCols+i); + continue; + } + j = aXRef[i]; + if( new_col_mask&((u32)1<<i) || new_col_mask==0xffffffff ){ + if( j<0 ){ + sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regCols+i); + sqlite3ColumnDefault(v, pTab, i); + }else{ + sqlite3ExprCodeAndCache(pParse, pChanges->a[j].pExpr, regCols+i); + } + }else{ + sqlite3VdbeAddOp2(v, OP_Null, 0, regCols+i); + } + } + sqlite3VdbeAddOp3(v, OP_MakeRecord, regCols, pTab->nCol, regRow); + if( !isView ){ + sqlite3TableAffinityStr(v, pTab); + sqlite3ExprCacheAffinityChange(pParse, regCols, pTab->nCol); + } + sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol); + /* if( pParse->nErr ) goto update_cleanup; */ + sqlite3VdbeAddOp3(v, OP_Insert, newIdx, regRow, regRowid); + sqlite3ReleaseTempReg(pParse, regRowid); + sqlite3ReleaseTempReg(pParse, regRow); + + sqlite3VdbeAddOp2(v, OP_Goto, 0, iBeginBeforeTrigger); + sqlite3VdbeJumpHere(v, iEndBeforeTrigger); + } + + if( !isView && !IsVirtual(pTab) ){ + /* Loop over every record that needs updating. We have to load + ** the old data for each record to be updated because some columns + ** might not change and we will need to copy the old value. + ** Also, the old data is needed to delete the old index entries. + ** So make the cursor point at the old record. + */ + sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid); + + /* If the record number will change, push the record number as it + ** will be after the update. (The old record number is currently + ** on top of the stack.) + */ + if( chngRowid ){ + sqlite3ExprCode(pParse, pRowidExpr, regNewRowid); + sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid); + } + + /* Compute new data for this record. + */ + for(i=0; i<pTab->nCol; i++){ + if( i==pTab->iPKey ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, regData+i); + continue; + } + j = aXRef[i]; + if( j<0 ){ + sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regData+i); + sqlite3ColumnDefault(v, pTab, i); + }else{ + sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regData+i); + } + } + + /* Do constraint checks + */ + sqlite3GenerateConstraintChecks(pParse, pTab, iCur, regNewRowid, + aRegIdx, chngRowid, 1, + onError, addr); + + /* Delete the old indices for the current record. + */ + j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regOldRowid); + sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, aRegIdx); + + /* If changing the record number, delete the old record. + */ + if( chngRowid ){ + sqlite3VdbeAddOp2(v, OP_Delete, iCur, 0); + } + sqlite3VdbeJumpHere(v, j1); + + /* Create the new index entries and the new record. + */ + sqlite3CompleteInsertion(pParse, pTab, iCur, regNewRowid, + aRegIdx, chngRowid, 1, -1, 0); + } + + /* Increment the row counter + */ + if( db->flags & SQLITE_CountRows && !pParse->trigStack){ + sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); + } + + /* If there are triggers, close all the cursors after each iteration + ** through the loop. The fire the after triggers. + */ + if( triggers_exist ){ + sqlite3VdbeAddOp2(v, OP_Goto, 0, iBeginAfterTrigger); + sqlite3VdbeJumpHere(v, iEndAfterTrigger); + } + + /* Repeat the above with the next record to be updated, until + ** all record selected by the WHERE clause have been updated. + */ + sqlite3VdbeAddOp2(v, OP_Goto, 0, addr); + sqlite3VdbeJumpHere(v, addr); + + /* Close all tables */ + for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ + if( openAll || aRegIdx[i]>0 ){ + sqlite3VdbeAddOp2(v, OP_Close, iCur+i+1, 0); + } + } + sqlite3VdbeAddOp2(v, OP_Close, iCur, 0); + if( triggers_exist ){ + sqlite3VdbeAddOp2(v, OP_Close, newIdx, 0); + sqlite3VdbeAddOp2(v, OP_Close, oldIdx, 0); + } + + /* + ** Return the number of rows that were changed. If this routine is + ** generating code because of a call to sqlite3NestedParse(), do not + ** invoke the callback function. + */ + if( db->flags & SQLITE_CountRows && !pParse->trigStack && pParse->nested==0 ){ + sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", P4_STATIC); + } + +update_cleanup: + sqlite3AuthContextPop(&sContext); + sqlite3DbFree(db, aRegIdx); + sqlite3DbFree(db, aXRef); + sqlite3SrcListDelete(db, pTabList); + sqlite3ExprListDelete(db, pChanges); + sqlite3ExprDelete(db, pWhere); + return; +} + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* +** Generate code for an UPDATE of a virtual table. +** +** The strategy is that we create an ephemerial table that contains +** for each row to be changed: +** +** (A) The original rowid of that row. +** (B) The revised rowid for the row. (note1) +** (C) The content of every column in the row. +** +** Then we loop over this ephemeral table and for each row in +** the ephermeral table call VUpdate. +** +** When finished, drop the ephemeral table. +** +** (note1) Actually, if we know in advance that (A) is always the same +** as (B) we only store (A), then duplicate (A) when pulling +** it out of the ephemeral table before calling VUpdate. +*/ +static void updateVirtualTable( + Parse *pParse, /* The parsing context */ + SrcList *pSrc, /* The virtual table to be modified */ + Table *pTab, /* The virtual table */ + ExprList *pChanges, /* The columns to change in the UPDATE statement */ + Expr *pRowid, /* Expression used to recompute the rowid */ + int *aXRef, /* Mapping from columns of pTab to entries in pChanges */ + Expr *pWhere /* WHERE clause of the UPDATE statement */ +){ + Vdbe *v = pParse->pVdbe; /* Virtual machine under construction */ + ExprList *pEList = 0; /* The result set of the SELECT statement */ + Select *pSelect = 0; /* The SELECT statement */ + Expr *pExpr; /* Temporary expression */ + int ephemTab; /* Table holding the result of the SELECT */ + int i; /* Loop counter */ + int addr; /* Address of top of loop */ + int iReg; /* First register in set passed to OP_VUpdate */ + sqlite3 *db = pParse->db; /* Database connection */ + const char *pVtab = (const char*)pTab->pVtab; + SelectDest dest; + + /* Construct the SELECT statement that will find the new values for + ** all updated rows. + */ + pEList = sqlite3ExprListAppend(pParse, 0, + sqlite3CreateIdExpr(pParse, "_rowid_"), 0); + if( pRowid ){ + pEList = sqlite3ExprListAppend(pParse, pEList, + sqlite3ExprDup(db, pRowid), 0); + } + assert( pTab->iPKey<0 ); + for(i=0; i<pTab->nCol; i++){ + if( aXRef[i]>=0 ){ + pExpr = sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr); + }else{ + pExpr = sqlite3CreateIdExpr(pParse, pTab->aCol[i].zName); + } + pEList = sqlite3ExprListAppend(pParse, pEList, pExpr, 0); + } + pSelect = sqlite3SelectNew(pParse, pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0); + + /* Create the ephemeral table into which the update results will + ** be stored. + */ + assert( v ); + ephemTab = pParse->nTab++; + sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, pTab->nCol+1+(pRowid!=0)); + + /* fill the ephemeral table + */ + sqlite3SelectDestInit(&dest, SRT_Table, ephemTab); + sqlite3Select(pParse, pSelect, &dest, 0, 0, 0); + + /* Generate code to scan the ephemeral table and call VUpdate. */ + iReg = ++pParse->nMem; + pParse->nMem += pTab->nCol+1; + sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0); + addr = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp3(v, OP_Column, ephemTab, 0, iReg); + sqlite3VdbeAddOp3(v, OP_Column, ephemTab, (pRowid?1:0), iReg+1); + for(i=0; i<pTab->nCol; i++){ + sqlite3VdbeAddOp3(v, OP_Column, ephemTab, i+1+(pRowid!=0), iReg+2+i); + } + sqlite3VtabMakeWritable(pParse, pTab); + sqlite3VdbeAddOp4(v, OP_VUpdate, 0, pTab->nCol+2, iReg, pVtab, P4_VTAB); + sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr); + sqlite3VdbeJumpHere(v, addr-1); + sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0); + + /* Cleanup */ + sqlite3SelectDelete(db, pSelect); +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +/* Make sure "isView" gets undefined in case this file becomes part of +** the amalgamation - so that subsequent files do not see isView as a +** macro. */ +#undef isView diff --git a/third_party/sqlite/src/utf.c b/third_party/sqlite/src/utf.c new file mode 100755 index 0000000..8711a4c --- /dev/null +++ b/third_party/sqlite/src/utf.c @@ -0,0 +1,530 @@ +/* +** 2004 April 13 +** +** 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 routines used to translate between UTF-8, +** UTF-16, UTF-16BE, and UTF-16LE. +** +** $Id: utf.c,v 1.63 2008/07/29 11:25:14 danielk1977 Exp $ +** +** Notes on UTF-8: +** +** Byte-0 Byte-1 Byte-2 Byte-3 Value +** 0xxxxxxx 00000000 00000000 0xxxxxxx +** 110yyyyy 10xxxxxx 00000000 00000yyy yyxxxxxx +** 1110zzzz 10yyyyyy 10xxxxxx 00000000 zzzzyyyy yyxxxxxx +** 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx 000uuuuu zzzzyyyy yyxxxxxx +** +** +** Notes on UTF-16: (with wwww+1==uuuuu) +** +** Word-0 Word-1 Value +** 110110ww wwzzzzyy 110111yy yyxxxxxx 000uuuuu zzzzyyyy yyxxxxxx +** zzzzyyyy yyxxxxxx 00000000 zzzzyyyy yyxxxxxx +** +** +** BOM or Byte Order Mark: +** 0xff 0xfe little-endian utf-16 follows +** 0xfe 0xff big-endian utf-16 follows +** +*/ +#include "sqliteInt.h" +#include <assert.h> +#include "vdbeInt.h" + +/* +** The following constant value is used by the SQLITE_BIGENDIAN and +** SQLITE_LITTLEENDIAN macros. +*/ +const int sqlite3one = 1; + +/* +** This lookup table is used to help decode the first byte of +** a multi-byte UTF8 character. +*/ +static const unsigned char sqlite3UtfTrans1[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00, +}; + + +#define WRITE_UTF8(zOut, c) { \ + if( c<0x00080 ){ \ + *zOut++ = (c&0xFF); \ + } \ + else if( c<0x00800 ){ \ + *zOut++ = 0xC0 + ((c>>6)&0x1F); \ + *zOut++ = 0x80 + (c & 0x3F); \ + } \ + else if( c<0x10000 ){ \ + *zOut++ = 0xE0 + ((c>>12)&0x0F); \ + *zOut++ = 0x80 + ((c>>6) & 0x3F); \ + *zOut++ = 0x80 + (c & 0x3F); \ + }else{ \ + *zOut++ = 0xF0 + ((c>>18) & 0x07); \ + *zOut++ = 0x80 + ((c>>12) & 0x3F); \ + *zOut++ = 0x80 + ((c>>6) & 0x3F); \ + *zOut++ = 0x80 + (c & 0x3F); \ + } \ +} + +#define WRITE_UTF16LE(zOut, c) { \ + if( c<=0xFFFF ){ \ + *zOut++ = (c&0x00FF); \ + *zOut++ = ((c>>8)&0x00FF); \ + }else{ \ + *zOut++ = (((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0)); \ + *zOut++ = (0x00D8 + (((c-0x10000)>>18)&0x03)); \ + *zOut++ = (c&0x00FF); \ + *zOut++ = (0x00DC + ((c>>8)&0x03)); \ + } \ +} + +#define WRITE_UTF16BE(zOut, c) { \ + if( c<=0xFFFF ){ \ + *zOut++ = ((c>>8)&0x00FF); \ + *zOut++ = (c&0x00FF); \ + }else{ \ + *zOut++ = (0x00D8 + (((c-0x10000)>>18)&0x03)); \ + *zOut++ = (((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0)); \ + *zOut++ = (0x00DC + ((c>>8)&0x03)); \ + *zOut++ = (c&0x00FF); \ + } \ +} + +#define READ_UTF16LE(zIn, c){ \ + c = (*zIn++); \ + c += ((*zIn++)<<8); \ + if( c>=0xD800 && c<0xE000 ){ \ + int c2 = (*zIn++); \ + c2 += ((*zIn++)<<8); \ + c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \ + if( (c & 0xFFFF0000)==0 ) c = 0xFFFD; \ + } \ +} + +#define READ_UTF16BE(zIn, c){ \ + c = ((*zIn++)<<8); \ + c += (*zIn++); \ + if( c>=0xD800 && c<0xE000 ){ \ + int c2 = ((*zIn++)<<8); \ + c2 += (*zIn++); \ + c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \ + if( (c & 0xFFFF0000)==0 ) c = 0xFFFD; \ + } \ +} + +/* +** Translate a single UTF-8 character. Return the unicode value. +** +** During translation, assume that the byte that zTerm points +** is a 0x00. +** +** Write a pointer to the next unread byte back into *pzNext. +** +** Notes On Invalid UTF-8: +** +** * This routine never allows a 7-bit character (0x00 through 0x7f) to +** be encoded as a multi-byte character. Any multi-byte character that +** attempts to encode a value between 0x00 and 0x7f is rendered as 0xfffd. +** +** * This routine never allows a UTF16 surrogate value to be encoded. +** If a multi-byte character attempts to encode a value between +** 0xd800 and 0xe000 then it is rendered as 0xfffd. +** +** * Bytes in the range of 0x80 through 0xbf which occur as the first +** byte of a character are interpreted as single-byte characters +** and rendered as themselves even though they are technically +** invalid characters. +** +** * This routine accepts an infinite number of different UTF8 encodings +** for unicode values 0x80 and greater. It do not change over-length +** encodings to 0xfffd as some systems recommend. +*/ +#define READ_UTF8(zIn, zTerm, c) \ + c = *(zIn++); \ + if( c>=0xc0 ){ \ + c = sqlite3UtfTrans1[c-0xc0]; \ + while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \ + c = (c<<6) + (0x3f & *(zIn++)); \ + } \ + if( c<0x80 \ + || (c&0xFFFFF800)==0xD800 \ + || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \ + } +int sqlite3Utf8Read( + const unsigned char *z, /* First byte of UTF-8 character */ + const unsigned char *zTerm, /* Pretend this byte is 0x00 */ + const unsigned char **pzNext /* Write first byte past UTF-8 char here */ +){ + int c; + READ_UTF8(z, zTerm, c); + *pzNext = z; + return c; +} + + + + +/* +** If the TRANSLATE_TRACE macro is defined, the value of each Mem is +** printed on stderr on the way into and out of sqlite3VdbeMemTranslate(). +*/ +/* #define TRANSLATE_TRACE 1 */ + +#ifndef SQLITE_OMIT_UTF16 +/* +** This routine transforms the internal text encoding used by pMem to +** desiredEnc. It is an error if the string is already of the desired +** encoding, or if *pMem does not contain a string value. +*/ +int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){ + int len; /* Maximum length of output string in bytes */ + unsigned char *zOut; /* Output buffer */ + unsigned char *zIn; /* Input iterator */ + unsigned char *zTerm; /* End of input */ + unsigned char *z; /* Output iterator */ + unsigned int c; + + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + assert( pMem->flags&MEM_Str ); + assert( pMem->enc!=desiredEnc ); + assert( pMem->enc!=0 ); + assert( pMem->n>=0 ); + +#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG) + { + char zBuf[100]; + sqlite3VdbeMemPrettyPrint(pMem, zBuf); + fprintf(stderr, "INPUT: %s\n", zBuf); + } +#endif + + /* If the translation is between UTF-16 little and big endian, then + ** all that is required is to swap the byte order. This case is handled + ** differently from the others. + */ + if( pMem->enc!=SQLITE_UTF8 && desiredEnc!=SQLITE_UTF8 ){ + u8 temp; + int rc; + rc = sqlite3VdbeMemMakeWriteable(pMem); + if( rc!=SQLITE_OK ){ + assert( rc==SQLITE_NOMEM ); + return SQLITE_NOMEM; + } + zIn = (u8*)pMem->z; + zTerm = &zIn[pMem->n]; + while( zIn<zTerm ){ + temp = *zIn; + *zIn = *(zIn+1); + zIn++; + *zIn++ = temp; + } + pMem->enc = desiredEnc; + goto translate_out; + } + + /* Set len to the maximum number of bytes required in the output buffer. */ + if( desiredEnc==SQLITE_UTF8 ){ + /* When converting from UTF-16, the maximum growth results from + ** translating a 2-byte character to a 4-byte UTF-8 character. + ** A single byte is required for the output string + ** nul-terminator. + */ + len = pMem->n * 2 + 1; + }else{ + /* When converting from UTF-8 to UTF-16 the maximum growth is caused + ** when a 1-byte UTF-8 character is translated into a 2-byte UTF-16 + ** character. Two bytes are required in the output buffer for the + ** nul-terminator. + */ + len = pMem->n * 2 + 2; + } + + /* Set zIn to point at the start of the input buffer and zTerm to point 1 + ** byte past the end. + ** + ** Variable zOut is set to point at the output buffer, space obtained + ** from sqlite3_malloc(). + */ + zIn = (u8*)pMem->z; + zTerm = &zIn[pMem->n]; + zOut = sqlite3DbMallocRaw(pMem->db, len); + if( !zOut ){ + return SQLITE_NOMEM; + } + z = zOut; + + if( pMem->enc==SQLITE_UTF8 ){ + if( desiredEnc==SQLITE_UTF16LE ){ + /* UTF-8 -> UTF-16 Little-endian */ + while( zIn<zTerm ){ + /* c = sqlite3Utf8Read(zIn, zTerm, (const u8**)&zIn); */ + READ_UTF8(zIn, zTerm, c); + WRITE_UTF16LE(z, c); + } + }else{ + assert( desiredEnc==SQLITE_UTF16BE ); + /* UTF-8 -> UTF-16 Big-endian */ + while( zIn<zTerm ){ + /* c = sqlite3Utf8Read(zIn, zTerm, (const u8**)&zIn); */ + READ_UTF8(zIn, zTerm, c); + WRITE_UTF16BE(z, c); + } + } + pMem->n = z - zOut; + *z++ = 0; + }else{ + assert( desiredEnc==SQLITE_UTF8 ); + if( pMem->enc==SQLITE_UTF16LE ){ + /* UTF-16 Little-endian -> UTF-8 */ + while( zIn<zTerm ){ + READ_UTF16LE(zIn, c); + WRITE_UTF8(z, c); + } + }else{ + /* UTF-16 Big-endian -> UTF-8 */ + while( zIn<zTerm ){ + READ_UTF16BE(zIn, c); + WRITE_UTF8(z, c); + } + } + pMem->n = z - zOut; + } + *z = 0; + assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len ); + + sqlite3VdbeMemRelease(pMem); + pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem); + pMem->enc = desiredEnc; + pMem->flags |= (MEM_Term|MEM_Dyn); + pMem->z = (char*)zOut; + pMem->zMalloc = pMem->z; + +translate_out: +#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG) + { + char zBuf[100]; + sqlite3VdbeMemPrettyPrint(pMem, zBuf); + fprintf(stderr, "OUTPUT: %s\n", zBuf); + } +#endif + return SQLITE_OK; +} + +/* +** This routine checks for a byte-order mark at the beginning of the +** UTF-16 string stored in *pMem. If one is present, it is removed and +** the encoding of the Mem adjusted. This routine does not do any +** byte-swapping, it just sets Mem.enc appropriately. +** +** The allocation (static, dynamic etc.) and encoding of the Mem may be +** changed by this function. +*/ +int sqlite3VdbeMemHandleBom(Mem *pMem){ + int rc = SQLITE_OK; + u8 bom = 0; + + if( pMem->n<0 || pMem->n>1 ){ + u8 b1 = *(u8 *)pMem->z; + u8 b2 = *(((u8 *)pMem->z) + 1); + if( b1==0xFE && b2==0xFF ){ + bom = SQLITE_UTF16BE; + } + if( b1==0xFF && b2==0xFE ){ + bom = SQLITE_UTF16LE; + } + } + + if( bom ){ + rc = sqlite3VdbeMemMakeWriteable(pMem); + if( rc==SQLITE_OK ){ + pMem->n -= 2; + memmove(pMem->z, &pMem->z[2], pMem->n); + pMem->z[pMem->n] = '\0'; + pMem->z[pMem->n+1] = '\0'; + pMem->flags |= MEM_Term; + pMem->enc = bom; + } + } + return rc; +} +#endif /* SQLITE_OMIT_UTF16 */ + +/* +** pZ is a UTF-8 encoded unicode string. If nByte is less than zero, +** return the number of unicode characters in pZ up to (but not including) +** the first 0x00 byte. If nByte is not less than zero, return the +** number of unicode characters in the first nByte of pZ (or up to +** the first 0x00, whichever comes first). +*/ +int sqlite3Utf8CharLen(const char *zIn, int nByte){ + int r = 0; + const u8 *z = (const u8*)zIn; + const u8 *zTerm; + if( nByte>=0 ){ + zTerm = &z[nByte]; + }else{ + zTerm = (const u8*)(-1); + } + assert( z<=zTerm ); + while( *z!=0 && z<zTerm ){ + SQLITE_SKIP_UTF8(z); + r++; + } + return r; +} + +/* This test function is not currently used by the automated test-suite. +** Hence it is only available in debug builds. +*/ +#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) +/* +** Translate UTF-8 to UTF-8. +** +** This has the effect of making sure that the string is well-formed +** UTF-8. Miscoded characters are removed. +** +** The translation is done in-place (since it is impossible for the +** correct UTF-8 encoding to be longer than a malformed encoding). +*/ +int sqlite3Utf8To8(unsigned char *zIn){ + unsigned char *zOut = zIn; + unsigned char *zStart = zIn; + unsigned char *zTerm; + u32 c; + + while( zIn[0] ){ + c = sqlite3Utf8Read(zIn, zTerm, (const u8**)&zIn); + if( c!=0xfffd ){ + WRITE_UTF8(zOut, c); + } + } + *zOut = 0; + return zOut - zStart; +} +#endif + +#ifndef SQLITE_OMIT_UTF16 +/* +** Convert a UTF-16 string in the native encoding into a UTF-8 string. +** Memory to hold the UTF-8 string is obtained from sqlite3_malloc and must +** be freed by the calling function. +** +** NULL is returned if there is an allocation error. +*/ +char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte){ + Mem m; + memset(&m, 0, sizeof(m)); + m.db = db; + sqlite3VdbeMemSetStr(&m, z, nByte, SQLITE_UTF16NATIVE, SQLITE_STATIC); + sqlite3VdbeChangeEncoding(&m, SQLITE_UTF8); + if( db->mallocFailed ){ + sqlite3VdbeMemRelease(&m); + m.z = 0; + } + assert( (m.flags & MEM_Term)!=0 || db->mallocFailed ); + assert( (m.flags & MEM_Str)!=0 || db->mallocFailed ); + return (m.flags & MEM_Dyn)!=0 ? m.z : sqlite3DbStrDup(db, m.z); +} + +/* +** pZ is a UTF-16 encoded unicode string. If nChar is less than zero, +** return the number of bytes up to (but not including), the first pair +** of consecutive 0x00 bytes in pZ. If nChar is not less than zero, +** then return the number of bytes in the first nChar unicode characters +** in pZ (or up until the first pair of 0x00 bytes, whichever comes first). +*/ +int sqlite3Utf16ByteLen(const void *zIn, int nChar){ + unsigned int c = 1; + char const *z = zIn; + int n = 0; + if( SQLITE_UTF16NATIVE==SQLITE_UTF16BE ){ + /* Using an "if (SQLITE_UTF16NATIVE==SQLITE_UTF16BE)" construct here + ** and in other parts of this file means that at one branch will + ** not be covered by coverage testing on any single host. But coverage + ** will be complete if the tests are run on both a little-endian and + ** big-endian host. Because both the UTF16NATIVE and SQLITE_UTF16BE + ** macros are constant at compile time the compiler can determine + ** which branch will be followed. It is therefore assumed that no runtime + ** penalty is paid for this "if" statement. + */ + while( c && ((nChar<0) || n<nChar) ){ + READ_UTF16BE(z, c); + n++; + } + }else{ + while( c && ((nChar<0) || n<nChar) ){ + READ_UTF16LE(z, c); + n++; + } + } + return (z-(char const *)zIn)-((c==0)?2:0); +} + +#if defined(SQLITE_TEST) +/* +** This routine is called from the TCL test function "translate_selftest". +** It checks that the primitives for serializing and deserializing +** characters in each encoding are inverses of each other. +*/ +void sqlite3UtfSelfTest(){ + unsigned int i, t; + unsigned char zBuf[20]; + unsigned char *z; + unsigned char *zTerm; + int n; + unsigned int c; + + for(i=0; i<0x00110000; i++){ + z = zBuf; + WRITE_UTF8(z, i); + n = z-zBuf; + z[0] = 0; + zTerm = z; + z = zBuf; + c = sqlite3Utf8Read(z, zTerm, (const u8**)&z); + t = i; + if( i>=0xD800 && i<=0xDFFF ) t = 0xFFFD; + if( (i&0xFFFFFFFE)==0xFFFE ) t = 0xFFFD; + assert( c==t ); + assert( (z-zBuf)==n ); + } + for(i=0; i<0x00110000; i++){ + if( i>=0xD800 && i<0xE000 ) continue; + z = zBuf; + WRITE_UTF16LE(z, i); + n = z-zBuf; + z[0] = 0; + z = zBuf; + READ_UTF16LE(z, c); + assert( c==i ); + assert( (z-zBuf)==n ); + } + for(i=0; i<0x00110000; i++){ + if( i>=0xD800 && i<0xE000 ) continue; + z = zBuf; + WRITE_UTF16BE(z, i); + n = z-zBuf; + z[0] = 0; + z = zBuf; + READ_UTF16BE(z, c); + assert( c==i ); + assert( (z-zBuf)==n ); + } +} +#endif /* SQLITE_TEST */ +#endif /* SQLITE_OMIT_UTF16 */ diff --git a/third_party/sqlite/src/util.c b/third_party/sqlite/src/util.c new file mode 100755 index 0000000..919452c --- /dev/null +++ b/third_party/sqlite/src/util.c @@ -0,0 +1,952 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** Utility functions used throughout sqlite. +** +** This file contains functions for allocating memory, comparing +** strings, and stuff like that. +** +** $Id: util.c,v 1.241 2008/07/28 19:34:54 drh Exp $ +*/ +#include "sqliteInt.h" +#include <stdarg.h> +#include <ctype.h> + + +/* +** Return true if the floating point value is Not a Number (NaN). +*/ +int sqlite3IsNaN(double x){ + /* This NaN test sometimes fails if compiled on GCC with -ffast-math. + ** On the other hand, the use of -ffast-math comes with the following + ** warning: + ** + ** This option [-ffast-math] should never be turned on by any + ** -O option since it can result in incorrect output for programs + ** which depend on an exact implementation of IEEE or ISO + ** rules/specifications for math functions. + ** + ** Under MSVC, this NaN test may fail if compiled with a floating- + ** point precision mode other than /fp:precise. From the MSDN + ** documentation: + ** + ** The compiler [with /fp:precise] will properly handle comparisons + ** involving NaN. For example, x != x evaluates to true if x is NaN + ** ... + */ +#ifdef __FAST_MATH__ +# error SQLite will not work correctly with the -ffast-math option of GCC. +#endif + volatile double y = x; + volatile double z = y; + return y!=z; +} + +/* +** Return the length of a string, except do not allow the string length +** to exceed the SQLITE_LIMIT_LENGTH setting. +*/ +int sqlite3Strlen(sqlite3 *db, const char *z){ + const char *z2 = z; + int len; + size_t x; + while( *z2 ){ z2++; } + x = z2 - z; + len = 0x7fffffff & x; + if( len!=x || len > db->aLimit[SQLITE_LIMIT_LENGTH] ){ + return db->aLimit[SQLITE_LIMIT_LENGTH]; + }else{ + return len; + } +} + +/* +** Set the most recent error code and error string for the sqlite +** handle "db". The error code is set to "err_code". +** +** If it is not NULL, string zFormat specifies the format of the +** error string in the style of the printf functions: The following +** format characters are allowed: +** +** %s Insert a string +** %z A string that should be freed after use +** %d Insert an integer +** %T Insert a token +** %S Insert the first element of a SrcList +** +** zFormat and any string tokens that follow it are assumed to be +** encoded in UTF-8. +** +** To clear the most recent error for sqlite handle "db", sqlite3Error +** should be called with err_code set to SQLITE_OK and zFormat set +** to NULL. +*/ +void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){ + if( db && (db->pErr || (db->pErr = sqlite3ValueNew(db))!=0) ){ + db->errCode = err_code; + if( zFormat ){ + char *z; + va_list ap; + va_start(ap, zFormat); + z = sqlite3VMPrintf(db, zFormat, ap); + va_end(ap); + sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC); + }else{ + sqlite3ValueSetStr(db->pErr, 0, 0, SQLITE_UTF8, SQLITE_STATIC); + } + } +} + +/* +** Add an error message to pParse->zErrMsg and increment pParse->nErr. +** The following formatting characters are allowed: +** +** %s Insert a string +** %z A string that should be freed after use +** %d Insert an integer +** %T Insert a token +** %S Insert the first element of a SrcList +** +** This function should be used to report any error that occurs whilst +** compiling an SQL statement (i.e. within sqlite3_prepare()). The +** last thing the sqlite3_prepare() function does is copy the error +** stored by this function into the database handle using sqlite3Error(). +** Function sqlite3Error() should be used during statement execution +** (sqlite3_step() etc.). +*/ +void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){ + va_list ap; + sqlite3 *db = pParse->db; + pParse->nErr++; + sqlite3DbFree(db, pParse->zErrMsg); + va_start(ap, zFormat); + pParse->zErrMsg = sqlite3VMPrintf(db, zFormat, ap); + va_end(ap); + if( pParse->rc==SQLITE_OK ){ + pParse->rc = SQLITE_ERROR; + } +} + +/* +** Clear the error message in pParse, if any +*/ +void sqlite3ErrorClear(Parse *pParse){ + sqlite3DbFree(pParse->db, pParse->zErrMsg); + pParse->zErrMsg = 0; + pParse->nErr = 0; +} + +/* +** Convert an SQL-style quoted string into a normal string by removing +** the quote characters. The conversion is done in-place. If the +** input does not begin with a quote character, then this routine +** is a no-op. +** +** 2002-Feb-14: This routine is extended to remove MS-Access style +** brackets from around identifers. For example: "[a-b-c]" becomes +** "a-b-c". +*/ +void sqlite3Dequote(char *z){ + int quote; + int i, j; + if( z==0 ) return; + quote = z[0]; + switch( quote ){ + case '\'': break; + case '"': break; + case '`': break; /* For MySQL compatibility */ + case '[': quote = ']'; break; /* For MS SqlServer compatibility */ + default: return; + } + for(i=1, j=0; z[i]; i++){ + if( z[i]==quote ){ + if( z[i+1]==quote ){ + z[j++] = quote; + i++; + }else{ + z[j++] = 0; + break; + } + }else{ + z[j++] = z[i]; + } + } +} + +/* Convenient short-hand */ +#define UpperToLower sqlite3UpperToLower + +/* +** Some systems have stricmp(). Others have strcasecmp(). Because +** there is no consistency, we will define our own. +*/ +int sqlite3StrICmp(const char *zLeft, const char *zRight){ + register unsigned char *a, *b; + a = (unsigned char *)zLeft; + b = (unsigned char *)zRight; + while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; } + return UpperToLower[*a] - UpperToLower[*b]; +} +int sqlite3StrNICmp(const char *zLeft, const char *zRight, int N){ + register unsigned char *a, *b; + a = (unsigned char *)zLeft; + b = (unsigned char *)zRight; + while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; } + return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b]; +} + +/* +** Return TRUE if z is a pure numeric string. Return FALSE if the +** string contains any character which is not part of a number. If +** the string is numeric and contains the '.' character, set *realnum +** to TRUE (otherwise FALSE). +** +** An empty string is considered non-numeric. +*/ +int sqlite3IsNumber(const char *z, int *realnum, u8 enc){ + int incr = (enc==SQLITE_UTF8?1:2); + if( enc==SQLITE_UTF16BE ) z++; + if( *z=='-' || *z=='+' ) z += incr; + if( !isdigit(*(u8*)z) ){ + return 0; + } + z += incr; + if( realnum ) *realnum = 0; + while( isdigit(*(u8*)z) ){ z += incr; } + if( *z=='.' ){ + z += incr; + if( !isdigit(*(u8*)z) ) return 0; + while( isdigit(*(u8*)z) ){ z += incr; } + if( realnum ) *realnum = 1; + } + if( *z=='e' || *z=='E' ){ + z += incr; + if( *z=='+' || *z=='-' ) z += incr; + if( !isdigit(*(u8*)z) ) return 0; + while( isdigit(*(u8*)z) ){ z += incr; } + if( realnum ) *realnum = 1; + } + return *z==0; +} + +/* +** The string z[] is an ascii representation of a real number. +** Convert this string to a double. +** +** This routine assumes that z[] really is a valid number. If it +** is not, the result is undefined. +** +** This routine is used instead of the library atof() function because +** the library atof() might want to use "," as the decimal point instead +** of "." depending on how locale is set. But that would cause problems +** for SQL. So this routine always uses "." regardless of locale. +*/ +int sqlite3AtoF(const char *z, double *pResult){ +#ifndef SQLITE_OMIT_FLOATING_POINT + int sign = 1; + const char *zBegin = z; + LONGDOUBLE_TYPE v1 = 0.0; + int nSignificant = 0; + while( isspace(*(u8*)z) ) z++; + if( *z=='-' ){ + sign = -1; + z++; + }else if( *z=='+' ){ + z++; + } + while( z[0]=='0' ){ + z++; + } + while( isdigit(*(u8*)z) ){ + v1 = v1*10.0 + (*z - '0'); + z++; + nSignificant++; + } + if( *z=='.' ){ + LONGDOUBLE_TYPE divisor = 1.0; + z++; + if( nSignificant==0 ){ + while( z[0]=='0' ){ + divisor *= 10.0; + z++; + } + } + while( isdigit(*(u8*)z) ){ + if( nSignificant<18 ){ + v1 = v1*10.0 + (*z - '0'); + divisor *= 10.0; + nSignificant++; + } + z++; + } + v1 /= divisor; + } + if( *z=='e' || *z=='E' ){ + int esign = 1; + int eval = 0; + LONGDOUBLE_TYPE scale = 1.0; + z++; + if( *z=='-' ){ + esign = -1; + z++; + }else if( *z=='+' ){ + z++; + } + while( isdigit(*(u8*)z) ){ + eval = eval*10 + *z - '0'; + z++; + } + while( eval>=64 ){ scale *= 1.0e+64; eval -= 64; } + while( eval>=16 ){ scale *= 1.0e+16; eval -= 16; } + while( eval>=4 ){ scale *= 1.0e+4; eval -= 4; } + while( eval>=1 ){ scale *= 1.0e+1; eval -= 1; } + if( esign<0 ){ + v1 /= scale; + }else{ + v1 *= scale; + } + } + *pResult = sign<0 ? -v1 : v1; + return z - zBegin; +#else + return sqlite3Atoi64(z, pResult); +#endif /* SQLITE_OMIT_FLOATING_POINT */ +} + +/* +** Compare the 19-character string zNum against the text representation +** value 2^63: 9223372036854775808. Return negative, zero, or positive +** if zNum is less than, equal to, or greater than the string. +** +** Unlike memcmp() this routine is guaranteed to return the difference +** in the values of the last digit if the only difference is in the +** last digit. So, for example, +** +** compare2pow63("9223372036854775800") +** +** will return -8. +*/ +static int compare2pow63(const char *zNum){ + int c; + c = memcmp(zNum,"922337203685477580",18); + if( c==0 ){ + c = zNum[18] - '8'; + } + return c; +} + + +/* +** Return TRUE if zNum is a 64-bit signed integer and write +** the value of the integer into *pNum. If zNum is not an integer +** or is an integer that is too large to be expressed with 64 bits, +** then return false. +** +** When this routine was originally written it dealt with only +** 32-bit numbers. At that time, it was much faster than the +** atoi() library routine in RedHat 7.2. +*/ +int sqlite3Atoi64(const char *zNum, i64 *pNum){ + i64 v = 0; + int neg; + int i, c; + const char *zStart; + while( isspace(*(u8*)zNum) ) zNum++; + if( *zNum=='-' ){ + neg = 1; + zNum++; + }else if( *zNum=='+' ){ + neg = 0; + zNum++; + }else{ + neg = 0; + } + zStart = zNum; + while( zNum[0]=='0' ){ zNum++; } /* Skip over leading zeros. Ticket #2454 */ + for(i=0; (c=zNum[i])>='0' && c<='9'; i++){ + v = v*10 + c - '0'; + } + *pNum = neg ? -v : v; + if( c!=0 || (i==0 && zStart==zNum) || i>19 ){ + /* zNum is empty or contains non-numeric text or is longer + ** than 19 digits (thus guaranting that it is too large) */ + return 0; + }else if( i<19 ){ + /* Less than 19 digits, so we know that it fits in 64 bits */ + return 1; + }else{ + /* 19-digit numbers must be no larger than 9223372036854775807 if positive + ** or 9223372036854775808 if negative. Note that 9223372036854665808 + ** is 2^63. */ + return compare2pow63(zNum)<neg; + } +} + +/* +** The string zNum represents an integer. There might be some other +** information following the integer too, but that part is ignored. +** If the integer that the prefix of zNum represents will fit in a +** 64-bit signed integer, return TRUE. Otherwise return FALSE. +** +** This routine returns FALSE for the string -9223372036854775808 even that +** that number will, in theory fit in a 64-bit integer. Positive +** 9223373036854775808 will not fit in 64 bits. So it seems safer to return +** false. +*/ +int sqlite3FitsIn64Bits(const char *zNum, int negFlag){ + int i, c; + int neg = 0; + if( *zNum=='-' ){ + neg = 1; + zNum++; + }else if( *zNum=='+' ){ + zNum++; + } + if( negFlag ) neg = 1-neg; + while( *zNum=='0' ){ + zNum++; /* Skip leading zeros. Ticket #2454 */ + } + for(i=0; (c=zNum[i])>='0' && c<='9'; i++){} + if( i<19 ){ + /* Guaranteed to fit if less than 19 digits */ + return 1; + }else if( i>19 ){ + /* Guaranteed to be too big if greater than 19 digits */ + return 0; + }else{ + /* Compare against 2^63. */ + return compare2pow63(zNum)<neg; + } +} + +/* +** If zNum represents an integer that will fit in 32-bits, then set +** *pValue to that integer and return true. Otherwise return false. +** +** Any non-numeric characters that following zNum are ignored. +** This is different from sqlite3Atoi64() which requires the +** input number to be zero-terminated. +*/ +int sqlite3GetInt32(const char *zNum, int *pValue){ + sqlite_int64 v = 0; + int i, c; + int neg = 0; + if( zNum[0]=='-' ){ + neg = 1; + zNum++; + }else if( zNum[0]=='+' ){ + zNum++; + } + while( zNum[0]=='0' ) zNum++; + for(i=0; i<11 && (c = zNum[i] - '0')>=0 && c<=9; i++){ + v = v*10 + c; + } + + /* The longest decimal representation of a 32 bit integer is 10 digits: + ** + ** 1234567890 + ** 2^31 -> 2147483648 + */ + if( i>10 ){ + return 0; + } + if( v-neg>2147483647 ){ + return 0; + } + if( neg ){ + v = -v; + } + *pValue = (int)v; + return 1; +} + +/* +** The variable-length integer encoding is as follows: +** +** KEY: +** A = 0xxxxxxx 7 bits of data and one flag bit +** B = 1xxxxxxx 7 bits of data and one flag bit +** C = xxxxxxxx 8 bits of data +** +** 7 bits - A +** 14 bits - BA +** 21 bits - BBA +** 28 bits - BBBA +** 35 bits - BBBBA +** 42 bits - BBBBBA +** 49 bits - BBBBBBA +** 56 bits - BBBBBBBA +** 64 bits - BBBBBBBBC +*/ + +/* +** Write a 64-bit variable-length integer to memory starting at p[0]. +** The length of data write will be between 1 and 9 bytes. The number +** of bytes written is returned. +** +** A variable-length integer consists of the lower 7 bits of each byte +** for all bytes that have the 8th bit set and one byte with the 8th +** bit clear. Except, if we get to the 9th byte, it stores the full +** 8 bits and is the last byte. +*/ +int sqlite3PutVarint(unsigned char *p, u64 v){ + int i, j, n; + u8 buf[10]; + if( v & (((u64)0xff000000)<<32) ){ + p[8] = v; + v >>= 8; + for(i=7; i>=0; i--){ + p[i] = (v & 0x7f) | 0x80; + v >>= 7; + } + return 9; + } + n = 0; + do{ + buf[n++] = (v & 0x7f) | 0x80; + v >>= 7; + }while( v!=0 ); + buf[0] &= 0x7f; + assert( n<=9 ); + for(i=0, j=n-1; j>=0; j--, i++){ + p[i] = buf[j]; + } + return n; +} + +/* +** This routine is a faster version of sqlite3PutVarint() that only +** works for 32-bit positive integers and which is optimized for +** the common case of small integers. A MACRO version, putVarint32, +** is provided which inlines the single-byte case. All code should use +** the MACRO version as this function assumes the single-byte case has +** already been handled. +*/ +int sqlite3PutVarint32(unsigned char *p, u32 v){ +#ifndef putVarint32 + if( (v & ~0x7f)==0 ){ + p[0] = v; + return 1; + } +#endif + if( (v & ~0x3fff)==0 ){ + p[0] = (v>>7) | 0x80; + p[1] = v & 0x7f; + return 2; + } + return sqlite3PutVarint(p, v); +} + +/* +** Read a 64-bit variable-length integer from memory starting at p[0]. +** Return the number of bytes read. The value is stored in *v. +*/ +int sqlite3GetVarint(const unsigned char *p, u64 *v){ + u32 a,b,s; + + a = *p; + /* a: p0 (unmasked) */ + if (!(a&0x80)) + { + *v = a; + return 1; + } + + p++; + b = *p; + /* b: p1 (unmasked) */ + if (!(b&0x80)) + { + a &= 0x7f; + a = a<<7; + a |= b; + *v = a; + return 2; + } + + p++; + a = a<<14; + a |= *p; + /* a: p0<<14 | p2 (unmasked) */ + if (!(a&0x80)) + { + a &= (0x7f<<14)|(0x7f); + b &= 0x7f; + b = b<<7; + a |= b; + *v = a; + return 3; + } + + /* CSE1 from below */ + a &= (0x7f<<14)|(0x7f); + p++; + b = b<<14; + b |= *p; + /* b: p1<<14 | p3 (unmasked) */ + if (!(b&0x80)) + { + b &= (0x7f<<14)|(0x7f); + /* moved CSE1 up */ + /* a &= (0x7f<<14)|(0x7f); */ + a = a<<7; + a |= b; + *v = a; + return 4; + } + + /* a: p0<<14 | p2 (masked) */ + /* b: p1<<14 | p3 (unmasked) */ + /* 1:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */ + /* moved CSE1 up */ + /* a &= (0x7f<<14)|(0x7f); */ + b &= (0x7f<<14)|(0x7f); + s = a; + /* s: p0<<14 | p2 (masked) */ + + p++; + a = a<<14; + a |= *p; + /* a: p0<<28 | p2<<14 | p4 (unmasked) */ + if (!(a&0x80)) + { + /* we can skip these cause they were (effectively) done above in calc'ing s */ + /* a &= (0x7f<<28)|(0x7f<<14)|(0x7f); */ + /* b &= (0x7f<<14)|(0x7f); */ + b = b<<7; + a |= b; + s = s>>18; + *v = ((u64)s)<<32 | a; + return 5; + } + + /* 2:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */ + s = s<<7; + s |= b; + /* s: p0<<21 | p1<<14 | p2<<7 | p3 (masked) */ + + p++; + b = b<<14; + b |= *p; + /* b: p1<<28 | p3<<14 | p5 (unmasked) */ + if (!(b&0x80)) + { + /* we can skip this cause it was (effectively) done above in calc'ing s */ + /* b &= (0x7f<<28)|(0x7f<<14)|(0x7f); */ + a &= (0x7f<<14)|(0x7f); + a = a<<7; + a |= b; + s = s>>18; + *v = ((u64)s)<<32 | a; + return 6; + } + + p++; + a = a<<14; + a |= *p; + /* a: p2<<28 | p4<<14 | p6 (unmasked) */ + if (!(a&0x80)) + { + a &= (0x7f<<28)|(0x7f<<14)|(0x7f); + b &= (0x7f<<14)|(0x7f); + b = b<<7; + a |= b; + s = s>>11; + *v = ((u64)s)<<32 | a; + return 7; + } + + /* CSE2 from below */ + a &= (0x7f<<14)|(0x7f); + p++; + b = b<<14; + b |= *p; + /* b: p3<<28 | p5<<14 | p7 (unmasked) */ + if (!(b&0x80)) + { + b &= (0x7f<<28)|(0x7f<<14)|(0x7f); + /* moved CSE2 up */ + /* a &= (0x7f<<14)|(0x7f); */ + a = a<<7; + a |= b; + s = s>>4; + *v = ((u64)s)<<32 | a; + return 8; + } + + p++; + a = a<<15; + a |= *p; + /* a: p4<<29 | p6<<15 | p8 (unmasked) */ + + /* moved CSE2 up */ + /* a &= (0x7f<<29)|(0x7f<<15)|(0xff); */ + b &= (0x7f<<14)|(0x7f); + b = b<<8; + a |= b; + + s = s<<4; + b = p[-4]; + b &= 0x7f; + b = b>>3; + s |= b; + + *v = ((u64)s)<<32 | a; + + return 9; +} + +/* +** Read a 32-bit variable-length integer from memory starting at p[0]. +** Return the number of bytes read. The value is stored in *v. +** A MACRO version, getVarint32, is provided which inlines the +** single-byte case. All code should use the MACRO version as +** this function assumes the single-byte case has already been handled. +*/ +int sqlite3GetVarint32(const unsigned char *p, u32 *v){ + u32 a,b; + + a = *p; + /* a: p0 (unmasked) */ +#ifndef getVarint32 + if (!(a&0x80)) + { + *v = a; + return 1; + } +#endif + + p++; + b = *p; + /* b: p1 (unmasked) */ + if (!(b&0x80)) + { + a &= 0x7f; + a = a<<7; + *v = a | b; + return 2; + } + + p++; + a = a<<14; + a |= *p; + /* a: p0<<14 | p2 (unmasked) */ + if (!(a&0x80)) + { + a &= (0x7f<<14)|(0x7f); + b &= 0x7f; + b = b<<7; + *v = a | b; + return 3; + } + + p++; + b = b<<14; + b |= *p; + /* b: p1<<14 | p3 (unmasked) */ + if (!(b&0x80)) + { + b &= (0x7f<<14)|(0x7f); + a &= (0x7f<<14)|(0x7f); + a = a<<7; + *v = a | b; + return 4; + } + + p++; + a = a<<14; + a |= *p; + /* a: p0<<28 | p2<<14 | p4 (unmasked) */ + if (!(a&0x80)) + { + a &= (0x7f<<28)|(0x7f<<14)|(0x7f); + b &= (0x7f<<28)|(0x7f<<14)|(0x7f); + b = b<<7; + *v = a | b; + return 5; + } + + /* We can only reach this point when reading a corrupt database + ** file. In that case we are not in any hurry. Use the (relatively + ** slow) general-purpose sqlite3GetVarint() routine to extract the + ** value. */ + { + u64 v64; + int n; + + p -= 4; + n = sqlite3GetVarint(p, &v64); + assert( n>5 && n<=9 ); + *v = (u32)v64; + return n; + } +} + +/* +** Return the number of bytes that will be needed to store the given +** 64-bit integer. +*/ +int sqlite3VarintLen(u64 v){ + int i = 0; + do{ + i++; + v >>= 7; + }while( v!=0 && i<9 ); + return i; +} + + +/* +** Read or write a four-byte big-endian integer value. +*/ +u32 sqlite3Get4byte(const u8 *p){ + return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; +} +void sqlite3Put4byte(unsigned char *p, u32 v){ + p[0] = v>>24; + p[1] = v>>16; + p[2] = v>>8; + p[3] = v; +} + + + +#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC) +/* +** Translate a single byte of Hex into an integer. +** This routinen only works if h really is a valid hexadecimal +** character: 0..9a..fA..F +*/ +static int hexToInt(int h){ + assert( (h>='0' && h<='9') || (h>='a' && h<='f') || (h>='A' && h<='F') ); +#ifdef SQLITE_ASCII + h += 9*(1&(h>>6)); +#endif +#ifdef SQLITE_EBCDIC + h += 9*(1&~(h>>4)); +#endif + return h & 0xf; +} +#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */ + +#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC) +/* +** Convert a BLOB literal of the form "x'hhhhhh'" into its binary +** value. Return a pointer to its binary value. Space to hold the +** binary value has been obtained from malloc and must be freed by +** the calling routine. +*/ +void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){ + char *zBlob; + int i; + + zBlob = (char *)sqlite3DbMallocRaw(db, n/2 + 1); + n--; + if( zBlob ){ + for(i=0; i<n; i+=2){ + zBlob[i/2] = (hexToInt(z[i])<<4) | hexToInt(z[i+1]); + } + zBlob[i/2] = 0; + } + return zBlob; +} +#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */ + + +/* +** Change the sqlite.magic from SQLITE_MAGIC_OPEN to SQLITE_MAGIC_BUSY. +** Return an error (non-zero) if the magic was not SQLITE_MAGIC_OPEN +** when this routine is called. +** +** This routine is called when entering an SQLite API. The SQLITE_MAGIC_OPEN +** value indicates that the database connection passed into the API is +** open and is not being used by another thread. By changing the value +** to SQLITE_MAGIC_BUSY we indicate that the connection is in use. +** sqlite3SafetyOff() below will change the value back to SQLITE_MAGIC_OPEN +** when the API exits. +** +** This routine is a attempt to detect if two threads use the +** same sqlite* pointer at the same time. There is a race +** condition so it is possible that the error is not detected. +** But usually the problem will be seen. The result will be an +** error which can be used to debug the application that is +** using SQLite incorrectly. +** +** Ticket #202: If db->magic is not a valid open value, take care not +** to modify the db structure at all. It could be that db is a stale +** pointer. In other words, it could be that there has been a prior +** call to sqlite3_close(db) and db has been deallocated. And we do +** not want to write into deallocated memory. +*/ +#ifdef SQLITE_DEBUG +int sqlite3SafetyOn(sqlite3 *db){ + if( db->magic==SQLITE_MAGIC_OPEN ){ + db->magic = SQLITE_MAGIC_BUSY; + assert( sqlite3_mutex_held(db->mutex) ); + return 0; + }else if( db->magic==SQLITE_MAGIC_BUSY ){ + db->magic = SQLITE_MAGIC_ERROR; + db->u1.isInterrupted = 1; + } + return 1; +} +#endif + +/* +** Change the magic from SQLITE_MAGIC_BUSY to SQLITE_MAGIC_OPEN. +** Return an error (non-zero) if the magic was not SQLITE_MAGIC_BUSY +** when this routine is called. +*/ +#ifdef SQLITE_DEBUG +int sqlite3SafetyOff(sqlite3 *db){ + if( db->magic==SQLITE_MAGIC_BUSY ){ + db->magic = SQLITE_MAGIC_OPEN; + assert( sqlite3_mutex_held(db->mutex) ); + return 0; + }else{ + db->magic = SQLITE_MAGIC_ERROR; + db->u1.isInterrupted = 1; + return 1; + } +} +#endif + +/* +** Check to make sure we have a valid db pointer. This test is not +** foolproof but it does provide some measure of protection against +** misuse of the interface such as passing in db pointers that are +** NULL or which have been previously closed. If this routine returns +** 1 it means that the db pointer is valid and 0 if it should not be +** dereferenced for any reason. The calling function should invoke +** SQLITE_MISUSE immediately. +** +** sqlite3SafetyCheckOk() requires that the db pointer be valid for +** use. sqlite3SafetyCheckSickOrOk() allows a db pointer that failed to +** open properly and is not fit for general use but which can be +** used as an argument to sqlite3_errmsg() or sqlite3_close(). +*/ +int sqlite3SafetyCheckOk(sqlite3 *db){ + int magic; + if( db==0 ) return 0; + magic = db->magic; + if( magic!=SQLITE_MAGIC_OPEN && + magic!=SQLITE_MAGIC_BUSY ) return 0; + return 1; +} +int sqlite3SafetyCheckSickOrOk(sqlite3 *db){ + int magic; + if( db==0 ) return 0; + magic = db->magic; + if( magic!=SQLITE_MAGIC_SICK && + magic!=SQLITE_MAGIC_OPEN && + magic!=SQLITE_MAGIC_BUSY ) return 0; + return 1; +} diff --git a/third_party/sqlite/src/vacuum.c b/third_party/sqlite/src/vacuum.c new file mode 100755 index 0000000..45bc61e --- /dev/null +++ b/third_party/sqlite/src/vacuum.c @@ -0,0 +1,293 @@ +/* +** 2003 April 6 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains code used to implement the VACUUM command. +** +** Most of the code in this file may be omitted by defining the +** SQLITE_OMIT_VACUUM macro. +** +** $Id: vacuum.c,v 1.81 2008/07/08 19:34:07 drh Exp $ +*/ +#include "sqliteInt.h" +#include "vdbeInt.h" + +#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) +/* +** Execute zSql on database db. Return an error code. +*/ +static int execSql(sqlite3 *db, const char *zSql){ + sqlite3_stmt *pStmt; + if( !zSql ){ + return SQLITE_NOMEM; + } + if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){ + return sqlite3_errcode(db); + } + while( SQLITE_ROW==sqlite3_step(pStmt) ){} + return sqlite3_finalize(pStmt); +} + +/* +** Execute zSql on database db. The statement returns exactly +** one column. Execute this as SQL on the same database. +*/ +static int execExecSql(sqlite3 *db, const char *zSql){ + sqlite3_stmt *pStmt; + int rc; + + rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); + if( rc!=SQLITE_OK ) return rc; + + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + rc = execSql(db, (char*)sqlite3_column_text(pStmt, 0)); + if( rc!=SQLITE_OK ){ + sqlite3_finalize(pStmt); + return rc; + } + } + + return sqlite3_finalize(pStmt); +} + +/* +** The non-standard VACUUM command is used to clean up the database, +** collapse free space, etc. It is modelled after the VACUUM command +** in PostgreSQL. +** +** In version 1.0.x of SQLite, the VACUUM command would call +** gdbm_reorganize() on all the database tables. But beginning +** with 2.0.0, SQLite no longer uses GDBM so this command has +** become a no-op. +*/ +void sqlite3Vacuum(Parse *pParse){ + Vdbe *v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0); + } + return; +} + +/* +** This routine implements the OP_Vacuum opcode of the VDBE. +*/ +int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ + int rc = SQLITE_OK; /* Return code from service routines */ + Btree *pMain; /* The database being vacuumed */ + Btree *pTemp; /* The temporary database we vacuum into */ + char *zSql = 0; /* SQL statements */ + int saved_flags; /* Saved value of the db->flags */ + int saved_nChange; /* Saved value of db->nChange */ + int saved_nTotalChange; /* Saved value of db->nTotalChange */ + Db *pDb = 0; /* Database to detach at end of vacuum */ + int nRes; + + /* Save the current value of the write-schema flag before setting it. */ + saved_flags = db->flags; + saved_nChange = db->nChange; + saved_nTotalChange = db->nTotalChange; + db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks; + + if( !db->autoCommit ){ + sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction"); + rc = SQLITE_ERROR; + goto end_of_vacuum; + } + pMain = db->aDb[0].pBt; + + /* Attach the temporary database as 'vacuum_db'. The synchronous pragma + ** can be set to 'off' for this file, as it is not recovered if a crash + ** occurs anyway. The integrity of the database is maintained by a + ** (possibly synchronous) transaction opened on the main database before + ** sqlite3BtreeCopyFile() is called. + ** + ** An optimisation would be to use a non-journaled pager. + ** (Later:) I tried setting "PRAGMA vacuum_db.journal_mode=OFF" but + ** that actually made the VACUUM run slower. Very little journalling + ** actually occurs when doing a vacuum since the vacuum_db is initially + ** empty. Only the journal header is written. Apparently it takes more + ** time to parse and run the PRAGMA to turn journalling off than it does + ** to write the journal header file. + */ + zSql = "ATTACH '' AS vacuum_db;"; + rc = execSql(db, zSql); + if( rc!=SQLITE_OK ) goto end_of_vacuum; + pDb = &db->aDb[db->nDb-1]; + assert( strcmp(db->aDb[db->nDb-1].zName,"vacuum_db")==0 ); + pTemp = db->aDb[db->nDb-1].pBt; + + nRes = sqlite3BtreeGetReserve(pMain); + + /* A VACUUM cannot change the pagesize of an encrypted database. */ +#ifdef SQLITE_HAS_CODEC + if( db->nextPagesize ){ + extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); + int nKey; + char *zKey; + sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey); + if( nKey ) db->nextPagesize = 0; + } +#endif + + if( sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), nRes) + || sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes) + || db->mallocFailed + ){ + rc = SQLITE_NOMEM; + goto end_of_vacuum; + } + rc = execSql(db, "PRAGMA vacuum_db.synchronous=OFF"); + if( rc!=SQLITE_OK ){ + goto end_of_vacuum; + } + +#ifndef SQLITE_OMIT_AUTOVACUUM + sqlite3BtreeSetAutoVacuum(pTemp, db->nextAutovac>=0 ? db->nextAutovac : + sqlite3BtreeGetAutoVacuum(pMain)); +#endif + + /* Begin a transaction */ + rc = execSql(db, "BEGIN EXCLUSIVE;"); + if( rc!=SQLITE_OK ) goto end_of_vacuum; + + /* Query the schema of the main database. Create a mirror schema + ** in the temporary database. + */ + rc = execExecSql(db, + "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14) " + " FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'" + " AND rootpage>0" + ); + if( rc!=SQLITE_OK ) goto end_of_vacuum; + rc = execExecSql(db, + "SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14)" + " FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %' "); + if( rc!=SQLITE_OK ) goto end_of_vacuum; + rc = execExecSql(db, + "SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21) " + " FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'"); + if( rc!=SQLITE_OK ) goto end_of_vacuum; + + /* Loop through the tables in the main database. For each, do + ** an "INSERT INTO vacuum_db.xxx SELECT * FROM xxx;" to copy + ** the contents to the temporary database. + */ + rc = execExecSql(db, + "SELECT 'INSERT INTO vacuum_db.' || quote(name) " + "|| ' SELECT * FROM ' || quote(name) || ';'" + "FROM sqlite_master " + "WHERE type = 'table' AND name!='sqlite_sequence' " + " AND rootpage>0" + + ); + if( rc!=SQLITE_OK ) goto end_of_vacuum; + + /* Copy over the sequence table + */ + rc = execExecSql(db, + "SELECT 'DELETE FROM vacuum_db.' || quote(name) || ';' " + "FROM vacuum_db.sqlite_master WHERE name='sqlite_sequence' " + ); + if( rc!=SQLITE_OK ) goto end_of_vacuum; + rc = execExecSql(db, + "SELECT 'INSERT INTO vacuum_db.' || quote(name) " + "|| ' SELECT * FROM ' || quote(name) || ';' " + "FROM vacuum_db.sqlite_master WHERE name=='sqlite_sequence';" + ); + if( rc!=SQLITE_OK ) goto end_of_vacuum; + + + /* Copy the triggers, views, and virtual tables from the main database + ** over to the temporary database. None of these objects has any + ** associated storage, so all we have to do is copy their entries + ** from the SQLITE_MASTER table. + */ + rc = execSql(db, + "INSERT INTO vacuum_db.sqlite_master " + " SELECT type, name, tbl_name, rootpage, sql" + " FROM sqlite_master" + " WHERE type='view' OR type='trigger'" + " OR (type='table' AND rootpage=0)" + ); + if( rc ) goto end_of_vacuum; + + /* At this point, unless the main db was completely empty, there is now a + ** transaction open on the vacuum database, but not on the main database. + ** Open a btree level transaction on the main database. This allows a + ** call to sqlite3BtreeCopyFile(). The main database btree level + ** transaction is then committed, so the SQL level never knows it was + ** opened for writing. This way, the SQL transaction used to create the + ** temporary database never needs to be committed. + */ + if( rc==SQLITE_OK ){ + u32 meta; + int i; + + /* This array determines which meta meta values are preserved in the + ** vacuum. Even entries are the meta value number and odd entries + ** are an increment to apply to the meta value after the vacuum. + ** The increment is used to increase the schema cookie so that other + ** connections to the same database will know to reread the schema. + */ + static const unsigned char aCopy[] = { + 1, 1, /* Add one to the old schema cookie */ + 3, 0, /* Preserve the default page cache size */ + 5, 0, /* Preserve the default text encoding */ + 6, 0, /* Preserve the user version */ + }; + + assert( 1==sqlite3BtreeIsInTrans(pTemp) ); + assert( 1==sqlite3BtreeIsInTrans(pMain) ); + + /* Copy Btree meta values */ + for(i=0; i<sizeof(aCopy)/sizeof(aCopy[0]); i+=2){ + rc = sqlite3BtreeGetMeta(pMain, aCopy[i], &meta); + if( rc!=SQLITE_OK ) goto end_of_vacuum; + rc = sqlite3BtreeUpdateMeta(pTemp, aCopy[i], meta+aCopy[i+1]); + if( rc!=SQLITE_OK ) goto end_of_vacuum; + } + + rc = sqlite3BtreeCopyFile(pMain, pTemp); + if( rc!=SQLITE_OK ) goto end_of_vacuum; + rc = sqlite3BtreeCommit(pTemp); + if( rc!=SQLITE_OK ) goto end_of_vacuum; + rc = sqlite3BtreeCommit(pMain); + } + + if( rc==SQLITE_OK ){ + rc = sqlite3BtreeSetPageSize(pMain, sqlite3BtreeGetPageSize(pTemp), nRes); + } + +end_of_vacuum: + /* Restore the original value of db->flags */ + db->flags = saved_flags; + db->nChange = saved_nChange; + db->nTotalChange = saved_nTotalChange; + + /* Currently there is an SQL level transaction open on the vacuum + ** database. No locks are held on any other files (since the main file + ** was committed at the btree level). So it safe to end the transaction + ** by manually setting the autoCommit flag to true and detaching the + ** vacuum database. The vacuum_db journal file is deleted when the pager + ** is closed by the DETACH. + */ + db->autoCommit = 1; + + if( pDb ){ + sqlite3BtreeClose(pDb->pBt); + pDb->pBt = 0; + pDb->pSchema = 0; + } + + sqlite3ResetInternalSchema(db, 0); + + return rc; +} +#endif /* SQLITE_OMIT_VACUUM && SQLITE_OMIT_ATTACH */ diff --git a/third_party/sqlite/src/vdbe.c b/third_party/sqlite/src/vdbe.c new file mode 100755 index 0000000..b326c79 --- /dev/null +++ b/third_party/sqlite/src/vdbe.c @@ -0,0 +1,5118 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** The code in this file implements execution method of the +** Virtual Database Engine (VDBE). A separate file ("vdbeaux.c") +** handles housekeeping details such as creating and deleting +** VDBE instances. This file is solely interested in executing +** the VDBE program. +** +** In the external interface, an "sqlite3_stmt*" is an opaque pointer +** to a VDBE. +** +** The SQL parser generates a program which is then executed by +** the VDBE to do the work of the SQL statement. VDBE programs are +** similar in form to assembly language. The program consists of +** a linear sequence of operations. Each operation has an opcode +** and 5 operands. Operands P1, P2, and P3 are integers. Operand P4 +** is a null-terminated string. Operand P5 is an unsigned character. +** Few opcodes use all 5 operands. +** +** Computation results are stored on a set of registers numbered beginning +** with 1 and going up to Vdbe.nMem. Each register can store +** either an integer, a null-terminated string, a floating point +** number, or the SQL "NULL" value. An implicit conversion from one +** type to the other occurs as necessary. +** +** Most of the code in this file is taken up by the sqlite3VdbeExec() +** function which does the work of interpreting a VDBE program. +** But other routines are also provided to help in building up +** a program instruction by instruction. +** +** Various scripts scan this source file in order to generate HTML +** documentation, headers files, or other derived files. The formatting +** of the code in this file is, therefore, important. See other comments +** in this file for details. If in doubt, do not deviate from existing +** commenting and indentation practices when changing or adding code. +** +** $Id: vdbe.c,v 1.772 2008/08/02 15:10:09 danielk1977 Exp $ +*/ +#include "sqliteInt.h" +#include <ctype.h> +#include "vdbeInt.h" + +/* +** The following global variable is incremented every time a cursor +** moves, either by the OP_MoveXX, OP_Next, or OP_Prev opcodes. The test +** procedures use this information to make sure that indices are +** working correctly. This variable has no function other than to +** help verify the correct operation of the library. +*/ +#ifdef SQLITE_TEST +int sqlite3_search_count = 0; +#endif + +/* +** When this global variable is positive, it gets decremented once before +** each instruction in the VDBE. When reaches zero, the u1.isInterrupted +** field of the sqlite3 structure is set in order to simulate and interrupt. +** +** This facility is used for testing purposes only. It does not function +** in an ordinary build. +*/ +#ifdef SQLITE_TEST +int sqlite3_interrupt_count = 0; +#endif + +/* +** The next global variable is incremented each type the OP_Sort opcode +** is executed. The test procedures use this information to make sure that +** sorting is occurring or not occurring at appropriate times. This variable +** has no function other than to help verify the correct operation of the +** library. +*/ +#ifdef SQLITE_TEST +int sqlite3_sort_count = 0; +#endif + +/* +** The next global variable records the size of the largest MEM_Blob +** or MEM_Str that has been used by a VDBE opcode. The test procedures +** use this information to make sure that the zero-blob functionality +** is working correctly. This variable has no function other than to +** help verify the correct operation of the library. +*/ +#ifdef SQLITE_TEST +int sqlite3_max_blobsize = 0; +static void updateMaxBlobsize(Mem *p){ + if( (p->flags & (MEM_Str|MEM_Blob))!=0 && p->n>sqlite3_max_blobsize ){ + sqlite3_max_blobsize = p->n; + } +} +#endif + +/* +** Test a register to see if it exceeds the current maximum blob size. +** If it does, record the new maximum blob size. +*/ +#if defined(SQLITE_TEST) && !defined(SQLITE_OMIT_BUILTIN_TEST) +# define UPDATE_MAX_BLOBSIZE(P) updateMaxBlobsize(P) +#else +# define UPDATE_MAX_BLOBSIZE(P) +#endif + +/* +** Release the memory associated with a register. This +** leaves the Mem.flags field in an inconsistent state. +*/ +#define Release(P) if((P)->flags&MEM_Dyn){ sqlite3VdbeMemRelease(P); } + +/* +** Convert the given register into a string if it isn't one +** already. Return non-zero if a malloc() fails. +*/ +#define Stringify(P, enc) \ + if(((P)->flags&(MEM_Str|MEM_Blob))==0 && sqlite3VdbeMemStringify(P,enc)) \ + { goto no_mem; } + +/* +** An ephemeral string value (signified by the MEM_Ephem flag) contains +** a pointer to a dynamically allocated string where some other entity +** is responsible for deallocating that string. Because the register +** does not control the string, it might be deleted without the register +** knowing it. +** +** This routine converts an ephemeral string into a dynamically allocated +** string that the register itself controls. In other words, it +** converts an MEM_Ephem string into an MEM_Dyn string. +*/ +#define Deephemeralize(P) \ + if( ((P)->flags&MEM_Ephem)!=0 \ + && sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;} + +/* +** Call sqlite3VdbeMemExpandBlob() on the supplied value (type Mem*) +** P if required. +*/ +#define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0) + +/* +** Argument pMem points at a register that will be passed to a +** user-defined function or returned to the user as the result of a query. +** The second argument, 'db_enc' is the text encoding used by the vdbe for +** register variables. This routine sets the pMem->enc and pMem->type +** variables used by the sqlite3_value_*() routines. +*/ +#define storeTypeInfo(A,B) _storeTypeInfo(A) +static void _storeTypeInfo(Mem *pMem){ + int flags = pMem->flags; + if( flags & MEM_Null ){ + pMem->type = SQLITE_NULL; + } + else if( flags & MEM_Int ){ + pMem->type = SQLITE_INTEGER; + } + else if( flags & MEM_Real ){ + pMem->type = SQLITE_FLOAT; + } + else if( flags & MEM_Str ){ + pMem->type = SQLITE_TEXT; + }else{ + pMem->type = SQLITE_BLOB; + } +} + +/* +** Properties of opcodes. The OPFLG_INITIALIZER macro is +** created by mkopcodeh.awk during compilation. Data is obtained +** from the comments following the "case OP_xxxx:" statements in +** this file. +*/ +static unsigned char opcodeProperty[] = OPFLG_INITIALIZER; + +/* +** Return true if an opcode has any of the OPFLG_xxx properties +** specified by mask. +*/ +int sqlite3VdbeOpcodeHasProperty(int opcode, int mask){ + assert( opcode>0 && opcode<sizeof(opcodeProperty) ); + return (opcodeProperty[opcode]&mask)!=0; +} + +/* +** Allocate cursor number iCur. Return a pointer to it. Return NULL +** if we run out of memory. +*/ +static Cursor *allocateCursor( + Vdbe *p, + int iCur, + Op *pOp, + int iDb, + int isBtreeCursor +){ + /* Find the memory cell that will be used to store the blob of memory + ** required for this Cursor structure. It is convenient to use a + ** vdbe memory cell to manage the memory allocation required for a + ** Cursor structure for the following reasons: + ** + ** * Sometimes cursor numbers are used for a couple of different + ** purposes in a vdbe program. The different uses might require + ** different sized allocations. Memory cells provide growable + ** allocations. + ** + ** * When using ENABLE_MEMORY_MANAGEMENT, memory cell buffers can + ** be freed lazily via the sqlite3_release_memory() API. This + ** minimizes the number of malloc calls made by the system. + ** + ** Memory cells for cursors are allocated at the top of the address + ** space. Memory cell (p->nMem) corresponds to cursor 0. Space for + ** cursor 1 is managed by memory cell (p->nMem-1), etc. + */ + Mem *pMem = &p->aMem[p->nMem-iCur]; + + int nByte; + Cursor *pCx = 0; + /* If the opcode of pOp is OP_SetNumColumns, then pOp->p2 contains + ** the number of fields in the records contained in the table or + ** index being opened. Use this to reserve space for the + ** Cursor.aType[] array. + */ + int nField = 0; + if( pOp->opcode==OP_SetNumColumns || pOp->opcode==OP_OpenEphemeral ){ + nField = pOp->p2; + } + nByte = + sizeof(Cursor) + + (isBtreeCursor?sqlite3BtreeCursorSize():0) + + 2*nField*sizeof(u32); + + assert( iCur<p->nCursor ); + if( p->apCsr[iCur] ){ + sqlite3VdbeFreeCursor(p, p->apCsr[iCur]); + p->apCsr[iCur] = 0; + } + if( SQLITE_OK==sqlite3VdbeMemGrow(pMem, nByte, 0) ){ + p->apCsr[iCur] = pCx = (Cursor *)pMem->z; + memset(pMem->z, 0, nByte); + pCx->iDb = iDb; + pCx->nField = nField; + if( nField ){ + pCx->aType = (u32 *)&pMem->z[sizeof(Cursor)]; + } + if( isBtreeCursor ){ + pCx->pCursor = (BtCursor *)&pMem->z[sizeof(Cursor)+2*nField*sizeof(u32)]; + } + } + return pCx; +} + +/* +** Try to convert a value into a numeric representation if we can +** do so without loss of information. In other words, if the string +** looks like a number, convert it into a number. If it does not +** look like a number, leave it alone. +*/ +static void applyNumericAffinity(Mem *pRec){ + if( (pRec->flags & (MEM_Real|MEM_Int))==0 ){ + int realnum; + sqlite3VdbeMemNulTerminate(pRec); + if( (pRec->flags&MEM_Str) + && sqlite3IsNumber(pRec->z, &realnum, pRec->enc) ){ + i64 value; + sqlite3VdbeChangeEncoding(pRec, SQLITE_UTF8); + if( !realnum && sqlite3Atoi64(pRec->z, &value) ){ + pRec->u.i = value; + MemSetTypeFlag(pRec, MEM_Int); + }else{ + sqlite3VdbeMemRealify(pRec); + } + } + } +} + +/* +** Processing is determine by the affinity parameter: +** +** SQLITE_AFF_INTEGER: +** SQLITE_AFF_REAL: +** SQLITE_AFF_NUMERIC: +** Try to convert pRec to an integer representation or a +** floating-point representation if an integer representation +** is not possible. Note that the integer representation is +** always preferred, even if the affinity is REAL, because +** an integer representation is more space efficient on disk. +** +** SQLITE_AFF_TEXT: +** Convert pRec to a text representation. +** +** SQLITE_AFF_NONE: +** No-op. pRec is unchanged. +*/ +static void applyAffinity( + Mem *pRec, /* The value to apply affinity to */ + char affinity, /* The affinity to be applied */ + u8 enc /* Use this text encoding */ +){ + if( affinity==SQLITE_AFF_TEXT ){ + /* Only attempt the conversion to TEXT if there is an integer or real + ** representation (blob and NULL do not get converted) but no string + ** representation. + */ + if( 0==(pRec->flags&MEM_Str) && (pRec->flags&(MEM_Real|MEM_Int)) ){ + sqlite3VdbeMemStringify(pRec, enc); + } + pRec->flags &= ~(MEM_Real|MEM_Int); + }else if( affinity!=SQLITE_AFF_NONE ){ + assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL + || affinity==SQLITE_AFF_NUMERIC ); + applyNumericAffinity(pRec); + if( pRec->flags & MEM_Real ){ + sqlite3VdbeIntegerAffinity(pRec); + } + } +} + +/* +** Try to convert the type of a function argument or a result column +** into a numeric representation. Use either INTEGER or REAL whichever +** is appropriate. But only do the conversion if it is possible without +** loss of information and return the revised type of the argument. +** +** This is an EXPERIMENTAL api and is subject to change or removal. +*/ +int sqlite3_value_numeric_type(sqlite3_value *pVal){ + Mem *pMem = (Mem*)pVal; + applyNumericAffinity(pMem); + storeTypeInfo(pMem, 0); + return pMem->type; +} + +/* +** Exported version of applyAffinity(). This one works on sqlite3_value*, +** not the internal Mem* type. +*/ +void sqlite3ValueApplyAffinity( + sqlite3_value *pVal, + u8 affinity, + u8 enc +){ + applyAffinity((Mem *)pVal, affinity, enc); +} + +#ifdef SQLITE_DEBUG +/* +** Write a nice string representation of the contents of cell pMem +** into buffer zBuf, length nBuf. +*/ +void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){ + char *zCsr = zBuf; + int f = pMem->flags; + + static const char *const encnames[] = {"(X)", "(8)", "(16LE)", "(16BE)"}; + + if( f&MEM_Blob ){ + int i; + char c; + if( f & MEM_Dyn ){ + c = 'z'; + assert( (f & (MEM_Static|MEM_Ephem))==0 ); + }else if( f & MEM_Static ){ + c = 't'; + assert( (f & (MEM_Dyn|MEM_Ephem))==0 ); + }else if( f & MEM_Ephem ){ + c = 'e'; + assert( (f & (MEM_Static|MEM_Dyn))==0 ); + }else{ + c = 's'; + } + + sqlite3_snprintf(100, zCsr, "%c", c); + zCsr += strlen(zCsr); + sqlite3_snprintf(100, zCsr, "%d[", pMem->n); + zCsr += strlen(zCsr); + for(i=0; i<16 && i<pMem->n; i++){ + sqlite3_snprintf(100, zCsr, "%02X", ((int)pMem->z[i] & 0xFF)); + zCsr += strlen(zCsr); + } + for(i=0; i<16 && i<pMem->n; i++){ + char z = pMem->z[i]; + if( z<32 || z>126 ) *zCsr++ = '.'; + else *zCsr++ = z; + } + + sqlite3_snprintf(100, zCsr, "]%s", encnames[pMem->enc]); + zCsr += strlen(zCsr); + if( f & MEM_Zero ){ + sqlite3_snprintf(100, zCsr,"+%lldz",pMem->u.i); + zCsr += strlen(zCsr); + } + *zCsr = '\0'; + }else if( f & MEM_Str ){ + int j, k; + zBuf[0] = ' '; + if( f & MEM_Dyn ){ + zBuf[1] = 'z'; + assert( (f & (MEM_Static|MEM_Ephem))==0 ); + }else if( f & MEM_Static ){ + zBuf[1] = 't'; + assert( (f & (MEM_Dyn|MEM_Ephem))==0 ); + }else if( f & MEM_Ephem ){ + zBuf[1] = 'e'; + assert( (f & (MEM_Static|MEM_Dyn))==0 ); + }else{ + zBuf[1] = 's'; + } + k = 2; + sqlite3_snprintf(100, &zBuf[k], "%d", pMem->n); + k += strlen(&zBuf[k]); + zBuf[k++] = '['; + for(j=0; j<15 && j<pMem->n; j++){ + u8 c = pMem->z[j]; + if( c>=0x20 && c<0x7f ){ + zBuf[k++] = c; + }else{ + zBuf[k++] = '.'; + } + } + zBuf[k++] = ']'; + sqlite3_snprintf(100,&zBuf[k], encnames[pMem->enc]); + k += strlen(&zBuf[k]); + zBuf[k++] = 0; + } +} +#endif + +#ifdef SQLITE_DEBUG +/* +** Print the value of a register for tracing purposes: +*/ +static void memTracePrint(FILE *out, Mem *p){ + if( p->flags & MEM_Null ){ + fprintf(out, " NULL"); + }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){ + fprintf(out, " si:%lld", p->u.i); + }else if( p->flags & MEM_Int ){ + fprintf(out, " i:%lld", p->u.i); + }else if( p->flags & MEM_Real ){ + fprintf(out, " r:%g", p->r); + }else{ + char zBuf[200]; + sqlite3VdbeMemPrettyPrint(p, zBuf); + fprintf(out, " "); + fprintf(out, "%s", zBuf); + } +} +static void registerTrace(FILE *out, int iReg, Mem *p){ + fprintf(out, "REG[%d] = ", iReg); + memTracePrint(out, p); + fprintf(out, "\n"); +} +#endif + +#ifdef SQLITE_DEBUG +# define REGISTER_TRACE(R,M) if(p->trace)registerTrace(p->trace,R,M) +#else +# define REGISTER_TRACE(R,M) +#endif + + +#ifdef VDBE_PROFILE + +/* +** hwtime.h contains inline assembler code for implementing +** high-performance timing routines. +*/ +#include "hwtime.h" + +#endif + +/* +** The CHECK_FOR_INTERRUPT macro defined here looks to see if the +** sqlite3_interrupt() routine has been called. If it has been, then +** processing of the VDBE program is interrupted. +** +** This macro added to every instruction that does a jump in order to +** implement a loop. This test used to be on every single instruction, +** but that meant we more testing that we needed. By only testing the +** flag on jump instructions, we get a (small) speed improvement. +*/ +#define CHECK_FOR_INTERRUPT \ + if( db->u1.isInterrupted ) goto abort_due_to_interrupt; + +#ifdef SQLITE_DEBUG +static int fileExists(sqlite3 *db, const char *zFile){ + int res = 0; + int rc = SQLITE_OK; +#ifdef SQLITE_TEST + /* If we are currently testing IO errors, then do not call OsAccess() to + ** test for the presence of zFile. This is because any IO error that + ** occurs here will not be reported, causing the test to fail. + */ + extern int sqlite3_io_error_pending; + if( sqlite3_io_error_pending<=0 ) +#endif + rc = sqlite3OsAccess(db->pVfs, zFile, SQLITE_ACCESS_EXISTS, &res); + return (res && rc==SQLITE_OK); +} +#endif + +/* +** Execute as much of a VDBE program as we can then return. +** +** sqlite3VdbeMakeReady() must be called before this routine in order to +** close the program with a final OP_Halt and to set up the callbacks +** and the error message pointer. +** +** Whenever a row or result data is available, this routine will either +** invoke the result callback (if there is one) or return with +** SQLITE_ROW. +** +** If an attempt is made to open a locked database, then this routine +** will either invoke the busy callback (if there is one) or it will +** return SQLITE_BUSY. +** +** If an error occurs, an error message is written to memory obtained +** from sqlite3_malloc() and p->zErrMsg is made to point to that memory. +** The error code is stored in p->rc and this routine returns SQLITE_ERROR. +** +** If the callback ever returns non-zero, then the program exits +** immediately. There will be no error message but the p->rc field is +** set to SQLITE_ABORT and this routine will return SQLITE_ERROR. +** +** A memory allocation error causes p->rc to be set to SQLITE_NOMEM and this +** routine to return SQLITE_ERROR. +** +** Other fatal errors return SQLITE_ERROR. +** +** After this routine has finished, sqlite3VdbeFinalize() should be +** used to clean up the mess that was left behind. +*/ +int sqlite3VdbeExec( + Vdbe *p /* The VDBE */ +){ + int pc; /* The program counter */ + Op *pOp; /* Current operation */ + int rc = SQLITE_OK; /* Value to return */ + sqlite3 *db = p->db; /* The database */ + u8 encoding = ENC(db); /* The database encoding */ + Mem *pIn1, *pIn2, *pIn3; /* Input operands */ + Mem *pOut; /* Output operand */ + u8 opProperty; + int iCompare = 0; /* Result of last OP_Compare operation */ + int *aPermute = 0; /* Permuation of columns for OP_Compare */ +#ifdef VDBE_PROFILE + u64 start; /* CPU clock count at start of opcode */ + int origPc; /* Program counter at start of opcode */ +#endif +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK + int nProgressOps = 0; /* Opcodes executed since progress callback. */ +#endif + + assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */ + assert( db->magic==SQLITE_MAGIC_BUSY ); + sqlite3BtreeMutexArrayEnter(&p->aMutex); + if( p->rc==SQLITE_NOMEM ){ + /* This happens if a malloc() inside a call to sqlite3_column_text() or + ** sqlite3_column_text16() failed. */ + goto no_mem; + } + assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY ); + p->rc = SQLITE_OK; + assert( p->explain==0 ); + p->pResultSet = 0; + db->busyHandler.nBusy = 0; + CHECK_FOR_INTERRUPT; + sqlite3VdbeIOTraceSql(p); +#ifdef SQLITE_DEBUG + sqlite3BeginBenignMalloc(); + if( p->pc==0 + && ((p->db->flags & SQLITE_VdbeListing) || fileExists(db, "vdbe_explain")) + ){ + int i; + printf("VDBE Program Listing:\n"); + sqlite3VdbePrintSql(p); + for(i=0; i<p->nOp; i++){ + sqlite3VdbePrintOp(stdout, i, &p->aOp[i]); + } + } + if( fileExists(db, "vdbe_trace") ){ + p->trace = stdout; + } + sqlite3EndBenignMalloc(); +#endif + for(pc=p->pc; rc==SQLITE_OK; pc++){ + assert( pc>=0 && pc<p->nOp ); + if( db->mallocFailed ) goto no_mem; +#ifdef VDBE_PROFILE + origPc = pc; + start = sqlite3Hwtime(); +#endif + pOp = &p->aOp[pc]; + + /* Only allow tracing if SQLITE_DEBUG is defined. + */ +#ifdef SQLITE_DEBUG + if( p->trace ){ + if( pc==0 ){ + printf("VDBE Execution Trace:\n"); + sqlite3VdbePrintSql(p); + } + sqlite3VdbePrintOp(p->trace, pc, pOp); + } + if( p->trace==0 && pc==0 ){ + sqlite3BeginBenignMalloc(); + if( fileExists(db, "vdbe_sqltrace") ){ + sqlite3VdbePrintSql(p); + } + sqlite3EndBenignMalloc(); + } +#endif + + + /* Check to see if we need to simulate an interrupt. This only happens + ** if we have a special test build. + */ +#ifdef SQLITE_TEST + if( sqlite3_interrupt_count>0 ){ + sqlite3_interrupt_count--; + if( sqlite3_interrupt_count==0 ){ + sqlite3_interrupt(db); + } + } +#endif + +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK + /* Call the progress callback if it is configured and the required number + ** of VDBE ops have been executed (either since this invocation of + ** sqlite3VdbeExec() or since last time the progress callback was called). + ** If the progress callback returns non-zero, exit the virtual machine with + ** a return code SQLITE_ABORT. + */ + if( db->xProgress ){ + if( db->nProgressOps==nProgressOps ){ + int prc; + if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; + prc =db->xProgress(db->pProgressArg); + if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; + if( prc!=0 ){ + rc = SQLITE_INTERRUPT; + goto vdbe_error_halt; + } + nProgressOps = 0; + } + nProgressOps++; + } +#endif + + /* Do common setup processing for any opcode that is marked + ** with the "out2-prerelease" tag. Such opcodes have a single + ** output which is specified by the P2 parameter. The P2 register + ** is initialized to a NULL. + */ + opProperty = opcodeProperty[pOp->opcode]; + if( (opProperty & OPFLG_OUT2_PRERELEASE)!=0 ){ + assert( pOp->p2>0 ); + assert( pOp->p2<=p->nMem ); + pOut = &p->aMem[pOp->p2]; + sqlite3VdbeMemReleaseExternal(pOut); + pOut->flags = MEM_Null; + }else + + /* Do common setup for opcodes marked with one of the following + ** combinations of properties. + ** + ** in1 + ** in1 in2 + ** in1 in2 out3 + ** in1 in3 + ** + ** Variables pIn1, pIn2, and pIn3 are made to point to appropriate + ** registers for inputs. Variable pOut points to the output register. + */ + if( (opProperty & OPFLG_IN1)!=0 ){ + assert( pOp->p1>0 ); + assert( pOp->p1<=p->nMem ); + pIn1 = &p->aMem[pOp->p1]; + REGISTER_TRACE(pOp->p1, pIn1); + if( (opProperty & OPFLG_IN2)!=0 ){ + assert( pOp->p2>0 ); + assert( pOp->p2<=p->nMem ); + pIn2 = &p->aMem[pOp->p2]; + REGISTER_TRACE(pOp->p2, pIn2); + if( (opProperty & OPFLG_OUT3)!=0 ){ + assert( pOp->p3>0 ); + assert( pOp->p3<=p->nMem ); + pOut = &p->aMem[pOp->p3]; + } + }else if( (opProperty & OPFLG_IN3)!=0 ){ + assert( pOp->p3>0 ); + assert( pOp->p3<=p->nMem ); + pIn3 = &p->aMem[pOp->p3]; + REGISTER_TRACE(pOp->p3, pIn3); + } + }else if( (opProperty & OPFLG_IN2)!=0 ){ + assert( pOp->p2>0 ); + assert( pOp->p2<=p->nMem ); + pIn2 = &p->aMem[pOp->p2]; + REGISTER_TRACE(pOp->p2, pIn2); + }else if( (opProperty & OPFLG_IN3)!=0 ){ + assert( pOp->p3>0 ); + assert( pOp->p3<=p->nMem ); + pIn3 = &p->aMem[pOp->p3]; + REGISTER_TRACE(pOp->p3, pIn3); + } + + switch( pOp->opcode ){ + +/***************************************************************************** +** What follows is a massive switch statement where each case implements a +** separate instruction in the virtual machine. If we follow the usual +** indentation conventions, each case should be indented by 6 spaces. But +** that is a lot of wasted space on the left margin. So the code within +** the switch statement will break with convention and be flush-left. Another +** big comment (similar to this one) will mark the point in the code where +** we transition back to normal indentation. +** +** The formatting of each case is important. The makefile for SQLite +** generates two C files "opcodes.h" and "opcodes.c" by scanning this +** file looking for lines that begin with "case OP_". The opcodes.h files +** will be filled with #defines that give unique integer values to each +** opcode and the opcodes.c file is filled with an array of strings where +** each string is the symbolic name for the corresponding opcode. If the +** case statement is followed by a comment of the form "/# same as ... #/" +** that comment is used to determine the particular value of the opcode. +** +** Other keywords in the comment that follows each case are used to +** construct the OPFLG_INITIALIZER value that initializes opcodeProperty[]. +** Keywords include: in1, in2, in3, out2_prerelease, out2, out3. See +** the mkopcodeh.awk script for additional information. +** +** Documentation about VDBE opcodes is generated by scanning this file +** for lines of that contain "Opcode:". That line and all subsequent +** comment lines are used in the generation of the opcode.html documentation +** file. +** +** SUMMARY: +** +** Formatting is important to scripts that scan this file. +** Do not deviate from the formatting style currently in use. +** +*****************************************************************************/ + +/* Opcode: Goto * P2 * * * +** +** An unconditional jump to address P2. +** The next instruction executed will be +** the one at index P2 from the beginning of +** the program. +*/ +case OP_Goto: { /* jump */ + CHECK_FOR_INTERRUPT; + pc = pOp->p2 - 1; + break; +} + +/* Opcode: Gosub P1 P2 * * * +** +** Write the current address onto register P1 +** and then jump to address P2. +*/ +case OP_Gosub: { /* jump */ + assert( pOp->p1>0 ); + assert( pOp->p1<=p->nMem ); + pIn1 = &p->aMem[pOp->p1]; + assert( (pIn1->flags & MEM_Dyn)==0 ); + pIn1->flags = MEM_Int; + pIn1->u.i = pc; + REGISTER_TRACE(pOp->p1, pIn1); + pc = pOp->p2 - 1; + break; +} + +/* Opcode: Return P1 * * * * +** +** Jump to the next instruction after the address in register P1. +*/ +case OP_Return: { /* in1 */ + assert( pIn1->flags & MEM_Int ); + pc = pIn1->u.i; + break; +} + +/* Opcode: Yield P1 * * * * +** +** Swap the program counter with the value in register P1. +*/ +case OP_Yield: { + int pcDest; + assert( pOp->p1>0 ); + assert( pOp->p1<=p->nMem ); + pIn1 = &p->aMem[pOp->p1]; + assert( (pIn1->flags & MEM_Dyn)==0 ); + pIn1->flags = MEM_Int; + pcDest = pIn1->u.i; + pIn1->u.i = pc; + REGISTER_TRACE(pOp->p1, pIn1); + pc = pcDest; + break; +} + + +/* Opcode: Halt P1 P2 * P4 * +** +** Exit immediately. All open cursors, Fifos, etc are closed +** automatically. +** +** P1 is the result code returned by sqlite3_exec(), sqlite3_reset(), +** or sqlite3_finalize(). For a normal halt, this should be SQLITE_OK (0). +** For errors, it can be some other value. If P1!=0 then P2 will determine +** whether or not to rollback the current transaction. Do not rollback +** if P2==OE_Fail. Do the rollback if P2==OE_Rollback. If P2==OE_Abort, +** then back out all changes that have occurred during this execution of the +** VDBE, but do not rollback the transaction. +** +** If P4 is not null then it is an error message string. +** +** There is an implied "Halt 0 0 0" instruction inserted at the very end of +** every program. So a jump past the last instruction of the program +** is the same as executing Halt. +*/ +case OP_Halt: { + p->rc = pOp->p1; + p->pc = pc; + p->errorAction = pOp->p2; + if( pOp->p4.z ){ + sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z); + } + rc = sqlite3VdbeHalt(p); + assert( rc==SQLITE_BUSY || rc==SQLITE_OK ); + if( rc==SQLITE_BUSY ){ + p->rc = rc = SQLITE_BUSY; + }else{ + rc = p->rc ? SQLITE_ERROR : SQLITE_DONE; + } + goto vdbe_return; +} + +/* Opcode: Integer P1 P2 * * * +** +** The 32-bit integer value P1 is written into register P2. +*/ +case OP_Integer: { /* out2-prerelease */ + pOut->flags = MEM_Int; + pOut->u.i = pOp->p1; + break; +} + +/* Opcode: Int64 * P2 * P4 * +** +** P4 is a pointer to a 64-bit integer value. +** Write that value into register P2. +*/ +case OP_Int64: { /* out2-prerelease */ + assert( pOp->p4.pI64!=0 ); + pOut->flags = MEM_Int; + pOut->u.i = *pOp->p4.pI64; + break; +} + +/* Opcode: Real * P2 * P4 * +** +** P4 is a pointer to a 64-bit floating point value. +** Write that value into register P2. +*/ +case OP_Real: { /* same as TK_FLOAT, out2-prerelease */ + pOut->flags = MEM_Real; + assert( !sqlite3IsNaN(*pOp->p4.pReal) ); + pOut->r = *pOp->p4.pReal; + break; +} + +/* Opcode: String8 * P2 * P4 * +** +** P4 points to a nul terminated UTF-8 string. This opcode is transformed +** into an OP_String before it is executed for the first time. +*/ +case OP_String8: { /* same as TK_STRING, out2-prerelease */ + assert( pOp->p4.z!=0 ); + pOp->opcode = OP_String; + pOp->p1 = strlen(pOp->p4.z); + +#ifndef SQLITE_OMIT_UTF16 + if( encoding!=SQLITE_UTF8 ){ + sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC); + if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem; + if( SQLITE_OK!=sqlite3VdbeMemMakeWriteable(pOut) ) goto no_mem; + pOut->zMalloc = 0; + pOut->flags |= MEM_Static; + pOut->flags &= ~MEM_Dyn; + if( pOp->p4type==P4_DYNAMIC ){ + sqlite3DbFree(db, pOp->p4.z); + } + pOp->p4type = P4_DYNAMIC; + pOp->p4.z = pOut->z; + pOp->p1 = pOut->n; + if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + goto too_big; + } + UPDATE_MAX_BLOBSIZE(pOut); + break; + } +#endif + if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + goto too_big; + } + /* Fall through to the next case, OP_String */ +} + +/* Opcode: String P1 P2 * P4 * +** +** The string value P4 of length P1 (bytes) is stored in register P2. +*/ +case OP_String: { /* out2-prerelease */ + assert( pOp->p4.z!=0 ); + pOut->flags = MEM_Str|MEM_Static|MEM_Term; + pOut->z = pOp->p4.z; + pOut->n = pOp->p1; + pOut->enc = encoding; + UPDATE_MAX_BLOBSIZE(pOut); + break; +} + +/* Opcode: Null * P2 * * * +** +** Write a NULL into register P2. +*/ +case OP_Null: { /* out2-prerelease */ + break; +} + + +#ifndef SQLITE_OMIT_BLOB_LITERAL +/* Opcode: Blob P1 P2 * P4 +** +** P4 points to a blob of data P1 bytes long. Store this +** blob in register P2. This instruction is not coded directly +** by the compiler. Instead, the compiler layer specifies +** an OP_HexBlob opcode, with the hex string representation of +** the blob as P4. This opcode is transformed to an OP_Blob +** the first time it is executed. +*/ +case OP_Blob: { /* out2-prerelease */ + assert( pOp->p1 <= SQLITE_MAX_LENGTH ); + sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0); + pOut->enc = encoding; + UPDATE_MAX_BLOBSIZE(pOut); + break; +} +#endif /* SQLITE_OMIT_BLOB_LITERAL */ + +/* Opcode: Variable P1 P2 * * * +** +** The value of variable P1 is written into register P2. A variable is +** an unknown in the original SQL string as handed to sqlite3_compile(). +** Any occurrence of the '?' character in the original SQL is considered +** a variable. Variables in the SQL string are number from left to +** right beginning with 1. The values of variables are set using the +** sqlite3_bind() API. +*/ +case OP_Variable: { /* out2-prerelease */ + int j = pOp->p1 - 1; + Mem *pVar; + assert( j>=0 && j<p->nVar ); + + pVar = &p->aVar[j]; + if( sqlite3VdbeMemTooBig(pVar) ){ + goto too_big; + } + sqlite3VdbeMemShallowCopy(pOut, &p->aVar[j], MEM_Static); + UPDATE_MAX_BLOBSIZE(pOut); + break; +} + +/* Opcode: Move P1 P2 P3 * * +** +** Move the values in register P1..P1+P3-1 over into +** registers P2..P2+P3-1. Registers P1..P1+P1-1 are +** left holding a NULL. It is an error for register ranges +** P1..P1+P3-1 and P2..P2+P3-1 to overlap. +*/ +case OP_Move: { + char *zMalloc; + int n = pOp->p3; + int p1 = pOp->p1; + int p2 = pOp->p2; + assert( n>0 ); + assert( p1>0 ); + assert( p1+n<p->nMem ); + pIn1 = &p->aMem[p1]; + assert( p2>0 ); + assert( p2+n<p->nMem ); + pOut = &p->aMem[p2]; + assert( p1+n<=p2 || p2+n<=p1 ); + while( n-- ){ + zMalloc = pOut->zMalloc; + pOut->zMalloc = 0; + sqlite3VdbeMemMove(pOut, pIn1); + pIn1->zMalloc = zMalloc; + REGISTER_TRACE(p2++, pOut); + pIn1++; + pOut++; + } + break; +} + +/* Opcode: Copy P1 P2 * * * +** +** Make a copy of register P1 into register P2. +** +** This instruction makes a deep copy of the value. A duplicate +** is made of any string or blob constant. See also OP_SCopy. +*/ +case OP_Copy: { + assert( pOp->p1>0 ); + assert( pOp->p1<=p->nMem ); + pIn1 = &p->aMem[pOp->p1]; + assert( pOp->p2>0 ); + assert( pOp->p2<=p->nMem ); + pOut = &p->aMem[pOp->p2]; + assert( pOut!=pIn1 ); + sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); + Deephemeralize(pOut); + REGISTER_TRACE(pOp->p2, pOut); + break; +} + +/* Opcode: SCopy P1 P2 * * * +** +** Make a shallow copy of register P1 into register P2. +** +** This instruction makes a shallow copy of the value. If the value +** is a string or blob, then the copy is only a pointer to the +** original and hence if the original changes so will the copy. +** Worse, if the original is deallocated, the copy becomes invalid. +** Thus the program must guarantee that the original will not change +** during the lifetime of the copy. Use OP_Copy to make a complete +** copy. +*/ +case OP_SCopy: { + assert( pOp->p1>0 ); + assert( pOp->p1<=p->nMem ); + pIn1 = &p->aMem[pOp->p1]; + REGISTER_TRACE(pOp->p1, pIn1); + assert( pOp->p2>0 ); + assert( pOp->p2<=p->nMem ); + pOut = &p->aMem[pOp->p2]; + assert( pOut!=pIn1 ); + sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); + REGISTER_TRACE(pOp->p2, pOut); + break; +} + +/* Opcode: ResultRow P1 P2 * * * +** +** The registers P1 through P1+P2-1 contain a single row of +** results. This opcode causes the sqlite3_step() call to terminate +** with an SQLITE_ROW return code and it sets up the sqlite3_stmt +** structure to provide access to the top P1 values as the result +** row. +*/ +case OP_ResultRow: { + Mem *pMem; + int i; + assert( p->nResColumn==pOp->p2 ); + assert( pOp->p1>0 ); + assert( pOp->p1+pOp->p2<=p->nMem ); + + /* Invalidate all ephemeral cursor row caches */ + p->cacheCtr = (p->cacheCtr + 2)|1; + + /* Make sure the results of the current row are \000 terminated + ** and have an assigned type. The results are de-ephemeralized as + ** as side effect. + */ + pMem = p->pResultSet = &p->aMem[pOp->p1]; + for(i=0; i<pOp->p2; i++){ + sqlite3VdbeMemNulTerminate(&pMem[i]); + storeTypeInfo(&pMem[i], encoding); + REGISTER_TRACE(pOp->p1+i, &pMem[i]); + } + if( db->mallocFailed ) goto no_mem; + + /* Return SQLITE_ROW + */ + p->nCallback++; + p->pc = pc + 1; + rc = SQLITE_ROW; + goto vdbe_return; +} + +/* Opcode: Concat P1 P2 P3 * * +** +** Add the text in register P1 onto the end of the text in +** register P2 and store the result in register P3. +** If either the P1 or P2 text are NULL then store NULL in P3. +** +** P3 = P2 || P1 +** +** It is illegal for P1 and P3 to be the same register. Sometimes, +** if P3 is the same register as P2, the implementation is able +** to avoid a memcpy(). +*/ +case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ + i64 nByte; + + assert( pIn1!=pOut ); + if( (pIn1->flags | pIn2->flags) & MEM_Null ){ + sqlite3VdbeMemSetNull(pOut); + break; + } + ExpandBlob(pIn1); + Stringify(pIn1, encoding); + ExpandBlob(pIn2); + Stringify(pIn2, encoding); + nByte = pIn1->n + pIn2->n; + if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + goto too_big; + } + MemSetTypeFlag(pOut, MEM_Str); + if( sqlite3VdbeMemGrow(pOut, nByte+2, pOut==pIn2) ){ + goto no_mem; + } + if( pOut!=pIn2 ){ + memcpy(pOut->z, pIn2->z, pIn2->n); + } + memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n); + pOut->z[nByte] = 0; + pOut->z[nByte+1] = 0; + pOut->flags |= MEM_Term; + pOut->n = nByte; + pOut->enc = encoding; + UPDATE_MAX_BLOBSIZE(pOut); + break; +} + +/* Opcode: Add P1 P2 P3 * * +** +** Add the value in register P1 to the value in register P2 +** and store the result in register P3. +** If either input is NULL, the result is NULL. +*/ +/* Opcode: Multiply P1 P2 P3 * * +** +** +** Multiply the value in register P1 by the value in register P2 +** and store the result in register P3. +** If either input is NULL, the result is NULL. +*/ +/* Opcode: Subtract P1 P2 P3 * * +** +** Subtract the value in register P1 from the value in register P2 +** and store the result in register P3. +** If either input is NULL, the result is NULL. +*/ +/* Opcode: Divide P1 P2 P3 * * +** +** Divide the value in register P1 by the value in register P2 +** and store the result in register P3. If the value in register P2 +** is zero, then the result is NULL. +** If either input is NULL, the result is NULL. +*/ +/* Opcode: Remainder P1 P2 P3 * * +** +** Compute the remainder after integer division of the value in +** register P1 by the value in register P2 and store the result in P3. +** If the value in register P2 is zero the result is NULL. +** If either operand is NULL, the result is NULL. +*/ +case OP_Add: /* same as TK_PLUS, in1, in2, out3 */ +case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */ +case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */ +case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */ +case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ + int flags; + applyNumericAffinity(pIn1); + applyNumericAffinity(pIn2); + flags = pIn1->flags | pIn2->flags; + if( (flags & MEM_Null)!=0 ) goto arithmetic_result_is_null; + if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){ + i64 a, b; + a = pIn1->u.i; + b = pIn2->u.i; + switch( pOp->opcode ){ + case OP_Add: b += a; break; + case OP_Subtract: b -= a; break; + case OP_Multiply: b *= a; break; + case OP_Divide: { + if( a==0 ) goto arithmetic_result_is_null; + /* Dividing the largest possible negative 64-bit integer (1<<63) by + ** -1 returns an integer too large to store in a 64-bit data-type. On + ** some architectures, the value overflows to (1<<63). On others, + ** a SIGFPE is issued. The following statement normalizes this + ** behavior so that all architectures behave as if integer + ** overflow occurred. + */ + if( a==-1 && b==SMALLEST_INT64 ) a = 1; + b /= a; + break; + } + default: { + if( a==0 ) goto arithmetic_result_is_null; + if( a==-1 ) a = 1; + b %= a; + break; + } + } + pOut->u.i = b; + MemSetTypeFlag(pOut, MEM_Int); + }else{ + double a, b; + a = sqlite3VdbeRealValue(pIn1); + b = sqlite3VdbeRealValue(pIn2); + switch( pOp->opcode ){ + case OP_Add: b += a; break; + case OP_Subtract: b -= a; break; + case OP_Multiply: b *= a; break; + case OP_Divide: { + if( a==0.0 ) goto arithmetic_result_is_null; + b /= a; + break; + } + default: { + i64 ia = (i64)a; + i64 ib = (i64)b; + if( ia==0 ) goto arithmetic_result_is_null; + if( ia==-1 ) ia = 1; + b = ib % ia; + break; + } + } + if( sqlite3IsNaN(b) ){ + goto arithmetic_result_is_null; + } + pOut->r = b; + MemSetTypeFlag(pOut, MEM_Real); + if( (flags & MEM_Real)==0 ){ + sqlite3VdbeIntegerAffinity(pOut); + } + } + break; + +arithmetic_result_is_null: + sqlite3VdbeMemSetNull(pOut); + break; +} + +/* Opcode: CollSeq * * P4 +** +** P4 is a pointer to a CollSeq struct. If the next call to a user function +** or aggregate calls sqlite3GetFuncCollSeq(), this collation sequence will +** be returned. This is used by the built-in min(), max() and nullif() +** functions. +** +** The interface used by the implementation of the aforementioned functions +** to retrieve the collation sequence set by this opcode is not available +** publicly, only to user functions defined in func.c. +*/ +case OP_CollSeq: { + assert( pOp->p4type==P4_COLLSEQ ); + break; +} + +/* Opcode: Function P1 P2 P3 P4 P5 +** +** Invoke a user function (P4 is a pointer to a Function structure that +** defines the function) with P5 arguments taken from register P2 and +** successors. The result of the function is stored in register P3. +** Register P3 must not be one of the function inputs. +** +** P1 is a 32-bit bitmask indicating whether or not each argument to the +** function was determined to be constant at compile time. If the first +** argument was constant then bit 0 of P1 is set. This is used to determine +** whether meta data associated with a user function argument using the +** sqlite3_set_auxdata() API may be safely retained until the next +** invocation of this opcode. +** +** See also: AggStep and AggFinal +*/ +case OP_Function: { + int i; + Mem *pArg; + sqlite3_context ctx; + sqlite3_value **apVal; + int n = pOp->p5; + + apVal = p->apArg; + assert( apVal || n==0 ); + + assert( n==0 || (pOp->p2>0 && pOp->p2+n<=p->nMem) ); + assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n ); + pArg = &p->aMem[pOp->p2]; + for(i=0; i<n; i++, pArg++){ + apVal[i] = pArg; + storeTypeInfo(pArg, encoding); + REGISTER_TRACE(pOp->p2, pArg); + } + + assert( pOp->p4type==P4_FUNCDEF || pOp->p4type==P4_VDBEFUNC ); + if( pOp->p4type==P4_FUNCDEF ){ + ctx.pFunc = pOp->p4.pFunc; + ctx.pVdbeFunc = 0; + }else{ + ctx.pVdbeFunc = (VdbeFunc*)pOp->p4.pVdbeFunc; + ctx.pFunc = ctx.pVdbeFunc->pFunc; + } + + assert( pOp->p3>0 && pOp->p3<=p->nMem ); + pOut = &p->aMem[pOp->p3]; + ctx.s.flags = MEM_Null; + ctx.s.db = db; + ctx.s.xDel = 0; + ctx.s.zMalloc = 0; + + /* The output cell may already have a buffer allocated. Move + ** the pointer to ctx.s so in case the user-function can use + ** the already allocated buffer instead of allocating a new one. + */ + sqlite3VdbeMemMove(&ctx.s, pOut); + MemSetTypeFlag(&ctx.s, MEM_Null); + + ctx.isError = 0; + if( ctx.pFunc->needCollSeq ){ + assert( pOp>p->aOp ); + assert( pOp[-1].p4type==P4_COLLSEQ ); + assert( pOp[-1].opcode==OP_CollSeq ); + ctx.pColl = pOp[-1].p4.pColl; + } + if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; + (*ctx.pFunc->xFunc)(&ctx, n, apVal); + if( sqlite3SafetyOn(db) ){ + sqlite3VdbeMemRelease(&ctx.s); + goto abort_due_to_misuse; + } + if( db->mallocFailed ){ + /* Even though a malloc() has failed, the implementation of the + ** user function may have called an sqlite3_result_XXX() function + ** to return a value. The following call releases any resources + ** associated with such a value. + ** + ** Note: Maybe MemRelease() should be called if sqlite3SafetyOn() + ** fails also (the if(...) statement above). But if people are + ** misusing sqlite, they have bigger problems than a leaked value. + */ + sqlite3VdbeMemRelease(&ctx.s); + goto no_mem; + } + + /* If any auxiliary data functions have been called by this user function, + ** immediately call the destructor for any non-static values. + */ + if( ctx.pVdbeFunc ){ + sqlite3VdbeDeleteAuxData(ctx.pVdbeFunc, pOp->p1); + pOp->p4.pVdbeFunc = ctx.pVdbeFunc; + pOp->p4type = P4_VDBEFUNC; + } + + /* If the function returned an error, throw an exception */ + if( ctx.isError ){ + sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&ctx.s)); + rc = ctx.isError; + } + + /* Copy the result of the function into register P3 */ + sqlite3VdbeChangeEncoding(&ctx.s, encoding); + sqlite3VdbeMemMove(pOut, &ctx.s); + if( sqlite3VdbeMemTooBig(pOut) ){ + goto too_big; + } + REGISTER_TRACE(pOp->p3, pOut); + UPDATE_MAX_BLOBSIZE(pOut); + break; +} + +/* Opcode: BitAnd P1 P2 P3 * * +** +** Take the bit-wise AND of the values in register P1 and P2 and +** store the result in register P3. +** If either input is NULL, the result is NULL. +*/ +/* Opcode: BitOr P1 P2 P3 * * +** +** Take the bit-wise OR of the values in register P1 and P2 and +** store the result in register P3. +** If either input is NULL, the result is NULL. +*/ +/* Opcode: ShiftLeft P1 P2 P3 * * +** +** Shift the integer value in register P2 to the left by the +** number of bits specified by the integer in regiser P1. +** Store the result in register P3. +** If either input is NULL, the result is NULL. +*/ +/* Opcode: ShiftRight P1 P2 P3 * * +** +** Shift the integer value in register P2 to the right by the +** number of bits specified by the integer in register P1. +** Store the result in register P3. +** If either input is NULL, the result is NULL. +*/ +case OP_BitAnd: /* same as TK_BITAND, in1, in2, out3 */ +case OP_BitOr: /* same as TK_BITOR, in1, in2, out3 */ +case OP_ShiftLeft: /* same as TK_LSHIFT, in1, in2, out3 */ +case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */ + i64 a, b; + + if( (pIn1->flags | pIn2->flags) & MEM_Null ){ + sqlite3VdbeMemSetNull(pOut); + break; + } + a = sqlite3VdbeIntValue(pIn2); + b = sqlite3VdbeIntValue(pIn1); + switch( pOp->opcode ){ + case OP_BitAnd: a &= b; break; + case OP_BitOr: a |= b; break; + case OP_ShiftLeft: a <<= b; break; + default: assert( pOp->opcode==OP_ShiftRight ); + a >>= b; break; + } + pOut->u.i = a; + MemSetTypeFlag(pOut, MEM_Int); + break; +} + +/* Opcode: AddImm P1 P2 * * * +** +** Add the constant P2 to the value in register P1. +** The result is always an integer. +** +** To force any register to be an integer, just add 0. +*/ +case OP_AddImm: { /* in1 */ + sqlite3VdbeMemIntegerify(pIn1); + pIn1->u.i += pOp->p2; + break; +} + +/* Opcode: ForceInt P1 P2 P3 * * +** +** Convert value in register P1 into an integer. If the value +** in P1 is not numeric (meaning that is is a NULL or a string that +** does not look like an integer or floating point number) then +** jump to P2. If the value in P1 is numeric then +** convert it into the least integer that is greater than or equal to its +** current value if P3==0, or to the least integer that is strictly +** greater than its current value if P3==1. +*/ +case OP_ForceInt: { /* jump, in1 */ + i64 v; + applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding); + if( (pIn1->flags & (MEM_Int|MEM_Real))==0 ){ + pc = pOp->p2 - 1; + break; + } + if( pIn1->flags & MEM_Int ){ + v = pIn1->u.i + (pOp->p3!=0); + }else{ + assert( pIn1->flags & MEM_Real ); + v = (sqlite3_int64)pIn1->r; + if( pIn1->r>(double)v ) v++; + if( pOp->p3 && pIn1->r==(double)v ) v++; + } + pIn1->u.i = v; + MemSetTypeFlag(pIn1, MEM_Int); + break; +} + +/* Opcode: MustBeInt P1 P2 * * * +** +** Force the value in register P1 to be an integer. If the value +** in P1 is not an integer and cannot be converted into an integer +** without data loss, then jump immediately to P2, or if P2==0 +** raise an SQLITE_MISMATCH exception. +*/ +case OP_MustBeInt: { /* jump, in1 */ + applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding); + if( (pIn1->flags & MEM_Int)==0 ){ + if( pOp->p2==0 ){ + rc = SQLITE_MISMATCH; + goto abort_due_to_error; + }else{ + pc = pOp->p2 - 1; + } + }else{ + MemSetTypeFlag(pIn1, MEM_Int); + } + break; +} + +/* Opcode: RealAffinity P1 * * * * +** +** If register P1 holds an integer convert it to a real value. +** +** This opcode is used when extracting information from a column that +** has REAL affinity. Such column values may still be stored as +** integers, for space efficiency, but after extraction we want them +** to have only a real value. +*/ +case OP_RealAffinity: { /* in1 */ + if( pIn1->flags & MEM_Int ){ + sqlite3VdbeMemRealify(pIn1); + } + break; +} + +#ifndef SQLITE_OMIT_CAST +/* Opcode: ToText P1 * * * * +** +** Force the value in register P1 to be text. +** If the value is numeric, convert it to a string using the +** equivalent of printf(). Blob values are unchanged and +** are afterwards simply interpreted as text. +** +** A NULL value is not changed by this routine. It remains NULL. +*/ +case OP_ToText: { /* same as TK_TO_TEXT, in1 */ + if( pIn1->flags & MEM_Null ) break; + assert( MEM_Str==(MEM_Blob>>3) ); + pIn1->flags |= (pIn1->flags&MEM_Blob)>>3; + applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding); + rc = ExpandBlob(pIn1); + assert( pIn1->flags & MEM_Str || db->mallocFailed ); + pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_Blob); + UPDATE_MAX_BLOBSIZE(pIn1); + break; +} + +/* Opcode: ToBlob P1 * * * * +** +** Force the value in register P1 to be a BLOB. +** If the value is numeric, convert it to a string first. +** Strings are simply reinterpreted as blobs with no change +** to the underlying data. +** +** A NULL value is not changed by this routine. It remains NULL. +*/ +case OP_ToBlob: { /* same as TK_TO_BLOB, in1 */ + if( pIn1->flags & MEM_Null ) break; + if( (pIn1->flags & MEM_Blob)==0 ){ + applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding); + assert( pIn1->flags & MEM_Str || db->mallocFailed ); + } + MemSetTypeFlag(pIn1, MEM_Blob); + UPDATE_MAX_BLOBSIZE(pIn1); + break; +} + +/* Opcode: ToNumeric P1 * * * * +** +** Force the value in register P1 to be numeric (either an +** integer or a floating-point number.) +** If the value is text or blob, try to convert it to an using the +** equivalent of atoi() or atof() and store 0 if no such conversion +** is possible. +** +** A NULL value is not changed by this routine. It remains NULL. +*/ +case OP_ToNumeric: { /* same as TK_TO_NUMERIC, in1 */ + if( (pIn1->flags & (MEM_Null|MEM_Int|MEM_Real))==0 ){ + sqlite3VdbeMemNumerify(pIn1); + } + break; +} +#endif /* SQLITE_OMIT_CAST */ + +/* Opcode: ToInt P1 * * * * +** +** Force the value in register P1 be an integer. If +** The value is currently a real number, drop its fractional part. +** If the value is text or blob, try to convert it to an integer using the +** equivalent of atoi() and store 0 if no such conversion is possible. +** +** A NULL value is not changed by this routine. It remains NULL. +*/ +case OP_ToInt: { /* same as TK_TO_INT, in1 */ + if( (pIn1->flags & MEM_Null)==0 ){ + sqlite3VdbeMemIntegerify(pIn1); + } + break; +} + +#ifndef SQLITE_OMIT_CAST +/* Opcode: ToReal P1 * * * * +** +** Force the value in register P1 to be a floating point number. +** If The value is currently an integer, convert it. +** If the value is text or blob, try to convert it to an integer using the +** equivalent of atoi() and store 0.0 if no such conversion is possible. +** +** A NULL value is not changed by this routine. It remains NULL. +*/ +case OP_ToReal: { /* same as TK_TO_REAL, in1 */ + if( (pIn1->flags & MEM_Null)==0 ){ + sqlite3VdbeMemRealify(pIn1); + } + break; +} +#endif /* SQLITE_OMIT_CAST */ + +/* Opcode: Lt P1 P2 P3 P4 P5 +** +** Compare the values in register P1 and P3. If reg(P3)<reg(P1) then +** jump to address P2. +** +** If the SQLITE_JUMPIFNULL bit of P5 is set and either reg(P1) or +** reg(P3) is NULL then take the jump. If the SQLITE_JUMPIFNULL +** bit is clear then fall thru if either operand is NULL. +** +** The SQLITE_AFF_MASK portion of P5 must be an affinity character - +** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made +** to coerce both inputs according to this affinity before the +** comparison is made. If the SQLITE_AFF_MASK is 0x00, then numeric +** affinity is used. Note that the affinity conversions are stored +** back into the input registers P1 and P3. So this opcode can cause +** persistent changes to registers P1 and P3. +** +** Once any conversions have taken place, and neither value is NULL, +** the values are compared. If both values are blobs then memcmp() is +** used to determine the results of the comparison. If both values +** are text, then the appropriate collating function specified in +** P4 is used to do the comparison. If P4 is not specified then +** memcmp() is used to compare text string. If both values are +** numeric, then a numeric comparison is used. If the two values +** are of different types, then numbers are considered less than +** strings and strings are considered less than blobs. +** +** If the SQLITE_STOREP2 bit of P5 is set, then do not jump. Instead, +** store a boolean result (either 0, or 1, or NULL) in register P2. +*/ +/* Opcode: Ne P1 P2 P3 P4 P5 +** +** This works just like the Lt opcode except that the jump is taken if +** the operands in registers P1 and P3 are not equal. See the Lt opcode for +** additional information. +*/ +/* Opcode: Eq P1 P2 P3 P4 P5 +** +** This works just like the Lt opcode except that the jump is taken if +** the operands in registers P1 and P3 are equal. +** See the Lt opcode for additional information. +*/ +/* Opcode: Le P1 P2 P3 P4 P5 +** +** This works just like the Lt opcode except that the jump is taken if +** the content of register P3 is less than or equal to the content of +** register P1. See the Lt opcode for additional information. +*/ +/* Opcode: Gt P1 P2 P3 P4 P5 +** +** This works just like the Lt opcode except that the jump is taken if +** the content of register P3 is greater than the content of +** register P1. See the Lt opcode for additional information. +*/ +/* Opcode: Ge P1 P2 P3 P4 P5 +** +** This works just like the Lt opcode except that the jump is taken if +** the content of register P3 is greater than or equal to the content of +** register P1. See the Lt opcode for additional information. +*/ +case OP_Eq: /* same as TK_EQ, jump, in1, in3 */ +case OP_Ne: /* same as TK_NE, jump, in1, in3 */ +case OP_Lt: /* same as TK_LT, jump, in1, in3 */ +case OP_Le: /* same as TK_LE, jump, in1, in3 */ +case OP_Gt: /* same as TK_GT, jump, in1, in3 */ +case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ + int flags; + int res; + char affinity; + + flags = pIn1->flags|pIn3->flags; + + if( flags&MEM_Null ){ + /* If either operand is NULL then the result is always NULL. + ** The jump is taken if the SQLITE_JUMPIFNULL bit is set. + */ + if( pOp->p5 & SQLITE_STOREP2 ){ + pOut = &p->aMem[pOp->p2]; + MemSetTypeFlag(pOut, MEM_Null); + REGISTER_TRACE(pOp->p2, pOut); + }else if( pOp->p5 & SQLITE_JUMPIFNULL ){ + pc = pOp->p2-1; + } + break; + } + + affinity = pOp->p5 & SQLITE_AFF_MASK; + if( affinity ){ + applyAffinity(pIn1, affinity, encoding); + applyAffinity(pIn3, affinity, encoding); + } + + assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 ); + ExpandBlob(pIn1); + ExpandBlob(pIn3); + res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl); + switch( pOp->opcode ){ + case OP_Eq: res = res==0; break; + case OP_Ne: res = res!=0; break; + case OP_Lt: res = res<0; break; + case OP_Le: res = res<=0; break; + case OP_Gt: res = res>0; break; + default: res = res>=0; break; + } + + if( pOp->p5 & SQLITE_STOREP2 ){ + pOut = &p->aMem[pOp->p2]; + MemSetTypeFlag(pOut, MEM_Int); + pOut->u.i = res; + REGISTER_TRACE(pOp->p2, pOut); + }else if( res ){ + pc = pOp->p2-1; + } + break; +} + +/* Opcode: Permutation * * * P4 * +** +** Set the permuation used by the OP_Compare operator to be the array +** of integers in P4. +** +** The permutation is only valid until the next OP_Permutation, OP_Compare, +** OP_Halt, or OP_ResultRow. Typically the OP_Permutation should occur +** immediately prior to the OP_Compare. +*/ +case OP_Permutation: { + assert( pOp->p4type==P4_INTARRAY ); + assert( pOp->p4.ai ); + aPermute = pOp->p4.ai; + break; +} + +/* Opcode: Compare P1 P2 P3 P4 * +** +** Compare to vectors of registers in reg(P1)..reg(P1+P3-1) (all this +** one "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of +** the comparison for use by the next OP_Jump instruct. +** +** P4 is a KeyInfo structure that defines collating sequences and sort +** orders for the comparison. The permutation applies to registers +** only. The KeyInfo elements are used sequentially. +** +** The comparison is a sort comparison, so NULLs compare equal, +** NULLs are less than numbers, numbers are less than strings, +** and strings are less than blobs. +*/ +case OP_Compare: { + int n = pOp->p3; + int i, p1, p2; + const KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; + assert( n>0 ); + assert( pKeyInfo!=0 ); + p1 = pOp->p1; + assert( p1>0 && p1+n-1<p->nMem ); + p2 = pOp->p2; + assert( p2>0 && p2+n-1<p->nMem ); + for(i=0; i<n; i++){ + int idx = aPermute ? aPermute[i] : i; + CollSeq *pColl; /* Collating sequence to use on this term */ + int bRev; /* True for DESCENDING sort order */ + REGISTER_TRACE(p1+idx, &p->aMem[p1+idx]); + REGISTER_TRACE(p2+idx, &p->aMem[p2+idx]); + assert( i<pKeyInfo->nField ); + pColl = pKeyInfo->aColl[i]; + bRev = pKeyInfo->aSortOrder[i]; + iCompare = sqlite3MemCompare(&p->aMem[p1+idx], &p->aMem[p2+idx], pColl); + if( iCompare ){ + if( bRev ) iCompare = -iCompare; + break; + } + } + aPermute = 0; + break; +} + +/* Opcode: Jump P1 P2 P3 * * +** +** Jump to the instruction at address P1, P2, or P3 depending on whether +** in the most recent OP_Compare instruction the P1 vector was less than +** equal to, or greater than the P2 vector, respectively. +*/ +case OP_Jump: { /* jump */ + if( iCompare<0 ){ + pc = pOp->p1 - 1; + }else if( iCompare==0 ){ + pc = pOp->p2 - 1; + }else{ + pc = pOp->p3 - 1; + } + break; +} + +/* Opcode: And P1 P2 P3 * * +** +** Take the logical AND of the values in registers P1 and P2 and +** write the result into register P3. +** +** If either P1 or P2 is 0 (false) then the result is 0 even if +** the other input is NULL. A NULL and true or two NULLs give +** a NULL output. +*/ +/* Opcode: Or P1 P2 P3 * * +** +** Take the logical OR of the values in register P1 and P2 and +** store the answer in register P3. +** +** If either P1 or P2 is nonzero (true) then the result is 1 (true) +** even if the other input is NULL. A NULL and false or two NULLs +** give a NULL output. +*/ +case OP_And: /* same as TK_AND, in1, in2, out3 */ +case OP_Or: { /* same as TK_OR, in1, in2, out3 */ + int v1, v2; /* 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ + + if( pIn1->flags & MEM_Null ){ + v1 = 2; + }else{ + v1 = sqlite3VdbeIntValue(pIn1)!=0; + } + if( pIn2->flags & MEM_Null ){ + v2 = 2; + }else{ + v2 = sqlite3VdbeIntValue(pIn2)!=0; + } + if( pOp->opcode==OP_And ){ + static const unsigned char and_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 }; + v1 = and_logic[v1*3+v2]; + }else{ + static const unsigned char or_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 }; + v1 = or_logic[v1*3+v2]; + } + if( v1==2 ){ + MemSetTypeFlag(pOut, MEM_Null); + }else{ + pOut->u.i = v1; + MemSetTypeFlag(pOut, MEM_Int); + } + break; +} + +/* Opcode: Not P1 * * * * +** +** Interpret the value in register P1 as a boolean value. Replace it +** with its complement. If the value in register P1 is NULL its value +** is unchanged. +*/ +case OP_Not: { /* same as TK_NOT, in1 */ + if( pIn1->flags & MEM_Null ) break; /* Do nothing to NULLs */ + sqlite3VdbeMemIntegerify(pIn1); + pIn1->u.i = !pIn1->u.i; + assert( pIn1->flags&MEM_Int ); + break; +} + +/* Opcode: BitNot P1 * * * * +** +** Interpret the content of register P1 as an integer. Replace it +** with its ones-complement. If the value is originally NULL, leave +** it unchanged. +*/ +case OP_BitNot: { /* same as TK_BITNOT, in1 */ + if( pIn1->flags & MEM_Null ) break; /* Do nothing to NULLs */ + sqlite3VdbeMemIntegerify(pIn1); + pIn1->u.i = ~pIn1->u.i; + assert( pIn1->flags&MEM_Int ); + break; +} + +/* Opcode: If P1 P2 P3 * * +** +** Jump to P2 if the value in register P1 is true. The value is +** is considered true if it is numeric and non-zero. If the value +** in P1 is NULL then take the jump if P3 is true. +*/ +/* Opcode: IfNot P1 P2 P3 * * +** +** Jump to P2 if the value in register P1 is False. The value is +** is considered true if it has a numeric value of zero. If the value +** in P1 is NULL then take the jump if P3 is true. +*/ +case OP_If: /* jump, in1 */ +case OP_IfNot: { /* jump, in1 */ + int c; + if( pIn1->flags & MEM_Null ){ + c = pOp->p3; + }else{ +#ifdef SQLITE_OMIT_FLOATING_POINT + c = sqlite3VdbeIntValue(pIn1); +#else + c = sqlite3VdbeRealValue(pIn1)!=0.0; +#endif + if( pOp->opcode==OP_IfNot ) c = !c; + } + if( c ){ + pc = pOp->p2-1; + } + break; +} + +/* Opcode: IsNull P1 P2 P3 * * +** +** Jump to P2 if the value in register P1 is NULL. If P3 is greater +** than zero, then check all values reg(P1), reg(P1+1), +** reg(P1+2), ..., reg(P1+P3-1). +*/ +case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */ + int n = pOp->p3; + assert( pOp->p3==0 || pOp->p1>0 ); + do{ + if( (pIn1->flags & MEM_Null)!=0 ){ + pc = pOp->p2 - 1; + break; + } + pIn1++; + }while( --n > 0 ); + break; +} + +/* Opcode: NotNull P1 P2 * * * +** +** Jump to P2 if the value in register P1 is not NULL. +*/ +case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ + if( (pIn1->flags & MEM_Null)==0 ){ + pc = pOp->p2 - 1; + } + break; +} + +/* Opcode: SetNumColumns * P2 * * * +** +** This opcode sets the number of columns for the cursor opened by the +** following instruction to P2. +** +** An OP_SetNumColumns is only useful if it occurs immediately before +** one of the following opcodes: +** +** OpenRead +** OpenWrite +** OpenPseudo +** +** If the OP_Column opcode is to be executed on a cursor, then +** this opcode must be present immediately before the opcode that +** opens the cursor. +*/ +case OP_SetNumColumns: { + break; +} + +/* Opcode: Column P1 P2 P3 P4 * +** +** Interpret the data that cursor P1 points to as a structure built using +** the MakeRecord instruction. (See the MakeRecord opcode for additional +** information about the format of the data.) Extract the P2-th column +** from this record. If there are less that (P2+1) +** values in the record, extract a NULL. +** +** The value extracted is stored in register P3. +** +** If the KeyAsData opcode has previously executed on this cursor, then the +** field might be extracted from the key rather than the data. +** +** If the column contains fewer than P2 fields, then extract a NULL. Or, +** if the P4 argument is a P4_MEM use the value of the P4 argument as +** the result. +*/ +case OP_Column: { + u32 payloadSize; /* Number of bytes in the record */ + int p1 = pOp->p1; /* P1 value of the opcode */ + int p2 = pOp->p2; /* column number to retrieve */ + Cursor *pC = 0; /* The VDBE cursor */ + char *zRec; /* Pointer to complete record-data */ + BtCursor *pCrsr; /* The BTree cursor */ + u32 *aType; /* aType[i] holds the numeric type of the i-th column */ + u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */ + u32 nField; /* number of fields in the record */ + int len; /* The length of the serialized data for the column */ + int i; /* Loop counter */ + char *zData; /* Part of the record being decoded */ + Mem *pDest; /* Where to write the extracted value */ + Mem sMem; /* For storing the record being decoded */ + + sMem.flags = 0; + sMem.db = 0; + sMem.zMalloc = 0; + assert( p1<p->nCursor ); + assert( pOp->p3>0 && pOp->p3<=p->nMem ); + pDest = &p->aMem[pOp->p3]; + MemSetTypeFlag(pDest, MEM_Null); + + /* This block sets the variable payloadSize to be the total number of + ** bytes in the record. + ** + ** zRec is set to be the complete text of the record if it is available. + ** The complete record text is always available for pseudo-tables + ** If the record is stored in a cursor, the complete record text + ** might be available in the pC->aRow cache. Or it might not be. + ** If the data is unavailable, zRec is set to NULL. + ** + ** We also compute the number of columns in the record. For cursors, + ** the number of columns is stored in the Cursor.nField element. + */ + pC = p->apCsr[p1]; + assert( pC!=0 ); +#ifndef SQLITE_OMIT_VIRTUALTABLE + assert( pC->pVtabCursor==0 ); +#endif + if( pC->pCursor!=0 ){ + /* The record is stored in a B-Tree */ + rc = sqlite3VdbeCursorMoveto(pC); + if( rc ) goto abort_due_to_error; + zRec = 0; + pCrsr = pC->pCursor; + if( pC->nullRow ){ + payloadSize = 0; + }else if( pC->cacheStatus==p->cacheCtr ){ + payloadSize = pC->payloadSize; + zRec = (char*)pC->aRow; + }else if( pC->isIndex ){ + i64 payloadSize64; + sqlite3BtreeKeySize(pCrsr, &payloadSize64); + payloadSize = payloadSize64; + }else{ + sqlite3BtreeDataSize(pCrsr, &payloadSize); + } + nField = pC->nField; + }else{ + assert( pC->pseudoTable ); + /* The record is the sole entry of a pseudo-table */ + payloadSize = pC->nData; + zRec = pC->pData; + pC->cacheStatus = CACHE_STALE; + assert( payloadSize==0 || zRec!=0 ); + nField = pC->nField; + pCrsr = 0; + } + + /* If payloadSize is 0, then just store a NULL */ + if( payloadSize==0 ){ + assert( pDest->flags&MEM_Null ); + goto op_column_out; + } + if( payloadSize>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + goto too_big; + } + + assert( p2<nField ); + + /* Read and parse the table header. Store the results of the parse + ** into the record header cache fields of the cursor. + */ + aType = pC->aType; + if( pC->cacheStatus==p->cacheCtr ){ + aOffset = pC->aOffset; + }else{ + u8 *zIdx; /* Index into header */ + u8 *zEndHdr; /* Pointer to first byte after the header */ + u32 offset; /* Offset into the data */ + int szHdrSz; /* Size of the header size field at start of record */ + int avail; /* Number of bytes of available data */ + + assert(aType); + pC->aOffset = aOffset = &aType[nField]; + pC->payloadSize = payloadSize; + pC->cacheStatus = p->cacheCtr; + + /* Figure out how many bytes are in the header */ + if( zRec ){ + zData = zRec; + }else{ + if( pC->isIndex ){ + zData = (char*)sqlite3BtreeKeyFetch(pCrsr, &avail); + }else{ + zData = (char*)sqlite3BtreeDataFetch(pCrsr, &avail); + } + /* If KeyFetch()/DataFetch() managed to get the entire payload, + ** save the payload in the pC->aRow cache. That will save us from + ** having to make additional calls to fetch the content portion of + ** the record. + */ + if( avail>=payloadSize ){ + zRec = zData; + pC->aRow = (u8*)zData; + }else{ + pC->aRow = 0; + } + } + /* The following assert is true in all cases accept when + ** the database file has been corrupted externally. + ** assert( zRec!=0 || avail>=payloadSize || avail>=9 ); */ + szHdrSz = getVarint32((u8*)zData, offset); + + /* The KeyFetch() or DataFetch() above are fast and will get the entire + ** record header in most cases. But they will fail to get the complete + ** record header if the record header does not fit on a single page + ** in the B-Tree. When that happens, use sqlite3VdbeMemFromBtree() to + ** acquire the complete header text. + */ + if( !zRec && avail<offset ){ + sMem.flags = 0; + sMem.db = 0; + rc = sqlite3VdbeMemFromBtree(pCrsr, 0, offset, pC->isIndex, &sMem); + if( rc!=SQLITE_OK ){ + goto op_column_out; + } + zData = sMem.z; + } + zEndHdr = (u8 *)&zData[offset]; + zIdx = (u8 *)&zData[szHdrSz]; + + /* Scan the header and use it to fill in the aType[] and aOffset[] + ** arrays. aType[i] will contain the type integer for the i-th + ** column and aOffset[i] will contain the offset from the beginning + ** of the record to the start of the data for the i-th column + */ + for(i=0; i<nField; i++){ + if( zIdx<zEndHdr ){ + aOffset[i] = offset; + zIdx += getVarint32(zIdx, aType[i]); + offset += sqlite3VdbeSerialTypeLen(aType[i]); + }else{ + /* If i is less that nField, then there are less fields in this + ** record than SetNumColumns indicated there are columns in the + ** table. Set the offset for any extra columns not present in + ** the record to 0. This tells code below to store a NULL + ** instead of deserializing a value from the record. + */ + aOffset[i] = 0; + } + } + sqlite3VdbeMemRelease(&sMem); + sMem.flags = MEM_Null; + + /* If we have read more header data than was contained in the header, + ** or if the end of the last field appears to be past the end of the + ** record, or if the end of the last field appears to be before the end + ** of the record (when all fields present), then we must be dealing + ** with a corrupt database. + */ + if( zIdx>zEndHdr || offset>payloadSize || (zIdx==zEndHdr && offset!=payloadSize) ){ + rc = SQLITE_CORRUPT_BKPT; + goto op_column_out; + } + } + + /* Get the column information. If aOffset[p2] is non-zero, then + ** deserialize the value from the record. If aOffset[p2] is zero, + ** then there are not enough fields in the record to satisfy the + ** request. In this case, set the value NULL or to P4 if P4 is + ** a pointer to a Mem object. + */ + if( aOffset[p2] ){ + assert( rc==SQLITE_OK ); + if( zRec ){ + sqlite3VdbeMemReleaseExternal(pDest); + sqlite3VdbeSerialGet((u8 *)&zRec[aOffset[p2]], aType[p2], pDest); + }else{ + len = sqlite3VdbeSerialTypeLen(aType[p2]); + sqlite3VdbeMemMove(&sMem, pDest); + rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, pC->isIndex, &sMem); + if( rc!=SQLITE_OK ){ + goto op_column_out; + } + zData = sMem.z; + sqlite3VdbeSerialGet((u8*)zData, aType[p2], pDest); + } + pDest->enc = encoding; + }else{ + if( pOp->p4type==P4_MEM ){ + sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static); + }else{ + assert( pDest->flags&MEM_Null ); + } + } + + /* If we dynamically allocated space to hold the data (in the + ** sqlite3VdbeMemFromBtree() call above) then transfer control of that + ** dynamically allocated space over to the pDest structure. + ** This prevents a memory copy. + */ + if( sMem.zMalloc ){ + assert( sMem.z==sMem.zMalloc ); + assert( !(pDest->flags & MEM_Dyn) ); + assert( !(pDest->flags & (MEM_Blob|MEM_Str)) || pDest->z==sMem.z ); + pDest->flags &= ~(MEM_Ephem|MEM_Static); + pDest->flags |= MEM_Term; + pDest->z = sMem.z; + pDest->zMalloc = sMem.zMalloc; + } + + rc = sqlite3VdbeMemMakeWriteable(pDest); + +op_column_out: + UPDATE_MAX_BLOBSIZE(pDest); + REGISTER_TRACE(pOp->p3, pDest); + break; +} + +/* Opcode: Affinity P1 P2 * P4 * +** +** Apply affinities to a range of P2 registers starting with P1. +** +** P4 is a string that is P2 characters long. The nth character of the +** string indicates the column affinity that should be used for the nth +** memory cell in the range. +*/ +case OP_Affinity: { + char *zAffinity = pOp->p4.z; + Mem *pData0 = &p->aMem[pOp->p1]; + Mem *pLast = &pData0[pOp->p2-1]; + Mem *pRec; + + for(pRec=pData0; pRec<=pLast; pRec++){ + ExpandBlob(pRec); + applyAffinity(pRec, zAffinity[pRec-pData0], encoding); + } + break; +} + +/* Opcode: MakeRecord P1 P2 P3 P4 * +** +** Convert P2 registers beginning with P1 into a single entry +** suitable for use as a data record in a database table or as a key +** in an index. The details of the format are irrelevant as long as +** the OP_Column opcode can decode the record later. +** Refer to source code comments for the details of the record +** format. +** +** P4 may be a string that is P2 characters long. The nth character of the +** string indicates the column affinity that should be used for the nth +** field of the index key. +** +** The mapping from character to affinity is given by the SQLITE_AFF_ +** macros defined in sqliteInt.h. +** +** If P4 is NULL then all index fields have the affinity NONE. +*/ +case OP_MakeRecord: { + /* Assuming the record contains N fields, the record format looks + ** like this: + ** + ** ------------------------------------------------------------------------ + ** | hdr-size | type 0 | type 1 | ... | type N-1 | data0 | ... | data N-1 | + ** ------------------------------------------------------------------------ + ** + ** Data(0) is taken from register P1. Data(1) comes from register P1+1 + ** and so froth. + ** + ** Each type field is a varint representing the serial type of the + ** corresponding data element (see sqlite3VdbeSerialType()). The + ** hdr-size field is also a varint which is the offset from the beginning + ** of the record to data0. + */ + u8 *zNewRecord; /* A buffer to hold the data for the new record */ + Mem *pRec; /* The new record */ + u64 nData = 0; /* Number of bytes of data space */ + int nHdr = 0; /* Number of bytes of header space */ + u64 nByte = 0; /* Data space required for this record */ + int nZero = 0; /* Number of zero bytes at the end of the record */ + int nVarint; /* Number of bytes in a varint */ + u32 serial_type; /* Type field */ + Mem *pData0; /* First field to be combined into the record */ + Mem *pLast; /* Last field of the record */ + int nField; /* Number of fields in the record */ + char *zAffinity; /* The affinity string for the record */ + int file_format; /* File format to use for encoding */ + int i; /* Space used in zNewRecord[] */ + + nField = pOp->p1; + zAffinity = pOp->p4.z; + assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=p->nMem ); + pData0 = &p->aMem[nField]; + nField = pOp->p2; + pLast = &pData0[nField-1]; + file_format = p->minWriteFileFormat; + + /* Loop through the elements that will make up the record to figure + ** out how much space is required for the new record. + */ + for(pRec=pData0; pRec<=pLast; pRec++){ + int len; + if( zAffinity ){ + applyAffinity(pRec, zAffinity[pRec-pData0], encoding); + } + if( pRec->flags&MEM_Zero && pRec->n>0 ){ + sqlite3VdbeMemExpandBlob(pRec); + } + serial_type = sqlite3VdbeSerialType(pRec, file_format); + len = sqlite3VdbeSerialTypeLen(serial_type); + nData += len; + nHdr += sqlite3VarintLen(serial_type); + if( pRec->flags & MEM_Zero ){ + /* Only pure zero-filled BLOBs can be input to this Opcode. + ** We do not allow blobs with a prefix and a zero-filled tail. */ + nZero += pRec->u.i; + }else if( len ){ + nZero = 0; + } + } + + /* Add the initial header varint and total the size */ + nHdr += nVarint = sqlite3VarintLen(nHdr); + if( nVarint<sqlite3VarintLen(nHdr) ){ + nHdr++; + } + nByte = nHdr+nData-nZero; + if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + goto too_big; + } + + /* Make sure the output register has a buffer large enough to store + ** the new record. The output register (pOp->p3) is not allowed to + ** be one of the input registers (because the following call to + ** sqlite3VdbeMemGrow() could clobber the value before it is used). + */ + assert( pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2 ); + pOut = &p->aMem[pOp->p3]; + if( sqlite3VdbeMemGrow(pOut, nByte, 0) ){ + goto no_mem; + } + zNewRecord = (u8 *)pOut->z; + + /* Write the record */ + i = putVarint32(zNewRecord, nHdr); + for(pRec=pData0; pRec<=pLast; pRec++){ + serial_type = sqlite3VdbeSerialType(pRec, file_format); + i += putVarint32(&zNewRecord[i], serial_type); /* serial type */ + } + for(pRec=pData0; pRec<=pLast; pRec++){ /* serial data */ + i += sqlite3VdbeSerialPut(&zNewRecord[i], nByte-i, pRec, file_format); + } + assert( i==nByte ); + + assert( pOp->p3>0 && pOp->p3<=p->nMem ); + pOut->n = nByte; + pOut->flags = MEM_Blob | MEM_Dyn; + pOut->xDel = 0; + if( nZero ){ + pOut->u.i = nZero; + pOut->flags |= MEM_Zero; + } + pOut->enc = SQLITE_UTF8; /* In case the blob is ever converted to text */ + REGISTER_TRACE(pOp->p3, pOut); + UPDATE_MAX_BLOBSIZE(pOut); + break; +} + +/* Opcode: Statement P1 * * * * +** +** Begin an individual statement transaction which is part of a larger +** transaction. This is needed so that the statement +** can be rolled back after an error without having to roll back the +** entire transaction. The statement transaction will automatically +** commit when the VDBE halts. +** +** If the database connection is currently in autocommit mode (that +** is to say, if it is in between BEGIN and COMMIT) +** and if there are no other active statements on the same database +** connection, then this operation is a no-op. No statement transaction +** is needed since any error can use the normal ROLLBACK process to +** undo changes. +** +** If a statement transaction is started, then a statement journal file +** will be allocated and initialized. +** +** The statement is begun on the database file with index P1. The main +** database file has an index of 0 and the file used for temporary tables +** has an index of 1. +*/ +case OP_Statement: { + if( db->autoCommit==0 || db->activeVdbeCnt>1 ){ + int i = pOp->p1; + Btree *pBt; + assert( i>=0 && i<db->nDb ); + assert( db->aDb[i].pBt!=0 ); + pBt = db->aDb[i].pBt; + assert( sqlite3BtreeIsInTrans(pBt) ); + assert( (p->btreeMask & (1<<i))!=0 ); + if( !sqlite3BtreeIsInStmt(pBt) ){ + rc = sqlite3BtreeBeginStmt(pBt); + p->openedStatement = 1; + } + } + break; +} + +/* Opcode: AutoCommit P1 P2 * * * +** +** Set the database auto-commit flag to P1 (1 or 0). If P2 is true, roll +** back any currently active btree transactions. If there are any active +** VMs (apart from this one), then the COMMIT or ROLLBACK statement fails. +** +** This instruction causes the VM to halt. +*/ +case OP_AutoCommit: { + u8 i = pOp->p1; + u8 rollback = pOp->p2; + + assert( i==1 || i==0 ); + assert( i==1 || rollback==0 ); + + assert( db->activeVdbeCnt>0 ); /* At least this one VM is active */ + + if( db->activeVdbeCnt>1 && i && !db->autoCommit ){ + /* If this instruction implements a COMMIT or ROLLBACK, other VMs are + ** still running, and a transaction is active, return an error indicating + ** that the other VMs must complete first. + */ + sqlite3SetString(&p->zErrMsg, db, "cannot %s transaction - " + "SQL statements in progress", + rollback ? "rollback" : "commit"); + rc = SQLITE_ERROR; + }else if( i!=db->autoCommit ){ + if( pOp->p2 ){ + assert( i==1 ); + sqlite3RollbackAll(db); + db->autoCommit = 1; + }else{ + db->autoCommit = i; + if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ + p->pc = pc; + db->autoCommit = 1-i; + p->rc = rc = SQLITE_BUSY; + goto vdbe_return; + } + } + if( p->rc==SQLITE_OK ){ + rc = SQLITE_DONE; + }else{ + rc = SQLITE_ERROR; + } + goto vdbe_return; + }else{ + sqlite3SetString(&p->zErrMsg, db, + (!i)?"cannot start a transaction within a transaction":( + (rollback)?"cannot rollback - no transaction is active": + "cannot commit - no transaction is active")); + + rc = SQLITE_ERROR; + } + break; +} + +/* Opcode: Transaction P1 P2 * * * +** +** Begin a transaction. The transaction ends when a Commit or Rollback +** opcode is encountered. Depending on the ON CONFLICT setting, the +** transaction might also be rolled back if an error is encountered. +** +** P1 is the index of the database file on which the transaction is +** started. Index 0 is the main database file and index 1 is the +** file used for temporary tables. Indices of 2 or more are used for +** attached databases. +** +** If P2 is non-zero, then a write-transaction is started. A RESERVED lock is +** obtained on the database file when a write-transaction is started. No +** other process can start another write transaction while this transaction is +** underway. Starting a write transaction also creates a rollback journal. A +** write transaction must be started before any changes can be made to the +** database. If P2 is 2 or greater then an EXCLUSIVE lock is also obtained +** on the file. +** +** If P2 is zero, then a read-lock is obtained on the database file. +*/ +case OP_Transaction: { + int i = pOp->p1; + Btree *pBt; + + assert( i>=0 && i<db->nDb ); + assert( (p->btreeMask & (1<<i))!=0 ); + pBt = db->aDb[i].pBt; + + if( pBt ){ + rc = sqlite3BtreeBeginTrans(pBt, pOp->p2); + if( rc==SQLITE_BUSY ){ + p->pc = pc; + p->rc = rc = SQLITE_BUSY; + goto vdbe_return; + } + if( rc!=SQLITE_OK && rc!=SQLITE_READONLY /* && rc!=SQLITE_BUSY */ ){ + goto abort_due_to_error; + } + } + break; +} + +/* Opcode: ReadCookie P1 P2 P3 * * +** +** Read cookie number P3 from database P1 and write it into register P2. +** P3==0 is the schema version. P3==1 is the database format. +** P3==2 is the recommended pager cache size, and so forth. P1==0 is +** the main database file and P1==1 is the database file used to store +** temporary tables. +** +** If P1 is negative, then this is a request to read the size of a +** databases free-list. P3 must be set to 1 in this case. The actual +** database accessed is ((P1+1)*-1). For example, a P1 parameter of -1 +** corresponds to database 0 ("main"), a P1 of -2 is database 1 ("temp"). +** +** There must be a read-lock on the database (either a transaction +** must be started or there must be an open cursor) before +** executing this instruction. +*/ +case OP_ReadCookie: { /* out2-prerelease */ + int iMeta; + int iDb = pOp->p1; + int iCookie = pOp->p3; + + assert( pOp->p3<SQLITE_N_BTREE_META ); + if( iDb<0 ){ + iDb = (-1*(iDb+1)); + iCookie *= -1; + } + assert( iDb>=0 && iDb<db->nDb ); + assert( db->aDb[iDb].pBt!=0 ); + assert( (p->btreeMask & (1<<iDb))!=0 ); + /* The indexing of meta values at the schema layer is off by one from + ** the indexing in the btree layer. The btree considers meta[0] to + ** be the number of free pages in the database (a read-only value) + ** and meta[1] to be the schema cookie. The schema layer considers + ** meta[1] to be the schema cookie. So we have to shift the index + ** by one in the following statement. + */ + rc = sqlite3BtreeGetMeta(db->aDb[iDb].pBt, 1 + iCookie, (u32 *)&iMeta); + pOut->u.i = iMeta; + MemSetTypeFlag(pOut, MEM_Int); + break; +} + +/* Opcode: SetCookie P1 P2 P3 * * +** +** Write the content of register P3 (interpreted as an integer) +** into cookie number P2 of database P1. +** P2==0 is the schema version. P2==1 is the database format. +** P2==2 is the recommended pager cache size, and so forth. P1==0 is +** the main database file and P1==1 is the database file used to store +** temporary tables. +** +** A transaction must be started before executing this opcode. +*/ +case OP_SetCookie: { /* in3 */ + Db *pDb; + assert( pOp->p2<SQLITE_N_BTREE_META ); + assert( pOp->p1>=0 && pOp->p1<db->nDb ); + assert( (p->btreeMask & (1<<pOp->p1))!=0 ); + pDb = &db->aDb[pOp->p1]; + assert( pDb->pBt!=0 ); + sqlite3VdbeMemIntegerify(pIn3); + /* See note about index shifting on OP_ReadCookie */ + rc = sqlite3BtreeUpdateMeta(pDb->pBt, 1+pOp->p2, (int)pIn3->u.i); + if( pOp->p2==0 ){ + /* When the schema cookie changes, record the new cookie internally */ + pDb->pSchema->schema_cookie = pIn3->u.i; + db->flags |= SQLITE_InternChanges; + }else if( pOp->p2==1 ){ + /* Record changes in the file format */ + pDb->pSchema->file_format = pIn3->u.i; + } + if( pOp->p1==1 ){ + /* Invalidate all prepared statements whenever the TEMP database + ** schema is changed. Ticket #1644 */ + sqlite3ExpirePreparedStatements(db); + } + break; +} + +/* Opcode: VerifyCookie P1 P2 * +** +** Check the value of global database parameter number 0 (the +** schema version) and make sure it is equal to P2. +** P1 is the database number which is 0 for the main database file +** and 1 for the file holding temporary tables and some higher number +** for auxiliary databases. +** +** The cookie changes its value whenever the database schema changes. +** This operation is used to detect when that the cookie has changed +** and that the current process needs to reread the schema. +** +** Either a transaction needs to have been started or an OP_Open needs +** to be executed (to establish a read lock) before this opcode is +** invoked. +*/ +case OP_VerifyCookie: { + int iMeta; + Btree *pBt; + assert( pOp->p1>=0 && pOp->p1<db->nDb ); + assert( (p->btreeMask & (1<<pOp->p1))!=0 ); + pBt = db->aDb[pOp->p1].pBt; + if( pBt ){ + rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&iMeta); + }else{ + rc = SQLITE_OK; + iMeta = 0; + } + if( rc==SQLITE_OK && iMeta!=pOp->p2 ){ + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed"); + /* If the schema-cookie from the database file matches the cookie + ** stored with the in-memory representation of the schema, do + ** not reload the schema from the database file. + ** + ** If virtual-tables are in use, this is not just an optimization. + ** Often, v-tables store their data in other SQLite tables, which + ** are queried from within xNext() and other v-table methods using + ** prepared queries. If such a query is out-of-date, we do not want to + ** discard the database schema, as the user code implementing the + ** v-table would have to be ready for the sqlite3_vtab structure itself + ** to be invalidated whenever sqlite3_step() is called from within + ** a v-table method. + */ + if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){ + sqlite3ResetInternalSchema(db, pOp->p1); + } + + sqlite3ExpirePreparedStatements(db); + rc = SQLITE_SCHEMA; + } + break; +} + +/* Opcode: OpenRead P1 P2 P3 P4 P5 +** +** Open a read-only cursor for the database table whose root page is +** P2 in a database file. The database file is determined by P3. +** P3==0 means the main database, P3==1 means the database used for +** temporary tables, and P3>1 means used the corresponding attached +** database. Give the new cursor an identifier of P1. The P1 +** values need not be contiguous but all P1 values should be small integers. +** It is an error for P1 to be negative. +** +** If P5!=0 then use the content of register P2 as the root page, not +** the value of P2 itself. +** +** There will be a read lock on the database whenever there is an +** open cursor. If the database was unlocked prior to this instruction +** then a read lock is acquired as part of this instruction. A read +** lock allows other processes to read the database but prohibits +** any other process from modifying the database. The read lock is +** released when all cursors are closed. If this instruction attempts +** to get a read lock but fails, the script terminates with an +** SQLITE_BUSY error code. +** +** The P4 value is a pointer to a KeyInfo structure that defines the +** content and collating sequence of indices. P4 is NULL for cursors +** that are not pointing to indices. +** +** See also OpenWrite. +*/ +/* Opcode: OpenWrite P1 P2 P3 P4 P5 +** +** Open a read/write cursor named P1 on the table or index whose root +** page is P2. Or if P5!=0 use the content of register P2 to find the +** root page. +** +** The P4 value is a pointer to a KeyInfo structure that defines the +** content and collating sequence of indices. P4 is NULL for cursors +** that are not pointing to indices. +** +** This instruction works just like OpenRead except that it opens the cursor +** in read/write mode. For a given table, there can be one or more read-only +** cursors or a single read/write cursor but not both. +** +** See also OpenRead. +*/ +case OP_OpenRead: +case OP_OpenWrite: { + int i = pOp->p1; + int p2 = pOp->p2; + int iDb = pOp->p3; + int wrFlag; + Btree *pX; + Cursor *pCur; + Db *pDb; + + assert( iDb>=0 && iDb<db->nDb ); + assert( (p->btreeMask & (1<<iDb))!=0 ); + pDb = &db->aDb[iDb]; + pX = pDb->pBt; + assert( pX!=0 ); + if( pOp->opcode==OP_OpenWrite ){ + wrFlag = 1; + if( pDb->pSchema->file_format < p->minWriteFileFormat ){ + p->minWriteFileFormat = pDb->pSchema->file_format; + } + }else{ + wrFlag = 0; + } + if( pOp->p5 ){ + assert( p2>0 ); + assert( p2<=p->nMem ); + pIn2 = &p->aMem[p2]; + sqlite3VdbeMemIntegerify(pIn2); + p2 = pIn2->u.i; + assert( p2>=2 ); + } + assert( i>=0 ); + pCur = allocateCursor(p, i, &pOp[-1], iDb, 1); + if( pCur==0 ) goto no_mem; + pCur->nullRow = 1; + rc = sqlite3BtreeCursor(pX, p2, wrFlag, pOp->p4.p, pCur->pCursor); + if( pOp->p4type==P4_KEYINFO ){ + pCur->pKeyInfo = pOp->p4.pKeyInfo; + pCur->pIncrKey = &pCur->pKeyInfo->incrKey; + pCur->pKeyInfo->enc = ENC(p->db); + }else{ + pCur->pKeyInfo = 0; + pCur->pIncrKey = &pCur->bogusIncrKey; + } + switch( rc ){ + case SQLITE_BUSY: { + p->pc = pc; + p->rc = rc = SQLITE_BUSY; + goto vdbe_return; + } + case SQLITE_OK: { + int flags = sqlite3BtreeFlags(pCur->pCursor); + /* Sanity checking. Only the lower four bits of the flags byte should + ** be used. Bit 3 (mask 0x08) is unpredictable. The lower 3 bits + ** (mask 0x07) should be either 5 (intkey+leafdata for tables) or + ** 2 (zerodata for indices). If these conditions are not met it can + ** only mean that we are dealing with a corrupt database file + */ + if( (flags & 0xf0)!=0 || ((flags & 0x07)!=5 && (flags & 0x07)!=2) ){ + rc = SQLITE_CORRUPT_BKPT; + goto abort_due_to_error; + } + pCur->isTable = (flags & BTREE_INTKEY)!=0; + pCur->isIndex = (flags & BTREE_ZERODATA)!=0; + /* If P4==0 it means we are expected to open a table. If P4!=0 then + ** we expect to be opening an index. If this is not what happened, + ** then the database is corrupt + */ + if( (pCur->isTable && pOp->p4type==P4_KEYINFO) + || (pCur->isIndex && pOp->p4type!=P4_KEYINFO) ){ + rc = SQLITE_CORRUPT_BKPT; + goto abort_due_to_error; + } + break; + } + case SQLITE_EMPTY: { + pCur->isTable = pOp->p4type!=P4_KEYINFO; + pCur->isIndex = !pCur->isTable; + pCur->pCursor = 0; + rc = SQLITE_OK; + break; + } + default: { + goto abort_due_to_error; + } + } + break; +} + +/* Opcode: OpenEphemeral P1 P2 * P4 * +** +** Open a new cursor P1 to a transient table. +** The cursor is always opened read/write even if +** the main database is read-only. The transient or virtual +** table is deleted automatically when the cursor is closed. +** +** P2 is the number of columns in the virtual table. +** The cursor points to a BTree table if P4==0 and to a BTree index +** if P4 is not 0. If P4 is not NULL, it points to a KeyInfo structure +** that defines the format of keys in the index. +** +** This opcode was once called OpenTemp. But that created +** confusion because the term "temp table", might refer either +** to a TEMP table at the SQL level, or to a table opened by +** this opcode. Then this opcode was call OpenVirtual. But +** that created confusion with the whole virtual-table idea. +*/ +case OP_OpenEphemeral: { + int i = pOp->p1; + Cursor *pCx; + static const int openFlags = + SQLITE_OPEN_READWRITE | + SQLITE_OPEN_CREATE | + SQLITE_OPEN_EXCLUSIVE | + SQLITE_OPEN_DELETEONCLOSE | + SQLITE_OPEN_TRANSIENT_DB; + + assert( i>=0 ); + pCx = allocateCursor(p, i, pOp, -1, 1); + if( pCx==0 ) goto no_mem; + pCx->nullRow = 1; + rc = sqlite3BtreeFactory(db, 0, 1, SQLITE_DEFAULT_TEMP_CACHE_SIZE, openFlags, + &pCx->pBt); + if( rc==SQLITE_OK ){ + rc = sqlite3BtreeBeginTrans(pCx->pBt, 1); + } + if( rc==SQLITE_OK ){ + /* If a transient index is required, create it by calling + ** sqlite3BtreeCreateTable() with the BTREE_ZERODATA flag before + ** opening it. If a transient table is required, just use the + ** automatically created table with root-page 1 (an INTKEY table). + */ + if( pOp->p4.pKeyInfo ){ + int pgno; + assert( pOp->p4type==P4_KEYINFO ); + rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_ZERODATA); + if( rc==SQLITE_OK ){ + assert( pgno==MASTER_ROOT+1 ); + rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, + (KeyInfo*)pOp->p4.z, pCx->pCursor); + pCx->pKeyInfo = pOp->p4.pKeyInfo; + pCx->pKeyInfo->enc = ENC(p->db); + pCx->pIncrKey = &pCx->pKeyInfo->incrKey; + } + pCx->isTable = 0; + }else{ + rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, pCx->pCursor); + pCx->isTable = 1; + pCx->pIncrKey = &pCx->bogusIncrKey; + } + } + pCx->isIndex = !pCx->isTable; + break; +} + +/* Opcode: OpenPseudo P1 P2 * * * +** +** Open a new cursor that points to a fake table that contains a single +** row of data. Any attempt to write a second row of data causes the +** first row to be deleted. All data is deleted when the cursor is +** closed. +** +** A pseudo-table created by this opcode is useful for holding the +** NEW or OLD tables in a trigger. Also used to hold the a single +** row output from the sorter so that the row can be decomposed into +** individual columns using the OP_Column opcode. +** +** When OP_Insert is executed to insert a row in to the pseudo table, +** the pseudo-table cursor may or may not make it's own copy of the +** original row data. If P2 is 0, then the pseudo-table will copy the +** original row data. Otherwise, a pointer to the original memory cell +** is stored. In this case, the vdbe program must ensure that the +** memory cell containing the row data is not overwritten until the +** pseudo table is closed (or a new row is inserted into it). +*/ +case OP_OpenPseudo: { + int i = pOp->p1; + Cursor *pCx; + assert( i>=0 ); + pCx = allocateCursor(p, i, &pOp[-1], -1, 0); + if( pCx==0 ) goto no_mem; + pCx->nullRow = 1; + pCx->pseudoTable = 1; + pCx->ephemPseudoTable = pOp->p2; + pCx->pIncrKey = &pCx->bogusIncrKey; + pCx->isTable = 1; + pCx->isIndex = 0; + break; +} + +/* Opcode: Close P1 * * * * +** +** Close a cursor previously opened as P1. If P1 is not +** currently open, this instruction is a no-op. +*/ +case OP_Close: { + int i = pOp->p1; + assert( i>=0 && i<p->nCursor ); + sqlite3VdbeFreeCursor(p, p->apCsr[i]); + p->apCsr[i] = 0; + break; +} + +/* Opcode: MoveGe P1 P2 P3 P4 * +** +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), +** use the integer value in register P3 as a key. If cursor P1 refers +** to an SQL index, then P3 is the first in an array of P4 registers +** that are used as an unpacked index key. +** +** Reposition cursor P1 so that it points to the smallest entry that +** is greater than or equal to the key value. If there are no records +** greater than or equal to the key and P2 is not zero, then jump to P2. +** +** A special feature of this opcode (and different from the +** related OP_MoveGt, OP_MoveLt, and OP_MoveLe) is that if P2 is +** zero and P1 is an SQL table (a b-tree with integer keys) then +** the seek is deferred until it is actually needed. It might be +** the case that the cursor is never accessed. By deferring the +** seek, we avoid unnecessary seeks. +** +** See also: Found, NotFound, Distinct, MoveLt, MoveGt, MoveLe +*/ +/* Opcode: MoveGt P1 P2 P3 P4 * +** +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), +** use the integer value in register P3 as a key. If cursor P1 refers +** to an SQL index, then P3 is the first in an array of P4 registers +** that are used as an unpacked index key. +** +** Reposition cursor P1 so that it points to the smallest entry that +** is greater than the key value. If there are no records greater than +** the key and P2 is not zero, then jump to P2. +** +** See also: Found, NotFound, Distinct, MoveLt, MoveGe, MoveLe +*/ +/* Opcode: MoveLt P1 P2 P3 P4 * +** +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), +** use the integer value in register P3 as a key. If cursor P1 refers +** to an SQL index, then P3 is the first in an array of P4 registers +** that are used as an unpacked index key. +** +** Reposition cursor P1 so that it points to the largest entry that +** is less than the key value. If there are no records less than +** the key and P2 is not zero, then jump to P2. +** +** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLe +*/ +/* Opcode: MoveLe P1 P2 P3 P4 * +** +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), +** use the integer value in register P3 as a key. If cursor P1 refers +** to an SQL index, then P3 is the first in an array of P4 registers +** that are used as an unpacked index key. +** +** Reposition cursor P1 so that it points to the largest entry that +** is less than or equal to the key value. If there are no records +** less than or equal to the key and P2 is not zero, then jump to P2. +** +** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLt +*/ +case OP_MoveLt: /* jump, in3 */ +case OP_MoveLe: /* jump, in3 */ +case OP_MoveGe: /* jump, in3 */ +case OP_MoveGt: { /* jump, in3 */ + int i = pOp->p1; + Cursor *pC; + + assert( i>=0 && i<p->nCursor ); + pC = p->apCsr[i]; + assert( pC!=0 ); + if( pC->pCursor!=0 ){ + int res, oc; + oc = pOp->opcode; + pC->nullRow = 0; + *pC->pIncrKey = oc==OP_MoveGt || oc==OP_MoveLe; + if( pC->isTable ){ + i64 iKey = sqlite3VdbeIntValue(pIn3); + if( pOp->p2==0 ){ + assert( pOp->opcode==OP_MoveGe ); + pC->movetoTarget = iKey; + pC->rowidIsValid = 0; + pC->deferredMoveto = 1; + break; + } + rc = sqlite3BtreeMoveto(pC->pCursor, 0, 0, (u64)iKey, 0, &res); + if( rc!=SQLITE_OK ){ + goto abort_due_to_error; + } + pC->lastRowid = iKey; + pC->rowidIsValid = res==0; + }else{ + UnpackedRecord r; + int nField = pOp->p4.i; + assert( pOp->p4type==P4_INT32 ); + assert( nField>0 ); + r.pKeyInfo = pC->pKeyInfo; + r.nField = nField; + r.needFree = 0; + r.needDestroy = 0; + r.aMem = &p->aMem[pOp->p3]; + rc = sqlite3BtreeMoveto(pC->pCursor, 0, &r, 0, 0, &res); + if( rc!=SQLITE_OK ){ + goto abort_due_to_error; + } + pC->rowidIsValid = 0; + } + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; + *pC->pIncrKey = 0; +#ifdef SQLITE_TEST + sqlite3_search_count++; +#endif + if( oc==OP_MoveGe || oc==OP_MoveGt ){ + if( res<0 ){ + rc = sqlite3BtreeNext(pC->pCursor, &res); + if( rc!=SQLITE_OK ) goto abort_due_to_error; + pC->rowidIsValid = 0; + }else{ + res = 0; + } + }else{ + assert( oc==OP_MoveLt || oc==OP_MoveLe ); + if( res>=0 ){ + rc = sqlite3BtreePrevious(pC->pCursor, &res); + if( rc!=SQLITE_OK ) goto abort_due_to_error; + pC->rowidIsValid = 0; + }else{ + /* res might be negative because the table is empty. Check to + ** see if this is the case. + */ + res = sqlite3BtreeEof(pC->pCursor); + } + } + assert( pOp->p2>0 ); + if( res ){ + pc = pOp->p2 - 1; + } + }else if( !pC->pseudoTable ){ + /* This happens when attempting to open the sqlite3_master table + ** for read access returns SQLITE_EMPTY. In this case always + ** take the jump (since there are no records in the table). + */ + pc = pOp->p2 - 1; + } + break; +} + +/* Opcode: Found P1 P2 P3 * * +** +** Register P3 holds a blob constructed by MakeRecord. P1 is an index. +** If an entry that matches the value in register p3 exists in P1 then +** jump to P2. If the P3 value does not match any entry in P1 +** then fall thru. The P1 cursor is left pointing at the matching entry +** if it exists. +** +** This instruction is used to implement the IN operator where the +** left-hand side is a SELECT statement. P1 may be a true index, or it +** may be a temporary index that holds the results of the SELECT +** statement. This instruction is also used to implement the +** DISTINCT keyword in SELECT statements. +** +** This instruction checks if index P1 contains a record for which +** the first N serialized values exactly match the N serialized values +** in the record in register P3, where N is the total number of values in +** the P3 record (the P3 record is a prefix of the P1 record). +** +** See also: NotFound, MoveTo, IsUnique, NotExists +*/ +/* Opcode: NotFound P1 P2 P3 * * +** +** Register P3 holds a blob constructed by MakeRecord. P1 is +** an index. If no entry exists in P1 that matches the blob then jump +** to P2. If an entry does existing, fall through. The cursor is left +** pointing to the entry that matches. +** +** See also: Found, MoveTo, NotExists, IsUnique +*/ +case OP_NotFound: /* jump, in3 */ +case OP_Found: { /* jump, in3 */ + int i = pOp->p1; + int alreadyExists = 0; + Cursor *pC; + assert( i>=0 && i<p->nCursor ); + assert( p->apCsr[i]!=0 ); + if( (pC = p->apCsr[i])->pCursor!=0 ){ + int res; + assert( pC->isTable==0 ); + assert( pIn3->flags & MEM_Blob ); + if( pOp->opcode==OP_Found ){ + pC->pKeyInfo->prefixIsEqual = 1; + } + rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, 0, pIn3->n, 0, &res); + pC->pKeyInfo->prefixIsEqual = 0; + if( rc!=SQLITE_OK ){ + break; + } + alreadyExists = (res==0); + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; + } + if( pOp->opcode==OP_Found ){ + if( alreadyExists ) pc = pOp->p2 - 1; + }else{ + if( !alreadyExists ) pc = pOp->p2 - 1; + } + break; +} + +/* Opcode: IsUnique P1 P2 P3 P4 * +** +** The P3 register contains an integer record number. Call this +** record number R. The P4 register contains an index key created +** using MakeIdxRec. Call it K. +** +** P1 is an index. So it has no data and its key consists of a +** record generated by OP_MakeRecord where the last field is the +** rowid of the entry that the index refers to. +** +** This instruction asks if there is an entry in P1 where the +** fields matches K but the rowid is different from R. +** If there is no such entry, then there is an immediate +** jump to P2. If any entry does exist where the index string +** matches K but the record number is not R, then the record +** number for that entry is written into P3 and control +** falls through to the next instruction. +** +** See also: NotFound, NotExists, Found +*/ +case OP_IsUnique: { /* jump, in3 */ + int i = pOp->p1; + Cursor *pCx; + BtCursor *pCrsr; + Mem *pK; + i64 R; + + /* Pop the value R off the top of the stack + */ + assert( pOp->p4type==P4_INT32 ); + assert( pOp->p4.i>0 && pOp->p4.i<=p->nMem ); + pK = &p->aMem[pOp->p4.i]; + sqlite3VdbeMemIntegerify(pIn3); + R = pIn3->u.i; + assert( i>=0 && i<p->nCursor ); + pCx = p->apCsr[i]; + assert( pCx!=0 ); + pCrsr = pCx->pCursor; + if( pCrsr!=0 ){ + int res; + i64 v; /* The record number on the P1 entry that matches K */ + char *zKey; /* The value of K */ + int nKey; /* Number of bytes in K */ + int len; /* Number of bytes in K without the rowid at the end */ + int szRowid; /* Size of the rowid column at the end of zKey */ + + /* Make sure K is a string and make zKey point to K + */ + assert( pK->flags & MEM_Blob ); + zKey = pK->z; + nKey = pK->n; + + /* sqlite3VdbeIdxRowidLen() only returns other than SQLITE_OK when the + ** record passed as an argument corrupt. Since the record in this case + ** has just been created by an OP_MakeRecord instruction, and not loaded + ** from the database file, it is not possible for it to be corrupt. + ** Therefore, assert(rc==SQLITE_OK). + */ + rc = sqlite3VdbeIdxRowidLen((u8*)zKey, nKey, &szRowid); + assert(rc==SQLITE_OK); + len = nKey-szRowid; + + /* Search for an entry in P1 where all but the last four bytes match K. + ** If there is no such entry, jump immediately to P2. + */ + assert( pCx->deferredMoveto==0 ); + pCx->cacheStatus = CACHE_STALE; + rc = sqlite3BtreeMoveto(pCrsr, zKey, 0, len, 0, &res); + if( rc!=SQLITE_OK ){ + goto abort_due_to_error; + } + if( res<0 ){ + rc = sqlite3BtreeNext(pCrsr, &res); + if( res ){ + pc = pOp->p2 - 1; + break; + } + } + rc = sqlite3VdbeIdxKeyCompare(pCx, 0, len, (u8*)zKey, &res); + if( rc!=SQLITE_OK ) goto abort_due_to_error; + if( res>0 ){ + pc = pOp->p2 - 1; + break; + } + + /* At this point, pCrsr is pointing to an entry in P1 where all but + ** the final entry (the rowid) matches K. Check to see if the + ** final rowid column is different from R. If it equals R then jump + ** immediately to P2. + */ + rc = sqlite3VdbeIdxRowid(pCrsr, &v); + if( rc!=SQLITE_OK ){ + goto abort_due_to_error; + } + if( v==R ){ + pc = pOp->p2 - 1; + break; + } + + /* The final varint of the key is different from R. Store it back + ** into register R3. (The record number of an entry that violates + ** a UNIQUE constraint.) + */ + pIn3->u.i = v; + assert( pIn3->flags&MEM_Int ); + } + break; +} + +/* Opcode: NotExists P1 P2 P3 * * +** +** Use the content of register P3 as a integer key. If a record +** with that key does not exist in table of P1, then jump to P2. +** If the record does exist, then fall thru. The cursor is left +** pointing to the record if it exists. +** +** The difference between this operation and NotFound is that this +** operation assumes the key is an integer and that P1 is a table whereas +** NotFound assumes key is a blob constructed from MakeRecord and +** P1 is an index. +** +** See also: Found, MoveTo, NotFound, IsUnique +*/ +case OP_NotExists: { /* jump, in3 */ + int i = pOp->p1; + Cursor *pC; + BtCursor *pCrsr; + assert( i>=0 && i<p->nCursor ); + assert( p->apCsr[i]!=0 ); + if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ + int res; + u64 iKey; + assert( pIn3->flags & MEM_Int ); + assert( p->apCsr[i]->isTable ); + iKey = intToKey(pIn3->u.i); + rc = sqlite3BtreeMoveto(pCrsr, 0, 0, iKey, 0,&res); + pC->lastRowid = pIn3->u.i; + pC->rowidIsValid = res==0; + pC->nullRow = 0; + pC->cacheStatus = CACHE_STALE; + /* res might be uninitialized if rc!=SQLITE_OK. But if rc!=SQLITE_OK + ** processing is about to abort so we really do not care whether or not + ** the following jump is taken. (In other words, do not stress over + ** the error that valgrind sometimes shows on the next statement when + ** running ioerr.test and similar failure-recovery test scripts.) */ + if( res!=0 ){ + pc = pOp->p2 - 1; + assert( pC->rowidIsValid==0 ); + } + }else if( !pC->pseudoTable ){ + /* This happens when an attempt to open a read cursor on the + ** sqlite_master table returns SQLITE_EMPTY. + */ + assert( pC->isTable ); + pc = pOp->p2 - 1; + assert( pC->rowidIsValid==0 ); + } + break; +} + +/* Opcode: Sequence P1 P2 * * * +** +** Find the next available sequence number for cursor P1. +** Write the sequence number into register P2. +** The sequence number on the cursor is incremented after this +** instruction. +*/ +case OP_Sequence: { /* out2-prerelease */ + int i = pOp->p1; + assert( i>=0 && i<p->nCursor ); + assert( p->apCsr[i]!=0 ); + pOut->u.i = p->apCsr[i]->seqCount++; + MemSetTypeFlag(pOut, MEM_Int); + break; +} + + +/* Opcode: NewRowid P1 P2 P3 * * +** +** Get a new integer record number (a.k.a "rowid") used as the key to a table. +** The record number is not previously used as a key in the database +** table that cursor P1 points to. The new record number is written +** written to register P2. +** +** If P3>0 then P3 is a register that holds the largest previously +** generated record number. No new record numbers are allowed to be less +** than this value. When this value reaches its maximum, a SQLITE_FULL +** error is generated. The P3 register is updated with the generated +** record number. This P3 mechanism is used to help implement the +** AUTOINCREMENT feature. +*/ +case OP_NewRowid: { /* out2-prerelease */ + int i = pOp->p1; + i64 v = 0; + Cursor *pC; + assert( i>=0 && i<p->nCursor ); + assert( p->apCsr[i]!=0 ); + if( (pC = p->apCsr[i])->pCursor==0 ){ + /* The zero initialization above is all that is needed */ + }else{ + /* The next rowid or record number (different terms for the same + ** thing) is obtained in a two-step algorithm. + ** + ** First we attempt to find the largest existing rowid and add one + ** to that. But if the largest existing rowid is already the maximum + ** positive integer, we have to fall through to the second + ** probabilistic algorithm + ** + ** The second algorithm is to select a rowid at random and see if + ** it already exists in the table. If it does not exist, we have + ** succeeded. If the random rowid does exist, we select a new one + ** and try again, up to 1000 times. + ** + ** For a table with less than 2 billion entries, the probability + ** of not finding a unused rowid is about 1.0e-300. This is a + ** non-zero probability, but it is still vanishingly small and should + ** never cause a problem. You are much, much more likely to have a + ** hardware failure than for this algorithm to fail. + ** + ** The analysis in the previous paragraph assumes that you have a good + ** source of random numbers. Is a library function like lrand48() + ** good enough? Maybe. Maybe not. It's hard to know whether there + ** might be subtle bugs is some implementations of lrand48() that + ** could cause problems. To avoid uncertainty, SQLite uses its own + ** random number generator based on the RC4 algorithm. + ** + ** To promote locality of reference for repetitive inserts, the + ** first few attempts at choosing a random rowid pick values just a little + ** larger than the previous rowid. This has been shown experimentally + ** to double the speed of the COPY operation. + */ + int res, rx=SQLITE_OK, cnt; + i64 x; + cnt = 0; + if( (sqlite3BtreeFlags(pC->pCursor)&(BTREE_INTKEY|BTREE_ZERODATA)) != + BTREE_INTKEY ){ + rc = SQLITE_CORRUPT_BKPT; + goto abort_due_to_error; + } + assert( (sqlite3BtreeFlags(pC->pCursor) & BTREE_INTKEY)!=0 ); + assert( (sqlite3BtreeFlags(pC->pCursor) & BTREE_ZERODATA)==0 ); + +#ifdef SQLITE_32BIT_ROWID +# define MAX_ROWID 0x7fffffff +#else + /* Some compilers complain about constants of the form 0x7fffffffffffffff. + ** Others complain about 0x7ffffffffffffffffLL. The following macro seems + ** to provide the constant while making all compilers happy. + */ +# define MAX_ROWID ( (((u64)0x7fffffff)<<32) | (u64)0xffffffff ) +#endif + + if( !pC->useRandomRowid ){ + if( pC->nextRowidValid ){ + v = pC->nextRowid; + }else{ + rc = sqlite3BtreeLast(pC->pCursor, &res); + if( rc!=SQLITE_OK ){ + goto abort_due_to_error; + } + if( res ){ + v = 1; + }else{ + sqlite3BtreeKeySize(pC->pCursor, &v); + v = keyToInt(v); + if( v==MAX_ROWID ){ + pC->useRandomRowid = 1; + }else{ + v++; + } + } + } + +#ifndef SQLITE_OMIT_AUTOINCREMENT + if( pOp->p3 ){ + Mem *pMem; + assert( pOp->p3>0 && pOp->p3<=p->nMem ); /* P3 is a valid memory cell */ + pMem = &p->aMem[pOp->p3]; + REGISTER_TRACE(pOp->p3, pMem); + sqlite3VdbeMemIntegerify(pMem); + assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */ + if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){ + rc = SQLITE_FULL; + goto abort_due_to_error; + } + if( v<pMem->u.i+1 ){ + v = pMem->u.i + 1; + } + pMem->u.i = v; + } +#endif + + if( v<MAX_ROWID ){ + pC->nextRowidValid = 1; + pC->nextRowid = v+1; + }else{ + pC->nextRowidValid = 0; + } + } + if( pC->useRandomRowid ){ + assert( pOp->p3==0 ); /* SQLITE_FULL must have occurred prior to this */ + v = db->priorNewRowid; + cnt = 0; + do{ + if( cnt==0 && (v&0xffffff)==v ){ + v++; + }else{ + sqlite3_randomness(sizeof(v), &v); + if( cnt<5 ) v &= 0xffffff; + } + if( v==0 ) continue; + x = intToKey(v); + rx = sqlite3BtreeMoveto(pC->pCursor, 0, 0, (u64)x, 0, &res); + cnt++; + }while( cnt<100 && rx==SQLITE_OK && res==0 ); + db->priorNewRowid = v; + if( rx==SQLITE_OK && res==0 ){ + rc = SQLITE_FULL; + goto abort_due_to_error; + } + } + pC->rowidIsValid = 0; + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; + } + MemSetTypeFlag(pOut, MEM_Int); + pOut->u.i = v; + break; +} + +/* Opcode: Insert P1 P2 P3 P4 P5 +** +** Write an entry into the table of cursor P1. A new entry is +** created if it doesn't already exist or the data for an existing +** entry is overwritten. The data is the value stored register +** number P2. The key is stored in register P3. The key must +** be an integer. +** +** If the OPFLAG_NCHANGE flag of P5 is set, then the row change count is +** incremented (otherwise not). If the OPFLAG_LASTROWID flag of P5 is set, +** then rowid is stored for subsequent return by the +** sqlite3_last_insert_rowid() function (otherwise it is unmodified). +** +** Parameter P4 may point to a string containing the table-name, or +** may be NULL. If it is not NULL, then the update-hook +** (sqlite3.xUpdateCallback) is invoked following a successful insert. +** +** (WARNING/TODO: If P1 is a pseudo-cursor and P2 is dynamically +** allocated, then ownership of P2 is transferred to the pseudo-cursor +** and register P2 becomes ephemeral. If the cursor is changed, the +** value of register P2 will then change. Make sure this does not +** cause any problems.) +** +** This instruction only works on tables. The equivalent instruction +** for indices is OP_IdxInsert. +*/ +case OP_Insert: { + Mem *pData = &p->aMem[pOp->p2]; + Mem *pKey = &p->aMem[pOp->p3]; + + i64 iKey; /* The integer ROWID or key for the record to be inserted */ + int i = pOp->p1; + Cursor *pC; + assert( i>=0 && i<p->nCursor ); + pC = p->apCsr[i]; + assert( pC!=0 ); + assert( pC->pCursor!=0 || pC->pseudoTable ); + assert( pKey->flags & MEM_Int ); + assert( pC->isTable ); + REGISTER_TRACE(pOp->p2, pData); + REGISTER_TRACE(pOp->p3, pKey); + + iKey = intToKey(pKey->u.i); + if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; + if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = pKey->u.i; + if( pC->nextRowidValid && pKey->u.i>=pC->nextRowid ){ + pC->nextRowidValid = 0; + } + if( pData->flags & MEM_Null ){ + pData->z = 0; + pData->n = 0; + }else{ + assert( pData->flags & (MEM_Blob|MEM_Str) ); + } + if( pC->pseudoTable ){ + if( !pC->ephemPseudoTable ){ + sqlite3DbFree(db, pC->pData); + } + pC->iKey = iKey; + pC->nData = pData->n; + if( pData->z==pData->zMalloc || pC->ephemPseudoTable ){ + pC->pData = pData->z; + if( !pC->ephemPseudoTable ){ + pData->flags &= ~MEM_Dyn; + pData->flags |= MEM_Ephem; + pData->zMalloc = 0; + } + }else{ + pC->pData = sqlite3Malloc( pC->nData+2 ); + if( !pC->pData ) goto no_mem; + memcpy(pC->pData, pData->z, pC->nData); + pC->pData[pC->nData] = 0; + pC->pData[pC->nData+1] = 0; + } + pC->nullRow = 0; + }else{ + int nZero; + if( pData->flags & MEM_Zero ){ + nZero = pData->u.i; + }else{ + nZero = 0; + } + rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey, + pData->z, pData->n, nZero, + pOp->p5 & OPFLAG_APPEND); + } + + pC->rowidIsValid = 0; + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; + + /* Invoke the update-hook if required. */ + if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){ + const char *zDb = db->aDb[pC->iDb].zName; + const char *zTbl = pOp->p4.z; + int op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); + assert( pC->isTable ); + db->xUpdateCallback(db->pUpdateArg, op, zDb, zTbl, iKey); + assert( pC->iDb>=0 ); + } + break; +} + +/* Opcode: Delete P1 P2 * P4 * +** +** Delete the record at which the P1 cursor is currently pointing. +** +** The cursor will be left pointing at either the next or the previous +** record in the table. If it is left pointing at the next record, then +** the next Next instruction will be a no-op. Hence it is OK to delete +** a record from within an Next loop. +** +** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is +** incremented (otherwise not). +** +** P1 must not be pseudo-table. It has to be a real table with +** multiple rows. +** +** If P4 is not NULL, then it is the name of the table that P1 is +** pointing to. The update hook will be invoked, if it exists. +** If P4 is not NULL then the P1 cursor must have been positioned +** using OP_NotFound prior to invoking this opcode. +*/ +case OP_Delete: { + int i = pOp->p1; + i64 iKey; + Cursor *pC; + + assert( i>=0 && i<p->nCursor ); + pC = p->apCsr[i]; + assert( pC!=0 ); + assert( pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */ + + /* If the update-hook will be invoked, set iKey to the rowid of the + ** row being deleted. + */ + if( db->xUpdateCallback && pOp->p4.z ){ + assert( pC->isTable ); + assert( pC->rowidIsValid ); /* lastRowid set by previous OP_NotFound */ + iKey = pC->lastRowid; + } + + rc = sqlite3VdbeCursorMoveto(pC); + if( rc ) goto abort_due_to_error; + rc = sqlite3BtreeDelete(pC->pCursor); + pC->nextRowidValid = 0; + pC->cacheStatus = CACHE_STALE; + + /* Invoke the update-hook if required. */ + if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){ + const char *zDb = db->aDb[pC->iDb].zName; + const char *zTbl = pOp->p4.z; + db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, iKey); + assert( pC->iDb>=0 ); + } + if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++; + break; +} + +/* Opcode: ResetCount P1 * * +** +** This opcode resets the VMs internal change counter to 0. If P1 is true, +** then the value of the change counter is copied to the database handle +** change counter (returned by subsequent calls to sqlite3_changes()) +** before it is reset. This is used by trigger programs. +*/ +case OP_ResetCount: { + if( pOp->p1 ){ + sqlite3VdbeSetChanges(db, p->nChange); + } + p->nChange = 0; + break; +} + +/* Opcode: RowData P1 P2 * * * +** +** Write into register P2 the complete row data for cursor P1. +** There is no interpretation of the data. +** It is just copied onto the P2 register exactly as +** it is found in the database file. +** +** If the P1 cursor must be pointing to a valid row (not a NULL row) +** of a real table, not a pseudo-table. +*/ +/* Opcode: RowKey P1 P2 * * * +** +** Write into register P2 the complete row key for cursor P1. +** There is no interpretation of the data. +** The key is copied onto the P3 register exactly as +** it is found in the database file. +** +** If the P1 cursor must be pointing to a valid row (not a NULL row) +** of a real table, not a pseudo-table. +*/ +case OP_RowKey: +case OP_RowData: { + int i = pOp->p1; + Cursor *pC; + BtCursor *pCrsr; + u32 n; + + pOut = &p->aMem[pOp->p2]; + + /* Note that RowKey and RowData are really exactly the same instruction */ + assert( i>=0 && i<p->nCursor ); + pC = p->apCsr[i]; + assert( pC->isTable || pOp->opcode==OP_RowKey ); + assert( pC->isIndex || pOp->opcode==OP_RowData ); + assert( pC!=0 ); + assert( pC->nullRow==0 ); + assert( pC->pseudoTable==0 ); + assert( pC->pCursor!=0 ); + pCrsr = pC->pCursor; + rc = sqlite3VdbeCursorMoveto(pC); + if( rc ) goto abort_due_to_error; + if( pC->isIndex ){ + i64 n64; + assert( !pC->isTable ); + sqlite3BtreeKeySize(pCrsr, &n64); + if( n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + goto too_big; + } + n = n64; + }else{ + sqlite3BtreeDataSize(pCrsr, &n); + if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + goto too_big; + } + } + if( sqlite3VdbeMemGrow(pOut, n, 0) ){ + goto no_mem; + } + pOut->n = n; + MemSetTypeFlag(pOut, MEM_Blob); + if( pC->isIndex ){ + rc = sqlite3BtreeKey(pCrsr, 0, n, pOut->z); + }else{ + rc = sqlite3BtreeData(pCrsr, 0, n, pOut->z); + } + pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */ + UPDATE_MAX_BLOBSIZE(pOut); + break; +} + +/* Opcode: Rowid P1 P2 * * * +** +** Store in register P2 an integer which is the key of the table entry that +** P1 is currently point to. +*/ +case OP_Rowid: { /* out2-prerelease */ + int i = pOp->p1; + Cursor *pC; + i64 v; + + assert( i>=0 && i<p->nCursor ); + pC = p->apCsr[i]; + assert( pC!=0 ); + rc = sqlite3VdbeCursorMoveto(pC); + if( rc ) goto abort_due_to_error; + if( pC->rowidIsValid ){ + v = pC->lastRowid; + }else if( pC->pseudoTable ){ + v = keyToInt(pC->iKey); + }else if( pC->nullRow ){ + /* Leave the rowid set to a NULL */ + break; + }else{ + assert( pC->pCursor!=0 ); + sqlite3BtreeKeySize(pC->pCursor, &v); + v = keyToInt(v); + } + pOut->u.i = v; + MemSetTypeFlag(pOut, MEM_Int); + break; +} + +/* Opcode: NullRow P1 * * * * +** +** Move the cursor P1 to a null row. Any OP_Column operations +** that occur while the cursor is on the null row will always +** write a NULL. +*/ +case OP_NullRow: { + int i = pOp->p1; + Cursor *pC; + + assert( i>=0 && i<p->nCursor ); + pC = p->apCsr[i]; + assert( pC!=0 ); + pC->nullRow = 1; + pC->rowidIsValid = 0; + break; +} + +/* Opcode: Last P1 P2 * * * +** +** The next use of the Rowid or Column or Next instruction for P1 +** will refer to the last entry in the database table or index. +** If the table or index is empty and P2>0, then jump immediately to P2. +** If P2 is 0 or if the table or index is not empty, fall through +** to the following instruction. +*/ +case OP_Last: { /* jump */ + int i = pOp->p1; + Cursor *pC; + BtCursor *pCrsr; + int res; + + assert( i>=0 && i<p->nCursor ); + pC = p->apCsr[i]; + assert( pC!=0 ); + pCrsr = pC->pCursor; + assert( pCrsr!=0 ); + rc = sqlite3BtreeLast(pCrsr, &res); + pC->nullRow = res; + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; + if( res && pOp->p2>0 ){ + pc = pOp->p2 - 1; + } + break; +} + + +/* Opcode: Sort P1 P2 * * * +** +** This opcode does exactly the same thing as OP_Rewind except that +** it increments an undocumented global variable used for testing. +** +** Sorting is accomplished by writing records into a sorting index, +** then rewinding that index and playing it back from beginning to +** end. We use the OP_Sort opcode instead of OP_Rewind to do the +** rewinding so that the global variable will be incremented and +** regression tests can determine whether or not the optimizer is +** correctly optimizing out sorts. +*/ +case OP_Sort: { /* jump */ +#ifdef SQLITE_TEST + sqlite3_sort_count++; + sqlite3_search_count--; +#endif + /* Fall through into OP_Rewind */ +} +/* Opcode: Rewind P1 P2 * * * +** +** The next use of the Rowid or Column or Next instruction for P1 +** will refer to the first entry in the database table or index. +** If the table or index is empty and P2>0, then jump immediately to P2. +** If P2 is 0 or if the table or index is not empty, fall through +** to the following instruction. +*/ +case OP_Rewind: { /* jump */ + int i = pOp->p1; + Cursor *pC; + BtCursor *pCrsr; + int res; + + assert( i>=0 && i<p->nCursor ); + pC = p->apCsr[i]; + assert( pC!=0 ); + if( (pCrsr = pC->pCursor)!=0 ){ + rc = sqlite3BtreeFirst(pCrsr, &res); + pC->atFirst = res==0; + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; + }else{ + res = 1; + } + pC->nullRow = res; + assert( pOp->p2>0 && pOp->p2<p->nOp ); + if( res ){ + pc = pOp->p2 - 1; + } + break; +} + +/* Opcode: Next P1 P2 * * * +** +** Advance cursor P1 so that it points to the next key/data pair in its +** table or index. If there are no more key/value pairs then fall through +** to the following instruction. But if the cursor advance was successful, +** jump immediately to P2. +** +** The P1 cursor must be for a real table, not a pseudo-table. +** +** See also: Prev +*/ +/* Opcode: Prev P1 P2 * * * +** +** Back up cursor P1 so that it points to the previous key/data pair in its +** table or index. If there is no previous key/value pairs then fall through +** to the following instruction. But if the cursor backup was successful, +** jump immediately to P2. +** +** The P1 cursor must be for a real table, not a pseudo-table. +*/ +case OP_Prev: /* jump */ +case OP_Next: { /* jump */ + Cursor *pC; + BtCursor *pCrsr; + int res; + + CHECK_FOR_INTERRUPT; + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + pC = p->apCsr[pOp->p1]; + if( pC==0 ){ + break; /* See ticket #2273 */ + } + pCrsr = pC->pCursor; + assert( pCrsr ); + res = 1; + assert( pC->deferredMoveto==0 ); + rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(pCrsr, &res) : + sqlite3BtreePrevious(pCrsr, &res); + pC->nullRow = res; + pC->cacheStatus = CACHE_STALE; + if( res==0 ){ + pc = pOp->p2 - 1; +#ifdef SQLITE_TEST + sqlite3_search_count++; +#endif + } + pC->rowidIsValid = 0; + break; +} + +/* Opcode: IdxInsert P1 P2 P3 * * +** +** Register P2 holds a SQL index key made using the +** MakeIdxRec instructions. This opcode writes that key +** into the index P1. Data for the entry is nil. +** +** P3 is a flag that provides a hint to the b-tree layer that this +** insert is likely to be an append. +** +** This instruction only works for indices. The equivalent instruction +** for tables is OP_Insert. +*/ +case OP_IdxInsert: { /* in2 */ + int i = pOp->p1; + Cursor *pC; + BtCursor *pCrsr; + assert( i>=0 && i<p->nCursor ); + assert( p->apCsr[i]!=0 ); + assert( pIn2->flags & MEM_Blob ); + if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ + assert( pC->isTable==0 ); + rc = ExpandBlob(pIn2); + if( rc==SQLITE_OK ){ + int nKey = pIn2->n; + const char *zKey = pIn2->z; + rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0, 0, pOp->p3); + assert( pC->deferredMoveto==0 ); + pC->cacheStatus = CACHE_STALE; + } + } + break; +} + +/* Opcode: IdxDeleteM P1 P2 P3 * * +** +** The content of P3 registers starting at register P2 form +** an unpacked index key. This opcode removes that entry from the +** index opened by cursor P1. +*/ +case OP_IdxDelete: { + int i = pOp->p1; + Cursor *pC; + BtCursor *pCrsr; + assert( pOp->p3>0 ); + assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem ); + assert( i>=0 && i<p->nCursor ); + assert( p->apCsr[i]!=0 ); + if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ + int res; + UnpackedRecord r; + r.pKeyInfo = pC->pKeyInfo; + r.nField = pOp->p3; + r.needFree = 0; + r.needDestroy = 0; + r.aMem = &p->aMem[pOp->p2]; + rc = sqlite3BtreeMoveto(pCrsr, 0, &r, 0, 0, &res); + if( rc==SQLITE_OK && res==0 ){ + rc = sqlite3BtreeDelete(pCrsr); + } + assert( pC->deferredMoveto==0 ); + pC->cacheStatus = CACHE_STALE; + } + break; +} + +/* Opcode: IdxRowid P1 P2 * * * +** +** Write into register P2 an integer which is the last entry in the record at +** the end of the index key pointed to by cursor P1. This integer should be +** the rowid of the table entry to which this index entry points. +** +** See also: Rowid, MakeIdxRec. +*/ +case OP_IdxRowid: { /* out2-prerelease */ + int i = pOp->p1; + BtCursor *pCrsr; + Cursor *pC; + + assert( i>=0 && i<p->nCursor ); + assert( p->apCsr[i]!=0 ); + if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ + i64 rowid; + + assert( pC->deferredMoveto==0 ); + assert( pC->isTable==0 ); + if( !pC->nullRow ){ + rc = sqlite3VdbeIdxRowid(pCrsr, &rowid); + if( rc!=SQLITE_OK ){ + goto abort_due_to_error; + } + MemSetTypeFlag(pOut, MEM_Int); + pOut->u.i = rowid; + } + } + break; +} + +/* Opcode: IdxGE P1 P2 P3 P4 P5 +** +** The P4 register values beginning with P3 form an unpacked index +** key that omits the ROWID. Compare this key value against the index +** that P1 is currently pointing to, ignoring the ROWID on the P1 index. +** +** If the P1 index entry is greater than or equal to the key value +** then jump to P2. Otherwise fall through to the next instruction. +** +** If P5 is non-zero then the key value is increased by an epsilon +** prior to the comparison. This make the opcode work like IdxGT except +** that if the key from register P3 is a prefix of the key in the cursor, +** the result is false whereas it would be true with IdxGT. +*/ +/* Opcode: IdxLT P1 P2 P3 * P5 +** +** The P4 register values beginning with P3 form an unpacked index +** key that omits the ROWID. Compare this key value against the index +** that P1 is currently pointing to, ignoring the ROWID on the P1 index. +** +** If the P1 index entry is less than the key value then jump to P2. +** Otherwise fall through to the next instruction. +** +** If P5 is non-zero then the key value is increased by an epsilon prior +** to the comparison. This makes the opcode work like IdxLE. +*/ +case OP_IdxLT: /* jump, in3 */ +case OP_IdxGE: { /* jump, in3 */ + int i= pOp->p1; + Cursor *pC; + + assert( i>=0 && i<p->nCursor ); + assert( p->apCsr[i]!=0 ); + if( (pC = p->apCsr[i])->pCursor!=0 ){ + int res; + UnpackedRecord r; + assert( pC->deferredMoveto==0 ); + assert( pOp->p5==0 || pOp->p5==1 ); + assert( pOp->p4type==P4_INT32 ); + r.pKeyInfo = pC->pKeyInfo; + r.nField = pOp->p4.i; + r.needFree = 0; + r.needDestroy = 0; + r.aMem = &p->aMem[pOp->p3]; + *pC->pIncrKey = pOp->p5; + rc = sqlite3VdbeIdxKeyCompare(pC, &r, 0, 0, &res); + *pC->pIncrKey = 0; + if( pOp->opcode==OP_IdxLT ){ + res = -res; + }else{ + assert( pOp->opcode==OP_IdxGE ); + res++; + } + if( res>0 ){ + pc = pOp->p2 - 1 ; + } + } + break; +} + +/* Opcode: Destroy P1 P2 P3 * * +** +** Delete an entire database table or index whose root page in the database +** file is given by P1. +** +** The table being destroyed is in the main database file if P3==0. If +** P3==1 then the table to be clear is in the auxiliary database file +** that is used to store tables create using CREATE TEMPORARY TABLE. +** +** If AUTOVACUUM is enabled then it is possible that another root page +** might be moved into the newly deleted root page in order to keep all +** root pages contiguous at the beginning of the database. The former +** value of the root page that moved - its value before the move occurred - +** is stored in register P2. If no page +** movement was required (because the table being dropped was already +** the last one in the database) then a zero is stored in register P2. +** If AUTOVACUUM is disabled then a zero is stored in register P2. +** +** See also: Clear +*/ +case OP_Destroy: { /* out2-prerelease */ + int iMoved; + int iCnt; +#ifndef SQLITE_OMIT_VIRTUALTABLE + Vdbe *pVdbe; + iCnt = 0; + for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){ + if( pVdbe->magic==VDBE_MAGIC_RUN && pVdbe->inVtabMethod<2 && pVdbe->pc>=0 ){ + iCnt++; + } + } +#else + iCnt = db->activeVdbeCnt; +#endif + if( iCnt>1 ){ + rc = SQLITE_LOCKED; + p->errorAction = OE_Abort; + }else{ + int iDb = pOp->p3; + assert( iCnt==1 ); + assert( (p->btreeMask & (1<<iDb))!=0 ); + rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved); + MemSetTypeFlag(pOut, MEM_Int); + pOut->u.i = iMoved; +#ifndef SQLITE_OMIT_AUTOVACUUM + if( rc==SQLITE_OK && iMoved!=0 ){ + sqlite3RootPageMoved(&db->aDb[iDb], iMoved, pOp->p1); + } +#endif + } + break; +} + +/* Opcode: Clear P1 P2 * +** +** Delete all contents of the database table or index whose root page +** in the database file is given by P1. But, unlike Destroy, do not +** remove the table or index from the database file. +** +** The table being clear is in the main database file if P2==0. If +** P2==1 then the table to be clear is in the auxiliary database file +** that is used to store tables create using CREATE TEMPORARY TABLE. +** +** See also: Destroy +*/ +case OP_Clear: { + assert( (p->btreeMask & (1<<pOp->p2))!=0 ); + rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, pOp->p1); + break; +} + +/* Opcode: CreateTable P1 P2 * * * +** +** Allocate a new table in the main database file if P1==0 or in the +** auxiliary database file if P1==1 or in an attached database if +** P1>1. Write the root page number of the new table into +** register P2 +** +** The difference between a table and an index is this: A table must +** have a 4-byte integer key and can have arbitrary data. An index +** has an arbitrary key but no data. +** +** See also: CreateIndex +*/ +/* Opcode: CreateIndex P1 P2 * * * +** +** Allocate a new index in the main database file if P1==0 or in the +** auxiliary database file if P1==1 or in an attached database if +** P1>1. Write the root page number of the new table into +** register P2. +** +** See documentation on OP_CreateTable for additional information. +*/ +case OP_CreateIndex: /* out2-prerelease */ +case OP_CreateTable: { /* out2-prerelease */ + int pgno; + int flags; + Db *pDb; + assert( pOp->p1>=0 && pOp->p1<db->nDb ); + assert( (p->btreeMask & (1<<pOp->p1))!=0 ); + pDb = &db->aDb[pOp->p1]; + assert( pDb->pBt!=0 ); + if( pOp->opcode==OP_CreateTable ){ + /* flags = BTREE_INTKEY; */ + flags = BTREE_LEAFDATA|BTREE_INTKEY; + }else{ + flags = BTREE_ZERODATA; + } + rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags); + if( rc==SQLITE_OK ){ + pOut->u.i = pgno; + MemSetTypeFlag(pOut, MEM_Int); + } + break; +} + +/* Opcode: ParseSchema P1 P2 * P4 * +** +** Read and parse all entries from the SQLITE_MASTER table of database P1 +** that match the WHERE clause P4. P2 is the "force" flag. Always do +** the parsing if P2 is true. If P2 is false, then this routine is a +** no-op if the schema is not currently loaded. In other words, if P2 +** is false, the SQLITE_MASTER table is only parsed if the rest of the +** schema is already loaded into the symbol table. +** +** This opcode invokes the parser to create a new virtual machine, +** then runs the new virtual machine. It is thus a re-entrant opcode. +*/ +case OP_ParseSchema: { + char *zSql; + int iDb = pOp->p1; + const char *zMaster; + InitData initData; + + assert( iDb>=0 && iDb<db->nDb ); + if( !pOp->p2 && !DbHasProperty(db, iDb, DB_SchemaLoaded) ){ + break; + } + zMaster = SCHEMA_TABLE(iDb); + initData.db = db; + initData.iDb = pOp->p1; + initData.pzErrMsg = &p->zErrMsg; + zSql = sqlite3MPrintf(db, + "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s", + db->aDb[iDb].zName, zMaster, pOp->p4.z); + if( zSql==0 ) goto no_mem; + (void)sqlite3SafetyOff(db); + assert( db->init.busy==0 ); + db->init.busy = 1; + assert( !db->mallocFailed ); + rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); + if( rc==SQLITE_ABORT ) rc = initData.rc; + sqlite3DbFree(db, zSql); + db->init.busy = 0; + (void)sqlite3SafetyOn(db); + if( rc==SQLITE_NOMEM ){ + goto no_mem; + } + break; +} + +#if !defined(SQLITE_OMIT_ANALYZE) && !defined(SQLITE_OMIT_PARSER) +/* Opcode: LoadAnalysis P1 * * * * +** +** Read the sqlite_stat1 table for database P1 and load the content +** of that table into the internal index hash table. This will cause +** the analysis to be used when preparing all subsequent queries. +*/ +case OP_LoadAnalysis: { + int iDb = pOp->p1; + assert( iDb>=0 && iDb<db->nDb ); + rc = sqlite3AnalysisLoad(db, iDb); + break; +} +#endif /* !defined(SQLITE_OMIT_ANALYZE) && !defined(SQLITE_OMIT_PARSER) */ + +/* Opcode: DropTable P1 * * P4 * +** +** Remove the internal (in-memory) data structures that describe +** the table named P4 in database P1. This is called after a table +** is dropped in order to keep the internal representation of the +** schema consistent with what is on disk. +*/ +case OP_DropTable: { + sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p4.z); + break; +} + +/* Opcode: DropIndex P1 * * P4 * +** +** Remove the internal (in-memory) data structures that describe +** the index named P4 in database P1. This is called after an index +** is dropped in order to keep the internal representation of the +** schema consistent with what is on disk. +*/ +case OP_DropIndex: { + sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p4.z); + break; +} + +/* Opcode: DropTrigger P1 * * P4 * +** +** Remove the internal (in-memory) data structures that describe +** the trigger named P4 in database P1. This is called after a trigger +** is dropped in order to keep the internal representation of the +** schema consistent with what is on disk. +*/ +case OP_DropTrigger: { + sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p4.z); + break; +} + + +#ifndef SQLITE_OMIT_INTEGRITY_CHECK +/* Opcode: IntegrityCk P1 P2 P3 * P5 +** +** Do an analysis of the currently open database. Store in +** register P1 the text of an error message describing any problems. +** If no problems are found, store a NULL in register P1. +** +** The register P3 contains the maximum number of allowed errors. +** At most reg(P3) errors will be reported. +** In other words, the analysis stops as soon as reg(P1) errors are +** seen. Reg(P1) is updated with the number of errors remaining. +** +** The root page numbers of all tables in the database are integer +** stored in reg(P1), reg(P1+1), reg(P1+2), .... There are P2 tables +** total. +** +** If P5 is not zero, the check is done on the auxiliary database +** file, not the main database file. +** +** This opcode is used to implement the integrity_check pragma. +*/ +case OP_IntegrityCk: { + int nRoot; /* Number of tables to check. (Number of root pages.) */ + int *aRoot; /* Array of rootpage numbers for tables to be checked */ + int j; /* Loop counter */ + int nErr; /* Number of errors reported */ + char *z; /* Text of the error report */ + Mem *pnErr; /* Register keeping track of errors remaining */ + + nRoot = pOp->p2; + assert( nRoot>0 ); + aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(nRoot+1) ); + if( aRoot==0 ) goto no_mem; + assert( pOp->p3>0 && pOp->p3<=p->nMem ); + pnErr = &p->aMem[pOp->p3]; + assert( (pnErr->flags & MEM_Int)!=0 ); + assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 ); + pIn1 = &p->aMem[pOp->p1]; + for(j=0; j<nRoot; j++){ + aRoot[j] = sqlite3VdbeIntValue(&pIn1[j]); + } + aRoot[j] = 0; + assert( pOp->p5<db->nDb ); + assert( (p->btreeMask & (1<<pOp->p5))!=0 ); + z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot, + pnErr->u.i, &nErr); + sqlite3DbFree(db, aRoot); + pnErr->u.i -= nErr; + sqlite3VdbeMemSetNull(pIn1); + if( nErr==0 ){ + assert( z==0 ); + }else if( z==0 ){ + goto no_mem; + }else{ + sqlite3VdbeMemSetStr(pIn1, z, -1, SQLITE_UTF8, sqlite3_free); + } + UPDATE_MAX_BLOBSIZE(pIn1); + sqlite3VdbeChangeEncoding(pIn1, encoding); + break; +} +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ + +/* Opcode: FifoWrite P1 * * * * +** +** Write the integer from register P1 into the Fifo. +*/ +case OP_FifoWrite: { /* in1 */ + p->sFifo.db = db; + if( sqlite3VdbeFifoPush(&p->sFifo, sqlite3VdbeIntValue(pIn1))==SQLITE_NOMEM ){ + goto no_mem; + } + break; +} + +/* Opcode: FifoRead P1 P2 * * * +** +** Attempt to read a single integer from the Fifo. Store that +** integer in register P1. +** +** If the Fifo is empty jump to P2. +*/ +case OP_FifoRead: { /* jump */ + CHECK_FOR_INTERRUPT; + assert( pOp->p1>0 && pOp->p1<=p->nMem ); + pOut = &p->aMem[pOp->p1]; + MemSetTypeFlag(pOut, MEM_Int); + if( sqlite3VdbeFifoPop(&p->sFifo, &pOut->u.i)==SQLITE_DONE ){ + pc = pOp->p2 - 1; + } + break; +} + +#ifndef SQLITE_OMIT_TRIGGER +/* Opcode: ContextPush * * * +** +** Save the current Vdbe context such that it can be restored by a ContextPop +** opcode. The context stores the last insert row id, the last statement change +** count, and the current statement change count. +*/ +case OP_ContextPush: { + int i = p->contextStackTop++; + Context *pContext; + + assert( i>=0 ); + /* FIX ME: This should be allocated as part of the vdbe at compile-time */ + if( i>=p->contextStackDepth ){ + p->contextStackDepth = i+1; + p->contextStack = sqlite3DbReallocOrFree(db, p->contextStack, + sizeof(Context)*(i+1)); + if( p->contextStack==0 ) goto no_mem; + } + pContext = &p->contextStack[i]; + pContext->lastRowid = db->lastRowid; + pContext->nChange = p->nChange; + pContext->sFifo = p->sFifo; + sqlite3VdbeFifoInit(&p->sFifo, db); + break; +} + +/* Opcode: ContextPop * * * +** +** Restore the Vdbe context to the state it was in when contextPush was last +** executed. The context stores the last insert row id, the last statement +** change count, and the current statement change count. +*/ +case OP_ContextPop: { + Context *pContext = &p->contextStack[--p->contextStackTop]; + assert( p->contextStackTop>=0 ); + db->lastRowid = pContext->lastRowid; + p->nChange = pContext->nChange; + sqlite3VdbeFifoClear(&p->sFifo); + p->sFifo = pContext->sFifo; + break; +} +#endif /* #ifndef SQLITE_OMIT_TRIGGER */ + +#ifndef SQLITE_OMIT_AUTOINCREMENT +/* Opcode: MemMax P1 P2 * * * +** +** Set the value of register P1 to the maximum of its current value +** and the value in register P2. +** +** This instruction throws an error if the memory cell is not initially +** an integer. +*/ +case OP_MemMax: { /* in1, in2 */ + sqlite3VdbeMemIntegerify(pIn1); + sqlite3VdbeMemIntegerify(pIn2); + if( pIn1->u.i<pIn2->u.i){ + pIn1->u.i = pIn2->u.i; + } + break; +} +#endif /* SQLITE_OMIT_AUTOINCREMENT */ + +/* Opcode: IfPos P1 P2 * * * +** +** If the value of register P1 is 1 or greater, jump to P2. +** +** It is illegal to use this instruction on a register that does +** not contain an integer. An assertion fault will result if you try. +*/ +case OP_IfPos: { /* jump, in1 */ + assert( pIn1->flags&MEM_Int ); + if( pIn1->u.i>0 ){ + pc = pOp->p2 - 1; + } + break; +} + +/* Opcode: IfNeg P1 P2 * * * +** +** If the value of register P1 is less than zero, jump to P2. +** +** It is illegal to use this instruction on a register that does +** not contain an integer. An assertion fault will result if you try. +*/ +case OP_IfNeg: { /* jump, in1 */ + assert( pIn1->flags&MEM_Int ); + if( pIn1->u.i<0 ){ + pc = pOp->p2 - 1; + } + break; +} + +/* Opcode: IfZero P1 P2 * * * +** +** If the value of register P1 is exactly 0, jump to P2. +** +** It is illegal to use this instruction on a register that does +** not contain an integer. An assertion fault will result if you try. +*/ +case OP_IfZero: { /* jump, in1 */ + assert( pIn1->flags&MEM_Int ); + if( pIn1->u.i==0 ){ + pc = pOp->p2 - 1; + } + break; +} + +/* Opcode: AggStep * P2 P3 P4 P5 +** +** Execute the step function for an aggregate. The +** function has P5 arguments. P4 is a pointer to the FuncDef +** structure that specifies the function. Use register +** P3 as the accumulator. +** +** The P5 arguments are taken from register P2 and its +** successors. +*/ +case OP_AggStep: { + int n = pOp->p5; + int i; + Mem *pMem, *pRec; + sqlite3_context ctx; + sqlite3_value **apVal; + + assert( n>=0 ); + pRec = &p->aMem[pOp->p2]; + apVal = p->apArg; + assert( apVal || n==0 ); + for(i=0; i<n; i++, pRec++){ + apVal[i] = pRec; + storeTypeInfo(pRec, encoding); + } + ctx.pFunc = pOp->p4.pFunc; + assert( pOp->p3>0 && pOp->p3<=p->nMem ); + ctx.pMem = pMem = &p->aMem[pOp->p3]; + pMem->n++; + ctx.s.flags = MEM_Null; + ctx.s.z = 0; + ctx.s.zMalloc = 0; + ctx.s.xDel = 0; + ctx.s.db = db; + ctx.isError = 0; + ctx.pColl = 0; + if( ctx.pFunc->needCollSeq ){ + assert( pOp>p->aOp ); + assert( pOp[-1].p4type==P4_COLLSEQ ); + assert( pOp[-1].opcode==OP_CollSeq ); + ctx.pColl = pOp[-1].p4.pColl; + } + (ctx.pFunc->xStep)(&ctx, n, apVal); + if( ctx.isError ){ + sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&ctx.s)); + rc = ctx.isError; + } + sqlite3VdbeMemRelease(&ctx.s); + break; +} + +/* Opcode: AggFinal P1 P2 * P4 * +** +** Execute the finalizer function for an aggregate. P1 is +** the memory location that is the accumulator for the aggregate. +** +** P2 is the number of arguments that the step function takes and +** P4 is a pointer to the FuncDef for this function. The P2 +** argument is not used by this opcode. It is only there to disambiguate +** functions that can take varying numbers of arguments. The +** P4 argument is only needed for the degenerate case where +** the step function was not previously called. +*/ +case OP_AggFinal: { + Mem *pMem; + assert( pOp->p1>0 && pOp->p1<=p->nMem ); + pMem = &p->aMem[pOp->p1]; + assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 ); + rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc); + if( rc==SQLITE_ERROR ){ + sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(pMem)); + } + sqlite3VdbeChangeEncoding(pMem, encoding); + UPDATE_MAX_BLOBSIZE(pMem); + if( sqlite3VdbeMemTooBig(pMem) ){ + goto too_big; + } + break; +} + + +#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) +/* Opcode: Vacuum * * * * * +** +** Vacuum the entire database. This opcode will cause other virtual +** machines to be created and run. It may not be called from within +** a transaction. +*/ +case OP_Vacuum: { + if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; + rc = sqlite3RunVacuum(&p->zErrMsg, db); + if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; + break; +} +#endif + +#if !defined(SQLITE_OMIT_AUTOVACUUM) +/* Opcode: IncrVacuum P1 P2 * * * +** +** Perform a single step of the incremental vacuum procedure on +** the P1 database. If the vacuum has finished, jump to instruction +** P2. Otherwise, fall through to the next instruction. +*/ +case OP_IncrVacuum: { /* jump */ + Btree *pBt; + + assert( pOp->p1>=0 && pOp->p1<db->nDb ); + assert( (p->btreeMask & (1<<pOp->p1))!=0 ); + pBt = db->aDb[pOp->p1].pBt; + rc = sqlite3BtreeIncrVacuum(pBt); + if( rc==SQLITE_DONE ){ + pc = pOp->p2 - 1; + rc = SQLITE_OK; + } + break; +} +#endif + +/* Opcode: Expire P1 * * * * +** +** Cause precompiled statements to become expired. An expired statement +** fails with an error code of SQLITE_SCHEMA if it is ever executed +** (via sqlite3_step()). +** +** If P1 is 0, then all SQL statements become expired. If P1 is non-zero, +** then only the currently executing statement is affected. +*/ +case OP_Expire: { + if( !pOp->p1 ){ + sqlite3ExpirePreparedStatements(db); + }else{ + p->expired = 1; + } + break; +} + +#ifndef SQLITE_OMIT_SHARED_CACHE +/* Opcode: TableLock P1 P2 P3 P4 * +** +** Obtain a lock on a particular table. This instruction is only used when +** the shared-cache feature is enabled. +** +** If P1 is the index of the database in sqlite3.aDb[] of the database +** on which the lock is acquired. A readlock is obtained if P3==0 or +** a write lock if P3==1. +** +** P2 contains the root-page of the table to lock. +** +** P4 contains a pointer to the name of the table being locked. This is only +** used to generate an error message if the lock cannot be obtained. +*/ +case OP_TableLock: { + int p1 = pOp->p1; + u8 isWriteLock = pOp->p3; + assert( p1>=0 && p1<db->nDb ); + assert( (p->btreeMask & (1<<p1))!=0 ); + assert( isWriteLock==0 || isWriteLock==1 ); + rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock); + if( rc==SQLITE_LOCKED ){ + const char *z = pOp->p4.z; + sqlite3SetString(&p->zErrMsg, db, "database table is locked: %s", z); + } + break; +} +#endif /* SQLITE_OMIT_SHARED_CACHE */ + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* Opcode: VBegin * * * P4 * +** +** P4 may be a pointer to an sqlite3_vtab structure. If so, call the +** xBegin method for that table. +** +** Also, whether or not P4 is set, check that this is not being called from +** within a callback to a virtual table xSync() method. If it is, set the +** error code to SQLITE_LOCKED. +*/ +case OP_VBegin: { + sqlite3_vtab *pVtab = pOp->p4.pVtab; + rc = sqlite3VtabBegin(db, pVtab); + if( pVtab ){ + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = pVtab->zErrMsg; + pVtab->zErrMsg = 0; + } + break; +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* Opcode: VCreate P1 * * P4 * +** +** P4 is the name of a virtual table in database P1. Call the xCreate method +** for that table. +*/ +case OP_VCreate: { + rc = sqlite3VtabCallCreate(db, pOp->p1, pOp->p4.z, &p->zErrMsg); + break; +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* Opcode: VDestroy P1 * * P4 * +** +** P4 is the name of a virtual table in database P1. Call the xDestroy method +** of that table. +*/ +case OP_VDestroy: { + p->inVtabMethod = 2; + rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p4.z); + p->inVtabMethod = 0; + break; +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* Opcode: VOpen P1 * * P4 * +** +** P4 is a pointer to a virtual table object, an sqlite3_vtab structure. +** P1 is a cursor number. This opcode opens a cursor to the virtual +** table and stores that cursor in P1. +*/ +case OP_VOpen: { + Cursor *pCur = 0; + sqlite3_vtab_cursor *pVtabCursor = 0; + + sqlite3_vtab *pVtab = pOp->p4.pVtab; + sqlite3_module *pModule = (sqlite3_module *)pVtab->pModule; + + assert(pVtab && pModule); + if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; + rc = pModule->xOpen(pVtab, &pVtabCursor); + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = pVtab->zErrMsg; + pVtab->zErrMsg = 0; + if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; + if( SQLITE_OK==rc ){ + /* Initialize sqlite3_vtab_cursor base class */ + pVtabCursor->pVtab = pVtab; + + /* Initialise vdbe cursor object */ + pCur = allocateCursor(p, pOp->p1, &pOp[-1], -1, 0); + if( pCur ){ + pCur->pVtabCursor = pVtabCursor; + pCur->pModule = pVtabCursor->pVtab->pModule; + }else{ + db->mallocFailed = 1; + pModule->xClose(pVtabCursor); + } + } + break; +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* Opcode: VFilter P1 P2 P3 P4 * +** +** P1 is a cursor opened using VOpen. P2 is an address to jump to if +** the filtered result set is empty. +** +** P4 is either NULL or a string that was generated by the xBestIndex +** method of the module. The interpretation of the P4 string is left +** to the module implementation. +** +** This opcode invokes the xFilter method on the virtual table specified +** by P1. The integer query plan parameter to xFilter is stored in register +** P3. Register P3+1 stores the argc parameter to be passed to the +** xFilter method. Registers P3+2..P3+1+argc are the argc +** additional parameters which are passed to +** xFilter as argv. Register P3+2 becomes argv[0] when passed to xFilter. +** +** A jump is made to P2 if the result set after filtering would be empty. +*/ +case OP_VFilter: { /* jump */ + int nArg; + int iQuery; + const sqlite3_module *pModule; + Mem *pQuery = &p->aMem[pOp->p3]; + Mem *pArgc = &pQuery[1]; + sqlite3_vtab_cursor *pVtabCursor; + sqlite3_vtab *pVtab; + + Cursor *pCur = p->apCsr[pOp->p1]; + + REGISTER_TRACE(pOp->p3, pQuery); + assert( pCur->pVtabCursor ); + pVtabCursor = pCur->pVtabCursor; + pVtab = pVtabCursor->pVtab; + pModule = pVtab->pModule; + + /* Grab the index number and argc parameters */ + assert( (pQuery->flags&MEM_Int)!=0 && pArgc->flags==MEM_Int ); + nArg = pArgc->u.i; + iQuery = pQuery->u.i; + + /* Invoke the xFilter method */ + { + int res = 0; + int i; + Mem **apArg = p->apArg; + for(i = 0; i<nArg; i++){ + apArg[i] = &pArgc[i+1]; + storeTypeInfo(apArg[i], 0); + } + + if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; + sqlite3VtabLock(pVtab); + p->inVtabMethod = 1; + rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg); + p->inVtabMethod = 0; + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = pVtab->zErrMsg; + pVtab->zErrMsg = 0; + sqlite3VtabUnlock(db, pVtab); + if( rc==SQLITE_OK ){ + res = pModule->xEof(pVtabCursor); + } + if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; + + if( res ){ + pc = pOp->p2 - 1; + } + } + pCur->nullRow = 0; + + break; +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* Opcode: VRowid P1 P2 * * * +** +** Store into register P2 the rowid of +** the virtual-table that the P1 cursor is pointing to. +*/ +case OP_VRowid: { /* out2-prerelease */ + sqlite3_vtab *pVtab; + const sqlite3_module *pModule; + sqlite_int64 iRow; + Cursor *pCur = p->apCsr[pOp->p1]; + + assert( pCur->pVtabCursor ); + if( pCur->nullRow ){ + break; + } + pVtab = pCur->pVtabCursor->pVtab; + pModule = pVtab->pModule; + assert( pModule->xRowid ); + if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; + rc = pModule->xRowid(pCur->pVtabCursor, &iRow); + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = pVtab->zErrMsg; + pVtab->zErrMsg = 0; + if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; + MemSetTypeFlag(pOut, MEM_Int); + pOut->u.i = iRow; + break; +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* Opcode: VColumn P1 P2 P3 * * +** +** Store the value of the P2-th column of +** the row of the virtual-table that the +** P1 cursor is pointing to into register P3. +*/ +case OP_VColumn: { + sqlite3_vtab *pVtab; + const sqlite3_module *pModule; + Mem *pDest; + sqlite3_context sContext; + + Cursor *pCur = p->apCsr[pOp->p1]; + assert( pCur->pVtabCursor ); + assert( pOp->p3>0 && pOp->p3<=p->nMem ); + pDest = &p->aMem[pOp->p3]; + if( pCur->nullRow ){ + sqlite3VdbeMemSetNull(pDest); + break; + } + pVtab = pCur->pVtabCursor->pVtab; + pModule = pVtab->pModule; + assert( pModule->xColumn ); + memset(&sContext, 0, sizeof(sContext)); + + /* The output cell may already have a buffer allocated. Move + ** the current contents to sContext.s so in case the user-function + ** can use the already allocated buffer instead of allocating a + ** new one. + */ + sqlite3VdbeMemMove(&sContext.s, pDest); + MemSetTypeFlag(&sContext.s, MEM_Null); + + if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; + rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2); + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = pVtab->zErrMsg; + pVtab->zErrMsg = 0; + + /* Copy the result of the function to the P3 register. We + ** do this regardless of whether or not an error occured to ensure any + ** dynamic allocation in sContext.s (a Mem struct) is released. + */ + sqlite3VdbeChangeEncoding(&sContext.s, encoding); + REGISTER_TRACE(pOp->p3, pDest); + sqlite3VdbeMemMove(pDest, &sContext.s); + UPDATE_MAX_BLOBSIZE(pDest); + + if( sqlite3SafetyOn(db) ){ + goto abort_due_to_misuse; + } + if( sqlite3VdbeMemTooBig(pDest) ){ + goto too_big; + } + break; +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* Opcode: VNext P1 P2 * * * +** +** Advance virtual table P1 to the next row in its result set and +** jump to instruction P2. Or, if the virtual table has reached +** the end of its result set, then fall through to the next instruction. +*/ +case OP_VNext: { /* jump */ + sqlite3_vtab *pVtab; + const sqlite3_module *pModule; + int res = 0; + + Cursor *pCur = p->apCsr[pOp->p1]; + assert( pCur->pVtabCursor ); + if( pCur->nullRow ){ + break; + } + pVtab = pCur->pVtabCursor->pVtab; + pModule = pVtab->pModule; + assert( pModule->xNext ); + + /* Invoke the xNext() method of the module. There is no way for the + ** underlying implementation to return an error if one occurs during + ** xNext(). Instead, if an error occurs, true is returned (indicating that + ** data is available) and the error code returned when xColumn or + ** some other method is next invoked on the save virtual table cursor. + */ + if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; + sqlite3VtabLock(pVtab); + p->inVtabMethod = 1; + rc = pModule->xNext(pCur->pVtabCursor); + p->inVtabMethod = 0; + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = pVtab->zErrMsg; + pVtab->zErrMsg = 0; + sqlite3VtabUnlock(db, pVtab); + if( rc==SQLITE_OK ){ + res = pModule->xEof(pCur->pVtabCursor); + } + if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; + + if( !res ){ + /* If there is data, jump to P2 */ + pc = pOp->p2 - 1; + } + break; +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* Opcode: VRename P1 * * P4 * +** +** P4 is a pointer to a virtual table object, an sqlite3_vtab structure. +** This opcode invokes the corresponding xRename method. The value +** in register P1 is passed as the zName argument to the xRename method. +*/ +case OP_VRename: { + sqlite3_vtab *pVtab = pOp->p4.pVtab; + Mem *pName = &p->aMem[pOp->p1]; + assert( pVtab->pModule->xRename ); + REGISTER_TRACE(pOp->p1, pName); + + Stringify(pName, encoding); + + if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; + sqlite3VtabLock(pVtab); + rc = pVtab->pModule->xRename(pVtab, pName->z); + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = pVtab->zErrMsg; + pVtab->zErrMsg = 0; + sqlite3VtabUnlock(db, pVtab); + if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; + + break; +} +#endif + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* Opcode: VUpdate P1 P2 P3 P4 * +** +** P4 is a pointer to a virtual table object, an sqlite3_vtab structure. +** This opcode invokes the corresponding xUpdate method. P2 values +** are contiguous memory cells starting at P3 to pass to the xUpdate +** invocation. The value in register (P3+P2-1) corresponds to the +** p2th element of the argv array passed to xUpdate. +** +** The xUpdate method will do a DELETE or an INSERT or both. +** The argv[0] element (which corresponds to memory cell P3) +** is the rowid of a row to delete. If argv[0] is NULL then no +** deletion occurs. The argv[1] element is the rowid of the new +** row. This can be NULL to have the virtual table select the new +** rowid for itself. The subsequent elements in the array are +** the values of columns in the new row. +** +** If P2==1 then no insert is performed. argv[0] is the rowid of +** a row to delete. +** +** P1 is a boolean flag. If it is set to true and the xUpdate call +** is successful, then the value returned by sqlite3_last_insert_rowid() +** is set to the value of the rowid for the row just inserted. +*/ +case OP_VUpdate: { + sqlite3_vtab *pVtab = pOp->p4.pVtab; + sqlite3_module *pModule = (sqlite3_module *)pVtab->pModule; + int nArg = pOp->p2; + assert( pOp->p4type==P4_VTAB ); + if( pModule->xUpdate==0 ){ + sqlite3SetString(&p->zErrMsg, db, "read-only table"); + rc = SQLITE_ERROR; + }else{ + int i; + sqlite_int64 rowid; + Mem **apArg = p->apArg; + Mem *pX = &p->aMem[pOp->p3]; + for(i=0; i<nArg; i++){ + storeTypeInfo(pX, 0); + apArg[i] = pX; + pX++; + } + if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; + sqlite3VtabLock(pVtab); + rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid); + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = pVtab->zErrMsg; + pVtab->zErrMsg = 0; + sqlite3VtabUnlock(db, pVtab); + if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; + if( pOp->p1 && rc==SQLITE_OK ){ + assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) ); + db->lastRowid = rowid; + } + p->nChange++; + } + break; +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +#ifndef SQLITE_OMIT_PAGER_PRAGMAS +/* Opcode: Pagecount P1 P2 * * * +** +** Write the current number of pages in database P1 to memory cell P2. +*/ +case OP_Pagecount: { /* out2-prerelease */ + int p1 = pOp->p1; + int nPage; + Pager *pPager = sqlite3BtreePager(db->aDb[p1].pBt); + + rc = sqlite3PagerPagecount(pPager, &nPage); + if( rc==SQLITE_OK ){ + pOut->flags = MEM_Int; + pOut->u.i = nPage; + } + break; +} +#endif + +#ifndef SQLITE_OMIT_TRACE +/* Opcode: Trace * * * P4 * +** +** If tracing is enabled (by the sqlite3_trace()) interface, then +** the UTF-8 string contained in P4 is emitted on the trace callback. +*/ +case OP_Trace: { + if( pOp->p4.z ){ + if( db->xTrace ){ + db->xTrace(db->pTraceArg, pOp->p4.z); + } +#ifdef SQLITE_DEBUG + if( (db->flags & SQLITE_SqlTrace)!=0 ){ + sqlite3DebugPrintf("SQL-trace: %s\n", pOp->p4.z); + } +#endif /* SQLITE_DEBUG */ + } + break; +} +#endif + + +/* Opcode: Noop * * * * * +** +** Do nothing. This instruction is often useful as a jump +** destination. +*/ +/* +** The magic Explain opcode are only inserted when explain==2 (which +** is to say when the EXPLAIN QUERY PLAN syntax is used.) +** This opcode records information from the optimizer. It is the +** the same as a no-op. This opcodesnever appears in a real VM program. +*/ +default: { /* This is really OP_Noop and OP_Explain */ + break; +} + +/***************************************************************************** +** The cases of the switch statement above this line should all be indented +** by 6 spaces. But the left-most 6 spaces have been removed to improve the +** readability. From this point on down, the normal indentation rules are +** restored. +*****************************************************************************/ + } + +#ifdef VDBE_PROFILE + { + u64 elapsed = sqlite3Hwtime() - start; + pOp->cycles += elapsed; + pOp->cnt++; +#if 0 + fprintf(stdout, "%10llu ", elapsed); + sqlite3VdbePrintOp(stdout, origPc, &p->aOp[origPc]); +#endif + } +#endif + + /* The following code adds nothing to the actual functionality + ** of the program. It is only here for testing and debugging. + ** On the other hand, it does burn CPU cycles every time through + ** the evaluator loop. So we can leave it out when NDEBUG is defined. + */ +#ifndef NDEBUG + assert( pc>=-1 && pc<p->nOp ); + +#ifdef SQLITE_DEBUG + if( p->trace ){ + if( rc!=0 ) fprintf(p->trace,"rc=%d\n",rc); + if( opProperty & OPFLG_OUT2_PRERELEASE ){ + registerTrace(p->trace, pOp->p2, pOut); + } + if( opProperty & OPFLG_OUT3 ){ + registerTrace(p->trace, pOp->p3, pOut); + } + } +#endif /* SQLITE_DEBUG */ +#endif /* NDEBUG */ + } /* The end of the for(;;) loop the loops through opcodes */ + + /* If we reach this point, it means that execution is finished with + ** an error of some kind. + */ +vdbe_error_halt: + assert( rc ); + p->rc = rc; + sqlite3VdbeHalt(p); + if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1; + rc = SQLITE_ERROR; + + /* This is the only way out of this procedure. We have to + ** release the mutexes on btrees that were acquired at the + ** top. */ +vdbe_return: + sqlite3BtreeMutexArrayLeave(&p->aMutex); + return rc; + + /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH + ** is encountered. + */ +too_big: + sqlite3SetString(&p->zErrMsg, db, "string or blob too big"); + rc = SQLITE_TOOBIG; + goto vdbe_error_halt; + + /* Jump to here if a malloc() fails. + */ +no_mem: + db->mallocFailed = 1; + sqlite3SetString(&p->zErrMsg, db, "out of memory"); + rc = SQLITE_NOMEM; + goto vdbe_error_halt; + + /* Jump to here for an SQLITE_MISUSE error. + */ +abort_due_to_misuse: + rc = SQLITE_MISUSE; + /* Fall thru into abort_due_to_error */ + + /* Jump to here for any other kind of fatal error. The "rc" variable + ** should hold the error number. + */ +abort_due_to_error: + assert( p->zErrMsg==0 ); + if( db->mallocFailed ) rc = SQLITE_NOMEM; + if( rc!=SQLITE_IOERR_NOMEM ){ + sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3ErrStr(rc)); + } + goto vdbe_error_halt; + + /* Jump to here if the sqlite3_interrupt() API sets the interrupt + ** flag. + */ +abort_due_to_interrupt: + assert( db->u1.isInterrupted ); + rc = SQLITE_INTERRUPT; + p->rc = rc; + sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3ErrStr(rc)); + goto vdbe_error_halt; +} diff --git a/third_party/sqlite/src/vdbe.h b/third_party/sqlite/src/vdbe.h new file mode 100755 index 0000000..815b615 --- /dev/null +++ b/third_party/sqlite/src/vdbe.h @@ -0,0 +1,206 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** Header file for the Virtual DataBase Engine (VDBE) +** +** This header defines the interface to the virtual database engine +** or VDBE. The VDBE implements an abstract machine that runs a +** simple program to access and modify the underlying database. +** +** $Id: vdbe.h,v 1.135 2008/08/01 20:10:08 drh Exp $ +*/ +#ifndef _SQLITE_VDBE_H_ +#define _SQLITE_VDBE_H_ +#include <stdio.h> + +/* +** A single VDBE is an opaque structure named "Vdbe". Only routines +** in the source file sqliteVdbe.c are allowed to see the insides +** of this structure. +*/ +typedef struct Vdbe Vdbe; + +/* +** The names of the following types declared in vdbeInt.h are required +** for the VdbeOp definition. +*/ +typedef struct VdbeFunc VdbeFunc; +typedef struct Mem Mem; +typedef struct UnpackedRecord UnpackedRecord; + +/* +** A single instruction of the virtual machine has an opcode +** and as many as three operands. The instruction is recorded +** as an instance of the following structure: +*/ +struct VdbeOp { + u8 opcode; /* What operation to perform */ + signed char p4type; /* One of the P4_xxx constants for p4 */ + u8 opflags; /* Not currently used */ + u8 p5; /* Fifth parameter is an unsigned character */ + int p1; /* First operand */ + int p2; /* Second parameter (often the jump destination) */ + int p3; /* The third parameter */ + union { /* forth parameter */ + int i; /* Integer value if p4type==P4_INT32 */ + void *p; /* Generic pointer */ + char *z; /* Pointer to data for string (char array) types */ + i64 *pI64; /* Used when p4type is P4_INT64 */ + double *pReal; /* Used when p4type is P4_REAL */ + FuncDef *pFunc; /* Used when p4type is P4_FUNCDEF */ + VdbeFunc *pVdbeFunc; /* Used when p4type is P4_VDBEFUNC */ + CollSeq *pColl; /* Used when p4type is P4_COLLSEQ */ + Mem *pMem; /* Used when p4type is P4_MEM */ + sqlite3_vtab *pVtab; /* Used when p4type is P4_VTAB */ + KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */ + int *ai; /* Used when p4type is P4_INTARRAY */ + } p4; +#ifdef SQLITE_DEBUG + char *zComment; /* Comment to improve readability */ +#endif +#ifdef VDBE_PROFILE + int cnt; /* Number of times this instruction was executed */ + u64 cycles; /* Total time spent executing this instruction */ +#endif +}; +typedef struct VdbeOp VdbeOp; + +/* +** A smaller version of VdbeOp used for the VdbeAddOpList() function because +** it takes up less space. +*/ +struct VdbeOpList { + u8 opcode; /* What operation to perform */ + signed char p1; /* First operand */ + signed char p2; /* Second parameter (often the jump destination) */ + signed char p3; /* Third parameter */ +}; +typedef struct VdbeOpList VdbeOpList; + +/* +** Allowed values of VdbeOp.p3type +*/ +#define P4_NOTUSED 0 /* The P4 parameter is not used */ +#define P4_DYNAMIC (-1) /* Pointer to a string obtained from sqliteMalloc() */ +#define P4_STATIC (-2) /* Pointer to a static string */ +#define P4_COLLSEQ (-4) /* P4 is a pointer to a CollSeq structure */ +#define P4_FUNCDEF (-5) /* P4 is a pointer to a FuncDef structure */ +#define P4_KEYINFO (-6) /* P4 is a pointer to a KeyInfo structure */ +#define P4_VDBEFUNC (-7) /* P4 is a pointer to a VdbeFunc structure */ +#define P4_MEM (-8) /* P4 is a pointer to a Mem* structure */ +#define P4_TRANSIENT (-9) /* P4 is a pointer to a transient string */ +#define P4_VTAB (-10) /* P4 is a pointer to an sqlite3_vtab structure */ +#define P4_MPRINTF (-11) /* P4 is a string obtained from sqlite3_mprintf() */ +#define P4_REAL (-12) /* P4 is a 64-bit floating point value */ +#define P4_INT64 (-13) /* P4 is a 64-bit signed integer */ +#define P4_INT32 (-14) /* P4 is a 32-bit signed integer */ +#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */ + +/* When adding a P4 argument using P4_KEYINFO, a copy of the KeyInfo structure +** is made. That copy is freed when the Vdbe is finalized. But if the +** argument is P4_KEYINFO_HANDOFF, the passed in pointer is used. It still +** gets freed when the Vdbe is finalized so it still should be obtained +** from a single sqliteMalloc(). But no copy is made and the calling +** function should *not* try to free the KeyInfo. +*/ +#define P4_KEYINFO_HANDOFF (-16) +#define P4_KEYINFO_STATIC (-17) + +/* +** The Vdbe.aColName array contains 5n Mem structures, where n is the +** number of columns of data returned by the statement. +*/ +#define COLNAME_NAME 0 +#define COLNAME_DECLTYPE 1 +#define COLNAME_DATABASE 2 +#define COLNAME_TABLE 3 +#define COLNAME_COLUMN 4 +#ifdef SQLITE_ENABLE_COLUMN_METADATA +# define COLNAME_N 5 /* Number of COLNAME_xxx symbols */ +#else +# ifdef SQLITE_OMIT_DECLTYPE +# define COLNAME_N 1 /* Store only the name */ +# else +# define COLNAME_N 2 /* Store the name and decltype */ +# endif +#endif + +/* +** The following macro converts a relative address in the p2 field +** of a VdbeOp structure into a negative number so that +** sqlite3VdbeAddOpList() knows that the address is relative. Calling +** the macro again restores the address. +*/ +#define ADDR(X) (-1-(X)) + +/* +** The makefile scans the vdbe.c source file and creates the "opcodes.h" +** header file that defines a number for each opcode used by the VDBE. +*/ +#include "opcodes.h" + +/* +** Prototypes for the VDBE interface. See comments on the implementation +** for a description of what each of these routines does. +*/ +Vdbe *sqlite3VdbeCreate(sqlite3*); +int sqlite3VdbeAddOp0(Vdbe*,int); +int sqlite3VdbeAddOp1(Vdbe*,int,int); +int sqlite3VdbeAddOp2(Vdbe*,int,int,int); +int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int); +int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int); +int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp); +void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1); +void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2); +void sqlite3VdbeChangeP3(Vdbe*, int addr, int P3); +void sqlite3VdbeChangeP5(Vdbe*, u8 P5); +void sqlite3VdbeJumpHere(Vdbe*, int addr); +void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N); +void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); +void sqlite3VdbeUsesBtree(Vdbe*, int); +VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); +int sqlite3VdbeMakeLabel(Vdbe*); +void sqlite3VdbeDelete(Vdbe*); +void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int); +int sqlite3VdbeFinalize(Vdbe*); +void sqlite3VdbeResolveLabel(Vdbe*, int); +int sqlite3VdbeCurrentAddr(Vdbe*); +#ifdef SQLITE_DEBUG + void sqlite3VdbeTrace(Vdbe*,FILE*); +#endif +void sqlite3VdbeResetStepResult(Vdbe*); +int sqlite3VdbeReset(Vdbe*); +void sqlite3VdbeSetNumCols(Vdbe*,int); +int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, int); +void sqlite3VdbeCountChanges(Vdbe*); +sqlite3 *sqlite3VdbeDb(Vdbe*); +void sqlite3VdbeSetSql(Vdbe*, const char *z, int n); +void sqlite3VdbeSwap(Vdbe*,Vdbe*); + +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +int sqlite3VdbeReleaseMemory(int); +#endif +UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,void*,int); +void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord*); +int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); + + +#ifndef NDEBUG + void sqlite3VdbeComment(Vdbe*, const char*, ...); +# define VdbeComment(X) sqlite3VdbeComment X + void sqlite3VdbeNoopComment(Vdbe*, const char*, ...); +# define VdbeNoopComment(X) sqlite3VdbeNoopComment X +#else +# define VdbeComment(X) +# define VdbeNoopComment(X) +#endif + +#endif diff --git a/third_party/sqlite/src/vdbeInt.h b/third_party/sqlite/src/vdbeInt.h new file mode 100755 index 0000000..6516f13 --- /dev/null +++ b/third_party/sqlite/src/vdbeInt.h @@ -0,0 +1,447 @@ +/* +** 2003 September 6 +** +** 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 is the header file for information that is private to the +** VDBE. This information used to all be at the top of the single +** source code file "vdbe.c". When that file became too big (over +** 6000 lines long) it was split up into several smaller files and +** this header information was factored out. +** +** $Id: vdbeInt.h,v 1.153 2008/08/02 03:50:39 drh Exp $ +*/ +#ifndef _VDBEINT_H_ +#define _VDBEINT_H_ + +/* +** intToKey() and keyToInt() used to transform the rowid. But with +** the latest versions of the design they are no-ops. +*/ +#define keyToInt(X) (X) +#define intToKey(X) (X) + + +/* +** SQL is translated into a sequence of instructions to be +** executed by a virtual machine. Each instruction is an instance +** of the following structure. +*/ +typedef struct VdbeOp Op; + +/* +** Boolean values +*/ +typedef unsigned char Bool; + +/* +** A cursor is a pointer into a single BTree within a database file. +** The cursor can seek to a BTree entry with a particular key, or +** loop over all entries of the Btree. You can also insert new BTree +** entries or retrieve the key or data from the entry that the cursor +** is currently pointing to. +** +** Every cursor that the virtual machine has open is represented by an +** instance of the following structure. +** +** If the Cursor.isTriggerRow flag is set it means that this cursor is +** really a single row that represents the NEW or OLD pseudo-table of +** a row trigger. The data for the row is stored in Cursor.pData and +** the rowid is in Cursor.iKey. +*/ +struct Cursor { + BtCursor *pCursor; /* The cursor structure of the backend */ + int iDb; /* Index of cursor database in db->aDb[] (or -1) */ + i64 lastRowid; /* Last rowid from a Next or NextIdx operation */ + i64 nextRowid; /* Next rowid returned by OP_NewRowid */ + Bool zeroed; /* True if zeroed out and ready for reuse */ + Bool rowidIsValid; /* True if lastRowid is valid */ + Bool atFirst; /* True if pointing to first entry */ + Bool useRandomRowid; /* Generate new record numbers semi-randomly */ + Bool nullRow; /* True if pointing to a row with no data */ + Bool nextRowidValid; /* True if the nextRowid field is valid */ + Bool pseudoTable; /* This is a NEW or OLD pseudo-tables of a trigger */ + Bool ephemPseudoTable; + Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ + Bool isTable; /* True if a table requiring integer keys */ + Bool isIndex; /* True if an index containing keys only - no data */ + u8 bogusIncrKey; /* Something for pIncrKey to point to if pKeyInfo==0 */ + i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ + Btree *pBt; /* Separate file holding temporary table */ + int nData; /* Number of bytes in pData */ + char *pData; /* Data for a NEW or OLD pseudo-table */ + i64 iKey; /* Key for the NEW or OLD pseudo-table row */ + u8 *pIncrKey; /* Pointer to pKeyInfo->incrKey */ + KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */ + int nField; /* Number of fields in the header */ + i64 seqCount; /* Sequence counter */ + sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */ + const sqlite3_module *pModule; /* Module for cursor pVtabCursor */ + + /* Cached information about the header for the data record that the + ** cursor is currently pointing to. Only valid if cacheValid is true. + ** aRow might point to (ephemeral) data for the current row, or it might + ** be NULL. + */ + int cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */ + int payloadSize; /* Total number of bytes in the record */ + u32 *aType; /* Type values for all entries in the record */ + u32 *aOffset; /* Cached offsets to the start of each columns data */ + u8 *aRow; /* Data for the current row, if all on one page */ +}; +typedef struct Cursor Cursor; + +/* +** A value for Cursor.cacheValid that means the cache is always invalid. +*/ +#define CACHE_STALE 0 + +/* +** Internally, the vdbe manipulates nearly all SQL values as Mem +** structures. Each Mem struct may cache multiple representations (string, +** integer etc.) of the same value. A value (and therefore Mem structure) +** has the following properties: +** +** Each value has a manifest type. The manifest type of the value stored +** in a Mem struct is returned by the MemType(Mem*) macro. The type is +** one of SQLITE_NULL, SQLITE_INTEGER, SQLITE_REAL, SQLITE_TEXT or +** SQLITE_BLOB. +*/ +struct Mem { + union { + i64 i; /* Integer value. Or FuncDef* when flags==MEM_Agg */ + FuncDef *pDef; /* Used only when flags==MEM_Agg */ + } u; + double r; /* Real value */ + sqlite3 *db; /* The associated database connection */ + char *z; /* String or BLOB value */ + int n; /* Number of characters in string value, excluding '\0' */ + u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */ + u8 type; /* One of SQLITE_NULL, SQLITE_TEXT, SQLITE_INTEGER, etc */ + u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */ + void (*xDel)(void *); /* If not null, call this function to delete Mem.z */ + char *zMalloc; /* Dynamic buffer allocated by sqlite3_malloc() */ +}; + +/* One or more of the following flags are set to indicate the validOK +** representations of the value stored in the Mem struct. +** +** If the MEM_Null flag is set, then the value is an SQL NULL value. +** No other flags may be set in this case. +** +** If the MEM_Str flag is set then Mem.z points at a string representation. +** Usually this is encoded in the same unicode encoding as the main +** database (see below for exceptions). If the MEM_Term flag is also +** set, then the string is nul terminated. The MEM_Int and MEM_Real +** flags may coexist with the MEM_Str flag. +** +** Multiple of these values can appear in Mem.flags. But only one +** at a time can appear in Mem.type. +*/ +#define MEM_Null 0x0001 /* Value is NULL */ +#define MEM_Str 0x0002 /* Value is a string */ +#define MEM_Int 0x0004 /* Value is an integer */ +#define MEM_Real 0x0008 /* Value is a real number */ +#define MEM_Blob 0x0010 /* Value is a BLOB */ + +#define MemSetTypeFlag(p, f) \ + ((p)->flags = ((p)->flags&~(MEM_Int|MEM_Real|MEM_Null|MEM_Blob|MEM_Str))|f) + +/* Whenever Mem contains a valid string or blob representation, one of +** the following flags must be set to determine the memory management +** policy for Mem.z. The MEM_Term flag tells us whether or not the +** string is \000 or \u0000 terminated +*/ +#define MEM_Term 0x0020 /* String rep is nul terminated */ +#define MEM_Dyn 0x0040 /* Need to call sqliteFree() on Mem.z */ +#define MEM_Static 0x0080 /* Mem.z points to a static string */ +#define MEM_Ephem 0x0100 /* Mem.z points to an ephemeral string */ +#define MEM_Agg 0x0400 /* Mem.z points to an agg function context */ +#define MEM_Zero 0x0800 /* Mem.i contains count of 0s appended to blob */ + +#ifdef SQLITE_OMIT_INCRBLOB + #undef MEM_Zero + #define MEM_Zero 0x0000 +#endif + + +/* A VdbeFunc is just a FuncDef (defined in sqliteInt.h) that contains +** additional information about auxiliary information bound to arguments +** of the function. This is used to implement the sqlite3_get_auxdata() +** and sqlite3_set_auxdata() APIs. The "auxdata" is some auxiliary data +** that can be associated with a constant argument to a function. This +** allows functions such as "regexp" to compile their constant regular +** expression argument once and reused the compiled code for multiple +** invocations. +*/ +struct VdbeFunc { + FuncDef *pFunc; /* The definition of the function */ + int nAux; /* Number of entries allocated for apAux[] */ + struct AuxData { + void *pAux; /* Aux data for the i-th argument */ + void (*xDelete)(void *); /* Destructor for the aux data */ + } apAux[1]; /* One slot for each function argument */ +}; + +/* +** The "context" argument for a installable function. A pointer to an +** instance of this structure is the first argument to the routines used +** implement the SQL functions. +** +** There is a typedef for this structure in sqlite.h. So all routines, +** even the public interface to SQLite, can use a pointer to this structure. +** But this file is the only place where the internal details of this +** structure are known. +** +** This structure is defined inside of vdbeInt.h because it uses substructures +** (Mem) which are only defined there. +*/ +struct sqlite3_context { + FuncDef *pFunc; /* Pointer to function information. MUST BE FIRST */ + VdbeFunc *pVdbeFunc; /* Auxilary data, if created. */ + Mem s; /* The return value is stored here */ + Mem *pMem; /* Memory cell used to store aggregate context */ + int isError; /* Error code returned by the function. */ + CollSeq *pColl; /* Collating sequence */ +}; + +/* +** A Set structure is used for quick testing to see if a value +** is part of a small set. Sets are used to implement code like +** this: +** x.y IN ('hi','hoo','hum') +*/ +typedef struct Set Set; +struct Set { + Hash hash; /* A set is just a hash table */ + HashElem *prev; /* Previously accessed hash elemen */ +}; + +/* +** A FifoPage structure holds a single page of valves. Pages are arranged +** in a list. +*/ +typedef struct FifoPage FifoPage; +struct FifoPage { + int nSlot; /* Number of entries aSlot[] */ + int iWrite; /* Push the next value into this entry in aSlot[] */ + int iRead; /* Read the next value from this entry in aSlot[] */ + FifoPage *pNext; /* Next page in the fifo */ + i64 aSlot[1]; /* One or more slots for rowid values */ +}; + +/* +** The Fifo structure is typedef-ed in vdbeInt.h. But the implementation +** of that structure is private to this file. +** +** The Fifo structure describes the entire fifo. +*/ +typedef struct Fifo Fifo; +struct Fifo { + int nEntry; /* Total number of entries */ + sqlite3 *db; /* The associated database connection */ + FifoPage *pFirst; /* First page on the list */ + FifoPage *pLast; /* Last page on the list */ +}; + +/* +** A Context stores the last insert rowid, the last statement change count, +** and the current statement change count (i.e. changes since last statement). +** The current keylist is also stored in the context. +** Elements of Context structure type make up the ContextStack, which is +** updated by the ContextPush and ContextPop opcodes (used by triggers). +** The context is pushed before executing a trigger a popped when the +** trigger finishes. +*/ +typedef struct Context Context; +struct Context { + i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */ + int nChange; /* Statement changes (Vdbe.nChanges) */ + Fifo sFifo; /* Records that will participate in a DELETE or UPDATE */ +}; + +/* +** An instance of the virtual machine. This structure contains the complete +** state of the virtual machine. +** +** The "sqlite3_stmt" structure pointer that is returned by sqlite3_compile() +** is really a pointer to an instance of this structure. +** +** The Vdbe.inVtabMethod variable is set to non-zero for the duration of +** any virtual table method invocations made by the vdbe program. It is +** set to 2 for xDestroy method calls and 1 for all other methods. This +** variable is used for two purposes: to allow xDestroy methods to execute +** "DROP TABLE" statements and to prevent some nasty side effects of +** malloc failure when SQLite is invoked recursively by a virtual table +** method function. +*/ +struct Vdbe { + sqlite3 *db; /* The whole database */ + Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */ + int nOp; /* Number of instructions in the program */ + int nOpAlloc; /* Number of slots allocated for aOp[] */ + Op *aOp; /* Space to hold the virtual machine's program */ + int nLabel; /* Number of labels used */ + int nLabelAlloc; /* Number of slots allocated in aLabel[] */ + int *aLabel; /* Space to hold the labels */ + Mem **apArg; /* Arguments to currently executing user function */ + Mem *aColName; /* Column names to return */ + int nCursor; /* Number of slots in apCsr[] */ + Cursor **apCsr; /* One element of this array for each open cursor */ + int nVar; /* Number of entries in aVar[] */ + Mem *aVar; /* Values for the OP_Variable opcode. */ + char **azVar; /* Name of variables */ + int okVar; /* True if azVar[] has been initialized */ + int magic; /* Magic number for sanity checking */ + int nMem; /* Number of memory locations currently allocated */ + Mem *aMem; /* The memory locations */ + int nCallback; /* Number of callbacks invoked so far */ + int cacheCtr; /* Cursor row cache generation counter */ + Fifo sFifo; /* A list of ROWIDs */ + int contextStackTop; /* Index of top element in the context stack */ + int contextStackDepth; /* The size of the "context" stack */ + Context *contextStack; /* Stack used by opcodes ContextPush & ContextPop*/ + int pc; /* The program counter */ + int rc; /* Value to return */ + unsigned uniqueCnt; /* Used by OP_MakeRecord when P2!=0 */ + int errorAction; /* Recovery action to do in case of an error */ + int inTempTrans; /* True if temp database is transactioned */ + int nResColumn; /* Number of columns in one row of the result set */ + char **azResColumn; /* Values for one row of result */ + char *zErrMsg; /* Error message written here */ + Mem *pResultSet; /* Pointer to an array of results */ + u8 explain; /* True if EXPLAIN present on SQL command */ + u8 changeCntOn; /* True to update the change-counter */ + u8 expired; /* True if the VM needs to be recompiled */ + u8 minWriteFileFormat; /* Minimum file format for writable database files */ + u8 inVtabMethod; /* See comments above */ + int nChange; /* Number of db changes made since last reset */ + i64 startTime; /* Time when query started - used for profiling */ + int btreeMask; /* Bitmask of db->aDb[] entries referenced */ + BtreeMutexArray aMutex; /* An array of Btree used here and needing locks */ + int nSql; /* Number of bytes in zSql */ + char *zSql; /* Text of the SQL statement that generated this */ +#ifdef SQLITE_DEBUG + FILE *trace; /* Write an execution trace here, if not NULL */ +#endif + int openedStatement; /* True if this VM has opened a statement journal */ +#ifdef SQLITE_SSE + int fetchId; /* Statement number used by sqlite3_fetch_statement */ + int lru; /* Counter used for LRU cache replacement */ +#endif +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + Vdbe *pLruPrev; + Vdbe *pLruNext; +#endif +}; + +/* +** An instance of the following structure holds information about a +** single index record that has already been parsed out into individual +** values. +** +** A record is an object that contains one or more fields of data. +** Records are used to store the content of a table row and to store +** the key of an index. A blob encoding of a record is created by +** the OP_MakeRecord opcode of the VDBE and is disassemblied by the +** OP_Column opcode. +** +** This structure holds a record that has already been disassembled +** into its constitutent fields. +*/ +struct UnpackedRecord { + KeyInfo *pKeyInfo; /* Collation and sort-order information */ + u16 nField; /* Number of entries in apMem[] */ + u8 needFree; /* True if memory obtained from sqlite3_malloc() */ + u8 needDestroy; /* True if apMem[]s should be destroyed on close */ + Mem *aMem; /* Values */ +}; + +/* +** The following are allowed values for Vdbe.magic +*/ +#define VDBE_MAGIC_INIT 0x26bceaa5 /* Building a VDBE program */ +#define VDBE_MAGIC_RUN 0xbdf20da3 /* VDBE is ready to execute */ +#define VDBE_MAGIC_HALT 0x519c2973 /* VDBE has completed execution */ +#define VDBE_MAGIC_DEAD 0xb606c3c8 /* The VDBE has been deallocated */ + +/* +** Function prototypes +*/ +void sqlite3VdbeFreeCursor(Vdbe *, Cursor*); +void sqliteVdbePopStack(Vdbe*,int); +int sqlite3VdbeCursorMoveto(Cursor*); +#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) +void sqlite3VdbePrintOp(FILE*, int, Op*); +#endif +int sqlite3VdbeSerialTypeLen(u32); +u32 sqlite3VdbeSerialType(Mem*, int); +int sqlite3VdbeSerialPut(unsigned char*, int, Mem*, int); +int sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); +void sqlite3VdbeDeleteAuxData(VdbeFunc*, int); + +int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *); +int sqlite3VdbeIdxKeyCompare(Cursor*,UnpackedRecord *,int,const unsigned char*,int*); +int sqlite3VdbeIdxRowid(BtCursor *, i64 *); +int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); +int sqlite3VdbeIdxRowidLen(const u8*, int, int*); +int sqlite3VdbeExec(Vdbe*); +int sqlite3VdbeList(Vdbe*); +int sqlite3VdbeHalt(Vdbe*); +int sqlite3VdbeChangeEncoding(Mem *, int); +int sqlite3VdbeMemTooBig(Mem*); +int sqlite3VdbeMemCopy(Mem*, const Mem*); +void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int); +void sqlite3VdbeMemMove(Mem*, Mem*); +int sqlite3VdbeMemNulTerminate(Mem*); +int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*)); +void sqlite3VdbeMemSetInt64(Mem*, i64); +void sqlite3VdbeMemSetDouble(Mem*, double); +void sqlite3VdbeMemSetNull(Mem*); +void sqlite3VdbeMemSetZeroBlob(Mem*,int); +int sqlite3VdbeMemMakeWriteable(Mem*); +int sqlite3VdbeMemStringify(Mem*, int); +i64 sqlite3VdbeIntValue(Mem*); +int sqlite3VdbeMemIntegerify(Mem*); +double sqlite3VdbeRealValue(Mem*); +void sqlite3VdbeIntegerAffinity(Mem*); +int sqlite3VdbeMemRealify(Mem*); +int sqlite3VdbeMemNumerify(Mem*); +int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*); +void sqlite3VdbeMemRelease(Mem *p); +void sqlite3VdbeMemReleaseExternal(Mem *p); +int sqlite3VdbeMemFinalize(Mem*, FuncDef*); +const char *sqlite3OpcodeName(int); +int sqlite3VdbeOpcodeHasProperty(int, int); +int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +int sqlite3VdbeReleaseBuffers(Vdbe *p); +#endif + +#ifndef NDEBUG + void sqlite3VdbeMemSanity(Mem*); +#endif +int sqlite3VdbeMemTranslate(Mem*, u8); +#ifdef SQLITE_DEBUG + void sqlite3VdbePrintSql(Vdbe*); + void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf); +#endif +int sqlite3VdbeMemHandleBom(Mem *pMem); +void sqlite3VdbeFifoInit(Fifo*, sqlite3*); +int sqlite3VdbeFifoPush(Fifo*, i64); +int sqlite3VdbeFifoPop(Fifo*, i64*); +void sqlite3VdbeFifoClear(Fifo*); + +#ifndef SQLITE_OMIT_INCRBLOB + int sqlite3VdbeMemExpandBlob(Mem *); +#else + #define sqlite3VdbeMemExpandBlob(x) SQLITE_OK +#endif + +#endif /* !defined(_VDBEINT_H_) */ diff --git a/third_party/sqlite/src/vdbeapi.c b/third_party/sqlite/src/vdbeapi.c new file mode 100755 index 0000000..880c4ae --- /dev/null +++ b/third_party/sqlite/src/vdbeapi.c @@ -0,0 +1,1275 @@ +/* +** 2004 May 26 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file contains code use to implement APIs that are part of the +** VDBE. +** +** $Id: vdbeapi.c,v 1.138 2008/08/02 03:50:39 drh Exp $ +*/ +#include "sqliteInt.h" +#include "vdbeInt.h" + +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +/* +** The following structure contains pointers to the end points of a +** doubly-linked list of all compiled SQL statements that may be holding +** buffers eligible for release when the sqlite3_release_memory() interface is +** invoked. Access to this list is protected by the SQLITE_MUTEX_STATIC_LRU2 +** mutex. +** +** Statements are added to the end of this list when sqlite3_reset() is +** called. They are removed either when sqlite3_step() or sqlite3_finalize() +** is called. When statements are added to this list, the associated +** register array (p->aMem[1..p->nMem]) may contain dynamic buffers that +** can be freed using sqlite3VdbeReleaseMemory(). +** +** When statements are added or removed from this list, the mutex +** associated with the Vdbe being added or removed (Vdbe.db->mutex) is +** already held. The LRU2 mutex is then obtained, blocking if necessary, +** the linked-list pointers manipulated and the LRU2 mutex relinquished. +*/ +struct StatementLruList { + Vdbe *pFirst; + Vdbe *pLast; +}; +static struct StatementLruList sqlite3LruStatements; + +/* +** Check that the list looks to be internally consistent. This is used +** as part of an assert() statement as follows: +** +** assert( stmtLruCheck() ); +*/ +#ifndef NDEBUG +static int stmtLruCheck(){ + Vdbe *p; + for(p=sqlite3LruStatements.pFirst; p; p=p->pLruNext){ + assert(p->pLruNext || p==sqlite3LruStatements.pLast); + assert(!p->pLruNext || p->pLruNext->pLruPrev==p); + assert(p->pLruPrev || p==sqlite3LruStatements.pFirst); + assert(!p->pLruPrev || p->pLruPrev->pLruNext==p); + } + return 1; +} +#endif + +/* +** Add vdbe p to the end of the statement lru list. It is assumed that +** p is not already part of the list when this is called. The lru list +** is protected by the SQLITE_MUTEX_STATIC_LRU mutex. +*/ +static void stmtLruAdd(Vdbe *p){ + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2)); + + if( p->pLruPrev || p->pLruNext || sqlite3LruStatements.pFirst==p ){ + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2)); + return; + } + + assert( stmtLruCheck() ); + + if( !sqlite3LruStatements.pFirst ){ + assert( !sqlite3LruStatements.pLast ); + sqlite3LruStatements.pFirst = p; + sqlite3LruStatements.pLast = p; + }else{ + assert( !sqlite3LruStatements.pLast->pLruNext ); + p->pLruPrev = sqlite3LruStatements.pLast; + sqlite3LruStatements.pLast->pLruNext = p; + sqlite3LruStatements.pLast = p; + } + + assert( stmtLruCheck() ); + + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2)); +} + +/* +** Assuming the SQLITE_MUTEX_STATIC_LRU2 mutext is already held, remove +** statement p from the least-recently-used statement list. If the +** statement is not currently part of the list, this call is a no-op. +*/ +static void stmtLruRemoveNomutex(Vdbe *p){ + if( p->pLruPrev || p->pLruNext || p==sqlite3LruStatements.pFirst ){ + assert( stmtLruCheck() ); + if( p->pLruNext ){ + p->pLruNext->pLruPrev = p->pLruPrev; + }else{ + sqlite3LruStatements.pLast = p->pLruPrev; + } + if( p->pLruPrev ){ + p->pLruPrev->pLruNext = p->pLruNext; + }else{ + sqlite3LruStatements.pFirst = p->pLruNext; + } + p->pLruNext = 0; + p->pLruPrev = 0; + assert( stmtLruCheck() ); + } +} + +/* +** Assuming the SQLITE_MUTEX_STATIC_LRU2 mutext is not held, remove +** statement p from the least-recently-used statement list. If the +** statement is not currently part of the list, this call is a no-op. +*/ +static void stmtLruRemove(Vdbe *p){ + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2)); + stmtLruRemoveNomutex(p); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2)); +} + +/* +** Try to release n bytes of memory by freeing buffers associated +** with the memory registers of currently unused vdbes. +*/ +int sqlite3VdbeReleaseMemory(int n){ + Vdbe *p; + Vdbe *pNext; + int nFree = 0; + + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2)); + for(p=sqlite3LruStatements.pFirst; p && nFree<n; p=pNext){ + pNext = p->pLruNext; + + /* For each statement handle in the lru list, attempt to obtain the + ** associated database mutex. If it cannot be obtained, continue + ** to the next statement handle. It is not possible to block on + ** the database mutex - that could cause deadlock. + */ + if( SQLITE_OK==sqlite3_mutex_try(p->db->mutex) ){ + nFree += sqlite3VdbeReleaseBuffers(p); + stmtLruRemoveNomutex(p); + sqlite3_mutex_leave(p->db->mutex); + } + } + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2)); + + return nFree; +} + +/* +** Call sqlite3Reprepare() on the statement. Remove it from the +** lru list before doing so, as Reprepare() will free all the +** memory register buffers anyway. +*/ +int vdbeReprepare(Vdbe *p){ + stmtLruRemove(p); + return sqlite3Reprepare(p); +} + +#else /* !SQLITE_ENABLE_MEMORY_MANAGEMENT */ + #define stmtLruRemove(x) + #define stmtLruAdd(x) + #define vdbeReprepare(x) sqlite3Reprepare(x) +#endif + + +/* +** Return TRUE (non-zero) of the statement supplied as an argument needs +** to be recompiled. A statement needs to be recompiled whenever the +** execution environment changes in a way that would alter the program +** that sqlite3_prepare() generates. For example, if new functions or +** collating sequences are registered or if an authorizer function is +** added or changed. +*/ +int sqlite3_expired(sqlite3_stmt *pStmt){ + Vdbe *p = (Vdbe*)pStmt; + return p==0 || p->expired; +} + +/* +** The following routine destroys a virtual machine that is created by +** the sqlite3_compile() routine. The integer returned is an SQLITE_ +** success/failure code that describes the result of executing the virtual +** machine. +** +** This routine sets the error code and string returned by +** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). +*/ +int sqlite3_finalize(sqlite3_stmt *pStmt){ + int rc; + if( pStmt==0 ){ + rc = SQLITE_OK; + }else{ + Vdbe *v = (Vdbe*)pStmt; +#ifndef SQLITE_MUTEX_NOOP + sqlite3_mutex *mutex = v->db->mutex; +#endif + sqlite3_mutex_enter(mutex); + stmtLruRemove(v); + rc = sqlite3VdbeFinalize(v); + sqlite3_mutex_leave(mutex); + } + return rc; +} + +/* +** Terminate the current execution of an SQL statement and reset it +** back to its starting state so that it can be reused. A success code from +** the prior execution is returned. +** +** This routine sets the error code and string returned by +** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). +*/ +int sqlite3_reset(sqlite3_stmt *pStmt){ + int rc; + if( pStmt==0 ){ + rc = SQLITE_OK; + }else{ + Vdbe *v = (Vdbe*)pStmt; + sqlite3_mutex_enter(v->db->mutex); + rc = sqlite3VdbeReset(v); + stmtLruAdd(v); + sqlite3VdbeMakeReady(v, -1, 0, 0, 0); + assert( (rc & (v->db->errMask))==rc ); + sqlite3_mutex_leave(v->db->mutex); + } + return rc; +} + +/* +** Set all the parameters in the compiled SQL statement to NULL. +*/ +int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ + int i; + int rc = SQLITE_OK; + Vdbe *p = (Vdbe*)pStmt; +#ifndef SQLITE_MUTEX_NOOP + sqlite3_mutex *mutex = ((Vdbe*)pStmt)->db->mutex; +#endif + sqlite3_mutex_enter(mutex); + for(i=0; i<p->nVar; i++){ + sqlite3VdbeMemRelease(&p->aVar[i]); + p->aVar[i].flags = MEM_Null; + } + sqlite3_mutex_leave(mutex); + return rc; +} + + +/**************************** sqlite3_value_ ******************************* +** The following routines extract information from a Mem or sqlite3_value +** structure. +*/ +const void *sqlite3_value_blob(sqlite3_value *pVal){ + Mem *p = (Mem*)pVal; + if( p->flags & (MEM_Blob|MEM_Str) ){ + sqlite3VdbeMemExpandBlob(p); + p->flags &= ~MEM_Str; + p->flags |= MEM_Blob; + return p->z; + }else{ + return sqlite3_value_text(pVal); + } +} +int sqlite3_value_bytes(sqlite3_value *pVal){ + return sqlite3ValueBytes(pVal, SQLITE_UTF8); +} +int sqlite3_value_bytes16(sqlite3_value *pVal){ + return sqlite3ValueBytes(pVal, SQLITE_UTF16NATIVE); +} +double sqlite3_value_double(sqlite3_value *pVal){ + return sqlite3VdbeRealValue((Mem*)pVal); +} +int sqlite3_value_int(sqlite3_value *pVal){ + return sqlite3VdbeIntValue((Mem*)pVal); +} +sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){ + return sqlite3VdbeIntValue((Mem*)pVal); +} +const unsigned char *sqlite3_value_text(sqlite3_value *pVal){ + return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8); +} +#ifndef SQLITE_OMIT_UTF16 +const void *sqlite3_value_text16(sqlite3_value* pVal){ + return sqlite3ValueText(pVal, SQLITE_UTF16NATIVE); +} +const void *sqlite3_value_text16be(sqlite3_value *pVal){ + return sqlite3ValueText(pVal, SQLITE_UTF16BE); +} +const void *sqlite3_value_text16le(sqlite3_value *pVal){ + return sqlite3ValueText(pVal, SQLITE_UTF16LE); +} +#endif /* SQLITE_OMIT_UTF16 */ +int sqlite3_value_type(sqlite3_value* pVal){ + return pVal->type; +} + +/**************************** sqlite3_result_ ******************************* +** The following routines are used by user-defined functions to specify +** the function result. +*/ +void sqlite3_result_blob( + sqlite3_context *pCtx, + const void *z, + int n, + void (*xDel)(void *) +){ + assert( n>=0 ); + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); + sqlite3VdbeMemSetStr(&pCtx->s, z, n, 0, xDel); +} +void sqlite3_result_double(sqlite3_context *pCtx, double rVal){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); + sqlite3VdbeMemSetDouble(&pCtx->s, rVal); +} +void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); + pCtx->isError = SQLITE_ERROR; + sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, SQLITE_TRANSIENT); +} +#ifndef SQLITE_OMIT_UTF16 +void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); + pCtx->isError = SQLITE_ERROR; + sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT); +} +#endif +void sqlite3_result_int(sqlite3_context *pCtx, int iVal){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); + sqlite3VdbeMemSetInt64(&pCtx->s, (i64)iVal); +} +void sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); + sqlite3VdbeMemSetInt64(&pCtx->s, iVal); +} +void sqlite3_result_null(sqlite3_context *pCtx){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); + sqlite3VdbeMemSetNull(&pCtx->s); +} +void sqlite3_result_text( + sqlite3_context *pCtx, + const char *z, + int n, + void (*xDel)(void *) +){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); + sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, xDel); +} +#ifndef SQLITE_OMIT_UTF16 +void sqlite3_result_text16( + sqlite3_context *pCtx, + const void *z, + int n, + void (*xDel)(void *) +){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); + sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16NATIVE, xDel); +} +void sqlite3_result_text16be( + sqlite3_context *pCtx, + const void *z, + int n, + void (*xDel)(void *) +){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); + sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16BE, xDel); +} +void sqlite3_result_text16le( + sqlite3_context *pCtx, + const void *z, + int n, + void (*xDel)(void *) +){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); + sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16LE, xDel); +} +#endif /* SQLITE_OMIT_UTF16 */ +void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); + sqlite3VdbeMemCopy(&pCtx->s, pValue); +} +void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); + sqlite3VdbeMemSetZeroBlob(&pCtx->s, n); +} +void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ + pCtx->isError = errCode; +} + +/* Force an SQLITE_TOOBIG error. */ +void sqlite3_result_error_toobig(sqlite3_context *pCtx){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); + pCtx->isError = SQLITE_TOOBIG; + sqlite3VdbeMemSetStr(&pCtx->s, "string or blob too big", -1, + SQLITE_UTF8, SQLITE_STATIC); +} + +/* An SQLITE_NOMEM error. */ +void sqlite3_result_error_nomem(sqlite3_context *pCtx){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); + sqlite3VdbeMemSetNull(&pCtx->s); + pCtx->isError = SQLITE_NOMEM; + pCtx->s.db->mallocFailed = 1; +} + +/* +** Execute the statement pStmt, either until a row of data is ready, the +** statement is completely executed or an error occurs. +** +** This routine implements the bulk of the logic behind the sqlite_step() +** API. The only thing omitted is the automatic recompile if a +** schema change has occurred. That detail is handled by the +** outer sqlite3_step() wrapper procedure. +*/ +static int sqlite3Step(Vdbe *p){ + sqlite3 *db; + int rc; + + assert(p); + if( p->magic!=VDBE_MAGIC_RUN ){ + return SQLITE_MISUSE; + } + + /* Assert that malloc() has not failed */ + db = p->db; + assert( !db->mallocFailed ); + + if( p->pc<=0 && p->expired ){ + if( p->rc==SQLITE_OK ){ + p->rc = SQLITE_SCHEMA; + } + rc = SQLITE_ERROR; + goto end_of_step; + } + if( sqlite3SafetyOn(db) ){ + p->rc = SQLITE_MISUSE; + return SQLITE_MISUSE; + } + if( p->pc<0 ){ + /* If there are no other statements currently running, then + ** reset the interrupt flag. This prevents a call to sqlite3_interrupt + ** from interrupting a statement that has not yet started. + */ + if( db->activeVdbeCnt==0 ){ + db->u1.isInterrupted = 0; + } + +#ifndef SQLITE_OMIT_TRACE + if( db->xProfile && !db->init.busy ){ + double rNow; + sqlite3OsCurrentTime(db->pVfs, &rNow); + p->startTime = (rNow - (int)rNow)*3600.0*24.0*1000000000.0; + } +#endif + + db->activeVdbeCnt++; + p->pc = 0; + stmtLruRemove(p); + } +#ifndef SQLITE_OMIT_EXPLAIN + if( p->explain ){ + rc = sqlite3VdbeList(p); + }else +#endif /* SQLITE_OMIT_EXPLAIN */ + { + rc = sqlite3VdbeExec(p); + } + + if( sqlite3SafetyOff(db) ){ + rc = SQLITE_MISUSE; + } + +#ifndef SQLITE_OMIT_TRACE + /* Invoke the profile callback if there is one + */ + if( rc!=SQLITE_ROW && db->xProfile && !db->init.busy && p->nOp>0 + && p->aOp[0].opcode==OP_Trace && p->aOp[0].p4.z!=0 ){ + double rNow; + u64 elapseTime; + + sqlite3OsCurrentTime(db->pVfs, &rNow); + elapseTime = (rNow - (int)rNow)*3600.0*24.0*1000000000.0 - p->startTime; + db->xProfile(db->pProfileArg, p->aOp[0].p4.z, elapseTime); + } +#endif + + db->errCode = rc; + /*sqlite3Error(p->db, rc, 0);*/ + p->rc = sqlite3ApiExit(p->db, p->rc); +end_of_step: + assert( (rc&0xff)==rc ); + if( p->zSql && (rc&0xff)<SQLITE_ROW ){ + /* This behavior occurs if sqlite3_prepare_v2() was used to build + ** the prepared statement. Return error codes directly */ + p->db->errCode = p->rc; + /* sqlite3Error(p->db, p->rc, 0); */ + return p->rc; + }else{ + /* This is for legacy sqlite3_prepare() builds and when the code + ** is SQLITE_ROW or SQLITE_DONE */ + return rc; + } +} + +/* +** This is the top-level implementation of sqlite3_step(). Call +** sqlite3Step() to do most of the work. If a schema error occurs, +** call sqlite3Reprepare() and try again. +*/ +#ifdef SQLITE_OMIT_PARSER +int sqlite3_step(sqlite3_stmt *pStmt){ + int rc = SQLITE_MISUSE; + if( pStmt ){ + Vdbe *v; + v = (Vdbe*)pStmt; + sqlite3_mutex_enter(v->db->mutex); + rc = sqlite3Step(v); + sqlite3_mutex_leave(v->db->mutex); + } + return rc; +} +#else +int sqlite3_step(sqlite3_stmt *pStmt){ + int rc = SQLITE_MISUSE; + if( pStmt ){ + int cnt = 0; + Vdbe *v = (Vdbe*)pStmt; + sqlite3 *db = v->db; + sqlite3_mutex_enter(db->mutex); + while( (rc = sqlite3Step(v))==SQLITE_SCHEMA + && cnt++ < 5 + && vdbeReprepare(v) ){ + sqlite3_reset(pStmt); + v->expired = 0; + } + if( rc==SQLITE_SCHEMA && v->zSql && db->pErr ){ + /* This case occurs after failing to recompile an sql statement. + ** The error message from the SQL compiler has already been loaded + ** into the database handle. This block copies the error message + ** from the database handle into the statement and sets the statement + ** program counter to 0 to ensure that when the statement is + ** finalized or reset the parser error message is available via + ** sqlite3_errmsg() and sqlite3_errcode(). + */ + const char *zErr = (const char *)sqlite3_value_text(db->pErr); + sqlite3DbFree(db, v->zErrMsg); + if( !db->mallocFailed ){ + v->zErrMsg = sqlite3DbStrDup(db, zErr); + } else { + v->zErrMsg = 0; + v->rc = SQLITE_NOMEM; + } + } + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + } + return rc; +} +#endif + +/* +** Extract the user data from a sqlite3_context structure and return a +** pointer to it. +*/ +void *sqlite3_user_data(sqlite3_context *p){ + assert( p && p->pFunc ); + return p->pFunc->pUserData; +} + +/* +** Extract the user data from a sqlite3_context structure and return a +** pointer to it. +*/ +sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){ + assert( p && p->pFunc ); + return p->s.db; +} + +/* +** The following is the implementation of an SQL function that always +** fails with an error message stating that the function is used in the +** wrong context. The sqlite3_overload_function() API might construct +** SQL function that use this routine so that the functions will exist +** for name resolution but are actually overloaded by the xFindFunction +** method of virtual tables. +*/ +void sqlite3InvalidFunction( + sqlite3_context *context, /* The function calling context */ + int argc, /* Number of arguments to the function */ + sqlite3_value **argv /* Value of each argument */ +){ + const char *zName = context->pFunc->zName; + char *zErr; + zErr = sqlite3MPrintf(0, + "unable to use function %s in the requested context", zName); + sqlite3_result_error(context, zErr, -1); + sqlite3_free(zErr); +} + +/* +** Allocate or return the aggregate context for a user function. A new +** context is allocated on the first call. Subsequent calls return the +** same context that was returned on prior calls. +*/ +void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){ + Mem *pMem; + assert( p && p->pFunc && p->pFunc->xStep ); + assert( sqlite3_mutex_held(p->s.db->mutex) ); + pMem = p->pMem; + if( (pMem->flags & MEM_Agg)==0 ){ + if( nByte==0 ){ + sqlite3VdbeMemReleaseExternal(pMem); + pMem->flags = MEM_Null; + pMem->z = 0; + }else{ + sqlite3VdbeMemGrow(pMem, nByte, 0); + pMem->flags = MEM_Agg; + pMem->u.pDef = p->pFunc; + if( pMem->z ){ + memset(pMem->z, 0, nByte); + } + } + } + return (void*)pMem->z; +} + +/* +** Return the auxilary data pointer, if any, for the iArg'th argument to +** the user-function defined by pCtx. +*/ +void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){ + VdbeFunc *pVdbeFunc; + + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); + pVdbeFunc = pCtx->pVdbeFunc; + if( !pVdbeFunc || iArg>=pVdbeFunc->nAux || iArg<0 ){ + return 0; + } + return pVdbeFunc->apAux[iArg].pAux; +} + +/* +** Set the auxilary data pointer and delete function, for the iArg'th +** argument to the user-function defined by pCtx. Any previous value is +** deleted by calling the delete function specified when it was set. +*/ +void sqlite3_set_auxdata( + sqlite3_context *pCtx, + int iArg, + void *pAux, + void (*xDelete)(void*) +){ + struct AuxData *pAuxData; + VdbeFunc *pVdbeFunc; + if( iArg<0 ) goto failed; + + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); + pVdbeFunc = pCtx->pVdbeFunc; + if( !pVdbeFunc || pVdbeFunc->nAux<=iArg ){ + int nAux = (pVdbeFunc ? pVdbeFunc->nAux : 0); + int nMalloc = sizeof(VdbeFunc) + sizeof(struct AuxData)*iArg; + pVdbeFunc = sqlite3DbRealloc(pCtx->s.db, pVdbeFunc, nMalloc); + if( !pVdbeFunc ){ + goto failed; + } + pCtx->pVdbeFunc = pVdbeFunc; + memset(&pVdbeFunc->apAux[nAux], 0, sizeof(struct AuxData)*(iArg+1-nAux)); + pVdbeFunc->nAux = iArg+1; + pVdbeFunc->pFunc = pCtx->pFunc; + } + + pAuxData = &pVdbeFunc->apAux[iArg]; + if( pAuxData->pAux && pAuxData->xDelete ){ + pAuxData->xDelete(pAuxData->pAux); + } + pAuxData->pAux = pAux; + pAuxData->xDelete = xDelete; + return; + +failed: + if( xDelete ){ + xDelete(pAux); + } +} + +/* +** Return the number of times the Step function of a aggregate has been +** called. +** +** This function is deprecated. Do not use it for new code. It is +** provide only to avoid breaking legacy code. New aggregate function +** implementations should keep their own counts within their aggregate +** context. +*/ +int sqlite3_aggregate_count(sqlite3_context *p){ + assert( p && p->pFunc && p->pFunc->xStep ); + return p->pMem->n; +} + +/* +** Return the number of columns in the result set for the statement pStmt. +*/ +int sqlite3_column_count(sqlite3_stmt *pStmt){ + Vdbe *pVm = (Vdbe *)pStmt; + return pVm ? pVm->nResColumn : 0; +} + +/* +** Return the number of values available from the current row of the +** currently executing statement pStmt. +*/ +int sqlite3_data_count(sqlite3_stmt *pStmt){ + Vdbe *pVm = (Vdbe *)pStmt; + if( pVm==0 || pVm->pResultSet==0 ) return 0; + return pVm->nResColumn; +} + + +/* +** Check to see if column iCol of the given statement is valid. If +** it is, return a pointer to the Mem for the value of that column. +** If iCol is not valid, return a pointer to a Mem which has a value +** of NULL. +*/ +static Mem *columnMem(sqlite3_stmt *pStmt, int i){ + Vdbe *pVm; + int vals; + Mem *pOut; + + pVm = (Vdbe *)pStmt; + if( pVm && pVm->pResultSet!=0 && i<pVm->nResColumn && i>=0 ){ + sqlite3_mutex_enter(pVm->db->mutex); + vals = sqlite3_data_count(pStmt); + pOut = &pVm->pResultSet[i]; + }else{ + static const Mem nullMem = {{0}, 0.0, 0, "", 0, MEM_Null, SQLITE_NULL, 0, 0, 0 }; + if( pVm->db ){ + sqlite3_mutex_enter(pVm->db->mutex); + sqlite3Error(pVm->db, SQLITE_RANGE, 0); + } + pOut = (Mem*)&nullMem; + } + return pOut; +} + +/* +** This function is called after invoking an sqlite3_value_XXX function on a +** column value (i.e. a value returned by evaluating an SQL expression in the +** select list of a SELECT statement) that may cause a malloc() failure. If +** malloc() has failed, the threads mallocFailed flag is cleared and the result +** code of statement pStmt set to SQLITE_NOMEM. +** +** Specifically, this is called from within: +** +** sqlite3_column_int() +** sqlite3_column_int64() +** sqlite3_column_text() +** sqlite3_column_text16() +** sqlite3_column_real() +** sqlite3_column_bytes() +** sqlite3_column_bytes16() +** +** But not for sqlite3_column_blob(), which never calls malloc(). +*/ +static void columnMallocFailure(sqlite3_stmt *pStmt) +{ + /* If malloc() failed during an encoding conversion within an + ** sqlite3_column_XXX API, then set the return code of the statement to + ** SQLITE_NOMEM. The next call to _step() (if any) will return SQLITE_ERROR + ** and _finalize() will return NOMEM. + */ + Vdbe *p = (Vdbe *)pStmt; + if( p ){ + p->rc = sqlite3ApiExit(p->db, p->rc); + sqlite3_mutex_leave(p->db->mutex); + } +} + +/**************************** sqlite3_column_ ******************************* +** The following routines are used to access elements of the current row +** in the result set. +*/ +const void *sqlite3_column_blob(sqlite3_stmt *pStmt, int i){ + const void *val; + val = sqlite3_value_blob( columnMem(pStmt,i) ); + /* Even though there is no encoding conversion, value_blob() might + ** need to call malloc() to expand the result of a zeroblob() + ** expression. + */ + columnMallocFailure(pStmt); + return val; +} +int sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){ + int val = sqlite3_value_bytes( columnMem(pStmt,i) ); + columnMallocFailure(pStmt); + return val; +} +int sqlite3_column_bytes16(sqlite3_stmt *pStmt, int i){ + int val = sqlite3_value_bytes16( columnMem(pStmt,i) ); + columnMallocFailure(pStmt); + return val; +} +double sqlite3_column_double(sqlite3_stmt *pStmt, int i){ + double val = sqlite3_value_double( columnMem(pStmt,i) ); + columnMallocFailure(pStmt); + return val; +} +int sqlite3_column_int(sqlite3_stmt *pStmt, int i){ + int val = sqlite3_value_int( columnMem(pStmt,i) ); + columnMallocFailure(pStmt); + return val; +} +sqlite_int64 sqlite3_column_int64(sqlite3_stmt *pStmt, int i){ + sqlite_int64 val = sqlite3_value_int64( columnMem(pStmt,i) ); + columnMallocFailure(pStmt); + return val; +} +const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int i){ + const unsigned char *val = sqlite3_value_text( columnMem(pStmt,i) ); + columnMallocFailure(pStmt); + return val; +} +sqlite3_value *sqlite3_column_value(sqlite3_stmt *pStmt, int i){ + sqlite3_value *pOut = columnMem(pStmt, i); + columnMallocFailure(pStmt); + return pOut; +} +#ifndef SQLITE_OMIT_UTF16 +const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){ + const void *val = sqlite3_value_text16( columnMem(pStmt,i) ); + columnMallocFailure(pStmt); + return val; +} +#endif /* SQLITE_OMIT_UTF16 */ +int sqlite3_column_type(sqlite3_stmt *pStmt, int i){ + int iType = sqlite3_value_type( columnMem(pStmt,i) ); + columnMallocFailure(pStmt); + return iType; +} + +/* The following function is experimental and subject to change or +** removal */ +/*int sqlite3_column_numeric_type(sqlite3_stmt *pStmt, int i){ +** return sqlite3_value_numeric_type( columnMem(pStmt,i) ); +**} +*/ + +/* +** Convert the N-th element of pStmt->pColName[] into a string using +** xFunc() then return that string. If N is out of range, return 0. +** +** There are up to 5 names for each column. useType determines which +** name is returned. Here are the names: +** +** 0 The column name as it should be displayed for output +** 1 The datatype name for the column +** 2 The name of the database that the column derives from +** 3 The name of the table that the column derives from +** 4 The name of the table column that the result column derives from +** +** If the result is not a simple column reference (if it is an expression +** or a constant) then useTypes 2, 3, and 4 return NULL. +*/ +static const void *columnName( + sqlite3_stmt *pStmt, + int N, + const void *(*xFunc)(Mem*), + int useType +){ + const void *ret = 0; + Vdbe *p = (Vdbe *)pStmt; + int n; + + + if( p!=0 ){ + n = sqlite3_column_count(pStmt); + if( N<n && N>=0 ){ + N += useType*n; + sqlite3_mutex_enter(p->db->mutex); + ret = xFunc(&p->aColName[N]); + + /* A malloc may have failed inside of the xFunc() call. If this + ** is the case, clear the mallocFailed flag and return NULL. + */ + if( p->db && p->db->mallocFailed ){ + p->db->mallocFailed = 0; + ret = 0; + } + sqlite3_mutex_leave(p->db->mutex); + } + } + return ret; +} + +/* +** Return the name of the Nth column of the result set returned by SQL +** statement pStmt. +*/ +const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){ + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_NAME); +} +#ifndef SQLITE_OMIT_UTF16 +const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){ + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_NAME); +} +#endif + +/* +** Constraint: If you have ENABLE_COLUMN_METADATA then you must +** not define OMIT_DECLTYPE. +*/ +#if defined(SQLITE_OMIT_DECLTYPE) && defined(SQLITE_ENABLE_COLUMN_METADATA) +# error "Must not define both SQLITE_OMIT_DECLTYPE \ + and SQLITE_ENABLE_COLUMN_METADATA" +#endif + +#ifndef SQLITE_OMIT_DECLTYPE +/* +** Return the column declaration type (if applicable) of the 'i'th column +** of the result set of SQL statement pStmt. +*/ +const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){ + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DECLTYPE); +} +#ifndef SQLITE_OMIT_UTF16 +const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){ + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DECLTYPE); +} +#endif /* SQLITE_OMIT_UTF16 */ +#endif /* SQLITE_OMIT_DECLTYPE */ + +#ifdef SQLITE_ENABLE_COLUMN_METADATA +/* +** Return the name of the database from which a result column derives. +** NULL is returned if the result column is an expression or constant or +** anything else which is not an unabiguous reference to a database column. +*/ +const char *sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){ + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DATABASE); +} +#ifndef SQLITE_OMIT_UTF16 +const void *sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){ + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DATABASE); +} +#endif /* SQLITE_OMIT_UTF16 */ + +/* +** Return the name of the table from which a result column derives. +** NULL is returned if the result column is an expression or constant or +** anything else which is not an unabiguous reference to a database column. +*/ +const char *sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){ + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_TABLE); +} +#ifndef SQLITE_OMIT_UTF16 +const void *sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){ + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_TABLE); +} +#endif /* SQLITE_OMIT_UTF16 */ + +/* +** Return the name of the table column from which a result column derives. +** NULL is returned if the result column is an expression or constant or +** anything else which is not an unabiguous reference to a database column. +*/ +const char *sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){ + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_COLUMN); +} +#ifndef SQLITE_OMIT_UTF16 +const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){ + return columnName( + pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_COLUMN); +} +#endif /* SQLITE_OMIT_UTF16 */ +#endif /* SQLITE_ENABLE_COLUMN_METADATA */ + + +/******************************* sqlite3_bind_ *************************** +** +** Routines used to attach values to wildcards in a compiled SQL statement. +*/ +/* +** Unbind the value bound to variable i in virtual machine p. This is the +** the same as binding a NULL value to the column. If the "i" parameter is +** out of range, then SQLITE_RANGE is returned. Othewise SQLITE_OK. +** +** The error code stored in database p->db is overwritten with the return +** value in any case. +*/ +static int vdbeUnbind(Vdbe *p, int i){ + Mem *pVar; + if( p==0 || p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){ + if( p ) sqlite3Error(p->db, SQLITE_MISUSE, 0); + return SQLITE_MISUSE; + } + if( i<1 || i>p->nVar ){ + sqlite3Error(p->db, SQLITE_RANGE, 0); + return SQLITE_RANGE; + } + i--; + pVar = &p->aVar[i]; + sqlite3VdbeMemRelease(pVar); + pVar->flags = MEM_Null; + sqlite3Error(p->db, SQLITE_OK, 0); + return SQLITE_OK; +} + +/* +** Bind a text or BLOB value. +*/ +static int bindText( + sqlite3_stmt *pStmt, /* The statement to bind against */ + int i, /* Index of the parameter to bind */ + const void *zData, /* Pointer to the data to be bound */ + int nData, /* Number of bytes of data to be bound */ + void (*xDel)(void*), /* Destructor for the data */ + int encoding /* Encoding for the data */ +){ + Vdbe *p = (Vdbe *)pStmt; + Mem *pVar; + int rc; + + if( p==0 ){ + return SQLITE_MISUSE; + } + sqlite3_mutex_enter(p->db->mutex); + rc = vdbeUnbind(p, i); + if( rc==SQLITE_OK && zData!=0 ){ + pVar = &p->aVar[i-1]; + rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel); + if( rc==SQLITE_OK && encoding!=0 ){ + rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db)); + } + sqlite3Error(p->db, rc, 0); + rc = sqlite3ApiExit(p->db, rc); + } + sqlite3_mutex_leave(p->db->mutex); + return rc; +} + + +/* +** Bind a blob value to an SQL statement variable. +*/ +int sqlite3_bind_blob( + sqlite3_stmt *pStmt, + int i, + const void *zData, + int nData, + void (*xDel)(void*) +){ + return bindText(pStmt, i, zData, nData, xDel, 0); +} +int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){ + int rc; + Vdbe *p = (Vdbe *)pStmt; + sqlite3_mutex_enter(p->db->mutex); + rc = vdbeUnbind(p, i); + if( rc==SQLITE_OK ){ + sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue); + } + sqlite3_mutex_leave(p->db->mutex); + return rc; +} +int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){ + return sqlite3_bind_int64(p, i, (i64)iValue); +} +int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){ + int rc; + Vdbe *p = (Vdbe *)pStmt; + sqlite3_mutex_enter(p->db->mutex); + rc = vdbeUnbind(p, i); + if( rc==SQLITE_OK ){ + sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue); + } + sqlite3_mutex_leave(p->db->mutex); + return rc; +} +int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){ + int rc; + Vdbe *p = (Vdbe*)pStmt; + sqlite3_mutex_enter(p->db->mutex); + rc = vdbeUnbind(p, i); + sqlite3_mutex_leave(p->db->mutex); + return rc; +} +int sqlite3_bind_text( + sqlite3_stmt *pStmt, + int i, + const char *zData, + int nData, + void (*xDel)(void*) +){ + return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8); +} +#ifndef SQLITE_OMIT_UTF16 +int sqlite3_bind_text16( + sqlite3_stmt *pStmt, + int i, + const void *zData, + int nData, + void (*xDel)(void*) +){ + return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE); +} +#endif /* SQLITE_OMIT_UTF16 */ +int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){ + int rc; + Vdbe *p = (Vdbe *)pStmt; + sqlite3_mutex_enter(p->db->mutex); + rc = vdbeUnbind(p, i); + if( rc==SQLITE_OK ){ + rc = sqlite3VdbeMemCopy(&p->aVar[i-1], pValue); + if( rc==SQLITE_OK ){ + rc = sqlite3VdbeChangeEncoding(&p->aVar[i-1], ENC(p->db)); + } + } + rc = sqlite3ApiExit(p->db, rc); + sqlite3_mutex_leave(p->db->mutex); + return rc; +} +int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){ + int rc; + Vdbe *p = (Vdbe *)pStmt; + sqlite3_mutex_enter(p->db->mutex); + rc = vdbeUnbind(p, i); + if( rc==SQLITE_OK ){ + sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n); + } + sqlite3_mutex_leave(p->db->mutex); + return rc; +} + +/* +** Return the number of wildcards that can be potentially bound to. +** This routine is added to support DBD::SQLite. +*/ +int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){ + Vdbe *p = (Vdbe*)pStmt; + return p ? p->nVar : 0; +} + +/* +** Create a mapping from variable numbers to variable names +** in the Vdbe.azVar[] array, if such a mapping does not already +** exist. +*/ +static void createVarMap(Vdbe *p){ + if( !p->okVar ){ + sqlite3_mutex_enter(p->db->mutex); + if( !p->okVar ){ + int j; + Op *pOp; + for(j=0, pOp=p->aOp; j<p->nOp; j++, pOp++){ + if( pOp->opcode==OP_Variable ){ + assert( pOp->p1>0 && pOp->p1<=p->nVar ); + p->azVar[pOp->p1-1] = pOp->p4.z; + } + } + p->okVar = 1; + } + sqlite3_mutex_leave(p->db->mutex); + } +} + +/* +** Return the name of a wildcard parameter. Return NULL if the index +** is out of range or if the wildcard is unnamed. +** +** The result is always UTF-8. +*/ +const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){ + Vdbe *p = (Vdbe*)pStmt; + if( p==0 || i<1 || i>p->nVar ){ + return 0; + } + createVarMap(p); + return p->azVar[i-1]; +} + +/* +** Given a wildcard parameter name, return the index of the variable +** with that name. If there is no variable with the given name, +** return 0. +*/ +int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){ + Vdbe *p = (Vdbe*)pStmt; + int i; + if( p==0 ){ + return 0; + } + createVarMap(p); + if( zName ){ + for(i=0; i<p->nVar; i++){ + const char *z = p->azVar[i]; + if( z && strcmp(z,zName)==0 ){ + return i+1; + } + } + } + return 0; +} + +/* +** 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. +*/ +int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){ + Vdbe *pFrom = (Vdbe*)pFromStmt; + Vdbe *pTo = (Vdbe*)pToStmt; + int i, rc = SQLITE_OK; + if( (pFrom->magic!=VDBE_MAGIC_RUN && pFrom->magic!=VDBE_MAGIC_HALT) + || (pTo->magic!=VDBE_MAGIC_RUN && pTo->magic!=VDBE_MAGIC_HALT) + || pTo->db!=pFrom->db ){ + return SQLITE_MISUSE; + } + if( pFrom->nVar!=pTo->nVar ){ + return SQLITE_ERROR; + } + sqlite3_mutex_enter(pTo->db->mutex); + for(i=0; rc==SQLITE_OK && i<pFrom->nVar; i++){ + sqlite3VdbeMemMove(&pTo->aVar[i], &pFrom->aVar[i]); + } + sqlite3_mutex_leave(pTo->db->mutex); + assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); + return rc; +} + +/* +** Return the sqlite3* database handle to which the prepared statement given +** in the argument belongs. This is the same database handle that was +** the first argument to the sqlite3_prepare() that was used to create +** the statement in the first place. +*/ +sqlite3 *sqlite3_db_handle(sqlite3_stmt *pStmt){ + return pStmt ? ((Vdbe*)pStmt)->db : 0; +} + +/* +** Return a pointer to the next prepared statement after pStmt associated +** with database connection pDb. If pStmt is NULL, return the first +** prepared statement for the database connection. Return NULL if there +** are no more. +*/ +sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){ + sqlite3_stmt *pNext; + sqlite3_mutex_enter(pDb->mutex); + if( pStmt==0 ){ + pNext = (sqlite3_stmt*)pDb->pVdbe; + }else{ + pNext = (sqlite3_stmt*)((Vdbe*)pStmt)->pNext; + } + sqlite3_mutex_leave(pDb->mutex); + return pNext; +} diff --git a/third_party/sqlite/src/vdbeaux.c b/third_party/sqlite/src/vdbeaux.c new file mode 100755 index 0000000..cded81f --- /dev/null +++ b/third_party/sqlite/src/vdbeaux.c @@ -0,0 +1,2498 @@ +/* +** 2003 September 6 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains code used for creating, destroying, and populating +** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.) Prior +** to version 2.8.7, all this code was combined into the vdbe.c source file. +** But that file was getting too big so this subroutines were split out. +** +** $Id: vdbeaux.c,v 1.405 2008/08/02 03:50:39 drh Exp $ +*/ +#include "sqliteInt.h" +#include <ctype.h> +#include "vdbeInt.h" + + + +/* +** When debugging the code generator in a symbolic debugger, one can +** set the sqlite3VdbeAddopTrace to 1 and all opcodes will be printed +** as they are added to the instruction stream. +*/ +#ifdef SQLITE_DEBUG +int sqlite3VdbeAddopTrace = 0; +#endif + + +/* +** Create a new virtual database engine. +*/ +Vdbe *sqlite3VdbeCreate(sqlite3 *db){ + Vdbe *p; + p = sqlite3DbMallocZero(db, sizeof(Vdbe) ); + if( p==0 ) return 0; + p->db = db; + if( db->pVdbe ){ + db->pVdbe->pPrev = p; + } + p->pNext = db->pVdbe; + p->pPrev = 0; + db->pVdbe = p; + p->magic = VDBE_MAGIC_INIT; + return p; +} + +/* +** Remember the SQL string for a prepared statement. +*/ +void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n){ + if( p==0 ) return; + assert( p->zSql==0 ); + p->zSql = sqlite3DbStrNDup(p->db, z, n); +} + +/* +** Return the SQL associated with a prepared statement +*/ +const char *sqlite3_sql(sqlite3_stmt *pStmt){ + return ((Vdbe *)pStmt)->zSql; +} + +/* +** Swap all content between two VDBE structures. +*/ +void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){ + Vdbe tmp, *pTmp; + char *zTmp; + int nTmp; + tmp = *pA; + *pA = *pB; + *pB = tmp; + pTmp = pA->pNext; + pA->pNext = pB->pNext; + pB->pNext = pTmp; + pTmp = pA->pPrev; + pA->pPrev = pB->pPrev; + pB->pPrev = pTmp; + zTmp = pA->zSql; + pA->zSql = pB->zSql; + pB->zSql = zTmp; + nTmp = pA->nSql; + pA->nSql = pB->nSql; + pB->nSql = nTmp; +} + +#ifdef SQLITE_DEBUG +/* +** Turn tracing on or off +*/ +void sqlite3VdbeTrace(Vdbe *p, FILE *trace){ + p->trace = trace; +} +#endif + +/* +** Resize the Vdbe.aOp array so that it contains at least N +** elements. +** +** If an out-of-memory error occurs while resizing the array, +** Vdbe.aOp and Vdbe.nOpAlloc remain unchanged (this is so that +** any opcodes already allocated can be correctly deallocated +** along with the rest of the Vdbe). +*/ +static void resizeOpArray(Vdbe *p, int N){ + VdbeOp *pNew; + pNew = sqlite3DbRealloc(p->db, p->aOp, N*sizeof(Op)); + if( pNew ){ + p->nOpAlloc = N; + p->aOp = pNew; + } +} + +/* +** Add a new instruction to the list of instructions current in the +** VDBE. Return the address of the new instruction. +** +** Parameters: +** +** p Pointer to the VDBE +** +** op The opcode for this instruction +** +** p1, p2, p3 Operands +** +** Use the sqlite3VdbeResolveLabel() function to fix an address and +** the sqlite3VdbeChangeP4() function to change the value of the P4 +** operand. +*/ +int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ + int i; + VdbeOp *pOp; + + i = p->nOp; + assert( p->magic==VDBE_MAGIC_INIT ); + if( p->nOpAlloc<=i ){ + resizeOpArray(p, p->nOpAlloc ? p->nOpAlloc*2 : 1024/sizeof(Op)); + if( p->db->mallocFailed ){ + return 0; + } + } + p->nOp++; + pOp = &p->aOp[i]; + pOp->opcode = op; + pOp->p5 = 0; + pOp->p1 = p1; + pOp->p2 = p2; + pOp->p3 = p3; + pOp->p4.p = 0; + pOp->p4type = P4_NOTUSED; + p->expired = 0; +#ifdef SQLITE_DEBUG + pOp->zComment = 0; + if( sqlite3VdbeAddopTrace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]); +#endif +#ifdef VDBE_PROFILE + pOp->cycles = 0; + pOp->cnt = 0; +#endif + return i; +} +int sqlite3VdbeAddOp0(Vdbe *p, int op){ + return sqlite3VdbeAddOp3(p, op, 0, 0, 0); +} +int sqlite3VdbeAddOp1(Vdbe *p, int op, int p1){ + return sqlite3VdbeAddOp3(p, op, p1, 0, 0); +} +int sqlite3VdbeAddOp2(Vdbe *p, int op, int p1, int p2){ + return sqlite3VdbeAddOp3(p, op, p1, p2, 0); +} + + +/* +** Add an opcode that includes the p4 value as a pointer. +*/ +int sqlite3VdbeAddOp4( + Vdbe *p, /* Add the opcode to this VM */ + int op, /* The new opcode */ + int p1, /* The P1 operand */ + int p2, /* The P2 operand */ + int p3, /* The P3 operand */ + const char *zP4, /* The P4 operand */ + int p4type /* P4 operand type */ +){ + int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3); + sqlite3VdbeChangeP4(p, addr, zP4, p4type); + return addr; +} + +/* +** Create a new symbolic label for an instruction that has yet to be +** coded. The symbolic label is really just a negative number. The +** label can be used as the P2 value of an operation. Later, when +** the label is resolved to a specific address, the VDBE will scan +** through its operation list and change all values of P2 which match +** the label into the resolved address. +** +** The VDBE knows that a P2 value is a label because labels are +** always negative and P2 values are suppose to be non-negative. +** Hence, a negative P2 value is a label that has yet to be resolved. +** +** Zero is returned if a malloc() fails. +*/ +int sqlite3VdbeMakeLabel(Vdbe *p){ + int i; + i = p->nLabel++; + assert( p->magic==VDBE_MAGIC_INIT ); + if( i>=p->nLabelAlloc ){ + p->nLabelAlloc = p->nLabelAlloc*2 + 10; + p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel, + p->nLabelAlloc*sizeof(p->aLabel[0])); + } + if( p->aLabel ){ + p->aLabel[i] = -1; + } + return -1-i; +} + +/* +** Resolve label "x" to be the address of the next instruction to +** be inserted. The parameter "x" must have been obtained from +** a prior call to sqlite3VdbeMakeLabel(). +*/ +void sqlite3VdbeResolveLabel(Vdbe *p, int x){ + int j = -1-x; + assert( p->magic==VDBE_MAGIC_INIT ); + assert( j>=0 && j<p->nLabel ); + if( p->aLabel ){ + p->aLabel[j] = p->nOp; + } +} + +/* +** Loop through the program looking for P2 values that are negative +** on jump instructions. Each such value is a label. Resolve the +** label by setting the P2 value to its correct non-zero value. +** +** This routine is called once after all opcodes have been inserted. +** +** Variable *pMaxFuncArgs is set to the maximum value of any P2 argument +** to an OP_Function, OP_AggStep or OP_VFilter opcode. This is used by +** sqlite3VdbeMakeReady() to size the Vdbe.apArg[] array. +** +** This routine also does the following optimization: It scans for +** instructions that might cause a statement rollback. Such instructions +** are: +** +** * OP_Halt with P1=SQLITE_CONSTRAINT and P2=OE_Abort. +** * OP_Destroy +** * OP_VUpdate +** * OP_VRename +** +** If no such instruction is found, then every Statement instruction +** is changed to a Noop. In this way, we avoid creating the statement +** journal file unnecessarily. +*/ +static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ + int i; + int nMaxArgs = 0; + Op *pOp; + int *aLabel = p->aLabel; + int doesStatementRollback = 0; + int hasStatementBegin = 0; + for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ + u8 opcode = pOp->opcode; + + if( opcode==OP_Function || opcode==OP_AggStep ){ + if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5; +#ifndef SQLITE_OMIT_VIRTUALTABLE + }else if( opcode==OP_VUpdate ){ + if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2; +#endif + } + if( opcode==OP_Halt ){ + if( pOp->p1==SQLITE_CONSTRAINT && pOp->p2==OE_Abort ){ + doesStatementRollback = 1; + } + }else if( opcode==OP_Statement ){ + hasStatementBegin = 1; + }else if( opcode==OP_Destroy ){ + doesStatementRollback = 1; +#ifndef SQLITE_OMIT_VIRTUALTABLE + }else if( opcode==OP_VUpdate || opcode==OP_VRename ){ + doesStatementRollback = 1; + }else if( opcode==OP_VFilter ){ + int n; + assert( p->nOp - i >= 3 ); + assert( pOp[-1].opcode==OP_Integer ); + n = pOp[-1].p1; + if( n>nMaxArgs ) nMaxArgs = n; +#endif + } + + if( sqlite3VdbeOpcodeHasProperty(opcode, OPFLG_JUMP) && pOp->p2<0 ){ + assert( -1-pOp->p2<p->nLabel ); + pOp->p2 = aLabel[-1-pOp->p2]; + } + } + sqlite3DbFree(p->db, p->aLabel); + p->aLabel = 0; + + *pMaxFuncArgs = nMaxArgs; + + /* If we never rollback a statement transaction, then statement + ** transactions are not needed. So change every OP_Statement + ** opcode into an OP_Noop. This avoid a call to sqlite3OsOpenExclusive() + ** which can be expensive on some platforms. + */ + if( hasStatementBegin && !doesStatementRollback ){ + for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ + if( pOp->opcode==OP_Statement ){ + pOp->opcode = OP_Noop; + } + } + } +} + +/* +** Return the address of the next instruction to be inserted. +*/ +int sqlite3VdbeCurrentAddr(Vdbe *p){ + assert( p->magic==VDBE_MAGIC_INIT ); + return p->nOp; +} + +/* +** Add a whole list of operations to the operation stack. Return the +** address of the first operation added. +*/ +int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){ + int addr; + assert( p->magic==VDBE_MAGIC_INIT ); + if( p->nOp + nOp > p->nOpAlloc ){ + resizeOpArray(p, p->nOpAlloc ? p->nOpAlloc*2 : 1024/sizeof(Op)); + assert( p->nOp+nOp<=p->nOpAlloc || p->db->mallocFailed ); + } + if( p->db->mallocFailed ){ + return 0; + } + addr = p->nOp; + if( nOp>0 ){ + int i; + VdbeOpList const *pIn = aOp; + for(i=0; i<nOp; i++, pIn++){ + int p2 = pIn->p2; + VdbeOp *pOut = &p->aOp[i+addr]; + pOut->opcode = pIn->opcode; + pOut->p1 = pIn->p1; + if( p2<0 && sqlite3VdbeOpcodeHasProperty(pOut->opcode, OPFLG_JUMP) ){ + pOut->p2 = addr + ADDR(p2); + }else{ + pOut->p2 = p2; + } + pOut->p3 = pIn->p3; + pOut->p4type = P4_NOTUSED; + pOut->p4.p = 0; + pOut->p5 = 0; +#ifdef SQLITE_DEBUG + pOut->zComment = 0; + if( sqlite3VdbeAddopTrace ){ + sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]); + } +#endif + } + p->nOp += nOp; + } + return addr; +} + +/* +** Change the value of the P1 operand for a specific instruction. +** This routine is useful when a large program is loaded from a +** static array using sqlite3VdbeAddOpList but we want to make a +** few minor changes to the program. +*/ +void sqlite3VdbeChangeP1(Vdbe *p, int addr, int val){ + assert( p==0 || p->magic==VDBE_MAGIC_INIT ); + if( p && addr>=0 && p->nOp>addr && p->aOp ){ + p->aOp[addr].p1 = val; + } +} + +/* +** Change the value of the P2 operand for a specific instruction. +** This routine is useful for setting a jump destination. +*/ +void sqlite3VdbeChangeP2(Vdbe *p, int addr, int val){ + assert( p==0 || p->magic==VDBE_MAGIC_INIT ); + if( p && addr>=0 && p->nOp>addr && p->aOp ){ + p->aOp[addr].p2 = val; + } +} + +/* +** Change the value of the P3 operand for a specific instruction. +*/ +void sqlite3VdbeChangeP3(Vdbe *p, int addr, int val){ + assert( p==0 || p->magic==VDBE_MAGIC_INIT ); + if( p && addr>=0 && p->nOp>addr && p->aOp ){ + p->aOp[addr].p3 = val; + } +} + +/* +** Change the value of the P5 operand for the most recently +** added operation. +*/ +void sqlite3VdbeChangeP5(Vdbe *p, u8 val){ + assert( p==0 || p->magic==VDBE_MAGIC_INIT ); + if( p && p->aOp ){ + assert( p->nOp>0 ); + p->aOp[p->nOp-1].p5 = val; + } +} + +/* +** Change the P2 operand of instruction addr so that it points to +** the address of the next instruction to be coded. +*/ +void sqlite3VdbeJumpHere(Vdbe *p, int addr){ + sqlite3VdbeChangeP2(p, addr, p->nOp); +} + + +/* +** If the input FuncDef structure is ephemeral, then free it. If +** the FuncDef is not ephermal, then do nothing. +*/ +static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){ + if( pDef && (pDef->flags & SQLITE_FUNC_EPHEM)!=0 ){ + sqlite3DbFree(db, pDef); + } +} + +/* +** Delete a P4 value if necessary. +*/ +static void freeP4(sqlite3 *db, int p4type, void *p4){ + if( p4 ){ + switch( p4type ){ + case P4_REAL: + case P4_INT64: + case P4_MPRINTF: + case P4_DYNAMIC: + case P4_KEYINFO: + case P4_INTARRAY: + case P4_KEYINFO_HANDOFF: { + sqlite3DbFree(db, p4); + break; + } + case P4_VDBEFUNC: { + VdbeFunc *pVdbeFunc = (VdbeFunc *)p4; + freeEphemeralFunction(db, pVdbeFunc->pFunc); + sqlite3VdbeDeleteAuxData(pVdbeFunc, 0); + sqlite3DbFree(db, pVdbeFunc); + break; + } + case P4_FUNCDEF: { + freeEphemeralFunction(db, (FuncDef*)p4); + break; + } + case P4_MEM: { + sqlite3ValueFree((sqlite3_value*)p4); + break; + } + } + } +} + + +/* +** Change N opcodes starting at addr to No-ops. +*/ +void sqlite3VdbeChangeToNoop(Vdbe *p, int addr, int N){ + if( p && p->aOp ){ + VdbeOp *pOp = &p->aOp[addr]; + sqlite3 *db = p->db; + while( N-- ){ + freeP4(db, pOp->p4type, pOp->p4.p); + memset(pOp, 0, sizeof(pOp[0])); + pOp->opcode = OP_Noop; + pOp++; + } + } +} + +/* +** Change the value of the P4 operand for a specific instruction. +** This routine is useful when a large program is loaded from a +** static array using sqlite3VdbeAddOpList but we want to make a +** few minor changes to the program. +** +** If n>=0 then the P4 operand is dynamic, meaning that a copy of +** the string is made into memory obtained from sqlite3_malloc(). +** A value of n==0 means copy bytes of zP4 up to and including the +** first null byte. If n>0 then copy n+1 bytes of zP4. +** +** If n==P4_KEYINFO it means that zP4 is a pointer to a KeyInfo structure. +** A copy is made of the KeyInfo structure into memory obtained from +** sqlite3_malloc, to be freed when the Vdbe is finalized. +** n==P4_KEYINFO_HANDOFF indicates that zP4 points to a KeyInfo structure +** stored in memory that the caller has obtained from sqlite3_malloc. The +** caller should not free the allocation, it will be freed when the Vdbe is +** finalized. +** +** Other values of n (P4_STATIC, P4_COLLSEQ etc.) indicate that zP4 points +** to a string or structure that is guaranteed to exist for the lifetime of +** the Vdbe. In these cases we can just copy the pointer. +** +** If addr<0 then change P4 on the most recently inserted instruction. +*/ +void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){ + Op *pOp; + sqlite3 *db; + assert( p!=0 ); + db = p->db; + assert( p->magic==VDBE_MAGIC_INIT ); + if( p->aOp==0 || db->mallocFailed ){ + if (n != P4_KEYINFO) { + freeP4(db, n, (void*)*(char**)&zP4); + } + return; + } + assert( addr<p->nOp ); + if( addr<0 ){ + addr = p->nOp - 1; + if( addr<0 ) return; + } + pOp = &p->aOp[addr]; + freeP4(db, pOp->p4type, pOp->p4.p); + pOp->p4.p = 0; + if( n==P4_INT32 ){ + /* Note: this cast is safe, because the origin data point was an int + ** that was cast to a (const char *). */ + pOp->p4.i = SQLITE_PTR_TO_INT(zP4); + pOp->p4type = n; + }else if( zP4==0 ){ + pOp->p4.p = 0; + pOp->p4type = P4_NOTUSED; + }else if( n==P4_KEYINFO ){ + KeyInfo *pKeyInfo; + int nField, nByte; + + nField = ((KeyInfo*)zP4)->nField; + nByte = sizeof(*pKeyInfo) + (nField-1)*sizeof(pKeyInfo->aColl[0]) + nField; + pKeyInfo = sqlite3Malloc( nByte ); + pOp->p4.pKeyInfo = pKeyInfo; + if( pKeyInfo ){ + u8 *aSortOrder; + memcpy(pKeyInfo, zP4, nByte); + aSortOrder = pKeyInfo->aSortOrder; + if( aSortOrder ){ + pKeyInfo->aSortOrder = (unsigned char*)&pKeyInfo->aColl[nField]; + memcpy(pKeyInfo->aSortOrder, aSortOrder, nField); + } + pOp->p4type = P4_KEYINFO; + }else{ + p->db->mallocFailed = 1; + pOp->p4type = P4_NOTUSED; + } + }else if( n==P4_KEYINFO_HANDOFF ){ + pOp->p4.p = (void*)zP4; + pOp->p4type = P4_KEYINFO; + }else if( n<0 ){ + pOp->p4.p = (void*)zP4; + pOp->p4type = n; + }else{ + if( n==0 ) n = strlen(zP4); + pOp->p4.z = sqlite3DbStrNDup(p->db, zP4, n); + pOp->p4type = P4_DYNAMIC; + } +} + +#ifndef NDEBUG +/* +** Change the comment on the the most recently coded instruction. Or +** insert a No-op and add the comment to that new instruction. This +** makes the code easier to read during debugging. None of this happens +** in a production build. +*/ +void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){ + va_list ap; + assert( p->nOp>0 || p->aOp==0 ); + assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed ); + if( p->nOp ){ + char **pz = &p->aOp[p->nOp-1].zComment; + va_start(ap, zFormat); + sqlite3DbFree(p->db, *pz); + *pz = sqlite3VMPrintf(p->db, zFormat, ap); + va_end(ap); + } +} +void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){ + va_list ap; + sqlite3VdbeAddOp0(p, OP_Noop); + assert( p->nOp>0 || p->aOp==0 ); + assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed ); + if( p->nOp ){ + char **pz = &p->aOp[p->nOp-1].zComment; + va_start(ap, zFormat); + sqlite3DbFree(p->db, *pz); + *pz = sqlite3VMPrintf(p->db, zFormat, ap); + va_end(ap); + } +} +#endif /* NDEBUG */ + +/* +** Return the opcode for a given address. +*/ +VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){ + assert( p->magic==VDBE_MAGIC_INIT ); + assert( (addr>=0 && addr<p->nOp) || p->db->mallocFailed ); + return ((addr>=0 && addr<p->nOp)?(&p->aOp[addr]):0); +} + +#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \ + || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) +/* +** Compute a string that describes the P4 parameter for an opcode. +** Use zTemp for any required temporary buffer space. +*/ +static char *displayP4(Op *pOp, char *zTemp, int nTemp){ + char *zP4 = zTemp; + assert( nTemp>=20 ); + switch( pOp->p4type ){ + case P4_KEYINFO_STATIC: + case P4_KEYINFO: { + int i, j; + KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; + sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField); + i = strlen(zTemp); + for(j=0; j<pKeyInfo->nField; j++){ + CollSeq *pColl = pKeyInfo->aColl[j]; + if( pColl ){ + int n = strlen(pColl->zName); + if( i+n>nTemp-6 ){ + memcpy(&zTemp[i],",...",4); + break; + } + zTemp[i++] = ','; + if( pKeyInfo->aSortOrder && pKeyInfo->aSortOrder[j] ){ + zTemp[i++] = '-'; + } + memcpy(&zTemp[i], pColl->zName,n+1); + i += n; + }else if( i+4<nTemp-6 ){ + memcpy(&zTemp[i],",nil",4); + i += 4; + } + } + zTemp[i++] = ')'; + zTemp[i] = 0; + assert( i<nTemp ); + break; + } + case P4_COLLSEQ: { + CollSeq *pColl = pOp->p4.pColl; + sqlite3_snprintf(nTemp, zTemp, "collseq(%.20s)", pColl->zName); + break; + } + case P4_FUNCDEF: { + FuncDef *pDef = pOp->p4.pFunc; + sqlite3_snprintf(nTemp, zTemp, "%s(%d)", pDef->zName, pDef->nArg); + break; + } + case P4_INT64: { + sqlite3_snprintf(nTemp, zTemp, "%lld", *pOp->p4.pI64); + break; + } + case P4_INT32: { + sqlite3_snprintf(nTemp, zTemp, "%d", pOp->p4.i); + break; + } + case P4_REAL: { + sqlite3_snprintf(nTemp, zTemp, "%.16g", *pOp->p4.pReal); + break; + } + case P4_MEM: { + Mem *pMem = pOp->p4.pMem; + assert( (pMem->flags & MEM_Null)==0 ); + if( pMem->flags & MEM_Str ){ + zP4 = pMem->z; + }else if( pMem->flags & MEM_Int ){ + sqlite3_snprintf(nTemp, zTemp, "%lld", pMem->u.i); + }else if( pMem->flags & MEM_Real ){ + sqlite3_snprintf(nTemp, zTemp, "%.16g", pMem->r); + } + break; + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + case P4_VTAB: { + sqlite3_vtab *pVtab = pOp->p4.pVtab; + sqlite3_snprintf(nTemp, zTemp, "vtab:%p:%p", pVtab, pVtab->pModule); + break; + } +#endif + case P4_INTARRAY: { + sqlite3_snprintf(nTemp, zTemp, "intarray"); + break; + } + default: { + zP4 = pOp->p4.z; + if( zP4==0 ){ + zP4 = zTemp; + zTemp[0] = 0; + } + } + } + assert( zP4!=0 ); + return zP4; +} +#endif + +/* +** Declare to the Vdbe that the BTree object at db->aDb[i] is used. +** +*/ +void sqlite3VdbeUsesBtree(Vdbe *p, int i){ + int mask; + assert( i>=0 && i<p->db->nDb ); + assert( i<sizeof(p->btreeMask)*8 ); + mask = 1<<i; + if( (p->btreeMask & mask)==0 ){ + p->btreeMask |= mask; + sqlite3BtreeMutexArrayInsert(&p->aMutex, p->db->aDb[i].pBt); + } +} + + +#if defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) +/* +** Print a single opcode. This routine is used for debugging only. +*/ +void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){ + char *zP4; + char zPtr[50]; + static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-4s %.2X %s\n"; + if( pOut==0 ) pOut = stdout; + zP4 = displayP4(pOp, zPtr, sizeof(zPtr)); + fprintf(pOut, zFormat1, pc, + sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5, +#ifdef SQLITE_DEBUG + pOp->zComment ? pOp->zComment : "" +#else + "" +#endif + ); + fflush(pOut); +} +#endif + +/* +** Release an array of N Mem elements +*/ +static void releaseMemArray(Mem *p, int N){ + if( p && N ){ + sqlite3 *db = p->db; + int malloc_failed = db->mallocFailed; + while( N-->0 ){ + assert( N<2 || p[0].db==p[1].db ); + sqlite3VdbeMemRelease(p); + p->flags = MEM_Null; + p++; + } + db->mallocFailed = malloc_failed; + } +} + +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +int sqlite3VdbeReleaseBuffers(Vdbe *p){ + int ii; + int nFree = 0; + assert( sqlite3_mutex_held(p->db->mutex) ); + for(ii=1; ii<=p->nMem; ii++){ + Mem *pMem = &p->aMem[ii]; + if( pMem->z && pMem->flags&MEM_Dyn ){ + assert( !pMem->xDel ); + nFree += sqlite3DbMallocSize(pMem->db, pMem->z); + sqlite3VdbeMemRelease(pMem); + } + } + return nFree; +} +#endif + +#ifndef SQLITE_OMIT_EXPLAIN +/* +** Give a listing of the program in the virtual machine. +** +** The interface is the same as sqlite3VdbeExec(). But instead of +** running the code, it invokes the callback once for each instruction. +** This feature is used to implement "EXPLAIN". +** +** When p->explain==1, each instruction is listed. When +** p->explain==2, only OP_Explain instructions are listed and these +** are shown in a different format. p->explain==2 is used to implement +** EXPLAIN QUERY PLAN. +*/ +int sqlite3VdbeList( + Vdbe *p /* The VDBE */ +){ + sqlite3 *db = p->db; + int i; + int rc = SQLITE_OK; + Mem *pMem = p->pResultSet = &p->aMem[1]; + + assert( p->explain ); + if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE; + assert( db->magic==SQLITE_MAGIC_BUSY ); + assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY ); + + /* Even though this opcode does not use dynamic strings for + ** the result, result columns may become dynamic if the user calls + ** sqlite3_column_text16(), causing a translation to UTF-16 encoding. + */ + releaseMemArray(pMem, p->nMem); + + do{ + i = p->pc++; + }while( i<p->nOp && p->explain==2 && p->aOp[i].opcode!=OP_Explain ); + if( i>=p->nOp ){ + p->rc = SQLITE_OK; + rc = SQLITE_DONE; + }else if( db->u1.isInterrupted ){ + p->rc = SQLITE_INTERRUPT; + rc = SQLITE_ERROR; + sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3ErrStr(p->rc)); + }else{ + char *z; + Op *pOp = &p->aOp[i]; + if( p->explain==1 ){ + pMem->flags = MEM_Int; + pMem->type = SQLITE_INTEGER; + pMem->u.i = i; /* Program counter */ + pMem++; + + pMem->flags = MEM_Static|MEM_Str|MEM_Term; + pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */ + assert( pMem->z!=0 ); + pMem->n = strlen(pMem->z); + pMem->type = SQLITE_TEXT; + pMem->enc = SQLITE_UTF8; + pMem++; + } + + pMem->flags = MEM_Int; + pMem->u.i = pOp->p1; /* P1 */ + pMem->type = SQLITE_INTEGER; + pMem++; + + pMem->flags = MEM_Int; + pMem->u.i = pOp->p2; /* P2 */ + pMem->type = SQLITE_INTEGER; + pMem++; + + if( p->explain==1 ){ + pMem->flags = MEM_Int; + pMem->u.i = pOp->p3; /* P3 */ + pMem->type = SQLITE_INTEGER; + pMem++; + } + + if( sqlite3VdbeMemGrow(pMem, 32, 0) ){ /* P4 */ + p->db->mallocFailed = 1; + return SQLITE_NOMEM; + } + pMem->flags = MEM_Dyn|MEM_Str|MEM_Term; + z = displayP4(pOp, pMem->z, 32); + if( z!=pMem->z ){ + sqlite3VdbeMemSetStr(pMem, z, -1, SQLITE_UTF8, 0); + }else{ + assert( pMem->z!=0 ); + pMem->n = strlen(pMem->z); + pMem->enc = SQLITE_UTF8; + } + pMem->type = SQLITE_TEXT; + pMem++; + + if( p->explain==1 ){ + if( sqlite3VdbeMemGrow(pMem, 4, 0) ){ + p->db->mallocFailed = 1; + return SQLITE_NOMEM; + } + pMem->flags = MEM_Dyn|MEM_Str|MEM_Term; + pMem->n = 2; + sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */ + pMem->type = SQLITE_TEXT; + pMem->enc = SQLITE_UTF8; + pMem++; + +#ifdef SQLITE_DEBUG + if( pOp->zComment ){ + pMem->flags = MEM_Str|MEM_Term; + pMem->z = pOp->zComment; + pMem->n = strlen(pMem->z); + pMem->enc = SQLITE_UTF8; + }else +#endif + { + pMem->flags = MEM_Null; /* Comment */ + pMem->type = SQLITE_NULL; + } + } + + p->nResColumn = 8 - 5*(p->explain-1); + p->rc = SQLITE_OK; + rc = SQLITE_ROW; + } + return rc; +} +#endif /* SQLITE_OMIT_EXPLAIN */ + +#ifdef SQLITE_DEBUG +/* +** Print the SQL that was used to generate a VDBE program. +*/ +void sqlite3VdbePrintSql(Vdbe *p){ + int nOp = p->nOp; + VdbeOp *pOp; + if( nOp<1 ) return; + pOp = &p->aOp[0]; + if( pOp->opcode==OP_Trace && pOp->p4.z!=0 ){ + const char *z = pOp->p4.z; + while( isspace(*(u8*)z) ) z++; + printf("SQL: [%s]\n", z); + } +} +#endif + +#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE) +/* +** Print an IOTRACE message showing SQL content. +*/ +void sqlite3VdbeIOTraceSql(Vdbe *p){ + int nOp = p->nOp; + VdbeOp *pOp; + if( sqlite3IoTrace==0 ) return; + if( nOp<1 ) return; + pOp = &p->aOp[0]; + if( pOp->opcode==OP_Trace && pOp->p4.z!=0 ){ + int i, j; + char z[1000]; + sqlite3_snprintf(sizeof(z), z, "%s", pOp->p4.z); + for(i=0; isspace((unsigned char)z[i]); i++){} + for(j=0; z[i]; i++){ + if( isspace((unsigned char)z[i]) ){ + if( z[i-1]!=' ' ){ + z[j++] = ' '; + } + }else{ + z[j++] = z[i]; + } + } + z[j] = 0; + sqlite3IoTrace("SQL %s\n", z); + } +} +#endif /* !SQLITE_OMIT_TRACE && SQLITE_ENABLE_IOTRACE */ + + +/* +** Prepare a virtual machine for execution. This involves things such +** as allocating stack space and initializing the program counter. +** After the VDBE has be prepped, it can be executed by one or more +** calls to sqlite3VdbeExec(). +** +** This is the only way to move a VDBE from VDBE_MAGIC_INIT to +** VDBE_MAGIC_RUN. +*/ +void sqlite3VdbeMakeReady( + Vdbe *p, /* The VDBE */ + int nVar, /* Number of '?' see in the SQL statement */ + int nMem, /* Number of memory cells to allocate */ + int nCursor, /* Number of cursors to allocate */ + int isExplain /* True if the EXPLAIN keywords is present */ +){ + int n; + sqlite3 *db = p->db; + + assert( p!=0 ); + assert( p->magic==VDBE_MAGIC_INIT ); + + /* There should be at least one opcode. + */ + assert( p->nOp>0 ); + + /* Set the magic to VDBE_MAGIC_RUN sooner rather than later. This + * is because the call to resizeOpArray() below may shrink the + * p->aOp[] array to save memory if called when in VDBE_MAGIC_RUN + * state. + */ + p->magic = VDBE_MAGIC_RUN; + + /* For each cursor required, also allocate a memory cell. Memory + ** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by + ** the vdbe program. Instead they are used to allocate space for + ** Cursor/BtCursor structures. The blob of memory associated with + ** cursor 0 is stored in memory cell nMem. Memory cell (nMem-1) + ** stores the blob of memory associated with cursor 1, etc. + ** + ** See also: allocateCursor(). + */ + nMem += nCursor; + + /* + ** Allocation space for registers. + */ + if( p->aMem==0 ){ + int nArg; /* Maximum number of args passed to a user function. */ + resolveP2Values(p, &nArg); + /*resizeOpArray(p, p->nOp);*/ + assert( nVar>=0 ); + if( isExplain && nMem<10 ){ + p->nMem = nMem = 10; + } + p->aMem = sqlite3DbMallocZero(db, + nMem*sizeof(Mem) /* aMem */ + + nVar*sizeof(Mem) /* aVar */ + + nArg*sizeof(Mem*) /* apArg */ + + nVar*sizeof(char*) /* azVar */ + + nCursor*sizeof(Cursor*) + 1 /* apCsr */ + ); + if( !db->mallocFailed ){ + p->aMem--; /* aMem[] goes from 1..nMem */ + p->nMem = nMem; /* not from 0..nMem-1 */ + p->aVar = &p->aMem[nMem+1]; + p->nVar = nVar; + p->okVar = 0; + p->apArg = (Mem**)&p->aVar[nVar]; + p->azVar = (char**)&p->apArg[nArg]; + p->apCsr = (Cursor**)&p->azVar[nVar]; + p->nCursor = nCursor; + for(n=0; n<nVar; n++){ + p->aVar[n].flags = MEM_Null; + p->aVar[n].db = db; + } + for(n=1; n<=nMem; n++){ + p->aMem[n].flags = MEM_Null; + p->aMem[n].db = db; + } + } + } +#ifdef SQLITE_DEBUG + for(n=1; n<p->nMem; n++){ + assert( p->aMem[n].db==db ); + } +#endif + + p->pc = -1; + p->rc = SQLITE_OK; + p->uniqueCnt = 0; + p->errorAction = OE_Abort; + p->explain |= isExplain; + p->magic = VDBE_MAGIC_RUN; + p->nChange = 0; + p->cacheCtr = 1; + p->minWriteFileFormat = 255; + p->openedStatement = 0; +#ifdef VDBE_PROFILE + { + int i; + for(i=0; i<p->nOp; i++){ + p->aOp[i].cnt = 0; + p->aOp[i].cycles = 0; + } + } +#endif +} + +/* +** Close a VDBE cursor and release all the resources that cursor +** happens to hold. +*/ +void sqlite3VdbeFreeCursor(Vdbe *p, Cursor *pCx){ + if( pCx==0 ){ + return; + } + if( pCx->pBt ){ + sqlite3BtreeClose(pCx->pBt); + /* The pCx->pCursor will be close automatically, if it exists, by + ** the call above. */ + }else if( pCx->pCursor ){ + sqlite3BtreeCloseCursor(pCx->pCursor); + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( pCx->pVtabCursor ){ + sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor; + const sqlite3_module *pModule = pCx->pModule; + p->inVtabMethod = 1; + (void)sqlite3SafetyOff(p->db); + pModule->xClose(pVtabCursor); + (void)sqlite3SafetyOn(p->db); + p->inVtabMethod = 0; + } +#endif + if( !pCx->ephemPseudoTable ){ + sqlite3DbFree(p->db, pCx->pData); + } +} + +/* +** Close all cursors except for VTab cursors that are currently +** in use. +*/ +static void closeAllCursorsExceptActiveVtabs(Vdbe *p){ + int i; + if( p->apCsr==0 ) return; + for(i=0; i<p->nCursor; i++){ + Cursor *pC = p->apCsr[i]; + if( pC && (!p->inVtabMethod || !pC->pVtabCursor) ){ + sqlite3VdbeFreeCursor(p, pC); + p->apCsr[i] = 0; + } + } +} + +/* +** Clean up the VM after execution. +** +** This routine will automatically close any cursors, lists, and/or +** sorters that were left open. It also deletes the values of +** variables in the aVar[] array. +*/ +static void Cleanup(Vdbe *p){ + int i; + sqlite3 *db = p->db; + closeAllCursorsExceptActiveVtabs(p); + for(i=1; i<=p->nMem; i++){ + MemSetTypeFlag(&p->aMem[i], MEM_Null); + } + releaseMemArray(&p->aMem[1], p->nMem); + sqlite3VdbeFifoClear(&p->sFifo); + if( p->contextStack ){ + for(i=0; i<p->contextStackTop; i++){ + sqlite3VdbeFifoClear(&p->contextStack[i].sFifo); + } + sqlite3DbFree(db, p->contextStack); + } + p->contextStack = 0; + p->contextStackDepth = 0; + p->contextStackTop = 0; + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = 0; + p->pResultSet = 0; +} + +/* +** Set the number of result columns that will be returned by this SQL +** statement. This is now set at compile time, rather than during +** execution of the vdbe program so that sqlite3_column_count() can +** be called on an SQL statement before sqlite3_step(). +*/ +void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){ + Mem *pColName; + int n; + sqlite3 *db = p->db; + + releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); + sqlite3DbFree(db, p->aColName); + n = nResColumn*COLNAME_N; + p->nResColumn = nResColumn; + p->aColName = pColName = (Mem*)sqlite3DbMallocZero(db, sizeof(Mem)*n ); + if( p->aColName==0 ) return; + while( n-- > 0 ){ + pColName->flags = MEM_Null; + pColName->db = p->db; + pColName++; + } +} + +/* +** Set the name of the idx'th column to be returned by the SQL statement. +** zName must be a pointer to a nul terminated string. +** +** This call must be made after a call to sqlite3VdbeSetNumCols(). +** +** If N==P4_STATIC it means that zName is a pointer to a constant static +** string and we can just copy the pointer. If it is P4_DYNAMIC, then +** the string is freed using sqlite3DbFree(db, ) when the vdbe is finished with +** it. Otherwise, N bytes of zName are copied. +*/ +int sqlite3VdbeSetColName(Vdbe *p, int idx, int var, const char *zName, int N){ + int rc; + Mem *pColName; + assert( idx<p->nResColumn ); + assert( var<COLNAME_N ); + if( p->db->mallocFailed ) return SQLITE_NOMEM; + assert( p->aColName!=0 ); + pColName = &(p->aColName[idx+var*p->nResColumn]); + if( N==P4_DYNAMIC || N==P4_STATIC ){ + rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, SQLITE_STATIC); + }else{ + rc = sqlite3VdbeMemSetStr(pColName, zName, N, SQLITE_UTF8,SQLITE_TRANSIENT); + } + if( rc==SQLITE_OK && N==P4_DYNAMIC ){ + pColName->flags &= (~MEM_Static); + pColName->zMalloc = pColName->z; + } + return rc; +} + +/* +** A read or write transaction may or may not be active on database handle +** db. If a transaction is active, commit it. If there is a +** write-transaction spanning more than one database file, this routine +** takes care of the master journal trickery. +*/ +static int vdbeCommit(sqlite3 *db, Vdbe *p){ + int i; + int nTrans = 0; /* Number of databases with an active write-transaction */ + int rc = SQLITE_OK; + int needXcommit = 0; + + /* Before doing anything else, call the xSync() callback for any + ** virtual module tables written in this transaction. This has to + ** be done before determining whether a master journal file is + ** required, as an xSync() callback may add an attached database + ** to the transaction. + */ + rc = sqlite3VtabSync(db, &p->zErrMsg); + if( rc!=SQLITE_OK ){ + return rc; + } + + /* This loop determines (a) if the commit hook should be invoked and + ** (b) how many database files have open write transactions, not + ** including the temp database. (b) is important because if more than + ** one database file has an open write transaction, a master journal + ** file is required for an atomic commit. + */ + for(i=0; i<db->nDb; i++){ + Btree *pBt = db->aDb[i].pBt; + if( sqlite3BtreeIsInTrans(pBt) ){ + needXcommit = 1; + if( i!=1 ) nTrans++; + } + } + + /* If there are any write-transactions at all, invoke the commit hook */ + if( needXcommit && db->xCommitCallback ){ + (void)sqlite3SafetyOff(db); + rc = db->xCommitCallback(db->pCommitArg); + (void)sqlite3SafetyOn(db); + if( rc ){ + return SQLITE_CONSTRAINT; + } + } + + /* The simple case - no more than one database file (not counting the + ** TEMP database) has a transaction active. There is no need for the + ** master-journal. + ** + ** If the return value of sqlite3BtreeGetFilename() is a zero length + ** string, it means the main database is :memory: or a temp file. In + ** that case we do not support atomic multi-file commits, so use the + ** simple case then too. + */ + if( 0==strlen(sqlite3BtreeGetFilename(db->aDb[0].pBt)) || nTrans<=1 ){ + for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ + Btree *pBt = db->aDb[i].pBt; + if( pBt ){ + rc = sqlite3BtreeCommitPhaseOne(pBt, 0); + } + } + + /* Do the commit only if all databases successfully complete phase 1. + ** If one of the BtreeCommitPhaseOne() calls fails, this indicates an + ** IO error while deleting or truncating a journal file. It is unlikely, + ** but could happen. In this case abandon processing and return the error. + */ + for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ + Btree *pBt = db->aDb[i].pBt; + if( pBt ){ + rc = sqlite3BtreeCommitPhaseTwo(pBt); + } + } + if( rc==SQLITE_OK ){ + sqlite3VtabCommit(db); + } + } + + /* The complex case - There is a multi-file write-transaction active. + ** This requires a master journal file to ensure the transaction is + ** committed atomicly. + */ +#ifndef SQLITE_OMIT_DISKIO + else{ + sqlite3_vfs *pVfs = db->pVfs; + int needSync = 0; + char *zMaster = 0; /* File-name for the master journal */ + char const *zMainFile = sqlite3BtreeGetFilename(db->aDb[0].pBt); + sqlite3_file *pMaster = 0; + i64 offset = 0; + int res; + + /* Select a master journal file name */ + do { + u32 random; + sqlite3DbFree(db, zMaster); + sqlite3_randomness(sizeof(random), &random); + zMaster = sqlite3MPrintf(db, "%s-mj%08X", zMainFile, random&0x7fffffff); + if( !zMaster ){ + return SQLITE_NOMEM; + } + rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res); + }while( rc==SQLITE_OK && res ); + if( rc==SQLITE_OK ){ + /* Open the master journal. */ + rc = sqlite3OsOpenMalloc(pVfs, zMaster, &pMaster, + SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE| + SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_MASTER_JOURNAL, 0 + ); + } + if( rc!=SQLITE_OK ){ + sqlite3DbFree(db, zMaster); + return rc; + } + + /* Write the name of each database file in the transaction into the new + ** master journal file. If an error occurs at this point close + ** and delete the master journal file. All the individual journal files + ** still have 'null' as the master journal pointer, so they will roll + ** back independently if a failure occurs. + */ + for(i=0; i<db->nDb; i++){ + Btree *pBt = db->aDb[i].pBt; + if( i==1 ) continue; /* Ignore the TEMP database */ + if( sqlite3BtreeIsInTrans(pBt) ){ + char const *zFile = sqlite3BtreeGetJournalname(pBt); + if( zFile[0]==0 ) continue; /* Ignore :memory: databases */ + if( !needSync && !sqlite3BtreeSyncDisabled(pBt) ){ + needSync = 1; + } + rc = sqlite3OsWrite(pMaster, zFile, strlen(zFile)+1, offset); + offset += strlen(zFile)+1; + if( rc!=SQLITE_OK ){ + sqlite3OsCloseFree(pMaster); + sqlite3OsDelete(pVfs, zMaster, 0); + sqlite3DbFree(db, zMaster); + return rc; + } + } + } + + /* Sync the master journal file. If the IOCAP_SEQUENTIAL device + ** flag is set this is not required. + */ + zMainFile = sqlite3BtreeGetDirname(db->aDb[0].pBt); + if( (needSync + && (0==(sqlite3OsDeviceCharacteristics(pMaster)&SQLITE_IOCAP_SEQUENTIAL)) + && (rc=sqlite3OsSync(pMaster, SQLITE_SYNC_NORMAL))!=SQLITE_OK) ){ + sqlite3OsCloseFree(pMaster); + sqlite3OsDelete(pVfs, zMaster, 0); + sqlite3DbFree(db, zMaster); + return rc; + } + + /* Sync all the db files involved in the transaction. The same call + ** sets the master journal pointer in each individual journal. If + ** an error occurs here, do not delete the master journal file. + ** + ** If the error occurs during the first call to + ** sqlite3BtreeCommitPhaseOne(), then there is a chance that the + ** master journal file will be orphaned. But we cannot delete it, + ** in case the master journal file name was written into the journal + ** file before the failure occured. + */ + for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ + Btree *pBt = db->aDb[i].pBt; + if( pBt ){ + rc = sqlite3BtreeCommitPhaseOne(pBt, zMaster); + } + } + sqlite3OsCloseFree(pMaster); + if( rc!=SQLITE_OK ){ + sqlite3DbFree(db, zMaster); + return rc; + } + + /* Delete the master journal file. This commits the transaction. After + ** doing this the directory is synced again before any individual + ** transaction files are deleted. + */ + rc = sqlite3OsDelete(pVfs, zMaster, 1); + sqlite3DbFree(db, zMaster); + zMaster = 0; + if( rc ){ + return rc; + } + + /* All files and directories have already been synced, so the following + ** calls to sqlite3BtreeCommitPhaseTwo() are only closing files and + ** deleting or truncating journals. If something goes wrong while + ** this is happening we don't really care. The integrity of the + ** transaction is already guaranteed, but some stray 'cold' journals + ** may be lying around. Returning an error code won't help matters. + */ + disable_simulated_io_errors(); + sqlite3BeginBenignMalloc(); + for(i=0; i<db->nDb; i++){ + Btree *pBt = db->aDb[i].pBt; + if( pBt ){ + sqlite3BtreeCommitPhaseTwo(pBt); + } + } + sqlite3EndBenignMalloc(); + enable_simulated_io_errors(); + + sqlite3VtabCommit(db); + } +#endif + + return rc; +} + +/* +** This routine checks that the sqlite3.activeVdbeCnt count variable +** matches the number of vdbe's in the list sqlite3.pVdbe that are +** currently active. An assertion fails if the two counts do not match. +** This is an internal self-check only - it is not an essential processing +** step. +** +** This is a no-op if NDEBUG is defined. +*/ +#ifndef NDEBUG +static void checkActiveVdbeCnt(sqlite3 *db){ + Vdbe *p; + int cnt = 0; + p = db->pVdbe; + while( p ){ + if( p->magic==VDBE_MAGIC_RUN && p->pc>=0 ){ + cnt++; + } + p = p->pNext; + } + assert( cnt==db->activeVdbeCnt ); +} +#else +#define checkActiveVdbeCnt(x) +#endif + +/* +** For every Btree that in database connection db which +** has been modified, "trip" or invalidate each cursor in +** that Btree might have been modified so that the cursor +** can never be used again. This happens when a rollback +*** occurs. We have to trip all the other cursors, even +** cursor from other VMs in different database connections, +** so that none of them try to use the data at which they +** were pointing and which now may have been changed due +** to the rollback. +** +** Remember that a rollback can delete tables complete and +** reorder rootpages. So it is not sufficient just to save +** the state of the cursor. We have to invalidate the cursor +** so that it is never used again. +*/ +static void invalidateCursorsOnModifiedBtrees(sqlite3 *db){ + int i; + for(i=0; i<db->nDb; i++){ + Btree *p = db->aDb[i].pBt; + if( p && sqlite3BtreeIsInTrans(p) ){ + sqlite3BtreeTripAllCursors(p, SQLITE_ABORT); + } + } +} + +/* +** This routine is called the when a VDBE tries to halt. If the VDBE +** has made changes and is in autocommit mode, then commit those +** changes. If a rollback is needed, then do the rollback. +** +** This routine is the only way to move the state of a VM from +** SQLITE_MAGIC_RUN to SQLITE_MAGIC_HALT. It is harmless to +** call this on a VM that is in the SQLITE_MAGIC_HALT state. +** +** Return an error code. If the commit could not complete because of +** lock contention, return SQLITE_BUSY. If SQLITE_BUSY is returned, it +** means the close did not happen and needs to be repeated. +*/ +int sqlite3VdbeHalt(Vdbe *p){ + sqlite3 *db = p->db; + int i; + int (*xFunc)(Btree *pBt) = 0; /* Function to call on each btree backend */ + int isSpecialError; /* Set to true if SQLITE_NOMEM or IOERR */ + + /* This function contains the logic that determines if a statement or + ** transaction will be committed or rolled back as a result of the + ** execution of this virtual machine. + ** + ** If any of the following errors occur: + ** + ** SQLITE_NOMEM + ** SQLITE_IOERR + ** SQLITE_FULL + ** SQLITE_INTERRUPT + ** + ** Then the internal cache might have been left in an inconsistent + ** state. We need to rollback the statement transaction, if there is + ** one, or the complete transaction if there is no statement transaction. + */ + + if( p->db->mallocFailed ){ + p->rc = SQLITE_NOMEM; + } + closeAllCursorsExceptActiveVtabs(p); + if( p->magic!=VDBE_MAGIC_RUN ){ + return SQLITE_OK; + } + checkActiveVdbeCnt(db); + + /* No commit or rollback needed if the program never started */ + if( p->pc>=0 ){ + int mrc; /* Primary error code from p->rc */ + + /* Lock all btrees used by the statement */ + sqlite3BtreeMutexArrayEnter(&p->aMutex); + + /* Check for one of the special errors */ + mrc = p->rc & 0xff; + isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR + || mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL; + if( isSpecialError ){ + /* This loop does static analysis of the query to see which of the + ** following three categories it falls into: + ** + ** Read-only + ** Query with statement journal + ** Query without statement journal + ** + ** We could do something more elegant than this static analysis (i.e. + ** store the type of query as part of the compliation phase), but + ** handling malloc() or IO failure is a fairly obscure edge case so + ** this is probably easier. Todo: Might be an opportunity to reduce + ** code size a very small amount though... + */ + int notReadOnly = 0; + int isStatement = 0; + assert(p->aOp || p->nOp==0); + for(i=0; i<p->nOp; i++){ + switch( p->aOp[i].opcode ){ + case OP_Transaction: + notReadOnly |= p->aOp[i].p2; + break; + case OP_Statement: + isStatement = 1; + break; + } + } + + + /* If the query was read-only, we need do no rollback at all. Otherwise, + ** proceed with the special handling. + */ + if( notReadOnly || mrc!=SQLITE_INTERRUPT ){ + if( p->rc==SQLITE_IOERR_BLOCKED && isStatement ){ + xFunc = sqlite3BtreeRollbackStmt; + p->rc = SQLITE_BUSY; + } else if( (mrc==SQLITE_NOMEM || mrc==SQLITE_FULL) && isStatement ){ + xFunc = sqlite3BtreeRollbackStmt; + }else{ + /* We are forced to roll back the active transaction. Before doing + ** so, abort any other statements this handle currently has active. + */ + invalidateCursorsOnModifiedBtrees(db); + sqlite3RollbackAll(db); + db->autoCommit = 1; + } + } + } + + /* If the auto-commit flag is set and this is the only active vdbe, then + ** we do either a commit or rollback of the current transaction. + ** + ** Note: This block also runs if one of the special errors handled + ** above has occured. + */ + if( db->autoCommit && db->activeVdbeCnt==1 ){ + if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){ + /* The auto-commit flag is true, and the vdbe program was + ** successful or hit an 'OR FAIL' constraint. This means a commit + ** is required. + */ + int rc = vdbeCommit(db, p); + if( rc==SQLITE_BUSY ){ + sqlite3BtreeMutexArrayLeave(&p->aMutex); + return SQLITE_BUSY; + }else if( rc!=SQLITE_OK ){ + p->rc = rc; + sqlite3RollbackAll(db); + }else{ + sqlite3CommitInternalChanges(db); + } + }else{ + sqlite3RollbackAll(db); + } + }else if( !xFunc ){ + if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){ + if( p->openedStatement ){ + xFunc = sqlite3BtreeCommitStmt; + } + }else if( p->errorAction==OE_Abort ){ + xFunc = sqlite3BtreeRollbackStmt; + }else{ + invalidateCursorsOnModifiedBtrees(db); + sqlite3RollbackAll(db); + db->autoCommit = 1; + } + } + + /* If xFunc is not NULL, then it is one of sqlite3BtreeRollbackStmt or + ** sqlite3BtreeCommitStmt. Call it once on each backend. If an error occurs + ** and the return code is still SQLITE_OK, set the return code to the new + ** error value. + */ + assert(!xFunc || + xFunc==sqlite3BtreeCommitStmt || + xFunc==sqlite3BtreeRollbackStmt + ); + for(i=0; xFunc && i<db->nDb; i++){ + int rc; + Btree *pBt = db->aDb[i].pBt; + if( pBt ){ + rc = xFunc(pBt); + if( rc && (p->rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT) ){ + p->rc = rc; + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = 0; + } + } + } + + /* If this was an INSERT, UPDATE or DELETE and the statement was committed, + ** set the change counter. + */ + if( p->changeCntOn && p->pc>=0 ){ + if( !xFunc || xFunc==sqlite3BtreeCommitStmt ){ + sqlite3VdbeSetChanges(db, p->nChange); + }else{ + sqlite3VdbeSetChanges(db, 0); + } + p->nChange = 0; + } + + /* Rollback or commit any schema changes that occurred. */ + if( p->rc!=SQLITE_OK && db->flags&SQLITE_InternChanges ){ + sqlite3ResetInternalSchema(db, 0); + db->flags = (db->flags | SQLITE_InternChanges); + } + + /* Release the locks */ + sqlite3BtreeMutexArrayLeave(&p->aMutex); + } + + /* We have successfully halted and closed the VM. Record this fact. */ + if( p->pc>=0 ){ + db->activeVdbeCnt--; + } + p->magic = VDBE_MAGIC_HALT; + checkActiveVdbeCnt(db); + if( p->db->mallocFailed ){ + p->rc = SQLITE_NOMEM; + } + + return SQLITE_OK; +} + + +/* +** Each VDBE holds the result of the most recent sqlite3_step() call +** in p->rc. This routine sets that result back to SQLITE_OK. +*/ +void sqlite3VdbeResetStepResult(Vdbe *p){ + p->rc = SQLITE_OK; +} + +/* +** Clean up a VDBE after execution but do not delete the VDBE just yet. +** Write any error messages into *pzErrMsg. Return the result code. +** +** After this routine is run, the VDBE should be ready to be executed +** again. +** +** To look at it another way, this routine resets the state of the +** virtual machine from VDBE_MAGIC_RUN or VDBE_MAGIC_HALT back to +** VDBE_MAGIC_INIT. +*/ +int sqlite3VdbeReset(Vdbe *p){ + sqlite3 *db; + db = p->db; + + /* If the VM did not run to completion or if it encountered an + ** error, then it might not have been halted properly. So halt + ** it now. + */ + (void)sqlite3SafetyOn(db); + sqlite3VdbeHalt(p); + (void)sqlite3SafetyOff(db); + + /* If the VDBE has be run even partially, then transfer the error code + ** and error message from the VDBE into the main database structure. But + ** if the VDBE has just been set to run but has not actually executed any + ** instructions yet, leave the main database error information unchanged. + */ + if( p->pc>=0 ){ + if( p->zErrMsg ){ + sqlite3ValueSetStr(db->pErr,-1,p->zErrMsg,SQLITE_UTF8,SQLITE_TRANSIENT); + db->errCode = p->rc; + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = 0; + }else if( p->rc ){ + sqlite3Error(db, p->rc, 0); + }else{ + sqlite3Error(db, SQLITE_OK, 0); + } + }else if( p->rc && p->expired ){ + /* The expired flag was set on the VDBE before the first call + ** to sqlite3_step(). For consistency (since sqlite3_step() was + ** called), set the database error in this case as well. + */ + sqlite3Error(db, p->rc, 0); + sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT); + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = 0; + } + + /* Reclaim all memory used by the VDBE + */ + Cleanup(p); + + /* Save profiling information from this VDBE run. + */ +#ifdef VDBE_PROFILE + { + FILE *out = fopen("vdbe_profile.out", "a"); + if( out ){ + int i; + fprintf(out, "---- "); + for(i=0; i<p->nOp; i++){ + fprintf(out, "%02x", p->aOp[i].opcode); + } + fprintf(out, "\n"); + for(i=0; i<p->nOp; i++){ + fprintf(out, "%6d %10lld %8lld ", + p->aOp[i].cnt, + p->aOp[i].cycles, + p->aOp[i].cnt>0 ? p->aOp[i].cycles/p->aOp[i].cnt : 0 + ); + sqlite3VdbePrintOp(out, i, &p->aOp[i]); + } + fclose(out); + } + } +#endif + p->magic = VDBE_MAGIC_INIT; + return p->rc & db->errMask; +} + +/* +** Clean up and delete a VDBE after execution. Return an integer which is +** the result code. Write any error message text into *pzErrMsg. +*/ +int sqlite3VdbeFinalize(Vdbe *p){ + int rc = SQLITE_OK; + if( p->magic==VDBE_MAGIC_RUN || p->magic==VDBE_MAGIC_HALT ){ + rc = sqlite3VdbeReset(p); + assert( (rc & p->db->errMask)==rc ); + }else if( p->magic!=VDBE_MAGIC_INIT ){ + return SQLITE_MISUSE; + } + sqlite3VdbeDelete(p); + return rc; +} + +/* +** Call the destructor for each auxdata entry in pVdbeFunc for which +** the corresponding bit in mask is clear. Auxdata entries beyond 31 +** are always destroyed. To destroy all auxdata entries, call this +** routine with mask==0. +*/ +void sqlite3VdbeDeleteAuxData(VdbeFunc *pVdbeFunc, int mask){ + int i; + for(i=0; i<pVdbeFunc->nAux; i++){ + struct AuxData *pAux = &pVdbeFunc->apAux[i]; + if( (i>31 || !(mask&(1<<i))) && pAux->pAux ){ + if( pAux->xDelete ){ + pAux->xDelete(pAux->pAux); + } + pAux->pAux = 0; + } + } +} + +/* +** Delete an entire VDBE. +*/ +void sqlite3VdbeDelete(Vdbe *p){ + int i; + sqlite3 *db; + + if( p==0 ) return; + db = p->db; + if( p->pPrev ){ + p->pPrev->pNext = p->pNext; + }else{ + assert( db->pVdbe==p ); + db->pVdbe = p->pNext; + } + if( p->pNext ){ + p->pNext->pPrev = p->pPrev; + } + if( p->aOp ){ + Op *pOp = p->aOp; + for(i=0; i<p->nOp; i++, pOp++){ + freeP4(db, pOp->p4type, pOp->p4.p); +#ifdef SQLITE_DEBUG + sqlite3DbFree(db, pOp->zComment); +#endif + } + sqlite3DbFree(db, p->aOp); + } + releaseMemArray(p->aVar, p->nVar); + sqlite3DbFree(db, p->aLabel); + if( p->aMem ){ + sqlite3DbFree(db, &p->aMem[1]); + } + releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); + sqlite3DbFree(db, p->aColName); + sqlite3DbFree(db, p->zSql); + p->magic = VDBE_MAGIC_DEAD; + sqlite3DbFree(db, p); +} + +/* +** If a MoveTo operation is pending on the given cursor, then do that +** MoveTo now. Return an error code. If no MoveTo is pending, this +** routine does nothing and returns SQLITE_OK. +*/ +int sqlite3VdbeCursorMoveto(Cursor *p){ + if( p->deferredMoveto ){ + int res, rc; +#ifdef SQLITE_TEST + extern int sqlite3_search_count; +#endif + assert( p->isTable ); + rc = sqlite3BtreeMoveto(p->pCursor, 0, 0, p->movetoTarget, 0, &res); + if( rc ) return rc; + *p->pIncrKey = 0; + p->lastRowid = keyToInt(p->movetoTarget); + p->rowidIsValid = res==0; + if( res<0 ){ + rc = sqlite3BtreeNext(p->pCursor, &res); + if( rc ) return rc; + } +#ifdef SQLITE_TEST + sqlite3_search_count++; +#endif + p->deferredMoveto = 0; + p->cacheStatus = CACHE_STALE; + }else if( p->pCursor ){ + int hasMoved; + int rc = sqlite3BtreeCursorHasMoved(p->pCursor, &hasMoved); + if( rc ) return rc; + if( hasMoved ){ + p->cacheStatus = CACHE_STALE; + p->nullRow = 1; + } + } + return SQLITE_OK; +} + +/* +** The following functions: +** +** sqlite3VdbeSerialType() +** sqlite3VdbeSerialTypeLen() +** sqlite3VdbeSerialLen() +** sqlite3VdbeSerialPut() +** sqlite3VdbeSerialGet() +** +** encapsulate the code that serializes values for storage in SQLite +** data and index records. Each serialized value consists of a +** 'serial-type' and a blob of data. The serial type is an 8-byte unsigned +** integer, stored as a varint. +** +** In an SQLite index record, the serial type is stored directly before +** the blob of data that it corresponds to. In a table record, all serial +** types are stored at the start of the record, and the blobs of data at +** the end. Hence these functions allow the caller to handle the +** serial-type and data blob seperately. +** +** The following table describes the various storage classes for data: +** +** serial type bytes of data type +** -------------- --------------- --------------- +** 0 0 NULL +** 1 1 signed integer +** 2 2 signed integer +** 3 3 signed integer +** 4 4 signed integer +** 5 6 signed integer +** 6 8 signed integer +** 7 8 IEEE float +** 8 0 Integer constant 0 +** 9 0 Integer constant 1 +** 10,11 reserved for expansion +** N>=12 and even (N-12)/2 BLOB +** N>=13 and odd (N-13)/2 text +** +** The 8 and 9 types were added in 3.3.0, file format 4. Prior versions +** of SQLite will not understand those serial types. +*/ + +/* +** Return the serial-type for the value stored in pMem. +*/ +u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){ + int flags = pMem->flags; + int n; + + if( flags&MEM_Null ){ + return 0; + } + if( flags&MEM_Int ){ + /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */ +# define MAX_6BYTE ((((i64)0x00008000)<<32)-1) + i64 i = pMem->u.i; + u64 u; + if( file_format>=4 && (i&1)==i ){ + return 8+i; + } + u = i<0 ? -i : i; + if( u<=127 ) return 1; + if( u<=32767 ) return 2; + if( u<=8388607 ) return 3; + if( u<=2147483647 ) return 4; + if( u<=MAX_6BYTE ) return 5; + return 6; + } + if( flags&MEM_Real ){ + return 7; + } + assert( flags&(MEM_Str|MEM_Blob) ); + n = pMem->n; + if( flags & MEM_Zero ){ + n += pMem->u.i; + } + assert( n>=0 ); + return ((n*2) + 12 + ((flags&MEM_Str)!=0)); +} + +/* +** Return the length of the data corresponding to the supplied serial-type. +*/ +int sqlite3VdbeSerialTypeLen(u32 serial_type){ + if( serial_type>=12 ){ + return (serial_type-12)/2; + }else{ + static const u8 aSize[] = { 0, 1, 2, 3, 4, 6, 8, 8, 0, 0, 0, 0 }; + return aSize[serial_type]; + } +} + +/* +** If we are on an architecture with mixed-endian floating +** points (ex: ARM7) then swap the lower 4 bytes with the +** upper 4 bytes. Return the result. +** +** For most architectures, this is a no-op. +** +** (later): It is reported to me that the mixed-endian problem +** on ARM7 is an issue with GCC, not with the ARM7 chip. It seems +** that early versions of GCC stored the two words of a 64-bit +** float in the wrong order. And that error has been propagated +** ever since. The blame is not necessarily with GCC, though. +** GCC might have just copying the problem from a prior compiler. +** I am also told that newer versions of GCC that follow a different +** ABI get the byte order right. +** +** Developers using SQLite on an ARM7 should compile and run their +** application using -DSQLITE_DEBUG=1 at least once. With DEBUG +** enabled, some asserts below will ensure that the byte order of +** floating point values is correct. +** +** (2007-08-30) Frank van Vugt has studied this problem closely +** and has send his findings to the SQLite developers. Frank +** writes that some Linux kernels offer floating point hardware +** emulation that uses only 32-bit mantissas instead of a full +** 48-bits as required by the IEEE standard. (This is the +** CONFIG_FPE_FASTFPE option.) On such systems, floating point +** byte swapping becomes very complicated. To avoid problems, +** the necessary byte swapping is carried out using a 64-bit integer +** rather than a 64-bit float. Frank assures us that the code here +** works for him. We, the developers, have no way to independently +** verify this, but Frank seems to know what he is talking about +** so we trust him. +*/ +#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT +static u64 floatSwap(u64 in){ + union { + u64 r; + u32 i[2]; + } u; + u32 t; + + u.r = in; + t = u.i[0]; + u.i[0] = u.i[1]; + u.i[1] = t; + return u.r; +} +# define swapMixedEndianFloat(X) X = floatSwap(X) +#else +# define swapMixedEndianFloat(X) +#endif + +/* +** Write the serialized data blob for the value stored in pMem into +** buf. It is assumed that the caller has allocated sufficient space. +** Return the number of bytes written. +** +** nBuf is the amount of space left in buf[]. nBuf must always be +** large enough to hold the entire field. Except, if the field is +** a blob with a zero-filled tail, then buf[] might be just the right +** size to hold everything except for the zero-filled tail. If buf[] +** is only big enough to hold the non-zero prefix, then only write that +** prefix into buf[]. But if buf[] is large enough to hold both the +** prefix and the tail then write the prefix and set the tail to all +** zeros. +** +** Return the number of bytes actually written into buf[]. The number +** of bytes in the zero-filled tail is included in the return value only +** if those bytes were zeroed in buf[]. +*/ +int sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_format){ + u32 serial_type = sqlite3VdbeSerialType(pMem, file_format); + int len; + + /* Integer and Real */ + if( serial_type<=7 && serial_type>0 ){ + u64 v; + int i; + if( serial_type==7 ){ + assert( sizeof(v)==sizeof(pMem->r) ); + memcpy(&v, &pMem->r, sizeof(v)); + swapMixedEndianFloat(v); + }else{ + v = pMem->u.i; + } + len = i = sqlite3VdbeSerialTypeLen(serial_type); + assert( len<=nBuf ); + while( i-- ){ + buf[i] = (v&0xFF); + v >>= 8; + } + return len; + } + + /* String or blob */ + if( serial_type>=12 ){ + assert( pMem->n + ((pMem->flags & MEM_Zero)?pMem->u.i:0) + == sqlite3VdbeSerialTypeLen(serial_type) ); + assert( pMem->n<=nBuf ); + len = pMem->n; + memcpy(buf, pMem->z, len); + if( pMem->flags & MEM_Zero ){ + len += pMem->u.i; + if( len>nBuf ){ + len = nBuf; + } + memset(&buf[pMem->n], 0, len-pMem->n); + } + return len; + } + + /* NULL or constants 0 or 1 */ + return 0; +} + +/* +** Deserialize the data blob pointed to by buf as serial type serial_type +** and store the result in pMem. Return the number of bytes read. +*/ +int sqlite3VdbeSerialGet( + const unsigned char *buf, /* Buffer to deserialize from */ + u32 serial_type, /* Serial type to deserialize */ + Mem *pMem /* Memory cell to write value into */ +){ + switch( serial_type ){ + case 10: /* Reserved for future use */ + case 11: /* Reserved for future use */ + case 0: { /* NULL */ + pMem->flags = MEM_Null; + break; + } + case 1: { /* 1-byte signed integer */ + pMem->u.i = (signed char)buf[0]; + pMem->flags = MEM_Int; + return 1; + } + case 2: { /* 2-byte signed integer */ + pMem->u.i = (((signed char)buf[0])<<8) | buf[1]; + pMem->flags = MEM_Int; + return 2; + } + case 3: { /* 3-byte signed integer */ + pMem->u.i = (((signed char)buf[0])<<16) | (buf[1]<<8) | buf[2]; + pMem->flags = MEM_Int; + return 3; + } + case 4: { /* 4-byte signed integer */ + pMem->u.i = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3]; + pMem->flags = MEM_Int; + return 4; + } + case 5: { /* 6-byte signed integer */ + u64 x = (((signed char)buf[0])<<8) | buf[1]; + u32 y = (buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5]; + x = (x<<32) | y; + pMem->u.i = *(i64*)&x; + pMem->flags = MEM_Int; + return 6; + } + case 6: /* 8-byte signed integer */ + case 7: { /* IEEE floating point */ + u64 x; + u32 y; +#if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT) + /* Verify that integers and floating point values use the same + ** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is + ** defined that 64-bit floating point values really are mixed + ** endian. + */ + static const u64 t1 = ((u64)0x3ff00000)<<32; + static const double r1 = 1.0; + u64 t2 = t1; + swapMixedEndianFloat(t2); + assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 ); +#endif + + x = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3]; + y = (buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7]; + x = (x<<32) | y; + if( serial_type==6 ){ + pMem->u.i = *(i64*)&x; + pMem->flags = MEM_Int; + }else{ + assert( sizeof(x)==8 && sizeof(pMem->r)==8 ); + swapMixedEndianFloat(x); + memcpy(&pMem->r, &x, sizeof(x)); + pMem->flags = sqlite3IsNaN(pMem->r) ? MEM_Null : MEM_Real; + } + return 8; + } + case 8: /* Integer 0 */ + case 9: { /* Integer 1 */ + pMem->u.i = serial_type-8; + pMem->flags = MEM_Int; + return 0; + } + default: { + int len = (serial_type-12)/2; + pMem->z = (char *)buf; + pMem->n = len; + pMem->xDel = 0; + if( serial_type&0x01 ){ + pMem->flags = MEM_Str | MEM_Ephem; + }else{ + pMem->flags = MEM_Blob | MEM_Ephem; + } + return len; + } + } + return 0; +} + + +/* +** Given the nKey-byte encoding of a record in pKey[], parse the +** record into a UnpackedRecord structure. Return a pointer to +** that structure. +** +** The calling function might provide szSpace bytes of memory +** space at pSpace. This space can be used to hold the returned +** VDbeParsedRecord structure if it is large enough. If it is +** not big enough, space is obtained from sqlite3_malloc(). +** +** The returned structure should be closed by a call to +** sqlite3VdbeDeleteUnpackedRecord(). +*/ +UnpackedRecord *sqlite3VdbeRecordUnpack( + KeyInfo *pKeyInfo, /* Information about the record format */ + int nKey, /* Size of the binary record */ + const void *pKey, /* The binary record */ + void *pSpace, /* Space available to hold resulting object */ + int szSpace /* Size of pSpace[] in bytes */ +){ + const unsigned char *aKey = (const unsigned char *)pKey; + UnpackedRecord *p; + int nByte; + int idx, d; + u16 u; /* Unsigned loop counter */ + u32 szHdr; + Mem *pMem; + + assert( sizeof(Mem)>sizeof(*p) ); + nByte = sizeof(Mem)*(pKeyInfo->nField+2); + if( nByte>szSpace ){ + p = sqlite3DbMallocRaw(pKeyInfo->db, nByte); + if( p==0 ) return 0; + p->needFree = 1; + }else{ + p = pSpace; + p->needFree = 0; + } + p->pKeyInfo = pKeyInfo; + p->nField = pKeyInfo->nField + 1; + p->needDestroy = 1; + p->aMem = pMem = &((Mem*)p)[1]; + idx = getVarint32(aKey, szHdr); + d = szHdr; + u = 0; + while( idx<szHdr && u<p->nField ){ + u32 serial_type; + + idx += getVarint32( aKey+idx, serial_type); + if( d>=nKey && sqlite3VdbeSerialTypeLen(serial_type)>0 ) break; + pMem->enc = pKeyInfo->enc; + pMem->db = pKeyInfo->db; + pMem->flags = 0; + pMem->zMalloc = 0; + d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem); + pMem++; + u++; + } + p->nField = u; + return (void*)p; +} + +/* +** This routine destroys a UnpackedRecord object +*/ +void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){ + if( p ){ + if( p->needDestroy ){ + int i; + Mem *pMem; + for(i=0, pMem=p->aMem; i<p->nField; i++, pMem++){ + if( pMem->zMalloc ){ + sqlite3VdbeMemRelease(pMem); + } + } + } + if( p->needFree ){ + sqlite3DbFree(p->pKeyInfo->db, p); + } + } +} + +/* +** This function compares the two table rows or index records +** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero +** or positive integer if {nKey1, pKey1} is less than, equal to or +** greater than pPKey2. The {nKey1, pKey1} key must be a blob +** created by th OP_MakeRecord opcode of the VDBE. The pPKey2 +** key must be a parsed key such as obtained from +** sqlite3VdbeParseRecord. +** +** Key1 and Key2 do not have to contain the same number of fields. +** But if the lengths differ, Key2 must be the shorter of the two. +** +** Historical note: In earlier versions of this routine both Key1 +** and Key2 were blobs obtained from OP_MakeRecord. But we found +** that in typical use the same Key2 would be submitted multiple times +** in a row. So an optimization was added to parse the Key2 key +** separately and submit the parsed version. In this way, we avoid +** parsing the same Key2 multiple times in a row. +*/ +int sqlite3VdbeRecordCompare( + int nKey1, const void *pKey1, + UnpackedRecord *pPKey2 +){ + u32 d1; /* Offset into aKey[] of next data element */ + u32 idx1; /* Offset into aKey[] of next header element */ + u32 szHdr1; /* Number of bytes in header */ + int i = 0; + int nField; + int rc = 0; + const unsigned char *aKey1 = (const unsigned char *)pKey1; + KeyInfo *pKeyInfo; + Mem mem1; + + pKeyInfo = pPKey2->pKeyInfo; + mem1.enc = pKeyInfo->enc; + mem1.db = pKeyInfo->db; + mem1.flags = 0; + mem1.zMalloc = 0; + + idx1 = getVarint32(aKey1, szHdr1); + d1 = szHdr1; + nField = pKeyInfo->nField; + while( idx1<szHdr1 && i<pPKey2->nField ){ + u32 serial_type1; + + /* Read the serial types for the next element in each key. */ + idx1 += getVarint32( aKey1+idx1, serial_type1 ); + if( d1>=nKey1 && sqlite3VdbeSerialTypeLen(serial_type1)>0 ) break; + + /* Extract the values to be compared. + */ + d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1); + + /* Do the comparison + */ + rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i], + i<nField ? pKeyInfo->aColl[i] : 0); + if( rc!=0 ){ + break; + } + i++; + } + if( mem1.zMalloc ) sqlite3VdbeMemRelease(&mem1); + + /* One of the keys ran out of fields, but all the fields up to that point + ** were equal. If the incrKey flag is true, then the second key is + ** treated as larger. + */ + if( rc==0 ){ + if( pKeyInfo->incrKey ){ + rc = -1; + }else if( !pKeyInfo->prefixIsEqual ){ + if( d1<nKey1 ){ + rc = 1; + } + } + }else if( pKeyInfo->aSortOrder && i<pKeyInfo->nField + && pKeyInfo->aSortOrder[i] ){ + rc = -rc; + } + + return rc; +} + +/* +** The argument is an index entry composed using the OP_MakeRecord opcode. +** The last entry in this record should be an integer (specifically +** an integer rowid). This routine returns the number of bytes in +** that integer. +*/ +int sqlite3VdbeIdxRowidLen(const u8 *aKey, int nKey, int *pRowidLen){ + u32 szHdr; /* Size of the header */ + u32 typeRowid; /* Serial type of the rowid */ + + (void)getVarint32(aKey, szHdr); + if( szHdr>nKey ){ + return SQLITE_CORRUPT_BKPT; + } + (void)getVarint32(&aKey[szHdr-1], typeRowid); + *pRowidLen = sqlite3VdbeSerialTypeLen(typeRowid); + return SQLITE_OK; +} + + +/* +** pCur points at an index entry created using the OP_MakeRecord opcode. +** Read the rowid (the last field in the record) and store it in *rowid. +** Return SQLITE_OK if everything works, or an error code otherwise. +*/ +int sqlite3VdbeIdxRowid(BtCursor *pCur, i64 *rowid){ + i64 nCellKey = 0; + int rc; + u32 szHdr; /* Size of the header */ + u32 typeRowid; /* Serial type of the rowid */ + u32 lenRowid; /* Size of the rowid */ + Mem m, v; + + sqlite3BtreeKeySize(pCur, &nCellKey); + if( nCellKey<=0 ){ + return SQLITE_CORRUPT_BKPT; + } + m.flags = 0; + m.db = 0; + m.zMalloc = 0; + rc = sqlite3VdbeMemFromBtree(pCur, 0, nCellKey, 1, &m); + if( rc ){ + return rc; + } + (void)getVarint32((u8*)m.z, szHdr); + (void)getVarint32((u8*)&m.z[szHdr-1], typeRowid); + lenRowid = sqlite3VdbeSerialTypeLen(typeRowid); + sqlite3VdbeSerialGet((u8*)&m.z[m.n-lenRowid], typeRowid, &v); + *rowid = v.u.i; + sqlite3VdbeMemRelease(&m); + return SQLITE_OK; +} + +/* +** Compare the key of the index entry that cursor pC is point to against +** the key string in pKey (of length nKey). Write into *pRes a number +** that is negative, zero, or positive if pC is less than, equal to, +** or greater than pKey. Return SQLITE_OK on success. +** +** pKey is either created without a rowid or is truncated so that it +** omits the rowid at the end. The rowid at the end of the index entry +** is ignored as well. +*/ +int sqlite3VdbeIdxKeyCompare( + Cursor *pC, /* The cursor to compare against */ + UnpackedRecord *pUnpacked, + int nKey, const u8 *pKey, /* The key to compare */ + int *res /* Write the comparison result here */ +){ + i64 nCellKey = 0; + int rc; + BtCursor *pCur = pC->pCursor; + int lenRowid; + Mem m; + UnpackedRecord *pRec; + char zSpace[200]; + + sqlite3BtreeKeySize(pCur, &nCellKey); + if( nCellKey<=0 ){ + *res = 0; + return SQLITE_OK; + } + m.db = 0; + m.flags = 0; + m.zMalloc = 0; + if( (rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, nCellKey, 1, &m)) + || (rc = sqlite3VdbeIdxRowidLen((u8*)m.z, m.n, &lenRowid)) + ){ + return rc; + } + if( !pUnpacked ){ + pRec = sqlite3VdbeRecordUnpack(pC->pKeyInfo, nKey, pKey, + zSpace, sizeof(zSpace)); + }else{ + pRec = pUnpacked; + } + if( pRec==0 ){ + return SQLITE_NOMEM; + } + *res = sqlite3VdbeRecordCompare(m.n-lenRowid, m.z, pRec); + if( !pUnpacked ){ + sqlite3VdbeDeleteUnpackedRecord(pRec); + } + sqlite3VdbeMemRelease(&m); + return SQLITE_OK; +} + +/* +** This routine sets the value to be returned by subsequent calls to +** sqlite3_changes() on the database handle 'db'. +*/ +void sqlite3VdbeSetChanges(sqlite3 *db, int nChange){ + assert( sqlite3_mutex_held(db->mutex) ); + db->nChange = nChange; + db->nTotalChange += nChange; +} + +/* +** Set a flag in the vdbe to update the change counter when it is finalised +** or reset. +*/ +void sqlite3VdbeCountChanges(Vdbe *v){ + v->changeCntOn = 1; +} + +/* +** Mark every prepared statement associated with a database connection +** as expired. +** +** An expired statement means that recompilation of the statement is +** recommend. Statements expire when things happen that make their +** programs obsolete. Removing user-defined functions or collating +** sequences, or changing an authorization function are the types of +** things that make prepared statements obsolete. +*/ +void sqlite3ExpirePreparedStatements(sqlite3 *db){ + Vdbe *p; + for(p = db->pVdbe; p; p=p->pNext){ + p->expired = 1; + } +} + +/* +** Return the database associated with the Vdbe. +*/ +sqlite3 *sqlite3VdbeDb(Vdbe *v){ + return v->db; +} diff --git a/third_party/sqlite/src/vdbeblob.c b/third_party/sqlite/src/vdbeblob.c new file mode 100755 index 0000000..746bfe4 --- /dev/null +++ b/third_party/sqlite/src/vdbeblob.c @@ -0,0 +1,348 @@ +/* +** 2007 May 1 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file contains code used to implement incremental BLOB I/O. +** +** $Id: vdbeblob.c,v 1.25 2008/07/28 19:34:54 drh Exp $ +*/ + +#include "sqliteInt.h" +#include "vdbeInt.h" + +#ifndef SQLITE_OMIT_INCRBLOB + +/* +** Valid sqlite3_blob* handles point to Incrblob structures. +*/ +typedef struct Incrblob Incrblob; +struct Incrblob { + int flags; /* Copy of "flags" passed to sqlite3_blob_open() */ + int nByte; /* Size of open blob, in bytes */ + int iOffset; /* Byte offset of blob in cursor data */ + BtCursor *pCsr; /* Cursor pointing at blob row */ + sqlite3_stmt *pStmt; /* Statement holding cursor open */ + sqlite3 *db; /* The associated database */ +}; + +/* +** Open a blob handle. +*/ +int sqlite3_blob_open( + sqlite3* db, /* The database connection */ + const char *zDb, /* The attached database containing the blob */ + const char *zTable, /* The table containing the blob */ + const char *zColumn, /* The column containing the blob */ + sqlite_int64 iRow, /* The row containing the glob */ + int flags, /* True -> read/write access, false -> read-only */ + sqlite3_blob **ppBlob /* Handle for accessing the blob returned here */ +){ + int nAttempt = 0; + int iCol; /* Index of zColumn in row-record */ + + /* This VDBE program seeks a btree cursor to the identified + ** db/table/row entry. The reason for using a vdbe program instead + ** of writing code to use the b-tree layer directly is that the + ** vdbe program will take advantage of the various transaction, + ** locking and error handling infrastructure built into the vdbe. + ** + ** After seeking the cursor, the vdbe executes an OP_ResultRow. + ** Code external to the Vdbe then "borrows" the b-tree cursor and + ** uses it to implement the blob_read(), blob_write() and + ** blob_bytes() functions. + ** + ** The sqlite3_blob_close() function finalizes the vdbe program, + ** which closes the b-tree cursor and (possibly) commits the + ** transaction. + */ + static const VdbeOpList openBlob[] = { + {OP_Transaction, 0, 0, 0}, /* 0: Start a transaction */ + {OP_VerifyCookie, 0, 0, 0}, /* 1: Check the schema cookie */ + + /* One of the following two instructions is replaced by an + ** OP_Noop before exection. + */ + {OP_SetNumColumns, 0, 0, 0}, /* 2: Num cols for cursor */ + {OP_OpenRead, 0, 0, 0}, /* 3: Open cursor 0 for reading */ + {OP_SetNumColumns, 0, 0, 0}, /* 4: Num cols for cursor */ + {OP_OpenWrite, 0, 0, 0}, /* 5: Open cursor 0 for read/write */ + + {OP_Variable, 1, 1, 0}, /* 6: Push the rowid to the stack */ + {OP_NotExists, 0, 10, 1}, /* 7: Seek the cursor */ + {OP_Column, 0, 0, 1}, /* 8 */ + {OP_ResultRow, 1, 0, 0}, /* 9 */ + {OP_Close, 0, 0, 0}, /* 10 */ + {OP_Halt, 0, 0, 0}, /* 11 */ + }; + + Vdbe *v = 0; + int rc = SQLITE_OK; + char zErr[128]; + + zErr[0] = 0; + sqlite3_mutex_enter(db->mutex); + do { + Parse sParse; + Table *pTab; + + memset(&sParse, 0, sizeof(Parse)); + sParse.db = db; + + if( sqlite3SafetyOn(db) ){ + sqlite3_mutex_leave(db->mutex); + return SQLITE_MISUSE; + } + + sqlite3BtreeEnterAll(db); + pTab = sqlite3LocateTable(&sParse, 0, zTable, zDb); + if( pTab && IsVirtual(pTab) ){ + pTab = 0; + sqlite3ErrorMsg(&sParse, "cannot open virtual table: %s", zTable); + } +#ifndef SQLITE_OMIT_VIEW + if( pTab && pTab->pSelect ){ + pTab = 0; + sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable); + } +#endif + if( !pTab ){ + if( sParse.zErrMsg ){ + sqlite3_snprintf(sizeof(zErr), zErr, "%s", sParse.zErrMsg); + } + sqlite3DbFree(db, sParse.zErrMsg); + rc = SQLITE_ERROR; + (void)sqlite3SafetyOff(db); + sqlite3BtreeLeaveAll(db); + goto blob_open_out; + } + + /* Now search pTab for the exact column. */ + for(iCol=0; iCol < pTab->nCol; iCol++) { + if( sqlite3StrICmp(pTab->aCol[iCol].zName, zColumn)==0 ){ + break; + } + } + if( iCol==pTab->nCol ){ + sqlite3_snprintf(sizeof(zErr), zErr, "no such column: \"%s\"", zColumn); + rc = SQLITE_ERROR; + (void)sqlite3SafetyOff(db); + sqlite3BtreeLeaveAll(db); + goto blob_open_out; + } + + /* If the value is being opened for writing, check that the + ** column is not indexed. It is against the rules to open an + ** indexed column for writing. + */ + if( flags ){ + Index *pIdx; + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + int j; + for(j=0; j<pIdx->nColumn; j++){ + if( pIdx->aiColumn[j]==iCol ){ + sqlite3_snprintf(sizeof(zErr), zErr, + "cannot open indexed column for writing"); + rc = SQLITE_ERROR; + (void)sqlite3SafetyOff(db); + sqlite3BtreeLeaveAll(db); + goto blob_open_out; + } + } + } + } + + v = sqlite3VdbeCreate(db); + if( v ){ + int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + sqlite3VdbeAddOpList(v, sizeof(openBlob)/sizeof(VdbeOpList), openBlob); + + /* Configure the OP_Transaction */ + sqlite3VdbeChangeP1(v, 0, iDb); + sqlite3VdbeChangeP2(v, 0, (flags ? 1 : 0)); + + /* Configure the OP_VerifyCookie */ + sqlite3VdbeChangeP1(v, 1, iDb); + sqlite3VdbeChangeP2(v, 1, pTab->pSchema->schema_cookie); + + /* Make sure a mutex is held on the table to be accessed */ + sqlite3VdbeUsesBtree(v, iDb); + + /* Remove either the OP_OpenWrite or OpenRead. Set the P2 + ** parameter of the other to pTab->tnum. + */ + sqlite3VdbeChangeToNoop(v, (flags ? 3 : 5), 1); + sqlite3VdbeChangeP2(v, (flags ? 5 : 3), pTab->tnum); + sqlite3VdbeChangeP3(v, (flags ? 5 : 3), iDb); + + /* Configure the OP_SetNumColumns. Configure the cursor to + ** think that the table has one more column than it really + ** does. An OP_Column to retrieve this imaginary column will + ** always return an SQL NULL. This is useful because it means + ** we can invoke OP_Column to fill in the vdbe cursors type + ** and offset cache without causing any IO. + */ + sqlite3VdbeChangeP2(v, flags ? 4 : 2, pTab->nCol+1); + sqlite3VdbeChangeP2(v, 8, pTab->nCol); + if( !db->mallocFailed ){ + sqlite3VdbeMakeReady(v, 1, 1, 1, 0); + } + } + + sqlite3BtreeLeaveAll(db); + rc = sqlite3SafetyOff(db); + if( rc!=SQLITE_OK || db->mallocFailed ){ + goto blob_open_out; + } + + sqlite3_bind_int64((sqlite3_stmt *)v, 1, iRow); + rc = sqlite3_step((sqlite3_stmt *)v); + if( rc!=SQLITE_ROW ){ + nAttempt++; + rc = sqlite3_finalize((sqlite3_stmt *)v); + sqlite3_snprintf(sizeof(zErr), zErr, sqlite3_errmsg(db)); + v = 0; + } + } while( nAttempt<5 && rc==SQLITE_SCHEMA ); + + if( rc==SQLITE_ROW ){ + /* The row-record has been opened successfully. Check that the + ** column in question contains text or a blob. If it contains + ** text, it is up to the caller to get the encoding right. + */ + Incrblob *pBlob; + u32 type = v->apCsr[0]->aType[iCol]; + + if( type<12 ){ + sqlite3_snprintf(sizeof(zErr), zErr, "cannot open value of type %s", + type==0?"null": type==7?"real": "integer" + ); + rc = SQLITE_ERROR; + goto blob_open_out; + } + pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob)); + if( db->mallocFailed ){ + sqlite3DbFree(db, pBlob); + goto blob_open_out; + } + pBlob->flags = flags; + pBlob->pCsr = v->apCsr[0]->pCursor; + sqlite3BtreeEnterCursor(pBlob->pCsr); + sqlite3BtreeCacheOverflow(pBlob->pCsr); + sqlite3BtreeLeaveCursor(pBlob->pCsr); + pBlob->pStmt = (sqlite3_stmt *)v; + pBlob->iOffset = v->apCsr[0]->aOffset[iCol]; + pBlob->nByte = sqlite3VdbeSerialTypeLen(type); + pBlob->db = db; + *ppBlob = (sqlite3_blob *)pBlob; + rc = SQLITE_OK; + }else if( rc==SQLITE_OK ){ + sqlite3_snprintf(sizeof(zErr), zErr, "no such rowid: %lld", iRow); + rc = SQLITE_ERROR; + } + +blob_open_out: + zErr[sizeof(zErr)-1] = '\0'; + if( rc!=SQLITE_OK || db->mallocFailed ){ + sqlite3_finalize((sqlite3_stmt *)v); + } + sqlite3Error(db, rc, (rc==SQLITE_OK?0:zErr)); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; +} + +/* +** Close a blob handle that was previously created using +** sqlite3_blob_open(). +*/ +int sqlite3_blob_close(sqlite3_blob *pBlob){ + Incrblob *p = (Incrblob *)pBlob; + int rc; + + rc = sqlite3_finalize(p->pStmt); + sqlite3DbFree(p->db, p); + return rc; +} + +/* +** Perform a read or write operation on a blob +*/ +static int blobReadWrite( + sqlite3_blob *pBlob, + void *z, + int n, + int iOffset, + int (*xCall)(BtCursor*, u32, u32, void*) +){ + int rc; + Incrblob *p = (Incrblob *)pBlob; + Vdbe *v; + sqlite3 *db = p->db; + + /* Request is out of range. Return a transient error. */ + if( (iOffset+n)>p->nByte ){ + return SQLITE_ERROR; + } + sqlite3_mutex_enter(db->mutex); + + /* If there is no statement handle, then the blob-handle has + ** already been invalidated. Return SQLITE_ABORT in this case. + */ + v = (Vdbe*)p->pStmt; + if( v==0 ){ + rc = SQLITE_ABORT; + }else{ + /* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is + ** returned, clean-up the statement handle. + */ + assert( db == v->db ); + sqlite3BtreeEnterCursor(p->pCsr); + rc = xCall(p->pCsr, iOffset+p->iOffset, n, z); + sqlite3BtreeLeaveCursor(p->pCsr); + if( rc==SQLITE_ABORT ){ + sqlite3VdbeFinalize(v); + p->pStmt = 0; + }else{ + db->errCode = rc; + v->rc = rc; + } + } + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; +} + +/* +** Read data from a blob handle. +*/ +int sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){ + return blobReadWrite(pBlob, z, n, iOffset, sqlite3BtreeData); +} + +/* +** Write data to a blob handle. +*/ +int sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){ + return blobReadWrite(pBlob, (void *)z, n, iOffset, sqlite3BtreePutData); +} + +/* +** Query a blob handle for the size of the data. +** +** The Incrblob.nByte field is fixed for the lifetime of the Incrblob +** so no mutex is required for access. +*/ +int sqlite3_blob_bytes(sqlite3_blob *pBlob){ + Incrblob *p = (Incrblob *)pBlob; + return p->nByte; +} + +#endif /* #ifndef SQLITE_OMIT_INCRBLOB */ diff --git a/third_party/sqlite/src/vdbefifo.c b/third_party/sqlite/src/vdbefifo.c new file mode 100755 index 0000000..a5e270d --- /dev/null +++ b/third_party/sqlite/src/vdbefifo.c @@ -0,0 +1,130 @@ +/* +** 2005 June 16 +** +** 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 implements a FIFO queue of rowids used for processing +** UPDATE and DELETE statements. +** +** $Id: vdbefifo.c,v 1.8 2008/07/28 19:34:54 drh Exp $ +*/ +#include "sqliteInt.h" +#include "vdbeInt.h" + +/* +** Constants FIFOSIZE_FIRST and FIFOSIZE_MAX are the initial +** number of entries in a fifo page and the maximum number of +** entries in a fifo page. +*/ +#define FIFOSIZE_FIRST (((128-sizeof(FifoPage))/8)+1) +#ifdef SQLITE_MALLOC_SOFT_LIMIT +# define FIFOSIZE_MAX (((SQLITE_MALLOC_SOFT_LIMIT-sizeof(FifoPage))/8)+1) +#else +# define FIFOSIZE_MAX (((262144-sizeof(FifoPage))/8)+1) +#endif + +/* +** Allocate a new FifoPage and return a pointer to it. Return NULL if +** we run out of memory. Leave space on the page for nEntry entries. +*/ +static FifoPage *allocateFifoPage(sqlite3 *db, int nEntry){ + FifoPage *pPage; + if( nEntry>FIFOSIZE_MAX ){ + nEntry = FIFOSIZE_MAX; + } + pPage = sqlite3DbMallocRaw(db, sizeof(FifoPage) + sizeof(i64)*(nEntry-1) ); + if( pPage ){ + pPage->nSlot = nEntry; + pPage->iWrite = 0; + pPage->iRead = 0; + pPage->pNext = 0; + } + return pPage; +} + +/* +** Initialize a Fifo structure. +*/ +void sqlite3VdbeFifoInit(Fifo *pFifo, sqlite3 *db){ + memset(pFifo, 0, sizeof(*pFifo)); + pFifo->db = db; +} + +/* +** Push a single 64-bit integer value into the Fifo. Return SQLITE_OK +** normally. SQLITE_NOMEM is returned if we are unable to allocate +** memory. +*/ +int sqlite3VdbeFifoPush(Fifo *pFifo, i64 val){ + FifoPage *pPage; + pPage = pFifo->pLast; + if( pPage==0 ){ + pPage = pFifo->pLast = pFifo->pFirst = + allocateFifoPage(pFifo->db, FIFOSIZE_FIRST); + if( pPage==0 ){ + return SQLITE_NOMEM; + } + }else if( pPage->iWrite>=pPage->nSlot ){ + pPage->pNext = allocateFifoPage(pFifo->db, pFifo->nEntry); + if( pPage->pNext==0 ){ + return SQLITE_NOMEM; + } + pPage = pFifo->pLast = pPage->pNext; + } + pPage->aSlot[pPage->iWrite++] = val; + pFifo->nEntry++; + return SQLITE_OK; +} + +/* +** Extract a single 64-bit integer value from the Fifo. The integer +** extracted is the one least recently inserted. If the Fifo is empty +** return SQLITE_DONE. +*/ +int sqlite3VdbeFifoPop(Fifo *pFifo, i64 *pVal){ + FifoPage *pPage; + if( pFifo->nEntry==0 ){ + return SQLITE_DONE; + } + assert( pFifo->nEntry>0 ); + pPage = pFifo->pFirst; + assert( pPage!=0 ); + assert( pPage->iWrite>pPage->iRead ); + assert( pPage->iWrite<=pPage->nSlot ); + assert( pPage->iRead<pPage->nSlot ); + assert( pPage->iRead>=0 ); + *pVal = pPage->aSlot[pPage->iRead++]; + pFifo->nEntry--; + if( pPage->iRead>=pPage->iWrite ){ + pFifo->pFirst = pPage->pNext; + sqlite3DbFree(pFifo->db, pPage); + if( pFifo->nEntry==0 ){ + assert( pFifo->pLast==pPage ); + pFifo->pLast = 0; + }else{ + assert( pFifo->pFirst!=0 ); + } + }else{ + assert( pFifo->nEntry>0 ); + } + return SQLITE_OK; +} + +/* +** Delete all information from a Fifo object. Free all memory held +** by the Fifo. +*/ +void sqlite3VdbeFifoClear(Fifo *pFifo){ + FifoPage *pPage, *pNextPage; + for(pPage=pFifo->pFirst; pPage; pPage=pNextPage){ + pNextPage = pPage->pNext; + sqlite3DbFree(pFifo->db, pPage); + } + sqlite3VdbeFifoInit(pFifo, pFifo->db); +} diff --git a/third_party/sqlite/src/vdbemem.c b/third_party/sqlite/src/vdbemem.c new file mode 100755 index 0000000..8b94e3e --- /dev/null +++ b/third_party/sqlite/src/vdbemem.c @@ -0,0 +1,1044 @@ +/* +** 2004 May 26 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file contains code use to manipulate "Mem" structure. A "Mem" +** stores a single value in the VDBE. Mem is an opaque structure visible +** only within the VDBE. Interface routines refer to a Mem using the +** name sqlite_value +** +** $Id: vdbemem.c,v 1.121 2008/08/01 20:10:09 drh Exp $ +*/ +#include "sqliteInt.h" +#include <ctype.h> +#include "vdbeInt.h" + +/* +** Call sqlite3VdbeMemExpandBlob() on the supplied value (type Mem*) +** P if required. +*/ +#define expandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0) + +/* +** If pMem is an object with a valid string representation, this routine +** ensures the internal encoding for the string representation is +** 'desiredEnc', one of SQLITE_UTF8, SQLITE_UTF16LE or SQLITE_UTF16BE. +** +** If pMem is not a string object, or the encoding of the string +** representation is already stored using the requested encoding, then this +** routine is a no-op. +** +** SQLITE_OK is returned if the conversion is successful (or not required). +** SQLITE_NOMEM may be returned if a malloc() fails during conversion +** between formats. +*/ +int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){ + int rc; + if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){ + return SQLITE_OK; + } + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); +#ifdef SQLITE_OMIT_UTF16 + return SQLITE_ERROR; +#else + + /* MemTranslate() may return SQLITE_OK or SQLITE_NOMEM. If NOMEM is returned, + ** then the encoding of the value may not have changed. + */ + rc = sqlite3VdbeMemTranslate(pMem, desiredEnc); + assert(rc==SQLITE_OK || rc==SQLITE_NOMEM); + assert(rc==SQLITE_OK || pMem->enc!=desiredEnc); + assert(rc==SQLITE_NOMEM || pMem->enc==desiredEnc); + return rc; +#endif +} + +/* +** Make sure pMem->z points to a writable allocation of at least +** n bytes. +** +** If the memory cell currently contains string or blob data +** and the third argument passed to this function is true, the +** current content of the cell is preserved. Otherwise, it may +** be discarded. +** +** This function sets the MEM_Dyn flag and clears any xDel callback. +** It also clears MEM_Ephem and MEM_Static. If the preserve flag is +** not set, Mem.n is zeroed. +*/ +int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){ + assert( 1 >= + ((pMem->zMalloc && pMem->zMalloc==pMem->z) ? 1 : 0) + + (((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) + + ((pMem->flags&MEM_Ephem) ? 1 : 0) + + ((pMem->flags&MEM_Static) ? 1 : 0) + ); + + if( n<32 ) n = 32; + if( sqlite3DbMallocSize(pMem->db, pMem->zMalloc)<n ){ + if( preserve && pMem->z==pMem->zMalloc ){ + pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n); + if( !pMem->z ){ + pMem->flags = MEM_Null; + } + preserve = 0; + }else{ + sqlite3DbFree(pMem->db, pMem->zMalloc); + pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n); + } + } + + if( preserve && pMem->z && pMem->zMalloc && pMem->z!=pMem->zMalloc ){ + memcpy(pMem->zMalloc, pMem->z, pMem->n); + } + if( pMem->flags&MEM_Dyn && pMem->xDel ){ + pMem->xDel((void *)(pMem->z)); + } + + pMem->z = pMem->zMalloc; + pMem->flags &= ~(MEM_Ephem|MEM_Static); + pMem->xDel = 0; + return (pMem->z ? SQLITE_OK : SQLITE_NOMEM); +} + +/* +** Make the given Mem object MEM_Dyn. In other words, make it so +** that any TEXT or BLOB content is stored in memory obtained from +** malloc(). In this way, we know that the memory is safe to be +** overwritten or altered. +** +** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails. +*/ +int sqlite3VdbeMemMakeWriteable(Mem *pMem){ + int f; + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + expandBlob(pMem); + f = pMem->flags; + if( (f&(MEM_Str|MEM_Blob)) && pMem->z!=pMem->zMalloc ){ + if( sqlite3VdbeMemGrow(pMem, pMem->n + 2, 1) ){ + return SQLITE_NOMEM; + } + pMem->z[pMem->n] = 0; + pMem->z[pMem->n+1] = 0; + pMem->flags |= MEM_Term; + } + + return SQLITE_OK; +} + +/* +** If the given Mem* has a zero-filled tail, turn it into an ordinary +** blob stored in dynamically allocated space. +*/ +#ifndef SQLITE_OMIT_INCRBLOB +int sqlite3VdbeMemExpandBlob(Mem *pMem){ + if( pMem->flags & MEM_Zero ){ + int nByte; + assert( pMem->flags&MEM_Blob ); + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + + /* Set nByte to the number of bytes required to store the expanded blob. */ + nByte = pMem->n + pMem->u.i; + if( nByte<=0 ){ + nByte = 1; + } + if( sqlite3VdbeMemGrow(pMem, nByte, 1) ){ + return SQLITE_NOMEM; + } + + memset(&pMem->z[pMem->n], 0, pMem->u.i); + pMem->n += pMem->u.i; + pMem->flags &= ~(MEM_Zero|MEM_Term); + } + return SQLITE_OK; +} +#endif + + +/* +** Make sure the given Mem is \u0000 terminated. +*/ +int sqlite3VdbeMemNulTerminate(Mem *pMem){ + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + if( (pMem->flags & MEM_Term)!=0 || (pMem->flags & MEM_Str)==0 ){ + return SQLITE_OK; /* Nothing to do */ + } + if( sqlite3VdbeMemGrow(pMem, pMem->n+2, 1) ){ + return SQLITE_NOMEM; + } + pMem->z[pMem->n] = 0; + pMem->z[pMem->n+1] = 0; + pMem->flags |= MEM_Term; + return SQLITE_OK; +} + +/* +** Add MEM_Str to the set of representations for the given Mem. Numbers +** are converted using sqlite3_snprintf(). Converting a BLOB to a string +** is a no-op. +** +** Existing representations MEM_Int and MEM_Real are *not* invalidated. +** +** A MEM_Null value will never be passed to this function. This function is +** used for converting values to text for returning to the user (i.e. via +** sqlite3_value_text()), or for ensuring that values to be used as btree +** keys are strings. In the former case a NULL pointer is returned the +** user and the later is an internal programming error. +*/ +int sqlite3VdbeMemStringify(Mem *pMem, int enc){ + int rc = SQLITE_OK; + int fg = pMem->flags; + const int nByte = 32; + + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + assert( !(fg&MEM_Zero) ); + assert( !(fg&(MEM_Str|MEM_Blob)) ); + assert( fg&(MEM_Int|MEM_Real) ); + + if( sqlite3VdbeMemGrow(pMem, nByte, 0) ){ + return SQLITE_NOMEM; + } + + /* For a Real or Integer, use sqlite3_mprintf() to produce the UTF-8 + ** string representation of the value. Then, if the required encoding + ** is UTF-16le or UTF-16be do a translation. + ** + ** FIX ME: It would be better if sqlite3_snprintf() could do UTF-16. + */ + if( fg & MEM_Int ){ + sqlite3_snprintf(nByte, pMem->z, "%lld", pMem->u.i); + }else{ + assert( fg & MEM_Real ); + sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->r); + } + pMem->n = strlen(pMem->z); + pMem->enc = SQLITE_UTF8; + pMem->flags |= MEM_Str|MEM_Term; + sqlite3VdbeChangeEncoding(pMem, enc); + return rc; +} + +/* +** Memory cell pMem contains the context of an aggregate function. +** This routine calls the finalize method for that function. The +** result of the aggregate is stored back into pMem. +** +** Return SQLITE_ERROR if the finalizer reports an error. SQLITE_OK +** otherwise. +*/ +int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){ + int rc = SQLITE_OK; + if( pFunc && pFunc->xFinalize ){ + sqlite3_context ctx; + assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef ); + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + ctx.s.flags = MEM_Null; + ctx.s.db = pMem->db; + ctx.s.zMalloc = 0; + ctx.pMem = pMem; + ctx.pFunc = pFunc; + ctx.isError = 0; + pFunc->xFinalize(&ctx); + assert( 0==(pMem->flags&MEM_Dyn) && !pMem->xDel ); + sqlite3DbFree(pMem->db, pMem->zMalloc); + *pMem = ctx.s; + rc = (ctx.isError?SQLITE_ERROR:SQLITE_OK); + } + return rc; +} + +/* +** If the memory cell contains a string value that must be freed by +** invoking an external callback, free it now. Calling this function +** does not free any Mem.zMalloc buffer. +*/ +void sqlite3VdbeMemReleaseExternal(Mem *p){ + assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) ); + if( p->flags&MEM_Agg ){ + sqlite3VdbeMemFinalize(p, p->u.pDef); + assert( (p->flags & MEM_Agg)==0 ); + sqlite3VdbeMemRelease(p); + }else if( p->flags&MEM_Dyn && p->xDel ){ + p->xDel((void *)p->z); + p->xDel = 0; + } +} + +/* +** Release any memory held by the Mem. This may leave the Mem in an +** inconsistent state, for example with (Mem.z==0) and +** (Mem.type==SQLITE_TEXT). +*/ +void sqlite3VdbeMemRelease(Mem *p){ + sqlite3VdbeMemReleaseExternal(p); + sqlite3DbFree(p->db, p->zMalloc); + p->z = 0; + p->zMalloc = 0; + p->xDel = 0; +} + +/* +** Convert a 64-bit IEEE double into a 64-bit signed integer. +** If the double is too large, return 0x8000000000000000. +** +** Most systems appear to do this simply by assigning +** variables and without the extra range tests. But +** there are reports that windows throws an expection +** if the floating point value is out of range. (See ticket #2880.) +** Because we do not completely understand the problem, we will +** take the conservative approach and always do range tests +** before attempting the conversion. +*/ +static i64 doubleToInt64(double r){ + /* + ** Many compilers we encounter do not define constants for the + ** minimum and maximum 64-bit integers, or they define them + ** inconsistently. And many do not understand the "LL" notation. + ** So we define our own static constants here using nothing + ** larger than a 32-bit integer constant. + */ + static const i64 maxInt = LARGEST_INT64; + static const i64 minInt = SMALLEST_INT64; + + if( r<(double)minInt ){ + return minInt; + }else if( r>(double)maxInt ){ + return minInt; + }else{ + return (i64)r; + } +} + +/* +** Return some kind of integer value which is the best we can do +** at representing the value that *pMem describes as an integer. +** If pMem is an integer, then the value is exact. If pMem is +** a floating-point then the value returned is the integer part. +** If pMem is a string or blob, then we make an attempt to convert +** it into a integer and return that. If pMem is NULL, return 0. +** +** If pMem is a string, its encoding might be changed. +*/ +i64 sqlite3VdbeIntValue(Mem *pMem){ + int flags; + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + flags = pMem->flags; + if( flags & MEM_Int ){ + return pMem->u.i; + }else if( flags & MEM_Real ){ + return doubleToInt64(pMem->r); + }else if( flags & (MEM_Str|MEM_Blob) ){ + i64 value; + pMem->flags |= MEM_Str; + if( sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8) + || sqlite3VdbeMemNulTerminate(pMem) ){ + return 0; + } + assert( pMem->z ); + sqlite3Atoi64(pMem->z, &value); + return value; + }else{ + return 0; + } +} + +/* +** Return the best representation of pMem that we can get into a +** double. If pMem is already a double or an integer, return its +** value. If it is a string or blob, try to convert it to a double. +** If it is a NULL, return 0.0. +*/ +double sqlite3VdbeRealValue(Mem *pMem){ + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + if( pMem->flags & MEM_Real ){ + return pMem->r; + }else if( pMem->flags & MEM_Int ){ + return (double)pMem->u.i; + }else if( pMem->flags & (MEM_Str|MEM_Blob) ){ + double val = 0.0; + pMem->flags |= MEM_Str; + if( sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8) + || sqlite3VdbeMemNulTerminate(pMem) ){ + return 0.0; + } + assert( pMem->z ); + sqlite3AtoF(pMem->z, &val); + return val; + }else{ + return 0.0; + } +} + +/* +** The MEM structure is already a MEM_Real. Try to also make it a +** MEM_Int if we can. +*/ +void sqlite3VdbeIntegerAffinity(Mem *pMem){ + assert( pMem->flags & MEM_Real ); + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + + pMem->u.i = doubleToInt64(pMem->r); + if( pMem->r==(double)pMem->u.i ){ + pMem->flags |= MEM_Int; + } +} + +static void setTypeFlag(Mem *pMem, int f){ + MemSetTypeFlag(pMem, f); +} + +/* +** Convert pMem to type integer. Invalidate any prior representations. +*/ +int sqlite3VdbeMemIntegerify(Mem *pMem){ + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + pMem->u.i = sqlite3VdbeIntValue(pMem); + setTypeFlag(pMem, MEM_Int); + return SQLITE_OK; +} + +/* +** Convert pMem so that it is of type MEM_Real. +** Invalidate any prior representations. +*/ +int sqlite3VdbeMemRealify(Mem *pMem){ + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + pMem->r = sqlite3VdbeRealValue(pMem); + setTypeFlag(pMem, MEM_Real); + return SQLITE_OK; +} + +/* +** Convert pMem so that it has types MEM_Real or MEM_Int or both. +** Invalidate any prior representations. +*/ +int sqlite3VdbeMemNumerify(Mem *pMem){ + double r1, r2; + i64 i; + assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ); + assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 ); + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + r1 = sqlite3VdbeRealValue(pMem); + i = doubleToInt64(r1); + r2 = (double)i; + if( r1==r2 ){ + sqlite3VdbeMemIntegerify(pMem); + }else{ + pMem->r = r1; + setTypeFlag(pMem, MEM_Real); + } + return SQLITE_OK; +} + +/* +** Delete any previous value and set the value stored in *pMem to NULL. +*/ +void sqlite3VdbeMemSetNull(Mem *pMem){ + setTypeFlag(pMem, MEM_Null); + pMem->type = SQLITE_NULL; +} + +/* +** Delete any previous value and set the value to be a BLOB of length +** n containing all zeros. +*/ +void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){ + sqlite3VdbeMemRelease(pMem); + setTypeFlag(pMem, MEM_Blob); + pMem->flags = MEM_Blob|MEM_Zero; + pMem->type = SQLITE_BLOB; + pMem->n = 0; + if( n<0 ) n = 0; + pMem->u.i = n; + pMem->enc = SQLITE_UTF8; +} + +/* +** Delete any previous value and set the value stored in *pMem to val, +** manifest type INTEGER. +*/ +void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){ + sqlite3VdbeMemRelease(pMem); + pMem->u.i = val; + pMem->flags = MEM_Int; + pMem->type = SQLITE_INTEGER; +} + +/* +** Delete any previous value and set the value stored in *pMem to val, +** manifest type REAL. +*/ +void sqlite3VdbeMemSetDouble(Mem *pMem, double val){ + if( sqlite3IsNaN(val) ){ + sqlite3VdbeMemSetNull(pMem); + }else{ + sqlite3VdbeMemRelease(pMem); + pMem->r = val; + pMem->flags = MEM_Real; + pMem->type = SQLITE_FLOAT; + } +} + +/* +** Return true if the Mem object contains a TEXT or BLOB that is +** too large - whose size exceeds SQLITE_MAX_LENGTH. +*/ +int sqlite3VdbeMemTooBig(Mem *p){ + assert( p->db!=0 ); + if( p->flags & (MEM_Str|MEM_Blob) ){ + int n = p->n; + if( p->flags & MEM_Zero ){ + n += p->u.i; + } + return n>p->db->aLimit[SQLITE_LIMIT_LENGTH]; + } + return 0; +} + +/* +** Size of struct Mem not including the Mem.zMalloc member. +*/ +#define MEMCELLSIZE (size_t)(&(((Mem *)0)->zMalloc)) + +/* +** Make an shallow copy of pFrom into pTo. Prior contents of +** pTo are freed. The pFrom->z field is not duplicated. If +** pFrom->z is used, then pTo->z points to the same thing as pFrom->z +** and flags gets srcType (either MEM_Ephem or MEM_Static). +*/ +void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){ + sqlite3VdbeMemReleaseExternal(pTo); + memcpy(pTo, pFrom, MEMCELLSIZE); + pTo->xDel = 0; + if( (pFrom->flags&MEM_Dyn)!=0 || pFrom->z==pFrom->zMalloc ){ + pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem); + assert( srcType==MEM_Ephem || srcType==MEM_Static ); + pTo->flags |= srcType; + } +} + +/* +** Make a full copy of pFrom into pTo. Prior contents of pTo are +** freed before the copy is made. +*/ +int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){ + int rc = SQLITE_OK; + + sqlite3VdbeMemReleaseExternal(pTo); + memcpy(pTo, pFrom, MEMCELLSIZE); + pTo->flags &= ~MEM_Dyn; + + if( pTo->flags&(MEM_Str|MEM_Blob) ){ + if( 0==(pFrom->flags&MEM_Static) ){ + pTo->flags |= MEM_Ephem; + rc = sqlite3VdbeMemMakeWriteable(pTo); + } + } + + return rc; +} + +/* +** Transfer the contents of pFrom to pTo. Any existing value in pTo is +** freed. If pFrom contains ephemeral data, a copy is made. +** +** pFrom contains an SQL NULL when this routine returns. +*/ +void sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){ + assert( pFrom->db==0 || sqlite3_mutex_held(pFrom->db->mutex) ); + assert( pTo->db==0 || sqlite3_mutex_held(pTo->db->mutex) ); + assert( pFrom->db==0 || pTo->db==0 || pFrom->db==pTo->db ); + + sqlite3VdbeMemRelease(pTo); + memcpy(pTo, pFrom, sizeof(Mem)); + pFrom->flags = MEM_Null; + pFrom->xDel = 0; + pFrom->zMalloc = 0; +} + +/* +** Change the value of a Mem to be a string or a BLOB. +** +** The memory management strategy depends on the value of the xDel +** parameter. If the value passed is SQLITE_TRANSIENT, then the +** string is copied into a (possibly existing) buffer managed by the +** Mem structure. Otherwise, any existing buffer is freed and the +** pointer copied. +*/ +int sqlite3VdbeMemSetStr( + Mem *pMem, /* Memory cell to set to string value */ + const char *z, /* String pointer */ + int n, /* Bytes in string, or negative */ + u8 enc, /* Encoding of z. 0 for BLOBs */ + void (*xDel)(void*) /* Destructor function */ +){ + int nByte = n; /* New value for pMem->n */ + int iLimit; /* Maximum allowed string or blob size */ + int flags = 0; /* New value for pMem->flags */ + + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + + /* If z is a NULL pointer, set pMem to contain an SQL NULL. */ + if( !z ){ + sqlite3VdbeMemSetNull(pMem); + return SQLITE_OK; + } + + if( pMem->db ){ + iLimit = pMem->db->aLimit[SQLITE_LIMIT_LENGTH]; + }else{ + iLimit = SQLITE_MAX_LENGTH; + } + flags = (enc==0?MEM_Blob:MEM_Str); + if( nByte<0 ){ + assert( enc!=0 ); + if( enc==SQLITE_UTF8 ){ + for(nByte=0; nByte<=iLimit && z[nByte]; nByte++){} + }else{ + for(nByte=0; nByte<=iLimit && (z[nByte] | z[nByte+1]); nByte+=2){} + } + flags |= MEM_Term; + } + if( nByte>iLimit ){ + return SQLITE_TOOBIG; + } + + /* The following block sets the new values of Mem.z and Mem.xDel. It + ** also sets a flag in local variable "flags" to indicate the memory + ** management (one of MEM_Dyn or MEM_Static). + */ + if( xDel==SQLITE_TRANSIENT ){ + int nAlloc = nByte; + if( flags&MEM_Term ){ + nAlloc += (enc==SQLITE_UTF8?1:2); + } + if( sqlite3VdbeMemGrow(pMem, nAlloc, 0) ){ + return SQLITE_NOMEM; + } + memcpy(pMem->z, z, nAlloc); + }else if( xDel==SQLITE_DYNAMIC ){ + sqlite3VdbeMemRelease(pMem); + pMem->zMalloc = pMem->z = (char *)z; + pMem->xDel = 0; + }else{ + sqlite3VdbeMemRelease(pMem); + pMem->z = (char *)z; + pMem->xDel = xDel; + flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn); + } + + pMem->n = nByte; + pMem->flags = flags; + pMem->enc = (enc==0 ? SQLITE_UTF8 : enc); + pMem->type = (enc==0 ? SQLITE_BLOB : SQLITE_TEXT); + +#ifndef SQLITE_OMIT_UTF16 + if( pMem->enc!=SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){ + return SQLITE_NOMEM; + } +#endif + + return SQLITE_OK; +} + +/* +** Compare the values contained by the two memory cells, returning +** negative, zero or positive if pMem1 is less than, equal to, or greater +** than pMem2. Sorting order is NULL's first, followed by numbers (integers +** and reals) sorted numerically, followed by text ordered by the collating +** sequence pColl and finally blob's ordered by memcmp(). +** +** Two NULL values are considered equal by this function. +*/ +int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){ + int rc; + int f1, f2; + int combined_flags; + + /* Interchange pMem1 and pMem2 if the collating sequence specifies + ** DESC order. + */ + f1 = pMem1->flags; + f2 = pMem2->flags; + combined_flags = f1|f2; + + /* If one value is NULL, it is less than the other. If both values + ** are NULL, return 0. + */ + if( combined_flags&MEM_Null ){ + return (f2&MEM_Null) - (f1&MEM_Null); + } + + /* If one value is a number and the other is not, the number is less. + ** If both are numbers, compare as reals if one is a real, or as integers + ** if both values are integers. + */ + if( combined_flags&(MEM_Int|MEM_Real) ){ + if( !(f1&(MEM_Int|MEM_Real)) ){ + return 1; + } + if( !(f2&(MEM_Int|MEM_Real)) ){ + return -1; + } + if( (f1 & f2 & MEM_Int)==0 ){ + double r1, r2; + if( (f1&MEM_Real)==0 ){ + r1 = pMem1->u.i; + }else{ + r1 = pMem1->r; + } + if( (f2&MEM_Real)==0 ){ + r2 = pMem2->u.i; + }else{ + r2 = pMem2->r; + } + if( r1<r2 ) return -1; + if( r1>r2 ) return 1; + return 0; + }else{ + assert( f1&MEM_Int ); + assert( f2&MEM_Int ); + if( pMem1->u.i < pMem2->u.i ) return -1; + if( pMem1->u.i > pMem2->u.i ) return 1; + return 0; + } + } + + /* If one value is a string and the other is a blob, the string is less. + ** If both are strings, compare using the collating functions. + */ + if( combined_flags&MEM_Str ){ + if( (f1 & MEM_Str)==0 ){ + return 1; + } + if( (f2 & MEM_Str)==0 ){ + return -1; + } + + assert( pMem1->enc==pMem2->enc ); + assert( pMem1->enc==SQLITE_UTF8 || + pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE ); + + /* The collation sequence must be defined at this point, even if + ** the user deletes the collation sequence after the vdbe program is + ** compiled (this was not always the case). + */ + assert( !pColl || pColl->xCmp ); + + if( pColl ){ + if( pMem1->enc==pColl->enc ){ + /* The strings are already in the correct encoding. Call the + ** comparison function directly */ + return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z); + }else{ + u8 origEnc = pMem1->enc; + const void *v1, *v2; + int n1, n2; + /* Convert the strings into the encoding that the comparison + ** function expects */ + v1 = sqlite3ValueText((sqlite3_value*)pMem1, pColl->enc); + n1 = v1==0 ? 0 : pMem1->n; + assert( n1==sqlite3ValueBytes((sqlite3_value*)pMem1, pColl->enc) ); + v2 = sqlite3ValueText((sqlite3_value*)pMem2, pColl->enc); + n2 = v2==0 ? 0 : pMem2->n; + assert( n2==sqlite3ValueBytes((sqlite3_value*)pMem2, pColl->enc) ); + /* Do the comparison */ + rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2); + /* Convert the strings back into the database encoding */ + sqlite3ValueText((sqlite3_value*)pMem1, origEnc); + sqlite3ValueText((sqlite3_value*)pMem2, origEnc); + return rc; + } + } + /* If a NULL pointer was passed as the collate function, fall through + ** to the blob case and use memcmp(). */ + } + + /* Both values must be blobs. Compare using memcmp(). */ + rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n); + if( rc==0 ){ + rc = pMem1->n - pMem2->n; + } + return rc; +} + +/* +** Move data out of a btree key or data field and into a Mem structure. +** The data or key is taken from the entry that pCur is currently pointing +** to. offset and amt determine what portion of the data or key to retrieve. +** key is true to get the key or false to get data. The result is written +** into the pMem element. +** +** The pMem structure is assumed to be uninitialized. Any prior content +** is overwritten without being freed. +** +** If this routine fails for any reason (malloc returns NULL or unable +** to read from the disk) then the pMem is left in an inconsistent state. +*/ +int sqlite3VdbeMemFromBtree( + BtCursor *pCur, /* Cursor pointing at record to retrieve. */ + int offset, /* Offset from the start of data to return bytes from. */ + int amt, /* Number of bytes to return. */ + int key, /* If true, retrieve from the btree key, not data. */ + Mem *pMem /* OUT: Return data in this Mem structure. */ +){ + char *zData; /* Data from the btree layer */ + int available = 0; /* Number of bytes available on the local btree page */ + sqlite3 *db; /* Database connection */ + int rc = SQLITE_OK; + + db = sqlite3BtreeCursorDb(pCur); + assert( sqlite3_mutex_held(db->mutex) ); + if( key ){ + zData = (char *)sqlite3BtreeKeyFetch(pCur, &available); + }else{ + zData = (char *)sqlite3BtreeDataFetch(pCur, &available); + } + assert( zData!=0 ); + + if( offset+amt<=available && ((pMem->flags&MEM_Dyn)==0 || pMem->xDel) ){ + sqlite3VdbeMemRelease(pMem); + pMem->z = &zData[offset]; + pMem->flags = MEM_Blob|MEM_Ephem; + }else if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){ + pMem->flags = MEM_Blob|MEM_Dyn|MEM_Term; + pMem->enc = 0; + pMem->type = SQLITE_BLOB; + if( key ){ + rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z); + }else{ + rc = sqlite3BtreeData(pCur, offset, amt, pMem->z); + } + pMem->z[amt] = 0; + pMem->z[amt+1] = 0; + if( rc!=SQLITE_OK ){ + sqlite3VdbeMemRelease(pMem); + } + } + pMem->n = amt; + + return rc; +} + +#if 0 +/* +** Perform various checks on the memory cell pMem. An assert() will +** fail if pMem is internally inconsistent. +*/ +void sqlite3VdbeMemSanity(Mem *pMem){ + int flags = pMem->flags; + assert( flags!=0 ); /* Must define some type */ + if( flags & (MEM_Str|MEM_Blob) ){ + int x = flags & (MEM_Static|MEM_Dyn|MEM_Ephem|MEM_Short); + assert( x!=0 ); /* Strings must define a string subtype */ + assert( (x & (x-1))==0 ); /* Only one string subtype can be defined */ + assert( pMem->z!=0 ); /* Strings must have a value */ + /* Mem.z points to Mem.zShort iff the subtype is MEM_Short */ + assert( (x & MEM_Short)==0 || pMem->z==pMem->zShort ); + assert( (x & MEM_Short)!=0 || pMem->z!=pMem->zShort ); + /* No destructor unless there is MEM_Dyn */ + assert( pMem->xDel==0 || (pMem->flags & MEM_Dyn)!=0 ); + + if( (flags & MEM_Str) ){ + assert( pMem->enc==SQLITE_UTF8 || + pMem->enc==SQLITE_UTF16BE || + pMem->enc==SQLITE_UTF16LE + ); + /* If the string is UTF-8 encoded and nul terminated, then pMem->n + ** must be the length of the string. (Later:) If the database file + ** has been corrupted, '\000' characters might have been inserted + ** into the middle of the string. In that case, the strlen() might + ** be less. + */ + if( pMem->enc==SQLITE_UTF8 && (flags & MEM_Term) ){ + assert( strlen(pMem->z)<=pMem->n ); + assert( pMem->z[pMem->n]==0 ); + } + } + }else{ + /* Cannot define a string subtype for non-string objects */ + assert( (pMem->flags & (MEM_Static|MEM_Dyn|MEM_Ephem|MEM_Short))==0 ); + assert( pMem->xDel==0 ); + } + /* MEM_Null excludes all other types */ + assert( (pMem->flags&(MEM_Str|MEM_Int|MEM_Real|MEM_Blob))==0 + || (pMem->flags&MEM_Null)==0 ); + /* If the MEM is both real and integer, the values are equal */ + assert( (pMem->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real) + || pMem->r==pMem->u.i ); +} +#endif + +/* This function is only available internally, it is not part of the +** external API. It works in a similar way to sqlite3_value_text(), +** except the data returned is in the encoding specified by the second +** parameter, which must be one of SQLITE_UTF16BE, SQLITE_UTF16LE or +** SQLITE_UTF8. +** +** (2006-02-16:) The enc value can be or-ed with SQLITE_UTF16_ALIGNED. +** If that is the case, then the result must be aligned on an even byte +** boundary. +*/ +const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){ + if( !pVal ) return 0; + + assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) ); + assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) ); + + if( pVal->flags&MEM_Null ){ + return 0; + } + assert( (MEM_Blob>>3) == MEM_Str ); + pVal->flags |= (pVal->flags & MEM_Blob)>>3; + expandBlob(pVal); + if( pVal->flags&MEM_Str ){ + sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED); + if( (enc & SQLITE_UTF16_ALIGNED)!=0 && 1==(1&SQLITE_PTR_TO_INT(pVal->z)) ){ + assert( (pVal->flags & (MEM_Ephem|MEM_Static))!=0 ); + if( sqlite3VdbeMemMakeWriteable(pVal)!=SQLITE_OK ){ + return 0; + } + } + sqlite3VdbeMemNulTerminate(pVal); + }else{ + assert( (pVal->flags&MEM_Blob)==0 ); + sqlite3VdbeMemStringify(pVal, enc); + assert( 0==(1&(int)pVal->z) ); + } + assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || pVal->db==0 + || pVal->db->mallocFailed ); + if( pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) ){ + return pVal->z; + }else{ + return 0; + } +} + +/* +** Create a new sqlite3_value object. +*/ +sqlite3_value *sqlite3ValueNew(sqlite3 *db){ + Mem *p = sqlite3DbMallocZero(db, sizeof(*p)); + if( p ){ + p->flags = MEM_Null; + p->type = SQLITE_NULL; + p->db = db; + } + return p; +} + +/* +** Create a new sqlite3_value object, containing the value of pExpr. +** +** This only works for very simple expressions that consist of one constant +** token (i.e. "5", "5.1", "'a string'"). If the expression can +** be converted directly into a value, then the value is allocated and +** a pointer written to *ppVal. The caller is responsible for deallocating +** the value by passing it to sqlite3ValueFree() later on. If the expression +** cannot be converted to a value, then *ppVal is set to NULL. +*/ +int sqlite3ValueFromExpr( + sqlite3 *db, /* The database connection */ + Expr *pExpr, /* The expression to evaluate */ + u8 enc, /* Encoding to use */ + u8 affinity, /* Affinity to use */ + sqlite3_value **ppVal /* Write the new value here */ +){ + int op; + char *zVal = 0; + sqlite3_value *pVal = 0; + + if( !pExpr ){ + *ppVal = 0; + return SQLITE_OK; + } + op = pExpr->op; + + if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){ + zVal = sqlite3DbStrNDup(db, (char*)pExpr->token.z, pExpr->token.n); + pVal = sqlite3ValueNew(db); + if( !zVal || !pVal ) goto no_mem; + sqlite3Dequote(zVal); + sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC); + if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){ + sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, enc); + }else{ + sqlite3ValueApplyAffinity(pVal, affinity, enc); + } + }else if( op==TK_UMINUS ) { + if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal) ){ + pVal->u.i = -1 * pVal->u.i; + pVal->r = -1.0 * pVal->r; + } + } +#ifndef SQLITE_OMIT_BLOB_LITERAL + else if( op==TK_BLOB ){ + int nVal; + assert( pExpr->token.n>=3 ); + assert( pExpr->token.z[0]=='x' || pExpr->token.z[0]=='X' ); + assert( pExpr->token.z[1]=='\'' ); + assert( pExpr->token.z[pExpr->token.n-1]=='\'' ); + pVal = sqlite3ValueNew(db); + nVal = pExpr->token.n - 3; + zVal = (char*)pExpr->token.z + 2; + sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2, + 0, SQLITE_DYNAMIC); + } +#endif + + *ppVal = pVal; + return SQLITE_OK; + +no_mem: + db->mallocFailed = 1; + sqlite3DbFree(db, zVal); + sqlite3ValueFree(pVal); + *ppVal = 0; + return SQLITE_NOMEM; +} + +/* +** Change the string value of an sqlite3_value object +*/ +void sqlite3ValueSetStr( + sqlite3_value *v, /* Value to be set */ + int n, /* Length of string z */ + const void *z, /* Text of the new string */ + u8 enc, /* Encoding to use */ + void (*xDel)(void*) /* Destructor for the string */ +){ + if( v ) sqlite3VdbeMemSetStr((Mem *)v, z, n, enc, xDel); +} + +/* +** Free an sqlite3_value object +*/ +void sqlite3ValueFree(sqlite3_value *v){ + if( !v ) return; + sqlite3VdbeMemRelease((Mem *)v); + sqlite3DbFree(((Mem*)v)->db, v); +} + +/* +** Return the number of bytes in the sqlite3_value object assuming +** that it uses the encoding "enc" +*/ +int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){ + Mem *p = (Mem*)pVal; + if( (p->flags & MEM_Blob)!=0 || sqlite3ValueText(pVal, enc) ){ + if( p->flags & MEM_Zero ){ + return p->n+p->u.i; + }else{ + return p->n; + } + } + return 0; +} diff --git a/third_party/sqlite/src/vtab.c b/third_party/sqlite/src/vtab.c new file mode 100755 index 0000000..bd18c479 --- /dev/null +++ b/third_party/sqlite/src/vtab.c @@ -0,0 +1,838 @@ +/* +** 2006 June 10 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains code used to help implement virtual tables. +** +** $Id: vtab.c,v 1.74 2008/08/02 03:50:39 drh Exp $ +*/ +#ifndef SQLITE_OMIT_VIRTUALTABLE +#include "sqliteInt.h" + +static int createModule( + sqlite3 *db, /* Database in which module is registered */ + const char *zName, /* Name assigned to this module */ + const sqlite3_module *pModule, /* The definition of the module */ + void *pAux, /* Context pointer for xCreate/xConnect */ + void (*xDestroy)(void *) /* Module destructor function */ +) { + int rc, nName; + Module *pMod; + + sqlite3_mutex_enter(db->mutex); + nName = strlen(zName); + pMod = (Module *)sqlite3DbMallocRaw(db, sizeof(Module) + nName + 1); + if( pMod ){ + Module *pDel; + char *zCopy = (char *)(&pMod[1]); + memcpy(zCopy, zName, nName+1); + pMod->zName = zCopy; + pMod->pModule = pModule; + pMod->pAux = pAux; + pMod->xDestroy = xDestroy; + pDel = (Module *)sqlite3HashInsert(&db->aModule, zCopy, nName, (void*)pMod); + if( pDel && pDel->xDestroy ){ + pDel->xDestroy(pDel->pAux); + } + sqlite3DbFree(db, pDel); + if( pDel==pMod ){ + db->mallocFailed = 1; + } + sqlite3ResetInternalSchema(db, 0); + } + rc = sqlite3ApiExit(db, SQLITE_OK); + sqlite3_mutex_leave(db->mutex); + return rc; +} + + +/* +** External API function used to create a new virtual-table module. +*/ +int sqlite3_create_module( + sqlite3 *db, /* Database in which module is registered */ + const char *zName, /* Name assigned to this module */ + const sqlite3_module *pModule, /* The definition of the module */ + void *pAux /* Context pointer for xCreate/xConnect */ +){ + return createModule(db, zName, pModule, pAux, 0); +} + +/* +** External API function used to create a new virtual-table module. +*/ +int sqlite3_create_module_v2( + sqlite3 *db, /* Database in which module is registered */ + const char *zName, /* Name assigned to this module */ + const sqlite3_module *pModule, /* The definition of the module */ + void *pAux, /* Context pointer for xCreate/xConnect */ + void (*xDestroy)(void *) /* Module destructor function */ +){ + return createModule(db, zName, pModule, pAux, xDestroy); +} + +/* +** Lock the virtual table so that it cannot be disconnected. +** Locks nest. Every lock should have a corresponding unlock. +** If an unlock is omitted, resources leaks will occur. +** +** If a disconnect is attempted while a virtual table is locked, +** the disconnect is deferred until all locks have been removed. +*/ +void sqlite3VtabLock(sqlite3_vtab *pVtab){ + pVtab->nRef++; +} + +/* +** Unlock a virtual table. When the last lock is removed, +** disconnect the virtual table. +*/ +void sqlite3VtabUnlock(sqlite3 *db, sqlite3_vtab *pVtab){ + pVtab->nRef--; + assert(db); + assert( sqlite3SafetyCheckOk(db) ); + if( pVtab->nRef==0 ){ + if( db->magic==SQLITE_MAGIC_BUSY ){ + (void)sqlite3SafetyOff(db); + pVtab->pModule->xDisconnect(pVtab); + (void)sqlite3SafetyOn(db); + } else { + pVtab->pModule->xDisconnect(pVtab); + } + } +} + +/* +** Clear any and all virtual-table information from the Table record. +** This routine is called, for example, just before deleting the Table +** record. +*/ +void sqlite3VtabClear(Table *p){ + sqlite3_vtab *pVtab = p->pVtab; + sqlite3 *db = p->db; + if( pVtab ){ + assert( p->pMod && p->pMod->pModule ); + sqlite3VtabUnlock(db, pVtab); + p->pVtab = 0; + } + if( p->azModuleArg ){ + int i; + for(i=0; i<p->nModuleArg; i++){ + sqlite3DbFree(db, p->azModuleArg[i]); + } + sqlite3DbFree(db, p->azModuleArg); + } +} + +/* +** Add a new module argument to pTable->azModuleArg[]. +** The string is not copied - the pointer is stored. The +** string will be freed automatically when the table is +** deleted. +*/ +static void addModuleArgument(sqlite3 *db, Table *pTable, char *zArg){ + int i = pTable->nModuleArg++; + int nBytes = sizeof(char *)*(1+pTable->nModuleArg); + char **azModuleArg; + azModuleArg = sqlite3DbRealloc(db, pTable->azModuleArg, nBytes); + if( azModuleArg==0 ){ + int j; + for(j=0; j<i; j++){ + sqlite3DbFree(db, pTable->azModuleArg[j]); + } + sqlite3DbFree(db, zArg); + sqlite3DbFree(db, pTable->azModuleArg); + pTable->nModuleArg = 0; + }else{ + azModuleArg[i] = zArg; + azModuleArg[i+1] = 0; + } + pTable->azModuleArg = azModuleArg; +} + +/* +** The parser calls this routine when it first sees a CREATE VIRTUAL TABLE +** statement. The module name has been parsed, but the optional list +** of parameters that follow the module name are still pending. +*/ +void sqlite3VtabBeginParse( + Parse *pParse, /* Parsing context */ + Token *pName1, /* Name of new table, or database name */ + Token *pName2, /* Name of new table or NULL */ + Token *pModuleName /* Name of the module for the virtual table */ +){ + int iDb; /* The database the table is being created in */ + Table *pTable; /* The new virtual table */ + sqlite3 *db; /* Database connection */ + + if( pParse->db->flags & SQLITE_SharedCache ){ + sqlite3ErrorMsg(pParse, "Cannot use virtual tables in shared-cache mode"); + return; + } + + sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, 0); + pTable = pParse->pNewTable; + if( pTable==0 || pParse->nErr ) return; + assert( 0==pTable->pIndex ); + + db = pParse->db; + iDb = sqlite3SchemaToIndex(db, pTable->pSchema); + assert( iDb>=0 ); + + pTable->isVirtual = 1; + pTable->nModuleArg = 0; + addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName)); + addModuleArgument(db, pTable, sqlite3DbStrDup(db, db->aDb[iDb].zName)); + addModuleArgument(db, pTable, sqlite3DbStrDup(db, pTable->zName)); + pParse->sNameToken.n = pModuleName->z + pModuleName->n - pName1->z; + +#ifndef SQLITE_OMIT_AUTHORIZATION + /* Creating a virtual table invokes the authorization callback twice. + ** The first invocation, to obtain permission to INSERT a row into the + ** sqlite_master table, has already been made by sqlite3StartTable(). + ** The second call, to obtain permission to create the table, is made now. + */ + if( pTable->azModuleArg ){ + sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName, + pTable->azModuleArg[0], pParse->db->aDb[iDb].zName); + } +#endif +} + +/* +** This routine takes the module argument that has been accumulating +** in pParse->zArg[] and appends it to the list of arguments on the +** virtual table currently under construction in pParse->pTable. +*/ +static void addArgumentToVtab(Parse *pParse){ + if( pParse->sArg.z && pParse->pNewTable ){ + const char *z = (const char*)pParse->sArg.z; + int n = pParse->sArg.n; + sqlite3 *db = pParse->db; + addModuleArgument(db, pParse->pNewTable, sqlite3DbStrNDup(db, z, n)); + } +} + +/* +** The parser calls this routine after the CREATE VIRTUAL TABLE statement +** has been completely parsed. +*/ +void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ + Table *pTab; /* The table being constructed */ + sqlite3 *db; /* The database connection */ + char *zModule; /* The module name of the table: USING modulename */ + Module *pMod = 0; + + addArgumentToVtab(pParse); + pParse->sArg.z = 0; + + /* Lookup the module name. */ + pTab = pParse->pNewTable; + if( pTab==0 ) return; + db = pParse->db; + if( pTab->nModuleArg<1 ) return; + zModule = pTab->azModuleArg[0]; + pMod = (Module *)sqlite3HashFind(&db->aModule, zModule, strlen(zModule)); + pTab->pMod = pMod; + + /* If the CREATE VIRTUAL TABLE statement is being entered for the + ** first time (in other words if the virtual table is actually being + ** created now instead of just being read out of sqlite_master) then + ** do additional initialization work and store the statement text + ** in the sqlite_master table. + */ + if( !db->init.busy ){ + char *zStmt; + char *zWhere; + int iDb; + Vdbe *v; + + /* Compute the complete text of the CREATE VIRTUAL TABLE statement */ + if( pEnd ){ + pParse->sNameToken.n = pEnd->z - pParse->sNameToken.z + pEnd->n; + } + zStmt = sqlite3MPrintf(db, "CREATE VIRTUAL TABLE %T", &pParse->sNameToken); + + /* A slot for the record has already been allocated in the + ** SQLITE_MASTER table. We just need to update that slot with all + ** the information we've collected. + ** + ** The VM register number pParse->regRowid holds the rowid of an + ** entry in the sqlite_master table tht was created for this vtab + ** by sqlite3StartTable(). + */ + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + sqlite3NestedParse(pParse, + "UPDATE %Q.%s " + "SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q " + "WHERE rowid=#%d", + db->aDb[iDb].zName, SCHEMA_TABLE(iDb), + pTab->zName, + pTab->zName, + zStmt, + pParse->regRowid + ); + sqlite3DbFree(db, zStmt); + v = sqlite3GetVdbe(pParse); + sqlite3ChangeCookie(pParse, iDb); + + sqlite3VdbeAddOp2(v, OP_Expire, 0, 0); + zWhere = sqlite3MPrintf(db, "name='%q'", pTab->zName); + sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 1, 0, zWhere, P4_DYNAMIC); + sqlite3VdbeAddOp4(v, OP_VCreate, iDb, 0, 0, + pTab->zName, strlen(pTab->zName) + 1); + } + + /* If we are rereading the sqlite_master table create the in-memory + ** record of the table. If the module has already been registered, + ** also call the xConnect method here. + */ + else { + Table *pOld; + Schema *pSchema = pTab->pSchema; + const char *zName = pTab->zName; + int nName = strlen(zName) + 1; + pOld = sqlite3HashInsert(&pSchema->tblHash, zName, nName, pTab); + if( pOld ){ + db->mallocFailed = 1; + assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */ + return; + } + pSchema->db = pParse->db; + pParse->pNewTable = 0; + } +} + +/* +** The parser calls this routine when it sees the first token +** of an argument to the module name in a CREATE VIRTUAL TABLE statement. +*/ +void sqlite3VtabArgInit(Parse *pParse){ + addArgumentToVtab(pParse); + pParse->sArg.z = 0; + pParse->sArg.n = 0; +} + +/* +** The parser calls this routine for each token after the first token +** in an argument to the module name in a CREATE VIRTUAL TABLE statement. +*/ +void sqlite3VtabArgExtend(Parse *pParse, Token *p){ + Token *pArg = &pParse->sArg; + if( pArg->z==0 ){ + pArg->z = p->z; + pArg->n = p->n; + }else{ + assert(pArg->z < p->z); + pArg->n = (p->z + p->n - pArg->z); + } +} + +/* +** Invoke a virtual table constructor (either xCreate or xConnect). The +** pointer to the function to invoke is passed as the fourth parameter +** to this procedure. +*/ +static int vtabCallConstructor( + sqlite3 *db, + Table *pTab, + Module *pMod, + int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**), + char **pzErr +){ + int rc; + int rc2; + sqlite3_vtab *pVtab = 0; + const char *const*azArg = (const char *const*)pTab->azModuleArg; + int nArg = pTab->nModuleArg; + char *zErr = 0; + char *zModuleName = sqlite3MPrintf(db, "%s", pTab->zName); + + if( !zModuleName ){ + return SQLITE_NOMEM; + } + + assert( !db->pVTab ); + assert( xConstruct ); + + db->pVTab = pTab; + rc = sqlite3SafetyOff(db); + assert( rc==SQLITE_OK ); + rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVtab, &zErr); + rc2 = sqlite3SafetyOn(db); + if( rc==SQLITE_OK && pVtab ){ + pVtab->pModule = pMod->pModule; + pVtab->nRef = 1; + pTab->pVtab = pVtab; + } + + if( SQLITE_OK!=rc ){ + if( zErr==0 ){ + *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName); + }else { + *pzErr = sqlite3MPrintf(db, "%s", zErr); + sqlite3DbFree(db, zErr); + } + }else if( db->pVTab ){ + const char *zFormat = "vtable constructor did not declare schema: %s"; + *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName); + rc = SQLITE_ERROR; + } + if( rc==SQLITE_OK ){ + rc = rc2; + } + db->pVTab = 0; + sqlite3DbFree(db, zModuleName); + + /* If everything went according to plan, loop through the columns + ** of the table to see if any of them contain the token "hidden". + ** If so, set the Column.isHidden flag and remove the token from + ** the type string. + */ + if( rc==SQLITE_OK ){ + int iCol; + for(iCol=0; iCol<pTab->nCol; iCol++){ + char *zType = pTab->aCol[iCol].zType; + int nType; + int i = 0; + if( !zType ) continue; + nType = strlen(zType); + if( sqlite3StrNICmp("hidden", zType, 6) || (zType[6] && zType[6]!=' ') ){ + for(i=0; i<nType; i++){ + if( (0==sqlite3StrNICmp(" hidden", &zType[i], 7)) + && (zType[i+7]=='\0' || zType[i+7]==' ') + ){ + i++; + break; + } + } + } + if( i<nType ){ + int j; + int nDel = 6 + (zType[i+6] ? 1 : 0); + for(j=i; (j+nDel)<=nType; j++){ + zType[j] = zType[j+nDel]; + } + if( zType[i]=='\0' && i>0 ){ + assert(zType[i-1]==' '); + zType[i-1] = '\0'; + } + pTab->aCol[iCol].isHidden = 1; + } + } + } + return rc; +} + +/* +** This function is invoked by the parser to call the xConnect() method +** of the virtual table pTab. If an error occurs, an error code is returned +** and an error left in pParse. +** +** This call is a no-op if table pTab is not a virtual table. +*/ +int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){ + Module *pMod; + int rc = SQLITE_OK; + + if( !pTab || !pTab->isVirtual || pTab->pVtab ){ + return SQLITE_OK; + } + + pMod = pTab->pMod; + if( !pMod ){ + const char *zModule = pTab->azModuleArg[0]; + sqlite3ErrorMsg(pParse, "no such module: %s", zModule); + rc = SQLITE_ERROR; + } else { + char *zErr = 0; + sqlite3 *db = pParse->db; + rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr); + if( rc!=SQLITE_OK ){ + sqlite3ErrorMsg(pParse, "%s", zErr); + } + sqlite3DbFree(db, zErr); + } + + return rc; +} + +/* +** Add the virtual table pVtab to the array sqlite3.aVTrans[]. +*/ +static int addToVTrans(sqlite3 *db, sqlite3_vtab *pVtab){ + const int ARRAY_INCR = 5; + + /* Grow the sqlite3.aVTrans array if required */ + if( (db->nVTrans%ARRAY_INCR)==0 ){ + sqlite3_vtab **aVTrans; + int nBytes = sizeof(sqlite3_vtab *) * (db->nVTrans + ARRAY_INCR); + aVTrans = sqlite3DbRealloc(db, (void *)db->aVTrans, nBytes); + if( !aVTrans ){ + return SQLITE_NOMEM; + } + memset(&aVTrans[db->nVTrans], 0, sizeof(sqlite3_vtab *)*ARRAY_INCR); + db->aVTrans = aVTrans; + } + + /* Add pVtab to the end of sqlite3.aVTrans */ + db->aVTrans[db->nVTrans++] = pVtab; + sqlite3VtabLock(pVtab); + return SQLITE_OK; +} + +/* +** This function is invoked by the vdbe to call the xCreate method +** of the virtual table named zTab in database iDb. +** +** If an error occurs, *pzErr is set to point an an English language +** description of the error and an SQLITE_XXX error code is returned. +** In this case the caller must call sqlite3DbFree(db, ) on *pzErr. +*/ +int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){ + int rc = SQLITE_OK; + Table *pTab; + Module *pMod; + const char *zModule; + + pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); + assert(pTab && pTab->isVirtual && !pTab->pVtab); + pMod = pTab->pMod; + zModule = pTab->azModuleArg[0]; + + /* If the module has been registered and includes a Create method, + ** invoke it now. If the module has not been registered, return an + ** error. Otherwise, do nothing. + */ + if( !pMod ){ + *pzErr = sqlite3MPrintf(db, "no such module: %s", zModule); + rc = SQLITE_ERROR; + }else{ + rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xCreate, pzErr); + } + + if( rc==SQLITE_OK && pTab->pVtab ){ + rc = addToVTrans(db, pTab->pVtab); + } + + return rc; +} + +/* +** This function is used to set the schema of a virtual table. It is only +** valid to call this function from within the xCreate() or xConnect() of a +** virtual table module. +*/ +int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ + Parse sParse; + + int rc = SQLITE_OK; + Table *pTab; + char *zErr = 0; + + sqlite3_mutex_enter(db->mutex); + pTab = db->pVTab; + if( !pTab ){ + sqlite3Error(db, SQLITE_MISUSE, 0); + sqlite3_mutex_leave(db->mutex); + return SQLITE_MISUSE; + } + assert(pTab->isVirtual && pTab->nCol==0 && pTab->aCol==0); + + memset(&sParse, 0, sizeof(Parse)); + sParse.declareVtab = 1; + sParse.db = db; + + if( + SQLITE_OK == sqlite3RunParser(&sParse, zCreateTable, &zErr) && + sParse.pNewTable && + !sParse.pNewTable->pSelect && + !sParse.pNewTable->isVirtual + ){ + pTab->aCol = sParse.pNewTable->aCol; + pTab->nCol = sParse.pNewTable->nCol; + sParse.pNewTable->nCol = 0; + sParse.pNewTable->aCol = 0; + db->pVTab = 0; + } else { + sqlite3Error(db, SQLITE_ERROR, zErr); + sqlite3DbFree(db, zErr); + rc = SQLITE_ERROR; + } + sParse.declareVtab = 0; + + sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe); + sqlite3DeleteTable(sParse.pNewTable); + sParse.pNewTable = 0; + + assert( (rc&0xff)==rc ); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; +} + +/* +** This function is invoked by the vdbe to call the xDestroy method +** of the virtual table named zTab in database iDb. This occurs +** when a DROP TABLE is mentioned. +** +** This call is a no-op if zTab is not a virtual table. +*/ +int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab) +{ + int rc = SQLITE_OK; + Table *pTab; + + pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); + assert(pTab); + if( pTab->pVtab ){ + int (*xDestroy)(sqlite3_vtab *pVTab) = pTab->pMod->pModule->xDestroy; + rc = sqlite3SafetyOff(db); + assert( rc==SQLITE_OK ); + if( xDestroy ){ + rc = xDestroy(pTab->pVtab); + } + (void)sqlite3SafetyOn(db); + if( rc==SQLITE_OK ){ + int i; + for(i=0; i<db->nVTrans; i++){ + if( db->aVTrans[i]==pTab->pVtab ){ + db->aVTrans[i] = db->aVTrans[--db->nVTrans]; + break; + } + } + pTab->pVtab = 0; + } + } + + return rc; +} + +/* +** This function invokes either the xRollback or xCommit method +** of each of the virtual tables in the sqlite3.aVTrans array. The method +** called is identified by the second argument, "offset", which is +** the offset of the method to call in the sqlite3_module structure. +** +** The array is cleared after invoking the callbacks. +*/ +static void callFinaliser(sqlite3 *db, int offset){ + int i; + if( db->aVTrans ){ + for(i=0; i<db->nVTrans && db->aVTrans[i]; i++){ + sqlite3_vtab *pVtab = db->aVTrans[i]; + int (*x)(sqlite3_vtab *); + x = *(int (**)(sqlite3_vtab *))((char *)pVtab->pModule + offset); + if( x ) x(pVtab); + sqlite3VtabUnlock(db, pVtab); + } + sqlite3DbFree(db, db->aVTrans); + db->nVTrans = 0; + db->aVTrans = 0; + } +} + +/* +** Invoke the xSync method of all virtual tables in the sqlite3.aVTrans +** array. Return the error code for the first error that occurs, or +** SQLITE_OK if all xSync operations are successful. +** +** Set *pzErrmsg to point to a buffer that should be released using +** sqlite3DbFree() containing an error message, if one is available. +*/ +int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){ + int i; + int rc = SQLITE_OK; + int rcsafety; + sqlite3_vtab **aVTrans = db->aVTrans; + + rc = sqlite3SafetyOff(db); + db->aVTrans = 0; + for(i=0; rc==SQLITE_OK && i<db->nVTrans && aVTrans[i]; i++){ + sqlite3_vtab *pVtab = aVTrans[i]; + int (*x)(sqlite3_vtab *); + x = pVtab->pModule->xSync; + if( x ){ + rc = x(pVtab); + sqlite3DbFree(db, *pzErrmsg); + *pzErrmsg = pVtab->zErrMsg; + pVtab->zErrMsg = 0; + } + } + db->aVTrans = aVTrans; + rcsafety = sqlite3SafetyOn(db); + + if( rc==SQLITE_OK ){ + rc = rcsafety; + } + return rc; +} + +/* +** Invoke the xRollback method of all virtual tables in the +** sqlite3.aVTrans array. Then clear the array itself. +*/ +int sqlite3VtabRollback(sqlite3 *db){ + callFinaliser(db, offsetof(sqlite3_module,xRollback)); + return SQLITE_OK; +} + +/* +** Invoke the xCommit method of all virtual tables in the +** sqlite3.aVTrans array. Then clear the array itself. +*/ +int sqlite3VtabCommit(sqlite3 *db){ + callFinaliser(db, offsetof(sqlite3_module,xCommit)); + return SQLITE_OK; +} + +/* +** If the virtual table pVtab supports the transaction interface +** (xBegin/xRollback/xCommit and optionally xSync) and a transaction is +** not currently open, invoke the xBegin method now. +** +** If the xBegin call is successful, place the sqlite3_vtab pointer +** in the sqlite3.aVTrans array. +*/ +int sqlite3VtabBegin(sqlite3 *db, sqlite3_vtab *pVtab){ + int rc = SQLITE_OK; + const sqlite3_module *pModule; + + /* Special case: If db->aVTrans is NULL and db->nVTrans is greater + ** than zero, then this function is being called from within a + ** virtual module xSync() callback. It is illegal to write to + ** virtual module tables in this case, so return SQLITE_LOCKED. + */ + if( 0==db->aVTrans && db->nVTrans>0 ){ + return SQLITE_LOCKED; + } + if( !pVtab ){ + return SQLITE_OK; + } + pModule = pVtab->pModule; + + if( pModule->xBegin ){ + int i; + + + /* If pVtab is already in the aVTrans array, return early */ + for(i=0; (i<db->nVTrans) && 0!=db->aVTrans[i]; i++){ + if( db->aVTrans[i]==pVtab ){ + return SQLITE_OK; + } + } + + /* Invoke the xBegin method */ + rc = pModule->xBegin(pVtab); + if( rc==SQLITE_OK ){ + rc = addToVTrans(db, pVtab); + } + } + return rc; +} + +/* +** The first parameter (pDef) is a function implementation. The +** second parameter (pExpr) is the first argument to this function. +** If pExpr is a column in a virtual table, then let the virtual +** table implementation have an opportunity to overload the function. +** +** This routine is used to allow virtual table implementations to +** overload MATCH, LIKE, GLOB, and REGEXP operators. +** +** Return either the pDef argument (indicating no change) or a +** new FuncDef structure that is marked as ephemeral using the +** SQLITE_FUNC_EPHEM flag. +*/ +FuncDef *sqlite3VtabOverloadFunction( + sqlite3 *db, /* Database connection for reporting malloc problems */ + FuncDef *pDef, /* Function to possibly overload */ + int nArg, /* Number of arguments to the function */ + Expr *pExpr /* First argument to the function */ +){ + Table *pTab; + sqlite3_vtab *pVtab; + sqlite3_module *pMod; + void (*xFunc)(sqlite3_context*,int,sqlite3_value**); + void *pArg; + FuncDef *pNew; + int rc = 0; + char *zLowerName; + unsigned char *z; + + + /* Check to see the left operand is a column in a virtual table */ + if( pExpr==0 ) return pDef; + if( pExpr->op!=TK_COLUMN ) return pDef; + pTab = pExpr->pTab; + if( pTab==0 ) return pDef; + if( !pTab->isVirtual ) return pDef; + pVtab = pTab->pVtab; + assert( pVtab!=0 ); + assert( pVtab->pModule!=0 ); + pMod = (sqlite3_module *)pVtab->pModule; + if( pMod->xFindFunction==0 ) return pDef; + + /* Call the xFindFunction method on the virtual table implementation + ** to see if the implementation wants to overload this function + */ + zLowerName = sqlite3DbStrDup(db, pDef->zName); + if( zLowerName ){ + for(z=(unsigned char*)zLowerName; *z; z++){ + *z = sqlite3UpperToLower[*z]; + } + rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xFunc, &pArg); + sqlite3DbFree(db, zLowerName); + if( pVtab->zErrMsg ){ + sqlite3Error(db, rc, "%s", pVtab->zErrMsg); + sqlite3DbFree(db, pVtab->zErrMsg); + pVtab->zErrMsg = 0; + } + } + if( rc==0 ){ + return pDef; + } + + /* Create a new ephemeral function definition for the overloaded + ** function */ + pNew = sqlite3DbMallocZero(db, sizeof(*pNew) + strlen(pDef->zName) ); + if( pNew==0 ){ + return pDef; + } + *pNew = *pDef; + memcpy(pNew->zName, pDef->zName, strlen(pDef->zName)+1); + pNew->xFunc = xFunc; + pNew->pUserData = pArg; + pNew->flags |= SQLITE_FUNC_EPHEM; + return pNew; +} + +/* +** Make sure virtual table pTab is contained in the pParse->apVirtualLock[] +** array so that an OP_VBegin will get generated for it. Add pTab to the +** array if it is missing. If pTab is already in the array, this routine +** is a no-op. +*/ +void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){ + int i, n; + assert( IsVirtual(pTab) ); + for(i=0; i<pParse->nVtabLock; i++){ + if( pTab==pParse->apVtabLock[i] ) return; + } + n = (pParse->nVtabLock+1)*sizeof(pParse->apVtabLock[0]); + pParse->apVtabLock = sqlite3_realloc(pParse->apVtabLock, n); + if( pParse->apVtabLock ){ + pParse->apVtabLock[pParse->nVtabLock++] = pTab; + }else{ + pParse->db->mallocFailed = 1; + } +} + +#endif /* SQLITE_OMIT_VIRTUALTABLE */ diff --git a/third_party/sqlite/src/where.c b/third_party/sqlite/src/where.c new file mode 100755 index 0000000..9c70c31 --- /dev/null +++ b/third_party/sqlite/src/where.c @@ -0,0 +1,2895 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This module contains C code that generates VDBE code used to process +** the WHERE clause of SQL statements. This module is responsible for +** generating the code that loops through a table looking for applicable +** rows. Indices are selected and used to speed the search when doing +** so is applicable. Because this module is responsible for selecting +** indices, you might also think of this module as the "query optimizer". +** +** $Id: where.c,v 1.319 2008/08/01 17:37:41 danielk1977 Exp $ +*/ +#include "sqliteInt.h" + +/* +** The number of bits in a Bitmask. "BMS" means "BitMask Size". +*/ +#define BMS (sizeof(Bitmask)*8) + +/* +** Trace output macros +*/ +#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) +int sqlite3WhereTrace = 0; +#endif +#if 0 +# define WHERETRACE(X) if(sqlite3WhereTrace) sqlite3DebugPrintf X +#else +# define WHERETRACE(X) +#endif + +/* Forward reference +*/ +typedef struct WhereClause WhereClause; +typedef struct ExprMaskSet ExprMaskSet; + +/* +** The query generator uses an array of instances of this structure to +** help it analyze the subexpressions of the WHERE clause. Each WHERE +** clause subexpression is separated from the others by an AND operator. +** +** All WhereTerms are collected into a single WhereClause structure. +** The following identity holds: +** +** WhereTerm.pWC->a[WhereTerm.idx] == WhereTerm +** +** When a term is of the form: +** +** X <op> <expr> +** +** where X is a column name and <op> is one of certain operators, +** then WhereTerm.leftCursor and WhereTerm.leftColumn record the +** cursor number and column number for X. WhereTerm.operator records +** the <op> using a bitmask encoding defined by WO_xxx below. The +** use of a bitmask encoding for the operator allows us to search +** quickly for terms that match any of several different operators. +** +** prereqRight and prereqAll record sets of cursor numbers, +** but they do so indirectly. A single ExprMaskSet structure translates +** cursor number into bits and the translated bit is stored in the prereq +** fields. The translation is used in order to maximize the number of +** bits that will fit in a Bitmask. The VDBE cursor numbers might be +** spread out over the non-negative integers. For example, the cursor +** numbers might be 3, 8, 9, 10, 20, 23, 41, and 45. The ExprMaskSet +** translates these sparse cursor numbers into consecutive integers +** beginning with 0 in order to make the best possible use of the available +** bits in the Bitmask. So, in the example above, the cursor numbers +** would be mapped into integers 0 through 7. +*/ +typedef struct WhereTerm WhereTerm; +struct WhereTerm { + Expr *pExpr; /* Pointer to the subexpression */ + i16 iParent; /* Disable pWC->a[iParent] when this term disabled */ + i16 leftCursor; /* Cursor number of X in "X <op> <expr>" */ + i16 leftColumn; /* Column number of X in "X <op> <expr>" */ + u16 eOperator; /* A WO_xx value describing <op> */ + u8 flags; /* Bit flags. See below */ + u8 nChild; /* Number of children that must disable us */ + WhereClause *pWC; /* The clause this term is part of */ + Bitmask prereqRight; /* Bitmask of tables used by pRight */ + Bitmask prereqAll; /* Bitmask of tables referenced by p */ +}; + +/* +** Allowed values of WhereTerm.flags +*/ +#define TERM_DYNAMIC 0x01 /* Need to call sqlite3ExprDelete(db, pExpr) */ +#define TERM_VIRTUAL 0x02 /* Added by the optimizer. Do not code */ +#define TERM_CODED 0x04 /* This term is already coded */ +#define TERM_COPIED 0x08 /* Has a child */ +#define TERM_OR_OK 0x10 /* Used during OR-clause processing */ + +/* +** An instance of the following structure holds all information about a +** WHERE clause. Mostly this is a container for one or more WhereTerms. +*/ +struct WhereClause { + Parse *pParse; /* The parser context */ + ExprMaskSet *pMaskSet; /* Mapping of table indices to bitmasks */ + int nTerm; /* Number of terms */ + int nSlot; /* Number of entries in a[] */ + WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */ + WhereTerm aStatic[10]; /* Initial static space for a[] */ +}; + +/* +** An instance of the following structure keeps track of a mapping +** between VDBE cursor numbers and bits of the bitmasks in WhereTerm. +** +** The VDBE cursor numbers are small integers contained in +** SrcList_item.iCursor and Expr.iTable fields. For any given WHERE +** clause, the cursor numbers might not begin with 0 and they might +** contain gaps in the numbering sequence. But we want to make maximum +** use of the bits in our bitmasks. This structure provides a mapping +** from the sparse cursor numbers into consecutive integers beginning +** with 0. +** +** If ExprMaskSet.ix[A]==B it means that The A-th bit of a Bitmask +** corresponds VDBE cursor number B. The A-th bit of a bitmask is 1<<A. +** +** For example, if the WHERE clause expression used these VDBE +** cursors: 4, 5, 8, 29, 57, 73. Then the ExprMaskSet structure +** would map those cursor numbers into bits 0 through 5. +** +** Note that the mapping is not necessarily ordered. In the example +** above, the mapping might go like this: 4->3, 5->1, 8->2, 29->0, +** 57->5, 73->4. Or one of 719 other combinations might be used. It +** does not really matter. What is important is that sparse cursor +** numbers all get mapped into bit numbers that begin with 0 and contain +** no gaps. +*/ +struct ExprMaskSet { + int n; /* Number of assigned cursor values */ + int ix[sizeof(Bitmask)*8]; /* Cursor assigned to each bit */ +}; + + +/* +** Bitmasks for the operators that indices are able to exploit. An +** OR-ed combination of these values can be used when searching for +** terms in the where clause. +*/ +#define WO_IN 1 +#define WO_EQ 2 +#define WO_LT (WO_EQ<<(TK_LT-TK_EQ)) +#define WO_LE (WO_EQ<<(TK_LE-TK_EQ)) +#define WO_GT (WO_EQ<<(TK_GT-TK_EQ)) +#define WO_GE (WO_EQ<<(TK_GE-TK_EQ)) +#define WO_MATCH 64 +#define WO_ISNULL 128 + +/* +** Value for flags returned by bestIndex(). +** +** The least significant byte is reserved as a mask for WO_ values above. +** The WhereLevel.flags field is usually set to WO_IN|WO_EQ|WO_ISNULL. +** But if the table is the right table of a left join, WhereLevel.flags +** is set to WO_IN|WO_EQ. The WhereLevel.flags field can then be used as +** the "op" parameter to findTerm when we are resolving equality constraints. +** ISNULL constraints will then not be used on the right table of a left +** join. Tickets #2177 and #2189. +*/ +#define WHERE_ROWID_EQ 0x000100 /* rowid=EXPR or rowid IN (...) */ +#define WHERE_ROWID_RANGE 0x000200 /* rowid<EXPR and/or rowid>EXPR */ +#define WHERE_COLUMN_EQ 0x001000 /* x=EXPR or x IN (...) */ +#define WHERE_COLUMN_RANGE 0x002000 /* x<EXPR and/or x>EXPR */ +#define WHERE_COLUMN_IN 0x004000 /* x IN (...) */ +#define WHERE_TOP_LIMIT 0x010000 /* x<EXPR or x<=EXPR constraint */ +#define WHERE_BTM_LIMIT 0x020000 /* x>EXPR or x>=EXPR constraint */ +#define WHERE_IDX_ONLY 0x080000 /* Use index only - omit table */ +#define WHERE_ORDERBY 0x100000 /* Output will appear in correct order */ +#define WHERE_REVERSE 0x200000 /* Scan in reverse order */ +#define WHERE_UNIQUE 0x400000 /* Selects no more than one row */ +#define WHERE_VIRTUALTABLE 0x800000 /* Use virtual-table processing */ + +/* +** Initialize a preallocated WhereClause structure. +*/ +static void whereClauseInit( + WhereClause *pWC, /* The WhereClause to be initialized */ + Parse *pParse, /* The parsing context */ + ExprMaskSet *pMaskSet /* Mapping from table indices to bitmasks */ +){ + pWC->pParse = pParse; + pWC->pMaskSet = pMaskSet; + pWC->nTerm = 0; + pWC->nSlot = ArraySize(pWC->aStatic); + pWC->a = pWC->aStatic; +} + +/* +** Deallocate a WhereClause structure. The WhereClause structure +** itself is not freed. This routine is the inverse of whereClauseInit(). +*/ +static void whereClauseClear(WhereClause *pWC){ + int i; + WhereTerm *a; + sqlite3 *db = pWC->pParse->db; + for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){ + if( a->flags & TERM_DYNAMIC ){ + sqlite3ExprDelete(db, a->pExpr); + } + } + if( pWC->a!=pWC->aStatic ){ + sqlite3DbFree(db, pWC->a); + } +} + +/* +** Add a new entries to the WhereClause structure. Increase the allocated +** space as necessary. +** +** If the flags argument includes TERM_DYNAMIC, then responsibility +** for freeing the expression p is assumed by the WhereClause object. +** +** WARNING: This routine might reallocate the space used to store +** WhereTerms. All pointers to WhereTerms should be invalidated after +** calling this routine. Such pointers may be reinitialized by referencing +** the pWC->a[] array. +*/ +static int whereClauseInsert(WhereClause *pWC, Expr *p, int flags){ + WhereTerm *pTerm; + int idx; + if( pWC->nTerm>=pWC->nSlot ){ + WhereTerm *pOld = pWC->a; + sqlite3 *db = pWC->pParse->db; + pWC->a = sqlite3DbMallocRaw(db, sizeof(pWC->a[0])*pWC->nSlot*2 ); + if( pWC->a==0 ){ + if( flags & TERM_DYNAMIC ){ + sqlite3ExprDelete(db, p); + } + pWC->a = pOld; + return 0; + } + memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm); + if( pOld!=pWC->aStatic ){ + sqlite3DbFree(db, pOld); + } + pWC->nSlot *= 2; + } + pTerm = &pWC->a[idx = pWC->nTerm]; + pWC->nTerm++; + pTerm->pExpr = p; + pTerm->flags = flags; + pTerm->pWC = pWC; + pTerm->iParent = -1; + return idx; +} + +/* +** This routine identifies subexpressions in the WHERE clause where +** each subexpression is separated by the AND operator or some other +** operator specified in the op parameter. The WhereClause structure +** is filled with pointers to subexpressions. For example: +** +** WHERE a=='hello' AND coalesce(b,11)<10 AND (c+12!=d OR c==22) +** \________/ \_______________/ \________________/ +** slot[0] slot[1] slot[2] +** +** The original WHERE clause in pExpr is unaltered. All this routine +** does is make slot[] entries point to substructure within pExpr. +** +** In the previous sentence and in the diagram, "slot[]" refers to +** the WhereClause.a[] array. This array grows as needed to contain +** all terms of the WHERE clause. +*/ +static void whereSplit(WhereClause *pWC, Expr *pExpr, int op){ + if( pExpr==0 ) return; + if( pExpr->op!=op ){ + whereClauseInsert(pWC, pExpr, 0); + }else{ + whereSplit(pWC, pExpr->pLeft, op); + whereSplit(pWC, pExpr->pRight, op); + } +} + +/* +** Initialize an expression mask set +*/ +#define initMaskSet(P) memset(P, 0, sizeof(*P)) + +/* +** Return the bitmask for the given cursor number. Return 0 if +** iCursor is not in the set. +*/ +static Bitmask getMask(ExprMaskSet *pMaskSet, int iCursor){ + int i; + for(i=0; i<pMaskSet->n; i++){ + if( pMaskSet->ix[i]==iCursor ){ + return ((Bitmask)1)<<i; + } + } + return 0; +} + +/* +** Create a new mask for cursor iCursor. +** +** There is one cursor per table in the FROM clause. The number of +** tables in the FROM clause is limited by a test early in the +** sqlite3WhereBegin() routine. So we know that the pMaskSet->ix[] +** array will never overflow. +*/ +static void createMask(ExprMaskSet *pMaskSet, int iCursor){ + assert( pMaskSet->n < ArraySize(pMaskSet->ix) ); + pMaskSet->ix[pMaskSet->n++] = iCursor; +} + +/* +** This routine walks (recursively) an expression tree and generates +** a bitmask indicating which tables are used in that expression +** tree. +** +** In order for this routine to work, the calling function must have +** previously invoked sqlite3ExprResolveNames() on the expression. See +** the header comment on that routine for additional information. +** The sqlite3ExprResolveNames() routines looks for column names and +** sets their opcodes to TK_COLUMN and their Expr.iTable fields to +** the VDBE cursor number of the table. This routine just has to +** translate the cursor numbers into bitmask values and OR all +** the bitmasks together. +*/ +static Bitmask exprListTableUsage(ExprMaskSet*, ExprList*); +static Bitmask exprSelectTableUsage(ExprMaskSet*, Select*); +static Bitmask exprTableUsage(ExprMaskSet *pMaskSet, Expr *p){ + Bitmask mask = 0; + if( p==0 ) return 0; + if( p->op==TK_COLUMN ){ + mask = getMask(pMaskSet, p->iTable); + return mask; + } + mask = exprTableUsage(pMaskSet, p->pRight); + mask |= exprTableUsage(pMaskSet, p->pLeft); + mask |= exprListTableUsage(pMaskSet, p->pList); + mask |= exprSelectTableUsage(pMaskSet, p->pSelect); + return mask; +} +static Bitmask exprListTableUsage(ExprMaskSet *pMaskSet, ExprList *pList){ + int i; + Bitmask mask = 0; + if( pList ){ + for(i=0; i<pList->nExpr; i++){ + mask |= exprTableUsage(pMaskSet, pList->a[i].pExpr); + } + } + return mask; +} +static Bitmask exprSelectTableUsage(ExprMaskSet *pMaskSet, Select *pS){ + Bitmask mask = 0; + while( pS ){ + mask |= exprListTableUsage(pMaskSet, pS->pEList); + mask |= exprListTableUsage(pMaskSet, pS->pGroupBy); + mask |= exprListTableUsage(pMaskSet, pS->pOrderBy); + mask |= exprTableUsage(pMaskSet, pS->pWhere); + mask |= exprTableUsage(pMaskSet, pS->pHaving); + pS = pS->pPrior; + } + return mask; +} + +/* +** Return TRUE if the given operator is one of the operators that is +** allowed for an indexable WHERE clause term. The allowed operators are +** "=", "<", ">", "<=", ">=", and "IN". +*/ +static int allowedOp(int op){ + assert( TK_GT>TK_EQ && TK_GT<TK_GE ); + assert( TK_LT>TK_EQ && TK_LT<TK_GE ); + assert( TK_LE>TK_EQ && TK_LE<TK_GE ); + assert( TK_GE==TK_EQ+4 ); + return op==TK_IN || (op>=TK_EQ && op<=TK_GE) || op==TK_ISNULL; +} + +/* +** Swap two objects of type T. +*/ +#define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;} + +/* +** Commute a comparison operator. Expressions of the form "X op Y" +** are converted into "Y op X". +** +** If a collation sequence is associated with either the left or right +** side of the comparison, it remains associated with the same side after +** the commutation. So "Y collate NOCASE op X" becomes +** "X collate NOCASE op Y". This is because any collation sequence on +** the left hand side of a comparison overrides any collation sequence +** attached to the right. For the same reason the EP_ExpCollate flag +** is not commuted. +*/ +static void exprCommute(Expr *pExpr){ + u16 expRight = (pExpr->pRight->flags & EP_ExpCollate); + u16 expLeft = (pExpr->pLeft->flags & EP_ExpCollate); + assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN ); + SWAP(CollSeq*,pExpr->pRight->pColl,pExpr->pLeft->pColl); + pExpr->pRight->flags = (pExpr->pRight->flags & ~EP_ExpCollate) | expLeft; + pExpr->pLeft->flags = (pExpr->pLeft->flags & ~EP_ExpCollate) | expRight; + SWAP(Expr*,pExpr->pRight,pExpr->pLeft); + if( pExpr->op>=TK_GT ){ + assert( TK_LT==TK_GT+2 ); + assert( TK_GE==TK_LE+2 ); + assert( TK_GT>TK_EQ ); + assert( TK_GT<TK_LE ); + assert( pExpr->op>=TK_GT && pExpr->op<=TK_GE ); + pExpr->op = ((pExpr->op-TK_GT)^2)+TK_GT; + } +} + +/* +** Translate from TK_xx operator to WO_xx bitmask. +*/ +static int operatorMask(int op){ + int c; + assert( allowedOp(op) ); + if( op==TK_IN ){ + c = WO_IN; + }else if( op==TK_ISNULL ){ + c = WO_ISNULL; + }else{ + c = WO_EQ<<(op-TK_EQ); + } + assert( op!=TK_ISNULL || c==WO_ISNULL ); + assert( op!=TK_IN || c==WO_IN ); + assert( op!=TK_EQ || c==WO_EQ ); + assert( op!=TK_LT || c==WO_LT ); + assert( op!=TK_LE || c==WO_LE ); + assert( op!=TK_GT || c==WO_GT ); + assert( op!=TK_GE || c==WO_GE ); + return c; +} + +/* +** Search for a term in the WHERE clause that is of the form "X <op> <expr>" +** where X is a reference to the iColumn of table iCur and <op> is one of +** the WO_xx operator codes specified by the op parameter. +** Return a pointer to the term. Return 0 if not found. +*/ +static WhereTerm *findTerm( + WhereClause *pWC, /* The WHERE clause to be searched */ + int iCur, /* Cursor number of LHS */ + int iColumn, /* Column number of LHS */ + Bitmask notReady, /* RHS must not overlap with this mask */ + u16 op, /* Mask of WO_xx values describing operator */ + Index *pIdx /* Must be compatible with this index, if not NULL */ +){ + WhereTerm *pTerm; + int k; + assert( iCur>=0 ); + for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){ + if( pTerm->leftCursor==iCur + && (pTerm->prereqRight & notReady)==0 + && pTerm->leftColumn==iColumn + && (pTerm->eOperator & op)!=0 + ){ + if( pIdx && pTerm->eOperator!=WO_ISNULL ){ + Expr *pX = pTerm->pExpr; + CollSeq *pColl; + char idxaff; + int j; + Parse *pParse = pWC->pParse; + + idxaff = pIdx->pTable->aCol[iColumn].affinity; + if( !sqlite3IndexAffinityOk(pX, idxaff) ) continue; + + /* Figure out the collation sequence required from an index for + ** it to be useful for optimising expression pX. Store this + ** value in variable pColl. + */ + assert(pX->pLeft); + pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); + if( !pColl ){ + pColl = pParse->db->pDfltColl; + } + + for(j=0; pIdx->aiColumn[j]!=iColumn; j++){ + if( NEVER(j>=pIdx->nColumn) ) return 0; + } + if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue; + } + return pTerm; + } + } + return 0; +} + +/* Forward reference */ +static void exprAnalyze(SrcList*, WhereClause*, int); + +/* +** Call exprAnalyze on all terms in a WHERE clause. +** +** +*/ +static void exprAnalyzeAll( + SrcList *pTabList, /* the FROM clause */ + WhereClause *pWC /* the WHERE clause to be analyzed */ +){ + int i; + for(i=pWC->nTerm-1; i>=0; i--){ + exprAnalyze(pTabList, pWC, i); + } +} + +#ifndef SQLITE_OMIT_LIKE_OPTIMIZATION +/* +** Check to see if the given expression is a LIKE or GLOB operator that +** can be optimized using inequality constraints. Return TRUE if it is +** so and false if not. +** +** In order for the operator to be optimizible, the RHS must be a string +** literal that does not begin with a wildcard. +*/ +static int isLikeOrGlob( + sqlite3 *db, /* The database */ + Expr *pExpr, /* Test this expression */ + int *pnPattern, /* Number of non-wildcard prefix characters */ + int *pisComplete, /* True if the only wildcard is % in the last character */ + int *pnoCase /* True if uppercase is equivalent to lowercase */ +){ + const char *z; + Expr *pRight, *pLeft; + ExprList *pList; + int c, cnt; + char wc[3]; + CollSeq *pColl; + + if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, wc) ){ + return 0; + } +#ifdef SQLITE_EBCDIC + if( *pnoCase ) return 0; +#endif + pList = pExpr->pList; + pRight = pList->a[0].pExpr; + if( pRight->op!=TK_STRING + && (pRight->op!=TK_REGISTER || pRight->iColumn!=TK_STRING) ){ + return 0; + } + pLeft = pList->a[1].pExpr; + if( pLeft->op!=TK_COLUMN ){ + return 0; + } + pColl = pLeft->pColl; + assert( pColl!=0 || pLeft->iColumn==-1 ); + if( pColl==0 ){ + /* No collation is defined for the ROWID. Use the default. */ + pColl = db->pDfltColl; + } + if( (pColl->type!=SQLITE_COLL_BINARY || *pnoCase) && + (pColl->type!=SQLITE_COLL_NOCASE || !*pnoCase) ){ + return 0; + } + sqlite3DequoteExpr(db, pRight); + z = (char *)pRight->token.z; + cnt = 0; + if( z ){ + while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ cnt++; } + } + if( cnt==0 || 255==(u8)z[cnt] ){ + return 0; + } + *pisComplete = z[cnt]==wc[0] && z[cnt+1]==0; + *pnPattern = cnt; + return 1; +} +#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */ + + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* +** Check to see if the given expression is of the form +** +** column MATCH expr +** +** If it is then return TRUE. If not, return FALSE. +*/ +static int isMatchOfColumn( + Expr *pExpr /* Test this expression */ +){ + ExprList *pList; + + if( pExpr->op!=TK_FUNCTION ){ + return 0; + } + if( pExpr->token.n!=5 || + sqlite3StrNICmp((const char*)pExpr->token.z,"match",5)!=0 ){ + return 0; + } + pList = pExpr->pList; + if( pList->nExpr!=2 ){ + return 0; + } + if( pList->a[1].pExpr->op != TK_COLUMN ){ + return 0; + } + return 1; +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +/* +** If the pBase expression originated in the ON or USING clause of +** a join, then transfer the appropriate markings over to derived. +*/ +static void transferJoinMarkings(Expr *pDerived, Expr *pBase){ + pDerived->flags |= pBase->flags & EP_FromJoin; + pDerived->iRightJoinTable = pBase->iRightJoinTable; +} + +#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY) +/* +** Return TRUE if the given term of an OR clause can be converted +** into an IN clause. The iCursor and iColumn define the left-hand +** side of the IN clause. +** +** The context is that we have multiple OR-connected equality terms +** like this: +** +** a=<expr1> OR a=<expr2> OR b=<expr3> OR ... +** +** The pOrTerm input to this routine corresponds to a single term of +** this OR clause. In order for the term to be a candidate for +** conversion to an IN operator, the following must be true: +** +** * The left-hand side of the term must be the column which +** is identified by iCursor and iColumn. +** +** * If the right-hand side is also a column, then the affinities +** of both right and left sides must be such that no type +** conversions are required on the right. (Ticket #2249) +** +** If both of these conditions are true, then return true. Otherwise +** return false. +*/ +static int orTermIsOptCandidate(WhereTerm *pOrTerm, int iCursor, int iColumn){ + int affLeft, affRight; + assert( pOrTerm->eOperator==WO_EQ ); + if( pOrTerm->leftCursor!=iCursor ){ + return 0; + } + if( pOrTerm->leftColumn!=iColumn ){ + return 0; + } + affRight = sqlite3ExprAffinity(pOrTerm->pExpr->pRight); + if( affRight==0 ){ + return 1; + } + affLeft = sqlite3ExprAffinity(pOrTerm->pExpr->pLeft); + if( affRight!=affLeft ){ + return 0; + } + return 1; +} + +/* +** Return true if the given term of an OR clause can be ignored during +** a check to make sure all OR terms are candidates for optimization. +** In other words, return true if a call to the orTermIsOptCandidate() +** above returned false but it is not necessary to disqualify the +** optimization. +** +** Suppose the original OR phrase was this: +** +** a=4 OR a=11 OR a=b +** +** During analysis, the third term gets flipped around and duplicate +** so that we are left with this: +** +** a=4 OR a=11 OR a=b OR b=a +** +** Since the last two terms are duplicates, only one of them +** has to qualify in order for the whole phrase to qualify. When +** this routine is called, we know that pOrTerm did not qualify. +** This routine merely checks to see if pOrTerm has a duplicate that +** might qualify. If there is a duplicate that has not yet been +** disqualified, then return true. If there are no duplicates, or +** the duplicate has also been disqualified, return false. +*/ +static int orTermHasOkDuplicate(WhereClause *pOr, WhereTerm *pOrTerm){ + if( pOrTerm->flags & TERM_COPIED ){ + /* This is the original term. The duplicate is to the left had + ** has not yet been analyzed and thus has not yet been disqualified. */ + return 1; + } + if( (pOrTerm->flags & TERM_VIRTUAL)!=0 + && (pOr->a[pOrTerm->iParent].flags & TERM_OR_OK)!=0 ){ + /* This is a duplicate term. The original qualified so this one + ** does not have to. */ + return 1; + } + /* This is either a singleton term or else it is a duplicate for + ** which the original did not qualify. Either way we are done for. */ + return 0; +} +#endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */ + +/* +** The input to this routine is an WhereTerm structure with only the +** "pExpr" field filled in. The job of this routine is to analyze the +** subexpression and populate all the other fields of the WhereTerm +** structure. +** +** If the expression is of the form "<expr> <op> X" it gets commuted +** to the standard form of "X <op> <expr>". If the expression is of +** the form "X <op> Y" where both X and Y are columns, then the original +** expression is unchanged and a new virtual expression of the form +** "Y <op> X" is added to the WHERE clause and analyzed separately. +*/ +static void exprAnalyze( + SrcList *pSrc, /* the FROM clause */ + WhereClause *pWC, /* the WHERE clause */ + int idxTerm /* Index of the term to be analyzed */ +){ + WhereTerm *pTerm; + ExprMaskSet *pMaskSet; + Expr *pExpr; + Bitmask prereqLeft; + Bitmask prereqAll; + Bitmask extraRight = 0; + int nPattern; + int isComplete; + int noCase; + int op; + Parse *pParse = pWC->pParse; + sqlite3 *db = pParse->db; + + if( db->mallocFailed ){ + return; + } + pTerm = &pWC->a[idxTerm]; + pMaskSet = pWC->pMaskSet; + pExpr = pTerm->pExpr; + prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft); + op = pExpr->op; + if( op==TK_IN ){ + assert( pExpr->pRight==0 ); + pTerm->prereqRight = exprListTableUsage(pMaskSet, pExpr->pList) + | exprSelectTableUsage(pMaskSet, pExpr->pSelect); + }else if( op==TK_ISNULL ){ + pTerm->prereqRight = 0; + }else{ + pTerm->prereqRight = exprTableUsage(pMaskSet, pExpr->pRight); + } + prereqAll = exprTableUsage(pMaskSet, pExpr); + if( ExprHasProperty(pExpr, EP_FromJoin) ){ + Bitmask x = getMask(pMaskSet, pExpr->iRightJoinTable); + prereqAll |= x; + extraRight = x-1; /* ON clause terms may not be used with an index + ** on left table of a LEFT JOIN. Ticket #3015 */ + } + pTerm->prereqAll = prereqAll; + pTerm->leftCursor = -1; + pTerm->iParent = -1; + pTerm->eOperator = 0; + if( allowedOp(op) && (pTerm->prereqRight & prereqLeft)==0 ){ + Expr *pLeft = pExpr->pLeft; + Expr *pRight = pExpr->pRight; + if( pLeft->op==TK_COLUMN ){ + pTerm->leftCursor = pLeft->iTable; + pTerm->leftColumn = pLeft->iColumn; + pTerm->eOperator = operatorMask(op); + } + if( pRight && pRight->op==TK_COLUMN ){ + WhereTerm *pNew; + Expr *pDup; + if( pTerm->leftCursor>=0 ){ + int idxNew; + pDup = sqlite3ExprDup(db, pExpr); + if( db->mallocFailed ){ + sqlite3ExprDelete(db, pDup); + return; + } + idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC); + if( idxNew==0 ) return; + pNew = &pWC->a[idxNew]; + pNew->iParent = idxTerm; + pTerm = &pWC->a[idxTerm]; + pTerm->nChild = 1; + pTerm->flags |= TERM_COPIED; + }else{ + pDup = pExpr; + pNew = pTerm; + } + exprCommute(pDup); + pLeft = pDup->pLeft; + pNew->leftCursor = pLeft->iTable; + pNew->leftColumn = pLeft->iColumn; + pNew->prereqRight = prereqLeft; + pNew->prereqAll = prereqAll; + pNew->eOperator = operatorMask(pDup->op); + } + } + +#ifndef SQLITE_OMIT_BETWEEN_OPTIMIZATION + /* If a term is the BETWEEN operator, create two new virtual terms + ** that define the range that the BETWEEN implements. + */ + else if( pExpr->op==TK_BETWEEN ){ + ExprList *pList = pExpr->pList; + int i; + static const u8 ops[] = {TK_GE, TK_LE}; + assert( pList!=0 ); + assert( pList->nExpr==2 ); + for(i=0; i<2; i++){ + Expr *pNewExpr; + int idxNew; + pNewExpr = sqlite3Expr(db, ops[i], sqlite3ExprDup(db, pExpr->pLeft), + sqlite3ExprDup(db, pList->a[i].pExpr), 0); + idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); + exprAnalyze(pSrc, pWC, idxNew); + pTerm = &pWC->a[idxTerm]; + pWC->a[idxNew].iParent = idxTerm; + } + pTerm->nChild = 2; + } +#endif /* SQLITE_OMIT_BETWEEN_OPTIMIZATION */ + +#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY) + /* Attempt to convert OR-connected terms into an IN operator so that + ** they can make use of indices. Example: + ** + ** x = expr1 OR expr2 = x OR x = expr3 + ** + ** is converted into + ** + ** x IN (expr1,expr2,expr3) + ** + ** This optimization must be omitted if OMIT_SUBQUERY is defined because + ** the compiler for the the IN operator is part of sub-queries. + */ + else if( pExpr->op==TK_OR ){ + int ok; + int i, j; + int iColumn, iCursor; + WhereClause sOr; + WhereTerm *pOrTerm; + + assert( (pTerm->flags & TERM_DYNAMIC)==0 ); + whereClauseInit(&sOr, pWC->pParse, pMaskSet); + whereSplit(&sOr, pExpr, TK_OR); + exprAnalyzeAll(pSrc, &sOr); + assert( sOr.nTerm>=2 ); + j = 0; + if( db->mallocFailed ) goto or_not_possible; + do{ + assert( j<sOr.nTerm ); + iColumn = sOr.a[j].leftColumn; + iCursor = sOr.a[j].leftCursor; + ok = iCursor>=0; + for(i=sOr.nTerm-1, pOrTerm=sOr.a; i>=0 && ok; i--, pOrTerm++){ + if( pOrTerm->eOperator!=WO_EQ ){ + goto or_not_possible; + } + if( orTermIsOptCandidate(pOrTerm, iCursor, iColumn) ){ + pOrTerm->flags |= TERM_OR_OK; + }else if( orTermHasOkDuplicate(&sOr, pOrTerm) ){ + pOrTerm->flags &= ~TERM_OR_OK; + }else{ + ok = 0; + } + } + }while( !ok && (sOr.a[j++].flags & TERM_COPIED)!=0 && j<2 ); + if( ok ){ + ExprList *pList = 0; + Expr *pNew, *pDup; + Expr *pLeft = 0; + for(i=sOr.nTerm-1, pOrTerm=sOr.a; i>=0; i--, pOrTerm++){ + if( (pOrTerm->flags & TERM_OR_OK)==0 ) continue; + pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight); + pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup, 0); + pLeft = pOrTerm->pExpr->pLeft; + } + assert( pLeft!=0 ); + pDup = sqlite3ExprDup(db, pLeft); + pNew = sqlite3Expr(db, TK_IN, pDup, 0, 0); + if( pNew ){ + int idxNew; + transferJoinMarkings(pNew, pExpr); + pNew->pList = pList; + idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC); + exprAnalyze(pSrc, pWC, idxNew); + pTerm = &pWC->a[idxTerm]; + pWC->a[idxNew].iParent = idxTerm; + pTerm->nChild = 1; + }else{ + sqlite3ExprListDelete(db, pList); + } + } +or_not_possible: + whereClauseClear(&sOr); + } +#endif /* SQLITE_OMIT_OR_OPTIMIZATION */ + +#ifndef SQLITE_OMIT_LIKE_OPTIMIZATION + /* Add constraints to reduce the search space on a LIKE or GLOB + ** operator. + ** + ** A like pattern of the form "x LIKE 'abc%'" is changed into constraints + ** + ** x>='abc' AND x<'abd' AND x LIKE 'abc%' + ** + ** The last character of the prefix "abc" is incremented to form the + ** termination condition "abd". + */ + if( isLikeOrGlob(db, pExpr, &nPattern, &isComplete, &noCase) ){ + Expr *pLeft, *pRight; + Expr *pStr1, *pStr2; + Expr *pNewExpr1, *pNewExpr2; + int idxNew1, idxNew2; + + pLeft = pExpr->pList->a[1].pExpr; + pRight = pExpr->pList->a[0].pExpr; + pStr1 = sqlite3PExpr(pParse, TK_STRING, 0, 0, 0); + if( pStr1 ){ + sqlite3TokenCopy(db, &pStr1->token, &pRight->token); + pStr1->token.n = nPattern; + pStr1->flags = EP_Dequoted; + } + pStr2 = sqlite3ExprDup(db, pStr1); + if( !db->mallocFailed ){ + u8 c, *pC; + assert( pStr2->token.dyn ); + pC = (u8*)&pStr2->token.z[nPattern-1]; + c = *pC; + if( noCase ){ + if( c=='@' ) isComplete = 0; + c = sqlite3UpperToLower[c]; + } + *pC = c + 1; + } + pNewExpr1 = sqlite3PExpr(pParse, TK_GE, sqlite3ExprDup(db,pLeft), pStr1, 0); + idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC); + exprAnalyze(pSrc, pWC, idxNew1); + pNewExpr2 = sqlite3PExpr(pParse, TK_LT, sqlite3ExprDup(db,pLeft), pStr2, 0); + idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC); + exprAnalyze(pSrc, pWC, idxNew2); + pTerm = &pWC->a[idxTerm]; + if( isComplete ){ + pWC->a[idxNew1].iParent = idxTerm; + pWC->a[idxNew2].iParent = idxTerm; + pTerm->nChild = 2; + } + } +#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */ + +#ifndef SQLITE_OMIT_VIRTUALTABLE + /* Add a WO_MATCH auxiliary term to the constraint set if the + ** current expression is of the form: column MATCH expr. + ** This information is used by the xBestIndex methods of + ** virtual tables. The native query optimizer does not attempt + ** to do anything with MATCH functions. + */ + if( isMatchOfColumn(pExpr) ){ + int idxNew; + Expr *pRight, *pLeft; + WhereTerm *pNewTerm; + Bitmask prereqColumn, prereqExpr; + + pRight = pExpr->pList->a[0].pExpr; + pLeft = pExpr->pList->a[1].pExpr; + prereqExpr = exprTableUsage(pMaskSet, pRight); + prereqColumn = exprTableUsage(pMaskSet, pLeft); + if( (prereqExpr & prereqColumn)==0 ){ + Expr *pNewExpr; + pNewExpr = sqlite3Expr(db, TK_MATCH, 0, sqlite3ExprDup(db, pRight), 0); + idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); + pNewTerm = &pWC->a[idxNew]; + pNewTerm->prereqRight = prereqExpr; + pNewTerm->leftCursor = pLeft->iTable; + pNewTerm->leftColumn = pLeft->iColumn; + pNewTerm->eOperator = WO_MATCH; + pNewTerm->iParent = idxTerm; + pTerm = &pWC->a[idxTerm]; + pTerm->nChild = 1; + pTerm->flags |= TERM_COPIED; + pNewTerm->prereqAll = pTerm->prereqAll; + } + } +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + + /* Prevent ON clause terms of a LEFT JOIN from being used to drive + ** an index for tables to the left of the join. + */ + pTerm->prereqRight |= extraRight; +} + +/* +** Return TRUE if any of the expressions in pList->a[iFirst...] contain +** a reference to any table other than the iBase table. +*/ +static int referencesOtherTables( + ExprList *pList, /* Search expressions in ths list */ + ExprMaskSet *pMaskSet, /* Mapping from tables to bitmaps */ + int iFirst, /* Be searching with the iFirst-th expression */ + int iBase /* Ignore references to this table */ +){ + Bitmask allowed = ~getMask(pMaskSet, iBase); + while( iFirst<pList->nExpr ){ + if( (exprTableUsage(pMaskSet, pList->a[iFirst++].pExpr)&allowed)!=0 ){ + return 1; + } + } + return 0; +} + + +/* +** This routine decides if pIdx can be used to satisfy the ORDER BY +** clause. If it can, it returns 1. If pIdx cannot satisfy the +** ORDER BY clause, this routine returns 0. +** +** pOrderBy is an ORDER BY clause from a SELECT statement. pTab is the +** left-most table in the FROM clause of that same SELECT statement and +** the table has a cursor number of "base". pIdx is an index on pTab. +** +** nEqCol is the number of columns of pIdx that are used as equality +** constraints. Any of these columns may be missing from the ORDER BY +** clause and the match can still be a success. +** +** All terms of the ORDER BY that match against the index must be either +** ASC or DESC. (Terms of the ORDER BY clause past the end of a UNIQUE +** index do not need to satisfy this constraint.) The *pbRev value is +** set to 1 if the ORDER BY clause is all DESC and it is set to 0 if +** the ORDER BY clause is all ASC. +*/ +static int isSortingIndex( + Parse *pParse, /* Parsing context */ + ExprMaskSet *pMaskSet, /* Mapping from table indices to bitmaps */ + Index *pIdx, /* The index we are testing */ + int base, /* Cursor number for the table to be sorted */ + ExprList *pOrderBy, /* The ORDER BY clause */ + int nEqCol, /* Number of index columns with == constraints */ + int *pbRev /* Set to 1 if ORDER BY is DESC */ +){ + int i, j; /* Loop counters */ + int sortOrder = 0; /* XOR of index and ORDER BY sort direction */ + int nTerm; /* Number of ORDER BY terms */ + struct ExprList_item *pTerm; /* A term of the ORDER BY clause */ + sqlite3 *db = pParse->db; + + assert( pOrderBy!=0 ); + nTerm = pOrderBy->nExpr; + assert( nTerm>0 ); + + /* Match terms of the ORDER BY clause against columns of + ** the index. + ** + ** Note that indices have pIdx->nColumn regular columns plus + ** one additional column containing the rowid. The rowid column + ** of the index is also allowed to match against the ORDER BY + ** clause. + */ + for(i=j=0, pTerm=pOrderBy->a; j<nTerm && i<=pIdx->nColumn; i++){ + Expr *pExpr; /* The expression of the ORDER BY pTerm */ + CollSeq *pColl; /* The collating sequence of pExpr */ + int termSortOrder; /* Sort order for this term */ + int iColumn; /* The i-th column of the index. -1 for rowid */ + int iSortOrder; /* 1 for DESC, 0 for ASC on the i-th index term */ + const char *zColl; /* Name of the collating sequence for i-th index term */ + + pExpr = pTerm->pExpr; + if( pExpr->op!=TK_COLUMN || pExpr->iTable!=base ){ + /* Can not use an index sort on anything that is not a column in the + ** left-most table of the FROM clause */ + break; + } + pColl = sqlite3ExprCollSeq(pParse, pExpr); + if( !pColl ){ + pColl = db->pDfltColl; + } + if( i<pIdx->nColumn ){ + iColumn = pIdx->aiColumn[i]; + if( iColumn==pIdx->pTable->iPKey ){ + iColumn = -1; + } + iSortOrder = pIdx->aSortOrder[i]; + zColl = pIdx->azColl[i]; + }else{ + iColumn = -1; + iSortOrder = 0; + zColl = pColl->zName; + } + if( pExpr->iColumn!=iColumn || sqlite3StrICmp(pColl->zName, zColl) ){ + /* Term j of the ORDER BY clause does not match column i of the index */ + if( i<nEqCol ){ + /* If an index column that is constrained by == fails to match an + ** ORDER BY term, that is OK. Just ignore that column of the index + */ + continue; + }else if( i==pIdx->nColumn ){ + /* Index column i is the rowid. All other terms match. */ + break; + }else{ + /* If an index column fails to match and is not constrained by == + ** then the index cannot satisfy the ORDER BY constraint. + */ + return 0; + } + } + assert( pIdx->aSortOrder!=0 ); + assert( pTerm->sortOrder==0 || pTerm->sortOrder==1 ); + assert( iSortOrder==0 || iSortOrder==1 ); + termSortOrder = iSortOrder ^ pTerm->sortOrder; + if( i>nEqCol ){ + if( termSortOrder!=sortOrder ){ + /* Indices can only be used if all ORDER BY terms past the + ** equality constraints are all either DESC or ASC. */ + return 0; + } + }else{ + sortOrder = termSortOrder; + } + j++; + pTerm++; + if( iColumn<0 && !referencesOtherTables(pOrderBy, pMaskSet, j, base) ){ + /* If the indexed column is the primary key and everything matches + ** so far and none of the ORDER BY terms to the right reference other + ** tables in the join, then we are assured that the index can be used + ** to sort because the primary key is unique and so none of the other + ** columns will make any difference + */ + j = nTerm; + } + } + + *pbRev = sortOrder!=0; + if( j>=nTerm ){ + /* All terms of the ORDER BY clause are covered by this index so + ** this index can be used for sorting. */ + return 1; + } + if( pIdx->onError!=OE_None && i==pIdx->nColumn + && !referencesOtherTables(pOrderBy, pMaskSet, j, base) ){ + /* All terms of this index match some prefix of the ORDER BY clause + ** and the index is UNIQUE and no terms on the tail of the ORDER BY + ** clause reference other tables in a join. If this is all true then + ** the order by clause is superfluous. */ + return 1; + } + return 0; +} + +/* +** Check table to see if the ORDER BY clause in pOrderBy can be satisfied +** by sorting in order of ROWID. Return true if so and set *pbRev to be +** true for reverse ROWID and false for forward ROWID order. +*/ +static int sortableByRowid( + int base, /* Cursor number for table to be sorted */ + ExprList *pOrderBy, /* The ORDER BY clause */ + ExprMaskSet *pMaskSet, /* Mapping from tables to bitmaps */ + int *pbRev /* Set to 1 if ORDER BY is DESC */ +){ + Expr *p; + + assert( pOrderBy!=0 ); + assert( pOrderBy->nExpr>0 ); + p = pOrderBy->a[0].pExpr; + if( p->op==TK_COLUMN && p->iTable==base && p->iColumn==-1 + && !referencesOtherTables(pOrderBy, pMaskSet, 1, base) ){ + *pbRev = pOrderBy->a[0].sortOrder; + return 1; + } + return 0; +} + +/* +** Prepare a crude estimate of the logarithm of the input value. +** The results need not be exact. This is only used for estimating +** the total cost of performing operations with O(logN) or O(NlogN) +** complexity. Because N is just a guess, it is no great tragedy if +** logN is a little off. +*/ +static double estLog(double N){ + double logN = 1; + double x = 10; + while( N>x ){ + logN += 1; + x *= 10; + } + return logN; +} + +/* +** Two routines for printing the content of an sqlite3_index_info +** structure. Used for testing and debugging only. If neither +** SQLITE_TEST or SQLITE_DEBUG are defined, then these routines +** are no-ops. +*/ +#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_DEBUG) +static void TRACE_IDX_INPUTS(sqlite3_index_info *p){ + int i; + if( !sqlite3WhereTrace ) return; + for(i=0; i<p->nConstraint; i++){ + sqlite3DebugPrintf(" constraint[%d]: col=%d termid=%d op=%d usabled=%d\n", + i, + p->aConstraint[i].iColumn, + p->aConstraint[i].iTermOffset, + p->aConstraint[i].op, + p->aConstraint[i].usable); + } + for(i=0; i<p->nOrderBy; i++){ + sqlite3DebugPrintf(" orderby[%d]: col=%d desc=%d\n", + i, + p->aOrderBy[i].iColumn, + p->aOrderBy[i].desc); + } +} +static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){ + int i; + if( !sqlite3WhereTrace ) return; + for(i=0; i<p->nConstraint; i++){ + sqlite3DebugPrintf(" usage[%d]: argvIdx=%d omit=%d\n", + i, + p->aConstraintUsage[i].argvIndex, + p->aConstraintUsage[i].omit); + } + sqlite3DebugPrintf(" idxNum=%d\n", p->idxNum); + sqlite3DebugPrintf(" idxStr=%s\n", p->idxStr); + sqlite3DebugPrintf(" orderByConsumed=%d\n", p->orderByConsumed); + sqlite3DebugPrintf(" estimatedCost=%g\n", p->estimatedCost); +} +#else +#define TRACE_IDX_INPUTS(A) +#define TRACE_IDX_OUTPUTS(A) +#endif + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* +** Compute the best index for a virtual table. +** +** The best index is computed by the xBestIndex method of the virtual +** table module. This routine is really just a wrapper that sets up +** the sqlite3_index_info structure that is used to communicate with +** xBestIndex. +** +** In a join, this routine might be called multiple times for the +** same virtual table. The sqlite3_index_info structure is created +** and initialized on the first invocation and reused on all subsequent +** invocations. The sqlite3_index_info structure is also used when +** code is generated to access the virtual table. The whereInfoDelete() +** routine takes care of freeing the sqlite3_index_info structure after +** everybody has finished with it. +*/ +static double bestVirtualIndex( + Parse *pParse, /* The parsing context */ + WhereClause *pWC, /* The WHERE clause */ + struct SrcList_item *pSrc, /* The FROM clause term to search */ + Bitmask notReady, /* Mask of cursors that are not available */ + ExprList *pOrderBy, /* The order by clause */ + int orderByUsable, /* True if we can potential sort */ + sqlite3_index_info **ppIdxInfo /* Index information passed to xBestIndex */ +){ + Table *pTab = pSrc->pTab; + sqlite3_vtab *pVtab = pTab->pVtab; + sqlite3_index_info *pIdxInfo; + struct sqlite3_index_constraint *pIdxCons; + struct sqlite3_index_orderby *pIdxOrderBy; + struct sqlite3_index_constraint_usage *pUsage; + WhereTerm *pTerm; + int i, j; + int nOrderBy; + int rc; + + /* If the sqlite3_index_info structure has not been previously + ** allocated and initialized for this virtual table, then allocate + ** and initialize it now + */ + pIdxInfo = *ppIdxInfo; + if( pIdxInfo==0 ){ + WhereTerm *pTerm; + int nTerm; + WHERETRACE(("Recomputing index info for %s...\n", pTab->zName)); + + /* Count the number of possible WHERE clause constraints referring + ** to this virtual table */ + for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ + if( pTerm->leftCursor != pSrc->iCursor ) continue; + if( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); + testcase( pTerm->eOperator==WO_IN ); + testcase( pTerm->eOperator==WO_ISNULL ); + if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue; + nTerm++; + } + + /* If the ORDER BY clause contains only columns in the current + ** virtual table then allocate space for the aOrderBy part of + ** the sqlite3_index_info structure. + */ + nOrderBy = 0; + if( pOrderBy ){ + for(i=0; i<pOrderBy->nExpr; i++){ + Expr *pExpr = pOrderBy->a[i].pExpr; + if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break; + } + if( i==pOrderBy->nExpr ){ + nOrderBy = pOrderBy->nExpr; + } + } + + /* Allocate the sqlite3_index_info structure + */ + pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo) + + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm + + sizeof(*pIdxOrderBy)*nOrderBy ); + if( pIdxInfo==0 ){ + sqlite3ErrorMsg(pParse, "out of memory"); + return 0.0; + } + *ppIdxInfo = pIdxInfo; + + /* Initialize the structure. The sqlite3_index_info structure contains + ** many fields that are declared "const" to prevent xBestIndex from + ** changing them. We have to do some funky casting in order to + ** initialize those fields. + */ + pIdxCons = (struct sqlite3_index_constraint*)&pIdxInfo[1]; + pIdxOrderBy = (struct sqlite3_index_orderby*)&pIdxCons[nTerm]; + pUsage = (struct sqlite3_index_constraint_usage*)&pIdxOrderBy[nOrderBy]; + *(int*)&pIdxInfo->nConstraint = nTerm; + *(int*)&pIdxInfo->nOrderBy = nOrderBy; + *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint = pIdxCons; + *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy; + *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage = + pUsage; + + for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ + if( pTerm->leftCursor != pSrc->iCursor ) continue; + if( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); + testcase( pTerm->eOperator==WO_IN ); + testcase( pTerm->eOperator==WO_ISNULL ); + if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue; + pIdxCons[j].iColumn = pTerm->leftColumn; + pIdxCons[j].iTermOffset = i; + pIdxCons[j].op = pTerm->eOperator; + /* The direct assignment in the previous line is possible only because + ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The + ** following asserts verify this fact. */ + assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ ); + assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT ); + assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE ); + assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT ); + assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE ); + assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH ); + assert( pTerm->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) ); + j++; + } + for(i=0; i<nOrderBy; i++){ + Expr *pExpr = pOrderBy->a[i].pExpr; + pIdxOrderBy[i].iColumn = pExpr->iColumn; + pIdxOrderBy[i].desc = pOrderBy->a[i].sortOrder; + } + } + + /* At this point, the sqlite3_index_info structure that pIdxInfo points + ** to will have been initialized, either during the current invocation or + ** during some prior invocation. Now we just have to customize the + ** details of pIdxInfo for the current invocation and pass it to + ** xBestIndex. + */ + + /* The module name must be defined. Also, by this point there must + ** be a pointer to an sqlite3_vtab structure. Otherwise + ** sqlite3ViewGetColumnNames() would have picked up the error. + */ + assert( pTab->azModuleArg && pTab->azModuleArg[0] ); + assert( pVtab ); +#if 0 + if( pTab->pVtab==0 ){ + sqlite3ErrorMsg(pParse, "undefined module %s for table %s", + pTab->azModuleArg[0], pTab->zName); + return 0.0; + } +#endif + + /* Set the aConstraint[].usable fields and initialize all + ** output variables to zero. + ** + ** aConstraint[].usable is true for constraints where the right-hand + ** side contains only references to tables to the left of the current + ** table. In other words, if the constraint is of the form: + ** + ** column = expr + ** + ** and we are evaluating a join, then the constraint on column is + ** only valid if all tables referenced in expr occur to the left + ** of the table containing column. + ** + ** The aConstraints[] array contains entries for all constraints + ** on the current table. That way we only have to compute it once + ** even though we might try to pick the best index multiple times. + ** For each attempt at picking an index, the order of tables in the + ** join might be different so we have to recompute the usable flag + ** each time. + */ + pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; + pUsage = pIdxInfo->aConstraintUsage; + for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){ + j = pIdxCons->iTermOffset; + pTerm = &pWC->a[j]; + pIdxCons->usable = (pTerm->prereqRight & notReady)==0; + } + memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint); + if( pIdxInfo->needToFreeIdxStr ){ + sqlite3_free(pIdxInfo->idxStr); + } + pIdxInfo->idxStr = 0; + pIdxInfo->idxNum = 0; + pIdxInfo->needToFreeIdxStr = 0; + pIdxInfo->orderByConsumed = 0; + pIdxInfo->estimatedCost = SQLITE_BIG_DBL / 2.0; + nOrderBy = pIdxInfo->nOrderBy; + if( pIdxInfo->nOrderBy && !orderByUsable ){ + *(int*)&pIdxInfo->nOrderBy = 0; + } + + (void)sqlite3SafetyOff(pParse->db); + WHERETRACE(("xBestIndex for %s\n", pTab->zName)); + TRACE_IDX_INPUTS(pIdxInfo); + rc = pVtab->pModule->xBestIndex(pVtab, pIdxInfo); + TRACE_IDX_OUTPUTS(pIdxInfo); + (void)sqlite3SafetyOn(pParse->db); + + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_NOMEM ){ + pParse->db->mallocFailed = 1; + }else if( !pVtab->zErrMsg ){ + sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc)); + }else{ + sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg); + } + } + sqlite3DbFree(pParse->db, pVtab->zErrMsg); + pVtab->zErrMsg = 0; + + for(i=0; i<pIdxInfo->nConstraint; i++){ + if( !pIdxInfo->aConstraint[i].usable && pUsage[i].argvIndex>0 ){ + sqlite3ErrorMsg(pParse, + "table %s: xBestIndex returned an invalid plan", pTab->zName); + return 0.0; + } + } + + *(int*)&pIdxInfo->nOrderBy = nOrderBy; + return pIdxInfo->estimatedCost; +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +/* +** Find the best index for accessing a particular table. Return a pointer +** to the index, flags that describe how the index should be used, the +** number of equality constraints, and the "cost" for this index. +** +** The lowest cost index wins. The cost is an estimate of the amount of +** CPU and disk I/O need to process the request using the selected index. +** Factors that influence cost include: +** +** * The estimated number of rows that will be retrieved. (The +** fewer the better.) +** +** * Whether or not sorting must occur. +** +** * Whether or not there must be separate lookups in the +** index and in the main table. +** +*/ +static double bestIndex( + Parse *pParse, /* The parsing context */ + WhereClause *pWC, /* The WHERE clause */ + struct SrcList_item *pSrc, /* The FROM clause term to search */ + Bitmask notReady, /* Mask of cursors that are not available */ + ExprList *pOrderBy, /* The order by clause */ + Index **ppIndex, /* Make *ppIndex point to the best index */ + int *pFlags, /* Put flags describing this choice in *pFlags */ + int *pnEq /* Put the number of == or IN constraints here */ +){ + WhereTerm *pTerm; + Index *bestIdx = 0; /* Index that gives the lowest cost */ + double lowestCost; /* The cost of using bestIdx */ + int bestFlags = 0; /* Flags associated with bestIdx */ + int bestNEq = 0; /* Best value for nEq */ + int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */ + Index *pProbe; /* An index we are evaluating */ + int rev; /* True to scan in reverse order */ + int flags; /* Flags associated with pProbe */ + int nEq; /* Number of == or IN constraints */ + int eqTermMask; /* Mask of valid equality operators */ + double cost; /* Cost of using pProbe */ + + WHERETRACE(("bestIndex: tbl=%s notReady=%llx\n", pSrc->pTab->zName, notReady)); + lowestCost = SQLITE_BIG_DBL; + pProbe = pSrc->pTab->pIndex; + + /* If the table has no indices and there are no terms in the where + ** clause that refer to the ROWID, then we will never be able to do + ** anything other than a full table scan on this table. We might as + ** well put it first in the join order. That way, perhaps it can be + ** referenced by other tables in the join. + */ + if( pProbe==0 && + findTerm(pWC, iCur, -1, 0, WO_EQ|WO_IN|WO_LT|WO_LE|WO_GT|WO_GE,0)==0 && + (pOrderBy==0 || !sortableByRowid(iCur, pOrderBy, pWC->pMaskSet, &rev)) ){ + *pFlags = 0; + *ppIndex = 0; + *pnEq = 0; + return 0.0; + } + + /* Check for a rowid=EXPR or rowid IN (...) constraints + */ + pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0); + if( pTerm ){ + Expr *pExpr; + *ppIndex = 0; + bestFlags = WHERE_ROWID_EQ; + if( pTerm->eOperator & WO_EQ ){ + /* Rowid== is always the best pick. Look no further. Because only + ** a single row is generated, output is always in sorted order */ + *pFlags = WHERE_ROWID_EQ | WHERE_UNIQUE; + *pnEq = 1; + WHERETRACE(("... best is rowid\n")); + return 0.0; + }else if( (pExpr = pTerm->pExpr)->pList!=0 ){ + /* Rowid IN (LIST): cost is NlogN where N is the number of list + ** elements. */ + lowestCost = pExpr->pList->nExpr; + lowestCost *= estLog(lowestCost); + }else{ + /* Rowid IN (SELECT): cost is NlogN where N is the number of rows + ** in the result of the inner select. We have no way to estimate + ** that value so make a wild guess. */ + lowestCost = 200; + } + WHERETRACE(("... rowid IN cost: %.9g\n", lowestCost)); + } + + /* Estimate the cost of a table scan. If we do not know how many + ** entries are in the table, use 1 million as a guess. + */ + cost = pProbe ? pProbe->aiRowEst[0] : 1000000; + WHERETRACE(("... table scan base cost: %.9g\n", cost)); + flags = WHERE_ROWID_RANGE; + + /* Check for constraints on a range of rowids in a table scan. + */ + pTerm = findTerm(pWC, iCur, -1, notReady, WO_LT|WO_LE|WO_GT|WO_GE, 0); + if( pTerm ){ + if( findTerm(pWC, iCur, -1, notReady, WO_LT|WO_LE, 0) ){ + flags |= WHERE_TOP_LIMIT; + cost /= 3; /* Guess that rowid<EXPR eliminates two-thirds or rows */ + } + if( findTerm(pWC, iCur, -1, notReady, WO_GT|WO_GE, 0) ){ + flags |= WHERE_BTM_LIMIT; + cost /= 3; /* Guess that rowid>EXPR eliminates two-thirds of rows */ + } + WHERETRACE(("... rowid range reduces cost to %.9g\n", cost)); + }else{ + flags = 0; + } + + /* If the table scan does not satisfy the ORDER BY clause, increase + ** the cost by NlogN to cover the expense of sorting. */ + if( pOrderBy ){ + if( sortableByRowid(iCur, pOrderBy, pWC->pMaskSet, &rev) ){ + flags |= WHERE_ORDERBY|WHERE_ROWID_RANGE; + if( rev ){ + flags |= WHERE_REVERSE; + } + }else{ + cost += cost*estLog(cost); + WHERETRACE(("... sorting increases cost to %.9g\n", cost)); + } + } + if( cost<lowestCost ){ + lowestCost = cost; + bestFlags = flags; + } + + /* If the pSrc table is the right table of a LEFT JOIN then we may not + ** use an index to satisfy IS NULL constraints on that table. This is + ** because columns might end up being NULL if the table does not match - + ** a circumstance which the index cannot help us discover. Ticket #2177. + */ + if( (pSrc->jointype & JT_LEFT)!=0 ){ + eqTermMask = WO_EQ|WO_IN; + }else{ + eqTermMask = WO_EQ|WO_IN|WO_ISNULL; + } + + /* Look at each index. + */ + for(; pProbe; pProbe=pProbe->pNext){ + int i; /* Loop counter */ + double inMultiplier = 1; + + WHERETRACE(("... index %s:\n", pProbe->zName)); + + /* Count the number of columns in the index that are satisfied + ** by x=EXPR constraints or x IN (...) constraints. + */ + flags = 0; + for(i=0; i<pProbe->nColumn; i++){ + int j = pProbe->aiColumn[i]; + pTerm = findTerm(pWC, iCur, j, notReady, eqTermMask, pProbe); + if( pTerm==0 ) break; + flags |= WHERE_COLUMN_EQ; + if( pTerm->eOperator & WO_IN ){ + Expr *pExpr = pTerm->pExpr; + flags |= WHERE_COLUMN_IN; + if( pExpr->pSelect!=0 ){ + inMultiplier *= 25; + }else if( ALWAYS(pExpr->pList) ){ + inMultiplier *= pExpr->pList->nExpr + 1; + } + } + } + cost = pProbe->aiRowEst[i] * inMultiplier * estLog(inMultiplier); + nEq = i; + if( pProbe->onError!=OE_None && (flags & WHERE_COLUMN_IN)==0 + && nEq==pProbe->nColumn ){ + flags |= WHERE_UNIQUE; + } + WHERETRACE(("...... nEq=%d inMult=%.9g cost=%.9g\n",nEq,inMultiplier,cost)); + + /* Look for range constraints + */ + if( nEq<pProbe->nColumn ){ + int j = pProbe->aiColumn[nEq]; + pTerm = findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE|WO_GT|WO_GE, pProbe); + if( pTerm ){ + flags |= WHERE_COLUMN_RANGE; + if( findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE, pProbe) ){ + flags |= WHERE_TOP_LIMIT; + cost /= 3; + } + if( findTerm(pWC, iCur, j, notReady, WO_GT|WO_GE, pProbe) ){ + flags |= WHERE_BTM_LIMIT; + cost /= 3; + } + WHERETRACE(("...... range reduces cost to %.9g\n", cost)); + } + } + + /* Add the additional cost of sorting if that is a factor. + */ + if( pOrderBy ){ + if( (flags & WHERE_COLUMN_IN)==0 && + isSortingIndex(pParse,pWC->pMaskSet,pProbe,iCur,pOrderBy,nEq,&rev) ){ + if( flags==0 ){ + flags = WHERE_COLUMN_RANGE; + } + flags |= WHERE_ORDERBY; + if( rev ){ + flags |= WHERE_REVERSE; + } + }else{ + cost += cost*estLog(cost); + WHERETRACE(("...... orderby increases cost to %.9g\n", cost)); + } + } + + /* Check to see if we can get away with using just the index without + ** ever reading the table. If that is the case, then halve the + ** cost of this index. + */ + if( flags && pSrc->colUsed < (((Bitmask)1)<<(BMS-1)) ){ + Bitmask m = pSrc->colUsed; + int j; + for(j=0; j<pProbe->nColumn; j++){ + int x = pProbe->aiColumn[j]; + if( x<BMS-1 ){ + m &= ~(((Bitmask)1)<<x); + } + } + if( m==0 ){ + flags |= WHERE_IDX_ONLY; + cost /= 2; + WHERETRACE(("...... idx-only reduces cost to %.9g\n", cost)); + } + } + + /* If this index has achieved the lowest cost so far, then use it. + */ + if( flags && cost < lowestCost ){ + bestIdx = pProbe; + lowestCost = cost; + bestFlags = flags; + bestNEq = nEq; + } + } + + /* Report the best result + */ + *ppIndex = bestIdx; + WHERETRACE(("best index is %s, cost=%.9g, flags=%x, nEq=%d\n", + bestIdx ? bestIdx->zName : "(none)", lowestCost, bestFlags, bestNEq)); + *pFlags = bestFlags | eqTermMask; + *pnEq = bestNEq; + return lowestCost; +} + + +/* +** Disable a term in the WHERE clause. Except, do not disable the term +** if it controls a LEFT OUTER JOIN and it did not originate in the ON +** or USING clause of that join. +** +** Consider the term t2.z='ok' in the following queries: +** +** (1) SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x WHERE t2.z='ok' +** (2) SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x AND t2.z='ok' +** (3) SELECT * FROM t1, t2 WHERE t1.a=t2.x AND t2.z='ok' +** +** The t2.z='ok' is disabled in the in (2) because it originates +** in the ON clause. The term is disabled in (3) because it is not part +** of a LEFT OUTER JOIN. In (1), the term is not disabled. +** +** Disabling a term causes that term to not be tested in the inner loop +** of the join. Disabling is an optimization. When terms are satisfied +** by indices, we disable them to prevent redundant tests in the inner +** loop. We would get the correct results if nothing were ever disabled, +** but joins might run a little slower. The trick is to disable as much +** as we can without disabling too much. If we disabled in (1), we'd get +** the wrong answer. See ticket #813. +*/ +static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){ + if( pTerm + && ALWAYS((pTerm->flags & TERM_CODED)==0) + && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin)) + ){ + pTerm->flags |= TERM_CODED; + if( pTerm->iParent>=0 ){ + WhereTerm *pOther = &pTerm->pWC->a[pTerm->iParent]; + if( (--pOther->nChild)==0 ){ + disableTerm(pLevel, pOther); + } + } + } +} + +/* +** Apply the affinities associated with the first n columns of index +** pIdx to the values in the n registers starting at base. +*/ +static void codeApplyAffinity(Parse *pParse, int base, int n, Index *pIdx){ + if( n>0 ){ + Vdbe *v = pParse->pVdbe; + assert( v!=0 ); + sqlite3VdbeAddOp2(v, OP_Affinity, base, n); + sqlite3IndexAffinityStr(v, pIdx); + sqlite3ExprCacheAffinityChange(pParse, base, n); + } +} + + +/* +** Generate code for a single equality term of the WHERE clause. An equality +** term can be either X=expr or X IN (...). pTerm is the term to be +** coded. +** +** The current value for the constraint is left in register iReg. +** +** For a constraint of the form X=expr, the expression is evaluated and its +** result is left on the stack. For constraints of the form X IN (...) +** this routine sets up a loop that will iterate over all values of X. +*/ +static int codeEqualityTerm( + Parse *pParse, /* The parsing context */ + WhereTerm *pTerm, /* The term of the WHERE clause to be coded */ + WhereLevel *pLevel, /* When level of the FROM clause we are working on */ + int iTarget /* Attempt to leave results in this register */ +){ + Expr *pX = pTerm->pExpr; + Vdbe *v = pParse->pVdbe; + int iReg; /* Register holding results */ + + if( iTarget<=0 ){ + iReg = iTarget = sqlite3GetTempReg(pParse); + } + if( pX->op==TK_EQ ){ + iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget); + }else if( pX->op==TK_ISNULL ){ + iReg = iTarget; + sqlite3VdbeAddOp2(v, OP_Null, 0, iReg); +#ifndef SQLITE_OMIT_SUBQUERY + }else{ + int eType; + int iTab; + struct InLoop *pIn; + + assert( pX->op==TK_IN ); + iReg = iTarget; + eType = sqlite3FindInIndex(pParse, pX, 0); + iTab = pX->iTable; + sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); + VdbeComment((v, "%.*s", pX->span.n, pX->span.z)); + if( pLevel->nIn==0 ){ + pLevel->nxt = sqlite3VdbeMakeLabel(v); + } + pLevel->nIn++; + pLevel->aInLoop = sqlite3DbReallocOrFree(pParse->db, pLevel->aInLoop, + sizeof(pLevel->aInLoop[0])*pLevel->nIn); + pIn = pLevel->aInLoop; + if( pIn ){ + pIn += pLevel->nIn - 1; + pIn->iCur = iTab; + if( eType==IN_INDEX_ROWID ){ + pIn->topAddr = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iReg); + }else{ + pIn->topAddr = sqlite3VdbeAddOp3(v, OP_Column, iTab, 0, iReg); + } + sqlite3VdbeAddOp1(v, OP_IsNull, iReg); + }else{ + pLevel->nIn = 0; + } +#endif + } + disableTerm(pLevel, pTerm); + return iReg; +} + +/* +** Generate code that will evaluate all == and IN constraints for an +** index. The values for all constraints are left on the stack. +** +** For example, consider table t1(a,b,c,d,e,f) with index i1(a,b,c). +** Suppose the WHERE clause is this: a==5 AND b IN (1,2,3) AND c>5 AND c<10 +** The index has as many as three equality constraints, but in this +** example, the third "c" value is an inequality. So only two +** constraints are coded. This routine will generate code to evaluate +** a==5 and b IN (1,2,3). The current values for a and b will be left +** on the stack - a is the deepest and b the shallowest. +** +** In the example above nEq==2. But this subroutine works for any value +** of nEq including 0. If nEq==0, this routine is nearly a no-op. +** The only thing it does is allocate the pLevel->iMem memory cell. +** +** This routine always allocates at least one memory cell and puts +** the address of that memory cell in pLevel->iMem. The code that +** calls this routine will use pLevel->iMem to store the termination +** key value of the loop. If one or more IN operators appear, then +** this routine allocates an additional nEq memory cells for internal +** use. +*/ +static int codeAllEqualityTerms( + Parse *pParse, /* Parsing context */ + WhereLevel *pLevel, /* Which nested loop of the FROM we are coding */ + WhereClause *pWC, /* The WHERE clause */ + Bitmask notReady, /* Which parts of FROM have not yet been coded */ + int nExtraReg /* Number of extra registers to allocate */ +){ + int nEq = pLevel->nEq; /* The number of == or IN constraints to code */ + Vdbe *v = pParse->pVdbe; /* The virtual machine under construction */ + Index *pIdx = pLevel->pIdx; /* The index being used for this loop */ + int iCur = pLevel->iTabCur; /* The cursor of the table */ + WhereTerm *pTerm; /* A single constraint term */ + int j; /* Loop counter */ + int regBase; /* Base register */ + + /* Figure out how many memory cells we will need then allocate them. + ** We always need at least one used to store the loop terminator + ** value. If there are IN operators we'll need one for each == or + ** IN constraint. + */ + pLevel->iMem = pParse->nMem + 1; + regBase = pParse->nMem + 2; + pParse->nMem += pLevel->nEq + 2 + nExtraReg; + + /* Evaluate the equality constraints + */ + assert( pIdx->nColumn>=nEq ); + for(j=0; j<nEq; j++){ + int r1; + int k = pIdx->aiColumn[j]; + pTerm = findTerm(pWC, iCur, k, notReady, pLevel->flags, pIdx); + if( NEVER(pTerm==0) ) break; + assert( (pTerm->flags & TERM_CODED)==0 ); + r1 = codeEqualityTerm(pParse, pTerm, pLevel, regBase+j); + if( r1!=regBase+j ){ + sqlite3VdbeAddOp2(v, OP_SCopy, r1, regBase+j); + } + testcase( pTerm->eOperator & WO_ISNULL ); + testcase( pTerm->eOperator & WO_IN ); + if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){ + sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->brk); + } + } + return regBase; +} + +#if defined(SQLITE_TEST) +/* +** The following variable holds a text description of query plan generated +** by the most recent call to sqlite3WhereBegin(). Each call to WhereBegin +** overwrites the previous. This information is used for testing and +** analysis only. +*/ +char sqlite3_query_plan[BMS*2*40]; /* Text of the join */ +static int nQPlan = 0; /* Next free slow in _query_plan[] */ + +#endif /* SQLITE_TEST */ + + +/* +** Free a WhereInfo structure +*/ +static void whereInfoFree(WhereInfo *pWInfo){ + if( pWInfo ){ + int i; + sqlite3 *db = pWInfo->pParse->db; + for(i=0; i<pWInfo->nLevel; i++){ + sqlite3_index_info *pInfo = pWInfo->a[i].pIdxInfo; + if( pInfo ){ + assert( pInfo->needToFreeIdxStr==0 ); + sqlite3DbFree(db, pInfo); + } + } + sqlite3DbFree(db, pWInfo); + } +} + + +/* +** Generate the beginning of the loop used for WHERE clause processing. +** The return value is a pointer to an opaque structure that contains +** information needed to terminate the loop. Later, the calling routine +** should invoke sqlite3WhereEnd() with the return value of this function +** in order to complete the WHERE clause processing. +** +** If an error occurs, this routine returns NULL. +** +** The basic idea is to do a nested loop, one loop for each table in +** the FROM clause of a select. (INSERT and UPDATE statements are the +** same as a SELECT with only a single table in the FROM clause.) For +** example, if the SQL is this: +** +** SELECT * FROM t1, t2, t3 WHERE ...; +** +** Then the code generated is conceptually like the following: +** +** foreach row1 in t1 do \ Code generated +** foreach row2 in t2 do |-- by sqlite3WhereBegin() +** foreach row3 in t3 do / +** ... +** end \ Code generated +** end |-- by sqlite3WhereEnd() +** end / +** +** Note that the loops might not be nested in the order in which they +** appear in the FROM clause if a different order is better able to make +** use of indices. Note also that when the IN operator appears in +** the WHERE clause, it might result in additional nested loops for +** scanning through all values on the right-hand side of the IN. +** +** There are Btree cursors associated with each table. t1 uses cursor +** number pTabList->a[0].iCursor. t2 uses the cursor pTabList->a[1].iCursor. +** And so forth. This routine generates code to open those VDBE cursors +** and sqlite3WhereEnd() generates the code to close them. +** +** The code that sqlite3WhereBegin() generates leaves the cursors named +** in pTabList pointing at their appropriate entries. The [...] code +** can use OP_Column and OP_Rowid opcodes on these cursors to extract +** data from the various tables of the loop. +** +** If the WHERE clause is empty, the foreach loops must each scan their +** entire tables. Thus a three-way join is an O(N^3) operation. But if +** the tables have indices and there are terms in the WHERE clause that +** refer to those indices, a complete table scan can be avoided and the +** code will run much faster. Most of the work of this routine is checking +** to see if there are indices that can be used to speed up the loop. +** +** Terms of the WHERE clause are also used to limit which rows actually +** make it to the "..." in the middle of the loop. After each "foreach", +** terms of the WHERE clause that use only terms in that loop and outer +** loops are evaluated and if false a jump is made around all subsequent +** inner loops (or around the "..." if the test occurs within the inner- +** most loop) +** +** OUTER JOINS +** +** An outer join of tables t1 and t2 is conceptally coded as follows: +** +** foreach row1 in t1 do +** flag = 0 +** foreach row2 in t2 do +** start: +** ... +** flag = 1 +** end +** if flag==0 then +** move the row2 cursor to a null row +** goto start +** fi +** end +** +** ORDER BY CLAUSE PROCESSING +** +** *ppOrderBy is a pointer to the ORDER BY clause of a SELECT statement, +** if there is one. If there is no ORDER BY clause or if this routine +** is called from an UPDATE or DELETE statement, then ppOrderBy is NULL. +** +** If an index can be used so that the natural output order of the table +** scan is correct for the ORDER BY clause, then that index is used and +** *ppOrderBy is set to NULL. This is an optimization that prevents an +** unnecessary sort of the result set if an index appropriate for the +** ORDER BY clause already exists. +** +** If the where clause loops cannot be arranged to provide the correct +** output order, then the *ppOrderBy is unchanged. +*/ +WhereInfo *sqlite3WhereBegin( + Parse *pParse, /* The parser context */ + SrcList *pTabList, /* A list of all tables to be scanned */ + Expr *pWhere, /* The WHERE clause */ + ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */ + u8 wflags /* One of the WHERE_* flags defined in sqliteInt.h */ +){ + int i; /* Loop counter */ + WhereInfo *pWInfo; /* Will become the return value of this function */ + Vdbe *v = pParse->pVdbe; /* The virtual database engine */ + int brk, cont = 0; /* Addresses used during code generation */ + Bitmask notReady; /* Cursors that are not yet positioned */ + WhereTerm *pTerm; /* A single term in the WHERE clause */ + ExprMaskSet maskSet; /* The expression mask set */ + WhereClause wc; /* The WHERE clause is divided into these terms */ + struct SrcList_item *pTabItem; /* A single entry from pTabList */ + WhereLevel *pLevel; /* A single level in the pWInfo list */ + int iFrom; /* First unused FROM clause element */ + int andFlags; /* AND-ed combination of all wc.a[].flags */ + sqlite3 *db; /* Database connection */ + ExprList *pOrderBy = 0; + + /* The number of tables in the FROM clause is limited by the number of + ** bits in a Bitmask + */ + if( pTabList->nSrc>BMS ){ + sqlite3ErrorMsg(pParse, "at most %d tables in a join", BMS); + return 0; + } + + if( ppOrderBy ){ + pOrderBy = *ppOrderBy; + } + + /* Split the WHERE clause into separate subexpressions where each + ** subexpression is separated by an AND operator. + */ + initMaskSet(&maskSet); + whereClauseInit(&wc, pParse, &maskSet); + sqlite3ExprCodeConstants(pParse, pWhere); + whereSplit(&wc, pWhere, TK_AND); + + /* Allocate and initialize the WhereInfo structure that will become the + ** return value. + */ + db = pParse->db; + pWInfo = sqlite3DbMallocZero(db, + sizeof(WhereInfo) + pTabList->nSrc*sizeof(WhereLevel)); + if( db->mallocFailed ){ + goto whereBeginNoMem; + } + pWInfo->nLevel = pTabList->nSrc; + pWInfo->pParse = pParse; + pWInfo->pTabList = pTabList; + pWInfo->iBreak = sqlite3VdbeMakeLabel(v); + + /* Special case: a WHERE clause that is constant. Evaluate the + ** expression and either jump over all of the code or fall thru. + */ + if( pWhere && (pTabList->nSrc==0 || sqlite3ExprIsConstantNotJoin(pWhere)) ){ + sqlite3ExprIfFalse(pParse, pWhere, pWInfo->iBreak, SQLITE_JUMPIFNULL); + pWhere = 0; + } + + /* Assign a bit from the bitmask to every term in the FROM clause. + ** + ** When assigning bitmask values to FROM clause cursors, it must be + ** the case that if X is the bitmask for the N-th FROM clause term then + ** the bitmask for all FROM clause terms to the left of the N-th term + ** is (X-1). An expression from the ON clause of a LEFT JOIN can use + ** its Expr.iRightJoinTable value to find the bitmask of the right table + ** of the join. Subtracting one from the right table bitmask gives a + ** bitmask for all tables to the left of the join. Knowing the bitmask + ** for all tables to the left of a left join is important. Ticket #3015. + */ + for(i=0; i<pTabList->nSrc; i++){ + createMask(&maskSet, pTabList->a[i].iCursor); + } +#ifndef NDEBUG + { + Bitmask toTheLeft = 0; + for(i=0; i<pTabList->nSrc; i++){ + Bitmask m = getMask(&maskSet, pTabList->a[i].iCursor); + assert( (m-1)==toTheLeft ); + toTheLeft |= m; + } + } +#endif + + /* Analyze all of the subexpressions. Note that exprAnalyze() might + ** add new virtual terms onto the end of the WHERE clause. We do not + ** want to analyze these virtual terms, so start analyzing at the end + ** and work forward so that the added virtual terms are never processed. + */ + exprAnalyzeAll(pTabList, &wc); + if( db->mallocFailed ){ + goto whereBeginNoMem; + } + + /* Chose the best index to use for each table in the FROM clause. + ** + ** This loop fills in the following fields: + ** + ** pWInfo->a[].pIdx The index to use for this level of the loop. + ** pWInfo->a[].flags WHERE_xxx flags associated with pIdx + ** pWInfo->a[].nEq The number of == and IN constraints + ** pWInfo->a[].iFrom When term of the FROM clause is being coded + ** pWInfo->a[].iTabCur The VDBE cursor for the database table + ** pWInfo->a[].iIdxCur The VDBE cursor for the index + ** + ** This loop also figures out the nesting order of tables in the FROM + ** clause. + */ + notReady = ~(Bitmask)0; + pTabItem = pTabList->a; + pLevel = pWInfo->a; + andFlags = ~0; + WHERETRACE(("*** Optimizer Start ***\n")); + for(i=iFrom=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){ + Index *pIdx; /* Index for FROM table at pTabItem */ + int flags; /* Flags asssociated with pIdx */ + int nEq; /* Number of == or IN constraints */ + double cost; /* The cost for pIdx */ + int j; /* For looping over FROM tables */ + Index *pBest = 0; /* The best index seen so far */ + int bestFlags = 0; /* Flags associated with pBest */ + int bestNEq = 0; /* nEq associated with pBest */ + double lowestCost; /* Cost of the pBest */ + int bestJ = 0; /* The value of j */ + Bitmask m; /* Bitmask value for j or bestJ */ + int once = 0; /* True when first table is seen */ + sqlite3_index_info *pIndex; /* Current virtual index */ + + lowestCost = SQLITE_BIG_DBL; + for(j=iFrom, pTabItem=&pTabList->a[j]; j<pTabList->nSrc; j++, pTabItem++){ + int doNotReorder; /* True if this table should not be reordered */ + + doNotReorder = (pTabItem->jointype & (JT_LEFT|JT_CROSS))!=0; + if( once && doNotReorder ) break; + m = getMask(&maskSet, pTabItem->iCursor); + if( (m & notReady)==0 ){ + if( j==iFrom ) iFrom++; + continue; + } + assert( pTabItem->pTab ); +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( IsVirtual(pTabItem->pTab) ){ + sqlite3_index_info **ppIdxInfo = &pWInfo->a[j].pIdxInfo; + cost = bestVirtualIndex(pParse, &wc, pTabItem, notReady, + ppOrderBy ? *ppOrderBy : 0, i==0, + ppIdxInfo); + flags = WHERE_VIRTUALTABLE; + pIndex = *ppIdxInfo; + if( pIndex && pIndex->orderByConsumed ){ + flags = WHERE_VIRTUALTABLE | WHERE_ORDERBY; + } + pIdx = 0; + nEq = 0; + if( (SQLITE_BIG_DBL/2.0)<cost ){ + /* The cost is not allowed to be larger than SQLITE_BIG_DBL (the + ** inital value of lowestCost in this loop. If it is, then + ** the (cost<lowestCost) test below will never be true and + ** pLevel->pBestIdx never set. + */ + cost = (SQLITE_BIG_DBL/2.0); + } + }else +#endif + { + cost = bestIndex(pParse, &wc, pTabItem, notReady, + (i==0 && ppOrderBy) ? *ppOrderBy : 0, + &pIdx, &flags, &nEq); + pIndex = 0; + } + if( cost<lowestCost ){ + once = 1; + lowestCost = cost; + pBest = pIdx; + bestFlags = flags; + bestNEq = nEq; + bestJ = j; + pLevel->pBestIdx = pIndex; + } + if( doNotReorder ) break; + } + WHERETRACE(("*** Optimizer selects table %d for loop %d\n", bestJ, + pLevel-pWInfo->a)); + if( (bestFlags & WHERE_ORDERBY)!=0 ){ + *ppOrderBy = 0; + } + andFlags &= bestFlags; + pLevel->flags = bestFlags; + pLevel->pIdx = pBest; + pLevel->nEq = bestNEq; + pLevel->aInLoop = 0; + pLevel->nIn = 0; + if( pBest ){ + pLevel->iIdxCur = pParse->nTab++; + }else{ + pLevel->iIdxCur = -1; + } + notReady &= ~getMask(&maskSet, pTabList->a[bestJ].iCursor); + pLevel->iFrom = bestJ; + } + WHERETRACE(("*** Optimizer Finished ***\n")); + + /* If the total query only selects a single row, then the ORDER BY + ** clause is irrelevant. + */ + if( (andFlags & WHERE_UNIQUE)!=0 && ppOrderBy ){ + *ppOrderBy = 0; + } + + /* If the caller is an UPDATE or DELETE statement that is requesting + ** to use a one-pass algorithm, determine if this is appropriate. + ** The one-pass algorithm only works if the WHERE clause constraints + ** the statement to update a single row. + */ + assert( (wflags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 ); + if( (wflags & WHERE_ONEPASS_DESIRED)!=0 && (andFlags & WHERE_UNIQUE)!=0 ){ + pWInfo->okOnePass = 1; + pWInfo->a[0].flags &= ~WHERE_IDX_ONLY; + } + + /* Open all tables in the pTabList and any indices selected for + ** searching those tables. + */ + sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */ + for(i=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){ + Table *pTab; /* Table to open */ + Index *pIx; /* Index used to access pTab (if any) */ + int iDb; /* Index of database containing table/index */ + int iIdxCur = pLevel->iIdxCur; + +#ifndef SQLITE_OMIT_EXPLAIN + if( pParse->explain==2 ){ + char *zMsg; + struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom]; + zMsg = sqlite3MPrintf(db, "TABLE %s", pItem->zName); + if( pItem->zAlias ){ + zMsg = sqlite3MAppendf(db, zMsg, "%s AS %s", zMsg, pItem->zAlias); + } + if( (pIx = pLevel->pIdx)!=0 ){ + zMsg = sqlite3MAppendf(db, zMsg, "%s WITH INDEX %s", zMsg, pIx->zName); + }else if( pLevel->flags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){ + zMsg = sqlite3MAppendf(db, zMsg, "%s USING PRIMARY KEY", zMsg); + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + else if( pLevel->pBestIdx ){ + sqlite3_index_info *pBestIdx = pLevel->pBestIdx; + zMsg = sqlite3MAppendf(db, zMsg, "%s VIRTUAL TABLE INDEX %d:%s", zMsg, + pBestIdx->idxNum, pBestIdx->idxStr); + } +#endif + if( pLevel->flags & WHERE_ORDERBY ){ + zMsg = sqlite3MAppendf(db, zMsg, "%s ORDER BY", zMsg); + } + sqlite3VdbeAddOp4(v, OP_Explain, i, pLevel->iFrom, 0, zMsg, P4_DYNAMIC); + } +#endif /* SQLITE_OMIT_EXPLAIN */ + pTabItem = &pTabList->a[pLevel->iFrom]; + pTab = pTabItem->pTab; + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + if( pTab->isEphem || pTab->pSelect ) continue; +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( pLevel->pBestIdx ){ + int iCur = pTabItem->iCursor; + sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, + (const char*)pTab->pVtab, P4_VTAB); + }else +#endif + if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){ + int op = pWInfo->okOnePass ? OP_OpenWrite : OP_OpenRead; + sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op); + if( !pWInfo->okOnePass && pTab->nCol<(sizeof(Bitmask)*8) ){ + Bitmask b = pTabItem->colUsed; + int n = 0; + for(; b; b=b>>1, n++){} + sqlite3VdbeChangeP2(v, sqlite3VdbeCurrentAddr(v)-2, n); + assert( n<=pTab->nCol ); + } + }else{ + sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); + } + pLevel->iTabCur = pTabItem->iCursor; + if( (pIx = pLevel->pIdx)!=0 ){ + KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIx); + assert( pIx->pSchema==pTab->pSchema ); + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pIx->nColumn+1); + sqlite3VdbeAddOp4(v, OP_OpenRead, iIdxCur, pIx->tnum, iDb, + (char*)pKey, P4_KEYINFO_HANDOFF); + VdbeComment((v, "%s", pIx->zName)); + } + sqlite3CodeVerifySchema(pParse, iDb); + } + pWInfo->iTop = sqlite3VdbeCurrentAddr(v); + + /* Generate the code to do the search. Each iteration of the for + ** loop below generates code for a single nested loop of the VM + ** program. + */ + notReady = ~(Bitmask)0; + for(i=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){ + int j; + int iCur = pTabItem->iCursor; /* The VDBE cursor for the table */ + Index *pIdx; /* The index we will be using */ + int nxt; /* Where to jump to continue with the next IN case */ + int iIdxCur; /* The VDBE cursor for the index */ + int omitTable; /* True if we use the index only */ + int bRev; /* True if we need to scan in reverse order */ + + pTabItem = &pTabList->a[pLevel->iFrom]; + iCur = pTabItem->iCursor; + pIdx = pLevel->pIdx; + iIdxCur = pLevel->iIdxCur; + bRev = (pLevel->flags & WHERE_REVERSE)!=0; + omitTable = (pLevel->flags & WHERE_IDX_ONLY)!=0; + + /* Create labels for the "break" and "continue" instructions + ** for the current loop. Jump to brk to break out of a loop. + ** Jump to cont to go immediately to the next iteration of the + ** loop. + ** + ** When there is an IN operator, we also have a "nxt" label that + ** means to continue with the next IN value combination. When + ** there are no IN operators in the constraints, the "nxt" label + ** is the same as "brk". + */ + brk = pLevel->brk = pLevel->nxt = sqlite3VdbeMakeLabel(v); + cont = pLevel->cont = sqlite3VdbeMakeLabel(v); + + /* If this is the right table of a LEFT OUTER JOIN, allocate and + ** initialize a memory cell that records if this table matches any + ** row of the left table of the join. + */ + if( pLevel->iFrom>0 && (pTabItem[0].jointype & JT_LEFT)!=0 ){ + pLevel->iLeftJoin = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin); + VdbeComment((v, "init LEFT JOIN no-match flag")); + } + +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( pLevel->pBestIdx ){ + /* Case 0: The table is a virtual-table. Use the VFilter and VNext + ** to access the data. + */ + int j; + int iReg; /* P3 Value for OP_VFilter */ + sqlite3_index_info *pBestIdx = pLevel->pBestIdx; + int nConstraint = pBestIdx->nConstraint; + struct sqlite3_index_constraint_usage *aUsage = + pBestIdx->aConstraintUsage; + const struct sqlite3_index_constraint *aConstraint = + pBestIdx->aConstraint; + + iReg = sqlite3GetTempRange(pParse, nConstraint+2); + pParse->disableColCache++; + for(j=1; j<=nConstraint; j++){ + int k; + for(k=0; k<nConstraint; k++){ + if( aUsage[k].argvIndex==j ){ + int iTerm = aConstraint[k].iTermOffset; + assert( pParse->disableColCache ); + sqlite3ExprCode(pParse, wc.a[iTerm].pExpr->pRight, iReg+j+1); + break; + } + } + if( k==nConstraint ) break; + } + assert( pParse->disableColCache ); + pParse->disableColCache--; + sqlite3VdbeAddOp2(v, OP_Integer, pBestIdx->idxNum, iReg); + sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1); + sqlite3VdbeAddOp4(v, OP_VFilter, iCur, brk, iReg, pBestIdx->idxStr, + pBestIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC); + sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2); + pBestIdx->needToFreeIdxStr = 0; + for(j=0; j<nConstraint; j++){ + if( aUsage[j].omit ){ + int iTerm = aConstraint[j].iTermOffset; + disableTerm(pLevel, &wc.a[iTerm]); + } + } + pLevel->op = OP_VNext; + pLevel->p1 = iCur; + pLevel->p2 = sqlite3VdbeCurrentAddr(v); + }else +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + + if( pLevel->flags & WHERE_ROWID_EQ ){ + /* Case 1: We can directly reference a single row using an + ** equality comparison against the ROWID field. Or + ** we reference multiple rows using a "rowid IN (...)" + ** construct. + */ + int r1; + pTerm = findTerm(&wc, iCur, -1, notReady, WO_EQ|WO_IN, 0); + assert( pTerm!=0 ); + assert( pTerm->pExpr!=0 ); + assert( pTerm->leftCursor==iCur ); + assert( omitTable==0 ); + r1 = codeEqualityTerm(pParse, pTerm, pLevel, 0); + nxt = pLevel->nxt; + sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, nxt); + sqlite3VdbeAddOp3(v, OP_NotExists, iCur, nxt, r1); + VdbeComment((v, "pk")); + pLevel->op = OP_Noop; + }else if( pLevel->flags & WHERE_ROWID_RANGE ){ + /* Case 2: We have an inequality comparison against the ROWID field. + */ + int testOp = OP_Noop; + int start; + WhereTerm *pStart, *pEnd; + + assert( omitTable==0 ); + pStart = findTerm(&wc, iCur, -1, notReady, WO_GT|WO_GE, 0); + pEnd = findTerm(&wc, iCur, -1, notReady, WO_LT|WO_LE, 0); + if( bRev ){ + pTerm = pStart; + pStart = pEnd; + pEnd = pTerm; + } + if( pStart ){ + Expr *pX; + int r1, regFree1; + pX = pStart->pExpr; + assert( pX!=0 ); + assert( pStart->leftCursor==iCur ); + r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, ®Free1); + sqlite3VdbeAddOp3(v, OP_ForceInt, r1, brk, + pX->op==TK_LE || pX->op==TK_GT); + sqlite3VdbeAddOp3(v, bRev ? OP_MoveLt : OP_MoveGe, iCur, brk, r1); + VdbeComment((v, "pk")); + sqlite3ReleaseTempReg(pParse, regFree1); + disableTerm(pLevel, pStart); + }else{ + sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, brk); + } + if( pEnd ){ + Expr *pX; + pX = pEnd->pExpr; + assert( pX!=0 ); + assert( pEnd->leftCursor==iCur ); + pLevel->iMem = ++pParse->nMem; + sqlite3ExprCode(pParse, pX->pRight, pLevel->iMem); + if( pX->op==TK_LT || pX->op==TK_GT ){ + testOp = bRev ? OP_Le : OP_Ge; + }else{ + testOp = bRev ? OP_Lt : OP_Gt; + } + disableTerm(pLevel, pEnd); + } + start = sqlite3VdbeCurrentAddr(v); + pLevel->op = bRev ? OP_Prev : OP_Next; + pLevel->p1 = iCur; + pLevel->p2 = start; + if( testOp!=OP_Noop ){ + int r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp2(v, OP_Rowid, iCur, r1); + /* sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem, 0); */ + sqlite3VdbeAddOp3(v, testOp, pLevel->iMem, brk, r1); + sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL); + sqlite3ReleaseTempReg(pParse, r1); + } + }else if( pLevel->flags & (WHERE_COLUMN_RANGE|WHERE_COLUMN_EQ) ){ + /* Case 3: A scan using an index. + ** + ** The WHERE clause may contain zero or more equality + ** terms ("==" or "IN" operators) that refer to the N + ** left-most columns of the index. It may also contain + ** inequality constraints (>, <, >= or <=) on the indexed + ** column that immediately follows the N equalities. Only + ** the right-most column can be an inequality - the rest must + ** use the "==" and "IN" operators. For example, if the + ** index is on (x,y,z), then the following clauses are all + ** optimized: + ** + ** x=5 + ** x=5 AND y=10 + ** x=5 AND y<10 + ** x=5 AND y>5 AND y<10 + ** x=5 AND y=5 AND z<=10 + ** + ** The z<10 term of the following cannot be used, only + ** the x=5 term: + ** + ** x=5 AND z<10 + ** + ** N may be zero if there are inequality constraints. + ** If there are no inequality constraints, then N is at + ** least one. + ** + ** This case is also used when there are no WHERE clause + ** constraints but an index is selected anyway, in order + ** to force the output order to conform to an ORDER BY. + */ + int aStartOp[] = { + 0, + 0, + OP_Rewind, /* 2: (!start_constraints && startEq && !bRev) */ + OP_Last, /* 3: (!start_constraints && startEq && bRev) */ + OP_MoveGt, /* 4: (start_constraints && !startEq && !bRev) */ + OP_MoveLt, /* 5: (start_constraints && !startEq && bRev) */ + OP_MoveGe, /* 6: (start_constraints && startEq && !bRev) */ + OP_MoveLe /* 7: (start_constraints && startEq && bRev) */ + }; + int aEndOp[] = { + OP_Noop, /* 0: (!end_constraints) */ + OP_IdxGE, /* 1: (end_constraints && !bRev) */ + OP_IdxLT /* 2: (end_constraints && bRev) */ + }; + int nEq = pLevel->nEq; + int isMinQuery = 0; /* If this is an optimized SELECT min(x).. */ + int regBase; /* Base register holding constraint values */ + int r1; /* Temp register */ + WhereTerm *pRangeStart = 0; /* Inequality constraint at range start */ + WhereTerm *pRangeEnd = 0; /* Inequality constraint at range end */ + int startEq; /* True if range start uses ==, >= or <= */ + int endEq; /* True if range end uses ==, >= or <= */ + int start_constraints; /* Start of range is constrained */ + int k = pIdx->aiColumn[nEq]; /* Column for inequality constraints */ + int nConstraint; /* Number of constraint terms */ + int op; + + /* Generate code to evaluate all constraint terms using == or IN + ** and store the values of those terms in an array of registers + ** starting at regBase. + */ + regBase = codeAllEqualityTerms(pParse, pLevel, &wc, notReady, 2); + nxt = pLevel->nxt; + + /* If this loop satisfies a sort order (pOrderBy) request that + ** was passed to this function to implement a "SELECT min(x) ..." + ** query, then the caller will only allow the loop to run for + ** a single iteration. This means that the first row returned + ** should not have a NULL value stored in 'x'. If column 'x' is + ** the first one after the nEq equality constraints in the index, + ** this requires some special handling. + */ + if( (wflags&WHERE_ORDERBY_MIN)!=0 + && (pLevel->flags&WHERE_ORDERBY) + && (pIdx->nColumn>nEq) + ){ + assert( pOrderBy->nExpr==1 ); + assert( pOrderBy->a[0].pExpr->iColumn==pIdx->aiColumn[nEq] ); + isMinQuery = 1; + } + + /* Find any inequality constraint terms for the start and end + ** of the range. + */ + if( pLevel->flags & WHERE_TOP_LIMIT ){ + pRangeEnd = findTerm(&wc, iCur, k, notReady, (WO_LT|WO_LE), pIdx); + } + if( pLevel->flags & WHERE_BTM_LIMIT ){ + pRangeStart = findTerm(&wc, iCur, k, notReady, (WO_GT|WO_GE), pIdx); + } + + /* If we are doing a reverse order scan on an ascending index, or + ** a forward order scan on a descending index, interchange the + ** start and end terms (pRangeStart and pRangeEnd). + */ + if( bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC) ){ + SWAP(WhereTerm *, pRangeEnd, pRangeStart); + } + + testcase( pRangeStart && pRangeStart->eOperator & WO_LE ); + testcase( pRangeStart && pRangeStart->eOperator & WO_GE ); + testcase( pRangeEnd && pRangeEnd->eOperator & WO_LE ); + testcase( pRangeEnd && pRangeEnd->eOperator & WO_GE ); + startEq = !pRangeStart || pRangeStart->eOperator & (WO_LE|WO_GE); + endEq = !pRangeEnd || pRangeEnd->eOperator & (WO_LE|WO_GE); + start_constraints = pRangeStart || nEq>0; + + /* Seek the index cursor to the start of the range. */ + nConstraint = nEq; + if( pRangeStart ){ + int dcc = pParse->disableColCache; + if( pRangeEnd ){ + pParse->disableColCache++; + } + sqlite3ExprCode(pParse, pRangeStart->pExpr->pRight, regBase+nEq); + pParse->disableColCache = dcc; + sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, nxt); + nConstraint++; + }else if( isMinQuery ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); + nConstraint++; + startEq = 0; + start_constraints = 1; + } + codeApplyAffinity(pParse, regBase, nConstraint, pIdx); + op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev]; + assert( op!=0 ); + testcase( op==OP_Rewind ); + testcase( op==OP_Last ); + testcase( op==OP_MoveGt ); + testcase( op==OP_MoveGe ); + testcase( op==OP_MoveLe ); + testcase( op==OP_MoveLt ); + sqlite3VdbeAddOp4(v, op, iIdxCur, nxt, regBase, + SQLITE_INT_TO_PTR(nConstraint), P4_INT32); + + /* Load the value for the inequality constraint at the end of the + ** range (if any). + */ + nConstraint = nEq; + if( pRangeEnd ){ + sqlite3ExprCode(pParse, pRangeEnd->pExpr->pRight, regBase+nEq); + sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, nxt); + codeApplyAffinity(pParse, regBase, nEq+1, pIdx); + nConstraint++; + } + + /* Top of the loop body */ + pLevel->p2 = sqlite3VdbeCurrentAddr(v); + + /* Check if the index cursor is past the end of the range. */ + op = aEndOp[(pRangeEnd || nEq) * (1 + bRev)]; + testcase( op==OP_Noop ); + testcase( op==OP_IdxGE ); + testcase( op==OP_IdxLT ); + sqlite3VdbeAddOp4(v, op, iIdxCur, nxt, regBase, + SQLITE_INT_TO_PTR(nConstraint), P4_INT32); + sqlite3VdbeChangeP5(v, endEq!=bRev); + + /* If there are inequality constraints, check that the value + ** of the table column that the inequality contrains is not NULL. + ** If it is, jump to the next iteration of the loop. + */ + r1 = sqlite3GetTempReg(pParse); + testcase( pLevel->flags & WHERE_BTM_LIMIT ); + testcase( pLevel->flags & WHERE_TOP_LIMIT ); + if( pLevel->flags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT) ){ + sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, nEq, r1); + sqlite3VdbeAddOp2(v, OP_IsNull, r1, cont); + } + + /* Seek the table cursor, if required */ + if( !omitTable ){ + sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, r1); + sqlite3VdbeAddOp3(v, OP_MoveGe, iCur, 0, r1); /* Deferred seek */ + } + sqlite3ReleaseTempReg(pParse, r1); + + /* Record the instruction used to terminate the loop. Disable + ** WHERE clause terms made redundant by the index range scan. + */ + pLevel->op = bRev ? OP_Prev : OP_Next; + pLevel->p1 = iIdxCur; + disableTerm(pLevel, pRangeStart); + disableTerm(pLevel, pRangeEnd); + }else{ + /* Case 4: There is no usable index. We must do a complete + ** scan of the entire table. + */ + assert( omitTable==0 ); + assert( bRev==0 ); + pLevel->op = OP_Next; + pLevel->p1 = iCur; + pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, OP_Rewind, iCur, brk); + } + notReady &= ~getMask(&maskSet, iCur); + + /* Insert code to test every subexpression that can be completely + ** computed using the current set of tables. + */ + for(pTerm=wc.a, j=wc.nTerm; j>0; j--, pTerm++){ + Expr *pE; + testcase( pTerm->flags & TERM_VIRTUAL ); + testcase( pTerm->flags & TERM_CODED ); + if( pTerm->flags & (TERM_VIRTUAL|TERM_CODED) ) continue; + if( (pTerm->prereqAll & notReady)!=0 ) continue; + pE = pTerm->pExpr; + assert( pE!=0 ); + if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){ + continue; + } + sqlite3ExprIfFalse(pParse, pE, cont, SQLITE_JUMPIFNULL); + pTerm->flags |= TERM_CODED; + } + + /* For a LEFT OUTER JOIN, generate code that will record the fact that + ** at least one row of the right table has matched the left table. + */ + if( pLevel->iLeftJoin ){ + pLevel->top = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin); + VdbeComment((v, "record LEFT JOIN hit")); + sqlite3ExprClearColumnCache(pParse, pLevel->iTabCur); + sqlite3ExprClearColumnCache(pParse, pLevel->iIdxCur); + for(pTerm=wc.a, j=0; j<wc.nTerm; j++, pTerm++){ + testcase( pTerm->flags & TERM_VIRTUAL ); + testcase( pTerm->flags & TERM_CODED ); + if( pTerm->flags & (TERM_VIRTUAL|TERM_CODED) ) continue; + if( (pTerm->prereqAll & notReady)!=0 ) continue; + assert( pTerm->pExpr ); + sqlite3ExprIfFalse(pParse, pTerm->pExpr, cont, SQLITE_JUMPIFNULL); + pTerm->flags |= TERM_CODED; + } + } + } + +#ifdef SQLITE_TEST /* For testing and debugging use only */ + /* Record in the query plan information about the current table + ** and the index used to access it (if any). If the table itself + ** is not used, its name is just '{}'. If no index is used + ** the index is listed as "{}". If the primary key is used the + ** index name is '*'. + */ + for(i=0; i<pTabList->nSrc; i++){ + char *z; + int n; + pLevel = &pWInfo->a[i]; + pTabItem = &pTabList->a[pLevel->iFrom]; + z = pTabItem->zAlias; + if( z==0 ) z = pTabItem->pTab->zName; + n = strlen(z); + if( n+nQPlan < sizeof(sqlite3_query_plan)-10 ){ + if( pLevel->flags & WHERE_IDX_ONLY ){ + memcpy(&sqlite3_query_plan[nQPlan], "{}", 2); + nQPlan += 2; + }else{ + memcpy(&sqlite3_query_plan[nQPlan], z, n); + nQPlan += n; + } + sqlite3_query_plan[nQPlan++] = ' '; + } + testcase( pLevel->flags & WHERE_ROWID_EQ ); + testcase( pLevel->flags & WHERE_ROWID_RANGE ); + if( pLevel->flags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){ + memcpy(&sqlite3_query_plan[nQPlan], "* ", 2); + nQPlan += 2; + }else if( pLevel->pIdx==0 ){ + memcpy(&sqlite3_query_plan[nQPlan], "{} ", 3); + nQPlan += 3; + }else{ + n = strlen(pLevel->pIdx->zName); + if( n+nQPlan < sizeof(sqlite3_query_plan)-2 ){ + memcpy(&sqlite3_query_plan[nQPlan], pLevel->pIdx->zName, n); + nQPlan += n; + sqlite3_query_plan[nQPlan++] = ' '; + } + } + } + while( nQPlan>0 && sqlite3_query_plan[nQPlan-1]==' ' ){ + sqlite3_query_plan[--nQPlan] = 0; + } + sqlite3_query_plan[nQPlan] = 0; + nQPlan = 0; +#endif /* SQLITE_TEST // Testing and debugging use only */ + + /* Record the continuation address in the WhereInfo structure. Then + ** clean up and return. + */ + pWInfo->iContinue = cont; + whereClauseClear(&wc); + return pWInfo; + + /* Jump here if malloc fails */ +whereBeginNoMem: + whereClauseClear(&wc); + whereInfoFree(pWInfo); + return 0; +} + +/* +** Generate the end of the WHERE loop. See comments on +** sqlite3WhereBegin() for additional information. +*/ +void sqlite3WhereEnd(WhereInfo *pWInfo){ + Parse *pParse = pWInfo->pParse; + Vdbe *v = pParse->pVdbe; + int i; + WhereLevel *pLevel; + SrcList *pTabList = pWInfo->pTabList; + sqlite3 *db = pParse->db; + + /* Generate loop termination code. + */ + sqlite3ExprClearColumnCache(pParse, -1); + for(i=pTabList->nSrc-1; i>=0; i--){ + pLevel = &pWInfo->a[i]; + sqlite3VdbeResolveLabel(v, pLevel->cont); + if( pLevel->op!=OP_Noop ){ + sqlite3VdbeAddOp2(v, pLevel->op, pLevel->p1, pLevel->p2); + } + if( pLevel->nIn ){ + struct InLoop *pIn; + int j; + sqlite3VdbeResolveLabel(v, pLevel->nxt); + for(j=pLevel->nIn, pIn=&pLevel->aInLoop[j-1]; j>0; j--, pIn--){ + sqlite3VdbeJumpHere(v, pIn->topAddr+1); + sqlite3VdbeAddOp2(v, OP_Next, pIn->iCur, pIn->topAddr); + sqlite3VdbeJumpHere(v, pIn->topAddr-1); + } + sqlite3DbFree(db, pLevel->aInLoop); + } + sqlite3VdbeResolveLabel(v, pLevel->brk); + if( pLevel->iLeftJoin ){ + int addr; + addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); + sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor); + if( pLevel->iIdxCur>=0 ){ + sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur); + } + sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->top); + sqlite3VdbeJumpHere(v, addr); + } + } + + /* The "break" point is here, just past the end of the outer loop. + ** Set it. + */ + sqlite3VdbeResolveLabel(v, pWInfo->iBreak); + + /* Close all of the cursors that were opened by sqlite3WhereBegin. + */ + for(i=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){ + struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom]; + Table *pTab = pTabItem->pTab; + assert( pTab!=0 ); + if( pTab->isEphem || pTab->pSelect ) continue; + if( !pWInfo->okOnePass && (pLevel->flags & WHERE_IDX_ONLY)==0 ){ + sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor); + } + if( pLevel->pIdx!=0 ){ + sqlite3VdbeAddOp1(v, OP_Close, pLevel->iIdxCur); + } + + /* If this scan uses an index, make code substitutions to read data + ** from the index in preference to the table. Sometimes, this means + ** the table need never be read from. This is a performance boost, + ** as the vdbe level waits until the table is read before actually + ** seeking the table cursor to the record corresponding to the current + ** position in the index. + ** + ** Calls to the code generator in between sqlite3WhereBegin and + ** sqlite3WhereEnd will have created code that references the table + ** directly. This loop scans all that code looking for opcodes + ** that reference the table and converts them into opcodes that + ** reference the index. + */ + if( pLevel->pIdx ){ + int k, j, last; + VdbeOp *pOp; + Index *pIdx = pLevel->pIdx; + int useIndexOnly = pLevel->flags & WHERE_IDX_ONLY; + + assert( pIdx!=0 ); + pOp = sqlite3VdbeGetOp(v, pWInfo->iTop); + last = sqlite3VdbeCurrentAddr(v); + for(k=pWInfo->iTop; k<last; k++, pOp++){ + if( pOp->p1!=pLevel->iTabCur ) continue; + if( pOp->opcode==OP_Column ){ + for(j=0; j<pIdx->nColumn; j++){ + if( pOp->p2==pIdx->aiColumn[j] ){ + pOp->p2 = j; + pOp->p1 = pLevel->iIdxCur; + break; + } + } + assert(!useIndexOnly || j<pIdx->nColumn); + }else if( pOp->opcode==OP_Rowid ){ + pOp->p1 = pLevel->iIdxCur; + pOp->opcode = OP_IdxRowid; + }else if( pOp->opcode==OP_NullRow && useIndexOnly ){ + pOp->opcode = OP_Noop; + } + } + } + } + + /* Final cleanup + */ + whereInfoFree(pWInfo); + return; +} |