Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix a problem with IN(...) constraints where the LHS is a sub-select that is an aggregate query. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | rowvalue |
Files: | files | file ages | folders |
SHA1: |
1f4dba87da4a44ad26223ad965731164 |
User & Date: | dan 2016-08-01 16:37:43.292 |
Context
2016-08-01
| ||
20:14 | Fix a problem with vector range constraints involving the rowid column. And other issues. (check-in: 3ef75d45eb user: dan tags: rowvalue) | |
16:37 | Fix a problem with IN(...) constraints where the LHS is a sub-select that is an aggregate query. (check-in: 1f4dba87da user: dan tags: rowvalue) | |
2016-07-30
| ||
21:02 | Fix problems with vector == comparisons and NULL values. (check-in: 059d0d0535 user: dan tags: rowvalue) | |
Changes
Changes to src/expr.c.
︙ | ︙ | |||
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 | p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight); p5 = binaryCompareP5(pLeft, pRight, jumpIfNull); addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1, (void*)p4, P4_COLLSEQ); sqlite3VdbeChangeP5(pParse->pVdbe, (u8)p5); return addr; } /* ** If the expression passed as the only argument is of type TK_VECTOR ** return the number of expressions in the vector. Or, if the expression ** is a sub-select, return the number of columns in the sub-select. For ** any other type of expression, return 1. */ int sqlite3ExprVectorSize(Expr *pExpr){ if( sqlite3ExprIsVector(pExpr)==0 ) return 1; if( pExpr->flags & EP_xIsSelect ){ return pExpr->x.pSelect->pEList->nExpr; } return pExpr->x.pList->nExpr; } | > > > > > > > > > < < < < < < < < < < > | | > | < > | | | | > | | > | > > > > | > > > > < < < < < < < < | > > | | | | 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 | p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight); p5 = binaryCompareP5(pLeft, pRight, jumpIfNull); addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1, (void*)p4, P4_COLLSEQ); sqlite3VdbeChangeP5(pParse->pVdbe, (u8)p5); return addr; } /* ** Return true if expression pExpr is a vector, or false otherwise. */ int sqlite3ExprIsVector(Expr *pExpr){ return ( (pExpr->op==TK_VECTOR) || (pExpr->op==TK_SELECT && pExpr->x.pSelect->pEList->nExpr>1) ); } /* ** If the expression passed as the only argument is of type TK_VECTOR ** return the number of expressions in the vector. Or, if the expression ** is a sub-select, return the number of columns in the sub-select. For ** any other type of expression, return 1. */ int sqlite3ExprVectorSize(Expr *pExpr){ if( sqlite3ExprIsVector(pExpr)==0 ) return 1; if( pExpr->flags & EP_xIsSelect ){ return pExpr->x.pSelect->pEList->nExpr; } return pExpr->x.pList->nExpr; } /* ** 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. */ static Expr *exprVectorField(Expr *pVector, int i){ assert( i<sqlite3ExprVectorSize(pVector) ); if( sqlite3ExprIsVector(pVector) ){ if( pVector->op==TK_SELECT ){ return pVector->x.pSelect->pEList->a[i].pExpr; }else{ return pVector->x.pList->a[i].pExpr; } } return pVector; } /* ** If expression pExpr is of type TK_SELECT, generate code to evaluate ** it. Return the register in which the result is stored (or, if the ** sub-select returns more than one column, the first in an array ** of registers in which the result is stored). ** ** If pExpr is not a TK_SELECT expression, return 0. */ static int exprCodeSubselect(Parse *pParse, Expr *pExpr){ int reg = 0; if( pExpr->op==TK_SELECT ){ reg = sqlite3CodeSubselect(pParse, pExpr, 0, 0); } return reg; } /* ** Argument pVector points to a vector expression - either a TK_VECTOR ** or TK_SELECT that returns more than one column. This function returns ** the register number of a register that contains the value of ** element iField of the vector. ** ** If pVector is a TK_SELECT expression, then code for it must have ** already been generated using the exprCodeSubselect() routine. In this ** case parameter regSelect should be the first in an array of registers ** containing the results of the sub-select. ** ** If pVector is of type TK_VECTOR, then code for the requested field ** is generated. In this case (*pRegFree) may be set to the number of ** a temporary register to be freed by the caller before returning. ** ** Before returning, output parameter (*ppExpr) is set to point to the ** Expr object corresponding to element iElem of the vector. */ static int exprVectorRegister( Parse *pParse, /* Parse context */ Expr *pVector, /* Vector to extract element from */ int iField, /* Field to extract from pVector */ int regSelect, /* First in array of registers */ Expr **ppExpr, /* OUT: Expression element */ int *pRegFree /* OUT: Temp register to free */ ){ assert( pVector->op==TK_VECTOR || pVector->op==TK_SELECT ); assert( (pVector->op==TK_VECTOR)==(regSelect==0) ); if( regSelect ){ *ppExpr = pVector->x.pSelect->pEList->a[iField].pExpr; return regSelect+iField; } *ppExpr = pVector->x.pList->a[iField].pExpr; return sqlite3ExprCodeTemp(pParse, *ppExpr, pRegFree); } /* ** Expression pExpr is a comparison between two vector values. Compute ** the result of the comparison and write it to register dest. */ |
︙ | ︙ | |||
412 413 414 415 416 417 418 | /* Check that both sides of the comparison are vectors, and that ** both are the same length. */ if( nLeft!=nRight ){ sqlite3ErrorMsg(pParse, "invalid use of row value"); }else{ int p5 = (pExpr->op==TK_IS || pExpr->op==TK_ISNOT) ? SQLITE_NULLEQ : 0; | < < < | 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 | /* Check that both sides of the comparison are vectors, and that ** both are the same length. */ if( nLeft!=nRight ){ sqlite3ErrorMsg(pParse, "invalid use of row value"); }else{ int p5 = (pExpr->op==TK_IS || pExpr->op==TK_ISNOT) ? SQLITE_NULLEQ : 0; int i; int regLeft = 0; int regRight = 0; int regTmp = 0; assert( pExpr->op==TK_EQ || pExpr->op==TK_NE || pExpr->op==TK_IS || pExpr->op==TK_ISNOT || pExpr->op==TK_LT || pExpr->op==TK_GT |
︙ | ︙ | |||
1773 1774 1775 1776 1777 1778 1779 | /* ** pX is the RHS of an IN operator. If pX is a SELECT statement ** that can be simplified to a direct table access, then return ** a pointer to the SELECT statement. If pX is not a SELECT statement, ** or if the SELECT statement needs to be manifested into a transient ** table, then return NULL. | < < < < < < < | 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 | /* ** pX is the RHS of an IN operator. If pX is a SELECT statement ** that can be simplified to a direct table access, then return ** a pointer to the SELECT statement. If pX is not a SELECT statement, ** or if the SELECT statement needs to be manifested into a transient ** table, then return NULL. */ #ifndef SQLITE_OMIT_SUBQUERY static Select *isCandidateForInOpt(Expr *pX){ Select *p; SrcList *pSrc; ExprList *pEList; Table *pTab; |
︙ | ︙ | |||
1953 1954 1955 1956 1957 1958 1959 | Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */ assert( pX->op==TK_IN ); mustBeUnique = (inFlags & IN_INDEX_LOOP)!=0; /* If the RHS of this IN(...) operator is a SELECT, and if it matters ** whether or not the SELECT result contains NULL values, check whether | | | < | 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 | Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */ assert( pX->op==TK_IN ); mustBeUnique = (inFlags & IN_INDEX_LOOP)!=0; /* If the RHS of this IN(...) operator is a SELECT, and if it matters ** whether or not the SELECT result contains NULL values, check whether ** or not NULL is actually possible (it may not be, for example, due ** to NOT NULL constraints in the schema). If no NULL values are possible, ** set prRhsHasNull to 0 before continuing. */ if( prRhsHasNull && (pX->flags & EP_xIsSelect) ){ int i; ExprList *pEList = pX->x.pSelect->pEList; for(i=0; i<pEList->nExpr; i++){ if( sqlite3ExprCanBeNull(pEList->a[i].pExpr) ) break; } if( i==pEList->nExpr ){ |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
655 656 657 658 659 660 661 | r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1); sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, r1); sqlite3ReleaseTempReg(pParse, r1); } | < < < < < < < < < < < < < < < < < < < < < < < < | 655 656 657 658 659 660 661 662 663 664 665 666 667 668 | r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1); sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, r1); sqlite3ReleaseTempReg(pParse, r1); } /* ** This routine generates the code for the inside of the inner loop ** of a SELECT. ** ** If srcTab is negative, then the pEList expressions ** are evaluated in order to get the data for this row. If srcTab is ** zero or more, then data is pulled from srcTab and pEList is used only |
︙ | ︙ | |||
915 916 917 918 919 920 921 | case SRT_Exists: { sqlite3VdbeAddOp2(v, OP_Integer, 1, iParm); /* The LIMIT clause will terminate the loop for us */ break; } /* If this is a scalar select that is part of an expression, then | | | > | | 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 | case SRT_Exists: { sqlite3VdbeAddOp2(v, OP_Integer, 1, iParm); /* The LIMIT clause will terminate the loop for us */ break; } /* If this is a scalar select that is part of an expression, then ** store the results in the appropriate memory cell or array of ** memory cells and break out of the scan loop. */ case SRT_Mem: { assert( nResultCol==pDest->nSdst ); if( pSort ){ pushOntoSorter( pParse, pSort, p, regResult, regResult, nResultCol, nPrefixReg); }else{ assert( regResult==iParm ); /* The LIMIT clause will jump out of the loop for us */ } break; } #endif /* #ifndef SQLITE_OMIT_SUBQUERY */ |
︙ | ︙ | |||
4888 4889 4890 4891 4892 4893 4894 | assert( p->pEList!=0 ); isAgg = (p->selFlags & SF_Aggregate)!=0; #if SELECTTRACE_ENABLED if( sqlite3SelectTrace & 0x100 ){ SELECTTRACE(0x100,pParse,p, ("after name resolution:\n")); sqlite3TreeViewSelect(0, p, 0); } | < < < < < < < < < < | 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 | assert( p->pEList!=0 ); isAgg = (p->selFlags & SF_Aggregate)!=0; #if SELECTTRACE_ENABLED if( sqlite3SelectTrace & 0x100 ){ SELECTTRACE(0x100,pParse,p, ("after name resolution:\n")); sqlite3TreeViewSelect(0, p, 0); } #endif /* Try to flatten subqueries in the FROM clause up into the main query */ #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) for(i=0; !p->pPrior && i<pTabList->nSrc; i++){ struct SrcList_item *pItem = &pTabList->a[i]; |
︙ | ︙ |
Changes to src/whereexpr.c.
︙ | ︙ | |||
868 869 870 871 872 873 874 | return 1; } } } return 0; } | > > > > > > > > > > > | > | | | | 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 | return 1; } } } 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 |
︙ | ︙ | |||
1190 1191 1192 1193 1194 1195 1196 | )){ int nLeft = sqlite3ExprVectorSize(pExpr->pLeft); if( nLeft==sqlite3ExprVectorSize(pExpr->pRight) ){ int i; for(i=0; i<sqlite3ExprVectorSize(pExpr->pLeft); i++){ int idxNew; Expr *pNew; | | | | 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 | )){ int nLeft = sqlite3ExprVectorSize(pExpr->pLeft); if( nLeft==sqlite3ExprVectorSize(pExpr->pRight) ){ int i; 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); pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight, 0); idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC); exprAnalyze(pSrc, pWC, idxNew); markTermAsChild(pWC, idxNew, idxTerm); } } |
︙ | ︙ |
Changes to test/rowvalue.test.
︙ | ︙ | |||
190 191 192 193 194 195 196 197 198 199 200 | "0 0 0 {SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid>?)}" } { do_eqp_test 7.$tn.1 $sql $eqp do_execsql_test 7.$tn.2 $sql $res } finish_test | > > > > > > | 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | "0 0 0 {SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid>?)}" } { do_eqp_test 7.$tn.1 $sql $eqp do_execsql_test 7.$tn.2 $sql $res } do_execsql_test 8.0 { CREATE TABLE j1(a); } do_execsql_test 8.1 { SELECT * FROM j1 WHERE (select min(a) FROM j1) IN (?, ?, ?) } finish_test |