/ Check-in [56562a03]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Catch vector size mismatch problems during name resolution to avoid later problems.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | early-vector-size-check
Files: files | file ages | folders
SHA1:56562a0346170cf7b72445976864b058437a8ac3
User & Date: drh 2016-09-05 12:02:34
Context
2016-09-05
12:12
Do vector comparison size checking early - at name resolution time - to forestall future problems. check-in: ae127bcc user: drh tags: rowvalue
12:02
Catch vector size mismatch problems during name resolution to avoid later problems. Closed-Leaf check-in: 56562a03 user: drh tags: early-vector-size-check
2016-09-03
19:52
Fix a problem causing the affinity of sub-select row-value elements to be ignored in some contextes. check-in: 7d9bd22c user: dan tags: rowvalue
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/expr.c.

   518    518     u8 op,                /* Comparison operator */
   519    519     u8 p5                 /* SQLITE_NULLEQ or zero */
   520    520   ){
   521    521     Vdbe *v = pParse->pVdbe;
   522    522     Expr *pLeft = pExpr->pLeft;
   523    523     Expr *pRight = pExpr->pRight;
   524    524     int nLeft = sqlite3ExprVectorSize(pLeft);
   525         -  int nRight = sqlite3ExprVectorSize(pRight);
   526         -
   527         -  /* Check that both sides of the comparison are vectors, and that
   528         -  ** both are the same length.  */
   529         -  if( nLeft!=nRight ){
   530         -    sqlite3ErrorMsg(pParse, "row value misused");
   531         -  }else{
   532         -    int i;
   533         -    int regLeft = 0;
   534         -    int regRight = 0;
   535         -    u8 opx = op;
   536         -    int addrDone = sqlite3VdbeMakeLabel(v);
   537         -
   538         -    assert( pExpr->op==TK_EQ || pExpr->op==TK_NE 
   539         -         || pExpr->op==TK_IS || pExpr->op==TK_ISNOT 
   540         -         || pExpr->op==TK_LT || pExpr->op==TK_GT 
   541         -         || pExpr->op==TK_LE || pExpr->op==TK_GE 
   542         -    );
   543         -    assert( pExpr->op==op || (pExpr->op==TK_IS && op==TK_EQ)
   544         -              || (pExpr->op==TK_ISNOT && op==TK_NE) );
   545         -    assert( p5==0 || pExpr->op!=op );
   546         -    assert( p5==SQLITE_NULLEQ || pExpr->op==op );
   547         -
   548         -    p5 |= SQLITE_STOREP2;
   549         -    if( opx==TK_LE ) opx = TK_LT;
   550         -    if( opx==TK_GE ) opx = TK_GT;
   551         -
   552         -    regLeft = exprCodeSubselect(pParse, pLeft);
   553         -    regRight = exprCodeSubselect(pParse, pRight);
   554         -
   555         -    for(i=0; 1 /*Loop exits by "break"*/; i++){
   556         -      int regFree1 = 0, regFree2 = 0;
   557         -      Expr *pL, *pR; 
   558         -      int r1, r2;
   559         -      assert( i>=0 && i<nLeft );
   560         -      if( i>0 ) sqlite3ExprCachePush(pParse);
   561         -      r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, &regFree1);
   562         -      r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, &regFree2);
   563         -      codeCompare(pParse, pL, pR, opx, r1, r2, dest, p5);
   564         -      testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
   565         -      testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
   566         -      testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
   567         -      testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge);
   568         -      testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq);
   569         -      testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
   570         -      sqlite3ReleaseTempReg(pParse, regFree1);
   571         -      sqlite3ReleaseTempReg(pParse, regFree2);
   572         -      if( i>0 ) sqlite3ExprCachePop(pParse);
   573         -      if( i==nLeft-1 ){
   574         -        break;
   575         -      }
   576         -      if( opx==TK_EQ ){
   577         -        sqlite3VdbeAddOp2(v, OP_IfNot, dest, addrDone); VdbeCoverage(v);
   578         -        p5 |= SQLITE_KEEPNULL;
   579         -      }else if( opx==TK_NE ){
   580         -        sqlite3VdbeAddOp2(v, OP_If, dest, addrDone); VdbeCoverage(v);
   581         -        p5 |= SQLITE_KEEPNULL;
   582         -      }else{
   583         -        assert( op==TK_LT || op==TK_GT || op==TK_LE || op==TK_GE );
   584         -        sqlite3VdbeAddOp2(v, OP_ElseNotEq, 0, addrDone);
   585         -        VdbeCoverageIf(v, op==TK_LT);
   586         -        VdbeCoverageIf(v, op==TK_GT);
   587         -        VdbeCoverageIf(v, op==TK_LE);
   588         -        VdbeCoverageIf(v, op==TK_GE);
   589         -        if( i==nLeft-2 ) opx = op;
   590         -      }
   591         -    }
   592         -    sqlite3VdbeResolveLabel(v, addrDone);
   593         -  }
          525  +  int i;
          526  +  int regLeft = 0;
          527  +  int regRight = 0;
          528  +  u8 opx = op;
          529  +  int addrDone = sqlite3VdbeMakeLabel(v);
          530  +
          531  +  assert( nLeft==sqlite3ExprVectorSize(pRight) );
          532  +  assert( pExpr->op==TK_EQ || pExpr->op==TK_NE 
          533  +       || pExpr->op==TK_IS || pExpr->op==TK_ISNOT 
          534  +       || pExpr->op==TK_LT || pExpr->op==TK_GT 
          535  +       || pExpr->op==TK_LE || pExpr->op==TK_GE 
          536  +  );
          537  +  assert( pExpr->op==op || (pExpr->op==TK_IS && op==TK_EQ)
          538  +            || (pExpr->op==TK_ISNOT && op==TK_NE) );
          539  +  assert( p5==0 || pExpr->op!=op );
          540  +  assert( p5==SQLITE_NULLEQ || pExpr->op==op );
          541  +
          542  +  p5 |= SQLITE_STOREP2;
          543  +  if( opx==TK_LE ) opx = TK_LT;
          544  +  if( opx==TK_GE ) opx = TK_GT;
          545  +
          546  +  regLeft = exprCodeSubselect(pParse, pLeft);
          547  +  regRight = exprCodeSubselect(pParse, pRight);
          548  +
          549  +  for(i=0; 1 /*Loop exits by "break"*/; i++){
          550  +    int regFree1 = 0, regFree2 = 0;
          551  +    Expr *pL, *pR; 
          552  +    int r1, r2;
          553  +    assert( i>=0 && i<nLeft );
          554  +    if( i>0 ) sqlite3ExprCachePush(pParse);
          555  +    r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, &regFree1);
          556  +    r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, &regFree2);
          557  +    codeCompare(pParse, pL, pR, opx, r1, r2, dest, p5);
          558  +    testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
          559  +    testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
          560  +    testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
          561  +    testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge);
          562  +    testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq);
          563  +    testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
          564  +    sqlite3ReleaseTempReg(pParse, regFree1);
          565  +    sqlite3ReleaseTempReg(pParse, regFree2);
          566  +    if( i>0 ) sqlite3ExprCachePop(pParse);
          567  +    if( i==nLeft-1 ){
          568  +      break;
          569  +    }
          570  +    if( opx==TK_EQ ){
          571  +      sqlite3VdbeAddOp2(v, OP_IfNot, dest, addrDone); VdbeCoverage(v);
          572  +      p5 |= SQLITE_KEEPNULL;
          573  +    }else if( opx==TK_NE ){
          574  +      sqlite3VdbeAddOp2(v, OP_If, dest, addrDone); VdbeCoverage(v);
          575  +      p5 |= SQLITE_KEEPNULL;
          576  +    }else{
          577  +      assert( op==TK_LT || op==TK_GT || op==TK_LE || op==TK_GE );
          578  +      sqlite3VdbeAddOp2(v, OP_ElseNotEq, 0, addrDone);
          579  +      VdbeCoverageIf(v, op==TK_LT);
          580  +      VdbeCoverageIf(v, op==TK_GT);
          581  +      VdbeCoverageIf(v, op==TK_LE);
          582  +      VdbeCoverageIf(v, op==TK_GE);
          583  +      if( i==nLeft-2 ) opx = op;
          584  +    }
          585  +  }
          586  +  sqlite3VdbeResolveLabel(v, addrDone);
   594    587   }
   595    588   
   596    589   #if SQLITE_MAX_EXPR_DEPTH>0
   597    590   /*
   598    591   ** Check that argument nHeight is less than or equal to the maximum
   599    592   ** expression depth allowed. If it is not, leave an error message in
   600    593   ** pParse.

Changes to src/resolve.c.

   771    771           }
   772    772         }
   773    773         break;
   774    774       }
   775    775       case TK_VARIABLE: {
   776    776         notValid(pParse, pNC, "parameters", NC_IsCheck|NC_PartIdx|NC_IdxExpr);
   777    777         break;
          778  +    }
          779  +    case TK_EQ:
          780  +    case TK_NE:
          781  +    case TK_LT:
          782  +    case TK_LE:
          783  +    case TK_GT:
          784  +    case TK_GE:
          785  +    case TK_IS:
          786  +    case TK_ISNOT: {
          787  +      int nLeft, nRight;
          788  +      if( pParse->db->mallocFailed ) break;
          789  +      assert( pExpr->pRight!=0 );
          790  +      assert( pExpr->pLeft!=0 );
          791  +      nLeft = sqlite3ExprVectorSize(pExpr->pLeft);
          792  +      nRight = sqlite3ExprVectorSize(pExpr->pRight);
          793  +      if( nLeft!=nRight ){
          794  +        testcase( pExpr->op==TK_EQ );
          795  +        testcase( pExpr->op==TK_NE );
          796  +        testcase( pExpr->op==TK_LT );
          797  +        testcase( pExpr->op==TK_LE );
          798  +        testcase( pExpr->op==TK_GT );
          799  +        testcase( pExpr->op==TK_GE );
          800  +        testcase( pExpr->op==TK_IS );
          801  +        testcase( pExpr->op==TK_ISNOT );
          802  +        sqlite3ErrorMsg(pParse, "row value misused");
          803  +      }
          804  +      break; 
   778    805       }
   779    806     }
   780    807     return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue;
   781    808   }
   782    809   
   783    810   /*
   784    811   ** pEList is a list of expressions which are really the result set of the

Changes to src/whereexpr.c.

  1184   1184     if( pWC->op==TK_AND 
  1185   1185     && (pExpr->op==TK_EQ || pExpr->op==TK_IS)
  1186   1186     && sqlite3ExprIsVector(pExpr->pLeft)
  1187   1187     && ( (pExpr->pLeft->flags & EP_xIsSelect)==0 
  1188   1188       || (pExpr->pRight->flags & EP_xIsSelect)==0
  1189   1189     )){
  1190   1190       int nLeft = sqlite3ExprVectorSize(pExpr->pLeft);
  1191         -    if( nLeft==sqlite3ExprVectorSize(pExpr->pRight) ){
  1192         -      int i;
  1193         -      for(i=0; i<sqlite3ExprVectorSize(pExpr->pLeft); i++){
  1194         -        int idxNew;
  1195         -        Expr *pNew;
  1196         -        Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i);
  1197         -        Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i);
         1191  +    int i;
         1192  +    assert( nLeft==sqlite3ExprVectorSize(pExpr->pRight) );
         1193  +    for(i=0; i<nLeft; i++){
         1194  +      int idxNew;
         1195  +      Expr *pNew;
         1196  +      Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i);
         1197  +      Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i);
  1198   1198   
  1199         -        pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight, 0);
  1200         -        idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC);
  1201         -        exprAnalyze(pSrc, pWC, idxNew);
  1202         -      }
  1203         -      pTerm = &pWC->a[idxTerm];
  1204         -      pTerm->wtFlags = TERM_CODED|TERM_VIRTUAL;  /* Disable the original */
  1205         -      pTerm->eOperator = 0;
         1199  +      pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight, 0);
         1200  +      idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC);
         1201  +      exprAnalyze(pSrc, pWC, idxNew);
  1206   1202       }
         1203  +    pTerm = &pWC->a[idxTerm];
         1204  +    pTerm->wtFlags = TERM_CODED|TERM_VIRTUAL;  /* Disable the original */
         1205  +    pTerm->eOperator = 0;
  1207   1206     }
  1208   1207   
  1209   1208     /* If there is a vector IN term - e.g. "(a, b) IN (SELECT ...)" - create
  1210   1209     ** a virtual term for each vector component. The expression object
  1211   1210     ** used by each such virtual term is pExpr (the full vector IN(...) 
  1212   1211     ** expression). The WhereTerm.iField variable identifies the index within
  1213   1212     ** the vector on the LHS that the virtual term represents.  */

