mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-11 01:42:22 +03:00
Enhance UPSERT so that it allows multiple ON CONFLICT clauses and does
not require a conflict target for DO UPDATE. FossilOrigin-Name: 6b01a24daab1e5bcb0768ebf994368d941b1dfc217bf6b661211d900331e68cf
This commit is contained in:
@@ -2316,16 +2316,22 @@ struct FKey {
|
||||
** is returned. REPLACE means that preexisting database rows that caused
|
||||
** a UNIQUE constraint violation are removed so that the new insert or
|
||||
** update can proceed. Processing continues and no error is reported.
|
||||
** UPDATE applies to insert operations only and means that the insert
|
||||
** is omitted and the DO UPDATE clause of an upsert is run instead.
|
||||
**
|
||||
** RESTRICT, SETNULL, and CASCADE actions apply only to foreign keys.
|
||||
** RESTRICT, SETNULL, SETDFLT, and CASCADE actions apply only to foreign keys.
|
||||
** RESTRICT is the same as ABORT for IMMEDIATE foreign keys and the
|
||||
** same as ROLLBACK for DEFERRED keys. SETNULL means that the foreign
|
||||
** key is set to NULL. CASCADE means that a DELETE or UPDATE of the
|
||||
** key is set to NULL. SETDFLT means that the foreign key is set
|
||||
** to its default value. CASCADE means that a DELETE or UPDATE of the
|
||||
** referenced table row is propagated into the row that holds the
|
||||
** foreign key.
|
||||
**
|
||||
** The OE_Default value is a place holder that means to use whatever
|
||||
** conflict resolution algorthm is required from context.
|
||||
**
|
||||
** The following symbolic values are used to record which type
|
||||
** of action to take.
|
||||
** of conflict resolution action to take.
|
||||
*/
|
||||
#define OE_None 0 /* There is no constraint to check */
|
||||
#define OE_Rollback 1 /* Fail the operation and rollback the transaction */
|
||||
@@ -3079,15 +3085,21 @@ struct NameContext {
|
||||
** WHERE clause is omitted.
|
||||
*/
|
||||
struct Upsert {
|
||||
ExprList *pUpsertTarget; /* Optional description of conflicting index */
|
||||
ExprList *pUpsertTarget; /* Optional description of conflict target */
|
||||
Expr *pUpsertTargetWhere; /* WHERE clause for partial index targets */
|
||||
ExprList *pUpsertSet; /* The SET clause from an ON CONFLICT UPDATE */
|
||||
Expr *pUpsertWhere; /* WHERE clause for the ON CONFLICT UPDATE */
|
||||
/* The fields above comprise the parse tree for the upsert clause.
|
||||
** The fields below are used to transfer information from the INSERT
|
||||
** processing down into the UPDATE processing while generating code.
|
||||
** Upsert owns the memory allocated above, but not the memory below. */
|
||||
Index *pUpsertIdx; /* Constraint that pUpsertTarget identifies */
|
||||
Upsert *pNextUpsert; /* Next ON CONFLICT clause in the list */
|
||||
u8 isDoUpdate; /* True for DO UPDATE. False for DO NOTHING */
|
||||
/* Above this point is the parse tree for the ON CONFLICT clauses.
|
||||
** The next group of fields stores intermediate data. */
|
||||
void *pToFree; /* Free memory when deleting the Upsert object */
|
||||
/* All fields above are owned by the Upsert object and must be freed
|
||||
** when the Upsert is destroyed. The fields below are used to transfer
|
||||
** information from the INSERT processing down into the UPDATE processing
|
||||
** while generating code. The fields below are owned by the INSERT
|
||||
** statement and will be freed by INSERT processing. */
|
||||
Index *pUpsertIdx; /* UNIQUE constraint specified by pUpsertTarget */
|
||||
SrcList *pUpsertSrc; /* Table to be updated */
|
||||
int regData; /* First register holding array of VALUES */
|
||||
int iDataCur; /* Index of the data cursor */
|
||||
@@ -4837,15 +4849,19 @@ const char *sqlite3JournalModename(int);
|
||||
#define sqlite3WithDelete(x,y)
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_UPSERT
|
||||
Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*);
|
||||
Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*,Upsert*);
|
||||
void sqlite3UpsertDelete(sqlite3*,Upsert*);
|
||||
Upsert *sqlite3UpsertDup(sqlite3*,Upsert*);
|
||||
int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*);
|
||||
void sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int);
|
||||
Upsert *sqlite3UpsertOfIndex(Upsert*,Index*);
|
||||
int sqlite3UpsertNextIsIPK(Upsert*);
|
||||
#else
|
||||
#define sqlite3UpsertNew(v,w,x,y,z) ((Upsert*)0)
|
||||
#define sqlite3UpsertNew(u,v,w,x,y,z) ((Upsert*)0)
|
||||
#define sqlite3UpsertDelete(x,y)
|
||||
#define sqlite3UpsertDup(x,y) ((Upsert*)0)
|
||||
#define sqlite3UpsertDup(x,y) ((Upsert*)0)
|
||||
#define sqlite3UpsertOfIndex(x,y) ((Upsert*)0)
|
||||
#define sqlite3UpsertNextIsIPK(x) 0
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user