Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Registerify the AUTOINCREMENT processing and the OP_IsNull and OP_NotNull operators. (CVS 4692) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
aa48867cfa04da265b906e5b583bc7ac |
User & Date: | drh 2008-01-07 19:20:25.000 |
Context
2008-01-08
| ||
02:57 | Progress toward registerification of the constraint checking logic for INSERT and UPDATE. (CVS 4693) (check-in: b9bf509e39 user: drh tags: trunk) | |
2008-01-07
| ||
19:20 | Registerify the AUTOINCREMENT processing and the OP_IsNull and OP_NotNull operators. (CVS 4692) (check-in: aa48867cfa user: drh tags: trunk) | |
10:16 | Comment changes in select.c. (CVS 4691) (check-in: 38020592f1 user: danielk1977 tags: trunk) | |
Changes
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.336 2008/01/07 19:20:25 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** Return the 'affinity' of the expression pExpr if any. ** |
︙ | ︙ | |||
2130 2131 2132 2133 2134 2135 2136 | sqlite3ExprCode(pParse, pExpr->pLeft, 0); sqlite3VdbeAddOp0(v, op); stackChng = 0; break; } case TK_ISNULL: case TK_NOTNULL: { | | < | > | 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 | sqlite3ExprCode(pParse, pExpr->pLeft, 0); sqlite3VdbeAddOp0(v, op); stackChng = 0; break; } case TK_ISNULL: case TK_NOTNULL: { int addr; assert( TK_ISNULL==OP_IsNull ); assert( TK_NOTNULL==OP_NotNull ); sqlite3VdbeAddOp2(v, OP_Integer, 1, target); sqlite3ExprCode(pParse, pExpr->pLeft, 0); addr = sqlite3VdbeAddOp0(v, op); sqlite3VdbeAddOp2(v, OP_AddImm, target, -1); sqlite3VdbeJumpHere(v, addr); stackChng = 0; inReg = target; break; } case TK_AGG_FUNCTION: { AggInfo *pInfo = pExpr->pAggInfo; if( pInfo==0 ){ |
︙ | ︙ | |||
2218 2219 2220 2221 2222 2223 2224 | } inReg = pExpr->iColumn; /* sqlite3VdbeAddOp1(v, OP_SCopy, pExpr->iColumn); VdbeComment((v, "load subquery result")); */ break; } case TK_IN: { | | < | | | > < | | | > > | < | | | | | 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 | } inReg = pExpr->iColumn; /* sqlite3VdbeAddOp1(v, OP_SCopy, pExpr->iColumn); VdbeComment((v, "load subquery result")); */ break; } case TK_IN: { int j1, j2, j3, j4, j5; char affinity; int ckOffset = pParse->ckOffset; int eType; eType = sqlite3FindInIndex(pParse, pExpr, 0); /* Figure out the affinity to use to create a key from the results ** of the expression. affinityStr stores a static string suitable for ** P4 of OP_MakeRecord. */ affinity = comparisonAffinity(pExpr); sqlite3VdbeAddOp1(v, OP_Integer, 1); pParse->ckOffset = (ckOffset ? (ckOffset+1) : 0); /* Code the <expr> from "<expr> IN (...)". The temporary table ** pExpr->iTable contains the values that make up the (...) set. */ sqlite3ExprCode(pParse, pExpr->pLeft, 0); sqlite3VdbeAddOp0(v, OP_SCopy); j1 = sqlite3VdbeAddOp0(v, OP_NotNull); sqlite3VdbeAddOp1(v, OP_Pop, 2); sqlite3VdbeAddOp0(v, OP_Null); j2 = sqlite3VdbeAddOp0(v, OP_Goto); sqlite3VdbeJumpHere(v, j1); if( eType==IN_INDEX_ROWID ){ j3 = sqlite3VdbeAddOp1(v, OP_MustBeInt, 1); j4 = sqlite3VdbeAddOp1(v, OP_NotExists, pExpr->iTable); j5 = sqlite3VdbeAddOp0(v, OP_Goto); sqlite3VdbeJumpHere(v, j3); sqlite3VdbeJumpHere(v, j4); }else{ sqlite3VdbeAddOp4(v, OP_MakeRecord, 1, 0, 0, &affinity, 1); j5 = sqlite3VdbeAddOp1(v, OP_Found, pExpr->iTable); } sqlite3VdbeAddOp2(v, OP_AddImm, 0, -1); sqlite3VdbeJumpHere(v, j2); sqlite3VdbeJumpHere(v, j5); break; } #endif case TK_BETWEEN: { Expr *pLeft = pExpr->pLeft; struct ExprList_item *pLItem = pExpr->pList->a; Expr *pRight = pLItem->pExpr; |
︙ | ︙ | |||
2481 2482 2483 2484 2485 2486 2487 | break; } case TK_ISNULL: case TK_NOTNULL: { assert( TK_ISNULL==OP_IsNull ); assert( TK_NOTNULL==OP_NotNull ); sqlite3ExprCode(pParse, pExpr->pLeft, 0); | | | 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 | break; } case TK_ISNULL: case TK_NOTNULL: { assert( TK_ISNULL==OP_IsNull ); assert( TK_NOTNULL==OP_NotNull ); sqlite3ExprCode(pParse, pExpr->pLeft, 0); sqlite3VdbeAddOp2(v, op, 0, dest); break; } case TK_BETWEEN: { /* The expression "x BETWEEN y AND z" is implemented as: ** ** 1 IF (x < y) GOTO 3 ** 2 IF (x <= z) GOTO <dest> |
︙ | ︙ | |||
2593 2594 2595 2596 2597 2598 2599 | sqlite3ExprCode(pParse, pExpr->pRight, 0); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, dest, jumpIfNull); break; } case TK_ISNULL: case TK_NOTNULL: { sqlite3ExprCode(pParse, pExpr->pLeft, 0); | | | 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 | sqlite3ExprCode(pParse, pExpr->pRight, 0); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, dest, jumpIfNull); break; } case TK_ISNULL: case TK_NOTNULL: { sqlite3ExprCode(pParse, pExpr->pLeft, 0); sqlite3VdbeAddOp2(v, op, 0, dest); break; } case TK_BETWEEN: { /* The expression is "x BETWEEN y AND z". It is implemented as: ** ** 1 IF (x >= y) GOTO 3 ** 2 GOTO <dest> |
︙ | ︙ |
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.215 2008/01/07 19:20:25 drh 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: |
︙ | ︙ | |||
134 135 136 137 138 139 140 | return 0; } #ifndef SQLITE_OMIT_AUTOINCREMENT /* ** Write out code to initialize the autoincrement logic. This code ** looks up the current autoincrement value in the sqlite_sequence | | | | > > | | > | | | | | > | | | < | < | | | | | | > < | < | | | | | | | | 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 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 | return 0; } #ifndef SQLITE_OMIT_AUTOINCREMENT /* ** Write out code to initialize the autoincrement logic. This code ** looks up the current autoincrement value in the sqlite_sequence ** table and stores that value in a register. Code generated by ** autoIncStep() will keep that register holding the largest ** rowid value. Code generated by autoIncEnd() will write the new ** largest value of the counter back into the sqlite_sequence table. ** ** This routine returns the index of the mem[] cell that contains ** the maximum rowid counter. ** ** Three consecutive registers are allocated by this routine. The ** first two hold the name of the target table and the maximum rowid ** inserted into the target table, respectively. ** The third holds the rowid in sqlite_sequence where we will ** write back the revised maximum rowid. This routine returns the ** index of the second of these three registers. */ static int autoIncBegin( Parse *pParse, /* Parsing context */ int iDb, /* Index of the database holding pTab */ Table *pTab /* The table we are writing to */ ){ int memId = 0; /* Register holding maximum rowid */ if( pTab->autoInc ){ Vdbe *v = pParse->pVdbe; Db *pDb = &pParse->db->aDb[iDb]; int iCur = pParse->nTab; int addr; /* Address of the top of the loop */ assert( v ); pParse->nMem++; /* Holds name of table */ memId = ++pParse->nMem; pParse->nMem++; sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenRead); addr = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp2(v, OP_Rewind, iCur, addr+8); sqlite3VdbeAddOp2(v, OP_Column, iCur, 0); sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, pTab->zName, 0); sqlite3VdbeAddOp2(v, OP_Ne, 0x100, addr+7); sqlite3VdbeAddOp2(v, OP_Rowid, iCur, memId+1); sqlite3VdbeAddOp3(v, OP_Column, iCur, 1, memId); sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+8); sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+1); sqlite3VdbeAddOp2(v, OP_Close, iCur, 0); } return memId; } /* ** Update the maximum rowid for an autoincrement calculation. ** ** This routine should be called when the top of the stack holds a ** new rowid that is about to be inserted. If that new rowid is ** larger than the maximum rowid in the memId memory cell, then the ** memory cell is updated. The stack is unchanged. */ static void autoIncStep(Parse *pParse, int memId, int regRowid){ if( memId>0 ){ sqlite3VdbeAddOp2(pParse->pVdbe, OP_MemMax, memId, regRowid); } } /* ** After doing one or more inserts, the maximum rowid is stored ** in reg[memId]. Generate code to write this value back into the ** the sqlite_sequence table. */ static void autoIncEnd( Parse *pParse, /* The parsing context */ int iDb, /* Index of the database holding pTab */ Table *pTab, /* Table we are inserting into */ int memId /* Memory cell holding the maximum rowid */ ){ if( pTab->autoInc ){ int iCur = pParse->nTab; Vdbe *v = pParse->pVdbe; Db *pDb = &pParse->db->aDb[iDb]; int j1; assert( v ); sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); sqlite3VdbeAddOp2(v, OP_NewRowid, iCur, memId+1); sqlite3VdbeJumpHere(v, j1); sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, pTab->zName, 0); sqlite3VdbeAddOp3(v, OP_RegMakeRec, memId-1, 2, memId-1); sqlite3VdbeAddOp3(v, OP_Insert, iCur, memId-1, memId+1); sqlite3VdbeChangeP5(v, -1, OPFLAG_APPEND); sqlite3VdbeAddOp1(v, OP_Close, iCur); } } #else /* ** If SQLITE_OMIT_AUTOINCREMENT is defined, then the three routines ** above are all no-ops */ |
︙ | ︙ | |||
337 338 339 340 341 342 343 | Parse *pParse, /* Parser context */ SrcList *pTabList, /* Name of table into which we are inserting */ ExprList *pList, /* List of values to be inserted */ Select *pSelect, /* A SELECT statement to use as the data source */ IdList *pColumn, /* Column names corresponding to IDLIST. */ int onError /* How to handle constraint errors */ ){ | > | > < < > < < | > < | > > > > > > > > < | 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 | Parse *pParse, /* Parser context */ SrcList *pTabList, /* Name of table into which we are inserting */ ExprList *pList, /* List of values to be inserted */ Select *pSelect, /* A SELECT statement to use as the data source */ IdList *pColumn, /* Column names corresponding to IDLIST. */ int onError /* How to handle constraint errors */ ){ sqlite3 *db; /* The main database structure */ Table *pTab; /* The table to insert into. aka TABLE */ char *zTab; /* Name of the table into which we are inserting */ const char *zDb; /* Name of the database holding this table */ int i, j, idx; /* Loop counters */ Vdbe *v; /* Generate code into this virtual machine */ Index *pIdx; /* For looping over indices of the table */ int nColumn; /* Number of columns in the data */ int nHidden = 0; /* Number of hidden columns if TABLE is virtual */ int base = 0; /* VDBE Cursor number for pTab */ int keyColumn = -1; /* Column that is the INTEGER PRIMARY KEY */ int endOfLoop; /* Label for the end of the insertion loop */ int useTempTable = 0; /* Store SELECT results in intermediate table */ int srcTab = 0; /* Data comes from this temporary cursor if >=0 */ int iCont=0,iBreak=0; /* Beginning and end of the loop over srcTab */ int iSelectLoop = 0; /* Address of code that implements the SELECT */ int iCleanup = 0; /* Address of the cleanup code */ int iInsertBlock = 0; /* Address of the subroutine used to insert data */ int newIdx = -1; /* Cursor for the NEW pseudo-table */ int iDb; /* Index of database holding TABLE */ Db *pDb; /* The database containing table being inserted into */ int appendFlag = 0; /* True if the insert is likely to be an append */ /* Register allocations */ int regFromSelect; /* Base register for data coming from SELECT */ int regAutoinc = 0; /* Register holding the AUTOINCREMENT counter */ int regRowCount = 0; /* Memory cell used for the row counter */ int regIns; /* Block of regs holding rowid+data being inserted */ int regRowid; /* registers holding insert rowid */ int regData; /* register holding first column to insert */ int regRecord; /* Holds the assemblied row record */ #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to insert into a view */ int triggers_exist = 0; /* True if there are FOR EACH ROW triggers */ #endif db = pParse->db; |
︙ | ︙ | |||
451 452 453 454 455 456 457 | assert( !triggers_exist ); assert( pList==0 ); goto insert_cleanup; } #endif /* SQLITE_OMIT_XFER_OPT */ /* If this is an AUTOINCREMENT table, look up the sequence number in the | | < < | | 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 | assert( !triggers_exist ); assert( pList==0 ); goto insert_cleanup; } #endif /* SQLITE_OMIT_XFER_OPT */ /* If this is an AUTOINCREMENT table, look up the sequence number in the ** sqlite_sequence table and store it in memory cell regAutoinc. */ regAutoinc = autoIncBegin(pParse, iDb, pTab); /* Figure out how many columns of data are supplied. If the data ** is coming from a SELECT statement, then this step also generates ** all the code to implement the SELECT statement and invoke a subroutine ** to process each row of the result. (Template 2.) If the SELECT ** statement uses the the table that is being inserted into, then the ** subroutine is also coded here. That subroutine stores the SELECT |
︙ | ︙ | |||
482 483 484 485 486 487 488 | /* Resolve the expressions in the SELECT statement and execute it. */ rc = sqlite3Select(pParse, pSelect, &dest, 0, 0, 0, 0); if( rc || pParse->nErr || db->mallocFailed ){ goto insert_cleanup; } | | | 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 | /* Resolve the expressions in the SELECT statement and execute it. */ rc = sqlite3Select(pParse, pSelect, &dest, 0, 0, 0, 0); if( rc || pParse->nErr || db->mallocFailed ){ goto insert_cleanup; } regFromSelect = dest.iMem; iCleanup = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp2(v, OP_Goto, 0, iCleanup); assert( pSelect->pEList ); nColumn = pSelect->pEList->nExpr; /* Set useTempTable to TRUE if the result of the SELECT statement ** should be written into a temporary table. Set to FALSE if each |
︙ | ︙ | |||
506 507 508 509 510 511 512 | if( useTempTable ){ /* Generate the subroutine that SELECT calls to process each row of ** the result. Store the result in a temporary table */ srcTab = pParse->nTab++; sqlite3VdbeResolveLabel(v, iInsertBlock); | | | 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 | if( useTempTable ){ /* Generate the subroutine that SELECT calls to process each row of ** the result. Store the result in a temporary table */ srcTab = pParse->nTab++; sqlite3VdbeResolveLabel(v, iInsertBlock); sqlite3VdbeAddOp2(v, OP_RegMakeRec, regFromSelect, nColumn); sqlite3VdbeAddOp1(v, OP_NewRowid, srcTab); sqlite3VdbeAddOp2(v, OP_Pull, 1, 0); sqlite3CodeInsert(pParse, srcTab, OPFLAG_APPEND); sqlite3VdbeAddOp2(v, OP_Return, 0, 0); /* The following code runs first because the GOTO at the very top ** of the program jumps to it. Create the temporary table, then jump |
︙ | ︙ | |||
616 617 618 619 620 621 622 | sqlite3VdbeAddOp2(v, OP_OpenPseudo, newIdx, 0); sqlite3VdbeAddOp2(v, OP_SetNumColumns, newIdx, pTab->nCol); } /* Initialize the count of rows to be inserted */ if( db->flags & SQLITE_CountRows ){ | | | | > > > > > > > > > > > > > | > | | > | | 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 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 696 697 | sqlite3VdbeAddOp2(v, OP_OpenPseudo, newIdx, 0); sqlite3VdbeAddOp2(v, OP_SetNumColumns, newIdx, pTab->nCol); } /* Initialize the count of rows to be inserted */ if( db->flags & SQLITE_CountRows ){ regRowCount = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); } /* If this is not a view, open the table and and all indices */ if( !isView ){ base = pParse->nTab; sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite); } /* If the data source is a temporary table, then we have to create ** a loop because there might be multiple rows of data. If the data ** source is a subroutine call from the SELECT statement, then we need ** to launch the SELECT statement processing. */ if( useTempTable ){ iBreak = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp2(v, OP_Rewind, srcTab, iBreak); iCont = sqlite3VdbeCurrentAddr(v); }else if( pSelect ){ sqlite3VdbeAddOp2(v, OP_Goto, 0, iSelectLoop); sqlite3VdbeResolveLabel(v, iInsertBlock); sqlite3RegToStack(pParse, regFromSelect, nColumn); sqlite3VdbeAddOp2(v, OP_StackDepth, -1, 0); } /* Allocate registers for holding the rowid of the new row, ** the content of the new row, and the assemblied row record. */ regRecord = ++pParse->nMem; regRowid = regIns = pParse->nMem+1; pParse->nMem += pTab->nCol + 1; if( IsVirtual(pTab) ){ regRowid++; pParse->nMem++; } regData = regRowid+1; /* Run the BEFORE and INSTEAD OF triggers, if there are any */ endOfLoop = sqlite3VdbeMakeLabel(v); if( triggers_exist & TRIGGER_BEFORE ){ /* build the NEW.* reference row. Note that if there is an INTEGER ** PRIMARY KEY into which a NULL is being inserted, that NULL will be ** translated into a unique ID for the row. But on a BEFORE trigger, ** we do not know what the unique ID will be (because the insert has ** not happened yet) so we substitute a rowid of -1 */ if( keyColumn<0 ){ sqlite3VdbeAddOp2(v, OP_Integer, -1, 0); }else if( useTempTable ){ sqlite3VdbeAddOp2(v, OP_Column, srcTab, keyColumn); }else{ int j1; assert( pSelect==0 ); /* Otherwise useTempTable is true */ sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, 0); sqlite3VdbeAddOp0(v, OP_SCopy); j1 = sqlite3VdbeAddOp0(v, OP_NotNull); sqlite3VdbeAddOp1(v, OP_Pop, 1); sqlite3VdbeAddOp1(v, OP_Integer, -1); sqlite3VdbeJumpHere(v, j1); sqlite3VdbeAddOp0(v, OP_MustBeInt); } /* Cannot have triggers on a virtual table. If it were possible, ** this block would have to account for hidden column. */ assert(!IsVirtual(pTab)); |
︙ | ︙ | |||
715 716 717 718 719 720 721 | /* Push the record number for the new entry onto the stack. The ** record number is a randomly generate integer created by NewRowid ** except when the table has an INTEGER PRIMARY KEY column, in which ** case the record number is the same as that column. */ if( !isView ){ | < < < < | | | | | | | | | | | | | | 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 | /* Push the record number for the new entry onto the stack. The ** record number is a randomly generate integer created by NewRowid ** except when the table has an INTEGER PRIMARY KEY column, in which ** case the record number is the same as that column. */ if( !isView ){ if( IsVirtual(pTab) ){ /* The row that the VUpdate opcode will delete: none */ sqlite3VdbeAddOp2(v, OP_Null, 0, regIns); } if( keyColumn>=0 ){ if( useTempTable ){ sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regRowid); }else if( pSelect ){ sqlite3VdbeAddOp2(v, OP_SCopy, -(nColumn - keyColumn - 1), regRowid); }else{ VdbeOp *pOp; sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, 0); pOp = sqlite3VdbeGetOp(v, sqlite3VdbeCurrentAddr(v) - 1); if( pOp && pOp->opcode==OP_Null ){ appendFlag = 1; pOp->opcode = OP_NewRowid; pOp->p1 = base; pOp->p2 = regRowid; pOp->p3 = regAutoinc; }else{ /* TODO: Avoid this use of the stack. */ sqlite3VdbeAddOp2(v, OP_Move, 0, regRowid); } } /* If the PRIMARY KEY expression is NULL, then use OP_NewRowid ** to generate a unique primary key value. */ if( !appendFlag ){ sqlite3VdbeAddOp2(v, OP_IfMemNull, regRowid, sqlite3VdbeCurrentAddr(v)+2); sqlite3VdbeAddOp2(v, OP_Goto, -1, sqlite3VdbeCurrentAddr(v)+2); sqlite3VdbeAddOp3(v, OP_NewRowid, base, regRowid, regAutoinc); sqlite3VdbeAddOp3(v, OP_MustBeInt, 0, 0, regRowid); } }else if( IsVirtual(pTab) ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regRowid); }else{ sqlite3VdbeAddOp3(v, OP_NewRowid, base, regRowid, regAutoinc); appendFlag = 1; } autoIncStep(pParse, regAutoinc, regRowid); /* Push onto the stack, data for all columns of the new entry, beginning ** with the first column. */ nHidden = 0; for(i=0; i<pTab->nCol; i++){ int iRegStore = regRowid+1+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. */ sqlite3VdbeAddOp2(v, OP_Null, 0, iRegStore); continue; |
︙ | ︙ | |||
804 805 806 807 808 809 810 | /* Generate code to check constraints and generate index keys and ** do the insertion. */ #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTab) ){ pParse->pVirtualLock = pTab; | | | | | 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 | /* Generate code to check constraints and generate index keys and ** do the insertion. */ #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTab) ){ pParse->pVirtualLock = pTab; sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, (const char*)pTab->pVtab, P4_VTAB); }else #endif { sqlite3RegToStack(pParse, regIns, pTab->nCol+1); sqlite3GenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0, 0, onError, endOfLoop); sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0, (triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1, appendFlag); } } /* Update the count of rows that are inserted */ if( (db->flags & SQLITE_CountRows)!=0 ){ sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); } if( triggers_exist ){ /* Code AFTER triggers */ if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_AFTER, pTab, newIdx, -1, onError, endOfLoop, 0, 0) ){ goto insert_cleanup; |
︙ | ︙ | |||
854 855 856 857 858 859 860 | sqlite3VdbeAddOp2(v, OP_Close, base, 0); for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){ sqlite3VdbeAddOp2(v, OP_Close, idx+base, 0); } } /* Update the sqlite_sequence table by storing the content of the | | | | | | | 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 | sqlite3VdbeAddOp2(v, OP_Close, base, 0); for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){ sqlite3VdbeAddOp2(v, OP_Close, idx+base, 0); } } /* Update the sqlite_sequence table by storing the content of the ** counter value in memory regAutoinc back into the sqlite_sequence ** table. */ autoIncEnd(pParse, iDb, pTab, regAutoinc); /* ** Return the number of rows inserted. If this routine is ** generating code because of a call to sqlite3NestedParse(), do not ** invoke the callback function. */ if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){ sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1); sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", P4_STATIC); } insert_cleanup: sqlite3SrcListDelete(pTabList); sqlite3ExprListDelete(pList); sqlite3SelectDelete(pSelect); sqlite3IdListDelete(pColumn); } /* ** Generate code to do constraint checks prior to an INSERT or an UPDATE. ** ** When this routine is called, the stack contains (from bottom to top) ** the following values: ** ** 1. The rowid of the row to be updated before the update. This ** value is omitted unless we are doing an UPDATE that involves a ** change to the record number. (Or writing to a virtual table.) ** ** 2. The rowid of the row after the update. ** ** 3. The data in the first column of the entry after the update. ** ** i. Data from middle columns... ** |
︙ | ︙ | |||
1000 1001 1002 1003 1004 1005 1006 | }else if( onError==OE_Default ){ onError = OE_Abort; } if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){ onError = OE_Abort; } sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol-1-i)); | | | 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 | }else if( onError==OE_Default ){ onError = OE_Abort; } if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){ onError = OE_Abort; } sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol-1-i)); addr = sqlite3VdbeAddOp0(v, OP_NotNull); assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail || onError==OE_Ignore || onError==OE_Replace ); switch( onError ){ case OE_Rollback: case OE_Abort: case OE_Fail: { char *zMsg = 0; |
︙ | ︙ | |||
1409 1410 1411 1412 1413 1414 1415 | int iDbSrc; /* The database of pSrc */ int iSrc, iDest; /* Cursors from source and destination */ int addr1, addr2; /* Loop addresses */ int emptyDestTest; /* Address of test for empty pDest */ int emptySrcTest; /* Address of test for empty pSrc */ Vdbe *v; /* The VDBE we are building */ KeyInfo *pKey; /* Key information for an index */ | | | 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 | int iDbSrc; /* The database of pSrc */ int iSrc, iDest; /* Cursors from source and destination */ int addr1, addr2; /* Loop addresses */ int emptyDestTest; /* Address of test for empty pDest */ int emptySrcTest; /* Address of test for empty pSrc */ Vdbe *v; /* The VDBE we are building */ KeyInfo *pKey; /* Key information for an index */ int regAutoinc; /* Memory register used by AUTOINC */ int destHasUniqueIdx = 0; /* True if pDest has a UNIQUE index */ if( pSelect==0 ){ return 0; /* Must be of the form INSERT INTO ... SELECT ... */ } if( pDest->pTrigger ){ return 0; /* tab1 must not have triggers */ |
︙ | ︙ | |||
1537 1538 1539 1540 1541 1542 1543 | sqlite3_xferopt_count++; #endif iDbSrc = sqlite3SchemaToIndex(pParse->db, pSrc->pSchema); v = sqlite3GetVdbe(pParse); sqlite3CodeVerifySchema(pParse, iDbSrc); iSrc = pParse->nTab++; iDest = pParse->nTab++; | | | 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 | sqlite3_xferopt_count++; #endif iDbSrc = sqlite3SchemaToIndex(pParse->db, pSrc->pSchema); v = sqlite3GetVdbe(pParse); sqlite3CodeVerifySchema(pParse, iDbSrc); iSrc = pParse->nTab++; iDest = pParse->nTab++; regAutoinc = autoIncBegin(pParse, iDbDest, pDest); sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite); if( (pDest->iPKey<0 && pDest->pIndex!=0) || destHasUniqueIdx ){ /* If tables do not have an INTEGER PRIMARY KEY and there ** are indices to be copied and the destination is not empty, ** we have to disallow the transfer optimization because the ** the rowids might change which will mess up indexing. ** |
︙ | ︙ | |||
1565 1566 1567 1568 1569 1570 1571 | if( pDest->iPKey>=0 ){ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, 0); sqlite3VdbeAddOp0(v, OP_Copy); addr2 = sqlite3VdbeAddOp2(v, OP_NotExists, iDest, 0); sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, "PRIMARY KEY must be unique", P4_STATIC); sqlite3VdbeJumpHere(v, addr2); | | | | 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 | if( pDest->iPKey>=0 ){ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, 0); sqlite3VdbeAddOp0(v, OP_Copy); addr2 = sqlite3VdbeAddOp2(v, OP_NotExists, iDest, 0); sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, "PRIMARY KEY must be unique", P4_STATIC); sqlite3VdbeJumpHere(v, addr2); autoIncStep(pParse, regAutoinc, 0); }else if( pDest->pIndex==0 ){ addr1 = sqlite3VdbeAddOp1(v, OP_NewRowid, iDest); }else{ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, 0); assert( pDest->autoInc==0 ); } sqlite3VdbeAddOp2(v, OP_RowData, iSrc, 0); sqlite3CodeInsert(pParse,iDest,OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND); sqlite3VdbeChangeP4(v, -1, pDest->zName, 0); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); autoIncEnd(pParse, iDbDest, pDest, regAutoinc); for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){ if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; } assert( pSrcIdx ); sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); |
︙ | ︙ |
Changes to src/pragma.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2003 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. ** ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2003 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. ** ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** ** $Id: pragma.c,v 1.162 2008/01/07 19:20:25 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* Ignore this whole file if pragmas are disabled */ #if !defined(SQLITE_OMIT_PRAGMA) && !defined(SQLITE_OMIT_PARSER) |
︙ | ︙ | |||
878 879 880 881 882 883 884 | for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ sqlite3VdbeAddOp2(v, OP_Integer, pIdx->tnum, 0); cnt++; } } if( cnt==0 ) continue; sqlite3VdbeAddOp2(v, OP_IntegrityCk, 1, i); | | | 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 | for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ sqlite3VdbeAddOp2(v, OP_Integer, pIdx->tnum, 0); cnt++; } } if( cnt==0 ) continue; sqlite3VdbeAddOp2(v, OP_IntegrityCk, 1, i); addr = sqlite3VdbeAddOp2(v, OP_StackIsNull, -1, 0); sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName), P4_DYNAMIC); sqlite3VdbeAddOp2(v, OP_Pull, 1, 0); sqlite3VdbeAddOp0(v, OP_Concat); sqlite3VdbeAddOp2(v, OP_Callback, 1, 0); sqlite3VdbeJumpHere(v, addr); |
︙ | ︙ |
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.392 2008/01/07 19:20:25 drh Exp $ */ #include "sqliteInt.h" /* ** Delete all the content of a Select structure but do not deallocate ** the select structure itself. |
︙ | ︙ | |||
805 806 807 808 809 810 811 812 | sqlite3VdbeAddOp1(v, OP_NewRowid, iParm); sqlite3VdbeAddOp2(v, OP_Pull, 1, 0); sqlite3CodeInsert(pParse, iParm, OPFLAG_APPEND); break; } #ifndef SQLITE_OMIT_SUBQUERY case SRT_Set: { assert( nColumn==1 ); | > | > | | > > | 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 | sqlite3VdbeAddOp1(v, OP_NewRowid, iParm); sqlite3VdbeAddOp2(v, OP_Pull, 1, 0); sqlite3CodeInsert(pParse, iParm, OPFLAG_APPEND); break; } #ifndef SQLITE_OMIT_SUBQUERY case SRT_Set: { int j1, j2; assert( nColumn==1 ); sqlite3VdbeAddOp0(v, OP_SCopy); j1 = sqlite3VdbeAddOp0(v, OP_NotNull); sqlite3VdbeAddOp1(v, OP_Pop, 1); j2 = sqlite3VdbeAddOp0(v, OP_Goto); sqlite3VdbeJumpHere(v, j1); sqlite3VdbeAddOp4(v, OP_MakeRecord, 1, 0, 0, &p->affinity, 1); sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, 0); sqlite3VdbeJumpHere(v, j2); break; } case SRT_Mem: { assert( nColumn==1 ); sqlite3VdbeAddOp2(v, OP_Move, 0, iParm); /* The LIMIT clause will terminate the loop for us */ break; |
︙ | ︙ |
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.687 2008/01/07 19:20:25 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> #include "vdbeInt.h" /* ** The following global variable is incremented every time a cursor |
︙ | ︙ | |||
2106 2107 2108 2109 2110 2111 2112 | } Release(pTos); pTos--; if( c ) pc = pOp->p2-1; break; } | | | | | | > > | < < < | | < < < < | > > | < < | < < < < | | < > | 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 | } Release(pTos); pTos--; if( c ) pc = pOp->p2-1; break; } /* Opcode: StackIsNull P1 P2 * ** ** Check the top of the stack and jump to P2 if the top of the stack ** is NULL. If P1 is positive, then pop P1 elements from the stack ** regardless of whether or not the jump is taken. If P1 is negative, ** pop -P1 elements from the stack only if the jump is taken and leave ** the stack unchanged if the jump is not taken. */ case OP_StackIsNull: { /* no-push, jump */ if( pTos->flags & MEM_Null ){ pc = pOp->p2-1; if( pOp->p1<0 ){ popStack(&pTos, -pOp->p1); } } if( pOp->p1>0 ){ popStack(&pTos, pOp->p1); } break; } /* Opcode: IsNull P1 P2 * ** ** Jump to P2 if the value in register P1 is NULL. ** ** If P1 is 0 then use the top of the stack instead of a register ** and pop the stack regardless of whether or not the jump is taken. */ case OP_IsNull: { /* same as TK_ISNULL, no-push, jump, in1 */ if( (pIn1->flags & MEM_Null)!=0 ){ pc = pOp->p2 - 1; } break; } /* Opcode: NotNull P1 P2 * ** ** Jump to P2 if the value in register P1 is not NULL. ** ** If P1 is 0 then use the top of the stack instead of a register ** and pop the stack regardless of whether or not the jump is taken. */ case OP_NotNull: { /* same as TK_NOTNULL, no-push, jump, in1 */ if( (pIn1->flags & MEM_Null)==0 ){ pc = pOp->p2 - 1; } break; } /* Opcode: SetNumColumns P1 P2 * ** ** Before the OP_Column opcode can be executed on a cursor, this ** opcode must be called to set the number of fields in the table. |
︙ | ︙ |
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.277 2008/01/07 19:20:25 drh Exp $ */ #include "sqliteInt.h" /* ** The number of bits in a Bitmask. "BMS" means "BitMask Size". */ #define BMS (sizeof(Bitmask)*8) |
︙ | ︙ | |||
1753 1754 1755 1756 1757 1758 1759 | sizeof(pLevel->aInLoop[0])*pLevel->nIn); pIn = pLevel->aInLoop; if( pIn ){ int op = ((eType==IN_INDEX_ROWID)?OP_Rowid:OP_Column); pIn += pLevel->nIn - 1; pIn->iCur = iTab; pIn->topAddr = sqlite3VdbeAddOp2(v, op, iTab, 0); | | | 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 | sizeof(pLevel->aInLoop[0])*pLevel->nIn); pIn = pLevel->aInLoop; if( pIn ){ int op = ((eType==IN_INDEX_ROWID)?OP_Rowid:OP_Column); pIn += pLevel->nIn - 1; pIn->iCur = iTab; pIn->topAddr = sqlite3VdbeAddOp2(v, op, iTab, 0); sqlite3VdbeAddOp2(v, OP_StackIsNull, -1, 0); }else{ pLevel->nIn = 0; } #endif } disableTerm(pLevel, pTerm); } |
︙ | ︙ | |||
1820 1821 1822 1823 1824 1825 1826 | for(j=0; j<nEq; j++){ int k = pIdx->aiColumn[j]; pTerm = findTerm(pWC, iCur, k, notReady, pLevel->flags, pIdx); if( pTerm==0 ) break; assert( (pTerm->flags & TERM_CODED)==0 ); codeEqualityTerm(pParse, pTerm, pLevel); if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){ | | | 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 | for(j=0; j<nEq; j++){ int k = pIdx->aiColumn[j]; pTerm = findTerm(pWC, iCur, k, notReady, pLevel->flags, pIdx); if( pTerm==0 ) break; assert( (pTerm->flags & TERM_CODED)==0 ); codeEqualityTerm(pParse, pTerm, pLevel); if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){ sqlite3VdbeAddOp2(v, OP_StackIsNull, termsInMem ? -1 : -(j+1), pLevel->brk); } if( termsInMem ){ sqlite3VdbeAddOp2(v, OP_Move, 0, pLevel->iMem+j+1); } } /* Make sure all the constraint values are on the top of the stack |
︙ | ︙ | |||
2463 2464 2465 2466 2467 2468 2469 | Expr *pX; int k = pIdx->aiColumn[j]; pTerm = findTerm(&wc, iCur, k, notReady, topOp, pIdx); assert( pTerm!=0 ); pX = pTerm->pExpr; assert( (pTerm->flags & TERM_CODED)==0 ); sqlite3ExprCode(pParse, pX->pRight, 0); | | | 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 | Expr *pX; int k = pIdx->aiColumn[j]; pTerm = findTerm(&wc, iCur, k, notReady, topOp, pIdx); assert( pTerm!=0 ); pX = pTerm->pExpr; assert( (pTerm->flags & TERM_CODED)==0 ); sqlite3ExprCode(pParse, pX->pRight, 0); sqlite3VdbeAddOp2(v, OP_StackIsNull, -(nEq*2+1), nxt); topEq = pTerm->eOperator & (WO_LE|WO_GE); disableTerm(pLevel, pTerm); testOp = OP_IdxGE; }else{ testOp = nEq>0 ? OP_IdxGE : OP_Noop; topEq = 1; } |
︙ | ︙ | |||
2507 2508 2509 2510 2511 2512 2513 | Expr *pX; int k = pIdx->aiColumn[j]; pTerm = findTerm(&wc, iCur, k, notReady, btmOp, pIdx); assert( pTerm!=0 ); pX = pTerm->pExpr; assert( (pTerm->flags & TERM_CODED)==0 ); sqlite3ExprCode(pParse, pX->pRight, 0); | | | 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 | Expr *pX; int k = pIdx->aiColumn[j]; pTerm = findTerm(&wc, iCur, k, notReady, btmOp, pIdx); assert( pTerm!=0 ); pX = pTerm->pExpr; assert( (pTerm->flags & TERM_CODED)==0 ); sqlite3ExprCode(pParse, pX->pRight, 0); sqlite3VdbeAddOp2(v, OP_StackIsNull, -(nEq+1), nxt); btmEq = pTerm->eOperator & (WO_LE|WO_GE); disableTerm(pLevel, pTerm); }else{ btmEq = 1; } if( nEq>0 || btmLimit || (isMinQuery&&!bRev) ){ int nCol = nEq + btmLimit; |
︙ | ︙ | |||
2549 2550 2551 2552 2553 2554 2555 | sqlite3VdbeAddOp2(v, testOp, iIdxCur, nxt); if( (topEq && !bRev) || (!btmEq && bRev) ){ sqlite3VdbeChangeP4(v, -1, "+", P4_STATIC); } } if( topLimit | btmLimit ){ sqlite3VdbeAddOp2(v, OP_Column, iIdxCur, nEq); | | | 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 | sqlite3VdbeAddOp2(v, testOp, iIdxCur, nxt); if( (topEq && !bRev) || (!btmEq && bRev) ){ sqlite3VdbeChangeP4(v, -1, "+", P4_STATIC); } } if( topLimit | btmLimit ){ sqlite3VdbeAddOp2(v, OP_Column, iIdxCur, nEq); sqlite3VdbeAddOp2(v, OP_StackIsNull, 1, cont); } if( !omitTable ){ sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, 0); sqlite3VdbeAddOp2(v, OP_MoveGe, iCur, 0); } /* Record the instruction used to terminate the loop. |
︙ | ︙ |
Changes to test/tester.tcl.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements some common TCL routines used for regression # testing the SQLite library # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements some common TCL routines used for regression # testing the SQLite library # # $Id: tester.tcl,v 1.96 2008/01/07 19:20:25 drh Exp $ set tcl_precision 15 set sqlite_pending_byte 0x0010000 # # Check the command-line arguments for a default soft-heap-limit. |
︙ | ︙ | |||
47 48 49 50 51 52 53 54 55 56 57 58 59 60 | for {set i 0} {$i<[llength $argv]} {incr i} { if {[regexp {^--backtrace=(\d+)$} [lindex $argv $i] all value]} { sqlite3_memdebug_backtrace $value set argv [lreplace $argv $i $i] } } # Use the pager codec if it is available # if {[sqlite3 -has-codec] && [info command sqlite_orig]==""} { rename sqlite3 sqlite_orig proc sqlite3 {args} { if {[llength $args]==2 && [string index [lindex $args 0] 0]!="-"} { | > > > > > > > > > > > > > > | 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 | for {set i 0} {$i<[llength $argv]} {incr i} { if {[regexp {^--backtrace=(\d+)$} [lindex $argv $i] all value]} { sqlite3_memdebug_backtrace $value set argv [lreplace $argv $i $i] } } # # Check the command-line arguments to set the maximum number of # errors tolerated before halting. # if {![info exists maxErr]} { set maxErr 1000 } for {set i 0} {$i<[llength $argv]} {incr i} { if {[regexp {^--maxerror=(\d+)$} [lindex $argv $i] all maxErr]} { set argv [lreplace $argv $i $i] } } #puts "Max error = $maxErr" # Use the pager codec if it is available # if {[sqlite3 -has-codec] && [info command sqlite_orig]==""} { rename sqlite3 sqlite_orig proc sqlite3 {args} { if {[llength $args]==2 && [string index [lindex $args 0] 0]!="-"} { |
︙ | ︙ | |||
82 83 84 85 86 87 88 | # Set the test counters to zero # set nErr 0 set nTest 0 set skip_test 0 set failList {} | < | 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | # Set the test counters to zero # set nErr 0 set nTest 0 set skip_test 0 set failList {} if {![info exists speedTest]} { set speedTest 0 } # Invoke the do_test procedure to run a single test # proc do_test {name cmd expected} { |
︙ | ︙ |