Changes to test/rowvalue.test.

   224    224     CREATE TABLE t3(a TEXT,b TEXT,c TEXT,d TEXT,e TEXT,f TEXT);
   225    225     CREATE INDEX t3x ON t3(b,c,d,e,f);
   226    226   
   227    227     SELECT a FROM t3
   228    228       WHERE (c,d) IN (SELECT 'c','d' FROM dual)
   229    229       AND (a,b,e) IN (SELECT 'a','b','d' FROM dual);
   230    230   }
          231  +
          232  +do_catchsql_test 11.1 {
          233  +  CREATE TABLE t11(a);
          234  +  SELECT * FROM t11 WHERE (a,a)<=1;
          235  +} {1 {row value misused}}
          236  +do_catchsql_test 11.2 {
          237  +  SELECT * FROM t11 WHERE (a,a)<1;
          238  +} {1 {row value misused}}
          239  +do_catchsql_test 11.3 {
          240  +  SELECT * FROM t11 WHERE (a,a)>=1;
          241  +} {1 {row value misused}}
          242  +do_catchsql_test 11.4 {
          243  +  SELECT * FROM t11 WHERE (a,a)>1;
          244  +} {1 {row value misused}}
          245  +do_catchsql_test 11.5 {
          246  +  SELECT * FROM t11 WHERE (a,a)==1;
          247  +} {1 {row value misused}}
          248  +do_catchsql_test 11.6 {
          249  +  SELECT * FROM t11 WHERE (a,a)<>1;
          250  +} {1 {row value misused}}
          251  +do_catchsql_test 11.7 {
          252  +  SELECT * FROM t11 WHERE (a,a) IS 1;
          253  +} {1 {row value misused}}
          254  +do_catchsql_test 11.8 {
          255  +  SELECT * FROM t11 WHERE (a,a) IS NOT 1;
          256  +} {1 {row value misused}}
          257  +
   231    258   
   232    259   finish_test

