Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Improvements to IN operator code generator comments. Avoid unnecessary Copy operations on the LHS of the IN operator. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | rowvalue |
Files: | files | file ages | folders |
SHA1: |
b6344298783a1207cba3f635939ddc9b |
User & Date: | drh 2016-08-25 15:46:25.026 |
Context
2016-08-25
| ||
17:40 | Further refinement of the in-operator.md documentation. (check-in: df0648373a user: drh tags: rowvalue) | |
15:46 | Improvements to IN operator code generator comments. Avoid unnecessary Copy operations on the LHS of the IN operator. (check-in: b634429878 user: drh tags: rowvalue) | |
14:23 | Corrections to the IN-operator notes. (check-in: 25033ee945 user: drh tags: rowvalue) | |
Changes
Changes to src/expr.c.
︙ | ︙ | |||
2633 2634 2635 2636 2637 2638 2639 | #ifndef SQLITE_OMIT_SUBQUERY /* ** Generate code for an IN expression. ** ** x IN (SELECT ...) ** x IN (value, value, ...) ** | | | | | | > > > | | | | < < | < < > > > > > > > > > < > > > > > > > | | > | 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 | #ifndef SQLITE_OMIT_SUBQUERY /* ** Generate code for an IN expression. ** ** x IN (SELECT ...) ** x IN (value, value, ...) ** ** The left-hand side (LHS) is a scalar or vector expression. The ** right-hand side (RHS) is an array of zero or more values. The IN operator ** is true if the LHS is contained within the RHS. The result is false ** if the LHS is definitely not in the RHS. The result is NULL if the presence ** of the LHS in the RHS cannot be determined due to NULLs. ** ** This routine generates code that jumps to destIfFalse if the LHS is not ** contained within the RHS. If due to NULLs we cannot determine if the LHS ** is contained in the RHS then jump to destIfNull. If the LHS is contained ** within the RHS then fall through. ** ** See the separate in-operator.md documentation file in the canonical ** SQLite source tree for additional information. */ static void sqlite3ExprCodeIN( Parse *pParse, /* Parsing and code generating context */ Expr *pExpr, /* The IN expression */ int destIfFalse, /* Jump here if LHS is not contained in the RHS */ int destIfNull /* Jump here if the results are unknown due to NULLs */ ){ int rRhsHasNull = 0; /* Register that is true if RHS contains NULL values */ int eType; /* Type of the RHS */ int r1, r2; /* Temporary use registers */ Vdbe *v; /* Statement under construction */ int *aiMap = 0; /* Map from vector field to index column */ char *zAff = 0; /* Affinity string for comparisons */ int nVector; /* Size of vectors for this IN operator */ int iDummy; /* Dummy parameter to exprCodeVector() */ Expr *pLeft = pExpr->pLeft; /* The LHS of the IN operator */ int i; /* loop counter */ if( sqlite3ExprCheckIN(pParse, pExpr) ) return; zAff = exprINAffinity(pParse, pExpr); nVector = sqlite3ExprVectorSize(pExpr->pLeft); aiMap = (int*)sqlite3DbMallocZero( pParse->db, nVector*(sizeof(int) + sizeof(char)) + 1 ); if( pParse->db->mallocFailed ) goto end_code_IN_op; /* Attempt to compute the RHS. After this step, if anything other than ** IN_INDEX_NOOP is returned, the table opened ith cursor pExpr->iTable ** contains the values that make up the RHS. If IN_INDEX_NOOP is returned, ** the RHS has not yet been coded. */ v = pParse->pVdbe; assert( v!=0 ); /* OOM detected prior to this routine */ VdbeNoopComment((v, "begin IN expr")); eType = sqlite3FindInIndex(pParse, pExpr, IN_INDEX_MEMBERSHIP | IN_INDEX_NOOP_OK, destIfFalse==destIfNull ? 0 : &rRhsHasNull, aiMap); assert( pParse->nErr || nVector==1 || eType==IN_INDEX_EPH || eType==IN_INDEX_INDEX_ASC || eType==IN_INDEX_INDEX_DESC ); #ifdef SQLITE_DEBUG /* Confirm that aiMap[] contains nVector integer values between 0 and ** nVector-1. */ for(i=0; i<nVector; i++){ int j, cnt; for(cnt=j=0; j<nVector; j++) if( aiMap[j]==i ) cnt++; assert( cnt==1 ); } #endif /* Code the LHS, the <expr> from "<expr> IN (...)". If the LHS is a ** vector, then it is stored in an array of nVector registers starting ** at r1. */ sqlite3ExprCachePush(pParse); r2 = exprCodeVector(pParse, pLeft, &iDummy); for(i=0; i<nVector && aiMap[i]==i; i++){} if( i==nVector ){ /* LHS fields are already in the correct order */ r1 = r2; }else{ /* Need to reorder the LHS fields according to aiMap */ r1 = sqlite3GetTempRange(pParse, nVector); for(i=0; i<nVector; i++){ sqlite3VdbeAddOp3(v, OP_Copy, r2+i, r1+aiMap[i], 0); } } /* If sqlite3FindInIndex() did not find or create an index that is ** suitable for evaluating the IN operator, then evaluate using a ** sequence of comparisons. */ if( eType==IN_INDEX_NOOP ){ |
︙ | ︙ | |||
2857 2858 2859 2860 2861 2862 2863 | sqlite3VdbeAddOp2(v, OP_IsNull, rRhsHasNull, destIfNull); VdbeCoverage(v); sqlite3VdbeGoto(v, destIfFalse); sqlite3VdbeJumpHere(v, addr1); } } } | | > > < | 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 | sqlite3VdbeAddOp2(v, OP_IsNull, rRhsHasNull, destIfNull); VdbeCoverage(v); sqlite3VdbeGoto(v, destIfFalse); sqlite3VdbeJumpHere(v, addr1); } } } if( r2!=r1 ) sqlite3ReleaseTempReg(pParse, r1); sqlite3ExprCachePop(pParse); VdbeComment((v, "end IN expr")); end_code_IN_op: sqlite3DbFree(pParse->db, aiMap); sqlite3DbFree(pParse->db, zAff); } #endif /* SQLITE_OMIT_SUBQUERY */ #ifndef SQLITE_OMIT_FLOATING_POINT /* ** Generate an instruction that will put the floating point ** value described by z[0..n-1] into register iMem. |
︙ | ︙ |