Allow a VALUES clause to be used any place that a SELECT statement can be

used.

FossilOrigin-Name: c9ea7d199f06a7801ab639e7ac98ebeb98706f24
This commit is contained in:
drh 2014-01-10 20:46:55 +00:00
parent c740752470
commit 75593d96be
6 changed files with 46 additions and 70 deletions

View File

@ -1,5 +1,5 @@
C Fix\sCREATE\sTABLE\s...\sAS\sso\sthat\sit\sworks\swith\scolumn\snames\sthat\sare\sempty\nstrings. C Allow\sa\sVALUES\sclause\sto\sbe\sused\sany\splace\sthat\sa\sSELECT\sstatement\scan\sbe\nused.
D 2014-01-10T20:38:12.815 D 2014-01-10T20:46:55.338
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@ -183,7 +183,7 @@ F src/global.c 1d7bb7ea8254ae6a68ed9bfaf65fcb3d1690b486
F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4 F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22 F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c e6b3d7847aaf06170967ff6ea9076717fbc08d3f F src/insert.c 5ddb48c7f1cb399993744f23f03948989ce1790e
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12 F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
@ -209,7 +209,7 @@ F src/os_unix.c 3a4dcb554d3c915075766162f28c3fd4cdb75968
F src/os_win.c 16eac0961603182ffc10c02b39fe830126538e07 F src/os_win.c 16eac0961603182ffc10c02b39fe830126538e07
F src/pager.c efa923693e958696eee69b205a20bfbc402c8480 F src/pager.c efa923693e958696eee69b205a20bfbc402c8480
F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428 F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428
F src/parse.y acee1a9958539e21263362b194594c5255ad2fca F src/parse.y 0a284e3f2bb78363ddce6f796ca2074e1e265eb7
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346 F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222 F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
F src/pcache1.c 57fee9a9a617218f5037afbbe49b09da65bde56b F src/pcache1.c 57fee9a9a617218f5037afbbe49b09da65bde56b
@ -224,7 +224,7 @@ F src/shell.c a3541193d5fce37e91dad8ef46a9505aa7c9b344
F src/sqlite.h.in d94a8b89522f526ba711182ee161e06f8669bcc9 F src/sqlite.h.in d94a8b89522f526ba711182ee161e06f8669bcc9
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
F src/sqliteInt.h 672ef78e9e6f8b03fc9d37884f9784fb02e6ce2d F src/sqliteInt.h 0c65967bb807dee3c9eef2bbd17f880eeb28ea30
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@ -275,7 +275,7 @@ F src/test_vfs.c e72f555ef7a59080f898fcf1a233deb9eb704ea9
F src/test_vfstrace.c 3a0ab304682fecbceb689e7d9b904211fde11d78 F src/test_vfstrace.c 3a0ab304682fecbceb689e7d9b904211fde11d78
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/tokenize.c ec4c1a62b890bf1dbcdb966399e140b904c700a4 F src/tokenize.c ec4c1a62b890bf1dbcdb966399e140b904c700a4
F src/trigger.c d84e1f3669e9a217731a14a9d472b1c7b87c87ba F src/trigger.c 5c1c0b899ac0ce284763dcb8fdbaa38ecf15ef98
F src/update.c c2706a6eb232a96345c35b7e1e75a188e26812bb F src/update.c c2706a6eb232a96345c35b7e1e75a188e26812bb
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269 F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
F src/util.c e71f19b272f05c8695cf747b4bac1732685f9e5c F src/util.c e71f19b272f05c8695cf747b4bac1732685f9e5c
@ -1148,7 +1148,7 @@ F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
P 0484549bb82ca5246488330c8d266e429ccd19b9 P 632045f21c553e10f59a14c772d50d7824ca0c2c
R 00ef541b0e35ee7a66a11f656f6dc3e2 R cf996bb200e200afa8de950e78c84a55
U drh U drh
Z 1394adca743ceab6563433db8e16d260 Z 54c4a7cb2ec6e5258f05fa3eca37aefd

View File

@ -1 +1 @@
632045f21c553e10f59a14c772d50d7824ca0c2c c9ea7d199f06a7801ab639e7ac98ebeb98706f24

View File