Changes to test/rowvalue4.test.

   302    302   
   303    303     CREATE TABLE c3(d);
   304    304   }
   305    305   do_catchsql_test 8.2 {
   306    306     SELECT * FROM c2 CROSS JOIN c3 WHERE 
   307    307       ( (a, b) == (SELECT x, y FROM c1) AND c3.d = c ) OR
   308    308       ( c == (SELECT x, y FROM c1) AND c3.d = c )
   309         -} {1 {sub-select returns 2 columns - expected 1}}
          309  +} {1 {row value misused}}
   310    310   
   311    311   finish_test

Changes to test/subselect.test.

    36     36   } {3 4}
    37     37   
    38     38   # Try a select with more than one result column.
    39     39   #
    40     40   do_test subselect-1.2 {
    41     41     set v [catch {execsql {SELECT * FROM t1 WHERE a = (SELECT * FROM t1)}} msg]
    42     42     lappend v $msg
    43         -} {1 {sub-select returns 2 columns - expected 1}}
           43  +} {1 {row value misused}}
    44     44   
    45     45   # A subselect without an aggregate.
    46     46   #
    47     47   do_test subselect-1.3a {
    48     48     execsql {SELECT b from t1 where a = (SELECT a FROM t1 WHERE b=2)}
    49     49   } {2}
    50     50   do_test subselect-1.3b {