aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/build.c8
-rw-r--r--src/parse.y22
-rw-r--r--src/sqliteInt.h2
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