Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Changes sqlite3_prepare_v2() (and related routines) so that if it fails due to a missing table and the schema is out of date, it retries once before returning SQLITE_SCHEMA. Other changes to prepare.c to facilitate coverage testing. (CVS 6769) |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
256ec3c6af41c2324db82e4deb54edbb |
User & Date: | drh 2009-06-16 17:49:36 |
Context
2009-06-17
| ||
00:35 | Changes to prepare.c and callback.c to promote better test coverage. (CVS 6770) (check-in: 08cca219 user: drh tags: trunk) | |
2009-06-16
| ||
17:49 | Changes sqlite3_prepare_v2() (and related routines) so that if it fails due to a missing table and the schema is out of date, it retries once before returning SQLITE_SCHEMA. Other changes to prepare.c to facilitate coverage testing. (CVS 6769) (check-in: 256ec3c6 user: drh tags: trunk) | |
16:50 | Changes to balance_nonroot() and BtreeDelete() to simplify delete operations and reduce stack/heap usage while balancing b-tree structures. (CVS 6768) (check-in: 092b276e user: danielk1977 tags: trunk) | |
Changes
Changes to src/prepare.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** 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. ** | | | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the implementation of the sqlite3_prepare() ** interface, and routines that contribute to loading the database schema ** from disk. ** ** $Id: prepare.c,v 1.122 2009/06/16 17:49:36 drh Exp $ */ #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 ){ if( zObj==0 ) zObj = "?"; sqlite3SetString(pData->pzErrMsg, pData->db, "malformed database schema (%s)", zObj); if( zExtra ){ *pData->pzErrMsg = sqlite3MAppendf(pData->db, *pData->pzErrMsg, "%s - %s", *pData->pzErrMsg, zExtra); } } pData->rc = db->mallocFailed ? SQLITE_NOMEM : SQLITE_CORRUPT; } /* ** This is the callback routine for the code that initializes the ** database. See sqlite3Init() below for additional information. ** This routine is also called from the OP_ParseSchema opcode of the VDBE. ** |
︙ | ︙ | |||
58 59 60 61 62 63 64 | 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); | | | 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | 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( argv[2] && argv[2][0] ){ |
︙ | ︙ | |||
83 84 85 86 87 88 89 | rc = sqlite3_exec(db, argv[2], 0, 0, &zErr); db->init.iDb = 0; assert( rc!=SQLITE_OK || zErr==0 ); if( SQLITE_OK!=rc ){ pData->rc = rc; if( rc==SQLITE_NOMEM ){ db->mallocFailed = 1; | | | < | > | 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | rc = sqlite3_exec(db, argv[2], 0, 0, &zErr); db->init.iDb = 0; assert( rc!=SQLITE_OK || zErr==0 ); if( SQLITE_OK!=rc ){ pData->rc = rc; if( rc==SQLITE_NOMEM ){ db->mallocFailed = 1; }else if( rc!=SQLITE_INTERRUPT ){ corruptSchema(pData, argv[0], zErr); } sqlite3DbFree(db, zErr); } }else if( argv[0]==0 ){ corruptSchema(pData, 0, 0); }else{ /* If the SQL column is blank it means this is an index that ** was created to be the PRIMARY KEY or to fulfill a UNIQUE ** constraint for a CREATE TABLE. The index should have already ** been created when we processed the CREATE TABLE. All we have ** to do here is record the root page number for that index. */ Index *pIndex; pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zName); if( pIndex==0 ){ /* 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 |
︙ | ︙ | |||
193 194 195 196 197 198 199 | sqlite3InitCallback(&initData, 3, (char **)azArg, 0); (void)sqlite3SafetyOn(db); if( initData.rc ){ rc = initData.rc; goto error_out; } pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName); | | | | 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 | sqlite3InitCallback(&initData, 3, (char **)azArg, 0); (void)sqlite3SafetyOn(db); if( initData.rc ){ rc = initData.rc; goto error_out; } pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName); if( ALWAYS(pTab) ){ pTab->tabFlags |= TF_Readonly; } /* 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; } curMain = sqlite3MallocZero(sqlite3BtreeCursorSize()); if( !curMain ){ rc = SQLITE_NOMEM; |
︙ | ︙ | |||
299 300 301 302 303 304 305 | 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 ); | < < < < > | 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 | 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 '%q'.%s", db->aDb[iDb].zName, zMasterName); (void)sqlite3SafetyOff(db); #ifndef SQLITE_OMIT_AUTHORIZATION { |
︙ | ︙ | |||
376 377 378 379 380 381 382 | ** file was of zero-length, then the DB_Empty flag is also set. */ int sqlite3Init(sqlite3 *db, char **pzErrMsg){ int i, rc; int commit_internal = !(db->flags&SQLITE_InternChanges); assert( sqlite3_mutex_held(db->mutex) ); | < > | | 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 | ** file was of zero-length, then the DB_Empty flag is also set. */ int sqlite3Init(sqlite3 *db, char **pzErrMsg){ int i, rc; int commit_internal = !(db->flags&SQLITE_InternChanges); assert( sqlite3_mutex_held(db->mutex) ); 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 && ALWAYS(db->nDb>1) && !DbHasProperty(db, 1, DB_SchemaLoaded) ){ rc = sqlite3InitOne(db, 1, pzErrMsg); if( rc ){ sqlite3ResetInternalSchema(db, 1); } } #endif |
︙ | ︙ | |||
679 680 681 682 683 684 685 686 687 688 689 690 691 692 | *ppStmt = 0; if( !sqlite3SafetyCheckOk(db) ){ return SQLITE_MISUSE; } sqlite3_mutex_enter(db->mutex); sqlite3BtreeEnterAll(db); rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, ppStmt, pzTail); sqlite3BtreeLeaveAll(db); sqlite3_mutex_leave(db->mutex); return rc; } /* ** Rerun the compilation of a statement after a schema change. | > > > > | 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 | *ppStmt = 0; if( !sqlite3SafetyCheckOk(db) ){ return SQLITE_MISUSE; } sqlite3_mutex_enter(db->mutex); sqlite3BtreeEnterAll(db); rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, ppStmt, pzTail); if( rc==SQLITE_SCHEMA ){ sqlite3_finalize(*ppStmt); rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, ppStmt, pzTail); } sqlite3BtreeLeaveAll(db); sqlite3_mutex_leave(db->mutex); return rc; } /* ** Rerun the compilation of a statement after a schema change. |
︙ | ︙ |
Changes to test/lock.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 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 implements regression tests for SQLite library. The # focus of this script is database locks. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 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 implements regression tests for SQLite library. The # focus of this script is database locks. # # $Id: lock.test,v 1.40 2009/06/16 17:49:36 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Create an alternative connection to the database # |
︙ | ︙ | |||
76 77 78 79 80 81 82 | do_test lock-1.13 { execsql {CREATE TABLE t2(x int, y int)} execsql {INSERT INTO t2 VALUES(8,9)} execsql {SELECT * FROM t2} } {8 9} do_test lock-1.14.1 { catchsql {SELECT * FROM t2} db2 | | | 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | do_test lock-1.13 { execsql {CREATE TABLE t2(x int, y int)} execsql {INSERT INTO t2 VALUES(8,9)} execsql {SELECT * FROM t2} } {8 9} do_test lock-1.14.1 { catchsql {SELECT * FROM t2} db2 } {0 {8 9}} do_test lock-1.14.2 { catchsql {SELECT * FROM t1} db2 } {0 {2 1}} do_test lock-1.15 { catchsql {SELECT * FROM t2} db2 } {0 {8 9}} |
︙ | ︙ |
Changes to test/temptable.test.
︙ | ︙ | |||
8 9 10 11 12 13 14 | # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. # # This file implements tests for temporary tables and indices. # | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. # # This file implements tests for temporary tables and indices. # # $Id: temptable.test,v 1.21 2009/06/16 17:49:36 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !tempdb { finish_test return |
︙ | ︙ | |||
176 177 178 179 180 181 182 | SELECT * FROM temp.t2; } db2 } {0 {10 20}} do_test temptable-4.4.2 { catchsql { SELECT * FROM main.t2; } db2 | | | 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | SELECT * FROM temp.t2; } db2 } {0 {10 20}} do_test temptable-4.4.2 { catchsql { SELECT * FROM main.t2; } db2 } {0 {9 8 7}} #do_test temptable-4.4.3 { # catchsql { # SELECT name FROM main.sqlite_master WHERE type='table'; # } db2 #} {1 {database schema has changed}} do_test temptable-4.4.4 { catchsql { |
︙ | ︙ |