]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Change the way TK_SELECT_COLUMN is handled so that the subquery is only
authordrh <drh@noemail.net>
Sat, 20 Aug 2016 00:07:01 +0000 (00:07 +0000)
committerdrh <drh@noemail.net>
Sat, 20 Aug 2016 00:07:01 +0000 (00:07 +0000)
generated once even if part of the vector comparison is used for indexing
and the other part is now.  This change also is a pathway to vector assignment
in UPDATE statements.

FossilOrigin-Name: d8feea7dcde83179bff303072426561cfe825e58

manifest
manifest.uuid
src/expr.c
src/sqliteInt.h
src/vdbemem.c
src/wherecode.c
src/whereexpr.c

index 760f93473cab68c1e3785c2b305b2b59d7876967..52c2870784e158f64ed9a748dbdaea12587c683a 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Replace\sthe\smagic\snumber\s(-2)\swith\sits\ssymbol\sXN_EXPR\sin\sthe\nexprMightBeIndexed()\sroutine.\s\sNo\slogic\schanges.
-D 2016-08-19T19:58:06.626
+C Change\sthe\sway\sTK_SELECT_COLUMN\sis\shandled\sso\sthat\sthe\ssubquery\sis\sonly\ngenerated\sonce\seven\sif\spart\sof\sthe\svector\scomparison\sis\sused\sfor\sindexing\nand\sthe\sother\spart\sis\snow.\s\sThis\schange\salso\sis\sa\spathway\sto\svector\sassignment\nin\sUPDATE\sstatements.
+D 2016-08-20T00:07:01.602
 F Makefile.in cfd8fb987cd7a6af046daa87daa146d5aad0e088
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc d66d0395c38571aab3804f8db0fa20707ae4609a
@@ -338,7 +338,7 @@ F src/ctime.c e77f3dc297b4b65c96da78b4ae4272fdfae863d7
 F src/date.c 95c9a8d00767e7221a8e9a31f4e913fc8029bf6b
 F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d
 F src/delete.c 76c084f0265f4a3cd1ecf17eee112a94f1ccbc05
-F src/expr.c e139851835a8532e3974ca4bc8f6b0e5aef0e06f
+F src/expr.c ff73eb6cae76c2423928d46ceff6f2fdc379a568
 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
 F src/fkey.c e2be0968c1adc679c87e467aa5b4f167588f38a8
 F src/func.c 29cc9acb170ec1387b9f63eb52cd85f8de96c771
@@ -389,7 +389,7 @@ F src/shell.c 79dda477be6c96eba6e952a934957ad36f87acc7
 F src/sqlite.h.in 0f7580280d1b009b507d8beec1ff0f197ba0cc99
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae
-F src/sqliteInt.h 02b7f4bd9f945fbc46b05f7914b9c43d89517c59
+F src/sqliteInt.h 84f32ad3a5bfaf698b82bf5a9c6939f3e3d79ee0
 F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
 F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
 F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9
@@ -456,7 +456,7 @@ F src/vdbeInt.h c59381049af5c7751a83456c39b80d1a6fde1f9d
 F src/vdbeapi.c a32d61b7dd05e6890d8fd44d2805f55e2f5ba9f3
 F src/vdbeaux.c a32d79aeaa88dc2b97c261172d952d395254a055
 F src/vdbeblob.c 3e82a797b60c3b9fed7b8de8c539ca7607874937
-F src/vdbemem.c 77d6505956bf4e45c328ab3ebef6b461334cab5d
+F src/vdbemem.c e67dc6d8177fd1830efb5d15e17793408251a187
 F src/vdbesort.c 91fda3909326860382b0ca8aa251e609c6a9d62c
 F src/vdbetrace.c 41963d5376f0349842b5fc4aaaaacd7d9cdc0834
 F src/vtab.c 5ca4fa8b028f9e2ed4793ee1670911a83cfcefd8
@@ -466,8 +466,8 @@ F src/wal.h 6dd221ed384afdc204bc61e25c23ef7fd5a511f2
 F src/walker.c 2d2cc7fb0f320f7f415215d7247f3c584141ac09
 F src/where.c c7cdfd54f383090bb801cdd50d36de1a24684bb2
 F src/whereInt.h 14dd243e13b81cbb0a66063d38b70f93a7d6e613
