diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/build.c | 26 | ||||
-rw-r--r-- | src/parse.y | 13 | ||||
-rw-r--r-- | src/sqliteInt.h | 4 |
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 |