Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | In shared-cache mode, lock all required tables before beginning to execute the body of the statement program. (CVS 2881) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
23b587b05b89727248805e6d9e5141e0 |
User & Date: | danielk1977 2006-01-07 13:21:04.000 |
Context
2006-01-07
| ||
14:02 | Fix some memory leaks caused by obscure syntax errors in SQL. (CVS 2882) (check-in: 6593199a4d user: danielk1977 tags: trunk) | |
13:21 | In shared-cache mode, lock all required tables before beginning to execute the body of the statement program. (CVS 2881) (check-in: 23b587b05b user: danielk1977 tags: trunk) | |
04:06 | Drop the mutex if the TSD key allocation fails. Ticket #1585. (CVS 2880) (check-in: 77ac231c0e user: drh tags: trunk) | |
Changes
Changes to src/analyze.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2005 July 8 ** ** 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 contains code associated with the ANALYZE command. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2005 July 8 ** ** 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 contains code associated with the ANALYZE command. ** ** @(#) $Id: analyze.c,v 1.13 2006/01/07 13:21:04 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_ANALYZE #include "sqliteInt.h" /* ** This routine generates code that opens the sqlite_stat1 table on cursor ** iStatCur. |
︙ | ︙ | |||
57 58 59 60 61 62 63 | iRootPage = pStat->tnum; }else{ /* The sqlite_stat1 table already exists. Delete all rows. */ iRootPage = pStat->tnum; sqlite3VdbeAddOp(v, OP_Clear, pStat->tnum, iDb); } | | > > > > > > | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | iRootPage = pStat->tnum; }else{ /* The sqlite_stat1 table already exists. Delete all rows. */ iRootPage = pStat->tnum; sqlite3VdbeAddOp(v, OP_Clear, pStat->tnum, iDb); } /* Open the sqlite_stat1 table for writing. Unless it was created ** by this vdbe program, lock it for writing at the shared-cache level. ** If this vdbe did create the sqlite_stat1 table, then it must have ** already obtained a schema-lock, making the write-lock redundant. */ if( iRootPage>0 ){ sqlite3TableLock(pParse, iDb, iRootPage, 1, "sqlite_stat1"); } sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); sqlite3VdbeAddOp(v, OP_OpenWrite, iStatCur, iRootPage); sqlite3VdbeAddOp(v, OP_SetNumColumns, iStatCur, 3); } /* ** Generate code to do an analysis of all indices associated with |
︙ | ︙ | |||
98 99 100 101 102 103 104 105 106 107 108 109 110 111 | assert( iDb>=0 ); #ifndef SQLITE_OMIT_AUTHORIZATION if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0, pParse->db->aDb[iDb].zName ) ){ return; } #endif iIdxCur = pParse->nTab; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ /* Open a cursor to the index to be analyzed */ assert( iDb==sqlite3SchemaToIndex(pParse->db, pIdx->pSchema) ); sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); | > > > | 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | assert( iDb>=0 ); #ifndef SQLITE_OMIT_AUTHORIZATION if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0, pParse->db->aDb[iDb].zName ) ){ return; } #endif /* Establish a read-lock on the table at the shared-cache level. */ sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); iIdxCur = pParse->nTab; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ /* Open a cursor to the index to be analyzed */ assert( iDb==sqlite3SchemaToIndex(pParse->db, pIdx->pSchema) ); sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); |
︙ | ︙ |
Changes to src/btree.c.
1 2 3 4 5 6 7 8 9 10 11 | /* ** 2004 April 6 ** ** 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. ** ************************************************************************* | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ** 2004 April 6 ** ** 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. ** ************************************************************************* ** $Id: btree.c,v 1.285 2006/01/07 13:21:04 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to ** ** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: ** "Sorting And Searching", pages 473-480. Addison-Wesley ** Publishing Company, Reading, Massachusetts. |
︙ | ︙ | |||
2682 2683 2684 2685 2686 2687 2688 | return SQLITE_READONLY; } if( checkReadLocks(pBt, iTable, 0) ){ return SQLITE_LOCKED; } } | < < < < < < < < < < < < < < | 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 | return SQLITE_READONLY; } if( checkReadLocks(pBt, iTable, 0) ){ return SQLITE_LOCKED; } } if( pBt->pPage1==0 ){ rc = lockBtreeWithRetry(p); if( rc!=SQLITE_OK ){ return rc; } } pCur = sqliteMalloc( sizeof(*pCur) ); if( pCur==0 ){ rc = SQLITE_NOMEM; goto create_cursor_exception; } pCur->pgnoRoot = (Pgno)iTable; pCur->pPage = 0; /* For exit-handler, in case getAndInitPage() fails. */ if( iTable==1 && sqlite3pager_pagecount(pBt->pPager)==0 ){ rc = SQLITE_EMPTY; goto create_cursor_exception; } rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->pPage, 0); if( rc!=SQLITE_OK ){ goto create_cursor_exception; } /* Now that no other errors can occur, finish filling in the BtCursor ** variables, link the cursor into the BtShared list and set *ppCur (the ** output argument to this function). */ |
︙ | ︙ | |||
6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 | /* ** Return true if another user of the same shared btree as the argument ** handle holds an exclusive lock on the sqlite_master table. */ int sqlite3BtreeSchemaLocked(Btree *p){ return (queryTableLock(p, MASTER_ROOT, READ_LOCK)!=SQLITE_OK); } #ifndef SQLITE_OMIT_SHARED_CACHE /* ** Enable the shared pager and schema features. */ int sqlite3_enable_shared_cache(int enable){ SqliteTsd *pTsd = sqlite3Tsd(); | > > > > > > > > > | 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 | /* ** Return true if another user of the same shared btree as the argument ** handle holds an exclusive lock on the sqlite_master table. */ int sqlite3BtreeSchemaLocked(Btree *p){ return (queryTableLock(p, MASTER_ROOT, READ_LOCK)!=SQLITE_OK); } int sqlite3BtreeLockTable(Btree *p, int iTab, u8 isWriteLock){ u8 lockType = (isWriteLock?WRITE_LOCK:READ_LOCK); int rc = queryTableLock(p, iTab, lockType); if( rc==SQLITE_OK ){ rc = lockTable(p, iTab, lockType); } return rc; } #ifndef SQLITE_OMIT_SHARED_CACHE /* ** Enable the shared pager and schema features. */ int sqlite3_enable_shared_cache(int enable){ SqliteTsd *pTsd = sqlite3Tsd(); |
︙ | ︙ |
Changes to src/btree.h.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the sqlite B-Tree file ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** | | | 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 header file defines the interface that the sqlite B-Tree file ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** ** @(#) $Id: btree.h,v 1.69 2006/01/07 13:21:04 danielk1977 Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ /* TODO: This definition is just included so other modules compile. It ** needs to be revisited. */ |
︙ | ︙ | |||
74 75 76 77 78 79 80 81 82 83 84 85 86 87 | int sqlite3BtreeRollbackStmt(Btree*); int sqlite3BtreeCreateTable(Btree*, int*, int flags); int sqlite3BtreeIsInTrans(Btree*); int sqlite3BtreeIsInStmt(Btree*); int sqlite3BtreeSync(Btree*, const char *zMaster); void *sqlite3BtreeSchema(Btree *, int, void(*)(void *)); int sqlite3BtreeSchemaLocked(Btree *); const char *sqlite3BtreeGetFilename(Btree *); const char *sqlite3BtreeGetDirname(Btree *); const char *sqlite3BtreeGetJournalname(Btree *); int sqlite3BtreeCopyFile(Btree *, Btree *); /* The flags parameter to sqlite3BtreeCreateTable can be the bitwise OR | > | 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | int sqlite3BtreeRollbackStmt(Btree*); int sqlite3BtreeCreateTable(Btree*, int*, int flags); int sqlite3BtreeIsInTrans(Btree*); int sqlite3BtreeIsInStmt(Btree*); int sqlite3BtreeSync(Btree*, const char *zMaster); void *sqlite3BtreeSchema(Btree *, int, void(*)(void *)); int sqlite3BtreeSchemaLocked(Btree *); int sqlite3BtreeLockTable(Btree *, int, u8); const char *sqlite3BtreeGetFilename(Btree *); const char *sqlite3BtreeGetDirname(Btree *); const char *sqlite3BtreeGetJournalname(Btree *); int sqlite3BtreeCopyFile(Btree *, Btree *); /* The flags parameter to sqlite3BtreeCreateTable can be the bitwise OR |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
18 19 20 21 22 23 24 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 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 74 75 76 77 78 79 80 81 82 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 122 123 124 125 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** ** $Id: build.c,v 1.369 2006/01/07 13:21:04 danielk1977 Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Initialize the pParse structure as needed. */ void sqlite3BeginParse(Parse *pParse, int explainFlag){ pParse->explain = explainFlag; pParse->nVar = 0; } #ifndef SQLITE_OMIT_SHARED_CACHE /* ** The TableLock structure is only used by the sqlite3TableLock() and ** codeTableLocks() functions. */ struct TableLock { int iDb; int iTab; u8 isWriteLock; const char *zName; }; /* ** Have the compiled statement lock the table with rootpage iTab in database ** iDb at the shared-cache level when executed. The isWriteLock argument ** is zero for a read-lock, or non-zero for a write-lock. ** ** The zName parameter should point to the unqualified table name. This is ** used to provide a more informative error message should the lock fail. */ void sqlite3TableLock( Parse *pParse, int iDb, int iTab, u8 isWriteLock, const char *zName ){ int i; int nBytes; TableLock *p; SqliteTsd *pTsd = sqlite3Tsd(); if( 0==pTsd->useSharedData ){ return; } for(i=0; i<pParse->nTableLock; i++){ p = &pParse->aTableLock[i]; if( p->iDb==iDb && p->iTab==iTab ){ p->isWriteLock = (p->isWriteLock || isWriteLock); return; } } nBytes = sizeof(TableLock) * (pParse->nTableLock+1); sqliteReallocOrFree((void **)&pParse->aTableLock, nBytes); if( pParse->aTableLock ){ p = &pParse->aTableLock[pParse->nTableLock++]; p->iDb = iDb; p->iTab = iTab; p->isWriteLock = isWriteLock; p->zName = zName; } } /* ** Code an OP_TableLock instruction for each table locked by the ** statement (configured by calls to sqlite3TableLock()). */ static void codeTableLocks(Parse *pParse){ int i; Vdbe *pVdbe; assert( sqlite3Tsd()->useSharedData || pParse->nTableLock==0 ); if( 0==(pVdbe = sqlite3GetVdbe(pParse)) ){ return; } for(i=0; i<pParse->nTableLock; i++){ TableLock *p = &pParse->aTableLock[i]; int p1 = p->iDb; if( p->isWriteLock ){ p1 = -1*(p1+1); } sqlite3VdbeOp3(pVdbe, OP_TableLock, p1, p->iTab, p->zName, P3_STATIC); } } #else #define codeTableLocks(x) #endif /* ** This routine is called after a single SQL statement has been ** parsed and a VDBE program to execute that statement has been ** prepared. This routine puts the finishing touches on the ** VDBE program and resets the pParse structure for the next ** parse. |
︙ | ︙ | |||
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | /* The cookie mask contains one bit for each database file open. ** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are ** set for each database that is used. Generate code to start a ** transaction on each used database and to verify the schema cookie ** on each used database. */ if( pParse->cookieGoto>0 ){ u32 mask; int iDb; sqlite3VdbeJumpHere(v, pParse->cookieGoto-1); for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){ if( (mask & pParse->cookieMask)==0 ) continue; sqlite3VdbeAddOp(v, OP_Transaction, iDb, (mask & pParse->writeMask)!=0); sqlite3VdbeAddOp(v, OP_VerifyCookie, iDb, pParse->cookieValue[iDb]); } sqlite3VdbeAddOp(v, OP_Goto, 0, pParse->cookieGoto); } #ifndef SQLITE_OMIT_TRACE /* Add a No-op that contains the complete text of the compiled SQL ** statement as its P3 argument. This does not change the functionality ** of the program. | > > > > > > > | 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 | /* The cookie mask contains one bit for each database file open. ** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are ** set for each database that is used. Generate code to start a ** transaction on each used database and to verify the schema cookie ** on each used database. */ assert( pParse->cookieGoto>0 || pParse->nTableLock==0 ); if( pParse->cookieGoto>0 ){ u32 mask; int iDb; sqlite3VdbeJumpHere(v, pParse->cookieGoto-1); for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){ if( (mask & pParse->cookieMask)==0 ) continue; sqlite3VdbeAddOp(v, OP_Transaction, iDb, (mask & pParse->writeMask)!=0); sqlite3VdbeAddOp(v, OP_VerifyCookie, iDb, pParse->cookieValue[iDb]); } /* Once all the cookies have been verified and transactions opened, ** obtain the required table-locks. This is a no-op unless the ** shared-cache feature is enabled. */ codeTableLocks(pParse); sqlite3VdbeAddOp(v, OP_Goto, 0, pParse->cookieGoto); } #ifndef SQLITE_OMIT_TRACE /* Add a No-op that contains the complete text of the compiled SQL ** statement as its P3 argument. This does not change the functionality ** of the program. |
︙ | ︙ | |||
505 506 507 508 509 510 511 | return zName; } /* ** Open the sqlite_master table stored in database number iDb for ** writing. The table is opened using cursor 0. */ | | > > | 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 | return zName; } /* ** Open the sqlite_master table stored in database number iDb for ** writing. The table is opened using cursor 0. */ void sqlite3OpenMasterTable(Parse *p, int iDb){ Vdbe *v = sqlite3GetVdbe(p); sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb)); sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); sqlite3VdbeAddOp(v, OP_OpenWrite, 0, MASTER_ROOT); sqlite3VdbeAddOp(v, OP_SetNumColumns, 0, 5); /* sqlite_master has 5 columns */ } /* ** The token *pName contains the name of a database (either "main" or |
︙ | ︙ | |||
773 774 775 776 777 778 779 | if( isView ){ sqlite3VdbeAddOp(v, OP_Integer, 0, 0); }else #endif { sqlite3VdbeAddOp(v, OP_CreateTable, iDb, 0); } | | | 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 | if( isView ){ sqlite3VdbeAddOp(v, OP_Integer, 0, 0); }else #endif { sqlite3VdbeAddOp(v, OP_CreateTable, iDb, 0); } sqlite3OpenMasterTable(pParse, iDb); sqlite3VdbeAddOp(v, OP_NewRowid, 0, 0); sqlite3VdbeAddOp(v, OP_Dup, 0, 0); sqlite3VdbeAddOp(v, OP_Null, 0, 0); sqlite3VdbeAddOp(v, OP_Insert, 0, 0); sqlite3VdbeAddOp(v, OP_Close, 0, 0); sqlite3VdbeAddOp(v, OP_Pull, 1, 0); } |
︙ | ︙ | |||
1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 | /* If this is a CREATE TABLE xx AS SELECT ..., execute the SELECT ** statement to populate the new table. The root-page number for the ** new table is on the top of the vdbe stack. ** ** Once the SELECT has been coded by sqlite3Select(), it is in a ** suitable state to query for the column names and types to be used ** by the new table. */ if( pSelect ){ Table *pSelTab; sqlite3VdbeAddOp(v, OP_Dup, 0, 0); sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); sqlite3VdbeAddOp(v, OP_OpenWrite, 1, 0); pParse->nTab = 2; | > > > > > | 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 | /* If this is a CREATE TABLE xx AS SELECT ..., execute the SELECT ** statement to populate the new table. The root-page number for the ** new table is on the top of the vdbe stack. ** ** Once the SELECT has been coded by sqlite3Select(), it is in a ** suitable state to query for the column names and types to be used ** by the new table. ** ** A shared-cache write-lock is not required to write to the new table, ** as a schema-lock must have already been obtained to create it. Since ** a schema-lock excludes all other database users, the write-lock would ** be redundant. */ if( pSelect ){ Table *pSelTab; sqlite3VdbeAddOp(v, OP_Dup, 0, 0); sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); sqlite3VdbeAddOp(v, OP_OpenWrite, 1, 0); pParse->nTab = 2; |
︙ | ︙ | |||
2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 | ** routine will invoke the collation-needed callback if necessary (and ** if one has been registered). */ if( sqlite3CheckIndexCollSeq(pParse, pIndex) ){ return; } v = sqlite3GetVdbe(pParse); if( v==0 ) return; if( memRootPage>=0 ){ sqlite3VdbeAddOp(v, OP_MemLoad, memRootPage, 0); tnum = 0; }else{ tnum = pIndex->tnum; sqlite3VdbeAddOp(v, OP_Clear, tnum, iDb); } sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); sqlite3VdbeOp3(v, OP_OpenWrite, iIdx, tnum, (char*)&pIndex->keyInfo, P3_KEYINFO); | > > > | | 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 | ** routine will invoke the collation-needed callback if necessary (and ** if one has been registered). */ if( sqlite3CheckIndexCollSeq(pParse, pIndex) ){ return; } /* Require a write-lock on the table to perform this operation */ sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName); v = sqlite3GetVdbe(pParse); if( v==0 ) return; if( memRootPage>=0 ){ sqlite3VdbeAddOp(v, OP_MemLoad, memRootPage, 0); tnum = 0; }else{ tnum = pIndex->tnum; sqlite3VdbeAddOp(v, OP_Clear, tnum, iDb); } sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); sqlite3VdbeOp3(v, OP_OpenWrite, iIdx, tnum, (char*)&pIndex->keyInfo, P3_KEYINFO); sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iTab, 0); sqlite3GenerateIndexKey(v, pIndex, iTab); if( pIndex->onError!=OE_None ){ int curaddr = sqlite3VdbeCurrentAddr(v); int addr2 = curaddr+4; sqlite3VdbeChangeP2(v, curaddr-1, addr2); sqlite3VdbeAddOp(v, OP_Rowid, iTab, 0); |
︙ | ︙ |
Changes to src/delete.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 ** in order to generate code for DELETE FROM statements. ** | | | 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 ** in order to generate code for DELETE FROM statements. ** ** $Id: delete.c,v 1.115 2006/01/07 13:21:04 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** Look up every table that is named in pSrc. If any table is not found, ** add an error message to pParse->zErrMsg and return NULL. If all tables ** are found, return a pointer to the last table. |
︙ | ︙ | |||
55 56 57 58 59 60 61 | #endif return 0; } /* ** Generate code that will open a table for reading. */ | | | | > > > > | | 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | #endif return 0; } /* ** Generate code that will open a table for reading. */ void sqlite3OpenTable( Parse *p, /* Generate code into this VDBE */ int iCur, /* The cursor number of the table */ int iDb, /* The database index in sqlite3.aDb[] */ Table *pTab, /* The table to be opened */ int opcode /* OP_OpenRead or OP_OpenWrite */ ){ Vdbe *v = sqlite3GetVdbe(p); assert( opcode==OP_OpenWrite || opcode==OP_OpenRead ); sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite), pTab->zName); sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); VdbeComment((v, "# %s", pTab->zName)); sqlite3VdbeAddOp(v, opcode, iCur, pTab->tnum); sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, pTab->nCol); } /* ** Generate code for a DELETE FROM statement. ** |
︙ | ︙ | |||
204 205 206 207 208 209 210 | if( pWhere==0 && !triggers_exist ){ if( db->flags & SQLITE_CountRows ){ /* If counting rows deleted, just count the total number of ** entries in the table. */ int endOfLoop = sqlite3VdbeMakeLabel(v); int addr; if( !isView ){ | | | 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | if( pWhere==0 && !triggers_exist ){ if( db->flags & SQLITE_CountRows ){ /* If counting rows deleted, just count the total number of ** entries in the table. */ int endOfLoop = sqlite3VdbeMakeLabel(v); int addr; if( !isView ){ sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead); } sqlite3VdbeAddOp(v, OP_Rewind, iCur, sqlite3VdbeCurrentAddr(v)+2); addr = sqlite3VdbeAddOp(v, OP_AddImm, 1, 0); sqlite3VdbeAddOp(v, OP_Next, iCur, addr); sqlite3VdbeResolveLabel(v, endOfLoop); sqlite3VdbeAddOp(v, OP_Close, iCur, 0); } |
︙ | ︙ | |||
272 273 274 275 276 277 278 | /* This is the beginning of the delete loop when there are ** row triggers. */ if( triggers_exist ){ addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, end); if( !isView ){ sqlite3VdbeAddOp(v, OP_Dup, 0, 0); | | | 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 | /* This is the beginning of the delete loop when there are ** row triggers. */ if( triggers_exist ){ addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, end); if( !isView ){ sqlite3VdbeAddOp(v, OP_Dup, 0, 0); sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead); } sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0); sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0); sqlite3VdbeAddOp(v, OP_RowData, iCur, 0); sqlite3VdbeAddOp(v, OP_Insert, oldIdx, 0); if( !isView ){ sqlite3VdbeAddOp(v, OP_Close, iCur, 0); |
︙ | ︙ |
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.153 2006/01/07 13:21:04 danielk1977 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: |
︙ | ︙ | |||
301 302 303 304 305 306 307 | ** counterRowid. */ if( pTab->autoInc ){ int iCur = pParse->nTab; int base = sqlite3VdbeCurrentAddr(v); counterRowid = pParse->nMem++; counterMem = pParse->nMem++; | < | < | 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 | ** counterRowid. */ if( pTab->autoInc ){ int iCur = pParse->nTab; int base = sqlite3VdbeCurrentAddr(v); counterRowid = pParse->nMem++; counterMem = pParse->nMem++; sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenRead); sqlite3VdbeAddOp(v, OP_Rewind, iCur, base+13); sqlite3VdbeAddOp(v, OP_Column, iCur, 0); sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0); sqlite3VdbeAddOp(v, OP_Ne, 0x100, base+12); sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0); sqlite3VdbeAddOp(v, OP_MemStore, counterRowid, 1); sqlite3VdbeAddOp(v, OP_Column, iCur, 1); |
︙ | ︙ | |||
682 683 684 685 686 687 688 | /* Update the sqlite_sequence table by storing the content of the ** counter value in memory counterMem back into the sqlite_sequence ** table. */ if( pTab->autoInc ){ int iCur = pParse->nTab; int base = sqlite3VdbeCurrentAddr(v); | < | < | 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 | /* Update the sqlite_sequence table by storing the content of the ** counter value in memory counterMem back into the sqlite_sequence ** table. */ if( pTab->autoInc ){ int iCur = pParse->nTab; int base = sqlite3VdbeCurrentAddr(v); sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); sqlite3VdbeAddOp(v, OP_MemLoad, counterRowid, 0); sqlite3VdbeAddOp(v, OP_NotNull, -1, base+7); sqlite3VdbeAddOp(v, OP_Pop, 1, 0); sqlite3VdbeAddOp(v, OP_NewRowid, iCur, 0); sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0); sqlite3VdbeAddOp(v, OP_MemLoad, counterMem, 0); sqlite3VdbeAddOp(v, OP_MakeRecord, 2, 0); |
︙ | ︙ | |||
1106 1107 1108 1109 1110 1111 1112 | int op /* OP_OpenRead or OP_OpenWrite */ ){ int i; int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); Index *pIdx; Vdbe *v = sqlite3GetVdbe(pParse); assert( v!=0 ); | < < | < | 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 | int op /* OP_OpenRead or OP_OpenWrite */ ){ int i; int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); Index *pIdx; Vdbe *v = sqlite3GetVdbe(pParse); assert( v!=0 ); sqlite3OpenTable(pParse, base, iDb, pTab, op); for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ assert( pIdx->pSchema==pTab->pSchema ); sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); VdbeComment((v, "# %s", pIdx->zName)); sqlite3VdbeOp3(v, op, i+base, pIdx->tnum, (char*)&pIdx->keyInfo, P3_KEYINFO); } if( pParse->nTab<=base+i ){ pParse->nTab = base+i; } } |
Changes to src/select.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 SELECT 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 SELECT statements in SQLite. ** ** $Id: select.c,v 1.286 2006/01/07 13:21:04 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** Allocate a new Select structure and return a pointer to that ** structure. |
︙ | ︙ | |||
2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 | }else{ return 0; } pExpr = pList->a[0].pExpr; if( pExpr->op!=TK_COLUMN ) return 0; iCol = pExpr->iColumn; pTab = pSrc->a[0].pTab; /* If we get to here, it means the query is of the correct form. ** Check to make sure we have an index and make pIdx point to the ** appropriate index. If the min() or max() is on an INTEGER PRIMARY ** key column, no index is necessary so set pIdx to NULL. If no ** usable index is found, return 0. */ | > | 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 | }else{ return 0; } pExpr = pList->a[0].pExpr; if( pExpr->op!=TK_COLUMN ) return 0; iCol = pExpr->iColumn; pTab = pSrc->a[0].pTab; /* If we get to here, it means the query is of the correct form. ** Check to make sure we have an index and make pIdx point to the ** appropriate index. If the min() or max() is on an INTEGER PRIMARY ** key column, no index is necessary so set pIdx to NULL. If no ** usable index is found, return 0. */ |
︙ | ︙ | |||
2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 | /* Generating code to find the min or the max. Basically all we have ** to do is find the first or the last entry in the chosen index. If ** the min() or max() is on the INTEGER PRIMARY KEY, then find the first ** or last entry in the main table. */ iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); sqlite3CodeVerifySchema(pParse, iDb); base = pSrc->a[0].iCursor; brk = sqlite3VdbeMakeLabel(v); computeLimitRegisters(pParse, p, brk); if( pSrc->a[0].pSelect==0 ){ | > | | 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 | /* Generating code to find the min or the max. Basically all we have ** to do is find the first or the last entry in the chosen index. If ** the min() or max() is on the INTEGER PRIMARY KEY, then find the first ** or last entry in the main table. */ iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); sqlite3CodeVerifySchema(pParse, iDb); sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); base = pSrc->a[0].iCursor; brk = sqlite3VdbeMakeLabel(v); computeLimitRegisters(pParse, p, brk); if( pSrc->a[0].pSelect==0 ){ sqlite3OpenTable(pParse, base, iDb, pTab, OP_OpenRead); } if( pIdx==0 ){ sqlite3VdbeAddOp(v, seekOp, base, 0); }else{ /* Even though the cursor used to open the index here is closed ** as soon as a single value has been read from it, allocate it ** using (pParse->nTab++) to prevent the cursor id from being |
︙ | ︙ |
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.453 2006/01/07 13:21:04 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** Extra interface definitions for those who need them */ |
︙ | ︙ | |||
251 252 253 254 255 256 257 | ** pointer arithmetic. */ #define Addr(X) ((uptr)X) #ifdef SQLITE_MEMDEBUG /* ** The following global variables are used for testing and debugging | | | | | | | > | | | | | > | 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 | ** pointer arithmetic. */ #define Addr(X) ((uptr)X) #ifdef SQLITE_MEMDEBUG /* ** The following global variables are used for testing and debugging ** only. They only work if SQLITE_MEMDEBUG is defined. */ extern int sqlite3_nMalloc; /* Number of sqliteMalloc() calls */ extern int sqlite3_nFree; /* Number of sqliteFree() calls */ extern int sqlite3_iMallocFail; /* Fail sqliteMalloc() after this many calls */ extern int sqlite3_iMallocReset; /* Set iMallocFail to this when it reaches 0 */ #define ENTER_MALLOC (\ sqlite3Tsd()->zFile = __FILE__, sqlite3Tsd()->iLine = __LINE__ \ ) #define sqliteMalloc(x) (ENTER_MALLOC, sqlite3Malloc(x)) #define sqliteMallocRaw(x) (ENTER_MALLOC, sqlite3MallocRaw(x)) #define sqliteRealloc(x,y) (ENTER_MALLOC, sqlite3Realloc(x,y)) #define sqliteStrDup(x) (ENTER_MALLOC, sqlite3StrDup(x)) #define sqliteStrNDup(x,y) (ENTER_MALLOC, sqlite3StrNDup(x,y)) #define sqliteReallocOrFree(x,y) (ENTER_MALLOC, sqlite3ReallocOrFree(x,y)) #else #define sqliteMalloc(x) sqlite3Malloc(x) #define sqliteMallocRaw(x) sqlite3MallocRaw(x) #define sqliteRealloc(x,y) sqlite3Realloc(x,y) #define sqliteStrDup(x) sqlite3StrDup(x) #define sqliteStrNDup(x,y) sqlite3StrNDup(x,y) #define sqliteReallocOrFree(x,y) sqlite3ReallocOrFree(x,y) #endif #define sqliteFree(x) sqlite3FreeX(x) #define sqliteAllocSize(x) sqlite3AllocSize(x) /* |
︙ | ︙ | |||
355 356 357 358 359 360 361 362 363 364 365 366 367 368 | typedef struct KeyInfo KeyInfo; typedef struct NameContext NameContext; typedef struct Parse Parse; typedef struct Select Select; typedef struct SrcList SrcList; typedef struct SqliteTsd SqliteTsd; typedef struct Table Table; typedef struct Token Token; typedef struct TriggerStack TriggerStack; typedef struct TriggerStep TriggerStep; typedef struct Trigger Trigger; typedef struct WhereInfo WhereInfo; typedef struct WhereLevel WhereLevel; | > | 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 | typedef struct KeyInfo KeyInfo; typedef struct NameContext NameContext; typedef struct Parse Parse; typedef struct Select Select; typedef struct SrcList SrcList; typedef struct SqliteTsd SqliteTsd; typedef struct Table Table; typedef struct TableLock TableLock; typedef struct Token Token; typedef struct TriggerStack TriggerStack; typedef struct TriggerStep TriggerStep; typedef struct Trigger Trigger; typedef struct WhereInfo WhereInfo; typedef struct WhereLevel WhereLevel; |
︙ | ︙ | |||
1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 | ** the parser and down into all the parser action routine in order to ** carry around information that is global to the entire parse. ** ** The structure is divided into two parts. When the parser and code ** generate call themselves recursively, the first part of the structure ** is constant but the second part is reset at the beginning and end of ** each recursion. */ struct Parse { sqlite3 *db; /* The main database structure */ int rc; /* Return code from execution */ char *zErrMsg; /* An error message */ Vdbe *pVdbe; /* An engine for executing database bytecode */ u8 colNamesSet; /* TRUE after OP_ColumnName has been issued to pVdbe */ u8 nameClash; /* A permanent table name clashes with temp table name */ u8 checkSchema; /* Causes schema cookie check after an error */ u8 nested; /* Number of nested calls to the parser/code generator */ 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 ckOffset; /* Stack offset to data used by CHECK constraints */ u32 writeMask; /* Start a write transaction on these databases */ u32 cookieMask; /* Bitmask of schema verified databases */ int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */ int cookieValue[MAX_ATTACHED+2]; /* Values of cookies to verify */ /* Above is constant between recursions. Below is reset before and after ** each recursion */ int nVar; /* Number of '?' variables seen in the SQL so far */ int nVarExpr; /* Number of used slots in apVarExpr[] */ int nVarExprAlloc; /* Number of allocated slots in apVarExpr[] */ | > > > > > > > > > > | 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 | ** the parser and down into all the parser action routine in order to ** carry around information that is global to the entire parse. ** ** The structure is divided into two parts. When the parser and code ** generate call themselves recursively, the first part of the structure ** is constant but the second part is reset at the beginning and end of ** each recursion. ** ** The nTableLock and aTableLock variables are only used if the shared-cache ** feature is enabled (if sqlite3Tsd()->useSharedData is true). They are ** used to store the set of table-locks required by the statement being ** compiled. Function sqlite3TableLock() is used to add entries to the ** list. */ struct Parse { sqlite3 *db; /* The main database structure */ int rc; /* Return code from execution */ char *zErrMsg; /* An error message */ Vdbe *pVdbe; /* An engine for executing database bytecode */ u8 colNamesSet; /* TRUE after OP_ColumnName has been issued to pVdbe */ u8 nameClash; /* A permanent table name clashes with temp table name */ u8 checkSchema; /* Causes schema cookie check after an error */ u8 nested; /* Number of nested calls to the parser/code generator */ 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 ckOffset; /* Stack offset to data used by CHECK constraints */ u32 writeMask; /* Start a write transaction on these databases */ u32 cookieMask; /* Bitmask of schema verified databases */ int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */ int cookieValue[MAX_ATTACHED+2]; /* Values of cookies to verify */ #ifndef SQLITE_OMIT_SHARED_CACHE int nTableLock; /* Number of locks in aTableLock */ TableLock *aTableLock; /* Required table locks for shared-cache mode */ #endif /* Above is constant between recursions. Below is reset before and after ** each recursion */ int nVar; /* Number of '?' variables seen in the SQL so far */ int nVarExpr; /* Number of used slots in apVarExpr[] */ int nVarExprAlloc; /* Number of allocated slots in apVarExpr[] */ |
︙ | ︙ | |||
1501 1502 1503 1504 1505 1506 1507 | int sqlite3InitCallback(void*, int, char**, char**); void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); void sqlite3ResetInternalSchema(sqlite3*, int); void sqlite3BeginParse(Parse*,int); void sqlite3RollbackInternalChanges(sqlite3*); void sqlite3CommitInternalChanges(sqlite3*); Table *sqlite3ResultSetOfSelect(Parse*,char*,Select*); | | | 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 | int sqlite3InitCallback(void*, int, char**, char**); void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); void sqlite3ResetInternalSchema(sqlite3*, int); void sqlite3BeginParse(Parse*,int); void sqlite3RollbackInternalChanges(sqlite3*); void sqlite3CommitInternalChanges(sqlite3*); Table *sqlite3ResultSetOfSelect(Parse*,char*,Select*); void sqlite3OpenMasterTable(Parse *, int); void sqlite3StartTable(Parse*,Token*,Token*,Token*,int,int,int); void sqlite3AddColumn(Parse*,Token*); void sqlite3AddNotNull(Parse*, int); void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int); void sqlite3AddCheckConstraint(Parse*, Expr*); void sqlite3AddColumnType(Parse*,Token*); void sqlite3AddDefaultValue(Parse*,Expr*); |
︙ | ︙ | |||
1542 1543 1544 1545 1546 1547 1548 | int sqlite3Select(Parse*, Select*, int, int, Select*, int, int*, char *aff); Select *sqlite3SelectNew(ExprList*,SrcList*,Expr*,ExprList*,Expr*,ExprList*, int,Expr*,Expr*); void sqlite3SelectDelete(Select*); void sqlite3SelectUnbind(Select*); Table *sqlite3SrcListLookup(Parse*, SrcList*); int sqlite3IsReadOnly(Parse*, Table*, int); | | < | 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 | int sqlite3Select(Parse*, Select*, int, int, Select*, int, int*, char *aff); Select *sqlite3SelectNew(ExprList*,SrcList*,Expr*,ExprList*,Expr*,ExprList*, int,Expr*,Expr*); void sqlite3SelectDelete(Select*); void sqlite3SelectUnbind(Select*); Table *sqlite3SrcListLookup(Parse*, SrcList*); int sqlite3IsReadOnly(Parse*, Table*, int); void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); void sqlite3DeleteFrom(Parse*, SrcList*, Expr*); void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**); void sqlite3WhereEnd(WhereInfo*); void sqlite3ExprCode(Parse*, Expr*); void sqlite3ExprCodeAndCache(Parse*, Expr*); int sqlite3ExprCodeExprList(Parse*, ExprList*); |
︙ | ︙ | |||
1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 | int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*); SqliteTsd *sqlite3Tsd(); void sqlite3AttachFunctions(sqlite3 *); void sqlite3MinimumFileFormat(Parse*, int, int); void sqlite3SchemaFree(void *); DbSchema *sqlite3SchemaGet(Btree *); int sqlite3SchemaToIndex(sqlite3 *db, DbSchema *); void sqlite3MallocClearFailed(); #ifdef NDEBUG #define sqlite3MallocDisallow() #define sqlite3MallocAllow() #else void sqlite3MallocDisallow(); | > > > > > > | 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 | int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*); SqliteTsd *sqlite3Tsd(); void sqlite3AttachFunctions(sqlite3 *); void sqlite3MinimumFileFormat(Parse*, int, int); void sqlite3SchemaFree(void *); DbSchema *sqlite3SchemaGet(Btree *); int sqlite3SchemaToIndex(sqlite3 *db, DbSchema *); #ifndef SQLITE_OMIT_SHARED_CACHE void sqlite3TableLock(Parse *, int, int, u8, const char *); #else #define sqlite3TableLock(v,w,x,y,z) #endif void sqlite3MallocClearFailed(); #ifdef NDEBUG #define sqlite3MallocDisallow() #define sqlite3MallocAllow() #else void sqlite3MallocDisallow(); |
︙ | ︙ |
Changes to src/tokenize.c.
︙ | ︙ | |||
11 12 13 14 15 16 17 | ************************************************************************* ** An tokenizer for SQL ** ** This file contains C code that splits an SQL input string up into ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ************************************************************************* ** An tokenizer for SQL ** ** This file contains C code that splits an SQL input string up into ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** ** $Id: tokenize.c,v 1.111 2006/01/07 13:21:04 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include <stdlib.h> /* |
︙ | ︙ | |||
421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 | pParse->zErrMsg = 0; if( !nErr ) nErr++; } if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){ sqlite3VdbeDelete(pParse->pVdbe); pParse->pVdbe = 0; } sqlite3DeleteTable(pParse->db, pParse->pNewTable); sqlite3DeleteTrigger(pParse->pNewTrigger); sqliteFree(pParse->apVarExpr); if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){ pParse->rc = SQLITE_ERROR; } return nErr; } | > > > > > > > | 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 | pParse->zErrMsg = 0; if( !nErr ) nErr++; } if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){ sqlite3VdbeDelete(pParse->pVdbe); pParse->pVdbe = 0; } #ifndef SQLITE_OMIT_SHARED_CACHE if( pParse->nested==0 ){ sqliteFree(pParse->aTableLock); pParse->aTableLock = 0; pParse->nTableLock = 0; } #endif sqlite3DeleteTable(pParse->db, pParse->pNewTable); sqlite3DeleteTrigger(pParse->pNewTrigger); sqliteFree(pParse->apVarExpr); if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){ pParse->rc = SQLITE_ERROR; } return nErr; } |
Changes to src/trigger.c.
︙ | ︙ | |||
233 234 235 236 237 238 239 | int addr; Vdbe *v; /* Make an entry in the sqlite_master table */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto triggerfinish_cleanup; sqlite3BeginWriteOperation(pParse, 0, iDb); | | | 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 | int addr; Vdbe *v; /* Make an entry in the sqlite_master table */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto triggerfinish_cleanup; sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3OpenMasterTable(pParse, iDb); addr = sqlite3VdbeAddOpList(v, ArraySize(insertTrig), insertTrig); sqlite3VdbeChangeP3(v, addr+2, pTrig->name, 0); sqlite3VdbeChangeP3(v, addr+3, pTrig->table, 0); sqlite3VdbeChangeP3(v, addr+6, (char*)pAll->z, pAll->n); sqlite3ChangeCookie(db, v, iDb); sqlite3VdbeAddOp(v, OP_Close, 0, 0); sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, |
︙ | ︙ | |||
516 517 518 519 520 521 522 | { 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); | | | 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 | { 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(pParse, 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); } } |
︙ | ︙ |
Changes to src/update.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 UPDATE statements. ** | | | 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 UPDATE statements. ** ** $Id: update.c,v 1.116 2006/01/07 13:21:04 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** The most recently coded instruction was an OP_Column to retrieve the ** i-th column of table pTab. This routine sets the P3 parameter of the ** OP_Column to the default value, if any. |
︙ | ︙ | |||
305 306 307 308 309 310 311 | if( !isView ){ sqlite3VdbeAddOp(v, OP_Dup, 0, 0); sqlite3VdbeAddOp(v, OP_Dup, 0, 0); /* Open a cursor and make it point to the record that is ** being updated. */ | | | 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 | if( !isView ){ sqlite3VdbeAddOp(v, OP_Dup, 0, 0); sqlite3VdbeAddOp(v, OP_Dup, 0, 0); /* Open a cursor and make it point to the record that is ** being updated. */ sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead); } sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0); /* Generate the OLD table */ sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0); sqlite3VdbeAddOp(v, OP_RowData, iCur, 0); |
︙ | ︙ | |||
360 361 362 363 364 365 366 | if( !isView ){ /* ** Open every index that needs updating. Note that if any ** index could potentially invoke a REPLACE conflict resolution ** action, then we need to open all indices because we might need ** to be deleting some records. */ | < | < | 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 | if( !isView ){ /* ** Open every index that needs updating. Note that if any ** index could potentially invoke a REPLACE conflict resolution ** action, then we need to open all indices because we might need ** to be deleting some records. */ sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite); if( onError==OE_Replace ){ openAll = 1; }else{ openAll = 0; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ if( pIdx->onError==OE_Replace ){ openAll = 1; |
︙ | ︙ |
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.514 2006/01/07 13:21:04 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include "vdbeInt.h" /* |
︙ | ︙ | |||
4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 | sqlite3ExpirePreparedStatements(db); }else{ p->expired = 1; } break; } /* An other opcode is illegal... */ default: { assert( 0 ); break; } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 | sqlite3ExpirePreparedStatements(db); }else{ p->expired = 1; } break; } #ifndef SQLITE_OMIT_SHARED_CACHE /* Opcode: TableLock P1 P2 P3 ** ** Obtain a lock on a particular table. This instruction is only used when ** the shared-cache feature is enabled. ** ** If P1 is not negative, then it is the index of the index of the database ** in sqlite3.aDb[] and a read-lock is required. If P1 is negative, a ** write-lock is required. In this case the index of the database is the ** absolute value of P1 minus one (iDb = abs(P1) - 1;) and a write-lock is ** required. ** ** P2 contains the root-page of the table to lock. ** ** P3 contains a pointer to the name of the table being locked. This is only ** used to generate an error message if the lock cannot be obtained. */ case OP_TableLock: { /* no-push */ int p1 = pOp->p1; u8 isWriteLock = (p1<0); if( isWriteLock ){ p1 = (-1*p1)-1; } rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock); if( rc==SQLITE_LOCKED ){ const char *z = (const char *)pOp->p3; sqlite3SetString(&p->zErrMsg, "database table is locked: ", z, (char*)0); } break; } #endif /* SHARED_OMIT_SHARED_CACHE */ /* An other opcode is illegal... */ default: { assert( 0 ); break; } |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 | ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. This module is reponsible for ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. This module is reponsible for ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** ** $Id: where.c,v 1.191 2006/01/07 13:21:04 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** The number of bits in a Bitmask. "BMS" means "BitMask Size". */ #define BMS (sizeof(Bitmask)*8) |
︙ | ︙ | |||
1576 1577 1578 1579 1580 1581 1582 | } #endif /* SQLITE_OMIT_EXPLAIN */ pTabItem = &pTabList->a[pLevel->iFrom]; pTab = pTabItem->pTab; iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); if( pTab->isTransient || pTab->pSelect ) continue; if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){ | | > > | 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 | } #endif /* SQLITE_OMIT_EXPLAIN */ pTabItem = &pTabList->a[pLevel->iFrom]; pTab = pTabItem->pTab; iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); if( pTab->isTransient || pTab->pSelect ) continue; if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){ sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, OP_OpenRead); }else{ sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); } pLevel->iTabCur = pTabItem->iCursor; if( (pIx = pLevel->pIdx)!=0 ){ assert( pIx->pSchema==pTab->pSchema ); sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); VdbeComment((v, "# %s", pIx->zName)); sqlite3VdbeOp3(v, OP_OpenRead, iIdxCur, pIx->tnum, |
︙ | ︙ |
Changes to test/shared.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2005 December 30 # # 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 file is testing the SELECT statement. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2005 December 30 # # 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 file is testing the SELECT statement. # # $Id: shared.test,v 1.6 2006/01/07 13:21:04 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl db close ifcapable !shared_cache { finish_test |
︙ | ︙ | |||
30 31 32 33 34 35 36 37 38 39 40 41 42 43 | # shared-2.*: Test that a read transaction can co-exist with a # write-transaction, including a simple test to ensure the # external locking protocol is still working. # shared-3.*: Simple test of read-uncommitted mode. # shared-4.*: Check that the schema is locked and unlocked correctly. # shared-5.*: Test that creating/dropping schema items works when databases # are attached in different orders to different handles. # do_test shared-1.1 { # Open a second database on the file test.db. It should use the same pager # cache and schema as the original connection. Verify that only 1 file is # opened. sqlite3 db2 test.db | > | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | # shared-2.*: Test that a read transaction can co-exist with a # write-transaction, including a simple test to ensure the # external locking protocol is still working. # shared-3.*: Simple test of read-uncommitted mode. # shared-4.*: Check that the schema is locked and unlocked correctly. # shared-5.*: Test that creating/dropping schema items works when databases # are attached in different orders to different handles. # shared-6.*: Locking, UNION ALL queries and sub-queries. # do_test shared-1.1 { # Open a second database on the file test.db. It should use the same pager # cache and schema as the original connection. Verify that only 1 file is # opened. sqlite3 db2 test.db |
︙ | ︙ | |||
70 71 72 73 74 75 76 | do_test shared-1.4 { # Try to insert a row into abc via connection 2. This should fail because # of the read-lock connection 1 is holding on table abc (obtained in the # previous test case). catchsql { INSERT INTO abc VALUES(4, 5, 6); } db2 | | | | 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | do_test shared-1.4 { # Try to insert a row into abc via connection 2. This should fail because # of the read-lock connection 1 is holding on table abc (obtained in the # previous test case). catchsql { INSERT INTO abc VALUES(4, 5, 6); } db2 } {1 {database table is locked: abc}} do_test shared-1.5 { # Using connection 2 (the one without the open transaction), try to create # a new table. This should fail because of the open read transaction # held by connection 1. catchsql { CREATE TABLE def(d, e, f); } db2 } {1 {database table is locked: sqlite_master}} do_test shared-1.6 { # Upgrade connection 1's transaction to a write transaction. Create # a new table - def - and insert a row into it. Because the connection 1 # transaction modifies the schema, it should not be possible for # connection 2 to access the database at all until the connection 1 # has finished the transaction. execsql { |
︙ | ︙ | |||
130 131 132 133 134 135 136 | execsql { BEGIN; SELECT * FROM abc; } db2 catchsql { INSERT INTO abc VALUES(1, 2, 3); } db2 | | | 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | execsql { BEGIN; SELECT * FROM abc; } db2 catchsql { INSERT INTO abc VALUES(1, 2, 3); } db2 } {1 {database table is locked: abc}} do_test shared-2.3 { # Turn db's transaction into a write-transaction. db3 should still be # able to read from table def (but will not see the new row). Connection # db2 should not be able to read def (because of the write-lock). # Todo: The failed "INSERT INTO abc ..." statement in the above test # has started a write-transaction on db2 (should this be so?). This |
︙ | ︙ | |||
154 155 156 157 158 159 160 | INSERT INTO def VALUES('VII', 'VIII', 'IX'); } concat [ catchsql { SELECT * FROM def; } db3 ] [ catchsql { SELECT * FROM def; } db2 ] | | | 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | INSERT INTO def VALUES('VII', 'VIII', 'IX'); } concat [ catchsql { SELECT * FROM def; } db3 ] [ catchsql { SELECT * FROM def; } db2 ] } {0 {IV V VI} 1 {database table is locked: def}} do_test shared-2.4 { # Commit the open transaction on db. db2 still holds a read-transaction. # This should prevent db3 from writing to the database, but not from # reading. execsql { COMMIT; } |
︙ | ︙ | |||
286 287 288 289 290 291 292 | SELECT * FROM test.abc; } db2 } {i ii iii} do_test shared-4.3.2 { catchsql { INSERT INTO abc VALUES('iv', 'v', 'vi'); } | | | | 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 | SELECT * FROM test.abc; } db2 } {i ii iii} do_test shared-4.3.2 { catchsql { INSERT INTO abc VALUES('iv', 'v', 'vi'); } } {1 {database table is locked: abc}} do_test shared-4.3.3 { catchsql { CREATE TABLE ghi(g, h, i); } } {1 {database table is locked: sqlite_master}} do_test shared-4.3.3 { catchsql { INSERT INTO def VALUES('IV', 'V', 'VI'); } } {0 {}} do_test shared-4.3.4 { # Cleanup: commit the transaction opened by db2. |
︙ | ︙ | |||
402 403 404 405 406 407 408 409 410 411 412 413 414 415 | } db2 } {} do_test shared-5.1.2 { execsql { SELECT * FROM sqlite_master UNION ALL SELECT * FROM test1.sqlite_master } db1 } {} catch {db1 close} catch {db2 close} finish_test sqlite3_enable_shared_cache $::enable_shared_cache | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | } db2 } {} do_test shared-5.1.2 { execsql { SELECT * FROM sqlite_master UNION ALL SELECT * FROM test1.sqlite_master } db1 } {} #-------------------------------------------------------------------------- # Tests shared-6.* test that a query obtains all the read-locks it needs # before starting execution of the query. This means that there is no chance # some rows of data will be returned before a lock fails and SQLITE_LOCK # is returned. # do_test shared-6.1.1 { execsql { CREATE TABLE t1(a, b); CREATE TABLE t2(a, b); INSERT INTO t1 VALUES(1, 2); INSERT INTO t2 VALUES(3, 4); } db1 execsql { SELECT * FROM t1 UNION ALL SELECT * FROM t2; } db2 } {1 2 3 4} do_test shared-6.1.2 { # Establish a write lock on table t2 via connection db2. Then make a # UNION all query using connection db1 that first accesses t1, followed # by t2. If the locks are grabbed at the start of the statement (as # they should be), no rows are returned. If (as was previously the case) # they are grabbed as the tables are accessed, the t1 rows will be # returned before the query fails. # execsql { BEGIN; INSERT INTO t2 VALUES(5, 6); } db2 set ret [list] catch { db1 eval {SELECT * FROM t1 UNION ALL SELECT * FROM t2} { lappend ret $a $b } } set ret } {} do_test shared-6.1.3 { execsql { COMMIT; BEGIN; INSERT INTO t1 VALUES(7, 8); } db2 set ret [list] catch { db1 eval { SELECT (CASE WHEN a>4 THEN (SELECT a FROM t1) ELSE 0 END) AS d FROM t2; } { lappend ret $d } } set ret } {} catch {db1 close} catch {db2 close} finish_test sqlite3_enable_shared_cache $::enable_shared_cache |