]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
"LATERAL" may not be a keyword, as that would cause problems for legacy
authordrh <>
Sat, 20 Jul 2024 03:19:40 +0000 (03:19 +0000)
committerdrh <>
Sat, 20 Jul 2024 03:19:40 +0000 (03:19 +0000)
databases that have tables named "lateral".  It has to be parsed as an
identifier.

FossilOrigin-Name: 8217bddaf8c0697799c7518746996665bbd1f5a327315d18091a6ab3250f1112

manifest
manifest.uuid
src/parse.y
test/joinL.test
tool/mkkeywordhash.c

index 0fa6ca7065f65fbfb0fc150e5174c58ee3f9944c..55f65b4aaefc5b526d3bbf29ead42f34eb83d6d8 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Experimental\simplementation\sof\sLATERAL\sJOIN.
-D 2024-07-20T01:19:18.644
+C "LATERAL"\smay\snot\sbe\sa\skeyword,\sas\sthat\swould\scause\sproblems\sfor\slegacy\ndatabases\sthat\shave\stables\snamed\s"lateral".\s\sIt\shas\sto\sbe\sparsed\sas\san\nidentifier.
+D 2024-07-20T03:19:40.623
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -744,7 +744,7 @@ F src/os_win.c 6ff43bac175bd9ed79e7c0f96840b139f2f51d01689a638fd05128becf94908a
 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
 F src/pager.c b08600ebf0db90b6d1e9b8b6577c6fa3877cbe1a100bd0b2899e4c6e9adad4b3
 F src/pager.h 4b1140d691860de0be1347474c51fee07d5420bd7f802d38cbab8ea4ab9f538a
-F src/parse.y 4be218b2b28316145aae99695ccec0bd08d1b9f1088304a72e5e526bb9bbb083
+F src/parse.y c681bcadfb08325e425c3798a6fa0fb374426ffa2db943cf4e7e97b6545e09fb
 F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
 F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
 F src/pcache1.c 49516ad7718a3626f28f710fa7448ef1fce3c07fd169acbb4817341950264319
@@ -1347,7 +1347,7 @@ F test/joinD.test 2ce62e7353a0702ca5e70008faf319c1d4686aa19fba34275c6d1da0e960be
 F test/joinE.test d5d182f3812771e2c0d97c9dcf5dbe4c41c8e21c82560e59358731c4a3981d6b
 F test/joinF.test 53dd66158806823ea680dd7543b5406af151b5aafa5cd06a7f3231cd94938127
 F test/joinH.test 55f69e64da74d4eca2235237f3acb657aef181e22e45daa228e35bba865e0255
-F test/joinL.test 42f319f9fc60a3dddb248a71f4d8ace80741772c8a8606f4ce878e96311822ee
+F test/joinL.test d18dc1f85a8254b260ef5d0e1d3695dca65309f20f04b79e0b1cb754fdef9334
 F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497
 F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
 F test/journal3.test 7c3cf23ffc77db06601c1fcfc9743de8441cb77db9d1aa931863d94f5ffa140e
@@ -2117,7 +2117,7 @@ F tool/merge-test.tcl de76b62f2de2a92d4c1ca4f976bce0aea6899e0229e250479b229b2a19
 F tool/mkautoconfamal.sh cbdcf993fa83dccbef7fb77b39cdeb31ef9f77d9d88c9e343b58d35ca3898a6a
 F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
 F tool/mkctimec.tcl 060e9785e9503bf51f8b1b11b542bdeef90fd0ceb0738154f6762acec0c61e5f x
-F tool/mkkeywordhash.c 10f6a1eb691b17d4a87b0a9bf809420c5cfb806273d3e5101add1544b223f9d4
+F tool/mkkeywordhash.c b9faa0ae7e14e4dbbcd951cddd786bf46b8a65bb07b129ba8c0cfade723aaffd
 F tool/mkmsvcmin.tcl 8897d515ef7f94772322db95a3b6fce6c614d84fe0bdd06ba5a1c786351d5a1d
 F tool/mkopcodec.tcl 33d20791e191df43209b77d37f0ff0904620b28465cca6990cf8d60da61a07ef
 F tool/mkopcodeh.tcl 2b4e6967a670ef21bf53a164964c35c6163277d002a4c6f56fa231d68c88d023
