diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/build.c | 8 | ||||
-rw-r--r-- | src/parse.y | 22 | ||||
-rw-r--r-- | src/sqliteInt.h | 2 |
3 files changed, 27 insertions, 5 deletions
diff --git a/src/build.c b/src/build.c index 50289c6a1..5b4bbe499 100644 --- a/src/build.c +++ b/src/build.c @@ -1243,6 +1243,14 @@ void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){ } #endif +/* +** Add the RETURNING clause to the parser currently underway. +*/ +void sqlite3AddReturning(Parse *pParse, ExprList *pList){ + sqlite3ParserAddCleanup(pParse, + (void(*)(sqlite3*,void*))sqlite3ExprListDelete, pList); + pParse->pReturning = pList; +} /* ** Add a new column to the table currently being constructed. diff --git a/src/parse.y b/src/parse.y index faec4b5cf..4c79d4a87 100644 --- a/src/parse.y +++ b/src/parse.y @@ -868,7 +868,7 @@ limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y). /////////////////////////// The DELETE statement ///////////////////////////// // %if SQLITE_ENABLE_UPDATE_DELETE_LIMIT || SQLITE_UDL_CAPABLE_PARSER -cmd ::= with DELETE FROM xfullname(X) indexed_opt(I) where_opt(W) +cmd ::= with DELETE FROM xfullname(X) indexed_opt(I) where_opt_ret(W) orderby_opt(O) limit_opt(L). { sqlite3SrcListIndexedBy(pParse, X, &I); #ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT @@ -881,7 +881,7 @@ cmd ::= with DELETE FROM xfullname(X) indexed_opt(I) where_opt(W) sqlite3DeleteFrom(pParse,X,W,O,L); } %else -cmd ::= with DELETE FROM xfullname(X) indexed_opt(I) where_opt(W). { +cmd ::= with DELETE FROM xfullname(X) indexed_opt(I) where_opt_ret(W). { sqlite3SrcListIndexedBy(pParse, X, &I); sqlite3DeleteFrom(pParse,X,W,0,0); } @@ -889,9 +889,17 @@ cmd ::= with DELETE FROM xfullname(X) indexed_opt(I) where_opt(W). { %type where_opt {Expr*} %destructor where_opt {sqlite3ExprDelete(pParse->db, $$);} +%type where_opt_ret {Expr*} +%destructor where_opt_ret {sqlite3ExprDelete(pParse->db, $$);} where_opt(A) ::= . {A = 0;} where_opt(A) ::= WHERE expr(X). {A = X;} +where_opt_ret(A) ::= . {A = 0;} +where_opt_ret(A) ::= WHERE expr(X). {A = X;} +where_opt_ret(A) ::= RETURNING selcollist(X). + {sqlite3AddReturning(pParse,X); A = 0;} +where_opt_ret(A) ::= WHERE expr(X) RETURNING selcollist(Y). + {sqlite3AddReturning(pParse,Y); A = X;} ////////////////////////// The UPDATE command //////////////////////////////// // @@ -946,7 +954,7 @@ cmd ::= with insert_cmd(R) INTO xfullname(X) idlist_opt(F) select(S) upsert(U). { sqlite3Insert(pParse, X, S, F, R, U); } -cmd ::= with insert_cmd(R) INTO xfullname(X) idlist_opt(F) DEFAULT VALUES. +cmd ::= with insert_cmd(R) INTO xfullname(X) idlist_opt(F) DEFAULT VALUES returning. { sqlite3Insert(pParse, X, 0, F, R, 0); } @@ -959,16 +967,20 @@ cmd ::= with insert_cmd(R) INTO xfullname(X) idlist_opt(F) DEFAULT VALUES. // avoid unreachable code. //%destructor upsert {sqlite3UpsertDelete(pParse->db,$$);} upsert(A) ::= . { A = 0; } +upsert(A) ::= RETURNING selcollist(X). { A = 0; sqlite3AddReturning(pParse,X); } upsert(A) ::= ON CONFLICT LP sortlist(T) RP where_opt(TW) DO UPDATE SET setlist(Z) where_opt(W) upsert(N). { A = sqlite3UpsertNew(pParse->db,T,TW,Z,W,N);} upsert(A) ::= ON CONFLICT LP sortlist(T) RP where_opt(TW) DO NOTHING upsert(N). { A = sqlite3UpsertNew(pParse->db,T,TW,0,0,N); } -upsert(A) ::= ON CONFLICT DO NOTHING. +upsert(A) ::= ON CONFLICT DO NOTHING returning. { A = sqlite3UpsertNew(pParse->db,0,0,0,0,0); } -upsert(A) ::= ON CONFLICT DO UPDATE SET setlist(Z) where_opt(W). +upsert(A) ::= ON CONFLICT DO UPDATE SET setlist(Z) where_opt(W) returning. { A = sqlite3UpsertNew(pParse->db,0,0,Z,W,0);} +returning ::= RETURNING selcollist(X). {sqlite3AddReturning(pParse,X);} +returning ::= . + %type insert_cmd {int} insert_cmd(A) ::= INSERT orconf(R). {A = R;} insert_cmd(A) ::= REPLACE. {A = OE_Replace;} diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 510aab1ca..c66b44290 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3441,6 +3441,7 @@ struct Parse { int aTempReg[8]; /* Holding area for temporary registers */ Token sNameToken; /* Token with unqualified schema object name */ + ExprList *pReturning; /* The RETURNING clause, if any */ /************************************************************************ ** Above is constant between recursions. Below is reset before and after @@ -4252,6 +4253,7 @@ void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*); void sqlite3AddCollateType(Parse*, Token*); void sqlite3AddGenerated(Parse*,Expr*,Token*); void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*); +void sqlite3AddReturning(Parse*,ExprList*); int sqlite3ParseUri(const char*,const char*,unsigned int*, sqlite3_vfs**,char**,char **); #define sqlite3CodecQueryParameters(A,B,C) 0 |