mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Add the Upsert object for holding upsert clause information.
FossilOrigin-Name: d83eaed539b274c2abd650d07522f491865d4917acbb64d05d01b3ba5c3cd446
This commit is contained in:
20
manifest
20
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Merge\schanges\sfrom\strunk.
|
C Add\sthe\sUpsert\sobject\sfor\sholding\supsert\sclause\sinformation.
|
||||||
D 2018-04-12T12:25:45.560
|
D 2018-04-12T13:15:43.659
|
||||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||||
F Makefile.in 7016fc56c6b9bfe5daac4f34be8be38d8c0b5fab79ccbfb764d3b23bf1c6fff3
|
F Makefile.in 7016fc56c6b9bfe5daac4f34be8be38d8c0b5fab79ccbfb764d3b23bf1c6fff3
|
||||||
@@ -435,7 +435,7 @@ F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca
|
|||||||
F src/btree.c 9eb9531c65346bbfccf5325384b7db1849daf4db6601dcfe21ba5c5b20623b64
|
F src/btree.c 9eb9531c65346bbfccf5325384b7db1849daf4db6601dcfe21ba5c5b20623b64
|
||||||
F src/btree.h 0866c0a08255142ea0e754aabd211c843cab32045c978a592a43152405ed0c84
|
F src/btree.h 0866c0a08255142ea0e754aabd211c843cab32045c978a592a43152405ed0c84
|
||||||
F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96
|
F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96
|
||||||
F src/build.c 61320fb84034c24313de699f3385c6bfe093c925b4df2931c6eb63d7c94ec62a
|
F src/build.c 1932d05343aa5cf8462c10ac3c738be411908694482745682cc6f88370a83cab
|
||||||
F src/callback.c fe677cb5f5abb02f7a772a62a98c2f516426081df68856e8f2d5f950929b966a
|
F src/callback.c fe677cb5f5abb02f7a772a62a98c2f516426081df68856e8f2d5f950929b966a
|
||||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||||
F src/ctime.c bd9da3f1ff21b432564a16ef0b154cff03585dc43742842e99c58907c6cb4bef
|
F src/ctime.c bd9da3f1ff21b432564a16ef0b154cff03585dc43742842e99c58907c6cb4bef
|
||||||
@@ -452,7 +452,7 @@ F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a
|
|||||||
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
|
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
|
||||||
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
|
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
|
||||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||||
F src/insert.c 5e7a7dd617950277436e9d7f0b4782a310dc73a70a22fa1ed704f84dd687b638
|
F src/insert.c aca5346dc1cf32c0c7928e85ac6136341565f87ddf9a2fa8066fcf02720d8dc5
|
||||||
F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
|
F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
|
||||||
F src/loadext.c f6e4e416a736369f9e80eba609f0acda97148a8b0453784d670c78d3eed2f302
|
F src/loadext.c f6e4e416a736369f9e80eba609f0acda97148a8b0453784d670c78d3eed2f302
|
||||||
F src/main.c 1648fc7a9bcfdbfd9a9a04af96ff2796c3164b3f3c7e56ed63a3c51cd11d198d
|
F src/main.c 1648fc7a9bcfdbfd9a9a04af96ff2796c3164b3f3c7e56ed63a3c51cd11d198d
|
||||||
@@ -480,7 +480,7 @@ F src/os_win.c eb03c6d52f893bcd7fdd4c6006674c13c1b5e49543fec98d605201af2997171c
|
|||||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||||
F src/pager.c 1bb6a57fa0465296a4d6109a1a64610a0e7adde1f3acf3ef539a9d972908ce8f
|
F src/pager.c 1bb6a57fa0465296a4d6109a1a64610a0e7adde1f3acf3ef539a9d972908ce8f
|
||||||
F src/pager.h c571b064df842ec8f2e90855dead9acf4cbe0d1b2c05afe0ef0d0145f7fd0388
|
F src/pager.h c571b064df842ec8f2e90855dead9acf4cbe0d1b2c05afe0ef0d0145f7fd0388
|
||||||
F src/parse.y 306ece8a7ccc4d38e29d6b86d8707dfcc62c85901e32ffe30f8e4909c3d768b8
|
F src/parse.y d12dad9be6676ec6d71375ee4daf12446479c37c3e67b5d161ced94770ed891f
|
||||||
F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd
|
F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd
|
||||||
F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170
|
F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170
|
||||||
F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880
|
F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880
|
||||||
@@ -496,7 +496,7 @@ F src/shell.c.in cc960721e56ebc1a78773bb5d2f5608b54275f945cbe49e4afe919d6888062a
|
|||||||
F src/sqlite.h.in e0be726ea6e4e6571724d39d242472ecd8bd1ba6f84ade88e1641bde98a6d02b
|
F src/sqlite.h.in e0be726ea6e4e6571724d39d242472ecd8bd1ba6f84ade88e1641bde98a6d02b
|
||||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||||
F src/sqlite3ext.h 83a3c4ce93d650bedfd1aa558cb85a516bd6d094445ee989740827d0d944368d
|
F src/sqlite3ext.h 83a3c4ce93d650bedfd1aa558cb85a516bd6d094445ee989740827d0d944368d
|
||||||
F src/sqliteInt.h a1a986e2b9d1c7920e355bb88f6c4a1db2667befc59dcadfdb0ae559d5ba7c70
|
F src/sqliteInt.h 1c6d9e73447dedb745332f13e721ae286c89a2608229ff2766c551f7e82cb59f
|
||||||
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
|
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
|
||||||
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
|
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
|
||||||
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
|
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
|
||||||
@@ -555,7 +555,7 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
|||||||
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
||||||
F src/tokenize.c 5b0c661a85f783d35b9883830736eeb63be4aefc4f6b7d9cd081d48782c041e2
|
F src/tokenize.c 5b0c661a85f783d35b9883830736eeb63be4aefc4f6b7d9cd081d48782c041e2
|
||||||
F src/treeview.c 14d5d1254702ec96876aa52642cb31548612384134970409fae333b25b39d6bb
|
F src/treeview.c 14d5d1254702ec96876aa52642cb31548612384134970409fae333b25b39d6bb
|
||||||
F src/trigger.c 974377de987711636aa7faec963863ae8864139a051d5ba2a2a4a0329dcd8895
|
F src/trigger.c 00ef0b16ab3f0063439e6582086f57f3beb93cd7e7ba46569a8bdc490c16283d
|
||||||
F src/update.c 97d4c9514229f540f8c441e124d5af7f93c5b030c9574539d01e99462e273998
|
F src/update.c 97d4c9514229f540f8c441e124d5af7f93c5b030c9574539d01e99462e273998
|
||||||
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
|
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
|
||||||
F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157
|
F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157
|
||||||
@@ -1717,7 +1717,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||||
P 7dfd4543da7ef741852252d3c78ba89a919d737787e9e5118579e35fdfdeb24c d7ec7b5970df9e542401f8299e098a5039d1875e2e3383dad06a0ec998589b6e
|
P 9f6f11805eb7cc02f7eb3044250f3981d46d2dbf0c421bd73e7f8b437390db25
|
||||||
R 22c0de7699239b37705a12f37b4c7dac
|
R 9c9bfe6b21b590d3496b5647552569d5
|
||||||
U drh
|
U drh
|
||||||
Z 5bc8368030e26095e5c80de69174e4cd
|
Z 1c9e24d2d854f92e297db13f4513adcb
|
||||||
|
@@ -1 +1 @@
|
|||||||
9f6f11805eb7cc02f7eb3044250f3981d46d2dbf0c421bd73e7f8b437390db25
|
d83eaed539b274c2abd650d07522f491865d4917acbb64d05d01b3ba5c3cd446
|
31
src/build.c
31
src/build.c
@@ -4473,3 +4473,34 @@ void sqlite3WithDelete(sqlite3 *db, With *pWith){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* !defined(SQLITE_OMIT_CTE) */
|
#endif /* !defined(SQLITE_OMIT_CTE) */
|
||||||
|
|
||||||
|
#ifndef SQLITE_OMIT_UPSERT
|
||||||
|
/*
|
||||||
|
** Free a list of Upsert objects
|
||||||
|
*/
|
||||||
|
void sqlite3UpsertDelete(sqlite3 *db, Upsert *p){
|
||||||
|
while( p ){
|
||||||
|
Upsert *pNext = p->pUpsertNext;
|
||||||
|
sqlite3ExprListDelete(db, p->pUpsertTarget);
|
||||||
|
sqlite3ExprListDelete(db, p->pUpsertSet);
|
||||||
|
sqlite3DbFree(db, p);
|
||||||
|
p = pNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* SQLITE_OMIT_UPSERT */
|
||||||
|
|
||||||
|
#ifndef SQLITE_OMIT_UPSERT
|
||||||
|
/*
|
||||||
|
** Duplicate an Upsert object
|
||||||
|
*/
|
||||||
|
Upsert *sqlite3UpsertDup(sqlite3 *db, Upsert *p){
|
||||||
|
Upsert *pNew;
|
||||||
|
if( p==0 ) return 0;
|
||||||
|
pNew = sqlite3DbMallocRaw(db, sizeof(Upsert));
|
||||||
|
if( pNew==0 ) return 0;
|
||||||
|
pNew->pUpsertTarget = sqlite3ExprListDup(db, p->pUpsertTarget, 0);
|
||||||
|
pNew->pUpsertSet = sqlite3ExprListDup(db, p->pUpsertSet, 0);
|
||||||
|
pNew->pUpsertNext = sqlite3UpsertDup(db, p->pUpsertNext);
|
||||||
|
return pNew;
|
||||||
|
}
|
||||||
|
#endif /* SQLITE_OMIT_UPSERT */
|
||||||
|
@@ -489,7 +489,7 @@ void sqlite3Insert(
|
|||||||
Select *pSelect, /* A SELECT statement to use as the data source */
|
Select *pSelect, /* A SELECT statement to use as the data source */
|
||||||
IdList *pColumn, /* Column names corresponding to IDLIST. */
|
IdList *pColumn, /* Column names corresponding to IDLIST. */
|
||||||
int onError, /* How to handle constraint errors */
|
int onError, /* How to handle constraint errors */
|
||||||
ExprList *pUpsert /* Upsert values */
|
Upsert *pUpsert /* ON CONFLICT clauses for upsert, or NULL */
|
||||||
){
|
){
|
||||||
sqlite3 *db; /* The main database structure */
|
sqlite3 *db; /* The main database structure */
|
||||||
Table *pTab; /* The table to insert into. aka TABLE */
|
Table *pTab; /* The table to insert into. aka TABLE */
|
||||||
@@ -528,11 +528,6 @@ void sqlite3Insert(
|
|||||||
int tmask; /* Mask of trigger times */
|
int tmask; /* Mask of trigger times */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The conflict resolution type is always OE_Update or OE_Replace when
|
|
||||||
** there is an upsert clause */
|
|
||||||
assert( onError==OE_Update || pUpsert==0 );
|
|
||||||
assert( OE_Update==OE_Replace );
|
|
||||||
|
|
||||||
db = pParse->db;
|
db = pParse->db;
|
||||||
if( pParse->nErr || db->mallocFailed ){
|
if( pParse->nErr || db->mallocFailed ){
|
||||||
goto insert_cleanup;
|
goto insert_cleanup;
|
||||||
@@ -1080,7 +1075,7 @@ insert_end:
|
|||||||
insert_cleanup:
|
insert_cleanup:
|
||||||
sqlite3SrcListDelete(db, pTabList);
|
sqlite3SrcListDelete(db, pTabList);
|
||||||
sqlite3ExprListDelete(db, pList);
|
sqlite3ExprListDelete(db, pList);
|
||||||
sqlite3ExprListDelete(db, pUpsert);
|
sqlite3UpsertDelete(db, pUpsert);
|
||||||
sqlite3SelectDelete(db, pSelect);
|
sqlite3SelectDelete(db, pSelect);
|
||||||
sqlite3IdListDelete(db, pColumn);
|
sqlite3IdListDelete(db, pColumn);
|
||||||
sqlite3DbFree(db, aRegIdx);
|
sqlite3DbFree(db, aRegIdx);
|
||||||
|
57
src/parse.y
57
src/parse.y
@@ -98,22 +98,6 @@
|
|||||||
*/
|
*/
|
||||||
struct TrigEvent { int a; IdList * b; };
|
struct TrigEvent { int a; IdList * b; };
|
||||||
|
|
||||||
/*
|
|
||||||
** An instance of this object holds the argument of the ON CONFLICT
|
|
||||||
** clause of an UPSERT.
|
|
||||||
**
|
|
||||||
** The ON CONFLICT clause takes three forms, identified by the Upsert.e
|
|
||||||
** field:
|
|
||||||
**
|
|
||||||
** OE_None: No ON CONFLICT clause
|
|
||||||
** OE_Ignore: ON CONFLICT DO NOTHING
|
|
||||||
** OE_Update: ON CONFLICT DO UPDATE ...
|
|
||||||
*/
|
|
||||||
struct Upsert {
|
|
||||||
ExprList *p; /* column=expr entries for the UPDATE. Or NULL */
|
|
||||||
int e; /* OE_None, OE_Replace, or OE_Ignore */
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Disable lookaside memory allocation for objects that might be
|
** Disable lookaside memory allocation for objects that might be
|
||||||
** shared across database connections.
|
** shared across database connections.
|
||||||
@@ -875,44 +859,18 @@ setlist(A) ::= LP idlist(X) RP EQ expr(Y). {
|
|||||||
//
|
//
|
||||||
cmd ::= with insert_cmd(R) INTO fullname(X) idlist_opt(F) select(S)
|
cmd ::= with insert_cmd(R) INTO fullname(X) idlist_opt(F) select(S)
|
||||||
upsert(U). {
|
upsert(U). {
|
||||||
sqlite3Insert(pParse, X, S, F, upsertType(pParse, R, U.e), U.p);
|
sqlite3Insert(pParse, X, S, F, R, U);
|
||||||
}
|
}
|
||||||
cmd ::= with insert_cmd(R) INTO fullname(X) idlist_opt(F) DEFAULT VALUES.
|
cmd ::= with insert_cmd(R) INTO fullname(X) idlist_opt(F) DEFAULT VALUES.
|
||||||
{
|
{
|
||||||
sqlite3Insert(pParse, X, 0, F, R, 0);
|
sqlite3Insert(pParse, X, 0, F, R, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
%type upsert {struct Upsert}
|
%type upsert {Upsert*}
|
||||||
%destructor upsert {sqlite3ExprListDelete(pParse->db,$$.p);}
|
%destructor upsert {sqlite3UpsertDelete(pParse->db,$$);}
|
||||||
upsert(A) ::= . {
|
upsert(A) ::= . { A = 0; }
|
||||||
A.p = 0;
|
upsert(A) ::= ON CONFLICT DO UPDATE SET setlist. { A = 0; }
|
||||||
A.e = OE_None;
|
upsert(A) ::= ON CONFLICT DO NOTHING. { A = 0; }
|
||||||
}
|
|
||||||
upsert(A) ::= ON CONFLICT DO UPDATE SET setlist(X). {
|
|
||||||
A.p = X; /*A-overwrites-X*/
|
|
||||||
A.e = OE_Update;
|
|
||||||
}
|
|
||||||
upsert(A) ::= ON CONFLICT DO NOTHING. {
|
|
||||||
A.p = 0;
|
|
||||||
A.e = OE_Ignore;
|
|
||||||
}
|
|
||||||
|
|
||||||
%include {
|
|
||||||
/* Compute and return the correct conflict resolution strategy for an
|
|
||||||
** INSERT statement. If the statement begins with REPLACE or with
|
|
||||||
** INSERT OR, and it contains an ON CONFLICT clause, throw an error.
|
|
||||||
*/
|
|
||||||
static int upsertType(Parse *pParse, int orconf, int upsertType){
|
|
||||||
if( upsertType!=OE_None ){
|
|
||||||
if( orconf!=OE_Default ){
|
|
||||||
sqlite3ErrorMsg(pParse, "ON CONFLICT clause not allowed");
|
|
||||||
}
|
|
||||||
return upsertType;
|
|
||||||
}else{
|
|
||||||
return orconf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
%type insert_cmd {int}
|
%type insert_cmd {int}
|
||||||
insert_cmd(A) ::= INSERT orconf(R). {A = R;}
|
insert_cmd(A) ::= INSERT orconf(R). {A = R;}
|
||||||
@@ -1460,8 +1418,7 @@ trigger_cmd(A) ::=
|
|||||||
// INSERT
|
// INSERT
|
||||||
trigger_cmd(A) ::= scanpt(B) insert_cmd(R) INTO
|
trigger_cmd(A) ::= scanpt(B) insert_cmd(R) INTO
|
||||||
trnm(X) idlist_opt(F) select(S) upsert(U) scanpt(Z). {
|
trnm(X) idlist_opt(F) select(S) upsert(U) scanpt(Z). {
|
||||||
A = sqlite3TriggerInsertStep(pParse->db,&X,F,S,upsertType(pParse,R,U.e),
|
A = sqlite3TriggerInsertStep(pParse->db,&X,F,S,R,U,B,Z);/*A-overwrites-R*/
|
||||||
U.p,B,Z);/*A-overwrites-R*/
|
|
||||||
}
|
}
|
||||||
// DELETE
|
// DELETE
|
||||||
trigger_cmd(A) ::= DELETE(B) FROM trnm(X) tridxby where_opt(Y) scanpt(E).
|
trigger_cmd(A) ::= DELETE(B) FROM trnm(X) tridxby where_opt(Y) scanpt(E).
|
||||||
|
@@ -1095,6 +1095,7 @@ typedef struct Trigger Trigger;
|
|||||||
typedef struct TriggerPrg TriggerPrg;
|
typedef struct TriggerPrg TriggerPrg;
|
||||||
typedef struct TriggerStep TriggerStep;
|
typedef struct TriggerStep TriggerStep;
|
||||||
typedef struct UnpackedRecord UnpackedRecord;
|
typedef struct UnpackedRecord UnpackedRecord;
|
||||||
|
typedef struct Upsert Upsert;
|
||||||
typedef struct VTable VTable;
|
typedef struct VTable VTable;
|
||||||
typedef struct VtabCtx VtabCtx;
|
typedef struct VtabCtx VtabCtx;
|
||||||
typedef struct Walker Walker;
|
typedef struct Walker Walker;
|
||||||
@@ -2046,7 +2047,6 @@ struct FKey {
|
|||||||
#define OE_Fail 3 /* Stop the operation but leave all prior changes */
|
#define OE_Fail 3 /* Stop the operation but leave all prior changes */
|
||||||
#define OE_Ignore 4 /* Ignore the error. Do not do the INSERT or UPDATE */
|
#define OE_Ignore 4 /* Ignore the error. Do not do the INSERT or UPDATE */
|
||||||
#define OE_Replace 5 /* Delete existing record, then do INSERT or UPDATE */
|
#define OE_Replace 5 /* Delete existing record, then do INSERT or UPDATE */
|
||||||
#define OE_Update 5 /* An UPSERT. Same value as OE_Replace. */
|
|
||||||
|
|
||||||
#define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */
|
#define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */
|
||||||
#define OE_SetNull 7 /* Set the foreign key value to NULL */
|
#define OE_SetNull 7 /* Set the foreign key value to NULL */
|
||||||
@@ -2709,6 +2709,17 @@ struct NameContext {
|
|||||||
#define NC_MinMaxAgg 0x1000 /* min/max aggregates seen. See note above */
|
#define NC_MinMaxAgg 0x1000 /* min/max aggregates seen. See note above */
|
||||||
#define NC_Complex 0x2000 /* True if a function or subquery seen */
|
#define NC_Complex 0x2000 /* True if a function or subquery seen */
|
||||||
|
|
||||||
|
/*
|
||||||
|
** An instance of the following object describes a single ON CONFLICT
|
||||||
|
** clause in an upsert. A list of these objects may be attached to
|
||||||
|
** an INSERT statement in order to form an upsert.
|
||||||
|
*/
|
||||||
|
struct Upsert {
|
||||||
|
ExprList *pUpsertTarget; /* Optional description of conflicting index */
|
||||||
|
ExprList *pUpsertSet; /* The SET clause from an ON CONFLICT UPDATE */
|
||||||
|
Upsert *pUpsertNext; /* Next ON CONFLICT clause in the list */
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** An instance of the following structure contains all information
|
** An instance of the following structure contains all information
|
||||||
** needed to generate code for a single SELECT statement.
|
** needed to generate code for a single SELECT statement.
|
||||||
@@ -3208,8 +3219,9 @@ struct TriggerStep {
|
|||||||
Select *pSelect; /* SELECT statement or RHS of INSERT INTO SELECT ... */
|
Select *pSelect; /* SELECT statement or RHS of INSERT INTO SELECT ... */
|
||||||
char *zTarget; /* Target table for DELETE, UPDATE, INSERT */
|
char *zTarget; /* Target table for DELETE, UPDATE, INSERT */
|
||||||
Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */
|
Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */
|
||||||
ExprList *pExprList; /* SET clause for UPDATE or UPSERT. */
|
ExprList *pExprList; /* SET clause for UPDATE */
|
||||||
IdList *pIdList; /* Column names for INSERT */
|
IdList *pIdList; /* Column names for INSERT */
|
||||||
|
Upsert *pUpsert; /* Upsert clauses on an INSERT */
|
||||||
char *zSpan; /* Original SQL text of this command */
|
char *zSpan; /* Original SQL text of this command */
|
||||||
TriggerStep *pNext; /* Next in the link-list */
|
TriggerStep *pNext; /* Next in the link-list */
|
||||||
TriggerStep *pLast; /* Last element in link-list. Valid for 1st elem only */
|
TriggerStep *pLast; /* Last element in link-list. Valid for 1st elem only */
|
||||||
@@ -3741,7 +3753,7 @@ void sqlite3DeleteTable(sqlite3*, Table*);
|
|||||||
# define sqlite3AutoincrementBegin(X)
|
# define sqlite3AutoincrementBegin(X)
|
||||||
# define sqlite3AutoincrementEnd(X)
|
# define sqlite3AutoincrementEnd(X)
|
||||||
#endif
|
#endif
|
||||||
void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int, ExprList*);
|
void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int, Upsert*);
|
||||||
void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
|
void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
|
||||||
IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*);
|
IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*);
|
||||||
int sqlite3IdListIndex(IdList*,const char*);
|
int sqlite3IdListIndex(IdList*,const char*);
|
||||||
@@ -3917,7 +3929,7 @@ void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int);
|
|||||||
TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*,
|
TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*,
|
||||||
const char*,const char*);
|
const char*,const char*);
|
||||||
TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*,
|
TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*,
|
||||||
Select*,u8,ExprList*,
|
Select*,u8,Upsert*,
|
||||||
const char*,const char*);
|
const char*,const char*);
|
||||||
TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8,
|
TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8,
|
||||||
const char*,const char*);
|
const char*,const char*);
|
||||||
@@ -4257,6 +4269,14 @@ const char *sqlite3JournalModename(int);
|
|||||||
#define sqlite3WithPush(x,y,z)
|
#define sqlite3WithPush(x,y,z)
|
||||||
#define sqlite3WithDelete(x,y)
|
#define sqlite3WithDelete(x,y)
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef SQLITE_OMIT_UPSERT
|
||||||
|
void sqlite3UpsertDelete(sqlite3*,Upsert*);
|
||||||
|
Upsert *sqlite3UpsertDup(sqlite3*,Upsert*);
|
||||||
|
#else
|
||||||
|
#define sqlite3UpsertDelete(x,y)
|
||||||
|
#define sqlite3UpsertDup(x,y) ((Upsert*)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Declarations for functions in fkey.c. All of these are replaced by
|
/* Declarations for functions in fkey.c. All of these are replaced by
|
||||||
** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign
|
** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign
|
||||||
|
@@ -25,6 +25,7 @@ void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerStep){
|
|||||||
sqlite3ExprListDelete(db, pTmp->pExprList);
|
sqlite3ExprListDelete(db, pTmp->pExprList);
|
||||||
sqlite3SelectDelete(db, pTmp->pSelect);
|
sqlite3SelectDelete(db, pTmp->pSelect);
|
||||||
sqlite3IdListDelete(db, pTmp->pIdList);
|
sqlite3IdListDelete(db, pTmp->pIdList);
|
||||||
|
sqlite3UpsertDelete(db, pTmp->pUpsert);
|
||||||
sqlite3DbFree(db, pTmp->zSpan);
|
sqlite3DbFree(db, pTmp->zSpan);
|
||||||
|
|
||||||
sqlite3DbFree(db, pTmp);
|
sqlite3DbFree(db, pTmp);
|
||||||
@@ -416,7 +417,7 @@ TriggerStep *sqlite3TriggerInsertStep(
|
|||||||
IdList *pColumn, /* List of columns in pTableName to insert into */
|
IdList *pColumn, /* List of columns in pTableName to insert into */
|
||||||
Select *pSelect, /* A SELECT statement that supplies values */
|
Select *pSelect, /* A SELECT statement that supplies values */
|
||||||
u8 orconf, /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
|
u8 orconf, /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
|
||||||
ExprList *pUpsert, /* Upsert values */
|
Upsert *pUpsert, /* ON CONFLICT clauses for upsert */
|
||||||
const char *zStart, /* Start of SQL text */
|
const char *zStart, /* Start of SQL text */
|
||||||
const char *zEnd /* End of SQL text */
|
const char *zEnd /* End of SQL text */
|
||||||
){
|
){
|
||||||
@@ -428,10 +429,11 @@ TriggerStep *sqlite3TriggerInsertStep(
|
|||||||
if( pTriggerStep ){
|
if( pTriggerStep ){
|
||||||
pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
|
pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
|
||||||
pTriggerStep->pIdList = pColumn;
|
pTriggerStep->pIdList = pColumn;
|
||||||
|
pTriggerStep->pUpsert = pUpsert;
|
||||||
pTriggerStep->orconf = orconf;
|
pTriggerStep->orconf = orconf;
|
||||||
}else{
|
}else{
|
||||||
sqlite3IdListDelete(db, pColumn);
|
sqlite3IdListDelete(db, pColumn);
|
||||||
sqlite3ExprListDelete(db, pUpsert);
|
sqlite3UpsertDelete(db, pUpsert);
|
||||||
}
|
}
|
||||||
sqlite3SelectDelete(db, pSelect);
|
sqlite3SelectDelete(db, pSelect);
|
||||||
|
|
||||||
@@ -757,8 +759,8 @@ static int codeTriggerProgram(
|
|||||||
targetSrcList(pParse, pStep),
|
targetSrcList(pParse, pStep),
|
||||||
sqlite3SelectDup(db, pStep->pSelect, 0),
|
sqlite3SelectDup(db, pStep->pSelect, 0),
|
||||||
sqlite3IdListDup(db, pStep->pIdList),
|
sqlite3IdListDup(db, pStep->pIdList),
|
||||||
pStep->pExprList ? OE_Update : pParse->eOrconf,
|
pParse->eOrconf,
|
||||||
sqlite3ExprListDup(db, pStep->pExprList, 0)
|
sqlite3UpsertDup(db, pStep->pUpsert)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user