@@ -2196,11 +2196,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P bf54b26092ded2e6acc779acfb960364f05c665c7626c38ffae61caae5636184
-R fd0426e8bf5d734a1d48d710a5bc9a8a
-T *branch * lateral-join
-T *sym-lateral-join *
-T -sym-trunk *
+P 3c045a96bc65713e5544af82b8547cdcdf93fa20f9b7b0851d77f8c090cc650b
+R f090a6ec615c741ecafebf974126b522
 U drh
-Z 0351f62d422552d2d5b55232d6520d93
+Z ff3d32fb657fae9cfdb48424d2f017eb
 # Remove this line to create a well-formed Fossil manifest.
index 55f341b9bf6e2652648d33dbeccabfd9f59b36fd..5cd623bdcfcb00690f27c85f5047c74f45fb46a2 100644 (file)
@@ -1 +1 @@
-3c045a96bc65713e5544af82b8547cdcdf93fa20f9b7b0851d77f8c090cc650b
+8217bddaf8c0697799c7518746996665bbd1f5a327315d18091a6ab3250f1112
index 963b52d423179aa7659e103f2e0cc1033da3b30d..92f5e5989b04ba04d85ae220173ecd56f152e492 100644 (file)
@@ -253,7 +253,7 @@ columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,A,Y);}
   ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST COLUMNKW
   CONFLICT DATABASE DEFERRED DESC DETACH DO
   EACH END EXCLUSIVE EXPLAIN FAIL FOR
-  IGNORE IMMEDIATE INITIALLY INSTEAD LATERAL LIKE_KW MATCH NO PLAN
+  IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH NO PLAN
   QUERY KEY OF OFFSET PRAGMA RAISE RECURSIVE RELEASE REPLACE RESTRICT ROW ROWS
   ROLLBACK SAVEPOINT TEMP TRIGGER VACUUM VIEW VIRTUAL WITH WITHOUT
   NULLS FIRST LAST
@@ -732,8 +732,25 @@ seltablist(A) ::= stl_prefix(A) nm(Y) dbnm(D) LP exprlist(E) RP as(Z) on_using(N
   seltablist(A) ::= stl_prefix(A) LP select(S) RP as(Z) on_using(N). {
     A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,S,&N);
   }
