📄 prepare.c
字号:
** file_format==1 Version 3.0.0. ** file_format==2 Version 3.1.3. ** file_format==3 Version 3.1.4. ** ** Version 3.0 can only use files with file_format==1. Version 3.1.3 ** can read and write files with file_format==1 or file_format==2. ** Version 3.1.4 can read and write file formats 1, 2 and 3. */ if( meta[1]>3 ){ sqlite3BtreeCloseCursor(curMain); sqlite3SetString(pzErrMsg, "unsupported file format", (char*)0); return SQLITE_ERROR; } sqlite3BtreeSetCacheSize(db->aDb[iDb].pBt, db->aDb[iDb].cache_size); /* Read the schema information out of the schema tables */ assert( db->init.busy ); if( rc==SQLITE_EMPTY ){ /* For an empty database, there is nothing to read */ rc = SQLITE_OK; }else{ char *zSql; zSql = sqlite3MPrintf( "SELECT name, rootpage, sql, '%s' FROM '%q'.%s", zDbNum, db->aDb[iDb].zName, zMasterName); sqlite3SafetyOff(db); rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); sqlite3SafetyOn(db); sqliteFree(zSql); sqlite3BtreeCloseCursor(curMain); } if( sqlite3_malloc_failed ){ sqlite3SetString(pzErrMsg, "out of memory", (char*)0); rc = SQLITE_NOMEM; sqlite3ResetInternalSchema(db, 0); } if( rc==SQLITE_OK ){ DbSetProperty(db, iDb, DB_SchemaLoaded); }else{ sqlite3ResetInternalSchema(db, iDb); } 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 the database is initialized, the SQLITE_Initialized** bit is set in the flags field of the sqlite structure. */int sqlite3Init(sqlite3 *db, char **pzErrMsg){ int i, rc; if( db->init.busy ) return SQLITE_OK; assert( (db->flags & SQLITE_Initialized)==0 ); rc = SQLITE_OK; db->init.busy = 1; for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue; rc = sqlite3InitOne(db, i, pzErrMsg); if( rc ){ sqlite3ResetInternalSchema(db, i); } } /* Once all the other databases have been initialised, load the schema ** for the TEMP database. This is loaded last, as the TEMP database ** schema may contain references to objects in other databases. */#ifndef SQLITE_OMIT_TEMPDB if( rc==SQLITE_OK && db->nDb>1 && !DbHasProperty(db, 1, DB_SchemaLoaded) ){ rc = sqlite3InitOne(db, 1, pzErrMsg); if( rc ){ sqlite3ResetInternalSchema(db, 1); } }#endif db->init.busy = 0; if( rc==SQLITE_OK ){ db->flags |= SQLITE_Initialized; sqlite3CommitInternalChanges(db); } if( rc!=SQLITE_OK ){ db->flags &= ~SQLITE_Initialized; } 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 ){ if( (db->flags & SQLITE_Initialized)==0 ){ rc = sqlite3Init(db, &pParse->zErrMsg); } } assert( rc!=SQLITE_OK || (db->flags & SQLITE_Initialized)||db->init.busy ); if( rc!=SQLITE_OK ){ pParse->rc = rc; pParse->nErr++; } 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].schema_cookie ){ allOk = 0; } sqlite3BtreeCloseCursor(curTemp); } } return allOk;}/*** Compile the UTF-8 encoded SQL statement zSql into a statement handle.*/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 */){ Parse sParse; char *zErrMsg = 0; int rc = SQLITE_OK; if( sqlite3_malloc_failed ){ return SQLITE_NOMEM; } assert( ppStmt ); *ppStmt = 0; if( sqlite3SafetyOn(db) ){ return SQLITE_MISUSE; } memset(&sParse, 0, sizeof(sParse)); sParse.db = db; sqlite3RunParser(&sParse, zSql, &zErrMsg); if( sqlite3_malloc_failed ){ rc = SQLITE_NOMEM; sqlite3RollbackAll(db); sqlite3ResetInternalSchema(db, 0); db->flags &= ~SQLITE_InTrans; goto prepare_out; } if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK; if( sParse.rc!=SQLITE_OK && sParse.checkSchema && !schemaIsValid(db) ){ sParse.rc = SQLITE_SCHEMA; } if( sParse.rc==SQLITE_SCHEMA ){ sqlite3ResetInternalSchema(db, 0); } if( pzTail ) *pzTail = sParse.zTail; rc = sParse.rc;#ifndef SQLITE_OMIT_EXPLAIN if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){ sqlite3VdbeSetNumCols(sParse.pVdbe, 5); sqlite3VdbeSetColName(sParse.pVdbe, 0, "addr", P3_STATIC); sqlite3VdbeSetColName(sParse.pVdbe, 1, "opcode", P3_STATIC); sqlite3VdbeSetColName(sParse.pVdbe, 2, "p1", P3_STATIC); sqlite3VdbeSetColName(sParse.pVdbe, 3, "p2", P3_STATIC); sqlite3VdbeSetColName(sParse.pVdbe, 4, "p3", P3_STATIC); } #endifprepare_out: if( sqlite3SafetyOff(db) ){ rc = SQLITE_MISUSE; } if( rc==SQLITE_OK ){ *ppStmt = (sqlite3_stmt*)sParse.pVdbe; }else if( sParse.pVdbe ){ sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe); } if( zErrMsg ){ sqlite3Error(db, rc, "%s", zErrMsg); sqliteFree(zErrMsg); }else{ sqlite3Error(db, rc, 0); } return rc;}#ifndef SQLITE_OMIT_UTF16/*** Compile the UTF-16 encoded SQL statement zSql into a statement handle.*/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 */){ /* 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 const *zSql8 = 0; char const *zTail8 = 0; int rc; sqlite3_value *pTmp; if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } pTmp = sqlite3GetTransientValue(db); sqlite3ValueSetStr(pTmp, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC); zSql8 = sqlite3ValueText(pTmp, SQLITE_UTF8); if( !zSql8 ){ sqlite3Error(db, SQLITE_NOMEM, 0); return SQLITE_NOMEM; } rc = sqlite3_prepare(db, zSql8, -1, 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); } return rc;}#endif /* SQLITE_OMIT_UTF16 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -