aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/build.c26
-rw-r--r--src/parse.y13
-rw-r--r--src/sqliteInt.h4
3 files changed, 39 insertions, 4 deletions
diff --git a/src/build.c b/src/build.c
index e947f2c84..62d9bb012 100644
--- a/src/build.c
+++ b/src/build.c
@@ -4504,3 +4504,29 @@ Upsert *sqlite3UpsertDup(sqlite3 *db, Upsert *p){
return pNew;
}
#endif /* SQLITE_OMIT_UPSERT */
+
+#ifndef SQLITE_OMIT_UPSERT
+/*
+** Create a new Upsert object.
+*/
+Upsert *sqlite3UpsertNew(
+ sqlite3 *db, /* Determines which memory allocator to use */
+ Upsert *pPrior, /* Append new upsert to the end of this one */
+ ExprList *pTarget, /* Target argument to ON CONFLICT, or NULL */
+ ExprList *pSet /* UPDATE columns, or NULL for a DO NOTHING */
+){
+ Upsert *pNew;
+ pNew = sqlite3DbMallocRaw(db, sizeof(Upsert));
+ if( pNew==0 ){
+ sqlite3UpsertDelete(db, pPrior);
+ sqlite3ExprListDelete(db, pTarget);
+ sqlite3ExprListDelete(db, pSet);
+ return 0;
+ }else{
+ pNew->pUpsertTarget = pTarget;
+ pNew->pUpsertSet = pSet;
+ pNew->pUpsertNext = pPrior;
+ }
+ return pNew;
+}
+#endif /* SQLITE_OMIT_UPSERT */
diff --git a/src/parse.y b/src/parse.y
index 09335d21e..059cd2614 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -205,7 +205,8 @@ columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,&A,&Y);}
//
%fallback ID
ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST COLUMNKW
- CONFLICT DATABASE DEFERRED DESC DETACH DO EACH END EXCLUSIVE EXPLAIN FAIL FOR
+ CONFLICT DATABASE DEFERRED DESC DETACH DO DUPLICATE
+ EACH END EXCLUSIVE EXPLAIN FAIL FOR
IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH NO PLAN
QUERY KEY OF OFFSET PRAGMA RAISE RECURSIVE RELEASE REPLACE RESTRICT ROW
ROLLBACK SAVEPOINT TEMP TRIGGER VACUUM VIEW VIRTUAL WITH WITHOUT
@@ -869,8 +870,14 @@ cmd ::= with insert_cmd(R) INTO fullname(X) idlist_opt(F) DEFAULT VALUES.
%type upsert {Upsert*}
%destructor upsert {sqlite3UpsertDelete(pParse->db,$$);}
upsert(A) ::= . { A = 0; }
-upsert(A) ::= ON CONFLICT DO UPDATE SET setlist. { A = 0; }
-upsert(A) ::= ON CONFLICT DO NOTHING. { A = 0; }
+upsert(A) ::= upsert(X) ON CONFLICT LP sortlist(Y) RP DO UPDATE SET setlist(Z).
+ { A = sqlite3UpsertNew(pParse->db,X,Y,Z); /*X-overwrites-A*/ }
+upsert(A) ::= upsert(X) ON DUPLIATE KEY UPDATE setlist(Z).
+ { A = sqlite3UpsertNew(pParse->db,X,0,Z); /*X-overwrites-A*/ }
+upsert(A) ::= upsert(X) ON CONFLICT LP sortlist(Y) RP DO NOTHING.
+ { A = sqlite3UpsertNew(pParse->db,X,Y,0); /*X-overwrites-A*/ }
+upsert(A) ::= upsert(X) ON CONFLICT DO NOTHING.
+ { A = sqlite3UpsertNew(pParse->db,X,0,0); /*X-overwrites-A*/ }
%type insert_cmd {int}
insert_cmd(A) ::= INSERT orconf(R). {A = R;}
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index d77df3ef9..1be52c258 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -4270,11 +4270,13 @@ const char *sqlite3JournalModename(int);
#define sqlite3WithDelete(x,y)
#endif
#ifndef SQLITE_OMIT_UPSERT
+ Upsert *sqlite3UpsertNew(sqlite3*,Upsert*,ExprList*,ExprList*);
void sqlite3UpsertDelete(sqlite3*,Upsert*);
Upsert *sqlite3UpsertDup(sqlite3*,Upsert*);
#else
+#define sqlite3UpsertNew(x,y,z) ((Upsert*)0)
#define sqlite3UpsertDelete(x,y)
-#define sqlite3UpsertDup(x,y) ((Upsert*)0)
+#define sqlite3UpsertDup(x,y) ((Upsert*)0)
#endif