Created
October 9, 2017 11:43
-
-
Save mingodad/768b47903e54715e919e08b94c05804f to your computer and use it in GitHub Desktop.
Patch to allow table alias for delete/update on sqlite3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: src/delete.c | |
================================================================== | |
--- src/delete.c | |
+++ src/delete.c | |
@@ -206,10 +206,11 @@ | |
** pTabList pWhere | |
*/ | |
void sqlite3DeleteFrom( | |
Parse *pParse, /* The parser context */ | |
SrcList *pTabList, /* The table from which we should delete things */ | |
+ Token *pAlias, /* The right-hand side of the AS subexpression */ | |
Expr *pWhere /* The WHERE clause. May be null */ | |
){ | |
Vdbe *v; /* The virtual database engine */ | |
Table *pTab; /* The table from which records will be deleted */ | |
int i; /* Loop counter */ | |
@@ -238,11 +239,12 @@ | |
int addrBypass = 0; /* Address of jump over the delete logic */ | |
int addrLoop = 0; /* Top of the delete loop */ | |
int addrEphOpen = 0; /* Instruction to open the Ephemeral table */ | |
int bComplex; /* True if there are triggers or FKs or | |
** subqueries in the WHERE clause */ | |
- | |
+ struct SrcList_item *pItem; /*To namage table alias*/ | |
+ | |
#ifndef SQLITE_OMIT_TRIGGER | |
int isView; /* True if attempting to delete from a view */ | |
Trigger *pTrigger; /* List of table triggers, if required */ | |
#endif | |
@@ -250,10 +252,15 @@ | |
db = pParse->db; | |
if( pParse->nErr || db->mallocFailed ){ | |
goto delete_from_cleanup; | |
} | |
assert( pTabList->nSrc==1 ); | |
+ /*Manage table alias*/ | |
+ pItem = &pTabList->a[pTabList->nSrc-1]; | |
+ if( pAlias && pAlias->n ){ | |
+ pItem->zAlias = sqlite3NameFromToken(db, pAlias); | |
+ } | |
/* Locate the table which we want to delete. This table has to be | |
** put in an SrcList structure because some of the subroutines we | |
** will be calling are designed to work with multiple tables and expect | |
** an SrcList* parameter instead of just a Table* parameter. | |
Index: src/fkey.c | |
================================================================== | |
--- src/fkey.c | |
+++ src/fkey.c | |
@@ -723,11 +723,11 @@ | |
iSkip = sqlite3VdbeMakeLabel(v); | |
sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip); VdbeCoverage(v); | |
} | |
pParse->disableTriggers = 1; | |
- sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0); | |
+ sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0, 0); | |
pParse->disableTriggers = 0; | |
/* If the DELETE has generated immediate foreign key constraint | |
** violations, halt the VDBE and return an error at this point, before | |
** any modifications to the schema are made. This is because statement | |
Index: src/parse.y | |
================================================================== | |
--- src/parse.y | |
+++ src/parse.y | |
@@ -747,23 +747,23 @@ | |
{A.pOffset = X.pExpr; A.pLimit = Y.pExpr;} | |
/////////////////////////// The DELETE statement ///////////////////////////// | |
// | |
%ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT | |
-cmd ::= with(C) DELETE FROM fullname(X) indexed_opt(I) where_opt(W) | |
+cmd ::= with(C) DELETE FROM fullname(X) as(Z) indexed_opt(I) where_opt(W) | |
orderby_opt(O) limit_opt(L). { | |
sqlite3WithPush(pParse, C, 1); | |
sqlite3SrcListIndexedBy(pParse, X, &I); | |
W = sqlite3LimitWhere(pParse, X, W, O, L.pLimit, L.pOffset, "DELETE"); | |
- sqlite3DeleteFrom(pParse,X,W); | |
+ sqlite3DeleteFrom(pParse,X,&Z,W); | |
} | |
%endif | |
%ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT | |
-cmd ::= with(C) DELETE FROM fullname(X) indexed_opt(I) where_opt(W). { | |
+cmd ::= with(C) DELETE FROM fullname(X) as(Z) indexed_opt(I) where_opt(W). { | |
sqlite3WithPush(pParse, C, 1); | |
sqlite3SrcListIndexedBy(pParse, X, &I); | |
- sqlite3DeleteFrom(pParse,X,W); | |
+ sqlite3DeleteFrom(pParse,X,&Z,W); | |
} | |
%endif | |
%type where_opt {Expr*} | |
%destructor where_opt {sqlite3ExprDelete(pParse->db, $$);} | |
@@ -772,26 +772,26 @@ | |
where_opt(A) ::= WHERE expr(X). {A = X.pExpr;} | |
////////////////////////// The UPDATE command //////////////////////////////// | |
// | |
%ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT | |
-cmd ::= with(C) UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y) | |
+cmd ::= with(C) UPDATE orconf(R) fullname(X) as(Z) indexed_opt(I) SET setlist(Y) | |
where_opt(W) orderby_opt(O) limit_opt(L). { | |
sqlite3WithPush(pParse, C, 1); | |
sqlite3SrcListIndexedBy(pParse, X, &I); | |
sqlite3ExprListCheckLength(pParse,Y,"set list"); | |
W = sqlite3LimitWhere(pParse, X, W, O, L.pLimit, L.pOffset, "UPDATE"); | |
- sqlite3Update(pParse,X,Y,W,R); | |
+ sqlite3Update(pParse,X,&Z,Y,W,R); | |
} | |
%endif | |
%ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT | |
-cmd ::= with(C) UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y) | |
+cmd ::= with(C) UPDATE orconf(R) fullname(X) as(Z) indexed_opt(I) SET setlist(Y) | |
where_opt(W). { | |
sqlite3WithPush(pParse, C, 1); | |
sqlite3SrcListIndexedBy(pParse, X, &I); | |
sqlite3ExprListCheckLength(pParse,Y,"set list"); | |
- sqlite3Update(pParse,X,Y,W,R); | |
+ sqlite3Update(pParse,X,&Z,Y,W,R); | |
} | |
%endif | |
%type setlist {ExprList*} | |
%destructor setlist {sqlite3ExprListDelete(pParse->db, $$);} | |
Index: src/sqliteInt.h | |
================================================================== | |
--- src/sqliteInt.h | |
+++ src/sqliteInt.h | |
@@ -3759,12 +3759,12 @@ | |
int sqlite3IsReadOnly(Parse*, Table*, int); | |
void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); | |
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) | |
Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,Expr*,char*); | |
#endif | |
-void sqlite3DeleteFrom(Parse*, SrcList*, Expr*); | |
-void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); | |
+void sqlite3DeleteFrom(Parse*, SrcList*, Token*, Expr*); | |
+void sqlite3Update(Parse*, SrcList*, Token*, ExprList*, Expr*, int); | |
WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int); | |
void sqlite3WhereEnd(WhereInfo*); | |
LogEst sqlite3WhereOutputRowCount(WhereInfo*); | |
int sqlite3WhereIsDistinct(WhereInfo*); | |
int sqlite3WhereIsOrdered(WhereInfo*); | |
Index: src/trigger.c | |
================================================================== | |
--- src/trigger.c | |
+++ src/trigger.c | |
@@ -706,11 +706,11 @@ | |
assert( pParse->okConstFactor==0 ); | |
switch( pStep->op ){ | |
case TK_UPDATE: { | |
sqlite3Update(pParse, | |
- targetSrcList(pParse, pStep), | |
+ targetSrcList(pParse, pStep), 0, | |
sqlite3ExprListDup(db, pStep->pExprList, 0), | |
sqlite3ExprDup(db, pStep->pWhere, 0), | |
pParse->eOrconf | |
); | |
break; | |
@@ -724,11 +724,11 @@ | |
); | |
break; | |
} | |
case TK_DELETE: { | |
sqlite3DeleteFrom(pParse, | |
- targetSrcList(pParse, pStep), | |
+ targetSrcList(pParse, pStep), 0, | |
sqlite3ExprDup(db, pStep->pWhere, 0) | |
); | |
break; | |
} | |
default: assert( pStep->op==TK_SELECT ); { | |
Index: src/update.c | |
================================================================== | |
--- src/update.c | |
+++ src/update.c | |
@@ -87,10 +87,11 @@ | |
* onError pTabList pChanges pWhere | |
*/ | |
void sqlite3Update( | |
Parse *pParse, /* The parser context */ | |
SrcList *pTabList, /* The table in which we should change things */ | |
+ Token *pAlias, /* The right-hand side of the AS subexpression */ | |
ExprList *pChanges, /* Things to be changed */ | |
Expr *pWhere, /* The WHERE clause. May be null */ | |
int onError /* How to handle constraint errors */ | |
){ | |
int i, j; /* Loop counters */ | |
@@ -120,11 +121,11 @@ | |
int eOnePass; /* ONEPASS_XXX value from where.c */ | |
int hasFK; /* True if foreign key processing is required */ | |
int labelBreak; /* Jump here to break out of UPDATE loop */ | |
int labelContinue; /* Jump here to continue next step of UPDATE loop */ | |
int flags; /* Flags for sqlite3WhereBegin() */ | |
- | |
+ struct SrcList_item *pItem; /*To namage table alias*/ | |
#ifndef SQLITE_OMIT_TRIGGER | |
int isView; /* True when updating a view (INSTEAD OF trigger) */ | |
Trigger *pTrigger; /* List of triggers on pTab, if required */ | |
int tmask; /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */ | |
#endif | |
@@ -151,10 +152,16 @@ | |
if( pParse->nErr || db->mallocFailed ){ | |
goto update_cleanup; | |
} | |
assert( pTabList->nSrc==1 ); | |
+ /*Manage table alias*/ | |
+ pItem = &pTabList->a[pTabList->nSrc-1]; | |
+ if( pAlias && pAlias->n ){ | |
+ pItem->zAlias = sqlite3NameFromToken(db, pAlias); | |
+ } | |
+ | |
/* Locate the table which we want to update. | |
*/ | |
pTab = sqlite3SrcListLookup(pParse, pTabList); | |
if( pTab==0 ) goto update_cleanup; | |
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment