Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Style fixes to triggers code in various *.c files (partial fix to ticket #39) (CVS 571) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
8a4195c7466962291a296e8f53034ea8 |
User & Date: | danielk1977 2002-05-19 23:43:13.000 |
Context
2002-05-21
| ||
11:38 | Additional code cleanup resulting from a review of the new trigger code. (CVS 572) (check-in: 37dbdd551e user: drh tags: trunk) | |
2002-05-19
| ||
23:43 | Style fixes to triggers code in various *.c files (partial fix to ticket #39) (CVS 571) (check-in: 8a4195c746 user: danielk1977 tags: trunk) | |
2002-05-17
| ||
00:05 | Stylistic changes to src/trigger.c (partial fix to ticket #39). Also more comments. (CVS 570) (check-in: b1d72cb584 user: danielk1977 tags: trunk) | |
Changes
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.91 2002/05/19 23:43:14 danielk1977 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 |
︙ | ︙ | |||
255 256 257 258 259 260 261 | for(pElem=sqliteHashFirst(&db->trigHash); pElem; pElem=sqliteHashNext(pElem)){ Trigger *pTrigger = sqliteHashData(pElem); pTrigger->isCommit = 1; } /* Delete the structures for triggers removed this transaction */ pElem = sqliteHashFirst(&db->trigDrop); | | | 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 | for(pElem=sqliteHashFirst(&db->trigHash); pElem; pElem=sqliteHashNext(pElem)){ Trigger *pTrigger = sqliteHashData(pElem); pTrigger->isCommit = 1; } /* Delete the structures for triggers removed this transaction */ pElem = sqliteHashFirst(&db->trigDrop); while( pElem ){ Trigger *pTrigger = sqliteHashData(pElem); sqliteDeleteTrigger(pTrigger); pElem = sqliteHashNext(pElem); } sqliteHashClear(&db->trigDrop); db->flags &= ~SQLITE_InternChanges; |
︙ | ︙ | |||
319 320 321 322 323 324 325 | pOld = sqliteHashInsert(&db->idxHash, p->zName, strlen(p->zName)+1, p); assert( pOld==0 || pOld==p ); } sqliteHashClear(&db->idxDrop); /* Remove any triggers that haven't been commited yet */ for(pElem = sqliteHashFirst(&db->trigHash); pElem; | | | | | | | | | 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 | pOld = sqliteHashInsert(&db->idxHash, p->zName, strlen(p->zName)+1, p); assert( pOld==0 || pOld==p ); } sqliteHashClear(&db->idxDrop); /* Remove any triggers that haven't been commited yet */ for(pElem = sqliteHashFirst(&db->trigHash); pElem; pElem = (pElem?sqliteHashNext(pElem):0)){ Trigger *pTrigger = sqliteHashData(pElem); if( !pTrigger->isCommit ){ Table *pTbl = sqliteFindTable(db, pTrigger->table); if( pTbl ){ if( pTbl->pTrigger == pTrigger ){ pTbl->pTrigger = pTrigger->pNext; }else{ Trigger *cc = pTbl->pTrigger; while( cc ){ if( cc->pNext == pTrigger ){ cc->pNext = cc->pNext->pNext; break; } cc = cc->pNext; } assert(cc); } } sqliteHashInsert(&db->trigHash, pTrigger->name, 1 + strlen(pTrigger->name), 0); sqliteDeleteTrigger(pTrigger); pElem = sqliteHashFirst(&db->trigHash); } } /* Any triggers that were dropped - put 'em back in place */ for(pElem = sqliteHashFirst(&db->trigDrop); pElem; pElem = sqliteHashNext(pElem)){ Trigger *pTrigger = sqliteHashData(pElem); Table *pTbl = sqliteFindTable(db, pTrigger->table); sqliteHashInsert(&db->trigHash, pTrigger->name, strlen(pTrigger->name) + 1, pTrigger); pTrigger->pNext = pTbl->pTrigger; pTbl->pTrigger = pTrigger; } sqliteHashClear(&db->trigDrop); db->flags &= ~SQLITE_InternChanges; } /* |
︙ | ︙ | |||
1751 1752 1753 1754 1755 1756 1757 | ** Generate code that concludes an operation that may have changed ** the database. This is a companion function to BeginWriteOperation(). ** If a transaction was started, then commit it. If a checkpoint was ** started then commit that. */ void sqliteEndWriteOperation(Parse *pParse){ Vdbe *v; | | | 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 | ** Generate code that concludes an operation that may have changed ** the database. This is a companion function to BeginWriteOperation(). ** If a transaction was started, then commit it. If a checkpoint was ** started then commit that. */ void sqliteEndWriteOperation(Parse *pParse){ Vdbe *v; if( pParse->trigStack ) return; /* if this is in a trigger */ v = sqliteGetVdbe(pParse); if( v==0 ) return; if( pParse->db->flags & SQLITE_InTrans ){ /* Do Nothing */ }else{ sqliteVdbeAddOp(v, OP_Commit, 0, 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 ** to handle 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 ** to handle DELETE FROM statements. ** ** $Id: delete.c,v 1.33 2002/05/19 23:43:14 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** Given a table name, find the corresponding table and make sure the ** table is writeable. Generate an error and return NULL if not. If |
︙ | ︙ | |||
90 91 92 93 94 95 96 | if( pParse->nErr || sqlite_malloc_failed ){ pTabList = 0; goto delete_from_cleanup; } db = pParse->db; /* Check for the special case of a VIEW with one or more ON DELETE triggers | | | | | | | | | > > | > | | > | | 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 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 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 | if( pParse->nErr || sqlite_malloc_failed ){ pTabList = 0; goto delete_from_cleanup; } db = pParse->db; /* Check for the special case of a VIEW with one or more ON DELETE triggers ** defined */ { Table *pTab; char *zTab = sqliteTableNameFromToken(pTableName); if( zTab != 0 ){ pTab = sqliteFindTable(pParse->db, zTab); if( pTab ){ row_triggers_exist = sqliteTriggersExist(pParse, pTab->pTrigger, TK_DELETE, TK_BEFORE, TK_ROW, 0) || sqliteTriggersExist(pParse, pTab->pTrigger, TK_DELETE, TK_AFTER, TK_ROW, 0); } sqliteFree(zTab); if( row_triggers_exist && pTab->pSelect ){ /* Just fire VIEW triggers */ sqliteViewTriggers(pParse, pTab, pWhere, OE_Replace, 0); return; } } } /* Locate the table which we want to delete. This table has to be ** put in an IdList structure because some of the subroutines we ** will be calling are designed to work with multiple tables and expect ** an IdList* parameter instead of just a Table* parameger. */ pTabList = sqliteTableTokenToIdList(pParse, pTableName); if( pTabList==0 ) goto delete_from_cleanup; assert( pTabList->nId==1 ); pTab = pTabList->a[0].pTab; assert( pTab->pSelect==0 ); /* This table is not a view */ if( row_triggers_exist ){ oldIdx = pParse->nTab++; } /* Resolve the column names in all the expressions. */ base = pParse->nTab++; if( pWhere ){ if( sqliteExprResolveIds(pParse, base, pTabList, 0, pWhere) ){ goto delete_from_cleanup; } if( sqliteExprCheck(pParse, pWhere, 0, 0) ){ goto delete_from_cleanup; } } /* Begin generating code. */ v = sqliteGetVdbe(pParse); if( v==0 ){ goto delete_from_cleanup; } if( row_triggers_exist ){ sqliteBeginMultiWriteOperation(pParse); } else { sqliteBeginWriteOperation(pParse); } /* Initialize the counter of the number of rows deleted, if ** we are counting rows. */ if( db->flags & SQLITE_CountRows ){ sqliteVdbeAddOp(v, OP_Integer, 0, 0); } /* Special case: A DELETE without a WHERE clause deletes everything. ** It is easier just to erase the whole table. */ if( pWhere==0 && !row_triggers_exist ){ if( db->flags & SQLITE_CountRows ){ /* If counting rows deleted, just count the total number of ** entries in the table. */ int endOfLoop = sqliteVdbeMakeLabel(v); int addr; openOp = pTab->isTemp ? OP_OpenAux : OP_Open; assert( base==0 ); |
︙ | ︙ | |||
207 208 209 210 211 212 213 | /* Delete every item whose key was written to the list during the ** database scan. We have to delete items after the scan is complete ** because deleting an item can change the scan order. */ sqliteVdbeAddOp(v, OP_ListRewind, 0, 0); end = sqliteVdbeMakeLabel(v); | | | | | > | > | | | 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 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 | /* Delete every item whose key was written to the list during the ** database scan. We have to delete items after the scan is complete ** because deleting an item can change the scan order. */ sqliteVdbeAddOp(v, OP_ListRewind, 0, 0); end = sqliteVdbeMakeLabel(v); if( row_triggers_exist ){ int ii; addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end); sqliteVdbeAddOp(v, OP_Dup, 0, 0); openOp = pTab->isTemp ? OP_OpenAux : OP_Open; sqliteVdbeAddOp(v, openOp, base, pTab->tnum); sqliteVdbeAddOp(v, OP_MoveTo, base, 0); sqliteVdbeAddOp(v, OP_OpenTemp, oldIdx, 0); sqliteVdbeAddOp(v, OP_Integer, 13, 0); for(ii = 0; ii<pTab->nCol; ii++){ if( ii==pTab->iPKey ){ sqliteVdbeAddOp(v, OP_Recno, base, 0); } else { sqliteVdbeAddOp(v, OP_Column, base, ii); } } sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); sqliteVdbeAddOp(v, OP_PutIntKey, oldIdx, 0); sqliteVdbeAddOp(v, OP_Close, base, 0); sqliteVdbeAddOp(v, OP_Rewind, oldIdx, 0); sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default); } pParse->nTab = base + 1; openOp = pTab->isTemp ? OP_OpenWrAux : OP_OpenWrite; sqliteVdbeAddOp(v, openOp, base, pTab->tnum); for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ sqliteVdbeAddOp(v, openOp, pParse->nTab++, pIdx->tnum); } if( !row_triggers_exist ){ addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end); } sqliteGenerateRowDelete(v, pTab, base, pParse->trigStack?0:1); if( row_triggers_exist ){ for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ sqliteVdbeAddOp(v, OP_Close, base + i, pIdx->tnum); } sqliteVdbeAddOp(v, OP_Close, base, 0); sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default); } sqliteVdbeAddOp(v, OP_Goto, 0, addr); sqliteVdbeResolveLabel(v, end); sqliteVdbeAddOp(v, OP_ListReset, 0, 0); if( !row_triggers_exist ){ for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ sqliteVdbeAddOp(v, OP_Close, base + i, pIdx->tnum); } sqliteVdbeAddOp(v, OP_Close, base, 0); pParse->nTab = base; } } |
︙ | ︙ |
Changes to src/expr.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 routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions 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 routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** ** $Id: expr.c,v 1.60 2002/05/19 23:43:14 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** Construct a new expression node and return a pointer to it. Memory ** for this node is obtained from sqliteMalloc(). The calling function |
︙ | ︙ | |||
480 481 482 483 484 485 486 | } } } } /* If we have not already resolved this *.* expression, then maybe * it is a new.* or old.* trigger argument reference */ | | | < | | | | | > | | > | 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 | } } } } /* If we have not already resolved this *.* expression, then maybe * it is a new.* or old.* trigger argument reference */ if( cnt == 0 && pParse->trigStack != 0 ){ TriggerStack *pTriggerStack = pParse->trigStack; int t = 0; if( pTriggerStack->newIdx != -1 && sqliteStrICmp("new", zLeft) == 0 ){ pExpr->iTable = pTriggerStack->newIdx; cntTab++; t = 1; } if( pTriggerStack->oldIdx != -1 && sqliteStrICmp("old", zLeft) == 0 ){ pExpr->iTable = pTriggerStack->oldIdx; cntTab++; t = 1; } if( t ){ int j; for(j=0; j < pTriggerStack->pTab->nCol; j++) { if( sqliteStrICmp(pTriggerStack->pTab->aCol[j].zName, zRight)==0 ){ cnt++; pExpr->iColumn = j; } } } } if( cnt==0 && cntTab==1 && sqliteIsRowid(zRight) ){ cnt = 1; pExpr->iColumn = -1; } sqliteFree(zLeft); |
︙ | ︙ |
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.55 2002/05/19 23:43:14 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** This routine is call to handle SQL of the following forms: ** ** insert into TABLE (IDLIST) values(EXPRLIST) |
︙ | ︙ | |||
98 99 100 101 102 103 104 | if( pSelect || row_triggers_exist ){ sqliteBeginMultiWriteOperation(pParse); }else{ sqliteBeginWriteOperation(pParse); } /* if there are row triggers, allocate a temp table for new.* references. */ | | > | 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | if( pSelect || row_triggers_exist ){ sqliteBeginMultiWriteOperation(pParse); }else{ sqliteBeginWriteOperation(pParse); } /* if there are row triggers, allocate a temp table for new.* references. */ if( row_triggers_exist ){ newIdx = pParse->nTab++; } /* Figure out how many columns of data are supplied. If the data ** is coming from a SELECT statement, then this step has to generate ** all the code to implement the SELECT statement and leave the data ** in a temporary table. If data is coming from an expression list, ** then we just have to count the number of expressions. */ |
︙ | ︙ | |||
200 201 202 203 204 205 206 | ** in the original table definition. */ if( pColumn==0 ){ keyColumn = pTab->iPKey; } /* Open the temp table for FOR EACH ROW triggers */ | | > | | | 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 | ** in the original table definition. */ if( pColumn==0 ){ keyColumn = pTab->iPKey; } /* Open the temp table for FOR EACH ROW triggers */ if( row_triggers_exist ){ sqliteVdbeAddOp(v, OP_OpenTemp, newIdx, 0); } /* Initialize the count of rows to be inserted */ if( db->flags & SQLITE_CountRows && !pParse->trigStack ){ sqliteVdbeAddOp(v, OP_Integer, 0, 0); /* Initialize the row count */ } /* Open tables and indices if there are no row triggers */ if( !row_triggers_exist ){ base = pParse->nTab; openOp = pTab->isTemp ? OP_OpenWrAux : OP_OpenWrite; sqliteVdbeAddOp(v, openOp, base, pTab->tnum); sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC); for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){ sqliteVdbeAddOp(v, openOp, idx+base, pIdx->tnum); sqliteVdbeChangeP3(v, -1, pIdx->zName, P3_STATIC); |
︙ | ︙ | |||
233 234 235 236 237 238 239 | */ if( srcTab>=0 ){ iBreak = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_Rewind, srcTab, iBreak); iCont = sqliteVdbeCurrentAddr(v); } | | | 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 | */ if( srcTab>=0 ){ iBreak = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_Rewind, srcTab, iBreak); iCont = sqliteVdbeCurrentAddr(v); } if( row_triggers_exist ){ /* build the new.* reference row */ sqliteVdbeAddOp(v, OP_Integer, 13, 0); for(i=0; i<pTab->nCol; i++){ if( pColumn==0 ){ j = i; }else{ |
︙ | ︙ | |||
259 260 261 262 263 264 265 | } } sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0); sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0); /* Fire BEFORE triggers */ | < | | | | > | | | | | | | | | | 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 | } } sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0); sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0); /* Fire BEFORE triggers */ if( sqliteCodeRowTrigger(pParse, TK_INSERT, 0, TK_BEFORE, pTab, newIdx, -1, onError) ){ goto insert_cleanup; } /* Open the tables and indices for the INSERT */ if( !pTab->pSelect ){ base = pParse->nTab; openOp = pTab->isTemp ? OP_OpenWrAux : OP_OpenWrite; sqliteVdbeAddOp(v, openOp, base, pTab->tnum); sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC); for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){ sqliteVdbeAddOp(v, openOp, idx+base, pIdx->tnum); sqliteVdbeChangeP3(v, -1, pIdx->zName, P3_STATIC); } pParse->nTab += idx; } } /* Push the record number for the new entry onto the stack. The ** record number is a randomly generate integer created by NewRecno ** except when the table has an INTEGER PRIMARY KEY column, in which ** case the record number is the same as that column. */ if( !pTab->pSelect ){ if( keyColumn>=0 ){ if( srcTab>=0 ){ sqliteVdbeAddOp(v, OP_Column, srcTab, keyColumn); }else{ int addr; sqliteExprCode(pParse, pList->a[keyColumn].pExpr); /* If the PRIMARY KEY expression is NULL, then use OP_NewRecno ** to generate a unique primary key value. */ addr = sqliteVdbeAddOp(v, OP_Dup, 0, 1); sqliteVdbeAddOp(v, OP_NotNull, 0, addr+4); sqliteVdbeAddOp(v, OP_Pop, 1, 0); sqliteVdbeAddOp(v, OP_NewRecno, base, 0); } sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0); }else{ sqliteVdbeAddOp(v, OP_NewRecno, base, 0); } /* Push onto the stack, data for all columns of the new entry, beginning ** with the first column. */ for(i=0; i<pTab->nCol; i++){ if( i==pTab->iPKey ){ /* The value of the INTEGER PRIMARY KEY column is always a NULL. ** Whenever this column is read, the record number will be substituted ** in its place. So will fill this column with a NULL to avoid ** taking up data space with information that will never be used. */ sqliteVdbeAddOp(v, OP_String, 0, 0); continue; } if( pColumn==0 ){ j = i; }else{ for(j=0; j<pColumn->nId; j++){ |
︙ | ︙ | |||
334 335 336 337 338 339 340 | sqliteVdbeAddOp(v, OP_Column, srcTab, j); }else{ sqliteExprCode(pParse, pList->a[j].pExpr); } } /* Generate code to check constraints and generate index keys and | | | | | | < | | | > | | | | 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 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 | sqliteVdbeAddOp(v, OP_Column, srcTab, j); }else{ sqliteExprCode(pParse, pList->a[j].pExpr); } } /* Generate code to check constraints and generate index keys and ** do the insertion. */ endOfLoop = sqliteVdbeMakeLabel(v); sqliteGenerateConstraintChecks(pParse, pTab, base, 0,0,0,onError,endOfLoop); sqliteCompleteInsertion(pParse, pTab, base, 0,0,0); /* Update the count of rows that are inserted */ if( (db->flags & SQLITE_CountRows)!=0 && !pParse->trigStack){ sqliteVdbeAddOp(v, OP_AddImm, 1, 0); } } if( row_triggers_exist ){ /* Close all tables opened */ if( !pTab->pSelect ){ sqliteVdbeAddOp(v, OP_Close, base, 0); for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){ sqliteVdbeAddOp(v, OP_Close, idx+base, 0); } } /* Code AFTER triggers */ if( sqliteCodeRowTrigger(pParse, TK_INSERT, 0, TK_AFTER, pTab, newIdx, -1, onError) ){ goto insert_cleanup; } } /* The bottom of the loop, if the data source is a SELECT statement */ sqliteVdbeResolveLabel(v, endOfLoop); if( srcTab>=0 ){ sqliteVdbeAddOp(v, OP_Next, srcTab, iCont); sqliteVdbeResolveLabel(v, iBreak); sqliteVdbeAddOp(v, OP_Close, srcTab, 0); } if( !row_triggers_exist ){ /* Close all tables opened */ sqliteVdbeAddOp(v, OP_Close, base, 0); for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){ sqliteVdbeAddOp(v, OP_Close, idx+base, 0); } } sqliteEndWriteOperation(pParse); /* ** Return the number of rows inserted. */ if( db->flags & SQLITE_CountRows && !pParse->trigStack ){ sqliteVdbeAddOp(v, OP_ColumnCount, 1, 0); sqliteVdbeAddOp(v, OP_ColumnName, 0, 0); sqliteVdbeChangeP3(v, -1, "rows inserted", P3_STATIC); sqliteVdbeAddOp(v, OP_Callback, 1, 0); } |
︙ | ︙ |
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.75 2002/05/19 23:43:14 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* ** This is the callback routine for the code that initializes the |
︙ | ︙ | |||
390 391 392 393 394 395 396 | assert( sqliteHashFirst(&db->tblDrop)==0 ); /* There can not be uncommitted */ assert( sqliteHashFirst(&db->idxDrop)==0 ); /* DROP TABLEs or DROP INDEXs */ temp1 = db->tblHash; temp2 = db->trigHash; sqliteHashInit(&db->trigHash, SQLITE_HASH_STRING, 0); sqliteHashClear(&db->idxHash); | | | | | 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 | assert( sqliteHashFirst(&db->tblDrop)==0 ); /* There can not be uncommitted */ assert( sqliteHashFirst(&db->idxDrop)==0 ); /* DROP TABLEs or DROP INDEXs */ temp1 = db->tblHash; temp2 = db->trigHash; sqliteHashInit(&db->trigHash, SQLITE_HASH_STRING, 0); sqliteHashClear(&db->idxHash); for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){ Trigger * pTrigger = sqliteHashData(pElem); Table *pTab = sqliteFindTable(db, pTrigger->table); assert(pTab); if( pTab->isTemp ){ sqliteHashInsert(&db->trigHash, pTrigger->name, strlen(pTrigger->name), pTrigger); }else{ sqliteDeleteTrigger(pTrigger); } } sqliteHashClear(&temp2); sqliteHashInit(&db->tblHash, SQLITE_HASH_STRING, 0); |
︙ | ︙ | |||
430 431 432 433 434 435 436 | } } }else{ sqliteDeleteTable(db, pTab); } } sqliteHashClear(&temp1); | < | 430 431 432 433 434 435 436 437 438 439 440 441 442 443 | } } }else{ sqliteDeleteTable(db, pTab); } } sqliteHashClear(&temp1); db->flags &= ~SQLITE_Initialized; } /* ** Return the ROWID of the most recent insert */ int sqlite_last_insert_rowid(sqlite *db){ |
︙ | ︙ |
Changes to src/trigger.c.
︙ | ︙ | |||
76 77 78 79 80 81 82 | nt->strings = sqliteStrNDup(zData, zDataLen); offset = (int)(nt->strings - zData); sqliteExprMoveStrings(nt->pWhen, offset); ss = nt->step_list; | | > | > | 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | nt->strings = sqliteStrNDup(zData, zDataLen); offset = (int)(nt->strings - zData); sqliteExprMoveStrings(nt->pWhen, offset); ss = nt->step_list; while( ss ){ sqliteSelectMoveStrings(ss->pSelect, offset); if( ss->target.z ){ ss->target.z += offset; } sqliteExprMoveStrings(ss->pWhere, offset); sqliteExprListMoveStrings(ss->pExprList, offset); ss = ss->pNext; } /* if we are not initializing, and this trigger is not on a TEMP table, |
︙ | ︙ | |||
126 127 128 129 130 131 132 | /* Stick it in the hash-table */ sqliteHashInsert(&(pParse->db->trigHash), nt->name, pName->n + 1, nt); /* Attach it to the table object */ nt->pNext = tab->pTrigger; tab->pTrigger = nt; return; | | | | 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | /* Stick it in the hash-table */ sqliteHashInsert(&(pParse->db->trigHash), nt->name, pName->n + 1, nt); /* Attach it to the table object */ nt->pNext = tab->pTrigger; tab->pTrigger = nt; return; }else{ sqliteFree(nt->strings); sqliteFree(nt->name); sqliteFree(nt->table); sqliteFree(nt); } trigger_cleanup: sqliteIdListDelete(pColumns); sqliteExprDelete(pWhen); { TriggerStep * pp; TriggerStep * nn; pp = pStepList; while( pp ){ nn = pp->pNext; sqliteExprDelete(pp->pWhere); sqliteExprListDelete(pp->pExprList); sqliteSelectDelete(pp->pSelect); sqliteIdListDelete(pp->pIdList); sqliteFree(pp); pp = nn; |
︙ | ︙ | |||
224 225 226 227 228 229 230 | ** Recursively delete a Trigger structure */ void sqliteDeleteTrigger(Trigger *pTrigger) { TriggerStep *pTriggerStep; pTriggerStep = pTrigger->step_list; | | | 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 | ** Recursively delete a Trigger structure */ void sqliteDeleteTrigger(Trigger *pTrigger) { TriggerStep *pTriggerStep; pTriggerStep = pTrigger->step_list; while( pTriggerStep ){ TriggerStep * pTmp = pTriggerStep; pTriggerStep = pTriggerStep->pNext; sqliteExprDelete(pTmp->pWhere); sqliteExprListDelete(pTmp->pExprList); sqliteSelectDelete(pTmp->pSelect); sqliteIdListDelete(pTmp->pIdList); |
︙ | ︙ | |||
283 284 285 286 287 288 289 | */ if( !pParse->explain ){ /* 1 */ pTable = sqliteFindTable(pParse->db, pTrigger->table); assert(pTable); if( pTable->pTrigger == pTrigger ){ pTable->pTrigger = pTrigger->pNext; | | | 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 | */ if( !pParse->explain ){ /* 1 */ pTable = sqliteFindTable(pParse->db, pTrigger->table); assert(pTable); 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; |
︙ | ︙ | |||
342 343 344 345 346 347 348 | sqliteFree(zName); } static int checkColumnOverLap(IdList * pIdList, ExprList * pEList) { int i, e; | | | | | | > > > | 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 | sqliteFree(zName); } static int checkColumnOverLap(IdList * pIdList, ExprList * pEList) { int i, e; if( !pIdList )return 1; if( !pEList )return 1; for(i = 0; i < pIdList->nId; i++){ for(e = 0; e < pEList->nExpr; e++){ if( !sqliteStrICmp(pIdList->a[i].zName, pEList->a[e].zName) ){ return 1; } } } return 0; } /* A global variable that is TRUE if we should always set up temp tables for * for triggers, even if there are no triggers to code. This is used to test * how much overhead the triggers algorithm is causing. |
︙ | ︙ | |||
390 391 392 393 394 395 396 | while( pTriggerCursor ){ if( pTriggerCursor->op == op && pTriggerCursor->tr_tm == tr_tm && pTriggerCursor->foreach == foreach && checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){ TriggerStack * ss; ss = pParse->trigStack; | | > > | | 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 | while( pTriggerCursor ){ if( pTriggerCursor->op == op && pTriggerCursor->tr_tm == tr_tm && pTriggerCursor->foreach == foreach && checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){ TriggerStack * ss; ss = pParse->trigStack; while( ss && ss->pTrigger != pTrigger ){ ss = ss->pNext; } if( !ss )return 1; } pTriggerCursor = pTriggerCursor->pNext; } return 0; } |
︙ | ︙ | |||
489 490 491 492 493 494 495 | assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE); assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER); assert(newIdx != -1 || oldIdx != -1); pTrigger = pTab->pTrigger; | | | | | | > > | | | | > | | | 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 545 546 547 548 549 550 | assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE); assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER); assert(newIdx != -1 || oldIdx != -1); pTrigger = pTab->pTrigger; while( pTrigger ){ int fire_this = 0; /* determine whether we should code this trigger */ if( pTrigger->op == op && pTrigger->tr_tm == tr_tm && pTrigger->foreach == TK_ROW ){ fire_this = 1; pTriggerStack = pParse->trigStack; while( pTriggerStack ){ if( pTriggerStack->pTrigger == pTrigger ){ fire_this = 0; } pTriggerStack = pTriggerStack->pNext; } if( op == TK_UPDATE && pTrigger->pColumns && !checkColumnOverLap(pTrigger->pColumns, pChanges) ){ fire_this = 0; } } if( fire_this ){ int endTrigger; IdList dummyTablist; Expr * whenExpr; dummyTablist.nId = 0; dummyTablist.a = 0; /* Push an entry on to the trigger stack */ pTriggerStack = sqliteMalloc(sizeof(TriggerStack)); pTriggerStack->pTrigger = pTrigger; pTriggerStack->newIdx = newIdx; pTriggerStack->oldIdx = oldIdx; pTriggerStack->pTab = pTab; pTriggerStack->pNext = pParse->trigStack; pParse->trigStack = pTriggerStack; /* code the WHEN clause */ endTrigger = sqliteVdbeMakeLabel(pParse->pVdbe); whenExpr = sqliteExprDup(pTrigger->pWhen); if( sqliteExprResolveIds(pParse, 0, &dummyTablist, 0, whenExpr) ){ pParse->trigStack = pParse->trigStack->pNext; sqliteFree(pTriggerStack); sqliteExprDelete(whenExpr); return 1; } sqliteExprIfFalse(pParse, whenExpr, endTrigger); sqliteExprDelete(whenExpr); |
︙ | ︙ | |||
632 633 634 635 636 637 638 | for(ii = 0; ii < pTab->nCol; ii++){ aXRef[ii] = -1; } for(ii=0; ii<pChanges->nExpr; ii++){ int jj; if( sqliteExprResolveIds(pParse, oldIdx, theSelect.pSrc , 0, | | > | 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 | for(ii = 0; ii < pTab->nCol; ii++){ aXRef[ii] = -1; } for(ii=0; ii<pChanges->nExpr; ii++){ int jj; if( sqliteExprResolveIds(pParse, oldIdx, theSelect.pSrc , 0, pChanges->a[ii].pExpr) ){ goto trigger_cleanup; } if( sqliteExprCheck(pParse, pChanges->a[ii].pExpr, 0, 0) ) goto trigger_cleanup; for(jj=0; jj<pTab->nCol; jj++){ if( sqliteStrICmp(pTab->aCol[jj].zName, pChanges->a[ii].zName)==0 ){ aXRef[jj] = ii; |
︙ | ︙ | |||
657 658 659 660 661 662 663 | } sqliteVdbeAddOp(v, OP_Integer, 13, 0); for(ii = 0; ii<pTab->nCol; ii++){ if( aXRef[ii] < 0 ){ sqliteVdbeAddOp(v, OP_Column, oldIdx, ii); | | | | 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 | } sqliteVdbeAddOp(v, OP_Integer, 13, 0); for(ii = 0; ii<pTab->nCol; ii++){ if( aXRef[ii] < 0 ){ sqliteVdbeAddOp(v, OP_Column, oldIdx, ii); }else{ sqliteExprCode(pParse, pChanges->a[aXRef[ii]].pExpr); } } sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0); sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0); sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE, pTab, newIdx, oldIdx, orconf); sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER, pTab, newIdx, oldIdx, orconf); }else{ sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, oldIdx, orconf); sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, oldIdx, orconf); } sqliteVdbeAddOp(v, OP_Next, oldIdx, startOfLoop); |
︙ | ︙ |
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.39 2002/05/19 23:43:14 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** Process an UPDATE statement. */ void sqliteUpdate( |
︙ | ︙ | |||
55 56 57 58 59 60 61 | if( pParse->nErr || sqlite_malloc_failed ) goto update_cleanup; db = pParse->db; /* Check for the special case of a VIEW with one or more ON UPDATE triggers * defined */ { | | | | | > | | 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 | if( pParse->nErr || sqlite_malloc_failed ) goto update_cleanup; db = pParse->db; /* Check for the special case of a VIEW with one or more ON UPDATE triggers * defined */ { char *zTab = sqliteTableNameFromToken(pTableName); if( zTab != 0 ){ pTab = sqliteFindTable(pParse->db, zTab); if( pTab ){ row_triggers_exist = sqliteTriggersExist(pParse, pTab->pTrigger, TK_UPDATE, TK_BEFORE, TK_ROW, pChanges) || sqliteTriggersExist(pParse, pTab->pTrigger, TK_UPDATE, TK_AFTER, TK_ROW, pChanges); } sqliteFree(zTab); if( row_triggers_exist && pTab->pSelect ){ /* Just fire VIEW triggers */ sqliteViewTriggers(pParse, pTab, pWhere, onError, pChanges); return; } } } /* Locate the table which we want to update. This table has to be ** put in an IdList structure because some of the subroutines we ** will be calling are designed to work with multiple tables and expect ** an IdList* parameter instead of just a Table* parameter. */ pTabList = sqliteTableTokenToIdList(pParse, pTableName); if( pTabList==0 ) goto update_cleanup; pTab = pTabList->a[0].pTab; assert( pTab->pSelect==0 ); /* This table is not a VIEW */ aXRef = sqliteMalloc( sizeof(int) * pTab->nCol ); if( aXRef==0 ) goto update_cleanup; for(i=0; i<pTab->nCol; i++) aXRef[i] = -1; /* If there are FOR EACH ROW triggers, allocate temp tables */ if( row_triggers_exist ){ newIdx = pParse->nTab++; oldIdx = pParse->nTab++; } /* Resolve the column names in all the expressions in both the ** WHERE clause and in the new values. Also find the column index ** for each column to be updated in the pChanges array. |
︙ | ︙ | |||
193 194 195 196 197 198 199 | /* Initialize the count of updated rows */ if( db->flags & SQLITE_CountRows && !pParse->trigStack ){ sqliteVdbeAddOp(v, OP_Integer, 0, 0); } | | | | | | | > | | | > | | > > | 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 254 255 | /* Initialize the count of updated rows */ if( db->flags & SQLITE_CountRows && !pParse->trigStack ){ sqliteVdbeAddOp(v, OP_Integer, 0, 0); } if( row_triggers_exist ){ int ii; sqliteVdbeAddOp(v, OP_OpenTemp, oldIdx, 0); sqliteVdbeAddOp(v, OP_OpenTemp, newIdx, 0); sqliteVdbeAddOp(v, OP_ListRewind, 0, 0); addr = sqliteVdbeAddOp(v, OP_ListRead, 0, 0); sqliteVdbeAddOp(v, OP_Dup, 0, 0); sqliteVdbeAddOp(v, OP_Dup, 0, 0); sqliteVdbeAddOp(v, OP_Open, base, pTab->tnum); sqliteVdbeAddOp(v, OP_MoveTo, base, 0); sqliteVdbeAddOp(v, OP_Integer, 13, 0); for(ii = 0; ii < pTab->nCol; ii++){ if( ii == pTab->iPKey ){ sqliteVdbeAddOp(v, OP_Recno, base, 0); }else{ sqliteVdbeAddOp(v, OP_Column, base, ii); } } sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); sqliteVdbeAddOp(v, OP_PutIntKey, oldIdx, 0); sqliteVdbeAddOp(v, OP_Integer, 13, 0); for(ii = 0; ii < pTab->nCol; ii++){ if( aXRef[ii] < 0 ){ if( ii == pTab->iPKey ){ sqliteVdbeAddOp(v, OP_Recno, base, 0); }else{ sqliteVdbeAddOp(v, OP_Column, base, ii); } }else{ sqliteExprCode(pParse, pChanges->a[aXRef[ii]].pExpr); } } sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0); sqliteVdbeAddOp(v, OP_Close, base, 0); sqliteVdbeAddOp(v, OP_Rewind, oldIdx, 0); sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0); if( sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE, pTab, newIdx, oldIdx, onError) ){ goto update_cleanup; } } /* Rewind the list of records that need to be updated and ** 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. |
︙ | ︙ | |||
272 273 274 275 276 277 278 | /* Loop over every record that needs updating. We have to load ** the old data for each record to be updated because some columns ** might not change and we will need to copy the old value. ** Also, the old data is needed to delete the old index entires. ** So make the cursor point at the old record. */ | | | 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 | /* Loop over every record that needs updating. We have to load ** the old data for each record to be updated because some columns ** might not change and we will need to copy the old value. ** Also, the old data is needed to delete the old index entires. ** So make the cursor point at the old record. */ if( !row_triggers_exist ){ int ii; sqliteVdbeAddOp(v, OP_ListRewind, 0, 0); addr = sqliteVdbeAddOp(v, OP_ListRead, 0, 0); sqliteVdbeAddOp(v, OP_Dup, 0, 0); } sqliteVdbeAddOp(v, OP_MoveTo, base, 0); |
︙ | ︙ | |||
333 334 335 336 337 338 339 | /* Increment the row counter */ if( db->flags & SQLITE_CountRows && !pParse->trigStack){ sqliteVdbeAddOp(v, OP_AddImm, 1, 0); } | | | | > > | | | 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 | /* Increment the row counter */ if( db->flags & SQLITE_CountRows && !pParse->trigStack){ sqliteVdbeAddOp(v, OP_AddImm, 1, 0); } if( row_triggers_exist ){ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ if( openAll || aIdxUsed[i] ) sqliteVdbeAddOp(v, OP_Close, base+i+1, 0); } sqliteVdbeAddOp(v, OP_Close, base, 0); pParse->nTab = base; if( sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER, pTab, newIdx, oldIdx, onError) ){ goto update_cleanup; } } /* Repeat the above with the next record to be updated, until ** all record selected by the WHERE clause have been updated. */ sqliteVdbeAddOp(v, OP_Goto, 0, addr); sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v)); sqliteVdbeAddOp(v, OP_ListReset, 0, 0); /* Close all tables if there were no FOR EACH ROW triggers */ if( !row_triggers_exist ){ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ if( openAll || aIdxUsed[i] ){ sqliteVdbeAddOp(v, OP_Close, base+i+1, 0); } } sqliteVdbeAddOp(v, OP_Close, base, 0); pParse->nTab = base; }else{ sqliteVdbeAddOp(v, OP_Close, newIdx, 0); sqliteVdbeAddOp(v, OP_Close, oldIdx, 0); } sqliteEndWriteOperation(pParse); /* |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
26 27 28 29 30 31 32 | ** type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** | | | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | ** type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** ** $Id: vdbe.c,v 1.144 2002/05/19 23:43:14 danielk1977 Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** The following global variable is incremented every time a cursor ** moves, either by the OP_MoveTo or the OP_Next opcode. The test |
︙ | ︙ | |||
245 246 247 248 249 250 251 | Mem *aMem; /* The memory locations */ Agg agg; /* Aggregate information */ int nSet; /* Number of sets allocated */ Set *aSet; /* An array of sets */ int nCallback; /* Number of callbacks invoked so far */ int iLimit; /* Limit on the number of callbacks remaining */ int iOffset; /* Offset before beginning to do callbacks */ | < | | | 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 | Mem *aMem; /* The memory locations */ Agg agg; /* Aggregate information */ int nSet; /* Number of sets allocated */ Set *aSet; /* An array of sets */ int nCallback; /* Number of callbacks invoked so far */ int iLimit; /* Limit on the number of callbacks remaining */ int iOffset; /* Offset before beginning to do callbacks */ int keylistStackDepth; /* The size of the "keylist" stack */ Keylist **keylistStack; /* The stack used by opcodes PushList & PopList */ }; /* ** Create a new virtual database engine. */ Vdbe *sqliteVdbeCreate(sqlite *db){ Vdbe *p; |
︙ | ︙ | |||
998 999 1000 1001 1002 1003 1004 | AggReset(&p->agg); for(i=0; i<p->nSet; i++){ sqliteHashClear(&p->aSet[i].hash); } sqliteFree(p->aSet); p->aSet = 0; p->nSet = 0; | | | | 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 | AggReset(&p->agg); for(i=0; i<p->nSet; i++){ sqliteHashClear(&p->aSet[i].hash); } sqliteFree(p->aSet); p->aSet = 0; p->nSet = 0; if( p->keylistStackDepth > 0 ){ int ii; for(ii = 0; ii < p->keylistStackDepth; ii++){ KeylistFree(p->keylistStack[ii]); } sqliteFree(p->keylistStack); p->keylistStackDepth = 0; p->keylistStack = 0; } } |
︙ | ︙ | |||
4573 4574 4575 4576 4577 4578 4579 | */ case OP_PopList: { assert(p->keylistStackDepth > 0); p->keylistStackDepth--; KeylistFree(p->pList); p->pList = p->keylistStack[p->keylistStackDepth]; p->keylistStack[p->keylistStackDepth] = 0; | | | 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 | */ case OP_PopList: { assert(p->keylistStackDepth > 0); p->keylistStackDepth--; KeylistFree(p->pList); p->pList = p->keylistStack[p->keylistStackDepth]; p->keylistStack[p->keylistStackDepth] = 0; if( p->keylistStackDepth == 0 ){ sqliteFree(p->keylistStack); p->keylistStack = 0; } break; } /* Opcode: SetNotFound P1 P2 * |
︙ | ︙ |
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.44 2002/05/19 23:43:14 danielk1977 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. |
︙ | ︙ | |||
212 213 214 215 216 217 218 | memset(aExpr, 0, sizeof(aExpr)); nExpr = exprSplit(ARRAYSIZE(aExpr), aExpr, pWhere); /* Analyze all of the subexpressions. */ for(i=0; i<nExpr; i++){ exprAnalyze(base, &aExpr[i]); | | | | 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | memset(aExpr, 0, sizeof(aExpr)); nExpr = exprSplit(ARRAYSIZE(aExpr), aExpr, pWhere); /* Analyze all of the subexpressions. */ for(i=0; i<nExpr; i++){ exprAnalyze(base, &aExpr[i]); if( pParse->trigStack && pParse->trigStack->newIdx >= 0 ){ aExpr[i].prereqRight = aExpr[i].prereqRight & ~(1 << pParse->trigStack->newIdx - base); aExpr[i].prereqLeft = aExpr[i].prereqLeft & ~(1 << pParse->trigStack->newIdx - base); aExpr[i].prereqAll = aExpr[i].prereqAll & ~(1 << pParse->trigStack->newIdx - base); } if( pParse->trigStack && pParse->trigStack->oldIdx >= 0 ){ aExpr[i].prereqRight = aExpr[i].prereqRight & ~(1 << pParse->trigStack->oldIdx - base); aExpr[i].prereqLeft = aExpr[i].prereqLeft & ~(1 << pParse->trigStack->oldIdx - base); aExpr[i].prereqAll = aExpr[i].prereqAll & ~(1 << pParse->trigStack->oldIdx - base); } |
︙ | ︙ |