-F src/wherecode.c f3fd16b9b4cef1345330d22cf3f1628f87a56456
-F src/whereexpr.c bb22074cc2712c5013ecacdf7d652e7568a47bc3
+F src/wherecode.c 0c790c422ea5ecb6c83d6a78f2c4ebc036eea90e
+F src/whereexpr.c 021469f11930cc705a26f7f31ec37640588df1d4
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@@ -1518,7 +1518,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P acea4ee136def4815d22eec240c5903a72bde9bd
-R 223c403e8b392fa16a54efbf6c58e1ba
+P d4a5af69cc3bde6f8c02075c07b4d47a0252392d
+R 8a9288690d2190168e2ddd79f5078350
 U drh
-Z b5c0cabb5688d369770dffa65d09a7da
+Z 663c48e63b0d59d8fc6b403d2678eeeb
index 95b5affc2d0a1dc83ec4d7c1d3c069087467a14c..a8cf8cf3bcda1dd189396437881b7e9fc4b9c229 100644 (file)
@@ -1 +1 @@
-d4a5af69cc3bde6f8c02075c07b4d47a0252392d
\ No newline at end of file
+d8feea7dcde83179bff303072426561cfe825e58
\ No newline at end of file
index 1949be50afc02fdf1a1650c28310b60e77f5c604..de2c7a6a2675124575724b102b51520ad98319d8 100644 (file)
@@ -334,13 +334,21 @@ int sqlite3ExprVectorSize(Expr *pExpr){
 
 #ifndef SQLITE_OMIT_SUBQUERY
 /*
-** If the expression passed as the first argument is a TK_VECTOR, return
-** a pointer to the i'th field of the vector. Or, if the first argument
-** points to a sub-select that returns more than one column, return a 
-** pointer to the i'th returned column value. Otherwise, return a copy 
-** of the first argument.
+** Interpret the pVector input as a vector expression.  If pVector is
+** an ordinary scalar expression, treat it as a vector of size 1.
+**
+** Return a pointer to a subexpression of pVector that is the i-th
+** column of the vector (numbered starting with 0).  The caller must
+** ensure that i is within range.
+**
+** pVector retains ownership of the returned subexpression.
+**
+** If the vector is a (SELECT ...) then the expression returned is
+** just the expression for the i-th term of the result set, and is
+** necessarily ready to be evaluated because the table cursor might
+** not have been positioned yet.
 */
-Expr *sqlite3ExprVectorField(Expr *pVector, int i){
+Expr *sqlite3VectorFieldSubexpr(Expr *pVector, int i){
   assert( i<sqlite3ExprVectorSize(pVector) );
   if( sqlite3ExprIsVector(pVector) ){
     if( pVector->op==TK_SELECT ){
@@ -351,7 +359,57 @@ Expr *sqlite3ExprVectorField(Expr *pVector, int i){
   }
   return pVector;
 }
-#endif
+#endif /* !defined(SQLITE_OMIT_SUBQUERY) */
+
+#ifndef SQLITE_OMIT_SUBQUERY
+/*
+** Compute and return a new Expr object which when passed to
+** sqlite3ExprCode() will generate all necessary code to compute
+** the iField-th column of the vector expression pVector.
+**
+** The caller owns the returned Expr object and is responsible for
+** ensuring that the returned value eventually gets freed.
+**
+** Ownership of pVector is controlled by the takeOwnership parameter.  If
+** takeOwnership is true, this routine takes responsibility for freeing
+** pVector, and may do so before returning, hence the caller must not reference
+** pVector again.  If takeOwnership is false, then the caller takes
+** responsibility for freeing pVector and must ensure the pVector remains
+** valid as long as the returned value remains in use.
+*/
+Expr *sqlite3ExprForVectorField(
+  Parse *pParse,       /* Parsing context */
+  Expr *pVector,       /* The vector.  List of expressions or a sub-SELECT */
+  int iField,          /* Which column of the vector to return */
+  int takeOwnership    /* True to take ownership of pVector before returning */
+){
+  Expr *pRet;
+  assert( sqlite3ExprIsVector(pVector) );
+  /* FIXME: Add support for takeOwnership!=0 */ assert( takeOwnership==0 );
+  if( pVector->flags & EP_xIsSelect ){
+    /* The TK_SELECT_COLUMN Expr node:
+    **
+    ** pLeft:           pVector containing TK_SELECT
+    ** pRight:          pVector if ownership taken
+    ** iColumn:         Index of a column in pVector
+    ** pLeft->iTable:   First in an array of register holding result, or 0
+    **                  if the result is not yet computed.
+    **
+    ** sqlite3ExprDelete() specifically skips the recursive delete of
+    ** pLeft on TK_SELECT_COLUMN nodes.  But pRight is followed, so pVector
+    ** is included on pRight if ownership is taken.  Typically there will
+    ** be multiple TK_SELECT_COLUMN nodes with the same pLeft pointer to 
+    ** the pVector, but only one of them will own the pVector.
+    */
+    pRet = sqlite3PExpr(pParse, TK_SELECT_COLUMN, pVector, 0, 0);
+    if( pRet ) pRet->iColumn = iField;
+    assert( pRet==0 || pRet->iTable==0 );
+  }else{
+    pRet = sqlite3ExprDup(pParse->db, pVector->x.pList->a[iField].pExpr, 0);
+  }
+  return pRet;
+}
+#endif /* !define(SQLITE_OMIT_SUBQUERY) */
 
 /*
 ** If expression pExpr is of type TK_SELECT, generate code to evaluate
@@ -2025,7 +2083,7 @@ int sqlite3FindInIndex(
       ** comparison is the same as the affinity of each column. If
       ** it not, it is not possible to use any index.  */
       for(i=0; i<nExpr && affinity_ok; i++){
-        Expr *pLhs = sqlite3ExprVectorField(pX->pLeft, i);
+        Expr *pLhs = sqlite3VectorFieldSubexpr(pX->pLeft, i);
         int iCol = pEList->a[i].pExpr->iColumn;
         char idxaff = pTab->aCol[iCol].affinity;
         char cmpaff = sqlite3CompareAffinity(pLhs, idxaff);
@@ -2051,7 +2109,7 @@ int sqlite3FindInIndex(
         }
 
         for(i=0; i<nExpr; i++){
-          Expr *pLhs = sqlite3ExprVectorField(pX->pLeft, i);
+          Expr *pLhs = sqlite3VectorFieldSubexpr(pX->pLeft, i);
           Expr *pRhs = pEList->a[i].pExpr;
           CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
           int j;
@@ -2159,7 +2217,7 @@ static char *exprINAffinity(Parse *pParse, Expr *pExpr){
   if( zRet ){
     int i;
     for(i=0; i<nVal; i++){
-      Expr *pA = sqlite3ExprVectorField(pLeft, i);
+      Expr *pA = sqlite3VectorFieldSubexpr(pLeft, i);
       char a = sqlite3ExprAffinity(pA);
       if( pSelect ){
         zRet[i] = sqlite3CompareAffinity(pSelect->pEList->a[i].pExpr, a);
@@ -2313,7 +2371,7 @@ int sqlite3CodeSubselect(
           assert( pEList->nExpr>0 );
           assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
           for(i=0; i<nVal; i++){
-            Expr *p = (nVal>1) ? sqlite3ExprVectorField(pLeft, i) : pLeft;
+            Expr *p = (nVal>1) ? sqlite3VectorFieldSubexpr(pLeft, i) : pLeft;
             pKeyInfo->aColl[i] = sqlite3BinaryCompareCollSeq(
                 pParse, p, pEList->a[i].pExpr
             );
@@ -2553,7 +2611,7 @@ static void sqlite3ExprCodeIN(
     }
   }else{
     for(i=0; i<nVector; i++){
-      Expr *pLhs = sqlite3ExprVectorField(pLeft, i);
+      Expr *pLhs = sqlite3VectorFieldSubexpr(pLeft, i);
       sqlite3ExprCode(pParse, pLhs, r1+aiMap[i]);
     }
   }
@@ -2612,7 +2670,7 @@ static void sqlite3ExprCodeIN(
     ** completely empty, or NULL otherwise.  */
     if( destIfNull==destIfFalse ){
       for(i=0; i<nVector; i++){
-        Expr *p = sqlite3ExprVectorField(pExpr->pLeft, i);
+        Expr *p = sqlite3VectorFieldSubexpr(pExpr->pLeft, i);
         if( sqlite3ExprCanBeNull(p) ){
           sqlite3VdbeAddOp2(v, OP_IsNull, r1+aiMap[i], destIfNull);
           VdbeCoverage(v);
@@ -2654,7 +2712,7 @@ static void sqlite3ExprCodeIN(
           Expr *p;
           CollSeq *pColl;
           int r2 = sqlite3GetTempReg(pParse);
-          p = sqlite3ExprVectorField(pLeft, i);
+          p = sqlite3VectorFieldSubexpr(pLeft, i);
           pColl = sqlite3ExprCollSeq(pParse, p);
 
           sqlite3VdbeAddOp3(v, OP_Column, iIdx, i, r2);
@@ -2674,7 +2732,7 @@ static void sqlite3ExprCodeIN(
         ** result is 1.  */
         sqlite3VdbeJumpHere(v, addr);
         for(i=0; i<nVector; i++){
-          Expr *p = sqlite3ExprVectorField(pExpr->pLeft, i);
+          Expr *p = sqlite3VectorFieldSubexpr(pExpr->pLeft, i);
           if( sqlite3ExprCanBeNull(p) ){
             sqlite3VdbeAddOp2(v, OP_IsNull, r1+aiMap[i], destIfNull);
             VdbeCoverage(v);
@@ -3510,6 +3568,13 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
       }
       break;
     }
+    case TK_SELECT_COLUMN: {
+      if( pExpr->pLeft->iTable==0 ){
+        pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft, 0, 0);
+      }
+      inReg = pExpr->pLeft->iTable + pExpr->iColumn;
+      break;
+    }
     case TK_IN: {
       int destIfFalse = sqlite3VdbeMakeLabel(v);
       int destIfNull = sqlite3VdbeMakeLabel(v);
index 7b37b030cd42f9c9d817f8f1892df6d62df4f76c..7651ff69e4c1860123d2543dd1e02335d483c7ae 100644 (file)
@@ -2298,9 +2298,11 @@ struct Expr {
   int iTable;            /* TK_COLUMN: cursor number of table holding column
                          ** TK_REGISTER: register number
                          ** TK_TRIGGER: 1 -> new, 0 -> old
-                         ** EP_Unlikely:  134217728 times likelihood */
+                         ** EP_Unlikely:  134217728 times likelihood
+                         ** TK_SELECT: 1st register of result vector */
   ynVar iColumn;         /* TK_COLUMN: column index.  -1 for rowid.
-                         ** TK_VARIABLE: variable number (always >= 1). */
+                         ** TK_VARIABLE: variable number (always >= 1).
+                         ** TK_SELECT_COLUMN: column of the result vector */
   i16 iAgg;              /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
   i16 iRightJoinTable;   /* If EP_FromJoin, the right table of the join */
   u8 op2;                /* TK_REGISTER: original value of Expr.op
@@ -4273,6 +4275,7 @@ int sqlite3DbstatRegister(sqlite3*);
 
 int sqlite3ExprVectorSize(Expr *pExpr);
 int sqlite3ExprIsVector(Expr *pExpr);
-Expr *sqlite3ExprVectorField(Expr*, int);
+Expr *sqlite3VectorFieldSubexpr(Expr*, int);
+Expr *sqlite3ExprForVectorField(Parse*,Expr*,int,int);
 
 #endif /* SQLITEINT_H */
index 07095276347c2b2ddaea59cf35f261e2aa03bb0a..bc08042000fbc1aaaee2f005e82e5aa4989c9acb 100644 (file)
@@ -1571,7 +1571,7 @@ int sqlite3Stat4ProbeSetValue(
 
     for(i=0; i<nElem; i++){
       sqlite3_value *pVal = 0;
-      Expr *pElem = (pExpr ? sqlite3ExprVectorField(pExpr, i) : 0);
+      Expr *pElem = (pExpr ? sqlite3VectorFieldSubexpr(pExpr, i) : 0);
       u8 aff = sqlite3IndexColumnAffinity(pParse->db, pIdx, iVal+i);
       alloc.iVal = iVal+i;
       rc = stat4ValueFromExpr(pParse, pElem, aff, &alloc, &pVal);
index dd15b5893ced770998c88a76c10efe68eae80a19..2ef9a46b5dec18161405fb625850e253cf85ebda 100644 (file)
@@ -377,34 +377,7 @@ static int codeEqualityTerm(
   assert( pLevel->pWLoop->aLTerm[iEq]==pTerm );
   assert( iTarget>0 );
   if( pX->op==TK_EQ || pX->op==TK_IS ){
-    Expr *pRight = pX->pRight;
-#ifndef SQLITE_OMIT_SUBQUERY
-    if( pRight->op==TK_SELECT_COLUMN ){
-      /* This case occurs for expressions like "(a, b) == (SELECT ...)". */
-      WhereLoop *pLoop = pLevel->pWLoop;
-      int i;
-      Expr *pSub = pRight->pLeft;
-      assert( pSub->op==TK_SELECT );
-      for(i=pLoop->nSkip; i<iEq; i++){
-        Expr *pExpr = pLoop->aLTerm[i]->pExpr->pRight;
-        if( pExpr && pExpr->op==TK_SELECT_COLUMN && pExpr->pLeft==pSub ) break;
-      }
-
-      if( i==iEq ){
-        iReg = sqlite3CodeSubselect(pParse, pSub, 0, 0);
-        for(/*no-op*/; i<pLoop->nLTerm; i++){
-          Expr *pExpr = pLoop->aLTerm[i]->pExpr->pRight;
-          if( pExpr && pExpr->op==TK_SELECT_COLUMN && pExpr->pLeft==pSub ){
-            sqlite3VdbeAddOp2(v, OP_Copy, iReg+pExpr->iColumn, iTarget-iEq+i);
-          }
-        }
-      }
-      iReg = iTarget;
-    }else
-#endif
-    {
-      iReg = sqlite3ExprCodeTarget(pParse, pRight, iTarget);
-    }
+    iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget);
   }else if( pX->op==TK_ISNULL ){
     iReg = iTarget;
     sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
@@ -1101,11 +1074,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
         addrNotFound = pLevel->addrNxt;
       }else{
         Expr *pRight = pTerm->pExpr->pRight;
-        if( pRight->op==TK_SELECT_COLUMN ){
-          codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget);
-        }else{
-          codeExprOrVector(pParse, pRight, iTarget, 1);
-        }
+        codeExprOrVector(pParse, pRight, iTarget, 1);
       }
     }
     sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg);
index 2fc903ce6efe7febee8cc764925c70956beaffa0..55a4cf568ac10f1ac6d8150d8d1bf6b3d5ac4e36 100644 (file)
@@ -873,29 +873,6 @@ static int exprMightBeIndexed(
   return 0;
 }
 
-/*
-** The expression passed as the second argument is a vector (either a 
-** TK_VECTOR node or a TK_SELECT that returns more than one column). This
-** function returns a pointer to a new expression object representing
-** field iField of the vector.
-**
-** If pVector is of type TK_VECTOR, the returned object is just a copy of
-** the iField'th element of the vector. Or, if pVector is of type TK_SELECT,
-** the return value points to a new expression object of type 
-** TK_SELECT_COLUMN.
-*/
-static Expr *exprExtractVectorField(Parse *pParse, Expr *pVector, int iField){
-  Expr *pRet;
-  assert( sqlite3ExprIsVector(pVector) );
-  if( pVector->flags & EP_xIsSelect ){
-    pRet = sqlite3PExpr(pParse, TK_SELECT_COLUMN, pVector, 0, 0);
-    if( pRet ) pRet->iColumn = iField;
-  }else{
-    pRet = sqlite3ExprDup(pParse->db, pVector->x.pList->a[iField].pExpr, 0);
-  }
-  return pRet;
-}
-
 /*
 ** The input to this routine is an WhereTerm structure with only the
 ** "pExpr" field filled in.  The job of this routine is to analyze the
@@ -1211,14 +1188,17 @@ static void exprAnalyze(
       for(i=0; i<sqlite3ExprVectorSize(pExpr->pLeft); i++){
         int idxNew;
         Expr *pNew;
-        Expr *pLeft = exprExtractVectorField(pParse, pExpr->pLeft, i);
-        Expr *pRight = exprExtractVectorField(pParse, pExpr->pRight, i);
+        Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i, 0);
+        Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i, 0);
 
         pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight, 0);
-        idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
+        idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC);
         exprAnalyze(pSrc, pWC, idxNew);
         markTermAsChild(pWC, idxNew, idxTerm);
       }
+      pTerm = &pWC->a[idxTerm];
+      pTerm->wtFlags = TERM_CODED;
+      pTerm->eOperator = 0;
     }
   }