-  seltablist(A) ::= stl_prefix(A) LATERAL LP select(S) RP as(Z) on_using(N). {
-    SrcList *pSrc;
+  seltablist(A) ::= stl_prefix(A) nm(Y) dbnm(D) LP select(S) RP as(Z) on_using(N). {
+    //                            \___________/
+    //                                  |
+    //  This must be a single identifier token "LATERAL".  We cannot make
+    //  LATERAL a keyword, since there might be legacy databases that
+    //  use "lateral" as a table name and a table name is valid syntax
+    //  in this position.
+    SrcList *pSrc = A;
+    if( Y.n!=7 || sqlite3StrNICmp(Y.z,"lateral",7)!=0 || D.z!=0 ){
+      sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &Y);
+      pParse->db->errByteOffset = (int)(Y.z - pParse->zTail);
+    }else
+    if(  pSrc
+     && ALWAYS(pSrc->nSrc>0)
+     && (pSrc->a[pSrc->nSrc-1].fg.jointype & JT_RIGHT)!=0
+    ){
+      sqlite3ErrorMsg(pParse, "join must be INNER or LEFT for a LATERAL reference");
+      pParse->db->errByteOffset = (int)(Y.z - pParse->zTail);
+    } 
     pSrc = A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,S,&N);
     if( pSrc && pSrc->nSrc>1 ){
       pSrc->a[pSrc->nSrc-1].fg.isLateral = 1;
index 5d3366f98981e518cb2aff0c1ea3bc26dfa60ca7..508f2634c8df27226697fd1db9ae352e1f0c1a2f 100644 (file)
@@ -75,6 +75,44 @@ do_execsql_test 1.1 {
   3  cindy  15.0    2        5.28   banana     
 }
 
+
+do_catchsql_test 1.2 {
+  SELECT * 
+    FROM wishlist AS w RIGHT JOIN LATERAL (
+          SELECT * FROM  product AS p
+           WHERE  p.price < w.desired_price
+           ORDER BY p.price DESC LIMIT 3
+         ) AS x ON true
+  ORDER BY wishlist_id, price DESC;
+} {1 {join must be INNER or LEFT for a LATERAL reference}}
+do_catchsql_test 1.3 {
+  SELECT * 
+    FROM wishlist AS w FULL OUTER JOIN LATERAL (
+          SELECT * FROM  product AS p
+           WHERE  p.price < w.desired_price
+           ORDER BY p.price DESC LIMIT 3
+         ) AS x ON true
+  ORDER BY wishlist_id, price DESC;
+} {1 {join must be INNER or LEFT for a LATERAL reference}}
+do_catchsql_test 1.4 {
+  SELECT * 
+    FROM wishlist AS w FULL OUTER JOIN LATERALx (
+          SELECT * FROM  product AS p
+           WHERE  p.price < w.desired_price
+           ORDER BY p.price DESC LIMIT 3
+         ) AS x ON true
+  ORDER BY wishlist_id, price DESC;
+} {1 {near "LATERALx": syntax error}}
+do_catchsql_test 1.5 {
+  SELECT * 
+    FROM wishlist AS w FULL OUTER JOIN LATERAL.xyz (
+          SELECT * FROM  product AS p
+           WHERE  p.price < w.desired_price
+           ORDER BY p.price DESC LIMIT 3
+         ) AS x ON true
+  ORDER BY wishlist_id, price DESC;
+} {1 {near "LATERAL": syntax error}}
+
 do_execsql_test 2.0 {
   CREATE TABLE orders(id INTEGER PRIMARY KEY, user_id INT, created_at TEXT);
   INSERT INTO orders VALUES
@@ -99,6 +137,33 @@ do_execsql_test 2.0 {
   2   2024-07-20T01:35:07  NULL                NULL
   3   2024-07-20T01:35:10  2024-07-20T01:58:17 5
 }
+do_execsql_test 2.1 {
+  SELECT user_id, first_order_time, next_order_time, id FROM
+    LATERAL (SELECT user_id, min(created_at) AS first_order_time
+       FROM orders GROUP BY user_id) AS o1
+    LEFT JOIN LATERAL
+    (SELECT id, created_at AS next_order_time
+     FROM orders
+     WHERE user_id = o1.user_id AND created_at > o1.first_order_time
+     ORDER BY created_at ASC LIMIT 1) AS o2
+    ON true;
+} {
+  1   2024-07-20T01:35:03  2024-07-20T01:58:10 4
+  2   2024-07-20T01:35:07  NULL                NULL
+  3   2024-07-20T01:35:10  2024-07-20T01:58:17 5
+}
 
+# "LATERAL" is a not actually a keyword.  It can be used as an indentifier for
+# historical compatibility.
+#
+do_execsql_test 3.0 {
+  CREATE TABLE lateral(a,lateral lateral);
+  INSERT INTO lateral VALUES(1,2);
+  SELECT * FROM lateral;
+  ATTACH ':memory:' AS lateral;
+  CREATE TABLE lateral.t2(x,y);
+  INSERT INTO t2 VALUES(98,99);
+  SELECT * FROM t2;
+} {1 2 98 99}
 
 finish_test
index c6f96e691b6daf3077854cd5a1b5a06647cbdf4b..5386a36c4077b5f164c08899e320133ada8ce7b5 100644 (file)
@@ -251,7 +251,6 @@ static Keyword aKeywordTable[] = {
   { "JOIN",             "TK_JOIN",         ALWAYS,           5      },
   { "KEY",              "TK_KEY",          ALWAYS,           1      },
   { "LAST",             "TK_LAST",         ALWAYS,           4      },
-  { "LATERAL",          "TK_LATERAL",      ALWAYS,           7      },
   { "LEFT",             "TK_JOIN_KW",      ALWAYS,           5      },
   { "LIKE",             "TK_LIKE_KW",      ALWAYS,           5      },
   { "LIMIT",            "TK_LIMIT",        ALWAYS,           3      },