@ -540,7 +540,6 @@ static int xferOptimization(
void sqlite3Insert( void sqlite3Insert(
Parse *pParse, /* Parser context */ Parse *pParse, /* Parser context */
SrcList *pTabList, /* Name of table into which we are inserting */ 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 */ Select *pSelect, /* A SELECT statement to use as the data source */
IdList *pColumn, /* Column names corresponding to IDLIST. */ IdList *pColumn, /* Column names corresponding to IDLIST. */
int onError /* How to handle constraint errors */ int onError /* How to handle constraint errors */
@ -568,6 +567,7 @@ void sqlite3Insert(
Db *pDb; /* The database containing table being inserted into */ Db *pDb; /* The database containing table being inserted into */
int appendFlag = 0; /* True if the insert is likely to be an append */ int appendFlag = 0; /* True if the insert is likely to be an append */
int withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */ int withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */
ExprList *pList = 0; /* List of VALUES() to be inserted */
/* Register allocations */ /* Register allocations */
int regFromSelect = 0;/* Base register for data coming from SELECT */ int regFromSelect = 0;/* Base register for data coming from SELECT */
@ -591,6 +591,17 @@ void sqlite3Insert(
goto insert_cleanup; 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. /* Locate the table into which we will be inserting new information.
*/ */
assert( pTabList->nSrc==1 ); assert( pTabList->nSrc==1 );

View File

@ -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). { 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); 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 // The "distinct" nonterminal is true (1) if the DISTINCT keyword is
// present and false (0) if it is not. // present and false (0) if it is not.
@ -696,58 +713,15 @@ setlist(A) ::= nm(X) EQ expr(Y). {
////////////////////////// The INSERT command ///////////////////////////////// ////////////////////////// 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). 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. 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} %type insert_cmd {u8}
insert_cmd(A) ::= INSERT orconf(R). {A = R;} insert_cmd(A) ::= INSERT orconf(R). {A = R;}
insert_cmd(A) ::= REPLACE. {A = OE_Replace;} 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*} %type inscollist_opt {IdList*}
%destructor inscollist_opt {sqlite3IdListDelete(pParse->db, $$);} %destructor inscollist_opt {sqlite3IdListDelete(pParse->db, $$);}
%type idlist {IdList*} %type idlist {IdList*}
@ -1295,12 +1269,8 @@ trigger_cmd(A) ::=
{ A = sqlite3TriggerUpdateStep(pParse->db, &X, Y, Z, R); } { A = sqlite3TriggerUpdateStep(pParse->db, &X, Y, Z, R); }
// INSERT // 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). 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 // DELETE
trigger_cmd(A) ::= DELETE FROM trnm(X) tridxby where_opt(Y). trigger_cmd(A) ::= DELETE FROM trnm(X) tridxby where_opt(Y).

View File

@ -2483,7 +2483,7 @@ struct TriggerStep {
Select *pSelect; /* SELECT statment or RHS of INSERT INTO .. SELECT ... */ Select *pSelect; /* SELECT statment or RHS of INSERT INTO .. SELECT ... */
Token target; /* Target table for DELETE, UPDATE, INSERT */ Token target; /* Target table for DELETE, UPDATE, INSERT */
Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */ 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 */ IdList *pIdList; /* Column names for INSERT */
TriggerStep *pNext; /* Next in the link-list */ TriggerStep *pNext; /* Next in the link-list */
TriggerStep *pLast; /* Last element in link-list. Valid for 1st elem only */ TriggerStep *pLast; /* Last element in link-list. Valid for 1st elem only */
@ -2898,7 +2898,7 @@ void sqlite3DeleteTable(sqlite3*, Table*);
# define sqlite3AutoincrementEnd(X) # define sqlite3AutoincrementEnd(X)
#endif #endif
int sqlite3CodeCoroutine(Parse*, Select*, SelectDest*); 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*); void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*); IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*);
int sqlite3IdListIndex(IdList*,const char*); int sqlite3IdListIndex(IdList*,const char*);
@ -3036,7 +3036,7 @@ void sqlite3MaterializeView(Parse*, Table*, Expr*, int);
void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*); void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*);
TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*); TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*);
TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*, TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*,
ExprList*,Select*,u8); Select*,u8);
TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8); TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8);
TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*); TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*);
void sqlite3DeleteTrigger(sqlite3*, Trigger*); void sqlite3DeleteTrigger(sqlite3*, Trigger*);

View File

@ -397,25 +397,21 @@ TriggerStep *sqlite3TriggerInsertStep(
sqlite3 *db, /* The database connection */ sqlite3 *db, /* The database connection */
Token *pTableName, /* Name of the table into which we insert */ Token *pTableName, /* Name of the table into which we insert */
IdList *pColumn, /* List of columns in pTableName to insert into */ 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 */ Select *pSelect, /* A SELECT statement that supplies values */
u8 orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ u8 orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
){ ){
TriggerStep *pTriggerStep; TriggerStep *pTriggerStep;
assert(pEList == 0 || pSelect == 0); assert(pSelect != 0 || db->mallocFailed);
assert(pEList != 0 || pSelect != 0 || db->mallocFailed);
pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName); pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName);
if( pTriggerStep ){ if( pTriggerStep ){
pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
pTriggerStep->pIdList = pColumn; pTriggerStep->pIdList = pColumn;
pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE);
pTriggerStep->orconf = orconf; pTriggerStep->orconf = orconf;
}else{ }else{
sqlite3IdListDelete(db, pColumn); sqlite3IdListDelete(db, pColumn);
} }
sqlite3ExprListDelete(db, pEList);
sqlite3SelectDelete(db, pSelect); sqlite3SelectDelete(db, pSelect);
return pTriggerStep; return pTriggerStep;
@ -753,7 +749,6 @@ static int codeTriggerProgram(
case TK_INSERT: { case TK_INSERT: {
sqlite3Insert(pParse, sqlite3Insert(pParse,
targetSrcList(pParse, pStep), targetSrcList(pParse, pStep),
sqlite3ExprListDup(db, pStep->pExprList, 0),
sqlite3SelectDup(db, pStep->pSelect, 0), sqlite3SelectDup(db, pStep->pSelect, 0),
sqlite3IdListDup(db, pStep->pIdList), sqlite3IdListDup(db, pStep->pIdList),
pParse->eOrconf pParse->eOrconf