Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Prepared statements now work with CREATE and DROP. All tests pass. No memory leaks. (CVS 1866) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
ebdb661e0eefe123c422d3c1c371e325 |
User & Date: | drh 2004-07-24 17:38:29.000 |
Context
2004-07-26
| ||
00:31 | Various size optimizations. (CVS 1867) (check-in: 1186e3ce0b user: drh tags: trunk) | |
2004-07-24
| ||
17:38 | Prepared statements now work with CREATE and DROP. All tests pass. No memory leaks. (CVS 1866) (check-in: ebdb661e0e user: drh tags: trunk) | |
14:35 | Fix more problems with deferred execution of CREATE. Still need to do DROP. There is now a memory leak. (CVS 1865) (check-in: 6db3f122aa 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.243 2004/07/24 17:38:29 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 |
︙ | ︙ | |||
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 | int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue; p = sqlite3HashFind(&db->aDb[j].idxHash, zName, strlen(zName)+1); if( p ) break; } 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 but ** it 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){ Index *pOld; assert( db!=0 && p->zName!=0 ); pOld = sqlite3HashInsert(&db->aDb[p->iDb].idxHash, p->zName, strlen(p->zName)+1, 0); if( pOld!=0 && pOld!=p ){ sqlite3HashInsert(&db->aDb[p->iDb].idxHash, pOld->zName, strlen(pOld->zName)+1, pOld); } | > > > > > > > > < < < | | > > > > > > | | | | | | | | | | > > | 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 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue; p = sqlite3HashFind(&db->aDb[j].idxHash, zName, strlen(zName)+1); if( p ) break; } return p; } /* ** Reclaim the memory used by an index */ static void freeIndex(Index *p){ sqliteFree(p->zColAff); sqliteFree(p); } /* ** Remove the given index from the index hash table, and free ** its memory structures. ** ** The index is removed from the database hash tables but ** it 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){ Index *pOld; assert( db!=0 && p->zName!=0 ); pOld = sqlite3HashInsert(&db->aDb[p->iDb].idxHash, p->zName, strlen(p->zName)+1, 0); if( pOld!=0 && pOld!=p ){ sqlite3HashInsert(&db->aDb[p->iDb].idxHash, pOld->zName, strlen(pOld->zName)+1, pOld); } freeIndex(p); } /* ** Unlink the given index from its table, then remove ** the index from the index hash table and free its memory ** structures. */ void sqlite3UnlinkAndDeleteIndex(sqlite *db, int iDb, const char *zIdxName){ Index *pIndex; int len; len = strlen(zIdxName); pIndex = sqlite3HashInsert(&db->aDb[iDb].idxHash, zIdxName, len+1, 0); if( 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; } } freeIndex(pIndex); } db->flags |= SQLITE_InternChanges; } /* ** Erase all schema information from the in-memory hash tables of ** a single database. This routine is called to reclaim memory ** before the database closes. It is also called during a rollback ** if there were schema changes during the transaction or if a |
︙ | ︙ | |||
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 | /* ** This routine is called when a commit occurs. */ void sqlite3CommitInternalChanges(sqlite *db){ db->flags &= ~SQLITE_InternChanges; } /* ** 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. Nor does it remove ** foreign keys from the sqlite.aFKey hash table. But it does destroy ** memory structures of the indices and foreign keys associated with ** the table. ** ** Indices associated with the table are unlinked from the "db" ** data structure if db!=NULL. If db==NULL, indices attached to ** the table are deleted, but it is assumed they have already been ** unlinked. */ void sqlite3DeleteTable(sqlite *db, Table *pTable){ | > > > > > > > > > > > > > > > > > < | 336 337 338 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 | /* ** This routine is called when a commit occurs. */ void sqlite3CommitInternalChanges(sqlite *db){ db->flags &= ~SQLITE_InternChanges; } /* ** Clear the column names from a table or view. */ static void sqliteResetColumnNames(Table *pTable){ int i; Column *pCol; assert( pTable!=0 ); for(i=0, pCol=pTable->aCol; i<pTable->nCol; i++, pCol++){ sqliteFree(pCol->zName); sqliteFree(pCol->zDflt); sqliteFree(pCol->zType); } sqliteFree(pTable->aCol); pTable->aCol = 0; pTable->nCol = 0; } /* ** 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. Nor does it remove ** foreign keys from the sqlite.aFKey hash table. But it does destroy ** memory structures of the indices and foreign keys associated with ** the table. ** ** Indices associated with the table are unlinked from the "db" ** data structure if db!=NULL. If db==NULL, indices attached to ** the table are deleted, but it is assumed they have already been ** unlinked. */ void sqlite3DeleteTable(sqlite *db, Table *pTable){ Index *pIndex, *pNext; FKey *pFKey, *pNextFKey; if( pTable==0 ) return; /* Delete all indices associated with this table */ |
︙ | ︙ | |||
367 368 369 370 371 372 373 | assert( sqlite3HashFind(&db->aDb[pTable->iDb].aFKey, pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey ); sqliteFree(pFKey); } /* Delete the Table structure itself. */ | < < | < < < < < | < | | > | > > > | | | | | | | | | | | | | | | > > | 396 397 398 399 400 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 | assert( sqlite3HashFind(&db->aDb[pTable->iDb].aFKey, pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey ); sqliteFree(pFKey); } /* Delete the Table structure itself. */ sqliteResetColumnNames(pTable); sqliteFree(pTable->zName); sqliteFree(pTable->zColAff); sqlite3SelectDelete(pTable->pSelect); sqliteFree(pTable); } /* ** Unlink the given table from the hash tables and the delete the ** table structure with all its indices and foreign keys. */ void sqlite3UnlinkAndDeleteTable(sqlite *db, int iDb, const char *zTabName){ Table *p; FKey *pF1, *pF2; Db *pDb; assert( db!=0 ); assert( iDb>=0 && iDb<db->nDb ); assert( zTabName && zTabName[0] ); pDb = &db->aDb[iDb]; p = sqlite3HashInsert(&pDb->tblHash, zTabName, strlen(zTabName)+1, 0); if( p ){ for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){ int nTo = strlen(pF1->zTo) + 1; pF2 = sqlite3HashFind(&pDb->aFKey, pF1->zTo, nTo); if( pF2==pF1 ){ sqlite3HashInsert(&pDb->aFKey, pF1->zTo, nTo, pF1->pNextTo); }else{ while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; } if( pF2 ){ pF2->pNextTo = pF1->pNextTo; } } } sqlite3DeleteTable(db, p); } db->flags |= SQLITE_InternChanges; } /* ** Given a token, return a string that consists of the text of that ** token with any quotations removed. Space to hold the returned string ** is obtained from sqliteMalloc() and must be freed by the calling ** function. |
︙ | ︙ | |||
1526 1527 1528 1529 1530 1531 1532 | } sqlite3SelectUnbind(pSel); sqlite3ExprListDelete(pSel->pEList); pSel->pEList = pEList; return nErr; } | < < < < < < < < < < < < < < < < < < < < < < | | 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 | } sqlite3SelectUnbind(pSel); sqlite3ExprListDelete(pSel->pEList); pSel->pEList = pEList; return nErr; } /* ** Clear the column names from every VIEW in database idx. */ static void sqliteViewResetAll(sqlite *db, int idx){ HashElem *i; if( !DbHasProperty(db, idx, DB_UnresetViews) ) return; for(i=sqliteHashFirst(&db->aDb[idx].tblHash); i; i=sqliteHashNext(i)){ Table *pTab = sqliteHashData(i); if( pTab->pSelect ){ sqliteResetColumnNames(pTab); } } DbClearProperty(db, idx, DB_UnresetViews); } /* ** This routine is called to do the work of a DROP TABLE statement. |
︙ | ︙ | |||
1656 1657 1658 1659 1660 1661 1662 | ** is generated to remove entries from sqlite_master and/or ** sqlite_temp_master if required. */ pTrigger = pTab->pTrigger; while( pTrigger ){ assert( pTrigger->iDb==pTab->iDb || pTrigger->iDb==1 ); sqlite3DropTriggerPtr(pParse, pTrigger, 1); | < | < < < > < < < < < < < < < < | 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 | ** is generated to remove entries from sqlite_master and/or ** sqlite_temp_master if required. */ pTrigger = pTab->pTrigger; while( pTrigger ){ assert( pTrigger->iDb==pTab->iDb || pTrigger->iDb==1 ); sqlite3DropTriggerPtr(pParse, pTrigger, 1); pTrigger = pTrigger->pNext; } /* Drop all SQLITE_MASTER table and index entries that refer to the ** table. The program name loops through the master table and deletes ** every row that refers to a table of the same name as the one being ** dropped. Triggers are handled seperately because a trigger can be ** created in the temp database that refers to a table in another ** database. */ sqlite3OpenMasterTable(v, pTab->iDb); base = sqlite3VdbeAddOpList(v, ArraySize(dropTable), dropTable); sqlite3VdbeChangeP3(v, base+1, pTab->zName, 0); sqlite3ChangeCookie(db, v, pTab->iDb); sqlite3VdbeAddOp(v, OP_Close, 0, 0); if( !isView ){ sqlite3VdbeAddOp(v, OP_Destroy, pTab->tnum, pTab->iDb); for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ sqlite3VdbeAddOp(v, OP_Destroy, pIdx->tnum, pIdx->iDb); } } sqlite3VdbeOp3(v, OP_DropTable, pTab->iDb, 0, pTab->zName, 0); sqlite3EndWriteOperation(pParse); } sqliteViewResetAll(db, iDb); exit_drop_table: sqlite3SrcListDelete(pName); } /* |
︙ | ︙ | |||
2188 2189 2190 2191 2192 2193 2194 | pOther->pNext = pIndex; } pIndex = 0; } /* Clean up before exiting */ exit_create_index: | | > > | 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 | pOther->pNext = pIndex; } pIndex = 0; } /* Clean up before exiting */ exit_create_index: if( pIndex ){ freeIndex(pIndex); } sqlite3ExprListDelete(pList); sqlite3SrcListDelete(pTblName); sqliteFree(zName); return; } /* |
︙ | ︙ | |||
2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 | sqlite3BeginWriteOperation(pParse, 0, pIndex->iDb); sqlite3OpenMasterTable(v, pIndex->iDb); base = sqlite3VdbeAddOpList(v, ArraySize(dropIndex), dropIndex); sqlite3VdbeChangeP3(v, base+1, pIndex->zName, 0); sqlite3ChangeCookie(db, v, pIndex->iDb); sqlite3VdbeAddOp(v, OP_Close, 0, 0); sqlite3VdbeAddOp(v, OP_Destroy, pIndex->tnum, pIndex->iDb); sqlite3EndWriteOperation(pParse); } | > < < < < < < < | 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 | sqlite3BeginWriteOperation(pParse, 0, pIndex->iDb); sqlite3OpenMasterTable(v, pIndex->iDb); base = sqlite3VdbeAddOpList(v, ArraySize(dropIndex), dropIndex); sqlite3VdbeChangeP3(v, base+1, pIndex->zName, 0); sqlite3ChangeCookie(db, v, pIndex->iDb); sqlite3VdbeAddOp(v, OP_Close, 0, 0); sqlite3VdbeAddOp(v, OP_Destroy, pIndex->tnum, pIndex->iDb); sqlite3VdbeOp3(v, OP_DropIndex, pIndex->iDb, 0, pIndex->zName, 0); sqlite3EndWriteOperation(pParse); } exit_drop_index: sqlite3SrcListDelete(pName); } /* ** Append a new element to the given IdList. Create a new IdList if ** need be. |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** ** $Id: insert.c,v 1.114 2004/07/24 17:38:29 drh Exp $ */ #include "sqliteInt.h" /* ** Set P3 of the most recently inserted opcode to a column affinity ** string for index pIdx. A column affinity string has one character ** for each column in the table, according to the affinity of the column: |
︙ | ︙ | |||
46 47 48 49 50 51 52 | } for(n=0; n<pIdx->nColumn; n++){ pIdx->zColAff[n] = pTab->aCol[pIdx->aiColumn[n]].affinity; } pIdx->zColAff[pIdx->nColumn] = '\0'; } | | | 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | } for(n=0; n<pIdx->nColumn; n++){ pIdx->zColAff[n] = pTab->aCol[pIdx->aiColumn[n]].affinity; } pIdx->zColAff[pIdx->nColumn] = '\0'; } sqlite3VdbeChangeP3(v, -1, pIdx->zColAff, 0); } /* ** Set P3 of the most recently inserted opcode to a column affinity ** string for table pTab. A column affinity string has one character ** for each column indexed by the index, according to the affinity of the ** column: |
︙ | ︙ | |||
87 88 89 90 91 92 93 | zColAff[i] = pTab->aCol[i].affinity; } zColAff[pTab->nCol] = '\0'; pTab->zColAff = zColAff; } | | | 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | zColAff[i] = pTab->aCol[i].affinity; } zColAff[pTab->nCol] = '\0'; pTab->zColAff = zColAff; } sqlite3VdbeChangeP3(v, -1, pTab->zColAff, 0); } /* ** This routine is call to handle SQL of the following forms: ** ** insert into TABLE (IDLIST) values(EXPRLIST) |
︙ | ︙ |
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.311 2004/07/24 17:38:29 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ #include "config.h" #include "sqlite3.h" #include "hash.h" |
︙ | ︙ | |||
1268 1269 1270 1271 1272 1273 1274 | void sqlite3ExprCode(Parse*, Expr*); int sqlite3ExprCodeExprList(Parse*, ExprList*); void sqlite3ExprIfTrue(Parse*, Expr*, int, int); void sqlite3ExprIfFalse(Parse*, Expr*, int, int); Table *sqlite3FindTable(sqlite*,const char*, const char*); Table *sqlite3LocateTable(Parse*,const char*, const char*); Index *sqlite3FindIndex(sqlite*,const char*, const char*); | > | > | 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 | void sqlite3ExprCode(Parse*, Expr*); int sqlite3ExprCodeExprList(Parse*, ExprList*); void sqlite3ExprIfTrue(Parse*, Expr*, int, int); void sqlite3ExprIfFalse(Parse*, Expr*, int, int); Table *sqlite3FindTable(sqlite*,const char*, const char*); Table *sqlite3LocateTable(Parse*,const char*, const char*); Index *sqlite3FindIndex(sqlite*,const char*, const char*); void sqlite3UnlinkAndDeleteTable(sqlite*,int,const char*); void sqlite3UnlinkAndDeleteIndex(sqlite*,int,const char*); void sqlite3UnlinkAndDeleteTrigger(sqlite*,int,const char*); void sqlite3Vacuum(Parse*, Token*); int sqlite3RunVacuum(char**, sqlite*); int sqlite3GlobCompare(const unsigned char*,const unsigned char*); char *sqlite3NameFromToken(Token*); int sqlite3ExprCheck(Parse*, Expr*, int, int*); int sqlite3ExprCompare(Expr*, Expr*); int sqliteFuncId(Token*); |
︙ | ︙ |
Changes to src/trigger.c.
︙ | ︙ | |||
137 138 139 140 141 142 143 | int code = SQLITE_CREATE_TRIGGER; const char *zDb = db->aDb[pTab->iDb].zName; const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb; if( pTab->iDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER; if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){ goto trigger_cleanup; } | | | 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | int code = SQLITE_CREATE_TRIGGER; const char *zDb = db->aDb[pTab->iDb].zName; const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb; if( pTab->iDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER; if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){ goto trigger_cleanup; } if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(pTab->iDb),0,zDb)){ goto trigger_cleanup; } } #endif /* INSTEAD OF triggers can only appear on views and BEFORE triggers ** cannot appear on views. So we might as well translate every |
︙ | ︙ | |||
209 210 211 212 213 214 215 | /* if we are not initializing, and this trigger is not on a TEMP table, ** build the sqlite_master entry */ if( !db->init.busy ){ static VdbeOpList insertTrig[] = { { OP_NewRecno, 0, 0, 0 }, | | | | | | | > > | | 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 | /* if we are not initializing, and this trigger is not on a TEMP table, ** build the sqlite_master entry */ if( !db->init.busy ){ static VdbeOpList insertTrig[] = { { OP_NewRecno, 0, 0, 0 }, { OP_String8, 0, 0, "trigger" }, { OP_String8, 0, 0, 0 }, /* 2: trigger name */ { OP_String8, 0, 0, 0 }, /* 3: table name */ { OP_Integer, 0, 0, 0 }, { OP_String8, 0, 0, "CREATE TRIGGER "}, { OP_String8, 0, 0, 0 }, /* 6: SQL */ { OP_Concat8, 2, 0, 0 }, { OP_MakeRecord, 5, 0, "tttit" }, { OP_PutIntKey, 0, 0, 0 }, }; int addr; Vdbe *v; /* Make an entry in the sqlite_master table */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto triggerfinish_cleanup; sqlite3BeginWriteOperation(pParse, 0, nt->iDb); sqlite3OpenMasterTable(v, nt->iDb); addr = sqlite3VdbeAddOpList(v, ArraySize(insertTrig), insertTrig); sqlite3VdbeChangeP3(v, addr+2, nt->name, 0); sqlite3VdbeChangeP3(v, addr+3, nt->table, 0); sqlite3VdbeChangeP3(v, addr+6, pAll->z, pAll->n); if( nt->iDb!=0 ){ sqlite3ChangeCookie(db, v, nt->iDb); } sqlite3VdbeAddOp(v, OP_Close, 0, 0); sqlite3VdbeOp3(v, OP_ParseSchema, nt->iDb, 0, sqlite3MPrintf("type='trigger' AND name='%q'", nt->name), P3_DYNAMIC); sqlite3EndWriteOperation(pParse); } if( db->init.busy ){ Table *pTab; sqlite3HashInsert(&db->aDb[nt->iDb].trigHash, nt->name, strlen(nt->name)+1, nt); pTab = sqlite3LocateTable(pParse, nt->table, db->aDb[nt->iTabDb].zName); assert( pTab!=0 ); nt->pNext = pTab->pTrigger; pTab->pTrigger = nt; |
︙ | ︙ | |||
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 | goto drop_trigger_cleanup; } sqlite3DropTriggerPtr(pParse, pTrigger, 0); drop_trigger_cleanup: sqlite3SrcListDelete(pName); } /* ** Drop a trigger given a pointer to that trigger. If nested is false, ** then also generate code to remove the trigger from the SQLITE_MASTER ** table. */ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested){ Table *pTable; Vdbe *v; sqlite *db = pParse->db; | > > > > > > > > > > | > | | | | | | 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 | goto drop_trigger_cleanup; } sqlite3DropTriggerPtr(pParse, pTrigger, 0); drop_trigger_cleanup: sqlite3SrcListDelete(pName); } /* ** Return a pointer to the Table structure for the table that a trigger ** is set on. */ static Table *tableOfTrigger(sqlite3 *db, Trigger *pTrigger){ return sqlite3FindTable(db,pTrigger->table,db->aDb[pTrigger->iTabDb].zName); } /* ** Drop a trigger given a pointer to that trigger. If nested is false, ** then also generate code to remove the trigger from the SQLITE_MASTER ** table. */ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested){ Table *pTable; Vdbe *v; sqlite *db = pParse->db; int iDb; iDb = pTrigger->iDb; assert( iDb>=0 && iDb<db->nDb ); pTable = tableOfTrigger(db, pTrigger); assert(pTable); assert( pTable->iDb==iDb || iDb==1 ); #ifndef SQLITE_OMIT_AUTHORIZATION { int code = SQLITE_DROP_TRIGGER; const char *zDb = db->aDb[iDb].zName; const char *zTab = SCHEMA_TABLE(iDb); if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER; if( sqlite3AuthCheck(pParse, code, pTrigger->name, pTable->zName, zDb) || sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ return; } } #endif |
︙ | ︙ | |||
483 484 485 486 487 488 489 | { OP_String8, 0, 0, "trigger"}, { OP_Column, 0, 0, 0}, { OP_Ne, 0, ADDR(8), 0}, { OP_Delete, 0, 0, 0}, { OP_Next, 0, ADDR(1), 0}, /* 8 */ }; | | | | > | > | | | < | > | > > > > < > | 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 535 536 537 538 539 540 541 542 543 544 | { OP_String8, 0, 0, "trigger"}, { OP_Column, 0, 0, 0}, { OP_Ne, 0, ADDR(8), 0}, { OP_Delete, 0, 0, 0}, { OP_Next, 0, ADDR(1), 0}, /* 8 */ }; sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3OpenMasterTable(v, iDb); base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger); sqlite3VdbeChangeP3(v, base+1, pTrigger->name, 0); sqlite3ChangeCookie(db, v, iDb); sqlite3VdbeAddOp(v, OP_Close, 0, 0); sqlite3VdbeOp3(v, OP_DropTrigger, iDb, 0, pTrigger->name, 0); } } /* ** Remove a trigger from the hash tables of the sqlite* pointer. */ void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){ Trigger *pTrigger; int nName = strlen(zName); pTrigger = sqlite3HashInsert(&(db->aDb[iDb].trigHash), zName, nName+1, 0); if( pTrigger ){ Table *pTable = tableOfTrigger(db, pTrigger); assert( pTable!=0 ); if( pTable->pTrigger == pTrigger ){ pTable->pTrigger = pTrigger->pNext; }else{ Trigger *cc = pTable->pTrigger; while( cc ){ if( cc->pNext == pTrigger ){ cc->pNext = cc->pNext->pNext; break; } cc = cc->pNext; } assert(cc); } sqlite3DeleteTrigger(pTrigger); db->flags |= SQLITE_InternChanges; } } /* ** pEList is the SET clause of an UPDATE statement. Each entry ** in pEList is of the format <id>=<expr>. If any of the entries ** in pEList have an <id> which matches an identifier in pIdList, |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
39 40 41 42 43 44 45 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** ** $Id: vdbe.c,v 1.406 2004/07/24 17:38:29 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include "vdbeInt.h" /* |
︙ | ︙ | |||
3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 | db->init.busy = 1; rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); db->init.busy = 0; sqlite3SafetyOn(db); sqliteFree(zSql); break; } /* Opcode: IntegrityCk * P2 * ** ** Do an analysis of the currently open database. Push onto the ** stack the text of an error message describing any problems. ** If there are no errors, push a "ok" onto the stack. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 | db->init.busy = 1; rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); db->init.busy = 0; sqlite3SafetyOn(db); sqliteFree(zSql); break; } /* Opcode: DropTable P1 * P3 ** ** Remove the internal (in-memory) data structures that describe ** the table named P3 in database P1. This is called after a table ** is dropped in order to keep the internal representation of the ** schema consistent with what is on disk. */ case OP_DropTable: { sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p3); break; } /* Opcode: DropIndex P1 * P3 ** ** Remove the internal (in-memory) data structures that describe ** the index named P3 in database P1. This is called after an index ** is dropped in order to keep the internal representation of the ** schema consistent with what is on disk. */ case OP_DropIndex: { sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p3); break; } /* Opcode: DropTrigger P1 * P3 ** ** Remove the internal (in-memory) data structures that describe ** the trigger named P3 in database P1. This is called after a trigger ** is dropped in order to keep the internal representation of the ** schema consistent with what is on disk. */ case OP_DropTrigger: { sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p3); break; } /* Opcode: IntegrityCk * P2 * ** ** Do an analysis of the currently open database. Push onto the ** stack the text of an error message describing any problems. ** If there are no errors, push a "ok" onto the stack. |
︙ | ︙ |
Changes to test/misc4.test.
︙ | ︙ | |||
9 10 11 12 13 14 15 | # #*********************************************************************** # This file implements regression tests for SQLite library. # # This file implements tests for miscellanous features that were # left out of other test files. # | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # #*********************************************************************** # This file implements regression tests for SQLite library. # # This file implements tests for miscellanous features that were # left out of other test files. # # $Id: misc4.test,v 1.6 2004/07/24 17:38:30 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Prepare a statement that will create a temporary table. Then do # a rollback. Then try to execute the prepared statement. # |
︙ | ︙ | |||
60 61 62 63 64 65 66 | sqlite3_finalize $stmt } {SQLITE_SCHEMA} # Prepare but do not execute various CREATE statements. Then before # those statements are executed, try to use the tables, indices, views, # are triggers that were created. # | < < | | 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | sqlite3_finalize $stmt } {SQLITE_SCHEMA} # Prepare but do not execute various CREATE statements. Then before # those statements are executed, try to use the tables, indices, views, # are triggers that were created. # do_test misc4-2.1 { set stmt [sqlite3_prepare $DB {CREATE TABLE t3(x);} -1 TAIL] catchsql { INSERT INTO t3 VALUES(1); } } {1 {no such table: t3}} do_test misc4-2.2 { sqlite3_step $stmt } SQLITE_DONE do_test misc4-2.3 { sqlite3_finalize $stmt } SQLITE_OK do_test misc4-2.4 { catchsql { INSERT INTO t3 VALUES(1); } } {0 {}} finish_test |
Changes to test/pragma.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 the PRAGMA command. # | | | 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 the PRAGMA command. # # $Id: pragma.test,v 1.17 2004/07/24 17:38:30 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Test organization: # # pragma-1.*: Test cache_size, default_cache_size and synchronous on main db. |
︙ | ︙ | |||
302 303 304 305 306 307 308 309 310 311 312 313 314 315 | } } {2} catchsql {COMMIT;} # Test schema-query pragmas # do_test pragma-6.1 { foreach {idx name file} [execsql {pragma database_list}] { lappend res $idx $name } set res } {0 main 1 temp 2 aux} do_test pragma-6.2 { execsql { | > | 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 | } } {2} catchsql {COMMIT;} # Test schema-query pragmas # do_test pragma-6.1 { set res {} foreach {idx name file} [execsql {pragma database_list}] { lappend res $idx $name } set res } {0 main 1 temp 2 aux} do_test pragma-6.2 { execsql { |
︙ | ︙ |