-C Enhance\sLEMON\sto\sshow\sprecendence\sof\ssymbols\sand\sall\srules\sin\sthe\sreport\nthat\sis\sgenerated\sin\sparallel\sto\sthe\sparser.
-D 2018-04-06T19:12:55.023
+C Demonstration\sof\show\sthe\sparser\scan\sbe\saugmented\sto\srecognize\sa\nPostgreSQL-style\sUPSERT.\s\sThis\scheck-in\simplements\sparsing\sonly.
+D 2018-04-06T19:36:49.704
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in 7016fc56c6b9bfe5daac4f34be8be38d8c0b5fab79ccbfb764d3b23bf1c6fff3
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c 1bb6a57fa0465296a4d6109a1a64610a0e7adde1f3acf3ef539a9d972908ce8f
F src/pager.h c571b064df842ec8f2e90855dead9acf4cbe0d1b2c05afe0ef0d0145f7fd0388
-F src/parse.y 140bbc53b5f67f731239f7fc8704a4f1e60cbbc10fb84bf9577322f974725f19
+F src/parse.y b6f9277147926f21ef287fbb8bc6592d801bc8f369d414af47ff2f230f026ea0
F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd
F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170
F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 7594e60935b0b5dcf764476dccdf9b403303818a0419a30bc2c16d58e44f6d04
-R ef1c977dfaed4c346b10d938399c3d50
+P 602fbd8149b53d8f0e9a223cc1aec912e7df03fca35071e8d707776ce225371c
+R 944a876dd463c4d747f0489cc93d0c37
+T *branch * upsert
+T *sym-upsert *
+T -sym-trunk *
U drh
-Z 131d6c9ff99d8e76f2b61b25cec666a3
+Z e91165cd71d725e31774ced0fb05304c
%left CONCAT.
%left COLLATE.
%right BITNOT.
+%nonassoc ON.
// An IDENTIFIER can be a generic identifier, or one of several
// keywords. Any non-standard keyword can also be an identifier.
joinop(X) ::= JOIN_KW(A) nm(B) nm(C) JOIN.
{X = sqlite3JoinType(pParse,&A,&B,&C);/*X-overwrites-A*/}
+// There is a parsing abiguity in an upsert statement that uses a
+// SELECT on the RHS of a the INSERT:
+//
+// INSERT INTO tab SELECT * FROM aaa JOIN bbb ON CONFLICT ...
+// here ----^^
+//
+// When the ON token is encountered, the parser does not know if it is
+// the beginning of an ON CONFLICT clause, or the beginning of an ON
+// clause associated with the JOIN. The conflict is resolved in favor
+// of the JOIN. If an ON CONFLICT clause is intended, insert a dummy
+// WHERE clause in between, like this:
+//
+// INSERT INTO tab SELECT * FROM aaa JOIN bbb WHERE true ON CONFLICT ...
+//
+// The [AND] and [OR] precedence marks in the rules for on_opt cause the
+// ON in this context to always be interpreted as belonging to the JOIN.
+//
%type on_opt {Expr*}
%destructor on_opt {sqlite3ExprDelete(pParse->db, $$);}
-on_opt(N) ::= ON expr(E). {N = E;}
-on_opt(N) ::= . {N = 0;}
+on_opt(N) ::= ON expr(E). {N = E;}
+on_opt(N) ::= . [OR] {N = 0;}
// Note that this block abuses the Token type just a little. If there is
// no "INDEXED BY" clause, the returned token is empty (z==0 && n==0). If
////////////////////////// The INSERT command /////////////////////////////////
//
-cmd ::= with(W) insert_cmd(R) INTO fullname(X) idlist_opt(F) select(S). {
+cmd ::= with(W) insert_cmd(R) INTO fullname(X) idlist_opt(F) select(S) upsert. {
sqlite3WithPush(pParse, W, 1);
sqlite3Insert(pParse, X, S, F, R);
}
sqlite3Insert(pParse, X, 0, F, R);
}
+upsert ::= .
+upsert ::= ON CONFLICT SET setlist.
+
%type insert_cmd {int}
insert_cmd(A) ::= INSERT orconf(R). {A = R;}
insert_cmd(A) ::= REPLACE. {A = OE_Replace;}