aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordan <Dan Kennedy>2021-07-07 13:53:55 +0000
committerdan <Dan Kennedy>2021-07-07 13:53:55 +0000
commit74777f994d5735e0fb3020ef24f3d0229cdc7ca2 (patch)
treed3a7afd1d5be0b68ac064159080958d3b85e4069 /src
parentcc516af4cc35c8db816aed7c69f7aef7d663e78e (diff)
downloadsqlite-74777f994d5735e0fb3020ef24f3d0229cdc7ca2.tar.gz
sqlite-74777f994d5735e0fb3020ef24f3d0229cdc7ca2.zip
Improve the error message in cases where there is a row-value on the LHS of an IN() operator, the RHS is a list (not a sub-select) and at least one element of the list is not a row-value with the correct number of elements.
FossilOrigin-Name: 6b22f4e71dbc14c887ebbda67095b5faaa8079cac87cd4ab5a2ae90c71cd9633
Diffstat (limited to 'src')
-rw-r--r--src/expr.c34
-rw-r--r--src/parse.y9
-rw-r--r--src/sqliteInt.h2
3 files changed, 24 insertions, 21 deletions
diff --git a/src/expr.c b/src/expr.c
index 8351723f0..44abb58e5 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -948,37 +948,37 @@ void sqlite3PExprAddSelect(Parse *pParse, Expr *pExpr, Select *pSelect){
/*
** Expression list pEList is a list of vector values. This function
** converts the contents of pEList to a VALUES(...) Select statement
-** returning 1 row for each element of the list. If there are any
-** non-vector expressions in the list, the corresponding row returned
-** by the values statement contains a single column, the value of
-** the non-vector expression itself.
+** returning 1 row for each element of the list. For example, the
+** expression list:
**
-** For example, the expression list:
+** ( (1,2), (3,4) (5,6) )
**
-** ( (1, 2), 3, (3, 4, 5) )
+** is translated to the equivalent of:
**
-** is translated to:
+** VALUES(1,2), (3,4), (5,6)
**
-** VALUES(1, 2), (3), (3, 4, 5)
+** Each of the vector values in pEList must contain exactly nElem terms.
+** If a list element that is not a vector or does not contain nElem terms,
+** an error message is left in pParse.
**
** This is used as part of processing IN(...) expressions with a list
** of vectors on the RHS. e.g. "... IN ((1,2), (3,4), (5,6))".
*/
-Select *sqlite3ExprListToValues(Parse *pParse, ExprList *pEList){
+Select *sqlite3ExprListToValues(Parse *pParse, int nElem, ExprList *pEList){
int ii;
Select *pRet = 0;
for(ii=0; ii<pEList->nExpr; ii++){
Select *pSel;
- ExprList *pList;
Expr *pExpr = pEList->a[ii].pExpr;
- if( pExpr->op==TK_VECTOR ){
- pList = pExpr->x.pList;
- pExpr->x.pList = 0;
- }else{
- pList = sqlite3ExprListAppend(pParse, 0, pExpr);
- pEList->a[ii].pExpr = 0;
+ int nExprElem = sqlite3ExprVectorSize(pExpr);
+ if( nExprElem!=nElem ){
+ sqlite3ErrorMsg(pParse, "IN(...) element has %d term%s - expected %d",
+ nExprElem, nExprElem>1?"s":"", nElem
+ );
+ break;
}
- pSel = sqlite3SelectNew(pParse, pList, 0, 0, 0, 0, 0, SF_Values, 0);
+ pSel = sqlite3SelectNew(pParse, pExpr->x.pList, 0, 0, 0, 0, 0, SF_Values,0);
+ pExpr->x.pList = 0;
if( pSel ){
if( pRet ){
pSel->op = TK_ALL;
diff --git a/src/parse.y b/src/parse.y
index efc390ca0..7a0387336 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -1256,15 +1256,18 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
A = sqlite3Expr(pParse->db, TK_INTEGER, N ? "1" : "0");
}else{
Expr *pRHS = Y->a[0].pExpr;
- if( Y->nExpr==1 && sqlite3ExprIsConstant(pRHS) && pRHS->op!=TK_VECTOR ){
+ if( Y->nExpr==1 && sqlite3ExprIsConstant(pRHS) && A->op!=TK_VECTOR ){
Y->a[0].pExpr = 0;
sqlite3ExprListDelete(pParse->db, Y);
pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0);
A = sqlite3PExpr(pParse, TK_EQ, A, pRHS);
}else{
A = sqlite3PExpr(pParse, TK_IN, A, 0);
- if( pRHS->op==TK_VECTOR || A==0 ){
- Select *pRHS = sqlite3ExprListToValues(pParse, Y);
+ if( A==0 ){
+ sqlite3ExprListDelete(pParse->db, Y);
+ }else if( A->pLeft->op==TK_VECTOR ){
+ int nExpr = A->pLeft->x.pList->nExpr;
+ Select *pRHS = sqlite3ExprListToValues(pParse, nExpr, Y);
if( pRHS ){
parserDoubleLinkSelect(pParse, pRHS);
sqlite3PExprAddSelect(pParse, A, pRHS);
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 935ee0953..4d92703f1 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -4324,7 +4324,7 @@ void sqlite3ExprDeferredDelete(Parse*, Expr*);
void sqlite3ExprUnmapAndDelete(Parse*, Expr*);
ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
-Select *sqlite3ExprListToValues(Parse*, ExprList*);
+Select *sqlite3ExprListToValues(Parse*, int, ExprList*);
void sqlite3ExprListSetSortOrder(ExprList*,int,int);
void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);