From: drh Date: Mon, 5 Jan 2015 19:16:42 +0000 (+0000) Subject: Handle compound-select statements originating from VALUES clauses as a X-Git-Tag: version-3.8.8~31^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=45f54a57783d85907d4a262dd36bfa376fcba876;p=thirdparty%2Fsqlite.git Handle compound-select statements originating from VALUES clauses as a special case that does not use recursion. FossilOrigin-Name: 9ce9e43af38e6bc362734463d4bfc40ff0c98f8f --- diff --git a/manifest b/manifest index 6cb20c1817..d9ca18ff03 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Towards\sgetting\sINSERT\sstatements\sto\sexcept\smany\sVALUE\sterms\s(more\sthan\nthe\slimit\simposed\sby\sSQLITE_LIMIT_COMPOUND_SELECT).\s\sThis\scheck-in\ssegfaults\non\sa\sstack\soverflow.\s\sAnd\sit\sis\sslow. -D 2015-01-05T16:27:43.075 +C Handle\scompound-select\sstatements\soriginating\sfrom\sVALUES\sclauses\sas\sa\nspecial\scase\sthat\sdoes\snot\suse\srecursion. +D 2015-01-05T19:16:42.892 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 335e2d3ff0f2455eacbfa3075fc37495e3321410 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -218,7 +218,7 @@ F src/os_win.c 91d3d08e33ec0258d180d4c8255492f47d15e007 F src/os_win.h 09e751b20bbc107ffbd46e13555dc73576d88e21 F src/pager.c 4120a49ecd37697e28f5ed807f470b9c0b88410c F src/pager.h c3476e7c89cdf1c6914e50a11f3714e30b4e0a77 -F src/parse.y 075cad65e0393df1362b87e5cd766220b880f3a7 +F src/parse.y c5d0d964f9ac023e8154cad512e54b0b6058e086 F src/pcache.c b83d160ce81ca101f98f0d27498e6d6bd49f1599 F src/pcache.h b44658c9c932d203510279439d891a2a83e12ba8 F src/pcache1.c 1e77432b40b7d3288327d9cdf399dcdfd2b6d3bf @@ -228,12 +228,12 @@ F src/printf.c 9e75a6a0b55bf61cfff7d7e19d89834a1b938236 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c f6c46d3434439ab2084618d603e6d6dbeb0d6ada F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e -F src/select.c 28cf616a8791ff154be86bd9a3f888440f618e78 +F src/select.c 4776e16d19296f0f93ecd9431dca8bc3e3182714 F src/shell.c 45d9c9bd7cde07845af957f2d849933b990773cf F src/sqlite.h.in ed799ff5c814227c7957eb4f4a217f67fdc0da48 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d -F src/sqliteInt.h 3e0079855cb7b3c85dffac5bcbb1cd712ac62e65 +F src/sqliteInt.h 5d5716d8b33a61606c6ee10112f4b6df56f42725 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 81712116e826b0089bb221b018929536b2b5406f F src/table.c e7a09215315a978057fb42c640f890160dbcc45e @@ -1235,10 +1235,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P fe677d13f03e24fa667efc0c2e7f5bbb99521791 -R 54acf3852000e5cc7341ca33524e221b -T *branch * many-VALUEs -T *sym-many-VALUEs * -T -sym-trunk * +P c9d65f739ad56f016c676e79aa39080be3fe868a +R 382474f6cec467234b3ff04ac38978b4 U drh -Z 9fc3f9e17e26a0964cf77234a16c2176 +Z 33ab3e676dc0271c6784ea259fd00ed6 diff --git a/manifest.uuid b/manifest.uuid index 32e2f42e5e..e3a83ccf8f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c9d65f739ad56f016c676e79aa39080be3fe868a \ No newline at end of file +9ce9e43af38e6bc362734463d4bfc40ff0c98f8f \ No newline at end of file diff --git a/src/parse.y b/src/parse.y index 4dbdbdea26..544888a228 100644 --- a/src/parse.y +++ b/src/parse.y @@ -415,14 +415,18 @@ select(A) ::= with(W) selectnowith(X). { int cnt = 0, mxSelect; p->pWith = W; if( p->pPrior ){ + u16 allValues = SF_Values; pNext = 0; for(pLoop=p; pLoop; pNext=pLoop, pLoop=pLoop->pPrior, cnt++){ pLoop->pNext = pNext; pLoop->selFlags |= SF_Compound; + allValues &= pLoop->selFlags; } - if( (p->selFlags & SF_Values)==0 - && (mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0 - && cnt>mxSelect + if( allValues ){ + p->selFlags |= SF_AllValues; + }else if( + (mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0 + && cnt>mxSelect ){ sqlite3ErrorMsg(pParse, "too many terms in compound SELECT"); } diff --git a/src/select.c b/src/select.c index bc4f8a37c3..5de489b86e 100644 --- a/src/select.c +++ b/src/select.c @@ -2076,6 +2076,66 @@ static int multiSelectOrderBy( SelectDest *pDest /* What to do with query results */ ); +/* +** Error message for when two or more terms of a compound select have different +** size result sets. +*/ +static void selectWrongNumTermsError(Parse *pParse, Select *p){ + if( p->selFlags & SF_Values ){ + sqlite3ErrorMsg(pParse, "all VALUES must have the same number of terms"); + }else{ + sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s" + " do not have the same number of result columns", selectOpName(p->op)); + } +} + +/* +** Handle the special case of a compound-select that originates from a +** VALUES clause. By handling this as a special case, we avoid deep +** recursion, and thus do not need to enforce the SQLITE_LIMIT_COMPOUND_SELECT +** on a VALUES clause. +** +** Because the Select object originates from a VALUES clause: +** (1) It has no LIMIT or OFFSET +** (2) All terms are UNION ALL +** (3) There is no ORDER BY clause +*/ +static int multiSelectValues( + Parse *pParse, /* Parsing context */ + Select *p, /* The right-most of SELECTs to be coded */ + SelectDest *pDest /* What to do with query results */ +){ + Select *pPrior; + int nExpr = p->pEList->nExpr; + int nRow = 1; + int rc = 0; + assert( p->pNext==0 ); + assert( p->selFlags & SF_AllValues ); + do{ + assert( p->selFlags & SF_Values ); + assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) ); + assert( p->pLimit==0 ); + assert( p->pOffset==0 ); + if( p->pEList->nExpr!=nExpr ){ + selectWrongNumTermsError(pParse, p); + return 1; + } + if( p->pPrior==0 ) break; + assert( p->pPrior->pNext==p ); + p = p->pPrior; + nRow++; + }while(1); + while( p ){ + pPrior = p->pPrior; + p->pPrior = 0; + rc = sqlite3Select(pParse, p, pDest); + p->pPrior = pPrior; + if( rc ) break; + p->nSelectRow = nRow; + p = p->pNext; + } + return rc; +} /* ** This routine is called to process a compound query form from @@ -2157,17 +2217,19 @@ static int multiSelect( dest.eDest = SRT_Table; } + /* Special handling for a compound-select that originates as a VALUES clause. + */ + if( p->selFlags & SF_AllValues ){ + rc = multiSelectValues(pParse, p, &dest); + goto multi_select_end; + } + /* Make sure all SELECTs in the statement have the same number of elements ** in their result sets. */ assert( p->pEList && pPrior->pEList ); if( p->pEList->nExpr!=pPrior->pEList->nExpr ){ - if( p->selFlags & SF_Values ){ - sqlite3ErrorMsg(pParse, "all VALUES must have the same number of terms"); - }else{ - sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s" - " do not have the same number of result columns", selectOpName(p->op)); - } + selectWrongNumTermsError(pParse, p); rc = 1; goto multi_select_end; } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 4a4137f0f6..0a1948fef8 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2349,7 +2349,7 @@ struct Select { #define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */ #define SF_Compound 0x0040 /* Part of a compound query */ #define SF_Values 0x0080 /* Synthesized from VALUES clause */ - /* 0x0100 NOT USED */ +#define SF_AllValues 0x0100 /* All terms of compound are VALUES */ #define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */ #define SF_MaybeConvert 0x0400 /* Need convertCompoundSelectToSubquery() */ #define SF_Recursive 0x0800 /* The recursive part of a recursive CTE */