aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2014-01-10 20:46:55 +0000
committerdrh <drh@noemail.net>2014-01-10 20:46:55 +0000
commit75593d96be4062a3fd6cf86135b945e95367b10b (patch)
treeebf32c3c53072f8fee20f451a1664006a17b43d4 /src
parentc740752470a0557b03299c5fd5036e5e096b78e3 (diff)
downloadsqlite-75593d96be4062a3fd6cf86135b945e95367b10b.tar.gz
sqlite-75593d96be4062a3fd6cf86135b945e95367b10b.zip
Allow a VALUES clause to be used any place that a SELECT statement can be
used. FossilOrigin-Name: c9ea7d199f06a7801ab639e7ac98ebeb98706f24
Diffstat (limited to 'src')
-rw-r--r--src/insert.c13
-rw-r--r--src/parse.y70
-rw-r--r--src/sqliteInt.h6
-rw-r--r--src/trigger.c7
4 files changed, 36 insertions, 60 deletions
diff --git a/src/insert.c b/src/insert.c
index abc34c03c..038d08a40 100644
--- a/src/insert.c
+++ b/src/insert.c
@@ -540,7 +540,6 @@ static int xferOptimization(
void sqlite3Insert(
Parse *pParse, /* Parser context */
SrcList *pTabList, /* Name of table into which we are inserting */
- ExprList *pList, /* List of values to be inserted */
Select *pSelect, /* A SELECT statement to use as the data source */
IdList *pColumn, /* Column names corresponding to IDLIST. */
int onError /* How to handle constraint errors */
@@ -568,6 +567,7 @@ void sqlite3Insert(
Db *pDb; /* The database containing table being inserted into */
int appendFlag = 0; /* True if the insert is likely to be an append */
int withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */
+ ExprList *pList = 0; /* List of VALUES() to be inserted */
/* Register allocations */
int regFromSelect = 0;/* Base register for data coming from SELECT */
@@ -591,6 +591,17 @@ void sqlite3Insert(
goto insert_cleanup;
}
+ /* If the Select object is really just a simple VALUES() list with a
+ ** single row values (the common case) then keep that one row of values
+ ** and go ahead and discard the Select object
+ */
+ if( pSelect && (pSelect->selFlags & SF_Values)!=0 && pSelect->pPrior==0 ){
+ pList = pSelect->pEList;
+ pSelect->pEList = 0;
+ sqlite3SelectDelete(db, pSelect);
+ pSelect = 0;
+ }
+
/* Locate the table into which we will be inserting new information.
*/
assert( pTabList->nSrc==1 );
diff --git a/src/parse.y b/src/parse.y
index ba9feb10f..00d47cd3e 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -442,6 +442,23 @@ oneselect(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y)
groupby_opt(P) having_opt(Q) orderby_opt(Z) limit_opt(L). {
A = sqlite3SelectNew(pParse,W,X,Y,P,Q,Z,D,L.pLimit,L.pOffset);
}
+oneselect(A) ::= values(X). {A = X;}
+
+%type values {Select*}
+%destructor values {sqlite3SelectDelete(pParse->db, $$);}
+values(A) ::= VALUES LP nexprlist(X) RP. {
+ A = sqlite3SelectNew(pParse,X,0,0,0,0,0,SF_Values,0,0);
+}
+values(A) ::= values(X) COMMA LP exprlist(Y) RP. {
+ Select *pRight = sqlite3SelectNew(pParse,Y,0,0,0,0,0,SF_Values,0,0);
+ if( pRight ){
+ pRight->op = TK_ALL;
+ pRight->pPrior = X;
+ A = pRight;
+ }else{
+ A = X;
+ }
+}
// The "distinct" nonterminal is true (1) if the DISTINCT keyword is
// present and false (0) if it is not.
@@ -696,58 +713,15 @@ setlist(A) ::= nm(X) EQ expr(Y). {
////////////////////////// The INSERT command /////////////////////////////////
//
-cmd ::= insert_cmd(R) INTO fullname(X) inscollist_opt(F) valuelist(Y).
- {sqlite3Insert(pParse, X, Y.pList, Y.pSelect, F, R);}
cmd ::= insert_cmd(R) INTO fullname(X) inscollist_opt(F) select(S).
- {sqlite3Insert(pParse, X, 0, S, F, R);}
+ {sqlite3Insert(pParse, X, S, F, R);}
cmd ::= insert_cmd(R) INTO fullname(X) inscollist_opt(F) DEFAULT VALUES.
- {sqlite3Insert(pParse, X, 0, 0, F, R);}
+ {sqlite3Insert(pParse, X, 0, F, R);}
%type insert_cmd {u8}
insert_cmd(A) ::= INSERT orconf(R). {A = R;}
insert_cmd(A) ::= REPLACE. {A = OE_Replace;}
-// A ValueList is either a single VALUES clause or a comma-separated list
-// of VALUES clauses. If it is a single VALUES clause then the
-// ValueList.pList field points to the expression list of that clause.
-// If it is a list of VALUES clauses, then those clauses are transformed
-// into a set of SELECT statements without FROM clauses and connected by
-// UNION ALL and the ValueList.pSelect points to the right-most SELECT in
-// that compound.
-%type valuelist {struct ValueList}
-%destructor valuelist {
- sqlite3ExprListDelete(pParse->db, $$.pList);
- sqlite3SelectDelete(pParse->db, $$.pSelect);
-}
-valuelist(A) ::= VALUES LP nexprlist(X) RP. {
- A.pList = X;
- A.pSelect = 0;
-}
-
-// Since a list of VALUEs is inplemented as a compound SELECT, we have
-// to disable the value list option if compound SELECTs are disabled.
-%ifndef SQLITE_OMIT_COMPOUND_SELECT
-valuelist(A) ::= valuelist(X) COMMA LP exprlist(Y) RP. {
- Select *pRight = sqlite3SelectNew(pParse, Y, 0, 0, 0, 0, 0, 0, 0, 0);
- if( X.pList ){
- X.pSelect = sqlite3SelectNew(pParse, X.pList, 0, 0, 0, 0, 0, 0, 0, 0);
- X.pList = 0;
- }
- A.pList = 0;
- if( X.pSelect==0 || pRight==0 ){
- sqlite3SelectDelete(pParse->db, pRight);
- sqlite3SelectDelete(pParse->db, X.pSelect);
- A.pSelect = 0;
- }else{
- pRight->op = TK_ALL;
- pRight->pPrior = X.pSelect;
- pRight->selFlags |= SF_Values;
- pRight->pPrior->selFlags |= SF_Values;
- A.pSelect = pRight;
- }
-}
-%endif SQLITE_OMIT_COMPOUND_SELECT
-
%type inscollist_opt {IdList*}
%destructor inscollist_opt {sqlite3IdListDelete(pParse->db, $$);}
%type idlist {IdList*}
@@ -1295,12 +1269,8 @@ trigger_cmd(A) ::=
{ A = sqlite3TriggerUpdateStep(pParse->db, &X, Y, Z, R); }
// INSERT
-trigger_cmd(A) ::=
- insert_cmd(R) INTO trnm(X) inscollist_opt(F) valuelist(Y).
- {A = sqlite3TriggerInsertStep(pParse->db, &X, F, Y.pList, Y.pSelect, R);}
-
trigger_cmd(A) ::= insert_cmd(R) INTO trnm(X) inscollist_opt(F) select(S).
- {A = sqlite3TriggerInsertStep(pParse->db, &X, F, 0, S, R);}
+ {A = sqlite3TriggerInsertStep(pParse->db, &X, F, S, R);}
// DELETE
trigger_cmd(A) ::= DELETE FROM trnm(X) tridxby where_opt(Y).
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index d3e993c13..188a7cacc 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -2483,7 +2483,7 @@ struct TriggerStep {
Select *pSelect; /* SELECT statment or RHS of INSERT INTO .. SELECT ... */
Token target; /* Target table for DELETE, UPDATE, INSERT */
Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */
- ExprList *pExprList; /* SET clause for UPDATE. VALUES clause for INSERT */
+ ExprList *pExprList; /* SET clause for UPDATE. */
IdList *pIdList; /* Column names for INSERT */
TriggerStep *pNext; /* Next in the link-list */
TriggerStep *pLast; /* Last element in link-list. Valid for 1st elem only */
@@ -2898,7 +2898,7 @@ void sqlite3DeleteTable(sqlite3*, Table*);
# define sqlite3AutoincrementEnd(X)
#endif
int sqlite3CodeCoroutine(Parse*, Select*, SelectDest*);
-void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int);
+void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int);
void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*);
int sqlite3IdListIndex(IdList*,const char*);
@@ -3036,7 +3036,7 @@ void sqlite3MaterializeView(Parse*, Table*, Expr*, int);
void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*);
TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*);
TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*,
- ExprList*,Select*,u8);
+ Select*,u8);
TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8);
TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*);
void sqlite3DeleteTrigger(sqlite3*, Trigger*);
diff --git a/src/trigger.c b/src/trigger.c
index 1c68a708d..fdc2a0388 100644
--- a/src/trigger.c
+++ b/src/trigger.c
@@ -397,25 +397,21 @@ TriggerStep *sqlite3TriggerInsertStep(
sqlite3 *db, /* The database connection */
Token *pTableName, /* Name of the table into which we insert */
IdList *pColumn, /* List of columns in pTableName to insert into */
- ExprList *pEList, /* The VALUE clause: a list of values to be inserted */
Select *pSelect, /* A SELECT statement that supplies values */
u8 orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
){
TriggerStep *pTriggerStep;
- assert(pEList == 0 || pSelect == 0);
- assert(pEList != 0 || pSelect != 0 || db->mallocFailed);
+ assert(pSelect != 0 || db->mallocFailed);
pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName);
if( pTriggerStep ){
pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
pTriggerStep->pIdList = pColumn;
- pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE);
pTriggerStep->orconf = orconf;
}else{
sqlite3IdListDelete(db, pColumn);
}
- sqlite3ExprListDelete(db, pEList);
sqlite3SelectDelete(db, pSelect);
return pTriggerStep;
@@ -753,7 +749,6 @@ static int codeTriggerProgram(
case TK_INSERT: {
sqlite3Insert(pParse,
targetSrcList(pParse, pStep),
- sqlite3ExprListDup(db, pStep->pExprList, 0),
sqlite3SelectDup(db, pStep->pSelect, 0),
sqlite3IdListDup(db, pStep->pIdList),
pParse->eOrconf