From: drh <> Date: Sat, 20 Jul 2024 03:19:40 +0000 (+0000) Subject: "LATERAL" may not be a keyword, as that would cause problems for legacy X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f772da8333654b02b9a6cb66b52ea0ec861b9f0e;p=thirdparty%2Fsqlite.git "LATERAL" may not be a keyword, as that would cause problems for legacy databases that have tables named "lateral". It has to be parsed as an identifier. FossilOrigin-Name: 8217bddaf8c0697799c7518746996665bbd1f5a327315d18091a6ab3250f1112 --- diff --git a/manifest b/manifest index 0fa6ca7065..55f65b4aae 100644 --- 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. diff --git a/manifest.uuid b/manifest.uuid index 55f341b9bf..5cd623bdcf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3c045a96bc65713e5544af82b8547cdcdf93fa20f9b7b0851d77f8c090cc650b +8217bddaf8c0697799c7518746996665bbd1f5a327315d18091a6ab3250f1112 diff --git a/src/parse.y b/src/parse.y index 963b52d423..92f5e5989b 100644 --- a/src/parse.y +++ b/src/parse.y @@ -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; diff --git a/test/joinL.test b/test/joinL.test index 5d3366f989..508f2634c8 100644 --- a/test/joinL.test +++ b/test/joinL.test @@ -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 diff --git a/tool/mkkeywordhash.c b/tool/mkkeywordhash.c index c6f96e691b..5386a36c40 100644 --- a/tool/mkkeywordhash.c +++ b/tool/mkkeywordhash.c @@ -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 },