Index: third_party/sqlite/amalgamation/sqlite3.05.c |
diff --git a/third_party/sqlite/amalgamation/sqlite3.05.c b/third_party/sqlite/amalgamation/sqlite3.05.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..7c65d7e29a337032792cfde70d0b3ae12f90a55a |
--- /dev/null |
+++ b/third_party/sqlite/amalgamation/sqlite3.05.c |
@@ -0,0 +1,21684 @@ |
+/************** Begin file callback.c ****************************************/ |
+/* |
+** 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. |
+*/ |
+ |
+/* #include "sqliteInt.h" */ |
+ |
+/* |
+** Invoke the 'collation needed' callback to request a collation sequence |
+** in the encoding enc of name zName, length nName. |
+*/ |
+static void callCollNeeded(sqlite3 *db, int enc, const char *zName){ |
+ assert( !db->xCollNeeded || !db->xCollNeeded16 ); |
+ if( db->xCollNeeded ){ |
+ char *zExternal = sqlite3DbStrDup(db, zName); |
+ if( !zExternal ) return; |
+ db->xCollNeeded(db->pCollNeededArg, db, enc, zExternal); |
+ sqlite3DbFree(db, zExternal); |
+ } |
+#ifndef SQLITE_OMIT_UTF16 |
+ if( db->xCollNeeded16 ){ |
+ char const *zExternal; |
+ sqlite3_value *pTmp = sqlite3ValueNew(db); |
+ sqlite3ValueSetStr(pTmp, -1, 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 i; |
+ static const u8 aEnc[] = { SQLITE_UTF16BE, SQLITE_UTF16LE, SQLITE_UTF8 }; |
+ for(i=0; i<3; i++){ |
+ pColl2 = sqlite3FindCollSeq(db, aEnc[i], z, 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 desired 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. If no collation is found, leave an error message. |
+** |
+** See also: sqlite3LocateCollSeq(), sqlite3FindCollSeq() |
+*/ |
+SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq( |
+ Parse *pParse, /* Parsing context */ |
+ u8 enc, /* The desired encoding for the collating sequence */ |
+ CollSeq *pColl, /* Collating sequence with native encoding, or NULL */ |
+ const char *zName /* Collating sequence name */ |
+){ |
+ CollSeq *p; |
+ sqlite3 *db = pParse->db; |
+ |
+ p = pColl; |
+ if( !p ){ |
+ p = sqlite3FindCollSeq(db, enc, zName, 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, enc, zName); |
+ p = sqlite3FindCollSeq(db, enc, zName, 0); |
+ } |
+ if( p && !p->xCmp && synthCollSeq(db, p) ){ |
+ p = 0; |
+ } |
+ assert( !p || p->xCmp ); |
+ if( p==0 ){ |
+ sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName); |
+ } |
+ 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. |
+*/ |
+SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){ |
+ if( pColl ){ |
+ const char *zName = pColl->zName; |
+ sqlite3 *db = pParse->db; |
+ CollSeq *p = sqlite3GetCollSeq(pParse, ENC(db), pColl, zName); |
+ if( !p ){ |
+ 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 |
+** preferred 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, /* Database connection */ |
+ const char *zName, /* Name of the collating sequence */ |
+ int create /* Create a new entry if true */ |
+){ |
+ CollSeq *pColl; |
+ pColl = sqlite3HashFind(&db->aCollSeq, zName); |
+ |
+ if( 0==pColl && create ){ |
+ int nName = sqlite3Strlen30(zName); |
+ 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, pColl); |
+ |
+ /* If a malloc() failure occurred 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 ){ |
+ sqlite3OomFault(db); |
+ 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. |
+** |
+** See also: sqlite3LocateCollSeq(), sqlite3GetCollSeq() |
+*/ |
+SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq( |
+ sqlite3 *db, |
+ u8 enc, |
+ const char *zName, |
+ int create |
+){ |
+ CollSeq *pColl; |
+ if( zName ){ |
+ pColl = findCollSeqEntry(db, zName, 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; |
+} |
+ |
+/* During the search for the best function definition, this procedure |
+** is called to test how well the function passed as the first argument |
+** matches the request for a function with nArg arguments in a system |
+** that uses encoding enc. The value returned indicates how well the |
+** request is matched. A higher value indicates a better match. |
+** |
+** If nArg is -1 that means to only return a match (non-zero) if p->nArg |
+** is also -1. In other words, we are searching for a function that |
+** takes a variable number of arguments. |
+** |
+** If nArg is -2 that means that we are searching for any function |
+** regardless of the number of arguments it uses, so return a positive |
+** match score for any |
+** |
+** The returned value is always between 0 and 6, as follows: |
+** |
+** 0: Not a match. |
+** 1: UTF8/16 conversion required and function takes any number of arguments. |
+** 2: UTF16 byte order change required and function takes any number of args. |
+** 3: encoding matches and function takes any number of arguments |
+** 4: UTF8/16 conversion required - argument count matches exactly |
+** 5: UTF16 byte order conversion required - argument count matches exactly |
+** 6: Perfect match: encoding and argument count match exactly. |
+** |
+** If nArg==(-2) then any function with a non-null xSFunc is |
+** a perfect match and any function with xSFunc NULL is |
+** a non-match. |
+*/ |
+#define FUNC_PERFECT_MATCH 6 /* The score for a perfect match */ |
+static int matchQuality( |
+ FuncDef *p, /* The function we are evaluating for match quality */ |
+ int nArg, /* Desired number of arguments. (-1)==any */ |
+ u8 enc /* Desired text encoding */ |
+){ |
+ int match; |
+ |
+ /* nArg of -2 is a special case */ |
+ if( nArg==(-2) ) return (p->xSFunc==0) ? 0 : FUNC_PERFECT_MATCH; |
+ |
+ /* Wrong number of arguments means "no match" */ |
+ if( p->nArg!=nArg && p->nArg>=0 ) return 0; |
+ |
+ /* Give a better score to a function with a specific number of arguments |
+ ** than to function that accepts any number of arguments. */ |
+ if( p->nArg==nArg ){ |
+ match = 4; |
+ }else{ |
+ match = 1; |
+ } |
+ |
+ /* Bonus points if the text encoding matches */ |
+ if( enc==(p->funcFlags & SQLITE_FUNC_ENCMASK) ){ |
+ match += 2; /* Exact encoding match */ |
+ }else if( (enc & p->funcFlags & 2)!=0 ){ |
+ match += 1; /* Both are UTF16, but with different byte orders */ |
+ } |
+ |
+ return match; |
+} |
+ |
+/* |
+** Search a FuncDefHash for a function with the given name. Return |
+** a pointer to the matching FuncDef if found, or 0 if there is no match. |
+*/ |
+static FuncDef *functionSearch( |
+ int h, /* Hash of the name */ |
+ const char *zFunc /* Name of function */ |
+){ |
+ FuncDef *p; |
+ for(p=sqlite3BuiltinFunctions.a[h]; p; p=p->u.pHash){ |
+ if( sqlite3StrICmp(p->zName, zFunc)==0 ){ |
+ return p; |
+ } |
+ } |
+ return 0; |
+} |
+ |
+/* |
+** Insert a new FuncDef into a FuncDefHash hash table. |
+*/ |
+SQLITE_PRIVATE void sqlite3InsertBuiltinFuncs( |
+ FuncDef *aDef, /* List of global functions to be inserted */ |
+ int nDef /* Length of the apDef[] list */ |
+){ |
+ int i; |
+ for(i=0; i<nDef; i++){ |
+ FuncDef *pOther; |
+ const char *zName = aDef[i].zName; |
+ int nName = sqlite3Strlen30(zName); |
+ int h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % SQLITE_FUNC_HASH_SZ; |
+ pOther = functionSearch(h, zName); |
+ if( pOther ){ |
+ assert( pOther!=&aDef[i] && pOther->pNext!=&aDef[i] ); |
+ aDef[i].pNext = pOther->pNext; |
+ pOther->pNext = &aDef[i]; |
+ }else{ |
+ aDef[i].pNext = 0; |
+ aDef[i].u.pHash = sqlite3BuiltinFunctions.a[h]; |
+ sqlite3BuiltinFunctions.a[h] = &aDef[i]; |
+ } |
+ } |
+} |
+ |
+ |
+ |
+/* |
+** 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. |
+** |
+** If nArg is -2, then the first valid function found is returned. A |
+** function is valid if xSFunc is non-zero. The nArg==(-2) |
+** case is used to see if zName is a valid function name for some number |
+** of arguments. If nArg is -2, then createFlag must be 0. |
+** |
+** 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. |
+*/ |
+SQLITE_PRIVATE FuncDef *sqlite3FindFunction( |
+ sqlite3 *db, /* An open database */ |
+ const char *zName, /* Name of the function. zero-terminated */ |
+ int nArg, /* Number of arguments. -1 means any number */ |
+ u8 enc, /* Preferred text encoding */ |
+ u8 createFlag /* Create new entry if true and does not otherwise exist */ |
+){ |
+ FuncDef *p; /* Iterator variable */ |
+ FuncDef *pBest = 0; /* Best match found so far */ |
+ int bestScore = 0; /* Score of best match */ |
+ int h; /* Hash value */ |
+ int nName; /* Length of the name */ |
+ |
+ assert( nArg>=(-2) ); |
+ assert( nArg>=(-1) || createFlag==0 ); |
+ nName = sqlite3Strlen30(zName); |
+ |
+ /* First search for a match amongst the application-defined functions. |
+ */ |
+ p = (FuncDef*)sqlite3HashFind(&db->aFunc, zName); |
+ while( p ){ |
+ int score = matchQuality(p, nArg, enc); |
+ if( score>bestScore ){ |
+ pBest = p; |
+ bestScore = score; |
+ } |
+ p = p->pNext; |
+ } |
+ |
+ /* If no match is found, search the built-in functions. |
+ ** |
+ ** If the SQLITE_PreferBuiltin flag is set, then search the built-in |
+ ** functions even if a prior app-defined function was found. And give |
+ ** priority to built-in functions. |
+ ** |
+ ** Except, if createFlag is true, that means that we are trying to |
+ ** install a new function. Whatever FuncDef structure is returned it will |
+ ** have fields overwritten with new information appropriate for the |
+ ** new function. But the FuncDefs for built-in functions are read-only. |
+ ** So we must not search for built-ins when creating a new function. |
+ */ |
+ if( !createFlag && (pBest==0 || (db->flags & SQLITE_PreferBuiltin)!=0) ){ |
+ bestScore = 0; |
+ h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % SQLITE_FUNC_HASH_SZ; |
+ p = functionSearch(h, zName); |
+ while( p ){ |
+ int score = matchQuality(p, nArg, enc); |
+ if( score>bestScore ){ |
+ pBest = p; |
+ bestScore = score; |
+ } |
+ p = p->pNext; |
+ } |
+ } |
+ |
+ /* If the createFlag parameter is true and the search 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 && bestScore<FUNC_PERFECT_MATCH && |
+ (pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){ |
+ FuncDef *pOther; |
+ pBest->zName = (const char*)&pBest[1]; |
+ pBest->nArg = (u16)nArg; |
+ pBest->funcFlags = enc; |
+ memcpy((char*)&pBest[1], zName, nName+1); |
+ pOther = (FuncDef*)sqlite3HashInsert(&db->aFunc, pBest->zName, pBest); |
+ if( pOther==pBest ){ |
+ sqlite3DbFree(db, pBest); |
+ sqlite3OomFault(db); |
+ return 0; |
+ }else{ |
+ pBest->pNext = pOther; |
+ } |
+ } |
+ |
+ if( pBest && (pBest->xSFunc || 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 subsidiary resources (i.e. the contents |
+** of the schema hash tables). |
+** |
+** The Schema.cache_size variable is not cleared. |
+*/ |
+SQLITE_PRIVATE void sqlite3SchemaClear(void *p){ |
+ Hash temp1; |
+ Hash temp2; |
+ HashElem *pElem; |
+ Schema *pSchema = (Schema *)p; |
+ |
+ temp1 = pSchema->tblHash; |
+ temp2 = pSchema->trigHash; |
+ sqlite3HashInit(&pSchema->trigHash); |
+ sqlite3HashClear(&pSchema->idxHash); |
+ for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){ |
+ sqlite3DeleteTrigger(0, (Trigger*)sqliteHashData(pElem)); |
+ } |
+ sqlite3HashClear(&temp2); |
+ sqlite3HashInit(&pSchema->tblHash); |
+ for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){ |
+ Table *pTab = sqliteHashData(pElem); |
+ sqlite3DeleteTable(0, pTab); |
+ } |
+ sqlite3HashClear(&temp1); |
+ sqlite3HashClear(&pSchema->fkeyHash); |
+ pSchema->pSeqTab = 0; |
+ if( pSchema->schemaFlags & DB_SchemaLoaded ){ |
+ pSchema->iGeneration++; |
+ pSchema->schemaFlags &= ~DB_SchemaLoaded; |
+ } |
+} |
+ |
+/* |
+** Find and return the schema associated with a BTree. Create |
+** a new one if necessary. |
+*/ |
+SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){ |
+ Schema * p; |
+ if( pBt ){ |
+ p = (Schema *)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaClear); |
+ }else{ |
+ p = (Schema *)sqlite3DbMallocZero(0, sizeof(Schema)); |
+ } |
+ if( !p ){ |
+ sqlite3OomFault(db); |
+ }else if ( 0==p->file_format ){ |
+ sqlite3HashInit(&p->tblHash); |
+ sqlite3HashInit(&p->idxHash); |
+ sqlite3HashInit(&p->trigHash); |
+ sqlite3HashInit(&p->fkeyHash); |
+ p->enc = SQLITE_UTF8; |
+ } |
+ return p; |
+} |
+ |
+/************** End of callback.c ********************************************/ |
+/************** Begin file delete.c ******************************************/ |
+/* |
+** 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. |
+*/ |
+/* #include "sqliteInt.h" */ |
+ |
+/* |
+** While a SrcList can in general represent multiple tables and subqueries |
+** (as in the FROM clause of a SELECT statement) in this case it contains |
+** the name of a single table, as one might find in an INSERT, DELETE, |
+** or UPDATE statement. Look up that table in the symbol table and |
+** return a pointer. Set an error message and return NULL if the table |
+** name is not found or if any other error occurs. |
+** |
+** The following fields are initialized appropriate in pSrc: |
+** |
+** pSrc->a[0].pTab Pointer to the Table object |
+** pSrc->a[0].pIndex Pointer to the INDEXED BY index, if there is one |
+** |
+*/ |
+SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){ |
+ struct SrcList_item *pItem = pSrc->a; |
+ Table *pTab; |
+ assert( pItem && pSrc->nSrc==1 ); |
+ pTab = sqlite3LocateTableItem(pParse, 0, pItem); |
+ sqlite3DeleteTable(pParse->db, pItem->pTab); |
+ pItem->pTab = pTab; |
+ if( pTab ){ |
+ pTab->nTabRef++; |
+ } |
+ if( sqlite3IndexedByLookup(pParse, pItem) ){ |
+ pTab = 0; |
+ } |
+ 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; |
+*/ |
+SQLITE_PRIVATE int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){ |
+ /* A table is not writable under the following circumstances: |
+ ** |
+ ** 1) It is a virtual table and no implementation of the xUpdate method |
+ ** has been provided, or |
+ ** 2) It is a system table (i.e. sqlite_master), this call is not |
+ ** part of a nested parse and writable_schema pragma has not |
+ ** been specified. |
+ ** |
+ ** In either case leave an error message in pParse and return non-zero. |
+ */ |
+ if( ( IsVirtual(pTab) |
+ && sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 ) |
+ || ( (pTab->tabFlags & TF_Readonly)!=0 |
+ && (pParse->db->flags & SQLITE_WriteSchema)==0 |
+ && pParse->nested==0 ) |
+ ){ |
+ sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName); |
+ return 1; |
+ } |
+ |
+#ifndef SQLITE_OMIT_VIEW |
+ if( !viewOk && pTab->pSelect ){ |
+ sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName); |
+ return 1; |
+ } |
+#endif |
+ return 0; |
+} |
+ |
+ |
+#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. |
+*/ |
+SQLITE_PRIVATE void sqlite3MaterializeView( |
+ Parse *pParse, /* Parsing context */ |
+ Table *pView, /* View definition */ |
+ Expr *pWhere, /* Optional WHERE clause to be added */ |
+ int iCur /* Cursor number for ephemeral table */ |
+){ |
+ SelectDest dest; |
+ Select *pSel; |
+ SrcList *pFrom; |
+ sqlite3 *db = pParse->db; |
+ int iDb = sqlite3SchemaToIndex(db, pView->pSchema); |
+ pWhere = sqlite3ExprDup(db, pWhere, 0); |
+ pFrom = sqlite3SrcListAppend(db, 0, 0, 0); |
+ if( pFrom ){ |
+ assert( pFrom->nSrc==1 ); |
+ pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName); |
+ pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName); |
+ assert( pFrom->a[0].pOn==0 ); |
+ assert( pFrom->a[0].pUsing==0 ); |
+ } |
+ pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, |
+ SF_IncludeHidden, 0, 0); |
+ sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur); |
+ sqlite3Select(pParse, pSel, &dest); |
+ sqlite3SelectDelete(db, pSel); |
+} |
+#endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */ |
+ |
+#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) |
+/* |
+** Generate an expression tree to implement the WHERE, ORDER BY, |
+** and LIMIT/OFFSET portion of DELETE and UPDATE statements. |
+** |
+** DELETE FROM table_wxyz WHERE a<5 ORDER BY a LIMIT 1; |
+** \__________________________/ |
+** pLimitWhere (pInClause) |
+*/ |
+SQLITE_PRIVATE Expr *sqlite3LimitWhere( |
+ Parse *pParse, /* The parser context */ |
+ SrcList *pSrc, /* the FROM clause -- which tables to scan */ |
+ Expr *pWhere, /* The WHERE clause. May be null */ |
+ ExprList *pOrderBy, /* The ORDER BY clause. May be null */ |
+ Expr *pLimit, /* The LIMIT clause. May be null */ |
+ Expr *pOffset, /* The OFFSET clause. May be null */ |
+ char *zStmtType /* Either DELETE or UPDATE. For err msgs. */ |
+){ |
+ Expr *pWhereRowid = NULL; /* WHERE rowid .. */ |
+ Expr *pInClause = NULL; /* WHERE rowid IN ( select ) */ |
+ Expr *pSelectRowid = NULL; /* SELECT rowid ... */ |
+ ExprList *pEList = NULL; /* Expression list contaning only pSelectRowid */ |
+ SrcList *pSelectSrc = NULL; /* SELECT rowid FROM x ... (dup of pSrc) */ |
+ Select *pSelect = NULL; /* Complete SELECT tree */ |
+ |
+ /* Check that there isn't an ORDER BY without a LIMIT clause. |
+ */ |
+ if( pOrderBy && (pLimit == 0) ) { |
+ sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on %s", zStmtType); |
+ goto limit_where_cleanup; |
+ } |
+ |
+ /* We only need to generate a select expression if there |
+ ** is a limit/offset term to enforce. |
+ */ |
+ if( pLimit == 0 ) { |
+ /* if pLimit is null, pOffset will always be null as well. */ |
+ assert( pOffset == 0 ); |
+ return pWhere; |
+ } |
+ |
+ /* Generate a select expression tree to enforce the limit/offset |
+ ** term for the DELETE or UPDATE statement. For example: |
+ ** DELETE FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1 |
+ ** becomes: |
+ ** DELETE FROM table_a WHERE rowid IN ( |
+ ** SELECT rowid FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1 |
+ ** ); |
+ */ |
+ |
+ pSelectRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0); |
+ if( pSelectRowid == 0 ) goto limit_where_cleanup; |
+ pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid); |
+ if( pEList == 0 ) goto limit_where_cleanup; |
+ |
+ /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree |
+ ** and the SELECT subtree. */ |
+ pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc, 0); |
+ if( pSelectSrc == 0 ) { |
+ sqlite3ExprListDelete(pParse->db, pEList); |
+ goto limit_where_cleanup; |
+ } |
+ |
+ /* generate the SELECT expression tree. */ |
+ pSelect = sqlite3SelectNew(pParse,pEList,pSelectSrc,pWhere,0,0, |
+ pOrderBy,0,pLimit,pOffset); |
+ if( pSelect == 0 ) return 0; |
+ |
+ /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */ |
+ pWhereRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0); |
+ pInClause = pWhereRowid ? sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0) : 0; |
+ sqlite3PExprAddSelect(pParse, pInClause, pSelect); |
+ return pInClause; |
+ |
+limit_where_cleanup: |
+ sqlite3ExprDelete(pParse->db, pWhere); |
+ sqlite3ExprListDelete(pParse->db, pOrderBy); |
+ sqlite3ExprDelete(pParse->db, pLimit); |
+ sqlite3ExprDelete(pParse->db, pOffset); |
+ return 0; |
+} |
+#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) */ |
+ /* && !defined(SQLITE_OMIT_SUBQUERY) */ |
+ |
+/* |
+** Generate code for a DELETE FROM statement. |
+** |
+** DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL; |
+** \________/ \________________/ |
+** pTabList pWhere |
+*/ |
+SQLITE_PRIVATE 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 */ |
+ int i; /* Loop counter */ |
+ WhereInfo *pWInfo; /* Information about the WHERE clause */ |
+ Index *pIdx; /* For looping over indices of the table */ |
+ int iTabCur; /* Cursor number for the table */ |
+ int iDataCur = 0; /* VDBE cursor for the canonical data source */ |
+ int iIdxCur = 0; /* Cursor number of the first index */ |
+ int nIdx; /* Number of indices */ |
+ sqlite3 *db; /* Main database structure */ |
+ AuthContext sContext; /* Authorization context */ |
+ NameContext sNC; /* Name context to resolve expressions in */ |
+ int iDb; /* Database number */ |
+ int memCnt = -1; /* Memory cell used for change counting */ |
+ int rcauth; /* Value returned by authorization callback */ |
+ int eOnePass; /* ONEPASS_OFF or _SINGLE or _MULTI */ |
+ int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */ |
+ u8 *aToOpen = 0; /* Open cursor iTabCur+j if aToOpen[j] is true */ |
+ Index *pPk; /* The PRIMARY KEY index on the table */ |
+ int iPk = 0; /* First of nPk registers holding PRIMARY KEY value */ |
+ i16 nPk = 1; /* Number of columns in the PRIMARY KEY */ |
+ int iKey; /* Memory cell holding key of row to be deleted */ |
+ i16 nKey; /* Number of memory cells in the row key */ |
+ int iEphCur = 0; /* Ephemeral table holding all primary key values */ |
+ int iRowSet = 0; /* Register for rowset of rows to delete */ |
+ int addrBypass = 0; /* Address of jump over the delete logic */ |
+ int addrLoop = 0; /* Top of the delete loop */ |
+ int addrEphOpen = 0; /* Instruction to open the Ephemeral table */ |
+ int bComplex; /* True if there are triggers or FKs or |
+ ** subqueries in the WHERE clause */ |
+ |
+#ifndef SQLITE_OMIT_TRIGGER |
+ int isView; /* True if attempting to delete from a view */ |
+ Trigger *pTrigger; /* List of table triggers, if required */ |
+#endif |
+ |
+ memset(&sContext, 0, sizeof(sContext)); |
+ 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 |
+ pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); |
+ isView = pTab->pSelect!=0; |
+ bComplex = pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0); |
+#else |
+# define pTrigger 0 |
+# define isView 0 |
+#endif |
+#ifdef SQLITE_OMIT_VIEW |
+# undef isView |
+# define isView 0 |
+#endif |
+ |
+ /* If pTab is really a view, make sure it has been initialized. |
+ */ |
+ if( sqlite3ViewGetColumnNames(pParse, pTab) ){ |
+ goto delete_from_cleanup; |
+ } |
+ |
+ if( sqlite3IsReadOnly(pParse, pTab, (pTrigger?1:0)) ){ |
+ goto delete_from_cleanup; |
+ } |
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
+ assert( iDb<db->nDb ); |
+ rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, |
+ db->aDb[iDb].zDbSName); |
+ assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE ); |
+ if( rcauth==SQLITE_DENY ){ |
+ goto delete_from_cleanup; |
+ } |
+ assert(!isView || pTrigger); |
+ |
+ /* Assign cursor numbers to the table and all its indices. |
+ */ |
+ assert( pTabList->nSrc==1 ); |
+ iTabCur = pTabList->a[0].iCursor = pParse->nTab++; |
+ for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ |
+ 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, 1, iDb); |
+ |
+ /* If we are trying to delete from a view, realize that view into |
+ ** an ephemeral table. |
+ */ |
+#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) |
+ if( isView ){ |
+ sqlite3MaterializeView(pParse, pTab, pWhere, iTabCur); |
+ iDataCur = iIdxCur = iTabCur; |
+ } |
+#endif |
+ |
+ /* Resolve the column names in the WHERE clause. |
+ */ |
+ memset(&sNC, 0, sizeof(sNC)); |
+ sNC.pParse = pParse; |
+ sNC.pSrcList = pTabList; |
+ if( sqlite3ResolveExprNames(&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); |
+ } |
+ |
+#ifndef SQLITE_OMIT_TRUNCATE_OPTIMIZATION |
+ /* Special case: A DELETE without a WHERE clause deletes everything. |
+ ** It is easier just to erase the whole table. Prior to version 3.6.5, |
+ ** this optimization caused the row change count (the value returned by |
+ ** API function sqlite3_count_changes) to be set incorrectly. */ |
+ if( rcauth==SQLITE_OK |
+ && pWhere==0 |
+ && !bComplex |
+ && !IsVirtual(pTab) |
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK |
+ && db->xPreUpdateCallback==0 |
+#endif |
+ ){ |
+ assert( !isView ); |
+ sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName); |
+ if( HasRowid(pTab) ){ |
+ sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt, |
+ pTab->zName, P4_STATIC); |
+ } |
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
+ assert( pIdx->pSchema==pTab->pSchema ); |
+ sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb); |
+ } |
+ }else |
+#endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */ |
+ { |
+ u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK|WHERE_SEEK_TABLE; |
+ if( sNC.ncFlags & NC_VarSelect ) bComplex = 1; |
+ wcf |= (bComplex ? 0 : WHERE_ONEPASS_MULTIROW); |
+ if( HasRowid(pTab) ){ |
+ /* For a rowid table, initialize the RowSet to an empty set */ |
+ pPk = 0; |
+ nPk = 1; |
+ iRowSet = ++pParse->nMem; |
+ sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet); |
+ }else{ |
+ /* For a WITHOUT ROWID table, create an ephemeral table used to |
+ ** hold all primary keys for rows to be deleted. */ |
+ pPk = sqlite3PrimaryKeyIndex(pTab); |
+ assert( pPk!=0 ); |
+ nPk = pPk->nKeyCol; |
+ iPk = pParse->nMem+1; |
+ pParse->nMem += nPk; |
+ iEphCur = pParse->nTab++; |
+ addrEphOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEphCur, nPk); |
+ sqlite3VdbeSetP4KeyInfo(pParse, pPk); |
+ } |
+ |
+ /* Construct a query to find the rowid or primary key for every row |
+ ** to be deleted, based on the WHERE clause. Set variable eOnePass |
+ ** to indicate the strategy used to implement this delete: |
+ ** |
+ ** ONEPASS_OFF: Two-pass approach - use a FIFO for rowids/PK values. |
+ ** ONEPASS_SINGLE: One-pass approach - at most one row deleted. |
+ ** ONEPASS_MULTI: One-pass approach - any number of rows may be deleted. |
+ */ |
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, wcf, iTabCur+1); |
+ if( pWInfo==0 ) goto delete_from_cleanup; |
+ eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); |
+ assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI ); |
+ assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF ); |
+ |
+ /* Keep track of the number of rows to be deleted */ |
+ if( db->flags & SQLITE_CountRows ){ |
+ sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1); |
+ } |
+ |
+ /* Extract the rowid or primary key for the current row */ |
+ if( pPk ){ |
+ for(i=0; i<nPk; i++){ |
+ assert( pPk->aiColumn[i]>=0 ); |
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, |
+ pPk->aiColumn[i], iPk+i); |
+ } |
+ iKey = iPk; |
+ }else{ |
+ iKey = pParse->nMem + 1; |
+ iKey = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iTabCur, iKey, 0); |
+ if( iKey>pParse->nMem ) pParse->nMem = iKey; |
+ } |
+ |
+ if( eOnePass!=ONEPASS_OFF ){ |
+ /* For ONEPASS, no need to store the rowid/primary-key. There is only |
+ ** one, so just keep it in its register(s) and fall through to the |
+ ** delete code. */ |
+ nKey = nPk; /* OP_Found will use an unpacked key */ |
+ aToOpen = sqlite3DbMallocRawNN(db, nIdx+2); |
+ if( aToOpen==0 ){ |
+ sqlite3WhereEnd(pWInfo); |
+ goto delete_from_cleanup; |
+ } |
+ memset(aToOpen, 1, nIdx+1); |
+ aToOpen[nIdx+1] = 0; |
+ if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iTabCur] = 0; |
+ if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iTabCur] = 0; |
+ if( addrEphOpen ) sqlite3VdbeChangeToNoop(v, addrEphOpen); |
+ }else{ |
+ if( pPk ){ |
+ /* Add the PK key for this row to the temporary table */ |
+ iKey = ++pParse->nMem; |
+ nKey = 0; /* Zero tells OP_Found to use a composite key */ |
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey, |
+ sqlite3IndexAffinityStr(pParse->db, pPk), nPk); |
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEphCur, iKey, iPk, nPk); |
+ }else{ |
+ /* Add the rowid of the row to be deleted to the RowSet */ |
+ nKey = 1; /* OP_Seek always uses a single rowid */ |
+ sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey); |
+ } |
+ } |
+ |
+ /* If this DELETE cannot use the ONEPASS strategy, this is the |
+ ** end of the WHERE loop */ |
+ if( eOnePass!=ONEPASS_OFF ){ |
+ addrBypass = sqlite3VdbeMakeLabel(v); |
+ }else{ |
+ sqlite3WhereEnd(pWInfo); |
+ } |
+ |
+ /* Unless this is a view, open cursors for the table we are |
+ ** deleting from and all its indices. If this is a view, then the |
+ ** only effect this statement has is to fire the INSTEAD OF |
+ ** triggers. |
+ */ |
+ if( !isView ){ |
+ int iAddrOnce = 0; |
+ if( eOnePass==ONEPASS_MULTI ){ |
+ iAddrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); |
+ } |
+ testcase( IsVirtual(pTab) ); |
+ sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, OPFLAG_FORDELETE, |
+ iTabCur, aToOpen, &iDataCur, &iIdxCur); |
+ assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur ); |
+ assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 ); |
+ if( eOnePass==ONEPASS_MULTI ) sqlite3VdbeJumpHere(v, iAddrOnce); |
+ } |
+ |
+ /* Set up a loop over the rowids/primary-keys that were found in the |
+ ** where-clause loop above. |
+ */ |
+ if( eOnePass!=ONEPASS_OFF ){ |
+ assert( nKey==nPk ); /* OP_Found will use an unpacked key */ |
+ if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){ |
+ assert( pPk!=0 || pTab->pSelect!=0 ); |
+ sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey); |
+ VdbeCoverage(v); |
+ } |
+ }else if( pPk ){ |
+ addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); VdbeCoverage(v); |
+ sqlite3VdbeAddOp2(v, OP_RowData, iEphCur, iKey); |
+ assert( nKey==0 ); /* OP_Found will use a composite key */ |
+ }else{ |
+ addrLoop = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, 0, iKey); |
+ VdbeCoverage(v); |
+ assert( nKey==1 ); |
+ } |
+ |
+ /* Delete the row */ |
+#ifndef SQLITE_OMIT_VIRTUALTABLE |
+ if( IsVirtual(pTab) ){ |
+ const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); |
+ sqlite3VtabMakeWritable(pParse, pTab); |
+ sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB); |
+ sqlite3VdbeChangeP5(v, OE_Abort); |
+ assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE ); |
+ sqlite3MayAbort(pParse); |
+ if( eOnePass==ONEPASS_SINGLE && sqlite3IsToplevel(pParse) ){ |
+ pParse->isMultiWrite = 0; |
+ } |
+ }else |
+#endif |
+ { |
+ int count = (pParse->nested==0); /* True to count changes */ |
+ sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, |
+ iKey, nKey, count, OE_Default, eOnePass, aiCurOnePass[1]); |
+ } |
+ |
+ /* End of the loop over all rowids/primary-keys. */ |
+ if( eOnePass!=ONEPASS_OFF ){ |
+ sqlite3VdbeResolveLabel(v, addrBypass); |
+ sqlite3WhereEnd(pWInfo); |
+ }else if( pPk ){ |
+ sqlite3VdbeAddOp2(v, OP_Next, iEphCur, addrLoop+1); VdbeCoverage(v); |
+ sqlite3VdbeJumpHere(v, addrLoop); |
+ }else{ |
+ sqlite3VdbeGoto(v, addrLoop); |
+ sqlite3VdbeJumpHere(v, addrLoop); |
+ } |
+ } /* End non-truncate path */ |
+ |
+ /* Update the sqlite_sequence table by storing the content of the |
+ ** maximum rowid counter values recorded while inserting into |
+ ** autoincrement tables. |
+ */ |
+ if( pParse->nested==0 && pParse->pTriggerTab==0 ){ |
+ sqlite3AutoincrementEnd(pParse); |
+ } |
+ |
+ /* 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 && !pParse->pTriggerTab ){ |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, memCnt, 1); |
+ sqlite3VdbeSetNumCols(v, 1); |
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC); |
+ } |
+ |
+delete_from_cleanup: |
+ sqlite3AuthContextPop(&sContext); |
+ sqlite3SrcListDelete(db, pTabList); |
+ sqlite3ExprDelete(db, pWhere); |
+ sqlite3DbFree(db, aToOpen); |
+ return; |
+} |
+/* Make sure "isView" and other macros defined above are undefined. Otherwise |
+** they may interfere with compilation of other functions in this file |
+** (or in another file, if this file becomes part of the amalgamation). */ |
+#ifdef isView |
+ #undef isView |
+#endif |
+#ifdef pTrigger |
+ #undef pTrigger |
+#endif |
+ |
+/* |
+** This routine generates VDBE code that causes a single row of a |
+** single table to be deleted. Both the original table entry and |
+** all indices are removed. |
+** |
+** Preconditions: |
+** |
+** 1. iDataCur is an open cursor on the btree that is the canonical data |
+** store for the table. (This will be either the table itself, |
+** in the case of a rowid table, or the PRIMARY KEY index in the case |
+** of a WITHOUT ROWID table.) |
+** |
+** 2. Read/write cursors for all indices of pTab must be open as |
+** cursor number iIdxCur+i for the i-th index. |
+** |
+** 3. The primary key for the row to be deleted must be stored in a |
+** sequence of nPk memory cells starting at iPk. If nPk==0 that means |
+** that a search record formed from OP_MakeRecord is contained in the |
+** single memory location iPk. |
+** |
+** eMode: |
+** Parameter eMode may be passed either ONEPASS_OFF (0), ONEPASS_SINGLE, or |
+** ONEPASS_MULTI. If eMode is not ONEPASS_OFF, then the cursor |
+** iDataCur already points to the row to delete. If eMode is ONEPASS_OFF |
+** then this function must seek iDataCur to the entry identified by iPk |
+** and nPk before reading from it. |
+** |
+** If eMode is ONEPASS_MULTI, then this call is being made as part |
+** of a ONEPASS delete that affects multiple rows. In this case, if |
+** iIdxNoSeek is a valid cursor number (>=0) and is not the same as |
+** iDataCur, then its position should be preserved following the delete |
+** operation. Or, if iIdxNoSeek is not a valid cursor number, the |
+** position of iDataCur should be preserved instead. |
+** |
+** iIdxNoSeek: |
+** If iIdxNoSeek is a valid cursor number (>=0) not equal to iDataCur, |
+** then it identifies an index cursor (from within array of cursors |
+** starting at iIdxCur) that already points to the index entry to be deleted. |
+** Except, this optimization is disabled if there are BEFORE triggers since |
+** the trigger body might have moved the cursor. |
+*/ |
+SQLITE_PRIVATE void sqlite3GenerateRowDelete( |
+ Parse *pParse, /* Parsing context */ |
+ Table *pTab, /* Table containing the row to be deleted */ |
+ Trigger *pTrigger, /* List of triggers to (potentially) fire */ |
+ int iDataCur, /* Cursor from which column data is extracted */ |
+ int iIdxCur, /* First index cursor */ |
+ int iPk, /* First memory cell containing the PRIMARY KEY */ |
+ i16 nPk, /* Number of PRIMARY KEY memory cells */ |
+ u8 count, /* If non-zero, increment the row change counter */ |
+ u8 onconf, /* Default ON CONFLICT policy for triggers */ |
+ u8 eMode, /* ONEPASS_OFF, _SINGLE, or _MULTI. See above */ |
+ int iIdxNoSeek /* Cursor number of cursor that does not need seeking */ |
+){ |
+ Vdbe *v = pParse->pVdbe; /* Vdbe */ |
+ int iOld = 0; /* First register in OLD.* array */ |
+ int iLabel; /* Label resolved to end of generated code */ |
+ u8 opSeek; /* Seek opcode */ |
+ |
+ /* Vdbe is guaranteed to have been allocated by this stage. */ |
+ assert( v ); |
+ VdbeModuleComment((v, "BEGIN: GenRowDel(%d,%d,%d,%d)", |
+ iDataCur, iIdxCur, iPk, (int)nPk)); |
+ |
+ /* Seek cursor iCur to the row to delete. If this row no longer exists |
+ ** (this can happen if a trigger program has already deleted it), do |
+ ** not attempt to delete it or fire any DELETE triggers. */ |
+ iLabel = sqlite3VdbeMakeLabel(v); |
+ opSeek = HasRowid(pTab) ? OP_NotExists : OP_NotFound; |
+ if( eMode==ONEPASS_OFF ){ |
+ sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk); |
+ VdbeCoverageIf(v, opSeek==OP_NotExists); |
+ VdbeCoverageIf(v, opSeek==OP_NotFound); |
+ } |
+ |
+ /* If there are any triggers to fire, allocate a range of registers to |
+ ** use for the old.* references in the triggers. */ |
+ if( sqlite3FkRequired(pParse, pTab, 0, 0) || pTrigger ){ |
+ u32 mask; /* Mask of OLD.* columns in use */ |
+ int iCol; /* Iterator used while populating OLD.* */ |
+ int addrStart; /* Start of BEFORE trigger programs */ |
+ |
+ /* TODO: Could use temporary registers here. Also could attempt to |
+ ** avoid copying the contents of the rowid register. */ |
+ mask = sqlite3TriggerColmask( |
+ pParse, pTrigger, 0, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onconf |
+ ); |
+ mask |= sqlite3FkOldmask(pParse, pTab); |
+ iOld = pParse->nMem+1; |
+ pParse->nMem += (1 + pTab->nCol); |
+ |
+ /* Populate the OLD.* pseudo-table register array. These values will be |
+ ** used by any BEFORE and AFTER triggers that exist. */ |
+ sqlite3VdbeAddOp2(v, OP_Copy, iPk, iOld); |
+ for(iCol=0; iCol<pTab->nCol; iCol++){ |
+ testcase( mask!=0xffffffff && iCol==31 ); |
+ testcase( mask!=0xffffffff && iCol==32 ); |
+ if( mask==0xffffffff || (iCol<=31 && (mask & MASKBIT32(iCol))!=0) ){ |
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, iCol, iOld+iCol+1); |
+ } |
+ } |
+ |
+ /* Invoke BEFORE DELETE trigger programs. */ |
+ addrStart = sqlite3VdbeCurrentAddr(v); |
+ sqlite3CodeRowTrigger(pParse, pTrigger, |
+ TK_DELETE, 0, TRIGGER_BEFORE, pTab, iOld, onconf, iLabel |
+ ); |
+ |
+ /* If any BEFORE triggers were coded, then seek the cursor to the |
+ ** row to be deleted again. It may be that the BEFORE triggers moved |
+ ** the cursor or already deleted the row that the cursor was |
+ ** pointing to. |
+ ** |
+ ** Also disable the iIdxNoSeek optimization since the BEFORE trigger |
+ ** may have moved that cursor. |
+ */ |
+ if( addrStart<sqlite3VdbeCurrentAddr(v) ){ |
+ sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk); |
+ VdbeCoverageIf(v, opSeek==OP_NotExists); |
+ VdbeCoverageIf(v, opSeek==OP_NotFound); |
+ testcase( iIdxNoSeek>=0 ); |
+ iIdxNoSeek = -1; |
+ } |
+ |
+ /* Do FK processing. This call checks that any FK constraints that |
+ ** refer to this table (i.e. constraints attached to other tables) |
+ ** are not violated by deleting this row. */ |
+ sqlite3FkCheck(pParse, pTab, iOld, 0, 0, 0); |
+ } |
+ |
+ /* Delete the index and table entries. Skip this step if pTab is really |
+ ** a view (in which case the only effect of the DELETE statement is to |
+ ** fire the INSTEAD OF triggers). |
+ ** |
+ ** If variable 'count' is non-zero, then this OP_Delete instruction should |
+ ** invoke the update-hook. The pre-update-hook, on the other hand should |
+ ** be invoked unless table pTab is a system table. The difference is that |
+ ** the update-hook is not invoked for rows removed by REPLACE, but the |
+ ** pre-update-hook is. |
+ */ |
+ if( pTab->pSelect==0 ){ |
+ u8 p5 = 0; |
+ sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek); |
+ sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0)); |
+ if( pParse->nested==0 ){ |
+ sqlite3VdbeAppendP4(v, (char*)pTab, P4_TABLE); |
+ } |
+ if( eMode!=ONEPASS_OFF ){ |
+ sqlite3VdbeChangeP5(v, OPFLAG_AUXDELETE); |
+ } |
+ if( iIdxNoSeek>=0 && iIdxNoSeek!=iDataCur ){ |
+ sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek); |
+ } |
+ if( eMode==ONEPASS_MULTI ) p5 |= OPFLAG_SAVEPOSITION; |
+ sqlite3VdbeChangeP5(v, p5); |
+ } |
+ |
+ /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to |
+ ** handle rows (possibly in other tables) that refer via a foreign key |
+ ** to the row just deleted. */ |
+ sqlite3FkActions(pParse, pTab, 0, iOld, 0, 0); |
+ |
+ /* Invoke AFTER DELETE trigger programs. */ |
+ sqlite3CodeRowTrigger(pParse, pTrigger, |
+ TK_DELETE, 0, TRIGGER_AFTER, pTab, iOld, onconf, iLabel |
+ ); |
+ |
+ /* Jump here if the row had already been deleted before any BEFORE |
+ ** trigger programs were invoked. Or if a trigger program throws a |
+ ** RAISE(IGNORE) exception. */ |
+ sqlite3VdbeResolveLabel(v, iLabel); |
+ VdbeModuleComment((v, "END: GenRowDel()")); |
+} |
+ |
+/* |
+** This routine generates VDBE code that causes the deletion of all |
+** index entries associated with a single row of a single table, pTab |
+** |
+** Preconditions: |
+** |
+** 1. A read/write cursor "iDataCur" must be open on the canonical storage |
+** btree for the table pTab. (This will be either the table itself |
+** for rowid tables or to the primary key index for WITHOUT ROWID |
+** tables.) |
+** |
+** 2. Read/write cursors for all indices of pTab must be open as |
+** cursor number iIdxCur+i for the i-th index. (The pTab->pIndex |
+** index is the 0-th index.) |
+** |
+** 3. The "iDataCur" cursor must be already be positioned on the row |
+** that is to be deleted. |
+*/ |
+SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete( |
+ Parse *pParse, /* Parsing and code generating context */ |
+ Table *pTab, /* Table containing the row to be deleted */ |
+ int iDataCur, /* Cursor of table holding data. */ |
+ int iIdxCur, /* First index cursor */ |
+ int *aRegIdx, /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */ |
+ int iIdxNoSeek /* Do not delete from this cursor */ |
+){ |
+ int i; /* Index loop counter */ |
+ int r1 = -1; /* Register holding an index key */ |
+ int iPartIdxLabel; /* Jump destination for skipping partial index entries */ |
+ Index *pIdx; /* Current index */ |
+ Index *pPrior = 0; /* Prior index */ |
+ Vdbe *v; /* The prepared statement under construction */ |
+ Index *pPk; /* PRIMARY KEY index, or NULL for rowid tables */ |
+ |
+ v = pParse->pVdbe; |
+ pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); |
+ for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ |
+ assert( iIdxCur+i!=iDataCur || pPk==pIdx ); |
+ if( aRegIdx!=0 && aRegIdx[i]==0 ) continue; |
+ if( pIdx==pPk ) continue; |
+ if( iIdxCur+i==iIdxNoSeek ) continue; |
+ VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName)); |
+ r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1, |
+ &iPartIdxLabel, pPrior, r1); |
+ sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1, |
+ pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn); |
+ sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel); |
+ pPrior = pIdx; |
+ } |
+} |
+ |
+/* |
+** Generate code that will assemble an index key and stores 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. If pTab is a WITHOUT ROWID table, then |
+** iCur must be the cursor of the PRIMARY KEY index. |
+** |
+** 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. |
+** |
+** If *piPartIdxLabel is not NULL, fill it in with a label and jump |
+** to that label if pIdx is a partial index that should be skipped. |
+** The label should be resolved using sqlite3ResolvePartIdxLabel(). |
+** A partial index should be skipped if its WHERE clause evaluates |
+** to false or null. If pIdx is not a partial index, *piPartIdxLabel |
+** will be set to zero which is an empty label that is ignored by |
+** sqlite3ResolvePartIdxLabel(). |
+** |
+** The pPrior and regPrior parameters are used to implement a cache to |
+** avoid unnecessary register loads. If pPrior is not NULL, then it is |
+** a pointer to a different index for which an index key has just been |
+** computed into register regPrior. If the current pIdx index is generating |
+** its key into the same sequence of registers and if pPrior and pIdx share |
+** a column in common, then the register corresponding to that column already |
+** holds the correct value and the loading of that register is skipped. |
+** This optimization is helpful when doing a DELETE or an INTEGRITY_CHECK |
+** on a table with multiple indices, and especially with the ROWID or |
+** PRIMARY KEY columns of the index. |
+*/ |
+SQLITE_PRIVATE int sqlite3GenerateIndexKey( |
+ Parse *pParse, /* Parsing context */ |
+ Index *pIdx, /* The index for which to generate a key */ |
+ int iDataCur, /* Cursor number from which to take column data */ |
+ int regOut, /* Put the new key into this register if not 0 */ |
+ int prefixOnly, /* Compute only a unique prefix of the key */ |
+ int *piPartIdxLabel, /* OUT: Jump to this label to skip partial index */ |
+ Index *pPrior, /* Previously generated index key */ |
+ int regPrior /* Register holding previous generated key */ |
+){ |
+ Vdbe *v = pParse->pVdbe; |
+ int j; |
+ int regBase; |
+ int nCol; |
+ |
+ if( piPartIdxLabel ){ |
+ if( pIdx->pPartIdxWhere ){ |
+ *piPartIdxLabel = sqlite3VdbeMakeLabel(v); |
+ pParse->iSelfTab = iDataCur; |
+ sqlite3ExprCachePush(pParse); |
+ sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel, |
+ SQLITE_JUMPIFNULL); |
+ }else{ |
+ *piPartIdxLabel = 0; |
+ } |
+ } |
+ nCol = (prefixOnly && pIdx->uniqNotNull) ? pIdx->nKeyCol : pIdx->nColumn; |
+ regBase = sqlite3GetTempRange(pParse, nCol); |
+ if( pPrior && (regBase!=regPrior || pPrior->pPartIdxWhere) ) pPrior = 0; |
+ for(j=0; j<nCol; j++){ |
+ if( pPrior |
+ && pPrior->aiColumn[j]==pIdx->aiColumn[j] |
+ && pPrior->aiColumn[j]!=XN_EXPR |
+ ){ |
+ /* This column was already computed by the previous index */ |
+ continue; |
+ } |
+ sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iDataCur, j, regBase+j); |
+ /* If the column affinity is REAL but the number is an integer, then it |
+ ** might be stored in the table as an integer (using a compact |
+ ** representation) then converted to REAL by an OP_RealAffinity opcode. |
+ ** But we are getting ready to store this value back into an index, where |
+ ** it should be converted by to INTEGER again. So omit the OP_RealAffinity |
+ ** opcode if it is present */ |
+ sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity); |
+ } |
+ if( regOut ){ |
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut); |
+ if( pIdx->pTable->pSelect ){ |
+ const char *zAff = sqlite3IndexAffinityStr(pParse->db, pIdx); |
+ sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT); |
+ } |
+ } |
+ sqlite3ReleaseTempRange(pParse, regBase, nCol); |
+ return regBase; |
+} |
+ |
+/* |
+** If a prior call to sqlite3GenerateIndexKey() generated a jump-over label |
+** because it was a partial index, then this routine should be called to |
+** resolve that label. |
+*/ |
+SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse *pParse, int iLabel){ |
+ if( iLabel ){ |
+ sqlite3VdbeResolveLabel(pParse->pVdbe, iLabel); |
+ sqlite3ExprCachePop(pParse); |
+ } |
+} |
+ |
+/************** End of delete.c **********************************************/ |
+/************** Begin file func.c ********************************************/ |
+/* |
+** 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-language implementations for many of the SQL |
+** functions of SQLite. (Some function, and in particular the date and |
+** time functions, are implemented separately.) |
+*/ |
+/* #include "sqliteInt.h" */ |
+/* #include <stdlib.h> */ |
+/* #include <assert.h> */ |
+/* #include "vdbeInt.h" */ |
+ |
+/* |
+** Return the collating function associated with a function. |
+*/ |
+static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){ |
+ VdbeOp *pOp; |
+ assert( context->pVdbe!=0 ); |
+ pOp = &context->pVdbe->aOp[context->iOp-1]; |
+ assert( pOp->opcode==OP_CollSeq ); |
+ assert( pOp->p4type==P4_COLLSEQ ); |
+ return pOp->p4.pColl; |
+} |
+ |
+/* |
+** Indicate that the accumulator load should be skipped on this |
+** iteration of the aggregate loop. |
+*/ |
+static void sqlite3SkipAccumulatorLoad(sqlite3_context *context){ |
+ context->skipFlag = 1; |
+} |
+ |
+/* |
+** 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; |
+ |
+ assert( argc>1 ); |
+ 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 ){ |
+ testcase( mask==0 ); |
+ iBest = i; |
+ } |
+ } |
+ sqlite3_result_value(context, argv[iBest]); |
+} |
+ |
+/* |
+** Return the type of the argument. |
+*/ |
+static void typeofFunc( |
+ sqlite3_context *context, |
+ int NotUsed, |
+ sqlite3_value **argv |
+){ |
+ const char *z = 0; |
+ UNUSED_PARAMETER(NotUsed); |
+ switch( sqlite3_value_type(argv[0]) ){ |
+ case SQLITE_INTEGER: z = "integer"; break; |
+ case SQLITE_TEXT: z = "text"; break; |
+ case SQLITE_FLOAT: z = "real"; break; |
+ case SQLITE_BLOB: z = "blob"; break; |
+ default: z = "null"; 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 ); |
+ UNUSED_PARAMETER(argc); |
+ 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. |
+** |
+** IMP: R-23979-26855 The abs(X) function returns the absolute value of |
+** the numeric argument X. |
+*/ |
+static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ |
+ assert( argc==1 ); |
+ UNUSED_PARAMETER(argc); |
+ switch( sqlite3_value_type(argv[0]) ){ |
+ case SQLITE_INTEGER: { |
+ i64 iVal = sqlite3_value_int64(argv[0]); |
+ if( iVal<0 ){ |
+ if( iVal==SMALLEST_INT64 ){ |
+ /* IMP: R-31676-45509 If X is the integer -9223372036854775808 |
+ ** then abs(X) throws an integer overflow error since there is no |
+ ** equivalent positive 64-bit two complement value. */ |
+ sqlite3_result_error(context, "integer overflow", -1); |
+ return; |
+ } |
+ iVal = -iVal; |
+ } |
+ sqlite3_result_int64(context, iVal); |
+ break; |
+ } |
+ case SQLITE_NULL: { |
+ /* IMP: R-37434-19929 Abs(X) returns NULL if X is NULL. */ |
+ sqlite3_result_null(context); |
+ break; |
+ } |
+ default: { |
+ /* Because sqlite3_value_double() returns 0.0 if the argument is not |
+ ** something that can be converted into a number, we have: |
+ ** IMP: R-01992-00519 Abs(X) returns 0.0 if X is a string or blob |
+ ** that cannot be converted to a numeric value. |
+ */ |
+ double rVal = sqlite3_value_double(argv[0]); |
+ if( rVal<0 ) rVal = -rVal; |
+ sqlite3_result_double(context, rVal); |
+ break; |
+ } |
+ } |
+} |
+ |
+/* |
+** Implementation of the instr() function. |
+** |
+** instr(haystack,needle) finds the first occurrence of needle |
+** in haystack and returns the number of previous characters plus 1, |
+** or 0 if needle does not occur within haystack. |
+** |
+** If both haystack and needle are BLOBs, then the result is one more than |
+** the number of bytes in haystack prior to the first occurrence of needle, |
+** or 0 if needle never occurs in haystack. |
+*/ |
+static void instrFunc( |
+ sqlite3_context *context, |
+ int argc, |
+ sqlite3_value **argv |
+){ |
+ const unsigned char *zHaystack; |
+ const unsigned char *zNeedle; |
+ int nHaystack; |
+ int nNeedle; |
+ int typeHaystack, typeNeedle; |
+ int N = 1; |
+ int isText; |
+ |
+ UNUSED_PARAMETER(argc); |
+ typeHaystack = sqlite3_value_type(argv[0]); |
+ typeNeedle = sqlite3_value_type(argv[1]); |
+ if( typeHaystack==SQLITE_NULL || typeNeedle==SQLITE_NULL ) return; |
+ nHaystack = sqlite3_value_bytes(argv[0]); |
+ nNeedle = sqlite3_value_bytes(argv[1]); |
+ if( nNeedle>0 ){ |
+ if( typeHaystack==SQLITE_BLOB && typeNeedle==SQLITE_BLOB ){ |
+ zHaystack = sqlite3_value_blob(argv[0]); |
+ zNeedle = sqlite3_value_blob(argv[1]); |
+ assert( zNeedle!=0 ); |
+ assert( zHaystack!=0 || nHaystack==0 ); |
+ isText = 0; |
+ }else{ |
+ zHaystack = sqlite3_value_text(argv[0]); |
+ zNeedle = sqlite3_value_text(argv[1]); |
+ isText = 1; |
+ if( zHaystack==0 || zNeedle==0 ) return; |
+ } |
+ while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){ |
+ N++; |
+ do{ |
+ nHaystack--; |
+ zHaystack++; |
+ }while( isText && (zHaystack[0]&0xc0)==0x80 ); |
+ } |
+ if( nNeedle>nHaystack ) N = 0; |
+ } |
+ sqlite3_result_int(context, N); |
+} |
+ |
+/* |
+** Implementation of the printf() function. |
+*/ |
+static void printfFunc( |
+ sqlite3_context *context, |
+ int argc, |
+ sqlite3_value **argv |
+){ |
+ PrintfArguments x; |
+ StrAccum str; |
+ const char *zFormat; |
+ int n; |
+ sqlite3 *db = sqlite3_context_db_handle(context); |
+ |
+ if( argc>=1 && (zFormat = (const char*)sqlite3_value_text(argv[0]))!=0 ){ |
+ x.nArg = argc-1; |
+ x.nUsed = 0; |
+ x.apArg = argv+1; |
+ sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); |
+ str.printfFlags = SQLITE_PRINTF_SQLFUNC; |
+ sqlite3XPrintf(&str, zFormat, &x); |
+ n = str.nChar; |
+ sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n, |
+ SQLITE_DYNAMIC); |
+ } |
+} |
+ |
+/* |
+** 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[]. |
+** |
+** If p2 is negative, return the p2 characters preceding p1. |
+*/ |
+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; |
+ int negP2 = 0; |
+ |
+ assert( argc==3 || argc==2 ); |
+ if( sqlite3_value_type(argv[1])==SQLITE_NULL |
+ || (argc==3 && sqlite3_value_type(argv[2])==SQLITE_NULL) |
+ ){ |
+ return; |
+ } |
+ p0type = sqlite3_value_type(argv[0]); |
+ p1 = sqlite3_value_int(argv[1]); |
+ 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; |
+ if( p1<0 ){ |
+ for(z2=z; *z2; len++){ |
+ SQLITE_SKIP_UTF8(z2); |
+ } |
+ } |
+ } |
+#ifdef SQLITE_SUBSTR_COMPATIBILITY |
+ /* If SUBSTR_COMPATIBILITY is defined then substr(X,0,N) work the same as |
+ ** as substr(X,1,N) - it returns the first N characters of X. This |
+ ** is essentially a back-out of the bug-fix in check-in [5fc125d362df4b8] |
+ ** from 2009-02-02 for compatibility of applications that exploited the |
+ ** old buggy behavior. */ |
+ if( p1==0 ) p1 = 1; /* <rdar://problem/6778339> */ |
+#endif |
+ if( argc==3 ){ |
+ p2 = sqlite3_value_int(argv[2]); |
+ if( p2<0 ){ |
+ p2 = -p2; |
+ negP2 = 1; |
+ } |
+ }else{ |
+ p2 = sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH]; |
+ } |
+ if( p1<0 ){ |
+ p1 += len; |
+ if( p1<0 ){ |
+ p2 += p1; |
+ if( p2<0 ) p2 = 0; |
+ p1 = 0; |
+ } |
+ }else if( p1>0 ){ |
+ p1--; |
+ }else if( p2>0 ){ |
+ p2--; |
+ } |
+ if( negP2 ){ |
+ p1 -= p2; |
+ if( p1<0 ){ |
+ p2 += p1; |
+ p1 = 0; |
+ } |
+ } |
+ assert( p1>=0 && p2>=0 ); |
+ if( p0type!=SQLITE_BLOB ){ |
+ while( *z && p1 ){ |
+ SQLITE_SKIP_UTF8(z); |
+ p1--; |
+ } |
+ for(z2=z; *z2 && p2; p2--){ |
+ SQLITE_SKIP_UTF8(z2); |
+ } |
+ sqlite3_result_text64(context, (char*)z, z2-z, SQLITE_TRANSIENT, |
+ SQLITE_UTF8); |
+ }else{ |
+ if( p1+p2>len ){ |
+ p2 = len-p1; |
+ if( p2<0 ) p2 = 0; |
+ } |
+ sqlite3_result_blob64(context, (char*)&z[p1], (u64)p2, SQLITE_TRANSIENT); |
+ } |
+} |
+ |
+/* |
+** Implementation of the round() function |
+*/ |
+#ifndef SQLITE_OMIT_FLOATING_POINT |
+static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ |
+ int n = 0; |
+ double r; |
+ char *zBuf; |
+ 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]); |
+ /* If Y==0 and X will fit in a 64-bit int, |
+ ** handle the rounding directly, |
+ ** otherwise use printf. |
+ */ |
+ if( n==0 && r>=0 && r<LARGEST_INT64-1 ){ |
+ r = (double)((sqlite_int64)(r+0.5)); |
+ }else if( n==0 && r<0 && (-r)<LARGEST_INT64-1 ){ |
+ r = -(double)((sqlite_int64)((-r)+0.5)); |
+ }else{ |
+ zBuf = sqlite3_mprintf("%.*f",n,r); |
+ if( zBuf==0 ){ |
+ sqlite3_result_error_nomem(context); |
+ return; |
+ } |
+ sqlite3AtoF(zBuf, &r, sqlite3Strlen30(zBuf), SQLITE_UTF8); |
+ sqlite3_free(zBuf); |
+ } |
+ sqlite3_result_double(context, r); |
+} |
+#endif |
+ |
+/* |
+** Allocate nByte bytes of space using sqlite3Malloc(). If the |
+** allocation fails, call sqlite3_result_error_nomem() to notify |
+** the database handle that malloc() has failed and return NULL. |
+** If nByte is larger than the maximum string or blob length, then |
+** raise an SQLITE_TOOBIG exception and return NULL. |
+*/ |
+static void *contextMalloc(sqlite3_context *context, i64 nByte){ |
+ char *z; |
+ sqlite3 *db = sqlite3_context_db_handle(context); |
+ assert( nByte>0 ); |
+ testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH] ); |
+ testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH]+1 ); |
+ if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ |
+ sqlite3_result_error_toobig(context); |
+ z = 0; |
+ }else{ |
+ z = sqlite3Malloc(nByte); |
+ if( !z ){ |
+ 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; |
+ UNUSED_PARAMETER(argc); |
+ 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 ){ |
+ for(i=0; i<n; i++){ |
+ z1[i] = (char)sqlite3Toupper(z2[i]); |
+ } |
+ sqlite3_result_text(context, z1, n, sqlite3_free); |
+ } |
+ } |
+} |
+static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ |
+ char *z1; |
+ const char *z2; |
+ int i, n; |
+ UNUSED_PARAMETER(argc); |
+ 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 ){ |
+ for(i=0; i<n; i++){ |
+ z1[i] = sqlite3Tolower(z2[i]); |
+ } |
+ sqlite3_result_text(context, z1, n, sqlite3_free); |
+ } |
+ } |
+} |
+ |
+/* |
+** Some functions like COALESCE() and IFNULL() and UNLIKELY() are implemented |
+** as VDBE code so that unused argument values do not have to be computed. |
+** However, we still need some kind of function implementation for this |
+** routines in the function table. The noopFunc macro provides this. |
+** noopFunc will never be called so it doesn't matter what the implementation |
+** is. We might as well use the "version()" function as a substitute. |
+*/ |
+#define noopFunc versionFunc /* Substitute function - never called */ |
+ |
+/* |
+** Implementation of random(). Return a random integer. |
+*/ |
+static void randomFunc( |
+ sqlite3_context *context, |
+ int NotUsed, |
+ sqlite3_value **NotUsed2 |
+){ |
+ sqlite_int64 r; |
+ UNUSED_PARAMETER2(NotUsed, NotUsed2); |
+ sqlite3_randomness(sizeof(r), &r); |
+ if( r<0 ){ |
+ /* We need to prevent a random number of 0x8000000000000000 |
+ ** (or -9223372036854775808) since when you do abs() of that |
+ ** number of you get the same value back again. To do this |
+ ** in a way that is testable, mask the sign bit off of negative |
+ ** values, resulting in a positive value. Then take the |
+ ** 2s complement of that positive value. The end result can |
+ ** therefore be no less than -9223372036854775807. |
+ */ |
+ r = -(r & LARGEST_INT64); |
+ } |
+ 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 ); |
+ UNUSED_PARAMETER(argc); |
+ 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 NotUsed, |
+ sqlite3_value **NotUsed2 |
+){ |
+ sqlite3 *db = sqlite3_context_db_handle(context); |
+ UNUSED_PARAMETER2(NotUsed, NotUsed2); |
+ /* IMP: R-51513-12026 The last_insert_rowid() SQL function is a |
+ ** wrapper around the sqlite3_last_insert_rowid() C/C++ interface |
+ ** function. */ |
+ sqlite3_result_int64(context, sqlite3_last_insert_rowid(db)); |
+} |
+ |
+/* |
+** Implementation of the changes() SQL function. |
+** |
+** IMP: R-62073-11209 The changes() SQL function is a wrapper |
+** around the sqlite3_changes() C/C++ function and hence follows the same |
+** rules for counting changes. |
+*/ |
+static void changes( |
+ sqlite3_context *context, |
+ int NotUsed, |
+ sqlite3_value **NotUsed2 |
+){ |
+ sqlite3 *db = sqlite3_context_db_handle(context); |
+ UNUSED_PARAMETER2(NotUsed, NotUsed2); |
+ 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 NotUsed, |
+ sqlite3_value **NotUsed2 |
+){ |
+ sqlite3 *db = sqlite3_context_db_handle(context); |
+ UNUSED_PARAMETER2(NotUsed, NotUsed2); |
+ /* IMP: R-52756-41993 This function is a wrapper around the |
+ ** sqlite3_total_changes() C/C++ interface. */ |
+ sqlite3_result_int(context, sqlite3_total_changes(db)); |
+} |
+ |
+/* |
+** A structure defining how to do GLOB-style comparisons. |
+*/ |
+struct compareInfo { |
+ u8 matchAll; /* "*" or "%" */ |
+ u8 matchOne; /* "?" or "_" */ |
+ u8 matchSet; /* "[" or 0 */ |
+ u8 noCase; /* true to ignore case differences */ |
+}; |
+ |
+/* |
+** For LIKE and GLOB matching on EBCDIC machines, assume that every |
+** character is exactly one byte in size. Also, provde the Utf8Read() |
+** macro for fast reading of the next character in the common case where |
+** the next character is ASCII. |
+*/ |
+#if defined(SQLITE_EBCDIC) |
+# define sqlite3Utf8Read(A) (*((*A)++)) |
+# define Utf8Read(A) (*(A++)) |
+#else |
+# define Utf8Read(A) (A[0]<0x80?*(A++):sqlite3Utf8Read(&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 }; |
+ |
+/* |
+** Possible error returns from patternMatch() |
+*/ |
+#define SQLITE_MATCH 0 |
+#define SQLITE_NOMATCH 1 |
+#define SQLITE_NOWILDCARDMATCH 2 |
+ |
+/* |
+** Compare two UTF-8 strings for equality where the first string is |
+** a GLOB or LIKE expression. Return values: |
+** |
+** SQLITE_MATCH: Match |
+** SQLITE_NOMATCH: No match |
+** SQLITE_NOWILDCARDMATCH: No match in spite of having * or % wildcards. |
+** |
+** 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. |
+** |
+** Like matching rules: |
+** |
+** '%' Matches any sequence of zero or more characters |
+** |
+*** '_' Matches any one character |
+** |
+** Ec Where E is the "esc" character and c is any other |
+** character, including '%', '_', and esc, match exactly c. |
+** |
+** The comments within this routine usually assume glob matching. |
+** |
+** This routine is usually quick, but can be N**2 in the worst case. |
+*/ |
+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 */ |
+ u32 matchOther /* The escape char (LIKE) or '[' (GLOB) */ |
+){ |
+ u32 c, c2; /* Next pattern and input string chars */ |
+ u32 matchOne = pInfo->matchOne; /* "?" or "_" */ |
+ u32 matchAll = pInfo->matchAll; /* "*" or "%" */ |
+ u8 noCase = pInfo->noCase; /* True if uppercase==lowercase */ |
+ const u8 *zEscaped = 0; /* One past the last escaped input char */ |
+ |
+ while( (c = Utf8Read(zPattern))!=0 ){ |
+ if( c==matchAll ){ /* Match "*" */ |
+ /* Skip over multiple "*" characters in the pattern. If there |
+ ** are also "?" characters, skip those as well, but consume a |
+ ** single character of the input string for each "?" skipped */ |
+ while( (c=Utf8Read(zPattern)) == matchAll || c == matchOne ){ |
+ if( c==matchOne && sqlite3Utf8Read(&zString)==0 ){ |
+ return SQLITE_NOWILDCARDMATCH; |
+ } |
+ } |
+ if( c==0 ){ |
+ return SQLITE_MATCH; /* "*" at the end of the pattern matches */ |
+ }else if( c==matchOther ){ |
+ if( pInfo->matchSet==0 ){ |
+ c = sqlite3Utf8Read(&zPattern); |
+ if( c==0 ) return SQLITE_NOWILDCARDMATCH; |
+ }else{ |
+ /* "[...]" immediately follows the "*". We have to do a slow |
+ ** recursive search in this case, but it is an unusual case. */ |
+ assert( matchOther<0x80 ); /* '[' is a single-byte character */ |
+ while( *zString ){ |
+ int bMatch = patternCompare(&zPattern[-1],zString,pInfo,matchOther); |
+ if( bMatch!=SQLITE_NOMATCH ) return bMatch; |
+ SQLITE_SKIP_UTF8(zString); |
+ } |
+ return SQLITE_NOWILDCARDMATCH; |
+ } |
+ } |
+ |
+ /* At this point variable c contains the first character of the |
+ ** pattern string past the "*". Search in the input string for the |
+ ** first matching character and recursively continue the match from |
+ ** that point. |
+ ** |
+ ** For a case-insensitive search, set variable cx to be the same as |
+ ** c but in the other case and search the input string for either |
+ ** c or cx. |
+ */ |
+ if( c<=0x80 ){ |
+ u32 cx; |
+ int bMatch; |
+ if( noCase ){ |
+ cx = sqlite3Toupper(c); |
+ c = sqlite3Tolower(c); |
+ }else{ |
+ cx = c; |
+ } |
+ while( (c2 = *(zString++))!=0 ){ |
+ if( c2!=c && c2!=cx ) continue; |
+ bMatch = patternCompare(zPattern,zString,pInfo,matchOther); |
+ if( bMatch!=SQLITE_NOMATCH ) return bMatch; |
+ } |
+ }else{ |
+ int bMatch; |
+ while( (c2 = Utf8Read(zString))!=0 ){ |
+ if( c2!=c ) continue; |
+ bMatch = patternCompare(zPattern,zString,pInfo,matchOther); |
+ if( bMatch!=SQLITE_NOMATCH ) return bMatch; |
+ } |
+ } |
+ return SQLITE_NOWILDCARDMATCH; |
+ } |
+ if( c==matchOther ){ |
+ if( pInfo->matchSet==0 ){ |
+ c = sqlite3Utf8Read(&zPattern); |
+ if( c==0 ) return SQLITE_NOMATCH; |
+ zEscaped = zPattern; |
+ }else{ |
+ u32 prior_c = 0; |
+ int seen = 0; |
+ int invert = 0; |
+ c = sqlite3Utf8Read(&zString); |
+ if( c==0 ) return SQLITE_NOMATCH; |
+ c2 = sqlite3Utf8Read(&zPattern); |
+ if( c2=='^' ){ |
+ invert = 1; |
+ c2 = sqlite3Utf8Read(&zPattern); |
+ } |
+ if( c2==']' ){ |
+ if( c==']' ) seen = 1; |
+ c2 = sqlite3Utf8Read(&zPattern); |
+ } |
+ while( c2 && c2!=']' ){ |
+ if( c2=='-' && zPattern[0]!=']' && zPattern[0]!=0 && prior_c>0 ){ |
+ c2 = sqlite3Utf8Read(&zPattern); |
+ if( c>=prior_c && c<=c2 ) seen = 1; |
+ prior_c = 0; |
+ }else{ |
+ if( c==c2 ){ |
+ seen = 1; |
+ } |
+ prior_c = c2; |
+ } |
+ c2 = sqlite3Utf8Read(&zPattern); |
+ } |
+ if( c2==0 || (seen ^ invert)==0 ){ |
+ return SQLITE_NOMATCH; |
+ } |
+ continue; |
+ } |
+ } |
+ c2 = Utf8Read(zString); |
+ if( c==c2 ) continue; |
+ if( noCase && sqlite3Tolower(c)==sqlite3Tolower(c2) && c<0x80 && c2<0x80 ){ |
+ continue; |
+ } |
+ if( c==matchOne && zPattern!=zEscaped && c2!=0 ) continue; |
+ return SQLITE_NOMATCH; |
+ } |
+ return *zString==0 ? SQLITE_MATCH : SQLITE_NOMATCH; |
+} |
+ |
+/* |
+** The sqlite3_strglob() interface. Return 0 on a match (like strcmp()) and |
+** non-zero if there is no match. |
+*/ |
+SQLITE_API int sqlite3_strglob(const char *zGlobPattern, const char *zString){ |
+ return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '['); |
+} |
+ |
+/* |
+** The sqlite3_strlike() interface. Return 0 on a match and non-zero for |
+** a miss - like strcmp(). |
+*/ |
+SQLITE_API int sqlite3_strlike(const char *zPattern, const char *zStr, unsigned int esc){ |
+ return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc); |
+} |
+ |
+/* |
+** 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 |
+SQLITE_API 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; |
+ u32 escape; |
+ int nPat; |
+ sqlite3 *db = sqlite3_context_db_handle(context); |
+ struct compareInfo *pInfo = sqlite3_user_data(context); |
+ |
+#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS |
+ if( sqlite3_value_type(argv[0])==SQLITE_BLOB |
+ || sqlite3_value_type(argv[1])==SQLITE_BLOB |
+ ){ |
+#ifdef SQLITE_TEST |
+ sqlite3_like_count++; |
+#endif |
+ sqlite3_result_int(context, 0); |
+ return; |
+ } |
+#endif |
+ 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(). |
+ */ |
+ nPat = sqlite3_value_bytes(argv[0]); |
+ testcase( nPat==db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] ); |
+ testcase( nPat==db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]+1 ); |
+ if( nPat > 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); |
+ }else{ |
+ escape = pInfo->matchSet; |
+ } |
+ if( zA && zB ){ |
+#ifdef SQLITE_TEST |
+ sqlite3_like_count++; |
+#endif |
+ sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape)==SQLITE_MATCH); |
+ } |
+} |
+ |
+/* |
+** 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 NotUsed, |
+ sqlite3_value **argv |
+){ |
+ CollSeq *pColl = sqlite3GetFuncCollSeq(context); |
+ UNUSED_PARAMETER(NotUsed); |
+ if( sqlite3MemCompare(argv[0], argv[1], pColl)!=0 ){ |
+ sqlite3_result_value(context, argv[0]); |
+ } |
+} |
+ |
+/* |
+** Implementation of the sqlite_version() function. The result is the version |
+** of the SQLite library that is running. |
+*/ |
+static void versionFunc( |
+ sqlite3_context *context, |
+ int NotUsed, |
+ sqlite3_value **NotUsed2 |
+){ |
+ UNUSED_PARAMETER2(NotUsed, NotUsed2); |
+ /* IMP: R-48699-48617 This function is an SQL wrapper around the |
+ ** sqlite3_libversion() C-interface. */ |
+ sqlite3_result_text(context, sqlite3_libversion(), -1, SQLITE_STATIC); |
+} |
+ |
+/* |
+** Implementation of the sqlite_source_id() function. The result is a string |
+** that identifies the particular version of the source code used to build |
+** SQLite. |
+*/ |
+static void sourceidFunc( |
+ sqlite3_context *context, |
+ int NotUsed, |
+ sqlite3_value **NotUsed2 |
+){ |
+ UNUSED_PARAMETER2(NotUsed, NotUsed2); |
+ /* IMP: R-24470-31136 This function is an SQL wrapper around the |
+ ** sqlite3_sourceid() C interface. */ |
+ sqlite3_result_text(context, sqlite3_sourceid(), -1, SQLITE_STATIC); |
+} |
+ |
+/* |
+** Implementation of the sqlite_log() function. This is a wrapper around |
+** sqlite3_log(). The return value is NULL. The function exists purely for |
+** its side-effects. |
+*/ |
+static void errlogFunc( |
+ sqlite3_context *context, |
+ int argc, |
+ sqlite3_value **argv |
+){ |
+ UNUSED_PARAMETER(argc); |
+ UNUSED_PARAMETER(context); |
+ sqlite3_log(sqlite3_value_int(argv[0]), "%s", sqlite3_value_text(argv[1])); |
+} |
+ |
+/* |
+** Implementation of the sqlite_compileoption_used() function. |
+** The result is an integer that identifies if the compiler option |
+** was used to build SQLite. |
+*/ |
+#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS |
+static void compileoptionusedFunc( |
+ sqlite3_context *context, |
+ int argc, |
+ sqlite3_value **argv |
+){ |
+ const char *zOptName; |
+ assert( argc==1 ); |
+ UNUSED_PARAMETER(argc); |
+ /* IMP: R-39564-36305 The sqlite_compileoption_used() SQL |
+ ** function is a wrapper around the sqlite3_compileoption_used() C/C++ |
+ ** function. |
+ */ |
+ if( (zOptName = (const char*)sqlite3_value_text(argv[0]))!=0 ){ |
+ sqlite3_result_int(context, sqlite3_compileoption_used(zOptName)); |
+ } |
+} |
+#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
+ |
+/* |
+** Implementation of the sqlite_compileoption_get() function. |
+** The result is a string that identifies the compiler options |
+** used to build SQLite. |
+*/ |
+#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS |
+static void compileoptiongetFunc( |
+ sqlite3_context *context, |
+ int argc, |
+ sqlite3_value **argv |
+){ |
+ int n; |
+ assert( argc==1 ); |
+ UNUSED_PARAMETER(argc); |
+ /* IMP: R-04922-24076 The sqlite_compileoption_get() SQL function |
+ ** is a wrapper around the sqlite3_compileoption_get() C/C++ function. |
+ */ |
+ n = sqlite3_value_int(argv[0]); |
+ sqlite3_result_text(context, sqlite3_compileoption_get(n), -1, SQLITE_STATIC); |
+} |
+#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
+ |
+/* 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' |
+}; |
+ |
+/* |
+** 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){ |
+ assert( argc==1 ); |
+ UNUSED_PARAMETER(argc); |
+ switch( sqlite3_value_type(argv[0]) ){ |
+ case SQLITE_FLOAT: { |
+ double r1, r2; |
+ char zBuf[50]; |
+ r1 = sqlite3_value_double(argv[0]); |
+ sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.15g", r1); |
+ sqlite3AtoF(zBuf, &r2, 20, SQLITE_UTF8); |
+ if( r1!=r2 ){ |
+ sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.20e", r1); |
+ } |
+ sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); |
+ break; |
+ } |
+ case SQLITE_INTEGER: { |
+ 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); |
+ } |
+ break; |
+ } |
+ default: { |
+ assert( sqlite3_value_type(argv[0])==SQLITE_NULL ); |
+ sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC); |
+ break; |
+ } |
+ } |
+} |
+ |
+/* |
+** The unicode() function. Return the integer unicode code-point value |
+** for the first character of the input string. |
+*/ |
+static void unicodeFunc( |
+ sqlite3_context *context, |
+ int argc, |
+ sqlite3_value **argv |
+){ |
+ const unsigned char *z = sqlite3_value_text(argv[0]); |
+ (void)argc; |
+ if( z && z[0] ) sqlite3_result_int(context, sqlite3Utf8Read(&z)); |
+} |
+ |
+/* |
+** The char() function takes zero or more arguments, each of which is |
+** an integer. It constructs a string where each character of the string |
+** is the unicode character for the corresponding integer argument. |
+*/ |
+static void charFunc( |
+ sqlite3_context *context, |
+ int argc, |
+ sqlite3_value **argv |
+){ |
+ unsigned char *z, *zOut; |
+ int i; |
+ zOut = z = sqlite3_malloc64( argc*4+1 ); |
+ if( z==0 ){ |
+ sqlite3_result_error_nomem(context); |
+ return; |
+ } |
+ for(i=0; i<argc; i++){ |
+ sqlite3_int64 x; |
+ unsigned c; |
+ x = sqlite3_value_int64(argv[i]); |
+ if( x<0 || x>0x10ffff ) x = 0xfffd; |
+ c = (unsigned)(x & 0x1fffff); |
+ if( c<0x00080 ){ |
+ *zOut++ = (u8)(c&0xFF); |
+ }else if( c<0x00800 ){ |
+ *zOut++ = 0xC0 + (u8)((c>>6)&0x1F); |
+ *zOut++ = 0x80 + (u8)(c & 0x3F); |
+ }else if( c<0x10000 ){ |
+ *zOut++ = 0xE0 + (u8)((c>>12)&0x0F); |
+ *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); |
+ *zOut++ = 0x80 + (u8)(c & 0x3F); |
+ }else{ |
+ *zOut++ = 0xF0 + (u8)((c>>18) & 0x07); |
+ *zOut++ = 0x80 + (u8)((c>>12) & 0x3F); |
+ *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); |
+ *zOut++ = 0x80 + (u8)(c & 0x3F); |
+ } \ |
+ } |
+ sqlite3_result_text64(context, (char*)z, zOut-z, sqlite3_free, SQLITE_UTF8); |
+} |
+ |
+/* |
+** 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 ); |
+ UNUSED_PARAMETER(argc); |
+ 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; |
+ int rc; |
+ assert( argc==1 ); |
+ UNUSED_PARAMETER(argc); |
+ n = sqlite3_value_int64(argv[0]); |
+ if( n<0 ) n = 0; |
+ rc = sqlite3_result_zeroblob64(context, n); /* IMP: R-00293-64994 */ |
+ if( rc ){ |
+ sqlite3_result_error_code(context, rc); |
+ } |
+} |
+ |
+/* |
+** 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 occurrence 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 ); |
+ UNUSED_PARAMETER(argc); |
+ 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 ){ |
+ assert( sqlite3_value_type(argv[1])==SQLITE_NULL |
+ || sqlite3_context_db_handle(context)->mallocFailed ); |
+ return; |
+ } |
+ if( zPattern[0]==0 ){ |
+ assert( sqlite3_value_type(argv[1])!=SQLITE_NULL ); |
+ sqlite3_result_value(context, argv[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; |
+ testcase( nOut-1==db->aLimit[SQLITE_LIMIT_LENGTH] ); |
+ testcase( nOut-2==db->aLimit[SQLITE_LIMIT_LENGTH] ); |
+ if( nOut-1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ |
+ sqlite3_result_error_toobig(context); |
+ sqlite3_free(zOut); |
+ return; |
+ } |
+ zOld = zOut; |
+ zOut = sqlite3_realloc64(zOut, (int)nOut); |
+ if( zOut==0 ){ |
+ sqlite3_result_error_nomem(context); |
+ sqlite3_free(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 = 0; /* Length of each character in zCharSet */ |
+ unsigned char **azChar = 0; /* 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 unsigned char * const 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] = (u8)(z - azChar[nChar]); |
+ } |
+ } |
+ } |
+ if( nChar>0 ){ |
+ flags = SQLITE_PTR_TO_INT(sqlite3_user_data(context)); |
+ if( flags & 1 ){ |
+ while( nIn>0 ){ |
+ int len = 0; |
+ for(i=0; i<nChar; i++){ |
+ len = aLen[i]; |
+ if( len<=nIn && memcmp(zIn, azChar[i], len)==0 ) break; |
+ } |
+ if( i>=nChar ) break; |
+ zIn += len; |
+ nIn -= len; |
+ } |
+ } |
+ if( flags & 2 ){ |
+ while( nIn>0 ){ |
+ int len = 0; |
+ 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(azChar); |
+ } |
+ } |
+ sqlite3_result_text(context, (char*)zIn, nIn, SQLITE_TRANSIENT); |
+} |
+ |
+ |
+#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION |
+/* |
+** The "unknown" function is automatically substituted in place of |
+** any unrecognized function name when doing an EXPLAIN or EXPLAIN QUERY PLAN |
+** when the SQLITE_ENABLE_UNKNOWN_FUNCTION compile-time option is used. |
+** When the "sqlite3" command-line shell is built using this functionality, |
+** that allows an EXPLAIN or EXPLAIN QUERY PLAN for complex queries |
+** involving application-defined functions to be examined in a generic |
+** sqlite3 shell. |
+*/ |
+static void unknownFunc( |
+ sqlite3_context *context, |
+ int argc, |
+ sqlite3_value **argv |
+){ |
+ /* no-op */ |
+} |
+#endif /*SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION*/ |
+ |
+ |
+/* IMP: R-25361-16150 This function is omitted from SQLite by default. It |
+** is only available if the SQLITE_SOUNDEX compile-time option is used |
+** when SQLite is built. |
+*/ |
+#ifdef SQLITE_SOUNDEX |
+/* |
+** Compute the soundex encoding of a word. |
+** |
+** IMP: R-59782-00072 The soundex(X) function returns a string that is the |
+** soundex encoding of the string X. |
+*/ |
+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] && !sqlite3Isalpha(zIn[i]); i++){} |
+ if( zIn[i] ){ |
+ u8 prevcode = iCode[zIn[i]&0x7f]; |
+ zResult[0] = sqlite3Toupper(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{ |
+ /* IMP: R-64894-50321 The string "?000" is returned if the argument |
+ ** is NULL or contains no ASCII alphabetic characters. */ |
+ sqlite3_result_text(context, "?000", 4, SQLITE_STATIC); |
+ } |
+} |
+#endif /* SQLITE_SOUNDEX */ |
+ |
+#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; |
+ |
+ /* Disallow the load_extension() SQL function unless the SQLITE_LoadExtFunc |
+ ** flag is set. See the sqlite3_enable_load_extension() API. |
+ */ |
+ if( (db->flags & SQLITE_LoadExtFunc)==0 ){ |
+ sqlite3_result_error(context, "not authorized", -1); |
+ return; |
+ } |
+ |
+ 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 ); |
+ UNUSED_PARAMETER(argc); |
+ 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 && sqlite3AddInt64(&p->iSum, v) ){ |
+ p->overflow = 1; |
+ } |
+ }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); |
+ /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ |
+ sqlite3_result_double(context, p ? p->rSum : (double)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++; |
+ } |
+ |
+#ifndef SQLITE_OMIT_DEPRECATED |
+ /* The sqlite3_aggregate_count() function is deprecated. But just to make |
+ ** sure it still operates correctly, verify that its count agrees with our |
+ ** internal count when using count(*) and when the total count can be |
+ ** expressed as a 32-bit integer. */ |
+ assert( argc==1 || p==0 || p->n>0x7fffffff |
+ || p->n==sqlite3_aggregate_count(context) ); |
+#endif |
+} |
+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 NotUsed, |
+ sqlite3_value **argv |
+){ |
+ Mem *pArg = (Mem *)argv[0]; |
+ Mem *pBest; |
+ UNUSED_PARAMETER(NotUsed); |
+ |
+ pBest = (Mem *)sqlite3_aggregate_context(context, sizeof(*pBest)); |
+ if( !pBest ) return; |
+ |
+ if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ |
+ if( pBest->flags ) sqlite3SkipAccumulatorLoad(context); |
+ }else 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{ |
+ sqlite3SkipAccumulatorLoad(context); |
+ } |
+ }else{ |
+ pBest->db = sqlite3_context_db_handle(context); |
+ 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; |
+ assert( argc==1 || argc==2 ); |
+ if( 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); |
+ int firstTerm = pAccum->mxAlloc==0; |
+ pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH]; |
+ if( !firstTerm ){ |
+ if( argc==2 ){ |
+ zSep = (char*)sqlite3_value_text(argv[1]); |
+ nSep = sqlite3_value_bytes(argv[1]); |
+ }else{ |
+ zSep = ","; |
+ nSep = 1; |
+ } |
+ if( zSep ) sqlite3StrAccumAppend(pAccum, zSep, nSep); |
+ } |
+ zVal = (char*)sqlite3_value_text(argv[0]); |
+ nVal = sqlite3_value_bytes(argv[0]); |
+ if( zVal ) sqlite3StrAccumAppend(pAccum, zVal, nVal); |
+ } |
+} |
+static void groupConcatFinalize(sqlite3_context *context){ |
+ StrAccum *pAccum; |
+ pAccum = sqlite3_aggregate_context(context, 0); |
+ if( pAccum ){ |
+ if( pAccum->accError==STRACCUM_TOOBIG ){ |
+ sqlite3_result_error_toobig(context); |
+ }else if( pAccum->accError==STRACCUM_NOMEM ){ |
+ sqlite3_result_error_nomem(context); |
+ }else{ |
+ sqlite3_result_text(context, sqlite3StrAccumFinish(pAccum), -1, |
+ sqlite3_free); |
+ } |
+ } |
+} |
+ |
+/* |
+** This routine does per-connection function registration. Most |
+** of the built-in functions above are part of the global function set. |
+** This routine only deals with those that are not global. |
+*/ |
+SQLITE_PRIVATE void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3 *db){ |
+ int rc = sqlite3_overload_function(db, "MATCH", 2); |
+ assert( rc==SQLITE_NOMEM || rc==SQLITE_OK ); |
+ if( rc==SQLITE_NOMEM ){ |
+ sqlite3OomFault(db); |
+ } |
+} |
+ |
+/* |
+** Set the LIKEOPT flag on the 2-argument function with the given name. |
+*/ |
+static void setLikeOptFlag(sqlite3 *db, const char *zName, u8 flagVal){ |
+ FuncDef *pDef; |
+ pDef = sqlite3FindFunction(db, zName, 2, SQLITE_UTF8, 0); |
+ if( ALWAYS(pDef) ){ |
+ pDef->funcFlags |= 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. |
+*/ |
+SQLITE_PRIVATE 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, 0); |
+ sqlite3CreateFunc(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0); |
+ sqlite3CreateFunc(db, "glob", 2, SQLITE_UTF8, |
+ (struct compareInfo*)&globInfo, likeFunc, 0, 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. |
+** |
+** *pIsNocase is set to true if uppercase and lowercase are equivalent for |
+** the function (default for LIKE). If the function makes the distinction |
+** between uppercase and lowercase (as does GLOB) then *pIsNocase is set to |
+** false. |
+*/ |
+SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){ |
+ FuncDef *pDef; |
+ if( pExpr->op!=TK_FUNCTION |
+ || !pExpr->x.pList |
+ || pExpr->x.pList->nExpr!=2 |
+ ){ |
+ return 0; |
+ } |
+ assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); |
+ pDef = sqlite3FindFunction(db, pExpr->u.zToken, 2, SQLITE_UTF8, 0); |
+ if( NEVER(pDef==0) || (pDef->funcFlags & 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->funcFlags & SQLITE_FUNC_CASE)==0; |
+ return 1; |
+} |
+ |
+/* |
+** All of the FuncDef structures in the aBuiltinFunc[] array above |
+** to the global function hash table. This occurs at start-time (as |
+** a consequence of calling sqlite3_initialize()). |
+** |
+** After this routine runs |
+*/ |
+SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){ |
+ /* |
+ ** The following array holds FuncDef structures for all of the functions |
+ ** defined in this file. |
+ ** |
+ ** The array cannot be constant since changes are made to the |
+ ** FuncDef.pHash elements at start-time. The elements of this array |
+ ** are read-only after initialization is complete. |
+ ** |
+ ** For peak efficiency, put the most frequently used function last. |
+ */ |
+ static FuncDef aBuiltinFunc[] = { |
+#ifdef SQLITE_SOUNDEX |
+ FUNCTION(soundex, 1, 0, 0, soundexFunc ), |
+#endif |
+#ifndef SQLITE_OMIT_LOAD_EXTENSION |
+ VFUNCTION(load_extension, 1, 0, 0, loadExt ), |
+ VFUNCTION(load_extension, 2, 0, 0, loadExt ), |
+#endif |
+#if SQLITE_USER_AUTHENTICATION |
+ FUNCTION(sqlite_crypt, 2, 0, 0, sqlite3CryptFunc ), |
+#endif |
+#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS |
+ DFUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ), |
+ DFUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ), |
+#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
+ FUNCTION2(unlikely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY), |
+ FUNCTION2(likelihood, 2, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY), |
+ FUNCTION2(likely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY), |
+#ifdef SQLITE_DEBUG |
+ FUNCTION2(affinity, 1, 0, 0, noopFunc, SQLITE_FUNC_AFFINITY), |
+#endif |
+ FUNCTION(ltrim, 1, 1, 0, trimFunc ), |
+ FUNCTION(ltrim, 2, 1, 0, trimFunc ), |
+ FUNCTION(rtrim, 1, 2, 0, trimFunc ), |
+ FUNCTION(rtrim, 2, 2, 0, trimFunc ), |
+ FUNCTION(trim, 1, 3, 0, trimFunc ), |
+ FUNCTION(trim, 2, 3, 0, trimFunc ), |
+ FUNCTION(min, -1, 0, 1, minmaxFunc ), |
+ FUNCTION(min, 0, 0, 1, 0 ), |
+ AGGREGATE2(min, 1, 0, 1, minmaxStep, minMaxFinalize, |
+ SQLITE_FUNC_MINMAX ), |
+ FUNCTION(max, -1, 1, 1, minmaxFunc ), |
+ FUNCTION(max, 0, 1, 1, 0 ), |
+ AGGREGATE2(max, 1, 1, 1, minmaxStep, minMaxFinalize, |
+ SQLITE_FUNC_MINMAX ), |
+ FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF), |
+ FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH), |
+ FUNCTION(instr, 2, 0, 0, instrFunc ), |
+ FUNCTION(printf, -1, 0, 0, printfFunc ), |
+ FUNCTION(unicode, 1, 0, 0, unicodeFunc ), |
+ FUNCTION(char, -1, 0, 0, charFunc ), |
+ FUNCTION(abs, 1, 0, 0, absFunc ), |
+#ifndef SQLITE_OMIT_FLOATING_POINT |
+ FUNCTION(round, 1, 0, 0, roundFunc ), |
+ FUNCTION(round, 2, 0, 0, roundFunc ), |
+#endif |
+ FUNCTION(upper, 1, 0, 0, upperFunc ), |
+ FUNCTION(lower, 1, 0, 0, lowerFunc ), |
+ FUNCTION(hex, 1, 0, 0, hexFunc ), |
+ FUNCTION2(ifnull, 2, 0, 0, noopFunc, SQLITE_FUNC_COALESCE), |
+ VFUNCTION(random, 0, 0, 0, randomFunc ), |
+ VFUNCTION(randomblob, 1, 0, 0, randomBlob ), |
+ FUNCTION(nullif, 2, 0, 1, nullifFunc ), |
+ DFUNCTION(sqlite_version, 0, 0, 0, versionFunc ), |
+ DFUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ), |
+ FUNCTION(sqlite_log, 2, 0, 0, errlogFunc ), |
+ FUNCTION(quote, 1, 0, 0, quoteFunc ), |
+ VFUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid), |
+ VFUNCTION(changes, 0, 0, 0, changes ), |
+ VFUNCTION(total_changes, 0, 0, 0, total_changes ), |
+ FUNCTION(replace, 3, 0, 0, replaceFunc ), |
+ FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ), |
+ FUNCTION(substr, 2, 0, 0, substrFunc ), |
+ FUNCTION(substr, 3, 0, 0, substrFunc ), |
+ AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize ), |
+ AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ), |
+ AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ), |
+ AGGREGATE2(count, 0, 0, 0, countStep, countFinalize, |
+ SQLITE_FUNC_COUNT ), |
+ AGGREGATE(count, 1, 0, 0, countStep, countFinalize ), |
+ AGGREGATE(group_concat, 1, 0, 0, groupConcatStep, groupConcatFinalize), |
+ AGGREGATE(group_concat, 2, 0, 0, groupConcatStep, groupConcatFinalize), |
+ |
+ LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), |
+#ifdef SQLITE_CASE_SENSITIVE_LIKE |
+ LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), |
+ LIKEFUNC(like, 3, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), |
+#else |
+ LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE), |
+ LIKEFUNC(like, 3, &likeInfoNorm, SQLITE_FUNC_LIKE), |
+#endif |
+#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION |
+ FUNCTION(unknown, -1, 0, 0, unknownFunc ), |
+#endif |
+ FUNCTION(coalesce, 1, 0, 0, 0 ), |
+ FUNCTION(coalesce, 0, 0, 0, 0 ), |
+ FUNCTION2(coalesce, -1, 0, 0, noopFunc, SQLITE_FUNC_COALESCE), |
+ }; |
+#ifndef SQLITE_OMIT_ALTERTABLE |
+ sqlite3AlterFunctions(); |
+#endif |
+#if defined(SQLITE_ENABLE_STAT3) || defined(SQLITE_ENABLE_STAT4) |
+ sqlite3AnalyzeFunctions(); |
+#endif |
+ sqlite3RegisterDateTimeFunctions(); |
+ sqlite3InsertBuiltinFuncs(aBuiltinFunc, ArraySize(aBuiltinFunc)); |
+ |
+#if 0 /* Enable to print out how the built-in functions are hashed */ |
+ { |
+ int i; |
+ FuncDef *p; |
+ for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){ |
+ printf("FUNC-HASH %02d:", i); |
+ for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash){ |
+ int n = sqlite3Strlen30(p->zName); |
+ int h = p->zName[0] + n; |
+ printf(" %s(%d)", p->zName, h); |
+ } |
+ printf("\n"); |
+ } |
+ } |
+#endif |
+} |
+ |
+/************** End of func.c ************************************************/ |
+/************** Begin file fkey.c ********************************************/ |
+/* |
+** |
+** 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 by the compiler to add foreign key |
+** support to compiled SQL statements. |
+*/ |
+/* #include "sqliteInt.h" */ |
+ |
+#ifndef SQLITE_OMIT_FOREIGN_KEY |
+#ifndef SQLITE_OMIT_TRIGGER |
+ |
+/* |
+** Deferred and Immediate FKs |
+** -------------------------- |
+** |
+** Foreign keys in SQLite come in two flavours: deferred and immediate. |
+** If an immediate foreign key constraint is violated, |
+** SQLITE_CONSTRAINT_FOREIGNKEY is returned and the current |
+** statement transaction rolled back. If a |
+** deferred foreign key constraint is violated, no action is taken |
+** immediately. However if the application attempts to commit the |
+** transaction before fixing the constraint violation, the attempt fails. |
+** |
+** Deferred constraints are implemented using a simple counter associated |
+** with the database handle. The counter is set to zero each time a |
+** database transaction is opened. Each time a statement is executed |
+** that causes a foreign key violation, the counter is incremented. Each |
+** time a statement is executed that removes an existing violation from |
+** the database, the counter is decremented. When the transaction is |
+** committed, the commit fails if the current value of the counter is |
+** greater than zero. This scheme has two big drawbacks: |
+** |
+** * When a commit fails due to a deferred foreign key constraint, |
+** there is no way to tell which foreign constraint is not satisfied, |
+** or which row it is not satisfied for. |
+** |
+** * If the database contains foreign key violations when the |
+** transaction is opened, this may cause the mechanism to malfunction. |
+** |
+** Despite these problems, this approach is adopted as it seems simpler |
+** than the alternatives. |
+** |
+** INSERT operations: |
+** |
+** I.1) For each FK for which the table is the child table, search |
+** the parent table for a match. If none is found increment the |
+** constraint counter. |
+** |
+** I.2) For each FK for which the table is the parent table, |
+** search the child table for rows that correspond to the new |
+** row in the parent table. Decrement the counter for each row |
+** found (as the constraint is now satisfied). |
+** |
+** DELETE operations: |
+** |
+** D.1) For each FK for which the table is the child table, |
+** search the parent table for a row that corresponds to the |
+** deleted row in the child table. If such a row is not found, |
+** decrement the counter. |
+** |
+** D.2) For each FK for which the table is the parent table, search |
+** the child table for rows that correspond to the deleted row |
+** in the parent table. For each found increment the counter. |
+** |
+** UPDATE operations: |
+** |
+** An UPDATE command requires that all 4 steps above are taken, but only |
+** for FK constraints for which the affected columns are actually |
+** modified (values must be compared at runtime). |
+** |
+** Note that I.1 and D.1 are very similar operations, as are I.2 and D.2. |
+** This simplifies the implementation a bit. |
+** |
+** For the purposes of immediate FK constraints, the OR REPLACE conflict |
+** resolution is considered to delete rows before the new row is inserted. |
+** If a delete caused by OR REPLACE violates an FK constraint, an exception |
+** is thrown, even if the FK constraint would be satisfied after the new |
+** row is inserted. |
+** |
+** Immediate constraints are usually handled similarly. The only difference |
+** is that the counter used is stored as part of each individual statement |
+** object (struct Vdbe). If, after the statement has run, its immediate |
+** constraint counter is greater than zero, |
+** it returns SQLITE_CONSTRAINT_FOREIGNKEY |
+** and the statement transaction is rolled back. An exception is an INSERT |
+** statement that inserts a single row only (no triggers). In this case, |
+** instead of using a counter, an exception is thrown immediately if the |
+** INSERT violates a foreign key constraint. This is necessary as such |
+** an INSERT does not open a statement transaction. |
+** |
+** TODO: How should dropping a table be handled? How should renaming a |
+** table be handled? |
+** |
+** |
+** Query API Notes |
+** --------------- |
+** |
+** Before coding an UPDATE or DELETE row operation, the code-generator |
+** for those two operations needs to know whether or not the operation |
+** requires any FK processing and, if so, which columns of the original |
+** row are required by the FK processing VDBE code (i.e. if FKs were |
+** implemented using triggers, which of the old.* columns would be |
+** accessed). No information is required by the code-generator before |
+** coding an INSERT operation. The functions used by the UPDATE/DELETE |
+** generation code to query for this information are: |
+** |
+** sqlite3FkRequired() - Test to see if FK processing is required. |
+** sqlite3FkOldmask() - Query for the set of required old.* columns. |
+** |
+** |
+** Externally accessible module functions |
+** -------------------------------------- |
+** |
+** sqlite3FkCheck() - Check for foreign key violations. |
+** sqlite3FkActions() - Code triggers for ON UPDATE/ON DELETE actions. |
+** sqlite3FkDelete() - Delete an FKey structure. |
+*/ |
+ |
+/* |
+** VDBE Calling Convention |
+** ----------------------- |
+** |
+** Example: |
+** |
+** For the following INSERT statement: |
+** |
+** CREATE TABLE t1(a, b INTEGER PRIMARY KEY, c); |
+** INSERT INTO t1 VALUES(1, 2, 3.1); |
+** |
+** Register (x): 2 (type integer) |
+** Register (x+1): 1 (type integer) |
+** Register (x+2): NULL (type NULL) |
+** Register (x+3): 3.1 (type real) |
+*/ |
+ |
+/* |
+** A foreign key constraint requires that the key columns in the parent |
+** table are collectively subject to a UNIQUE or PRIMARY KEY constraint. |
+** Given that pParent is the parent table for foreign key constraint pFKey, |
+** search the schema for a unique index on the parent key columns. |
+** |
+** If successful, zero is returned. If the parent key is an INTEGER PRIMARY |
+** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx |
+** is set to point to the unique index. |
+** |
+** If the parent key consists of a single column (the foreign key constraint |
+** is not a composite foreign key), output variable *paiCol is set to NULL. |
+** Otherwise, it is set to point to an allocated array of size N, where |
+** N is the number of columns in the parent key. The first element of the |
+** array is the index of the child table column that is mapped by the FK |
+** constraint to the parent table column stored in the left-most column |
+** of index *ppIdx. The second element of the array is the index of the |
+** child table column that corresponds to the second left-most column of |
+** *ppIdx, and so on. |
+** |
+** If the required index cannot be found, either because: |
+** |
+** 1) The named parent key columns do not exist, or |
+** |
+** 2) The named parent key columns do exist, but are not subject to a |
+** UNIQUE or PRIMARY KEY constraint, or |
+** |
+** 3) No parent key columns were provided explicitly as part of the |
+** foreign key definition, and the parent table does not have a |
+** PRIMARY KEY, or |
+** |
+** 4) No parent key columns were provided explicitly as part of the |
+** foreign key definition, and the PRIMARY KEY of the parent table |
+** consists of a different number of columns to the child key in |
+** the child table. |
+** |
+** then non-zero is returned, and a "foreign key mismatch" error loaded |
+** into pParse. If an OOM error occurs, non-zero is returned and the |
+** pParse->db->mallocFailed flag is set. |
+*/ |
+SQLITE_PRIVATE int sqlite3FkLocateIndex( |
+ Parse *pParse, /* Parse context to store any error in */ |
+ Table *pParent, /* Parent table of FK constraint pFKey */ |
+ FKey *pFKey, /* Foreign key to find index for */ |
+ Index **ppIdx, /* OUT: Unique index on parent table */ |
+ int **paiCol /* OUT: Map of index columns in pFKey */ |
+){ |
+ Index *pIdx = 0; /* Value to return via *ppIdx */ |
+ int *aiCol = 0; /* Value to return via *paiCol */ |
+ int nCol = pFKey->nCol; /* Number of columns in parent key */ |
+ char *zKey = pFKey->aCol[0].zCol; /* Name of left-most parent key column */ |
+ |
+ /* The caller is responsible for zeroing output parameters. */ |
+ assert( ppIdx && *ppIdx==0 ); |
+ assert( !paiCol || *paiCol==0 ); |
+ assert( pParse ); |
+ |
+ /* If this is a non-composite (single column) foreign key, check if it |
+ ** maps to the INTEGER PRIMARY KEY of table pParent. If so, leave *ppIdx |
+ ** and *paiCol set to zero and return early. |
+ ** |
+ ** Otherwise, for a composite foreign key (more than one column), allocate |
+ ** space for the aiCol array (returned via output parameter *paiCol). |
+ ** Non-composite foreign keys do not require the aiCol array. |
+ */ |
+ if( nCol==1 ){ |
+ /* The FK maps to the IPK if any of the following are true: |
+ ** |
+ ** 1) There is an INTEGER PRIMARY KEY column and the FK is implicitly |
+ ** mapped to the primary key of table pParent, or |
+ ** 2) The FK is explicitly mapped to a column declared as INTEGER |
+ ** PRIMARY KEY. |
+ */ |
+ if( pParent->iPKey>=0 ){ |
+ if( !zKey ) return 0; |
+ if( !sqlite3StrICmp(pParent->aCol[pParent->iPKey].zName, zKey) ) return 0; |
+ } |
+ }else if( paiCol ){ |
+ assert( nCol>1 ); |
+ aiCol = (int *)sqlite3DbMallocRawNN(pParse->db, nCol*sizeof(int)); |
+ if( !aiCol ) return 1; |
+ *paiCol = aiCol; |
+ } |
+ |
+ for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){ |
+ if( pIdx->nKeyCol==nCol && IsUniqueIndex(pIdx) && pIdx->pPartIdxWhere==0 ){ |
+ /* pIdx is a UNIQUE index (or a PRIMARY KEY) and has the right number |
+ ** of columns. If each indexed column corresponds to a foreign key |
+ ** column of pFKey, then this index is a winner. */ |
+ |
+ if( zKey==0 ){ |
+ /* If zKey is NULL, then this foreign key is implicitly mapped to |
+ ** the PRIMARY KEY of table pParent. The PRIMARY KEY index may be |
+ ** identified by the test. */ |
+ if( IsPrimaryKeyIndex(pIdx) ){ |
+ if( aiCol ){ |
+ int i; |
+ for(i=0; i<nCol; i++) aiCol[i] = pFKey->aCol[i].iFrom; |
+ } |
+ break; |
+ } |
+ }else{ |
+ /* If zKey is non-NULL, then this foreign key was declared to |
+ ** map to an explicit list of columns in table pParent. Check if this |
+ ** index matches those columns. Also, check that the index uses |
+ ** the default collation sequences for each column. */ |
+ int i, j; |
+ for(i=0; i<nCol; i++){ |
+ i16 iCol = pIdx->aiColumn[i]; /* Index of column in parent tbl */ |
+ const char *zDfltColl; /* Def. collation for column */ |
+ char *zIdxCol; /* Name of indexed column */ |
+ |
+ if( iCol<0 ) break; /* No foreign keys against expression indexes */ |
+ |
+ /* If the index uses a collation sequence that is different from |
+ ** the default collation sequence for the column, this index is |
+ ** unusable. Bail out early in this case. */ |
+ zDfltColl = pParent->aCol[iCol].zColl; |
+ if( !zDfltColl ) zDfltColl = sqlite3StrBINARY; |
+ if( sqlite3StrICmp(pIdx->azColl[i], zDfltColl) ) break; |
+ |
+ zIdxCol = pParent->aCol[iCol].zName; |
+ for(j=0; j<nCol; j++){ |
+ if( sqlite3StrICmp(pFKey->aCol[j].zCol, zIdxCol)==0 ){ |
+ if( aiCol ) aiCol[i] = pFKey->aCol[j].iFrom; |
+ break; |
+ } |
+ } |
+ if( j==nCol ) break; |
+ } |
+ if( i==nCol ) break; /* pIdx is usable */ |
+ } |
+ } |
+ } |
+ |
+ if( !pIdx ){ |
+ if( !pParse->disableTriggers ){ |
+ sqlite3ErrorMsg(pParse, |
+ "foreign key mismatch - \"%w\" referencing \"%w\"", |
+ pFKey->pFrom->zName, pFKey->zTo); |
+ } |
+ sqlite3DbFree(pParse->db, aiCol); |
+ return 1; |
+ } |
+ |
+ *ppIdx = pIdx; |
+ return 0; |
+} |
+ |
+/* |
+** This function is called when a row is inserted into or deleted from the |
+** child table of foreign key constraint pFKey. If an SQL UPDATE is executed |
+** on the child table of pFKey, this function is invoked twice for each row |
+** affected - once to "delete" the old row, and then again to "insert" the |
+** new row. |
+** |
+** Each time it is called, this function generates VDBE code to locate the |
+** row in the parent table that corresponds to the row being inserted into |
+** or deleted from the child table. If the parent row can be found, no |
+** special action is taken. Otherwise, if the parent row can *not* be |
+** found in the parent table: |
+** |
+** Operation | FK type | Action taken |
+** -------------------------------------------------------------------------- |
+** INSERT immediate Increment the "immediate constraint counter". |
+** |
+** DELETE immediate Decrement the "immediate constraint counter". |
+** |
+** INSERT deferred Increment the "deferred constraint counter". |
+** |
+** DELETE deferred Decrement the "deferred constraint counter". |
+** |
+** These operations are identified in the comment at the top of this file |
+** (fkey.c) as "I.1" and "D.1". |
+*/ |
+static void fkLookupParent( |
+ Parse *pParse, /* Parse context */ |
+ int iDb, /* Index of database housing pTab */ |
+ Table *pTab, /* Parent table of FK pFKey */ |
+ Index *pIdx, /* Unique index on parent key columns in pTab */ |
+ FKey *pFKey, /* Foreign key constraint */ |
+ int *aiCol, /* Map from parent key columns to child table columns */ |
+ int regData, /* Address of array containing child table row */ |
+ int nIncr, /* Increment constraint counter by this */ |
+ int isIgnore /* If true, pretend pTab contains all NULL values */ |
+){ |
+ int i; /* Iterator variable */ |
+ Vdbe *v = sqlite3GetVdbe(pParse); /* Vdbe to add code to */ |
+ int iCur = pParse->nTab - 1; /* Cursor number to use */ |
+ int iOk = sqlite3VdbeMakeLabel(v); /* jump here if parent key found */ |
+ |
+ /* If nIncr is less than zero, then check at runtime if there are any |
+ ** outstanding constraints to resolve. If there are not, there is no need |
+ ** to check if deleting this row resolves any outstanding violations. |
+ ** |
+ ** Check if any of the key columns in the child table row are NULL. If |
+ ** any are, then the constraint is considered satisfied. No need to |
+ ** search for a matching row in the parent table. */ |
+ if( nIncr<0 ){ |
+ sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, iOk); |
+ VdbeCoverage(v); |
+ } |
+ for(i=0; i<pFKey->nCol; i++){ |
+ int iReg = aiCol[i] + regData + 1; |
+ sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iOk); VdbeCoverage(v); |
+ } |
+ |
+ if( isIgnore==0 ){ |
+ if( pIdx==0 ){ |
+ /* If pIdx is NULL, then the parent key is the INTEGER PRIMARY KEY |
+ ** column of the parent table (table pTab). */ |
+ int iMustBeInt; /* Address of MustBeInt instruction */ |
+ int regTemp = sqlite3GetTempReg(pParse); |
+ |
+ /* Invoke MustBeInt to coerce the child key value to an integer (i.e. |
+ ** apply the affinity of the parent key). If this fails, then there |
+ ** is no matching parent key. Before using MustBeInt, make a copy of |
+ ** the value. Otherwise, the value inserted into the child key column |
+ ** will have INTEGER affinity applied to it, which may not be correct. */ |
+ sqlite3VdbeAddOp2(v, OP_SCopy, aiCol[0]+1+regData, regTemp); |
+ iMustBeInt = sqlite3VdbeAddOp2(v, OP_MustBeInt, regTemp, 0); |
+ VdbeCoverage(v); |
+ |
+ /* If the parent table is the same as the child table, and we are about |
+ ** to increment the constraint-counter (i.e. this is an INSERT operation), |
+ ** then check if the row being inserted matches itself. If so, do not |
+ ** increment the constraint-counter. */ |
+ if( pTab==pFKey->pFrom && nIncr==1 ){ |
+ sqlite3VdbeAddOp3(v, OP_Eq, regData, iOk, regTemp); VdbeCoverage(v); |
+ sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); |
+ } |
+ |
+ sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead); |
+ sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regTemp); VdbeCoverage(v); |
+ sqlite3VdbeGoto(v, iOk); |
+ sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); |
+ sqlite3VdbeJumpHere(v, iMustBeInt); |
+ sqlite3ReleaseTempReg(pParse, regTemp); |
+ }else{ |
+ int nCol = pFKey->nCol; |
+ int regTemp = sqlite3GetTempRange(pParse, nCol); |
+ int regRec = sqlite3GetTempReg(pParse); |
+ |
+ sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum, iDb); |
+ sqlite3VdbeSetP4KeyInfo(pParse, pIdx); |
+ for(i=0; i<nCol; i++){ |
+ sqlite3VdbeAddOp2(v, OP_Copy, aiCol[i]+1+regData, regTemp+i); |
+ } |
+ |
+ /* If the parent table is the same as the child table, and we are about |
+ ** to increment the constraint-counter (i.e. this is an INSERT operation), |
+ ** then check if the row being inserted matches itself. If so, do not |
+ ** increment the constraint-counter. |
+ ** |
+ ** If any of the parent-key values are NULL, then the row cannot match |
+ ** itself. So set JUMPIFNULL to make sure we do the OP_Found if any |
+ ** of the parent-key values are NULL (at this point it is known that |
+ ** none of the child key values are). |
+ */ |
+ if( pTab==pFKey->pFrom && nIncr==1 ){ |
+ int iJump = sqlite3VdbeCurrentAddr(v) + nCol + 1; |
+ for(i=0; i<nCol; i++){ |
+ int iChild = aiCol[i]+1+regData; |
+ int iParent = pIdx->aiColumn[i]+1+regData; |
+ assert( pIdx->aiColumn[i]>=0 ); |
+ assert( aiCol[i]!=pTab->iPKey ); |
+ if( pIdx->aiColumn[i]==pTab->iPKey ){ |
+ /* The parent key is a composite key that includes the IPK column */ |
+ iParent = regData; |
+ } |
+ sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent); VdbeCoverage(v); |
+ sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); |
+ } |
+ sqlite3VdbeGoto(v, iOk); |
+ } |
+ |
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, regTemp, nCol, regRec, |
+ sqlite3IndexAffinityStr(pParse->db,pIdx), nCol); |
+ sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0); VdbeCoverage(v); |
+ |
+ sqlite3ReleaseTempReg(pParse, regRec); |
+ sqlite3ReleaseTempRange(pParse, regTemp, nCol); |
+ } |
+ } |
+ |
+ if( !pFKey->isDeferred && !(pParse->db->flags & SQLITE_DeferFKs) |
+ && !pParse->pToplevel |
+ && !pParse->isMultiWrite |
+ ){ |
+ /* Special case: If this is an INSERT statement that will insert exactly |
+ ** one row into the table, raise a constraint immediately instead of |
+ ** incrementing a counter. This is necessary as the VM code is being |
+ ** generated for will not open a statement transaction. */ |
+ assert( nIncr==1 ); |
+ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY, |
+ OE_Abort, 0, P4_STATIC, P5_ConstraintFK); |
+ }else{ |
+ if( nIncr>0 && pFKey->isDeferred==0 ){ |
+ sqlite3MayAbort(pParse); |
+ } |
+ sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); |
+ } |
+ |
+ sqlite3VdbeResolveLabel(v, iOk); |
+ sqlite3VdbeAddOp1(v, OP_Close, iCur); |
+} |
+ |
+ |
+/* |
+** Return an Expr object that refers to a memory register corresponding |
+** to column iCol of table pTab. |
+** |
+** regBase is the first of an array of register that contains the data |
+** for pTab. regBase itself holds the rowid. regBase+1 holds the first |
+** column. regBase+2 holds the second column, and so forth. |
+*/ |
+static Expr *exprTableRegister( |
+ Parse *pParse, /* Parsing and code generating context */ |
+ Table *pTab, /* The table whose content is at r[regBase]... */ |
+ int regBase, /* Contents of table pTab */ |
+ i16 iCol /* Which column of pTab is desired */ |
+){ |
+ Expr *pExpr; |
+ Column *pCol; |
+ const char *zColl; |
+ sqlite3 *db = pParse->db; |
+ |
+ pExpr = sqlite3Expr(db, TK_REGISTER, 0); |
+ if( pExpr ){ |
+ if( iCol>=0 && iCol!=pTab->iPKey ){ |
+ pCol = &pTab->aCol[iCol]; |
+ pExpr->iTable = regBase + iCol + 1; |
+ pExpr->affinity = pCol->affinity; |
+ zColl = pCol->zColl; |
+ if( zColl==0 ) zColl = db->pDfltColl->zName; |
+ pExpr = sqlite3ExprAddCollateString(pParse, pExpr, zColl); |
+ }else{ |
+ pExpr->iTable = regBase; |
+ pExpr->affinity = SQLITE_AFF_INTEGER; |
+ } |
+ } |
+ return pExpr; |
+} |
+ |
+/* |
+** Return an Expr object that refers to column iCol of table pTab which |
+** has cursor iCur. |
+*/ |
+static Expr *exprTableColumn( |
+ sqlite3 *db, /* The database connection */ |
+ Table *pTab, /* The table whose column is desired */ |
+ int iCursor, /* The open cursor on the table */ |
+ i16 iCol /* The column that is wanted */ |
+){ |
+ Expr *pExpr = sqlite3Expr(db, TK_COLUMN, 0); |
+ if( pExpr ){ |
+ pExpr->pTab = pTab; |
+ pExpr->iTable = iCursor; |
+ pExpr->iColumn = iCol; |
+ } |
+ return pExpr; |
+} |
+ |
+/* |
+** This function is called to generate code executed when a row is deleted |
+** from the parent table of foreign key constraint pFKey and, if pFKey is |
+** deferred, when a row is inserted into the same table. When generating |
+** code for an SQL UPDATE operation, this function may be called twice - |
+** once to "delete" the old row and once to "insert" the new row. |
+** |
+** Parameter nIncr is passed -1 when inserting a row (as this may decrease |
+** the number of FK violations in the db) or +1 when deleting one (as this |
+** may increase the number of FK constraint problems). |
+** |
+** The code generated by this function scans through the rows in the child |
+** table that correspond to the parent table row being deleted or inserted. |
+** For each child row found, one of the following actions is taken: |
+** |
+** Operation | FK type | Action taken |
+** -------------------------------------------------------------------------- |
+** DELETE immediate Increment the "immediate constraint counter". |
+** Or, if the ON (UPDATE|DELETE) action is RESTRICT, |
+** throw a "FOREIGN KEY constraint failed" exception. |
+** |
+** INSERT immediate Decrement the "immediate constraint counter". |
+** |
+** DELETE deferred Increment the "deferred constraint counter". |
+** Or, if the ON (UPDATE|DELETE) action is RESTRICT, |
+** throw a "FOREIGN KEY constraint failed" exception. |
+** |
+** INSERT deferred Decrement the "deferred constraint counter". |
+** |
+** These operations are identified in the comment at the top of this file |
+** (fkey.c) as "I.2" and "D.2". |
+*/ |
+static void fkScanChildren( |
+ Parse *pParse, /* Parse context */ |
+ SrcList *pSrc, /* The child table to be scanned */ |
+ Table *pTab, /* The parent table */ |
+ Index *pIdx, /* Index on parent covering the foreign key */ |
+ FKey *pFKey, /* The foreign key linking pSrc to pTab */ |
+ int *aiCol, /* Map from pIdx cols to child table cols */ |
+ int regData, /* Parent row data starts here */ |
+ int nIncr /* Amount to increment deferred counter by */ |
+){ |
+ sqlite3 *db = pParse->db; /* Database handle */ |
+ int i; /* Iterator variable */ |
+ Expr *pWhere = 0; /* WHERE clause to scan with */ |
+ NameContext sNameContext; /* Context used to resolve WHERE clause */ |
+ WhereInfo *pWInfo; /* Context used by sqlite3WhereXXX() */ |
+ int iFkIfZero = 0; /* Address of OP_FkIfZero */ |
+ Vdbe *v = sqlite3GetVdbe(pParse); |
+ |
+ assert( pIdx==0 || pIdx->pTable==pTab ); |
+ assert( pIdx==0 || pIdx->nKeyCol==pFKey->nCol ); |
+ assert( pIdx!=0 || pFKey->nCol==1 ); |
+ assert( pIdx!=0 || HasRowid(pTab) ); |
+ |
+ if( nIncr<0 ){ |
+ iFkIfZero = sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, 0); |
+ VdbeCoverage(v); |
+ } |
+ |
+ /* Create an Expr object representing an SQL expression like: |
+ ** |
+ ** <parent-key1> = <child-key1> AND <parent-key2> = <child-key2> ... |
+ ** |
+ ** The collation sequence used for the comparison should be that of |
+ ** the parent key columns. The affinity of the parent key column should |
+ ** be applied to each child key value before the comparison takes place. |
+ */ |
+ for(i=0; i<pFKey->nCol; i++){ |
+ Expr *pLeft; /* Value from parent table row */ |
+ Expr *pRight; /* Column ref to child table */ |
+ Expr *pEq; /* Expression (pLeft = pRight) */ |
+ i16 iCol; /* Index of column in child table */ |
+ const char *zCol; /* Name of column in child table */ |
+ |
+ iCol = pIdx ? pIdx->aiColumn[i] : -1; |
+ pLeft = exprTableRegister(pParse, pTab, regData, iCol); |
+ iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; |
+ assert( iCol>=0 ); |
+ zCol = pFKey->pFrom->aCol[iCol].zName; |
+ pRight = sqlite3Expr(db, TK_ID, zCol); |
+ pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight); |
+ pWhere = sqlite3ExprAnd(db, pWhere, pEq); |
+ } |
+ |
+ /* If the child table is the same as the parent table, then add terms |
+ ** to the WHERE clause that prevent this entry from being scanned. |
+ ** The added WHERE clause terms are like this: |
+ ** |
+ ** $current_rowid!=rowid |
+ ** NOT( $current_a==a AND $current_b==b AND ... ) |
+ ** |
+ ** The first form is used for rowid tables. The second form is used |
+ ** for WITHOUT ROWID tables. In the second form, the primary key is |
+ ** (a,b,...) |
+ */ |
+ if( pTab==pFKey->pFrom && nIncr>0 ){ |
+ Expr *pNe; /* Expression (pLeft != pRight) */ |
+ Expr *pLeft; /* Value from parent table row */ |
+ Expr *pRight; /* Column ref to child table */ |
+ if( HasRowid(pTab) ){ |
+ pLeft = exprTableRegister(pParse, pTab, regData, -1); |
+ pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, -1); |
+ pNe = sqlite3PExpr(pParse, TK_NE, pLeft, pRight); |
+ }else{ |
+ Expr *pEq, *pAll = 0; |
+ Index *pPk = sqlite3PrimaryKeyIndex(pTab); |
+ assert( pIdx!=0 ); |
+ for(i=0; i<pPk->nKeyCol; i++){ |
+ i16 iCol = pIdx->aiColumn[i]; |
+ assert( iCol>=0 ); |
+ pLeft = exprTableRegister(pParse, pTab, regData, iCol); |
+ pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, iCol); |
+ pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight); |
+ pAll = sqlite3ExprAnd(db, pAll, pEq); |
+ } |
+ pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0); |
+ } |
+ pWhere = sqlite3ExprAnd(db, pWhere, pNe); |
+ } |
+ |
+ /* Resolve the references in the WHERE clause. */ |
+ memset(&sNameContext, 0, sizeof(NameContext)); |
+ sNameContext.pSrcList = pSrc; |
+ sNameContext.pParse = pParse; |
+ sqlite3ResolveExprNames(&sNameContext, pWhere); |
+ |
+ /* Create VDBE to loop through the entries in pSrc that match the WHERE |
+ ** clause. For each row found, increment either the deferred or immediate |
+ ** foreign key constraint counter. */ |
+ pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0); |
+ sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); |
+ if( pWInfo ){ |
+ sqlite3WhereEnd(pWInfo); |
+ } |
+ |
+ /* Clean up the WHERE clause constructed above. */ |
+ sqlite3ExprDelete(db, pWhere); |
+ if( iFkIfZero ){ |
+ sqlite3VdbeJumpHere(v, iFkIfZero); |
+ } |
+} |
+ |
+/* |
+** This function returns a linked list of FKey objects (connected by |
+** FKey.pNextTo) holding all children of table pTab. For example, |
+** given the following schema: |
+** |
+** CREATE TABLE t1(a PRIMARY KEY); |
+** CREATE TABLE t2(b REFERENCES t1(a); |
+** |
+** Calling this function with table "t1" as an argument returns a pointer |
+** to the FKey structure representing the foreign key constraint on table |
+** "t2". Calling this function with "t2" as the argument would return a |
+** NULL pointer (as there are no FK constraints for which t2 is the parent |
+** table). |
+*/ |
+SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *pTab){ |
+ return (FKey *)sqlite3HashFind(&pTab->pSchema->fkeyHash, pTab->zName); |
+} |
+ |
+/* |
+** The second argument is a Trigger structure allocated by the |
+** fkActionTrigger() routine. This function deletes the Trigger structure |
+** and all of its sub-components. |
+** |
+** The Trigger structure or any of its sub-components may be allocated from |
+** the lookaside buffer belonging to database handle dbMem. |
+*/ |
+static void fkTriggerDelete(sqlite3 *dbMem, Trigger *p){ |
+ if( p ){ |
+ TriggerStep *pStep = p->step_list; |
+ sqlite3ExprDelete(dbMem, pStep->pWhere); |
+ sqlite3ExprListDelete(dbMem, pStep->pExprList); |
+ sqlite3SelectDelete(dbMem, pStep->pSelect); |
+ sqlite3ExprDelete(dbMem, p->pWhen); |
+ sqlite3DbFree(dbMem, p); |
+ } |
+} |
+ |
+/* |
+** This function is called to generate code that runs when table pTab is |
+** being dropped from the database. The SrcList passed as the second argument |
+** to this function contains a single entry guaranteed to resolve to |
+** table pTab. |
+** |
+** Normally, no code is required. However, if either |
+** |
+** (a) The table is the parent table of a FK constraint, or |
+** (b) The table is the child table of a deferred FK constraint and it is |
+** determined at runtime that there are outstanding deferred FK |
+** constraint violations in the database, |
+** |
+** then the equivalent of "DELETE FROM <tbl>" is executed before dropping |
+** the table from the database. Triggers are disabled while running this |
+** DELETE, but foreign key actions are not. |
+*/ |
+SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){ |
+ sqlite3 *db = pParse->db; |
+ if( (db->flags&SQLITE_ForeignKeys) && !IsVirtual(pTab) && !pTab->pSelect ){ |
+ int iSkip = 0; |
+ Vdbe *v = sqlite3GetVdbe(pParse); |
+ |
+ assert( v ); /* VDBE has already been allocated */ |
+ if( sqlite3FkReferences(pTab)==0 ){ |
+ /* Search for a deferred foreign key constraint for which this table |
+ ** is the child table. If one cannot be found, return without |
+ ** generating any VDBE code. If one can be found, then jump over |
+ ** the entire DELETE if there are no outstanding deferred constraints |
+ ** when this statement is run. */ |
+ FKey *p; |
+ for(p=pTab->pFKey; p; p=p->pNextFrom){ |
+ if( p->isDeferred || (db->flags & SQLITE_DeferFKs) ) break; |
+ } |
+ if( !p ) return; |
+ iSkip = sqlite3VdbeMakeLabel(v); |
+ sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip); VdbeCoverage(v); |
+ } |
+ |
+ pParse->disableTriggers = 1; |
+ sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0); |
+ pParse->disableTriggers = 0; |
+ |
+ /* If the DELETE has generated immediate foreign key constraint |
+ ** violations, halt the VDBE and return an error at this point, before |
+ ** any modifications to the schema are made. This is because statement |
+ ** transactions are not able to rollback schema changes. |
+ ** |
+ ** If the SQLITE_DeferFKs flag is set, then this is not required, as |
+ ** the statement transaction will not be rolled back even if FK |
+ ** constraints are violated. |
+ */ |
+ if( (db->flags & SQLITE_DeferFKs)==0 ){ |
+ sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2); |
+ VdbeCoverage(v); |
+ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY, |
+ OE_Abort, 0, P4_STATIC, P5_ConstraintFK); |
+ } |
+ |
+ if( iSkip ){ |
+ sqlite3VdbeResolveLabel(v, iSkip); |
+ } |
+ } |
+} |
+ |
+ |
+/* |
+** The second argument points to an FKey object representing a foreign key |
+** for which pTab is the child table. An UPDATE statement against pTab |
+** is currently being processed. For each column of the table that is |
+** actually updated, the corresponding element in the aChange[] array |
+** is zero or greater (if a column is unmodified the corresponding element |
+** is set to -1). If the rowid column is modified by the UPDATE statement |
+** the bChngRowid argument is non-zero. |
+** |
+** This function returns true if any of the columns that are part of the |
+** child key for FK constraint *p are modified. |
+*/ |
+static int fkChildIsModified( |
+ Table *pTab, /* Table being updated */ |
+ FKey *p, /* Foreign key for which pTab is the child */ |
+ int *aChange, /* Array indicating modified columns */ |
+ int bChngRowid /* True if rowid is modified by this update */ |
+){ |
+ int i; |
+ for(i=0; i<p->nCol; i++){ |
+ int iChildKey = p->aCol[i].iFrom; |
+ if( aChange[iChildKey]>=0 ) return 1; |
+ if( iChildKey==pTab->iPKey && bChngRowid ) return 1; |
+ } |
+ return 0; |
+} |
+ |
+/* |
+** The second argument points to an FKey object representing a foreign key |
+** for which pTab is the parent table. An UPDATE statement against pTab |
+** is currently being processed. For each column of the table that is |
+** actually updated, the corresponding element in the aChange[] array |
+** is zero or greater (if a column is unmodified the corresponding element |
+** is set to -1). If the rowid column is modified by the UPDATE statement |
+** the bChngRowid argument is non-zero. |
+** |
+** This function returns true if any of the columns that are part of the |
+** parent key for FK constraint *p are modified. |
+*/ |
+static int fkParentIsModified( |
+ Table *pTab, |
+ FKey *p, |
+ int *aChange, |
+ int bChngRowid |
+){ |
+ int i; |
+ for(i=0; i<p->nCol; i++){ |
+ char *zKey = p->aCol[i].zCol; |
+ int iKey; |
+ for(iKey=0; iKey<pTab->nCol; iKey++){ |
+ if( aChange[iKey]>=0 || (iKey==pTab->iPKey && bChngRowid) ){ |
+ Column *pCol = &pTab->aCol[iKey]; |
+ if( zKey ){ |
+ if( 0==sqlite3StrICmp(pCol->zName, zKey) ) return 1; |
+ }else if( pCol->colFlags & COLFLAG_PRIMKEY ){ |
+ return 1; |
+ } |
+ } |
+ } |
+ } |
+ return 0; |
+} |
+ |
+/* |
+** Return true if the parser passed as the first argument is being |
+** used to code a trigger that is really a "SET NULL" action belonging |
+** to trigger pFKey. |
+*/ |
+static int isSetNullAction(Parse *pParse, FKey *pFKey){ |
+ Parse *pTop = sqlite3ParseToplevel(pParse); |
+ if( pTop->pTriggerPrg ){ |
+ Trigger *p = pTop->pTriggerPrg->pTrigger; |
+ if( (p==pFKey->apTrigger[0] && pFKey->aAction[0]==OE_SetNull) |
+ || (p==pFKey->apTrigger[1] && pFKey->aAction[1]==OE_SetNull) |
+ ){ |
+ return 1; |
+ } |
+ } |
+ return 0; |
+} |
+ |
+/* |
+** This function is called when inserting, deleting or updating a row of |
+** table pTab to generate VDBE code to perform foreign key constraint |
+** processing for the operation. |
+** |
+** For a DELETE operation, parameter regOld is passed the index of the |
+** first register in an array of (pTab->nCol+1) registers containing the |
+** rowid of the row being deleted, followed by each of the column values |
+** of the row being deleted, from left to right. Parameter regNew is passed |
+** zero in this case. |
+** |
+** For an INSERT operation, regOld is passed zero and regNew is passed the |
+** first register of an array of (pTab->nCol+1) registers containing the new |
+** row data. |
+** |
+** For an UPDATE operation, this function is called twice. Once before |
+** the original record is deleted from the table using the calling convention |
+** described for DELETE. Then again after the original record is deleted |
+** but before the new record is inserted using the INSERT convention. |
+*/ |
+SQLITE_PRIVATE void sqlite3FkCheck( |
+ Parse *pParse, /* Parse context */ |
+ Table *pTab, /* Row is being deleted from this table */ |
+ int regOld, /* Previous row data is stored here */ |
+ int regNew, /* New row data is stored here */ |
+ int *aChange, /* Array indicating UPDATEd columns (or 0) */ |
+ int bChngRowid /* True if rowid is UPDATEd */ |
+){ |
+ sqlite3 *db = pParse->db; /* Database handle */ |
+ FKey *pFKey; /* Used to iterate through FKs */ |
+ int iDb; /* Index of database containing pTab */ |
+ const char *zDb; /* Name of database containing pTab */ |
+ int isIgnoreErrors = pParse->disableTriggers; |
+ |
+ /* Exactly one of regOld and regNew should be non-zero. */ |
+ assert( (regOld==0)!=(regNew==0) ); |
+ |
+ /* If foreign-keys are disabled, this function is a no-op. */ |
+ if( (db->flags&SQLITE_ForeignKeys)==0 ) return; |
+ |
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
+ zDb = db->aDb[iDb].zDbSName; |
+ |
+ /* Loop through all the foreign key constraints for which pTab is the |
+ ** child table (the table that the foreign key definition is part of). */ |
+ for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){ |
+ Table *pTo; /* Parent table of foreign key pFKey */ |
+ Index *pIdx = 0; /* Index on key columns in pTo */ |
+ int *aiFree = 0; |
+ int *aiCol; |
+ int iCol; |
+ int i; |
+ int bIgnore = 0; |
+ |
+ if( aChange |
+ && sqlite3_stricmp(pTab->zName, pFKey->zTo)!=0 |
+ && fkChildIsModified(pTab, pFKey, aChange, bChngRowid)==0 |
+ ){ |
+ continue; |
+ } |
+ |
+ /* Find the parent table of this foreign key. Also find a unique index |
+ ** on the parent key columns in the parent table. If either of these |
+ ** schema items cannot be located, set an error in pParse and return |
+ ** early. */ |
+ if( pParse->disableTriggers ){ |
+ pTo = sqlite3FindTable(db, pFKey->zTo, zDb); |
+ }else{ |
+ pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb); |
+ } |
+ if( !pTo || sqlite3FkLocateIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){ |
+ assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) ); |
+ if( !isIgnoreErrors || db->mallocFailed ) return; |
+ if( pTo==0 ){ |
+ /* If isIgnoreErrors is true, then a table is being dropped. In this |
+ ** case SQLite runs a "DELETE FROM xxx" on the table being dropped |
+ ** before actually dropping it in order to check FK constraints. |
+ ** If the parent table of an FK constraint on the current table is |
+ ** missing, behave as if it is empty. i.e. decrement the relevant |
+ ** FK counter for each row of the current table with non-NULL keys. |
+ */ |
+ Vdbe *v = sqlite3GetVdbe(pParse); |
+ int iJump = sqlite3VdbeCurrentAddr(v) + pFKey->nCol + 1; |
+ for(i=0; i<pFKey->nCol; i++){ |
+ int iReg = pFKey->aCol[i].iFrom + regOld + 1; |
+ sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iJump); VdbeCoverage(v); |
+ } |
+ sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, -1); |
+ } |
+ continue; |
+ } |
+ assert( pFKey->nCol==1 || (aiFree && pIdx) ); |
+ |
+ if( aiFree ){ |
+ aiCol = aiFree; |
+ }else{ |
+ iCol = pFKey->aCol[0].iFrom; |
+ aiCol = &iCol; |
+ } |
+ for(i=0; i<pFKey->nCol; i++){ |
+ if( aiCol[i]==pTab->iPKey ){ |
+ aiCol[i] = -1; |
+ } |
+ assert( pIdx==0 || pIdx->aiColumn[i]>=0 ); |
+#ifndef SQLITE_OMIT_AUTHORIZATION |
+ /* Request permission to read the parent key columns. If the |
+ ** authorization callback returns SQLITE_IGNORE, behave as if any |
+ ** values read from the parent table are NULL. */ |
+ if( db->xAuth ){ |
+ int rcauth; |
+ char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName; |
+ rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb); |
+ bIgnore = (rcauth==SQLITE_IGNORE); |
+ } |
+#endif |
+ } |
+ |
+ /* Take a shared-cache advisory read-lock on the parent table. Allocate |
+ ** a cursor to use to search the unique index on the parent key columns |
+ ** in the parent table. */ |
+ sqlite3TableLock(pParse, iDb, pTo->tnum, 0, pTo->zName); |
+ pParse->nTab++; |
+ |
+ if( regOld!=0 ){ |
+ /* A row is being removed from the child table. Search for the parent. |
+ ** If the parent does not exist, removing the child row resolves an |
+ ** outstanding foreign key constraint violation. */ |
+ fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1, bIgnore); |
+ } |
+ if( regNew!=0 && !isSetNullAction(pParse, pFKey) ){ |
+ /* A row is being added to the child table. If a parent row cannot |
+ ** be found, adding the child row has violated the FK constraint. |
+ ** |
+ ** If this operation is being performed as part of a trigger program |
+ ** that is actually a "SET NULL" action belonging to this very |
+ ** foreign key, then omit this scan altogether. As all child key |
+ ** values are guaranteed to be NULL, it is not possible for adding |
+ ** this row to cause an FK violation. */ |
+ fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1, bIgnore); |
+ } |
+ |
+ sqlite3DbFree(db, aiFree); |
+ } |
+ |
+ /* Loop through all the foreign key constraints that refer to this table. |
+ ** (the "child" constraints) */ |
+ for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){ |
+ Index *pIdx = 0; /* Foreign key index for pFKey */ |
+ SrcList *pSrc; |
+ int *aiCol = 0; |
+ |
+ if( aChange && fkParentIsModified(pTab, pFKey, aChange, bChngRowid)==0 ){ |
+ continue; |
+ } |
+ |
+ if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs) |
+ && !pParse->pToplevel && !pParse->isMultiWrite |
+ ){ |
+ assert( regOld==0 && regNew!=0 ); |
+ /* Inserting a single row into a parent table cannot cause (or fix) |
+ ** an immediate foreign key violation. So do nothing in this case. */ |
+ continue; |
+ } |
+ |
+ if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){ |
+ if( !isIgnoreErrors || db->mallocFailed ) return; |
+ continue; |
+ } |
+ assert( aiCol || pFKey->nCol==1 ); |
+ |
+ /* Create a SrcList structure containing the child table. We need the |
+ ** child table as a SrcList for sqlite3WhereBegin() */ |
+ pSrc = sqlite3SrcListAppend(db, 0, 0, 0); |
+ if( pSrc ){ |
+ struct SrcList_item *pItem = pSrc->a; |
+ pItem->pTab = pFKey->pFrom; |
+ pItem->zName = pFKey->pFrom->zName; |
+ pItem->pTab->nTabRef++; |
+ pItem->iCursor = pParse->nTab++; |
+ |
+ if( regNew!=0 ){ |
+ fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1); |
+ } |
+ if( regOld!=0 ){ |
+ int eAction = pFKey->aAction[aChange!=0]; |
+ fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regOld, 1); |
+ /* If this is a deferred FK constraint, or a CASCADE or SET NULL |
+ ** action applies, then any foreign key violations caused by |
+ ** removing the parent key will be rectified by the action trigger. |
+ ** So do not set the "may-abort" flag in this case. |
+ ** |
+ ** Note 1: If the FK is declared "ON UPDATE CASCADE", then the |
+ ** may-abort flag will eventually be set on this statement anyway |
+ ** (when this function is called as part of processing the UPDATE |
+ ** within the action trigger). |
+ ** |
+ ** Note 2: At first glance it may seem like SQLite could simply omit |
+ ** all OP_FkCounter related scans when either CASCADE or SET NULL |
+ ** applies. The trouble starts if the CASCADE or SET NULL action |
+ ** trigger causes other triggers or action rules attached to the |
+ ** child table to fire. In these cases the fk constraint counters |
+ ** might be set incorrectly if any OP_FkCounter related scans are |
+ ** omitted. */ |
+ if( !pFKey->isDeferred && eAction!=OE_Cascade && eAction!=OE_SetNull ){ |
+ sqlite3MayAbort(pParse); |
+ } |
+ } |
+ pItem->zName = 0; |
+ sqlite3SrcListDelete(db, pSrc); |
+ } |
+ sqlite3DbFree(db, aiCol); |
+ } |
+} |
+ |
+#define COLUMN_MASK(x) (((x)>31) ? 0xffffffff : ((u32)1<<(x))) |
+ |
+/* |
+** This function is called before generating code to update or delete a |
+** row contained in table pTab. |
+*/ |
+SQLITE_PRIVATE u32 sqlite3FkOldmask( |
+ Parse *pParse, /* Parse context */ |
+ Table *pTab /* Table being modified */ |
+){ |
+ u32 mask = 0; |
+ if( pParse->db->flags&SQLITE_ForeignKeys ){ |
+ FKey *p; |
+ int i; |
+ for(p=pTab->pFKey; p; p=p->pNextFrom){ |
+ for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom); |
+ } |
+ for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ |
+ Index *pIdx = 0; |
+ sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0); |
+ if( pIdx ){ |
+ for(i=0; i<pIdx->nKeyCol; i++){ |
+ assert( pIdx->aiColumn[i]>=0 ); |
+ mask |= COLUMN_MASK(pIdx->aiColumn[i]); |
+ } |
+ } |
+ } |
+ } |
+ return mask; |
+} |
+ |
+ |
+/* |
+** This function is called before generating code to update or delete a |
+** row contained in table pTab. If the operation is a DELETE, then |
+** parameter aChange is passed a NULL value. For an UPDATE, aChange points |
+** to an array of size N, where N is the number of columns in table pTab. |
+** If the i'th column is not modified by the UPDATE, then the corresponding |
+** entry in the aChange[] array is set to -1. If the column is modified, |
+** the value is 0 or greater. Parameter chngRowid is set to true if the |
+** UPDATE statement modifies the rowid fields of the table. |
+** |
+** If any foreign key processing will be required, this function returns |
+** true. If there is no foreign key related processing, this function |
+** returns false. |
+*/ |
+SQLITE_PRIVATE int sqlite3FkRequired( |
+ Parse *pParse, /* Parse context */ |
+ Table *pTab, /* Table being modified */ |
+ int *aChange, /* Non-NULL for UPDATE operations */ |
+ int chngRowid /* True for UPDATE that affects rowid */ |
+){ |
+ if( pParse->db->flags&SQLITE_ForeignKeys ){ |
+ if( !aChange ){ |
+ /* A DELETE operation. Foreign key processing is required if the |
+ ** table in question is either the child or parent table for any |
+ ** foreign key constraint. */ |
+ return (sqlite3FkReferences(pTab) || pTab->pFKey); |
+ }else{ |
+ /* This is an UPDATE. Foreign key processing is only required if the |
+ ** operation modifies one or more child or parent key columns. */ |
+ FKey *p; |
+ |
+ /* Check if any child key columns are being modified. */ |
+ for(p=pTab->pFKey; p; p=p->pNextFrom){ |
+ if( fkChildIsModified(pTab, p, aChange, chngRowid) ) return 1; |
+ } |
+ |
+ /* Check if any parent key columns are being modified. */ |
+ for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ |
+ if( fkParentIsModified(pTab, p, aChange, chngRowid) ) return 1; |
+ } |
+ } |
+ } |
+ return 0; |
+} |
+ |
+/* |
+** This function is called when an UPDATE or DELETE operation is being |
+** compiled on table pTab, which is the parent table of foreign-key pFKey. |
+** If the current operation is an UPDATE, then the pChanges parameter is |
+** passed a pointer to the list of columns being modified. If it is a |
+** DELETE, pChanges is passed a NULL pointer. |
+** |
+** It returns a pointer to a Trigger structure containing a trigger |
+** equivalent to the ON UPDATE or ON DELETE action specified by pFKey. |
+** If the action is "NO ACTION" or "RESTRICT", then a NULL pointer is |
+** returned (these actions require no special handling by the triggers |
+** sub-system, code for them is created by fkScanChildren()). |
+** |
+** For example, if pFKey is the foreign key and pTab is table "p" in |
+** the following schema: |
+** |
+** CREATE TABLE p(pk PRIMARY KEY); |
+** CREATE TABLE c(ck REFERENCES p ON DELETE CASCADE); |
+** |
+** then the returned trigger structure is equivalent to: |
+** |
+** CREATE TRIGGER ... DELETE ON p BEGIN |
+** DELETE FROM c WHERE ck = old.pk; |
+** END; |
+** |
+** The returned pointer is cached as part of the foreign key object. It |
+** is eventually freed along with the rest of the foreign key object by |
+** sqlite3FkDelete(). |
+*/ |
+static Trigger *fkActionTrigger( |
+ Parse *pParse, /* Parse context */ |
+ Table *pTab, /* Table being updated or deleted from */ |
+ FKey *pFKey, /* Foreign key to get action for */ |
+ ExprList *pChanges /* Change-list for UPDATE, NULL for DELETE */ |
+){ |
+ sqlite3 *db = pParse->db; /* Database handle */ |
+ int action; /* One of OE_None, OE_Cascade etc. */ |
+ Trigger *pTrigger; /* Trigger definition to return */ |
+ int iAction = (pChanges!=0); /* 1 for UPDATE, 0 for DELETE */ |
+ |
+ action = pFKey->aAction[iAction]; |
+ if( action==OE_Restrict && (db->flags & SQLITE_DeferFKs) ){ |
+ return 0; |
+ } |
+ pTrigger = pFKey->apTrigger[iAction]; |
+ |
+ if( action!=OE_None && !pTrigger ){ |
+ char const *zFrom; /* Name of child table */ |
+ int nFrom; /* Length in bytes of zFrom */ |
+ Index *pIdx = 0; /* Parent key index for this FK */ |
+ int *aiCol = 0; /* child table cols -> parent key cols */ |
+ TriggerStep *pStep = 0; /* First (only) step of trigger program */ |
+ Expr *pWhere = 0; /* WHERE clause of trigger step */ |
+ ExprList *pList = 0; /* Changes list if ON UPDATE CASCADE */ |
+ Select *pSelect = 0; /* If RESTRICT, "SELECT RAISE(...)" */ |
+ int i; /* Iterator variable */ |
+ Expr *pWhen = 0; /* WHEN clause for the trigger */ |
+ |
+ if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0; |
+ assert( aiCol || pFKey->nCol==1 ); |
+ |
+ for(i=0; i<pFKey->nCol; i++){ |
+ Token tOld = { "old", 3 }; /* Literal "old" token */ |
+ Token tNew = { "new", 3 }; /* Literal "new" token */ |
+ Token tFromCol; /* Name of column in child table */ |
+ Token tToCol; /* Name of column in parent table */ |
+ int iFromCol; /* Idx of column in child table */ |
+ Expr *pEq; /* tFromCol = OLD.tToCol */ |
+ |
+ iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; |
+ assert( iFromCol>=0 ); |
+ assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKey<pTab->nCol) ); |
+ assert( pIdx==0 || pIdx->aiColumn[i]>=0 ); |
+ sqlite3TokenInit(&tToCol, |
+ pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName); |
+ sqlite3TokenInit(&tFromCol, pFKey->pFrom->aCol[iFromCol].zName); |
+ |
+ /* Create the expression "OLD.zToCol = zFromCol". It is important |
+ ** that the "OLD.zToCol" term is on the LHS of the = operator, so |
+ ** that the affinity and collation sequence associated with the |
+ ** parent table are used for the comparison. */ |
+ pEq = sqlite3PExpr(pParse, TK_EQ, |
+ sqlite3PExpr(pParse, TK_DOT, |
+ sqlite3ExprAlloc(db, TK_ID, &tOld, 0), |
+ sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)), |
+ sqlite3ExprAlloc(db, TK_ID, &tFromCol, 0) |
+ ); |
+ pWhere = sqlite3ExprAnd(db, pWhere, pEq); |
+ |
+ /* For ON UPDATE, construct the next term of the WHEN clause. |
+ ** The final WHEN clause will be like this: |
+ ** |
+ ** WHEN NOT(old.col1 IS new.col1 AND ... AND old.colN IS new.colN) |
+ */ |
+ if( pChanges ){ |
+ pEq = sqlite3PExpr(pParse, TK_IS, |
+ sqlite3PExpr(pParse, TK_DOT, |
+ sqlite3ExprAlloc(db, TK_ID, &tOld, 0), |
+ sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)), |
+ sqlite3PExpr(pParse, TK_DOT, |
+ sqlite3ExprAlloc(db, TK_ID, &tNew, 0), |
+ sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)) |
+ ); |
+ pWhen = sqlite3ExprAnd(db, pWhen, pEq); |
+ } |
+ |
+ if( action!=OE_Restrict && (action!=OE_Cascade || pChanges) ){ |
+ Expr *pNew; |
+ if( action==OE_Cascade ){ |
+ pNew = sqlite3PExpr(pParse, TK_DOT, |
+ sqlite3ExprAlloc(db, TK_ID, &tNew, 0), |
+ sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)); |
+ }else if( action==OE_SetDflt ){ |
+ Expr *pDflt = pFKey->pFrom->aCol[iFromCol].pDflt; |
+ if( pDflt ){ |
+ pNew = sqlite3ExprDup(db, pDflt, 0); |
+ }else{ |
+ pNew = sqlite3ExprAlloc(db, TK_NULL, 0, 0); |
+ } |
+ }else{ |
+ pNew = sqlite3ExprAlloc(db, TK_NULL, 0, 0); |
+ } |
+ pList = sqlite3ExprListAppend(pParse, pList, pNew); |
+ sqlite3ExprListSetName(pParse, pList, &tFromCol, 0); |
+ } |
+ } |
+ sqlite3DbFree(db, aiCol); |
+ |
+ zFrom = pFKey->pFrom->zName; |
+ nFrom = sqlite3Strlen30(zFrom); |
+ |
+ if( action==OE_Restrict ){ |
+ Token tFrom; |
+ Expr *pRaise; |
+ |
+ tFrom.z = zFrom; |
+ tFrom.n = nFrom; |
+ pRaise = sqlite3Expr(db, TK_RAISE, "FOREIGN KEY constraint failed"); |
+ if( pRaise ){ |
+ pRaise->affinity = OE_Abort; |
+ } |
+ pSelect = sqlite3SelectNew(pParse, |
+ sqlite3ExprListAppend(pParse, 0, pRaise), |
+ sqlite3SrcListAppend(db, 0, &tFrom, 0), |
+ pWhere, |
+ 0, 0, 0, 0, 0, 0 |
+ ); |
+ pWhere = 0; |
+ } |
+ |
+ /* Disable lookaside memory allocation */ |
+ db->lookaside.bDisable++; |
+ |
+ pTrigger = (Trigger *)sqlite3DbMallocZero(db, |
+ sizeof(Trigger) + /* struct Trigger */ |
+ sizeof(TriggerStep) + /* Single step in trigger program */ |
+ nFrom + 1 /* Space for pStep->zTarget */ |
+ ); |
+ if( pTrigger ){ |
+ pStep = pTrigger->step_list = (TriggerStep *)&pTrigger[1]; |
+ pStep->zTarget = (char *)&pStep[1]; |
+ memcpy((char *)pStep->zTarget, zFrom, nFrom); |
+ |
+ pStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); |
+ pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE); |
+ pStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); |
+ if( pWhen ){ |
+ pWhen = sqlite3PExpr(pParse, TK_NOT, pWhen, 0); |
+ pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); |
+ } |
+ } |
+ |
+ /* Re-enable the lookaside buffer, if it was disabled earlier. */ |
+ db->lookaside.bDisable--; |
+ |
+ sqlite3ExprDelete(db, pWhere); |
+ sqlite3ExprDelete(db, pWhen); |
+ sqlite3ExprListDelete(db, pList); |
+ sqlite3SelectDelete(db, pSelect); |
+ if( db->mallocFailed==1 ){ |
+ fkTriggerDelete(db, pTrigger); |
+ return 0; |
+ } |
+ assert( pStep!=0 ); |
+ |
+ switch( action ){ |
+ case OE_Restrict: |
+ pStep->op = TK_SELECT; |
+ break; |
+ case OE_Cascade: |
+ if( !pChanges ){ |
+ pStep->op = TK_DELETE; |
+ break; |
+ } |
+ default: |
+ pStep->op = TK_UPDATE; |
+ } |
+ pStep->pTrig = pTrigger; |
+ pTrigger->pSchema = pTab->pSchema; |
+ pTrigger->pTabSchema = pTab->pSchema; |
+ pFKey->apTrigger[iAction] = pTrigger; |
+ pTrigger->op = (pChanges ? TK_UPDATE : TK_DELETE); |
+ } |
+ |
+ return pTrigger; |
+} |
+ |
+/* |
+** This function is called when deleting or updating a row to implement |
+** any required CASCADE, SET NULL or SET DEFAULT actions. |
+*/ |
+SQLITE_PRIVATE void sqlite3FkActions( |
+ Parse *pParse, /* Parse context */ |
+ Table *pTab, /* Table being updated or deleted from */ |
+ ExprList *pChanges, /* Change-list for UPDATE, NULL for DELETE */ |
+ int regOld, /* Address of array containing old row */ |
+ int *aChange, /* Array indicating UPDATEd columns (or 0) */ |
+ int bChngRowid /* True if rowid is UPDATEd */ |
+){ |
+ /* If foreign-key support is enabled, iterate through all FKs that |
+ ** refer to table pTab. If there is an action associated with the FK |
+ ** for this operation (either update or delete), invoke the associated |
+ ** trigger sub-program. */ |
+ if( pParse->db->flags&SQLITE_ForeignKeys ){ |
+ FKey *pFKey; /* Iterator variable */ |
+ for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){ |
+ if( aChange==0 || fkParentIsModified(pTab, pFKey, aChange, bChngRowid) ){ |
+ Trigger *pAct = fkActionTrigger(pParse, pTab, pFKey, pChanges); |
+ if( pAct ){ |
+ sqlite3CodeRowTriggerDirect(pParse, pAct, pTab, regOld, OE_Abort, 0); |
+ } |
+ } |
+ } |
+ } |
+} |
+ |
+#endif /* ifndef SQLITE_OMIT_TRIGGER */ |
+ |
+/* |
+** Free all memory associated with foreign key definitions attached to |
+** table pTab. Remove the deleted foreign keys from the Schema.fkeyHash |
+** hash table. |
+*/ |
+SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *db, Table *pTab){ |
+ FKey *pFKey; /* Iterator variable */ |
+ FKey *pNext; /* Copy of pFKey->pNextFrom */ |
+ |
+ assert( db==0 || IsVirtual(pTab) |
+ || sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) ); |
+ for(pFKey=pTab->pFKey; pFKey; pFKey=pNext){ |
+ |
+ /* Remove the FK from the fkeyHash hash table. */ |
+ if( !db || db->pnBytesFreed==0 ){ |
+ if( pFKey->pPrevTo ){ |
+ pFKey->pPrevTo->pNextTo = pFKey->pNextTo; |
+ }else{ |
+ void *p = (void *)pFKey->pNextTo; |
+ const char *z = (p ? pFKey->pNextTo->zTo : pFKey->zTo); |
+ sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, p); |
+ } |
+ if( pFKey->pNextTo ){ |
+ pFKey->pNextTo->pPrevTo = pFKey->pPrevTo; |
+ } |
+ } |
+ |
+ /* EV: R-30323-21917 Each foreign key constraint in SQLite is |
+ ** classified as either immediate or deferred. |
+ */ |
+ assert( pFKey->isDeferred==0 || pFKey->isDeferred==1 ); |
+ |
+ /* Delete any triggers created to implement actions for this FK. */ |
+#ifndef SQLITE_OMIT_TRIGGER |
+ fkTriggerDelete(db, pFKey->apTrigger[0]); |
+ fkTriggerDelete(db, pFKey->apTrigger[1]); |
+#endif |
+ |
+ pNext = pFKey->pNextFrom; |
+ sqlite3DbFree(db, pFKey); |
+ } |
+} |
+#endif /* ifndef SQLITE_OMIT_FOREIGN_KEY */ |
+ |
+/************** End of fkey.c ************************************************/ |
+/************** Begin file insert.c ******************************************/ |
+/* |
+** 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. |
+*/ |
+/* #include "sqliteInt.h" */ |
+ |
+/* |
+** Generate code that will |
+** |
+** (1) acquire a lock for table pTab then |
+** (2) open pTab as cursor iCur. |
+** |
+** If pTab is a WITHOUT ROWID table, then it is the PRIMARY KEY index |
+** for that table that is actually opened. |
+*/ |
+SQLITE_PRIVATE void sqlite3OpenTable( |
+ Parse *pParse, /* 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; |
+ assert( !IsVirtual(pTab) ); |
+ v = sqlite3GetVdbe(pParse); |
+ assert( opcode==OP_OpenWrite || opcode==OP_OpenRead ); |
+ sqlite3TableLock(pParse, iDb, pTab->tnum, |
+ (opcode==OP_OpenWrite)?1:0, pTab->zName); |
+ if( HasRowid(pTab) ){ |
+ sqlite3VdbeAddOp4Int(v, opcode, iCur, pTab->tnum, iDb, pTab->nCol); |
+ VdbeComment((v, "%s", pTab->zName)); |
+ }else{ |
+ Index *pPk = sqlite3PrimaryKeyIndex(pTab); |
+ assert( pPk!=0 ); |
+ assert( pPk->tnum==pTab->tnum ); |
+ sqlite3VdbeAddOp3(v, opcode, iCur, pPk->tnum, iDb); |
+ sqlite3VdbeSetP4KeyInfo(pParse, pPk); |
+ VdbeComment((v, "%s", pTab->zName)); |
+ } |
+} |
+ |
+/* |
+** Return a pointer to the column affinity string associated with 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' BLOB |
+** 'B' TEXT |
+** 'C' NUMERIC |
+** 'D' INTEGER |
+** 'F' REAL |
+** |
+** An extra 'D' is appended to the end of the string to cover the |
+** rowid that appears as the last column in every index. |
+** |
+** Memory for the buffer containing the column index affinity string |
+** is managed along with the rest of the Index structure. It will be |
+** released when sqlite3DeleteIndex() is called. |
+*/ |
+SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3 *db, 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; |
+ pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+1); |
+ if( !pIdx->zColAff ){ |
+ sqlite3OomFault(db); |
+ return 0; |
+ } |
+ for(n=0; n<pIdx->nColumn; n++){ |
+ i16 x = pIdx->aiColumn[n]; |
+ if( x>=0 ){ |
+ pIdx->zColAff[n] = pTab->aCol[x].affinity; |
+ }else if( x==XN_ROWID ){ |
+ pIdx->zColAff[n] = SQLITE_AFF_INTEGER; |
+ }else{ |
+ char aff; |
+ assert( x==XN_EXPR ); |
+ assert( pIdx->aColExpr!=0 ); |
+ aff = sqlite3ExprAffinity(pIdx->aColExpr->a[n].pExpr); |
+ if( aff==0 ) aff = SQLITE_AFF_BLOB; |
+ pIdx->zColAff[n] = aff; |
+ } |
+ } |
+ pIdx->zColAff[n] = 0; |
+ } |
+ |
+ return pIdx->zColAff; |
+} |
+ |
+/* |
+** Compute the affinity string for table pTab, if it has not already been |
+** computed. As an optimization, omit trailing SQLITE_AFF_BLOB affinities. |
+** |
+** If the affinity exists (if it is no entirely SQLITE_AFF_BLOB values) and |
+** if iReg>0 then code an OP_Affinity opcode that will set the affinities |
+** for register iReg and following. Or if affinities exists and iReg==0, |
+** then just set the P4 operand of the previous opcode (which should be |
+** an OP_MakeRecord) to the affinity string. |
+** |
+** A column affinity string has one character per column: |
+** |
+** Character Column affinity |
+** ------------------------------ |
+** 'A' BLOB |
+** 'B' TEXT |
+** 'C' NUMERIC |
+** 'D' INTEGER |
+** 'E' REAL |
+*/ |
+SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){ |
+ int i; |
+ char *zColAff = pTab->zColAff; |
+ if( zColAff==0 ){ |
+ sqlite3 *db = sqlite3VdbeDb(v); |
+ zColAff = (char *)sqlite3DbMallocRaw(0, pTab->nCol+1); |
+ if( !zColAff ){ |
+ sqlite3OomFault(db); |
+ return; |
+ } |
+ |
+ for(i=0; i<pTab->nCol; i++){ |
+ zColAff[i] = pTab->aCol[i].affinity; |
+ } |
+ do{ |
+ zColAff[i--] = 0; |
+ }while( i>=0 && zColAff[i]==SQLITE_AFF_BLOB ); |
+ pTab->zColAff = zColAff; |
+ } |
+ i = sqlite3Strlen30(zColAff); |
+ if( i ){ |
+ if( iReg ){ |
+ sqlite3VdbeAddOp4(v, OP_Affinity, iReg, i, 0, zColAff, i); |
+ }else{ |
+ sqlite3VdbeChangeP4(v, -1, zColAff, i); |
+ } |
+ } |
+} |
+ |
+/* |
+** 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. This is used to see if |
+** a statement of the form "INSERT INTO <iDb, pTab> SELECT ..." can |
+** run without using a temporary table for the results of the SELECT. |
+*/ |
+static int readsTable(Parse *p, int iDb, Table *pTab){ |
+ Vdbe *v = sqlite3GetVdbe(p); |
+ int i; |
+ int iEnd = sqlite3VdbeCurrentAddr(v); |
+#ifndef SQLITE_OMIT_VIRTUALTABLE |
+ VTable *pVTab = IsVirtual(pTab) ? sqlite3GetVTable(p->db, pTab) : 0; |
+#endif |
+ |
+ for(i=1; 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==pVTab ){ |
+ assert( pOp->p4.pVtab!=0 ); |
+ assert( pOp->p4type==P4_VTAB ); |
+ return 1; |
+ } |
+#endif |
+ } |
+ return 0; |
+} |
+ |
+#ifndef SQLITE_OMIT_AUTOINCREMENT |
+/* |
+** Locate or create an AutoincInfo structure associated with table pTab |
+** which is in database iDb. Return the register number for the register |
+** that holds the maximum rowid. Return zero if pTab is not an AUTOINCREMENT |
+** table. (Also return zero when doing a VACUUM since we do not want to |
+** update the AUTOINCREMENT counters during a VACUUM.) |
+** |
+** There is at most one AutoincInfo structure per table even if the |
+** same table is autoincremented multiple times due to inserts within |
+** triggers. A new AutoincInfo structure is created if this is the |
+** first use of table pTab. On 2nd and subsequent uses, the original |
+** AutoincInfo structure is used. |
+** |
+** Three memory locations are allocated: |
+** |
+** (1) Register to hold the name of the pTab table. |
+** (2) Register to hold the maximum ROWID of pTab. |
+** (3) Register to hold the rowid in sqlite_sequence of pTab |
+** |
+** The 2nd register is the one that is returned. That is all the |
+** insert routine needs to know about. |
+*/ |
+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->tabFlags & TF_Autoincrement)!=0 |
+ && (pParse->db->flags & SQLITE_Vacuum)==0 |
+ ){ |
+ Parse *pToplevel = sqlite3ParseToplevel(pParse); |
+ AutoincInfo *pInfo; |
+ |
+ pInfo = pToplevel->pAinc; |
+ while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; } |
+ if( pInfo==0 ){ |
+ pInfo = sqlite3DbMallocRawNN(pParse->db, sizeof(*pInfo)); |
+ if( pInfo==0 ) return 0; |
+ pInfo->pNext = pToplevel->pAinc; |
+ pToplevel->pAinc = pInfo; |
+ pInfo->pTab = pTab; |
+ pInfo->iDb = iDb; |
+ pToplevel->nMem++; /* Register to hold name of table */ |
+ pInfo->regCtr = ++pToplevel->nMem; /* Max rowid register */ |
+ pToplevel->nMem++; /* Rowid in sqlite_sequence */ |
+ } |
+ memId = pInfo->regCtr; |
+ } |
+ return memId; |
+} |
+ |
+/* |
+** This routine generates code that will initialize all of the |
+** register used by the autoincrement tracker. |
+*/ |
+SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse){ |
+ AutoincInfo *p; /* Information about an AUTOINCREMENT */ |
+ sqlite3 *db = pParse->db; /* The database connection */ |
+ Db *pDb; /* Database only autoinc table */ |
+ int memId; /* Register holding max rowid */ |
+ Vdbe *v = pParse->pVdbe; /* VDBE under construction */ |
+ |
+ /* This routine is never called during trigger-generation. It is |
+ ** only called from the top-level */ |
+ assert( pParse->pTriggerTab==0 ); |
+ assert( sqlite3IsToplevel(pParse) ); |
+ |
+ assert( v ); /* We failed long ago if this is not so */ |
+ for(p = pParse->pAinc; p; p = p->pNext){ |
+ static const int iLn = VDBE_OFFSET_LINENO(2); |
+ static const VdbeOpList autoInc[] = { |
+ /* 0 */ {OP_Null, 0, 0, 0}, |
+ /* 1 */ {OP_Rewind, 0, 9, 0}, |
+ /* 2 */ {OP_Column, 0, 0, 0}, |
+ /* 3 */ {OP_Ne, 0, 7, 0}, |
+ /* 4 */ {OP_Rowid, 0, 0, 0}, |
+ /* 5 */ {OP_Column, 0, 1, 0}, |
+ /* 6 */ {OP_Goto, 0, 9, 0}, |
+ /* 7 */ {OP_Next, 0, 2, 0}, |
+ /* 8 */ {OP_Integer, 0, 0, 0}, |
+ /* 9 */ {OP_Close, 0, 0, 0} |
+ }; |
+ VdbeOp *aOp; |
+ pDb = &db->aDb[p->iDb]; |
+ memId = p->regCtr; |
+ assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); |
+ sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenRead); |
+ sqlite3VdbeLoadString(v, memId-1, p->pTab->zName); |
+ aOp = sqlite3VdbeAddOpList(v, ArraySize(autoInc), autoInc, iLn); |
+ if( aOp==0 ) break; |
+ aOp[0].p2 = memId; |
+ aOp[0].p3 = memId+1; |
+ aOp[2].p3 = memId; |
+ aOp[3].p1 = memId-1; |
+ aOp[3].p3 = memId; |
+ aOp[3].p5 = SQLITE_JUMPIFNULL; |
+ aOp[4].p2 = memId+1; |
+ aOp[5].p3 = memId; |
+ aOp[8].p2 = memId; |
+ } |
+} |
+ |
+/* |
+** Update the maximum rowid for an autoincrement calculation. |
+** |
+** This routine should be called when the regRowid register 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. |
+*/ |
+static void autoIncStep(Parse *pParse, int memId, int regRowid){ |
+ if( memId>0 ){ |
+ sqlite3VdbeAddOp2(pParse->pVdbe, OP_MemMax, memId, regRowid); |
+ } |
+} |
+ |
+/* |
+** This routine generates the code needed to write autoincrement |
+** maximum rowid values back into the sqlite_sequence register. |
+** Every statement that might do an INSERT into an autoincrement |
+** table (either directly or through triggers) needs to call this |
+** routine just before the "exit" code. |
+*/ |
+static SQLITE_NOINLINE void autoIncrementEnd(Parse *pParse){ |
+ AutoincInfo *p; |
+ Vdbe *v = pParse->pVdbe; |
+ sqlite3 *db = pParse->db; |
+ |
+ assert( v ); |
+ for(p = pParse->pAinc; p; p = p->pNext){ |
+ static const int iLn = VDBE_OFFSET_LINENO(2); |
+ static const VdbeOpList autoIncEnd[] = { |
+ /* 0 */ {OP_NotNull, 0, 2, 0}, |
+ /* 1 */ {OP_NewRowid, 0, 0, 0}, |
+ /* 2 */ {OP_MakeRecord, 0, 2, 0}, |
+ /* 3 */ {OP_Insert, 0, 0, 0}, |
+ /* 4 */ {OP_Close, 0, 0, 0} |
+ }; |
+ VdbeOp *aOp; |
+ Db *pDb = &db->aDb[p->iDb]; |
+ int iRec; |
+ int memId = p->regCtr; |
+ |
+ iRec = sqlite3GetTempReg(pParse); |
+ assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); |
+ sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); |
+ aOp = sqlite3VdbeAddOpList(v, ArraySize(autoIncEnd), autoIncEnd, iLn); |
+ if( aOp==0 ) break; |
+ aOp[0].p1 = memId+1; |
+ aOp[1].p2 = memId+1; |
+ aOp[2].p1 = memId-1; |
+ aOp[2].p3 = iRec; |
+ aOp[3].p2 = iRec; |
+ aOp[3].p3 = memId+1; |
+ aOp[3].p5 = OPFLAG_APPEND; |
+ sqlite3ReleaseTempReg(pParse, iRec); |
+ } |
+} |
+SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse){ |
+ if( pParse->pAinc ) autoIncrementEnd(pParse); |
+} |
+#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) |
+#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 called to handle SQL of the following forms: |
+** |
+** insert into TABLE (IDLIST) values(EXPRLIST),(EXPRLIST),... |
+** insert into TABLE (IDLIST) select |
+** insert into TABLE (IDLIST) default values |
+** |
+** The IDLIST following the table name is always optional. If omitted, |
+** then a list of all (non-hidden) columns for the table is substituted. |
+** The IDLIST appears in the pColumn parameter. pColumn is NULL if IDLIST |
+** is omitted. |
+** |
+** For the pSelect parameter holds the values to be inserted for the |
+** first two forms shown above. A VALUES clause is really just short-hand |
+** for a SELECT statement that omits the FROM clause and everything else |
+** that follows. If the pSelect parameter is NULL, that means that the |
+** DEFAULT VALUES form of the INSERT statement is intended. |
+** |
+** The code generated follows one of four templates. For a simple |
+** insert with data coming from a single-row 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 |
+** put VALUES clause expressions into registers |
+** 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: |
+** |
+** 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 |
+** end-coroutine X |
+** B: open write cursor to <table> and its indices |
+** C: yield X, at 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 an intermediate table to store the results of |
+** the select. The template is like this: |
+** |
+** 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 |
+** end co-routine R |
+** B: open temp table |
+** L: yield X, at 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 |
+*/ |
+SQLITE_PRIVATE void sqlite3Insert( |
+ Parse *pParse, /* Parser context */ |
+ SrcList *pTabList, /* Name of table into which we are inserting */ |
+ 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 */ |
+ int i, j; /* 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 iDataCur = 0; /* VDBE cursor that is the main data repository */ |
+ int iIdxCur = 0; /* First index cursor */ |
+ int ipkColumn = -1; /* Column that is the INTEGER PRIMARY KEY */ |
+ int endOfLoop; /* Label for the end of the insertion loop */ |
+ 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 */ |
+ SelectDest dest; /* Destination for SELECT on rhs of INSERT */ |
+ int iDb; /* Index of database holding TABLE */ |
+ u8 useTempTable = 0; /* Store SELECT results in intermediate table */ |
+ u8 appendFlag = 0; /* True if the insert is likely to be an append */ |
+ u8 withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */ |
+ u8 bIdListInOrder; /* True if IDLIST is in table order */ |
+ ExprList *pList = 0; /* List of VALUES() to be inserted */ |
+ |
+ /* Register allocations */ |
+ int regFromSelect = 0;/* 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 *aRegIdx = 0; /* One register allocated to each index */ |
+ |
+#ifndef SQLITE_OMIT_TRIGGER |
+ int isView; /* True if attempting to insert into a view */ |
+ Trigger *pTrigger; /* List of triggers on pTab, if required */ |
+ int tmask; /* Mask of trigger times */ |
+#endif |
+ |
+ db = pParse->db; |
+ memset(&dest, 0, sizeof(dest)); |
+ if( pParse->nErr || db->mallocFailed ){ |
+ goto insert_cleanup; |
+ } |
+ |
+ /* If the Select object is really just a simple VALUES() list with a |
+ ** single row (the common case) then keep that one row of values |
+ ** and discard the other (unused) parts of the pSelect object |
+ */ |
+ if( pSelect && (pSelect->selFlags & SF_Values)!=0 && pSelect->pPrior==0 ){ |
+ pList = pSelect->pEList; |
+ pSelect->pEList = 0; |
+ sqlite3SelectDelete(db, pSelect); |
+ pSelect = 0; |
+ } |
+ |
+ /* Locate the table into which we will be inserting new information. |
+ */ |
+ assert( pTabList->nSrc==1 ); |
+ zTab = pTabList->a[0].zName; |
+ if( NEVER(zTab==0) ) goto insert_cleanup; |
+ pTab = sqlite3SrcListLookup(pParse, pTabList); |
+ if( pTab==0 ){ |
+ goto insert_cleanup; |
+ } |
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
+ assert( iDb<db->nDb ); |
+ if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, |
+ db->aDb[iDb].zDbSName) ){ |
+ goto insert_cleanup; |
+ } |
+ withoutRowid = !HasRowid(pTab); |
+ |
+ /* Figure out if we have any triggers and if the table being |
+ ** inserted into is a view |
+ */ |
+#ifndef SQLITE_OMIT_TRIGGER |
+ pTrigger = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0, &tmask); |
+ isView = pTab->pSelect!=0; |
+#else |
+# define pTrigger 0 |
+# define tmask 0 |
+# define isView 0 |
+#endif |
+#ifdef SQLITE_OMIT_VIEW |
+# undef isView |
+# define isView 0 |
+#endif |
+ assert( (pTrigger && tmask) || (pTrigger==0 && tmask==0) ); |
+ |
+ /* If pTab is really a view, make sure it has been initialized. |
+ ** ViewGetColumnNames() is a no-op if pTab is not a view. |
+ */ |
+ if( sqlite3ViewGetColumnNames(pParse, pTab) ){ |
+ goto insert_cleanup; |
+ } |
+ |
+ /* Cannot insert into a read-only table. |
+ */ |
+ if( sqlite3IsReadOnly(pParse, pTab, tmask) ){ |
+ goto insert_cleanup; |
+ } |
+ |
+ /* Allocate a VDBE |
+ */ |
+ v = sqlite3GetVdbe(pParse); |
+ if( v==0 ) goto insert_cleanup; |
+ if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); |
+ sqlite3BeginWriteOperation(pParse, pSelect || pTrigger, iDb); |
+ |
+#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( !pTrigger ); |
+ assert( pList==0 ); |
+ goto insert_end; |
+ } |
+#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); |
+ |
+ /* Allocate registers for holding the rowid of the new row, |
+ ** the content of the new row, and the assembled row record. |
+ */ |
+ regRowid = regIns = pParse->nMem+1; |
+ pParse->nMem += pTab->nCol + 1; |
+ if( IsVirtual(pTab) ){ |
+ regRowid++; |
+ pParse->nMem++; |
+ } |
+ regData = regRowid+1; |
+ |
+ /* 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 ipkColumn variable |
+ ** the index into IDLIST of the primary key column. ipkColumn is |
+ ** the index of the primary key as it appears in IDLIST, not as |
+ ** is appears in the original table. (The index of the INTEGER |
+ ** PRIMARY KEY in the original table is pTab->iPKey.) |
+ */ |
+ bIdListInOrder = (pTab->tabFlags & TF_OOOHidden)==0; |
+ 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( i!=j ) bIdListInOrder = 0; |
+ if( j==pTab->iPKey ){ |
+ ipkColumn = i; assert( !withoutRowid ); |
+ } |
+ break; |
+ } |
+ } |
+ if( j>=pTab->nCol ){ |
+ if( sqlite3IsRowid(pColumn->a[i].zName) && !withoutRowid ){ |
+ ipkColumn = i; |
+ bIdListInOrder = 0; |
+ }else{ |
+ sqlite3ErrorMsg(pParse, "table %S has no column named %s", |
+ pTabList, 0, pColumn->a[i].zName); |
+ pParse->checkSchema = 1; |
+ goto insert_cleanup; |
+ } |
+ } |
+ } |
+ } |
+ |
+ /* 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 or from a multi-row VALUES clause. |
+ ** Generate a co-routine to run the SELECT. */ |
+ int regYield; /* Register holding co-routine entry-point */ |
+ int addrTop; /* Top of the co-routine */ |
+ int rc; /* Result code */ |
+ |
+ regYield = ++pParse->nMem; |
+ addrTop = sqlite3VdbeCurrentAddr(v) + 1; |
+ sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); |
+ sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); |
+ dest.iSdst = bIdListInOrder ? regData : 0; |
+ dest.nSdst = pTab->nCol; |
+ rc = sqlite3Select(pParse, pSelect, &dest); |
+ regFromSelect = dest.iSdst; |
+ if( rc || db->mallocFailed || pParse->nErr ) goto insert_cleanup; |
+ sqlite3VdbeEndCoroutine(v, regYield); |
+ sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */ |
+ assert( pSelect->pEList ); |
+ nColumn = pSelect->pEList->nExpr; |
+ |
+ /* 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 output 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( pTrigger || readsTable(pParse, 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, goto M at EOF |
+ ** insert row from R..R+n into temp table |
+ ** goto L |
+ ** M: ... |
+ */ |
+ int regRec; /* Register to hold packed record */ |
+ int regTempRowid; /* Register to hold temp table ROWID */ |
+ int addrL; /* Label "L" */ |
+ |
+ srcTab = pParse->nTab++; |
+ regRec = sqlite3GetTempReg(pParse); |
+ regTempRowid = sqlite3GetTempReg(pParse); |
+ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn); |
+ addrL = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); VdbeCoverage(v); |
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec); |
+ sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regTempRowid); |
+ sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regTempRowid); |
+ sqlite3VdbeGoto(v, addrL); |
+ sqlite3VdbeJumpHere(v, addrL); |
+ sqlite3ReleaseTempReg(pParse, regRec); |
+ sqlite3ReleaseTempReg(pParse, regTempRowid); |
+ } |
+ }else{ |
+ /* This is the case if the data for the INSERT is coming from a |
+ ** single-row VALUES clause |
+ */ |
+ NameContext sNC; |
+ memset(&sNC, 0, sizeof(sNC)); |
+ sNC.pParse = pParse; |
+ srcTab = -1; |
+ assert( useTempTable==0 ); |
+ if( pList ){ |
+ nColumn = pList->nExpr; |
+ if( sqlite3ResolveExprListNames(&sNC, pList) ){ |
+ goto insert_cleanup; |
+ } |
+ }else{ |
+ nColumn = 0; |
+ } |
+ } |
+ |
+ /* If there is no IDLIST term but the table has an integer primary |
+ ** key, the set the ipkColumn variable to the integer primary key |
+ ** column index in the original table definition. |
+ */ |
+ if( pColumn==0 && nColumn>0 ){ |
+ ipkColumn = pTab->iPKey; |
+ } |
+ |
+ /* Make sure the number of columns in the source data matches the number |
+ ** of columns to be inserted into the table. |
+ */ |
+ 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-nHidden, nColumn); |
+ goto insert_cleanup; |
+ } |
+ if( pColumn!=0 && nColumn!=pColumn->nId ){ |
+ sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId); |
+ goto insert_cleanup; |
+ } |
+ |
+ /* 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; |
+ nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, -1, 0, |
+ &iDataCur, &iIdxCur); |
+ aRegIdx = sqlite3DbMallocRawNN(db, sizeof(int)*(nIdx+1)); |
+ if( aRegIdx==0 ){ |
+ goto insert_cleanup; |
+ } |
+ for(i=0, pIdx=pTab->pIndex; i<nIdx; pIdx=pIdx->pNext, i++){ |
+ assert( pIdx ); |
+ aRegIdx[i] = ++pParse->nMem; |
+ pParse->nMem += pIdx->nColumn; |
+ } |
+ } |
+ |
+ /* 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, if empty goto D |
+ ** C: loop over rows of intermediate table |
+ ** transfer values form intermediate table into <table> |
+ ** end loop |
+ ** D: ... |
+ */ |
+ addrInsTop = sqlite3VdbeAddOp1(v, OP_Rewind, srcTab); VdbeCoverage(v); |
+ 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, at EOF goto D |
+ ** insert the select result into <table> from R..R+n |
+ ** goto C |
+ ** D: ... |
+ */ |
+ addrInsTop = addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); |
+ VdbeCoverage(v); |
+ } |
+ |
+ /* Run the BEFORE and INSTEAD OF triggers, if there are any |
+ */ |
+ endOfLoop = sqlite3VdbeMakeLabel(v); |
+ if( tmask & TRIGGER_BEFORE ){ |
+ int regCols = sqlite3GetTempRange(pParse, pTab->nCol+1); |
+ |
+ /* 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 |
+ */ |
+ if( ipkColumn<0 ){ |
+ sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols); |
+ }else{ |
+ int addr1; |
+ assert( !withoutRowid ); |
+ if( useTempTable ){ |
+ sqlite3VdbeAddOp3(v, OP_Column, srcTab, ipkColumn, regCols); |
+ }else{ |
+ assert( pSelect==0 ); /* Otherwise useTempTable is true */ |
+ sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regCols); |
+ } |
+ addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, regCols); VdbeCoverage(v); |
+ sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols); |
+ sqlite3VdbeJumpHere(v, addr1); |
+ sqlite3VdbeAddOp1(v, OP_MustBeInt, regCols); VdbeCoverage(v); |
+ } |
+ |
+ /* 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 |
+ */ |
+ for(i=j=0; i<pTab->nCol; i++){ |
+ if( pColumn ){ |
+ for(j=0; j<pColumn->nId; j++){ |
+ if( pColumn->a[j].idx==i ) break; |
+ } |
+ } |
+ if( (!useTempTable && !pList) || (pColumn && j>=pColumn->nId) |
+ || (pColumn==0 && IsOrdinaryHiddenColumn(&pTab->aCol[i])) ){ |
+ sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regCols+i+1); |
+ }else if( useTempTable ){ |
+ sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i+1); |
+ }else{ |
+ assert( pSelect==0 ); /* Otherwise useTempTable is true */ |
+ sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr, regCols+i+1); |
+ } |
+ if( pColumn==0 && !IsOrdinaryHiddenColumn(&pTab->aCol[i]) ) j++; |
+ } |
+ |
+ /* 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 ){ |
+ sqlite3TableAffinity(v, pTab, regCols+1); |
+ } |
+ |
+ /* Fire BEFORE or INSTEAD OF triggers */ |
+ sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_BEFORE, |
+ pTab, regCols-pTab->nCol-1, onError, endOfLoop); |
+ |
+ sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol+1); |
+ } |
+ |
+ /* Compute the content of the next row to insert into a range of |
+ ** registers beginning at regIns. |
+ */ |
+ if( !isView ){ |
+ if( IsVirtual(pTab) ){ |
+ /* The row that the VUpdate opcode will delete: none */ |
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regIns); |
+ } |
+ if( ipkColumn>=0 ){ |
+ if( useTempTable ){ |
+ sqlite3VdbeAddOp3(v, OP_Column, srcTab, ipkColumn, regRowid); |
+ }else if( pSelect ){ |
+ sqlite3VdbeAddOp2(v, OP_Copy, regFromSelect+ipkColumn, regRowid); |
+ }else{ |
+ VdbeOp *pOp; |
+ sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regRowid); |
+ pOp = sqlite3VdbeGetOp(v, -1); |
+ if( ALWAYS(pOp) && pOp->opcode==OP_Null && !IsVirtual(pTab) ){ |
+ appendFlag = 1; |
+ pOp->opcode = OP_NewRowid; |
+ pOp->p1 = iDataCur; |
+ 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 addr1; |
+ if( !IsVirtual(pTab) ){ |
+ addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid); VdbeCoverage(v); |
+ sqlite3VdbeAddOp3(v, OP_NewRowid, iDataCur, regRowid, regAutoinc); |
+ sqlite3VdbeJumpHere(v, addr1); |
+ }else{ |
+ addr1 = sqlite3VdbeCurrentAddr(v); |
+ sqlite3VdbeAddOp2(v, OP_IsNull, regRowid, addr1+2); VdbeCoverage(v); |
+ } |
+ sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid); VdbeCoverage(v); |
+ } |
+ }else if( IsVirtual(pTab) || withoutRowid ){ |
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regRowid); |
+ }else{ |
+ sqlite3VdbeAddOp3(v, OP_NewRowid, iDataCur, regRowid, regAutoinc); |
+ appendFlag = 1; |
+ } |
+ autoIncStep(pParse, regAutoinc, regRowid); |
+ |
+ /* Compute 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 rowid will be substituted |
+ ** in its place. Hence, fill this column with a NULL to avoid |
+ ** taking up data space with information that will never be used. |
+ ** As there may be shallow copies of this value, make it a soft-NULL */ |
+ sqlite3VdbeAddOp1(v, OP_SoftNull, iRegStore); |
+ continue; |
+ } |
+ if( pColumn==0 ){ |
+ if( IsHiddenColumn(&pTab->aCol[i]) ){ |
+ 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) ){ |
+ sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore); |
+ }else if( useTempTable ){ |
+ sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore); |
+ }else if( pSelect ){ |
+ if( regFromSelect!=regData ){ |
+ 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) ){ |
+ const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); |
+ sqlite3VtabMakeWritable(pParse, pTab); |
+ sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, pVTab, P4_VTAB); |
+ sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError); |
+ sqlite3MayAbort(pParse); |
+ }else |
+#endif |
+ { |
+ int isReplace; /* Set to true if constraints may cause a replace */ |
+ int bUseSeek; /* True to use OPFLAG_SEEKRESULT */ |
+ sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, |
+ regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0 |
+ ); |
+ sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0); |
+ |
+ /* Set the OPFLAG_USESEEKRESULT flag if either (a) there are no REPLACE |
+ ** constraints or (b) there are no triggers and this table is not a |
+ ** parent table in a foreign key constraint. It is safe to set the |
+ ** flag in the second case as if any REPLACE constraint is hit, an |
+ ** OP_Delete or OP_IdxDelete instruction will be executed on each |
+ ** cursor that is disturbed. And these instructions both clear the |
+ ** VdbeCursor.seekResult variable, disabling the OPFLAG_USESEEKRESULT |
+ ** functionality. */ |
+ bUseSeek = (isReplace==0 || (pTrigger==0 && |
+ ((db->flags & SQLITE_ForeignKeys)==0 || sqlite3FkReferences(pTab)==0) |
+ )); |
+ sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur, |
+ regIns, aRegIdx, 0, appendFlag, bUseSeek |
+ ); |
+ } |
+ } |
+ |
+ /* Update the count of rows that are inserted |
+ */ |
+ if( (db->flags & SQLITE_CountRows)!=0 ){ |
+ sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); |
+ } |
+ |
+ if( pTrigger ){ |
+ /* Code AFTER triggers */ |
+ sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_AFTER, |
+ pTab, regData-2-pTab->nCol, onError, endOfLoop); |
+ } |
+ |
+ /* 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); VdbeCoverage(v); |
+ sqlite3VdbeJumpHere(v, addrInsTop); |
+ sqlite3VdbeAddOp1(v, OP_Close, srcTab); |
+ }else if( pSelect ){ |
+ sqlite3VdbeGoto(v, addrCont); |
+ sqlite3VdbeJumpHere(v, addrInsTop); |
+ } |
+ |
+insert_end: |
+ /* Update the sqlite_sequence table by storing the content of the |
+ ** maximum rowid counter values recorded while inserting into |
+ ** autoincrement tables. |
+ */ |
+ if( pParse->nested==0 && pParse->pTriggerTab==0 ){ |
+ sqlite3AutoincrementEnd(pParse); |
+ } |
+ |
+ /* |
+ ** 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 && !pParse->pTriggerTab ){ |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1); |
+ sqlite3VdbeSetNumCols(v, 1); |
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", SQLITE_STATIC); |
+ } |
+ |
+insert_cleanup: |
+ sqlite3SrcListDelete(db, pTabList); |
+ sqlite3ExprListDelete(db, pList); |
+ sqlite3SelectDelete(db, pSelect); |
+ sqlite3IdListDelete(db, pColumn); |
+ sqlite3DbFree(db, aRegIdx); |
+} |
+ |
+/* Make sure "isView" and other macros defined above are undefined. Otherwise |
+** they may interfere with compilation of other functions in this file |
+** (or in another file, if this file becomes part of the amalgamation). */ |
+#ifdef isView |
+ #undef isView |
+#endif |
+#ifdef pTrigger |
+ #undef pTrigger |
+#endif |
+#ifdef tmask |
+ #undef tmask |
+#endif |
+ |
+/* |
+** Meanings of bits in of pWalker->eCode for checkConstraintUnchanged() |
+*/ |
+#define CKCNSTRNT_COLUMN 0x01 /* CHECK constraint uses a changing column */ |
+#define CKCNSTRNT_ROWID 0x02 /* CHECK constraint references the ROWID */ |
+ |
+/* This is the Walker callback from checkConstraintUnchanged(). Set |
+** bit 0x01 of pWalker->eCode if |
+** pWalker->eCode to 0 if this expression node references any of the |
+** columns that are being modifed by an UPDATE statement. |
+*/ |
+static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){ |
+ if( pExpr->op==TK_COLUMN ){ |
+ assert( pExpr->iColumn>=0 || pExpr->iColumn==-1 ); |
+ if( pExpr->iColumn>=0 ){ |
+ if( pWalker->u.aiCol[pExpr->iColumn]>=0 ){ |
+ pWalker->eCode |= CKCNSTRNT_COLUMN; |
+ } |
+ }else{ |
+ pWalker->eCode |= CKCNSTRNT_ROWID; |
+ } |
+ } |
+ return WRC_Continue; |
+} |
+ |
+/* |
+** pExpr is a CHECK constraint on a row that is being UPDATE-ed. The |
+** only columns that are modified by the UPDATE are those for which |
+** aiChng[i]>=0, and also the ROWID is modified if chngRowid is true. |
+** |
+** Return true if CHECK constraint pExpr does not use any of the |
+** changing columns (or the rowid if it is changing). In other words, |
+** return true if this CHECK constraint can be skipped when validating |
+** the new row in the UPDATE statement. |
+*/ |
+static int checkConstraintUnchanged(Expr *pExpr, int *aiChng, int chngRowid){ |
+ Walker w; |
+ memset(&w, 0, sizeof(w)); |
+ w.eCode = 0; |
+ w.xExprCallback = checkConstraintExprNode; |
+ w.u.aiCol = aiChng; |
+ sqlite3WalkExpr(&w, pExpr); |
+ if( !chngRowid ){ |
+ testcase( (w.eCode & CKCNSTRNT_ROWID)!=0 ); |
+ w.eCode &= ~CKCNSTRNT_ROWID; |
+ } |
+ testcase( w.eCode==0 ); |
+ testcase( w.eCode==CKCNSTRNT_COLUMN ); |
+ testcase( w.eCode==CKCNSTRNT_ROWID ); |
+ testcase( w.eCode==(CKCNSTRNT_ROWID|CKCNSTRNT_COLUMN) ); |
+ return !w.eCode; |
+} |
+ |
+/* |
+** Generate code to do constraint checks prior to an INSERT or an UPDATE |
+** on table pTab. |
+** |
+** The regNewData parameter is the first register in a range that contains |
+** the data to be inserted or the data after the update. There will be |
+** pTab->nCol+1 registers in this range. The first register (the one |
+** that regNewData points to) will contain the new rowid, or NULL in the |
+** case of a WITHOUT ROWID table. The second register in the range will |
+** contain the content of the first table column. The third register will |
+** contain the content of the second table column. And so forth. |
+** |
+** The regOldData parameter is similar to regNewData except that it contains |
+** the data prior to an UPDATE rather than afterwards. regOldData is zero |
+** for an INSERT. This routine can distinguish between UPDATE and INSERT by |
+** checking regOldData for zero. |
+** |
+** For an UPDATE, the pkChng boolean is true if the true primary key (the |
+** rowid for a normal table or the PRIMARY KEY for a WITHOUT ROWID table) |
+** might be modified by the UPDATE. If pkChng is false, then the key of |
+** the iDataCur content table is guaranteed to be unchanged by the UPDATE. |
+** |
+** For an INSERT, the pkChng boolean indicates whether or not the rowid |
+** was explicitly specified as part of the INSERT statement. If pkChng |
+** is zero, it means that the either rowid is computed automatically or |
+** that the table is a WITHOUT ROWID table and has no rowid. On an INSERT, |
+** pkChng will only be true if the INSERT statement provides an integer |
+** value for either the rowid column or its INTEGER PRIMARY KEY alias. |
+** |
+** The code generated by this routine will 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 |
+** at pTab->pIndex. |
+** |
+** The caller must have already opened writeable cursors on the main |
+** table and all applicable indices (that is to say, all indices for which |
+** aRegIdx[] is not zero). iDataCur is the cursor for the main table when |
+** inserting or updating a rowid table, or the cursor for the PRIMARY KEY |
+** index when operating on a WITHOUT ROWID table. iIdxCur is the cursor |
+** for the first index in the pTab->pIndex list. Cursors for other indices |
+** are at iIdxCur+N for the N-th element of the pTab->pIndex list. |
+** |
+** 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_step() 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_step() to return immediately |
+** with SQLITE_CONSTRAINT. |
+** |
+** any FAIL Sqlite3_step() returns immediately with a |
+** return code of SQLITE_CONSTRAINT. The |
+** transaction is not rolled back and any |
+** changes to prior rows are retained. |
+** |
+** any IGNORE The attempt in insert or update the current |
+** row is skipped, without throwing an error. |
+** Processing continues with the next row. |
+** (There is an immediate jump to 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. |
+*/ |
+SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( |
+ Parse *pParse, /* The parser context */ |
+ Table *pTab, /* The table being inserted or updated */ |
+ int *aRegIdx, /* Use register aRegIdx[i] for index i. 0 for unused */ |
+ int iDataCur, /* Canonical data cursor (main table or PK index) */ |
+ int iIdxCur, /* First index cursor */ |
+ int regNewData, /* First register in a range holding values to insert */ |
+ int regOldData, /* Previous content. 0 for INSERTs */ |
+ u8 pkChng, /* Non-zero if the rowid or PRIMARY KEY changed */ |
+ u8 overrideError, /* Override onError to this if not OE_Default */ |
+ int ignoreDest, /* Jump to this label on an OE_Ignore resolution */ |
+ int *pbMayReplace, /* OUT: Set to true if constraint may cause a replace */ |
+ int *aiChng /* column i is unchanged if aiChng[i]<0 */ |
+){ |
+ Vdbe *v; /* VDBE under constrution */ |
+ Index *pIdx; /* Pointer to one of the indices */ |
+ Index *pPk = 0; /* The PRIMARY KEY index */ |
+ sqlite3 *db; /* Database connection */ |
+ int i; /* loop counter */ |
+ int ix; /* Index loop counter */ |
+ int nCol; /* Number of columns */ |
+ int onError; /* Conflict resolution strategy */ |
+ int addr1; /* Address of jump instruction */ |
+ int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */ |
+ int nPkField; /* Number of fields in PRIMARY KEY. 1 for ROWID tables */ |
+ int ipkTop = 0; /* Top of the rowid change constraint check */ |
+ int ipkBottom = 0; /* Bottom of the rowid change constraint check */ |
+ u8 isUpdate; /* True if this is an UPDATE operation */ |
+ u8 bAffinityDone = 0; /* True if the OP_Affinity operation has been run */ |
+ |
+ isUpdate = regOldData!=0; |
+ db = pParse->db; |
+ v = sqlite3GetVdbe(pParse); |
+ assert( v!=0 ); |
+ assert( pTab->pSelect==0 ); /* This table is not a VIEW */ |
+ nCol = pTab->nCol; |
+ |
+ /* pPk is the PRIMARY KEY index for WITHOUT ROWID tables and NULL for |
+ ** normal rowid tables. nPkField is the number of key fields in the |
+ ** pPk index or 1 for a rowid table. In other words, nPkField is the |
+ ** number of fields in the true primary key of the table. */ |
+ if( HasRowid(pTab) ){ |
+ pPk = 0; |
+ nPkField = 1; |
+ }else{ |
+ pPk = sqlite3PrimaryKeyIndex(pTab); |
+ nPkField = pPk->nKeyCol; |
+ } |
+ |
+ /* Record that this module has started */ |
+ VdbeModuleComment((v, "BEGIN: GenCnstCks(%d,%d,%d,%d,%d)", |
+ iDataCur, iIdxCur, regNewData, regOldData, pkChng)); |
+ |
+ /* Test all NOT NULL constraints. |
+ */ |
+ for(i=0; i<nCol; i++){ |
+ if( i==pTab->iPKey ){ |
+ continue; /* ROWID is never NULL */ |
+ } |
+ if( aiChng && aiChng[i]<0 ){ |
+ /* Don't bother checking for NOT NULL on columns that do not change */ |
+ continue; |
+ } |
+ onError = pTab->aCol[i].notNull; |
+ if( onError==OE_None ) continue; /* This column is allowed to be NULL */ |
+ 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; |
+ } |
+ assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail |
+ || onError==OE_Ignore || onError==OE_Replace ); |
+ switch( onError ){ |
+ case OE_Abort: |
+ sqlite3MayAbort(pParse); |
+ /* Fall through */ |
+ case OE_Rollback: |
+ case OE_Fail: { |
+ char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName, |
+ pTab->aCol[i].zName); |
+ sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, onError, |
+ regNewData+1+i); |
+ sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC); |
+ sqlite3VdbeChangeP5(v, P5_ConstraintNotNull); |
+ VdbeCoverage(v); |
+ break; |
+ } |
+ case OE_Ignore: { |
+ sqlite3VdbeAddOp2(v, OP_IsNull, regNewData+1+i, ignoreDest); |
+ VdbeCoverage(v); |
+ break; |
+ } |
+ default: { |
+ assert( onError==OE_Replace ); |
+ addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, regNewData+1+i); |
+ VdbeCoverage(v); |
+ sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regNewData+1+i); |
+ sqlite3VdbeJumpHere(v, addr1); |
+ break; |
+ } |
+ } |
+ } |
+ |
+ /* Test all CHECK constraints |
+ */ |
+#ifndef SQLITE_OMIT_CHECK |
+ if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){ |
+ ExprList *pCheck = pTab->pCheck; |
+ pParse->ckBase = regNewData+1; |
+ onError = overrideError!=OE_Default ? overrideError : OE_Abort; |
+ for(i=0; i<pCheck->nExpr; i++){ |
+ int allOk; |
+ Expr *pExpr = pCheck->a[i].pExpr; |
+ if( aiChng && checkConstraintUnchanged(pExpr, aiChng, pkChng) ) continue; |
+ allOk = sqlite3VdbeMakeLabel(v); |
+ sqlite3ExprIfTrue(pParse, pExpr, allOk, SQLITE_JUMPIFNULL); |
+ if( onError==OE_Ignore ){ |
+ sqlite3VdbeGoto(v, ignoreDest); |
+ }else{ |
+ char *zName = pCheck->a[i].zName; |
+ if( zName==0 ) zName = pTab->zName; |
+ if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */ |
+ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_CHECK, |
+ onError, zName, P4_TRANSIENT, |
+ P5_ConstraintCheck); |
+ } |
+ sqlite3VdbeResolveLabel(v, allOk); |
+ } |
+ } |
+#endif /* !defined(SQLITE_OMIT_CHECK) */ |
+ |
+ /* If rowid is changing, make sure the new rowid does not previously |
+ ** exist in the table. |
+ */ |
+ if( pkChng && pPk==0 ){ |
+ int addrRowidOk = sqlite3VdbeMakeLabel(v); |
+ |
+ /* Figure out what action to take in case of a rowid collision */ |
+ onError = pTab->keyConf; |
+ if( overrideError!=OE_Default ){ |
+ onError = overrideError; |
+ }else if( onError==OE_Default ){ |
+ onError = OE_Abort; |
+ } |
+ |
+ if( isUpdate ){ |
+ /* pkChng!=0 does not mean that the rowid has changed, only that |
+ ** it might have changed. Skip the conflict logic below if the rowid |
+ ** is unchanged. */ |
+ sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRowidOk, regOldData); |
+ sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); |
+ VdbeCoverage(v); |
+ } |
+ |
+ /* If the response to a rowid conflict is REPLACE but the response |
+ ** to some other UNIQUE constraint is FAIL or IGNORE, then we need |
+ ** to defer the running of the rowid conflict checking until after |
+ ** the UNIQUE constraints have run. |
+ */ |
+ if( onError==OE_Replace && overrideError!=OE_Replace ){ |
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
+ if( pIdx->onError==OE_Ignore || pIdx->onError==OE_Fail ){ |
+ ipkTop = sqlite3VdbeAddOp0(v, OP_Goto); |
+ break; |
+ } |
+ } |
+ } |
+ |
+ /* Check to see if the new rowid already exists in the table. Skip |
+ ** the following conflict logic if it does not. */ |
+ sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData); |
+ VdbeCoverage(v); |
+ |
+ /* Generate code that deals with a rowid collision */ |
+ switch( onError ){ |
+ default: { |
+ onError = OE_Abort; |
+ /* Fall thru into the next case */ |
+ } |
+ case OE_Rollback: |
+ case OE_Abort: |
+ case OE_Fail: { |
+ sqlite3RowidConstraint(pParse, onError, pTab); |
+ break; |
+ } |
+ case OE_Replace: { |
+ /* If there are DELETE triggers on this table and the |
+ ** recursive-triggers flag is set, call GenerateRowDelete() to |
+ ** remove the conflicting row from the table. This will fire |
+ ** the triggers and remove both the table and index b-tree entries. |
+ ** |
+ ** Otherwise, if there are no triggers or the recursive-triggers |
+ ** flag is not set, but the table has one or more indexes, call |
+ ** GenerateRowIndexDelete(). This removes the index b-tree entries |
+ ** only. The table b-tree entry will be replaced by the new entry |
+ ** when it is inserted. |
+ ** |
+ ** If either GenerateRowDelete() or GenerateRowIndexDelete() is called, |
+ ** also invoke MultiWrite() to indicate that this VDBE may require |
+ ** statement rollback (if the statement is aborted after the delete |
+ ** takes place). Earlier versions called sqlite3MultiWrite() regardless, |
+ ** but being more selective here allows statements like: |
+ ** |
+ ** REPLACE INTO t(rowid) VALUES($newrowid) |
+ ** |
+ ** to run without a statement journal if there are no indexes on the |
+ ** table. |
+ */ |
+ Trigger *pTrigger = 0; |
+ if( db->flags&SQLITE_RecTriggers ){ |
+ pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); |
+ } |
+ if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){ |
+ sqlite3MultiWrite(pParse); |
+ sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, |
+ regNewData, 1, 0, OE_Replace, 1, -1); |
+ }else{ |
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK |
+ if( HasRowid(pTab) ){ |
+ /* This OP_Delete opcode fires the pre-update-hook only. It does |
+ ** not modify the b-tree. It is more efficient to let the coming |
+ ** OP_Insert replace the existing entry than it is to delete the |
+ ** existing entry and then insert a new one. */ |
+ sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, OPFLAG_ISNOOP); |
+ sqlite3VdbeAppendP4(v, pTab, P4_TABLE); |
+ } |
+#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ |
+ if( pTab->pIndex ){ |
+ sqlite3MultiWrite(pParse); |
+ sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,-1); |
+ } |
+ } |
+ seenReplace = 1; |
+ break; |
+ } |
+ case OE_Ignore: { |
+ /*assert( seenReplace==0 );*/ |
+ sqlite3VdbeGoto(v, ignoreDest); |
+ break; |
+ } |
+ } |
+ sqlite3VdbeResolveLabel(v, addrRowidOk); |
+ if( ipkTop ){ |
+ ipkBottom = sqlite3VdbeAddOp0(v, OP_Goto); |
+ sqlite3VdbeJumpHere(v, ipkTop); |
+ } |
+ } |
+ |
+ /* Test all UNIQUE constraints by creating entries for each UNIQUE |
+ ** index and making sure that duplicate entries do not already exist. |
+ ** Compute the revised record entries for indices as we go. |
+ ** |
+ ** This loop also handles the case of the PRIMARY KEY index for a |
+ ** WITHOUT ROWID table. |
+ */ |
+ for(ix=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, ix++){ |
+ int regIdx; /* Range of registers hold conent for pIdx */ |
+ int regR; /* Range of registers holding conflicting PK */ |
+ int iThisCur; /* Cursor for this UNIQUE index */ |
+ int addrUniqueOk; /* Jump here if the UNIQUE constraint is satisfied */ |
+ |
+ if( aRegIdx[ix]==0 ) continue; /* Skip indices that do not change */ |
+ if( bAffinityDone==0 ){ |
+ sqlite3TableAffinity(v, pTab, regNewData+1); |
+ bAffinityDone = 1; |
+ } |
+ iThisCur = iIdxCur+ix; |
+ addrUniqueOk = sqlite3VdbeMakeLabel(v); |
+ |
+ /* Skip partial indices for which the WHERE clause is not true */ |
+ if( pIdx->pPartIdxWhere ){ |
+ sqlite3VdbeAddOp2(v, OP_Null, 0, aRegIdx[ix]); |
+ pParse->ckBase = regNewData+1; |
+ sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, addrUniqueOk, |
+ SQLITE_JUMPIFNULL); |
+ pParse->ckBase = 0; |
+ } |
+ |
+ /* Create a record for this index entry as it should appear after |
+ ** the insert or update. Store that record in the aRegIdx[ix] register |
+ */ |
+ regIdx = aRegIdx[ix]+1; |
+ for(i=0; i<pIdx->nColumn; i++){ |
+ int iField = pIdx->aiColumn[i]; |
+ int x; |
+ if( iField==XN_EXPR ){ |
+ pParse->ckBase = regNewData+1; |
+ sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[i].pExpr, regIdx+i); |
+ pParse->ckBase = 0; |
+ VdbeComment((v, "%s column %d", pIdx->zName, i)); |
+ }else{ |
+ if( iField==XN_ROWID || iField==pTab->iPKey ){ |
+ x = regNewData; |
+ }else{ |
+ x = iField + regNewData + 1; |
+ } |
+ sqlite3VdbeAddOp2(v, iField<0 ? OP_IntCopy : OP_SCopy, x, regIdx+i); |
+ VdbeComment((v, "%s", iField<0 ? "rowid" : pTab->aCol[iField].zName)); |
+ } |
+ } |
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]); |
+ VdbeComment((v, "for %s", pIdx->zName)); |
+ |
+ /* In an UPDATE operation, if this index is the PRIMARY KEY index |
+ ** of a WITHOUT ROWID table and there has been no change the |
+ ** primary key, then no collision is possible. The collision detection |
+ ** logic below can all be skipped. */ |
+ if( isUpdate && pPk==pIdx && pkChng==0 ){ |
+ sqlite3VdbeResolveLabel(v, addrUniqueOk); |
+ continue; |
+ } |
+ |
+ /* Find out what action to take in case there is a uniqueness conflict */ |
+ onError = pIdx->onError; |
+ if( onError==OE_None ){ |
+ sqlite3VdbeResolveLabel(v, addrUniqueOk); |
+ continue; /* pIdx is not a UNIQUE index */ |
+ } |
+ if( overrideError!=OE_Default ){ |
+ onError = overrideError; |
+ }else if( onError==OE_Default ){ |
+ onError = OE_Abort; |
+ } |
+ |
+ /* Collision detection may be omitted if all of the following are true: |
+ ** (1) The conflict resolution algorithm is REPLACE |
+ ** (2) The table is a WITHOUT ROWID table |
+ ** (3) There are no secondary indexes on the table |
+ ** (4) No delete triggers need to be fired if there is a conflict |
+ ** (5) No FK constraint counters need to be updated if a conflict occurs. |
+ */ |
+ if( (ix==0 && pIdx->pNext==0) /* Condition 3 */ |
+ && pPk==pIdx /* Condition 2 */ |
+ && onError==OE_Replace /* Condition 1 */ |
+ && ( 0==(db->flags&SQLITE_RecTriggers) || /* Condition 4 */ |
+ 0==sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0)) |
+ && ( 0==(db->flags&SQLITE_ForeignKeys) || /* Condition 5 */ |
+ (0==pTab->pFKey && 0==sqlite3FkReferences(pTab))) |
+ ){ |
+ sqlite3VdbeResolveLabel(v, addrUniqueOk); |
+ continue; |
+ } |
+ |
+ /* Check to see if the new index entry will be unique */ |
+ sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk, |
+ regIdx, pIdx->nKeyCol); VdbeCoverage(v); |
+ |
+ /* Generate code to handle collisions */ |
+ regR = (pIdx==pPk) ? regIdx : sqlite3GetTempRange(pParse, nPkField); |
+ if( isUpdate || onError==OE_Replace ){ |
+ if( HasRowid(pTab) ){ |
+ sqlite3VdbeAddOp2(v, OP_IdxRowid, iThisCur, regR); |
+ /* Conflict only if the rowid of the existing index entry |
+ ** is different from old-rowid */ |
+ if( isUpdate ){ |
+ sqlite3VdbeAddOp3(v, OP_Eq, regR, addrUniqueOk, regOldData); |
+ sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); |
+ VdbeCoverage(v); |
+ } |
+ }else{ |
+ int x; |
+ /* Extract the PRIMARY KEY from the end of the index entry and |
+ ** store it in registers regR..regR+nPk-1 */ |
+ if( pIdx!=pPk ){ |
+ for(i=0; i<pPk->nKeyCol; i++){ |
+ assert( pPk->aiColumn[i]>=0 ); |
+ x = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]); |
+ sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i); |
+ VdbeComment((v, "%s.%s", pTab->zName, |
+ pTab->aCol[pPk->aiColumn[i]].zName)); |
+ } |
+ } |
+ if( isUpdate ){ |
+ /* If currently processing the PRIMARY KEY of a WITHOUT ROWID |
+ ** table, only conflict if the new PRIMARY KEY values are actually |
+ ** different from the old. |
+ ** |
+ ** For a UNIQUE index, only conflict if the PRIMARY KEY values |
+ ** of the matched index row are different from the original PRIMARY |
+ ** KEY values of this row before the update. */ |
+ int addrJump = sqlite3VdbeCurrentAddr(v)+pPk->nKeyCol; |
+ int op = OP_Ne; |
+ int regCmp = (IsPrimaryKeyIndex(pIdx) ? regIdx : regR); |
+ |
+ for(i=0; i<pPk->nKeyCol; i++){ |
+ char *p4 = (char*)sqlite3LocateCollSeq(pParse, pPk->azColl[i]); |
+ x = pPk->aiColumn[i]; |
+ assert( x>=0 ); |
+ if( i==(pPk->nKeyCol-1) ){ |
+ addrJump = addrUniqueOk; |
+ op = OP_Eq; |
+ } |
+ sqlite3VdbeAddOp4(v, op, |
+ regOldData+1+x, addrJump, regCmp+i, p4, P4_COLLSEQ |
+ ); |
+ sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); |
+ VdbeCoverageIf(v, op==OP_Eq); |
+ VdbeCoverageIf(v, op==OP_Ne); |
+ } |
+ } |
+ } |
+ } |
+ |
+ /* 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: { |
+ sqlite3UniqueConstraint(pParse, onError, pIdx); |
+ break; |
+ } |
+ case OE_Ignore: { |
+ sqlite3VdbeGoto(v, ignoreDest); |
+ break; |
+ } |
+ default: { |
+ Trigger *pTrigger = 0; |
+ assert( onError==OE_Replace ); |
+ sqlite3MultiWrite(pParse); |
+ if( db->flags&SQLITE_RecTriggers ){ |
+ pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); |
+ } |
+ sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, |
+ regR, nPkField, 0, OE_Replace, |
+ (pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur); |
+ seenReplace = 1; |
+ break; |
+ } |
+ } |
+ sqlite3VdbeResolveLabel(v, addrUniqueOk); |
+ if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField); |
+ } |
+ if( ipkTop ){ |
+ sqlite3VdbeGoto(v, ipkTop+1); |
+ sqlite3VdbeJumpHere(v, ipkBottom); |
+ } |
+ |
+ *pbMayReplace = seenReplace; |
+ VdbeModuleComment((v, "END: GenCnstCks(%d)", seenReplace)); |
+} |
+ |
+#ifdef SQLITE_ENABLE_NULL_TRIM |
+/* |
+** Change the P5 operand on the last opcode (which should be an OP_MakeRecord) |
+** to be the number of columns in table pTab that must not be NULL-trimmed. |
+** |
+** Or if no columns of pTab may be NULL-trimmed, leave P5 at zero. |
+*/ |
+SQLITE_PRIVATE void sqlite3SetMakeRecordP5(Vdbe *v, Table *pTab){ |
+ u16 i; |
+ |
+ /* Records with omitted columns are only allowed for schema format |
+ ** version 2 and later (SQLite version 3.1.4, 2005-02-20). */ |
+ if( pTab->pSchema->file_format<2 ) return; |
+ |
+ for(i=pTab->nCol; i>1 && pTab->aCol[i-1].pDflt==0; i--){} |
+ sqlite3VdbeChangeP5(v, i); |
+} |
+#endif |
+ |
+/* |
+** 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 regNewData 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. |
+*/ |
+SQLITE_PRIVATE void sqlite3CompleteInsertion( |
+ Parse *pParse, /* The parser context */ |
+ Table *pTab, /* the table into which we are inserting */ |
+ int iDataCur, /* Cursor of the canonical data source */ |
+ int iIdxCur, /* First index cursor */ |
+ int regNewData, /* Range of content */ |
+ int *aRegIdx, /* Register used by each index. 0 for unused indices */ |
+ int update_flags, /* True for UPDATE, False for INSERT */ |
+ int appendBias, /* True if this is likely to be an append */ |
+ int useSeekResult /* True to set the USESEEKRESULT flag on OP_[Idx]Insert */ |
+){ |
+ Vdbe *v; /* Prepared statements under construction */ |
+ Index *pIdx; /* An index being inserted or updated */ |
+ u8 pik_flags; /* flag values passed to the btree insert */ |
+ int regData; /* Content registers (after the rowid) */ |
+ int regRec; /* Register holding assembled record for the table */ |
+ int i; /* Loop counter */ |
+ u8 bAffinityDone = 0; /* True if OP_Affinity has been run already */ |
+ |
+ assert( update_flags==0 |
+ || update_flags==OPFLAG_ISUPDATE |
+ || update_flags==(OPFLAG_ISUPDATE|OPFLAG_SAVEPOSITION) |
+ ); |
+ |
+ v = sqlite3GetVdbe(pParse); |
+ assert( v!=0 ); |
+ assert( pTab->pSelect==0 ); /* This table is not a VIEW */ |
+ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ |
+ if( aRegIdx[i]==0 ) continue; |
+ bAffinityDone = 1; |
+ if( pIdx->pPartIdxWhere ){ |
+ sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2); |
+ VdbeCoverage(v); |
+ } |
+ pik_flags = (useSeekResult ? OPFLAG_USESEEKRESULT : 0); |
+ if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ |
+ assert( pParse->nested==0 ); |
+ pik_flags |= OPFLAG_NCHANGE; |
+ pik_flags |= (update_flags & OPFLAG_SAVEPOSITION); |
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK |
+ if( update_flags==0 ){ |
+ sqlite3VdbeAddOp4(v, OP_InsertInt, |
+ iIdxCur+i, aRegIdx[i], 0, (char*)pTab, P4_TABLE |
+ ); |
+ sqlite3VdbeChangeP5(v, OPFLAG_ISNOOP); |
+ } |
+#endif |
+ } |
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i], |
+ aRegIdx[i]+1, |
+ pIdx->uniqNotNull ? pIdx->nKeyCol: pIdx->nColumn); |
+ sqlite3VdbeChangeP5(v, pik_flags); |
+ } |
+ if( !HasRowid(pTab) ) return; |
+ regData = regNewData + 1; |
+ regRec = sqlite3GetTempReg(pParse); |
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec); |
+ sqlite3SetMakeRecordP5(v, pTab); |
+ if( !bAffinityDone ){ |
+ sqlite3TableAffinity(v, pTab, 0); |
+ sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol); |
+ } |
+ if( pParse->nested ){ |
+ pik_flags = 0; |
+ }else{ |
+ pik_flags = OPFLAG_NCHANGE; |
+ pik_flags |= (update_flags?update_flags:OPFLAG_LASTROWID); |
+ } |
+ if( appendBias ){ |
+ pik_flags |= OPFLAG_APPEND; |
+ } |
+ if( useSeekResult ){ |
+ pik_flags |= OPFLAG_USESEEKRESULT; |
+ } |
+ sqlite3VdbeAddOp3(v, OP_Insert, iDataCur, regRec, regNewData); |
+ if( !pParse->nested ){ |
+ sqlite3VdbeAppendP4(v, pTab, P4_TABLE); |
+ } |
+ sqlite3VdbeChangeP5(v, pik_flags); |
+} |
+ |
+/* |
+** Allocate cursors for the pTab table and all its indices and generate |
+** code to open and initialized those cursors. |
+** |
+** The cursor for the object that contains the complete data (normally |
+** the table itself, but the PRIMARY KEY index in the case of a WITHOUT |
+** ROWID table) is returned in *piDataCur. The first index cursor is |
+** returned in *piIdxCur. The number of indices is returned. |
+** |
+** Use iBase as the first cursor (either the *piDataCur for rowid tables |
+** or the first index for WITHOUT ROWID tables) if it is non-negative. |
+** If iBase is negative, then allocate the next available cursor. |
+** |
+** For a rowid table, *piDataCur will be exactly one less than *piIdxCur. |
+** For a WITHOUT ROWID table, *piDataCur will be somewhere in the range |
+** of *piIdxCurs, depending on where the PRIMARY KEY index appears on the |
+** pTab->pIndex list. |
+** |
+** If pTab is a virtual table, then this routine is a no-op and the |
+** *piDataCur and *piIdxCur values are left uninitialized. |
+*/ |
+SQLITE_PRIVATE int sqlite3OpenTableAndIndices( |
+ Parse *pParse, /* Parsing context */ |
+ Table *pTab, /* Table to be opened */ |
+ int op, /* OP_OpenRead or OP_OpenWrite */ |
+ u8 p5, /* P5 value for OP_Open* opcodes (except on WITHOUT ROWID) */ |
+ int iBase, /* Use this for the table cursor, if there is one */ |
+ u8 *aToOpen, /* If not NULL: boolean for each table and index */ |
+ int *piDataCur, /* Write the database source cursor number here */ |
+ int *piIdxCur /* Write the first index cursor number here */ |
+){ |
+ int i; |
+ int iDb; |
+ int iDataCur; |
+ Index *pIdx; |
+ Vdbe *v; |
+ |
+ assert( op==OP_OpenRead || op==OP_OpenWrite ); |
+ assert( op==OP_OpenWrite || p5==0 ); |
+ if( IsVirtual(pTab) ){ |
+ /* This routine is a no-op for virtual tables. Leave the output |
+ ** variables *piDataCur and *piIdxCur uninitialized so that valgrind |
+ ** can detect if they are used by mistake in the caller. */ |
+ return 0; |
+ } |
+ iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); |
+ v = sqlite3GetVdbe(pParse); |
+ assert( v!=0 ); |
+ if( iBase<0 ) iBase = pParse->nTab; |
+ iDataCur = iBase++; |
+ if( piDataCur ) *piDataCur = iDataCur; |
+ if( HasRowid(pTab) && (aToOpen==0 || aToOpen[0]) ){ |
+ sqlite3OpenTable(pParse, iDataCur, iDb, pTab, op); |
+ }else{ |
+ sqlite3TableLock(pParse, iDb, pTab->tnum, op==OP_OpenWrite, pTab->zName); |
+ } |
+ if( piIdxCur ) *piIdxCur = iBase; |
+ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ |
+ int iIdxCur = iBase++; |
+ assert( pIdx->pSchema==pTab->pSchema ); |
+ if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ |
+ if( piDataCur ) *piDataCur = iIdxCur; |
+ p5 = 0; |
+ } |
+ if( aToOpen==0 || aToOpen[i+1] ){ |
+ sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb); |
+ sqlite3VdbeSetP4KeyInfo(pParse, pIdx); |
+ sqlite3VdbeChangeP5(v, p5); |
+ VdbeComment((v, "%s", pIdx->zName)); |
+ } |
+ } |
+ if( iBase>pParse->nTab ) pParse->nTab = iBase; |
+ return i; |
+} |
+ |
+ |
+#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 supposed to. |
+*/ |
+SQLITE_API int sqlite3_xferopt_count; |
+#endif /* SQLITE_TEST */ |
+ |
+ |
+#ifndef SQLITE_OMIT_XFER_OPT |
+/* |
+** 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 |
+** * The index has the exact same WHERE clause |
+*/ |
+static int xferCompatibleIndex(Index *pDest, Index *pSrc){ |
+ int i; |
+ assert( pDest && pSrc ); |
+ assert( pDest->pTable!=pSrc->pTable ); |
+ if( pDest->nKeyCol!=pSrc->nKeyCol ){ |
+ return 0; /* Different number of columns */ |
+ } |
+ if( pDest->onError!=pSrc->onError ){ |
+ return 0; /* Different conflict resolution strategies */ |
+ } |
+ for(i=0; i<pSrc->nKeyCol; i++){ |
+ if( pSrc->aiColumn[i]!=pDest->aiColumn[i] ){ |
+ return 0; /* Different columns indexed */ |
+ } |
+ if( pSrc->aiColumn[i]==XN_EXPR ){ |
+ assert( pSrc->aColExpr!=0 && pDest->aColExpr!=0 ); |
+ if( sqlite3ExprCompare(pSrc->aColExpr->a[i].pExpr, |
+ pDest->aColExpr->a[i].pExpr, -1)!=0 ){ |
+ return 0; /* Different expressions in the index */ |
+ } |
+ } |
+ if( pSrc->aSortOrder[i]!=pDest->aSortOrder[i] ){ |
+ return 0; /* Different sort orders */ |
+ } |
+ if( sqlite3_stricmp(pSrc->azColl[i],pDest->azColl[i])!=0 ){ |
+ return 0; /* Different collating sequences */ |
+ } |
+ } |
+ if( sqlite3ExprCompare(pSrc->pPartIdxWhere, pDest->pPartIdxWhere, -1) ){ |
+ return 0; /* Different WHERE clauses */ |
+ } |
+ |
+ /* 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; |
+** |
+** The xfer optimization transfers raw records from tab2 over to tab1. |
+** Columns are not decoded and reassembled, which greatly improves |
+** performance. Raw index records are transferred in the same way. |
+** |
+** The xfer optimization is only attempted if tab1 and tab2 are compatible. |
+** There are lots of rules for determining compatibility - see comments |
+** embedded in the code for details. |
+** |
+** This routine returns TRUE if the optimization is guaranteed to be used. |
+** Sometimes the xfer optimization will only work if the destination table |
+** is empty - a factor that can only be determined at run-time. In that |
+** case, this routine generates code for the xfer optimization but also |
+** does a test to see if the destination table is empty and jumps over the |
+** xfer optimization code if the test fails. In that case, this routine |
+** returns FALSE so that the caller will know to go ahead and generate |
+** an unoptimized transfer. This routine also returns FALSE if there |
+** is no chance that the xfer optimization can be applied. |
+** |
+** This optimization is particularly useful at making VACUUM run faster. |
+*/ |
+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 */ |
+){ |
+ sqlite3 *db = pParse->db; |
+ 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 = 0; /* Address of test for empty pDest */ |
+ int emptySrcTest = 0; /* Address of test for empty pSrc */ |
+ Vdbe *v; /* The VDBE we are building */ |
+ 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( pParse->pWith || pSelect->pWith ){ |
+ /* Do not attempt to process this query if there are an WITH clauses |
+ ** attached to it. Proceeding may generate a false "no such table: xxx" |
+ ** error if pSelect reads from a CTE named "xxx". */ |
+ return 0; |
+ } |
+ if( sqlite3TriggerList(pParse, pDest) ){ |
+ return 0; /* tab1 must not have triggers */ |
+ } |
+#ifndef SQLITE_OMIT_VIRTUALTABLE |
+ if( pDest->tabFlags & TF_Virtual ){ |
+ return 0; /* tab1 must not be a virtual table */ |
+ } |
+#endif |
+ if( onError==OE_Default ){ |
+ if( pDest->iPKey>=0 ) onError = pDest->keyConf; |
+ if( onError==OE_Default ) onError = OE_Abort; |
+ } |
+ 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->selFlags & SF_Distinct ){ |
+ 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_ASTERISK ){ |
+ 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 = sqlite3LocateTableItem(pParse, 0, pItem); |
+ 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 */ |
+ } |
+ if( HasRowid(pDest)!=HasRowid(pSrc) ){ |
+ return 0; /* source and destination must both be WITHOUT ROWID or not */ |
+ } |
+#ifndef SQLITE_OMIT_VIRTUALTABLE |
+ if( pSrc->tabFlags & TF_Virtual ){ |
+ 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++){ |
+ Column *pDestCol = &pDest->aCol[i]; |
+ Column *pSrcCol = &pSrc->aCol[i]; |
+#ifdef SQLITE_ENABLE_HIDDEN_COLUMNS |
+ if( (db->flags & SQLITE_Vacuum)==0 |
+ && (pDestCol->colFlags | pSrcCol->colFlags) & COLFLAG_HIDDEN |
+ ){ |
+ return 0; /* Neither table may have __hidden__ columns */ |
+ } |
+#endif |
+ if( pDestCol->affinity!=pSrcCol->affinity ){ |
+ return 0; /* Affinity must be the same on all columns */ |
+ } |
+ if( sqlite3_stricmp(pDestCol->zColl, pSrcCol->zColl)!=0 ){ |
+ return 0; /* Collating sequence must be the same on all columns */ |
+ } |
+ if( pDestCol->notNull && !pSrcCol->notNull ){ |
+ return 0; /* tab2 must be NOT NULL if tab1 is */ |
+ } |
+ /* Default values for second and subsequent columns need to match. */ |
+ if( i>0 ){ |
+ assert( pDestCol->pDflt==0 || pDestCol->pDflt->op==TK_SPAN ); |
+ assert( pSrcCol->pDflt==0 || pSrcCol->pDflt->op==TK_SPAN ); |
+ if( (pDestCol->pDflt==0)!=(pSrcCol->pDflt==0) |
+ || (pDestCol->pDflt && strcmp(pDestCol->pDflt->u.zToken, |
+ pSrcCol->pDflt->u.zToken)!=0) |
+ ){ |
+ return 0; /* Default values must be the same for all columns */ |
+ } |
+ } |
+ } |
+ for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ |
+ if( IsUniqueIndex(pDestIdx) ){ |
+ 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 && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) ){ |
+ return 0; /* Tables have different CHECK constraints. Ticket #2252 */ |
+ } |
+#endif |
+#ifndef SQLITE_OMIT_FOREIGN_KEY |
+ /* Disallow the transfer optimization if the destination table constains |
+ ** any foreign key constraints. This is more restrictive than necessary. |
+ ** But the main beneficiary of the transfer optimization is the VACUUM |
+ ** command, and the VACUUM command disables foreign key constraints. So |
+ ** the extra complication to make this rule less restrictive is probably |
+ ** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e] |
+ */ |
+ if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){ |
+ return 0; |
+ } |
+#endif |
+ if( (db->flags & SQLITE_CountRows)!=0 ){ |
+ return 0; /* xfer opt does not play well with PRAGMA count_changes */ |
+ } |
+ |
+ /* If we get this far, it means that the xfer optimization is at |
+ ** least a possibility, though it might only work if the destination |
+ ** table (tab1) is initially empty. |
+ */ |
+#ifdef SQLITE_TEST |
+ sqlite3_xferopt_count++; |
+#endif |
+ iDbSrc = sqlite3SchemaToIndex(db, pSrc->pSchema); |
+ v = sqlite3GetVdbe(pParse); |
+ sqlite3CodeVerifySchema(pParse, iDbSrc); |
+ iSrc = pParse->nTab++; |
+ iDest = pParse->nTab++; |
+ regAutoinc = autoIncBegin(pParse, iDbDest, pDest); |
+ regData = sqlite3GetTempReg(pParse); |
+ regRowid = sqlite3GetTempReg(pParse); |
+ sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite); |
+ assert( HasRowid(pDest) || destHasUniqueIdx ); |
+ if( (db->flags & SQLITE_Vacuum)==0 && ( |
+ (pDest->iPKey<0 && pDest->pIndex!=0) /* (1) */ |
+ || destHasUniqueIdx /* (2) */ |
+ || (onError!=OE_Abort && onError!=OE_Rollback) /* (3) */ |
+ )){ |
+ /* In some circumstances, we are able to run the xfer optimization |
+ ** only if the destination table is initially empty. Unless the |
+ ** SQLITE_Vacuum flag is set, this block generates code to make |
+ ** that determination. If SQLITE_Vacuum is set, then the destination |
+ ** table is always empty. |
+ ** |
+ ** Conditions under which the destination must be empty: |
+ ** |
+ ** (1) There is no INTEGER PRIMARY KEY but there are indices. |
+ ** (If the destination is not initially empty, the rowid fields |
+ ** of index entries might need to change.) |
+ ** |
+ ** (2) The destination has a unique index. (The xfer optimization |
+ ** is unable to test uniqueness.) |
+ ** |
+ ** (3) onError is something other than OE_Abort and OE_Rollback. |
+ */ |
+ addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iDest, 0); VdbeCoverage(v); |
+ emptyDestTest = sqlite3VdbeAddOp0(v, OP_Goto); |
+ sqlite3VdbeJumpHere(v, addr1); |
+ } |
+ if( HasRowid(pSrc) ){ |
+ u8 insFlags; |
+ sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead); |
+ emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); |
+ if( pDest->iPKey>=0 ){ |
+ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); |
+ addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid); |
+ VdbeCoverage(v); |
+ sqlite3RowidConstraint(pParse, onError, pDest); |
+ 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->tabFlags & TF_Autoincrement)==0 ); |
+ } |
+ sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1); |
+ if( db->flags & SQLITE_Vacuum ){ |
+ sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1); |
+ insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID| |
+ OPFLAG_APPEND|OPFLAG_USESEEKRESULT; |
+ }else{ |
+ insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND; |
+ } |
+ sqlite3VdbeAddOp4(v, OP_Insert, iDest, regData, regRowid, |
+ (char*)pDest, P4_TABLE); |
+ sqlite3VdbeChangeP5(v, insFlags); |
+ sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); VdbeCoverage(v); |
+ sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); |
+ sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); |
+ }else{ |
+ sqlite3TableLock(pParse, iDbDest, pDest->tnum, 1, pDest->zName); |
+ sqlite3TableLock(pParse, iDbSrc, pSrc->tnum, 0, pSrc->zName); |
+ } |
+ for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ |
+ u8 idxInsFlags = 0; |
+ for(pSrcIdx=pSrc->pIndex; ALWAYS(pSrcIdx); pSrcIdx=pSrcIdx->pNext){ |
+ if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; |
+ } |
+ assert( pSrcIdx ); |
+ sqlite3VdbeAddOp3(v, OP_OpenRead, iSrc, pSrcIdx->tnum, iDbSrc); |
+ sqlite3VdbeSetP4KeyInfo(pParse, pSrcIdx); |
+ VdbeComment((v, "%s", pSrcIdx->zName)); |
+ sqlite3VdbeAddOp3(v, OP_OpenWrite, iDest, pDestIdx->tnum, iDbDest); |
+ sqlite3VdbeSetP4KeyInfo(pParse, pDestIdx); |
+ sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR); |
+ VdbeComment((v, "%s", pDestIdx->zName)); |
+ addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); |
+ sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1); |
+ if( db->flags & SQLITE_Vacuum ){ |
+ /* This INSERT command is part of a VACUUM operation, which guarantees |
+ ** that the destination table is empty. If all indexed columns use |
+ ** collation sequence BINARY, then it can also be assumed that the |
+ ** index will be populated by inserting keys in strictly sorted |
+ ** order. In this case, instead of seeking within the b-tree as part |
+ ** of every OP_IdxInsert opcode, an OP_Last is added before the |
+ ** OP_IdxInsert to seek to the point within the b-tree where each key |
+ ** should be inserted. This is faster. |
+ ** |
+ ** If any of the indexed columns use a collation sequence other than |
+ ** BINARY, this optimization is disabled. This is because the user |
+ ** might change the definition of a collation sequence and then run |
+ ** a VACUUM command. In that case keys may not be written in strictly |
+ ** sorted order. */ |
+ for(i=0; i<pSrcIdx->nColumn; i++){ |
+ const char *zColl = pSrcIdx->azColl[i]; |
+ assert( sqlite3_stricmp(sqlite3StrBINARY, zColl)!=0 |
+ || sqlite3StrBINARY==zColl ); |
+ if( sqlite3_stricmp(sqlite3StrBINARY, zColl) ) break; |
+ } |
+ if( i==pSrcIdx->nColumn ){ |
+ idxInsFlags = OPFLAG_USESEEKRESULT; |
+ sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1); |
+ } |
+ } |
+ if( !HasRowid(pSrc) && pDestIdx->idxType==2 ){ |
+ idxInsFlags |= OPFLAG_NCHANGE; |
+ } |
+ sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData); |
+ sqlite3VdbeChangeP5(v, idxInsFlags|OPFLAG_APPEND); |
+ sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v); |
+ sqlite3VdbeJumpHere(v, addr1); |
+ sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); |
+ sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); |
+ } |
+ if( emptySrcTest ) sqlite3VdbeJumpHere(v, emptySrcTest); |
+ sqlite3ReleaseTempReg(pParse, regRowid); |
+ sqlite3ReleaseTempReg(pParse, regData); |
+ if( emptyDestTest ){ |
+ sqlite3AutoincrementEnd(pParse); |
+ 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 */ |
+ |
+/************** End of insert.c **********************************************/ |
+/************** Begin file legacy.c ******************************************/ |
+/* |
+** 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. |
+*/ |
+ |
+/* #include "sqliteInt.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. |
+*/ |
+SQLITE_API 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; /* Return code */ |
+ const char *zLeftover; /* Tail of unprocessed SQL */ |
+ sqlite3_stmt *pStmt = 0; /* The current SQL statement */ |
+ char **azCols = 0; /* Names of result columns */ |
+ int callbackIsInit; /* True if callback data is initialized */ |
+ |
+ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; |
+ if( zSql==0 ) zSql = ""; |
+ |
+ sqlite3_mutex_enter(db->mutex); |
+ sqlite3Error(db, SQLITE_OK); |
+ while( rc==SQLITE_OK && zSql[0] ){ |
+ int nCol; |
+ char **azVals = 0; |
+ |
+ pStmt = 0; |
+ rc = sqlite3_prepare_v2(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; |
+ } |
+ |
+ callbackIsInit = 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 && !callbackIsInit |
+ && db->flags&SQLITE_NullCallback)) ){ |
+ if( !callbackIsInit ){ |
+ 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 ); |
+ } |
+ callbackIsInit = 1; |
+ } |
+ 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 ){ |
+ sqlite3OomFault(db); |
+ goto exec_out; |
+ } |
+ } |
+ } |
+ if( xCallback(pArg, nCol, azVals, azCols) ){ |
+ /* EVIDENCE-OF: R-38229-40159 If the callback function to |
+ ** sqlite3_exec() returns non-zero, then sqlite3_exec() will |
+ ** return SQLITE_ABORT. */ |
+ rc = SQLITE_ABORT; |
+ sqlite3VdbeFinalize((Vdbe *)pStmt); |
+ pStmt = 0; |
+ sqlite3Error(db, SQLITE_ABORT); |
+ goto exec_out; |
+ } |
+ } |
+ |
+ if( rc!=SQLITE_ROW ){ |
+ rc = sqlite3VdbeFinalize((Vdbe *)pStmt); |
+ pStmt = 0; |
+ zSql = zLeftover; |
+ while( sqlite3Isspace(zSql[0]) ) zSql++; |
+ break; |
+ } |
+ } |
+ |
+ sqlite3DbFree(db, azCols); |
+ azCols = 0; |
+ } |
+ |
+exec_out: |
+ if( pStmt ) sqlite3VdbeFinalize((Vdbe *)pStmt); |
+ sqlite3DbFree(db, azCols); |
+ |
+ rc = sqlite3ApiExit(db, rc); |
+ if( rc!=SQLITE_OK && pzErrMsg ){ |
+ int nErrMsg = 1 + sqlite3Strlen30(sqlite3_errmsg(db)); |
+ *pzErrMsg = sqlite3Malloc(nErrMsg); |
+ if( *pzErrMsg ){ |
+ memcpy(*pzErrMsg, sqlite3_errmsg(db), nErrMsg); |
+ }else{ |
+ rc = SQLITE_NOMEM_BKPT; |
+ sqlite3Error(db, SQLITE_NOMEM); |
+ } |
+ }else if( pzErrMsg ){ |
+ *pzErrMsg = 0; |
+ } |
+ |
+ assert( (rc&db->errMask)==rc ); |
+ sqlite3_mutex_leave(db->mutex); |
+ return rc; |
+} |
+ |
+/************** End of legacy.c **********************************************/ |
+/************** Begin file loadext.c *****************************************/ |
+/* |
+** 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. |
+*/ |
+ |
+#ifndef SQLITE_CORE |
+ #define SQLITE_CORE 1 /* Disable the API redefinition in sqlite3ext.h */ |
+#endif |
+/************** Include sqlite3ext.h in the middle of loadext.c **************/ |
+/************** Begin file sqlite3ext.h **************************************/ |
+/* |
+** 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. |
+*/ |
+#ifndef SQLITE3EXT_H |
+#define SQLITE3EXT_H |
+/* #include "sqlite3.h" */ |
+ |
+/* |
+** 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 other's 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); |
+ int (*backup_finish)(sqlite3_backup*); |
+ sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*); |
+ int (*backup_pagecount)(sqlite3_backup*); |
+ int (*backup_remaining)(sqlite3_backup*); |
+ int (*backup_step)(sqlite3_backup*,int); |
+ const char *(*compileoption_get)(int); |
+ int (*compileoption_used)(const char*); |
+ int (*create_function_v2)(sqlite3*,const char*,int,int,void*, |
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**), |
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**), |
+ void (*xFinal)(sqlite3_context*), |
+ void(*xDestroy)(void*)); |
+ int (*db_config)(sqlite3*,int,...); |
+ sqlite3_mutex *(*db_mutex)(sqlite3*); |
+ int (*db_status)(sqlite3*,int,int*,int*,int); |
+ int (*extended_errcode)(sqlite3*); |
+ void (*log)(int,const char*,...); |
+ sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64); |
+ const char *(*sourceid)(void); |
+ int (*stmt_status)(sqlite3_stmt*,int,int); |
+ int (*strnicmp)(const char*,const char*,int); |
+ int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*); |
+ int (*wal_autocheckpoint)(sqlite3*,int); |
+ int (*wal_checkpoint)(sqlite3*,const char*); |
+ void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*); |
+ int (*blob_reopen)(sqlite3_blob*,sqlite3_int64); |
+ int (*vtab_config)(sqlite3*,int op,...); |
+ int (*vtab_on_conflict)(sqlite3*); |
+ /* Version 3.7.16 and later */ |
+ int (*close_v2)(sqlite3*); |
+ const char *(*db_filename)(sqlite3*,const char*); |
+ int (*db_readonly)(sqlite3*,const char*); |
+ int (*db_release_memory)(sqlite3*); |
+ const char *(*errstr)(int); |
+ int (*stmt_busy)(sqlite3_stmt*); |
+ int (*stmt_readonly)(sqlite3_stmt*); |
+ int (*stricmp)(const char*,const char*); |
+ int (*uri_boolean)(const char*,const char*,int); |
+ sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64); |
+ const char *(*uri_parameter)(const char*,const char*); |
+ char *(*vsnprintf)(int,char*,const char*,va_list); |
+ int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*); |
+ /* Version 3.8.7 and later */ |
+ int (*auto_extension)(void(*)(void)); |
+ int (*bind_blob64)(sqlite3_stmt*,int,const void*,sqlite3_uint64, |
+ void(*)(void*)); |
+ int (*bind_text64)(sqlite3_stmt*,int,const char*,sqlite3_uint64, |
+ void(*)(void*),unsigned char); |
+ int (*cancel_auto_extension)(void(*)(void)); |
+ int (*load_extension)(sqlite3*,const char*,const char*,char**); |
+ void *(*malloc64)(sqlite3_uint64); |
+ sqlite3_uint64 (*msize)(void*); |
+ void *(*realloc64)(void*,sqlite3_uint64); |
+ void (*reset_auto_extension)(void); |
+ void (*result_blob64)(sqlite3_context*,const void*,sqlite3_uint64, |
+ void(*)(void*)); |
+ void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64, |
+ void(*)(void*), unsigned char); |
+ int (*strglob)(const char*,const char*); |
+ /* Version 3.8.11 and later */ |
+ sqlite3_value *(*value_dup)(const sqlite3_value*); |
+ void (*value_free)(sqlite3_value*); |
+ int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64); |
+ int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64); |
+ /* Version 3.9.0 and later */ |
+ unsigned int (*value_subtype)(sqlite3_value*); |
+ void (*result_subtype)(sqlite3_context*,unsigned int); |
+ /* Version 3.10.0 and later */ |
+ int (*status64)(int,sqlite3_int64*,sqlite3_int64*,int); |
+ int (*strlike)(const char*,const char*,unsigned int); |
+ int (*db_cacheflush)(sqlite3*); |
+ /* Version 3.12.0 and later */ |
+ int (*system_errno)(sqlite3*); |
+ /* Version 3.14.0 and later */ |
+ int (*trace_v2)(sqlite3*,unsigned,int(*)(unsigned,void*,void*,void*),void*); |
+ char *(*expanded_sql)(sqlite3_stmt*); |
+}; |
+ |
+/* |
+** This is the function signature used for all extension entry points. It |
+** is also defined in the file "loadext.c". |
+*/ |
+typedef int (*sqlite3_loadext_entry)( |
+ sqlite3 *db, /* Handle to the database. */ |
+ char **pzErrMsg, /* Used to set error string on failure. */ |
+ const sqlite3_api_routines *pThunk /* Extension API function pointers. */ |
+); |
+ |
+/* |
+** The following macros redefine the API routines so that they are |
+** redirected through 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. |
+*/ |
+#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) |
+#define sqlite3_aggregate_context sqlite3_api->aggregate_context |
+#ifndef SQLITE_OMIT_DEPRECATED |
+#define sqlite3_aggregate_count sqlite3_api->aggregate_count |
+#endif |
+#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 |
+#ifndef SQLITE_OMIT_DEPRECATED |
+#define sqlite3_expired sqlite3_api->expired |
+#endif |
+#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 |
+#ifndef SQLITE_OMIT_DEPRECATED |
+#define sqlite3_global_recover sqlite3_api->global_recover |
+#endif |
+#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 |
+#ifndef SQLITE_OMIT_DEPRECATED |
+#define sqlite3_transfer_bindings sqlite3_api->transfer_bindings |
+#endif |
+#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_vsnprintf sqlite3_api->vsnprintf |
+#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 sqlite3_backup_finish sqlite3_api->backup_finish |
+#define sqlite3_backup_init sqlite3_api->backup_init |
+#define sqlite3_backup_pagecount sqlite3_api->backup_pagecount |
+#define sqlite3_backup_remaining sqlite3_api->backup_remaining |
+#define sqlite3_backup_step sqlite3_api->backup_step |
+#define sqlite3_compileoption_get sqlite3_api->compileoption_get |
+#define sqlite3_compileoption_used sqlite3_api->compileoption_used |
+#define sqlite3_create_function_v2 sqlite3_api->create_function_v2 |
+#define sqlite3_db_config sqlite3_api->db_config |
+#define sqlite3_db_mutex sqlite3_api->db_mutex |
+#define sqlite3_db_status sqlite3_api->db_status |
+#define sqlite3_extended_errcode sqlite3_api->extended_errcode |
+#define sqlite3_log sqlite3_api->log |
+#define sqlite3_soft_heap_limit64 sqlite3_api->soft_heap_limit64 |
+#define sqlite3_sourceid sqlite3_api->sourceid |
+#define sqlite3_stmt_status sqlite3_api->stmt_status |
+#define sqlite3_strnicmp sqlite3_api->strnicmp |
+#define sqlite3_unlock_notify sqlite3_api->unlock_notify |
+#define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint |
+#define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint |
+#define sqlite3_wal_hook sqlite3_api->wal_hook |
+#define sqlite3_blob_reopen sqlite3_api->blob_reopen |
+#define sqlite3_vtab_config sqlite3_api->vtab_config |
+#define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict |
+/* Version 3.7.16 and later */ |
+#define sqlite3_close_v2 sqlite3_api->close_v2 |
+#define sqlite3_db_filename sqlite3_api->db_filename |
+#define sqlite3_db_readonly sqlite3_api->db_readonly |
+#define sqlite3_db_release_memory sqlite3_api->db_release_memory |
+#define sqlite3_errstr sqlite3_api->errstr |
+#define sqlite3_stmt_busy sqlite3_api->stmt_busy |
+#define sqlite3_stmt_readonly sqlite3_api->stmt_readonly |
+#define sqlite3_stricmp sqlite3_api->stricmp |
+#define sqlite3_uri_boolean sqlite3_api->uri_boolean |
+#define sqlite3_uri_int64 sqlite3_api->uri_int64 |
+#define sqlite3_uri_parameter sqlite3_api->uri_parameter |
+#define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf |
+#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2 |
+/* Version 3.8.7 and later */ |
+#define sqlite3_auto_extension sqlite3_api->auto_extension |
+#define sqlite3_bind_blob64 sqlite3_api->bind_blob64 |
+#define sqlite3_bind_text64 sqlite3_api->bind_text64 |
+#define sqlite3_cancel_auto_extension sqlite3_api->cancel_auto_extension |
+#define sqlite3_load_extension sqlite3_api->load_extension |
+#define sqlite3_malloc64 sqlite3_api->malloc64 |
+#define sqlite3_msize sqlite3_api->msize |
+#define sqlite3_realloc64 sqlite3_api->realloc64 |
+#define sqlite3_reset_auto_extension sqlite3_api->reset_auto_extension |
+#define sqlite3_result_blob64 sqlite3_api->result_blob64 |
+#define sqlite3_result_text64 sqlite3_api->result_text64 |
+#define sqlite3_strglob sqlite3_api->strglob |
+/* Version 3.8.11 and later */ |
+#define sqlite3_value_dup sqlite3_api->value_dup |
+#define sqlite3_value_free sqlite3_api->value_free |
+#define sqlite3_result_zeroblob64 sqlite3_api->result_zeroblob64 |
+#define sqlite3_bind_zeroblob64 sqlite3_api->bind_zeroblob64 |
+/* Version 3.9.0 and later */ |
+#define sqlite3_value_subtype sqlite3_api->value_subtype |
+#define sqlite3_result_subtype sqlite3_api->result_subtype |
+/* Version 3.10.0 and later */ |
+#define sqlite3_status64 sqlite3_api->status64 |
+#define sqlite3_strlike sqlite3_api->strlike |
+#define sqlite3_db_cacheflush sqlite3_api->db_cacheflush |
+/* Version 3.12.0 and later */ |
+#define sqlite3_system_errno sqlite3_api->system_errno |
+/* Version 3.14.0 and later */ |
+#define sqlite3_trace_v2 sqlite3_api->trace_v2 |
+#define sqlite3_expanded_sql sqlite3_api->expanded_sql |
+#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ |
+ |
+#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) |
+ /* This case when the file really is being compiled as a loadable |
+ ** extension */ |
+# define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; |
+# define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; |
+# define SQLITE_EXTENSION_INIT3 \ |
+ extern const sqlite3_api_routines *sqlite3_api; |
+#else |
+ /* This case when the file is being statically linked into the |
+ ** application */ |
+# define SQLITE_EXTENSION_INIT1 /*no-op*/ |
+# define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */ |
+# define SQLITE_EXTENSION_INIT3 /*no-op*/ |
+#endif |
+ |
+#endif /* SQLITE3EXT_H */ |
+ |
+/************** End of sqlite3ext.h ******************************************/ |
+/************** Continuing where we left off in loadext.c ********************/ |
+/* #include "sqliteInt.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 |
+#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_DECLTYPE |
+# define sqlite3_column_decltype16 0 |
+# define sqlite3_column_decltype 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 |
+# define sqlite3_vtab_config 0 |
+# define sqlite3_vtab_on_conflict 0 |
+#endif |
+ |
+#ifdef SQLITE_OMIT_SHARED_CACHE |
+# define sqlite3_enable_shared_cache 0 |
+#endif |
+ |
+#if defined(SQLITE_OMIT_TRACE) || defined(SQLITE_OMIT_DEPRECATED) |
+# 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 |
+#define sqlite3_blob_reopen 0 |
+#endif |
+ |
+#if defined(SQLITE_OMIT_TRACE) |
+# define sqlite3_trace_v2 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, |
+#ifndef SQLITE_OMIT_DEPRECATED |
+ sqlite3_aggregate_count, |
+#else |
+ 0, |
+#endif |
+ 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, |
+#ifndef SQLITE_OMIT_DEPRECATED |
+ sqlite3_expired, |
+#else |
+ 0, |
+#endif |
+ 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, |
+#ifndef SQLITE_OMIT_DEPRECATED |
+ sqlite3_thread_cleanup, |
+#else |
+ 0, |
+#endif |
+ sqlite3_total_changes, |
+ sqlite3_trace, |
+#ifndef SQLITE_OMIT_DEPRECATED |
+ sqlite3_transfer_bindings, |
+#else |
+ 0, |
+#endif |
+ 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_OMIT |
+ 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, |
+ |
+ /* |
+ ** Added for 3.7.4 |
+ */ |
+ sqlite3_backup_finish, |
+ sqlite3_backup_init, |
+ sqlite3_backup_pagecount, |
+ sqlite3_backup_remaining, |
+ sqlite3_backup_step, |
+#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS |
+ sqlite3_compileoption_get, |
+ sqlite3_compileoption_used, |
+#else |
+ 0, |
+ 0, |
+#endif |
+ sqlite3_create_function_v2, |
+ sqlite3_db_config, |
+ sqlite3_db_mutex, |
+ sqlite3_db_status, |
+ sqlite3_extended_errcode, |
+ sqlite3_log, |
+ sqlite3_soft_heap_limit64, |
+ sqlite3_sourceid, |
+ sqlite3_stmt_status, |
+ sqlite3_strnicmp, |
+#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY |
+ sqlite3_unlock_notify, |
+#else |
+ 0, |
+#endif |
+#ifndef SQLITE_OMIT_WAL |
+ sqlite3_wal_autocheckpoint, |
+ sqlite3_wal_checkpoint, |
+ sqlite3_wal_hook, |
+#else |
+ 0, |
+ 0, |
+ 0, |
+#endif |
+ sqlite3_blob_reopen, |
+ sqlite3_vtab_config, |
+ sqlite3_vtab_on_conflict, |
+ sqlite3_close_v2, |
+ sqlite3_db_filename, |
+ sqlite3_db_readonly, |
+ sqlite3_db_release_memory, |
+ sqlite3_errstr, |
+ sqlite3_stmt_busy, |
+ sqlite3_stmt_readonly, |
+ sqlite3_stricmp, |
+ sqlite3_uri_boolean, |
+ sqlite3_uri_int64, |
+ sqlite3_uri_parameter, |
+ sqlite3_vsnprintf, |
+ sqlite3_wal_checkpoint_v2, |
+ /* Version 3.8.7 and later */ |
+ sqlite3_auto_extension, |
+ sqlite3_bind_blob64, |
+ sqlite3_bind_text64, |
+ sqlite3_cancel_auto_extension, |
+ sqlite3_load_extension, |
+ sqlite3_malloc64, |
+ sqlite3_msize, |
+ sqlite3_realloc64, |
+ sqlite3_reset_auto_extension, |
+ sqlite3_result_blob64, |
+ sqlite3_result_text64, |
+ sqlite3_strglob, |
+ /* Version 3.8.11 and later */ |
+ (sqlite3_value*(*)(const sqlite3_value*))sqlite3_value_dup, |
+ sqlite3_value_free, |
+ sqlite3_result_zeroblob64, |
+ sqlite3_bind_zeroblob64, |
+ /* Version 3.9.0 and later */ |
+ sqlite3_value_subtype, |
+ sqlite3_result_subtype, |
+ /* Version 3.10.0 and later */ |
+ sqlite3_status64, |
+ sqlite3_strlike, |
+ sqlite3_db_cacheflush, |
+ /* Version 3.12.0 and later */ |
+ sqlite3_system_errno, |
+ /* Version 3.14.0 and later */ |
+ sqlite3_trace_v2, |
+ sqlite3_expanded_sql |
+}; |
+ |
+/* |
+** 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; |
+ sqlite3_loadext_entry xInit; |
+ char *zErrmsg = 0; |
+ const char *zEntry; |
+ char *zAltEntry = 0; |
+ void **aHandle; |
+ u64 nMsg = 300 + sqlite3Strlen30(zFile); |
+ int ii; |
+ int rc; |
+ |
+ /* Shared library endings to try if zFile cannot be loaded as written */ |
+ static const char *azEndings[] = { |
+#if SQLITE_OS_WIN |
+ "dll" |
+#elif defined(__APPLE__) |
+ "dylib" |
+#else |
+ "so" |
+#endif |
+ }; |
+ |
+ |
+ if( pzErrMsg ) *pzErrMsg = 0; |
+ |
+ /* 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 either sqlite3_enable_load_extension(db) or |
+ ** sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, 0) |
+ ** to turn on extension loading. |
+ */ |
+ if( (db->flags & SQLITE_LoadExtension)==0 ){ |
+ if( pzErrMsg ){ |
+ *pzErrMsg = sqlite3_mprintf("not authorized"); |
+ } |
+ return SQLITE_ERROR; |
+ } |
+ |
+ zEntry = zProc ? zProc : "sqlite3_extension_init"; |
+ |
+ handle = sqlite3OsDlOpen(pVfs, zFile); |
+#if SQLITE_OS_UNIX || SQLITE_OS_WIN |
+ for(ii=0; ii<ArraySize(azEndings) && handle==0; ii++){ |
+ char *zAltFile = sqlite3_mprintf("%s.%s", zFile, azEndings[ii]); |
+ if( zAltFile==0 ) return SQLITE_NOMEM_BKPT; |
+ handle = sqlite3OsDlOpen(pVfs, zAltFile); |
+ sqlite3_free(zAltFile); |
+ } |
+#endif |
+ if( handle==0 ){ |
+ if( pzErrMsg ){ |
+ *pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg); |
+ if( zErrmsg ){ |
+ sqlite3_snprintf(nMsg, zErrmsg, |
+ "unable to open shared library [%s]", zFile); |
+ sqlite3OsDlError(pVfs, nMsg-1, zErrmsg); |
+ } |
+ } |
+ return SQLITE_ERROR; |
+ } |
+ xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry); |
+ |
+ /* If no entry point was specified and the default legacy |
+ ** entry point name "sqlite3_extension_init" was not found, then |
+ ** construct an entry point name "sqlite3_X_init" where the X is |
+ ** replaced by the lowercase value of every ASCII alphabetic |
+ ** character in the filename after the last "/" upto the first ".", |
+ ** and eliding the first three characters if they are "lib". |
+ ** Examples: |
+ ** |
+ ** /usr/local/lib/libExample5.4.3.so ==> sqlite3_example_init |
+ ** C:/lib/mathfuncs.dll ==> sqlite3_mathfuncs_init |
+ */ |
+ if( xInit==0 && zProc==0 ){ |
+ int iFile, iEntry, c; |
+ int ncFile = sqlite3Strlen30(zFile); |
+ zAltEntry = sqlite3_malloc64(ncFile+30); |
+ if( zAltEntry==0 ){ |
+ sqlite3OsDlClose(pVfs, handle); |
+ return SQLITE_NOMEM_BKPT; |
+ } |
+ memcpy(zAltEntry, "sqlite3_", 8); |
+ for(iFile=ncFile-1; iFile>=0 && zFile[iFile]!='/'; iFile--){} |
+ iFile++; |
+ if( sqlite3_strnicmp(zFile+iFile, "lib", 3)==0 ) iFile += 3; |
+ for(iEntry=8; (c = zFile[iFile])!=0 && c!='.'; iFile++){ |
+ if( sqlite3Isalpha(c) ){ |
+ zAltEntry[iEntry++] = (char)sqlite3UpperToLower[(unsigned)c]; |
+ } |
+ } |
+ memcpy(zAltEntry+iEntry, "_init", 6); |
+ zEntry = zAltEntry; |
+ xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry); |
+ } |
+ if( xInit==0 ){ |
+ if( pzErrMsg ){ |
+ nMsg += sqlite3Strlen30(zEntry); |
+ *pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg); |
+ if( zErrmsg ){ |
+ sqlite3_snprintf(nMsg, zErrmsg, |
+ "no entry point [%s] in shared library [%s]", zEntry, zFile); |
+ sqlite3OsDlError(pVfs, nMsg-1, zErrmsg); |
+ } |
+ } |
+ sqlite3OsDlClose(pVfs, handle); |
+ sqlite3_free(zAltEntry); |
+ return SQLITE_ERROR; |
+ } |
+ sqlite3_free(zAltEntry); |
+ rc = xInit(db, &zErrmsg, &sqlite3Apis); |
+ if( rc ){ |
+ if( rc==SQLITE_OK_LOAD_PERMANENTLY ) return SQLITE_OK; |
+ 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_BKPT; |
+ } |
+ 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; |
+} |
+SQLITE_API 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); |
+ rc = sqlite3ApiExit(db, rc); |
+ sqlite3_mutex_leave(db->mutex); |
+ return rc; |
+} |
+ |
+/* |
+** Call this routine when the database connection is closing in order |
+** to clean up loaded extensions |
+*/ |
+SQLITE_PRIVATE 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. |
+*/ |
+SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff){ |
+ sqlite3_mutex_enter(db->mutex); |
+ if( onoff ){ |
+ db->flags |= SQLITE_LoadExtension|SQLITE_LoadExtFunc; |
+ }else{ |
+ db->flags &= ~(SQLITE_LoadExtension|SQLITE_LoadExtFunc); |
+ } |
+ sqlite3_mutex_leave(db->mutex); |
+ return SQLITE_OK; |
+} |
+ |
+#endif /* !defined(SQLITE_OMIT_LOAD_EXTENSION) */ |
+ |
+/* |
+** 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. |
+*/ |
+typedef struct sqlite3AutoExtList sqlite3AutoExtList; |
+static SQLITE_WSD struct sqlite3AutoExtList { |
+ u32 nExt; /* Number of entries in aExt[] */ |
+ void (**aExt)(void); /* Pointers to the extension init functions */ |
+} sqlite3Autoext = { 0, 0 }; |
+ |
+/* The "wsdAutoext" macro will resolve to the autoextension |
+** state vector. If writable static data is unsupported on the target, |
+** we have to locate the state vector at run-time. In the more common |
+** case where writable static data is supported, wsdStat can refer directly |
+** to the "sqlite3Autoext" state vector declared above. |
+*/ |
+#ifdef SQLITE_OMIT_WSD |
+# define wsdAutoextInit \ |
+ sqlite3AutoExtList *x = &GLOBAL(sqlite3AutoExtList,sqlite3Autoext) |
+# define wsdAutoext x[0] |
+#else |
+# define wsdAutoextInit |
+# define wsdAutoext sqlite3Autoext |
+#endif |
+ |
+ |
+/* |
+** Register a statically linked extension that is automatically |
+** loaded by every new database connection. |
+*/ |
+SQLITE_API int sqlite3_auto_extension( |
+ void (*xInit)(void) |
+){ |
+ int rc = SQLITE_OK; |
+#ifndef SQLITE_OMIT_AUTOINIT |
+ rc = sqlite3_initialize(); |
+ if( rc ){ |
+ return rc; |
+ }else |
+#endif |
+ { |
+ u32 i; |
+#if SQLITE_THREADSAFE |
+ sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); |
+#endif |
+ wsdAutoextInit; |
+ sqlite3_mutex_enter(mutex); |
+ for(i=0; i<wsdAutoext.nExt; i++){ |
+ if( wsdAutoext.aExt[i]==xInit ) break; |
+ } |
+ if( i==wsdAutoext.nExt ){ |
+ u64 nByte = (wsdAutoext.nExt+1)*sizeof(wsdAutoext.aExt[0]); |
+ void (**aNew)(void); |
+ aNew = sqlite3_realloc64(wsdAutoext.aExt, nByte); |
+ if( aNew==0 ){ |
+ rc = SQLITE_NOMEM_BKPT; |
+ }else{ |
+ wsdAutoext.aExt = aNew; |
+ wsdAutoext.aExt[wsdAutoext.nExt] = xInit; |
+ wsdAutoext.nExt++; |
+ } |
+ } |
+ sqlite3_mutex_leave(mutex); |
+ assert( (rc&0xff)==rc ); |
+ return rc; |
+ } |
+} |
+ |
+/* |
+** Cancel a prior call to sqlite3_auto_extension. Remove xInit from the |
+** set of routines that is invoked for each new database connection, if it |
+** is currently on the list. If xInit is not on the list, then this |
+** routine is a no-op. |
+** |
+** Return 1 if xInit was found on the list and removed. Return 0 if xInit |
+** was not on the list. |
+*/ |
+SQLITE_API int sqlite3_cancel_auto_extension( |
+ void (*xInit)(void) |
+){ |
+#if SQLITE_THREADSAFE |
+ sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); |
+#endif |
+ int i; |
+ int n = 0; |
+ wsdAutoextInit; |
+ sqlite3_mutex_enter(mutex); |
+ for(i=(int)wsdAutoext.nExt-1; i>=0; i--){ |
+ if( wsdAutoext.aExt[i]==xInit ){ |
+ wsdAutoext.nExt--; |
+ wsdAutoext.aExt[i] = wsdAutoext.aExt[wsdAutoext.nExt]; |
+ n++; |
+ break; |
+ } |
+ } |
+ sqlite3_mutex_leave(mutex); |
+ return n; |
+} |
+ |
+/* |
+** Reset the automatic extension loading mechanism. |
+*/ |
+SQLITE_API void sqlite3_reset_auto_extension(void){ |
+#ifndef SQLITE_OMIT_AUTOINIT |
+ if( sqlite3_initialize()==SQLITE_OK ) |
+#endif |
+ { |
+#if SQLITE_THREADSAFE |
+ sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); |
+#endif |
+ wsdAutoextInit; |
+ sqlite3_mutex_enter(mutex); |
+ sqlite3_free(wsdAutoext.aExt); |
+ wsdAutoext.aExt = 0; |
+ wsdAutoext.nExt = 0; |
+ sqlite3_mutex_leave(mutex); |
+ } |
+} |
+ |
+/* |
+** Load all automatic extensions. |
+** |
+** If anything goes wrong, set an error in the database connection. |
+*/ |
+SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){ |
+ u32 i; |
+ int go = 1; |
+ int rc; |
+ sqlite3_loadext_entry xInit; |
+ |
+ wsdAutoextInit; |
+ if( wsdAutoext.nExt==0 ){ |
+ /* Common case: early out without every having to acquire a mutex */ |
+ return; |
+ } |
+ for(i=0; go; i++){ |
+ char *zErrmsg; |
+#if SQLITE_THREADSAFE |
+ sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); |
+#endif |
+#ifdef SQLITE_OMIT_LOAD_EXTENSION |
+ const sqlite3_api_routines *pThunk = 0; |
+#else |
+ const sqlite3_api_routines *pThunk = &sqlite3Apis; |
+#endif |
+ sqlite3_mutex_enter(mutex); |
+ if( i>=wsdAutoext.nExt ){ |
+ xInit = 0; |
+ go = 0; |
+ }else{ |
+ xInit = (sqlite3_loadext_entry)wsdAutoext.aExt[i]; |
+ } |
+ sqlite3_mutex_leave(mutex); |
+ zErrmsg = 0; |
+ if( xInit && (rc = xInit(db, &zErrmsg, pThunk))!=0 ){ |
+ sqlite3ErrorWithMsg(db, rc, |
+ "automatic extension loading failed: %s", zErrmsg); |
+ go = 0; |
+ } |
+ sqlite3_free(zErrmsg); |
+ } |
+} |
+ |
+/************** End of loadext.c *********************************************/ |
+/************** Begin file pragma.c ******************************************/ |
+/* |
+** 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. |
+*/ |
+/* #include "sqliteInt.h" */ |
+ |
+#if !defined(SQLITE_ENABLE_LOCKING_STYLE) |
+# if defined(__APPLE__) |
+# define SQLITE_ENABLE_LOCKING_STYLE 1 |
+# else |
+# define SQLITE_ENABLE_LOCKING_STYLE 0 |
+# endif |
+#endif |
+ |
+/*************************************************************************** |
+** The "pragma.h" include file is an automatically generated file that |
+** that includes the PragType_XXXX macro definitions and the aPragmaName[] |
+** object. This ensures that the aPragmaName[] table is arranged in |
+** lexicographical order to facility a binary search of the pragma name. |
+** Do not edit pragma.h directly. Edit and rerun the script in at |
+** ../tool/mkpragmatab.tcl. */ |
+/************** Include pragma.h in the middle of pragma.c *******************/ |
+/************** Begin file pragma.h ******************************************/ |
+/* DO NOT EDIT! |
+** This file is automatically generated by the script at |
+** ../tool/mkpragmatab.tcl. To update the set of pragmas, edit |
+** that script and rerun it. |
+*/ |
+ |
+/* The various pragma types */ |
+#define PragTyp_HEADER_VALUE 0 |
+#define PragTyp_AUTO_VACUUM 1 |
+#define PragTyp_FLAG 2 |
+#define PragTyp_BUSY_TIMEOUT 3 |
+#define PragTyp_CACHE_SIZE 4 |
+#define PragTyp_CACHE_SPILL 5 |
+#define PragTyp_CASE_SENSITIVE_LIKE 6 |
+#define PragTyp_COLLATION_LIST 7 |
+#define PragTyp_COMPILE_OPTIONS 8 |
+#define PragTyp_DATA_STORE_DIRECTORY 9 |
+#define PragTyp_DATABASE_LIST 10 |
+#define PragTyp_DEFAULT_CACHE_SIZE 11 |
+#define PragTyp_ENCODING 12 |
+#define PragTyp_FOREIGN_KEY_CHECK 13 |
+#define PragTyp_FOREIGN_KEY_LIST 14 |
+#define PragTyp_INCREMENTAL_VACUUM 15 |
+#define PragTyp_INDEX_INFO 16 |
+#define PragTyp_INDEX_LIST 17 |
+#define PragTyp_INTEGRITY_CHECK 18 |
+#define PragTyp_JOURNAL_MODE 19 |
+#define PragTyp_JOURNAL_SIZE_LIMIT 20 |
+#define PragTyp_LOCK_PROXY_FILE 21 |
+#define PragTyp_LOCKING_MODE 22 |
+#define PragTyp_PAGE_COUNT 23 |
+#define PragTyp_MMAP_SIZE 24 |
+#define PragTyp_PAGE_SIZE 25 |
+#define PragTyp_SECURE_DELETE 26 |
+#define PragTyp_SHRINK_MEMORY 27 |
+#define PragTyp_SOFT_HEAP_LIMIT 28 |
+#define PragTyp_STATS 29 |
+#define PragTyp_SYNCHRONOUS 30 |
+#define PragTyp_TABLE_INFO 31 |
+#define PragTyp_TEMP_STORE 32 |
+#define PragTyp_TEMP_STORE_DIRECTORY 33 |
+#define PragTyp_THREADS 34 |
+#define PragTyp_WAL_AUTOCHECKPOINT 35 |
+#define PragTyp_WAL_CHECKPOINT 36 |
+#define PragTyp_ACTIVATE_EXTENSIONS 37 |
+#define PragTyp_HEXKEY 38 |
+#define PragTyp_KEY 39 |
+#define PragTyp_REKEY 40 |
+#define PragTyp_LOCK_STATUS 41 |
+#define PragTyp_PARSER_TRACE 42 |
+ |
+/* Property flags associated with various pragma. */ |
+#define PragFlg_NeedSchema 0x01 /* Force schema load before running */ |
+#define PragFlg_NoColumns 0x02 /* OP_ResultRow called with zero columns */ |
+#define PragFlg_NoColumns1 0x04 /* zero columns if RHS argument is present */ |
+#define PragFlg_ReadOnly 0x08 /* Read-only HEADER_VALUE */ |
+#define PragFlg_Result0 0x10 /* Acts as query when no argument */ |
+#define PragFlg_Result1 0x20 /* Acts as query when has one argument */ |
+#define PragFlg_SchemaOpt 0x40 /* Schema restricts name search if present */ |
+#define PragFlg_SchemaReq 0x80 /* Schema required - "main" is default */ |
+ |
+/* Names of columns for pragmas that return multi-column result |
+** or that return single-column results where the name of the |
+** result column is different from the name of the pragma |
+*/ |
+static const char *const pragCName[] = { |
+ /* 0 */ "cache_size", /* Used by: default_cache_size */ |
+ /* 1 */ "cid", /* Used by: table_info */ |
+ /* 2 */ "name", |
+ /* 3 */ "type", |
+ /* 4 */ "notnull", |
+ /* 5 */ "dflt_value", |
+ /* 6 */ "pk", |
+ /* 7 */ "table", /* Used by: stats */ |
+ /* 8 */ "index", |
+ /* 9 */ "width", |
+ /* 10 */ "height", |
+ /* 11 */ "seqno", /* Used by: index_info */ |
+ /* 12 */ "cid", |
+ /* 13 */ "name", |
+ /* 14 */ "seqno", /* Used by: index_xinfo */ |
+ /* 15 */ "cid", |
+ /* 16 */ "name", |
+ /* 17 */ "desc", |
+ /* 18 */ "coll", |
+ /* 19 */ "key", |
+ /* 20 */ "seq", /* Used by: index_list */ |
+ /* 21 */ "name", |
+ /* 22 */ "unique", |
+ /* 23 */ "origin", |
+ /* 24 */ "partial", |
+ /* 25 */ "seq", /* Used by: database_list */ |
+ /* 26 */ "name", |
+ /* 27 */ "file", |
+ /* 28 */ "seq", /* Used by: collation_list */ |
+ /* 29 */ "name", |
+ /* 30 */ "id", /* Used by: foreign_key_list */ |
+ /* 31 */ "seq", |
+ /* 32 */ "table", |
+ /* 33 */ "from", |
+ /* 34 */ "to", |
+ /* 35 */ "on_update", |
+ /* 36 */ "on_delete", |
+ /* 37 */ "match", |
+ /* 38 */ "table", /* Used by: foreign_key_check */ |
+ /* 39 */ "rowid", |
+ /* 40 */ "parent", |
+ /* 41 */ "fkid", |
+ /* 42 */ "busy", /* Used by: wal_checkpoint */ |
+ /* 43 */ "log", |
+ /* 44 */ "checkpointed", |
+ /* 45 */ "timeout", /* Used by: busy_timeout */ |
+ /* 46 */ "database", /* Used by: lock_status */ |
+ /* 47 */ "status", |
+}; |
+ |
+/* Definitions of all built-in pragmas */ |
+typedef struct PragmaName { |
+ const char *const zName; /* Name of pragma */ |
+ u8 ePragTyp; /* PragTyp_XXX value */ |
+ u8 mPragFlg; /* Zero or more PragFlg_XXX values */ |
+ u8 iPragCName; /* Start of column names in pragCName[] */ |
+ u8 nPragCName; /* Num of col names. 0 means use pragma name */ |
+ u32 iArg; /* Extra argument */ |
+} PragmaName; |
+static const PragmaName aPragmaName[] = { |
+#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD) |
+ {/* zName: */ "activate_extensions", |
+ /* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS, |
+ /* ePragFlg: */ 0, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
+ {/* zName: */ "application_id", |
+ /* ePragTyp: */ PragTyp_HEADER_VALUE, |
+ /* ePragFlg: */ PragFlg_NoColumns1|PragFlg_Result0, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ BTREE_APPLICATION_ID }, |
+#endif |
+#if !defined(SQLITE_OMIT_AUTOVACUUM) |
+ {/* zName: */ "auto_vacuum", |
+ /* ePragTyp: */ PragTyp_AUTO_VACUUM, |
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+#if !defined(SQLITE_OMIT_AUTOMATIC_INDEX) |
+ {/* zName: */ "automatic_index", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ SQLITE_AutoIndex }, |
+#endif |
+#endif |
+ {/* zName: */ "busy_timeout", |
+ /* ePragTyp: */ PragTyp_BUSY_TIMEOUT, |
+ /* ePragFlg: */ PragFlg_Result0, |
+ /* ColNames: */ 45, 1, |
+ /* iArg: */ 0 }, |
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
+ {/* zName: */ "cache_size", |
+ /* ePragTyp: */ PragTyp_CACHE_SIZE, |
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+ {/* zName: */ "cache_spill", |
+ /* ePragTyp: */ PragTyp_CACHE_SPILL, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+#endif |
+ {/* zName: */ "case_sensitive_like", |
+ /* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE, |
+ /* ePragFlg: */ PragFlg_NoColumns, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+ {/* zName: */ "cell_size_check", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ SQLITE_CellSizeCk }, |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+ {/* zName: */ "checkpoint_fullfsync", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ SQLITE_CkptFullFSync }, |
+#endif |
+#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
+ {/* zName: */ "collation_list", |
+ /* ePragTyp: */ PragTyp_COLLATION_LIST, |
+ /* ePragFlg: */ PragFlg_Result0, |
+ /* ColNames: */ 28, 2, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS) |
+ {/* zName: */ "compile_options", |
+ /* ePragTyp: */ PragTyp_COMPILE_OPTIONS, |
+ /* ePragFlg: */ PragFlg_Result0, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+ {/* zName: */ "count_changes", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ SQLITE_CountRows }, |
+#endif |
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN |
+ {/* zName: */ "data_store_directory", |
+ /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY, |
+ /* ePragFlg: */ PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
+ {/* zName: */ "data_version", |
+ /* ePragTyp: */ PragTyp_HEADER_VALUE, |
+ /* ePragFlg: */ PragFlg_ReadOnly|PragFlg_Result0, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ BTREE_DATA_VERSION }, |
+#endif |
+#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
+ {/* zName: */ "database_list", |
+ /* ePragTyp: */ PragTyp_DATABASE_LIST, |
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0, |
+ /* ColNames: */ 25, 3, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) |
+ {/* zName: */ "default_cache_size", |
+ /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE, |
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 1, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) |
+ {/* zName: */ "defer_foreign_keys", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ SQLITE_DeferFKs }, |
+#endif |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+ {/* zName: */ "empty_result_callbacks", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ SQLITE_NullCallback }, |
+#endif |
+#if !defined(SQLITE_OMIT_UTF16) |
+ {/* zName: */ "encoding", |
+ /* ePragTyp: */ PragTyp_ENCODING, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) |
+ {/* zName: */ "foreign_key_check", |
+ /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK, |
+ /* ePragFlg: */ PragFlg_NeedSchema, |
+ /* ColNames: */ 38, 4, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FOREIGN_KEY) |
+ {/* zName: */ "foreign_key_list", |
+ /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST, |
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, |
+ /* ColNames: */ 30, 8, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) |
+ {/* zName: */ "foreign_keys", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ SQLITE_ForeignKeys }, |
+#endif |
+#endif |
+#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
+ {/* zName: */ "freelist_count", |
+ /* ePragTyp: */ PragTyp_HEADER_VALUE, |
+ /* ePragFlg: */ PragFlg_ReadOnly|PragFlg_Result0, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ BTREE_FREE_PAGE_COUNT }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+ {/* zName: */ "full_column_names", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ SQLITE_FullColNames }, |
+ {/* zName: */ "fullfsync", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ SQLITE_FullFSync }, |
+#endif |
+#if defined(SQLITE_HAS_CODEC) |
+ {/* zName: */ "hexkey", |
+ /* ePragTyp: */ PragTyp_HEXKEY, |
+ /* ePragFlg: */ 0, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+ {/* zName: */ "hexrekey", |
+ /* ePragTyp: */ PragTyp_HEXKEY, |
+ /* ePragFlg: */ 0, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+#if !defined(SQLITE_OMIT_CHECK) |
+ {/* zName: */ "ignore_check_constraints", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ SQLITE_IgnoreChecks }, |
+#endif |
+#endif |
+#if !defined(SQLITE_OMIT_AUTOVACUUM) |
+ {/* zName: */ "incremental_vacuum", |
+ /* ePragTyp: */ PragTyp_INCREMENTAL_VACUUM, |
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_NoColumns, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
+ {/* zName: */ "index_info", |
+ /* ePragTyp: */ PragTyp_INDEX_INFO, |
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, |
+ /* ColNames: */ 11, 3, |
+ /* iArg: */ 0 }, |
+ {/* zName: */ "index_list", |
+ /* ePragTyp: */ PragTyp_INDEX_LIST, |
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, |
+ /* ColNames: */ 20, 5, |
+ /* iArg: */ 0 }, |
+ {/* zName: */ "index_xinfo", |
+ /* ePragTyp: */ PragTyp_INDEX_INFO, |
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, |
+ /* ColNames: */ 14, 6, |
+ /* iArg: */ 1 }, |
+#endif |
+#if !defined(SQLITE_OMIT_INTEGRITY_CHECK) |
+ {/* zName: */ "integrity_check", |
+ /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, |
+ /* ePragFlg: */ PragFlg_NeedSchema, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
+ {/* zName: */ "journal_mode", |
+ /* ePragTyp: */ PragTyp_JOURNAL_MODE, |
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+ {/* zName: */ "journal_size_limit", |
+ /* ePragTyp: */ PragTyp_JOURNAL_SIZE_LIMIT, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if defined(SQLITE_HAS_CODEC) |
+ {/* zName: */ "key", |
+ /* ePragTyp: */ PragTyp_KEY, |
+ /* ePragFlg: */ 0, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+ {/* zName: */ "legacy_file_format", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ SQLITE_LegacyFileFmt }, |
+#endif |
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE |
+ {/* zName: */ "lock_proxy_file", |
+ /* ePragTyp: */ PragTyp_LOCK_PROXY_FILE, |
+ /* ePragFlg: */ PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) |
+ {/* zName: */ "lock_status", |
+ /* ePragTyp: */ PragTyp_LOCK_STATUS, |
+ /* ePragFlg: */ PragFlg_Result0, |
+ /* ColNames: */ 46, 2, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
+ {/* zName: */ "locking_mode", |
+ /* ePragTyp: */ PragTyp_LOCKING_MODE, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+ {/* zName: */ "max_page_count", |
+ /* ePragTyp: */ PragTyp_PAGE_COUNT, |
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+ {/* zName: */ "mmap_size", |
+ /* ePragTyp: */ PragTyp_MMAP_SIZE, |
+ /* ePragFlg: */ 0, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+ {/* zName: */ "page_count", |
+ /* ePragTyp: */ PragTyp_PAGE_COUNT, |
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+ {/* zName: */ "page_size", |
+ /* ePragTyp: */ PragTyp_PAGE_SIZE, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_PARSER_TRACE) |
+ {/* zName: */ "parser_trace", |
+ /* ePragTyp: */ PragTyp_PARSER_TRACE, |
+ /* ePragFlg: */ 0, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+ {/* zName: */ "query_only", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ SQLITE_QueryOnly }, |
+#endif |
+#if !defined(SQLITE_OMIT_INTEGRITY_CHECK) |
+ {/* zName: */ "quick_check", |
+ /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, |
+ /* ePragFlg: */ PragFlg_NeedSchema, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+ {/* zName: */ "read_uncommitted", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ SQLITE_ReadUncommitted }, |
+ {/* zName: */ "recursive_triggers", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ SQLITE_RecTriggers }, |
+#endif |
+#if defined(SQLITE_HAS_CODEC) |
+ {/* zName: */ "rekey", |
+ /* ePragTyp: */ PragTyp_REKEY, |
+ /* ePragFlg: */ 0, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+ {/* zName: */ "reverse_unordered_selects", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ SQLITE_ReverseOrder }, |
+#endif |
+#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
+ {/* zName: */ "schema_version", |
+ /* ePragTyp: */ PragTyp_HEADER_VALUE, |
+ /* ePragFlg: */ PragFlg_NoColumns1|PragFlg_Result0, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ BTREE_SCHEMA_VERSION }, |
+#endif |
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
+ {/* zName: */ "secure_delete", |
+ /* ePragTyp: */ PragTyp_SECURE_DELETE, |
+ /* ePragFlg: */ PragFlg_Result0, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+ {/* zName: */ "short_column_names", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ SQLITE_ShortColNames }, |
+#endif |
+ {/* zName: */ "shrink_memory", |
+ /* ePragTyp: */ PragTyp_SHRINK_MEMORY, |
+ /* ePragFlg: */ PragFlg_NoColumns, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+ {/* zName: */ "soft_heap_limit", |
+ /* ePragTyp: */ PragTyp_SOFT_HEAP_LIMIT, |
+ /* ePragFlg: */ PragFlg_Result0, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+#if defined(SQLITE_DEBUG) |
+ {/* zName: */ "sql_trace", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ SQLITE_SqlTrace }, |
+#endif |
+#endif |
+#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
+ {/* zName: */ "stats", |
+ /* ePragTyp: */ PragTyp_STATS, |
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, |
+ /* ColNames: */ 7, 4, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
+ {/* zName: */ "synchronous", |
+ /* ePragTyp: */ PragTyp_SYNCHRONOUS, |
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
+ {/* zName: */ "table_info", |
+ /* ePragTyp: */ PragTyp_TABLE_INFO, |
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, |
+ /* ColNames: */ 1, 6, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
+ {/* zName: */ "temp_store", |
+ /* ePragTyp: */ PragTyp_TEMP_STORE, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+ {/* zName: */ "temp_store_directory", |
+ /* ePragTyp: */ PragTyp_TEMP_STORE_DIRECTORY, |
+ /* ePragFlg: */ PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+#endif |
+ {/* zName: */ "threads", |
+ /* ePragTyp: */ PragTyp_THREADS, |
+ /* ePragFlg: */ PragFlg_Result0, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
+ {/* zName: */ "user_version", |
+ /* ePragTyp: */ PragTyp_HEADER_VALUE, |
+ /* ePragFlg: */ PragFlg_NoColumns1|PragFlg_Result0, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ BTREE_USER_VERSION }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+#if defined(SQLITE_DEBUG) |
+ {/* zName: */ "vdbe_addoptrace", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ SQLITE_VdbeAddopTrace }, |
+ {/* zName: */ "vdbe_debug", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace }, |
+ {/* zName: */ "vdbe_eqp", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ SQLITE_VdbeEQP }, |
+ {/* zName: */ "vdbe_listing", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ SQLITE_VdbeListing }, |
+ {/* zName: */ "vdbe_trace", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ SQLITE_VdbeTrace }, |
+#endif |
+#endif |
+#if !defined(SQLITE_OMIT_WAL) |
+ {/* zName: */ "wal_autocheckpoint", |
+ /* ePragTyp: */ PragTyp_WAL_AUTOCHECKPOINT, |
+ /* ePragFlg: */ 0, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+ {/* zName: */ "wal_checkpoint", |
+ /* ePragTyp: */ PragTyp_WAL_CHECKPOINT, |
+ /* ePragFlg: */ PragFlg_NeedSchema, |
+ /* ColNames: */ 42, 3, |
+ /* iArg: */ 0 }, |
+#endif |
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+ {/* zName: */ "writable_schema", |
+ /* ePragTyp: */ PragTyp_FLAG, |
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, |
+#endif |
+}; |
+/* Number of pragmas: 60 on by default, 73 total. */ |
+ |
+/************** End of pragma.h **********************************************/ |
+/************** Continuing where we left off in pragma.c *********************/ |
+ |
+/* |
+** Interpret the given string as a safety level. Return 0 for OFF, |
+** 1 for ON or NORMAL, 2 for FULL, and 3 for EXTRA. Return 1 for an empty or |
+** unrecognized string argument. The FULL and EXTRA option is disallowed |
+** if the omitFull parameter it 1. |
+** |
+** 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 u8 getSafetyLevel(const char *z, int omitFull, u8 dflt){ |
+ /* 123456789 123456789 123 */ |
+ static const char zText[] = "onoffalseyestruextrafull"; |
+ static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 15, 20}; |
+ static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 5, 4}; |
+ static const u8 iValue[] = {1, 0, 0, 0, 1, 1, 3, 2}; |
+ /* on no off false yes true extra full */ |
+ int i, n; |
+ if( sqlite3Isdigit(*z) ){ |
+ return (u8)sqlite3Atoi(z); |
+ } |
+ n = sqlite3Strlen30(z); |
+ for(i=0; i<ArraySize(iLength); i++){ |
+ if( iLength[i]==n && sqlite3StrNICmp(&zText[iOffset[i]],z,n)==0 |
+ && (!omitFull || iValue[i]<=1) |
+ ){ |
+ return iValue[i]; |
+ } |
+ } |
+ return dflt; |
+} |
+ |
+/* |
+** Interpret the given string as a boolean value. |
+*/ |
+SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z, u8 dflt){ |
+ return getSafetyLevel(z,1,dflt)!=0; |
+} |
+ |
+/* The sqlite3GetBoolean() function is used by other modules but the |
+** remainder of this file is specific to PRAGMA processing. So omit |
+** the rest of the file if PRAGMAs are omitted from the build. |
+*/ |
+#if !defined(SQLITE_OMIT_PRAGMA) |
+ |
+/* |
+** 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 = sqlite3Atoi(z); |
+ return (u8)((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; |
+ sqlite3ResetAllSchemasOfConnection(db); |
+ } |
+ 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 = (u8)ts; |
+ return SQLITE_OK; |
+} |
+#endif /* SQLITE_PAGER_PRAGMAS */ |
+ |
+/* |
+** Set result column names for a pragma. |
+*/ |
+static void setPragmaResultColumnNames( |
+ Vdbe *v, /* The query under construction */ |
+ const PragmaName *pPragma /* The pragma */ |
+){ |
+ u8 n = pPragma->nPragCName; |
+ sqlite3VdbeSetNumCols(v, n==0 ? 1 : n); |
+ if( n==0 ){ |
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, pPragma->zName, SQLITE_STATIC); |
+ }else{ |
+ int i, j; |
+ for(i=0, j=pPragma->iPragCName; i<n; i++, j++){ |
+ sqlite3VdbeSetColName(v, i, COLNAME_NAME, pragCName[j], SQLITE_STATIC); |
+ } |
+ } |
+} |
+ |
+/* |
+** Generate code to return a single integer value. |
+*/ |
+static void returnSingleInt(Vdbe *v, i64 value){ |
+ sqlite3VdbeAddOp4Dup8(v, OP_Int64, 0, 1, 0, (const u8*)&value, P4_INT64); |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); |
+} |
+ |
+/* |
+** Generate code to return a single text value. |
+*/ |
+static void returnSingleText( |
+ Vdbe *v, /* Prepared statement under construction */ |
+ const char *zValue /* Value to be returned */ |
+){ |
+ if( zValue ){ |
+ sqlite3VdbeLoadString(v, 1, (const char*)zValue); |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); |
+ } |
+} |
+ |
+ |
+/* |
+** Set the safety_level and pager flags for pager iDb. Or if iDb<0 |
+** set these values for all pagers. |
+*/ |
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS |
+static void setAllPagerFlags(sqlite3 *db){ |
+ if( db->autoCommit ){ |
+ Db *pDb = db->aDb; |
+ int n = db->nDb; |
+ assert( SQLITE_FullFSync==PAGER_FULLFSYNC ); |
+ assert( SQLITE_CkptFullFSync==PAGER_CKPT_FULLFSYNC ); |
+ assert( SQLITE_CacheSpill==PAGER_CACHESPILL ); |
+ assert( (PAGER_FULLFSYNC | PAGER_CKPT_FULLFSYNC | PAGER_CACHESPILL) |
+ == PAGER_FLAGS_MASK ); |
+ assert( (pDb->safety_level & PAGER_SYNCHRONOUS_MASK)==pDb->safety_level ); |
+ while( (n--) > 0 ){ |
+ if( pDb->pBt ){ |
+ sqlite3BtreeSetPagerFlags(pDb->pBt, |
+ pDb->safety_level | (db->flags & PAGER_FLAGS_MASK) ); |
+ } |
+ pDb++; |
+ } |
+ } |
+} |
+#else |
+# define setAllPagerFlags(X) /* no-op */ |
+#endif |
+ |
+ |
+/* |
+** Return a human-readable name for a constraint resolution action. |
+*/ |
+#ifndef SQLITE_OMIT_FOREIGN_KEY |
+static const char *actionName(u8 action){ |
+ const char *zName; |
+ switch( action ){ |
+ case OE_SetNull: zName = "SET NULL"; break; |
+ case OE_SetDflt: zName = "SET DEFAULT"; break; |
+ case OE_Cascade: zName = "CASCADE"; break; |
+ case OE_Restrict: zName = "RESTRICT"; break; |
+ default: zName = "NO ACTION"; |
+ assert( action==OE_None ); break; |
+ } |
+ return zName; |
+} |
+#endif |
+ |
+ |
+/* |
+** Parameter eMode must be one of the PAGER_JOURNALMODE_XXX constants |
+** defined in pager.h. This function returns the associated lowercase |
+** journal-mode name. |
+*/ |
+SQLITE_PRIVATE const char *sqlite3JournalModename(int eMode){ |
+ static char * const azModeName[] = { |
+ "delete", "persist", "off", "truncate", "memory" |
+#ifndef SQLITE_OMIT_WAL |
+ , "wal" |
+#endif |
+ }; |
+ assert( PAGER_JOURNALMODE_DELETE==0 ); |
+ assert( PAGER_JOURNALMODE_PERSIST==1 ); |
+ assert( PAGER_JOURNALMODE_OFF==2 ); |
+ assert( PAGER_JOURNALMODE_TRUNCATE==3 ); |
+ assert( PAGER_JOURNALMODE_MEMORY==4 ); |
+ assert( PAGER_JOURNALMODE_WAL==5 ); |
+ assert( eMode>=0 && eMode<=ArraySize(azModeName) ); |
+ |
+ if( eMode==ArraySize(azModeName) ) return 0; |
+ return azModeName[eMode]; |
+} |
+ |
+/* |
+** Locate a pragma in the aPragmaName[] array. |
+*/ |
+static const PragmaName *pragmaLocate(const char *zName){ |
+ int upr, lwr, mid = 0, rc; |
+ lwr = 0; |
+ upr = ArraySize(aPragmaName)-1; |
+ while( lwr<=upr ){ |
+ mid = (lwr+upr)/2; |
+ rc = sqlite3_stricmp(zName, aPragmaName[mid].zName); |
+ if( rc==0 ) break; |
+ if( rc<0 ){ |
+ upr = mid - 1; |
+ }else{ |
+ lwr = mid + 1; |
+ } |
+ } |
+ return lwr>upr ? 0 : &aPragmaName[mid]; |
+} |
+ |
+/* |
+** Process a pragma statement. |
+** |
+** Pragmas are of this form: |
+** |
+** PRAGMA [schema.]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. |
+*/ |
+SQLITE_PRIVATE void sqlite3Pragma( |
+ Parse *pParse, |
+ Token *pId1, /* First part of [schema.]id field */ |
+ Token *pId2, /* Second part of [schema.]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 */ |
+ char *aFcntl[4]; /* Argument to SQLITE_FCNTL_PRAGMA */ |
+ int iDb; /* Database index for <database> */ |
+ int rc; /* return value form SQLITE_FCNTL_PRAGMA */ |
+ sqlite3 *db = pParse->db; /* The database connection */ |
+ Db *pDb; /* The specific database being pragmaed */ |
+ Vdbe *v = sqlite3GetVdbe(pParse); /* Prepared statement */ |
+ const PragmaName *pPragma; /* The pragma */ |
+ |
+ if( v==0 ) return; |
+ sqlite3VdbeRunOnlyOnce(v); |
+ pParse->nMem = 2; |
+ |
+ /* Interpret the [schema.] 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); |
+ } |
+ |
+ assert( pId2 ); |
+ zDb = pId2->n>0 ? pDb->zDbSName : 0; |
+ if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){ |
+ goto pragma_out; |
+ } |
+ |
+ /* Send an SQLITE_FCNTL_PRAGMA file-control to the underlying VFS |
+ ** connection. If it returns SQLITE_OK, then assume that the VFS |
+ ** handled the pragma and generate a no-op prepared statement. |
+ ** |
+ ** IMPLEMENTATION-OF: R-12238-55120 Whenever a PRAGMA statement is parsed, |
+ ** an SQLITE_FCNTL_PRAGMA file control is sent to the open sqlite3_file |
+ ** object corresponding to the database file to which the pragma |
+ ** statement refers. |
+ ** |
+ ** IMPLEMENTATION-OF: R-29875-31678 The argument to the SQLITE_FCNTL_PRAGMA |
+ ** file control is an array of pointers to strings (char**) in which the |
+ ** second element of the array is the name of the pragma and the third |
+ ** element is the argument to the pragma or NULL if the pragma has no |
+ ** argument. |
+ */ |
+ aFcntl[0] = 0; |
+ aFcntl[1] = zLeft; |
+ aFcntl[2] = zRight; |
+ aFcntl[3] = 0; |
+ db->busyHandler.nBusy = 0; |
+ rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl); |
+ if( rc==SQLITE_OK ){ |
+ sqlite3VdbeSetNumCols(v, 1); |
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, aFcntl[0], SQLITE_TRANSIENT); |
+ returnSingleText(v, aFcntl[0]); |
+ sqlite3_free(aFcntl[0]); |
+ goto pragma_out; |
+ } |
+ if( rc!=SQLITE_NOTFOUND ){ |
+ if( aFcntl[0] ){ |
+ sqlite3ErrorMsg(pParse, "%s", aFcntl[0]); |
+ sqlite3_free(aFcntl[0]); |
+ } |
+ pParse->nErr++; |
+ pParse->rc = rc; |
+ goto pragma_out; |
+ } |
+ |
+ /* Locate the pragma in the lookup table */ |
+ pPragma = pragmaLocate(zLeft); |
+ if( pPragma==0 ) goto pragma_out; |
+ |
+ /* Make sure the database schema is loaded if the pragma requires that */ |
+ if( (pPragma->mPragFlg & PragFlg_NeedSchema)!=0 ){ |
+ if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
+ } |
+ |
+ /* Register the result column names for pragmas that return results */ |
+ if( (pPragma->mPragFlg & PragFlg_NoColumns)==0 |
+ && ((pPragma->mPragFlg & PragFlg_NoColumns1)==0 || zRight==0) |
+ ){ |
+ setPragmaResultColumnNames(v, pPragma); |
+ } |
+ |
+ /* Jump to the appropriate pragma handler */ |
+ switch( pPragma->ePragTyp ){ |
+ |
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) |
+ /* |
+ ** PRAGMA [schema.]default_cache_size |
+ ** PRAGMA [schema.]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. |
+ ** |
+ ** Older versions of SQLite would set the default cache size to a |
+ ** negative number to indicate synchronous=OFF. These days, synchronous |
+ ** is always on by default regardless of the sign of the default cache |
+ ** size. But continue to take the absolute value of the default cache |
+ ** size of historical compatibility. |
+ */ |
+ case PragTyp_DEFAULT_CACHE_SIZE: { |
+ static const int iLn = VDBE_OFFSET_LINENO(2); |
+ static const VdbeOpList getCacheSize[] = { |
+ { OP_Transaction, 0, 0, 0}, /* 0 */ |
+ { OP_ReadCookie, 0, 1, BTREE_DEFAULT_CACHE_SIZE}, /* 1 */ |
+ { OP_IfPos, 1, 8, 0}, |
+ { OP_Integer, 0, 2, 0}, |
+ { OP_Subtract, 1, 2, 1}, |
+ { OP_IfPos, 1, 8, 0}, |
+ { OP_Integer, 0, 1, 0}, /* 6 */ |
+ { OP_Noop, 0, 0, 0}, |
+ { OP_ResultRow, 1, 1, 0}, |
+ }; |
+ VdbeOp *aOp; |
+ sqlite3VdbeUsesBtree(v, iDb); |
+ if( !zRight ){ |
+ pParse->nMem += 2; |
+ sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(getCacheSize)); |
+ aOp = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize, iLn); |
+ if( ONLY_IF_REALLOC_STRESS(aOp==0) ) break; |
+ aOp[0].p1 = iDb; |
+ aOp[1].p1 = iDb; |
+ aOp[6].p1 = SQLITE_DEFAULT_CACHE_SIZE; |
+ }else{ |
+ int size = sqlite3AbsInt32(sqlite3Atoi(zRight)); |
+ sqlite3BeginWriteOperation(pParse, 0, iDb); |
+ sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_DEFAULT_CACHE_SIZE, size); |
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
+ pDb->pSchema->cache_size = size; |
+ sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); |
+ } |
+ break; |
+ } |
+#endif /* !SQLITE_OMIT_PAGER_PRAGMAS && !SQLITE_OMIT_DEPRECATED */ |
+ |
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
+ /* |
+ ** PRAGMA [schema.]page_size |
+ ** PRAGMA [schema.]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. |
+ */ |
+ case PragTyp_PAGE_SIZE: { |
+ Btree *pBt = pDb->pBt; |
+ assert( pBt!=0 ); |
+ if( !zRight ){ |
+ int size = ALWAYS(pBt) ? sqlite3BtreeGetPageSize(pBt) : 0; |
+ returnSingleInt(v, 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 = sqlite3Atoi(zRight); |
+ if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize,-1,0) ){ |
+ sqlite3OomFault(db); |
+ } |
+ } |
+ break; |
+ } |
+ |
+ /* |
+ ** PRAGMA [schema.]secure_delete |
+ ** PRAGMA [schema.]secure_delete=ON/OFF |
+ ** |
+ ** The first form reports the current setting for the |
+ ** secure_delete flag. The second form changes the secure_delete |
+ ** flag setting and reports thenew value. |
+ */ |
+ case PragTyp_SECURE_DELETE: { |
+ Btree *pBt = pDb->pBt; |
+ int b = -1; |
+ assert( pBt!=0 ); |
+ if( zRight ){ |
+ b = sqlite3GetBoolean(zRight, 0); |
+ } |
+ if( pId2->n==0 && b>=0 ){ |
+ int ii; |
+ for(ii=0; ii<db->nDb; ii++){ |
+ sqlite3BtreeSecureDelete(db->aDb[ii].pBt, b); |
+ } |
+ } |
+ b = sqlite3BtreeSecureDelete(pBt, b); |
+ returnSingleInt(v, b); |
+ break; |
+ } |
+ |
+ /* |
+ ** PRAGMA [schema.]max_page_count |
+ ** PRAGMA [schema.]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. |
+ ** |
+ ** The absolute value of N is used. This is undocumented and might |
+ ** change. The only purpose is to provide an easy way to test |
+ ** the sqlite3AbsInt32() function. |
+ ** |
+ ** PRAGMA [schema.]page_count |
+ ** |
+ ** Return the number of pages in the specified database. |
+ */ |
+ case PragTyp_PAGE_COUNT: { |
+ int iReg; |
+ sqlite3CodeVerifySchema(pParse, iDb); |
+ iReg = ++pParse->nMem; |
+ if( sqlite3Tolower(zLeft[0])=='p' ){ |
+ sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg); |
+ }else{ |
+ sqlite3VdbeAddOp3(v, OP_MaxPgcnt, iDb, iReg, |
+ sqlite3AbsInt32(sqlite3Atoi(zRight))); |
+ } |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, iReg, 1); |
+ break; |
+ } |
+ |
+ /* |
+ ** PRAGMA [schema.]locking_mode |
+ ** PRAGMA [schema.]locking_mode = (normal|exclusive) |
+ */ |
+ case PragTyp_LOCKING_MODE: { |
+ 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 = (u8)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"; |
+ } |
+ returnSingleText(v, zRet); |
+ break; |
+ } |
+ |
+ /* |
+ ** PRAGMA [schema.]journal_mode |
+ ** PRAGMA [schema.]journal_mode = |
+ ** (delete|persist|off|truncate|memory|wal|off) |
+ */ |
+ case PragTyp_JOURNAL_MODE: { |
+ int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */ |
+ int ii; /* Loop counter */ |
+ |
+ if( zRight==0 ){ |
+ /* If there is no "=MODE" part of the pragma, do a query for the |
+ ** current mode */ |
+ eMode = PAGER_JOURNALMODE_QUERY; |
+ }else{ |
+ const char *zMode; |
+ int n = sqlite3Strlen30(zRight); |
+ for(eMode=0; (zMode = sqlite3JournalModename(eMode))!=0; eMode++){ |
+ if( sqlite3StrNICmp(zRight, zMode, n)==0 ) break; |
+ } |
+ if( !zMode ){ |
+ /* If the "=MODE" part does not match any known journal mode, |
+ ** then do a query */ |
+ eMode = PAGER_JOURNALMODE_QUERY; |
+ } |
+ } |
+ if( eMode==PAGER_JOURNALMODE_QUERY && pId2->n==0 ){ |
+ /* Convert "PRAGMA journal_mode" into "PRAGMA main.journal_mode" */ |
+ iDb = 0; |
+ pId2->n = 1; |
+ } |
+ for(ii=db->nDb-1; ii>=0; ii--){ |
+ if( db->aDb[ii].pBt && (ii==iDb || pId2->n==0) ){ |
+ sqlite3VdbeUsesBtree(v, ii); |
+ sqlite3VdbeAddOp3(v, OP_JournalMode, ii, 1, eMode); |
+ } |
+ } |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); |
+ break; |
+ } |
+ |
+ /* |
+ ** PRAGMA [schema.]journal_size_limit |
+ ** PRAGMA [schema.]journal_size_limit=N |
+ ** |
+ ** Get or set the size limit on rollback journal files. |
+ */ |
+ case PragTyp_JOURNAL_SIZE_LIMIT: { |
+ Pager *pPager = sqlite3BtreePager(pDb->pBt); |
+ i64 iLimit = -2; |
+ if( zRight ){ |
+ sqlite3DecOrHexToI64(zRight, &iLimit); |
+ if( iLimit<-1 ) iLimit = -1; |
+ } |
+ iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit); |
+ returnSingleInt(v, iLimit); |
+ break; |
+ } |
+ |
+#endif /* SQLITE_OMIT_PAGER_PRAGMAS */ |
+ |
+ /* |
+ ** PRAGMA [schema.]auto_vacuum |
+ ** PRAGMA [schema.]auto_vacuum=N |
+ ** |
+ ** Get or set the value of the database 'auto-vacuum' parameter. |
+ ** The value is one of: 0 NONE 1 FULL 2 INCREMENTAL |
+ */ |
+#ifndef SQLITE_OMIT_AUTOVACUUM |
+ case PragTyp_AUTO_VACUUM: { |
+ Btree *pBt = pDb->pBt; |
+ assert( pBt!=0 ); |
+ if( !zRight ){ |
+ returnSingleInt(v, sqlite3BtreeGetAutoVacuum(pBt)); |
+ }else{ |
+ int eAuto = getAutoVacuum(zRight); |
+ assert( eAuto>=0 && eAuto<=2 ); |
+ db->nextAutovac = (u8)eAuto; |
+ /* 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. |
+ */ |
+ 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 int iLn = VDBE_OFFSET_LINENO(2); |
+ static const VdbeOpList setMeta6[] = { |
+ { OP_Transaction, 0, 1, 0}, /* 0 */ |
+ { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE}, |
+ { OP_If, 1, 0, 0}, /* 2 */ |
+ { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */ |
+ { OP_SetCookie, 0, BTREE_INCR_VACUUM, 0}, /* 4 */ |
+ }; |
+ VdbeOp *aOp; |
+ int iAddr = sqlite3VdbeCurrentAddr(v); |
+ sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(setMeta6)); |
+ aOp = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6, iLn); |
+ if( ONLY_IF_REALLOC_STRESS(aOp==0) ) break; |
+ aOp[0].p1 = iDb; |
+ aOp[1].p1 = iDb; |
+ aOp[2].p2 = iAddr+4; |
+ aOp[4].p1 = iDb; |
+ aOp[4].p3 = eAuto - 1; |
+ sqlite3VdbeUsesBtree(v, iDb); |
+ } |
+ } |
+ break; |
+ } |
+#endif |
+ |
+ /* |
+ ** PRAGMA [schema.]incremental_vacuum(N) |
+ ** |
+ ** Do N steps of incremental vacuuming on a database. |
+ */ |
+#ifndef SQLITE_OMIT_AUTOVACUUM |
+ case PragTyp_INCREMENTAL_VACUUM: { |
+ int iLimit, addr; |
+ 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); VdbeCoverage(v); |
+ sqlite3VdbeAddOp1(v, OP_ResultRow, 1); |
+ sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); |
+ sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr); VdbeCoverage(v); |
+ sqlite3VdbeJumpHere(v, addr); |
+ break; |
+ } |
+#endif |
+ |
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS |
+ /* |
+ ** PRAGMA [schema.]cache_size |
+ ** PRAGMA [schema.]cache_size=N |
+ ** |
+ ** The first form reports the current local setting for the |
+ ** page cache size. The second form sets the local |
+ ** page cache size value. If N is positive then that is the |
+ ** number of pages in the cache. If N is negative, then the |
+ ** number of pages is adjusted so that the cache uses -N kibibytes |
+ ** of memory. |
+ */ |
+ case PragTyp_CACHE_SIZE: { |
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
+ if( !zRight ){ |
+ returnSingleInt(v, pDb->pSchema->cache_size); |
+ }else{ |
+ int size = sqlite3Atoi(zRight); |
+ pDb->pSchema->cache_size = size; |
+ sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); |
+ } |
+ break; |
+ } |
+ |
+ /* |
+ ** PRAGMA [schema.]cache_spill |
+ ** PRAGMA cache_spill=BOOLEAN |
+ ** PRAGMA [schema.]cache_spill=N |
+ ** |
+ ** The first form reports the current local setting for the |
+ ** page cache spill size. The second form turns cache spill on |
+ ** or off. When turnning cache spill on, the size is set to the |
+ ** current cache_size. The third form sets a spill size that |
+ ** may be different form the cache size. |
+ ** If N is positive then that is the |
+ ** number of pages in the cache. If N is negative, then the |
+ ** number of pages is adjusted so that the cache uses -N kibibytes |
+ ** of memory. |
+ ** |
+ ** If the number of cache_spill pages is less then the number of |
+ ** cache_size pages, no spilling occurs until the page count exceeds |
+ ** the number of cache_size pages. |
+ ** |
+ ** The cache_spill=BOOLEAN setting applies to all attached schemas, |
+ ** not just the schema specified. |
+ */ |
+ case PragTyp_CACHE_SPILL: { |
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
+ if( !zRight ){ |
+ returnSingleInt(v, |
+ (db->flags & SQLITE_CacheSpill)==0 ? 0 : |
+ sqlite3BtreeSetSpillSize(pDb->pBt,0)); |
+ }else{ |
+ int size = 1; |
+ if( sqlite3GetInt32(zRight, &size) ){ |
+ sqlite3BtreeSetSpillSize(pDb->pBt, size); |
+ } |
+ if( sqlite3GetBoolean(zRight, size!=0) ){ |
+ db->flags |= SQLITE_CacheSpill; |
+ }else{ |
+ db->flags &= ~SQLITE_CacheSpill; |
+ } |
+ setAllPagerFlags(db); |
+ } |
+ break; |
+ } |
+ |
+ /* |
+ ** PRAGMA [schema.]mmap_size(N) |
+ ** |
+ ** Used to set mapping size limit. The mapping size limit is |
+ ** used to limit the aggregate size of all memory mapped regions of the |
+ ** database file. If this parameter is set to zero, then memory mapping |
+ ** is not used at all. If N is negative, then the default memory map |
+ ** limit determined by sqlite3_config(SQLITE_CONFIG_MMAP_SIZE) is set. |
+ ** The parameter N is measured in bytes. |
+ ** |
+ ** This value is advisory. The underlying VFS is free to memory map |
+ ** as little or as much as it wants. Except, if N is set to 0 then the |
+ ** upper layers will never invoke the xFetch interfaces to the VFS. |
+ */ |
+ case PragTyp_MMAP_SIZE: { |
+ sqlite3_int64 sz; |
+#if SQLITE_MAX_MMAP_SIZE>0 |
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
+ if( zRight ){ |
+ int ii; |
+ sqlite3DecOrHexToI64(zRight, &sz); |
+ if( sz<0 ) sz = sqlite3GlobalConfig.szMmap; |
+ if( pId2->n==0 ) db->szMmap = sz; |
+ for(ii=db->nDb-1; ii>=0; ii--){ |
+ if( db->aDb[ii].pBt && (ii==iDb || pId2->n==0) ){ |
+ sqlite3BtreeSetMmapLimit(db->aDb[ii].pBt, sz); |
+ } |
+ } |
+ } |
+ sz = -1; |
+ rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_MMAP_SIZE, &sz); |
+#else |
+ sz = 0; |
+ rc = SQLITE_OK; |
+#endif |
+ if( rc==SQLITE_OK ){ |
+ returnSingleInt(v, sz); |
+ }else if( rc!=SQLITE_NOTFOUND ){ |
+ pParse->nErr++; |
+ pParse->rc = rc; |
+ } |
+ break; |
+ } |
+ |
+ /* |
+ ** 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 |
+ */ |
+ case PragTyp_TEMP_STORE: { |
+ if( !zRight ){ |
+ returnSingleInt(v, db->temp_store); |
+ }else{ |
+ changeTempStorage(pParse, zRight); |
+ } |
+ break; |
+ } |
+ |
+ /* |
+ ** 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. |
+ ** |
+ */ |
+ case PragTyp_TEMP_STORE_DIRECTORY: { |
+ if( !zRight ){ |
+ returnSingleText(v, sqlite3_temp_directory); |
+ }else{ |
+#ifndef SQLITE_OMIT_WSD |
+ if( zRight[0] ){ |
+ int res; |
+ rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res); |
+ if( rc!=SQLITE_OK || 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 = sqlite3_mprintf("%s", zRight); |
+ }else{ |
+ sqlite3_temp_directory = 0; |
+ } |
+#endif /* SQLITE_OMIT_WSD */ |
+ } |
+ break; |
+ } |
+ |
+#if SQLITE_OS_WIN |
+ /* |
+ ** PRAGMA data_store_directory |
+ ** PRAGMA data_store_directory = ""|"directory_name" |
+ ** |
+ ** Return or set the local value of the data_store_directory flag. Changing |
+ ** the value sets a specific directory to be used for database files that |
+ ** were specified with a relative pathname. Setting to a null string reverts |
+ ** to the default database directory, which for database files specified with |
+ ** a relative path will probably be based on the current directory for the |
+ ** process. Database file specified with an absolute path are not impacted |
+ ** by this setting, regardless of its value. |
+ ** |
+ */ |
+ case PragTyp_DATA_STORE_DIRECTORY: { |
+ if( !zRight ){ |
+ returnSingleText(v, sqlite3_data_directory); |
+ }else{ |
+#ifndef SQLITE_OMIT_WSD |
+ if( zRight[0] ){ |
+ int res; |
+ rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res); |
+ if( rc!=SQLITE_OK || res==0 ){ |
+ sqlite3ErrorMsg(pParse, "not a writable directory"); |
+ goto pragma_out; |
+ } |
+ } |
+ sqlite3_free(sqlite3_data_directory); |
+ if( zRight[0] ){ |
+ sqlite3_data_directory = sqlite3_mprintf("%s", zRight); |
+ }else{ |
+ sqlite3_data_directory = 0; |
+ } |
+#endif /* SQLITE_OMIT_WSD */ |
+ } |
+ break; |
+ } |
+#endif |
+ |
+#if SQLITE_ENABLE_LOCKING_STYLE |
+ /* |
+ ** PRAGMA [schema.]lock_proxy_file |
+ ** PRAGMA [schema.]lock_proxy_file = ":auto:"|"lock_file_path" |
+ ** |
+ ** Return or set the value of the lock_proxy_file flag. Changing |
+ ** the value sets a specific file to be used for database access locks. |
+ ** |
+ */ |
+ case PragTyp_LOCK_PROXY_FILE: { |
+ if( !zRight ){ |
+ Pager *pPager = sqlite3BtreePager(pDb->pBt); |
+ char *proxy_file_path = NULL; |
+ sqlite3_file *pFile = sqlite3PagerFile(pPager); |
+ sqlite3OsFileControlHint(pFile, SQLITE_GET_LOCKPROXYFILE, |
+ &proxy_file_path); |
+ returnSingleText(v, proxy_file_path); |
+ }else{ |
+ Pager *pPager = sqlite3BtreePager(pDb->pBt); |
+ sqlite3_file *pFile = sqlite3PagerFile(pPager); |
+ int res; |
+ if( zRight[0] ){ |
+ res=sqlite3OsFileControl(pFile, SQLITE_SET_LOCKPROXYFILE, |
+ zRight); |
+ } else { |
+ res=sqlite3OsFileControl(pFile, SQLITE_SET_LOCKPROXYFILE, |
+ NULL); |
+ } |
+ if( res!=SQLITE_OK ){ |
+ sqlite3ErrorMsg(pParse, "failed to set lock proxy file"); |
+ goto pragma_out; |
+ } |
+ } |
+ break; |
+ } |
+#endif /* SQLITE_ENABLE_LOCKING_STYLE */ |
+ |
+ /* |
+ ** PRAGMA [schema.]synchronous |
+ ** PRAGMA [schema.]synchronous=OFF|ON|NORMAL|FULL|EXTRA |
+ ** |
+ ** 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. |
+ */ |
+ case PragTyp_SYNCHRONOUS: { |
+ if( !zRight ){ |
+ returnSingleInt(v, pDb->safety_level-1); |
+ }else{ |
+ if( !db->autoCommit ){ |
+ sqlite3ErrorMsg(pParse, |
+ "Safety level may not be changed inside a transaction"); |
+ }else{ |
+ int iLevel = (getSafetyLevel(zRight,0,1)+1) & PAGER_SYNCHRONOUS_MASK; |
+ if( iLevel==0 ) iLevel = 1; |
+ pDb->safety_level = iLevel; |
+ pDb->bSyncSet = 1; |
+ setAllPagerFlags(db); |
+ } |
+ } |
+ break; |
+ } |
+#endif /* SQLITE_OMIT_PAGER_PRAGMAS */ |
+ |
+#ifndef SQLITE_OMIT_FLAG_PRAGMAS |
+ case PragTyp_FLAG: { |
+ if( zRight==0 ){ |
+ setPragmaResultColumnNames(v, pPragma); |
+ returnSingleInt(v, (db->flags & pPragma->iArg)!=0 ); |
+ }else{ |
+ int mask = pPragma->iArg; /* Mask of bits to set or clear. */ |
+ if( db->autoCommit==0 ){ |
+ /* Foreign key support may not be enabled or disabled while not |
+ ** in auto-commit mode. */ |
+ mask &= ~(SQLITE_ForeignKeys); |
+ } |
+#if SQLITE_USER_AUTHENTICATION |
+ if( db->auth.authLevel==UAUTH_User ){ |
+ /* Do not allow non-admin users to modify the schema arbitrarily */ |
+ mask &= ~(SQLITE_WriteSchema); |
+ } |
+#endif |
+ |
+ if( sqlite3GetBoolean(zRight, 0) ){ |
+ db->flags |= mask; |
+ }else{ |
+ db->flags &= ~mask; |
+ if( mask==SQLITE_DeferFKs ) db->nDeferredImmCons = 0; |
+ } |
+ |
+ /* 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. |
+ */ |
+ sqlite3VdbeAddOp0(v, OP_Expire); |
+ setAllPagerFlags(db); |
+ } |
+ break; |
+ } |
+#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. |
+ */ |
+ case PragTyp_TABLE_INFO: if( zRight ){ |
+ Table *pTab; |
+ pTab = sqlite3LocateTable(pParse, LOCATE_NOERR, zRight, zDb); |
+ if( pTab ){ |
+ int i, k; |
+ int nHidden = 0; |
+ Column *pCol; |
+ Index *pPk = sqlite3PrimaryKeyIndex(pTab); |
+ pParse->nMem = 6; |
+ sqlite3CodeVerifySchema(pParse, iDb); |
+ sqlite3ViewGetColumnNames(pParse, pTab); |
+ for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){ |
+ if( IsHiddenColumn(pCol) ){ |
+ nHidden++; |
+ continue; |
+ } |
+ if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){ |
+ k = 0; |
+ }else if( pPk==0 ){ |
+ k = 1; |
+ }else{ |
+ for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){} |
+ } |
+ assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN ); |
+ sqlite3VdbeMultiLoad(v, 1, "issisi", |
+ i-nHidden, |
+ pCol->zName, |
+ sqlite3ColumnType(pCol,""), |
+ pCol->notNull ? 1 : 0, |
+ pCol->pDflt ? pCol->pDflt->u.zToken : 0, |
+ k); |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); |
+ } |
+ } |
+ } |
+ break; |
+ |
+ case PragTyp_STATS: { |
+ Index *pIdx; |
+ HashElem *i; |
+ pParse->nMem = 4; |
+ sqlite3CodeVerifySchema(pParse, iDb); |
+ for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){ |
+ Table *pTab = sqliteHashData(i); |
+ sqlite3VdbeMultiLoad(v, 1, "ssii", |
+ pTab->zName, |
+ 0, |
+ pTab->szTabRow, |
+ pTab->nRowLogEst); |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); |
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
+ sqlite3VdbeMultiLoad(v, 2, "sii", |
+ pIdx->zName, |
+ pIdx->szIdxRow, |
+ pIdx->aiRowLogEst[0]); |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); |
+ } |
+ } |
+ } |
+ break; |
+ |
+ case PragTyp_INDEX_INFO: if( zRight ){ |
+ Index *pIdx; |
+ Table *pTab; |
+ pIdx = sqlite3FindIndex(db, zRight, zDb); |
+ if( pIdx ){ |
+ int i; |
+ int mx; |
+ if( pPragma->iArg ){ |
+ /* PRAGMA index_xinfo (newer version with more rows and columns) */ |
+ mx = pIdx->nColumn; |
+ pParse->nMem = 6; |
+ }else{ |
+ /* PRAGMA index_info (legacy version) */ |
+ mx = pIdx->nKeyCol; |
+ pParse->nMem = 3; |
+ } |
+ pTab = pIdx->pTable; |
+ sqlite3CodeVerifySchema(pParse, iDb); |
+ assert( pParse->nMem<=pPragma->nPragCName ); |
+ for(i=0; i<mx; i++){ |
+ i16 cnum = pIdx->aiColumn[i]; |
+ sqlite3VdbeMultiLoad(v, 1, "iis", i, cnum, |
+ cnum<0 ? 0 : pTab->aCol[cnum].zName); |
+ if( pPragma->iArg ){ |
+ sqlite3VdbeMultiLoad(v, 4, "isi", |
+ pIdx->aSortOrder[i], |
+ pIdx->azColl[i], |
+ i<pIdx->nKeyCol); |
+ } |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, pParse->nMem); |
+ } |
+ } |
+ } |
+ break; |
+ |
+ case PragTyp_INDEX_LIST: if( zRight ){ |
+ Index *pIdx; |
+ Table *pTab; |
+ int i; |
+ pTab = sqlite3FindTable(db, zRight, zDb); |
+ if( pTab ){ |
+ pParse->nMem = 5; |
+ sqlite3CodeVerifySchema(pParse, iDb); |
+ for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){ |
+ const char *azOrigin[] = { "c", "u", "pk" }; |
+ sqlite3VdbeMultiLoad(v, 1, "isisi", |
+ i, |
+ pIdx->zName, |
+ IsUniqueIndex(pIdx), |
+ azOrigin[pIdx->idxType], |
+ pIdx->pPartIdxWhere!=0); |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5); |
+ } |
+ } |
+ } |
+ break; |
+ |
+ case PragTyp_DATABASE_LIST: { |
+ int i; |
+ pParse->nMem = 3; |
+ for(i=0; i<db->nDb; i++){ |
+ if( db->aDb[i].pBt==0 ) continue; |
+ assert( db->aDb[i].zDbSName!=0 ); |
+ sqlite3VdbeMultiLoad(v, 1, "iss", |
+ i, |
+ db->aDb[i].zDbSName, |
+ sqlite3BtreeGetFilename(db->aDb[i].pBt)); |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); |
+ } |
+ } |
+ break; |
+ |
+ case PragTyp_COLLATION_LIST: { |
+ int i = 0; |
+ HashElem *p; |
+ pParse->nMem = 2; |
+ for(p=sqliteHashFirst(&db->aCollSeq); p; p=sqliteHashNext(p)){ |
+ CollSeq *pColl = (CollSeq *)sqliteHashData(p); |
+ sqlite3VdbeMultiLoad(v, 1, "is", i++, pColl->zName); |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2); |
+ } |
+ } |
+ break; |
+#endif /* SQLITE_OMIT_SCHEMA_PRAGMAS */ |
+ |
+#ifndef SQLITE_OMIT_FOREIGN_KEY |
+ case PragTyp_FOREIGN_KEY_LIST: if( zRight ){ |
+ FKey *pFK; |
+ Table *pTab; |
+ pTab = sqlite3FindTable(db, zRight, zDb); |
+ if( pTab ){ |
+ pFK = pTab->pFKey; |
+ if( pFK ){ |
+ int i = 0; |
+ pParse->nMem = 8; |
+ sqlite3CodeVerifySchema(pParse, iDb); |
+ while(pFK){ |
+ int j; |
+ for(j=0; j<pFK->nCol; j++){ |
+ sqlite3VdbeMultiLoad(v, 1, "iissssss", |
+ i, |
+ j, |
+ pFK->zTo, |
+ pTab->aCol[pFK->aCol[j].iFrom].zName, |
+ pFK->aCol[j].zCol, |
+ actionName(pFK->aAction[1]), /* ON UPDATE */ |
+ actionName(pFK->aAction[0]), /* ON DELETE */ |
+ "NONE"); |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 8); |
+ } |
+ ++i; |
+ pFK = pFK->pNextFrom; |
+ } |
+ } |
+ } |
+ } |
+ break; |
+#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ |
+ |
+#ifndef SQLITE_OMIT_FOREIGN_KEY |
+#ifndef SQLITE_OMIT_TRIGGER |
+ case PragTyp_FOREIGN_KEY_CHECK: { |
+ FKey *pFK; /* A foreign key constraint */ |
+ Table *pTab; /* Child table contain "REFERENCES" keyword */ |
+ Table *pParent; /* Parent table that child points to */ |
+ Index *pIdx; /* Index in the parent table */ |
+ int i; /* Loop counter: Foreign key number for pTab */ |
+ int j; /* Loop counter: Field of the foreign key */ |
+ HashElem *k; /* Loop counter: Next table in schema */ |
+ int x; /* result variable */ |
+ int regResult; /* 3 registers to hold a result row */ |
+ int regKey; /* Register to hold key for checking the FK */ |
+ int regRow; /* Registers to hold a row from pTab */ |
+ int addrTop; /* Top of a loop checking foreign keys */ |
+ int addrOk; /* Jump here if the key is OK */ |
+ int *aiCols; /* child to parent column mapping */ |
+ |
+ regResult = pParse->nMem+1; |
+ pParse->nMem += 4; |
+ regKey = ++pParse->nMem; |
+ regRow = ++pParse->nMem; |
+ sqlite3CodeVerifySchema(pParse, iDb); |
+ k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash); |
+ while( k ){ |
+ if( zRight ){ |
+ pTab = sqlite3LocateTable(pParse, 0, zRight, zDb); |
+ k = 0; |
+ }else{ |
+ pTab = (Table*)sqliteHashData(k); |
+ k = sqliteHashNext(k); |
+ } |
+ if( pTab==0 || pTab->pFKey==0 ) continue; |
+ sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); |
+ if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow; |
+ sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead); |
+ sqlite3VdbeLoadString(v, regResult, pTab->zName); |
+ for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ |
+ pParent = sqlite3FindTable(db, pFK->zTo, zDb); |
+ if( pParent==0 ) continue; |
+ pIdx = 0; |
+ sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName); |
+ x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0); |
+ if( x==0 ){ |
+ if( pIdx==0 ){ |
+ sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead); |
+ }else{ |
+ sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb); |
+ sqlite3VdbeSetP4KeyInfo(pParse, pIdx); |
+ } |
+ }else{ |
+ k = 0; |
+ break; |
+ } |
+ } |
+ assert( pParse->nErr>0 || pFK==0 ); |
+ if( pFK ) break; |
+ if( pParse->nTab<i ) pParse->nTab = i; |
+ addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); VdbeCoverage(v); |
+ for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ |
+ pParent = sqlite3FindTable(db, pFK->zTo, zDb); |
+ pIdx = 0; |
+ aiCols = 0; |
+ if( pParent ){ |
+ x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols); |
+ assert( x==0 ); |
+ } |
+ addrOk = sqlite3VdbeMakeLabel(v); |
+ if( pParent && pIdx==0 ){ |
+ int iKey = pFK->aCol[0].iFrom; |
+ assert( iKey>=0 && iKey<pTab->nCol ); |
+ if( iKey!=pTab->iPKey ){ |
+ sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow); |
+ sqlite3ColumnDefault(v, pTab, iKey, regRow); |
+ sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk); VdbeCoverage(v); |
+ }else{ |
+ sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow); |
+ } |
+ sqlite3VdbeAddOp3(v, OP_SeekRowid, i, 0, regRow); VdbeCoverage(v); |
+ sqlite3VdbeGoto(v, addrOk); |
+ sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); |
+ }else{ |
+ for(j=0; j<pFK->nCol; j++){ |
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, |
+ aiCols ? aiCols[j] : pFK->aCol[j].iFrom, regRow+j); |
+ sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); VdbeCoverage(v); |
+ } |
+ if( pParent ){ |
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey, |
+ sqlite3IndexAffinityStr(db,pIdx), pFK->nCol); |
+ sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0); |
+ VdbeCoverage(v); |
+ } |
+ } |
+ sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1); |
+ sqlite3VdbeMultiLoad(v, regResult+2, "si", pFK->zTo, i-1); |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4); |
+ sqlite3VdbeResolveLabel(v, addrOk); |
+ sqlite3DbFree(db, aiCols); |
+ } |
+ sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1); VdbeCoverage(v); |
+ sqlite3VdbeJumpHere(v, addrTop); |
+ } |
+ } |
+ break; |
+#endif /* !defined(SQLITE_OMIT_TRIGGER) */ |
+#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ |
+ |
+#ifndef NDEBUG |
+ case PragTyp_PARSER_TRACE: { |
+ if( zRight ){ |
+ if( sqlite3GetBoolean(zRight, 0) ){ |
+ sqlite3ParserTrace(stdout, "parser: "); |
+ }else{ |
+ sqlite3ParserTrace(0, 0); |
+ } |
+ } |
+ } |
+ break; |
+#endif |
+ |
+ /* Reinstall the LIKE and GLOB functions. The variant of LIKE |
+ ** used will be case sensitive or not depending on the RHS. |
+ */ |
+ case PragTyp_CASE_SENSITIVE_LIKE: { |
+ if( zRight ){ |
+ sqlite3RegisterLikeFunctions(db, sqlite3GetBoolean(zRight, 0)); |
+ } |
+ } |
+ break; |
+ |
+#ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX |
+# define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100 |
+#endif |
+ |
+#ifndef SQLITE_OMIT_INTEGRITY_CHECK |
+ /* Pragma "quick_check" is reduced version of |
+ ** integrity_check designed to detect most database corruption |
+ ** without most of the overhead of a full integrity-check. |
+ */ |
+ case PragTyp_INTEGRITY_CHECK: { |
+ int i, j, addr, mxErr; |
+ |
+ int isQuick = (sqlite3Tolower(zLeft[0])=='q'); |
+ |
+ /* If the PRAGMA command was of the form "PRAGMA <db>.integrity_check", |
+ ** then iDb is set to the index of the database identified by <db>. |
+ ** In this case, the integrity of database iDb only is verified by |
+ ** the VDBE created below. |
+ ** |
+ ** Otherwise, if the command was simply "PRAGMA integrity_check" (or |
+ ** "PRAGMA quick_check"), then iDb is set to 0. In this case, set iDb |
+ ** to -1 here, to indicate that the VDBE should verify the integrity |
+ ** of all attached databases. */ |
+ assert( iDb>=0 ); |
+ assert( iDb==0 || pId2->z ); |
+ if( pId2->z==0 ) iDb = -1; |
+ |
+ /* Initialize the VDBE program */ |
+ pParse->nMem = 6; |
+ |
+ /* Set the maximum error count */ |
+ mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; |
+ if( zRight ){ |
+ sqlite3GetInt32(zRight, &mxErr); |
+ 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 *aRoot; |
+ int cnt = 0; |
+ int mxIdx = 0; |
+ int nIdx; |
+ |
+ if( OMIT_TEMPDB && i==1 ) continue; |
+ if( iDb>=0 && i!=iDb ) continue; |
+ |
+ sqlite3CodeVerifySchema(pParse, i); |
+ addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Halt if out of errors */ |
+ VdbeCoverage(v); |
+ sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); |
+ sqlite3VdbeJumpHere(v, addr); |
+ |
+ /* Do an integrity check of the B-Tree |
+ ** |
+ ** Begin by finding the root pages numbers |
+ ** for all tables and indices in the database. |
+ */ |
+ assert( sqlite3SchemaMutexHeld(db, i, 0) ); |
+ pTbls = &db->aDb[i].pSchema->tblHash; |
+ for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ |
+ Table *pTab = sqliteHashData(x); |
+ Index *pIdx; |
+ if( HasRowid(pTab) ) cnt++; |
+ for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ cnt++; } |
+ if( nIdx>mxIdx ) mxIdx = nIdx; |
+ } |
+ aRoot = sqlite3DbMallocRawNN(db, sizeof(int)*(cnt+1)); |
+ if( aRoot==0 ) break; |
+ for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ |
+ Table *pTab = sqliteHashData(x); |
+ Index *pIdx; |
+ if( HasRowid(pTab) ) aRoot[cnt++] = pTab->tnum; |
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
+ aRoot[cnt++] = pIdx->tnum; |
+ } |
+ } |
+ aRoot[cnt] = 0; |
+ |
+ /* Make sure sufficient number of registers have been allocated */ |
+ pParse->nMem = MAX( pParse->nMem, 8+mxIdx ); |
+ |
+ /* Do the b-tree integrity checks */ |
+ sqlite3VdbeAddOp4(v, OP_IntegrityCk, 2, cnt, 1, (char*)aRoot,P4_INTARRAY); |
+ sqlite3VdbeChangeP5(v, (u8)i); |
+ addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); VdbeCoverage(v); |
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, |
+ sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zDbSName), |
+ 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, *pPk; |
+ Index *pPrior = 0; |
+ int loopTop; |
+ int iDataCur, iIdxCur; |
+ int r1 = -1; |
+ |
+ if( pTab->pIndex==0 ) continue; |
+ pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); |
+ addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Stop if out of errors */ |
+ VdbeCoverage(v); |
+ sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); |
+ sqlite3VdbeJumpHere(v, addr); |
+ sqlite3ExprCacheClear(pParse); |
+ sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0, |
+ 1, 0, &iDataCur, &iIdxCur); |
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, 7); |
+ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ |
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */ |
+ } |
+ assert( pParse->nMem>=8+j ); |
+ assert( sqlite3NoTempsInRange(pParse,1,7+j) ); |
+ sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v); |
+ loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1); |
+ /* Verify that all NOT NULL columns really are NOT NULL */ |
+ for(j=0; j<pTab->nCol; j++){ |
+ char *zErr; |
+ int jmp2, jmp3; |
+ if( j==pTab->iPKey ) continue; |
+ if( pTab->aCol[j].notNull==0 ) continue; |
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3); |
+ sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG); |
+ jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v); |
+ sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */ |
+ zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName, |
+ pTab->aCol[j].zName); |
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1); |
+ jmp3 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v); |
+ sqlite3VdbeAddOp0(v, OP_Halt); |
+ sqlite3VdbeJumpHere(v, jmp2); |
+ sqlite3VdbeJumpHere(v, jmp3); |
+ } |
+ /* Validate index entries for the current row */ |
+ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ |
+ int jmp2, jmp3, jmp4, jmp5; |
+ int ckUniq = sqlite3VdbeMakeLabel(v); |
+ if( pPk==pIdx ) continue; |
+ r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3, |
+ pPrior, r1); |
+ pPrior = pIdx; |
+ sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1); /* increment entry count */ |
+ /* Verify that an index entry exists for the current table row */ |
+ jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1, |
+ pIdx->nColumn); VdbeCoverage(v); |
+ sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */ |
+ sqlite3VdbeLoadString(v, 3, "row "); |
+ sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3); |
+ sqlite3VdbeLoadString(v, 4, " missing from index "); |
+ sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); |
+ jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName); |
+ sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1); |
+ jmp4 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v); |
+ sqlite3VdbeAddOp0(v, OP_Halt); |
+ sqlite3VdbeJumpHere(v, jmp2); |
+ /* For UNIQUE indexes, verify that only one entry exists with the |
+ ** current key. The entry is unique if (1) any column is NULL |
+ ** or (2) the next entry has a different key */ |
+ if( IsUniqueIndex(pIdx) ){ |
+ int uniqOk = sqlite3VdbeMakeLabel(v); |
+ int jmp6; |
+ int kk; |
+ for(kk=0; kk<pIdx->nKeyCol; kk++){ |
+ int iCol = pIdx->aiColumn[kk]; |
+ assert( iCol!=XN_ROWID && iCol<pTab->nCol ); |
+ if( iCol>=0 && pTab->aCol[iCol].notNull ) continue; |
+ sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk); |
+ VdbeCoverage(v); |
+ } |
+ jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v); |
+ sqlite3VdbeGoto(v, uniqOk); |
+ sqlite3VdbeJumpHere(v, jmp6); |
+ sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1, |
+ pIdx->nKeyCol); VdbeCoverage(v); |
+ sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */ |
+ sqlite3VdbeLoadString(v, 3, "non-unique entry in index "); |
+ sqlite3VdbeGoto(v, jmp5); |
+ sqlite3VdbeResolveLabel(v, uniqOk); |
+ } |
+ sqlite3VdbeJumpHere(v, jmp4); |
+ sqlite3ResolvePartIdxLabel(pParse, jmp3); |
+ } |
+ sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v); |
+ sqlite3VdbeJumpHere(v, loopTop-1); |
+#ifndef SQLITE_OMIT_BTREECOUNT |
+ sqlite3VdbeLoadString(v, 2, "wrong # of entries in index "); |
+ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ |
+ if( pPk==pIdx ) continue; |
+ addr = sqlite3VdbeCurrentAddr(v); |
+ sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr+2); VdbeCoverage(v); |
+ sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); |
+ sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3); |
+ sqlite3VdbeAddOp3(v, OP_Eq, 8+j, addr+8, 3); VdbeCoverage(v); |
+ sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); |
+ sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); |
+ sqlite3VdbeLoadString(v, 3, pIdx->zName); |
+ sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7); |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 7, 1); |
+ } |
+#endif /* SQLITE_OMIT_BTREECOUNT */ |
+ } |
+ } |
+ { |
+ static const int iLn = VDBE_OFFSET_LINENO(2); |
+ static const VdbeOpList endCode[] = { |
+ { OP_AddImm, 1, 0, 0}, /* 0 */ |
+ { OP_If, 1, 4, 0}, /* 1 */ |
+ { OP_String8, 0, 3, 0}, /* 2 */ |
+ { OP_ResultRow, 3, 1, 0}, /* 3 */ |
+ }; |
+ VdbeOp *aOp; |
+ |
+ aOp = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn); |
+ if( aOp ){ |
+ aOp[0].p2 = -mxErr; |
+ aOp[2].p4type = P4_STATIC; |
+ aOp[2].p4.z = "ok"; |
+ } |
+ } |
+ } |
+ break; |
+#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 |
+ */ |
+ case PragTyp_ENCODING: { |
+ static const struct EncName { |
+ char *zName; |
+ u8 enc; |
+ } encnames[] = { |
+ { "UTF8", SQLITE_UTF8 }, |
+ { "UTF-8", SQLITE_UTF8 }, /* Must be element [1] */ |
+ { "UTF-16le", SQLITE_UTF16LE }, /* Must be element [2] */ |
+ { "UTF-16be", SQLITE_UTF16BE }, /* Must be element [3] */ |
+ { "UTF16le", SQLITE_UTF16LE }, |
+ { "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; |
+ assert( encnames[SQLITE_UTF8].enc==SQLITE_UTF8 ); |
+ assert( encnames[SQLITE_UTF16LE].enc==SQLITE_UTF16LE ); |
+ assert( encnames[SQLITE_UTF16BE].enc==SQLITE_UTF16BE ); |
+ returnSingleText(v, encnames[ENC(pParse->db)].zName); |
+ }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) ){ |
+ SCHEMA_ENC(db) = ENC(db) = |
+ pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE; |
+ break; |
+ } |
+ } |
+ if( !pEnc->zName ){ |
+ sqlite3ErrorMsg(pParse, "unsupported encoding: %s", zRight); |
+ } |
+ } |
+ } |
+ } |
+ break; |
+#endif /* SQLITE_OMIT_UTF16 */ |
+ |
+#ifndef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS |
+ /* |
+ ** PRAGMA [schema.]schema_version |
+ ** PRAGMA [schema.]schema_version = <integer> |
+ ** |
+ ** PRAGMA [schema.]user_version |
+ ** PRAGMA [schema.]user_version = <integer> |
+ ** |
+ ** PRAGMA [schema.]freelist_count |
+ ** |
+ ** PRAGMA [schema.]data_version |
+ ** |
+ ** PRAGMA [schema.]application_id |
+ ** PRAGMA [schema.]application_id = <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. |
+ */ |
+ case PragTyp_HEADER_VALUE: { |
+ int iCookie = pPragma->iArg; /* Which cookie to read or write */ |
+ sqlite3VdbeUsesBtree(v, iDb); |
+ if( zRight && (pPragma->mPragFlg & PragFlg_ReadOnly)==0 ){ |
+ /* Write the specified cookie value */ |
+ static const VdbeOpList setCookie[] = { |
+ { OP_Transaction, 0, 1, 0}, /* 0 */ |
+ { OP_SetCookie, 0, 0, 0}, /* 1 */ |
+ }; |
+ VdbeOp *aOp; |
+ sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(setCookie)); |
+ aOp = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie, 0); |
+ if( ONLY_IF_REALLOC_STRESS(aOp==0) ) break; |
+ aOp[0].p1 = iDb; |
+ aOp[1].p1 = iDb; |
+ aOp[1].p2 = iCookie; |
+ aOp[1].p3 = sqlite3Atoi(zRight); |
+ }else{ |
+ /* Read the specified cookie value */ |
+ static const VdbeOpList readCookie[] = { |
+ { OP_Transaction, 0, 0, 0}, /* 0 */ |
+ { OP_ReadCookie, 0, 1, 0}, /* 1 */ |
+ { OP_ResultRow, 1, 1, 0} |
+ }; |
+ VdbeOp *aOp; |
+ sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(readCookie)); |
+ aOp = sqlite3VdbeAddOpList(v, ArraySize(readCookie),readCookie,0); |
+ if( ONLY_IF_REALLOC_STRESS(aOp==0) ) break; |
+ aOp[0].p1 = iDb; |
+ aOp[1].p1 = iDb; |
+ aOp[1].p3 = iCookie; |
+ sqlite3VdbeReusable(v); |
+ } |
+ } |
+ break; |
+#endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */ |
+ |
+#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS |
+ /* |
+ ** PRAGMA compile_options |
+ ** |
+ ** Return the names of all compile-time options used in this build, |
+ ** one option per row. |
+ */ |
+ case PragTyp_COMPILE_OPTIONS: { |
+ int i = 0; |
+ const char *zOpt; |
+ pParse->nMem = 1; |
+ while( (zOpt = sqlite3_compileoption_get(i++))!=0 ){ |
+ sqlite3VdbeLoadString(v, 1, zOpt); |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); |
+ } |
+ sqlite3VdbeReusable(v); |
+ } |
+ break; |
+#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
+ |
+#ifndef SQLITE_OMIT_WAL |
+ /* |
+ ** PRAGMA [schema.]wal_checkpoint = passive|full|restart|truncate |
+ ** |
+ ** Checkpoint the database. |
+ */ |
+ case PragTyp_WAL_CHECKPOINT: { |
+ int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED); |
+ int eMode = SQLITE_CHECKPOINT_PASSIVE; |
+ if( zRight ){ |
+ if( sqlite3StrICmp(zRight, "full")==0 ){ |
+ eMode = SQLITE_CHECKPOINT_FULL; |
+ }else if( sqlite3StrICmp(zRight, "restart")==0 ){ |
+ eMode = SQLITE_CHECKPOINT_RESTART; |
+ }else if( sqlite3StrICmp(zRight, "truncate")==0 ){ |
+ eMode = SQLITE_CHECKPOINT_TRUNCATE; |
+ } |
+ } |
+ pParse->nMem = 3; |
+ sqlite3VdbeAddOp3(v, OP_Checkpoint, iBt, eMode, 1); |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); |
+ } |
+ break; |
+ |
+ /* |
+ ** PRAGMA wal_autocheckpoint |
+ ** PRAGMA wal_autocheckpoint = N |
+ ** |
+ ** Configure a database connection to automatically checkpoint a database |
+ ** after accumulating N frames in the log. Or query for the current value |
+ ** of N. |
+ */ |
+ case PragTyp_WAL_AUTOCHECKPOINT: { |
+ if( zRight ){ |
+ sqlite3_wal_autocheckpoint(db, sqlite3Atoi(zRight)); |
+ } |
+ returnSingleInt(v, |
+ db->xWalCallback==sqlite3WalDefaultHook ? |
+ SQLITE_PTR_TO_INT(db->pWalArg) : 0); |
+ } |
+ break; |
+#endif |
+ |
+ /* |
+ ** PRAGMA shrink_memory |
+ ** |
+ ** IMPLEMENTATION-OF: R-23445-46109 This pragma causes the database |
+ ** connection on which it is invoked to free up as much memory as it |
+ ** can, by calling sqlite3_db_release_memory(). |
+ */ |
+ case PragTyp_SHRINK_MEMORY: { |
+ sqlite3_db_release_memory(db); |
+ break; |
+ } |
+ |
+ /* |
+ ** PRAGMA busy_timeout |
+ ** PRAGMA busy_timeout = N |
+ ** |
+ ** Call sqlite3_busy_timeout(db, N). Return the current timeout value |
+ ** if one is set. If no busy handler or a different busy handler is set |
+ ** then 0 is returned. Setting the busy_timeout to 0 or negative |
+ ** disables the timeout. |
+ */ |
+ /*case PragTyp_BUSY_TIMEOUT*/ default: { |
+ assert( pPragma->ePragTyp==PragTyp_BUSY_TIMEOUT ); |
+ if( zRight ){ |
+ sqlite3_busy_timeout(db, sqlite3Atoi(zRight)); |
+ } |
+ returnSingleInt(v, db->busyTimeout); |
+ break; |
+ } |
+ |
+ /* |
+ ** PRAGMA soft_heap_limit |
+ ** PRAGMA soft_heap_limit = N |
+ ** |
+ ** IMPLEMENTATION-OF: R-26343-45930 This pragma invokes the |
+ ** sqlite3_soft_heap_limit64() interface with the argument N, if N is |
+ ** specified and is a non-negative integer. |
+ ** IMPLEMENTATION-OF: R-64451-07163 The soft_heap_limit pragma always |
+ ** returns the same integer that would be returned by the |
+ ** sqlite3_soft_heap_limit64(-1) C-language function. |
+ */ |
+ case PragTyp_SOFT_HEAP_LIMIT: { |
+ sqlite3_int64 N; |
+ if( zRight && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK ){ |
+ sqlite3_soft_heap_limit64(N); |
+ } |
+ returnSingleInt(v, sqlite3_soft_heap_limit64(-1)); |
+ break; |
+ } |
+ |
+ /* |
+ ** PRAGMA threads |
+ ** PRAGMA threads = N |
+ ** |
+ ** Configure the maximum number of worker threads. Return the new |
+ ** maximum, which might be less than requested. |
+ */ |
+ case PragTyp_THREADS: { |
+ sqlite3_int64 N; |
+ if( zRight |
+ && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK |
+ && N>=0 |
+ ){ |
+ sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, (int)(N&0x7fffffff)); |
+ } |
+ returnSingleInt(v, sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, -1)); |
+ break; |
+ } |
+ |
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) |
+ /* |
+ ** Report the current state of file logs for all databases |
+ */ |
+ case PragTyp_LOCK_STATUS: { |
+ static const char *const azLockName[] = { |
+ "unlocked", "shared", "reserved", "pending", "exclusive" |
+ }; |
+ int i; |
+ pParse->nMem = 2; |
+ for(i=0; i<db->nDb; i++){ |
+ Btree *pBt; |
+ const char *zState = "unknown"; |
+ int j; |
+ if( db->aDb[i].zDbSName==0 ) continue; |
+ pBt = db->aDb[i].pBt; |
+ if( pBt==0 || sqlite3BtreePager(pBt)==0 ){ |
+ zState = "closed"; |
+ }else if( sqlite3_file_control(db, i ? db->aDb[i].zDbSName : 0, |
+ SQLITE_FCNTL_LOCKSTATE, &j)==SQLITE_OK ){ |
+ zState = azLockName[j]; |
+ } |
+ sqlite3VdbeMultiLoad(v, 1, "ss", db->aDb[i].zDbSName, zState); |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2); |
+ } |
+ break; |
+ } |
+#endif |
+ |
+#ifdef SQLITE_HAS_CODEC |
+ case PragTyp_KEY: { |
+ if( zRight ) sqlite3_key_v2(db, zDb, zRight, sqlite3Strlen30(zRight)); |
+ break; |
+ } |
+ case PragTyp_REKEY: { |
+ if( zRight ) sqlite3_rekey_v2(db, zDb, zRight, sqlite3Strlen30(zRight)); |
+ break; |
+ } |
+ case PragTyp_HEXKEY: { |
+ if( zRight ){ |
+ u8 iByte; |
+ int i; |
+ char zKey[40]; |
+ for(i=0, iByte=0; i<sizeof(zKey)*2 && sqlite3Isxdigit(zRight[i]); i++){ |
+ iByte = (iByte<<4) + sqlite3HexToInt(zRight[i]); |
+ if( (i&1)!=0 ) zKey[i/2] = iByte; |
+ } |
+ if( (zLeft[3] & 0xf)==0xb ){ |
+ sqlite3_key_v2(db, zDb, zKey, i/2); |
+ }else{ |
+ sqlite3_rekey_v2(db, zDb, zKey, i/2); |
+ } |
+ } |
+ break; |
+ } |
+#endif |
+#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD) |
+ case PragTyp_ACTIVATE_EXTENSIONS: if( zRight ){ |
+#ifdef SQLITE_HAS_CODEC |
+ if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){ |
+ sqlite3_activate_see(&zRight[4]); |
+ } |
+#endif |
+#ifdef SQLITE_ENABLE_CEROD |
+ if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){ |
+ sqlite3_activate_cerod(&zRight[6]); |
+ } |
+#endif |
+ } |
+ break; |
+#endif |
+ |
+ } /* End of the PRAGMA switch */ |
+ |
+ /* The following block is a no-op unless SQLITE_DEBUG is defined. Its only |
+ ** purpose is to execute assert() statements to verify that if the |
+ ** PragFlg_NoColumns1 flag is set and the caller specified an argument |
+ ** to the PRAGMA, the implementation has not added any OP_ResultRow |
+ ** instructions to the VM. */ |
+ if( (pPragma->mPragFlg & PragFlg_NoColumns1) && zRight ){ |
+ sqlite3VdbeVerifyNoResultRow(v); |
+ } |
+ |
+pragma_out: |
+ sqlite3DbFree(db, zLeft); |
+ sqlite3DbFree(db, zRight); |
+} |
+#ifndef SQLITE_OMIT_VIRTUALTABLE |
+/***************************************************************************** |
+** Implementation of an eponymous virtual table that runs a pragma. |
+** |
+*/ |
+typedef struct PragmaVtab PragmaVtab; |
+typedef struct PragmaVtabCursor PragmaVtabCursor; |
+struct PragmaVtab { |
+ sqlite3_vtab base; /* Base class. Must be first */ |
+ sqlite3 *db; /* The database connection to which it belongs */ |
+ const PragmaName *pName; /* Name of the pragma */ |
+ u8 nHidden; /* Number of hidden columns */ |
+ u8 iHidden; /* Index of the first hidden column */ |
+}; |
+struct PragmaVtabCursor { |
+ sqlite3_vtab_cursor base; /* Base class. Must be first */ |
+ sqlite3_stmt *pPragma; /* The pragma statement to run */ |
+ sqlite_int64 iRowid; /* Current rowid */ |
+ char *azArg[2]; /* Value of the argument and schema */ |
+}; |
+ |
+/* |
+** Pragma virtual table module xConnect method. |
+*/ |
+static int pragmaVtabConnect( |
+ sqlite3 *db, |
+ void *pAux, |
+ int argc, const char *const*argv, |
+ sqlite3_vtab **ppVtab, |
+ char **pzErr |
+){ |
+ const PragmaName *pPragma = (const PragmaName*)pAux; |
+ PragmaVtab *pTab = 0; |
+ int rc; |
+ int i, j; |
+ char cSep = '('; |
+ StrAccum acc; |
+ char zBuf[200]; |
+ |
+ UNUSED_PARAMETER(argc); |
+ UNUSED_PARAMETER(argv); |
+ sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); |
+ sqlite3StrAccumAppendAll(&acc, "CREATE TABLE x"); |
+ for(i=0, j=pPragma->iPragCName; i<pPragma->nPragCName; i++, j++){ |
+ sqlite3XPrintf(&acc, "%c\"%s\"", cSep, pragCName[j]); |
+ cSep = ','; |
+ } |
+ if( i==0 ){ |
+ sqlite3XPrintf(&acc, "(\"%s\"", pPragma->zName); |
+ cSep = ','; |
+ i++; |
+ } |
+ j = 0; |
+ if( pPragma->mPragFlg & PragFlg_Result1 ){ |
+ sqlite3StrAccumAppendAll(&acc, ",arg HIDDEN"); |
+ j++; |
+ } |
+ if( pPragma->mPragFlg & (PragFlg_SchemaOpt|PragFlg_SchemaReq) ){ |
+ sqlite3StrAccumAppendAll(&acc, ",schema HIDDEN"); |
+ j++; |
+ } |
+ sqlite3StrAccumAppend(&acc, ")", 1); |
+ sqlite3StrAccumFinish(&acc); |
+ assert( strlen(zBuf) < sizeof(zBuf)-1 ); |
+ rc = sqlite3_declare_vtab(db, zBuf); |
+ if( rc==SQLITE_OK ){ |
+ pTab = (PragmaVtab*)sqlite3_malloc(sizeof(PragmaVtab)); |
+ if( pTab==0 ){ |
+ rc = SQLITE_NOMEM; |
+ }else{ |
+ memset(pTab, 0, sizeof(PragmaVtab)); |
+ pTab->pName = pPragma; |
+ pTab->db = db; |
+ pTab->iHidden = i; |
+ pTab->nHidden = j; |
+ } |
+ }else{ |
+ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); |
+ } |
+ |
+ *ppVtab = (sqlite3_vtab*)pTab; |
+ return rc; |
+} |
+ |
+/* |
+** Pragma virtual table module xDisconnect method. |
+*/ |
+static int pragmaVtabDisconnect(sqlite3_vtab *pVtab){ |
+ PragmaVtab *pTab = (PragmaVtab*)pVtab; |
+ sqlite3_free(pTab); |
+ return SQLITE_OK; |
+} |
+ |
+/* Figure out the best index to use to search a pragma virtual table. |
+** |
+** There are not really any index choices. But we want to encourage the |
+** query planner to give == constraints on as many hidden parameters as |
+** possible, and especially on the first hidden parameter. So return a |
+** high cost if hidden parameters are unconstrained. |
+*/ |
+static int pragmaVtabBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ |
+ PragmaVtab *pTab = (PragmaVtab*)tab; |
+ const struct sqlite3_index_constraint *pConstraint; |
+ int i, j; |
+ int seen[2]; |
+ |
+ pIdxInfo->estimatedCost = (double)1; |
+ if( pTab->nHidden==0 ){ return SQLITE_OK; } |
+ pConstraint = pIdxInfo->aConstraint; |
+ seen[0] = 0; |
+ seen[1] = 0; |
+ for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ |
+ if( pConstraint->usable==0 ) continue; |
+ if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; |
+ if( pConstraint->iColumn < pTab->iHidden ) continue; |
+ j = pConstraint->iColumn - pTab->iHidden; |
+ assert( j < 2 ); |
+ seen[j] = i+1; |
+ } |
+ if( seen[0]==0 ){ |
+ pIdxInfo->estimatedCost = (double)2147483647; |
+ pIdxInfo->estimatedRows = 2147483647; |
+ return SQLITE_OK; |
+ } |
+ j = seen[0]-1; |
+ pIdxInfo->aConstraintUsage[j].argvIndex = 1; |
+ pIdxInfo->aConstraintUsage[j].omit = 1; |
+ if( seen[1]==0 ) return SQLITE_OK; |
+ pIdxInfo->estimatedCost = (double)20; |
+ pIdxInfo->estimatedRows = 20; |
+ j = seen[1]-1; |
+ pIdxInfo->aConstraintUsage[j].argvIndex = 2; |
+ pIdxInfo->aConstraintUsage[j].omit = 1; |
+ return SQLITE_OK; |
+} |
+ |
+/* Create a new cursor for the pragma virtual table */ |
+static int pragmaVtabOpen(sqlite3_vtab *pVtab, sqlite3_vtab_cursor **ppCursor){ |
+ PragmaVtabCursor *pCsr; |
+ pCsr = (PragmaVtabCursor*)sqlite3_malloc(sizeof(*pCsr)); |
+ if( pCsr==0 ) return SQLITE_NOMEM; |
+ memset(pCsr, 0, sizeof(PragmaVtabCursor)); |
+ pCsr->base.pVtab = pVtab; |
+ *ppCursor = &pCsr->base; |
+ return SQLITE_OK; |
+} |
+ |
+/* Clear all content from pragma virtual table cursor. */ |
+static void pragmaVtabCursorClear(PragmaVtabCursor *pCsr){ |
+ int i; |
+ sqlite3_finalize(pCsr->pPragma); |
+ pCsr->pPragma = 0; |
+ for(i=0; i<ArraySize(pCsr->azArg); i++){ |
+ sqlite3_free(pCsr->azArg[i]); |
+ pCsr->azArg[i] = 0; |
+ } |
+} |
+ |
+/* Close a pragma virtual table cursor */ |
+static int pragmaVtabClose(sqlite3_vtab_cursor *cur){ |
+ PragmaVtabCursor *pCsr = (PragmaVtabCursor*)cur; |
+ pragmaVtabCursorClear(pCsr); |
+ sqlite3_free(pCsr); |
+ return SQLITE_OK; |
+} |
+ |
+/* Advance the pragma virtual table cursor to the next row */ |
+static int pragmaVtabNext(sqlite3_vtab_cursor *pVtabCursor){ |
+ PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor; |
+ int rc = SQLITE_OK; |
+ |
+ /* Increment the xRowid value */ |
+ pCsr->iRowid++; |
+ assert( pCsr->pPragma ); |
+ if( SQLITE_ROW!=sqlite3_step(pCsr->pPragma) ){ |
+ rc = sqlite3_finalize(pCsr->pPragma); |
+ pCsr->pPragma = 0; |
+ pragmaVtabCursorClear(pCsr); |
+ } |
+ return rc; |
+} |
+ |
+/* |
+** Pragma virtual table module xFilter method. |
+*/ |
+static int pragmaVtabFilter( |
+ sqlite3_vtab_cursor *pVtabCursor, |
+ int idxNum, const char *idxStr, |
+ int argc, sqlite3_value **argv |
+){ |
+ PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor; |
+ PragmaVtab *pTab = (PragmaVtab*)(pVtabCursor->pVtab); |
+ int rc; |
+ int i, j; |
+ StrAccum acc; |
+ char *zSql; |
+ |
+ UNUSED_PARAMETER(idxNum); |
+ UNUSED_PARAMETER(idxStr); |
+ pragmaVtabCursorClear(pCsr); |
+ j = (pTab->pName->mPragFlg & PragFlg_Result1)!=0 ? 0 : 1; |
+ for(i=0; i<argc; i++, j++){ |
+ assert( j<ArraySize(pCsr->azArg) ); |
+ pCsr->azArg[j] = sqlite3_mprintf("%s", sqlite3_value_text(argv[i])); |
+ if( pCsr->azArg[j]==0 ){ |
+ return SQLITE_NOMEM; |
+ } |
+ } |
+ sqlite3StrAccumInit(&acc, 0, 0, 0, pTab->db->aLimit[SQLITE_LIMIT_SQL_LENGTH]); |
+ sqlite3StrAccumAppendAll(&acc, "PRAGMA "); |
+ if( pCsr->azArg[1] ){ |
+ sqlite3XPrintf(&acc, "%Q.", pCsr->azArg[1]); |
+ } |
+ sqlite3StrAccumAppendAll(&acc, pTab->pName->zName); |
+ if( pCsr->azArg[0] ){ |
+ sqlite3XPrintf(&acc, "=%Q", pCsr->azArg[0]); |
+ } |
+ zSql = sqlite3StrAccumFinish(&acc); |
+ if( zSql==0 ) return SQLITE_NOMEM; |
+ rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pPragma, 0); |
+ sqlite3_free(zSql); |
+ if( rc!=SQLITE_OK ){ |
+ pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db)); |
+ return rc; |
+ } |
+ return pragmaVtabNext(pVtabCursor); |
+} |
+ |
+/* |
+** Pragma virtual table module xEof method. |
+*/ |
+static int pragmaVtabEof(sqlite3_vtab_cursor *pVtabCursor){ |
+ PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor; |
+ return (pCsr->pPragma==0); |
+} |
+ |
+/* The xColumn method simply returns the corresponding column from |
+** the PRAGMA. |
+*/ |
+static int pragmaVtabColumn( |
+ sqlite3_vtab_cursor *pVtabCursor, |
+ sqlite3_context *ctx, |
+ int i |
+){ |
+ PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor; |
+ PragmaVtab *pTab = (PragmaVtab*)(pVtabCursor->pVtab); |
+ if( i<pTab->iHidden ){ |
+ sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pPragma, i)); |
+ }else{ |
+ sqlite3_result_text(ctx, pCsr->azArg[i-pTab->iHidden],-1,SQLITE_TRANSIENT); |
+ } |
+ return SQLITE_OK; |
+} |
+ |
+/* |
+** Pragma virtual table module xRowid method. |
+*/ |
+static int pragmaVtabRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *p){ |
+ PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor; |
+ *p = pCsr->iRowid; |
+ return SQLITE_OK; |
+} |
+ |
+/* The pragma virtual table object */ |
+static const sqlite3_module pragmaVtabModule = { |
+ 0, /* iVersion */ |
+ 0, /* xCreate - create a table */ |
+ pragmaVtabConnect, /* xConnect - connect to an existing table */ |
+ pragmaVtabBestIndex, /* xBestIndex - Determine search strategy */ |
+ pragmaVtabDisconnect, /* xDisconnect - Disconnect from a table */ |
+ 0, /* xDestroy - Drop a table */ |
+ pragmaVtabOpen, /* xOpen - open a cursor */ |
+ pragmaVtabClose, /* xClose - close a cursor */ |
+ pragmaVtabFilter, /* xFilter - configure scan constraints */ |
+ pragmaVtabNext, /* xNext - advance a cursor */ |
+ pragmaVtabEof, /* xEof */ |
+ pragmaVtabColumn, /* xColumn - read data */ |
+ pragmaVtabRowid, /* xRowid - read data */ |
+ 0, /* xUpdate - write data */ |
+ 0, /* xBegin - begin transaction */ |
+ 0, /* xSync - sync transaction */ |
+ 0, /* xCommit - commit transaction */ |
+ 0, /* xRollback - rollback transaction */ |
+ 0, /* xFindFunction - function overloading */ |
+ 0, /* xRename - rename the table */ |
+ 0, /* xSavepoint */ |
+ 0, /* xRelease */ |
+ 0 /* xRollbackTo */ |
+}; |
+ |
+/* |
+** Check to see if zTabName is really the name of a pragma. If it is, |
+** then register an eponymous virtual table for that pragma and return |
+** a pointer to the Module object for the new virtual table. |
+*/ |
+SQLITE_PRIVATE Module *sqlite3PragmaVtabRegister(sqlite3 *db, const char *zName){ |
+ const PragmaName *pName; |
+ assert( sqlite3_strnicmp(zName, "pragma_", 7)==0 ); |
+ pName = pragmaLocate(zName+7); |
+ if( pName==0 ) return 0; |
+ if( (pName->mPragFlg & (PragFlg_Result0|PragFlg_Result1))==0 ) return 0; |
+ assert( sqlite3HashFind(&db->aModule, zName)==0 ); |
+ return sqlite3VtabCreateModule(db, zName, &pragmaVtabModule, (void*)pName, 0); |
+} |
+ |
+#endif /* SQLITE_OMIT_VIRTUALTABLE */ |
+ |
+#endif /* SQLITE_OMIT_PRAGMA */ |
+ |
+/************** End of pragma.c **********************************************/ |
+/************** Begin file prepare.c *****************************************/ |
+/* |
+** 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. |
+*/ |
+/* #include "sqliteInt.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 */ |
+){ |
+ sqlite3 *db = pData->db; |
+ if( !db->mallocFailed && (db->flags & SQLITE_RecoveryMode)==0 ){ |
+ char *z; |
+ if( zObj==0 ) zObj = "?"; |
+ z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj); |
+ if( zExtra ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra); |
+ sqlite3DbFree(db, *pData->pzErrMsg); |
+ *pData->pzErrMsg = z; |
+ } |
+ pData->rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_CORRUPT_BKPT; |
+} |
+ |
+/* |
+** 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. |
+** |
+*/ |
+SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){ |
+ InitData *pData = (InitData*)pInit; |
+ sqlite3 *db = pData->db; |
+ int iDb = pData->iDb; |
+ |
+ assert( argc==3 ); |
+ UNUSED_PARAMETER2(NotUsed, argc); |
+ assert( sqlite3_mutex_held(db->mutex) ); |
+ DbClearProperty(db, iDb, DB_Empty); |
+ if( db->mallocFailed ){ |
+ corruptSchema(pData, argv[0], 0); |
+ return 1; |
+ } |
+ |
+ assert( iDb>=0 && iDb<db->nDb ); |
+ if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */ |
+ if( argv[1]==0 ){ |
+ corruptSchema(pData, argv[0], 0); |
+ }else if( sqlite3_strnicmp(argv[2],"create ",7)==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. |
+ */ |
+ int rc; |
+ u8 saved_iDb = db->init.iDb; |
+ sqlite3_stmt *pStmt; |
+ TESTONLY(int rcp); /* Return code from sqlite3_prepare() */ |
+ |
+ assert( db->init.busy ); |
+ db->init.iDb = iDb; |
+ db->init.newTnum = sqlite3Atoi(argv[1]); |
+ db->init.orphanTrigger = 0; |
+ TESTONLY(rcp = ) sqlite3_prepare(db, argv[2], -1, &pStmt, 0); |
+ rc = db->errCode; |
+ assert( (rc&0xFF)==(rcp&0xFF) ); |
+ db->init.iDb = saved_iDb; |
+ assert( saved_iDb==0 || (db->flags & SQLITE_Vacuum)!=0 ); |
+ if( SQLITE_OK!=rc ){ |
+ if( db->init.orphanTrigger ){ |
+ assert( iDb==1 ); |
+ }else{ |
+ pData->rc = rc; |
+ if( rc==SQLITE_NOMEM ){ |
+ sqlite3OomFault(db); |
+ }else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){ |
+ corruptSchema(pData, argv[0], sqlite3_errmsg(db)); |
+ } |
+ } |
+ } |
+ sqlite3_finalize(pStmt); |
+ }else if( argv[0]==0 || (argv[2]!=0 && argv[2][0]!=0) ){ |
+ corruptSchema(pData, argv[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].zDbSName); |
+ if( pIndex==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 if( sqlite3GetInt32(argv[1], &pIndex->tnum)==0 ){ |
+ corruptSchema(pData, argv[0], "invalid rootpage"); |
+ } |
+ } |
+ 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; |
+ int i; |
+#ifndef SQLITE_OMIT_DEPRECATED |
+ int size; |
+#endif |
+ Db *pDb; |
+ char const *azArg[4]; |
+ int meta[5]; |
+ InitData initData; |
+ const char *zMasterName; |
+ int openedTransaction = 0; |
+ |
+ 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) ); |
+ |
+ /* Construct the in-memory representation schema tables (sqlite_master or |
+ ** sqlite_temp_master) by invoking the parser directly. The appropriate |
+ ** table name will be inserted automatically by the parser so we can just |
+ ** use the abbreviation "x" here. The parser will also automatically tag |
+ ** the schema table as read-only. */ |
+ azArg[0] = zMasterName = SCHEMA_TABLE(iDb); |
+ azArg[1] = "1"; |
+ azArg[2] = "CREATE TABLE x(type text,name text,tbl_name text," |
+ "rootpage integer,sql text)"; |
+ azArg[3] = 0; |
+ initData.db = db; |
+ initData.iDb = iDb; |
+ initData.rc = SQLITE_OK; |
+ initData.pzErrMsg = pzErrMsg; |
+ sqlite3InitCallback(&initData, 3, (char **)azArg, 0); |
+ if( initData.rc ){ |
+ rc = initData.rc; |
+ goto error_out; |
+ } |
+ |
+ /* Create a cursor to hold the database open |
+ */ |
+ pDb = &db->aDb[iDb]; |
+ if( pDb->pBt==0 ){ |
+ if( !OMIT_TEMPDB && ALWAYS(iDb==1) ){ |
+ DbSetProperty(db, 1, DB_SchemaLoaded); |
+ } |
+ return SQLITE_OK; |
+ } |
+ |
+ /* If there is not already a read-only (or read-write) transaction opened |
+ ** on the b-tree database, open one now. If a transaction is opened, it |
+ ** will be closed before this function returns. */ |
+ sqlite3BtreeEnter(pDb->pBt); |
+ if( !sqlite3BtreeIsInReadTrans(pDb->pBt) ){ |
+ rc = sqlite3BtreeBeginTrans(pDb->pBt, 0); |
+ if( rc!=SQLITE_OK ){ |
+ sqlite3SetString(pzErrMsg, db, sqlite3ErrStr(rc)); |
+ goto initone_error_out; |
+ } |
+ openedTransaction = 1; |
+ } |
+ |
+ /* 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] Largest rootpage (auto/incr_vacuum mode) |
+ ** meta[4] Db text encoding. 1:UTF-8 2:UTF-16LE 3:UTF-16BE |
+ ** meta[5] User version |
+ ** meta[6] Incremental vacuum mode |
+ ** meta[7] unused |
+ ** meta[8] unused |
+ ** meta[9] unused |
+ ** |
+ ** Note: The #defined SQLITE_UTF* symbols in sqliteInt.h correspond to |
+ ** the possible values of meta[4]. |
+ */ |
+ for(i=0; i<ArraySize(meta); i++){ |
+ sqlite3BtreeGetMeta(pDb->pBt, i+1, (u32 *)&meta[i]); |
+ } |
+ pDb->pSchema->schema_cookie = meta[BTREE_SCHEMA_VERSION-1]; |
+ |
+ /* 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[BTREE_TEXT_ENCODING-1] ){ /* text encoding */ |
+ if( iDb==0 ){ |
+#ifndef SQLITE_OMIT_UTF16 |
+ u8 encoding; |
+ /* If opening the main database, set ENC(db). */ |
+ encoding = (u8)meta[BTREE_TEXT_ENCODING-1] & 3; |
+ if( encoding==0 ) encoding = SQLITE_UTF8; |
+ ENC(db) = encoding; |
+#else |
+ ENC(db) = SQLITE_UTF8; |
+#endif |
+ }else{ |
+ /* If opening an attached database, the encoding much match ENC(db) */ |
+ if( meta[BTREE_TEXT_ENCODING-1]!=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 ){ |
+#ifndef SQLITE_OMIT_DEPRECATED |
+ size = sqlite3AbsInt32(meta[BTREE_DEFAULT_CACHE_SIZE-1]); |
+ if( size==0 ){ size = SQLITE_DEFAULT_CACHE_SIZE; } |
+ pDb->pSchema->cache_size = size; |
+#else |
+ pDb->pSchema->cache_size = SQLITE_DEFAULT_CACHE_SIZE; |
+#endif |
+ 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 = (u8)meta[BTREE_FILE_FORMAT-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[BTREE_FILE_FORMAT-1]>=4 ){ |
+ db->flags &= ~SQLITE_LegacyFileFmt; |
+ } |
+ |
+ /* Read the schema information out of the schema tables |
+ */ |
+ assert( db->init.busy ); |
+ { |
+ char *zSql; |
+ zSql = sqlite3MPrintf(db, |
+ "SELECT name, rootpage, sql FROM \"%w\".%s ORDER BY rowid", |
+ db->aDb[iDb].zDbSName, zMasterName); |
+#ifndef SQLITE_OMIT_AUTHORIZATION |
+ { |
+ sqlite3_xauth xAuth; |
+ 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_OK ) rc = initData.rc; |
+ sqlite3DbFree(db, zSql); |
+#ifndef SQLITE_OMIT_ANALYZE |
+ if( rc==SQLITE_OK ){ |
+ sqlite3AnalysisLoad(db, iDb); |
+ } |
+#endif |
+ } |
+ if( db->mallocFailed ){ |
+ rc = SQLITE_NOMEM_BKPT; |
+ sqlite3ResetAllSchemasOfConnection(db); |
+ } |
+ 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 occurred. 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 occurred. 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: |
+ if( openedTransaction ){ |
+ sqlite3BtreeCommit(pDb->pBt); |
+ } |
+ sqlite3BtreeLeave(pDb->pBt); |
+ |
+error_out: |
+ if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ |
+ sqlite3OomFault(db); |
+ } |
+ 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. |
+*/ |
+SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){ |
+ int i, rc; |
+ int commit_internal = !(db->flags&SQLITE_InternChanges); |
+ |
+ assert( sqlite3_mutex_held(db->mutex) ); |
+ assert( sqlite3BtreeHoldsMutex(db->aDb[0].pBt) ); |
+ assert( db->init.busy==0 ); |
+ rc = SQLITE_OK; |
+ db->init.busy = 1; |
+ ENC(db) = SCHEMA_ENC(db); |
+ 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 ){ |
+ sqlite3ResetOneSchema(db, i); |
+ } |
+ } |
+ |
+ /* Once all the other databases have been initialized, 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 |
+ assert( db->nDb>1 ); |
+ if( rc==SQLITE_OK && !DbHasProperty(db, 1, DB_SchemaLoaded) ){ |
+ rc = sqlite3InitOne(db, 1, pzErrMsg); |
+ if( rc ){ |
+ sqlite3ResetOneSchema(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 initialized. |
+** Otherwise, the schema is loaded. An error code is returned. |
+*/ |
+SQLITE_PRIVATE 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 set pParse->rc to SQLITE_SCHEMA. If all schema cookies |
+** make no changes to pParse->rc. |
+*/ |
+static void schemaIsValid(Parse *pParse){ |
+ sqlite3 *db = pParse->db; |
+ int iDb; |
+ int rc; |
+ int cookie; |
+ |
+ assert( pParse->checkSchema ); |
+ assert( sqlite3_mutex_held(db->mutex) ); |
+ for(iDb=0; iDb<db->nDb; iDb++){ |
+ int openedTransaction = 0; /* True if a transaction is opened */ |
+ Btree *pBt = db->aDb[iDb].pBt; /* Btree database to read cookie from */ |
+ if( pBt==0 ) continue; |
+ |
+ /* If there is not already a read-only (or read-write) transaction opened |
+ ** on the b-tree database, open one now. If a transaction is opened, it |
+ ** will be closed immediately after reading the meta-value. */ |
+ if( !sqlite3BtreeIsInReadTrans(pBt) ){ |
+ rc = sqlite3BtreeBeginTrans(pBt, 0); |
+ if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ |
+ sqlite3OomFault(db); |
+ } |
+ if( rc!=SQLITE_OK ) return; |
+ openedTransaction = 1; |
+ } |
+ |
+ /* Read the schema cookie from the database. If it does not match the |
+ ** value stored as part of the in-memory schema representation, |
+ ** set Parse.rc to SQLITE_SCHEMA. */ |
+ sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&cookie); |
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
+ if( cookie!=db->aDb[iDb].pSchema->schema_cookie ){ |
+ sqlite3ResetOneSchema(db, iDb); |
+ pParse->rc = SQLITE_SCHEMA; |
+ } |
+ |
+ /* Close the transaction, if one was opened. */ |
+ if( openedTransaction ){ |
+ sqlite3BtreeCommit(pBt); |
+ } |
+ } |
+} |
+ |
+/* |
+** 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. |
+*/ |
+SQLITE_PRIVATE 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 the incorrect 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; ALWAYS(i<db->nDb); i++){ |
+ if( db->aDb[i].pSchema==pSchema ){ |
+ break; |
+ } |
+ } |
+ assert( i>=0 && i<db->nDb ); |
+ } |
+ return i; |
+} |
+ |
+/* |
+** Free all memory allocations in the pParse object |
+*/ |
+SQLITE_PRIVATE void sqlite3ParserReset(Parse *pParse){ |
+ if( pParse ){ |
+ sqlite3 *db = pParse->db; |
+ sqlite3DbFree(db, pParse->aLabel); |
+ sqlite3ExprListDelete(db, pParse->pConstExpr); |
+ if( db ){ |
+ assert( db->lookaside.bDisable >= pParse->disableLookaside ); |
+ db->lookaside.bDisable -= pParse->disableLookaside; |
+ } |
+ pParse->disableLookaside = 0; |
+ } |
+} |
+ |
+/* |
+** 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 */ |
+ Vdbe *pReprepare, /* VM being reprepared */ |
+ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ |
+ const char **pzTail /* OUT: End of parsed string */ |
+){ |
+ char *zErrMsg = 0; /* Error message */ |
+ int rc = SQLITE_OK; /* Result code */ |
+ int i; /* Loop counter */ |
+ Parse sParse; /* Parsing context */ |
+ |
+ memset(&sParse, 0, PARSE_HDR_SZ); |
+ memset(PARSE_TAIL(&sParse), 0, PARSE_TAIL_SZ); |
+ sParse.pReprepare = pReprepare; |
+ assert( ppStmt && *ppStmt==0 ); |
+ /* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */ |
+ assert( sqlite3_mutex_held(db->mutex) ); |
+ |
+ /* Check to verify that it is possible to get a read lock on all |
+ ** database schemas. The inability to get a read lock indicates that |
+ ** some other database connection is holding a write-lock, which in |
+ ** turn means that the other connection has made uncommitted changes |
+ ** to the schema. |
+ ** |
+ ** Were we to proceed and prepare the statement against the uncommitted |
+ ** schema changes and if those schema changes are subsequently rolled |
+ ** back and different changes are made in their place, then when this |
+ ** prepared statement goes to run the schema cookie would fail to detect |
+ ** the schema change. Disaster would follow. |
+ ** |
+ ** This thread is currently holding mutexes on all Btrees (because |
+ ** of the sqlite3BtreeEnterAll() in sqlite3LockAndPrepare()) so it |
+ ** is not possible for another thread to start a new schema change |
+ ** while this routine is running. Hence, we do not need to hold |
+ ** locks on the schema, we just need to make sure nobody else is |
+ ** holding them. |
+ ** |
+ ** Note that setting READ_UNCOMMITTED overrides most lock detection, |
+ ** but it does *not* override schema lock detection, so this all still |
+ ** works even if READ_UNCOMMITTED is set. |
+ */ |
+ for(i=0; i<db->nDb; i++) { |
+ Btree *pBt = db->aDb[i].pBt; |
+ if( pBt ){ |
+ assert( sqlite3BtreeHoldsMutex(pBt) ); |
+ rc = sqlite3BtreeSchemaLocked(pBt); |
+ if( rc ){ |
+ const char *zDb = db->aDb[i].zDbSName; |
+ sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb); |
+ testcase( db->flags & SQLITE_ReadUncommitted ); |
+ goto end_prepare; |
+ } |
+ } |
+ } |
+ |
+ sqlite3VtabUnlockList(db); |
+ |
+ sParse.db = db; |
+ if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){ |
+ char *zSqlCopy; |
+ int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; |
+ testcase( nBytes==mxLen ); |
+ testcase( nBytes==mxLen+1 ); |
+ if( nBytes>mxLen ){ |
+ sqlite3ErrorWithMsg(db, SQLITE_TOOBIG, "statement too long"); |
+ rc = sqlite3ApiExit(db, SQLITE_TOOBIG); |
+ goto end_prepare; |
+ } |
+ zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes); |
+ if( zSqlCopy ){ |
+ sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg); |
+ sParse.zTail = &zSql[sParse.zTail-zSqlCopy]; |
+ sqlite3DbFree(db, zSqlCopy); |
+ }else{ |
+ sParse.zTail = &zSql[nBytes]; |
+ } |
+ }else{ |
+ sqlite3RunParser(&sParse, zSql, &zErrMsg); |
+ } |
+ assert( 0==sParse.nQueryLoop ); |
+ |
+ if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK; |
+ if( sParse.checkSchema ){ |
+ schemaIsValid(&sParse); |
+ } |
+ if( db->mallocFailed ){ |
+ sParse.rc = SQLITE_NOMEM_BKPT; |
+ } |
+ if( pzTail ){ |
+ *pzTail = sParse.zTail; |
+ } |
+ rc = sParse.rc; |
+ |
+#ifndef SQLITE_OMIT_EXPLAIN |
+ if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){ |
+ static const char * const azColName[] = { |
+ "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment", |
+ "selectid", "order", "from", "detail" |
+ }; |
+ int iFirst, mx; |
+ if( sParse.explain==2 ){ |
+ sqlite3VdbeSetNumCols(sParse.pVdbe, 4); |
+ iFirst = 8; |
+ mx = 12; |
+ }else{ |
+ sqlite3VdbeSetNumCols(sParse.pVdbe, 8); |
+ iFirst = 0; |
+ mx = 8; |
+ } |
+ for(i=iFirst; i<mx; i++){ |
+ sqlite3VdbeSetColName(sParse.pVdbe, i-iFirst, COLNAME_NAME, |
+ azColName[i], SQLITE_STATIC); |
+ } |
+ } |
+#endif |
+ |
+ if( db->init.busy==0 ){ |
+ Vdbe *pVdbe = sParse.pVdbe; |
+ sqlite3VdbeSetSql(pVdbe, zSql, (int)(sParse.zTail-zSql), saveSqlFlag); |
+ } |
+ if( sParse.pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){ |
+ sqlite3VdbeFinalize(sParse.pVdbe); |
+ assert(!(*ppStmt)); |
+ }else{ |
+ *ppStmt = (sqlite3_stmt*)sParse.pVdbe; |
+ } |
+ |
+ if( zErrMsg ){ |
+ sqlite3ErrorWithMsg(db, rc, "%s", zErrMsg); |
+ sqlite3DbFree(db, zErrMsg); |
+ }else{ |
+ sqlite3Error(db, rc); |
+ } |
+ |
+ /* Delete any TriggerPrg structures allocated while parsing this statement. */ |
+ while( sParse.pTriggerPrg ){ |
+ TriggerPrg *pT = sParse.pTriggerPrg; |
+ sParse.pTriggerPrg = pT->pNext; |
+ sqlite3DbFree(db, pT); |
+ } |
+ |
+end_prepare: |
+ |
+ sqlite3ParserReset(&sParse); |
+ 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 */ |
+ Vdbe *pOld, /* VM being reprepared */ |
+ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ |
+ const char **pzTail /* OUT: End of parsed string */ |
+){ |
+ int rc; |
+ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( ppStmt==0 ) return SQLITE_MISUSE_BKPT; |
+#endif |
+ *ppStmt = 0; |
+ if( !sqlite3SafetyCheckOk(db)||zSql==0 ){ |
+ return SQLITE_MISUSE_BKPT; |
+ } |
+ sqlite3_mutex_enter(db->mutex); |
+ sqlite3BtreeEnterAll(db); |
+ rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail); |
+ if( rc==SQLITE_SCHEMA ){ |
+ sqlite3_finalize(*ppStmt); |
+ rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail); |
+ } |
+ sqlite3BtreeLeaveAll(db); |
+ sqlite3_mutex_leave(db->mutex); |
+ assert( rc==SQLITE_OK || *ppStmt==0 ); |
+ return rc; |
+} |
+ |
+/* |
+** Rerun the compilation of a statement after a schema change. |
+** |
+** If the statement is successfully recompiled, return SQLITE_OK. Otherwise, |
+** if the statement cannot be recompiled because another connection has |
+** locked the sqlite3_master table, return SQLITE_LOCKED. If any other error |
+** occurs, return SQLITE_SCHEMA. |
+*/ |
+SQLITE_PRIVATE 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, p, &pNew, 0); |
+ if( rc ){ |
+ if( rc==SQLITE_NOMEM ){ |
+ sqlite3OomFault(db); |
+ } |
+ assert( pNew==0 ); |
+ return rc; |
+ }else{ |
+ assert( pNew!=0 ); |
+ } |
+ sqlite3VdbeSwap((Vdbe*)pNew, p); |
+ sqlite3TransferBindings(pNew, (sqlite3_stmt*)p); |
+ sqlite3VdbeResetStepResult((Vdbe*)pNew); |
+ sqlite3VdbeFinalize((Vdbe*)pNew); |
+ return SQLITE_OK; |
+} |
+ |
+ |
+/* |
+** 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. |
+*/ |
+SQLITE_API 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,0,ppStmt,pzTail); |
+ assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ |
+ return rc; |
+} |
+SQLITE_API 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,0,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-16 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; |
+ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( ppStmt==0 ) return SQLITE_MISUSE_BKPT; |
+#endif |
+ *ppStmt = 0; |
+ if( !sqlite3SafetyCheckOk(db)||zSql==0 ){ |
+ return SQLITE_MISUSE_BKPT; |
+ } |
+ if( nBytes>=0 ){ |
+ int sz; |
+ const char *z = (const char*)zSql; |
+ for(sz=0; sz<nBytes && (z[sz]!=0 || z[sz+1]!=0); sz += 2){} |
+ nBytes = sz; |
+ } |
+ sqlite3_mutex_enter(db->mutex); |
+ zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE); |
+ if( zSql8 ){ |
+ rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, 0, 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, (int)(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. |
+*/ |
+SQLITE_API int sqlite3_prepare16( |
+ sqlite3 *db, /* Database handle. */ |
+ const void *zSql, /* UTF-16 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; |
+} |
+SQLITE_API int sqlite3_prepare16_v2( |
+ sqlite3 *db, /* Database handle. */ |
+ const void *zSql, /* UTF-16 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 */ |
+ |
+/************** End of prepare.c *********************************************/ |
+/************** Begin file select.c ******************************************/ |
+/* |
+** 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. |
+*/ |
+/* #include "sqliteInt.h" */ |
+ |
+/* |
+** Trace output macros |
+*/ |
+#if SELECTTRACE_ENABLED |
+/***/ int sqlite3SelectTrace = 0; |
+# define SELECTTRACE(K,P,S,X) \ |
+ if(sqlite3SelectTrace&(K)) \ |
+ sqlite3DebugPrintf("%*s%s.%p: ",(P)->nSelectIndent*2-2,"",\ |
+ (S)->zSelName,(S)),\ |
+ sqlite3DebugPrintf X |
+#else |
+# define SELECTTRACE(K,P,S,X) |
+#endif |
+ |
+ |
+/* |
+** An instance of the following object is used to record information about |
+** how to process the DISTINCT keyword, to simplify passing that information |
+** into the selectInnerLoop() routine. |
+*/ |
+typedef struct DistinctCtx DistinctCtx; |
+struct DistinctCtx { |
+ u8 isTnct; /* True if the DISTINCT keyword is present */ |
+ u8 eTnctType; /* One of the WHERE_DISTINCT_* operators */ |
+ int tabTnct; /* Ephemeral table used for DISTINCT processing */ |
+ int addrTnct; /* Address of OP_OpenEphemeral opcode for tabTnct */ |
+}; |
+ |
+/* |
+** An instance of the following object is used to record information about |
+** the ORDER BY (or GROUP BY) clause of query is being coded. |
+*/ |
+typedef struct SortCtx SortCtx; |
+struct SortCtx { |
+ ExprList *pOrderBy; /* The ORDER BY (or GROUP BY clause) */ |
+ int nOBSat; /* Number of ORDER BY terms satisfied by indices */ |
+ int iECursor; /* Cursor number for the sorter */ |
+ int regReturn; /* Register holding block-output return address */ |
+ int labelBkOut; /* Start label for the block-output subroutine */ |
+ int addrSortIndex; /* Address of the OP_SorterOpen or OP_OpenEphemeral */ |
+ int labelDone; /* Jump here when done, ex: LIMIT reached */ |
+ u8 sortFlags; /* Zero or more SORTFLAG_* bits */ |
+ u8 bOrderedInnerLoop; /* ORDER BY correctly sorts the inner loop */ |
+}; |
+#define SORTFLAG_UseSorter 0x01 /* Use SorterOpen instead of OpenEphemeral */ |
+ |
+/* |
+** Delete all the content of a Select structure. Deallocate the structure |
+** itself only if bFree is true. |
+*/ |
+static void clearSelect(sqlite3 *db, Select *p, int bFree){ |
+ while( p ){ |
+ Select *pPrior = p->pPrior; |
+ sqlite3ExprListDelete(db, p->pEList); |
+ sqlite3SrcListDelete(db, p->pSrc); |
+ sqlite3ExprDelete(db, p->pWhere); |
+ sqlite3ExprListDelete(db, p->pGroupBy); |
+ sqlite3ExprDelete(db, p->pHaving); |
+ sqlite3ExprListDelete(db, p->pOrderBy); |
+ sqlite3ExprDelete(db, p->pLimit); |
+ sqlite3ExprDelete(db, p->pOffset); |
+ if( p->pWith ) sqlite3WithDelete(db, p->pWith); |
+ if( bFree ) sqlite3DbFree(db, p); |
+ p = pPrior; |
+ bFree = 1; |
+ } |
+} |
+ |
+/* |
+** Initialize a SelectDest structure. |
+*/ |
+SQLITE_PRIVATE void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){ |
+ pDest->eDest = (u8)eDest; |
+ pDest->iSDParm = iParm; |
+ pDest->zAffSdst = 0; |
+ pDest->iSdst = 0; |
+ pDest->nSdst = 0; |
+} |
+ |
+ |
+/* |
+** Allocate a new Select structure and return a pointer to that |
+** structure. |
+*/ |
+SQLITE_PRIVATE 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 */ |
+ u32 selFlags, /* Flag parameters, such as SF_Distinct */ |
+ 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 = sqlite3DbMallocRawNN(db, sizeof(*pNew) ); |
+ if( pNew==0 ){ |
+ assert( db->mallocFailed ); |
+ pNew = &standin; |
+ } |
+ if( pEList==0 ){ |
+ pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ASTERISK,0)); |
+ } |
+ pNew->pEList = pEList; |
+ pNew->op = TK_SELECT; |
+ pNew->selFlags = selFlags; |
+ pNew->iLimit = 0; |
+ pNew->iOffset = 0; |
+#if SELECTTRACE_ENABLED |
+ pNew->zSelName[0] = 0; |
+#endif |
+ pNew->addrOpenEphm[0] = -1; |
+ pNew->addrOpenEphm[1] = -1; |
+ pNew->nSelectRow = 0; |
+ if( pSrc==0 ) pSrc = sqlite3DbMallocZero(db, sizeof(*pSrc)); |
+ pNew->pSrc = pSrc; |
+ pNew->pWhere = pWhere; |
+ pNew->pGroupBy = pGroupBy; |
+ pNew->pHaving = pHaving; |
+ pNew->pOrderBy = pOrderBy; |
+ pNew->pPrior = 0; |
+ pNew->pNext = 0; |
+ pNew->pLimit = pLimit; |
+ pNew->pOffset = pOffset; |
+ pNew->pWith = 0; |
+ assert( pOffset==0 || pLimit!=0 || pParse->nErr>0 || db->mallocFailed!=0 ); |
+ if( db->mallocFailed ) { |
+ clearSelect(db, pNew, pNew!=&standin); |
+ pNew = 0; |
+ }else{ |
+ assert( pNew->pSrc!=0 || pParse->nErr>0 ); |
+ } |
+ assert( pNew!=&standin ); |
+ return pNew; |
+} |
+ |
+#if SELECTTRACE_ENABLED |
+/* |
+** Set the name of a Select object |
+*/ |
+SQLITE_PRIVATE void sqlite3SelectSetName(Select *p, const char *zName){ |
+ if( p && zName ){ |
+ sqlite3_snprintf(sizeof(p->zSelName), p->zSelName, "%s", zName); |
+ } |
+} |
+#endif |
+ |
+ |
+/* |
+** Delete the given Select structure and all of its substructures. |
+*/ |
+SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3 *db, Select *p){ |
+ if( p ) clearSelect(db, p, 1); |
+} |
+ |
+/* |
+** Return a pointer to the right-most SELECT statement in a compound. |
+*/ |
+static Select *findRightmost(Select *p){ |
+ while( p->pNext ) p = p->pNext; |
+ return p; |
+} |
+ |
+/* |
+** Given 1 to 3 identifiers preceding 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. |
+*/ |
+SQLITE_PRIVATE int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){ |
+ int jointype = 0; |
+ Token *apAll[3]; |
+ Token *p; |
+ /* 0123456789 123456789 123456789 123 */ |
+ static const char zKeyText[] = "naturaleftouterightfullinnercross"; |
+ static const struct { |
+ u8 i; /* Beginning of keyword text in zKeyText[] */ |
+ u8 nChar; /* Length of the keyword in characters */ |
+ u8 code; /* Join type mask */ |
+ } aKeyword[] = { |
+ /* natural */ { 0, 7, JT_NATURAL }, |
+ /* left */ { 6, 4, JT_LEFT|JT_OUTER }, |
+ /* outer */ { 10, 5, JT_OUTER }, |
+ /* right */ { 14, 5, JT_RIGHT|JT_OUTER }, |
+ /* full */ { 19, 4, JT_LEFT|JT_RIGHT|JT_OUTER }, |
+ /* inner */ { 23, 5, JT_INNER }, |
+ /* cross */ { 28, 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<ArraySize(aKeyword); j++){ |
+ if( p->n==aKeyword[j].nChar |
+ && sqlite3StrNICmp((char*)p->z, &zKeyText[aKeyword[j].i], p->n)==0 ){ |
+ jointype |= aKeyword[j].code; |
+ break; |
+ } |
+ } |
+ testcase( j==0 || j==1 || j==2 || j==3 || j==4 || j==5 || j==6 ); |
+ if( j>=ArraySize(aKeyword) ){ |
+ 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_OUTER)!=0 |
+ && (jointype & (JT_LEFT|JT_RIGHT))!=JT_LEFT ){ |
+ 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; |
+} |
+ |
+/* |
+** Search the first N tables in pSrc, from left to right, looking for a |
+** table that has a column named zCol. |
+** |
+** When found, set *piTab and *piCol to the table index and column index |
+** of the matching column and return TRUE. |
+** |
+** If not found, return FALSE. |
+*/ |
+static int tableAndColumnIndex( |
+ SrcList *pSrc, /* Array of tables to search */ |
+ int N, /* Number of tables in pSrc->a[] to search */ |
+ const char *zCol, /* Name of the column we are looking for */ |
+ int *piTab, /* Write index of pSrc->a[] here */ |
+ int *piCol /* Write index of pSrc->a[*piTab].pTab->aCol[] here */ |
+){ |
+ int i; /* For looping over tables in pSrc */ |
+ int iCol; /* Index of column matching zCol */ |
+ |
+ assert( (piTab==0)==(piCol==0) ); /* Both or neither are NULL */ |
+ for(i=0; i<N; i++){ |
+ iCol = columnIndex(pSrc->a[i].pTab, zCol); |
+ if( iCol>=0 ){ |
+ if( piTab ){ |
+ *piTab = i; |
+ *piCol = iCol; |
+ } |
+ return 1; |
+ } |
+ } |
+ return 0; |
+} |
+ |
+/* |
+** This function is used to add terms implied by JOIN syntax to the |
+** WHERE clause expression of a SELECT statement. The new term, which |
+** is ANDed with the existing WHERE clause, is of the form: |
+** |
+** (tab1.col1 = tab2.col2) |
+** |
+** where tab1 is the iSrc'th table in SrcList pSrc and tab2 is the |
+** (iSrc+1)'th. Column col1 is column iColLeft of tab1, and col2 is |
+** column iColRight of tab2. |
+*/ |
+static void addWhereTerm( |
+ Parse *pParse, /* Parsing context */ |
+ SrcList *pSrc, /* List of tables in FROM clause */ |
+ int iLeft, /* Index of first table to join in pSrc */ |
+ int iColLeft, /* Index of column in first table */ |
+ int iRight, /* Index of second table in pSrc */ |
+ int iColRight, /* Index of column in second table */ |
+ int isOuterJoin, /* True if this is an OUTER join */ |
+ Expr **ppWhere /* IN/OUT: The WHERE clause to add to */ |
+){ |
+ sqlite3 *db = pParse->db; |
+ Expr *pE1; |
+ Expr *pE2; |
+ Expr *pEq; |
+ |
+ assert( iLeft<iRight ); |
+ assert( pSrc->nSrc>iRight ); |
+ assert( pSrc->a[iLeft].pTab ); |
+ assert( pSrc->a[iRight].pTab ); |
+ |
+ pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iColLeft); |
+ pE2 = sqlite3CreateColumnExpr(db, pSrc, iRight, iColRight); |
+ |
+ pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2); |
+ if( pEq && isOuterJoin ){ |
+ ExprSetProperty(pEq, EP_FromJoin); |
+ assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) ); |
+ ExprSetVVAProperty(pEq, EP_NoReduce); |
+ pEq->iRightJoinTable = (i16)pE2->iTable; |
+ } |
+ *ppWhere = sqlite3ExprAnd(db, *ppWhere, pEq); |
+} |
+ |
+/* |
+** 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); |
+ assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); |
+ ExprSetVVAProperty(p, EP_NoReduce); |
+ p->iRightJoinTable = (i16)iTable; |
+ if( p->op==TK_FUNCTION && p->x.pList ){ |
+ int i; |
+ for(i=0; i<p->x.pList->nExpr; i++){ |
+ setJoinExpr(p->x.pList->a[i].pExpr, 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( NEVER(pLeftTab==0 || pRightTab==0) ) continue; |
+ isOuter = (pRight->fg.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->fg.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<pRightTab->nCol; j++){ |
+ char *zName; /* Name of column in the right table */ |
+ int iLeft; /* Matching left table */ |
+ int iLeftCol; /* Matching column in the left table */ |
+ |
+ zName = pRightTab->aCol[j].zName; |
+ if( tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol) ){ |
+ addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, j, |
+ isOuter, &p->pWhere); |
+ } |
+ } |
+ } |
+ |
+ /* 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; /* Name of the term in the USING clause */ |
+ int iLeft; /* Table on the left with matching column name */ |
+ int iLeftCol; /* Column number of matching column on the left */ |
+ int iRightCol; /* Column number of matching column on the right */ |
+ |
+ zName = pList->a[j].zName; |
+ iRightCol = columnIndex(pRightTab, zName); |
+ if( iRightCol<0 |
+ || !tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol) |
+ ){ |
+ sqlite3ErrorMsg(pParse, "cannot join using column %s - column " |
+ "not present in both tables", zName); |
+ return 1; |
+ } |
+ addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, iRightCol, |
+ isOuter, &p->pWhere); |
+ } |
+ } |
+ } |
+ return 0; |
+} |
+ |
+/* Forward reference */ |
+static KeyInfo *keyInfoFromExprList( |
+ Parse *pParse, /* Parsing context */ |
+ ExprList *pList, /* Form the KeyInfo object from this ExprList */ |
+ int iStart, /* Begin with this column of pList */ |
+ int nExtra /* Add this many extra columns to the end */ |
+); |
+ |
+/* |
+** Generate code that will push the record in registers regData |
+** through regData+nData-1 onto the sorter. |
+*/ |
+static void pushOntoSorter( |
+ Parse *pParse, /* Parser context */ |
+ SortCtx *pSort, /* Information about the ORDER BY clause */ |
+ Select *pSelect, /* The whole SELECT statement */ |
+ int regData, /* First register holding data to be sorted */ |
+ int regOrigData, /* First register holding data before packing */ |
+ int nData, /* Number of elements in the data array */ |
+ int nPrefixReg /* No. of reg prior to regData available for use */ |
+){ |
+ Vdbe *v = pParse->pVdbe; /* Stmt under construction */ |
+ int bSeq = ((pSort->sortFlags & SORTFLAG_UseSorter)==0); |
+ int nExpr = pSort->pOrderBy->nExpr; /* No. of ORDER BY terms */ |
+ int nBase = nExpr + bSeq + nData; /* Fields in sorter record */ |
+ int regBase; /* Regs for sorter record */ |
+ int regRecord = ++pParse->nMem; /* Assembled sorter record */ |
+ int nOBSat = pSort->nOBSat; /* ORDER BY terms to skip */ |
+ int op; /* Opcode to add sorter record to sorter */ |
+ int iLimit; /* LIMIT counter */ |
+ |
+ assert( bSeq==0 || bSeq==1 ); |
+ assert( nData==1 || regData==regOrigData || regOrigData==0 ); |
+ if( nPrefixReg ){ |
+ assert( nPrefixReg==nExpr+bSeq ); |
+ regBase = regData - nExpr - bSeq; |
+ }else{ |
+ regBase = pParse->nMem + 1; |
+ pParse->nMem += nBase; |
+ } |
+ assert( pSelect->iOffset==0 || pSelect->iLimit!=0 ); |
+ iLimit = pSelect->iOffset ? pSelect->iOffset+1 : pSelect->iLimit; |
+ pSort->labelDone = sqlite3VdbeMakeLabel(v); |
+ sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, regOrigData, |
+ SQLITE_ECEL_DUP | (regOrigData? SQLITE_ECEL_REF : 0)); |
+ if( bSeq ){ |
+ sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr); |
+ } |
+ if( nPrefixReg==0 && nData>0 ){ |
+ sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+bSeq, nData); |
+ } |
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regRecord); |
+ if( nOBSat>0 ){ |
+ int regPrevKey; /* The first nOBSat columns of the previous row */ |
+ int addrFirst; /* Address of the OP_IfNot opcode */ |
+ int addrJmp; /* Address of the OP_Jump opcode */ |
+ VdbeOp *pOp; /* Opcode that opens the sorter */ |
+ int nKey; /* Number of sorting key columns, including OP_Sequence */ |
+ KeyInfo *pKI; /* Original KeyInfo on the sorter table */ |
+ |
+ regPrevKey = pParse->nMem+1; |
+ pParse->nMem += pSort->nOBSat; |
+ nKey = nExpr - pSort->nOBSat + bSeq; |
+ if( bSeq ){ |
+ addrFirst = sqlite3VdbeAddOp1(v, OP_IfNot, regBase+nExpr); |
+ }else{ |
+ addrFirst = sqlite3VdbeAddOp1(v, OP_SequenceTest, pSort->iECursor); |
+ } |
+ VdbeCoverage(v); |
+ sqlite3VdbeAddOp3(v, OP_Compare, regPrevKey, regBase, pSort->nOBSat); |
+ pOp = sqlite3VdbeGetOp(v, pSort->addrSortIndex); |
+ if( pParse->db->mallocFailed ) return; |
+ pOp->p2 = nKey + nData; |
+ pKI = pOp->p4.pKeyInfo; |
+ memset(pKI->aSortOrder, 0, pKI->nField); /* Makes OP_Jump below testable */ |
+ sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO); |
+ testcase( pKI->nXField>2 ); |
+ pOp->p4.pKeyInfo = keyInfoFromExprList(pParse, pSort->pOrderBy, nOBSat, |
+ pKI->nXField-1); |
+ addrJmp = sqlite3VdbeCurrentAddr(v); |
+ sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v); |
+ pSort->labelBkOut = sqlite3VdbeMakeLabel(v); |
+ pSort->regReturn = ++pParse->nMem; |
+ sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut); |
+ sqlite3VdbeAddOp1(v, OP_ResetSorter, pSort->iECursor); |
+ if( iLimit ){ |
+ sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, pSort->labelDone); |
+ VdbeCoverage(v); |
+ } |
+ sqlite3VdbeJumpHere(v, addrFirst); |
+ sqlite3ExprCodeMove(pParse, regBase, regPrevKey, pSort->nOBSat); |
+ sqlite3VdbeJumpHere(v, addrJmp); |
+ } |
+ if( pSort->sortFlags & SORTFLAG_UseSorter ){ |
+ op = OP_SorterInsert; |
+ }else{ |
+ op = OP_IdxInsert; |
+ } |
+ sqlite3VdbeAddOp4Int(v, op, pSort->iECursor, regRecord, |
+ regBase+nOBSat, nBase-nOBSat); |
+ if( iLimit ){ |
+ int addr; |
+ int r1 = 0; |
+ /* Fill the sorter until it contains LIMIT+OFFSET entries. (The iLimit |
+ ** register is initialized with value of LIMIT+OFFSET.) After the sorter |
+ ** fills up, delete the least entry in the sorter after each insert. |
+ ** Thus we never hold more than the LIMIT+OFFSET rows in memory at once */ |
+ addr = sqlite3VdbeAddOp1(v, OP_IfNotZero, iLimit); VdbeCoverage(v); |
+ sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor); |
+ if( pSort->bOrderedInnerLoop ){ |
+ r1 = ++pParse->nMem; |
+ sqlite3VdbeAddOp3(v, OP_Column, pSort->iECursor, nExpr, r1); |
+ VdbeComment((v, "seq")); |
+ } |
+ sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor); |
+ if( pSort->bOrderedInnerLoop ){ |
+ /* If the inner loop is driven by an index such that values from |
+ ** the same iteration of the inner loop are in sorted order, then |
+ ** immediately jump to the next iteration of an inner loop if the |
+ ** entry from the current iteration does not fit into the top |
+ ** LIMIT+OFFSET entries of the sorter. */ |
+ int iBrk = sqlite3VdbeCurrentAddr(v) + 2; |
+ sqlite3VdbeAddOp3(v, OP_Eq, regBase+nExpr, iBrk, r1); |
+ sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); |
+ VdbeCoverage(v); |
+ } |
+ sqlite3VdbeJumpHere(v, addr); |
+ } |
+} |
+ |
+/* |
+** Add code to implement the OFFSET |
+*/ |
+static void codeOffset( |
+ Vdbe *v, /* Generate code into this VM */ |
+ int iOffset, /* Register holding the offset counter */ |
+ int iContinue /* Jump here to skip the current record */ |
+){ |
+ if( iOffset>0 ){ |
+ sqlite3VdbeAddOp3(v, OP_IfPos, iOffset, iContinue, 1); VdbeCoverage(v); |
+ VdbeComment((v, "OFFSET")); |
+ } |
+} |
+ |
+/* |
+** 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); |
+ sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); VdbeCoverage(v); |
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1); |
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r1, iMem, N); |
+ sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); |
+ sqlite3ReleaseTempReg(pParse, r1); |
+} |
+ |
+/* |
+** This routine generates the code for the inside of the inner loop |
+** of a SELECT. |
+** |
+** If srcTab is negative, then the pEList expressions |
+** are evaluated in order to get the data for this row. If srcTab is |
+** zero or more, then data is pulled from srcTab and pEList is used only |
+** to get the number of columns and the collation sequence 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 */ |
+ SortCtx *pSort, /* If not NULL, info on how to process ORDER BY */ |
+ DistinctCtx *pDistinct, /* If not NULL, info on how to process 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 eDest = pDest->eDest; /* How to dispose of results */ |
+ int iParm = pDest->iSDParm; /* First argument to disposal method */ |
+ int nResultCol; /* Number of result columns */ |
+ int nPrefixReg = 0; /* Number of extra registers before regResult */ |
+ |
+ /* Usually, regResult is the first cell in an array of memory cells |
+ ** containing the current result row. In this case regOrig is set to the |
+ ** same value. However, if the results are being sent to the sorter, the |
+ ** values for any expressions that are also part of the sort-key are omitted |
+ ** from this array. In this case regOrig is set to zero. */ |
+ int regResult; /* Start of memory holding current results */ |
+ int regOrig; /* Start of memory holding full result (or 0) */ |
+ |
+ assert( v ); |
+ assert( pEList!=0 ); |
+ hasDistinct = pDistinct ? pDistinct->eTnctType : WHERE_DISTINCT_NOOP; |
+ if( pSort && pSort->pOrderBy==0 ) pSort = 0; |
+ if( pSort==0 && !hasDistinct ){ |
+ assert( iContinue!=0 ); |
+ codeOffset(v, p->iOffset, iContinue); |
+ } |
+ |
+ /* Pull the requested columns. |
+ */ |
+ nResultCol = pEList->nExpr; |
+ |
+ if( pDest->iSdst==0 ){ |
+ if( pSort ){ |
+ nPrefixReg = pSort->pOrderBy->nExpr; |
+ if( !(pSort->sortFlags & SORTFLAG_UseSorter) ) nPrefixReg++; |
+ pParse->nMem += nPrefixReg; |
+ } |
+ pDest->iSdst = pParse->nMem+1; |
+ pParse->nMem += nResultCol; |
+ }else if( pDest->iSdst+nResultCol > pParse->nMem ){ |
+ /* This is an error condition that can result, for example, when a SELECT |
+ ** on the right-hand side of an INSERT contains more result columns than |
+ ** there are columns in the table on the left. The error will be caught |
+ ** and reported later. But we need to make sure enough memory is allocated |
+ ** to avoid other spurious errors in the meantime. */ |
+ pParse->nMem += nResultCol; |
+ } |
+ pDest->nSdst = nResultCol; |
+ regOrig = regResult = pDest->iSdst; |
+ if( srcTab>=0 ){ |
+ for(i=0; i<nResultCol; i++){ |
+ sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i); |
+ VdbeComment((v, "%s", pEList->a[i].zName)); |
+ } |
+ }else if( eDest!=SRT_Exists ){ |
+ /* If the destination is an EXISTS(...) expression, the actual |
+ ** values returned by the SELECT are not required. |
+ */ |
+ u8 ecelFlags; |
+ if( eDest==SRT_Mem || eDest==SRT_Output || eDest==SRT_Coroutine ){ |
+ ecelFlags = SQLITE_ECEL_DUP; |
+ }else{ |
+ ecelFlags = 0; |
+ } |
+ if( pSort && hasDistinct==0 && eDest!=SRT_EphemTab && eDest!=SRT_Table ){ |
+ /* For each expression in pEList that is a copy of an expression in |
+ ** the ORDER BY clause (pSort->pOrderBy), set the associated |
+ ** iOrderByCol value to one more than the index of the ORDER BY |
+ ** expression within the sort-key that pushOntoSorter() will generate. |
+ ** This allows the pEList field to be omitted from the sorted record, |
+ ** saving space and CPU cycles. */ |
+ ecelFlags |= (SQLITE_ECEL_OMITREF|SQLITE_ECEL_REF); |
+ for(i=pSort->nOBSat; i<pSort->pOrderBy->nExpr; i++){ |
+ int j; |
+ if( (j = pSort->pOrderBy->a[i].u.x.iOrderByCol)>0 ){ |
+ pEList->a[j-1].u.x.iOrderByCol = i+1-pSort->nOBSat; |
+ } |
+ } |
+ regOrig = 0; |
+ assert( eDest==SRT_Set || eDest==SRT_Mem |
+ || eDest==SRT_Coroutine || eDest==SRT_Output ); |
+ } |
+ nResultCol = sqlite3ExprCodeExprList(pParse,pEList,regResult,0,ecelFlags); |
+ } |
+ |
+ /* 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 ){ |
+ switch( pDistinct->eTnctType ){ |
+ case WHERE_DISTINCT_ORDERED: { |
+ VdbeOp *pOp; /* No longer required OpenEphemeral instr. */ |
+ int iJump; /* Jump destination */ |
+ int regPrev; /* Previous row content */ |
+ |
+ /* Allocate space for the previous row */ |
+ regPrev = pParse->nMem+1; |
+ pParse->nMem += nResultCol; |
+ |
+ /* Change the OP_OpenEphemeral coded earlier to an OP_Null |
+ ** sets the MEM_Cleared bit on the first register of the |
+ ** previous value. This will cause the OP_Ne below to always |
+ ** fail on the first iteration of the loop even if the first |
+ ** row is all NULLs. |
+ */ |
+ sqlite3VdbeChangeToNoop(v, pDistinct->addrTnct); |
+ pOp = sqlite3VdbeGetOp(v, pDistinct->addrTnct); |
+ pOp->opcode = OP_Null; |
+ pOp->p1 = 1; |
+ pOp->p2 = regPrev; |
+ |
+ iJump = sqlite3VdbeCurrentAddr(v) + nResultCol; |
+ for(i=0; i<nResultCol; i++){ |
+ CollSeq *pColl = sqlite3ExprCollSeq(pParse, pEList->a[i].pExpr); |
+ if( i<nResultCol-1 ){ |
+ sqlite3VdbeAddOp3(v, OP_Ne, regResult+i, iJump, regPrev+i); |
+ VdbeCoverage(v); |
+ }else{ |
+ sqlite3VdbeAddOp3(v, OP_Eq, regResult+i, iContinue, regPrev+i); |
+ VdbeCoverage(v); |
+ } |
+ sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ); |
+ sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); |
+ } |
+ assert( sqlite3VdbeCurrentAddr(v)==iJump || pParse->db->mallocFailed ); |
+ sqlite3VdbeAddOp3(v, OP_Copy, regResult, regPrev, nResultCol-1); |
+ break; |
+ } |
+ |
+ case WHERE_DISTINCT_UNIQUE: { |
+ sqlite3VdbeChangeToNoop(v, pDistinct->addrTnct); |
+ break; |
+ } |
+ |
+ default: { |
+ assert( pDistinct->eTnctType==WHERE_DISTINCT_UNORDERED ); |
+ codeDistinct(pParse, pDistinct->tabTnct, iContinue, nResultCol, |
+ regResult); |
+ break; |
+ } |
+ } |
+ if( pSort==0 ){ |
+ codeOffset(v, p->iOffset, iContinue); |
+ } |
+ } |
+ |
+ 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, nResultCol, r1); |
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol); |
+ 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, nResultCol); |
+ break; |
+ } |
+#endif /* SQLITE_OMIT_COMPOUND_SELECT */ |
+ |
+ /* Store the result as data using a unique key. |
+ */ |
+ case SRT_Fifo: |
+ case SRT_DistFifo: |
+ case SRT_Table: |
+ case SRT_EphemTab: { |
+ int r1 = sqlite3GetTempRange(pParse, nPrefixReg+1); |
+ testcase( eDest==SRT_Table ); |
+ testcase( eDest==SRT_EphemTab ); |
+ testcase( eDest==SRT_Fifo ); |
+ testcase( eDest==SRT_DistFifo ); |
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1+nPrefixReg); |
+#ifndef SQLITE_OMIT_CTE |
+ if( eDest==SRT_DistFifo ){ |
+ /* If the destination is DistFifo, then cursor (iParm+1) is open |
+ ** on an ephemeral index. If the current row is already present |
+ ** in the index, do not write it to the output. If not, add the |
+ ** current row to the index and proceed with writing it to the |
+ ** output table as well. */ |
+ int addr = sqlite3VdbeCurrentAddr(v) + 4; |
+ sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0); |
+ VdbeCoverage(v); |
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm+1, r1,regResult,nResultCol); |
+ assert( pSort==0 ); |
+ } |
+#endif |
+ if( pSort ){ |
+ pushOntoSorter(pParse, pSort, p, r1+nPrefixReg,regResult,1,nPrefixReg); |
+ }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); |
+ } |
+ sqlite3ReleaseTempRange(pParse, r1, nPrefixReg+1); |
+ 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: { |
+ if( pSort ){ |
+ /* 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, pSort, p, regResult, regOrig, nResultCol, nPrefixReg); |
+ }else{ |
+ int r1 = sqlite3GetTempReg(pParse); |
+ assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol ); |
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol, |
+ r1, pDest->zAffSdst, nResultCol); |
+ sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol); |
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol); |
+ 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 or array of |
+ ** memory cells and break out of the scan loop. |
+ */ |
+ case SRT_Mem: { |
+ if( pSort ){ |
+ assert( nResultCol<=pDest->nSdst ); |
+ pushOntoSorter( |
+ pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg); |
+ }else{ |
+ assert( nResultCol==pDest->nSdst ); |
+ assert( regResult==iParm ); |
+ /* The LIMIT clause will jump out of the loop for us */ |
+ } |
+ break; |
+ } |
+#endif /* #ifndef SQLITE_OMIT_SUBQUERY */ |
+ |
+ case SRT_Coroutine: /* Send data to a co-routine */ |
+ case SRT_Output: { /* Return the results */ |
+ testcase( eDest==SRT_Coroutine ); |
+ testcase( eDest==SRT_Output ); |
+ if( pSort ){ |
+ pushOntoSorter(pParse, pSort, p, regResult, regOrig, nResultCol, |
+ nPrefixReg); |
+ }else if( eDest==SRT_Coroutine ){ |
+ sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); |
+ }else{ |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nResultCol); |
+ sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol); |
+ } |
+ break; |
+ } |
+ |
+#ifndef SQLITE_OMIT_CTE |
+ /* Write the results into a priority queue that is order according to |
+ ** pDest->pOrderBy (in pSO). pDest->iSDParm (in iParm) is the cursor for an |
+ ** index with pSO->nExpr+2 columns. Build a key using pSO for the first |
+ ** pSO->nExpr columns, then make sure all keys are unique by adding a |
+ ** final OP_Sequence column. The last column is the record as a blob. |
+ */ |
+ case SRT_DistQueue: |
+ case SRT_Queue: { |
+ int nKey; |
+ int r1, r2, r3; |
+ int addrTest = 0; |
+ ExprList *pSO; |
+ pSO = pDest->pOrderBy; |
+ assert( pSO ); |
+ nKey = pSO->nExpr; |
+ r1 = sqlite3GetTempReg(pParse); |
+ r2 = sqlite3GetTempRange(pParse, nKey+2); |
+ r3 = r2+nKey+1; |
+ if( eDest==SRT_DistQueue ){ |
+ /* If the destination is DistQueue, then cursor (iParm+1) is open |
+ ** on a second ephemeral index that holds all values every previously |
+ ** added to the queue. */ |
+ addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0, |
+ regResult, nResultCol); |
+ VdbeCoverage(v); |
+ } |
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r3); |
+ if( eDest==SRT_DistQueue ){ |
+ sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r3); |
+ sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); |
+ } |
+ for(i=0; i<nKey; i++){ |
+ sqlite3VdbeAddOp2(v, OP_SCopy, |
+ regResult + pSO->a[i].u.x.iOrderByCol - 1, |
+ r2+i); |
+ } |
+ sqlite3VdbeAddOp2(v, OP_Sequence, iParm, r2+nKey); |
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, r2, nKey+2, r1); |
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, r2, nKey+2); |
+ if( addrTest ) sqlite3VdbeJumpHere(v, addrTest); |
+ sqlite3ReleaseTempReg(pParse, r1); |
+ sqlite3ReleaseTempRange(pParse, r2, nKey+2); |
+ break; |
+ } |
+#endif /* SQLITE_OMIT_CTE */ |
+ |
+ |
+ |
+#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. Except, if |
+ ** there is a sorter, in which case the sorter has already limited |
+ ** the output for us. |
+ */ |
+ if( pSort==0 && p->iLimit ){ |
+ sqlite3VdbeAddOp2(v, OP_DecrJumpZero, p->iLimit, iBreak); VdbeCoverage(v); |
+ } |
+} |
+ |
+/* |
+** Allocate a KeyInfo object sufficient for an index of N key columns and |
+** X extra columns. |
+*/ |
+SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){ |
+ int nExtra = (N+X)*(sizeof(CollSeq*)+1); |
+ KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra); |
+ if( p ){ |
+ p->aSortOrder = (u8*)&p->aColl[N+X]; |
+ p->nField = (u16)N; |
+ p->nXField = (u16)X; |
+ p->enc = ENC(db); |
+ p->db = db; |
+ p->nRef = 1; |
+ memset(&p[1], 0, nExtra); |
+ }else{ |
+ sqlite3OomFault(db); |
+ } |
+ return p; |
+} |
+ |
+/* |
+** Deallocate a KeyInfo object |
+*/ |
+SQLITE_PRIVATE void sqlite3KeyInfoUnref(KeyInfo *p){ |
+ if( p ){ |
+ assert( p->nRef>0 ); |
+ p->nRef--; |
+ if( p->nRef==0 ) sqlite3DbFree(p->db, p); |
+ } |
+} |
+ |
+/* |
+** Make a new pointer to a KeyInfo object |
+*/ |
+SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoRef(KeyInfo *p){ |
+ if( p ){ |
+ assert( p->nRef>0 ); |
+ p->nRef++; |
+ } |
+ return p; |
+} |
+ |
+#ifdef SQLITE_DEBUG |
+/* |
+** Return TRUE if a KeyInfo object can be change. The KeyInfo object |
+** can only be changed if this is just a single reference to the object. |
+** |
+** This routine is used only inside of assert() statements. |
+*/ |
+SQLITE_PRIVATE int sqlite3KeyInfoIsWriteable(KeyInfo *p){ return p->nRef==1; } |
+#endif /* SQLITE_DEBUG */ |
+ |
+/* |
+** 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 obtained from malloc. The calling |
+** function is responsible for seeing that this structure is eventually |
+** freed. |
+*/ |
+static KeyInfo *keyInfoFromExprList( |
+ Parse *pParse, /* Parsing context */ |
+ ExprList *pList, /* Form the KeyInfo object from this ExprList */ |
+ int iStart, /* Begin with this column of pList */ |
+ int nExtra /* Add this many extra columns to the end */ |
+){ |
+ int nExpr; |
+ KeyInfo *pInfo; |
+ struct ExprList_item *pItem; |
+ sqlite3 *db = pParse->db; |
+ int i; |
+ |
+ nExpr = pList->nExpr; |
+ pInfo = sqlite3KeyInfoAlloc(db, nExpr-iStart, nExtra+1); |
+ if( pInfo ){ |
+ assert( sqlite3KeyInfoIsWriteable(pInfo) ); |
+ for(i=iStart, pItem=pList->a+iStart; i<nExpr; i++, pItem++){ |
+ CollSeq *pColl; |
+ pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr); |
+ if( !pColl ) pColl = db->pDfltColl; |
+ pInfo->aColl[i-iStart] = pColl; |
+ pInfo->aSortOrder[i-iStart] = pItem->sortOrder; |
+ } |
+ } |
+ return pInfo; |
+} |
+ |
+/* |
+** 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; |
+} |
+ |
+#ifndef SQLITE_OMIT_EXPLAIN |
+/* |
+** Unless an "EXPLAIN QUERY PLAN" command is being processed, this function |
+** is a no-op. Otherwise, it adds a single row of output to the EQP result, |
+** where the caption is of the form: |
+** |
+** "USE TEMP B-TREE FOR xxx" |
+** |
+** where xxx is one of "DISTINCT", "ORDER BY" or "GROUP BY". Exactly which |
+** is determined by the zUsage argument. |
+*/ |
+static void explainTempTable(Parse *pParse, const char *zUsage){ |
+ if( pParse->explain==2 ){ |
+ Vdbe *v = pParse->pVdbe; |
+ char *zMsg = sqlite3MPrintf(pParse->db, "USE TEMP B-TREE FOR %s", zUsage); |
+ sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC); |
+ } |
+} |
+ |
+/* |
+** Assign expression b to lvalue a. A second, no-op, version of this macro |
+** is provided when SQLITE_OMIT_EXPLAIN is defined. This allows the code |
+** in sqlite3Select() to assign values to structure member variables that |
+** only exist if SQLITE_OMIT_EXPLAIN is not defined without polluting the |
+** code with #ifndef directives. |
+*/ |
+# define explainSetInteger(a, b) a = b |
+ |
+#else |
+/* No-op versions of the explainXXX() functions and macros. */ |
+# define explainTempTable(y,z) |
+# define explainSetInteger(y,z) |
+#endif |
+ |
+#if !defined(SQLITE_OMIT_EXPLAIN) && !defined(SQLITE_OMIT_COMPOUND_SELECT) |
+/* |
+** Unless an "EXPLAIN QUERY PLAN" command is being processed, this function |
+** is a no-op. Otherwise, it adds a single row of output to the EQP result, |
+** where the caption is of one of the two forms: |
+** |
+** "COMPOSITE SUBQUERIES iSub1 and iSub2 (op)" |
+** "COMPOSITE SUBQUERIES iSub1 and iSub2 USING TEMP B-TREE (op)" |
+** |
+** where iSub1 and iSub2 are the integers passed as the corresponding |
+** function parameters, and op is the text representation of the parameter |
+** of the same name. The parameter "op" must be one of TK_UNION, TK_EXCEPT, |
+** TK_INTERSECT or TK_ALL. The first form is used if argument bUseTmp is |
+** false, or the second form if it is true. |
+*/ |
+static void explainComposite( |
+ Parse *pParse, /* Parse context */ |
+ int op, /* One of TK_UNION, TK_EXCEPT etc. */ |
+ int iSub1, /* Subquery id 1 */ |
+ int iSub2, /* Subquery id 2 */ |
+ int bUseTmp /* True if a temp table was used */ |
+){ |
+ assert( op==TK_UNION || op==TK_EXCEPT || op==TK_INTERSECT || op==TK_ALL ); |
+ if( pParse->explain==2 ){ |
+ Vdbe *v = pParse->pVdbe; |
+ char *zMsg = sqlite3MPrintf( |
+ pParse->db, "COMPOUND SUBQUERIES %d AND %d %s(%s)", iSub1, iSub2, |
+ bUseTmp?"USING TEMP B-TREE ":"", selectOpName(op) |
+ ); |
+ sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC); |
+ } |
+} |
+#else |
+/* No-op versions of the explainXXX() functions and macros. */ |
+# define explainComposite(v,w,x,y,z) |
+#endif |
+ |
+/* |
+** 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 */ |
+ SortCtx *pSort, /* Information on the ORDER BY clause */ |
+ int nColumn, /* Number of columns of data */ |
+ SelectDest *pDest /* Write the sorted results here */ |
+){ |
+ Vdbe *v = pParse->pVdbe; /* The prepared statement */ |
+ int addrBreak = pSort->labelDone; /* Jump here to exit loop */ |
+ int addrContinue = sqlite3VdbeMakeLabel(v); /* Jump here for next cycle */ |
+ int addr; |
+ int addrOnce = 0; |
+ int iTab; |
+ ExprList *pOrderBy = pSort->pOrderBy; |
+ int eDest = pDest->eDest; |
+ int iParm = pDest->iSDParm; |
+ int regRow; |
+ int regRowid; |
+ int iCol; |
+ int nKey; |
+ int iSortTab; /* Sorter cursor to read from */ |
+ int nSortData; /* Trailing values to read from sorter */ |
+ int i; |
+ int bSeq; /* True if sorter record includes seq. no. */ |
+ struct ExprList_item *aOutEx = p->pEList->a; |
+ |
+ assert( addrBreak<0 ); |
+ if( pSort->labelBkOut ){ |
+ sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut); |
+ sqlite3VdbeGoto(v, addrBreak); |
+ sqlite3VdbeResolveLabel(v, pSort->labelBkOut); |
+ } |
+ iTab = pSort->iECursor; |
+ if( eDest==SRT_Output || eDest==SRT_Coroutine || eDest==SRT_Mem ){ |
+ regRowid = 0; |
+ regRow = pDest->iSdst; |
+ nSortData = nColumn; |
+ }else{ |
+ regRowid = sqlite3GetTempReg(pParse); |
+ regRow = sqlite3GetTempRange(pParse, nColumn); |
+ nSortData = nColumn; |
+ } |
+ nKey = pOrderBy->nExpr - pSort->nOBSat; |
+ if( pSort->sortFlags & SORTFLAG_UseSorter ){ |
+ int regSortOut = ++pParse->nMem; |
+ iSortTab = pParse->nTab++; |
+ if( pSort->labelBkOut ){ |
+ addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); |
+ } |
+ sqlite3VdbeAddOp3(v, OP_OpenPseudo, iSortTab, regSortOut, nKey+1+nSortData); |
+ if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce); |
+ addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak); |
+ VdbeCoverage(v); |
+ codeOffset(v, p->iOffset, addrContinue); |
+ sqlite3VdbeAddOp3(v, OP_SorterData, iTab, regSortOut, iSortTab); |
+ bSeq = 0; |
+ }else{ |
+ addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v); |
+ codeOffset(v, p->iOffset, addrContinue); |
+ iSortTab = iTab; |
+ bSeq = 1; |
+ } |
+ for(i=0, iCol=nKey+bSeq; i<nSortData; i++){ |
+ int iRead; |
+ if( aOutEx[i].u.x.iOrderByCol ){ |
+ iRead = aOutEx[i].u.x.iOrderByCol-1; |
+ }else{ |
+ iRead = iCol++; |
+ } |
+ sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iRead, regRow+i); |
+ VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan)); |
+ } |
+ 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==sqlite3Strlen30(pDest->zAffSdst) ); |
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, nColumn, regRowid, |
+ pDest->zAffSdst, nColumn); |
+ sqlite3ExprCacheAffinityChange(pParse, regRow, nColumn); |
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, regRowid, regRow, nColumn); |
+ break; |
+ } |
+ case SRT_Mem: { |
+ /* The LIMIT clause will terminate the loop for us */ |
+ break; |
+ } |
+#endif |
+ default: { |
+ assert( eDest==SRT_Output || eDest==SRT_Coroutine ); |
+ testcase( eDest==SRT_Output ); |
+ testcase( eDest==SRT_Coroutine ); |
+ if( eDest==SRT_Output ){ |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iSdst, nColumn); |
+ sqlite3ExprCacheAffinityChange(pParse, pDest->iSdst, nColumn); |
+ }else{ |
+ sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); |
+ } |
+ break; |
+ } |
+ } |
+ if( regRowid ){ |
+ if( eDest==SRT_Set ){ |
+ sqlite3ReleaseTempRange(pParse, regRow, nColumn); |
+ }else{ |
+ sqlite3ReleaseTempReg(pParse, regRow); |
+ } |
+ sqlite3ReleaseTempReg(pParse, regRowid); |
+ } |
+ /* The bottom of the loop |
+ */ |
+ sqlite3VdbeResolveLabel(v, addrContinue); |
+ if( pSort->sortFlags & SORTFLAG_UseSorter ){ |
+ sqlite3VdbeAddOp2(v, OP_SorterNext, iTab, addr); VdbeCoverage(v); |
+ }else{ |
+ sqlite3VdbeAddOp2(v, OP_Next, iTab, addr); VdbeCoverage(v); |
+ } |
+ if( pSort->regReturn ) sqlite3VdbeAddOp1(v, OP_Return, pSort->regReturn); |
+ sqlite3VdbeResolveLabel(v, addrBreak); |
+} |
+ |
+/* |
+** Return a pointer to a string containing the 'declaration type' of the |
+** expression pExpr. The string may be treated as static by the caller. |
+** |
+** Also try to estimate the size of the returned value and return that |
+** result in *pEstWidth. |
+** |
+** 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. |
+** |
+** This routine has either 3 or 6 parameters depending on whether or not |
+** the SQLITE_ENABLE_COLUMN_METADATA compile-time option is used. |
+*/ |
+#ifdef SQLITE_ENABLE_COLUMN_METADATA |
+# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,C,D,E,F) |
+#else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */ |
+# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,F) |
+#endif |
+static const char *columnTypeImpl( |
+ NameContext *pNC, |
+ Expr *pExpr, |
+#ifdef SQLITE_ENABLE_COLUMN_METADATA |
+ const char **pzOrigDb, |
+ const char **pzOrigTab, |
+ const char **pzOrigCol, |
+#endif |
+ u8 *pEstWidth |
+){ |
+ char const *zType = 0; |
+ int j; |
+ u8 estWidth = 1; |
+#ifdef SQLITE_ENABLE_COLUMN_METADATA |
+ char const *zOrigDb = 0; |
+ char const *zOrigTab = 0; |
+ char const *zOrigCol = 0; |
+#endif |
+ |
+ assert( pExpr!=0 ); |
+ assert( pNC->pSrcList!=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 */ |
+ testcase( pExpr->op==TK_AGG_COLUMN ); |
+ testcase( pExpr->op==TK_COLUMN ); |
+ 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 ){ |
+ /* At one time, code such as "SELECT new.x" within a trigger would |
+ ** cause this condition to run. Since then, we have restructured how |
+ ** trigger code is generated and so this condition is no longer |
+ ** possible. However, it can still be true for statements like |
+ ** the following: |
+ ** |
+ ** CREATE TABLE t1(col INTEGER); |
+ ** SELECT (SELECT t1.col) FROM FROM t1; |
+ ** |
+ ** when columnType() is called on the expression "t1.col" in the |
+ ** sub-select. In this case, set the column type to NULL, even |
+ ** though it should really be "INTEGER". |
+ ** |
+ ** This is not a problem, as the column type of "t1.col" is never |
+ ** used. When columnType() is called on the expression |
+ ** "(SELECT t1.col)", the correct type is returned (see the TK_SELECT |
+ ** branch below. */ |
+ break; |
+ } |
+ |
+ assert( pTab && pExpr->pTab==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 && ALWAYS(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. |
+ ** |
+ ** The ALWAYS() is because iCol>=pS->pEList->nExpr will have been |
+ ** caught already by name resolution. |
+ */ |
+ NameContext sNC; |
+ Expr *p = pS->pEList->a[iCol].pExpr; |
+ sNC.pSrcList = pS->pSrc; |
+ sNC.pNext = pNC; |
+ sNC.pParse = pNC->pParse; |
+ zType = columnType(&sNC, p,&zOrigDb,&zOrigTab,&zOrigCol, &estWidth); |
+ } |
+ }else if( pTab->pSchema ){ |
+ /* A real table */ |
+ assert( !pS ); |
+ if( iCol<0 ) iCol = pTab->iPKey; |
+ assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) ); |
+#ifdef SQLITE_ENABLE_COLUMN_METADATA |
+ if( iCol<0 ){ |
+ zType = "INTEGER"; |
+ zOrigCol = "rowid"; |
+ }else{ |
+ zOrigCol = pTab->aCol[iCol].zName; |
+ zType = sqlite3ColumnType(&pTab->aCol[iCol],0); |
+ estWidth = pTab->aCol[iCol].szEst; |
+ } |
+ zOrigTab = pTab->zName; |
+ if( pNC->pParse ){ |
+ int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema); |
+ zOrigDb = pNC->pParse->db->aDb[iDb].zDbSName; |
+ } |
+#else |
+ if( iCol<0 ){ |
+ zType = "INTEGER"; |
+ }else{ |
+ zType = sqlite3ColumnType(&pTab->aCol[iCol],0); |
+ estWidth = pTab->aCol[iCol].szEst; |
+ } |
+#endif |
+ } |
+ 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->x.pSelect; |
+ Expr *p = pS->pEList->a[0].pExpr; |
+ assert( ExprHasProperty(pExpr, EP_xIsSelect) ); |
+ sNC.pSrcList = pS->pSrc; |
+ sNC.pNext = pNC; |
+ sNC.pParse = pNC->pParse; |
+ zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, &estWidth); |
+ break; |
+ } |
+#endif |
+ } |
+ |
+#ifdef SQLITE_ENABLE_COLUMN_METADATA |
+ if( pzOrigDb ){ |
+ assert( pzOrigTab && pzOrigCol ); |
+ *pzOrigDb = zOrigDb; |
+ *pzOrigTab = zOrigTab; |
+ *pzOrigCol = zOrigCol; |
+ } |
+#endif |
+ if( pEstWidth ) *pEstWidth = estWidth; |
+ 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, 0); |
+ |
+ /* 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, SQLITE_TRANSIENT); |
+ sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT); |
+ sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT); |
+#else |
+ zType = columnType(&sNC, p, 0, 0, 0, 0); |
+#endif |
+ sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT); |
+ } |
+#endif /* !defined(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 |
+ |
+ if( pParse->colNamesSet || db->mallocFailed ) return; |
+ assert( v!=0 ); |
+ assert( pTabList!=0 ); |
+ 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( NEVER(p==0) ) continue; |
+ if( pEList->a[i].zName ){ |
+ char *zName = pEList->a[i].zName; |
+ sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT); |
+ }else if( p->op==TK_COLUMN || p->op==TK_AGG_COLUMN ){ |
+ Table *pTab; |
+ char *zCol; |
+ int iCol = p->iColumn; |
+ for(j=0; ALWAYS(j<pTabList->nSrc); j++){ |
+ if( pTabList->a[j].iCursor==p->iTable ) break; |
+ } |
+ 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, |
+ sqlite3DbStrDup(db, pEList->a[i].zSpan), SQLITE_DYNAMIC); |
+ }else if( fullNames ){ |
+ char *zName = 0; |
+ zName = sqlite3MPrintf(db, "%s.%s", pTab->zName, zCol); |
+ sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_DYNAMIC); |
+ }else{ |
+ sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, SQLITE_TRANSIENT); |
+ } |
+ }else{ |
+ const char *z = pEList->a[i].zSpan; |
+ z = z==0 ? sqlite3MPrintf(db, "column%d", i+1) : sqlite3DbStrDup(db, z); |
+ sqlite3VdbeSetColName(v, i, COLNAME_NAME, z, SQLITE_DYNAMIC); |
+ } |
+ } |
+ generateColumnTypes(pParse, pTabList, pEList); |
+} |
+ |
+/* |
+** Given an expression list (which is really the list of expressions |
+** that form the result set of a SELECT statement) compute appropriate |
+** column names for a table that would hold the expression list. |
+** |
+** All column names will be unique. |
+** |
+** Only the column names are computed. Column.zType, Column.zColl, |
+** and other fields of Column are zeroed. |
+** |
+** Return SQLITE_OK on success. If a memory allocation error occurs, |
+** store NULL in *paCol and 0 in *pnCol and return SQLITE_NOMEM. |
+*/ |
+SQLITE_PRIVATE int sqlite3ColumnsFromExprList( |
+ Parse *pParse, /* Parsing context */ |
+ ExprList *pEList, /* Expr list from which to derive column names */ |
+ i16 *pnCol, /* Write the number of columns here */ |
+ Column **paCol /* Write the new column list here */ |
+){ |
+ sqlite3 *db = pParse->db; /* Database connection */ |
+ int i, j; /* Loop counters */ |
+ u32 cnt; /* Index added to make the name unique */ |
+ Column *aCol, *pCol; /* For looping over result columns */ |
+ int nCol; /* Number of columns in the result set */ |
+ Expr *p; /* Expression for a single result column */ |
+ char *zName; /* Column name */ |
+ int nName; /* Size of name in zName[] */ |
+ Hash ht; /* Hash table of column names */ |
+ |
+ sqlite3HashInit(&ht); |
+ if( pEList ){ |
+ nCol = pEList->nExpr; |
+ aCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol); |
+ testcase( aCol==0 ); |
+ }else{ |
+ nCol = 0; |
+ aCol = 0; |
+ } |
+ assert( nCol==(i16)nCol ); |
+ *pnCol = nCol; |
+ *paCol = aCol; |
+ |
+ for(i=0, pCol=aCol; i<nCol && !db->mallocFailed; i++, pCol++){ |
+ /* Get an appropriate name for the column |
+ */ |
+ p = sqlite3ExprSkipCollate(pEList->a[i].pExpr); |
+ if( (zName = pEList->a[i].zName)!=0 ){ |
+ /* If the column contains an "AS <name>" phrase, use <name> as the name */ |
+ }else{ |
+ Expr *pColExpr = p; /* The expression that is the result column name */ |
+ Table *pTab; /* Table associated with this expression */ |
+ while( pColExpr->op==TK_DOT ){ |
+ pColExpr = pColExpr->pRight; |
+ assert( pColExpr!=0 ); |
+ } |
+ if( pColExpr->op==TK_COLUMN && ALWAYS(pColExpr->pTab!=0) ){ |
+ /* For columns use the column name name */ |
+ int iCol = pColExpr->iColumn; |
+ pTab = pColExpr->pTab; |
+ if( iCol<0 ) iCol = pTab->iPKey; |
+ zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid"; |
+ }else if( pColExpr->op==TK_ID ){ |
+ assert( !ExprHasProperty(pColExpr, EP_IntValue) ); |
+ zName = pColExpr->u.zToken; |
+ }else{ |
+ /* Use the original text of the column expression as its name */ |
+ zName = pEList->a[i].zSpan; |
+ } |
+ } |
+ zName = sqlite3MPrintf(db, "%s", zName); |
+ |
+ /* Make sure the column name is unique. If the name is not unique, |
+ ** append an integer to the name so that it becomes unique. |
+ */ |
+ cnt = 0; |
+ while( zName && sqlite3HashFind(&ht, zName)!=0 ){ |
+ nName = sqlite3Strlen30(zName); |
+ if( nName>0 ){ |
+ for(j=nName-1; j>0 && sqlite3Isdigit(zName[j]); j--){} |
+ if( zName[j]==':' ) nName = j; |
+ } |
+ zName = sqlite3MPrintf(db, "%.*z:%u", nName, zName, ++cnt); |
+ if( cnt>3 ) sqlite3_randomness(sizeof(cnt), &cnt); |
+ } |
+ pCol->zName = zName; |
+ sqlite3ColumnPropertiesFromName(0, pCol); |
+ if( zName && sqlite3HashInsert(&ht, zName, pCol)==pCol ){ |
+ sqlite3OomFault(db); |
+ } |
+ } |
+ sqlite3HashClear(&ht); |
+ if( db->mallocFailed ){ |
+ for(j=0; j<i; j++){ |
+ sqlite3DbFree(db, aCol[j].zName); |
+ } |
+ sqlite3DbFree(db, aCol); |
+ *paCol = 0; |
+ *pnCol = 0; |
+ return SQLITE_NOMEM_BKPT; |
+ } |
+ return SQLITE_OK; |
+} |
+ |
+/* |
+** Add type and collation information to a column list based on |
+** a SELECT statement. |
+** |
+** The column list presumably came from selectColumnNamesFromExprList(). |
+** The column list has only names, not types or collations. This |
+** routine goes through and adds the types and collations. |
+** |
+** This routine requires that all identifiers in the SELECT |
+** statement be resolved. |
+*/ |
+SQLITE_PRIVATE void sqlite3SelectAddColumnTypeAndCollation( |
+ Parse *pParse, /* Parsing contexts */ |
+ Table *pTab, /* Add column type information to this table */ |
+ Select *pSelect /* SELECT used to determine types and collations */ |
+){ |
+ sqlite3 *db = pParse->db; |
+ NameContext sNC; |
+ Column *pCol; |
+ CollSeq *pColl; |
+ int i; |
+ Expr *p; |
+ struct ExprList_item *a; |
+ u64 szAll = 0; |
+ |
+ assert( pSelect!=0 ); |
+ assert( (pSelect->selFlags & SF_Resolved)!=0 ); |
+ assert( pTab->nCol==pSelect->pEList->nExpr || db->mallocFailed ); |
+ if( db->mallocFailed ) return; |
+ memset(&sNC, 0, sizeof(sNC)); |
+ sNC.pSrcList = pSelect->pSrc; |
+ a = pSelect->pEList->a; |
+ for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){ |
+ const char *zType; |
+ int n, m; |
+ p = a[i].pExpr; |
+ zType = columnType(&sNC, p, 0, 0, 0, &pCol->szEst); |
+ szAll += pCol->szEst; |
+ pCol->affinity = sqlite3ExprAffinity(p); |
+ if( zType && (m = sqlite3Strlen30(zType))>0 ){ |
+ n = sqlite3Strlen30(pCol->zName); |
+ pCol->zName = sqlite3DbReallocOrFree(db, pCol->zName, n+m+2); |
+ if( pCol->zName ){ |
+ memcpy(&pCol->zName[n+1], zType, m+1); |
+ pCol->colFlags |= COLFLAG_HASTYPE; |
+ } |
+ } |
+ if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_BLOB; |
+ pColl = sqlite3ExprCollSeq(pParse, p); |
+ if( pColl && pCol->zColl==0 ){ |
+ pCol->zColl = sqlite3DbStrDup(db, pColl->zName); |
+ } |
+ } |
+ pTab->szTabRow = sqlite3LogEst(szAll*4); |
+} |
+ |
+/* |
+** Given a SELECT statement, generate a Table structure that describes |
+** the result set of that SELECT. |
+*/ |
+SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){ |
+ Table *pTab; |
+ sqlite3 *db = pParse->db; |
+ int savedFlags; |
+ |
+ savedFlags = db->flags; |
+ db->flags &= ~SQLITE_FullColNames; |
+ db->flags |= SQLITE_ShortColNames; |
+ sqlite3SelectPrep(pParse, pSelect, 0); |
+ if( pParse->nErr ) return 0; |
+ while( pSelect->pPrior ) pSelect = pSelect->pPrior; |
+ db->flags = savedFlags; |
+ pTab = sqlite3DbMallocZero(db, sizeof(Table) ); |
+ if( pTab==0 ){ |
+ return 0; |
+ } |
+ /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside |
+ ** is disabled */ |
+ assert( db->lookaside.bDisable ); |
+ pTab->nTabRef = 1; |
+ pTab->zName = 0; |
+ pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); |
+ sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); |
+ sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSelect); |
+ pTab->iPKey = -1; |
+ if( db->mallocFailed ){ |
+ sqlite3DeleteTable(db, pTab); |
+ return 0; |
+ } |
+ return pTab; |
+} |
+ |
+/* |
+** 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. |
+*/ |
+static SQLITE_NOINLINE Vdbe *allocVdbe(Parse *pParse){ |
+ Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(pParse); |
+ if( v ) sqlite3VdbeAddOp2(v, OP_Init, 0, 1); |
+ if( pParse->pToplevel==0 |
+ && OptimizationEnabled(pParse->db,SQLITE_FactorOutConst) |
+ ){ |
+ pParse->okConstFactor = 1; |
+ } |
+ return v; |
+} |
+SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse *pParse){ |
+ Vdbe *v = pParse->pVdbe; |
+ return v ? v : allocVdbe(pParse); |
+} |
+ |
+ |
+/* |
+** 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 (zero) |
+** prior to calling this routine. |
+** |
+** The iOffset register (if it exists) is initialized to the value |
+** of the OFFSET. The iLimit register is initialized to LIMIT. Register |
+** iOffset+1 is initialized to LIMIT+OFFSET. |
+** |
+** 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 n; |
+ if( p->iLimit ) return; |
+ |
+ /* |
+ ** "LIMIT -1" always shows all rows. There is some |
+ ** controversy about what the correct behavior should be. |
+ ** The current implementation interprets "LIMIT 0" to mean |
+ ** no rows. |
+ */ |
+ sqlite3ExprCacheClear(pParse); |
+ assert( p->pOffset==0 || p->pLimit!=0 ); |
+ if( p->pLimit ){ |
+ p->iLimit = iLimit = ++pParse->nMem; |
+ v = sqlite3GetVdbe(pParse); |
+ assert( v!=0 ); |
+ if( sqlite3ExprIsInteger(p->pLimit, &n) ){ |
+ sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit); |
+ VdbeComment((v, "LIMIT counter")); |
+ if( n==0 ){ |
+ sqlite3VdbeGoto(v, iBreak); |
+ }else if( n>=0 && p->nSelectRow>sqlite3LogEst((u64)n) ){ |
+ p->nSelectRow = sqlite3LogEst((u64)n); |
+ p->selFlags |= SF_FixedLimit; |
+ } |
+ }else{ |
+ sqlite3ExprCode(pParse, p->pLimit, iLimit); |
+ sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); VdbeCoverage(v); |
+ VdbeComment((v, "LIMIT counter")); |
+ sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, iBreak); VdbeCoverage(v); |
+ } |
+ if( p->pOffset ){ |
+ p->iOffset = iOffset = ++pParse->nMem; |
+ pParse->nMem++; /* Allocate an extra register for limit+offset */ |
+ sqlite3ExprCode(pParse, p->pOffset, iOffset); |
+ sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v); |
+ VdbeComment((v, "OFFSET counter")); |
+ sqlite3VdbeAddOp3(v, OP_OffsetLimit, iLimit, iOffset+1, iOffset); |
+ VdbeComment((v, "LIMIT+OFFSET")); |
+ } |
+ } |
+} |
+ |
+#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; |
+ } |
+ assert( iCol>=0 ); |
+ /* iCol must be less than p->pEList->nExpr. Otherwise an error would |
+ ** have been thrown during name resolution and we would not have gotten |
+ ** this far */ |
+ if( pRet==0 && ALWAYS(iCol<p->pEList->nExpr) ){ |
+ pRet = sqlite3ExprCollSeq(pParse, p->pEList->a[iCol].pExpr); |
+ } |
+ return pRet; |
+} |
+ |
+/* |
+** The select statement passed as the second parameter is a compound SELECT |
+** with an ORDER BY clause. This function allocates and returns a KeyInfo |
+** structure suitable for implementing the ORDER BY. |
+** |
+** Space to hold the KeyInfo structure is obtained from malloc. The calling |
+** function is responsible for ensuring that this structure is eventually |
+** freed. |
+*/ |
+static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){ |
+ ExprList *pOrderBy = p->pOrderBy; |
+ int nOrderBy = p->pOrderBy->nExpr; |
+ sqlite3 *db = pParse->db; |
+ KeyInfo *pRet = sqlite3KeyInfoAlloc(db, nOrderBy+nExtra, 1); |
+ if( pRet ){ |
+ int i; |
+ for(i=0; i<nOrderBy; i++){ |
+ struct ExprList_item *pItem = &pOrderBy->a[i]; |
+ Expr *pTerm = pItem->pExpr; |
+ CollSeq *pColl; |
+ |
+ if( pTerm->flags & EP_Collate ){ |
+ pColl = sqlite3ExprCollSeq(pParse, pTerm); |
+ }else{ |
+ pColl = multiSelectCollSeq(pParse, p, pItem->u.x.iOrderByCol-1); |
+ if( pColl==0 ) pColl = db->pDfltColl; |
+ pOrderBy->a[i].pExpr = |
+ sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName); |
+ } |
+ assert( sqlite3KeyInfoIsWriteable(pRet) ); |
+ pRet->aColl[i] = pColl; |
+ pRet->aSortOrder[i] = pOrderBy->a[i].sortOrder; |
+ } |
+ } |
+ |
+ return pRet; |
+} |
+ |
+#ifndef SQLITE_OMIT_CTE |
+/* |
+** This routine generates VDBE code to compute the content of a WITH RECURSIVE |
+** query of the form: |
+** |
+** <recursive-table> AS (<setup-query> UNION [ALL] <recursive-query>) |
+** \___________/ \_______________/ |
+** p->pPrior p |
+** |
+** |
+** There is exactly one reference to the recursive-table in the FROM clause |
+** of recursive-query, marked with the SrcList->a[].fg.isRecursive flag. |
+** |
+** The setup-query runs once to generate an initial set of rows that go |
+** into a Queue table. Rows are extracted from the Queue table one by |
+** one. Each row extracted from Queue is output to pDest. Then the single |
+** extracted row (now in the iCurrent table) becomes the content of the |
+** recursive-table for a recursive-query run. The output of the recursive-query |
+** is added back into the Queue table. Then another row is extracted from Queue |
+** and the iteration continues until the Queue table is empty. |
+** |
+** If the compound query operator is UNION then no duplicate rows are ever |
+** inserted into the Queue table. The iDistinct table keeps a copy of all rows |
+** that have ever been inserted into Queue and causes duplicates to be |
+** discarded. If the operator is UNION ALL, then duplicates are allowed. |
+** |
+** If the query has an ORDER BY, then entries in the Queue table are kept in |
+** ORDER BY order and the first entry is extracted for each cycle. Without |
+** an ORDER BY, the Queue table is just a FIFO. |
+** |
+** If a LIMIT clause is provided, then the iteration stops after LIMIT rows |
+** have been output to pDest. A LIMIT of zero means to output no rows and a |
+** negative LIMIT means to output all rows. If there is also an OFFSET clause |
+** with a positive value, then the first OFFSET outputs are discarded rather |
+** than being sent to pDest. The LIMIT count does not begin until after OFFSET |
+** rows have been skipped. |
+*/ |
+static void generateWithRecursiveQuery( |
+ Parse *pParse, /* Parsing context */ |
+ Select *p, /* The recursive SELECT to be coded */ |
+ SelectDest *pDest /* What to do with query results */ |
+){ |
+ SrcList *pSrc = p->pSrc; /* The FROM clause of the recursive query */ |
+ int nCol = p->pEList->nExpr; /* Number of columns in the recursive table */ |
+ Vdbe *v = pParse->pVdbe; /* The prepared statement under construction */ |
+ Select *pSetup = p->pPrior; /* The setup query */ |
+ int addrTop; /* Top of the loop */ |
+ int addrCont, addrBreak; /* CONTINUE and BREAK addresses */ |
+ int iCurrent = 0; /* The Current table */ |
+ int regCurrent; /* Register holding Current table */ |
+ int iQueue; /* The Queue table */ |
+ int iDistinct = 0; /* To ensure unique results if UNION */ |
+ int eDest = SRT_Fifo; /* How to write to Queue */ |
+ SelectDest destQueue; /* SelectDest targetting the Queue table */ |
+ int i; /* Loop counter */ |
+ int rc; /* Result code */ |
+ ExprList *pOrderBy; /* The ORDER BY clause */ |
+ Expr *pLimit, *pOffset; /* Saved LIMIT and OFFSET */ |
+ int regLimit, regOffset; /* Registers used by LIMIT and OFFSET */ |
+ |
+ /* Obtain authorization to do a recursive query */ |
+ if( sqlite3AuthCheck(pParse, SQLITE_RECURSIVE, 0, 0, 0) ) return; |
+ |
+ /* Process the LIMIT and OFFSET clauses, if they exist */ |
+ addrBreak = sqlite3VdbeMakeLabel(v); |
+ p->nSelectRow = 320; /* 4 billion rows */ |
+ computeLimitRegisters(pParse, p, addrBreak); |
+ pLimit = p->pLimit; |
+ pOffset = p->pOffset; |
+ regLimit = p->iLimit; |
+ regOffset = p->iOffset; |
+ p->pLimit = p->pOffset = 0; |
+ p->iLimit = p->iOffset = 0; |
+ pOrderBy = p->pOrderBy; |
+ |
+ /* Locate the cursor number of the Current table */ |
+ for(i=0; ALWAYS(i<pSrc->nSrc); i++){ |
+ if( pSrc->a[i].fg.isRecursive ){ |
+ iCurrent = pSrc->a[i].iCursor; |
+ break; |
+ } |
+ } |
+ |
+ /* Allocate cursors numbers for Queue and Distinct. The cursor number for |
+ ** the Distinct table must be exactly one greater than Queue in order |
+ ** for the SRT_DistFifo and SRT_DistQueue destinations to work. */ |
+ iQueue = pParse->nTab++; |
+ if( p->op==TK_UNION ){ |
+ eDest = pOrderBy ? SRT_DistQueue : SRT_DistFifo; |
+ iDistinct = pParse->nTab++; |
+ }else{ |
+ eDest = pOrderBy ? SRT_Queue : SRT_Fifo; |
+ } |
+ sqlite3SelectDestInit(&destQueue, eDest, iQueue); |
+ |
+ /* Allocate cursors for Current, Queue, and Distinct. */ |
+ regCurrent = ++pParse->nMem; |
+ sqlite3VdbeAddOp3(v, OP_OpenPseudo, iCurrent, regCurrent, nCol); |
+ if( pOrderBy ){ |
+ KeyInfo *pKeyInfo = multiSelectOrderByKeyInfo(pParse, p, 1); |
+ sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iQueue, pOrderBy->nExpr+2, 0, |
+ (char*)pKeyInfo, P4_KEYINFO); |
+ destQueue.pOrderBy = pOrderBy; |
+ }else{ |
+ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iQueue, nCol); |
+ } |
+ VdbeComment((v, "Queue table")); |
+ if( iDistinct ){ |
+ p->addrOpenEphm[0] = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iDistinct, 0); |
+ p->selFlags |= SF_UsesEphemeral; |
+ } |
+ |
+ /* Detach the ORDER BY clause from the compound SELECT */ |
+ p->pOrderBy = 0; |
+ |
+ /* Store the results of the setup-query in Queue. */ |
+ pSetup->pNext = 0; |
+ rc = sqlite3Select(pParse, pSetup, &destQueue); |
+ pSetup->pNext = p; |
+ if( rc ) goto end_of_recursive_query; |
+ |
+ /* Find the next row in the Queue and output that row */ |
+ addrTop = sqlite3VdbeAddOp2(v, OP_Rewind, iQueue, addrBreak); VdbeCoverage(v); |
+ |
+ /* Transfer the next row in Queue over to Current */ |
+ sqlite3VdbeAddOp1(v, OP_NullRow, iCurrent); /* To reset column cache */ |
+ if( pOrderBy ){ |
+ sqlite3VdbeAddOp3(v, OP_Column, iQueue, pOrderBy->nExpr+1, regCurrent); |
+ }else{ |
+ sqlite3VdbeAddOp2(v, OP_RowData, iQueue, regCurrent); |
+ } |
+ sqlite3VdbeAddOp1(v, OP_Delete, iQueue); |
+ |
+ /* Output the single row in Current */ |
+ addrCont = sqlite3VdbeMakeLabel(v); |
+ codeOffset(v, regOffset, addrCont); |
+ selectInnerLoop(pParse, p, p->pEList, iCurrent, |
+ 0, 0, pDest, addrCont, addrBreak); |
+ if( regLimit ){ |
+ sqlite3VdbeAddOp2(v, OP_DecrJumpZero, regLimit, addrBreak); |
+ VdbeCoverage(v); |
+ } |
+ sqlite3VdbeResolveLabel(v, addrCont); |
+ |
+ /* Execute the recursive SELECT taking the single row in Current as |
+ ** the value for the recursive-table. Store the results in the Queue. |
+ */ |
+ if( p->selFlags & SF_Aggregate ){ |
+ sqlite3ErrorMsg(pParse, "recursive aggregate queries not supported"); |
+ }else{ |
+ p->pPrior = 0; |
+ sqlite3Select(pParse, p, &destQueue); |
+ assert( p->pPrior==0 ); |
+ p->pPrior = pSetup; |
+ } |
+ |
+ /* Keep running the loop until the Queue is empty */ |
+ sqlite3VdbeGoto(v, addrTop); |
+ sqlite3VdbeResolveLabel(v, addrBreak); |
+ |
+end_of_recursive_query: |
+ sqlite3ExprListDelete(pParse->db, p->pOrderBy); |
+ p->pOrderBy = pOrderBy; |
+ p->pLimit = pLimit; |
+ p->pOffset = pOffset; |
+ return; |
+} |
+#endif /* SQLITE_OMIT_CTE */ |
+ |
+/* Forward references */ |
+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 */ |
+); |
+ |
+/* |
+** Handle the special case of a compound-select that originates from a |
+** VALUES clause. By handling this as a special case, we avoid deep |
+** recursion, and thus do not need to enforce the SQLITE_LIMIT_COMPOUND_SELECT |
+** on a VALUES clause. |
+** |
+** Because the Select object originates from a VALUES clause: |
+** (1) It has no LIMIT or OFFSET |
+** (2) All terms are UNION ALL |
+** (3) There is no ORDER BY clause |
+*/ |
+static int multiSelectValues( |
+ Parse *pParse, /* Parsing context */ |
+ Select *p, /* The right-most of SELECTs to be coded */ |
+ SelectDest *pDest /* What to do with query results */ |
+){ |
+ Select *pPrior; |
+ int nRow = 1; |
+ int rc = 0; |
+ assert( p->selFlags & SF_MultiValue ); |
+ do{ |
+ assert( p->selFlags & SF_Values ); |
+ assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) ); |
+ assert( p->pLimit==0 ); |
+ assert( p->pOffset==0 ); |
+ assert( p->pNext==0 || p->pEList->nExpr==p->pNext->pEList->nExpr ); |
+ if( p->pPrior==0 ) break; |
+ assert( p->pPrior->pNext==p ); |
+ p = p->pPrior; |
+ nRow++; |
+ }while(1); |
+ while( p ){ |
+ pPrior = p->pPrior; |
+ p->pPrior = 0; |
+ rc = sqlite3Select(pParse, p, pDest); |
+ p->pPrior = pPrior; |
+ if( rc ) break; |
+ p->nSelectRow = nRow; |
+ p = p->pNext; |
+ } |
+ return rc; |
+} |
+ |
+/* |
+** 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 */ |
+#ifndef SQLITE_OMIT_EXPLAIN |
+ int iSub1 = 0; /* EQP id of left-hand query */ |
+ int iSub2 = 0; /* EQP id of right-hand query */ |
+#endif |
+ |
+ /* 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 */ |
+ assert( (p->selFlags & SF_Recursive)==0 || p->op==TK_ALL || p->op==TK_UNION ); |
+ db = pParse->db; |
+ pPrior = p->pPrior; |
+ dest = *pDest; |
+ 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 |
+ */ |
+ if( dest.eDest==SRT_EphemTab ){ |
+ assert( p->pEList ); |
+ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, dest.iSDParm, p->pEList->nExpr); |
+ dest.eDest = SRT_Table; |
+ } |
+ |
+ /* Special handling for a compound-select that originates as a VALUES clause. |
+ */ |
+ if( p->selFlags & SF_MultiValue ){ |
+ rc = multiSelectValues(pParse, p, &dest); |
+ goto multi_select_end; |
+ } |
+ |
+ /* Make sure all SELECTs in the statement have the same number of elements |
+ ** in their result sets. |
+ */ |
+ assert( p->pEList && pPrior->pEList ); |
+ assert( p->pEList->nExpr==pPrior->pEList->nExpr ); |
+ |
+#ifndef SQLITE_OMIT_CTE |
+ if( p->selFlags & SF_Recursive ){ |
+ generateWithRecursiveQuery(pParse, p, &dest); |
+ }else |
+#endif |
+ |
+ /* Compound SELECTs that have an ORDER BY clause are handled separately. |
+ */ |
+ if( p->pOrderBy ){ |
+ return multiSelectOrderBy(pParse, p, pDest); |
+ }else |
+ |
+ /* Generate code for the left and right SELECT statements. |
+ */ |
+ switch( p->op ){ |
+ case TK_ALL: { |
+ int addr = 0; |
+ int nLimit; |
+ assert( !pPrior->pLimit ); |
+ pPrior->iLimit = p->iLimit; |
+ pPrior->iOffset = p->iOffset; |
+ pPrior->pLimit = p->pLimit; |
+ pPrior->pOffset = p->pOffset; |
+ explainSetInteger(iSub1, pParse->iNextSelectId); |
+ rc = sqlite3Select(pParse, pPrior, &dest); |
+ 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_IfNot, p->iLimit); VdbeCoverage(v); |
+ VdbeComment((v, "Jump ahead if LIMIT reached")); |
+ if( p->iOffset ){ |
+ sqlite3VdbeAddOp3(v, OP_OffsetLimit, |
+ p->iLimit, p->iOffset+1, p->iOffset); |
+ } |
+ } |
+ explainSetInteger(iSub2, pParse->iNextSelectId); |
+ rc = sqlite3Select(pParse, p, &dest); |
+ testcase( rc!=SQLITE_OK ); |
+ pDelete = p->pPrior; |
+ p->pPrior = pPrior; |
+ p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); |
+ if( pPrior->pLimit |
+ && sqlite3ExprIsInteger(pPrior->pLimit, &nLimit) |
+ && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit) |
+ ){ |
+ p->nSelectRow = sqlite3LogEst((u64)nLimit); |
+ } |
+ if( addr ){ |
+ sqlite3VdbeJumpHere(v, addr); |
+ } |
+ break; |
+ } |
+ case TK_EXCEPT: |
+ case TK_UNION: { |
+ int unionTab; /* Cursor number of the temporary table holding result */ |
+ u8 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; |
+ |
+ testcase( p->op==TK_EXCEPT ); |
+ testcase( p->op==TK_UNION ); |
+ priorOp = SRT_Union; |
+ if( dest.eDest==priorOp ){ |
+ /* We can reuse a temporary table generated by a SELECT to our |
+ ** right. |
+ */ |
+ assert( p->pLimit==0 ); /* Not allowed on leftward elements */ |
+ assert( p->pOffset==0 ); /* Not allowed on leftward elements */ |
+ unionTab = dest.iSDParm; |
+ }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; |
+ findRightmost(p)->selFlags |= SF_UsesEphemeral; |
+ assert( p->pEList ); |
+ } |
+ |
+ /* Code the SELECT statements to our left |
+ */ |
+ assert( !pPrior->pOrderBy ); |
+ sqlite3SelectDestInit(&uniondest, priorOp, unionTab); |
+ explainSetInteger(iSub1, pParse->iNextSelectId); |
+ rc = sqlite3Select(pParse, pPrior, &uniondest); |
+ 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; |
+ pLimit = p->pLimit; |
+ p->pLimit = 0; |
+ pOffset = p->pOffset; |
+ p->pOffset = 0; |
+ uniondest.eDest = op; |
+ explainSetInteger(iSub2, pParse->iNextSelectId); |
+ rc = sqlite3Select(pParse, p, &uniondest); |
+ testcase( rc!=SQLITE_OK ); |
+ /* 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; |
+ if( p->op==TK_UNION ){ |
+ p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); |
+ } |
+ sqlite3ExprDelete(db, p->pLimit); |
+ p->pLimit = pLimit; |
+ p->pOffset = pOffset; |
+ p->iLimit = 0; |
+ p->iOffset = 0; |
+ |
+ /* Convert the data in the temporary table into whatever form |
+ ** it is that we currently need. |
+ */ |
+ assert( unionTab==dest.iSDParm || dest.eDest!=priorOp ); |
+ if( dest.eDest!=priorOp ){ |
+ int iCont, iBreak, iStart; |
+ assert( p->pEList ); |
+ if( dest.eDest==SRT_Output ){ |
+ Select *pFirst = p; |
+ while( pFirst->pPrior ) pFirst = pFirst->pPrior; |
+ generateColumnNames(pParse, pFirst->pSrc, pFirst->pEList); |
+ } |
+ iBreak = sqlite3VdbeMakeLabel(v); |
+ iCont = sqlite3VdbeMakeLabel(v); |
+ computeLimitRegisters(pParse, p, iBreak); |
+ sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v); |
+ iStart = sqlite3VdbeCurrentAddr(v); |
+ selectInnerLoop(pParse, p, p->pEList, unionTab, |
+ 0, 0, &dest, iCont, iBreak); |
+ sqlite3VdbeResolveLabel(v, iCont); |
+ sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v); |
+ sqlite3VdbeResolveLabel(v, iBreak); |
+ sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0); |
+ } |
+ break; |
+ } |
+ default: assert( p->op==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; |
+ findRightmost(p)->selFlags |= SF_UsesEphemeral; |
+ assert( p->pEList ); |
+ |
+ /* Code the SELECTs to our left into temporary table "tab1". |
+ */ |
+ sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1); |
+ explainSetInteger(iSub1, pParse->iNextSelectId); |
+ rc = sqlite3Select(pParse, pPrior, &intersectdest); |
+ 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.iSDParm = tab2; |
+ explainSetInteger(iSub2, pParse->iNextSelectId); |
+ rc = sqlite3Select(pParse, p, &intersectdest); |
+ testcase( rc!=SQLITE_OK ); |
+ pDelete = p->pPrior; |
+ p->pPrior = pPrior; |
+ if( p->nSelectRow>pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow; |
+ sqlite3ExprDelete(db, p->pLimit); |
+ p->pLimit = pLimit; |
+ p->pOffset = pOffset; |
+ |
+ /* Generate code to take the intersection of the two temporary |
+ ** tables. |
+ */ |
+ assert( p->pEList ); |
+ if( dest.eDest==SRT_Output ){ |
+ Select *pFirst = p; |
+ while( pFirst->pPrior ) pFirst = pFirst->pPrior; |
+ generateColumnNames(pParse, pFirst->pSrc, pFirst->pEList); |
+ } |
+ iBreak = sqlite3VdbeMakeLabel(v); |
+ iCont = sqlite3VdbeMakeLabel(v); |
+ computeLimitRegisters(pParse, p, iBreak); |
+ sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v); |
+ r1 = sqlite3GetTempReg(pParse); |
+ iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1); |
+ sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); VdbeCoverage(v); |
+ sqlite3ReleaseTempReg(pParse, r1); |
+ selectInnerLoop(pParse, p, p->pEList, tab1, |
+ 0, 0, &dest, iCont, iBreak); |
+ sqlite3VdbeResolveLabel(v, iCont); |
+ sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v); |
+ sqlite3VdbeResolveLabel(v, iBreak); |
+ sqlite3VdbeAddOp2(v, OP_Close, tab2, 0); |
+ sqlite3VdbeAddOp2(v, OP_Close, tab1, 0); |
+ break; |
+ } |
+ } |
+ |
+ explainComposite(pParse, p->op, iSub1, iSub2, p->op!=TK_ALL); |
+ |
+ /* 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->selFlags & SF_UsesEphemeral ){ |
+ 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->pNext==0 ); |
+ nCol = p->pEList->nExpr; |
+ pKeyInfo = sqlite3KeyInfoAlloc(db, nCol, 1); |
+ if( !pKeyInfo ){ |
+ rc = SQLITE_NOMEM_BKPT; |
+ goto multi_select_end; |
+ } |
+ 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*)sqlite3KeyInfoRef(pKeyInfo), |
+ P4_KEYINFO); |
+ pLoop->addrOpenEphm[i] = -1; |
+ } |
+ } |
+ sqlite3KeyInfoUnref(pKeyInfo); |
+ } |
+ |
+multi_select_end: |
+ pDest->iSdst = dest.iSdst; |
+ pDest->nSdst = dest.nSdst; |
+ sqlite3SelectDelete(db, pDelete); |
+ return rc; |
+} |
+#endif /* SQLITE_OMIT_COMPOUND_SELECT */ |
+ |
+/* |
+** Error message for when two or more terms of a compound select have different |
+** size result sets. |
+*/ |
+SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p){ |
+ if( p->selFlags & SF_Values ){ |
+ sqlite3ErrorMsg(pParse, "all VALUES must have the same number of terms"); |
+ }else{ |
+ sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s" |
+ " do not have the same number of result columns", selectOpName(p->op)); |
+ } |
+} |
+ |
+/* |
+** Code an output subroutine for a coroutine implementation of a |
+** SELECT statment. |
+** |
+** The data to be output is contained in pIn->iSdst. There are |
+** pIn->nSdst 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 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 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 addr1, addr2; |
+ addr1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev); VdbeCoverage(v); |
+ addr2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iSdst, regPrev+1, pIn->nSdst, |
+ (char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO); |
+ sqlite3VdbeAddOp3(v, OP_Jump, addr2+2, iContinue, addr2+2); VdbeCoverage(v); |
+ sqlite3VdbeJumpHere(v, addr1); |
+ sqlite3VdbeAddOp3(v, OP_Copy, pIn->iSdst, regPrev+1, pIn->nSdst-1); |
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, regPrev); |
+ } |
+ if( pParse->db->mallocFailed ) return 0; |
+ |
+ /* Suppress the first OFFSET entries if there is an OFFSET clause |
+ */ |
+ codeOffset(v, p->iOffset, iContinue); |
+ |
+ assert( pDest->eDest!=SRT_Exists ); |
+ assert( pDest->eDest!=SRT_Table ); |
+ switch( pDest->eDest ){ |
+ /* Store the result as data using a unique key. |
+ */ |
+ case SRT_EphemTab: { |
+ int r1 = sqlite3GetTempReg(pParse); |
+ int r2 = sqlite3GetTempReg(pParse); |
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1); |
+ sqlite3VdbeAddOp2(v, OP_NewRowid, pDest->iSDParm, r2); |
+ sqlite3VdbeAddOp3(v, OP_Insert, pDest->iSDParm, 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 ...)". |
+ */ |
+ case SRT_Set: { |
+ int r1; |
+ testcase( pIn->nSdst>1 ); |
+ r1 = sqlite3GetTempReg(pParse); |
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, |
+ r1, pDest->zAffSdst, pIn->nSdst); |
+ sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst); |
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1, |
+ pIn->iSdst, pIn->nSdst); |
+ sqlite3ReleaseTempReg(pParse, r1); |
+ 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( pIn->nSdst==1 || pParse->nErr>0 ); testcase( pIn->nSdst!=1 ); |
+ sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, 1); |
+ /* The LIMIT clause will jump out of the loop for us */ |
+ break; |
+ } |
+#endif /* #ifndef SQLITE_OMIT_SUBQUERY */ |
+ |
+ /* The results are stored in a sequence of registers |
+ ** starting at pDest->iSdst. Then the co-routine yields. |
+ */ |
+ case SRT_Coroutine: { |
+ if( pDest->iSdst==0 ){ |
+ pDest->iSdst = sqlite3GetTempRange(pParse, pIn->nSdst); |
+ pDest->nSdst = pIn->nSdst; |
+ } |
+ sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSdst, pIn->nSdst); |
+ sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); |
+ break; |
+ } |
+ |
+ /* If none of the above, then the result destination must be |
+ ** SRT_Output. This routine is never called with any other |
+ ** destination other than the ones handled above or SRT_Output. |
+ ** |
+ ** For SRT_Output, results are stored in a sequence of registers. |
+ ** Then the OP_ResultRow opcode is used to cause sqlite3_step() to |
+ ** return the next row of result. |
+ */ |
+ default: { |
+ assert( pDest->eDest==SRT_Output ); |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iSdst, pIn->nSdst); |
+ sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst); |
+ break; |
+ } |
+ } |
+ |
+ /* Jump to the end of the loop if the LIMIT is reached. |
+ */ |
+ if( p->iLimit ){ |
+ sqlite3VdbeAddOp2(v, OP_DecrJumpZero, p->iLimit, iBreak); VdbeCoverage(v); |
+ } |
+ |
+ /* 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 regAddrB; /* Address register for select-B coroutine */ |
+ 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 = 0; /* Address of the output-B subroutine */ |
+ int addrEofA; /* Address of the select-A-exhausted subroutine */ |
+ int addrEofA_noB; /* Alternate addrEofA if B is uninitialized */ |
+ 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 addr1; /* Jump instructions that get retargetted */ |
+ int op; /* One of TK_ALL, TK_UNION, TK_EXCEPT, TK_INTERSECT */ |
+ KeyInfo *pKeyDup = 0; /* 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 */ |
+#ifndef SQLITE_OMIT_EXPLAIN |
+ int iSub1; /* EQP id of left-hand query */ |
+ int iSub2; /* EQP id of right-hand query */ |
+#endif |
+ |
+ assert( p->pOrderBy!=0 ); |
+ assert( pKeyDup==0 ); /* "Managed" code needs this. Ticket #3382. */ |
+ db = pParse->db; |
+ v = pParse->pVdbe; |
+ assert( v!=0 ); /* Already thrown the error if VDBE alloc failed */ |
+ 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 ); |
+ 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++){ |
+ struct ExprList_item *pItem; |
+ for(j=0, pItem=pOrderBy->a; j<nOrderBy; j++, pItem++){ |
+ assert( pItem->u.x.iOrderByCol>0 ); |
+ if( pItem->u.x.iOrderByCol==i ) break; |
+ } |
+ if( j==nOrderBy ){ |
+ Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0); |
+ if( pNew==0 ) return SQLITE_NOMEM_BKPT; |
+ pNew->flags |= EP_IntValue; |
+ pNew->u.iValue = i; |
+ pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew); |
+ if( pOrderBy ) pOrderBy->a[nOrderBy++].u.x.iOrderByCol = (u16)i; |
+ } |
+ } |
+ } |
+ |
+ /* Compute the comparison permutation and keyinfo that is used with |
+ ** the permutation used 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 = sqlite3DbMallocRawNN(db, sizeof(int)*(nOrderBy + 1)); |
+ if( aPermute ){ |
+ struct ExprList_item *pItem; |
+ aPermute[0] = nOrderBy; |
+ for(i=1, pItem=pOrderBy->a; i<=nOrderBy; i++, pItem++){ |
+ assert( pItem->u.x.iOrderByCol>0 ); |
+ assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr ); |
+ aPermute[i] = pItem->u.x.iOrderByCol - 1; |
+ } |
+ pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1); |
+ }else{ |
+ pKeyMerge = 0; |
+ } |
+ |
+ /* Reattach the ORDER BY clause to the query. |
+ */ |
+ p->pOrderBy = pOrderBy; |
+ pPrior->pOrderBy = sqlite3ExprListDup(pParse->db, pOrderBy, 0); |
+ |
+ /* 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 || db->mallocFailed ); |
+ regPrev = pParse->nMem+1; |
+ pParse->nMem += nExpr+1; |
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, regPrev); |
+ pKeyDup = sqlite3KeyInfoAlloc(db, nExpr, 1); |
+ if( pKeyDup ){ |
+ assert( sqlite3KeyInfoIsWriteable(pKeyDup) ); |
+ 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->pNext = 0; |
+ sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER"); |
+ if( pPrior->pPrior==0 ){ |
+ sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER"); |
+ } |
+ |
+ /* 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; |
+ regAddrB = ++pParse->nMem; |
+ regOutA = ++pParse->nMem; |
+ regOutB = ++pParse->nMem; |
+ sqlite3SelectDestInit(&destA, SRT_Coroutine, regAddrA); |
+ sqlite3SelectDestInit(&destB, SRT_Coroutine, regAddrB); |
+ |
+ /* Generate a coroutine to evaluate the SELECT statement to the |
+ ** left of the compound operator - the "A" select. |
+ */ |
+ addrSelectA = sqlite3VdbeCurrentAddr(v) + 1; |
+ addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA); |
+ VdbeComment((v, "left SELECT")); |
+ pPrior->iLimit = regLimitA; |
+ explainSetInteger(iSub1, pParse->iNextSelectId); |
+ sqlite3Select(pParse, pPrior, &destA); |
+ sqlite3VdbeEndCoroutine(v, regAddrA); |
+ sqlite3VdbeJumpHere(v, addr1); |
+ |
+ /* Generate a coroutine to evaluate the SELECT statement on |
+ ** the right - the "B" select |
+ */ |
+ addrSelectB = sqlite3VdbeCurrentAddr(v) + 1; |
+ addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrB, 0, addrSelectB); |
+ VdbeComment((v, "right SELECT")); |
+ savedLimit = p->iLimit; |
+ savedOffset = p->iOffset; |
+ p->iLimit = regLimitB; |
+ p->iOffset = 0; |
+ explainSetInteger(iSub2, pParse->iNextSelectId); |
+ sqlite3Select(pParse, p, &destB); |
+ p->iLimit = savedLimit; |
+ p->iOffset = savedOffset; |
+ sqlite3VdbeEndCoroutine(v, regAddrB); |
+ |
+ /* 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, 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, labelEnd); |
+ } |
+ sqlite3KeyInfoUnref(pKeyDup); |
+ |
+ /* Generate a subroutine to run when the results from select A |
+ ** are exhausted and only data in select B remains. |
+ */ |
+ if( op==TK_EXCEPT || op==TK_INTERSECT ){ |
+ addrEofA_noB = addrEofA = labelEnd; |
+ }else{ |
+ VdbeNoopComment((v, "eof-A subroutine")); |
+ addrEofA = sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); |
+ addrEofA_noB = sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, labelEnd); |
+ VdbeCoverage(v); |
+ sqlite3VdbeGoto(v, addrEofA); |
+ p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); |
+ } |
+ |
+ /* 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; |
+ if( p->nSelectRow > pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow; |
+ }else{ |
+ VdbeNoopComment((v, "eof-B subroutine")); |
+ addrEofB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); |
+ sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, labelEnd); VdbeCoverage(v); |
+ sqlite3VdbeGoto(v, addrEofB); |
+ } |
+ |
+ /* Generate code to handle the case of A<B |
+ */ |
+ VdbeNoopComment((v, "A-lt-B subroutine")); |
+ addrAltB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); |
+ sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); VdbeCoverage(v); |
+ sqlite3VdbeGoto(v, 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 = |
+ sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); VdbeCoverage(v); |
+ sqlite3VdbeGoto(v, 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); |
+ } |
+ sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v); |
+ sqlite3VdbeGoto(v, labelCmpr); |
+ |
+ /* This code runs once to initialize everything. |
+ */ |
+ sqlite3VdbeJumpHere(v, addr1); |
+ sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA_noB); VdbeCoverage(v); |
+ sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v); |
+ |
+ /* Implement the main merge loop |
+ */ |
+ sqlite3VdbeResolveLabel(v, labelCmpr); |
+ sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); |
+ sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy, |
+ (char*)pKeyMerge, P4_KEYINFO); |
+ sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE); |
+ sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); VdbeCoverage(v); |
+ |
+ /* Jump to the this point in order to terminate the query. |
+ */ |
+ sqlite3VdbeResolveLabel(v, labelEnd); |
+ |
+ /* Set the number of output columns |
+ */ |
+ if( pDest->eDest==SRT_Output ){ |
+ Select *pFirst = pPrior; |
+ while( pFirst->pPrior ) pFirst = pFirst->pPrior; |
+ generateColumnNames(pParse, pFirst->pSrc, 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; |
+ pPrior->pNext = p; |
+ |
+ /*** TBD: Insert subroutine calls to close cursors on incomplete |
+ **** subqueries ****/ |
+ explainComposite(pParse, p->op, iSub1, iSub2, 0); |
+ return pParse->nErr!=0; |
+} |
+#endif |
+ |
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) |
+/* Forward Declarations */ |
+static void substExprList(Parse*, ExprList*, int, ExprList*); |
+static void substSelect(Parse*, Select *, int, ExprList*, int); |
+ |
+/* |
+** 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 Expr *substExpr( |
+ Parse *pParse, /* Report errors here */ |
+ Expr *pExpr, /* Expr in which substitution occurs */ |
+ int iTable, /* Table to be substituted */ |
+ ExprList *pEList /* Substitute expressions */ |
+){ |
+ sqlite3 *db = pParse->db; |
+ if( pExpr==0 ) return 0; |
+ if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){ |
+ if( pExpr->iColumn<0 ){ |
+ pExpr->op = TK_NULL; |
+ }else{ |
+ Expr *pNew; |
+ Expr *pCopy = pEList->a[pExpr->iColumn].pExpr; |
+ assert( pEList!=0 && pExpr->iColumn<pEList->nExpr ); |
+ assert( pExpr->pLeft==0 && pExpr->pRight==0 ); |
+ if( sqlite3ExprIsVector(pCopy) ){ |
+ sqlite3VectorErrorMsg(pParse, pCopy); |
+ }else{ |
+ pNew = sqlite3ExprDup(db, pCopy, 0); |
+ if( pNew && (pExpr->flags & EP_FromJoin) ){ |
+ pNew->iRightJoinTable = pExpr->iRightJoinTable; |
+ pNew->flags |= EP_FromJoin; |
+ } |
+ sqlite3ExprDelete(db, pExpr); |
+ pExpr = pNew; |
+ } |
+ } |
+ }else{ |
+ pExpr->pLeft = substExpr(pParse, pExpr->pLeft, iTable, pEList); |
+ pExpr->pRight = substExpr(pParse, pExpr->pRight, iTable, pEList); |
+ if( ExprHasProperty(pExpr, EP_xIsSelect) ){ |
+ substSelect(pParse, pExpr->x.pSelect, iTable, pEList, 1); |
+ }else{ |
+ substExprList(pParse, pExpr->x.pList, iTable, pEList); |
+ } |
+ } |
+ return pExpr; |
+} |
+static void substExprList( |
+ Parse *pParse, /* Report 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++){ |
+ pList->a[i].pExpr = substExpr(pParse, pList->a[i].pExpr, iTable, pEList); |
+ } |
+} |
+static void substSelect( |
+ Parse *pParse, /* Report errors here */ |
+ Select *p, /* SELECT statement in which to make substitutions */ |
+ int iTable, /* Table to be replaced */ |
+ ExprList *pEList, /* Substitute values */ |
+ int doPrior /* Do substitutes on p->pPrior too */ |
+){ |
+ SrcList *pSrc; |
+ struct SrcList_item *pItem; |
+ int i; |
+ if( !p ) return; |
+ do{ |
+ substExprList(pParse, p->pEList, iTable, pEList); |
+ substExprList(pParse, p->pGroupBy, iTable, pEList); |
+ substExprList(pParse, p->pOrderBy, iTable, pEList); |
+ p->pHaving = substExpr(pParse, p->pHaving, iTable, pEList); |
+ p->pWhere = substExpr(pParse, p->pWhere, iTable, pEList); |
+ pSrc = p->pSrc; |
+ assert( pSrc!=0 ); |
+ for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){ |
+ substSelect(pParse, pItem->pSelect, iTable, pEList, 1); |
+ if( pItem->fg.isTabFunc ){ |
+ substExprList(pParse, pItem->u1.pFuncArg, iTable, pEList); |
+ } |
+ } |
+ }while( doPrior && (p = p->pPrior)!=0 ); |
+} |
+#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ |
+ |
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) |
+/* |
+** This routine attempts to flatten subqueries as a performance optimization. |
+** This routine 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 simplification 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 (2a) the outer query is not a join |
+** and (2b) the outer query does not use subqueries other than the one |
+** FROM-clause subquery that is a candidate for flattening. (2b is |
+** due to ticket [2f7170d73bf9abf80] from 2015-02-09.) |
+** |
+** (3) The subquery is not the right operand of a left outer join |
+** (Originally ticket #306. Strengthened by ticket #3300) |
+** |
+** (4) The subquery is not DISTINCT. |
+** |
+** (**) At one point restrictions (4) and (5) defined a subset of DISTINCT |
+** sub-queries that were excluded from this optimization. Restriction |
+** (4) has since been expanded to exclude all DISTINCT subqueries. |
+** |
+** (6) The subquery does not use aggregates or the outer query is not |
+** DISTINCT. |
+** |
+** (7) The subquery has a FROM clause. TODO: For subqueries without |
+** A FROM clause, consider adding a FROM close with the special |
+** table sqlite_once that consists of a single row containing a |
+** single NULL. |
+** |
+** (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. |
+** |
+** (**) Restriction (10) was removed from the code on 2005-02-05 but we |
+** accidently carried the comment forward until 2014-09-15. Original |
+** text: "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. |
+** |
+** (**) Not implemented. Subsumed into restriction (3). Was previously |
+** a separate restriction deriving from 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 a LIMIT clause. |
+** (See ticket #2339 and ticket [02a8e81d44]). |
+** |
+** (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 |
+** * is not a join |
+** |
+** 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. The subquery cannot use any compound |
+** operator other than UNION ALL because all the other compound |
+** operators have an implied DISTINCT which is disallowed by |
+** restriction (4). |
+** |
+** Also, each component of the sub-query must return the same number |
+** of result columns. This is actually a requirement for any compound |
+** SELECT statement, but all the code here does is make sure that no |
+** such (illegal) sub-query is flattened. The caller will detect the |
+** syntax error and return a detailed message. |
+** |
+** (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. |
+** |
+** (19) The subquery does not use LIMIT or the outer query does not |
+** have a WHERE clause. |
+** |
+** (20) If the sub-query is a compound select, then it must not use |
+** an ORDER BY clause. Ticket #3773. We could relax this constraint |
+** somewhat by saying that the terms of the ORDER BY clause must |
+** appear as unmodified result columns in the outer query. But we |
+** have other optimizations in mind to deal with that case. |
+** |
+** (21) The subquery does not use LIMIT or the outer query is not |
+** DISTINCT. (See ticket [752e1646fc]). |
+** |
+** (22) The subquery is not a recursive CTE. |
+** |
+** (23) The parent is not a recursive CTE, or the sub-query is not a |
+** compound query. This restriction is because transforming the |
+** parent to a compound query confuses the code that handles |
+** recursive queries in multiSelect(). |
+** |
+** (24) The subquery is not an aggregate that uses the built-in min() or |
+** or max() functions. (Without this restriction, a query like: |
+** "SELECT x FROM (SELECT max(y), x FROM t1)" would not necessarily |
+** return the value X for which Y was maximal.) |
+** |
+** |
+** 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; /* Current UNION ALL term of the other query */ |
+ 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. |
+ */ |
+ assert( p!=0 ); |
+ assert( p->pPrior==0 ); /* Unable to flatten compound queries */ |
+ if( OptimizationDisabled(db, SQLITE_QueryFlattener) ) 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( subqueryIsAgg ){ |
+ if( isAgg ) return 0; /* Restriction (1) */ |
+ if( pSrc->nSrc>1 ) return 0; /* Restriction (2a) */ |
+ if( (p->pWhere && ExprHasProperty(p->pWhere,EP_Subquery)) |
+ || (sqlite3ExprListFlags(p->pEList) & EP_Subquery)!=0 |
+ || (sqlite3ExprListFlags(p->pOrderBy) & EP_Subquery)!=0 |
+ ){ |
+ return 0; /* Restriction (2b) */ |
+ } |
+ } |
+ |
+ pSubSrc = pSub->pSrc; |
+ assert( pSubSrc ); |
+ /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants, |
+ ** not arbitrary expressions, 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->selFlags & SF_Compound)!=0 && pSub->pLimit ){ |
+ return 0; /* Restriction (15) */ |
+ } |
+ if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */ |
+ if( pSub->selFlags & SF_Distinct ) return 0; /* Restriction (5) */ |
+ if( pSub->pLimit && (pSrc->nSrc>1 || isAgg) ){ |
+ return 0; /* Restrictions (8)(9) */ |
+ } |
+ if( (p->selFlags & SF_Distinct)!=0 && subqueryIsAgg ){ |
+ return 0; /* Restriction (6) */ |
+ } |
+ if( p->pOrderBy && pSub->pOrderBy ){ |
+ return 0; /* Restriction (11) */ |
+ } |
+ if( isAgg && pSub->pOrderBy ) return 0; /* Restriction (16) */ |
+ if( pSub->pLimit && p->pWhere ) return 0; /* Restriction (19) */ |
+ if( pSub->pLimit && (p->selFlags & SF_Distinct)!=0 ){ |
+ return 0; /* Restriction (21) */ |
+ } |
+ testcase( pSub->selFlags & SF_Recursive ); |
+ testcase( pSub->selFlags & SF_MinMaxAgg ); |
+ if( pSub->selFlags & (SF_Recursive|SF_MinMaxAgg) ){ |
+ return 0; /* Restrictions (22) and (24) */ |
+ } |
+ if( (p->selFlags & SF_Recursive) && pSub->pPrior ){ |
+ return 0; /* Restriction (23) */ |
+ } |
+ |
+ /* OBSOLETE COMMENT 1: |
+ ** 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. |
+ ** |
+ ** OBSOLETE COMMENT 2: |
+ ** 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. |
+ ** |
+ ** THIS OVERRIDES OBSOLETE COMMENTS 1 AND 2 ABOVE: |
+ ** Ticket #3300 shows that flattening the right term of a LEFT JOIN |
+ ** is fraught with danger. Best to avoid the whole thing. If the |
+ ** subquery is the right term of a LEFT JOIN, then do not flatten. |
+ */ |
+ if( (pSubitem->fg.jointype & JT_OUTER)!=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( pSub->pOrderBy ){ |
+ return 0; /* Restriction 20 */ |
+ } |
+ if( isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){ |
+ return 0; |
+ } |
+ for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){ |
+ testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ); |
+ testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate ); |
+ assert( pSub->pSrc!=0 ); |
+ assert( pSub->pEList->nExpr==pSub1->pEList->nExpr ); |
+ if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0 |
+ || (pSub1->pPrior && pSub1->op!=TK_ALL) |
+ || pSub1->pSrc->nSrc<1 |
+ ){ |
+ return 0; |
+ } |
+ testcase( pSub1->pSrc->nSrc>1 ); |
+ } |
+ |
+ /* Restriction 18. */ |
+ if( p->pOrderBy ){ |
+ int ii; |
+ for(ii=0; ii<p->pOrderBy->nExpr; ii++){ |
+ if( p->pOrderBy->a[ii].u.x.iOrderByCol==0 ) return 0; |
+ } |
+ } |
+ } |
+ |
+ /***** If we reach this point, flattening is permitted. *****/ |
+ SELECTTRACE(1,pParse,p,("flatten %s.%p from term %d\n", |
+ pSub->zSelName, pSub, iFrom)); |
+ |
+ /* Authorize the subquery */ |
+ pParse->zAuthContext = pSubitem->zName; |
+ TESTONLY(i =) sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0); |
+ testcase( i==SQLITE_DENY ); |
+ pParse->zAuthContext = zSavedAuthContext; |
+ |
+ /* If the sub-query is a compound SELECT statement, then (by restrictions |
+ ** 17 and 18 above) 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-1 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. |
+ ** |
+ ** Example: |
+ ** |
+ ** SELECT a+1 FROM ( |
+ ** SELECT x FROM tab |
+ ** UNION ALL |
+ ** SELECT y FROM tab |
+ ** UNION ALL |
+ ** SELECT abs(z*2) FROM tab2 |
+ ** ) WHERE a!=5 ORDER BY 1 |
+ ** |
+ ** Transformed into: |
+ ** |
+ ** SELECT x+1 FROM tab WHERE x+1!=5 |
+ ** UNION ALL |
+ ** SELECT y+1 FROM tab WHERE y+1!=5 |
+ ** UNION ALL |
+ ** SELECT abs(z*2)+1 FROM tab2 WHERE abs(z*2)+1!=5 |
+ ** ORDER BY 1 |
+ ** |
+ ** We call this the "compound-subquery flattening". |
+ */ |
+ 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; |
+ p->pOffset = 0; |
+ pNew = sqlite3SelectDup(db, p, 0); |
+ sqlite3SelectSetName(pNew, pSub->zSelName); |
+ p->pOffset = pOffset; |
+ p->pLimit = pLimit; |
+ p->pOrderBy = pOrderBy; |
+ p->pSrc = pSrc; |
+ p->op = TK_ALL; |
+ if( pNew==0 ){ |
+ p->pPrior = pPrior; |
+ }else{ |
+ pNew->pPrior = pPrior; |
+ if( pPrior ) pPrior->pNext = pNew; |
+ pNew->pNext = p; |
+ p->pPrior = pNew; |
+ SELECTTRACE(2,pParse,p, |
+ ("compound-subquery flattener creates %s.%p as peer\n", |
+ pNew->zSelName, pNew)); |
+ } |
+ if( db->mallocFailed ) return 1; |
+ } |
+ |
+ /* Begin flattening the iFrom-th entry of the FROM clause |
+ ** in the outer query. |
+ */ |
+ pSub = pSub1 = pSubitem->pSelect; |
+ |
+ /* Delete the transient table structure associated with the |
+ ** subquery |
+ */ |
+ sqlite3DbFree(db, pSubitem->zDatabase); |
+ sqlite3DbFree(db, pSubitem->zName); |
+ sqlite3DbFree(db, pSubitem->zAlias); |
+ pSubitem->zDatabase = 0; |
+ pSubitem->zName = 0; |
+ pSubitem->zAlias = 0; |
+ pSubitem->pSelect = 0; |
+ |
+ /* Defer deleting the Table object associated with the |
+ ** subquery until code generation is |
+ ** complete, since there may still exist Expr.pTab entries that |
+ ** refer to the subquery even after flattening. Ticket #3346. |
+ ** |
+ ** pSubitem->pTab is always non-NULL by test restrictions and tests above. |
+ */ |
+ if( ALWAYS(pSubitem->pTab!=0) ){ |
+ Table *pTabToDel = pSubitem->pTab; |
+ if( pTabToDel->nTabRef==1 ){ |
+ Parse *pToplevel = sqlite3ParseToplevel(pParse); |
+ pTabToDel->pNextZombie = pToplevel->pZombieTab; |
+ pToplevel->pZombieTab = pTabToDel; |
+ }else{ |
+ pTabToDel->nTabRef--; |
+ } |
+ pSubitem->pTab = 0; |
+ } |
+ |
+ /* The following loop runs once for each term in a compound-subquery |
+ ** flattening (as described above). If we are doing a different kind |
+ ** of flattening - a flattening other than a compound-subquery flattening - |
+ ** then this loop only runs once. |
+ ** |
+ ** This loop moves 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. |
+ */ |
+ for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){ |
+ int nSubSrc; |
+ u8 jointype = 0; |
+ pSubSrc = pSub->pSrc; /* FROM clause of subquery */ |
+ nSubSrc = pSubSrc->nSrc; /* Number of terms in subquery FROM clause */ |
+ pSrc = pParent->pSrc; /* FROM clause of the outer query */ |
+ |
+ if( pSrc ){ |
+ assert( pParent==p ); /* First time through the loop */ |
+ jointype = pSubitem->fg.jointype; |
+ }else{ |
+ assert( pParent!=p ); /* 2nd and subsequent times through the loop */ |
+ pSrc = pParent->pSrc = sqlite3SrcListAppend(db, 0, 0, 0); |
+ if( pSrc==0 ){ |
+ assert( db->mallocFailed ); |
+ break; |
+ } |
+ } |
+ |
+ /* The subquery uses a single slot of the FROM clause of the outer |
+ ** query. If the subquery has more than one element in its FROM clause, |
+ ** then expand the outer query to make space for it to hold all elements |
+ ** of the subquery. |
+ ** |
+ ** Example: |
+ ** |
+ ** SELECT * FROM tabA, (SELECT * FROM sub1, sub2), tabB; |
+ ** |
+ ** The outer query has 3 slots in its FROM clause. One slot of the |
+ ** outer query (the middle slot) is used by the subquery. The next |
+ ** block of code will expand the outer query FROM clause to 4 slots. |
+ ** The middle slot is expanded to two slots in order to make space |
+ ** for the two elements in the FROM clause of the subquery. |
+ */ |
+ if( nSubSrc>1 ){ |
+ pParent->pSrc = pSrc = sqlite3SrcListEnlarge(db, pSrc, nSubSrc-1,iFrom+1); |
+ if( db->mallocFailed ){ |
+ break; |
+ } |
+ } |
+ |
+ /* Transfer the FROM clause terms from the subquery into the |
+ ** outer query. |
+ */ |
+ for(i=0; i<nSubSrc; i++){ |
+ sqlite3IdListDelete(db, pSrc->a[i+iFrom].pUsing); |
+ assert( pSrc->a[i+iFrom].fg.isTabFunc==0 ); |
+ pSrc->a[i+iFrom] = pSubSrc->a[i]; |
+ memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i])); |
+ } |
+ pSrc->a[iFrom].fg.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++){ |
+ if( pList->a[i].zName==0 ){ |
+ char *zName = sqlite3DbStrDup(db, pList->a[i].zSpan); |
+ sqlite3Dequote(zName); |
+ pList->a[i].zName = zName; |
+ } |
+ } |
+ if( pSub->pOrderBy ){ |
+ /* At this point, any non-zero iOrderByCol values indicate that the |
+ ** ORDER BY column expression is identical to the iOrderByCol'th |
+ ** expression returned by SELECT statement pSub. Since these values |
+ ** do not necessarily correspond to columns in SELECT statement pParent, |
+ ** zero them before transfering the ORDER BY clause. |
+ ** |
+ ** Not doing this may cause an error if a subsequent call to this |
+ ** function attempts to flatten a compound sub-query into pParent |
+ ** (the only way this can happen is if the compound sub-query is |
+ ** currently part of pSub->pSrc). See ticket [d11a6e908f]. */ |
+ ExprList *pOrderBy = pSub->pOrderBy; |
+ for(i=0; i<pOrderBy->nExpr; i++){ |
+ pOrderBy->a[i].u.x.iOrderByCol = 0; |
+ } |
+ assert( pParent->pOrderBy==0 ); |
+ assert( pSub->pPrior==0 ); |
+ pParent->pOrderBy = pOrderBy; |
+ pSub->pOrderBy = 0; |
+ } |
+ pWhere = sqlite3ExprDup(db, pSub->pWhere, 0); |
+ if( subqueryIsAgg ){ |
+ assert( pParent->pHaving==0 ); |
+ pParent->pHaving = pParent->pWhere; |
+ pParent->pWhere = pWhere; |
+ pParent->pHaving = sqlite3ExprAnd(db, |
+ sqlite3ExprDup(db, pSub->pHaving, 0), pParent->pHaving |
+ ); |
+ assert( pParent->pGroupBy==0 ); |
+ pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0); |
+ }else{ |
+ pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere); |
+ } |
+ substSelect(pParse, pParent, iParent, pSub->pEList, 0); |
+ |
+ /* The flattened query is distinct if either the inner or the |
+ ** outer query is distinct. |
+ */ |
+ pParent->selFlags |= pSub->selFlags & SF_Distinct; |
+ |
+ /* |
+ ** 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); |
+ |
+#if SELECTTRACE_ENABLED |
+ if( sqlite3SelectTrace & 0x100 ){ |
+ SELECTTRACE(0x100,pParse,p,("After flattening:\n")); |
+ sqlite3TreeViewSelect(0, p, 0); |
+ } |
+#endif |
+ |
+ return 1; |
+} |
+#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ |
+ |
+ |
+ |
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) |
+/* |
+** Make copies of relevant WHERE clause terms of the outer query into |
+** the WHERE clause of subquery. Example: |
+** |
+** SELECT * FROM (SELECT a AS x, c-d AS y FROM t1) WHERE x=5 AND y=10; |
+** |
+** Transformed into: |
+** |
+** SELECT * FROM (SELECT a AS x, c-d AS y FROM t1 WHERE a=5 AND c-d=10) |
+** WHERE x=5 AND y=10; |
+** |
+** The hope is that the terms added to the inner query will make it more |
+** efficient. |
+** |
+** Do not attempt this optimization if: |
+** |
+** (1) The inner query is an aggregate. (In that case, we'd really want |
+** to copy the outer WHERE-clause terms onto the HAVING clause of the |
+** inner query. But they probably won't help there so do not bother.) |
+** |
+** (2) The inner query is the recursive part of a common table expression. |
+** |
+** (3) The inner query has a LIMIT clause (since the changes to the WHERE |
+** close would change the meaning of the LIMIT). |
+** |
+** (4) The inner query is the right operand of a LEFT JOIN. (The caller |
+** enforces this restriction since this routine does not have enough |
+** information to know.) |
+** |
+** (5) The WHERE clause expression originates in the ON or USING clause |
+** of a LEFT JOIN. |
+** |
+** Return 0 if no changes are made and non-zero if one or more WHERE clause |
+** terms are duplicated into the subquery. |
+*/ |
+static int pushDownWhereTerms( |
+ Parse *pParse, /* Parse context (for malloc() and error reporting) */ |
+ Select *pSubq, /* The subquery whose WHERE clause is to be augmented */ |
+ Expr *pWhere, /* The WHERE clause of the outer query */ |
+ int iCursor /* Cursor number of the subquery */ |
+){ |
+ Expr *pNew; |
+ int nChng = 0; |
+ Select *pX; /* For looping over compound SELECTs in pSubq */ |
+ if( pWhere==0 ) return 0; |
+ for(pX=pSubq; pX; pX=pX->pPrior){ |
+ if( (pX->selFlags & (SF_Aggregate|SF_Recursive))!=0 ){ |
+ testcase( pX->selFlags & SF_Aggregate ); |
+ testcase( pX->selFlags & SF_Recursive ); |
+ testcase( pX!=pSubq ); |
+ return 0; /* restrictions (1) and (2) */ |
+ } |
+ } |
+ if( pSubq->pLimit!=0 ){ |
+ return 0; /* restriction (3) */ |
+ } |
+ while( pWhere->op==TK_AND ){ |
+ nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, iCursor); |
+ pWhere = pWhere->pLeft; |
+ } |
+ if( ExprHasProperty(pWhere,EP_FromJoin) ) return 0; /* restriction 5 */ |
+ if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){ |
+ nChng++; |
+ while( pSubq ){ |
+ pNew = sqlite3ExprDup(pParse->db, pWhere, 0); |
+ pNew = substExpr(pParse, pNew, iCursor, pSubq->pEList); |
+ pSubq->pWhere = sqlite3ExprAnd(pParse->db, pSubq->pWhere, pNew); |
+ pSubq = pSubq->pPrior; |
+ } |
+ } |
+ return nChng; |
+} |
+#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ |
+ |
+/* |
+** Based on the contents of the AggInfo structure indicated by the first |
+** argument, this function checks if the following are true: |
+** |
+** * the query contains just a single aggregate function, |
+** * the aggregate function is either min() or max(), and |
+** * the argument to the aggregate function is a column value. |
+** |
+** If all of the above are true, then WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX |
+** is returned as appropriate. Also, *ppMinMax is set to point to the |
+** list of arguments passed to the aggregate before returning. |
+** |
+** Or, if the conditions above are not met, *ppMinMax is set to 0 and |
+** WHERE_ORDERBY_NORMAL is returned. |
+*/ |
+static u8 minMaxQuery(AggInfo *pAggInfo, ExprList **ppMinMax){ |
+ int eRet = WHERE_ORDERBY_NORMAL; /* Return value */ |
+ |
+ *ppMinMax = 0; |
+ if( pAggInfo->nFunc==1 ){ |
+ Expr *pExpr = pAggInfo->aFunc[0].pExpr; /* Aggregate function */ |
+ ExprList *pEList = pExpr->x.pList; /* Arguments to agg function */ |
+ |
+ assert( pExpr->op==TK_AGG_FUNCTION ); |
+ if( pEList && pEList->nExpr==1 && pEList->a[0].pExpr->op==TK_AGG_COLUMN ){ |
+ const char *zFunc = pExpr->u.zToken; |
+ if( sqlite3StrICmp(zFunc, "min")==0 ){ |
+ eRet = WHERE_ORDERBY_MIN; |
+ *ppMinMax = pEList; |
+ }else if( sqlite3StrICmp(zFunc, "max")==0 ){ |
+ eRet = WHERE_ORDERBY_MAX; |
+ *ppMinMax = pEList; |
+ } |
+ } |
+ } |
+ |
+ assert( *ppMinMax==0 || (*ppMinMax)->nExpr==1 ); |
+ return eRet; |
+} |
+ |
+/* |
+** The select statement passed as the first argument is an aggregate query. |
+** The second argument is the associated aggregate-info object. This |
+** function tests if the SELECT is of the form: |
+** |
+** SELECT count(*) FROM <tbl> |
+** |
+** where table is a database table, not a sub-select or view. If the query |
+** does match this pattern, then a pointer to the Table object representing |
+** <tbl> is returned. Otherwise, 0 is returned. |
+*/ |
+static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){ |
+ Table *pTab; |
+ Expr *pExpr; |
+ |
+ assert( !p->pGroupBy ); |
+ |
+ if( p->pWhere || p->pEList->nExpr!=1 |
+ || p->pSrc->nSrc!=1 || p->pSrc->a[0].pSelect |
+ ){ |
+ return 0; |
+ } |
+ pTab = p->pSrc->a[0].pTab; |
+ pExpr = p->pEList->a[0].pExpr; |
+ assert( pTab && !pTab->pSelect && pExpr ); |
+ |
+ if( IsVirtual(pTab) ) return 0; |
+ if( pExpr->op!=TK_AGG_FUNCTION ) return 0; |
+ if( NEVER(pAggInfo->nFunc==0) ) return 0; |
+ if( (pAggInfo->aFunc[0].pFunc->funcFlags&SQLITE_FUNC_COUNT)==0 ) return 0; |
+ if( pExpr->flags&EP_Distinct ) return 0; |
+ |
+ return pTab; |
+} |
+ |
+/* |
+** If the source-list item passed as an argument was augmented with an |
+** INDEXED BY clause, then try to locate the specified index. If there |
+** was such a clause and the named index cannot be found, return |
+** SQLITE_ERROR and leave an error in pParse. Otherwise, populate |
+** pFrom->pIndex and return SQLITE_OK. |
+*/ |
+SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *pParse, struct SrcList_item *pFrom){ |
+ if( pFrom->pTab && pFrom->fg.isIndexedBy ){ |
+ Table *pTab = pFrom->pTab; |
+ char *zIndexedBy = pFrom->u1.zIndexedBy; |
+ Index *pIdx; |
+ for(pIdx=pTab->pIndex; |
+ pIdx && sqlite3StrICmp(pIdx->zName, zIndexedBy); |
+ pIdx=pIdx->pNext |
+ ); |
+ if( !pIdx ){ |
+ sqlite3ErrorMsg(pParse, "no such index: %s", zIndexedBy, 0); |
+ pParse->checkSchema = 1; |
+ return SQLITE_ERROR; |
+ } |
+ pFrom->pIBIndex = pIdx; |
+ } |
+ return SQLITE_OK; |
+} |
+/* |
+** Detect compound SELECT statements that use an ORDER BY clause with |
+** an alternative collating sequence. |
+** |
+** SELECT ... FROM t1 EXCEPT SELECT ... FROM t2 ORDER BY .. COLLATE ... |
+** |
+** These are rewritten as a subquery: |
+** |
+** SELECT * FROM (SELECT ... FROM t1 EXCEPT SELECT ... FROM t2) |
+** ORDER BY ... COLLATE ... |
+** |
+** This transformation is necessary because the multiSelectOrderBy() routine |
+** above that generates the code for a compound SELECT with an ORDER BY clause |
+** uses a merge algorithm that requires the same collating sequence on the |
+** result columns as on the ORDER BY clause. See ticket |
+** http://www.sqlite.org/src/info/6709574d2a |
+** |
+** This transformation is only needed for EXCEPT, INTERSECT, and UNION. |
+** The UNION ALL operator works fine with multiSelectOrderBy() even when |
+** there are COLLATE terms in the ORDER BY. |
+*/ |
+static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){ |
+ int i; |
+ Select *pNew; |
+ Select *pX; |
+ sqlite3 *db; |
+ struct ExprList_item *a; |
+ SrcList *pNewSrc; |
+ Parse *pParse; |
+ Token dummy; |
+ |
+ if( p->pPrior==0 ) return WRC_Continue; |
+ if( p->pOrderBy==0 ) return WRC_Continue; |
+ for(pX=p; pX && (pX->op==TK_ALL || pX->op==TK_SELECT); pX=pX->pPrior){} |
+ if( pX==0 ) return WRC_Continue; |
+ a = p->pOrderBy->a; |
+ for(i=p->pOrderBy->nExpr-1; i>=0; i--){ |
+ if( a[i].pExpr->flags & EP_Collate ) break; |
+ } |
+ if( i<0 ) return WRC_Continue; |
+ |
+ /* If we reach this point, that means the transformation is required. */ |
+ |
+ pParse = pWalker->pParse; |
+ db = pParse->db; |
+ pNew = sqlite3DbMallocZero(db, sizeof(*pNew) ); |
+ if( pNew==0 ) return WRC_Abort; |
+ memset(&dummy, 0, sizeof(dummy)); |
+ pNewSrc = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&dummy,pNew,0,0); |
+ if( pNewSrc==0 ) return WRC_Abort; |
+ *pNew = *p; |
+ p->pSrc = pNewSrc; |
+ p->pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ASTERISK, 0)); |
+ p->op = TK_SELECT; |
+ p->pWhere = 0; |
+ pNew->pGroupBy = 0; |
+ pNew->pHaving = 0; |
+ pNew->pOrderBy = 0; |
+ p->pPrior = 0; |
+ p->pNext = 0; |
+ p->pWith = 0; |
+ p->selFlags &= ~SF_Compound; |
+ assert( (p->selFlags & SF_Converted)==0 ); |
+ p->selFlags |= SF_Converted; |
+ assert( pNew->pPrior!=0 ); |
+ pNew->pPrior->pNext = pNew; |
+ pNew->pLimit = 0; |
+ pNew->pOffset = 0; |
+ return WRC_Continue; |
+} |
+ |
+/* |
+** Check to see if the FROM clause term pFrom has table-valued function |
+** arguments. If it does, leave an error message in pParse and return |
+** non-zero, since pFrom is not allowed to be a table-valued function. |
+*/ |
+static int cannotBeFunction(Parse *pParse, struct SrcList_item *pFrom){ |
+ if( pFrom->fg.isTabFunc ){ |
+ sqlite3ErrorMsg(pParse, "'%s' is not a function", pFrom->zName); |
+ return 1; |
+ } |
+ return 0; |
+} |
+ |
+#ifndef SQLITE_OMIT_CTE |
+/* |
+** Argument pWith (which may be NULL) points to a linked list of nested |
+** WITH contexts, from inner to outermost. If the table identified by |
+** FROM clause element pItem is really a common-table-expression (CTE) |
+** then return a pointer to the CTE definition for that table. Otherwise |
+** return NULL. |
+** |
+** If a non-NULL value is returned, set *ppContext to point to the With |
+** object that the returned CTE belongs to. |
+*/ |
+static struct Cte *searchWith( |
+ With *pWith, /* Current innermost WITH clause */ |
+ struct SrcList_item *pItem, /* FROM clause element to resolve */ |
+ With **ppContext /* OUT: WITH clause return value belongs to */ |
+){ |
+ const char *zName; |
+ if( pItem->zDatabase==0 && (zName = pItem->zName)!=0 ){ |
+ With *p; |
+ for(p=pWith; p; p=p->pOuter){ |
+ int i; |
+ for(i=0; i<p->nCte; i++){ |
+ if( sqlite3StrICmp(zName, p->a[i].zName)==0 ){ |
+ *ppContext = p; |
+ return &p->a[i]; |
+ } |
+ } |
+ } |
+ } |
+ return 0; |
+} |
+ |
+/* The code generator maintains a stack of active WITH clauses |
+** with the inner-most WITH clause being at the top of the stack. |
+** |
+** This routine pushes the WITH clause passed as the second argument |
+** onto the top of the stack. If argument bFree is true, then this |
+** WITH clause will never be popped from the stack. In this case it |
+** should be freed along with the Parse object. In other cases, when |
+** bFree==0, the With object will be freed along with the SELECT |
+** statement with which it is associated. |
+*/ |
+SQLITE_PRIVATE void sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){ |
+ assert( bFree==0 || (pParse->pWith==0 && pParse->pWithToFree==0) ); |
+ if( pWith ){ |
+ assert( pParse->pWith!=pWith ); |
+ pWith->pOuter = pParse->pWith; |
+ pParse->pWith = pWith; |
+ if( bFree ) pParse->pWithToFree = pWith; |
+ } |
+} |
+ |
+/* |
+** This function checks if argument pFrom refers to a CTE declared by |
+** a WITH clause on the stack currently maintained by the parser. And, |
+** if currently processing a CTE expression, if it is a recursive |
+** reference to the current CTE. |
+** |
+** If pFrom falls into either of the two categories above, pFrom->pTab |
+** and other fields are populated accordingly. The caller should check |
+** (pFrom->pTab!=0) to determine whether or not a successful match |
+** was found. |
+** |
+** Whether or not a match is found, SQLITE_OK is returned if no error |
+** occurs. If an error does occur, an error message is stored in the |
+** parser and some error code other than SQLITE_OK returned. |
+*/ |
+static int withExpand( |
+ Walker *pWalker, |
+ struct SrcList_item *pFrom |
+){ |
+ Parse *pParse = pWalker->pParse; |
+ sqlite3 *db = pParse->db; |
+ struct Cte *pCte; /* Matched CTE (or NULL if no match) */ |
+ With *pWith; /* WITH clause that pCte belongs to */ |
+ |
+ assert( pFrom->pTab==0 ); |
+ |
+ pCte = searchWith(pParse->pWith, pFrom, &pWith); |
+ if( pCte ){ |
+ Table *pTab; |
+ ExprList *pEList; |
+ Select *pSel; |
+ Select *pLeft; /* Left-most SELECT statement */ |
+ int bMayRecursive; /* True if compound joined by UNION [ALL] */ |
+ With *pSavedWith; /* Initial value of pParse->pWith */ |
+ |
+ /* If pCte->zCteErr is non-NULL at this point, then this is an illegal |
+ ** recursive reference to CTE pCte. Leave an error in pParse and return |
+ ** early. If pCte->zCteErr is NULL, then this is not a recursive reference. |
+ ** In this case, proceed. */ |
+ if( pCte->zCteErr ){ |
+ sqlite3ErrorMsg(pParse, pCte->zCteErr, pCte->zName); |
+ return SQLITE_ERROR; |
+ } |
+ if( cannotBeFunction(pParse, pFrom) ) return SQLITE_ERROR; |
+ |
+ assert( pFrom->pTab==0 ); |
+ pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); |
+ if( pTab==0 ) return WRC_Abort; |
+ pTab->nTabRef = 1; |
+ pTab->zName = sqlite3DbStrDup(db, pCte->zName); |
+ pTab->iPKey = -1; |
+ pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); |
+ pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid; |
+ pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0); |
+ if( db->mallocFailed ) return SQLITE_NOMEM_BKPT; |
+ assert( pFrom->pSelect ); |
+ |
+ /* Check if this is a recursive CTE. */ |
+ pSel = pFrom->pSelect; |
+ bMayRecursive = ( pSel->op==TK_ALL || pSel->op==TK_UNION ); |
+ if( bMayRecursive ){ |
+ int i; |
+ SrcList *pSrc = pFrom->pSelect->pSrc; |
+ for(i=0; i<pSrc->nSrc; i++){ |
+ struct SrcList_item *pItem = &pSrc->a[i]; |
+ if( pItem->zDatabase==0 |
+ && pItem->zName!=0 |
+ && 0==sqlite3StrICmp(pItem->zName, pCte->zName) |
+ ){ |
+ pItem->pTab = pTab; |
+ pItem->fg.isRecursive = 1; |
+ pTab->nTabRef++; |
+ pSel->selFlags |= SF_Recursive; |
+ } |
+ } |
+ } |
+ |
+ /* Only one recursive reference is permitted. */ |
+ if( pTab->nTabRef>2 ){ |
+ sqlite3ErrorMsg( |
+ pParse, "multiple references to recursive table: %s", pCte->zName |
+ ); |
+ return SQLITE_ERROR; |
+ } |
+ assert( pTab->nTabRef==1 || ((pSel->selFlags&SF_Recursive) && pTab->nTabRef==2 )); |
+ |
+ pCte->zCteErr = "circular reference: %s"; |
+ pSavedWith = pParse->pWith; |
+ pParse->pWith = pWith; |
+ if( bMayRecursive ){ |
+ Select *pPrior = pSel->pPrior; |
+ assert( pPrior->pWith==0 ); |
+ pPrior->pWith = pSel->pWith; |
+ sqlite3WalkSelect(pWalker, pPrior); |
+ pPrior->pWith = 0; |
+ }else{ |
+ sqlite3WalkSelect(pWalker, pSel); |
+ } |
+ pParse->pWith = pWith; |
+ |
+ for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior); |
+ pEList = pLeft->pEList; |
+ if( pCte->pCols ){ |
+ if( pEList && pEList->nExpr!=pCte->pCols->nExpr ){ |
+ sqlite3ErrorMsg(pParse, "table %s has %d values for %d columns", |
+ pCte->zName, pEList->nExpr, pCte->pCols->nExpr |
+ ); |
+ pParse->pWith = pSavedWith; |
+ return SQLITE_ERROR; |
+ } |
+ pEList = pCte->pCols; |
+ } |
+ |
+ sqlite3ColumnsFromExprList(pParse, pEList, &pTab->nCol, &pTab->aCol); |
+ if( bMayRecursive ){ |
+ if( pSel->selFlags & SF_Recursive ){ |
+ pCte->zCteErr = "multiple recursive references: %s"; |
+ }else{ |
+ pCte->zCteErr = "recursive reference in a subquery: %s"; |
+ } |
+ sqlite3WalkSelect(pWalker, pSel); |
+ } |
+ pCte->zCteErr = 0; |
+ pParse->pWith = pSavedWith; |
+ } |
+ |
+ return SQLITE_OK; |
+} |
+#endif |
+ |
+#ifndef SQLITE_OMIT_CTE |
+/* |
+** If the SELECT passed as the second argument has an associated WITH |
+** clause, pop it from the stack stored as part of the Parse object. |
+** |
+** This function is used as the xSelectCallback2() callback by |
+** sqlite3SelectExpand() when walking a SELECT tree to resolve table |
+** names and other FROM clause elements. |
+*/ |
+static void selectPopWith(Walker *pWalker, Select *p){ |
+ Parse *pParse = pWalker->pParse; |
+ if( pParse->pWith && p->pPrior==0 ){ |
+ With *pWith = findRightmost(p)->pWith; |
+ if( pWith!=0 ){ |
+ assert( pParse->pWith==pWith ); |
+ pParse->pWith = pWith->pOuter; |
+ } |
+ } |
+} |
+#else |
+#define selectPopWith 0 |
+#endif |
+ |
+/* |
+** This routine is a Walker callback for "expanding" a SELECT statement. |
+** "Expanding" means to do the following: |
+** |
+** (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 persistent representation |
+** of the view. |
+** |
+** (3) Add terms to the WHERE clause to accommodate 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. |
+** |
+*/ |
+static int selectExpander(Walker *pWalker, Select *p){ |
+ Parse *pParse = pWalker->pParse; |
+ int i, j, k; |
+ SrcList *pTabList; |
+ ExprList *pEList; |
+ struct SrcList_item *pFrom; |
+ sqlite3 *db = pParse->db; |
+ Expr *pE, *pRight, *pExpr; |
+ u16 selFlags = p->selFlags; |
+ |
+ p->selFlags |= SF_Expanded; |
+ if( db->mallocFailed ){ |
+ return WRC_Abort; |
+ } |
+ if( NEVER(p->pSrc==0) || (selFlags & SF_Expanded)!=0 ){ |
+ return WRC_Prune; |
+ } |
+ pTabList = p->pSrc; |
+ pEList = p->pEList; |
+ if( p->pWith ){ |
+ sqlite3WithPush(pParse, p->pWith, 0); |
+ } |
+ |
+ /* Make sure cursor numbers have been assigned to all entries in |
+ ** the FROM clause of the SELECT statement. |
+ */ |
+ sqlite3SrcListAssignCursors(pParse, pTabList); |
+ |
+ /* 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; |
+ assert( pFrom->fg.isRecursive==0 || pFrom->pTab!=0 ); |
+ if( pFrom->fg.isRecursive ) continue; |
+ assert( pFrom->pTab==0 ); |
+#ifndef SQLITE_OMIT_CTE |
+ if( withExpand(pWalker, pFrom) ) return WRC_Abort; |
+ if( pFrom->pTab ) {} else |
+#endif |
+ if( pFrom->zName==0 ){ |
+#ifndef SQLITE_OMIT_SUBQUERY |
+ Select *pSel = pFrom->pSelect; |
+ /* A sub-query in the FROM clause of a SELECT */ |
+ assert( pSel!=0 ); |
+ assert( pFrom->pTab==0 ); |
+ if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort; |
+ pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); |
+ if( pTab==0 ) return WRC_Abort; |
+ pTab->nTabRef = 1; |
+ pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab); |
+ while( pSel->pPrior ){ pSel = pSel->pPrior; } |
+ sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol); |
+ pTab->iPKey = -1; |
+ pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); |
+ pTab->tabFlags |= TF_Ephemeral; |
+#endif |
+ }else{ |
+ /* An ordinary table or view name in the FROM clause */ |
+ assert( pFrom->pTab==0 ); |
+ pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom); |
+ if( pTab==0 ) return WRC_Abort; |
+ if( pTab->nTabRef>=0xffff ){ |
+ sqlite3ErrorMsg(pParse, "too many references to \"%s\": max 65535", |
+ pTab->zName); |
+ pFrom->pTab = 0; |
+ return WRC_Abort; |
+ } |
+ pTab->nTabRef++; |
+ if( !IsVirtual(pTab) && cannotBeFunction(pParse, pFrom) ){ |
+ return WRC_Abort; |
+ } |
+#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE) |
+ if( IsVirtual(pTab) || pTab->pSelect ){ |
+ i16 nCol; |
+ if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort; |
+ assert( pFrom->pSelect==0 ); |
+ pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0); |
+ sqlite3SelectSetName(pFrom->pSelect, pTab->zName); |
+ nCol = pTab->nCol; |
+ pTab->nCol = -1; |
+ sqlite3WalkSelect(pWalker, pFrom->pSelect); |
+ pTab->nCol = nCol; |
+ } |
+#endif |
+ } |
+ |
+ /* Locate the index named by the INDEXED BY clause, if any. */ |
+ if( sqlite3IndexedByLookup(pParse, pFrom) ){ |
+ return WRC_Abort; |
+ } |
+ } |
+ |
+ /* Process NATURAL keywords, and ON and USING clauses of joins. |
+ */ |
+ if( db->mallocFailed || sqliteProcessJoin(pParse, p) ){ |
+ return WRC_Abort; |
+ } |
+ |
+ /* 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_ASTERISK operator for each "*" that it found in the column |
+ ** list. The following code just has to locate the TK_ASTERISK |
+ ** 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++){ |
+ pE = pEList->a[k].pExpr; |
+ if( pE->op==TK_ASTERISK ) break; |
+ assert( pE->op!=TK_DOT || pE->pRight!=0 ); |
+ assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) ); |
+ if( pE->op==TK_DOT && pE->pRight->op==TK_ASTERISK ) break; |
+ } |
+ 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++){ |
+ pE = a[k].pExpr; |
+ pRight = pE->pRight; |
+ assert( pE->op!=TK_DOT || pRight!=0 ); |
+ if( pE->op!=TK_ASTERISK |
+ && (pE->op!=TK_DOT || pRight->op!=TK_ASTERISK) |
+ ){ |
+ /* This particular expression does not need to be expanded. |
+ */ |
+ pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr); |
+ if( pNew ){ |
+ pNew->a[pNew->nExpr-1].zName = a[k].zName; |
+ pNew->a[pNew->nExpr-1].zSpan = a[k].zSpan; |
+ a[k].zName = 0; |
+ a[k].zSpan = 0; |
+ } |
+ a[k].pExpr = 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 = 0; /* text of name of TABLE */ |
+ if( pE->op==TK_DOT ){ |
+ assert( pE->pLeft!=0 ); |
+ assert( !ExprHasProperty(pE->pLeft, EP_IntValue) ); |
+ zTName = pE->pLeft->u.zToken; |
+ } |
+ for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ |
+ Table *pTab = pFrom->pTab; |
+ Select *pSub = pFrom->pSelect; |
+ char *zTabName = pFrom->zAlias; |
+ const char *zSchemaName = 0; |
+ int iDb; |
+ if( zTabName==0 ){ |
+ zTabName = pTab->zName; |
+ } |
+ if( db->mallocFailed ) break; |
+ if( pSub==0 || (pSub->selFlags & SF_NestedFrom)==0 ){ |
+ pSub = 0; |
+ if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ |
+ continue; |
+ } |
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
+ zSchemaName = iDb>=0 ? db->aDb[iDb].zDbSName : "*"; |
+ } |
+ for(j=0; j<pTab->nCol; j++){ |
+ char *zName = pTab->aCol[j].zName; |
+ char *zColname; /* The computed column name */ |
+ char *zToFree; /* Malloced string that needs to be freed */ |
+ Token sColname; /* Computed column name as a token */ |
+ |
+ assert( zName ); |
+ if( zTName && pSub |
+ && sqlite3MatchSpanName(pSub->pEList->a[j].zSpan, 0, zTName, 0)==0 |
+ ){ |
+ continue; |
+ } |
+ |
+ /* If a column is marked as 'hidden', omit it from the expanded |
+ ** result-set list unless the SELECT has the SF_IncludeHidden |
+ ** bit set. |
+ */ |
+ if( (p->selFlags & SF_IncludeHidden)==0 |
+ && IsHiddenColumn(&pTab->aCol[j]) |
+ ){ |
+ continue; |
+ } |
+ tableSeen = 1; |
+ |
+ if( i>0 && zTName==0 ){ |
+ if( (pFrom->fg.jointype & JT_NATURAL)!=0 |
+ && tableAndColumnIndex(pTabList, i, zName, 0, 0) |
+ ){ |
+ /* In a NATURAL join, omit the join columns from the |
+ ** table to the right of the join */ |
+ continue; |
+ } |
+ if( sqlite3IdListIndex(pFrom->pUsing, zName)>=0 ){ |
+ /* In a join with a USING clause, omit columns in the |
+ ** using clause from the table on the right. */ |
+ continue; |
+ } |
+ } |
+ pRight = sqlite3Expr(db, TK_ID, zName); |
+ zColname = zName; |
+ zToFree = 0; |
+ if( longNames || pTabList->nSrc>1 ){ |
+ Expr *pLeft; |
+ pLeft = sqlite3Expr(db, TK_ID, zTabName); |
+ pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight); |
+ if( zSchemaName ){ |
+ pLeft = sqlite3Expr(db, TK_ID, zSchemaName); |
+ pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr); |
+ } |
+ if( longNames ){ |
+ zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName); |
+ zToFree = zColname; |
+ } |
+ }else{ |
+ pExpr = pRight; |
+ } |
+ pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); |
+ sqlite3TokenInit(&sColname, zColname); |
+ sqlite3ExprListSetName(pParse, pNew, &sColname, 0); |
+ if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){ |
+ struct ExprList_item *pX = &pNew->a[pNew->nExpr-1]; |
+ if( pSub ){ |
+ pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan); |
+ testcase( pX->zSpan==0 ); |
+ }else{ |
+ pX->zSpan = sqlite3MPrintf(db, "%s.%s.%s", |
+ zSchemaName, zTabName, zColname); |
+ testcase( pX->zSpan==0 ); |
+ } |
+ pX->bSpanIsTab = 1; |
+ } |
+ sqlite3DbFree(db, zToFree); |
+ } |
+ } |
+ if( !tableSeen ){ |
+ if( zTName ){ |
+ sqlite3ErrorMsg(pParse, "no such table: %s", zTName); |
+ }else{ |
+ sqlite3ErrorMsg(pParse, "no tables specified"); |
+ } |
+ } |
+ } |
+ } |
+ 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"); |
+ return WRC_Abort; |
+ } |
+#endif |
+ return WRC_Continue; |
+} |
+ |
+/* |
+** No-op routine for the parse-tree walker. |
+** |
+** When this routine is the Walker.xExprCallback then expression trees |
+** are walked without any actions being taken at each node. Presumably, |
+** when this routine is used for Walker.xExprCallback then |
+** Walker.xSelectCallback is set to do something useful for every |
+** subquery in the parser tree. |
+*/ |
+SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){ |
+ UNUSED_PARAMETER2(NotUsed, NotUsed2); |
+ return WRC_Continue; |
+} |
+ |
+/* |
+** This routine "expands" a SELECT statement and all of its subqueries. |
+** For additional information on what it means to "expand" a SELECT |
+** statement, see the comment on the selectExpand worker callback above. |
+** |
+** Expanding a SELECT statement is the first step in processing a |
+** SELECT statement. The SELECT statement must be expanded before |
+** name resolution is performed. |
+** |
+** If anything goes wrong, an error message is written into pParse. |
+** The calling function can detect the problem by looking at pParse->nErr |
+** and/or pParse->db->mallocFailed. |
+*/ |
+static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){ |
+ Walker w; |
+ memset(&w, 0, sizeof(w)); |
+ w.xExprCallback = sqlite3ExprWalkNoop; |
+ w.pParse = pParse; |
+ if( pParse->hasCompound ){ |
+ w.xSelectCallback = convertCompoundSelectToSubquery; |
+ sqlite3WalkSelect(&w, pSelect); |
+ } |
+ w.xSelectCallback = selectExpander; |
+ w.xSelectCallback2 = selectPopWith; |
+ sqlite3WalkSelect(&w, pSelect); |
+} |
+ |
+ |
+#ifndef SQLITE_OMIT_SUBQUERY |
+/* |
+** This is a Walker.xSelectCallback callback for the sqlite3SelectTypeInfo() |
+** interface. |
+** |
+** For each FROM-clause subquery, add Column.zType and Column.zColl |
+** information to the Table structure that represents the result set |
+** of that subquery. |
+** |
+** The Table structure that represents the result set was constructed |
+** by selectExpander() but the type and collation information was omitted |
+** at that point because identifiers had not yet been resolved. This |
+** routine is called after identifier resolution. |
+*/ |
+static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){ |
+ Parse *pParse; |
+ int i; |
+ SrcList *pTabList; |
+ struct SrcList_item *pFrom; |
+ |
+ assert( p->selFlags & SF_Resolved ); |
+ assert( (p->selFlags & SF_HasTypeInfo)==0 ); |
+ p->selFlags |= SF_HasTypeInfo; |
+ pParse = pWalker->pParse; |
+ pTabList = p->pSrc; |
+ for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ |
+ Table *pTab = pFrom->pTab; |
+ assert( pTab!=0 ); |
+ if( (pTab->tabFlags & TF_Ephemeral)!=0 ){ |
+ /* A sub-query in the FROM clause of a SELECT */ |
+ Select *pSel = pFrom->pSelect; |
+ if( pSel ){ |
+ while( pSel->pPrior ) pSel = pSel->pPrior; |
+ sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSel); |
+ } |
+ } |
+ } |
+} |
+#endif |
+ |
+ |
+/* |
+** This routine adds datatype and collating sequence information to |
+** the Table structures of all FROM-clause subqueries in a |
+** SELECT statement. |
+** |
+** Use this routine after name resolution. |
+*/ |
+static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){ |
+#ifndef SQLITE_OMIT_SUBQUERY |
+ Walker w; |
+ memset(&w, 0, sizeof(w)); |
+ w.xSelectCallback2 = selectAddSubqueryTypeInfo; |
+ w.xExprCallback = sqlite3ExprWalkNoop; |
+ w.pParse = pParse; |
+ sqlite3WalkSelect(&w, pSelect); |
+#endif |
+} |
+ |
+ |
+/* |
+** This routine sets up a SELECT statement for processing. The |
+** following is accomplished: |
+** |
+** * VDBE Cursor numbers are assigned to all FROM-clause terms. |
+** * Ephemeral Table objects are created for all FROM-clause subqueries. |
+** * ON and USING clauses are shifted into WHERE statements |
+** * Wildcards "*" and "TABLE.*" in result sets are expanded. |
+** * Identifiers in expression are matched to tables. |
+** |
+** This routine acts recursively on all subqueries within the SELECT. |
+*/ |
+SQLITE_PRIVATE void sqlite3SelectPrep( |
+ Parse *pParse, /* The parser context */ |
+ Select *p, /* The SELECT statement being coded. */ |
+ NameContext *pOuterNC /* Name context for container */ |
+){ |
+ sqlite3 *db; |
+ if( NEVER(p==0) ) return; |
+ db = pParse->db; |
+ if( db->mallocFailed ) return; |
+ if( p->selFlags & SF_HasTypeInfo ) return; |
+ sqlite3SelectExpand(pParse, p); |
+ if( pParse->nErr || db->mallocFailed ) return; |
+ sqlite3ResolveSelectNames(pParse, p, pOuterNC); |
+ if( pParse->nErr || db->mallocFailed ) return; |
+ sqlite3SelectAddTypeInfo(pParse, p); |
+} |
+ |
+/* |
+** Reset the aggregate accumulator. |
+** |
+** The aggregate accumulator is a set of memory cells that hold |
+** intermediate results while calculating an aggregate. This |
+** routine generates code that 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; |
+ int nReg = pAggInfo->nFunc + pAggInfo->nColumn; |
+ if( nReg==0 ) return; |
+#ifdef SQLITE_DEBUG |
+ /* Verify that all AggInfo registers are within the range specified by |
+ ** AggInfo.mnReg..AggInfo.mxReg */ |
+ assert( nReg==pAggInfo->mxReg-pAggInfo->mnReg+1 ); |
+ for(i=0; i<pAggInfo->nColumn; i++){ |
+ assert( pAggInfo->aCol[i].iMem>=pAggInfo->mnReg |
+ && pAggInfo->aCol[i].iMem<=pAggInfo->mxReg ); |
+ } |
+ for(i=0; i<pAggInfo->nFunc; i++){ |
+ assert( pAggInfo->aFunc[i].iMem>=pAggInfo->mnReg |
+ && pAggInfo->aFunc[i].iMem<=pAggInfo->mxReg ); |
+ } |
+#endif |
+ sqlite3VdbeAddOp3(v, OP_Null, 0, pAggInfo->mnReg, pAggInfo->mxReg); |
+ for(pFunc=pAggInfo->aFunc, i=0; i<pAggInfo->nFunc; i++, pFunc++){ |
+ if( pFunc->iDistinct>=0 ){ |
+ Expr *pE = pFunc->pExpr; |
+ assert( !ExprHasProperty(pE, EP_xIsSelect) ); |
+ if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){ |
+ sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one " |
+ "argument"); |
+ pFunc->iDistinct = -1; |
+ }else{ |
+ KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->x.pList, 0, 0); |
+ sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 0, |
+ (char*)pKeyInfo, P4_KEYINFO); |
+ } |
+ } |
+ } |
+} |
+ |
+/* |
+** 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->x.pList; |
+ assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) ); |
+ sqlite3VdbeAddOp2(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0); |
+ sqlite3VdbeAppendP4(v, 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; |
+ int regHit = 0; |
+ int addrHitTest = 0; |
+ 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->x.pList; |
+ assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) ); |
+ if( pList ){ |
+ nArg = pList->nExpr; |
+ regAgg = sqlite3GetTempRange(pParse, nArg); |
+ sqlite3ExprCodeExprList(pParse, pList, regAgg, 0, SQLITE_ECEL_DUP); |
+ }else{ |
+ nArg = 0; |
+ regAgg = 0; |
+ } |
+ if( pF->iDistinct>=0 ){ |
+ addrNext = sqlite3VdbeMakeLabel(v); |
+ testcase( nArg==0 ); /* Error condition */ |
+ testcase( nArg>1 ); /* Also an error */ |
+ codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg); |
+ } |
+ if( pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ |
+ CollSeq *pColl = 0; |
+ struct ExprList_item *pItem; |
+ int j; |
+ assert( pList!=0 ); /* pList!=0 if pF->pFunc has NEEDCOLL */ |
+ for(j=0, pItem=pList->a; !pColl && j<nArg; j++, pItem++){ |
+ pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr); |
+ } |
+ if( !pColl ){ |
+ pColl = pParse->db->pDfltColl; |
+ } |
+ if( regHit==0 && pAggInfo->nAccumulator ) regHit = ++pParse->nMem; |
+ sqlite3VdbeAddOp4(v, OP_CollSeq, regHit, 0, 0, (char *)pColl, P4_COLLSEQ); |
+ } |
+ sqlite3VdbeAddOp3(v, OP_AggStep0, 0, regAgg, pF->iMem); |
+ sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF); |
+ sqlite3VdbeChangeP5(v, (u8)nArg); |
+ sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg); |
+ sqlite3ReleaseTempRange(pParse, regAgg, nArg); |
+ if( addrNext ){ |
+ sqlite3VdbeResolveLabel(v, addrNext); |
+ sqlite3ExprCacheClear(pParse); |
+ } |
+ } |
+ |
+ /* Before populating the accumulator registers, clear the column cache. |
+ ** Otherwise, if any of the required column values are already present |
+ ** in registers, sqlite3ExprCode() may use OP_SCopy to copy the value |
+ ** to pC->iMem. But by the time the value is used, the original register |
+ ** may have been used, invalidating the underlying buffer holding the |
+ ** text or blob value. See ticket [883034dcb5]. |
+ ** |
+ ** Another solution would be to change the OP_SCopy used to copy cached |
+ ** values to an OP_Copy. |
+ */ |
+ if( regHit ){ |
+ addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit); VdbeCoverage(v); |
+ } |
+ sqlite3ExprCacheClear(pParse); |
+ for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){ |
+ sqlite3ExprCode(pParse, pC->pExpr, pC->iMem); |
+ } |
+ pAggInfo->directMode = 0; |
+ sqlite3ExprCacheClear(pParse); |
+ if( addrHitTest ){ |
+ sqlite3VdbeJumpHere(v, addrHitTest); |
+ } |
+} |
+ |
+/* |
+** Add a single OP_Explain instruction to the VDBE to explain a simple |
+** count(*) query ("SELECT count(*) FROM pTab"). |
+*/ |
+#ifndef SQLITE_OMIT_EXPLAIN |
+static void explainSimpleCount( |
+ Parse *pParse, /* Parse context */ |
+ Table *pTab, /* Table being queried */ |
+ Index *pIdx /* Index used to optimize scan, or NULL */ |
+){ |
+ if( pParse->explain==2 ){ |
+ int bCover = (pIdx!=0 && (HasRowid(pTab) || !IsPrimaryKeyIndex(pIdx))); |
+ char *zEqp = sqlite3MPrintf(pParse->db, "SCAN TABLE %s%s%s", |
+ pTab->zName, |
+ bCover ? " USING COVERING INDEX " : "", |
+ bCover ? pIdx->zName : "" |
+ ); |
+ sqlite3VdbeAddOp4( |
+ pParse->pVdbe, OP_Explain, pParse->iSelectId, 0, 0, zEqp, P4_DYNAMIC |
+ ); |
+ } |
+} |
+#else |
+# define explainSimpleCount(a,b,c) |
+#endif |
+ |
+/* |
+** Generate code for the SELECT statement given in the p argument. |
+** |
+** The results are returned according to the SelectDest structure. |
+** See comments in sqliteInt.h for further information. |
+** |
+** 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. |
+*/ |
+SQLITE_PRIVATE int sqlite3Select( |
+ Parse *pParse, /* The parser context */ |
+ Select *p, /* The SELECT statement being coded. */ |
+ SelectDest *pDest /* What to do with the query results */ |
+){ |
+ 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 = 0; /* List of columns to extract. */ |
+ SrcList *pTabList; /* List of tables to select from */ |
+ Expr *pWhere; /* The WHERE clause. May be NULL */ |
+ ExprList *pGroupBy; /* The GROUP BY clause. May be NULL */ |
+ Expr *pHaving; /* The HAVING clause. May be NULL */ |
+ int rc = 1; /* Value to return from this function */ |
+ DistinctCtx sDistinct; /* Info on how to code the DISTINCT keyword */ |
+ SortCtx sSort; /* Info on how to code the ORDER BY clause */ |
+ AggInfo sAggInfo; /* Information used by aggregate queries */ |
+ int iEnd; /* Address of the end of the query */ |
+ sqlite3 *db; /* The database connection */ |
+ |
+#ifndef SQLITE_OMIT_EXPLAIN |
+ int iRestoreSelectId = pParse->iSelectId; |
+ pParse->iSelectId = pParse->iNextSelectId++; |
+#endif |
+ |
+ 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)); |
+#if SELECTTRACE_ENABLED |
+ pParse->nSelectIndent++; |
+ SELECTTRACE(1,pParse,p, ("begin processing:\n")); |
+ if( sqlite3SelectTrace & 0x100 ){ |
+ sqlite3TreeViewSelect(0, p, 0); |
+ } |
+#endif |
+ |
+ assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistFifo ); |
+ assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo ); |
+ assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistQueue ); |
+ assert( p->pOrderBy==0 || pDest->eDest!=SRT_Queue ); |
+ if( IgnorableOrderby(pDest) ){ |
+ assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union || |
+ pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard || |
+ pDest->eDest==SRT_Queue || pDest->eDest==SRT_DistFifo || |
+ pDest->eDest==SRT_DistQueue || pDest->eDest==SRT_Fifo); |
+ /* If ORDER BY makes no difference in the output then neither does |
+ ** DISTINCT so it can be removed too. */ |
+ sqlite3ExprListDelete(db, p->pOrderBy); |
+ p->pOrderBy = 0; |
+ p->selFlags &= ~SF_Distinct; |
+ } |
+ sqlite3SelectPrep(pParse, p, 0); |
+ memset(&sSort, 0, sizeof(sSort)); |
+ sSort.pOrderBy = p->pOrderBy; |
+ pTabList = p->pSrc; |
+ if( pParse->nErr || db->mallocFailed ){ |
+ goto select_end; |
+ } |
+ assert( p->pEList!=0 ); |
+ isAgg = (p->selFlags & SF_Aggregate)!=0; |
+#if SELECTTRACE_ENABLED |
+ if( sqlite3SelectTrace & 0x100 ){ |
+ SELECTTRACE(0x100,pParse,p, ("after name resolution:\n")); |
+ sqlite3TreeViewSelect(0, p, 0); |
+ } |
+#endif |
+ |
+ /* Try to flatten subqueries in the FROM clause up into the main query |
+ */ |
+#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]; |
+ Select *pSub = pItem->pSelect; |
+ int isAggSub; |
+ Table *pTab = pItem->pTab; |
+ if( pSub==0 ) continue; |
+ |
+ /* Catch mismatch in the declared columns of a view and the number of |
+ ** columns in the SELECT on the RHS */ |
+ if( pTab->nCol!=pSub->pEList->nExpr ){ |
+ sqlite3ErrorMsg(pParse, "expected %d columns for '%s' but got %d", |
+ pTab->nCol, pTab->zName, pSub->pEList->nExpr); |
+ goto select_end; |
+ } |
+ |
+ isAggSub = (pSub->selFlags & SF_Aggregate)!=0; |
+ if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){ |
+ /* This subquery can be absorbed into its parent. */ |
+ if( isAggSub ){ |
+ isAgg = 1; |
+ p->selFlags |= SF_Aggregate; |
+ } |
+ i = -1; |
+ } |
+ pTabList = p->pSrc; |
+ if( db->mallocFailed ) goto select_end; |
+ if( !IgnorableOrderby(pDest) ){ |
+ sSort.pOrderBy = p->pOrderBy; |
+ } |
+ } |
+#endif |
+ |
+ /* Get a pointer the VDBE under construction, allocating a new VDBE if one |
+ ** does not already exist */ |
+ v = sqlite3GetVdbe(pParse); |
+ if( v==0 ) goto select_end; |
+ |
+#ifndef SQLITE_OMIT_COMPOUND_SELECT |
+ /* Handle compound SELECT statements using the separate multiSelect() |
+ ** procedure. |
+ */ |
+ if( p->pPrior ){ |
+ rc = multiSelect(pParse, p, pDest); |
+ explainSetInteger(pParse->iSelectId, iRestoreSelectId); |
+#if SELECTTRACE_ENABLED |
+ SELECTTRACE(1,pParse,p,("end compound-select processing\n")); |
+ pParse->nSelectIndent--; |
+#endif |
+ return rc; |
+ } |
+#endif |
+ |
+ /* Generate code for all sub-queries in the FROM clause |
+ */ |
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) |
+ for(i=0; i<pTabList->nSrc; i++){ |
+ struct SrcList_item *pItem = &pTabList->a[i]; |
+ SelectDest dest; |
+ Select *pSub = pItem->pSelect; |
+ if( pSub==0 ) continue; |
+ |
+ /* Sometimes the code for a subquery will be generated more than |
+ ** once, if the subquery is part of the WHERE clause in a LEFT JOIN, |
+ ** for example. In that case, do not regenerate the code to manifest |
+ ** a view or the co-routine to implement a view. The first instance |
+ ** is sufficient, though the subroutine to manifest the view does need |
+ ** to be invoked again. */ |
+ if( pItem->addrFillSub ){ |
+ if( pItem->fg.viaCoroutine==0 ){ |
+ sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub); |
+ } |
+ continue; |
+ } |
+ |
+ /* Increment Parse.nHeight by the height of the largest expression |
+ ** tree referred 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); |
+ |
+ /* Make copies of constant WHERE-clause terms in the outer query down |
+ ** inside the subquery. This can help the subquery to run more efficiently. |
+ */ |
+ if( (pItem->fg.jointype & JT_OUTER)==0 |
+ && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor) |
+ ){ |
+#if SELECTTRACE_ENABLED |
+ if( sqlite3SelectTrace & 0x100 ){ |
+ SELECTTRACE(0x100,pParse,p,("After WHERE-clause push-down:\n")); |
+ sqlite3TreeViewSelect(0, p, 0); |
+ } |
+#endif |
+ } |
+ |
+ /* Generate code to implement the subquery |
+ ** |
+ ** The subquery is implemented as a co-routine if all of these are true: |
+ ** (1) The subquery is guaranteed to be the outer loop (so that it |
+ ** does not need to be computed more than once) |
+ ** (2) The ALL keyword after SELECT is omitted. (Applications are |
+ ** allowed to say "SELECT ALL" instead of just "SELECT" to disable |
+ ** the use of co-routines.) |
+ ** (3) Co-routines are not disabled using sqlite3_test_control() |
+ ** with SQLITE_TESTCTRL_OPTIMIZATIONS. |
+ ** |
+ ** TODO: Are there other reasons beside (1) to use a co-routine |
+ ** implementation? |
+ */ |
+ if( i==0 |
+ && (pTabList->nSrc==1 |
+ || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0) /* (1) */ |
+ && (p->selFlags & SF_All)==0 /* (2) */ |
+ && OptimizationEnabled(db, SQLITE_SubqCoroutine) /* (3) */ |
+ ){ |
+ /* Implement a co-routine that will return a single row of the result |
+ ** set on each invocation. |
+ */ |
+ int addrTop = sqlite3VdbeCurrentAddr(v)+1; |
+ pItem->regReturn = ++pParse->nMem; |
+ sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop); |
+ VdbeComment((v, "%s", pItem->pTab->zName)); |
+ pItem->addrFillSub = addrTop; |
+ sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn); |
+ explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); |
+ sqlite3Select(pParse, pSub, &dest); |
+ pItem->pTab->nRowLogEst = pSub->nSelectRow; |
+ pItem->fg.viaCoroutine = 1; |
+ pItem->regResult = dest.iSdst; |
+ sqlite3VdbeEndCoroutine(v, pItem->regReturn); |
+ sqlite3VdbeJumpHere(v, addrTop-1); |
+ sqlite3ClearTempRegCache(pParse); |
+ }else{ |
+ /* Generate a subroutine that will fill an ephemeral table with |
+ ** the content of this subquery. pItem->addrFillSub will point |
+ ** to the address of the generated subroutine. pItem->regReturn |
+ ** is a register allocated to hold the subroutine return address |
+ */ |
+ int topAddr; |
+ int onceAddr = 0; |
+ int retAddr; |
+ assert( pItem->addrFillSub==0 ); |
+ pItem->regReturn = ++pParse->nMem; |
+ topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn); |
+ pItem->addrFillSub = topAddr+1; |
+ if( pItem->fg.isCorrelated==0 ){ |
+ /* If the subquery is not correlated and if we are not inside of |
+ ** a trigger, then we only need to compute the value of the subquery |
+ ** once. */ |
+ onceAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); |
+ VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName)); |
+ }else{ |
+ VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName)); |
+ } |
+ sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); |
+ explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); |
+ sqlite3Select(pParse, pSub, &dest); |
+ pItem->pTab->nRowLogEst = pSub->nSelectRow; |
+ if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr); |
+ retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn); |
+ VdbeComment((v, "end %s", pItem->pTab->zName)); |
+ sqlite3VdbeChangeP1(v, topAddr, retAddr); |
+ sqlite3ClearTempRegCache(pParse); |
+ } |
+ if( db->mallocFailed ) goto select_end; |
+ pParse->nHeight -= sqlite3SelectExprHeight(p); |
+ } |
+#endif |
+ |
+ /* Various elements of the SELECT copied into local variables for |
+ ** convenience */ |
+ pEList = p->pEList; |
+ pWhere = p->pWhere; |
+ pGroupBy = p->pGroupBy; |
+ pHaving = p->pHaving; |
+ sDistinct.isTnct = (p->selFlags & SF_Distinct)!=0; |
+ |
+#if SELECTTRACE_ENABLED |
+ if( sqlite3SelectTrace & 0x400 ){ |
+ SELECTTRACE(0x400,pParse,p,("After all FROM-clause analysis:\n")); |
+ sqlite3TreeViewSelect(0, p, 0); |
+ } |
+#endif |
+ |
+ /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and |
+ ** if the select-list is the same as the ORDER BY list, then this query |
+ ** can be rewritten as a GROUP BY. In other words, this: |
+ ** |
+ ** SELECT DISTINCT xyz FROM ... ORDER BY xyz |
+ ** |
+ ** is transformed to: |
+ ** |
+ ** SELECT xyz FROM ... GROUP BY xyz ORDER BY xyz |
+ ** |
+ ** The second form is preferred as a single index (or temp-table) may be |
+ ** used for both the ORDER BY and DISTINCT processing. As originally |
+ ** written the query must use a temp-table for at least one of the ORDER |
+ ** BY and DISTINCT, and an index or separate temp-table for the other. |
+ */ |
+ if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct |
+ && sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0 |
+ ){ |
+ p->selFlags &= ~SF_Distinct; |
+ pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0); |
+ /* Notice that even thought SF_Distinct has been cleared from p->selFlags, |
+ ** the sDistinct.isTnct is still set. Hence, isTnct represents the |
+ ** original setting of the SF_Distinct flag, not the current setting */ |
+ assert( sDistinct.isTnct ); |
+ |
+#if SELECTTRACE_ENABLED |
+ if( sqlite3SelectTrace & 0x400 ){ |
+ SELECTTRACE(0x400,pParse,p,("Transform DISTINCT into GROUP BY:\n")); |
+ sqlite3TreeViewSelect(0, p, 0); |
+ } |
+#endif |
+ } |
+ |
+ /* If there is an ORDER BY clause, then create an ephemeral index to |
+ ** do the sorting. But this sorting ephemeral 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 sSort.addrSortIndex variable is used to facilitate |
+ ** that change. |
+ */ |
+ if( sSort.pOrderBy ){ |
+ KeyInfo *pKeyInfo; |
+ pKeyInfo = keyInfoFromExprList(pParse, sSort.pOrderBy, 0, pEList->nExpr); |
+ sSort.iECursor = pParse->nTab++; |
+ sSort.addrSortIndex = |
+ sqlite3VdbeAddOp4(v, OP_OpenEphemeral, |
+ sSort.iECursor, sSort.pOrderBy->nExpr+1+pEList->nExpr, 0, |
+ (char*)pKeyInfo, P4_KEYINFO |
+ ); |
+ }else{ |
+ sSort.addrSortIndex = -1; |
+ } |
+ |
+ /* If the output is destined for a temporary table, open that table. |
+ */ |
+ if( pDest->eDest==SRT_EphemTab ){ |
+ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest->iSDParm, pEList->nExpr); |
+ } |
+ |
+ /* Set the limiter. |
+ */ |
+ iEnd = sqlite3VdbeMakeLabel(v); |
+ if( (p->selFlags & SF_FixedLimit)==0 ){ |
+ p->nSelectRow = 320; /* 4 billion rows */ |
+ } |
+ computeLimitRegisters(pParse, p, iEnd); |
+ if( p->iLimit==0 && sSort.addrSortIndex>=0 ){ |
+ sqlite3VdbeChangeOpcode(v, sSort.addrSortIndex, OP_SorterOpen); |
+ sSort.sortFlags |= SORTFLAG_UseSorter; |
+ } |
+ |
+ /* Open an ephemeral index to use for the distinct set. |
+ */ |
+ if( p->selFlags & SF_Distinct ){ |
+ sDistinct.tabTnct = pParse->nTab++; |
+ sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, |
+ sDistinct.tabTnct, 0, 0, |
+ (char*)keyInfoFromExprList(pParse, p->pEList,0,0), |
+ P4_KEYINFO); |
+ sqlite3VdbeChangeP5(v, BTREE_UNORDERED); |
+ sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED; |
+ }else{ |
+ sDistinct.eTnctType = WHERE_DISTINCT_NOOP; |
+ } |
+ |
+ if( !isAgg && pGroupBy==0 ){ |
+ /* No aggregate functions and no GROUP BY clause */ |
+ u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0); |
+ assert( WHERE_USE_LIMIT==SF_FixedLimit ); |
+ wctrlFlags |= p->selFlags & SF_FixedLimit; |
+ |
+ /* Begin the database scan. */ |
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy, |
+ p->pEList, wctrlFlags, p->nSelectRow); |
+ if( pWInfo==0 ) goto select_end; |
+ if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){ |
+ p->nSelectRow = sqlite3WhereOutputRowCount(pWInfo); |
+ } |
+ if( sDistinct.isTnct && sqlite3WhereIsDistinct(pWInfo) ){ |
+ sDistinct.eTnctType = sqlite3WhereIsDistinct(pWInfo); |
+ } |
+ if( sSort.pOrderBy ){ |
+ sSort.nOBSat = sqlite3WhereIsOrdered(pWInfo); |
+ sSort.bOrderedInnerLoop = sqlite3WhereOrderedInnerLoop(pWInfo); |
+ if( sSort.nOBSat==sSort.pOrderBy->nExpr ){ |
+ sSort.pOrderBy = 0; |
+ } |
+ } |
+ |
+ /* 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( sSort.addrSortIndex>=0 && sSort.pOrderBy==0 ){ |
+ sqlite3VdbeChangeToNoop(v, sSort.addrSortIndex); |
+ } |
+ |
+ /* Use the standard inner loop. */ |
+ selectInnerLoop(pParse, p, pEList, -1, &sSort, &sDistinct, pDest, |
+ sqlite3WhereContinueLabel(pWInfo), |
+ sqlite3WhereBreakLabel(pWInfo)); |
+ |
+ /* End the database scan loop. |
+ */ |
+ sqlite3WhereEnd(pWInfo); |
+ }else{ |
+ /* This case when there exist aggregate functions or a GROUP BY clause |
+ ** or both */ |
+ 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 */ |
+ int addrEnd; /* End of processing for this SELECT */ |
+ int sortPTab = 0; /* Pseudotable used to decode sorting results */ |
+ int sortOut = 0; /* Output register from the sorter */ |
+ int orderByGrp = 0; /* True if the GROUP BY and ORDER BY are the same */ |
+ |
+ /* Remove any and all aliases between the result set and the |
+ ** GROUP BY clause. |
+ */ |
+ if( pGroupBy ){ |
+ int k; /* Loop counter */ |
+ struct ExprList_item *pItem; /* For looping over expression in a list */ |
+ |
+ for(k=p->pEList->nExpr, pItem=p->pEList->a; k>0; k--, pItem++){ |
+ pItem->u.x.iAlias = 0; |
+ } |
+ for(k=pGroupBy->nExpr, pItem=pGroupBy->a; k>0; k--, pItem++){ |
+ pItem->u.x.iAlias = 0; |
+ } |
+ assert( 66==sqlite3LogEst(100) ); |
+ if( p->nSelectRow>66 ) p->nSelectRow = 66; |
+ }else{ |
+ assert( 0==sqlite3LogEst(1) ); |
+ p->nSelectRow = 0; |
+ } |
+ |
+ /* If there is both a GROUP BY and an ORDER BY clause and they are |
+ ** identical, then it may be possible to disable the ORDER BY clause |
+ ** on the grounds that the GROUP BY will cause elements to come out |
+ ** in the correct order. It also may not - the GROUP BY might use a |
+ ** database index that causes rows to be grouped together as required |
+ ** but not actually sorted. Either way, record the fact that the |
+ ** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp |
+ ** variable. */ |
+ if( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){ |
+ orderByGrp = 1; |
+ } |
+ |
+ /* Create a label to jump to when we want to abort the query */ |
+ 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.mnReg = pParse->nMem+1; |
+ sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr : 0; |
+ sAggInfo.pGroupBy = pGroupBy; |
+ sqlite3ExprAnalyzeAggList(&sNC, pEList); |
+ sqlite3ExprAnalyzeAggList(&sNC, sSort.pOrderBy); |
+ if( pHaving ){ |
+ sqlite3ExprAnalyzeAggregates(&sNC, pHaving); |
+ } |
+ sAggInfo.nAccumulator = sAggInfo.nColumn; |
+ for(i=0; i<sAggInfo.nFunc; i++){ |
+ assert( !ExprHasProperty(sAggInfo.aFunc[i].pExpr, EP_xIsSelect) ); |
+ sNC.ncFlags |= NC_InAggFunc; |
+ sqlite3ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->x.pList); |
+ sNC.ncFlags &= ~NC_InAggFunc; |
+ } |
+ sAggInfo.mxReg = pParse->nMem; |
+ 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 addr1; /* A-vs-B comparision jump */ |
+ 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 addrTopOfLoop; /* Top of the input loop */ |
+ int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */ |
+ int addrReset; /* Subroutine for resetting the accumulator */ |
+ int regReset; /* Return address register for reset subroutine */ |
+ |
+ /* 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 OP_SorterOpen instruction |
+ ** will be converted into a Noop. |
+ */ |
+ sAggInfo.sortingIdx = pParse->nTab++; |
+ pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0, sAggInfo.nColumn); |
+ addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen, |
+ sAggInfo.sortingIdx, sAggInfo.nSortingColumn, |
+ 0, (char*)pKeyInfo, P4_KEYINFO); |
+ |
+ /* Initialize memory locations used by GROUP BY aggregate processing |
+ */ |
+ iUseFlag = ++pParse->nMem; |
+ iAbortFlag = ++pParse->nMem; |
+ regOutputRow = ++pParse->nMem; |
+ addrOutputRow = sqlite3VdbeMakeLabel(v); |
+ regReset = ++pParse->nMem; |
+ addrReset = sqlite3VdbeMakeLabel(v); |
+ 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")); |
+ sqlite3VdbeAddOp3(v, OP_Null, 0, iAMem, iAMem+pGroupBy->nExpr-1); |
+ |
+ /* 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. |
+ */ |
+ sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); |
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0, |
+ WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0), 0 |
+ ); |
+ if( pWInfo==0 ) goto select_end; |
+ if( sqlite3WhereIsOrdered(pWInfo)==pGroupBy->nExpr ){ |
+ /* 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 |
+ */ |
+ 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; |
+ |
+ explainTempTable(pParse, |
+ (sDistinct.isTnct && (p->selFlags&SF_Distinct)==0) ? |
+ "DISTINCT" : "GROUP BY"); |
+ |
+ groupBySort = 1; |
+ nGroupBy = pGroupBy->nExpr; |
+ nCol = nGroupBy; |
+ j = nGroupBy; |
+ for(i=0; i<sAggInfo.nColumn; i++){ |
+ if( sAggInfo.aCol[i].iSorterColumn>=j ){ |
+ nCol++; |
+ j++; |
+ } |
+ } |
+ regBase = sqlite3GetTempRange(pParse, nCol); |
+ sqlite3ExprCacheClear(pParse); |
+ sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0, 0); |
+ j = nGroupBy; |
+ for(i=0; i<sAggInfo.nColumn; i++){ |
+ struct AggInfo_col *pCol = &sAggInfo.aCol[i]; |
+ if( pCol->iSorterColumn>=j ){ |
+ int r1 = j + regBase; |
+ sqlite3ExprCodeGetColumnToReg(pParse, |
+ pCol->pTab, pCol->iColumn, pCol->iTable, r1); |
+ j++; |
+ } |
+ } |
+ regRecord = sqlite3GetTempReg(pParse); |
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord); |
+ sqlite3VdbeAddOp2(v, OP_SorterInsert, sAggInfo.sortingIdx, regRecord); |
+ sqlite3ReleaseTempReg(pParse, regRecord); |
+ sqlite3ReleaseTempRange(pParse, regBase, nCol); |
+ sqlite3WhereEnd(pWInfo); |
+ sAggInfo.sortingIdxPTab = sortPTab = pParse->nTab++; |
+ sortOut = sqlite3GetTempReg(pParse); |
+ sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol); |
+ sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd); |
+ VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v); |
+ sAggInfo.useSortingIdx = 1; |
+ sqlite3ExprCacheClear(pParse); |
+ |
+ } |
+ |
+ /* If the index or temporary table used by the GROUP BY sort |
+ ** will naturally deliver rows in the order required by the ORDER BY |
+ ** clause, cancel the ephemeral table open coded earlier. |
+ ** |
+ ** This is an optimization - the correct answer should result regardless. |
+ ** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER to |
+ ** disable this optimization for testing purposes. */ |
+ if( orderByGrp && OptimizationEnabled(db, SQLITE_GroupByOrder) |
+ && (groupBySort || sqlite3WhereIsSorted(pWInfo)) |
+ ){ |
+ sSort.pOrderBy = 0; |
+ sqlite3VdbeChangeToNoop(v, sSort.addrSortIndex); |
+ } |
+ |
+ /* 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); |
+ sqlite3ExprCacheClear(pParse); |
+ if( groupBySort ){ |
+ sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx, |
+ sortOut, sortPTab); |
+ } |
+ for(j=0; j<pGroupBy->nExpr; j++){ |
+ if( groupBySort ){ |
+ sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j); |
+ }else{ |
+ sAggInfo.directMode = 1; |
+ sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j); |
+ } |
+ } |
+ sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr, |
+ (char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO); |
+ addr1 = sqlite3VdbeCurrentAddr(v); |
+ sqlite3VdbeAddOp3(v, OP_Jump, addr1+1, 0, addr1+1); VdbeCoverage(v); |
+ |
+ /* 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); VdbeCoverage(v); |
+ 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, addr1); |
+ updateAccumulator(pParse, &sAggInfo); |
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag); |
+ VdbeComment((v, "indicate data in accumulator")); |
+ |
+ /* End of the loop |
+ */ |
+ if( groupBySort ){ |
+ sqlite3VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop); |
+ VdbeCoverage(v); |
+ }else{ |
+ sqlite3WhereEnd(pWInfo); |
+ sqlite3VdbeChangeToNoop(v, addrSortingIdx); |
+ } |
+ |
+ /* Output the final row of result |
+ */ |
+ sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow); |
+ VdbeComment((v, "output final row")); |
+ |
+ /* Jump over the subroutines |
+ */ |
+ sqlite3VdbeGoto(v, addrEnd); |
+ |
+ /* 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")); |
+ sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); |
+ sqlite3VdbeResolveLabel(v, addrOutputRow); |
+ addrOutputRow = sqlite3VdbeCurrentAddr(v); |
+ sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2); |
+ VdbeCoverage(v); |
+ VdbeComment((v, "Groupby result generator entry point")); |
+ sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); |
+ finalizeAggFunctions(pParse, &sAggInfo); |
+ sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL); |
+ selectInnerLoop(pParse, p, p->pEList, -1, &sSort, |
+ &sDistinct, 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 |
+ */ |
+ sqlite3VdbeResolveLabel(v, addrReset); |
+ resetAccumulator(pParse, &sAggInfo); |
+ sqlite3VdbeAddOp1(v, OP_Return, regReset); |
+ |
+ } /* endif pGroupBy. Begin aggregate queries without GROUP BY: */ |
+ else { |
+ ExprList *pDel = 0; |
+#ifndef SQLITE_OMIT_BTREECOUNT |
+ Table *pTab; |
+ if( (pTab = isSimpleCount(p, &sAggInfo))!=0 ){ |
+ /* If isSimpleCount() returns a pointer to a Table structure, then |
+ ** the SQL statement is of the form: |
+ ** |
+ ** SELECT count(*) FROM <tbl> |
+ ** |
+ ** where the Table structure returned represents table <tbl>. |
+ ** |
+ ** This statement is so common that it is optimized specially. The |
+ ** OP_Count instruction is executed either on the intkey table that |
+ ** contains the data for table <tbl> or on one of its indexes. It |
+ ** is better to execute the op on an index, as indexes are almost |
+ ** always spread across less pages than their corresponding tables. |
+ */ |
+ const int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); |
+ const int iCsr = pParse->nTab++; /* Cursor to scan b-tree */ |
+ Index *pIdx; /* Iterator variable */ |
+ KeyInfo *pKeyInfo = 0; /* Keyinfo for scanned index */ |
+ Index *pBest = 0; /* Best index found so far */ |
+ int iRoot = pTab->tnum; /* Root page of scanned b-tree */ |
+ |
+ sqlite3CodeVerifySchema(pParse, iDb); |
+ sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); |
+ |
+ /* Search for the index that has the lowest scan cost. |
+ ** |
+ ** (2011-04-15) Do not do a full scan of an unordered index. |
+ ** |
+ ** (2013-10-03) Do not count the entries in a partial index. |
+ ** |
+ ** In practice the KeyInfo structure will not be used. It is only |
+ ** passed to keep OP_OpenRead happy. |
+ */ |
+ if( !HasRowid(pTab) ) pBest = sqlite3PrimaryKeyIndex(pTab); |
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
+ if( pIdx->bUnordered==0 |
+ && pIdx->szIdxRow<pTab->szTabRow |
+ && pIdx->pPartIdxWhere==0 |
+ && (!pBest || pIdx->szIdxRow<pBest->szIdxRow) |
+ ){ |
+ pBest = pIdx; |
+ } |
+ } |
+ if( pBest ){ |
+ iRoot = pBest->tnum; |
+ pKeyInfo = sqlite3KeyInfoOfIndex(pParse, pBest); |
+ } |
+ |
+ /* Open a read-only cursor, execute the OP_Count, close the cursor. */ |
+ sqlite3VdbeAddOp4Int(v, OP_OpenRead, iCsr, iRoot, iDb, 1); |
+ if( pKeyInfo ){ |
+ sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO); |
+ } |
+ sqlite3VdbeAddOp2(v, OP_Count, iCsr, sAggInfo.aFunc[0].iMem); |
+ sqlite3VdbeAddOp1(v, OP_Close, iCsr); |
+ explainSimpleCount(pParse, pTab, pBest); |
+ }else |
+#endif /* SQLITE_OMIT_BTREECOUNT */ |
+ { |
+ /* 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 behavior 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. |
+ */ |
+ ExprList *pMinMax = 0; |
+ u8 flag = WHERE_ORDERBY_NORMAL; |
+ |
+ assert( p->pGroupBy==0 ); |
+ assert( flag==0 ); |
+ if( p->pHaving==0 ){ |
+ flag = minMaxQuery(&sAggInfo, &pMinMax); |
+ } |
+ assert( flag==0 || (pMinMax!=0 && pMinMax->nExpr==1) ); |
+ |
+ if( flag ){ |
+ pMinMax = sqlite3ExprListDup(db, pMinMax, 0); |
+ pDel = pMinMax; |
+ assert( db->mallocFailed || pMinMax!=0 ); |
+ if( !db->mallocFailed ){ |
+ pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0; |
+ 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, 0,flag,0); |
+ if( pWInfo==0 ){ |
+ sqlite3ExprListDelete(db, pDel); |
+ goto select_end; |
+ } |
+ updateAccumulator(pParse, &sAggInfo); |
+ assert( pMinMax==0 || pMinMax->nExpr==1 ); |
+ if( sqlite3WhereIsOrdered(pWInfo)>0 ){ |
+ sqlite3VdbeGoto(v, sqlite3WhereBreakLabel(pWInfo)); |
+ VdbeComment((v, "%s() by index", |
+ (flag==WHERE_ORDERBY_MIN?"min":"max"))); |
+ } |
+ sqlite3WhereEnd(pWInfo); |
+ finalizeAggFunctions(pParse, &sAggInfo); |
+ } |
+ |
+ sSort.pOrderBy = 0; |
+ sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL); |
+ selectInnerLoop(pParse, p, p->pEList, -1, 0, 0, |
+ pDest, addrEnd, addrEnd); |
+ sqlite3ExprListDelete(db, pDel); |
+ } |
+ sqlite3VdbeResolveLabel(v, addrEnd); |
+ |
+ } /* endif aggregate query */ |
+ |
+ if( sDistinct.eTnctType==WHERE_DISTINCT_UNORDERED ){ |
+ explainTempTable(pParse, "DISTINCT"); |
+ } |
+ |
+ /* If there is an ORDER BY clause, then we need to sort the results |
+ ** and send them to the callback one by one. |
+ */ |
+ if( sSort.pOrderBy ){ |
+ explainTempTable(pParse, |
+ sSort.nOBSat>0 ? "RIGHT PART OF ORDER BY":"ORDER BY"); |
+ generateSortTail(pParse, p, &sSort, pEList->nExpr, pDest); |
+ } |
+ |
+ /* Jump here to skip this query |
+ */ |
+ sqlite3VdbeResolveLabel(v, iEnd); |
+ |
+ /* The SELECT has been coded. If there is an error in the Parse structure, |
+ ** set the return code to 1. Otherwise 0. */ |
+ rc = (pParse->nErr>0); |
+ |
+ /* Control jumps to here if an error is encountered above, or upon |
+ ** successful coding of the SELECT. |
+ */ |
+select_end: |
+ explainSetInteger(pParse->iSelectId, iRestoreSelectId); |
+ |
+ /* Identify column names if results of the SELECT are to be output. |
+ */ |
+ if( rc==SQLITE_OK && pDest->eDest==SRT_Output ){ |
+ generateColumnNames(pParse, pTabList, pEList); |
+ } |
+ |
+ sqlite3DbFree(db, sAggInfo.aCol); |
+ sqlite3DbFree(db, sAggInfo.aFunc); |
+#if SELECTTRACE_ENABLED |
+ SELECTTRACE(1,pParse,p,("end processing\n")); |
+ pParse->nSelectIndent--; |
+#endif |
+ return rc; |
+} |
+ |
+/************** End of select.c **********************************************/ |
+/************** Begin file table.c *******************************************/ |
+/* |
+** 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. |
+*/ |
+/* #include "sqliteInt.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; /* Accumulated output */ |
+ char *zErrMsg; /* Error message text, if an error occurs */ |
+ u32 nAlloc; /* Slots allocated for azResult[] */ |
+ u32 nRow; /* Number of rows in the result */ |
+ u32 nColumn; /* Number of columns in the result */ |
+ u32 nData; /* Slots used in azResult[]. (nRow+1)*nColumn */ |
+ int rc; /* Return code from sqlite3_exec() */ |
+} 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; /* Result accumulator */ |
+ int need; /* Slots needed in p->azResult[] */ |
+ int i; /* Loop counter */ |
+ char *z; /* A single column of result */ |
+ |
+ /* 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; |
+ azNew = sqlite3_realloc64( 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( (int)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 = sqlite3Strlen30(argv[i])+1; |
+ z = sqlite3_malloc64( 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_BKPT; |
+ 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. |
+*/ |
+SQLITE_API 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; |
+ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) || pazResult==0 ) return SQLITE_MISUSE_BKPT; |
+#endif |
+ *pazResult = 0; |
+ if( pnColumn ) *pnColumn = 0; |
+ if( pnRow ) *pnRow = 0; |
+ if( pzErrMsg ) *pzErrMsg = 0; |
+ res.zErrMsg = 0; |
+ res.nRow = 0; |
+ res.nColumn = 0; |
+ res.nData = 1; |
+ res.nAlloc = 20; |
+ res.rc = SQLITE_OK; |
+ res.azResult = sqlite3_malloc64(sizeof(char*)*res.nAlloc ); |
+ if( res.azResult==0 ){ |
+ db->errCode = SQLITE_NOMEM; |
+ return SQLITE_NOMEM_BKPT; |
+ } |
+ 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_realloc64( res.azResult, sizeof(char*)*res.nData ); |
+ if( azNew==0 ){ |
+ sqlite3_free_table(&res.azResult[1]); |
+ db->errCode = SQLITE_NOMEM; |
+ return SQLITE_NOMEM_BKPT; |
+ } |
+ 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. |
+*/ |
+SQLITE_API void sqlite3_free_table( |
+ char **azResult /* Result returned 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 */ |
+ |
+/************** End of table.c ***********************************************/ |
+/************** Begin file trigger.c *****************************************/ |
+/* |
+** |
+** 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 for TRIGGERs |
+*/ |
+/* #include "sqliteInt.h" */ |
+ |
+#ifndef SQLITE_OMIT_TRIGGER |
+/* |
+** Delete a linked list of TriggerStep structures. |
+*/ |
+SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerStep){ |
+ while( pTriggerStep ){ |
+ TriggerStep * pTmp = pTriggerStep; |
+ pTriggerStep = pTriggerStep->pNext; |
+ |
+ sqlite3ExprDelete(db, pTmp->pWhere); |
+ sqlite3ExprListDelete(db, pTmp->pExprList); |
+ sqlite3SelectDelete(db, pTmp->pSelect); |
+ sqlite3IdListDelete(db, pTmp->pIdList); |
+ |
+ sqlite3DbFree(db, pTmp); |
+ } |
+} |
+ |
+/* |
+** Given table pTab, return a list of all the triggers attached to |
+** the table. The list is connected by Trigger.pNext pointers. |
+** |
+** All of the triggers on pTab that are in the same database as pTab |
+** are already attached to pTab->pTrigger. But there might be additional |
+** triggers on pTab in the TEMP schema. This routine prepends all |
+** TEMP triggers on pTab to the beginning of the pTab->pTrigger list |
+** and returns the combined list. |
+** |
+** To state it another way: This routine returns a list of all triggers |
+** that fire off of pTab. The list will include any TEMP triggers on |
+** pTab as well as the triggers lised in pTab->pTrigger. |
+*/ |
+SQLITE_PRIVATE Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){ |
+ Schema * const pTmpSchema = pParse->db->aDb[1].pSchema; |
+ Trigger *pList = 0; /* List of triggers to return */ |
+ |
+ if( pParse->disableTriggers ){ |
+ return 0; |
+ } |
+ |
+ if( pTmpSchema!=pTab->pSchema ){ |
+ HashElem *p; |
+ assert( sqlite3SchemaMutexHeld(pParse->db, 0, pTmpSchema) ); |
+ for(p=sqliteHashFirst(&pTmpSchema->trigHash); p; p=sqliteHashNext(p)){ |
+ Trigger *pTrig = (Trigger *)sqliteHashData(p); |
+ if( pTrig->pTabSchema==pTab->pSchema |
+ && 0==sqlite3StrICmp(pTrig->table, pTab->zName) |
+ ){ |
+ pTrig->pNext = (pList ? pList : pTab->pTrigger); |
+ pList = pTrig; |
+ } |
+ } |
+ } |
+ |
+ return (pList ? pList : pTab->pTrigger); |
+} |
+ |
+/* |
+** 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. |
+*/ |
+SQLITE_PRIVATE 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; /* The new trigger */ |
+ Table *pTab; /* Table that the trigger fires off of */ |
+ char *zName = 0; /* Name of the trigger */ |
+ sqlite3 *db = pParse->db; /* The database connection */ |
+ int iDb; /* The database to store the trigger in */ |
+ Token *pName; /* The unqualified db name */ |
+ DbFixer sFix; /* State vector for the DB fixer */ |
+ |
+ assert( pName1!=0 ); /* pName1->z might be NULL, but not pName1 itself */ |
+ assert( pName2!=0 ); |
+ assert( op==TK_INSERT || op==TK_UPDATE || op==TK_DELETE ); |
+ assert( op>0 && op<0xff ); |
+ 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 trigger will be created in */ |
+ iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); |
+ if( iDb<0 ){ |
+ goto trigger_cleanup; |
+ } |
+ } |
+ if( !pTableName || db->mallocFailed ){ |
+ goto trigger_cleanup; |
+ } |
+ |
+ /* A long-standing parser bug is that this syntax was allowed: |
+ ** |
+ ** CREATE TRIGGER attached.demo AFTER INSERT ON attached.tab .... |
+ ** ^^^^^^^^ |
+ ** |
+ ** To maintain backwards compatibility, ignore the database |
+ ** name on pTableName if we are reparsing out of SQLITE_MASTER. |
+ */ |
+ if( db->init.busy && iDb!=1 ){ |
+ sqlite3DbFree(db, pTableName->a[0].zDatabase); |
+ pTableName->a[0].zDatabase = 0; |
+ } |
+ |
+ /* 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. |
+ */ |
+ pTab = sqlite3SrcListLookup(pParse, pTableName); |
+ if( db->init.busy==0 && 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 ); |
+ sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName); |
+ if( sqlite3FixSrcList(&sFix, pTableName) ){ |
+ goto trigger_cleanup; |
+ } |
+ pTab = sqlite3SrcListLookup(pParse, pTableName); |
+ if( !pTab ){ |
+ /* The table does not exist. */ |
+ if( db->init.iDb==1 ){ |
+ /* Ticket #3810. |
+ ** Normally, whenever a table is dropped, all associated triggers are |
+ ** dropped too. But if a TEMP trigger is created on a non-TEMP table |
+ ** and the table is dropped by a different database connection, the |
+ ** trigger is not visible to the database connection that does the |
+ ** drop so the trigger cannot be dropped. This results in an |
+ ** "orphaned trigger" - a trigger whose associated table is missing. |
+ */ |
+ db->init.orphanTrigger = 1; |
+ } |
+ 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; |
+ } |
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
+ if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),zName) ){ |
+ if( !noErr ){ |
+ sqlite3ErrorMsg(pParse, "trigger %T already exists", pName); |
+ }else{ |
+ assert( !db->init.busy ); |
+ sqlite3CodeVerifySchema(pParse, iDb); |
+ } |
+ 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"); |
+ 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; |
+ } |
+ |
+#ifndef SQLITE_OMIT_AUTHORIZATION |
+ { |
+ int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
+ int code = SQLITE_CREATE_TRIGGER; |
+ const char *zDb = db->aDb[iTabDb].zDbSName; |
+ const char *zDbTrig = isTemp ? db->aDb[1].zDbSName : 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->zName = zName; |
+ zName = 0; |
+ pTrigger->table = sqlite3DbStrDup(db, pTableName->a[0].zName); |
+ pTrigger->pSchema = db->aDb[iDb].pSchema; |
+ pTrigger->pTabSchema = pTab->pSchema; |
+ pTrigger->op = (u8)op; |
+ pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER; |
+ pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); |
+ pTrigger->pColumns = sqlite3IdListDup(db, pColumns); |
+ 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. |
+*/ |
+SQLITE_PRIVATE void sqlite3FinishTrigger( |
+ Parse *pParse, /* Parser context */ |
+ TriggerStep *pStepList, /* The triggered program */ |
+ Token *pAll /* Token that describes the complete CREATE TRIGGER */ |
+){ |
+ Trigger *pTrig = pParse->pNewTrigger; /* Trigger being finished */ |
+ char *zName; /* Name of trigger */ |
+ sqlite3 *db = pParse->db; /* The database */ |
+ DbFixer sFix; /* Fixer object */ |
+ int iDb; /* Database containing the trigger */ |
+ Token nameToken; /* Trigger name for error reporting */ |
+ |
+ pParse->pNewTrigger = 0; |
+ if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup; |
+ zName = pTrig->zName; |
+ iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); |
+ pTrig->step_list = pStepList; |
+ while( pStepList ){ |
+ pStepList->pTrig = pTrig; |
+ pStepList = pStepList->pNext; |
+ } |
+ sqlite3TokenInit(&nameToken, pTrig->zName); |
+ sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken); |
+ if( sqlite3FixTriggerStep(&sFix, pTrig->step_list) |
+ || sqlite3FixExpr(&sFix, pTrig->pWhen) |
+ ){ |
+ goto triggerfinish_cleanup; |
+ } |
+ |
+ /* if we are not initializing, |
+ ** 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].zDbSName, MASTER_NAME, zName, |
+ pTrig->table, z); |
+ sqlite3DbFree(db, z); |
+ sqlite3ChangeCookie(pParse, iDb); |
+ sqlite3VdbeAddParseSchemaOp(v, iDb, |
+ sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName)); |
+ } |
+ |
+ if( db->init.busy ){ |
+ Trigger *pLink = pTrig; |
+ Hash *pHash = &db->aDb[iDb].pSchema->trigHash; |
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
+ pTrig = sqlite3HashInsert(pHash, zName, pTrig); |
+ if( pTrig ){ |
+ sqlite3OomFault(db); |
+ }else if( pLink->pSchema==pLink->pTabSchema ){ |
+ Table *pTab; |
+ pTab = sqlite3HashFind(&pLink->pTabSchema->tblHash, pLink->table); |
+ assert( pTab!=0 ); |
+ pLink->pNext = pTab->pTrigger; |
+ pTab->pTrigger = pLink; |
+ } |
+ } |
+ |
+triggerfinish_cleanup: |
+ sqlite3DeleteTrigger(db, pTrig); |
+ assert( !pParse->pNewTrigger ); |
+ sqlite3DeleteTriggerStep(db, pStepList); |
+} |
+ |
+/* |
+** 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. |
+*/ |
+SQLITE_PRIVATE 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; |
+ return pTriggerStep; |
+} |
+ |
+/* |
+** Allocate space to hold a new trigger step. The allocated space |
+** holds both the TriggerStep object and the TriggerStep.target.z string. |
+** |
+** If an OOM error occurs, NULL is returned and db->mallocFailed is set. |
+*/ |
+static TriggerStep *triggerStepAllocate( |
+ sqlite3 *db, /* Database connection */ |
+ u8 op, /* Trigger opcode */ |
+ Token *pName /* The target name */ |
+){ |
+ TriggerStep *pTriggerStep; |
+ |
+ pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n + 1); |
+ if( pTriggerStep ){ |
+ char *z = (char*)&pTriggerStep[1]; |
+ memcpy(z, pName->z, pName->n); |
+ sqlite3Dequote(z); |
+ pTriggerStep->zTarget = z; |
+ pTriggerStep->op = op; |
+ } |
+ 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. |
+*/ |
+SQLITE_PRIVATE 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 */ |
+ Select *pSelect, /* A SELECT statement that supplies values */ |
+ u8 orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ |
+){ |
+ TriggerStep *pTriggerStep; |
+ |
+ assert(pSelect != 0 || db->mallocFailed); |
+ |
+ pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName); |
+ if( pTriggerStep ){ |
+ pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); |
+ pTriggerStep->pIdList = pColumn; |
+ pTriggerStep->orconf = orconf; |
+ }else{ |
+ sqlite3IdListDelete(db, pColumn); |
+ } |
+ 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. |
+*/ |
+SQLITE_PRIVATE 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 */ |
+ u8 orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */ |
+){ |
+ TriggerStep *pTriggerStep; |
+ |
+ pTriggerStep = triggerStepAllocate(db, TK_UPDATE, pTableName); |
+ if( pTriggerStep ){ |
+ pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE); |
+ pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); |
+ pTriggerStep->orconf = orconf; |
+ } |
+ sqlite3ExprListDelete(db, pEList); |
+ sqlite3ExprDelete(db, pWhere); |
+ 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. |
+*/ |
+SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep( |
+ sqlite3 *db, /* Database connection */ |
+ Token *pTableName, /* The table from which rows are deleted */ |
+ Expr *pWhere /* The WHERE clause */ |
+){ |
+ TriggerStep *pTriggerStep; |
+ |
+ pTriggerStep = triggerStepAllocate(db, TK_DELETE, pTableName); |
+ if( pTriggerStep ){ |
+ pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); |
+ pTriggerStep->orconf = OE_Default; |
+ } |
+ sqlite3ExprDelete(db, pWhere); |
+ return pTriggerStep; |
+} |
+ |
+/* |
+** Recursively delete a Trigger structure |
+*/ |
+SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){ |
+ if( pTrigger==0 ) return; |
+ sqlite3DeleteTriggerStep(db, pTrigger->step_list); |
+ sqlite3DbFree(db, pTrigger->zName); |
+ sqlite3DbFree(db, pTrigger->table); |
+ sqlite3ExprDelete(db, pTrigger->pWhen); |
+ sqlite3IdListDelete(db, pTrigger->pColumns); |
+ 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. |
+**/ |
+SQLITE_PRIVATE void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){ |
+ Trigger *pTrigger = 0; |
+ int i; |
+ const char *zDb; |
+ const char *zName; |
+ 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; |
+ assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) ); |
+ 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].zDbSName, zDb) ) continue; |
+ assert( sqlite3SchemaMutexHeld(db, j, 0) ); |
+ pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName); |
+ if( pTrigger ) break; |
+ } |
+ if( !pTrigger ){ |
+ if( !noErr ){ |
+ sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0); |
+ }else{ |
+ sqlite3CodeVerifyNamedSchema(pParse, zDb); |
+ } |
+ pParse->checkSchema = 1; |
+ 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){ |
+ return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table); |
+} |
+ |
+ |
+/* |
+** Drop a trigger given a pointer to that trigger. |
+*/ |
+SQLITE_PRIVATE 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].zDbSName; |
+ const char *zTab = SCHEMA_TABLE(iDb); |
+ if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER; |
+ if( sqlite3AuthCheck(pParse, code, pTrigger->zName, 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 ){ |
+ sqlite3NestedParse(pParse, |
+ "DELETE FROM %Q.%s WHERE name=%Q AND type='trigger'", |
+ db->aDb[iDb].zDbSName, MASTER_NAME, pTrigger->zName |
+ ); |
+ sqlite3ChangeCookie(pParse, iDb); |
+ sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->zName, 0); |
+ } |
+} |
+ |
+/* |
+** Remove a trigger from the hash tables of the sqlite* pointer. |
+*/ |
+SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){ |
+ Trigger *pTrigger; |
+ Hash *pHash; |
+ |
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
+ pHash = &(db->aDb[iDb].pSchema->trigHash); |
+ pTrigger = sqlite3HashInsert(pHash, zName, 0); |
+ if( ALWAYS(pTrigger) ){ |
+ if( pTrigger->pSchema==pTrigger->pTabSchema ){ |
+ Table *pTab = tableOfTrigger(pTrigger); |
+ Trigger **pp; |
+ for(pp=&pTab->pTrigger; *pp!=pTrigger; pp=&((*pp)->pNext)); |
+ *pp = (*pp)->pNext; |
+ } |
+ 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==0 || NEVER(pEList==0) ) return 1; |
+ for(e=0; e<pEList->nExpr; e++){ |
+ if( sqlite3IdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1; |
+ } |
+ return 0; |
+} |
+ |
+/* |
+** Return a list of all triggers on table pTab if there exists at least |
+** one trigger that must be fired when an operation of type 'op' is |
+** performed on the table, and, if that operation is an UPDATE, if at |
+** least one of the columns in pChanges is being modified. |
+*/ |
+SQLITE_PRIVATE Trigger *sqlite3TriggersExist( |
+ Parse *pParse, /* Parse context */ |
+ 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 */ |
+ int *pMask /* OUT: Mask of TRIGGER_BEFORE|TRIGGER_AFTER */ |
+){ |
+ int mask = 0; |
+ Trigger *pList = 0; |
+ Trigger *p; |
+ |
+ if( (pParse->db->flags & SQLITE_EnableTrigger)!=0 ){ |
+ pList = sqlite3TriggerList(pParse, pTab); |
+ } |
+ assert( pList==0 || IsVirtual(pTab)==0 ); |
+ for(p=pList; p; p=p->pNext){ |
+ if( p->op==op && checkColumnOverlap(p->pColumns, pChanges) ){ |
+ mask |= p->tr_tm; |
+ } |
+ } |
+ if( pMask ){ |
+ *pMask = mask; |
+ } |
+ return (mask ? pList : 0); |
+} |
+ |
+/* |
+** Convert the pStep->zTarget string 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 */ |
+){ |
+ sqlite3 *db = pParse->db; |
+ int iDb; /* Index of the database to use */ |
+ SrcList *pSrc; /* SrcList to be returned */ |
+ |
+ pSrc = sqlite3SrcListAppend(db, 0, 0, 0); |
+ if( pSrc ){ |
+ assert( pSrc->nSrc>0 ); |
+ pSrc->a[pSrc->nSrc-1].zName = sqlite3DbStrDup(db, pStep->zTarget); |
+ iDb = sqlite3SchemaToIndex(db, pStep->pTrig->pSchema); |
+ if( iDb==0 || iDb>=2 ){ |
+ const char *zDb; |
+ assert( iDb<db->nDb ); |
+ zDb = db->aDb[iDb].zDbSName; |
+ pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, zDb); |
+ } |
+ } |
+ return pSrc; |
+} |
+ |
+/* |
+** Generate VDBE code for the statements inside the body of a single |
+** trigger. |
+*/ |
+static int codeTriggerProgram( |
+ Parse *pParse, /* The parser context */ |
+ TriggerStep *pStepList, /* List of statements inside the trigger body */ |
+ int orconf /* Conflict algorithm. (OE_Abort, etc) */ |
+){ |
+ TriggerStep *pStep; |
+ Vdbe *v = pParse->pVdbe; |
+ sqlite3 *db = pParse->db; |
+ |
+ assert( pParse->pTriggerTab && pParse->pToplevel ); |
+ assert( pStepList ); |
+ assert( v!=0 ); |
+ for(pStep=pStepList; pStep; pStep=pStep->pNext){ |
+ /* Figure out the ON CONFLICT policy that will be used for this step |
+ ** of the trigger program. If the statement that caused this trigger |
+ ** to fire had an explicit ON CONFLICT, then use it. Otherwise, use |
+ ** the ON CONFLICT policy that was specified as part of the trigger |
+ ** step statement. Example: |
+ ** |
+ ** CREATE TRIGGER AFTER INSERT ON t1 BEGIN; |
+ ** INSERT OR REPLACE INTO t2 VALUES(new.a, new.b); |
+ ** END; |
+ ** |
+ ** INSERT INTO t1 ... ; -- insert into t2 uses REPLACE policy |
+ ** INSERT OR IGNORE INTO t1 ... ; -- insert into t2 uses IGNORE policy |
+ */ |
+ pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf; |
+ assert( pParse->okConstFactor==0 ); |
+ |
+ switch( pStep->op ){ |
+ case TK_UPDATE: { |
+ sqlite3Update(pParse, |
+ targetSrcList(pParse, pStep), |
+ sqlite3ExprListDup(db, pStep->pExprList, 0), |
+ sqlite3ExprDup(db, pStep->pWhere, 0), |
+ pParse->eOrconf |
+ ); |
+ break; |
+ } |
+ case TK_INSERT: { |
+ sqlite3Insert(pParse, |
+ targetSrcList(pParse, pStep), |
+ sqlite3SelectDup(db, pStep->pSelect, 0), |
+ sqlite3IdListDup(db, pStep->pIdList), |
+ pParse->eOrconf |
+ ); |
+ break; |
+ } |
+ case TK_DELETE: { |
+ sqlite3DeleteFrom(pParse, |
+ targetSrcList(pParse, pStep), |
+ sqlite3ExprDup(db, pStep->pWhere, 0) |
+ ); |
+ break; |
+ } |
+ default: assert( pStep->op==TK_SELECT ); { |
+ SelectDest sDest; |
+ Select *pSelect = sqlite3SelectDup(db, pStep->pSelect, 0); |
+ sqlite3SelectDestInit(&sDest, SRT_Discard, 0); |
+ sqlite3Select(pParse, pSelect, &sDest); |
+ sqlite3SelectDelete(db, pSelect); |
+ break; |
+ } |
+ } |
+ if( pStep->op!=TK_SELECT ){ |
+ sqlite3VdbeAddOp0(v, OP_ResetCount); |
+ } |
+ } |
+ |
+ return 0; |
+} |
+ |
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS |
+/* |
+** This function is used to add VdbeComment() annotations to a VDBE |
+** program. It is not used in production code, only for debugging. |
+*/ |
+static const char *onErrorText(int onError){ |
+ switch( onError ){ |
+ case OE_Abort: return "abort"; |
+ case OE_Rollback: return "rollback"; |
+ case OE_Fail: return "fail"; |
+ case OE_Replace: return "replace"; |
+ case OE_Ignore: return "ignore"; |
+ case OE_Default: return "default"; |
+ } |
+ return "n/a"; |
+} |
+#endif |
+ |
+/* |
+** Parse context structure pFrom has just been used to create a sub-vdbe |
+** (trigger program). If an error has occurred, transfer error information |
+** from pFrom to pTo. |
+*/ |
+static void transferParseError(Parse *pTo, Parse *pFrom){ |
+ assert( pFrom->zErrMsg==0 || pFrom->nErr ); |
+ assert( pTo->zErrMsg==0 || pTo->nErr ); |
+ if( pTo->nErr==0 ){ |
+ pTo->zErrMsg = pFrom->zErrMsg; |
+ pTo->nErr = pFrom->nErr; |
+ pTo->rc = pFrom->rc; |
+ }else{ |
+ sqlite3DbFree(pFrom->db, pFrom->zErrMsg); |
+ } |
+} |
+ |
+/* |
+** Create and populate a new TriggerPrg object with a sub-program |
+** implementing trigger pTrigger with ON CONFLICT policy orconf. |
+*/ |
+static TriggerPrg *codeRowTrigger( |
+ Parse *pParse, /* Current parse context */ |
+ Trigger *pTrigger, /* Trigger to code */ |
+ Table *pTab, /* The table pTrigger is attached to */ |
+ int orconf /* ON CONFLICT policy to code trigger program with */ |
+){ |
+ Parse *pTop = sqlite3ParseToplevel(pParse); |
+ sqlite3 *db = pParse->db; /* Database handle */ |
+ TriggerPrg *pPrg; /* Value to return */ |
+ Expr *pWhen = 0; /* Duplicate of trigger WHEN expression */ |
+ Vdbe *v; /* Temporary VM */ |
+ NameContext sNC; /* Name context for sub-vdbe */ |
+ SubProgram *pProgram = 0; /* Sub-vdbe for trigger program */ |
+ Parse *pSubParse; /* Parse context for sub-vdbe */ |
+ int iEndTrigger = 0; /* Label to jump to if WHEN is false */ |
+ |
+ assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) ); |
+ assert( pTop->pVdbe ); |
+ |
+ /* Allocate the TriggerPrg and SubProgram objects. To ensure that they |
+ ** are freed if an error occurs, link them into the Parse.pTriggerPrg |
+ ** list of the top-level Parse object sooner rather than later. */ |
+ pPrg = sqlite3DbMallocZero(db, sizeof(TriggerPrg)); |
+ if( !pPrg ) return 0; |
+ pPrg->pNext = pTop->pTriggerPrg; |
+ pTop->pTriggerPrg = pPrg; |
+ pPrg->pProgram = pProgram = sqlite3DbMallocZero(db, sizeof(SubProgram)); |
+ if( !pProgram ) return 0; |
+ sqlite3VdbeLinkSubProgram(pTop->pVdbe, pProgram); |
+ pPrg->pTrigger = pTrigger; |
+ pPrg->orconf = orconf; |
+ pPrg->aColmask[0] = 0xffffffff; |
+ pPrg->aColmask[1] = 0xffffffff; |
+ |
+ /* Allocate and populate a new Parse context to use for coding the |
+ ** trigger sub-program. */ |
+ pSubParse = sqlite3StackAllocZero(db, sizeof(Parse)); |
+ if( !pSubParse ) return 0; |
+ memset(&sNC, 0, sizeof(sNC)); |
+ sNC.pParse = pSubParse; |
+ pSubParse->db = db; |
+ pSubParse->pTriggerTab = pTab; |
+ pSubParse->pToplevel = pTop; |
+ pSubParse->zAuthContext = pTrigger->zName; |
+ pSubParse->eTriggerOp = pTrigger->op; |
+ pSubParse->nQueryLoop = pParse->nQueryLoop; |
+ |
+ v = sqlite3GetVdbe(pSubParse); |
+ if( v ){ |
+ VdbeComment((v, "Start: %s.%s (%s %s%s%s ON %s)", |
+ pTrigger->zName, onErrorText(orconf), |
+ (pTrigger->tr_tm==TRIGGER_BEFORE ? "BEFORE" : "AFTER"), |
+ (pTrigger->op==TK_UPDATE ? "UPDATE" : ""), |
+ (pTrigger->op==TK_INSERT ? "INSERT" : ""), |
+ (pTrigger->op==TK_DELETE ? "DELETE" : ""), |
+ pTab->zName |
+ )); |
+#ifndef SQLITE_OMIT_TRACE |
+ sqlite3VdbeChangeP4(v, -1, |
+ sqlite3MPrintf(db, "-- TRIGGER %s", pTrigger->zName), P4_DYNAMIC |
+ ); |
+#endif |
+ |
+ /* If one was specified, code the WHEN clause. If it evaluates to false |
+ ** (or NULL) the sub-vdbe is immediately halted by jumping to the |
+ ** OP_Halt inserted at the end of the program. */ |
+ if( pTrigger->pWhen ){ |
+ pWhen = sqlite3ExprDup(db, pTrigger->pWhen, 0); |
+ if( SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen) |
+ && db->mallocFailed==0 |
+ ){ |
+ iEndTrigger = sqlite3VdbeMakeLabel(v); |
+ sqlite3ExprIfFalse(pSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL); |
+ } |
+ sqlite3ExprDelete(db, pWhen); |
+ } |
+ |
+ /* Code the trigger program into the sub-vdbe. */ |
+ codeTriggerProgram(pSubParse, pTrigger->step_list, orconf); |
+ |
+ /* Insert an OP_Halt at the end of the sub-program. */ |
+ if( iEndTrigger ){ |
+ sqlite3VdbeResolveLabel(v, iEndTrigger); |
+ } |
+ sqlite3VdbeAddOp0(v, OP_Halt); |
+ VdbeComment((v, "End: %s.%s", pTrigger->zName, onErrorText(orconf))); |
+ |
+ transferParseError(pParse, pSubParse); |
+ if( db->mallocFailed==0 ){ |
+ pProgram->aOp = sqlite3VdbeTakeOpArray(v, &pProgram->nOp, &pTop->nMaxArg); |
+ } |
+ pProgram->nMem = pSubParse->nMem; |
+ pProgram->nCsr = pSubParse->nTab; |
+ pProgram->token = (void *)pTrigger; |
+ pPrg->aColmask[0] = pSubParse->oldmask; |
+ pPrg->aColmask[1] = pSubParse->newmask; |
+ sqlite3VdbeDelete(v); |
+ } |
+ |
+ assert( !pSubParse->pAinc && !pSubParse->pZombieTab ); |
+ assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg ); |
+ sqlite3ParserReset(pSubParse); |
+ sqlite3StackFree(db, pSubParse); |
+ |
+ return pPrg; |
+} |
+ |
+/* |
+** Return a pointer to a TriggerPrg object containing the sub-program for |
+** trigger pTrigger with default ON CONFLICT algorithm orconf. If no such |
+** TriggerPrg object exists, a new object is allocated and populated before |
+** being returned. |
+*/ |
+static TriggerPrg *getRowTrigger( |
+ Parse *pParse, /* Current parse context */ |
+ Trigger *pTrigger, /* Trigger to code */ |
+ Table *pTab, /* The table trigger pTrigger is attached to */ |
+ int orconf /* ON CONFLICT algorithm. */ |
+){ |
+ Parse *pRoot = sqlite3ParseToplevel(pParse); |
+ TriggerPrg *pPrg; |
+ |
+ assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) ); |
+ |
+ /* It may be that this trigger has already been coded (or is in the |
+ ** process of being coded). If this is the case, then an entry with |
+ ** a matching TriggerPrg.pTrigger field will be present somewhere |
+ ** in the Parse.pTriggerPrg list. Search for such an entry. */ |
+ for(pPrg=pRoot->pTriggerPrg; |
+ pPrg && (pPrg->pTrigger!=pTrigger || pPrg->orconf!=orconf); |
+ pPrg=pPrg->pNext |
+ ); |
+ |
+ /* If an existing TriggerPrg could not be located, create a new one. */ |
+ if( !pPrg ){ |
+ pPrg = codeRowTrigger(pParse, pTrigger, pTab, orconf); |
+ } |
+ |
+ return pPrg; |
+} |
+ |
+/* |
+** Generate code for the trigger program associated with trigger p on |
+** table pTab. The reg, orconf and ignoreJump parameters passed to this |
+** function are the same as those described in the header function for |
+** sqlite3CodeRowTrigger() |
+*/ |
+SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect( |
+ Parse *pParse, /* Parse context */ |
+ Trigger *p, /* Trigger to code */ |
+ Table *pTab, /* The table to code triggers from */ |
+ int reg, /* Reg array containing OLD.* and NEW.* values */ |
+ int orconf, /* ON CONFLICT policy */ |
+ int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */ |
+){ |
+ Vdbe *v = sqlite3GetVdbe(pParse); /* Main VM */ |
+ TriggerPrg *pPrg; |
+ pPrg = getRowTrigger(pParse, p, pTab, orconf); |
+ assert( pPrg || pParse->nErr || pParse->db->mallocFailed ); |
+ |
+ /* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program |
+ ** is a pointer to the sub-vdbe containing the trigger program. */ |
+ if( pPrg ){ |
+ int bRecursive = (p->zName && 0==(pParse->db->flags&SQLITE_RecTriggers)); |
+ |
+ sqlite3VdbeAddOp4(v, OP_Program, reg, ignoreJump, ++pParse->nMem, |
+ (const char *)pPrg->pProgram, P4_SUBPROGRAM); |
+ VdbeComment( |
+ (v, "Call: %s.%s", (p->zName?p->zName:"fkey"), onErrorText(orconf))); |
+ |
+ /* Set the P5 operand of the OP_Program instruction to non-zero if |
+ ** recursive invocation of this trigger program is disallowed. Recursive |
+ ** invocation is disallowed if (a) the sub-program is really a trigger, |
+ ** not a foreign key action, and (b) the flag to enable recursive triggers |
+ ** is clear. */ |
+ sqlite3VdbeChangeP5(v, (u8)bRecursive); |
+ } |
+} |
+ |
+/* |
+** This is called to code the required FOR EACH ROW triggers for an operation |
+** on table pTab. The operation to code triggers for (INSERT, UPDATE or DELETE) |
+** is given by the op parameter. The tr_tm parameter determines whether the |
+** BEFORE or AFTER triggers are coded. If the operation is an UPDATE, then |
+** parameter pChanges is passed the list of columns being modified. |
+** |
+** If there are no triggers that fire at the specified time for the specified |
+** operation on pTab, this function is a no-op. |
+** |
+** The reg argument is the address of the first in an array of registers |
+** that contain the values substituted for the new.* and old.* references |
+** in the trigger program. If N is the number of columns in table pTab |
+** (a copy of pTab->nCol), then registers are populated as follows: |
+** |
+** Register Contains |
+** ------------------------------------------------------ |
+** reg+0 OLD.rowid |
+** reg+1 OLD.* value of left-most column of pTab |
+** ... ... |
+** reg+N OLD.* value of right-most column of pTab |
+** reg+N+1 NEW.rowid |
+** reg+N+2 OLD.* value of left-most column of pTab |
+** ... ... |
+** reg+N+N+1 NEW.* value of right-most column of pTab |
+** |
+** For ON DELETE triggers, the registers containing the NEW.* values will |
+** never be accessed by the trigger program, so they are not allocated or |
+** populated by the caller (there is no data to populate them with anyway). |
+** Similarly, for ON INSERT triggers the values stored in the OLD.* registers |
+** are never accessed, and so are not allocated by the caller. So, for an |
+** ON INSERT trigger, the value passed to this function as parameter reg |
+** is not a readable register, although registers (reg+N) through |
+** (reg+N+N+1) are. |
+** |
+** Parameter orconf is the default conflict resolution algorithm for the |
+** trigger program to use (REPLACE, IGNORE etc.). Parameter ignoreJump |
+** is the instruction that control should jump to if a trigger program |
+** raises an IGNORE exception. |
+*/ |
+SQLITE_PRIVATE void sqlite3CodeRowTrigger( |
+ Parse *pParse, /* Parse context */ |
+ Trigger *pTrigger, /* List of triggers on table pTab */ |
+ 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 reg, /* The first in an array of registers (see above) */ |
+ int orconf, /* ON CONFLICT policy */ |
+ int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */ |
+){ |
+ Trigger *p; /* Used to iterate through pTrigger list */ |
+ |
+ assert( op==TK_UPDATE || op==TK_INSERT || op==TK_DELETE ); |
+ assert( tr_tm==TRIGGER_BEFORE || tr_tm==TRIGGER_AFTER ); |
+ assert( (op==TK_UPDATE)==(pChanges!=0) ); |
+ |
+ for(p=pTrigger; p; p=p->pNext){ |
+ |
+ /* Sanity checking: The schema for the trigger and for the table are |
+ ** always defined. The trigger must be in the same schema as the table |
+ ** or else it must be a TEMP trigger. */ |
+ assert( p->pSchema!=0 ); |
+ assert( p->pTabSchema!=0 ); |
+ assert( p->pSchema==p->pTabSchema |
+ || p->pSchema==pParse->db->aDb[1].pSchema ); |
+ |
+ /* Determine whether we should code this trigger */ |
+ if( p->op==op |
+ && p->tr_tm==tr_tm |
+ && checkColumnOverlap(p->pColumns, pChanges) |
+ ){ |
+ sqlite3CodeRowTriggerDirect(pParse, p, pTab, reg, orconf, ignoreJump); |
+ } |
+ } |
+} |
+ |
+/* |
+** Triggers may access values stored in the old.* or new.* pseudo-table. |
+** This function returns a 32-bit bitmask indicating which columns of the |
+** old.* or new.* tables actually are used by triggers. This information |
+** may be used by the caller, for example, to avoid having to load the entire |
+** old.* record into memory when executing an UPDATE or DELETE command. |
+** |
+** Bit 0 of the returned mask is set if the left-most column of the |
+** table may be accessed using an [old|new].<col> reference. Bit 1 is set if |
+** the second leftmost column value is required, and so on. If there |
+** are more than 32 columns in the table, and at least one of the columns |
+** with an index greater than 32 may be accessed, 0xffffffff is returned. |
+** |
+** It is not possible to determine if the old.rowid or new.rowid column is |
+** accessed by triggers. The caller must always assume that it is. |
+** |
+** Parameter isNew must be either 1 or 0. If it is 0, then the mask returned |
+** applies to the old.* table. If 1, the new.* table. |
+** |
+** Parameter tr_tm must be a mask with one or both of the TRIGGER_BEFORE |
+** and TRIGGER_AFTER bits set. Values accessed by BEFORE triggers are only |
+** included in the returned mask if the TRIGGER_BEFORE bit is set in the |
+** tr_tm parameter. Similarly, values accessed by AFTER triggers are only |
+** included in the returned mask if the TRIGGER_AFTER bit is set in tr_tm. |
+*/ |
+SQLITE_PRIVATE u32 sqlite3TriggerColmask( |
+ Parse *pParse, /* Parse context */ |
+ Trigger *pTrigger, /* List of triggers on table pTab */ |
+ ExprList *pChanges, /* Changes list for any UPDATE OF triggers */ |
+ int isNew, /* 1 for new.* ref mask, 0 for old.* ref mask */ |
+ int tr_tm, /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */ |
+ Table *pTab, /* The table to code triggers from */ |
+ int orconf /* Default ON CONFLICT policy for trigger steps */ |
+){ |
+ const int op = pChanges ? TK_UPDATE : TK_DELETE; |
+ u32 mask = 0; |
+ Trigger *p; |
+ |
+ assert( isNew==1 || isNew==0 ); |
+ for(p=pTrigger; p; p=p->pNext){ |
+ if( p->op==op && (tr_tm&p->tr_tm) |
+ && checkColumnOverlap(p->pColumns,pChanges) |
+ ){ |
+ TriggerPrg *pPrg; |
+ pPrg = getRowTrigger(pParse, p, pTab, orconf); |
+ if( pPrg ){ |
+ mask |= pPrg->aColmask[isNew]; |
+ } |
+ } |
+ } |
+ |
+ return mask; |
+} |
+ |
+#endif /* !defined(SQLITE_OMIT_TRIGGER) */ |
+ |
+/************** End of trigger.c *********************************************/ |
+/************** Begin file update.c ******************************************/ |
+/* |
+** 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. |
+*/ |
+/* #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 */ |
+ int onError /* ON CONFLICT strategy */ |
+); |
+#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. |
+** |
+** If parameter iReg is not negative, code an OP_RealAffinity instruction |
+** on register iReg. This is used when an equivalent integer value is |
+** stored in place of an 8-byte floating point value in order to save |
+** space. |
+*/ |
+SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){ |
+ assert( pTab!=0 ); |
+ if( !pTab->pSelect ){ |
+ sqlite3_value *pValue = 0; |
+ 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 ){ |
+ sqlite3VdbeAppendP4(v, pValue, P4_MEM); |
+ } |
+ } |
+#ifndef SQLITE_OMIT_FLOATING_POINT |
+ if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){ |
+ sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg); |
+ } |
+#endif |
+} |
+ |
+/* |
+** 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 |
+*/ |
+SQLITE_PRIVATE 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 addrTop = 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 */ |
+ Index *pPk; /* The PRIMARY KEY index for WITHOUT ROWID tables */ |
+ int nIdx; /* Number of indices that need updating */ |
+ int iBaseCur; /* Base cursor number */ |
+ int iDataCur; /* Cursor for the canonical data btree */ |
+ int iIdxCur; /* Cursor for the first index */ |
+ sqlite3 *db; /* The database structure */ |
+ int *aRegIdx = 0; /* First register in array assigned to each index */ |
+ 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. */ |
+ u8 *aToOpen; /* 1 for tables and indices to be opened */ |
+ u8 chngPk; /* PRIMARY KEY changed in a WITHOUT ROWID table */ |
+ u8 chngRowid; /* Rowid changed in a normal table */ |
+ u8 chngKey; /* Either chngPk or chngRowid */ |
+ Expr *pRowidExpr = 0; /* Expression defining the new record number */ |
+ AuthContext sContext; /* The authorization context */ |
+ NameContext sNC; /* The name-context to resolve expressions in */ |
+ int iDb; /* Database containing the table being updated */ |
+ int eOnePass; /* ONEPASS_XXX value from where.c */ |
+ int hasFK; /* True if foreign key processing is required */ |
+ int labelBreak; /* Jump here to break out of UPDATE loop */ |
+ int labelContinue; /* Jump here to continue next step of UPDATE loop */ |
+ int flags; /* Flags for sqlite3WhereBegin() */ |
+ |
+#ifndef SQLITE_OMIT_TRIGGER |
+ int isView; /* True when updating a view (INSTEAD OF trigger) */ |
+ Trigger *pTrigger; /* List of triggers on pTab, if required */ |
+ int tmask; /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */ |
+#endif |
+ int newmask; /* Mask of NEW.* columns accessed by BEFORE triggers */ |
+ int iEph = 0; /* Ephemeral table holding all primary key values */ |
+ int nKey = 0; /* Number of elements in regKey for WITHOUT ROWID */ |
+ int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */ |
+ int addrOpen = 0; /* Address of OP_OpenEphemeral */ |
+ int iPk = 0; /* First of nPk cells holding PRIMARY KEY value */ |
+ i16 nPk = 0; /* Number of components of the PRIMARY KEY */ |
+ int bReplace = 0; /* True if REPLACE conflict resolution might happen */ |
+ |
+ /* Register Allocations */ |
+ int regRowCount = 0; /* A count of rows changed */ |
+ int regOldRowid = 0; /* The old rowid */ |
+ int regNewRowid = 0; /* The new rowid */ |
+ int regNew = 0; /* Content of the NEW.* table in triggers */ |
+ int regOld = 0; /* Content of OLD.* table in triggers */ |
+ int regRowSet = 0; /* Rowset of rows to be updated */ |
+ int regKey = 0; /* composite PRIMARY KEY value */ |
+ |
+ memset(&sContext, 0, sizeof(sContext)); |
+ 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 |
+ pTrigger = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges, &tmask); |
+ isView = pTab->pSelect!=0; |
+ assert( pTrigger || tmask==0 ); |
+#else |
+# define pTrigger 0 |
+# define isView 0 |
+# define tmask 0 |
+#endif |
+#ifdef SQLITE_OMIT_VIEW |
+# undef isView |
+# define isView 0 |
+#endif |
+ |
+ if( sqlite3ViewGetColumnNames(pParse, pTab) ){ |
+ goto update_cleanup; |
+ } |
+ if( sqlite3IsReadOnly(pParse, pTab, tmask) ){ |
+ goto update_cleanup; |
+ } |
+ |
+ /* 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 = iBaseCur = iDataCur = pParse->nTab++; |
+ iIdxCur = iDataCur+1; |
+ pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); |
+ for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ |
+ if( IsPrimaryKeyIndex(pIdx) && pPk!=0 ){ |
+ iDataCur = pParse->nTab; |
+ pTabList->a[0].iCursor = iDataCur; |
+ } |
+ pParse->nTab++; |
+ } |
+ |
+ /* Allocate space for aXRef[], aRegIdx[], and aToOpen[]. |
+ ** Initialize aXRef[] and aToOpen[] to their default values. |
+ */ |
+ aXRef = sqlite3DbMallocRawNN(db, sizeof(int) * (pTab->nCol+nIdx) + nIdx+2 ); |
+ if( aXRef==0 ) goto update_cleanup; |
+ aRegIdx = aXRef+pTab->nCol; |
+ aToOpen = (u8*)(aRegIdx+nIdx); |
+ memset(aToOpen, 1, nIdx+1); |
+ aToOpen[nIdx+1] = 0; |
+ for(i=0; i<pTab->nCol; i++) aXRef[i] = -1; |
+ |
+ /* 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 = chngPk = 0; |
+ for(i=0; i<pChanges->nExpr; i++){ |
+ if( sqlite3ResolveExprNames(&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; |
+ }else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){ |
+ chngPk = 1; |
+ } |
+ aXRef[j] = i; |
+ break; |
+ } |
+ } |
+ if( j>=pTab->nCol ){ |
+ if( pPk==0 && sqlite3IsRowid(pChanges->a[i].zName) ){ |
+ j = -1; |
+ chngRowid = 1; |
+ pRowidExpr = pChanges->a[i].pExpr; |
+ }else{ |
+ sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName); |
+ pParse->checkSchema = 1; |
+ goto update_cleanup; |
+ } |
+ } |
+#ifndef SQLITE_OMIT_AUTHORIZATION |
+ { |
+ int rc; |
+ rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName, |
+ j<0 ? "ROWID" : pTab->aCol[j].zName, |
+ db->aDb[iDb].zDbSName); |
+ if( rc==SQLITE_DENY ){ |
+ goto update_cleanup; |
+ }else if( rc==SQLITE_IGNORE ){ |
+ aXRef[j] = -1; |
+ } |
+ } |
+#endif |
+ } |
+ assert( (chngRowid & chngPk)==0 ); |
+ assert( chngRowid==0 || chngRowid==1 ); |
+ assert( chngPk==0 || chngPk==1 ); |
+ chngKey = chngRowid + chngPk; |
+ |
+ /* The SET expressions are not actually used inside the WHERE loop. |
+ ** So reset the colUsed mask. Unless this is a virtual table. In that |
+ ** case, set all bits of the colUsed mask (to ensure that the virtual |
+ ** table implementation makes all columns available). |
+ */ |
+ pTabList->a[0].colUsed = IsVirtual(pTab) ? ALLBITS : 0; |
+ |
+ hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngKey); |
+ |
+ /* There is one entry in the aRegIdx[] array for each index on the table |
+ ** being updated. Fill in aRegIdx[] with a register number that will hold |
+ ** the key for accessing each index. |
+ ** |
+ ** FIXME: Be smarter about omitting indexes that use expressions. |
+ */ |
+ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ |
+ int reg; |
+ if( chngKey || hasFK || pIdx->pPartIdxWhere || pIdx==pPk ){ |
+ reg = ++pParse->nMem; |
+ pParse->nMem += pIdx->nColumn; |
+ }else{ |
+ reg = 0; |
+ for(i=0; i<pIdx->nKeyCol; i++){ |
+ i16 iIdxCol = pIdx->aiColumn[i]; |
+ if( iIdxCol<0 || aXRef[iIdxCol]>=0 ){ |
+ reg = ++pParse->nMem; |
+ pParse->nMem += pIdx->nColumn; |
+ if( (onError==OE_Replace) |
+ || (onError==OE_Default && pIdx->onError==OE_Replace) |
+ ){ |
+ bReplace = 1; |
+ } |
+ break; |
+ } |
+ } |
+ } |
+ if( reg==0 ) aToOpen[j+1] = 0; |
+ aRegIdx[j] = reg; |
+ } |
+ if( bReplace ){ |
+ /* If REPLACE conflict resolution might be invoked, open cursors on all |
+ ** indexes in case they are needed to delete records. */ |
+ memset(aToOpen, 1, nIdx+1); |
+ } |
+ |
+ /* Begin generating code. */ |
+ v = sqlite3GetVdbe(pParse); |
+ if( v==0 ) goto update_cleanup; |
+ if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); |
+ sqlite3BeginWriteOperation(pParse, 1, iDb); |
+ |
+ /* Allocate required registers. */ |
+ if( !IsVirtual(pTab) ){ |
+ regRowSet = ++pParse->nMem; |
+ regOldRowid = regNewRowid = ++pParse->nMem; |
+ if( chngPk || pTrigger || hasFK ){ |
+ regOld = pParse->nMem + 1; |
+ pParse->nMem += pTab->nCol; |
+ } |
+ if( chngKey || pTrigger || hasFK ){ |
+ regNewRowid = ++pParse->nMem; |
+ } |
+ regNew = pParse->nMem + 1; |
+ pParse->nMem += pTab->nCol; |
+ } |
+ |
+ /* Start the view context. */ |
+ if( isView ){ |
+ sqlite3AuthContextPush(pParse, &sContext, pTab->zName); |
+ } |
+ |
+ /* If we are trying to update a view, realize that view into |
+ ** an ephemeral table. |
+ */ |
+#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) |
+ if( isView ){ |
+ sqlite3MaterializeView(pParse, pTab, pWhere, iDataCur); |
+ } |
+#endif |
+ |
+ /* Resolve the column names in all the expressions in the |
+ ** WHERE clause. |
+ */ |
+ if( sqlite3ResolveExprNames(&sNC, pWhere) ){ |
+ goto update_cleanup; |
+ } |
+ |
+#ifndef SQLITE_OMIT_VIRTUALTABLE |
+ /* Virtual tables must be handled separately */ |
+ if( IsVirtual(pTab) ){ |
+ updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef, |
+ pWhere, onError); |
+ goto update_cleanup; |
+ } |
+#endif |
+ |
+ /* Initialize the count of updated rows */ |
+ if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab ){ |
+ regRowCount = ++pParse->nMem; |
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); |
+ } |
+ |
+ if( HasRowid(pTab) ){ |
+ sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid); |
+ }else{ |
+ assert( pPk!=0 ); |
+ nPk = pPk->nKeyCol; |
+ iPk = pParse->nMem+1; |
+ pParse->nMem += nPk; |
+ regKey = ++pParse->nMem; |
+ iEph = pParse->nTab++; |
+ |
+ sqlite3VdbeAddOp2(v, OP_Null, 0, iPk); |
+ addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk); |
+ sqlite3VdbeSetP4KeyInfo(pParse, pPk); |
+ } |
+ |
+ /* Begin the database scan. |
+ ** |
+ ** Do not consider a single-pass strategy for a multi-row update if |
+ ** there are any triggers or foreign keys to process, or rows may |
+ ** be deleted as a result of REPLACE conflict handling. Any of these |
+ ** things might disturb a cursor being used to scan through the table |
+ ** or index, causing a single-pass approach to malfunction. */ |
+ flags = WHERE_ONEPASS_DESIRED|WHERE_SEEK_UNIQ_TABLE; |
+ if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){ |
+ flags |= WHERE_ONEPASS_MULTIROW; |
+ } |
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, flags, iIdxCur); |
+ if( pWInfo==0 ) goto update_cleanup; |
+ |
+ /* A one-pass strategy that might update more than one row may not |
+ ** be used if any column of the index used for the scan is being |
+ ** updated. Otherwise, if there is an index on "b", statements like |
+ ** the following could create an infinite loop: |
+ ** |
+ ** UPDATE t1 SET b=b+1 WHERE b>? |
+ ** |
+ ** Fall back to ONEPASS_OFF if where.c has selected a ONEPASS_MULTI |
+ ** strategy that uses an index for which one or more columns are being |
+ ** updated. */ |
+ eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); |
+ if( eOnePass==ONEPASS_MULTI ){ |
+ int iCur = aiCurOnePass[1]; |
+ if( iCur>=0 && iCur!=iDataCur && aToOpen[iCur-iBaseCur] ){ |
+ eOnePass = ONEPASS_OFF; |
+ } |
+ assert( iCur!=iDataCur || !HasRowid(pTab) ); |
+ } |
+ |
+ if( HasRowid(pTab) ){ |
+ /* Read the rowid of the current row of the WHERE scan. In ONEPASS_OFF |
+ ** mode, write the rowid into the FIFO. In either of the one-pass modes, |
+ ** leave it in register regOldRowid. */ |
+ sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid); |
+ if( eOnePass==ONEPASS_OFF ){ |
+ sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid); |
+ } |
+ }else{ |
+ /* Read the PK of the current row into an array of registers. In |
+ ** ONEPASS_OFF mode, serialize the array into a record and store it in |
+ ** the ephemeral table. Or, in ONEPASS_SINGLE or MULTI mode, change |
+ ** the OP_OpenEphemeral instruction to a Noop (the ephemeral table |
+ ** is not required) and leave the PK fields in the array of registers. */ |
+ for(i=0; i<nPk; i++){ |
+ assert( pPk->aiColumn[i]>=0 ); |
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur,pPk->aiColumn[i],iPk+i); |
+ } |
+ if( eOnePass ){ |
+ sqlite3VdbeChangeToNoop(v, addrOpen); |
+ nKey = nPk; |
+ regKey = iPk; |
+ }else{ |
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey, |
+ sqlite3IndexAffinityStr(db, pPk), nPk); |
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEph, regKey, iPk, nPk); |
+ } |
+ } |
+ |
+ if( eOnePass!=ONEPASS_MULTI ){ |
+ sqlite3WhereEnd(pWInfo); |
+ } |
+ |
+ labelBreak = sqlite3VdbeMakeLabel(v); |
+ if( !isView ){ |
+ int addrOnce = 0; |
+ |
+ /* Open every index that needs updating. */ |
+ if( eOnePass!=ONEPASS_OFF ){ |
+ if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0; |
+ if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0; |
+ } |
+ |
+ if( eOnePass==ONEPASS_MULTI && (nIdx-(aiCurOnePass[1]>=0))>0 ){ |
+ addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); |
+ } |
+ sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur, aToOpen, |
+ 0, 0); |
+ if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce); |
+ } |
+ |
+ /* Top of the update loop */ |
+ if( eOnePass!=ONEPASS_OFF ){ |
+ if( !isView && aiCurOnePass[0]!=iDataCur && aiCurOnePass[1]!=iDataCur ){ |
+ assert( pPk ); |
+ sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey); |
+ VdbeCoverageNeverTaken(v); |
+ } |
+ if( eOnePass==ONEPASS_SINGLE ){ |
+ labelContinue = labelBreak; |
+ }else{ |
+ labelContinue = sqlite3VdbeMakeLabel(v); |
+ } |
+ sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak); |
+ VdbeCoverageIf(v, pPk==0); |
+ VdbeCoverageIf(v, pPk!=0); |
+ }else if( pPk ){ |
+ labelContinue = sqlite3VdbeMakeLabel(v); |
+ sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v); |
+ addrTop = sqlite3VdbeAddOp2(v, OP_RowData, iEph, regKey); |
+ sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0); |
+ VdbeCoverage(v); |
+ }else{ |
+ labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, labelBreak, |
+ regOldRowid); |
+ VdbeCoverage(v); |
+ sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid); |
+ VdbeCoverage(v); |
+ } |
+ |
+ /* If the record number will change, set register regNewRowid to |
+ ** contain the new value. If the record number is not being modified, |
+ ** then regNewRowid is the same register as regOldRowid, which is |
+ ** already populated. */ |
+ assert( chngKey || pTrigger || hasFK || regOldRowid==regNewRowid ); |
+ if( chngRowid ){ |
+ sqlite3ExprCode(pParse, pRowidExpr, regNewRowid); |
+ sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid); VdbeCoverage(v); |
+ } |
+ |
+ /* Compute the old pre-UPDATE content of the row being changed, if that |
+ ** information is needed */ |
+ if( chngPk || hasFK || pTrigger ){ |
+ u32 oldmask = (hasFK ? sqlite3FkOldmask(pParse, pTab) : 0); |
+ oldmask |= sqlite3TriggerColmask(pParse, |
+ pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError |
+ ); |
+ for(i=0; i<pTab->nCol; i++){ |
+ if( oldmask==0xffffffff |
+ || (i<32 && (oldmask & MASKBIT32(i))!=0) |
+ || (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0 |
+ ){ |
+ testcase( oldmask!=0xffffffff && i==31 ); |
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regOld+i); |
+ }else{ |
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+i); |
+ } |
+ } |
+ if( chngRowid==0 && pPk==0 ){ |
+ sqlite3VdbeAddOp2(v, OP_Copy, regOldRowid, regNewRowid); |
+ } |
+ } |
+ |
+ /* Populate the array of registers beginning at regNew with the new |
+ ** row data. This array is used to check constants, create the new |
+ ** table and index records, and as the values for any new.* references |
+ ** made by triggers. |
+ ** |
+ ** If there are one or more BEFORE triggers, then do not populate the |
+ ** registers associated with columns that are (a) not modified by |
+ ** this UPDATE statement and (b) not accessed by new.* references. The |
+ ** values for registers not modified by the UPDATE must be reloaded from |
+ ** the database after the BEFORE triggers are fired anyway (as the trigger |
+ ** may have modified them). So not loading those that are not going to |
+ ** be used eliminates some redundant opcodes. |
+ */ |
+ newmask = sqlite3TriggerColmask( |
+ pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError |
+ ); |
+ for(i=0; i<pTab->nCol; i++){ |
+ if( i==pTab->iPKey ){ |
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); |
+ }else{ |
+ j = aXRef[i]; |
+ if( j>=0 ){ |
+ sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i); |
+ }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i)) ){ |
+ /* This branch loads the value of a column that will not be changed |
+ ** into a register. This is done if there are no BEFORE triggers, or |
+ ** if there are one or more BEFORE triggers that use this value via |
+ ** a new.* reference in a trigger program. |
+ */ |
+ testcase( i==31 ); |
+ testcase( i==32 ); |
+ sqlite3ExprCodeGetColumnToReg(pParse, pTab, i, iDataCur, regNew+i); |
+ }else{ |
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); |
+ } |
+ } |
+ } |
+ |
+ /* Fire any BEFORE UPDATE triggers. This happens before constraints are |
+ ** verified. One could argue that this is wrong. |
+ */ |
+ if( tmask&TRIGGER_BEFORE ){ |
+ sqlite3TableAffinity(v, pTab, regNew); |
+ sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, |
+ TRIGGER_BEFORE, pTab, regOldRowid, onError, labelContinue); |
+ |
+ /* The row-trigger may have deleted the row being updated. In this |
+ ** case, jump to the next row. No updates or AFTER triggers are |
+ ** required. This behavior - what happens when the row being updated |
+ ** is deleted or renamed by a BEFORE trigger - is left undefined in the |
+ ** documentation. |
+ */ |
+ if( pPk ){ |
+ sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue,regKey,nKey); |
+ VdbeCoverage(v); |
+ }else{ |
+ sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid); |
+ VdbeCoverage(v); |
+ } |
+ |
+ /* If it did not delete it, the row-trigger may still have modified |
+ ** some of the columns of the row being updated. Load the values for |
+ ** all columns not modified by the update statement into their |
+ ** registers in case this has happened. |
+ */ |
+ for(i=0; i<pTab->nCol; i++){ |
+ if( aXRef[i]<0 && i!=pTab->iPKey ){ |
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i); |
+ } |
+ } |
+ } |
+ |
+ if( !isView ){ |
+ int addr1 = 0; /* Address of jump instruction */ |
+ |
+ /* Do constraint checks. */ |
+ assert( regOldRowid>0 ); |
+ sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, |
+ regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace, |
+ aXRef); |
+ |
+ /* Do FK constraint checks. */ |
+ if( hasFK ){ |
+ sqlite3FkCheck(pParse, pTab, regOldRowid, 0, aXRef, chngKey); |
+ } |
+ |
+ /* Delete the index entries associated with the current record. */ |
+ if( bReplace || chngKey ){ |
+ if( pPk ){ |
+ addr1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey); |
+ }else{ |
+ addr1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid); |
+ } |
+ VdbeCoverageNeverTaken(v); |
+ } |
+ sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx, -1); |
+ |
+ /* If changing the rowid value, or if there are foreign key constraints |
+ ** to process, delete the old record. Otherwise, add a noop OP_Delete |
+ ** to invoke the pre-update hook. |
+ ** |
+ ** That (regNew==regnewRowid+1) is true is also important for the |
+ ** pre-update hook. If the caller invokes preupdate_new(), the returned |
+ ** value is copied from memory cell (regNewRowid+1+iCol), where iCol |
+ ** is the column index supplied by the user. |
+ */ |
+ assert( regNew==regNewRowid+1 ); |
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK |
+ sqlite3VdbeAddOp3(v, OP_Delete, iDataCur, |
+ OPFLAG_ISUPDATE | ((hasFK || chngKey) ? 0 : OPFLAG_ISNOOP), |
+ regNewRowid |
+ ); |
+ if( eOnePass==ONEPASS_MULTI ){ |
+ assert( hasFK==0 && chngKey==0 ); |
+ sqlite3VdbeChangeP5(v, OPFLAG_SAVEPOSITION); |
+ } |
+ if( !pParse->nested ){ |
+ sqlite3VdbeAppendP4(v, pTab, P4_TABLE); |
+ } |
+#else |
+ if( hasFK || chngKey ){ |
+ sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0); |
+ } |
+#endif |
+ if( bReplace || chngKey ){ |
+ sqlite3VdbeJumpHere(v, addr1); |
+ } |
+ |
+ if( hasFK ){ |
+ sqlite3FkCheck(pParse, pTab, 0, regNewRowid, aXRef, chngKey); |
+ } |
+ |
+ /* Insert the new index entries and the new record. */ |
+ sqlite3CompleteInsertion( |
+ pParse, pTab, iDataCur, iIdxCur, regNewRowid, aRegIdx, |
+ OPFLAG_ISUPDATE | (eOnePass==ONEPASS_MULTI ? OPFLAG_SAVEPOSITION : 0), |
+ 0, 0 |
+ ); |
+ |
+ /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to |
+ ** handle rows (possibly in other tables) that refer via a foreign key |
+ ** to the row just updated. */ |
+ if( hasFK ){ |
+ sqlite3FkActions(pParse, pTab, pChanges, regOldRowid, aXRef, chngKey); |
+ } |
+ } |
+ |
+ /* Increment the row counter |
+ */ |
+ if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab){ |
+ sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); |
+ } |
+ |
+ sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, |
+ TRIGGER_AFTER, pTab, regOldRowid, onError, labelContinue); |
+ |
+ /* Repeat the above with the next record to be updated, until |
+ ** all record selected by the WHERE clause have been updated. |
+ */ |
+ if( eOnePass==ONEPASS_SINGLE ){ |
+ /* Nothing to do at end-of-loop for a single-pass */ |
+ }else if( eOnePass==ONEPASS_MULTI ){ |
+ sqlite3VdbeResolveLabel(v, labelContinue); |
+ sqlite3WhereEnd(pWInfo); |
+ }else if( pPk ){ |
+ sqlite3VdbeResolveLabel(v, labelContinue); |
+ sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); VdbeCoverage(v); |
+ }else{ |
+ sqlite3VdbeGoto(v, labelContinue); |
+ } |
+ sqlite3VdbeResolveLabel(v, labelBreak); |
+ |
+ /* Update the sqlite_sequence table by storing the content of the |
+ ** maximum rowid counter values recorded while inserting into |
+ ** autoincrement tables. |
+ */ |
+ if( pParse->nested==0 && pParse->pTriggerTab==0 ){ |
+ sqlite3AutoincrementEnd(pParse); |
+ } |
+ |
+ /* |
+ ** 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->pTriggerTab && !pParse->nested ){ |
+ sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1); |
+ sqlite3VdbeSetNumCols(v, 1); |
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", SQLITE_STATIC); |
+ } |
+ |
+update_cleanup: |
+ sqlite3AuthContextPop(&sContext); |
+ sqlite3DbFree(db, aXRef); /* Also frees aRegIdx[] and aToOpen[] */ |
+ sqlite3SrcListDelete(db, pTabList); |
+ sqlite3ExprListDelete(db, pChanges); |
+ sqlite3ExprDelete(db, pWhere); |
+ return; |
+} |
+/* Make sure "isView" and other macros defined above are undefined. Otherwise |
+** they may interfere with compilation of other functions in this file |
+** (or in another file, if this file becomes part of the amalgamation). */ |
+#ifdef isView |
+ #undef isView |
+#endif |
+#ifdef pTrigger |
+ #undef pTrigger |
+#endif |
+ |
+#ifndef SQLITE_OMIT_VIRTUALTABLE |
+/* |
+** Generate code for an UPDATE of a virtual table. |
+** |
+** There are two possible strategies - the default and the special |
+** "onepass" strategy. Onepass is only used if the virtual table |
+** implementation indicates that pWhere may match at most one row. |
+** |
+** The default strategy is to create an ephemeral table that contains |
+** for each row to be changed: |
+** |
+** (A) The original rowid of that row. |
+** (B) The revised rowid for the row. |
+** (C) The content of every column in the row. |
+** |
+** Then loop through the contents of this ephemeral table executing a |
+** VUpdate for each row. When finished, drop the ephemeral table. |
+** |
+** The "onepass" strategy does not use an ephemeral table. Instead, it |
+** stores the same values (A, B and C above) in a register array and |
+** makes a single invocation of 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 */ |
+ int onError /* ON CONFLICT strategy */ |
+){ |
+ Vdbe *v = pParse->pVdbe; /* Virtual machine under construction */ |
+ int ephemTab; /* Table holding the result of the SELECT */ |
+ int i; /* Loop counter */ |
+ sqlite3 *db = pParse->db; /* Database connection */ |
+ const char *pVTab = (const char*)sqlite3GetVTable(db, pTab); |
+ WhereInfo *pWInfo; |
+ int nArg = 2 + pTab->nCol; /* Number of arguments to VUpdate */ |
+ int regArg; /* First register in VUpdate arg array */ |
+ int regRec; /* Register in which to assemble record */ |
+ int regRowid; /* Register for ephem table rowid */ |
+ int iCsr = pSrc->a[0].iCursor; /* Cursor used for virtual table scan */ |
+ int aDummy[2]; /* Unused arg for sqlite3WhereOkOnePass() */ |
+ int bOnePass; /* True to use onepass strategy */ |
+ int addr; /* Address of OP_OpenEphemeral */ |
+ |
+ /* Allocate nArg registers to martial the arguments to VUpdate. Then |
+ ** create and open the ephemeral table in which the records created from |
+ ** these arguments will be temporarily stored. */ |
+ assert( v ); |
+ ephemTab = pParse->nTab++; |
+ addr= sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, nArg); |
+ regArg = pParse->nMem + 1; |
+ pParse->nMem += nArg; |
+ regRec = ++pParse->nMem; |
+ regRowid = ++pParse->nMem; |
+ |
+ /* Start scanning the virtual table */ |
+ pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0,0,WHERE_ONEPASS_DESIRED,0); |
+ if( pWInfo==0 ) return; |
+ |
+ /* Populate the argument registers. */ |
+ sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg); |
+ if( pRowid ){ |
+ sqlite3ExprCode(pParse, pRowid, regArg+1); |
+ }else{ |
+ sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg+1); |
+ } |
+ for(i=0; i<pTab->nCol; i++){ |
+ if( aXRef[i]>=0 ){ |
+ sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i); |
+ }else{ |
+ sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i); |
+ } |
+ } |
+ |
+ bOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy); |
+ |
+ if( bOnePass ){ |
+ /* If using the onepass strategy, no-op out the OP_OpenEphemeral coded |
+ ** above. Also, if this is a top-level parse (not a trigger), clear the |
+ ** multi-write flag so that the VM does not open a statement journal */ |
+ sqlite3VdbeChangeToNoop(v, addr); |
+ if( sqlite3IsToplevel(pParse) ){ |
+ pParse->isMultiWrite = 0; |
+ } |
+ }else{ |
+ /* Create a record from the argument register contents and insert it into |
+ ** the ephemeral table. */ |
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regArg, nArg, regRec); |
+ sqlite3VdbeAddOp2(v, OP_NewRowid, ephemTab, regRowid); |
+ sqlite3VdbeAddOp3(v, OP_Insert, ephemTab, regRec, regRowid); |
+ } |
+ |
+ |
+ if( bOnePass==0 ){ |
+ /* End the virtual table scan */ |
+ sqlite3WhereEnd(pWInfo); |
+ |
+ /* Begin scannning through the ephemeral table. */ |
+ addr = sqlite3VdbeAddOp1(v, OP_Rewind, ephemTab); VdbeCoverage(v); |
+ |
+ /* Extract arguments from the current row of the ephemeral table and |
+ ** invoke the VUpdate method. */ |
+ for(i=0; i<nArg; i++){ |
+ sqlite3VdbeAddOp3(v, OP_Column, ephemTab, i, regArg+i); |
+ } |
+ } |
+ sqlite3VtabMakeWritable(pParse, pTab); |
+ sqlite3VdbeAddOp4(v, OP_VUpdate, 0, nArg, regArg, pVTab, P4_VTAB); |
+ sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError); |
+ sqlite3MayAbort(pParse); |
+ |
+ /* End of the ephemeral table scan. Or, if using the onepass strategy, |
+ ** jump to here if the scan visited zero rows. */ |
+ if( bOnePass==0 ){ |
+ sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v); |
+ sqlite3VdbeJumpHere(v, addr); |
+ sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0); |
+ }else{ |
+ sqlite3WhereEnd(pWInfo); |
+ } |
+} |
+#endif /* SQLITE_OMIT_VIRTUALTABLE */ |
+ |
+/************** End of update.c **********************************************/ |
+/************** Begin file vacuum.c ******************************************/ |
+/* |
+** 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. |
+*/ |
+/* #include "sqliteInt.h" */ |
+/* #include "vdbeInt.h" */ |
+ |
+#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) |
+ |
+/* |
+** Execute zSql on database db. |
+** |
+** If zSql returns rows, then each row will have exactly one |
+** column. (This will only happen if zSql begins with "SELECT".) |
+** Take each row of result and call execSql() again recursively. |
+** |
+** The execSqlF() routine does the same thing, except it accepts |
+** a format string as its third argument |
+*/ |
+static int execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){ |
+ sqlite3_stmt *pStmt; |
+ int rc; |
+ |
+ /* printf("SQL: [%s]\n", zSql); fflush(stdout); */ |
+ rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); |
+ if( rc!=SQLITE_OK ) return rc; |
+ while( SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){ |
+ const char *zSubSql = (const char*)sqlite3_column_text(pStmt,0); |
+ assert( sqlite3_strnicmp(zSql,"SELECT",6)==0 ); |
+ if( zSubSql ){ |
+ assert( zSubSql[0]!='S' ); |
+ rc = execSql(db, pzErrMsg, zSubSql); |
+ if( rc!=SQLITE_OK ) break; |
+ } |
+ } |
+ assert( rc!=SQLITE_ROW ); |
+ if( rc==SQLITE_DONE ) rc = SQLITE_OK; |
+ if( rc ){ |
+ sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db)); |
+ } |
+ (void)sqlite3_finalize(pStmt); |
+ return rc; |
+} |
+static int execSqlF(sqlite3 *db, char **pzErrMsg, const char *zSql, ...){ |
+ char *z; |
+ va_list ap; |
+ int rc; |
+ va_start(ap, zSql); |
+ z = sqlite3VMPrintf(db, zSql, ap); |
+ va_end(ap); |
+ if( z==0 ) return SQLITE_NOMEM; |
+ rc = execSql(db, pzErrMsg, z); |
+ sqlite3DbFree(db, z); |
+ return rc; |
+} |
+ |
+/* |
+** The VACUUM command is used to clean up the database, |
+** collapse free space, etc. It is modelled after the VACUUM command |
+** in PostgreSQL. The VACUUM command works as follows: |
+** |
+** (1) Create a new transient database file |
+** (2) Copy all content from the database being vacuumed into |
+** the new transient database file |
+** (3) Copy content from the transient database back into the |
+** original database. |
+** |
+** The transient database requires temporary disk space approximately |
+** equal to the size of the original database. The copy operation of |
+** step (3) requires additional temporary disk space approximately equal |
+** to the size of the original database for the rollback journal. |
+** Hence, temporary disk space that is approximately 2x the size of the |
+** original database is required. Every page of the database is written |
+** approximately 3 times: Once for step (2) and twice for step (3). |
+** Two writes per page are required in step (3) because the original |
+** database content must be written into the rollback journal prior to |
+** overwriting the database with the vacuumed content. |
+** |
+** Only 1x temporary space and only 1x writes would be required if |
+** the copy of step (3) were replaced by deleting the original database |
+** and renaming the transient database as the original. But that will |
+** not work if other processes are attached to the original database. |
+** And a power loss in between deleting the original and renaming the |
+** transient would cause the database file to appear to be deleted |
+** following reboot. |
+*/ |
+SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse, Token *pNm){ |
+ Vdbe *v = sqlite3GetVdbe(pParse); |
+ int iDb = pNm ? sqlite3TwoPartName(pParse, pNm, pNm, &pNm) : 0; |
+ if( v && (iDb>=2 || iDb==0) ){ |
+ sqlite3VdbeAddOp1(v, OP_Vacuum, iDb); |
+ sqlite3VdbeUsesBtree(v, iDb); |
+ } |
+ return; |
+} |
+ |
+/* |
+** This routine implements the OP_Vacuum opcode of the VDBE. |
+*/ |
+SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){ |
+ int rc = SQLITE_OK; /* Return code from service routines */ |
+ Btree *pMain; /* The database being vacuumed */ |
+ Btree *pTemp; /* The temporary database we vacuum into */ |
+ 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 */ |
+ u8 saved_mTrace; /* Saved trace settings */ |
+ Db *pDb = 0; /* Database to detach at end of vacuum */ |
+ int isMemDb; /* True if vacuuming a :memory: database */ |
+ int nRes; /* Bytes of reserved space at the end of each page */ |
+ int nDb; /* Number of attached databases */ |
+ const char *zDbMain; /* Schema name of database to vacuum */ |
+ |
+ if( !db->autoCommit ){ |
+ sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction"); |
+ return SQLITE_ERROR; |
+ } |
+ if( db->nVdbeActive>1 ){ |
+ sqlite3SetString(pzErrMsg, db,"cannot VACUUM - SQL statements in progress"); |
+ return SQLITE_ERROR; |
+ } |
+ |
+ /* Save the current value of the database flags so that it can be |
+ ** restored before returning. Then set the writable-schema flag, and |
+ ** disable CHECK and foreign key constraints. */ |
+ saved_flags = db->flags; |
+ saved_nChange = db->nChange; |
+ saved_nTotalChange = db->nTotalChange; |
+ saved_mTrace = db->mTrace; |
+ db->flags |= (SQLITE_WriteSchema | SQLITE_IgnoreChecks |
+ | SQLITE_PreferBuiltin | SQLITE_Vacuum); |
+ db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder | SQLITE_CountRows); |
+ db->mTrace = 0; |
+ |
+ zDbMain = db->aDb[iDb].zDbSName; |
+ pMain = db->aDb[iDb].pBt; |
+ isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain)); |
+ |
+ /* 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. |
+ */ |
+ nDb = db->nDb; |
+ rc = execSql(db, pzErrMsg, "ATTACH''AS vacuum_db"); |
+ if( rc!=SQLITE_OK ) goto end_of_vacuum; |
+ assert( (db->nDb-1)==nDb ); |
+ pDb = &db->aDb[nDb]; |
+ assert( strcmp(pDb->zDbSName,"vacuum_db")==0 ); |
+ pTemp = pDb->pBt; |
+ |
+ /* The call to execSql() to attach the temp database has left the file |
+ ** locked (as there was more than one active statement when the transaction |
+ ** to read the schema was concluded. Unlock it here so that this doesn't |
+ ** cause problems for the call to BtreeSetPageSize() below. */ |
+ sqlite3BtreeCommit(pTemp); |
+ |
+ nRes = sqlite3BtreeGetOptimalReserve(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 |
+ |
+ sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size); |
+ sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0)); |
+ sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF|PAGER_CACHESPILL); |
+ |
+ /* Begin a transaction and take an exclusive lock on the main database |
+ ** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below, |
+ ** to ensure that we do not try to change the page-size on a WAL database. |
+ */ |
+ rc = execSql(db, pzErrMsg, "BEGIN"); |
+ if( rc!=SQLITE_OK ) goto end_of_vacuum; |
+ rc = sqlite3BtreeBeginTrans(pMain, 2); |
+ if( rc!=SQLITE_OK ) goto end_of_vacuum; |
+ |
+ /* Do not attempt to change the page size for a WAL database */ |
+ if( sqlite3PagerGetJournalMode(sqlite3BtreePager(pMain)) |
+ ==PAGER_JOURNALMODE_WAL ){ |
+ db->nextPagesize = 0; |
+ } |
+ |
+ if( sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), nRes, 0) |
+ || (!isMemDb && sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes, 0)) |
+ || NEVER(db->mallocFailed) |
+ ){ |
+ rc = SQLITE_NOMEM_BKPT; |
+ goto end_of_vacuum; |
+ } |
+ |
+#ifndef SQLITE_OMIT_AUTOVACUUM |
+ sqlite3BtreeSetAutoVacuum(pTemp, db->nextAutovac>=0 ? db->nextAutovac : |
+ sqlite3BtreeGetAutoVacuum(pMain)); |
+#endif |
+ |
+ /* Query the schema of the main database. Create a mirror schema |
+ ** in the temporary database. |
+ */ |
+ db->init.iDb = nDb; /* force new CREATE statements into vacuum_db */ |
+ rc = execSqlF(db, pzErrMsg, |
+ "SELECT sql FROM \"%w\".sqlite_master" |
+ " WHERE type='table'AND name<>'sqlite_sequence'" |
+ " AND coalesce(rootpage,1)>0", |
+ zDbMain |
+ ); |
+ if( rc!=SQLITE_OK ) goto end_of_vacuum; |
+ rc = execSqlF(db, pzErrMsg, |
+ "SELECT sql FROM \"%w\".sqlite_master" |
+ " WHERE type='index' AND length(sql)>10", |
+ zDbMain |
+ ); |
+ if( rc!=SQLITE_OK ) goto end_of_vacuum; |
+ db->init.iDb = 0; |
+ |
+ /* Loop through the tables in the main database. For each, do |
+ ** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy |
+ ** the contents to the temporary database. |
+ */ |
+ rc = execSqlF(db, pzErrMsg, |
+ "SELECT'INSERT INTO vacuum_db.'||quote(name)" |
+ "||' SELECT*FROM\"%w\".'||quote(name)" |
+ "FROM vacuum_db.sqlite_master " |
+ "WHERE type='table'AND coalesce(rootpage,1)>0", |
+ zDbMain |
+ ); |
+ assert( (db->flags & SQLITE_Vacuum)!=0 ); |
+ db->flags &= ~SQLITE_Vacuum; |
+ 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 = execSqlF(db, pzErrMsg, |
+ "INSERT INTO vacuum_db.sqlite_master" |
+ " SELECT*FROM \"%w\".sqlite_master" |
+ " WHERE type IN('view','trigger')" |
+ " OR(type='table'AND rootpage=0)", |
+ zDbMain |
+ ); |
+ if( rc ) goto end_of_vacuum; |
+ |
+ /* At this point, there is a write transaction open on both the |
+ ** vacuum database and the main database. Assuming no error occurs, |
+ ** both transactions are closed by this block - the main database |
+ ** transaction by sqlite3BtreeCopyFile() and the other by an explicit |
+ ** call to sqlite3BtreeCommit(). |
+ */ |
+ { |
+ 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[] = { |
+ BTREE_SCHEMA_VERSION, 1, /* Add one to the old schema cookie */ |
+ BTREE_DEFAULT_CACHE_SIZE, 0, /* Preserve the default page cache size */ |
+ BTREE_TEXT_ENCODING, 0, /* Preserve the text encoding */ |
+ BTREE_USER_VERSION, 0, /* Preserve the user version */ |
+ BTREE_APPLICATION_ID, 0, /* Preserve the application id */ |
+ }; |
+ |
+ assert( 1==sqlite3BtreeIsInTrans(pTemp) ); |
+ assert( 1==sqlite3BtreeIsInTrans(pMain) ); |
+ |
+ /* Copy Btree meta values */ |
+ for(i=0; i<ArraySize(aCopy); i+=2){ |
+ /* GetMeta() and UpdateMeta() cannot fail in this context because |
+ ** we already have page 1 loaded into cache and marked dirty. */ |
+ sqlite3BtreeGetMeta(pMain, aCopy[i], &meta); |
+ rc = sqlite3BtreeUpdateMeta(pTemp, aCopy[i], meta+aCopy[i+1]); |
+ if( NEVER(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; |
+#ifndef SQLITE_OMIT_AUTOVACUUM |
+ sqlite3BtreeSetAutoVacuum(pMain, sqlite3BtreeGetAutoVacuum(pTemp)); |
+#endif |
+ } |
+ |
+ assert( rc==SQLITE_OK ); |
+ rc = sqlite3BtreeSetPageSize(pMain, sqlite3BtreeGetPageSize(pTemp), nRes,1); |
+ |
+end_of_vacuum: |
+ /* Restore the original value of db->flags */ |
+ db->init.iDb = 0; |
+ db->flags = saved_flags; |
+ db->nChange = saved_nChange; |
+ db->nTotalChange = saved_nTotalChange; |
+ db->mTrace = saved_mTrace; |
+ sqlite3BtreeSetPageSize(pMain, -1, -1, 1); |
+ |
+ /* 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; |
+ } |
+ |
+ /* This both clears the schemas and reduces the size of the db->aDb[] |
+ ** array. */ |
+ sqlite3ResetAllSchemasOfConnection(db); |
+ |
+ return rc; |
+} |
+ |
+#endif /* SQLITE_OMIT_VACUUM && SQLITE_OMIT_ATTACH */ |
+ |
+/************** End of vacuum.c **********************************************/ |
+/************** Begin file vtab.c ********************************************/ |
+/* |
+** 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. |
+*/ |
+#ifndef SQLITE_OMIT_VIRTUALTABLE |
+/* #include "sqliteInt.h" */ |
+ |
+/* |
+** Before a virtual table xCreate() or xConnect() method is invoked, the |
+** sqlite3.pVtabCtx member variable is set to point to an instance of |
+** this struct allocated on the stack. It is used by the implementation of |
+** the sqlite3_declare_vtab() and sqlite3_vtab_config() APIs, both of which |
+** are invoked only from within xCreate and xConnect methods. |
+*/ |
+struct VtabCtx { |
+ VTable *pVTable; /* The virtual table being constructed */ |
+ Table *pTab; /* The Table object to which the virtual table belongs */ |
+ VtabCtx *pPrior; /* Parent context (if any) */ |
+ int bDeclared; /* True after sqlite3_declare_vtab() is called */ |
+}; |
+ |
+/* |
+** Construct and install a Module object for a virtual table. When this |
+** routine is called, it is guaranteed that all appropriate locks are held |
+** and the module is not already part of the connection. |
+*/ |
+SQLITE_PRIVATE Module *sqlite3VtabCreateModule( |
+ 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 */ |
+){ |
+ Module *pMod; |
+ int nName = sqlite3Strlen30(zName); |
+ pMod = (Module *)sqlite3DbMallocRawNN(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; |
+ pMod->pEpoTab = 0; |
+ pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod); |
+ assert( pDel==0 || pDel==pMod ); |
+ if( pDel ){ |
+ sqlite3OomFault(db); |
+ sqlite3DbFree(db, pDel); |
+ pMod = 0; |
+ } |
+ } |
+ return pMod; |
+} |
+ |
+/* |
+** The actual function that does the work of creating a new module. |
+** This function implements the sqlite3_create_module() and |
+** sqlite3_create_module_v2() interfaces. |
+*/ |
+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 = SQLITE_OK; |
+ |
+ sqlite3_mutex_enter(db->mutex); |
+ if( sqlite3HashFind(&db->aModule, zName) ){ |
+ rc = SQLITE_MISUSE_BKPT; |
+ }else{ |
+ (void)sqlite3VtabCreateModule(db, zName, pModule, pAux, xDestroy); |
+ } |
+ rc = sqlite3ApiExit(db, rc); |
+ if( rc!=SQLITE_OK && xDestroy ) xDestroy(pAux); |
+ sqlite3_mutex_leave(db->mutex); |
+ return rc; |
+} |
+ |
+ |
+/* |
+** External API function used to create a new virtual-table module. |
+*/ |
+SQLITE_API 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 */ |
+){ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) || zName==0 ) return SQLITE_MISUSE_BKPT; |
+#endif |
+ return createModule(db, zName, pModule, pAux, 0); |
+} |
+ |
+/* |
+** External API function used to create a new virtual-table module. |
+*/ |
+SQLITE_API 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 */ |
+){ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) || zName==0 ) return SQLITE_MISUSE_BKPT; |
+#endif |
+ 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. |
+*/ |
+SQLITE_PRIVATE void sqlite3VtabLock(VTable *pVTab){ |
+ pVTab->nRef++; |
+} |
+ |
+ |
+/* |
+** pTab is a pointer to a Table structure representing a virtual-table. |
+** Return a pointer to the VTable object used by connection db to access |
+** this virtual-table, if one has been created, or NULL otherwise. |
+*/ |
+SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3 *db, Table *pTab){ |
+ VTable *pVtab; |
+ assert( IsVirtual(pTab) ); |
+ for(pVtab=pTab->pVTable; pVtab && pVtab->db!=db; pVtab=pVtab->pNext); |
+ return pVtab; |
+} |
+ |
+/* |
+** Decrement the ref-count on a virtual table object. When the ref-count |
+** reaches zero, call the xDisconnect() method to delete the object. |
+*/ |
+SQLITE_PRIVATE void sqlite3VtabUnlock(VTable *pVTab){ |
+ sqlite3 *db = pVTab->db; |
+ |
+ assert( db ); |
+ assert( pVTab->nRef>0 ); |
+ assert( db->magic==SQLITE_MAGIC_OPEN || db->magic==SQLITE_MAGIC_ZOMBIE ); |
+ |
+ pVTab->nRef--; |
+ if( pVTab->nRef==0 ){ |
+ sqlite3_vtab *p = pVTab->pVtab; |
+ if( p ){ |
+ p->pModule->xDisconnect(p); |
+ } |
+ sqlite3DbFree(db, pVTab); |
+ } |
+} |
+ |
+/* |
+** Table p is a virtual table. This function moves all elements in the |
+** p->pVTable list to the sqlite3.pDisconnect lists of their associated |
+** database connections to be disconnected at the next opportunity. |
+** Except, if argument db is not NULL, then the entry associated with |
+** connection db is left in the p->pVTable list. |
+*/ |
+static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){ |
+ VTable *pRet = 0; |
+ VTable *pVTable = p->pVTable; |
+ p->pVTable = 0; |
+ |
+ /* Assert that the mutex (if any) associated with the BtShared database |
+ ** that contains table p is held by the caller. See header comments |
+ ** above function sqlite3VtabUnlockList() for an explanation of why |
+ ** this makes it safe to access the sqlite3.pDisconnect list of any |
+ ** database connection that may have an entry in the p->pVTable list. |
+ */ |
+ assert( db==0 || sqlite3SchemaMutexHeld(db, 0, p->pSchema) ); |
+ |
+ while( pVTable ){ |
+ sqlite3 *db2 = pVTable->db; |
+ VTable *pNext = pVTable->pNext; |
+ assert( db2 ); |
+ if( db2==db ){ |
+ pRet = pVTable; |
+ p->pVTable = pRet; |
+ pRet->pNext = 0; |
+ }else{ |
+ pVTable->pNext = db2->pDisconnect; |
+ db2->pDisconnect = pVTable; |
+ } |
+ pVTable = pNext; |
+ } |
+ |
+ assert( !db || pRet ); |
+ return pRet; |
+} |
+ |
+/* |
+** Table *p is a virtual table. This function removes the VTable object |
+** for table *p associated with database connection db from the linked |
+** list in p->pVTab. It also decrements the VTable ref count. This is |
+** used when closing database connection db to free all of its VTable |
+** objects without disturbing the rest of the Schema object (which may |
+** be being used by other shared-cache connections). |
+*/ |
+SQLITE_PRIVATE void sqlite3VtabDisconnect(sqlite3 *db, Table *p){ |
+ VTable **ppVTab; |
+ |
+ assert( IsVirtual(p) ); |
+ assert( sqlite3BtreeHoldsAllMutexes(db) ); |
+ assert( sqlite3_mutex_held(db->mutex) ); |
+ |
+ for(ppVTab=&p->pVTable; *ppVTab; ppVTab=&(*ppVTab)->pNext){ |
+ if( (*ppVTab)->db==db ){ |
+ VTable *pVTab = *ppVTab; |
+ *ppVTab = pVTab->pNext; |
+ sqlite3VtabUnlock(pVTab); |
+ break; |
+ } |
+ } |
+} |
+ |
+ |
+/* |
+** Disconnect all the virtual table objects in the sqlite3.pDisconnect list. |
+** |
+** This function may only be called when the mutexes associated with all |
+** shared b-tree databases opened using connection db are held by the |
+** caller. This is done to protect the sqlite3.pDisconnect list. The |
+** sqlite3.pDisconnect list is accessed only as follows: |
+** |
+** 1) By this function. In this case, all BtShared mutexes and the mutex |
+** associated with the database handle itself must be held. |
+** |
+** 2) By function vtabDisconnectAll(), when it adds a VTable entry to |
+** the sqlite3.pDisconnect list. In this case either the BtShared mutex |
+** associated with the database the virtual table is stored in is held |
+** or, if the virtual table is stored in a non-sharable database, then |
+** the database handle mutex is held. |
+** |
+** As a result, a sqlite3.pDisconnect cannot be accessed simultaneously |
+** by multiple threads. It is thread-safe. |
+*/ |
+SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3 *db){ |
+ VTable *p = db->pDisconnect; |
+ db->pDisconnect = 0; |
+ |
+ assert( sqlite3BtreeHoldsAllMutexes(db) ); |
+ assert( sqlite3_mutex_held(db->mutex) ); |
+ |
+ if( p ){ |
+ sqlite3ExpirePreparedStatements(db); |
+ do { |
+ VTable *pNext = p->pNext; |
+ sqlite3VtabUnlock(p); |
+ p = pNext; |
+ }while( p ); |
+ } |
+} |
+ |
+/* |
+** Clear any and all virtual-table information from the Table record. |
+** This routine is called, for example, just before deleting the Table |
+** record. |
+** |
+** Since it is a virtual-table, the Table structure contains a pointer |
+** to the head of a linked list of VTable structures. Each VTable |
+** structure is associated with a single sqlite3* user of the schema. |
+** The reference count of the VTable structure associated with database |
+** connection db is decremented immediately (which may lead to the |
+** structure being xDisconnected and free). Any other VTable structures |
+** in the list are moved to the sqlite3.pDisconnect list of the associated |
+** database connection. |
+*/ |
+SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table *p){ |
+ if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p); |
+ if( p->azModuleArg ){ |
+ int i; |
+ for(i=0; i<p->nModuleArg; i++){ |
+ if( i!=1 ) 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 nBytes = sizeof(char *)*(2+pTable->nModuleArg); |
+ char **azModuleArg; |
+ azModuleArg = sqlite3DbRealloc(db, pTable->azModuleArg, nBytes); |
+ if( azModuleArg==0 ){ |
+ sqlite3DbFree(db, zArg); |
+ }else{ |
+ int i = pTable->nModuleArg++; |
+ 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. |
+*/ |
+SQLITE_PRIVATE 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 ifNotExists /* No error if the table already exists */ |
+){ |
+ int iDb; /* The database the table is being created in */ |
+ Table *pTable; /* The new virtual table */ |
+ sqlite3 *db; /* Database connection */ |
+ |
+ sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, ifNotExists); |
+ pTable = pParse->pNewTable; |
+ if( pTable==0 ) return; |
+ assert( 0==pTable->pIndex ); |
+ |
+ db = pParse->db; |
+ iDb = sqlite3SchemaToIndex(db, pTable->pSchema); |
+ assert( iDb>=0 ); |
+ |
+ pTable->tabFlags |= TF_Virtual; |
+ pTable->nModuleArg = 0; |
+ addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName)); |
+ addModuleArgument(db, pTable, 0); |
+ addModuleArgument(db, pTable, sqlite3DbStrDup(db, pTable->zName)); |
+ assert( (pParse->sNameToken.z==pName2->z && pName2->z!=0) |
+ || (pParse->sNameToken.z==pName1->z && pName2->z==0) |
+ ); |
+ pParse->sNameToken.n = (int)( |
+ &pModuleName->z[pModuleName->n] - pParse->sNameToken.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].zDbSName); |
+ } |
+#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. |
+*/ |
+SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ |
+ Table *pTab = pParse->pNewTable; /* The table being constructed */ |
+ sqlite3 *db = pParse->db; /* The database connection */ |
+ |
+ if( pTab==0 ) return; |
+ addArgumentToVtab(pParse); |
+ pParse->sArg.z = 0; |
+ if( pTab->nModuleArg<1 ) return; |
+ |
+ /* 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; |
+ int iReg; |
+ Vdbe *v; |
+ |
+ /* Compute the complete text of the CREATE VIRTUAL TABLE statement */ |
+ if( pEnd ){ |
+ pParse->sNameToken.n = (int)(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].zDbSName, MASTER_NAME, |
+ pTab->zName, |
+ pTab->zName, |
+ zStmt, |
+ pParse->regRowid |
+ ); |
+ sqlite3DbFree(db, zStmt); |
+ v = sqlite3GetVdbe(pParse); |
+ sqlite3ChangeCookie(pParse, iDb); |
+ |
+ sqlite3VdbeAddOp0(v, OP_Expire); |
+ zWhere = sqlite3MPrintf(db, "name='%q' AND type='table'", pTab->zName); |
+ sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere); |
+ |
+ iReg = ++pParse->nMem; |
+ sqlite3VdbeLoadString(v, iReg, pTab->zName); |
+ sqlite3VdbeAddOp2(v, OP_VCreate, iDb, iReg); |
+ } |
+ |
+ /* If we are rereading the sqlite_master table create the in-memory |
+ ** record of the table. The xConnect() method is not called until |
+ ** the first time the virtual table is used in an SQL statement. This |
+ ** allows a schema that contains virtual tables to be loaded before |
+ ** the required virtual table implementations are registered. */ |
+ else { |
+ Table *pOld; |
+ Schema *pSchema = pTab->pSchema; |
+ const char *zName = pTab->zName; |
+ assert( sqlite3SchemaMutexHeld(db, 0, pSchema) ); |
+ pOld = sqlite3HashInsert(&pSchema->tblHash, zName, pTab); |
+ if( pOld ){ |
+ sqlite3OomFault(db); |
+ assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */ |
+ return; |
+ } |
+ 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. |
+*/ |
+SQLITE_PRIVATE 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. |
+*/ |
+SQLITE_PRIVATE 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 = (int)(&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 |
+){ |
+ VtabCtx sCtx; |
+ VTable *pVTable; |
+ int rc; |
+ const char *const*azArg = (const char *const*)pTab->azModuleArg; |
+ int nArg = pTab->nModuleArg; |
+ char *zErr = 0; |
+ char *zModuleName; |
+ int iDb; |
+ VtabCtx *pCtx; |
+ |
+ /* Check that the virtual-table is not already being initialized */ |
+ for(pCtx=db->pVtabCtx; pCtx; pCtx=pCtx->pPrior){ |
+ if( pCtx->pTab==pTab ){ |
+ *pzErr = sqlite3MPrintf(db, |
+ "vtable constructor called recursively: %s", pTab->zName |
+ ); |
+ return SQLITE_LOCKED; |
+ } |
+ } |
+ |
+ zModuleName = sqlite3MPrintf(db, "%s", pTab->zName); |
+ if( !zModuleName ){ |
+ return SQLITE_NOMEM_BKPT; |
+ } |
+ |
+ pVTable = sqlite3DbMallocZero(db, sizeof(VTable)); |
+ if( !pVTable ){ |
+ sqlite3DbFree(db, zModuleName); |
+ return SQLITE_NOMEM_BKPT; |
+ } |
+ pVTable->db = db; |
+ pVTable->pMod = pMod; |
+ |
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
+ pTab->azModuleArg[1] = db->aDb[iDb].zDbSName; |
+ |
+ /* Invoke the virtual table constructor */ |
+ assert( &db->pVtabCtx ); |
+ assert( xConstruct ); |
+ sCtx.pTab = pTab; |
+ sCtx.pVTable = pVTable; |
+ sCtx.pPrior = db->pVtabCtx; |
+ sCtx.bDeclared = 0; |
+ db->pVtabCtx = &sCtx; |
+ rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); |
+ db->pVtabCtx = sCtx.pPrior; |
+ if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); |
+ assert( sCtx.pTab==pTab ); |
+ |
+ if( SQLITE_OK!=rc ){ |
+ if( zErr==0 ){ |
+ *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName); |
+ }else { |
+ *pzErr = sqlite3MPrintf(db, "%s", zErr); |
+ sqlite3_free(zErr); |
+ } |
+ sqlite3DbFree(db, pVTable); |
+ }else if( ALWAYS(pVTable->pVtab) ){ |
+ /* Justification of ALWAYS(): A correct vtab constructor must allocate |
+ ** the sqlite3_vtab object if successful. */ |
+ memset(pVTable->pVtab, 0, sizeof(pVTable->pVtab[0])); |
+ pVTable->pVtab->pModule = pMod->pModule; |
+ pVTable->nRef = 1; |
+ if( sCtx.bDeclared==0 ){ |
+ const char *zFormat = "vtable constructor did not declare schema: %s"; |
+ *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName); |
+ sqlite3VtabUnlock(pVTable); |
+ rc = SQLITE_ERROR; |
+ }else{ |
+ int iCol; |
+ u8 oooHidden = 0; |
+ /* If everything went according to plan, link the new VTable structure |
+ ** into the linked list headed by pTab->pVTable. Then loop through the |
+ ** columns of the table to see if any of them contain the token "hidden". |
+ ** If so, set the Column COLFLAG_HIDDEN flag and remove the token from |
+ ** the type string. */ |
+ pVTable->pNext = pTab->pVTable; |
+ pTab->pVTable = pVTable; |
+ |
+ for(iCol=0; iCol<pTab->nCol; iCol++){ |
+ char *zType = sqlite3ColumnType(&pTab->aCol[iCol], ""); |
+ int nType; |
+ int i = 0; |
+ nType = sqlite3Strlen30(zType); |
+ for(i=0; i<nType; i++){ |
+ if( 0==sqlite3StrNICmp("hidden", &zType[i], 6) |
+ && (i==0 || zType[i-1]==' ') |
+ && (zType[i+6]=='\0' || zType[i+6]==' ') |
+ ){ |
+ 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].colFlags |= COLFLAG_HIDDEN; |
+ oooHidden = TF_OOOHidden; |
+ }else{ |
+ pTab->tabFlags |= oooHidden; |
+ } |
+ } |
+ } |
+ } |
+ |
+ sqlite3DbFree(db, zModuleName); |
+ 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. |
+*/ |
+SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){ |
+ sqlite3 *db = pParse->db; |
+ const char *zMod; |
+ Module *pMod; |
+ int rc; |
+ |
+ assert( pTab ); |
+ if( (pTab->tabFlags & TF_Virtual)==0 || sqlite3GetVTable(db, pTab) ){ |
+ return SQLITE_OK; |
+ } |
+ |
+ /* Locate the required virtual table module */ |
+ zMod = pTab->azModuleArg[0]; |
+ pMod = (Module*)sqlite3HashFind(&db->aModule, zMod); |
+ |
+ if( !pMod ){ |
+ const char *zModule = pTab->azModuleArg[0]; |
+ sqlite3ErrorMsg(pParse, "no such module: %s", zModule); |
+ rc = SQLITE_ERROR; |
+ }else{ |
+ char *zErr = 0; |
+ rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr); |
+ if( rc!=SQLITE_OK ){ |
+ sqlite3ErrorMsg(pParse, "%s", zErr); |
+ } |
+ sqlite3DbFree(db, zErr); |
+ } |
+ |
+ return rc; |
+} |
+/* |
+** Grow the db->aVTrans[] array so that there is room for at least one |
+** more v-table. Return SQLITE_NOMEM if a malloc fails, or SQLITE_OK otherwise. |
+*/ |
+static int growVTrans(sqlite3 *db){ |
+ const int ARRAY_INCR = 5; |
+ |
+ /* Grow the sqlite3.aVTrans array if required */ |
+ if( (db->nVTrans%ARRAY_INCR)==0 ){ |
+ VTable **aVTrans; |
+ int nBytes = sizeof(sqlite3_vtab *) * (db->nVTrans + ARRAY_INCR); |
+ aVTrans = sqlite3DbRealloc(db, (void *)db->aVTrans, nBytes); |
+ if( !aVTrans ){ |
+ return SQLITE_NOMEM_BKPT; |
+ } |
+ memset(&aVTrans[db->nVTrans], 0, sizeof(sqlite3_vtab *)*ARRAY_INCR); |
+ db->aVTrans = aVTrans; |
+ } |
+ |
+ return SQLITE_OK; |
+} |
+ |
+/* |
+** Add the virtual table pVTab to the array sqlite3.aVTrans[]. Space should |
+** have already been reserved using growVTrans(). |
+*/ |
+static void addToVTrans(sqlite3 *db, VTable *pVTab){ |
+ /* Add pVtab to the end of sqlite3.aVTrans */ |
+ db->aVTrans[db->nVTrans++] = pVTab; |
+ sqlite3VtabLock(pVTab); |
+} |
+ |
+/* |
+** 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 to 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. |
+*/ |
+SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){ |
+ int rc = SQLITE_OK; |
+ Table *pTab; |
+ Module *pMod; |
+ const char *zMod; |
+ |
+ pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName); |
+ assert( pTab && (pTab->tabFlags & TF_Virtual)!=0 && !pTab->pVTable ); |
+ |
+ /* Locate the required virtual table module */ |
+ zMod = pTab->azModuleArg[0]; |
+ pMod = (Module*)sqlite3HashFind(&db->aModule, zMod); |
+ |
+ /* 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==0 || pMod->pModule->xCreate==0 || pMod->pModule->xDestroy==0 ){ |
+ *pzErr = sqlite3MPrintf(db, "no such module: %s", zMod); |
+ rc = SQLITE_ERROR; |
+ }else{ |
+ rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xCreate, pzErr); |
+ } |
+ |
+ /* Justification of ALWAYS(): The xConstructor method is required to |
+ ** create a valid sqlite3_vtab if it returns SQLITE_OK. */ |
+ if( rc==SQLITE_OK && ALWAYS(sqlite3GetVTable(db, pTab)) ){ |
+ rc = growVTrans(db); |
+ if( rc==SQLITE_OK ){ |
+ addToVTrans(db, sqlite3GetVTable(db, pTab)); |
+ } |
+ } |
+ |
+ 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. |
+*/ |
+SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ |
+ VtabCtx *pCtx; |
+ Parse *pParse; |
+ int rc = SQLITE_OK; |
+ Table *pTab; |
+ char *zErr = 0; |
+ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) || zCreateTable==0 ){ |
+ return SQLITE_MISUSE_BKPT; |
+ } |
+#endif |
+ sqlite3_mutex_enter(db->mutex); |
+ pCtx = db->pVtabCtx; |
+ if( !pCtx || pCtx->bDeclared ){ |
+ sqlite3Error(db, SQLITE_MISUSE); |
+ sqlite3_mutex_leave(db->mutex); |
+ return SQLITE_MISUSE_BKPT; |
+ } |
+ pTab = pCtx->pTab; |
+ assert( (pTab->tabFlags & TF_Virtual)!=0 ); |
+ |
+ pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); |
+ if( pParse==0 ){ |
+ rc = SQLITE_NOMEM_BKPT; |
+ }else{ |
+ pParse->declareVtab = 1; |
+ pParse->db = db; |
+ pParse->nQueryLoop = 1; |
+ |
+ if( SQLITE_OK==sqlite3RunParser(pParse, zCreateTable, &zErr) |
+ && pParse->pNewTable |
+ && !db->mallocFailed |
+ && !pParse->pNewTable->pSelect |
+ && (pParse->pNewTable->tabFlags & TF_Virtual)==0 |
+ ){ |
+ if( !pTab->aCol ){ |
+ Table *pNew = pParse->pNewTable; |
+ Index *pIdx; |
+ pTab->aCol = pNew->aCol; |
+ pTab->nCol = pNew->nCol; |
+ pTab->tabFlags |= pNew->tabFlags & (TF_WithoutRowid|TF_NoVisibleRowid); |
+ pNew->nCol = 0; |
+ pNew->aCol = 0; |
+ assert( pTab->pIndex==0 ); |
+ if( !HasRowid(pNew) && pCtx->pVTable->pMod->pModule->xUpdate!=0 ){ |
+ rc = SQLITE_ERROR; |
+ } |
+ pIdx = pNew->pIndex; |
+ if( pIdx ){ |
+ assert( pIdx->pNext==0 ); |
+ pTab->pIndex = pIdx; |
+ pNew->pIndex = 0; |
+ pIdx->pTable = pTab; |
+ } |
+ } |
+ pCtx->bDeclared = 1; |
+ }else{ |
+ sqlite3ErrorWithMsg(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr); |
+ sqlite3DbFree(db, zErr); |
+ rc = SQLITE_ERROR; |
+ } |
+ pParse->declareVtab = 0; |
+ |
+ if( pParse->pVdbe ){ |
+ sqlite3VdbeFinalize(pParse->pVdbe); |
+ } |
+ sqlite3DeleteTable(db, pParse->pNewTable); |
+ sqlite3ParserReset(pParse); |
+ sqlite3StackFree(db, pParse); |
+ } |
+ |
+ 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. |
+*/ |
+SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){ |
+ int rc = SQLITE_OK; |
+ Table *pTab; |
+ |
+ pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName); |
+ if( pTab!=0 && ALWAYS(pTab->pVTable!=0) ){ |
+ VTable *p; |
+ int (*xDestroy)(sqlite3_vtab *); |
+ for(p=pTab->pVTable; p; p=p->pNext){ |
+ assert( p->pVtab ); |
+ if( p->pVtab->nRef>0 ){ |
+ return SQLITE_LOCKED; |
+ } |
+ } |
+ p = vtabDisconnectAll(db, pTab); |
+ xDestroy = p->pMod->pModule->xDestroy; |
+ assert( xDestroy!=0 ); /* Checked before the virtual table is created */ |
+ rc = xDestroy(p->pVtab); |
+ /* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */ |
+ if( rc==SQLITE_OK ){ |
+ assert( pTab->pVTable==p && p->pNext==0 ); |
+ p->pVtab = 0; |
+ pTab->pVTable = 0; |
+ sqlite3VtabUnlock(p); |
+ } |
+ } |
+ |
+ 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 ){ |
+ VTable **aVTrans = db->aVTrans; |
+ db->aVTrans = 0; |
+ for(i=0; i<db->nVTrans; i++){ |
+ VTable *pVTab = aVTrans[i]; |
+ sqlite3_vtab *p = pVTab->pVtab; |
+ if( p ){ |
+ int (*x)(sqlite3_vtab *); |
+ x = *(int (**)(sqlite3_vtab *))((char *)p->pModule + offset); |
+ if( x ) x(p); |
+ } |
+ pVTab->iSavepoint = 0; |
+ sqlite3VtabUnlock(pVTab); |
+ } |
+ sqlite3DbFree(db, aVTrans); |
+ db->nVTrans = 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. |
+** |
+** If an error message is available, leave it in p->zErrMsg. |
+*/ |
+SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, Vdbe *p){ |
+ int i; |
+ int rc = SQLITE_OK; |
+ VTable **aVTrans = db->aVTrans; |
+ |
+ db->aVTrans = 0; |
+ for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){ |
+ int (*x)(sqlite3_vtab *); |
+ sqlite3_vtab *pVtab = aVTrans[i]->pVtab; |
+ if( pVtab && (x = pVtab->pModule->xSync)!=0 ){ |
+ rc = x(pVtab); |
+ sqlite3VtabImportErrmsg(p, pVtab); |
+ } |
+ } |
+ db->aVTrans = aVTrans; |
+ return rc; |
+} |
+ |
+/* |
+** Invoke the xRollback method of all virtual tables in the |
+** sqlite3.aVTrans array. Then clear the array itself. |
+*/ |
+SQLITE_PRIVATE 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. |
+*/ |
+SQLITE_PRIVATE 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. |
+*/ |
+SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *db, VTable *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( sqlite3VtabInSync(db) ){ |
+ return SQLITE_LOCKED; |
+ } |
+ if( !pVTab ){ |
+ return SQLITE_OK; |
+ } |
+ pModule = pVTab->pVtab->pModule; |
+ |
+ if( pModule->xBegin ){ |
+ int i; |
+ |
+ /* If pVtab is already in the aVTrans array, return early */ |
+ for(i=0; i<db->nVTrans; i++){ |
+ if( db->aVTrans[i]==pVTab ){ |
+ return SQLITE_OK; |
+ } |
+ } |
+ |
+ /* Invoke the xBegin method. If successful, add the vtab to the |
+ ** sqlite3.aVTrans[] array. */ |
+ rc = growVTrans(db); |
+ if( rc==SQLITE_OK ){ |
+ rc = pModule->xBegin(pVTab->pVtab); |
+ if( rc==SQLITE_OK ){ |
+ int iSvpt = db->nStatement + db->nSavepoint; |
+ addToVTrans(db, pVTab); |
+ if( iSvpt && pModule->xSavepoint ){ |
+ pVTab->iSavepoint = iSvpt; |
+ rc = pModule->xSavepoint(pVTab->pVtab, iSvpt-1); |
+ } |
+ } |
+ } |
+ } |
+ return rc; |
+} |
+ |
+/* |
+** Invoke either the xSavepoint, xRollbackTo or xRelease method of all |
+** virtual tables that currently have an open transaction. Pass iSavepoint |
+** as the second argument to the virtual table method invoked. |
+** |
+** If op is SAVEPOINT_BEGIN, the xSavepoint method is invoked. If it is |
+** SAVEPOINT_ROLLBACK, the xRollbackTo method. Otherwise, if op is |
+** SAVEPOINT_RELEASE, then the xRelease method of each virtual table with |
+** an open transaction is invoked. |
+** |
+** If any virtual table method returns an error code other than SQLITE_OK, |
+** processing is abandoned and the error returned to the caller of this |
+** function immediately. If all calls to virtual table methods are successful, |
+** SQLITE_OK is returned. |
+*/ |
+SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *db, int op, int iSavepoint){ |
+ int rc = SQLITE_OK; |
+ |
+ assert( op==SAVEPOINT_RELEASE||op==SAVEPOINT_ROLLBACK||op==SAVEPOINT_BEGIN ); |
+ assert( iSavepoint>=-1 ); |
+ if( db->aVTrans ){ |
+ int i; |
+ for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){ |
+ VTable *pVTab = db->aVTrans[i]; |
+ const sqlite3_module *pMod = pVTab->pMod->pModule; |
+ if( pVTab->pVtab && pMod->iVersion>=2 ){ |
+ int (*xMethod)(sqlite3_vtab *, int); |
+ switch( op ){ |
+ case SAVEPOINT_BEGIN: |
+ xMethod = pMod->xSavepoint; |
+ pVTab->iSavepoint = iSavepoint+1; |
+ break; |
+ case SAVEPOINT_ROLLBACK: |
+ xMethod = pMod->xRollbackTo; |
+ break; |
+ default: |
+ xMethod = pMod->xRelease; |
+ break; |
+ } |
+ if( xMethod && pVTab->iSavepoint>iSavepoint ){ |
+ rc = xMethod(pVTab->pVtab, iSavepoint); |
+ } |
+ } |
+ } |
+ } |
+ 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. |
+*/ |
+SQLITE_PRIVATE 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 (*xSFunc)(sqlite3_context*,int,sqlite3_value**) = 0; |
+ void *pArg = 0; |
+ FuncDef *pNew; |
+ int rc = 0; |
+ char *zLowerName; |
+ unsigned char *z; |
+ |
+ |
+ /* Check to see the left operand is a column in a virtual table */ |
+ if( NEVER(pExpr==0) ) return pDef; |
+ if( pExpr->op!=TK_COLUMN ) return pDef; |
+ pTab = pExpr->pTab; |
+ if( NEVER(pTab==0) ) return pDef; |
+ if( (pTab->tabFlags & TF_Virtual)==0 ) return pDef; |
+ pVtab = sqlite3GetVTable(db, 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, &xSFunc, &pArg); |
+ sqlite3DbFree(db, zLowerName); |
+ } |
+ if( rc==0 ){ |
+ return pDef; |
+ } |
+ |
+ /* Create a new ephemeral function definition for the overloaded |
+ ** function */ |
+ pNew = sqlite3DbMallocZero(db, sizeof(*pNew) |
+ + sqlite3Strlen30(pDef->zName) + 1); |
+ if( pNew==0 ){ |
+ return pDef; |
+ } |
+ *pNew = *pDef; |
+ pNew->zName = (const char*)&pNew[1]; |
+ memcpy((char*)&pNew[1], pDef->zName, sqlite3Strlen30(pDef->zName)+1); |
+ pNew->xSFunc = xSFunc; |
+ pNew->pUserData = pArg; |
+ pNew->funcFlags |= 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. |
+*/ |
+SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){ |
+ Parse *pToplevel = sqlite3ParseToplevel(pParse); |
+ int i, n; |
+ Table **apVtabLock; |
+ |
+ assert( IsVirtual(pTab) ); |
+ for(i=0; i<pToplevel->nVtabLock; i++){ |
+ if( pTab==pToplevel->apVtabLock[i] ) return; |
+ } |
+ n = (pToplevel->nVtabLock+1)*sizeof(pToplevel->apVtabLock[0]); |
+ apVtabLock = sqlite3_realloc64(pToplevel->apVtabLock, n); |
+ if( apVtabLock ){ |
+ pToplevel->apVtabLock = apVtabLock; |
+ pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab; |
+ }else{ |
+ sqlite3OomFault(pToplevel->db); |
+ } |
+} |
+ |
+/* |
+** Check to see if virtual table module pMod can be have an eponymous |
+** virtual table instance. If it can, create one if one does not already |
+** exist. Return non-zero if the eponymous virtual table instance exists |
+** when this routine returns, and return zero if it does not exist. |
+** |
+** An eponymous virtual table instance is one that is named after its |
+** module, and more importantly, does not require a CREATE VIRTUAL TABLE |
+** statement in order to come into existance. Eponymous virtual table |
+** instances always exist. They cannot be DROP-ed. |
+** |
+** Any virtual table module for which xConnect and xCreate are the same |
+** method can have an eponymous virtual table instance. |
+*/ |
+SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse *pParse, Module *pMod){ |
+ const sqlite3_module *pModule = pMod->pModule; |
+ Table *pTab; |
+ char *zErr = 0; |
+ int rc; |
+ sqlite3 *db = pParse->db; |
+ if( pMod->pEpoTab ) return 1; |
+ if( pModule->xCreate!=0 && pModule->xCreate!=pModule->xConnect ) return 0; |
+ pTab = sqlite3DbMallocZero(db, sizeof(Table)); |
+ if( pTab==0 ) return 0; |
+ pTab->zName = sqlite3DbStrDup(db, pMod->zName); |
+ if( pTab->zName==0 ){ |
+ sqlite3DbFree(db, pTab); |
+ return 0; |
+ } |
+ pMod->pEpoTab = pTab; |
+ pTab->nTabRef = 1; |
+ pTab->pSchema = db->aDb[0].pSchema; |
+ pTab->tabFlags |= TF_Virtual; |
+ pTab->nModuleArg = 0; |
+ pTab->iPKey = -1; |
+ addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName)); |
+ addModuleArgument(db, pTab, 0); |
+ addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName)); |
+ rc = vtabCallConstructor(db, pTab, pMod, pModule->xConnect, &zErr); |
+ if( rc ){ |
+ sqlite3ErrorMsg(pParse, "%s", zErr); |
+ sqlite3DbFree(db, zErr); |
+ sqlite3VtabEponymousTableClear(db, pMod); |
+ return 0; |
+ } |
+ return 1; |
+} |
+ |
+/* |
+** Erase the eponymous virtual table instance associated with |
+** virtual table module pMod, if it exists. |
+*/ |
+SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3 *db, Module *pMod){ |
+ Table *pTab = pMod->pEpoTab; |
+ if( pTab!=0 ){ |
+ /* Mark the table as Ephemeral prior to deleting it, so that the |
+ ** sqlite3DeleteTable() routine will know that it is not stored in |
+ ** the schema. */ |
+ pTab->tabFlags |= TF_Ephemeral; |
+ sqlite3DeleteTable(db, pTab); |
+ pMod->pEpoTab = 0; |
+ } |
+} |
+ |
+/* |
+** Return the ON CONFLICT resolution mode in effect for the virtual |
+** table update operation currently in progress. |
+** |
+** The results of this routine are undefined unless it is called from |
+** within an xUpdate method. |
+*/ |
+SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *db){ |
+ static const unsigned char aMap[] = { |
+ SQLITE_ROLLBACK, SQLITE_ABORT, SQLITE_FAIL, SQLITE_IGNORE, SQLITE_REPLACE |
+ }; |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; |
+#endif |
+ assert( OE_Rollback==1 && OE_Abort==2 && OE_Fail==3 ); |
+ assert( OE_Ignore==4 && OE_Replace==5 ); |
+ assert( db->vtabOnConflict>=1 && db->vtabOnConflict<=5 ); |
+ return (int)aMap[db->vtabOnConflict-1]; |
+} |
+ |
+/* |
+** Call from within the xCreate() or xConnect() methods to provide |
+** the SQLite core with additional information about the behavior |
+** of the virtual table being implemented. |
+*/ |
+SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){ |
+ va_list ap; |
+ int rc = SQLITE_OK; |
+ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; |
+#endif |
+ sqlite3_mutex_enter(db->mutex); |
+ va_start(ap, op); |
+ switch( op ){ |
+ case SQLITE_VTAB_CONSTRAINT_SUPPORT: { |
+ VtabCtx *p = db->pVtabCtx; |
+ if( !p ){ |
+ rc = SQLITE_MISUSE_BKPT; |
+ }else{ |
+ assert( p->pTab==0 || (p->pTab->tabFlags & TF_Virtual)!=0 ); |
+ p->pVTable->bConstraint = (u8)va_arg(ap, int); |
+ } |
+ break; |
+ } |
+ default: |
+ rc = SQLITE_MISUSE_BKPT; |
+ break; |
+ } |
+ va_end(ap); |
+ |
+ if( rc!=SQLITE_OK ) sqlite3Error(db, rc); |
+ sqlite3_mutex_leave(db->mutex); |
+ return rc; |
+} |
+ |
+#endif /* SQLITE_OMIT_VIRTUALTABLE */ |
+ |
+/************** End of vtab.c ************************************************/ |
+ |
+/* Chain include. */ |
+#include "sqlite3.06.c" |