Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Working on a bug: Dropping and recreating a table within a transaction causes an assertion failure. (CVS 342) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
b3656a5cfef91c89de2cbb9790087d0d |
User & Date: | drh 2002-01-09 03:19:59.000 |
Context
2002-01-09
| ||
13:30 | Continued work on the DROP/CREATE problem. (CVS 343) (check-in: 0a3aa99e11 user: drh tags: trunk) | |
03:19 | Working on a bug: Dropping and recreating a table within a transaction causes an assertion failure. (CVS 342) (check-in: b3656a5cfe user: drh tags: trunk) | |
2002-01-07
| ||
19:58 | Added a manpage from A. Rottmann. (CVS 341) (check-in: 7deb622413 user: drh tags: trunk) | |
Changes
Changes to Makefile.in.
︙ | ︙ | |||
299 300 301 302 303 304 305 | doc: $(DOC) mkdir -p doc mv $(DOC) doc install: sqlite libsqlite.la sqlite.h $(LIBTOOL) $(INSTALL) libsqlite.la $(prefix)/lib $(LIBTOOL) $(INSTALL) sqlite $(prefix)/bin | | | > > > > | 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 | doc: $(DOC) mkdir -p doc mv $(DOC) doc install: sqlite libsqlite.la sqlite.h $(LIBTOOL) $(INSTALL) libsqlite.la $(prefix)/lib $(LIBTOOL) $(INSTALL) sqlite $(prefix)/bin $(INSTALL) -m 0644 sqlite.h $(prefix)/include clean: rm -f *.lo *.la *.o sqlite libsqlite.la sqlite.h rm -rf .libs .deps rm -f lemon lempar.c parse.* sqlite*.tar.gz rm -f $(PUBLISH) rm -f *.da *.bb *.bbg gmon.out rm -f testfixture test.db rm -rf doc distclean: clean rm -f config.log config.status |
Changes to src/build.c.
︙ | ︙ | |||
21 22 23 24 25 26 27 | ** COPY ** VACUUM ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** | | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | ** COPY ** VACUUM ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** ** $Id: build.c,v 1.62 2002/01/09 03:20:00 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called after a single SQL statement has been ** parsed and we want to execute the VDBE code to implement |
︙ | ︙ | |||
142 143 144 145 146 147 148 | /* ** Locate the in-memory structure that describes ** a particular database table given the name ** of that table. Return NULL if not found. */ Table *sqliteFindTable(sqlite *db, char *zName){ Table *p = sqliteHashFind(&db->tblHash, zName, strlen(zName)+1); | | | | | | > > > | | > > > > > > > > > > > > > > > > > > > > > | 142 143 144 145 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 | /* ** Locate the in-memory structure that describes ** a particular database table given the name ** of that table. Return NULL if not found. */ Table *sqliteFindTable(sqlite *db, char *zName){ Table *p = sqliteHashFind(&db->tblHash, zName, strlen(zName)+1); return p; } /* ** Locate the in-memory structure that describes ** a particular index given the name of that index. ** Return NULL if not found. */ Index *sqliteFindIndex(sqlite *db, char *zName){ Index *p = sqliteHashFind(&db->idxHash, zName, strlen(zName)+1); return p; } /* ** Remove the given index from the index hash table, and free ** its memory structures. ** ** The index is removed from the database hash tables if db!=NULL. ** But the index is not unlinked from the Table that it indexes. ** Unlinking from the Table must be done by the calling function. */ static void sqliteDeleteIndex(sqlite *db, Index *p){ if( p->zName && db ){ Index *pOld; pOld = sqliteHashInsert(&db->idxHash, p->zName, strlen(p->zName)+1, 0); assert( pOld==0 || pOld==p ); sqliteHashInsert(&db->idxDrop, p, 0, 0); } sqliteFree(p); } /* ** Unlink the given index from its table, then remove ** the index from the index hash table and free its memory ** structures. */ void sqliteUnlinkAndDeleteIndex(sqlite *db, Index *pIndex){ if( pIndex->pTable->pIndex==pIndex ){ pIndex->pTable->pIndex = pIndex->pNext; }else{ Index *p; for(p=pIndex->pTable->pIndex; p && p->pNext!=pIndex; p=p->pNext){} if( p && p->pNext==pIndex ){ p->pNext = pIndex->pNext; } } sqliteDeleteIndex(db, pIndex); } /* ** Move the given index to the pending DROP INDEX queue if it has ** been committed. If this index was never committed, then just ** delete it. ** ** Indices on the pending drop queue are deleted when a COMMIT is ** executed. If a ROLLBACK occurs, the indices are moved back into ** the main index hash table. */ void sqlitePendingDropIndex(sqlite *db, Index *p){ if( !p->isCommit ){ sqliteUnlinkAndDeleteIndex(db, p); }else{ Index *pOld; pOld = sqliteHashInsert(&db->idxHash, p->zName, strlen(p->zName)+1, 0); assert( pOld==p ); sqliteHashInsert(&db->idxDrop, p, 0, p); p->isDropped = 1; } } /* ** Remove the memory data structures associated with the given ** Table. No changes are made to disk by this routine. ** ** This routine just deletes the data structure. It does not unlink ** the table data structure from the hash table. But it does destroy |
︙ | ︙ | |||
221 222 223 224 225 226 227 | sqliteFree(pTable->zName); sqliteFree(pTable->aCol); sqliteFree(pTable); } /* ** Unlink the given table from the hash tables and the delete the | | | | > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > | | | < < < < < < | | < | | | < < < | | < | | | 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 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 | sqliteFree(pTable->zName); sqliteFree(pTable->aCol); sqliteFree(pTable); } /* ** Unlink the given table from the hash tables and the delete the ** table structure with all its indices. */ static void sqliteUnlinkAndDeleteTable(sqlite *db, Table *p){ if( p->zName && db ){ Table *pOld; pOld = sqliteHashInsert(&db->tblHash, p->zName, strlen(p->zName)+1, 0); assert( pOld==0 || pOld==p ); sqliteHashInsert(&db->tblDrop, p, 0, 0); } sqliteDeleteTable(db, p); } /* ** Move the given table to the pending DROP TABLE queue if it has ** been committed. If this table was never committed, then just ** delete it. Do the same for all its indices. ** ** Table on the drop queue are not actually deleted until a COMMIT ** statement is executed. If a ROLLBACK occurs instead of a COMMIT, ** then the tables on the drop queue are moved back into the main ** hash table. */ void sqlitePendingDropTable(sqlite *db, Table *pTbl){ if( !pTbl->isCommit ){ sqliteUnlinkAndDeleteTable(db, pTbl); }else{ Table *pOld; Index *pIndex, *pNext; pOld = sqliteHashInsert(&db->tblHash, pTbl->zName, strlen(pTbl->zName)+1,0); assert( pOld==pTbl ); sqliteHashInsert(&db->tblDrop, pTbl, 0, pTbl); for(pIndex = pTbl->pIndex; pIndex; pIndex=pNext){ pNext = pIndex->pNext; sqlitePendingDropIndex(db, pIndex); } } } /* ** Check all Tables and Indexes in the internal hash table and commit ** any additions or deletions to those hash tables. ** ** When executing CREATE TABLE and CREATE INDEX statements, the Table ** and Index structures are created and added to the hash tables, but ** the "isCommit" field is not set. This routine sets those fields. ** When executing DROP TABLE and DROP INDEX, the table or index structures ** are moved out of tblHash and idxHash into tblDrop and idxDrop. This ** routine deletes the structure in tblDrop and idxDrop. ** ** See also: sqliteRollbackInternalChanges() */ void sqliteCommitInternalChanges(sqlite *db){ HashElem *pElem; if( (db->flags & SQLITE_InternChanges)==0 ) return; db->schema_cookie = db->next_cookie; for(pElem=sqliteHashFirst(&db->tblHash); pElem; pElem=sqliteHashNext(pElem)){ Table *pTable = sqliteHashData(pElem); pTable->isCommit = 1; } for(pElem=sqliteHashFirst(&db->tblDrop); pElem; pElem=sqliteHashNext(pElem)){ Table *pTable = sqliteHashData(pElem); sqliteDeleteTable(db, pTable); } sqliteHashClear(&db->tblDrop); for(pElem=sqliteHashFirst(&db->idxHash); pElem; pElem=sqliteHashNext(pElem)){ Index *pIndex = sqliteHashData(pElem); pIndex->isCommit = 1; } while( (pElem=sqliteHashFirst(&db->idxDrop))!=0 ){ Index *pIndex = sqliteHashData(pElem); sqliteUnlinkAndDeleteIndex(db, pIndex); } sqliteHashClear(&db->idxDrop); db->flags &= ~SQLITE_InternChanges; } /* ** This routine runs when one or more CREATE TABLE, CREATE INDEX, ** DROP TABLE, or DROP INDEX statements gets rolled back. The ** additions or deletions of Table and Index structures in the |
︙ | ︙ | |||
297 298 299 300 301 302 303 | if( (db->flags & SQLITE_InternChanges)==0 ) return; sqliteHashInit(&toDelete, SQLITE_HASH_POINTER, 0); db->next_cookie = db->schema_cookie; for(pElem=sqliteHashFirst(&db->tblHash); pElem; pElem=sqliteHashNext(pElem)){ Table *pTable = sqliteHashData(pElem); if( !pTable->isCommit ){ sqliteHashInsert(&toDelete, pTable, 0, pTable); | < < > > > > > > > < < > > > > > > > > | 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 | if( (db->flags & SQLITE_InternChanges)==0 ) return; sqliteHashInit(&toDelete, SQLITE_HASH_POINTER, 0); db->next_cookie = db->schema_cookie; for(pElem=sqliteHashFirst(&db->tblHash); pElem; pElem=sqliteHashNext(pElem)){ Table *pTable = sqliteHashData(pElem); if( !pTable->isCommit ){ sqliteHashInsert(&toDelete, pTable, 0, pTable); } } for(pElem=sqliteHashFirst(&toDelete); pElem; pElem=sqliteHashNext(pElem)){ Table *pTable = sqliteHashData(pElem); sqliteUnlinkAndDeleteTable(db, pTable); } sqliteHashClear(&toDelete); for(pElem=sqliteHashFirst(&db->tblDrop); pElem; pElem=sqliteHashNext(pElem)){ Table *pOld, *p = sqliteHashData(pElem); assert( p->isCommit ); pOld = sqliteHashInsert(&db->tblHash, p->zName, strlen(p->zName)+1, p); assert( pOld==0 || pOld==p ); } sqliteHashClear(&db->tblDrop); for(pElem=sqliteHashFirst(&db->idxHash); pElem; pElem=sqliteHashNext(pElem)){ Index *pIndex = sqliteHashData(pElem); if( !pIndex->isCommit ){ sqliteHashInsert(&toDelete, pIndex, 0, pIndex); } } for(pElem=sqliteHashFirst(&toDelete); pElem; pElem=sqliteHashNext(pElem)){ Index *pIndex = sqliteHashData(pElem); sqliteUnlinkAndDeleteIndex(db, pIndex); } sqliteHashClear(&toDelete); for(pElem=sqliteHashFirst(&db->idxDrop); pElem; pElem=sqliteHashNext(pElem)){ Index *pOld, *p = sqliteHashData(pElem); assert( p->isCommit ); p->isDropped = 0; pOld = sqliteHashInsert(&db->idxHash, p->zName, strlen(p->zName)+1, p); assert( pOld==0 || pOld==p ); } sqliteHashClear(&db->idxDrop); db->flags &= ~SQLITE_InternChanges; } /* ** Construct the name of a user table or index from a token. ** ** Space to hold the name is obtained from sqliteMalloc() and must |
︙ | ︙ | |||
636 637 638 639 640 641 642 | /* Add the table to the in-memory representation of the database. */ assert( pParse->nameClash==0 || pParse->initFlag==1 ); if( pParse->explain==0 && pParse->nameClash==0 ){ Table *pOld; pOld = sqliteHashInsert(&db->tblHash, p->zName, strlen(p->zName)+1, p); if( pOld ){ | | | 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 | /* Add the table to the in-memory representation of the database. */ assert( pParse->nameClash==0 || pParse->initFlag==1 ); if( pParse->explain==0 && pParse->nameClash==0 ){ Table *pOld; pOld = sqliteHashInsert(&db->tblHash, p->zName, strlen(p->zName)+1, p); if( pOld ){ assert( p==pOld ); /* Malloc must have failed inside HashInsert() */ return; } pParse->pNewTable = 0; db->nTable++; db->flags |= SQLITE_InternChanges; } |
︙ | ︙ | |||
772 773 774 775 776 777 778 | sqliteVdbeAddOp(v, OP_Destroy, pIdx->tnum, pTable->isTemp); } if( (db->flags & SQLITE_InTrans)==0 ){ sqliteVdbeAddOp(v, OP_Commit, 0, 0); } } | | > > | | | 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 | sqliteVdbeAddOp(v, OP_Destroy, pIdx->tnum, pTable->isTemp); } if( (db->flags & SQLITE_InTrans)==0 ){ sqliteVdbeAddOp(v, OP_Commit, 0, 0); } } /* Move the table (and all its indices) to the pending DROP queue. ** Or, if the table was never committed, just delete it. If the table ** has been committed and is placed on the pending DROP queue, then the ** delete will occur when sqliteCommitInternalChanges() executes. ** ** Exception: if the SQL statement began with the EXPLAIN keyword, ** then no changes should be made. */ if( !pParse->explain ){ sqlitePendingDropTable(db, pTable); db->flags |= SQLITE_InternChanges; } } /* ** Create a new index for an SQL table. pIndex is the name of the index ** and pTable is the name of the table that is to be indexed. Both will |
︙ | ︙ | |||
1062 1063 1064 1065 1066 1067 1068 | exit_create_index: sqliteIdListDelete(pList); sqliteFree(zName); return; } /* | | > | 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 | exit_create_index: sqliteIdListDelete(pList); sqliteFree(zName); return; } /* ** This routine will drop an existing named index. This routine ** implements the DROP INDEX statement. */ void sqliteDropIndex(Parse *pParse, Token *pName){ Index *pIndex; char *zName; Vdbe *v; sqlite *db = pParse->db; |
︙ | ︙ | |||
1119 1120 1121 1122 1123 1124 1125 | } sqliteVdbeAddOp(v, OP_Destroy, pIndex->tnum, pTab->isTemp); if( (db->flags & SQLITE_InTrans)==0 ){ sqliteVdbeAddOp(v, OP_Commit, 0, 0); } } | | > | > > | | 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 | } sqliteVdbeAddOp(v, OP_Destroy, pIndex->tnum, pTab->isTemp); if( (db->flags & SQLITE_InTrans)==0 ){ sqliteVdbeAddOp(v, OP_Commit, 0, 0); } } /* Move the index onto the pending DROP queue. Or, if the index was ** never committed, just delete it. Indices on the pending DROP queue ** get deleted by sqliteCommitInternalChanges() when the user executes ** a COMMIT. Or if a rollback occurs, the elements of the DROP queue ** are moved back into the main hash table. */ if( !pParse->explain ){ sqlitePendingDropIndex(db, pIndex); db->flags |= SQLITE_InternChanges; } } /* ** Add a new element to the end of an expression list. If pList is ** initially NULL, then create a new expression list. |
︙ | ︙ |
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.54 2002/01/09 03:20:00 drh Exp $ */ #include "sqliteInt.h" #include "os.h" /* ** This is the callback routine for the code that initializes the ** database. See sqliteInit() below for additional information. |
︙ | ︙ | |||
264 265 266 267 268 269 270 271 272 273 274 275 276 277 | /* Allocate the sqlite data structure */ db = sqliteMalloc( sizeof(sqlite) ); if( pzErrMsg ) *pzErrMsg = 0; if( db==0 ) goto no_mem_on_open; sqliteHashInit(&db->tblHash, SQLITE_HASH_STRING, 0); sqliteHashInit(&db->idxHash, SQLITE_HASH_STRING, 0); db->nextRowid = sqliteRandomInteger(); /* Open the backend database driver */ rc = sqliteBtreeOpen(zFilename, mode, MAX_PAGES, &db->pBe); if( rc!=SQLITE_OK ){ switch( rc ){ default: { | > > | 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 | /* Allocate the sqlite data structure */ db = sqliteMalloc( sizeof(sqlite) ); if( pzErrMsg ) *pzErrMsg = 0; if( db==0 ) goto no_mem_on_open; sqliteHashInit(&db->tblHash, SQLITE_HASH_STRING, 0); sqliteHashInit(&db->idxHash, SQLITE_HASH_STRING, 0); sqliteHashInit(&db->tblDrop, SQLITE_HASH_POINTER, 0); sqliteHashInit(&db->idxDrop, SQLITE_HASH_POINTER, 0); db->nextRowid = sqliteRandomInteger(); /* Open the backend database driver */ rc = sqliteBtreeOpen(zFilename, mode, MAX_PAGES, &db->pBe); if( rc!=SQLITE_OK ){ switch( rc ){ default: { |
︙ | ︙ | |||
314 315 316 317 318 319 320 321 322 323 324 325 326 327 | ** This routine erases the stored schema. This erasure occurs because ** either the database is being closed or because some other process ** changed the schema and this process needs to reread it. */ static void clearHashTable(sqlite *db, int preserveTemps){ HashElem *pElem; Hash temp1; temp1 = db->tblHash; sqliteHashInit(&db->tblHash, SQLITE_HASH_STRING, 0); sqliteHashClear(&db->idxHash); for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){ Table *pTab = sqliteHashData(pElem); if( preserveTemps && pTab->isTemp ){ Index *pIdx; | > > | 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 | ** This routine erases the stored schema. This erasure occurs because ** either the database is being closed or because some other process ** changed the schema and this process needs to reread it. */ static void clearHashTable(sqlite *db, int preserveTemps){ HashElem *pElem; Hash temp1; assert( sqliteHashFirst(&db->tblDrop)==0 ); /* There can not be uncommitted */ assert( sqliteHashFirst(&db->idxDrop)==0 ); /* DROP TABLEs or DROP INDEXs */ temp1 = db->tblHash; sqliteHashInit(&db->tblHash, SQLITE_HASH_STRING, 0); sqliteHashClear(&db->idxHash); for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){ Table *pTab = sqliteHashData(pElem); if( preserveTemps && pTab->isTemp ){ Index *pIdx; |
︙ | ︙ |
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.76 2002/01/09 03:20:00 drh Exp $ */ #include "sqlite.h" #include "hash.h" #include "vdbe.h" #include "parse.h" #include "btree.h" #include <stdio.h> |
︙ | ︙ | |||
175 176 177 178 179 180 181 182 183 184 185 186 187 188 | int schema_cookie; /* Magic number that changes with the schema */ int next_cookie; /* Value of schema_cookie after commit */ int nTable; /* Number of tables in the database */ void *pBusyArg; /* 1st Argument to the busy callback */ int (*xBusyCallback)(void *,const char*,int); /* The busy callback */ Hash tblHash; /* All tables indexed by name */ Hash idxHash; /* All (named) indices indexed by name */ int nextRowid; /* Next generated rowID */ }; /* ** Possible values for the sqlite.flags. */ #define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ | > > | 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | int schema_cookie; /* Magic number that changes with the schema */ int next_cookie; /* Value of schema_cookie after commit */ int nTable; /* Number of tables in the database */ void *pBusyArg; /* 1st Argument to the busy callback */ int (*xBusyCallback)(void *,const char*,int); /* The busy callback */ Hash tblHash; /* All tables indexed by name */ Hash idxHash; /* All (named) indices indexed by name */ Hash tblDrop; /* Uncommitted DROP TABLEs */ Hash idxDrop; /* Uncommitted DROP INDEXs */ int nextRowid; /* Next generated rowID */ }; /* ** Possible values for the sqlite.flags. */ #define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ |
︙ | ︙ | |||
224 225 226 227 228 229 230 | int nCol; /* Number of columns in this table */ Column *aCol; /* Information about each column */ int iPKey; /* If not less then 0, use aCol[iPKey] as the primary key */ Index *pIndex; /* List of SQL indexes on this table. */ int tnum; /* Page containing root for this table */ u8 readOnly; /* True if this table should not be written by the user */ u8 isCommit; /* True if creation of this table has been committed */ | < | 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | int nCol; /* Number of columns in this table */ Column *aCol; /* Information about each column */ int iPKey; /* If not less then 0, use aCol[iPKey] as the primary key */ Index *pIndex; /* List of SQL indexes on this table. */ int tnum; /* Page containing root for this table */ u8 readOnly; /* True if this table should not be written by the user */ u8 isCommit; /* True if creation of this table has been committed */ u8 isTemp; /* True if stored in db->pBeTemp instead of db->pBe */ u8 hasPrimKey; /* True if there exists a primary key */ }; /* ** Each SQL index is represented in memory by an ** instance of the following structure. |
︙ | ︙ | |||
256 257 258 259 260 261 262 | char *zName; /* Name of this index */ int nColumn; /* Number of columns in the table used by this index */ int *aiColumn; /* Which columns are used by this index. 1st is 0 */ Table *pTable; /* The SQL table being indexed */ int tnum; /* Page containing root of this index in database file */ u8 isUnique; /* True if keys must all be unique */ u8 isCommit; /* True if creation of this index has been committed */ | | | 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 | char *zName; /* Name of this index */ int nColumn; /* Number of columns in the table used by this index */ int *aiColumn; /* Which columns are used by this index. 1st is 0 */ Table *pTable; /* The SQL table being indexed */ int tnum; /* Page containing root of this index in database file */ u8 isUnique; /* True if keys must all be unique */ u8 isCommit; /* True if creation of this index has been committed */ u8 isDropped; /* True if a DROP INDEX has executed on this index */ Index *pNext; /* The next index associated with the same table */ }; /* ** Each token coming out of the lexer is an instance of ** this structure. */ |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. Also found here are subroutines ** to generate VDBE code to evaluate expressions. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. Also found here are subroutines ** to generate VDBE code to evaluate expressions. ** ** $Id: where.c,v 1.32 2002/01/09 03:20:00 drh Exp $ */ #include "sqliteInt.h" /* ** The query generator uses an array of instances of this structure to ** help it analyze the subexpressions of the WHERE clause. Each WHERE ** clause subexpression is separated from the others by an AND operator. |
︙ | ︙ | |||
298 299 300 301 302 303 304 305 306 307 308 309 310 311 | */ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ int eqMask = 0; /* Index columns covered by an x=... constraint */ int ltMask = 0; /* Index columns covered by an x<... constraint */ int gtMask = 0; /* Index columns covered by an x>... constraing */ int nEq, m, score; if( pIdx->nColumn>32 ) continue; /* Ignore indices too many columns */ for(j=0; j<nExpr; j++){ if( aExpr[j].idxLeft==idx && (aExpr[j].prereqRight & loopMask)==aExpr[j].prereqRight ){ int iColumn = aExpr[j].p->pLeft->iColumn; int k; for(k=0; k<pIdx->nColumn; k++){ | > | 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 | */ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ int eqMask = 0; /* Index columns covered by an x=... constraint */ int ltMask = 0; /* Index columns covered by an x<... constraint */ int gtMask = 0; /* Index columns covered by an x>... constraing */ int nEq, m, score; if( pIdx->isDropped ) continue; /* Ignore dropped indices */ if( pIdx->nColumn>32 ) continue; /* Ignore indices too many columns */ for(j=0; j<nExpr; j++){ if( aExpr[j].idxLeft==idx && (aExpr[j].prereqRight & loopMask)==aExpr[j].prereqRight ){ int iColumn = aExpr[j].p->pLeft->iColumn; int k; for(k=0; k<pIdx->nColumn; k++){ |
︙ | ︙ |
Changes to test/trans.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: trans.test,v 1.8 2002/01/09 03:20:00 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Create several tables to work with. |
︙ | ︙ | |||
401 402 403 404 405 406 407 408 409 | } } {i2x i2y t1 t2} do_test trans-5.23 { execsql { SELECT * FROM t2; } } {1 2 3} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 | } } {i2x i2y t1 t2} do_test trans-5.23 { execsql { SELECT * FROM t2; } } {1 2 3} # Try to DROP and CREATE tables and indices with the same name # within a transaction. Make sure ROLLBACK works. # do_test trans-6.1 { execsql2 { INSERT INTO t1 VALUES(1,2,3); BEGIN TRANSACTION; DROP TABLE t1; CREATE TABLE t1(p,q,r); ROLLBACK; SELECT * FROM t1; } } {a 1 b 2 c 3} do_test trans-6.2 { execsql2 { INSERT INTO t1 VALUES(1,2,3); BEGIN TRANSACTION; DROP TABLE t1; CREATE TABLE t1(p,q,r); COMMIT; SELECT * FROM t1; } } {} do_test trans-6.3 { execsql2 { INSERT INTO t1 VALUES(1,2,3); SELECT * FROM t1; } } {p 1 q 2 r 3} do_test trans-6.4 { execsql2 { BEGIN TRANSACTION; DROP TABLE t1; CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(4,5,6); SELECT * FROM t1; DROP TABLE t1; } } {a 4 b 5 c 6} do_test trans-6.5 { execsql2 { ROLLBACK; SELECT * FROM t1; } } {p 1 q 2 r 3} do_test trans-6.6 { execsql2 { BEGIN TRANSACTION; DROP TABLE t1; CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(4,5,6); SELECT * FROM t1; DROP TABLE t1; } } {a 4 b 5 c 6} do_test trans-6.7 { catchsql { COMMIT; SELECT * FROM t1; } } {1 {no such table: t1}} do_test trans-6.8 { execsql { CREATE TABLE t1(a integer primary key,b,c); INSERT INTO t1 VALUES(1,-2,-3); INSERT INTO t1 VALUES(4,-5,-6); SELECT * FROM t1; } } {1 -2 -3 4 -5 -6} do_test trans-6.9 { execsql { CREATE INDEX i1 ON t1(b); SELECT * FROM t1 WHERE b<1; } } {4 -5 -6 1 -2 -3} do_test trans-6.10 { execsql { BEGIN TRANSACTION; DROP INDEX i1; SELECT * FROM t1 WHERE b<1; ROLLBACK; } } {1 -2 -3 4 -5 -6} do_test trans-6.11 { execsql { SELECT * FROM t1 WHERE b<1; } } {4 -5 -6 1 -2 -3} do_test trans-6.12 { execsql { BEGIN TRANSACTION; DROP TABLE t1; ROLLBACK; SELECT * FROM t1 WHERE b<1; } } {4 -5 -6 1 -2 -3} do_test trans-6.13 { execsql { BEGIN TRANSACTION; DROP INDEX i1; CREATE INDEX i1 ON t1(c); SELECT * FROM t1 WHERE b<1; } } {1 -2 -3 4 -5 -6} do_test trans-6.14 { execsql { SELECT * FROM t1 WHERE c<1; } } {4 -5 -6 1 -2 -3} do_test trans-6.15 { execsql { ROLLBACK; SELECT * FROM t1 WHERE b<1; } } {4 -5 -6 1 -2 -3} do_test trans-6.16 { execsql { SELECT * FROM t1 WHERE c<1; } } {1 -2 -3 4 -5 -6} finish_test |
Changes to www/changes.tcl.
︙ | ︙ | |||
13 14 15 16 17 18 19 | proc chng {date desc} { puts "<DT><B>$date</B></DT>" puts "<DD><P><UL>$desc</UL></P></DD>" } | | > > > | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | proc chng {date desc} { puts "<DT><B>$date</B></DT>" puts "<DD><P><UL>$desc</UL></P></DD>" } chng {2002 Jan 8 (2.2.1)} { <li>Bug fix: An attempt to delete a single row of a table with a WHERE clause of "ROWID=x" when no such rowid exists was causing an error.</li> <li>Bug fix: Passing in a NULL as the 3rd parameter to <b>sqlite_open()</b> would sometimes cause a coredump.</li> <li>Bug fix: DROP TABLE followed by a CREATE TABLE with the same name all within a single transaction was causing a coredump.</li> <li>Makefile updates from A. Rottmann</li> } chng {2001 Dec 22 (2.2.0)} { <li>Columns of type INTEGER PRIMARY KEY are actually used as the primary key in underlying B-Tree representation of the table.</li> <li>Several obscure, unrelated bugs were found and fixed while implemented the integer primary key change of the previous bullet.</li> |
︙ | ︙ |