Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Combine the OP_MakeIdxKey and OP_MakeKey opcodes into a single OP_MakeKey that does the work of both. Standardize the parameter meanings on OP_MakeRecord and OP_MakeKey. Remove the unused OP_Seek opcode. Other related code simplifications and cleanup. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
ed5d6992cd896855ecaae58fa9bda625 |
User & Date: | drh 2013-07-30 20:27:26.605 |
Context
2013-07-31
| ||
08:37 | Fix up test/speed1.test so that it runs. check-in: 8f00d13162 user: drh tags: trunk | |
2013-07-30
| ||
20:27 | Combine the OP_MakeIdxKey and OP_MakeKey opcodes into a single OP_MakeKey that does the work of both. Standardize the parameter meanings on OP_MakeRecord and OP_MakeKey. Remove the unused OP_Seek opcode. Other related code simplifications and cleanup. check-in: ed5d6992cd user: drh tags: trunk | |
20:22 | Combine the OP_MakeIdxKey and OP_MakeKey opcodes into a single OP_MakeKey that does the work of both. Standardize the parameter meanings on OP_MakeRecord and OP_MakeKey. Remove the unused OP_Seek opcode. Other related code simplifications and cleanup. Closed-Leaf check-in: 1122ff55e5 user: drh tags: refactor-MakeRecord | |
20:01 | Add experimental sqlite_kvstore table. Currently read-only. check-in: c13692183a user: dan tags: trunk | |
Changes
Changes to src/analyze.c.
︙ | ︙ | |||
652 653 654 655 656 657 658 | sqlite4VdbeAddOp3(v, OP_Divide, aregCard+i, regTemp, regTemp); sqlite4VdbeAddOp1(v, OP_ToInt, regTemp); sqlite4VdbeAddOp3(v, OP_Concat, regTemp, regStat1, regStat1); } sqlite4VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0); sqlite4VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid); sqlite4VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regNewRowid); | < < | 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 | sqlite4VdbeAddOp3(v, OP_Divide, aregCard+i, regTemp, regTemp); sqlite4VdbeAddOp1(v, OP_ToInt, regTemp); sqlite4VdbeAddOp3(v, OP_Concat, regTemp, regStat1, regStat1); } sqlite4VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0); sqlite4VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid); sqlite4VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regNewRowid); } sqlite4VdbeJumpHere(v, jZeroRows); jZeroRows = sqlite4VdbeAddOp0(v, OP_Goto); sqlite4VdbeAddOp2(v, OP_Null, 0, regIdxname); sqlite4VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0); sqlite4VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid); sqlite4VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regNewRowid); if( pParse->nMem<regRec ) pParse->nMem = regRec; sqlite4VdbeJumpHere(v, jZeroRows); } /* ** Generate code that will cause the most recent index analysis to ** be loaded into internal hash tables where is can be used. |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
820 821 822 823 824 825 826 | int tnum = firstAvailableTableNumber(db, iDb); sqlite4VdbeAddOp2(v, OP_Integer, tnum, reg2); } #endif sqlite4OpenMasterTable(pParse, iDb); sqlite4VdbeAddOp2(v, OP_NewRowid, 0, reg1); sqlite4VdbeAddOp3(v, OP_Insert, 0, 0, reg1); | < | 820 821 822 823 824 825 826 827 828 829 830 831 832 833 | int tnum = firstAvailableTableNumber(db, iDb); sqlite4VdbeAddOp2(v, OP_Integer, tnum, reg2); } #endif sqlite4OpenMasterTable(pParse, iDb); sqlite4VdbeAddOp2(v, OP_NewRowid, 0, reg1); sqlite4VdbeAddOp3(v, OP_Insert, 0, 0, reg1); sqlite4VdbeAddOp0(v, OP_Close); } /* Normal (non-error) return. */ return; /* If an error occurs, we jump here */ |
︙ | ︙ |
Changes to src/delete.c.
︙ | ︙ | |||
551 552 553 554 555 556 557 | }else{ sqlite4VdbeAddOp3(v, OP_Column, iPkCsr, pPk->aiColumn[i], regVal); } } /* Build the index key. If bAddSeq is true, append a sequence number to ** the end of the key to ensure it is unique. */ | | | 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 | }else{ sqlite4VdbeAddOp3(v, OP_Column, iPkCsr, pPk->aiColumn[i], regVal); } } /* Build the index key. If bAddSeq is true, append a sequence number to ** the end of the key to ensure it is unique. */ sqlite4VdbeAddOp4Int(v, OP_MakeKey, regTmp, nTmpReg, regOut, iIdxCsr); if( bAddSeq ) sqlite4VdbeChangeP5(v, OPFLAG_SEQCOUNT); /* Release temp registers */ sqlite4ReleaseTempRange(pParse, regTmp, nTmpReg); } /* |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
1767 1768 1769 1770 1771 1772 1773 | sqlite4VdbeChangeToNoop(v, testAddr); testAddr = -1; } /* Evaluate the expression and insert it into the temp table */ r3 = sqlite4ExprCodeTarget(pParse, pE2, r1); r4 = sqlite4GetTempReg(pParse); | | > | | 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 | sqlite4VdbeChangeToNoop(v, testAddr); testAddr = -1; } /* Evaluate the expression and insert it into the temp table */ r3 = sqlite4ExprCodeTarget(pParse, pE2, r1); r4 = sqlite4GetTempReg(pParse); sqlite4VdbeAddOp4(v, OP_Affinity, r3, 1, 0, &affinity, 1); sqlite4VdbeAddOp4Int(v, OP_MakeKey, r3, 1, r4, pExpr->iTable); sqlite4VdbeAddOp3(v, OP_MakeRecord, r3, 1, r2); sqlite4ExprCacheAffinityChange(pParse, r3, 1); sqlite4VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r4); sqlite4ReleaseTempReg(pParse, r4); } sqlite4ReleaseTempReg(pParse, r1); sqlite4ReleaseTempReg(pParse, r2); } |
︙ | ︙ |
Changes to src/fkey.c.
︙ | ︙ | |||
361 362 363 364 365 366 367 | sqlite4VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent); sqlite4VdbeChangeP5(v, SQLITE4_JUMPIFNULL); assert( iChild<=pParse->nMem && iParent<=pParse->nMem ); } sqlite4VdbeAddOp2(v, OP_Goto, 0, iOk); } | | < < < < < < | 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 | sqlite4VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent); sqlite4VdbeChangeP5(v, SQLITE4_JUMPIFNULL); assert( iChild<=pParse->nMem && iParent<=pParse->nMem ); } sqlite4VdbeAddOp2(v, OP_Goto, 0, iOk); } sqlite4VdbeAddOp4Int(v, OP_MakeKey, regTemp, nCol, regRec, iCur); sqlite4VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0); sqlite4ReleaseTempReg(pParse, regRec); sqlite4ReleaseTempRange(pParse, regTemp, nCol); } if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){ /* Special case: If this is an INSERT statement that will insert exactly |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
360 361 362 363 364 365 366 | j5 = sqlite4VdbeAddOp0(v, OP_Goto); sqlite4VdbeJumpHere(v, j4); sqlite4VdbeAddOp2(v, OP_Rowid, 0, memId+1); sqlite4VdbeJumpHere(v, j1); sqlite4VdbeJumpHere(v, j5); sqlite4VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, iRec); sqlite4VdbeAddOp3(v, OP_Insert, 0, iRec, memId+1); | < | 360 361 362 363 364 365 366 367 368 369 370 371 372 373 | j5 = sqlite4VdbeAddOp0(v, OP_Goto); sqlite4VdbeJumpHere(v, j4); sqlite4VdbeAddOp2(v, OP_Rowid, 0, memId+1); sqlite4VdbeJumpHere(v, j1); sqlite4VdbeJumpHere(v, j5); sqlite4VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, iRec); sqlite4VdbeAddOp3(v, OP_Insert, 0, iRec, memId+1); sqlite4VdbeAddOp0(v, OP_Close); sqlite4ReleaseTempReg(pParse, iRec); } } #else /* ** If SQLITE4_OMIT_AUTOINCREMENT is defined, then the three routines |
︙ | ︙ | |||
1297 1298 1299 1300 1301 1302 1303 | } if( pIdx!=pPk ){ for(i=0; i<pPk->nColumn; i++){ int idx = pPk->aiColumn[i]; sqlite4VdbeAddOp2(v, OP_SCopy, regContent+idx, regTmp+i+pIdx->nColumn); } } | | | 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 | } if( pIdx!=pPk ){ for(i=0; i<pPk->nColumn; i++){ int idx = pPk->aiColumn[i]; sqlite4VdbeAddOp2(v, OP_SCopy, regContent+idx, regTmp+i+pIdx->nColumn); } } sqlite4VdbeAddOp4Int(v, OP_MakeKey, regTmp, nTmpReg-1, regKey, iIdx); VdbeComment((v, "key for %s", pIdx->zName)); /* If Index.onError==OE_None, then pIdx is not a UNIQUE or PRIMARY KEY ** index. In this case there is no need to test the index for uniqueness ** - all that is required is to populate the regKey register. Jump ** to the next iteration of the loop if this is the case. */ onError = pIdx->onError; |
︙ | ︙ |
Changes to src/pragma.c.
︙ | ︙ | |||
757 758 759 760 761 762 763 | } } if( (pPk->nColumn+pIdx->nColumn)>nMaxArray ){ nMaxArray = pPk->nColumn + pIdx->nColumn; } | | > | 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 | } } if( (pPk->nColumn+pIdx->nColumn)>nMaxArray ){ nMaxArray = pPk->nColumn + pIdx->nColumn; } sqlite4VdbeAddOp4Int(v, OP_MakeKey, regArray, pIdx->nColumn+pPk->nColumn, regKey, iCsr); jmp = sqlite4VdbeAddOp4(v, OP_Found, iCsr, 0, regKey, 0, P4_INT32); sqlite4VdbeAddOp2(v, OP_AddImm, regErrcnt, 1); zErr = sqlite4MPrintf( db, "entry missing from index %s: ", pIdx->zName ); sqlite4VdbeAddOp4(v, OP_String8, 0, regTmp, 0, zErr, 0); sqlite4VdbeAddOp3(v, OP_Concat, regTmp, regErrstr, regErrstr); |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
431 432 433 434 435 436 437 | ** number. The sequence number allows more than one row with the same ** sort-key. */ sqlite4ExprCacheClear(pParse); sqlite4ExprCodeExprList(pParse, pOrderBy, regBase, 0); sqlite4VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr); /* Encode the sort-key. */ | > | | | 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 | ** number. The sequence number allows more than one row with the same ** sort-key. */ sqlite4ExprCacheClear(pParse); sqlite4ExprCodeExprList(pParse, pOrderBy, regBase, 0); sqlite4VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr); /* Encode the sort-key. */ sqlite4VdbeAddOp4Int(v, OP_MakeKey, regBase, nExpr+1, regKey, pOrderBy->iECursor); /* Insert an entry into the sorter. The key inserted is the encoded key ** created by the OP_MakeKey coded above. The value is the record ** currently stored in register regData. */ sqlite4VdbeAddOp3(v, OP_Insert, pOrderBy->iECursor, regData, regKey); /* Release the temporary registers */ sqlite4ReleaseTempReg(pParse, regKey); sqlite4ReleaseTempRange(pParse, regBase, nExpr+1); |
︙ | ︙ | |||
501 502 503 504 505 506 507 | Vdbe *v; int r1, r2; v = pParse->pVdbe; r1 = sqlite4GetTempReg(pParse); r2 = sqlite4GetTempReg(pParse); sqlite4VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); | | > | 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 | Vdbe *v; int r1, r2; v = pParse->pVdbe; r1 = sqlite4GetTempReg(pParse); r2 = sqlite4GetTempReg(pParse); sqlite4VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); sqlite4VdbeAddOp4Int(v, OP_MakeKey, iMem, N, r2, iTab); sqlite4VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1); sqlite4VdbeChangeP5(v, OPFLAG_USEKEY); sqlite4VdbeAddOp3(v, OP_Insert, iTab, r1, r2); sqlite4ReleaseTempReg(pParse, r1); sqlite4ReleaseTempReg(pParse, r2); } #ifndef SQLITE4_OMIT_SUBQUERY /* |
︙ | ︙ | |||
619 620 621 622 623 624 625 | ** table iParm. */ #ifndef SQLITE4_OMIT_COMPOUND_SELECT case SRT_Union: { int r1, r2; r1 = sqlite4GetTempReg(pParse); r2 = sqlite4GetTempReg(pParse); | | > | < | 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 | ** table iParm. */ #ifndef SQLITE4_OMIT_COMPOUND_SELECT case SRT_Union: { int r1, r2; r1 = sqlite4GetTempReg(pParse); r2 = sqlite4GetTempReg(pParse); sqlite4VdbeAddOp4Int(v, OP_MakeKey, regResult, nColumn, r2, iParm); sqlite4VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); sqlite4VdbeChangeP5(v, OPFLAG_USEKEY); sqlite4VdbeAddOp3(v, OP_Insert, iParm, r1, r2); sqlite4ReleaseTempReg(pParse, r1); sqlite4ReleaseTempReg(pParse, r2); break; } /* This is used for processing queries of the form: ** ** <select-1> EXCEPT <select-2> ** ** Temporary index iParm contains the results of <select-1>. This ** code is processing the results of <select-2>. For each row of ** <select-2>, remove any identical row from iParm. */ case SRT_Except: { int regKey = sqlite4GetTempReg(pParse); sqlite4VdbeAddOp4Int(v, OP_MakeKey, regResult, nColumn, regKey, iParm); sqlite4VdbeAddOp3(v, OP_IdxDelete, iParm, 0, regKey); sqlite4ReleaseTempReg(pParse, regKey); break; } #endif /* Store the result as data using a unique key. */ case SRT_Table: case SRT_EphemTab: { int r1 = sqlite4GetTempReg(pParse); testcase( eDest==SRT_Table ); testcase( eDest==SRT_EphemTab ); sqlite4VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); if( pOrderBy ){ pushOntoSorter(pParse, pOrderBy, p, r1); }else{ int r2 = sqlite4GetTempReg(pParse); sqlite4VdbeAddOp2(v, OP_NewRowid, iParm, r2); sqlite4VdbeAddOp3(v, OP_Insert, iParm, r1, r2); sqlite4ReleaseTempReg(pParse, r2); } sqlite4ReleaseTempReg(pParse, r1); break; } #ifndef SQLITE4_OMIT_SUBQUERY |
︙ | ︙ | |||
682 683 684 685 686 687 688 | ** ORDER BY in this case since the order of entries in the set ** does not matter. But there might be a LIMIT clause, in which ** case the order does matter */ sqlite4VdbeAddOp4(v, OP_MakeRecord, regResult, 1, r1, &p->affinity, 1); pushOntoSorter(pParse, pOrderBy, p, r1); }else{ int r2 = sqlite4GetTempReg(pParse); | | | > > | 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 | ** ORDER BY in this case since the order of entries in the set ** does not matter. But there might be a LIMIT clause, in which ** case the order does matter */ sqlite4VdbeAddOp4(v, OP_MakeRecord, regResult, 1, r1, &p->affinity, 1); pushOntoSorter(pParse, pOrderBy, p, r1); }else{ int r2 = sqlite4GetTempReg(pParse); sqlite4VdbeAddOp4(v, OP_Affinity, regResult, 1, 0, &p->affinity, 1); sqlite4VdbeAddOp4Int(v, OP_MakeKey, regResult, 1, r2, iParm); sqlite4ExprCacheAffinityChange(pParse, regResult, 1); sqlite4VdbeAddOp3(v, OP_MakeRecord, regResult, 1, r1); sqlite4VdbeChangeP5(v, OPFLAG_USEKEY); sqlite4VdbeAddOp3(v, OP_Insert, iParm, r1, r2); sqlite4ReleaseTempReg(pParse, r2); } sqlite4ReleaseTempReg(pParse, r1); break; } |
︙ | ︙ | |||
934 935 936 937 938 939 940 | int regRowid = sqlite4GetTempReg(pParse); int regRow = sqlite4GetTempReg(pParse); testcase( eDest==SRT_Table ); testcase( eDest==SRT_EphemTab ); sqlite4VdbeAddOp2(v, OP_NewRowid, iParm, regRowid); sqlite4VdbeAddOp2(v, OP_RowData, iTab, regRow); sqlite4VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid); | < | > > | > | 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 | int regRowid = sqlite4GetTempReg(pParse); int regRow = sqlite4GetTempReg(pParse); testcase( eDest==SRT_Table ); testcase( eDest==SRT_EphemTab ); sqlite4VdbeAddOp2(v, OP_NewRowid, iParm, regRowid); sqlite4VdbeAddOp2(v, OP_RowData, iTab, regRow); sqlite4VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid); sqlite4ReleaseTempReg(pParse, regRow); sqlite4ReleaseTempReg(pParse, regRowid); break; } #ifndef SQLITE4_OMIT_SUBQUERY case SRT_Set: { int regRes = sqlite4GetTempReg(pParse); int regKey = sqlite4GetTempReg(pParse); int regValue = sqlite4GetTempReg(pParse); assert( nColumn==1 ); sqlite4VdbeAddOp3(v, OP_Column, iTab, 0, regRes); sqlite4VdbeAddOp4(v, OP_Affinity, regRes, 1, 0, &p->affinity, 1); sqlite4VdbeAddOp4Int(v, OP_MakeKey, regRes, 1, regKey, iParm); sqlite4ExprCacheAffinityChange(pParse, regRes, 1); sqlite4VdbeAddOp3(v, OP_MakeRecord, regRes, 1, regValue); sqlite4VdbeChangeP5(v, OPFLAG_USEKEY); sqlite4VdbeAddOp3(v, OP_Insert, iParm, regValue, regKey); sqlite4ReleaseTempReg(pParse, regKey); sqlite4ReleaseTempReg(pParse, regRes); sqlite4ReleaseTempReg(pParse, regValue); break; } case SRT_Mem: { |
︙ | ︙ | |||
1968 1969 1970 1971 1972 1973 1974 | int r1 = sqlite4GetTempReg(pParse); int r2 = sqlite4GetTempReg(pParse); testcase( pDest->eDest==SRT_Table ); testcase( pDest->eDest==SRT_EphemTab ); sqlite4VdbeAddOp3(v, OP_MakeRecord, pIn->iMem, pIn->nMem, r1); sqlite4VdbeAddOp2(v, OP_NewRowid, pDest->iParm, r2); sqlite4VdbeAddOp3(v, OP_Insert, pDest->iParm, r1, r2); | < < | > > > | 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 | int r1 = sqlite4GetTempReg(pParse); int r2 = sqlite4GetTempReg(pParse); testcase( pDest->eDest==SRT_Table ); testcase( pDest->eDest==SRT_EphemTab ); sqlite4VdbeAddOp3(v, OP_MakeRecord, pIn->iMem, pIn->nMem, r1); sqlite4VdbeAddOp2(v, OP_NewRowid, pDest->iParm, r2); sqlite4VdbeAddOp3(v, OP_Insert, pDest->iParm, r1, r2); sqlite4ReleaseTempReg(pParse, r2); sqlite4ReleaseTempReg(pParse, r1); break; } #ifndef SQLITE4_OMIT_SUBQUERY /* If we are creating a set for an "expr IN (SELECT ...)" construct, ** then there should be a single item on the stack. Write this ** item into the set table with bogus data. */ case SRT_Set: { int r1, r2; assert( pIn->nMem==1 ); p->affinity = sqlite4CompareAffinity(p->pEList->a[0].pExpr, pDest->affinity); r1 = sqlite4GetTempReg(pParse); r2 = sqlite4GetTempReg(pParse); sqlite4VdbeAddOp4(v, OP_Affinity, pIn->iMem, 1, 0, &p->affinity, 1); sqlite4ExprCacheAffinityChange(pParse, pIn->iMem, 1); sqlite4VdbeAddOp4Int(v, OP_MakeKey, pIn->iMem, 1, r2, pDest->iParm); sqlite4VdbeAddOp3(v, OP_MakeRecord, pIn->iMem, 1, r1); sqlite4VdbeChangeP5(v, OPFLAG_USEKEY); sqlite4VdbeAddOp3(v, OP_Insert, pDest->iParm, r1, r2); sqlite4ReleaseTempReg(pParse, r1); sqlite4ReleaseTempReg(pParse, r2); break; } #if 0 /* Never occurs on an ORDER BY query */ |
︙ | ︙ | |||
4151 4152 4153 4154 4155 4156 4157 | /* Encode the key for the sorting index. The key consists of each ** of the expressions in the GROUP BY list followed by a sequence ** number (to ensure each key is unique - the point of this is just ** to sort the rows, not to eliminate duplicates). */ sqlite4ExprCacheClear(pParse); regBase = sqlite4GetTempRange(pParse, nGroup); sqlite4ExprCodeExprList(pParse, pGroupBy, regBase, 0); | > | | 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 | /* Encode the key for the sorting index. The key consists of each ** of the expressions in the GROUP BY list followed by a sequence ** number (to ensure each key is unique - the point of this is just ** to sort the rows, not to eliminate duplicates). */ sqlite4ExprCacheClear(pParse); regBase = sqlite4GetTempRange(pParse, nGroup); sqlite4ExprCodeExprList(pParse, pGroupBy, regBase, 0); sqlite4VdbeAddOp4Int(v, OP_MakeKey, regBase, nGroup, regKey, sAggInfo.sortingIdx); sqlite4VdbeChangeP5(v, OPFLAG_SEQCOUNT); sqlite4ReleaseTempRange(pParse, regBase, nGroup); /* Encode the record for the sorting index. The record contains all ** required column values from the elements of the FROM clause. ** If no column values are required, insert a NULL into the sorting ** index instead of a record. No column values are required for |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
2005 2006 2007 2008 2009 2010 2011 | ** The KeyInfo for addrOpenTran[0] and [1] contains collating sequences ** for the result set. The KeyInfo for addrOpenTran[2] contains collating ** sequences for the ORDER BY clause. */ struct Select { ExprList *pEList; /* The fields of the result */ u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */ | | | 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 | ** The KeyInfo for addrOpenTran[0] and [1] contains collating sequences ** for the result set. The KeyInfo for addrOpenTran[2] contains collating ** sequences for the ORDER BY clause. */ struct Select { ExprList *pEList; /* The fields of the result */ u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */ char affinity; /* EncodeData with this affinity for SRT_Set */ u16 selFlags; /* Various SF_* values */ SrcList *pSrc; /* The FROM clause */ Expr *pWhere; /* The WHERE clause */ ExprList *pGroupBy; /* The GROUP BY clause */ Expr *pHaving; /* The HAVING clause */ ExprList *pOrderBy; /* The ORDER BY clause */ Select *pPrior; /* Prior select in a compound select statement */ |
︙ | ︙ | |||
2247 2248 2249 2250 2251 2252 2253 | Parse *pParse; /* The Parse structure */ }; /* ** Bitfield flags for P5 value in OP_Insert and OP_Delete */ #define OPFLAG_NCHANGE 0x01 /* Set to update db->nChange */ | < | | | | < | 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 | Parse *pParse; /* The Parse structure */ }; /* ** Bitfield flags for P5 value in OP_Insert and OP_Delete */ #define OPFLAG_NCHANGE 0x01 /* Set to update db->nChange */ #define OPFLAG_ISUPDATE 0x02 /* This OP_Insert is an sql UPDATE */ #define OPFLAG_USEKEY 0x04 /* Optimize OP_EncodeData using key content */ #define OPFLAG_SEQCOUNT 0x08 /* Append sequence number to key */ #define OPFLAG_CLEARCACHE 0x10 /* Clear pseudo-table cache in OP_Column */ /* * Each trigger present in the database schema is stored as an instance of * struct Trigger. * * Pointers to instances of struct Trigger are stored in two ways. * 1. In the "trigHash" hash table (part of the sqlite4* that represents the |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 | }else{ sqlite4VdbeMemSetNull(pDest); } UPDATE_MAX_BLOBSIZE(pDest); REGISTER_TRACE(pOp->p3, pDest); break; } /* Opcode: Affinity P1 P2 * P4 * ** ** Apply affinities to a range of P2 registers starting with P1. ** ** P4 is a string that is P2 characters long. The nth character of the ** string indicates the column affinity that should be used for the nth | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 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 | }else{ sqlite4VdbeMemSetNull(pDest); } UPDATE_MAX_BLOBSIZE(pDest); REGISTER_TRACE(pOp->p3, pDest); break; } /* Opcode: MakeKey P1 P2 P3 P4 P5 ** ** Encode the values in registers P1..P1+P2-1 using the key encoding ** and write the result into register P3. The cursor used for the encoding ** is given by the P4 value which must be an integer (P4_INT32). ** ** If the OPFLAG_SEQCOUNT bit of P5 is set, then a sequence number ** (unique within the cursor) is appended to the record. The sole purpose ** of this is to ensure that the key blob is unique within the cursor table. */ /* Opcode: MakeRecord P1 P2 P3 P4 P5 ** ** Encode the values in registers P1..P1+P2-1 using the data encoding ** and write the result into register P3. Apply affinities in P4 prior ** to performing the encoding. ** ** If the OPFLAG_USEKEY bit of P5 is set and this opcode immediately follows ** an MakeKey opcode, then the data encoding generated may try to refer ** to content in the previously generated key in order to make the encoding ** smaller. */ case OP_MakeKey: case OP_MakeRecord: { VdbeCursor *pC; /* The cursor for OP_MakeKey */ Mem *pData0; /* First field to be combined into the record */ Mem *pLast; /* Last field of the record */ Mem *pMem; /* For looping over inputs */ Mem *pOut; /* Where to store results */ int nIn; /* Number of input values to be encoded */ char *zAffinity; /* The affinity string */ u8 *aRec; /* The constructed key or value */ int nRec; /* Size of aRec[] in bytes */ int bRepeat; /* True to loop to the next opcode */ u8 aSeq[10]; /* Encoded sequence number */ int nSeq; /* Size of sequence number in bytes */ u64 iSeq; /* Sequence number, if any */ do{ bRepeat = 0; zAffinity = pOp->p4type==P4_INT32 ? 0 : pOp->p4.z; assert( pOp->p1>0 && pOp->p2>0 && pOp->p2+pOp->p1<=p->nMem+1 ); pData0 = &aMem[pOp->p1]; nIn = pOp->p2; pLast = &pData0[nIn-1]; assert( pOp->p3>0 && pOp->p3<=p->nMem ); pOut = &aMem[pOp->p3]; memAboutToChange(p, pOut); aRec = 0; nSeq = 0; /* Apply affinities */ if( zAffinity ){ for(pMem=pData0; pMem<=pLast; pMem++){ assert( memIsValid(pMem) ); applyAffinity(pMem, *(zAffinity++), encoding); } } if( pOp->opcode==OP_MakeKey ){ assert( pOp->p4type==P4_INT32 ); assert( pOp->p4.i>=0 && pOp->p4.i<p->nCursor ); pC = p->apCsr[pOp->p4.i]; /* If P4 contains OPFLAG_SEQCOUNT, encode the sequence number blob to be ** appended to the end of the key. Variable nSeq is set to the number ** of bytes in the encoded key. A non-standard encoding is used (not ** the usual varint encoding) so that the OP_GrpCompare opcode can easily ** back up over the sequence count to find the true end of the key. */ if( pOp->p5 & OPFLAG_SEQCOUNT ){ iSeq = pC->seqCount++; do { nSeq++; aSeq[sizeof(aSeq)-nSeq] = (u8)(iSeq & 0x007F); iSeq = iSeq >> 7; }while( iSeq ); aSeq[sizeof(aSeq)-nSeq] |= 0x80; } /* Generate the key encoding */ rc = sqlite4VdbeEncodeKey( db, pData0, nIn, pC->iRoot, pC->pKeyInfo, &aRec, &nRec, nSeq ); if( pOp[1].opcode==OP_MakeRecord ){ pc++; pOp++; bRepeat = 1; } }else{ assert( pOp->opcode==OP_MakeRecord ); rc = sqlite4VdbeEncodeData(db, pData0, aPermute, nIn, &aRec, &nRec); aPermute = 0; } /* Store the result */ if( rc!=SQLITE4_OK ){ sqlite4DbFree(db, aRec); }else{ if( nSeq ) memcpy(&aRec[nRec], &aSeq[sizeof(aSeq)-nSeq], nSeq); rc = sqlite4VdbeMemSetStr(pOut, (char *)aRec, nRec+nSeq, 0, SQLITE4_DYNAMIC, 0); REGISTER_TRACE(pOp->p3, pOut); UPDATE_MAX_BLOBSIZE(pOut); } }while( rc==SQLITE4_OK && bRepeat ); break; } /* Opcode: Affinity P1 P2 * P4 * ** ** Apply affinities to a range of P2 registers starting with P1. ** ** P4 is a string that is P2 characters long. The nth character of the ** string indicates the column affinity that should be used for the nth |
︙ | ︙ | |||
2158 2159 2160 2161 2162 2163 2164 | applyAffinity(pIn1, *(zAffinity++), encoding); REGISTER_TRACE(pIn1-aMem, pIn1); } break; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 | applyAffinity(pIn1, *(zAffinity++), encoding); REGISTER_TRACE(pIn1-aMem, pIn1); } break; } /* Opcode: Count P1 P2 * * * ** ** Store the number of entries (an integer value) in the table or index ** opened by cursor P1 in register P2 */ case OP_Count: { /* out2-prerelease */ i64 nEntry; |
︙ | ︙ | |||
2958 2959 2960 2961 2962 2963 2964 | /* Encode a database key consisting of the contents of the P4 registers ** starting at register P3. Have the vdbecodec module allocate an extra ** free byte at the end of the database key (see below). */ nField = pOp->p4.i; pIn3 = &aMem[pOp->p3]; if( pC->iRoot!=KVSTORE_ROOT ){ rc = sqlite4VdbeEncodeKey( | < | | 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 | /* Encode a database key consisting of the contents of the P4 registers ** starting at register P3. Have the vdbecodec module allocate an extra ** free byte at the end of the database key (see below). */ nField = pOp->p4.i; pIn3 = &aMem[pOp->p3]; if( pC->iRoot!=KVSTORE_ROOT ){ rc = sqlite4VdbeEncodeKey( db, pIn3, nField, pC->iRoot, pC->pKeyInfo, &aProbe, &nProbe, 1 ); /* Opcode search-dir increment-key ** -------------------------------------- ** SeekLt -1 no ** SeekLe -1 yes ** SeekGe +1 no |
︙ | ︙ | |||
3012 3013 3014 3015 3016 3017 3018 | if( rc==SQLITE4_NOTFOUND ){ rc = SQLITE4_OK; pc = pOp->p2 - 1; } break; } | | < < < < < < < < < < < < < < < < < < < < < < < < < < | 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 | if( rc==SQLITE4_NOTFOUND ){ rc = SQLITE4_OK; pc = pOp->p2 - 1; } break; } /* Opcode: Found P1 P2 P3 P4 * ** ** If P4==0 then register P3 holds a blob constructed by MakeKey. If ** P4>0 then register P3 is the first of P4 registers that should be ** combined to generate a key. ** |
︙ | ︙ | |||
3073 3074 3075 3076 3077 3078 3079 | ** Use the content of register 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 through. The cursor is left ** pointing to the record if it exists. ** ** The difference between this operation and NotFound is that this ** operation assumes the key is an integer and that P1 is a table whereas | | | 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 | ** Use the content of register 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 through. The cursor is left ** pointing to the record if it exists. ** ** 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 MakeKey and ** P1 is an index. ** ** See also: Found, NotFound, IsUnique */ case OP_NotExists: { /* jump, in3 */ pOp->p4.i = 1; pOp->p4type = P4_INT32; |
︙ | ︙ | |||
3108 3109 3110 3111 3112 3113 3114 | pC->sSeekKey.n = 0; pC->rowChnged = 1; assert( pC!=0 ); pIn3 = &aMem[pOp->p3]; assert( pC->pKVCur!=0 ); if( pOp->p4.i>0 ){ rc = sqlite4VdbeEncodeKey( | < | | 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 | pC->sSeekKey.n = 0; pC->rowChnged = 1; assert( pC!=0 ); pIn3 = &aMem[pOp->p3]; assert( pC->pKVCur!=0 ); if( pOp->p4.i>0 ){ rc = sqlite4VdbeEncodeKey( db, pIn3, pOp->p4.i, pC->iRoot, pC->pKeyInfo, &pProbe, &nProbe, 0 ); pFree = pProbe; }else{ pProbe = (KVByteArray*)pIn3->z; nProbe = pIn3->n; pFree = 0; } |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
216 217 218 219 220 221 222 223 224 225 226 227 228 229 | #endif sqlite4_value *sqlite4ColumnValue(sqlite4_stmt *pStmt, int iCol); #ifndef SQLITE4_OMIT_TRIGGER void sqlite4VdbeLinkSubProgram(Vdbe *, SubProgram *); #endif #ifndef NDEBUG void sqlite4VdbeComment(Vdbe*, const char*, ...); # define VdbeComment(X) sqlite4VdbeComment X void sqlite4VdbeNoopComment(Vdbe*, const char*, ...); # define VdbeNoopComment(X) sqlite4VdbeNoopComment X #else | > > > > > > > > > > | 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | #endif sqlite4_value *sqlite4ColumnValue(sqlite4_stmt *pStmt, int iCol); #ifndef SQLITE4_OMIT_TRIGGER void sqlite4VdbeLinkSubProgram(Vdbe *, SubProgram *); #endif int sqlite4VdbeEncodeKey( sqlite4 *db, /* The database connection */ Mem *aIn, /* Values to be encoded */ int nIn, /* Number of entries in aIn[] */ int iTabno, /* The table this key applies to */ KeyInfo *pKeyInfo, /* Collating sequence information */ u8 **pzOut, /* Write the resulting key here */ int *pnOut, /* Number of bytes in the key */ int nExtra /* Append extra bytes on end of key */ ); #ifndef NDEBUG void sqlite4VdbeComment(Vdbe*, const char*, ...); # define VdbeComment(X) sqlite4VdbeComment X void sqlite4VdbeNoopComment(Vdbe*, const char*, ...); # define VdbeNoopComment(X) sqlite4VdbeNoopComment X #else |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
363 364 365 366 367 368 369 | sqlite4 *db, /* The database connection */ Mem *aIn, /* Array of values to encode */ int *aPermute, /* Permutation (or NULL) */ int nIn, /* Number of entries in aIn[] */ u8 **pzOut, /* The output data record */ int *pnOut /* Bytes of content in pzOut */ ); | < < < < < < < < < < < | 363 364 365 366 367 368 369 370 371 372 373 374 375 376 | sqlite4 *db, /* The database connection */ Mem *aIn, /* Array of values to encode */ int *aPermute, /* Permutation (or NULL) */ int nIn, /* Number of entries in aIn[] */ u8 **pzOut, /* The output data record */ int *pnOut /* Bytes of content in pzOut */ ); int sqlite4VdbeEncodeIntKey(u8 *aBuf,sqlite4_int64 v); int sqlite4VdbeDecodeNumericKey(const KVByteArray*, KVSize, sqlite4_num*); int sqlite4VdbeShortKey(const u8 *, int, int, int *); int sqlite4MemCompare(Mem*, Mem*, const CollSeq*,int*); int sqlite4VdbeExec(Vdbe*); int sqlite4VdbeList(Vdbe*); int sqlite4VdbeHalt(Vdbe*); |
︙ | ︙ |
Changes to src/vdbecodec.c.
︙ | ︙ | |||
673 674 675 676 677 678 679 | vdbeEncodeData_error: sqlite4StackFree(db, aAux); sqlite4DbFree(db, aOut); return rc; } /* | | | 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 | vdbeEncodeData_error: sqlite4StackFree(db, aAux); sqlite4DbFree(db, aOut); return rc; } /* ** An output buffer for sqlite4VdbeEncodeKey */ typedef struct KeyEncoder KeyEncoder; struct KeyEncoder { sqlite4 *db; /* Database connection */ u8 *aOut; /* Output buffer */ int nOut; /* Slots of aOut[] used */ int nAlloc; /* Slots of aOut[] allocated */ |
︙ | ︙ | |||
1006 1007 1008 1009 1010 1011 1012 | ** Space to hold the key is obtained from sqlite4DbMalloc() and should ** be freed by the caller using sqlite4DbFree() to avoid a memory leak. */ int sqlite4VdbeEncodeKey( sqlite4 *db, /* The database connection */ Mem *aIn, /* Values to be encoded */ int nIn, /* Number of entries in aIn[] */ | < | 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 | ** Space to hold the key is obtained from sqlite4DbMalloc() and should ** be freed by the caller using sqlite4DbFree() to avoid a memory leak. */ int sqlite4VdbeEncodeKey( sqlite4 *db, /* The database connection */ Mem *aIn, /* Values to be encoded */ int nIn, /* Number of entries in aIn[] */ int iTabno, /* The table this key applies to, or negative */ KeyInfo *pKeyInfo, /* Collating sequence and sort-order info */ u8 **paOut, /* Write the resulting key here */ int *pnOut, /* Number of bytes in the key */ int nExtra /* extra bytes of space appended to the key */ ){ int i; |
︙ | ︙ | |||
1037 1038 1039 1040 1041 1042 1043 | if( iTabno>=0 ){ x.nOut = sqlite4PutVarint64(x.aOut, iTabno); } aColl = pKeyInfo->aColl; so = pKeyInfo->aSortOrder; for(i=0; i<nIn && rc==SQLITE4_OK; i++){ rc = encodeOneKeyValue(&x, aIn+i, so ? so[i] : SQLITE4_SO_ASC, | | | 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 | if( iTabno>=0 ){ x.nOut = sqlite4PutVarint64(x.aOut, iTabno); } aColl = pKeyInfo->aColl; so = pKeyInfo->aSortOrder; for(i=0; i<nIn && rc==SQLITE4_OK; i++){ rc = encodeOneKeyValue(&x, aIn+i, so ? so[i] : SQLITE4_SO_ASC, i==pKeyInfo->nField-1, aColl[i]); } if( rc==SQLITE4_OK && nExtra ){ rc = enlargeEncoderAllocation(&x, nExtra); } if( rc ){ sqlite4DbFree(db, x.aOut); }else{ *paOut = x.aOut; *pnOut = x.nOut; } return rc; } |
Changes to src/where.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | ** 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". */ #include "sqliteInt.h" | < < < | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | ** 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". */ #include "sqliteInt.h" /* ** Trace output macros */ #if defined(SQLITE4_TEST) || defined(SQLITE4_DEBUG) /***/ int sqlite4WhereTrace = 0; #endif #if defined(SQLITE4_DEBUG) \ |
︙ | ︙ | |||
2614 2615 2616 2617 2618 2619 2620 | }else{ rc = sqlite4ValueFromExpr(db, pExpr, SQLITE4_UTF8, aff, &pVal); } if( pVal && rc==SQLITE4_OK ){ u8 *aOut; int nOut; | | | 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 | }else{ rc = sqlite4ValueFromExpr(db, pExpr, SQLITE4_UTF8, aff, &pVal); } if( pVal && rc==SQLITE4_OK ){ u8 *aOut; int nOut; rc = sqlite4VdbeEncodeKey(db, pVal, 1, -1, pKeyinfo, &aOut, &nOut, 0); if( rc==SQLITE4_OK ){ rc = sqlite4_buffer_set(pBuf, aOut, nOut); } sqlite4DbFree(db, aOut); } sqlite4ValueFree(pVal); |
︙ | ︙ | |||
3623 3624 3625 3626 3627 3628 3629 | testcase( op==OP_Rewind ); testcase( op==OP_Last ); testcase( op==OP_SeekGt ); testcase( op==OP_SeekGe ); testcase( op==OP_SeekLe ); testcase( op==OP_SeekLt ); sqlite4VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); | < < < | 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 | testcase( op==OP_Rewind ); testcase( op==OP_Last ); testcase( op==OP_SeekGt ); testcase( op==OP_SeekGe ); testcase( op==OP_SeekLe ); testcase( op==OP_SeekLt ); sqlite4VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); /* Set variable op to the instruction required to determine if the ** cursor is passed the end of the range. If the range is unbounded, ** then set op to OP_Noop. Nothing to do in this case. */ assert( (endEq==0 || endEq==1) ); op = aEndOp[(pRangeEnd || nEq) * (1 + (endEq+endEq) + bRev)]; testcase( op==OP_Noop ); |
︙ | ︙ | |||
3666 3667 3668 3669 3670 3671 3672 | } } codeApplyAffinity(pParse, regBase, nEq+1, zEndAff); nConstraint++; testcase( pRangeEnd->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ } | | | < | < | 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 | } } codeApplyAffinity(pParse, regBase, nEq+1, zEndAff); nConstraint++; testcase( pRangeEnd->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ } /* Now compute an end-key using OP_MakeKey */ regEndKey = ++pParse->nMem; if( pIdx->tnum==KVSTORE_ROOT ){ sqlite4VdbeAddOp2(v, OP_Copy, regBase, regEndKey); sqlite4VdbeAddOp1(v, OP_ToBlob, regEndKey); }else{ sqlite4VdbeAddOp4Int(v, OP_MakeKey, regBase, nConstraint, regEndKey, iIdxCur); } } sqlite4DbFree(pParse->db, zStartAff); sqlite4DbFree(pParse->db, zEndAff); /* Top of the loop body */ pLevel->p2 = sqlite4VdbeCurrentAddr(v); |
︙ | ︙ |