Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Check for schema updates if the parser fails to find a table. More locking test updates. (CVS 1555) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
a22283512afe2df09d5783d189fbd738 |
User & Date: | drh 2004-06-10 00:29:09.000 |
Context
2004-06-10
| ||
00:51 | Fix a buffer overrun in the atomic multifile commit logic of the pager. (CVS 1556) (check-in: 3b78ffe0b5 user: drh tags: trunk) | |
00:29 | Check for schema updates if the parser fails to find a table. More locking test updates. (CVS 1555) (check-in: a22283512a user: drh tags: trunk) | |
2004-06-09
| ||
23:15 | Website changes for version 2.8.14. (CVS 1553) (check-in: 73afa14a04 user: drh tags: trunk) | |
Changes
Changes to src/build.c.
︙ | ︙ | |||
19 20 21 22 23 24 25 | ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** | | | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** ** $Id: build.c,v 1.213 2004/06/10 00:29:09 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Check to see if the schema for the database needs |
︙ | ︙ | |||
160 161 162 163 164 165 166 167 168 169 170 171 172 173 | sqlite3ErrorMsg(pParse, "no such table: %s.%s", zDbase, zName); }else if( sqlite3FindTable(pParse->db, zName, 0)!=0 ){ sqlite3ErrorMsg(pParse, "table \"%s\" is not in database \"%s\"", zName, zDbase); }else{ sqlite3ErrorMsg(pParse, "no such table: %s", zName); } } return p; } /* ** Locate the in-memory structure that describes ** a particular index given the name of that index | > | 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | sqlite3ErrorMsg(pParse, "no such table: %s.%s", zDbase, zName); }else if( sqlite3FindTable(pParse->db, zName, 0)!=0 ){ sqlite3ErrorMsg(pParse, "table \"%s\" is not in database \"%s\"", zName, zDbase); }else{ sqlite3ErrorMsg(pParse, "no such table: %s", zName); } pParse->checkSchema = 1; } return p; } /* ** Locate the in-memory structure that describes ** a particular index given the name of that index |
︙ | ︙ | |||
1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 | Table *pTab; zName = sqlite3TableNameFromToken(pTok); if( zName==0 ) return 0; pTab = sqlite3FindTable(pParse->db, zName, 0); sqliteFree(zName); if( pTab==0 ){ sqlite3ErrorMsg(pParse, "no such table: %T", pTok); } return pTab; } /* ** This routine is called to do the work of a DROP TABLE statement. ** pName is the name of the table to be dropped. | > | 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 | Table *pTab; zName = sqlite3TableNameFromToken(pTok); if( zName==0 ) return 0; pTab = sqlite3FindTable(pParse->db, zName, 0); sqliteFree(zName); if( pTab==0 ){ sqlite3ErrorMsg(pParse, "no such table: %T", pTok); pParse->checkSchema = 1; } return pTab; } /* ** This routine is called to do the work of a DROP TABLE statement. ** pName is the name of the table to be dropped. |
︙ | ︙ | |||
1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 | sqlite *db = pParse->db; if( pParse->nErr || sqlite3_malloc_failed ) return; assert( pName->nSrc==1 ); pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase); if( pIndex==0 ){ sqlite3ErrorMsg(pParse, "no such index: %S", pName, 0); goto exit_drop_index; } if( pIndex->autoIndex ){ sqlite3ErrorMsg(pParse, "index associated with UNIQUE " "or PRIMARY KEY constraint cannot be dropped", 0); goto exit_drop_index; } | > | 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 | sqlite *db = pParse->db; if( pParse->nErr || sqlite3_malloc_failed ) return; assert( pName->nSrc==1 ); pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase); if( pIndex==0 ){ sqlite3ErrorMsg(pParse, "no such index: %S", pName, 0); pParse->checkSchema = 1; goto exit_drop_index; } if( pIndex->autoIndex ){ sqlite3ErrorMsg(pParse, "index associated with UNIQUE " "or PRIMARY KEY constraint cannot be dropped", 0); goto exit_drop_index; } |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** 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. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: main.c,v 1.211 2004/06/10 00:29:09 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* ** A pointer to this structure is used to communicate information |
︙ | ︙ | |||
850 851 852 853 854 855 856 857 858 859 860 861 862 863 | } return db->zErrMsg16; } int sqlite3_errcode(sqlite3 *db){ return db->errCode; } /* ** 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. */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 | } return db->zErrMsg16; } int sqlite3_errcode(sqlite3 *db){ return db->errCode; } /* ** Check schema cookies in all databases except TEMP. If any cookie is out ** of date, return 0. If all schema cookies are current, return 1. */ static int schemaIsValid(sqlite *db){ int iDb; int rc; BtCursor *curTemp; int cookie; int allOk = 1; for(iDb=0; allOk && iDb<db->nDb; iDb++){ Btree *pBt; if( iDb==1 ) continue; 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, &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. */ |
︙ | ︙ | |||
907 908 909 910 911 912 913 914 915 916 917 918 919 920 | 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_SCHEMA ){ sqlite3ResetInternalSchema(db, 0); } assert( ppStmt ); *ppStmt = (sqlite3_stmt*)sParse.pVdbe; if( pzTail ) *pzTail = sParse.zTail; rc = sParse.rc; | > > > | 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 | 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.checkSchema && !schemaIsValid(db) ){ sParse.rc = SQLITE_SCHEMA; } if( sParse.rc==SQLITE_SCHEMA ){ sqlite3ResetInternalSchema(db, 0); } assert( ppStmt ); *ppStmt = (sqlite3_stmt*)sParse.pVdbe; if( pzTail ) *pzTail = sParse.zTail; rc = sParse.rc; |
︙ | ︙ |
Changes to src/sqliteInt.h.
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. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 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. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.277 2004/06/10 00:29:10 drh Exp $ */ #include "config.h" #include "sqlite3.h" #include "hash.h" #include "parse.h" #include <stdio.h> #include <stdlib.h> |
︙ | ︙ | |||
1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 | Table *pNewTable; /* A table being constructed by CREATE TABLE */ Vdbe *pVdbe; /* An engine for executing database bytecode */ u8 colNamesSet; /* TRUE after OP_ColumnName has been issued to pVdbe */ u8 explain; /* True if the EXPLAIN flag is found on the query */ u8 nameClash; /* A permanent table name clashes with temp table name */ u8 useAgg; /* If true, extract field values from the aggregator ** while generating expressions. Normally false */ int nErr; /* Number of errors seen */ int nTab; /* Number of previously allocated VDBE cursors */ int nMem; /* Number of memory cells used so far */ int nSet; /* Number of sets used so far */ int nAgg; /* Number of aggregate expressions */ int nVar; /* Number of '?' variables seen in the SQL so far */ AggExpr *aAgg; /* An array of aggregate expressions */ | > | 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 | Table *pNewTable; /* A table being constructed by CREATE TABLE */ Vdbe *pVdbe; /* An engine for executing database bytecode */ u8 colNamesSet; /* TRUE after OP_ColumnName has been issued to pVdbe */ u8 explain; /* True if the EXPLAIN flag is found on the query */ u8 nameClash; /* A permanent table name clashes with temp table name */ u8 useAgg; /* If true, extract field values from the aggregator ** while generating expressions. Normally false */ u8 checkSchema; /* Causes schema cookie check after an error */ int nErr; /* Number of errors seen */ int nTab; /* Number of previously allocated VDBE cursors */ int nMem; /* Number of memory cells used so far */ int nSet; /* Number of sets used so far */ int nAgg; /* Number of aggregate expressions */ int nVar; /* Number of '?' variables seen in the SQL so far */ AggExpr *aAgg; /* An array of aggregate expressions */ |
︙ | ︙ |
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.23 2004/06/10 00:29:12 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Create an alternative connection to the database # |
︙ | ︙ | |||
43 44 45 46 47 48 49 | execsql {INSERT INTO t1 VALUES(1,2)} execsql {SELECT * FROM t1} } {1 2} do_test lock-1.7.1 { catchsql {SELECT * FROM t1} db2 } {1 {no such table: t1}} do_test lock-1.7.2 { | < | | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | execsql {INSERT INTO t1 VALUES(1,2)} execsql {SELECT * FROM t1} } {1 2} do_test lock-1.7.1 { catchsql {SELECT * FROM t1} db2 } {1 {no such table: t1}} do_test lock-1.7.2 { catchsql {SELECT * FROM t1} db2 } {0 {1 2}} do_test lock-1.8 { execsql {UPDATE t1 SET a=b, b=a} db2 execsql {SELECT * FROM t1} db2 } {2 1} do_test lock-1.9 { execsql {SELECT * FROM t1} } {2 1} do_test lock-1.10 { execsql {BEGIN TRANSACTION} execsql {UPDATE t1 SET a = 0 WHERE 0} execsql {SELECT * FROM t1} } {2 1} do_test lock-1.11 { catchsql {SELECT * FROM t1} db2 } {0 {2 1}} do_test lock-1.12 { execsql {ROLLBACK} catchsql {SELECT * FROM t1} } {0 {2 1}} do_test lock-1.13 { execsql {CREATE TABLE t2(x int, y int)} |
︙ | ︙ | |||
147 148 149 150 151 152 153 | } set r } {0 2} } integrity_check lock-1.23 # If one thread has a transaction another thread cannot start | | > | | < | | | | | | | < < | 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | } set r } {0 2} } integrity_check lock-1.23 # If one thread has a transaction another thread cannot start # a transaction. -> Not true in version 3.0. But if one thread # as a RESERVED lock another thread cannot acquire one. # do_test lock-2.1 { execsql {BEGIN TRANSACTION} execsql {UPDATE t1 SET a = 0 WHERE 0} execsql {BEGIN TRANSACTION} db2 set r [catch {execsql {UPDATE t1 SET a = 0 WHERE 0} db2} msg] execsql {ROLLBACK} db2 lappend r $msg } {1 {database is locked}} # A thread can read when another has a RESERVED lock. # do_test lock-2.2 { catchsql {SELECT * FROM t2} db2 } {0 {9 8}} # If the other thread (the one that does not hold the transaction with # a RESERVED lock) tries to get a RESERVED lock, we get a busy callback. # do_test lock-2.3 { proc callback {args} { set ::callback_value $args break } set ::callback_value {} db2 busy callback set r [catch {execsql {UPDATE t1 SET a=b, b=a} db2} msg] lappend r $msg lappend r $::callback_value } {1 {database is locked} {{} 1}} do_test lock-2.4 { proc callback {file count} { lappend ::callback_value $count if {$count>4} break } set ::callback_value {} db2 busy callback set r [catch {execsql {UPDATE t1 SET a=b, b=a} db2} msg] lappend r $msg lappend r $::callback_value } {1 {database is locked} {1 2 3 4 5}} do_test lock-2.5 { proc callback {file count} { lappend ::callback_value $count if {$count>4} break } set ::callback_value {} db2 busy callback set r [catch {execsql {SELECT * FROM t1} db2} msg] lappend r $msg lappend r $::callback_value } {0 {2 1} {}} # In this test, the 3rd invocation of the busy callback causes # the first thread to release its transaction. That allows the # second thread to continue. # do_test lock-2.6 { proc callback {file count} { lappend ::callback_value $count if {$count>2} { execsql {ROLLBACK} } } set ::callback_value {} db2 busy callback set r [catch {execsql {SELECT * FROM t2} db2} msg] lappend r $msg lappend r $::callback_value } {0 {9 8} {}} do_test lock-2.7 { proc callback {file count} { lappend ::callback_value $count if {$count>2} { execsql {ROLLBACK} } } set ::callback_value {} |
︙ | ︙ | |||
272 273 274 275 276 277 278 | # do_test lock-4.1 { db2 close catch {db eval ROLLBACK} db eval BEGIN db eval {UPDATE t1 SET a=0 WHERE 0} sqlite db2 ./test.db | | < | | | > | | | | 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 | # do_test lock-4.1 { db2 close catch {db eval ROLLBACK} db eval BEGIN db eval {UPDATE t1 SET a=0 WHERE 0} sqlite db2 ./test.db catchsql {UPDATE t1 SET a=0} db2 } {1 {database is locked}} do_test lock-4.2 { set ::callback_value {} set rc [catch {db2 eval {UPDATE t1 SET a=0}} msg] lappend rc $msg $::callback_value } {1 {database is locked} {}} do_test lock-4.3 { proc callback {file count} { lappend ::callback_value $count if {$count>4} break } db2 busy callback set rc [catch {db2 eval {UPDATE t1 SET a=0}} msg] lappend rc $msg $::callback_value } {1 {database is locked} {1 2 3 4 5}} execsql {ROLLBACK} # When one thread is writing, other threads cannot read. Except if the # writing thread is writing to its temporary tables, the other threads # can still read. -> Not so in 3.0. One thread can read while another # holds a RESERVED lock. # proc tx_exec {sql} { db2 eval $sql } do_test lock-5.1 { execsql { SELECT * FROM t1 } } {2 1} do_test lock-5.2 { db function tx_exec tx_exec catchsql { INSERT INTO t1(a,b) SELECT 3, tx_exec('SELECT y FROM t2 LIMIT 1'); } } {0 {}} do_test lock-5.3 { execsql { CREATE TEMP TABLE t3(x); SELECT * FROM t3; } } {} do_test lock-5.4 { catchsql { INSERT INTO t3 SELECT tx_exec('SELECT y FROM t2 LIMIT 1'); } } {0 {}} do_test lock-5.5 { execsql { SELECT * FROM t3; } } {8} do_test lock-5.6 { catchsql { UPDATE t1 SET a=tx_exec('SELECT x FROM t2'); } } {0 {}} do_test lock-5.7 { execsql { SELECT * FROM t1; } } {9 1 9 8} do_test lock-5.8 { catchsql { UPDATE t3 SET x=tx_exec('SELECT x FROM t2'); } } {0 {}} do_test lock-5.9 { execsql { |
︙ | ︙ |