📄 prepare.c
字号:
} called_initone = 1; } /* Once all the other databases have been initialised, load the schema ** for the TEMP database. This is loaded last, as the TEMP database ** schema may contain references to objects in other databases. */#ifndef SQLITE_OMIT_TEMPDB if( rc==SQLITE_OK && db->nDb>1 && !DbHasProperty(db, 1, DB_SchemaLoaded) ){ rc = sqlite3InitOne(db, 1, pzErrMsg); if( rc ){ sqlite3ResetInternalSchema(db, 1); } called_initone = 1; }#endif db->init.busy = 0; if( rc==SQLITE_OK && called_initone ){ sqlite3CommitInternalChanges(db); } return rc; }/*** This routine is a no-op if the database schema is already initialised.** Otherwise, the schema is loaded. An error code is returned.*/int sqlite3ReadSchema(Parse *pParse){ int rc = SQLITE_OK; sqlite3 *db = pParse->db; if( !db->init.busy ){ rc = sqlite3Init(db, &pParse->zErrMsg); } if( rc!=SQLITE_OK ){ pParse->rc = rc; pParse->nErr++; } return rc;}/*** Check schema cookies in all databases. If any cookie is out** of date, return 0. If all schema cookies are current, return 1.*/static int schemaIsValid(sqlite3 *db){ int iDb; int rc; BtCursor *curTemp; int cookie; int allOk = 1; for(iDb=0; allOk && iDb<db->nDb; iDb++){ Btree *pBt; pBt = db->aDb[iDb].pBt; if( pBt==0 ) continue; rc = sqlite3BtreeCursor(pBt, MASTER_ROOT, 0, 0, 0, &curTemp); if( rc==SQLITE_OK ){ rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&cookie); if( rc==SQLITE_OK && cookie!=db->aDb[iDb].pSchema->schema_cookie ){ allOk = 0; } sqlite3BtreeCloseCursor(curTemp); } } return allOk;}/*** Convert a schema pointer into the iDb index that indicates** which database file in db->aDb[] the schema refers to.**** If the same database is attached more than once, the first** attached database is returned.*/int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){ int i = -1000000; /* If pSchema is NULL, then return -1000000. This happens when code in ** expr.c is trying to resolve a reference to a transient table (i.e. one ** created by a sub-select). In this case the return value of this ** function should never be used. ** ** We return -1000000 instead of the more usual -1 simply because using ** -1000000 as incorrectly using -1000000 index into db->aDb[] is much ** more likely to cause a segfault than -1 (of course there are assert() ** statements too, but it never hurts to play the odds). */ if( pSchema ){ for(i=0; i<db->nDb; i++){ if( db->aDb[i].pSchema==pSchema ){ break; } } assert( i>=0 &&i>=0 && i<db->nDb ); } return i;}/*** Compile the UTF-8 encoded SQL statement zSql into a statement handle.*/int sqlite3Prepare( sqlite3 *db, /* Database handle. */ const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const char **pzTail /* OUT: End of parsed string */){ Parse sParse; char *zErrMsg = 0; int rc = SQLITE_OK; int i; /* Assert that malloc() has not failed */ assert( !sqlite3MallocFailed() ); assert( ppStmt ); *ppStmt = 0; if( sqlite3SafetyOn(db) ){ return SQLITE_MISUSE; } /* If any attached database schemas are locked, do not proceed with ** compilation. Instead return SQLITE_LOCKED immediately. */ for(i=0; i<db->nDb; i++) { Btree *pBt = db->aDb[i].pBt; if( pBt && sqlite3BtreeSchemaLocked(pBt) ){ const char *zDb = db->aDb[i].zName; sqlite3Error(db, SQLITE_LOCKED, "database schema is locked: %s", zDb); sqlite3SafetyOff(db); return SQLITE_LOCKED; } } memset(&sParse, 0, sizeof(sParse)); sParse.db = db; if( nBytes>=0 && zSql[nBytes]!=0 ){ char *zSqlCopy; if( nBytes>SQLITE_MAX_SQL_LENGTH ){ return SQLITE_TOOBIG; } zSqlCopy = sqlite3StrNDup(zSql, nBytes); if( zSqlCopy ){ sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg); sqliteFree(zSqlCopy); } sParse.zTail = &zSql[nBytes]; }else{ sqlite3RunParser(&sParse, zSql, &zErrMsg); } if( sqlite3MallocFailed() ){ sParse.rc = SQLITE_NOMEM; } if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK; if( sParse.checkSchema && !schemaIsValid(db) ){ sParse.rc = SQLITE_SCHEMA; } if( sParse.rc==SQLITE_SCHEMA ){ sqlite3ResetInternalSchema(db, 0); } if( sqlite3MallocFailed() ){ sParse.rc = SQLITE_NOMEM; } if( pzTail ){ *pzTail = sParse.zTail; } rc = sParse.rc;#ifndef SQLITE_OMIT_EXPLAIN if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){ if( sParse.explain==2 ){ sqlite3VdbeSetNumCols(sParse.pVdbe, 3); sqlite3VdbeSetColName(sParse.pVdbe, 0, COLNAME_NAME, "order", P3_STATIC); sqlite3VdbeSetColName(sParse.pVdbe, 1, COLNAME_NAME, "from", P3_STATIC); sqlite3VdbeSetColName(sParse.pVdbe, 2, COLNAME_NAME, "detail", P3_STATIC); }else{ sqlite3VdbeSetNumCols(sParse.pVdbe, 5); sqlite3VdbeSetColName(sParse.pVdbe, 0, COLNAME_NAME, "addr", P3_STATIC); sqlite3VdbeSetColName(sParse.pVdbe, 1, COLNAME_NAME, "opcode", P3_STATIC); sqlite3VdbeSetColName(sParse.pVdbe, 2, COLNAME_NAME, "p1", P3_STATIC); sqlite3VdbeSetColName(sParse.pVdbe, 3, COLNAME_NAME, "p2", P3_STATIC); sqlite3VdbeSetColName(sParse.pVdbe, 4, COLNAME_NAME, "p3", P3_STATIC); } }#endif if( sqlite3SafetyOff(db) ){ rc = SQLITE_MISUSE; } if( saveSqlFlag ){ sqlite3VdbeSetSql(sParse.pVdbe, zSql, sParse.zTail - zSql); } if( rc!=SQLITE_OK || sqlite3MallocFailed() ){ sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe); assert(!(*ppStmt)); }else{ *ppStmt = (sqlite3_stmt*)sParse.pVdbe; } if( zErrMsg ){ sqlite3Error(db, rc, "%s", zErrMsg); sqliteFree(zErrMsg); }else{ sqlite3Error(db, rc, 0); } rc = sqlite3ApiExit(db, rc); sqlite3ReleaseThreadData(); assert( (rc&db->errMask)==rc ); return rc;}/*** Rerun the compilation of a statement after a schema change.** Return true if the statement was recompiled successfully.** Return false if there is an error of some kind.*/int sqlite3Reprepare(Vdbe *p){ int rc; sqlite3_stmt *pNew; const char *zSql; sqlite3 *db; zSql = sqlite3VdbeGetSql(p); if( zSql==0 ){ return 0; } db = sqlite3VdbeDb(p); rc = sqlite3Prepare(db, zSql, -1, 0, &pNew, 0); if( rc ){ assert( pNew==0 ); return 0; }else{ assert( pNew!=0 ); } sqlite3VdbeSwap((Vdbe*)pNew, p); sqlite3_transfer_bindings(pNew, (sqlite3_stmt*)p); sqlite3VdbeResetStepResult((Vdbe*)pNew); sqlite3VdbeFinalize((Vdbe*)pNew); return 1;}/*** Two versions of the official API. Legacy and new use. In the legacy** version, the original SQL text is not saved in the prepared statement** and so if a schema change occurs, SQLITE_SCHEMA is returned by** sqlite3_step(). In the new version, the original SQL text is retained** and the statement is automatically recompiled if an schema change** occurs.*/int sqlite3_prepare( sqlite3 *db, /* Database handle. */ const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const char **pzTail /* OUT: End of parsed string */){ return sqlite3Prepare(db,zSql,nBytes,0,ppStmt,pzTail);}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 */){ return sqlite3Prepare(db,zSql,nBytes,1,ppStmt,pzTail);}#ifndef SQLITE_OMIT_UTF16/*** Compile the UTF-16 encoded SQL statement zSql into a statement handle.*/static int sqlite3Prepare16( sqlite3 *db, /* Database handle. */ const void *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ int saveSqlFlag, /* True to save SQL text into the sqlite3_stmt */ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const void **pzTail /* OUT: End of parsed string */){ /* This function currently works by first transforming the UTF-16 ** encoded string to UTF-8, then invoking sqlite3_prepare(). The ** tricky bit is figuring out the pointer to return in *pzTail. */ char *zSql8; const char *zTail8 = 0; int rc = SQLITE_OK; if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } zSql8 = sqlite3Utf16to8(zSql, nBytes); if( zSql8 ){ rc = sqlite3Prepare(db, zSql8, -1, saveSqlFlag, ppStmt, &zTail8); } if( zTail8 && pzTail ){ /* If sqlite3_prepare returns a tail pointer, we calculate the ** equivalent pointer into the UTF-16 string by counting the unicode ** characters between zSql8 and zTail8, and then returning a pointer ** the same number of characters into the UTF-16 string. */ int chars_parsed = sqlite3Utf8CharLen(zSql8, zTail8-zSql8); *pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, chars_parsed); } sqliteFree(zSql8); return sqlite3ApiExit(db, rc);}/*** Two versions of the official API. Legacy and new use. In the legacy** version, the original SQL text is not saved in the prepared statement** and so if a schema change occurs, SQLITE_SCHEMA is returned by** sqlite3_step(). In the new version, the original SQL text is retained** and the statement is automatically recompiled if an schema change** occurs.*/int sqlite3_prepare16( sqlite3 *db, /* Database handle. */ const void *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const void **pzTail /* OUT: End of parsed string */){ return sqlite3Prepare16(db,zSql,nBytes,0,ppStmt,pzTail);}int sqlite3_prepare16_v2( sqlite3 *db, /* Database handle. */ const void *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const void **pzTail /* OUT: End of parsed string */){ return sqlite3Prepare16(db,zSql,nBytes,1,ppStmt,pzTail);}#endif /* SQLITE_OMIT_UTF16 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -