Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch omit-column-cache Excluding Merge-Ins
This is equivalent to a diff from 21235d9a to a500893b
2018-08-04
| ||
20:30 | Remove the column-cache from the code generator. The column-cache has been a persistent source of bugs for years and with recent improvements in the performance of OP_Column, it no longer provides a benefit. After the column cache is removed, the binary is almost 2KB smaller and the speed-check.sh performance test is over 3 million cycles faster. (check-in: cdff3af7 user: drh tags: trunk) | |
20:12 | Remove a testcase() that is no longer reachable without the column cache. Provide an assert() to help prove that the testcase is no longer reachable. (Closed-Leaf check-in: a500893b user: drh tags: omit-column-cache) | |
17:15 | Fix comments that were made obsolete by the removal of the column cache. (check-in: 2041231d user: drh tags: omit-column-cache) | |
15:16 | Ensure that all expressions that are to be evaluated once at the start of a prepared statement (the Parse.pConstExpr expressions) pass the sqlite3ExprIsConstantNotJoin() test. It is not sufficient to pass just the sqlite3ExprIsConstant() test as that would allow through column references that are bound to constants by the WHERE clause in the constant propagation optimization. This fixes a problem discovered by OSSFuzz. (check-in: 8bc7f84c user: drh tags: trunk) | |
2018-08-03
| ||
23:04 | Completely remove the column cache logic, which has been a persistent source of bugs for many years. Due to recent enhancements to the performance of the OP_Column opcode, removing the column cache actually makes speed-check.sh run faster. Removing the column cache also saves about 1,800 bytes of code space. (check-in: 3f5f60cd user: drh tags: omit-column-cache) | |
20:19 | Fix the handling of sub-queries with LIMIT clauses by the optimization activated by compile-time symbol SQLITE_COUNTOFVIEW_OPTIMIZATION. (check-in: 21235d9a user: dan tags: trunk) | |
15:58 | Fix the OP_SeekRowid opcode so that it has no type-change side-effects on the key register in P3. This fixes an obcure problem that arises when doing equi-joins between a table with a TEXT column against another table with an INTEGER PRIMARY KEY. The original problem was discovered when OSSFuzz created such a query and hit an assert() in OP_VerifyTabCol that was specifically designed to catch these kinds of errors at run-time. Test cases for this fix are in TH3. (check-in: fa94b49e user: drh tags: trunk) | |
Changes to src/build.c.
︙ | ︙ | |||
221 222 223 224 225 226 227 | } } /* Get the VDBE program ready for execution */ if( v && pParse->nErr==0 && !db->mallocFailed ){ | < | 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | } } /* Get the VDBE program ready for execution */ if( v && pParse->nErr==0 && !db->mallocFailed ){ /* A minimum of one cursor is required if autoincrement is used * See ticket [a696379c1f08866] */ if( pParse->pAinc!=0 && pParse->nTab==0 ) pParse->nTab = 1; sqlite3VdbeMakeReady(v, pParse); pParse->rc = SQLITE_DONE; }else{ pParse->rc = SQLITE_ERROR; |
︙ | ︙ |
Changes to src/delete.c.
︙ | ︙ | |||
459 460 461 462 463 464 465 | for(i=0; i<nPk; i++){ assert( pPk->aiColumn[i]>=0 ); sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, pPk->aiColumn[i], iPk+i); } iKey = iPk; }else{ | | | < | 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 | for(i=0; i<nPk; i++){ assert( pPk->aiColumn[i]>=0 ); sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, pPk->aiColumn[i], iPk+i); } iKey = iPk; }else{ iKey = ++pParse->nMem; sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, -1, iKey); } if( eOnePass!=ONEPASS_OFF ){ /* For ONEPASS, no need to store the rowid/primary-key. There is only ** one, so just keep it in its register(s) and fall through to the ** delete code. */ nKey = nPk; /* OP_Found will use an unpacked key */ |
︙ | ︙ | |||
894 895 896 897 898 899 900 | int regBase; int nCol; if( piPartIdxLabel ){ if( pIdx->pPartIdxWhere ){ *piPartIdxLabel = sqlite3VdbeMakeLabel(v); pParse->iSelfTab = iDataCur + 1; | < | 893 894 895 896 897 898 899 900 901 902 903 904 905 906 | int regBase; int nCol; if( piPartIdxLabel ){ if( pIdx->pPartIdxWhere ){ *piPartIdxLabel = sqlite3VdbeMakeLabel(v); pParse->iSelfTab = iDataCur + 1; sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel, SQLITE_JUMPIFNULL); pParse->iSelfTab = 0; }else{ *piPartIdxLabel = 0; } } |
︙ | ︙ | |||
941 942 943 944 945 946 947 | ** If a prior call to sqlite3GenerateIndexKey() generated a jump-over label ** because it was a partial index, then this routine should be called to ** resolve that label. */ void sqlite3ResolvePartIdxLabel(Parse *pParse, int iLabel){ if( iLabel ){ sqlite3VdbeResolveLabel(pParse->pVdbe, iLabel); | < | 939 940 941 942 943 944 945 946 947 | ** If a prior call to sqlite3GenerateIndexKey() generated a jump-over label ** because it was a partial index, then this routine should be called to ** resolve that label. */ void sqlite3ResolvePartIdxLabel(Parse *pParse, int iLabel){ if( iLabel ){ sqlite3VdbeResolveLabel(pParse->pVdbe, iLabel); } } |
Changes to src/expr.c.
︙ | ︙ | |||
577 578 579 580 581 582 583 | regRight = exprCodeSubselect(pParse, pRight); for(i=0; 1 /*Loop exits by "break"*/; i++){ int regFree1 = 0, regFree2 = 0; Expr *pL, *pR; int r1, r2; assert( i>=0 && i<nLeft ); | < < | 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 | regRight = exprCodeSubselect(pParse, pRight); for(i=0; 1 /*Loop exits by "break"*/; i++){ int regFree1 = 0, regFree2 = 0; Expr *pL, *pR; int r1, r2; assert( i>=0 && i<nLeft ); r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, ®Free1); r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, ®Free2); codeCompare(pParse, pL, pR, opx, r1, r2, dest, p5); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); sqlite3ReleaseTempReg(pParse, regFree1); sqlite3ReleaseTempReg(pParse, regFree2); if( i==nLeft-1 ){ break; } if( opx==TK_EQ ){ sqlite3VdbeAddOp2(v, OP_IfNot, dest, addrDone); VdbeCoverage(v); p5 |= SQLITE_KEEPNULL; }else if( opx==TK_NE ){ |
︙ | ︙ | |||
2623 2624 2625 2626 2627 2628 2629 | int rHasNullFlag, /* Register that records whether NULLs exist in RHS */ int isRowid /* If true, LHS of IN operator is a rowid */ ){ int jmpIfDynamic = -1; /* One-time test address */ int rReg = 0; /* Register storing resulting */ Vdbe *v = sqlite3GetVdbe(pParse); if( NEVER(v==0) ) return 0; | < | 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 | int rHasNullFlag, /* Register that records whether NULLs exist in RHS */ int isRowid /* If true, LHS of IN operator is a rowid */ ){ int jmpIfDynamic = -1; /* One-time test address */ int rReg = 0; /* Register storing resulting */ Vdbe *v = sqlite3GetVdbe(pParse); if( NEVER(v==0) ) return 0; /* The evaluation of the IN/EXISTS/SELECT must be repeated every time it ** is encountered if any of the following is true: ** ** * The right-hand side is a correlated subquery ** * The right-hand side is an expression list containing variables ** * We are inside a trigger |
︙ | ︙ | |||
2759 2760 2761 2762 2763 2764 2765 | if( isRowid ){ sqlite3VdbeAddOp2(v, OP_MustBeInt, r3, sqlite3VdbeCurrentAddr(v)+2); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3); }else{ sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1); | < | 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 | if( isRowid ){ sqlite3VdbeAddOp2(v, OP_MustBeInt, r3, sqlite3VdbeCurrentAddr(v)+2); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3); }else{ sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1); sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pExpr->iTable, r2, r3, 1); } } } sqlite3ReleaseTempReg(pParse, r1); sqlite3ReleaseTempReg(pParse, r2); } |
︙ | ︙ | |||
2840 2841 2842 2843 2844 2845 2846 | if( rHasNullFlag ){ sqlite3SetHasNullFlag(v, pExpr->iTable, rHasNullFlag); } if( jmpIfDynamic>=0 ){ sqlite3VdbeJumpHere(v, jmpIfDynamic); } | < | 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 | if( rHasNullFlag ){ sqlite3SetHasNullFlag(v, pExpr->iTable, rHasNullFlag); } if( jmpIfDynamic>=0 ){ sqlite3VdbeJumpHere(v, jmpIfDynamic); } return rReg; } #endif /* SQLITE_OMIT_SUBQUERY */ #ifndef SQLITE_OMIT_SUBQUERY /* |
︙ | ︙ | |||
2959 2960 2961 2962 2963 2964 2965 | ** at r1. ** ** sqlite3FindInIndex() might have reordered the fields of the LHS vector ** so that the fields are in the same order as an existing index. The ** aiMap[] array contains a mapping from the original LHS field order to ** the field order that matches the RHS index. */ | < | 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 | ** at r1. ** ** sqlite3FindInIndex() might have reordered the fields of the LHS vector ** so that the fields are in the same order as an existing index. The ** aiMap[] array contains a mapping from the original LHS field order to ** the field order that matches the RHS index. */ rLhsOrig = exprCodeVector(pParse, pLeft, &iDummy); for(i=0; i<nVector && aiMap[i]==i; i++){} /* Are LHS fields reordered? */ if( i==nVector ){ /* LHS fields are not reordered */ rLhs = rLhsOrig; }else{ /* Need to reorder the LHS fields according to aiMap */ |
︙ | ︙ | |||
3118 3119 3120 3121 3122 3123 3124 | } /* Jumps here in order to return true. */ sqlite3VdbeJumpHere(v, addrTruthOp); sqlite3ExprCodeIN_finished: if( rLhs!=rLhsOrig ) sqlite3ReleaseTempReg(pParse, rLhs); | < | 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 | } /* Jumps here in order to return true. */ sqlite3VdbeJumpHere(v, addrTruthOp); sqlite3ExprCodeIN_finished: if( rLhs!=rLhsOrig ) sqlite3ReleaseTempReg(pParse, rLhs); VdbeComment((v, "end IN expr")); sqlite3ExprCodeIN_oom_error: sqlite3DbFree(pParse->db, aiMap); sqlite3DbFree(pParse->db, zAff); } #endif /* SQLITE_OMIT_SUBQUERY */ |
︙ | ︙ | |||
3186 3187 3188 3189 3190 3191 3192 | }else{ if( negFlag ){ value = c==3 ? SMALLEST_INT64 : -value; } sqlite3VdbeAddOp4Dup8(v, OP_Int64, 0, iMem, 0, (u8*)&value, P4_INT64); } } } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 | }else{ if( negFlag ){ value = c==3 ? SMALLEST_INT64 : -value; } sqlite3VdbeAddOp4Dup8(v, OP_Int64, 0, iMem, 0, (u8*)&value, P4_INT64); } } } /* Generate code that will load into register regOut a value that is ** appropriate for the iIdxCol-th column of index pIdx. */ void sqlite3ExprCodeLoadIndexColumn( Parse *pParse, /* The parsing context */ Index *pIdx, /* The index whose column is to be loaded */ |
︙ | ︙ | |||
3387 3388 3389 3390 3391 3392 3393 | if( iCol>=0 ){ sqlite3ColumnDefault(v, pTab, iCol, regOut); } } /* ** Generate code that will extract the iColumn-th column from | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < | 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 | if( iCol>=0 ){ sqlite3ColumnDefault(v, pTab, iCol, regOut); } } /* ** Generate code that will extract the iColumn-th column from ** table pTab and store the column value in register iReg. ** ** There must be an open cursor to pTab in iTable when this routine ** is called. If iColumn<0 then code is generated that extracts the rowid. */ int sqlite3ExprCodeGetColumn( Parse *pParse, /* Parsing and code generating context */ Table *pTab, /* Description of the table we are reading from */ int iColumn, /* Index of the table column */ int iTable, /* The cursor pointing to the table */ int iReg, /* Store results here */ u8 p5 /* P5 value for OP_Column + FLAGS */ ){ Vdbe *v = pParse->pVdbe; assert( v!=0 ); sqlite3ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg); if( p5 ){ sqlite3VdbeChangeP5(v, p5); } return iReg; } /* ** Generate code to move content from registers iFrom...iFrom+nReg-1 ** over to iTo..iTo+nReg-1. */ void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){ assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo ); sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg); } /* ** Convert a scalar expression node to a TK_REGISTER referencing ** register iReg. The caller must ensure that iReg already contains ** the correct value for the expression. */ static void exprToRegister(Expr *p, int iReg){ |
︙ | ︙ | |||
3679 3680 3681 3682 3683 3684 3685 | inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); if( inReg!=target ){ sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target); inReg = target; } sqlite3VdbeAddOp2(v, OP_Cast, target, sqlite3AffinityType(pExpr->u.zToken, 0)); | < < | 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 | inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); if( inReg!=target ){ sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target); inReg = target; } sqlite3VdbeAddOp2(v, OP_Cast, target, sqlite3AffinityType(pExpr->u.zToken, 0)); return inReg; } #endif /* SQLITE_OMIT_CAST */ case TK_IS: case TK_ISNOT: op = (op==TK_IS) ? TK_EQ : TK_NE; p5 = SQLITE_NULLEQ; |
︙ | ︙ | |||
3866 3867 3868 3869 3870 3871 3872 | if( pDef->funcFlags & SQLITE_FUNC_COALESCE ){ int endCoalesce = sqlite3VdbeMakeLabel(v); assert( nFarg>=2 ); sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target); for(i=1; i<nFarg; i++){ sqlite3VdbeAddOp2(v, OP_NotNull, target, endCoalesce); VdbeCoverage(v); | < < < | 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 | if( pDef->funcFlags & SQLITE_FUNC_COALESCE ){ int endCoalesce = sqlite3VdbeMakeLabel(v); assert( nFarg>=2 ); sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target); for(i=1; i<nFarg; i++){ sqlite3VdbeAddOp2(v, OP_NotNull, target, endCoalesce); VdbeCoverage(v); sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target); } sqlite3VdbeResolveLabel(v, endCoalesce); break; } /* The UNLIKELY() function is a no-op. The result is the value ** of the first argument. |
︙ | ︙ | |||
3935 3936 3937 3938 3939 3940 3941 | assert( SQLITE_FUNC_TYPEOF==OPFLAG_TYPEOFARG ); testcase( pDef->funcFlags & OPFLAG_LENGTHARG ); pFarg->a[0].pExpr->op2 = pDef->funcFlags & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG); } } | < < | 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 | assert( SQLITE_FUNC_TYPEOF==OPFLAG_TYPEOFARG ); testcase( pDef->funcFlags & OPFLAG_LENGTHARG ); pFarg->a[0].pExpr->op2 = pDef->funcFlags & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG); } } sqlite3ExprCodeExprList(pParse, pFarg, r1, 0, SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR); }else{ r1 = 0; } #ifndef SQLITE_OMIT_VIRTUALTABLE /* Possibly overload the function if the first argument is ** a virtual table column. ** |
︙ | ︙ | |||
4111 4112 4113 4114 4115 4116 4117 | sqlite3ErrorMsg(pParse, "row value misused"); break; } case TK_IF_NULL_ROW: { int addrINR; addrINR = sqlite3VdbeAddOp1(v, OP_IfNullRow, pExpr->iTable); | < < | 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 | sqlite3ErrorMsg(pParse, "row value misused"); break; } case TK_IF_NULL_ROW: { int addrINR; addrINR = sqlite3VdbeAddOp1(v, OP_IfNullRow, pExpr->iTable); inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); sqlite3VdbeJumpHere(v, addrINR); sqlite3VdbeChangeP3(v, addrINR, inReg); break; } /* ** Form A: |
︙ | ︙ | |||
4150 4151 4152 4153 4154 4155 4156 | int nExpr; /* 2x number of WHEN terms */ int i; /* Loop counter */ ExprList *pEList; /* List of WHEN terms */ struct ExprList_item *aListelem; /* Array of WHEN terms */ Expr opCompare; /* The X==Ei expression */ Expr *pX; /* The X expression */ Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */ | < | 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 | int nExpr; /* 2x number of WHEN terms */ int i; /* Loop counter */ ExprList *pEList; /* List of WHEN terms */ struct ExprList_item *aListelem; /* Array of WHEN terms */ Expr opCompare; /* The X==Ei expression */ Expr *pX; /* The X expression */ Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */ assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList ); assert(pExpr->x.pList->nExpr > 0); pEList = pExpr->x.pList; aListelem = pEList->a; nExpr = pEList->nExpr; endLabel = sqlite3VdbeMakeLabel(v); |
︙ | ︙ | |||
4174 4175 4176 4177 4178 4179 4180 | /* Ticket b351d95f9cd5ef17e9d9dbae18f5ca8611190001: ** The value in regFree1 might get SCopy-ed into the file result. ** So make sure that the regFree1 register is not reused for other ** purposes and possibly overwritten. */ regFree1 = 0; } for(i=0; i<nExpr-1; i=i+2){ | < < < < < < | 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 | /* Ticket b351d95f9cd5ef17e9d9dbae18f5ca8611190001: ** The value in regFree1 might get SCopy-ed into the file result. ** So make sure that the regFree1 register is not reused for other ** purposes and possibly overwritten. */ regFree1 = 0; } for(i=0; i<nExpr-1; i=i+2){ if( pX ){ assert( pTest!=0 ); opCompare.pRight = aListelem[i].pExpr; }else{ pTest = aListelem[i].pExpr; } nextCase = sqlite3VdbeMakeLabel(v); testcase( pTest->op==TK_COLUMN ); sqlite3ExprIfFalse(pParse, pTest, nextCase, SQLITE_JUMPIFNULL); testcase( aListelem[i+1].pExpr->op==TK_COLUMN ); sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target); sqlite3VdbeGoto(v, endLabel); sqlite3VdbeResolveLabel(v, nextCase); } if( (nExpr&1)!=0 ){ sqlite3ExprCode(pParse, pEList->a[nExpr-1].pExpr, target); }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, target); } sqlite3VdbeResolveLabel(v, endLabel); break; } #ifndef SQLITE_OMIT_TRIGGER case TK_RAISE: { assert( pExpr->affinity==OE_Rollback || pExpr->affinity==OE_Abort |
︙ | ︙ | |||
4556 4557 4558 4559 4560 4561 4562 | if( NEVER(pExpr==0) ) return; /* No way this can happen */ op = pExpr->op; switch( op ){ case TK_AND: { int d2 = sqlite3VdbeMakeLabel(v); testcase( jumpIfNull==0 ); sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL); | < < < < | 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 | if( NEVER(pExpr==0) ) return; /* No way this can happen */ op = pExpr->op; switch( op ){ case TK_AND: { int d2 = sqlite3VdbeMakeLabel(v); testcase( jumpIfNull==0 ); sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL); sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); sqlite3VdbeResolveLabel(v, d2); break; } case TK_OR: { testcase( jumpIfNull==0 ); sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); break; } case TK_NOT: { testcase( jumpIfNull==0 ); sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); break; } |
︙ | ︙ | |||
4726 4727 4728 4729 4730 4731 4732 | assert( pExpr->op!=TK_GT || op==OP_Le ); assert( pExpr->op!=TK_GE || op==OP_Lt ); switch( pExpr->op ){ case TK_AND: { testcase( jumpIfNull==0 ); sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); | < < < < | 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 | assert( pExpr->op!=TK_GT || op==OP_Le ); assert( pExpr->op!=TK_GE || op==OP_Lt ); switch( pExpr->op ){ case TK_AND: { testcase( jumpIfNull==0 ); sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); break; } case TK_OR: { int d2 = sqlite3VdbeMakeLabel(v); testcase( jumpIfNull==0 ); sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL); sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); sqlite3VdbeResolveLabel(v, d2); break; } case TK_NOT: { testcase( jumpIfNull==0 ); sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); break; } |
︙ | ︙ | |||
5506 5507 5508 5509 5510 5511 5512 | } return pParse->aTempReg[--pParse->nTempReg]; } /* ** Deallocate a register, making available for reuse for some other ** purpose. | < < < < < < < < < < < < < < | 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 | } return pParse->aTempReg[--pParse->nTempReg]; } /* ** Deallocate a register, making available for reuse for some other ** purpose. */ void sqlite3ReleaseTempReg(Parse *pParse, int iReg){ if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){ pParse->aTempReg[pParse->nTempReg++] = iReg; } } /* ** Allocate or deallocate a block of nReg consecutive registers. */ int sqlite3GetTempRange(Parse *pParse, int nReg){ int i, n; if( nReg==1 ) return sqlite3GetTempReg(pParse); i = pParse->iRangeReg; n = pParse->nRangeReg; if( nReg<=n ){ pParse->iRangeReg += nReg; pParse->nRangeReg -= nReg; }else{ i = pParse->nMem+1; pParse->nMem += nReg; } return i; } void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){ if( nReg==1 ){ sqlite3ReleaseTempReg(pParse, iReg); return; } if( nReg>pParse->nRangeReg ){ pParse->nRangeReg = nReg; pParse->iRangeReg = iReg; } } /* |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
1529 1530 1531 1532 1533 1534 1535 | /* Check to see if the new rowid already exists in the table. Skip ** the following conflict logic if it does not. */ VdbeNoopComment((v, "uniqueness check for ROWID")); sqlite3VdbeVerifyAbortable(v, onError); sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData); VdbeCoverage(v); | < | 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 | /* Check to see if the new rowid already exists in the table. Skip ** the following conflict logic if it does not. */ VdbeNoopComment((v, "uniqueness check for ROWID")); sqlite3VdbeVerifyAbortable(v, onError); sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData); VdbeCoverage(v); switch( onError ){ default: { onError = OE_Abort; /* Fall thru into the next case */ } case OE_Rollback: |
︙ | ︙ | |||
1606 1607 1608 1609 1610 1611 1612 | #endif case OE_Ignore: { testcase( onError==OE_Ignore ); sqlite3VdbeGoto(v, ignoreDest); break; } } | < | 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 | #endif case OE_Ignore: { testcase( onError==OE_Ignore ); sqlite3VdbeGoto(v, ignoreDest); break; } } sqlite3VdbeResolveLabel(v, addrRowidOk); if( sAddr.ipkTop ){ sAddr.ipkBtm = sqlite3VdbeAddOp0(v, OP_Goto); sqlite3VdbeJumpHere(v, sAddr.ipkTop-1); } } |
︙ | ︙ | |||
1740 1741 1742 1743 1744 1745 1746 | (0==pTab->pFKey && 0==sqlite3FkReferences(pTab))) ){ sqlite3VdbeResolveLabel(v, addrUniqueOk); continue; } /* Check to see if the new index entry will be unique */ | < | 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 | (0==pTab->pFKey && 0==sqlite3FkReferences(pTab))) ){ sqlite3VdbeResolveLabel(v, addrUniqueOk); continue; } /* Check to see if the new index entry will be unique */ sqlite3VdbeVerifyAbortable(v, onError); sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk, regIdx, pIdx->nKeyCol); VdbeCoverage(v); /* Generate code to handle collisions */ regR = (pIdx==pPk) ? regIdx : sqlite3GetTempRange(pParse, nPkField); if( isUpdate || onError==OE_Replace ){ |
︙ | ︙ | |||
1846 1847 1848 1849 1850 1851 1852 | } } if( pUpIdx==pIdx ){ sqlite3VdbeJumpHere(v, upsertBypass); }else{ sqlite3VdbeResolveLabel(v, addrUniqueOk); } | < | 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 | } } if( pUpIdx==pIdx ){ sqlite3VdbeJumpHere(v, upsertBypass); }else{ sqlite3VdbeResolveLabel(v, addrUniqueOk); } if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField); } testcase( sAddr.ipkTop!=0 ); testcase( sAddr.upsertTop && sqlite3VdbeLabelHasBeenResolved(v,sAddr.upsertTop) ); reorderConstraintChecks(v, &sAddr); |
︙ | ︙ | |||
1950 1951 1952 1953 1954 1955 1956 | if( !HasRowid(pTab) ) return; regData = regNewData + 1; regRec = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec); sqlite3SetMakeRecordP5(v, pTab); if( !bAffinityDone ){ sqlite3TableAffinity(v, pTab, 0); | < | 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 | if( !HasRowid(pTab) ) return; regData = regNewData + 1; regRec = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec); sqlite3SetMakeRecordP5(v, pTab); if( !bAffinityDone ){ sqlite3TableAffinity(v, pTab, 0); } if( pParse->nested ){ pik_flags = 0; }else{ pik_flags = OPFLAG_NCHANGE; pik_flags |= (update_flags?update_flags:OPFLAG_LASTROWID); } |
︙ | ︙ |
Changes to src/pragma.c.
︙ | ︙ | |||
1546 1547 1548 1549 1550 1551 1552 | Index *pPrior = 0; int loopTop; int iDataCur, iIdxCur; int r1 = -1; if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */ pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); | < | 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 | Index *pPrior = 0; int loopTop; int iDataCur, iIdxCur; int r1 = -1; if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */ pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0, 1, 0, &iDataCur, &iIdxCur); /* reg[7] counts the number of entries in the table. ** reg[8+i] counts the number of entries in the i-th index */ sqlite3VdbeAddOp2(v, OP_Integer, 0, 7); for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ |
︙ | ︙ | |||
1589 1590 1591 1592 1593 1594 1595 | ExprList *pCheck = sqlite3ExprListDup(db, pTab->pCheck, 0); if( db->mallocFailed==0 ){ int addrCkFault = sqlite3VdbeMakeLabel(v); int addrCkOk = sqlite3VdbeMakeLabel(v); char *zErr; int k; pParse->iSelfTab = iDataCur + 1; | < < | 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 | ExprList *pCheck = sqlite3ExprListDup(db, pTab->pCheck, 0); if( db->mallocFailed==0 ){ int addrCkFault = sqlite3VdbeMakeLabel(v); int addrCkOk = sqlite3VdbeMakeLabel(v); char *zErr; int k; pParse->iSelfTab = iDataCur + 1; for(k=pCheck->nExpr-1; k>0; k--){ sqlite3ExprIfFalse(pParse, pCheck->a[k].pExpr, addrCkFault, 0); } sqlite3ExprIfTrue(pParse, pCheck->a[0].pExpr, addrCkOk, SQLITE_JUMPIFNULL); sqlite3VdbeResolveLabel(v, addrCkFault); pParse->iSelfTab = 0; zErr = sqlite3MPrintf(db, "CHECK constraint failed in %s", pTab->zName); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); integrityCheckResultRow(v); sqlite3VdbeResolveLabel(v, addrCkOk); } sqlite3ExprListDelete(db, pCheck); } if( !isQuick ){ /* Omit the remaining tests for quick_check */ /* Validate index entries for the current row */ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ int jmp2, jmp3, jmp4, jmp5; |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
1145 1146 1147 1148 1149 1150 1151 | pushOntoSorter( pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg); }else{ int r1 = sqlite3GetTempReg(pParse); assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol ); sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol, r1, pDest->zAffSdst, nResultCol); | < | 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 | pushOntoSorter( pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg); }else{ int r1 = sqlite3GetTempReg(pParse); assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol ); sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol, r1, pDest->zAffSdst, nResultCol); sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol); sqlite3ReleaseTempReg(pParse, r1); } break; } /* If any row exist in the result set, record that fact and abort. |
︙ | ︙ | |||
1189 1190 1191 1192 1193 1194 1195 | if( pSort ){ pushOntoSorter(pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg); }else if( eDest==SRT_Coroutine ){ sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); }else{ sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nResultCol); | < | 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 | if( pSort ){ pushOntoSorter(pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg); }else if( eDest==SRT_Coroutine ){ sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); }else{ sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nResultCol); } break; } #ifndef SQLITE_OMIT_CTE /* Write the results into a priority queue that is order according to ** pDest->pOrderBy (in pSO). pDest->iSDParm (in iParm) is the cursor for an |
︙ | ︙ | |||
1546 1547 1548 1549 1550 1551 1552 | break; } #ifndef SQLITE_OMIT_SUBQUERY case SRT_Set: { assert( nColumn==sqlite3Strlen30(pDest->zAffSdst) ); sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, nColumn, regRowid, pDest->zAffSdst, nColumn); | < < | 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 | break; } #ifndef SQLITE_OMIT_SUBQUERY case SRT_Set: { assert( nColumn==sqlite3Strlen30(pDest->zAffSdst) ); sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, nColumn, regRowid, pDest->zAffSdst, nColumn); sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, regRowid, regRow, nColumn); break; } case SRT_Mem: { /* The LIMIT clause will terminate the loop for us */ break; } #endif default: { assert( eDest==SRT_Output || eDest==SRT_Coroutine ); testcase( eDest==SRT_Output ); testcase( eDest==SRT_Coroutine ); if( eDest==SRT_Output ){ sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iSdst, nColumn); }else{ sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); } break; } } if( regRowid ){ |
︙ | ︙ | |||
2162 2163 2164 2165 2166 2167 2168 | /* ** "LIMIT -1" always shows all rows. There is some ** controversy about what the correct behavior should be. ** The current implementation interprets "LIMIT 0" to mean ** no rows. */ | < | 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 | /* ** "LIMIT -1" always shows all rows. There is some ** controversy about what the correct behavior should be. ** The current implementation interprets "LIMIT 0" to mean ** no rows. */ if( pLimit ){ assert( pLimit->op==TK_LIMIT ); assert( pLimit->pLeft!=0 ); p->iLimit = iLimit = ++pParse->nMem; v = sqlite3GetVdbe(pParse); assert( v!=0 ); if( sqlite3ExprIsInteger(pLimit->pLeft, &n) ){ |
︙ | ︙ | |||
2948 2949 2950 2951 2952 2953 2954 | */ case SRT_Set: { int r1; testcase( pIn->nSdst>1 ); r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1, pDest->zAffSdst, pIn->nSdst); | < | 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 | */ case SRT_Set: { int r1; testcase( pIn->nSdst>1 ); r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1, pDest->zAffSdst, pIn->nSdst); sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1, pIn->iSdst, pIn->nSdst); sqlite3ReleaseTempReg(pParse, r1); break; } /* If this is a scalar select that is part of an expression, then |
︙ | ︙ | |||
2991 2992 2993 2994 2995 2996 2997 | ** For SRT_Output, results are stored in a sequence of registers. ** Then the OP_ResultRow opcode is used to cause sqlite3_step() to ** return the next row of result. */ default: { assert( pDest->eDest==SRT_Output ); sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iSdst, pIn->nSdst); | < | 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 | ** For SRT_Output, results are stored in a sequence of registers. ** Then the OP_ResultRow opcode is used to cause sqlite3_step() to ** return the next row of result. */ default: { assert( pDest->eDest==SRT_Output ); sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iSdst, pIn->nSdst); break; } } /* Jump to the end of the loop if the LIMIT is reached. */ if( p->iLimit ){ |
︙ | ︙ | |||
5332 5333 5334 5335 5336 5337 5338 | } if( regHit==0 && pAggInfo->nAccumulator ) regHit = ++pParse->nMem; sqlite3VdbeAddOp4(v, OP_CollSeq, regHit, 0, 0, (char *)pColl, P4_COLLSEQ); } sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, pF->iMem); sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF); sqlite3VdbeChangeP5(v, (u8)nArg); | < < < < < < < < < < < < < < < | 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 | } if( regHit==0 && pAggInfo->nAccumulator ) regHit = ++pParse->nMem; sqlite3VdbeAddOp4(v, OP_CollSeq, regHit, 0, 0, (char *)pColl, P4_COLLSEQ); } sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, pF->iMem); sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF); sqlite3VdbeChangeP5(v, (u8)nArg); sqlite3ReleaseTempRange(pParse, regAgg, nArg); if( addrNext ){ sqlite3VdbeResolveLabel(v, addrNext); } } if( regHit==0 && pAggInfo->nAccumulator ){ regHit = regAcc; } if( regHit ){ addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit); VdbeCoverage(v); } for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){ sqlite3ExprCode(pParse, pC->pExpr, pC->iMem); } pAggInfo->directMode = 0; if( addrHitTest ){ sqlite3VdbeJumpHere(v, addrHitTest); } } /* ** Add a single OP_Explain instruction to the VDBE to explain a simple |
︙ | ︙ | |||
6314 6315 6316 6317 6318 6319 6320 | for(i=0; i<sAggInfo.nColumn; i++){ if( sAggInfo.aCol[i].iSorterColumn>=j ){ nCol++; j++; } } regBase = sqlite3GetTempRange(pParse, nCol); | < | | < < | 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 | for(i=0; i<sAggInfo.nColumn; i++){ if( sAggInfo.aCol[i].iSorterColumn>=j ){ nCol++; j++; } } regBase = sqlite3GetTempRange(pParse, nCol); sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0, 0); j = nGroupBy; for(i=0; i<sAggInfo.nColumn; i++){ struct AggInfo_col *pCol = &sAggInfo.aCol[i]; if( pCol->iSorterColumn>=j ){ int r1 = j + regBase; sqlite3ExprCodeGetColumnOfTable(v, pCol->pTab, pCol->iTable, pCol->iColumn, r1); j++; } } regRecord = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord); sqlite3VdbeAddOp2(v, OP_SorterInsert, sAggInfo.sortingIdx, regRecord); sqlite3ReleaseTempReg(pParse, regRecord); sqlite3ReleaseTempRange(pParse, regBase, nCol); sqlite3WhereEnd(pWInfo); sAggInfo.sortingIdxPTab = sortPTab = pParse->nTab++; sortOut = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol); sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd); VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v); sAggInfo.useSortingIdx = 1; } /* If the index or temporary table used by the GROUP BY sort ** will naturally deliver rows in the order required by the ORDER BY ** clause, cancel the ephemeral table open coded earlier. ** ** This is an optimization - the correct answer should result regardless. |
︙ | ︙ | |||
6362 6363 6364 6365 6366 6367 6368 | /* Evaluate the current GROUP BY terms and store in b0, b1, b2... ** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth) ** Then compare the current GROUP BY terms against the GROUP BY terms ** from the previous row currently stored in a0, a1, a2... */ addrTopOfLoop = sqlite3VdbeCurrentAddr(v); | < | 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 | /* Evaluate the current GROUP BY terms and store in b0, b1, b2... ** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth) ** Then compare the current GROUP BY terms against the GROUP BY terms ** from the previous row currently stored in a0, a1, a2... */ addrTopOfLoop = sqlite3VdbeCurrentAddr(v); if( groupBySort ){ sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx, sortOut, sortPTab); } for(j=0; j<pGroupBy->nExpr; j++){ if( groupBySort ){ sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j); |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
363 364 365 366 367 368 369 | #if !defined(NDEBUG) && !defined(SQLITE_DEBUG) # define NDEBUG 1 #endif #if defined(NDEBUG) && defined(SQLITE_DEBUG) # undef NDEBUG #endif | < < < < < < < < < < < | 363 364 365 366 367 368 369 370 371 372 373 374 375 376 | #if !defined(NDEBUG) && !defined(SQLITE_DEBUG) # define NDEBUG 1 #endif #if defined(NDEBUG) && defined(SQLITE_DEBUG) # undef NDEBUG #endif /* ** Enable SQLITE_ENABLE_EXPLAIN_COMMENTS if SQLITE_DEBUG is turned on. */ #if !defined(SQLITE_ENABLE_EXPLAIN_COMMENTS) && defined(SQLITE_DEBUG) # define SQLITE_ENABLE_EXPLAIN_COMMENTS 1 #endif |
︙ | ︙ | |||
1565 1566 1567 1568 1569 1570 1571 | /* ** Bits of the sqlite3.dbOptFlags field that are used by the ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to ** selectively disable various optimizations. */ #define SQLITE_QueryFlattener 0x0001 /* Query flattening */ | | | 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 | /* ** Bits of the sqlite3.dbOptFlags field that are used by the ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to ** selectively disable various optimizations. */ #define SQLITE_QueryFlattener 0x0001 /* Query flattening */ /* 0x0002 available for reuse */ #define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */ #define SQLITE_FactorOutConst 0x0008 /* Constant factoring */ #define SQLITE_DistinctOpt 0x0010 /* DISTINCT using indexes */ #define SQLITE_CoverIdxScan 0x0020 /* Covering index scans */ #define SQLITE_OrderByIdxJoin 0x0040 /* ORDER BY of joins via index */ #define SQLITE_Transitive 0x0080 /* Transitive constraints */ #define SQLITE_OmitNoopJoin 0x0100 /* Omit unused tables in joins */ |
︙ | ︙ | |||
2964 2965 2966 2967 2968 2969 2970 | struct AutoincInfo { AutoincInfo *pNext; /* Next info block in a list of them all */ Table *pTab; /* Table this info block refers to */ int iDb; /* Index in sqlite3.aDb[] of database holding pTab */ int regCtr; /* Memory register holding the rowid counter */ }; | < < < < < < < | 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 | struct AutoincInfo { AutoincInfo *pNext; /* Next info block in a list of them all */ Table *pTab; /* Table this info block refers to */ int iDb; /* Index in sqlite3.aDb[] of database holding pTab */ int regCtr; /* Memory register holding the rowid counter */ }; /* ** At least one instance of the following structure is created for each ** trigger that may be fired while parsing an INSERT, UPDATE or DELETE ** statement. All such objects are stored in the linked list headed at ** Parse.pTriggerPrg and deleted once statement compilation has been ** completed. ** |
︙ | ︙ | |||
3046 3047 3048 3049 3050 3051 3052 | u8 nested; /* Number of nested calls to the parser/code generator */ u8 nTempReg; /* Number of temporary registers in aTempReg[] */ u8 isMultiWrite; /* True if statement may modify/insert multiple rows */ u8 mayAbort; /* True if statement may throw an ABORT exception */ u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ u8 okConstFactor; /* OK to factor out constants */ u8 disableLookaside; /* Number of times lookaside has been disabled */ | < < < | 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 | u8 nested; /* Number of nested calls to the parser/code generator */ u8 nTempReg; /* Number of temporary registers in aTempReg[] */ u8 isMultiWrite; /* True if statement may modify/insert multiple rows */ u8 mayAbort; /* True if statement may throw an ABORT exception */ u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ u8 okConstFactor; /* OK to factor out constants */ u8 disableLookaside; /* Number of times lookaside has been disabled */ int nRangeReg; /* Size of the temporary register block */ int iRangeReg; /* First register in temporary register block */ int nErr; /* Number of errors seen */ int nTab; /* Number of previously allocated VDBE cursors */ int nMem; /* Number of memory cells used so far */ int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */ int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */ int iSelfTab; /* Table associated with an index on expr, or negative ** of the base register during check-constraint eval */ int nLabel; /* Number of labels used */ int *aLabel; /* Space to hold the labels */ ExprList *pConstExpr;/* Constant expressions */ Token constraintName;/* Name of the constraint currently being parsed */ yDbMask writeMask; /* Start a write transaction on these databases */ yDbMask cookieMask; /* Bitmask of schema verified databases */ int regRowid; /* Register holding rowid of CREATE TABLE entry */ |
︙ | ︙ | |||
3087 3088 3089 3090 3091 3092 3093 | u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ u8 disableTriggers; /* True to disable triggers */ /************************************************************************** ** Fields above must be initialized to zero. The fields that follow, ** down to the beginning of the recursive section, do not need to be ** initialized as they will be set before being used. The boundary is | | < < < < < < < < | 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 | u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ u8 disableTriggers; /* True to disable triggers */ /************************************************************************** ** Fields above must be initialized to zero. The fields that follow, ** down to the beginning of the recursive section, do not need to be ** initialized as they will be set before being used. The boundary is ** determined by offsetof(Parse,aTempReg). **************************************************************************/ int aTempReg[8]; /* Holding area for temporary registers */ Token sNameToken; /* Token with unqualified schema object name */ /************************************************************************ ** Above is constant between recursions. Below is reset before and after ** each recursion. The boundary between these two regions is determined ** using offsetof(Parse,sLastToken) so the sLastToken field must be the |
︙ | ︙ | |||
3139 3140 3141 3142 3143 3144 3145 | With *pWith; /* Current WITH clause, or NULL */ With *pWithToFree; /* Free this WITH object at the end of the parse */ }; /* ** Sizes and pointers of various parts of the Parse object. */ | | | 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 | With *pWith; /* Current WITH clause, or NULL */ With *pWithToFree; /* Free this WITH object at the end of the parse */ }; /* ** Sizes and pointers of various parts of the Parse object. */ #define PARSE_HDR_SZ offsetof(Parse,aTempReg) /* Recursive part w/o aColCache*/ #define PARSE_RECURSE_SZ offsetof(Parse,sLastToken) /* Recursive part */ #define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */ #define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ) /* Pointer to tail */ /* ** Return true if currently inside an sqlite3_declare_vtab() call. */ |
︙ | ︙ | |||
3923 3924 3925 3926 3927 3928 3929 | int sqlite3WhereBreakLabel(WhereInfo*); int sqlite3WhereOkOnePass(WhereInfo*, int*); #define ONEPASS_OFF 0 /* Use of ONEPASS not allowed */ #define ONEPASS_SINGLE 1 /* ONEPASS valid for a single row update */ #define ONEPASS_MULTI 2 /* ONEPASS is valid for multiple rows */ void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int); int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8); | < < < < < < < | 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 | int sqlite3WhereBreakLabel(WhereInfo*); int sqlite3WhereOkOnePass(WhereInfo*, int*); #define ONEPASS_OFF 0 /* Use of ONEPASS not allowed */ #define ONEPASS_SINGLE 1 /* ONEPASS valid for a single row update */ #define ONEPASS_MULTI 2 /* ONEPASS is valid for multiple rows */ void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int); int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8); void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int); void sqlite3ExprCodeMove(Parse*, int, int, int); void sqlite3ExprCode(Parse*, Expr*, int); void sqlite3ExprCodeCopy(Parse*, Expr*, int); void sqlite3ExprCodeFactorable(Parse*, Expr*, int); int sqlite3ExprCodeAtInit(Parse*, Expr*, int); int sqlite3ExprCodeTemp(Parse*, Expr*, int*); int sqlite3ExprCodeTarget(Parse*, Expr*, int); void sqlite3ExprCodeAndCache(Parse*, Expr*, int); |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
6978 6979 6980 6981 6982 6983 6984 | static const struct { const char *zOptName; int mask; } aOpt[] = { { "all", SQLITE_AllOpts }, { "none", 0 }, { "query-flattener", SQLITE_QueryFlattener }, | < | 6978 6979 6980 6981 6982 6983 6984 6985 6986 6987 6988 6989 6990 6991 | static const struct { const char *zOptName; int mask; } aOpt[] = { { "all", SQLITE_AllOpts }, { "none", 0 }, { "query-flattener", SQLITE_QueryFlattener }, { "groupby-order", SQLITE_GroupByOrder }, { "factor-constants", SQLITE_FactorOutConst }, { "distinct-opt", SQLITE_DistinctOpt }, { "cover-idx-scan", SQLITE_CoverIdxScan }, { "order-by-idx-join", SQLITE_OrderByIdxJoin }, { "transitive", SQLITE_Transitive }, { "omit-noop-join", SQLITE_OmitNoopJoin }, |
︙ | ︙ |
Changes to src/update.c.
︙ | ︙ | |||
606 607 608 609 610 611 612 | /* This branch loads the value of a column that will not be changed ** into a register. This is done if there are no BEFORE triggers, or ** if there are one or more BEFORE triggers that use this value via ** a new.* reference in a trigger program. */ testcase( i==31 ); testcase( i==32 ); | | < < < < < < | 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 | /* This branch loads the value of a column that will not be changed ** into a register. This is done if there are no BEFORE triggers, or ** if there are one or more BEFORE triggers that use this value via ** a new.* reference in a trigger program. */ testcase( i==31 ); testcase( i==32 ); sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i); }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); } } } /* Fire any BEFORE UPDATE triggers. This happens before constraints are |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
32 33 34 35 36 37 38 | */ #ifdef SQLITE_DEBUG # define memAboutToChange(P,M) sqlite3VdbeMemAboutToChange(P,M) #else # define memAboutToChange(P,M) #endif | < < < < < < < < < < < < | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | */ #ifdef SQLITE_DEBUG # define memAboutToChange(P,M) sqlite3VdbeMemAboutToChange(P,M) #else # define memAboutToChange(P,M) #endif /* ** The following global variable is incremented every time a cursor ** moves, either by the OP_SeekXX, OP_Next, or OP_Prev opcodes. The test ** procedures use this information to make sure that indices are ** working correctly. This variable has no function other than to ** help verify the correct operation of the library. */ |
︙ | ︙ | |||
1304 1305 1306 1307 1308 1309 1310 | assert( pOut!=pIn1 ); while( 1 ){ memAboutToChange(p, pOut); sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); Deephemeralize(pOut); #ifdef SQLITE_DEBUG pOut->pScopyFrom = 0; | < | 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 | assert( pOut!=pIn1 ); while( 1 ){ memAboutToChange(p, pOut); sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); Deephemeralize(pOut); #ifdef SQLITE_DEBUG pOut->pScopyFrom = 0; #endif REGISTER_TRACE(pOp->p2+pOp->p3-n, pOut); if( (n--)==0 ) break; pOut++; pIn1++; } break; |
︙ | ︙ | |||
1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 | case OP_Gt: /* same as TK_GT, jump, in1, in3 */ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ int res, res2; /* Result of the comparison of pIn1 against pIn3 */ char affinity; /* Affinity to use for comparison */ u16 flags1; /* Copy of initial value of pIn1->flags */ u16 flags3; /* Copy of initial value of pIn3->flags */ pIn1 = &aMem[pOp->p1]; pIn3 = &aMem[pOp->p3]; flags1 = pIn1->flags; flags3 = pIn3->flags; if( (flags1 | flags3)&MEM_Null ){ /* One or both operands are NULL */ if( pOp->p5 & SQLITE_NULLEQ ){ | > > > > > | 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 | case OP_Gt: /* same as TK_GT, jump, in1, in3 */ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ int res, res2; /* Result of the comparison of pIn1 against pIn3 */ char affinity; /* Affinity to use for comparison */ u16 flags1; /* Copy of initial value of pIn1->flags */ u16 flags3; /* Copy of initial value of pIn3->flags */ /* The only way for P1 and P3 to be the same is when comparing constants. ** But in that case, the affinities will always be SQLITE_AFF_BLOB or none */ assert( pOp->p1!=pOp->p3 || (pOp->p5 & SQLITE_AFF_MASK)<=SQLITE_AFF_BLOB ); testcase( pOp->p1==pOp->p3 ); pIn1 = &aMem[pOp->p1]; pIn3 = &aMem[pOp->p3]; flags1 = pIn1->flags; flags3 = pIn3->flags; if( (flags1 | flags3)&MEM_Null ){ /* One or both operands are NULL */ if( pOp->p5 & SQLITE_NULLEQ ){ |
︙ | ︙ | |||
1968 1969 1970 1971 1972 1973 1974 | }else{ /* Neither operand is NULL. Do a comparison. */ affinity = pOp->p5 & SQLITE_AFF_MASK; if( affinity>=SQLITE_AFF_NUMERIC ){ if( (flags1 | flags3)&MEM_Str ){ if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ applyNumericAffinity(pIn1,0); | | > > > > | 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 | }else{ /* Neither operand is NULL. Do a comparison. */ affinity = pOp->p5 & SQLITE_AFF_MASK; if( affinity>=SQLITE_AFF_NUMERIC ){ if( (flags1 | flags3)&MEM_Str ){ if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ applyNumericAffinity(pIn1,0); /* testcase( flags3!=pIn3->flags ); ** this used to be possible with pIn1==pIn3, but not since ** the column cache was removed. The following assignment ** is essentially a no-op. But, it prevents defense-in-depth ** in case our analysis is incorrect, so it is left in. */ flags3 = pIn3->flags; } if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ applyNumericAffinity(pIn3,0); } } /* Handle the common case of integer comparison here, as an |
︙ | ︙ | |||
7440 7441 7442 7443 7444 7445 7446 | ** An Abort is safe if either there have been no writes, or if there is ** an active statement journal. */ case OP_Abortable: { sqlite3VdbeAssertAbortable(p); break; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 7436 7437 7438 7439 7440 7441 7442 7443 7444 7445 7446 7447 7448 7449 | ** An Abort is safe if either there have been no writes, or if there is ** an active statement journal. */ case OP_Abortable: { sqlite3VdbeAssertAbortable(p); break; } #endif /* Opcode: Noop * * * * * ** ** Do nothing. This instruction is often useful as a jump ** destination. */ |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
207 208 209 210 211 212 213 | u32 uTemp; /* Transient storage for serial_type in OP_MakeRecord */ sqlite3 *db; /* The associated database connection */ void (*xDel)(void*);/* Destructor for Mem.z - only valid if MEM_Dyn */ #ifdef SQLITE_DEBUG Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */ u16 mScopyFlags; /* flags value immediately after the shallow copy */ #endif | < < < < | 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | u32 uTemp; /* Transient storage for serial_type in OP_MakeRecord */ sqlite3 *db; /* The associated database connection */ void (*xDel)(void*);/* Destructor for Mem.z - only valid if MEM_Dyn */ #ifdef SQLITE_DEBUG Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */ u16 mScopyFlags; /* flags value immediately after the shallow copy */ #endif }; /* ** Size of struct Mem not including the Mem.zMalloc member or anything that ** follows. */ #define MEMCELLSIZE offsetof(Mem,zMalloc) |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
968 969 970 971 972 973 974 | /* .uTemp = */ (u32)0, /* .db = */ (sqlite3*)0, /* .xDel = */ (void(*)(void*))0, #ifdef SQLITE_DEBUG /* .pScopyFrom = */ (Mem*)0, /* .mScopyFlags= */ 0, #endif | < < < | 968 969 970 971 972 973 974 975 976 977 978 979 980 981 | /* .uTemp = */ (u32)0, /* .db = */ (sqlite3*)0, /* .xDel = */ (void(*)(void*))0, #ifdef SQLITE_DEBUG /* .pScopyFrom = */ (Mem*)0, /* .mScopyFlags= */ 0, #endif }; return &nullMem; } /* ** Check to see if column iCol of the given statement is valid. If ** it is, return a pointer to the Mem for the value of that column. |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
189 190 191 192 193 194 195 | pOp->p4.p = 0; pOp->p4type = P4_NOTUSED; #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS pOp->zComment = 0; #endif #ifdef SQLITE_DEBUG if( p->db->flags & SQLITE_VdbeAddopTrace ){ | < < < < < < < < | 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | pOp->p4.p = 0; pOp->p4type = P4_NOTUSED; #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS pOp->zComment = 0; #endif #ifdef SQLITE_DEBUG if( p->db->flags & SQLITE_VdbeAddopTrace ){ sqlite3VdbePrintOp(0, i, &p->aOp[i]); test_addop_breakpoint(); } #endif #ifdef VDBE_PROFILE pOp->cycles = 0; pOp->cnt = 0; |
︙ | ︙ | |||
1643 1644 1645 1646 1647 1648 1649 | while( (N--)>0 ){ p->db = db; p->flags = flags; p->szMalloc = 0; #ifdef SQLITE_DEBUG p->pScopyFrom = 0; #endif | < < < | 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 | while( (N--)>0 ){ p->db = db; p->flags = flags; p->szMalloc = 0; #ifdef SQLITE_DEBUG p->pScopyFrom = 0; #endif p++; } } /* ** Release an array of N Mem elements */ |
︙ | ︙ |
Changes to src/vdbemem.c.
︙ | ︙ | |||
930 931 932 933 934 935 936 | /* pMem is the register that is changing. But also mark pX as ** undefined so that we can quickly detect the shallow-copy error */ pX->flags = MEM_Undefined; pX->pScopyFrom = 0; } } pMem->pScopyFrom = 0; | < < < < < < < < < | 930 931 932 933 934 935 936 937 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 968 969 970 971 972 973 974 975 976 977 978 979 980 | /* pMem is the register that is changing. But also mark pX as ** undefined so that we can quickly detect the shallow-copy error */ pX->flags = MEM_Undefined; pX->pScopyFrom = 0; } } pMem->pScopyFrom = 0; } #endif /* SQLITE_DEBUG */ /* ** Make an shallow copy of pFrom into pTo. Prior contents of ** pTo are freed. The pFrom->z field is not duplicated. If ** pFrom->z is used, then pTo->z points to the same thing as pFrom->z ** and flags gets srcType (either MEM_Ephem or MEM_Static). */ static SQLITE_NOINLINE void vdbeClrCopy(Mem *pTo, const Mem *pFrom, int eType){ vdbeMemClearExternAndSetNull(pTo); assert( !VdbeMemDynamic(pTo) ); sqlite3VdbeMemShallowCopy(pTo, pFrom, eType); } void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){ assert( (pFrom->flags & MEM_RowSet)==0 ); assert( pTo->db==pFrom->db ); if( VdbeMemDynamic(pTo) ){ vdbeClrCopy(pTo,pFrom,srcType); return; } memcpy(pTo, pFrom, MEMCELLSIZE); if( (pFrom->flags&MEM_Static)==0 ){ pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem); assert( srcType==MEM_Ephem || srcType==MEM_Static ); pTo->flags |= srcType; } } /* ** Make a full copy of pFrom into pTo. Prior contents of pTo are ** freed before the copy is made. */ int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){ int rc = SQLITE_OK; assert( (pFrom->flags & MEM_RowSet)==0 ); if( VdbeMemDynamic(pTo) ) vdbeMemClearExternAndSetNull(pTo); memcpy(pTo, pFrom, MEMCELLSIZE); pTo->flags &= ~MEM_Dyn; if( pTo->flags&(MEM_Str|MEM_Blob) ){ if( 0==(pFrom->flags&MEM_Static) ){ pTo->flags |= MEM_Ephem; rc = sqlite3VdbeMemMakeWriteable(pTo); } } |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
798 799 800 801 802 803 804 | assert( pLevel->iIdxCur>=0 ); pLevel->iIdxCur = pParse->nTab++; sqlite3VdbeAddOp2(v, OP_OpenAutoindex, pLevel->iIdxCur, nKeyCol+1); sqlite3VdbeSetP4KeyInfo(pParse, pIdx); VdbeComment((v, "for %s", pTable->zName)); /* Fill the automatic index with content */ | < | 798 799 800 801 802 803 804 805 806 807 808 809 810 811 | assert( pLevel->iIdxCur>=0 ); pLevel->iIdxCur = pParse->nTab++; sqlite3VdbeAddOp2(v, OP_OpenAutoindex, pLevel->iIdxCur, nKeyCol+1); sqlite3VdbeSetP4KeyInfo(pParse, pIdx); VdbeComment((v, "for %s", pTable->zName)); /* Fill the automatic index with content */ pTabItem = &pWC->pWInfo->pTabList->a[pLevel->iFrom]; if( pTabItem->fg.viaCoroutine ){ int regYield = pTabItem->regReturn; addrCounter = sqlite3VdbeAddOp2(v, OP_Integer, 0, 0); sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub); addrTop = sqlite3VdbeAddOp1(v, OP_Yield, regYield); VdbeCoverage(v); |
︙ | ︙ | |||
835 836 837 838 839 840 841 | pTabItem->fg.viaCoroutine = 0; }else{ sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v); } sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX); sqlite3VdbeJumpHere(v, addrTop); sqlite3ReleaseTempReg(pParse, regRecord); | < | 834 835 836 837 838 839 840 841 842 843 844 845 846 847 | pTabItem->fg.viaCoroutine = 0; }else{ sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v); } sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX); sqlite3VdbeJumpHere(v, addrTop); sqlite3ReleaseTempReg(pParse, regRecord); /* Jump here when skipping the initialization */ sqlite3VdbeJumpHere(v, addrInit); end_auto_index_create: sqlite3ExprDelete(pParse->db, pPartial); } |
︙ | ︙ | |||
5073 5074 5075 5076 5077 5078 5079 | WhereLoop *pLoop; SrcList *pTabList = pWInfo->pTabList; sqlite3 *db = pParse->db; /* Generate loop termination code. */ VdbeModuleComment((v, "End WHERE-core")); | < | 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 | WhereLoop *pLoop; SrcList *pTabList = pWInfo->pTabList; sqlite3 *db = pParse->db; /* Generate loop termination code. */ VdbeModuleComment((v, "End WHERE-core")); for(i=pWInfo->nLevel-1; i>=0; i--){ int addr; pLevel = &pWInfo->a[i]; pLoop = pLevel->pWLoop; if( pLevel->op!=OP_Noop ){ #ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT int addrSeek = 0; |
︙ | ︙ |
Changes to src/wherecode.c.
︙ | ︙ | |||
343 344 345 346 347 348 349 | while( n>1 && zAff[n-1]==SQLITE_AFF_BLOB ){ n--; } /* Code the OP_Affinity opcode if there is anything left to do. */ if( n>0 ){ sqlite3VdbeAddOp4(v, OP_Affinity, base, n, 0, zAff, n); | < | 343 344 345 346 347 348 349 350 351 352 353 354 355 356 | while( n>1 && zAff[n-1]==SQLITE_AFF_BLOB ){ n--; } /* Code the OP_Affinity opcode if there is anything left to do. */ if( n>0 ){ sqlite3VdbeAddOp4(v, OP_Affinity, base, n, 0, zAff, n); } } /* ** Expression pRight, which is the RHS of a comparison operation, is ** either a vector of n elements or, if n==1, a scalar expression. ** Before the comparison operation, affinity zAff is to be applied |
︙ | ︙ | |||
1252 1253 1254 1255 1256 1257 1258 | ** to access the data. */ int iReg; /* P3 Value for OP_VFilter */ int addrNotFound; int nConstraint = pLoop->nLTerm; int iIn; /* Counter for IN constraints */ | < | 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 | ** to access the data. */ int iReg; /* P3 Value for OP_VFilter */ int addrNotFound; int nConstraint = pLoop->nLTerm; int iIn; /* Counter for IN constraints */ iReg = sqlite3GetTempRange(pParse, nConstraint+2); addrNotFound = pLevel->addrBrk; for(j=0; j<nConstraint; j++){ int iTarget = iReg+j+2; pTerm = pLoop->aLTerm[j]; if( NEVER(pTerm==0) ) continue; if( pTerm->eOperator & WO_IN ){ |
︙ | ︙ | |||
1325 1326 1327 1328 1329 1330 1331 | /* These registers need to be preserved in case there is an IN operator ** loop. So we could deallocate the registers here (and potentially ** reuse them later) if (pLoop->wsFlags & WHERE_IN_ABLE)==0. But it seems ** simpler and safer to simply not reuse the registers. ** ** sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2); */ | < | 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 | /* These registers need to be preserved in case there is an IN operator ** loop. So we could deallocate the registers here (and potentially ** reuse them later) if (pLoop->wsFlags & WHERE_IN_ABLE)==0. But it seems ** simpler and safer to simply not reuse the registers. ** ** sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2); */ }else #endif /* SQLITE_OMIT_VIRTUALTABLE */ if( (pLoop->wsFlags & WHERE_IPK)!=0 && (pLoop->wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_EQ))!=0 ){ /* Case 2: We can directly reference a single row using an |
︙ | ︙ | |||
1418 1419 1420 1421 1422 1423 1424 | } sqlite3VdbeAddOp3(v, op, iCur, addrBrk, r1); VdbeComment((v, "pk")); VdbeCoverageIf(v, pX->op==TK_GT); VdbeCoverageIf(v, pX->op==TK_LE); VdbeCoverageIf(v, pX->op==TK_LT); VdbeCoverageIf(v, pX->op==TK_GE); | < | 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 | } sqlite3VdbeAddOp3(v, op, iCur, addrBrk, r1); VdbeComment((v, "pk")); VdbeCoverageIf(v, pX->op==TK_GT); VdbeCoverageIf(v, pX->op==TK_LE); VdbeCoverageIf(v, pX->op==TK_LT); VdbeCoverageIf(v, pX->op==TK_GE); sqlite3ReleaseTempReg(pParse, rTemp); }else{ sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrHalt); VdbeCoverageIf(v, bRev==0); VdbeCoverageIf(v, bRev!=0); } if( pEnd ){ |
︙ | ︙ | |||
1453 1454 1455 1456 1457 1458 1459 | pLevel->op = bRev ? OP_Prev : OP_Next; pLevel->p1 = iCur; pLevel->p2 = start; assert( pLevel->p5==0 ); if( testOp!=OP_Noop ){ iRowidReg = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg); | < | 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 | pLevel->op = bRev ? OP_Prev : OP_Next; pLevel->p1 = iCur; pLevel->p2 = start; assert( pLevel->p5==0 ); if( testOp!=OP_Noop ){ iRowidReg = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg); sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg); VdbeCoverageIf(v, testOp==OP_Le); VdbeCoverageIf(v, testOp==OP_Lt); VdbeCoverageIf(v, testOp==OP_Ge); VdbeCoverageIf(v, testOp==OP_Gt); sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL); } |
︙ | ︙ | |||
1679 1680 1681 1682 1683 1684 1685 | /* Load the value for the inequality constraint at the end of the ** range (if any). */ nConstraint = nEq; if( pRangeEnd ){ Expr *pRight = pRangeEnd->pExpr->pRight; | < | 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 | /* Load the value for the inequality constraint at the end of the ** range (if any). */ nConstraint = nEq; if( pRangeEnd ){ Expr *pRight = pRangeEnd->pExpr->pRight; codeExprOrVector(pParse, pRight, regBase+nEq, nTop); whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd); if( (pRangeEnd->wtFlags & TERM_VNULL)==0 && sqlite3ExprCanBeNull(pRight) ){ sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); VdbeCoverage(v); |
︙ | ︙ | |||
1704 1705 1706 1707 1708 1709 1710 | if( sqlite3ExprIsVector(pRight)==0 ){ disableTerm(pLevel, pRangeEnd); }else{ endEq = 1; } }else if( bStopAtNull ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); | < | 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 | if( sqlite3ExprIsVector(pRight)==0 ){ disableTerm(pLevel, pRangeEnd); }else{ endEq = 1; } }else if( bStopAtNull ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); endEq = 0; nConstraint++; } sqlite3DbFree(db, zStartAff); sqlite3DbFree(db, zEndAff); /* Top of the loop body */ |
︙ | ︙ | |||
1738 1739 1740 1741 1742 1743 1744 | }else if( HasRowid(pIdx->pTable) ){ if( (pWInfo->wctrlFlags & WHERE_SEEK_TABLE) || ( (pWInfo->wctrlFlags & WHERE_SEEK_UNIQ_TABLE) && (pWInfo->eOnePass==ONEPASS_SINGLE) )){ iRowidReg = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg); | < | 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 | }else if( HasRowid(pIdx->pTable) ){ if( (pWInfo->wctrlFlags & WHERE_SEEK_TABLE) || ( (pWInfo->wctrlFlags & WHERE_SEEK_UNIQ_TABLE) && (pWInfo->eOnePass==ONEPASS_SINGLE) )){ iRowidReg = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg); sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg); VdbeCoverage(v); }else{ codeDeferredSeek(pWInfo, pIdx, iCur, iIdxCur); } }else if( iCur!=iIdxCur ){ Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable); |
︙ | ︙ | |||
1973 1974 1975 1976 1977 1978 1979 | /* This is the sub-WHERE clause body. First skip over ** duplicate rows from prior sub-WHERE clauses, and record the ** rowid (or PRIMARY KEY) for the current row so that the same ** row will be skipped in subsequent sub-WHERE clauses. */ if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){ | < | | > | | 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 | /* This is the sub-WHERE clause body. First skip over ** duplicate rows from prior sub-WHERE clauses, and record the ** rowid (or PRIMARY KEY) for the current row so that the same ** row will be skipped in subsequent sub-WHERE clauses. */ if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){ int iSet = ((ii==pOrWc->nTerm-1)?-1:ii); if( HasRowid(pTab) ){ sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, -1, regRowid); jmp1 = sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, 0, regRowid, iSet); VdbeCoverage(v); }else{ Index *pPk = sqlite3PrimaryKeyIndex(pTab); int nPk = pPk->nKeyCol; int iPk; int r; /* Read the PK into an array of temp registers. */ r = sqlite3GetTempRange(pParse, nPk); for(iPk=0; iPk<nPk; iPk++){ int iCol = pPk->aiColumn[iPk]; sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol, r+iPk); } /* Check if the temp table already contains this key. If so, ** the row has already been included in the result set and ** can be ignored (by jumping past the Gosub below). Otherwise, ** insert the key into the temp table and proceed with processing ** the row. |
︙ | ︙ | |||
2222 2223 2224 2225 2226 2227 2228 | /* For a LEFT OUTER JOIN, generate code that will record the fact that ** at least one row of the right table has matched the left table. */ if( pLevel->iLeftJoin ){ pLevel->addrFirst = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin); VdbeComment((v, "record LEFT JOIN hit")); | < | 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 | /* For a LEFT OUTER JOIN, generate code that will record the fact that ** at least one row of the right table has matched the left table. */ if( pLevel->iLeftJoin ){ pLevel->addrFirst = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin); VdbeComment((v, "record LEFT JOIN hit")); for(pTerm=pWC->a, j=0; j<pWC->nTerm; j++, pTerm++){ testcase( pTerm->wtFlags & TERM_VIRTUAL ); testcase( pTerm->wtFlags & TERM_CODED ); if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( (pTerm->prereqAll & pLevel->notReady)!=0 ){ assert( pWInfo->untestedTerms ); continue; |
︙ | ︙ |
Changes to test/btree02.test.
︙ | ︙ | |||
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | INSERT INTO t3(cnt) SELECT i FROM c; SELECT count(*) FROM t1; } {10} do_test btree02-110 { db eval BEGIN set i 0 db eval {SELECT a, ax, b, cnt FROM t1 CROSS JOIN t3 WHERE b IS NOT NULL} { db eval {INSERT INTO t2(x,y) VALUES($b,$cnt)} # puts "a,b,cnt = ($a,$b,$cnt)" incr i if {$i%2==1} { set bx [expr {$b+1000}] # puts "INSERT ($a),$bx" db eval {INSERT INTO t1(a,ax,b) VALUES(printf('(%s)',$a),random(),$bx)} } else { # puts "DELETE a=$a" db eval {DELETE FROM t1 WHERE a=$a} } db eval {COMMIT; BEGIN} } db one {COMMIT; SELECT count(*) FROM t1;} | > > | | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | INSERT INTO t3(cnt) SELECT i FROM c; SELECT count(*) FROM t1; } {10} do_test btree02-110 { db eval BEGIN set i 0 db eval {SELECT a, ax, b, cnt FROM t1 CROSS JOIN t3 WHERE b IS NOT NULL} { if {$a==""} {set a 0} if {$b==""} {set b 0} db eval {INSERT INTO t2(x,y) VALUES($b,$cnt)} # puts "a,b,cnt = ($a,$b,$cnt)" incr i if {$i%2==1} { set bx [expr {$b+1000}] # puts "INSERT ($a),$bx" db eval {INSERT INTO t1(a,ax,b) VALUES(printf('(%s)',$a),random(),$bx)} } else { # puts "DELETE a=$a" db eval {DELETE FROM t1 WHERE a=$a} } db eval {COMMIT; BEGIN} } db one {COMMIT; SELECT count(*) FROM t1;} } {27} finish_test |