Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Modify the code generated for a DELETE to use registers instead of the vdbe stack. (CVS 4675) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
173f281334d340290e1978abea5d1ea8 |
User & Date: | danielk1977 2008-01-04 13:24:29.000 |
Context
2008-01-04
| ||
13:57 | Modify FifoRead and FifoWrite to work exclusively with memory cells. (CVS 4676) (check-in: 2c913908a4 user: danielk1977 tags: trunk) | |
13:24 | Modify the code generated for a DELETE to use registers instead of the vdbe stack. (CVS 4675) (check-in: 173f281334 user: danielk1977 tags: trunk) | |
11:01 | Add OP_MemSet, for setting a memory cell to a string value. (CVS 4674) (check-in: 8bb9f970dd user: danielk1977 tags: trunk) | |
Changes
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.145 2008/01/04 13:24:29 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. |
︙ | ︙ | |||
295 296 297 298 299 300 301 302 303 304 305 306 307 308 | } } } /* The usual case: There is a WHERE clause so we have to scan through ** the table and pick which records to delete. */ else{ /* Begin the database scan */ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0); if( pWInfo==0 ) goto delete_from_cleanup; /* Remember the rowid of every item to be deleted. */ | > > | 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | } } } /* The usual case: There is a WHERE clause so we have to scan through ** the table and pick which records to delete. */ else{ int iRowid = ++pParse->nMem; /* Used for storing value read from fifo */ /* Begin the database scan */ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0); if( pWInfo==0 ) goto delete_from_cleanup; /* Remember the rowid of every item to be deleted. */ |
︙ | ︙ | |||
338 339 340 341 342 343 344 | /* This is the beginning of the delete loop. If a trigger encounters ** an IGNORE constraint, it jumps back to here. */ if( triggers_exist ){ sqlite3VdbeResolveLabel(v, addr); } | | | < < | > > > | | > | | | < < < < | | < | | 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 | /* This is the beginning of the delete loop. If a trigger encounters ** an IGNORE constraint, it jumps back to here. */ if( triggers_exist ){ sqlite3VdbeResolveLabel(v, addr); } addr = sqlite3VdbeAddOp2(v, OP_FifoRead, iRowid, end); sqlite3VdbeAddOp1(v, OP_StackDepth, -1); if( triggers_exist ){ int iData = ++pParse->nMem; /* For storing row data of OLD table */ /* If the record is no longer present in the table, jump to the ** next iteration of the loop through the contents of the fifo. */ sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, iRowid); /* Populate the OLD.* pseudo-table */ if( old_col_mask ){ sqlite3VdbeAddOp3(v, OP_RowData, iCur, 0, iData); }else{ sqlite3VdbeAddOp2(v, OP_MemNull, 0, iData); } sqlite3VdbeAddOp3(v, OP_Insert, oldIdx, iData, iRowid); /* Jump back and run the BEFORE triggers */ sqlite3VdbeAddOp2(v, OP_Goto, 0, iBeginBeforeTrigger); sqlite3VdbeJumpHere(v, iEndBeforeTrigger); } if( !isView ){ /* Delete the row */ #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTab) ){ const char *pVtab = (const char *)pTab->pVtab; pParse->pVirtualLock = pTab; sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVtab, P4_VTAB); }else #endif { sqlite3GenerateRowDelete(db, v, pTab, iCur, iRowid, pParse->nested==0); } } /* If there are row triggers, close all cursors then invoke ** the AFTER triggers */ if( triggers_exist ){ |
︙ | ︙ | |||
432 433 434 435 436 437 438 | ** ** 1. A read/write cursor pointing to pTab, the table containing the row ** to be deleted, must be opened as cursor number "base". ** ** 2. Read/write cursors for all indices of pTab must be open as ** cursor number base+i for the i-th index. ** | | | > | | 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 | ** ** 1. A read/write cursor pointing to pTab, the table containing the row ** to be deleted, must be opened as cursor number "base". ** ** 2. Read/write cursors for all indices of pTab must be open as ** cursor number base+i for the i-th index. ** ** 3. The record number of the row to be deleted must be stored in ** memory cell iRowid. ** ** This routine pops the top of the stack to remove the record number ** and then generates code to remove both the table record and all index ** entries that point to that record. */ void sqlite3GenerateRowDelete( sqlite3 *db, /* The database containing the index */ Vdbe *v, /* Generate code into this VDBE */ Table *pTab, /* Table containing the row to be deleted */ int iCur, /* Cursor number for the table */ int iRowid, /* Memory cell that contains the rowid to delete */ int count /* Increment the row change counter */ ){ int addr; addr = sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowid); sqlite3GenerateRowIndexDelete(v, pTab, iCur, 0); sqlite3VdbeAddOp2(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0)); if( count ){ sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC); } sqlite3VdbeJumpHere(v, addr); } |
︙ | ︙ |
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.209 2008/01/04 13:24:29 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** Set P4 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: |
︙ | ︙ | |||
1172 1173 1174 1175 1176 1177 1178 | case OE_Ignore: { assert( seenReplace==0 ); sqlite3VdbeAddOp2(v, OP_Pop, nCol+extra+3+hasTwoRowids, 0); sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); break; } case OE_Replace: { | > | | 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 | case OE_Ignore: { assert( seenReplace==0 ); sqlite3VdbeAddOp2(v, OP_Pop, nCol+extra+3+hasTwoRowids, 0); sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); break; } case OE_Replace: { int iRowid = sqlite3StackToReg(pParse, 1); sqlite3GenerateRowDelete(pParse->db, v, pTab, base, iRowid, 0); if( isUpdate ){ sqlite3VdbeAddOp2(v, OP_Dup, nCol+extra+1+hasTwoRowids, 1); sqlite3VdbeAddOp2(v, OP_MoveGe, base, 0); } seenReplace = 1; break; } |
︙ | ︙ |
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.637 2008/01/04 13:24:29 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** The macro unlikely() is a hint that surrounds a boolean ** expression that is usually false. Macro likely() surrounds |
︙ | ︙ | |||
1764 1765 1766 1767 1768 1769 1770 | void sqlite3CommitTransaction(Parse*); void sqlite3RollbackTransaction(Parse*); int sqlite3ExprIsConstant(Expr*); int sqlite3ExprIsConstantNotJoin(Expr*); int sqlite3ExprIsConstantOrFunction(Expr*); int sqlite3ExprIsInteger(Expr*, int*); int sqlite3IsRowid(const char*); | | | 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 | void sqlite3CommitTransaction(Parse*); void sqlite3RollbackTransaction(Parse*); int sqlite3ExprIsConstant(Expr*); int sqlite3ExprIsConstantNotJoin(Expr*); int sqlite3ExprIsConstantOrFunction(Expr*); int sqlite3ExprIsInteger(Expr*, int*); int sqlite3IsRowid(const char*); void sqlite3GenerateRowDelete(sqlite3*, Vdbe*, Table*, int, int, int); void sqlite3GenerateRowIndexDelete(Vdbe*, Table*, int, char*); void sqlite3GenerateIndexKey(Vdbe*, Index*, int); void sqlite3GenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int); void sqlite3CompleteInsertion(Parse*, Table*, int, char*, int, int, int, int); void sqlite3OpenTableAndIndices(Parse*, Table*, int, int); void sqlite3BeginWriteOperation(Parse*, int, int); Expr *sqlite3ExprDup(sqlite3*,Expr*); |
︙ | ︙ |
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.675 2008/01/04 13:24:29 danielk1977 Exp $ */ #include "sqliteInt.h" #include <ctype.h> #include "vdbeInt.h" /* ** The following global variable is incremented every time a cursor |
︙ | ︙ | |||
3340 3341 3342 3343 3344 3345 3346 | pTos++; pTos->u.i = v; pTos->flags = MEM_Int; } break; } | | | > | | | > > > > > > > | > | | | > | | > | 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 | pTos++; pTos->u.i = v; pTos->flags = MEM_Int; } break; } /* Opcode: NotExists P1 P2 P3 ** ** Use the top of the stack as a integer key. Or, if P3 is non-zero, ** use the contents of memory cell P3 as an integer key. If a record ** with that key does not exist in table of P1, then jump to P2. ** If the record does exist, then fall thru. The cursor is left ** pointing to the record if it exists. The integer key is popped ** from the stack (unless it was read from a memory cell). ** ** The difference between this operation and NotFound is that this ** operation assumes the key is an integer and that P1 is a table whereas ** NotFound assumes key is a blob constructed from MakeRecord and ** P1 is an index. ** ** See also: Distinct, Found, MoveTo, NotFound, IsUnique */ case OP_NotExists: { /* no-push */ int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; Mem *pKey; if( pOp->p3 ){ assert( pOp->p3<=p->nMem ); pKey = &p->aMem[pOp->p3]; }else{ pKey = pTos; assert( pTos>=p->aStack ); } assert( i>=0 && i<p->nCursor ); assert( p->apCsr[i]!=0 ); if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ int res; u64 iKey; assert( pKey->flags & MEM_Int ); assert( p->apCsr[i]->isTable ); iKey = intToKey(pKey->u.i); rc = sqlite3BtreeMoveto(pCrsr, 0, iKey, 0,&res); pC->lastRowid = pKey->u.i; pC->rowidIsValid = res==0; pC->nullRow = 0; pC->cacheStatus = CACHE_STALE; /* res might be uninitialized if rc!=SQLITE_OK. But if rc!=SQLITE_OK ** processing is about to abort so we really do not care whether or not ** the following jump is taken. (In other words, do not stress over ** the error that valgrind sometimes shows on the next statement when ** running ioerr.test and similar failure-recovery test scripts.) */ if( res!=0 ){ pc = pOp->p2 - 1; pC->rowidIsValid = 0; } } if( pOp->p3==0 ){ Release(pTos); pTos--; } break; } /* Opcode: Sequence P1 * * ** ** Push an integer onto the stack which is the next available ** sequence number for cursor P1. The sequence number on the |
︙ | ︙ | |||
3723 3724 3725 3726 3727 3728 3729 | if( pOp->p1 ){ sqlite3VdbeSetChanges(db, p->nChange); } p->nChange = 0; break; } | | | > | > | | | | | > | > | > > > > | > | | | | | | | | | | | | | | | | 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 | if( pOp->p1 ){ sqlite3VdbeSetChanges(db, p->nChange); } p->nChange = 0; break; } /* Opcode: RowData P1 * P3 ** ** Push onto the stack the complete row data for cursor P1. Or if P3 ** is a positive non-zero integer register number, then the value ** is written into that register. There is no interpretation of the data. ** It is just copied onto the stack or into the memory cell exactly as ** it is found in the database file. ** ** If the cursor is not pointing to a valid row, a NULL value is ** pushed/inserted instead. */ /* Opcode: RowKey P1 * P3 ** ** Push onto the stack the complete row key for cursor P1. Or if P3 ** is a positive non-zero integer register number, then the value ** is written into that register. There is no interpretation of the data. ** It is just copied onto the stack or into the memory cell exactly as ** it is found in the database file. ** ** If the cursor is not pointing to a valid row, a NULL is pushed ** onto the stack. */ case OP_RowKey: case OP_RowData: { int i = pOp->p1; Cursor *pC; u32 n; Mem *pOut; /* Note that RowKey and RowData are really exactly the same instruction */ if( pOp->p3 ){ pOut = &p->aMem[pOp->p3]; }else{ pOut = ++pTos; } assert( i>=0 && i<p->nCursor ); pC = p->apCsr[i]; assert( pC->isTable || pOp->opcode==OP_RowKey ); assert( pC->isIndex || pOp->opcode==OP_RowData ); assert( pC!=0 ); if( pC->nullRow ){ pOut->flags = MEM_Null; }else if( pC->pCursor!=0 ){ BtCursor *pCrsr = pC->pCursor; rc = sqlite3VdbeCursorMoveto(pC); if( rc ) goto abort_due_to_error; if( pC->nullRow ){ pOut->flags = MEM_Null; break; }else if( pC->isIndex ){ i64 n64; assert( !pC->isTable ); sqlite3BtreeKeySize(pCrsr, &n64); if( n64>SQLITE_MAX_LENGTH ){ goto too_big; } n = n64; }else{ sqlite3BtreeDataSize(pCrsr, &n); } if( n>SQLITE_MAX_LENGTH ){ goto too_big; } pOut->n = n; if( n<=NBFS ){ pOut->flags = MEM_Blob | MEM_Short; pOut->z = pOut->zShort; }else{ char *z = sqlite3_malloc( n ); if( z==0 ) goto no_mem; pOut->flags = MEM_Blob | MEM_Dyn; pOut->xDel = 0; pOut->z = z; } if( pC->isIndex ){ rc = sqlite3BtreeKey(pCrsr, 0, n, pOut->z); }else{ rc = sqlite3BtreeData(pCrsr, 0, n, pOut->z); } }else if( pC->pseudoTable ){ pOut->n = pC->nData; assert( pC->nData<=SQLITE_MAX_LENGTH ); pOut->z = pC->pData; pOut->flags = MEM_Blob|MEM_Ephem; }else{ pOut->flags = MEM_Null; } pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */ break; } /* Opcode: Rowid P1 P2 * * * ** ** Store in register P2 an integer which is the key of the table entry that ** P1 is currently point to. If p2==0 then pust the integer. |
︙ | ︙ | |||
4501 4502 4503 4504 4505 4506 4507 | sqlite3_free(aRoot); break; } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ /* Opcode: FifoWrite * * * ** | | < | | > > > | | > > > | | > | | 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 | sqlite3_free(aRoot); break; } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ /* Opcode: FifoWrite * * * ** ** Write the integer on the top of the stack into the Fifo. */ case OP_FifoWrite: { /* no-push */ assert( pTos>=p->aStack ); sqlite3VdbeMemIntegerify(pTos); if( sqlite3VdbeFifoPush(&p->sFifo, pTos->u.i)==SQLITE_NOMEM ){ goto no_mem; } assert( (pTos->flags & MEM_Dyn)==0 ); pTos--; break; } /* Opcode: FifoRead P1 P2 * ** ** Attempt to read a single integer from the Fifo. If P1 is zero, ** push the result onto the stack. Otherwise, store the read integer ** in register P1. ** ** If the Fifo is empty do not push an entry onto the stack or set ** a memory register but instead jump to P2. */ case OP_FifoRead: { i64 v; CHECK_FOR_INTERRUPT; if( sqlite3VdbeFifoPop(&p->sFifo, &v)==SQLITE_DONE ){ pc = pOp->p2 - 1; }else{ Mem *pOut; if( pOp->p1 ){ pOut = &p->aMem[pOp->p1]; }else{ pOut = ++pTos; } sqlite3VdbeMemSetInt64(pOut, v); } break; } #ifndef SQLITE_OMIT_TRIGGER /* Opcode: ContextPush * * * ** |
︙ | ︙ |