]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Handle compound-select statements originating from VALUES clauses as a
authordrh <drh@noemail.net>
Mon, 5 Jan 2015 19:16:42 +0000 (19:16 +0000)
committerdrh <drh@noemail.net>
Mon, 5 Jan 2015 19:16:42 +0000 (19:16 +0000)
special case that does not use recursion.

FossilOrigin-Name: 9ce9e43af38e6bc362734463d4bfc40ff0c98f8f

manifest
manifest.uuid
src/parse.y
src/select.c
src/sqliteInt.h

index 6cb20c18178c7481f5ff90f3abe22281817cac7a..d9ca18ff0338fc23aa65651277b631b3b08985ff 100644 (file)
--- 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
index 32e2f42e5e4220083c87a7f57ce9256c41c0549a..e3a83ccf8ffa95aa369ca2e8523450f16bd83ed6 100644 (file)
@@ -1 +1 @@
-c9d65f739ad56f016c676e79aa39080be3fe868a
\ No newline at end of file
+9ce9e43af38e6bc362734463d4bfc40ff0c98f8f
\ No newline at end of file
index 4dbdbdea2685008ceae1184b1b317cd3bc5233fb..544888a2281ccd8a00d235403cfd78ab1b5eefc0 100644 (file)
@@ -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");
       }
index bc4f8a37c32557bef3a5556db512a6d45c704861..5de489b86edfce4a5a0e43a4bcbc6bba4b40e2e6 100644 (file)
@@ -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;
   }
index 4a4137f0f64ef5aaab5e7170efd81fd0bd2db396..0a1948fef8b14ec4a74b743414b9d8568312572f 100644 (file)
@@ -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 */