Enhance "INSERT INTO ... VALUES" so that the number of rows in the VALUES clause
is not limited by SQLITE_LIMIT_COMPOUND_SELECT, and so that the stack depth is constant regardless of the number of rows in VALUES. FossilOrigin-Name: e1c4a359aacfce97eb1652624789e71981e0d263
This commit is contained in:
commit
a5b43ac2f1
18
manifest
18
manifest
@ -1,5 +1,5 @@
|
||||
C Remove\ssome\sneedless\srecursion\sfrom\scompound\sSELECT\sprocessing.
|
||||
D 2015-01-05T15:48:45.607
|
||||
C Enhance\s"INSERT\sINTO\s...\sVALUES"\sso\sthat\sthe\snumber\sof\srows\sin\sthe\sVALUES\sclause\nis\snot\slimited\sby\sSQLITE_LIMIT_COMPOUND_SELECT,\sand\sso\sthat\sthe\sstack\sdepth\nis\sconstant\sregardless\sof\sthe\snumber\sof\srows\sin\sVALUES.
|
||||
D 2015-01-05T20:13:49.895
|
||||
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 5dfead8aed90cb0c7c1115898ee2266804daff45
|
||||
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 e4c38c75e36f28aed80a69a725d888751bfd53df
|
||||
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
|
||||
@ -840,6 +840,7 @@ F test/selectC.test 871fb55d884d3de5943c4057ebd22c2459e71977
|
||||
F test/selectD.test b0f02a04ef7737decb24e08be2c39b9664b43394
|
||||
F test/selectE.test fc02a1eb04c8eb537091482644b7d778ae8759b7
|
||||
F test/selectF.test 21c94e6438f76537b72532fa9fd4710cdd455fc3
|
||||
F test/selectG.test 6425730374fb1ebf9897b64db5a2c2550eff6ee7
|
||||
F test/server1.test 46803bd3fe8b99b30dbc5ff38ffc756f5c13a118
|
||||
F test/shared.test 1da9dbad400cee0d93f252ccf76e1ae007a63746
|
||||
F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879
|
||||
@ -1234,7 +1235,8 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 23d4c07eb81db5a5c6beb56b5820f0b6501f1fb6
|
||||
R 11413a03283b5c5b28fd422ab566eba3
|
||||
P fe677d13f03e24fa667efc0c2e7f5bbb99521791 ee30fb35217f3429ee89aaad7c19f29710420e4c
|
||||
R 7d358a2d55ab9540987f678e54c3928e
|
||||
T +closed ee30fb35217f3429ee89aaad7c19f29710420e4c
|
||||
U drh
|
||||
Z 4fbaf4abfb36941c7ce4c15be9a07b21
|
||||
Z cdc7cc4706725ec9fb1dc2fba8453ff0
|
||||
|
@ -1 +1 @@
|
||||
fe677d13f03e24fa667efc0c2e7f5bbb99521791
|
||||
e1c4a359aacfce97eb1652624789e71981e0d263
|
10
src/parse.y
10
src/parse.y
@ -415,13 +415,19 @@ 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;
|
||||
}
|
||||
mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT];
|
||||
if( mxSelect && 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");
|
||||
}
|
||||
}
|
||||
|
82
src/select.c
82
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;
|
||||
}
|
||||
@ -4053,7 +4115,9 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
}
|
||||
pTabList = p->pSrc;
|
||||
pEList = p->pEList;
|
||||
sqlite3WithPush(pParse, findRightmost(p)->pWith, 0);
|
||||
if( pWalker->xSelectCallback2==selectPopWith ){
|
||||
sqlite3WithPush(pParse, findRightmost(p)->pWith, 0);
|
||||
}
|
||||
|
||||
/* Make sure cursor numbers have been assigned to all entries in
|
||||
** the FROM clause of the SELECT statement.
|
||||
@ -4344,7 +4408,9 @@ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
|
||||
sqlite3WalkSelect(&w, pSelect);
|
||||
}
|
||||
w.xSelectCallback = selectExpander;
|
||||
w.xSelectCallback2 = selectPopWith;
|
||||
if( (pSelect->selFlags & SF_AllValues)==0 ){
|
||||
w.xSelectCallback2 = selectPopWith;
|
||||
}
|
||||
sqlite3WalkSelect(&w, pSelect);
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
1008
test/selectG.test
Normal file
1008
test/selectG.test
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user