Attempt to reduce the memory used by VALUES clauses in as many statements as possible, not just INSERT. This branch still has problems.
FossilOrigin-Name: 17d1f7cfabc7593d0725051b0c7c9619a23a482265f30f15ab9493fef5caeeb0
This commit is contained in:
parent
5dfff386e5
commit
815e055bff
29
manifest
29
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\sthe\s".import"\scommand\sin\sthe\sCLI\sso\sthat\sit\sworks\scorrectly\swith\stables\nthat\scontain\scomputed\scolumns.\n[forum:/forumpost/ca014d7358|forum\spost\sca014d7358].
|
||||
D 2024-03-11T11:24:59.268
|
||||
C Attempt\sto\sreduce\sthe\smemory\sused\sby\sVALUES\sclauses\sin\sas\smany\sstatements\sas\spossible,\snot\sjust\sINSERT.\sThis\sbranch\sstill\shas\sproblems.
|
||||
D 2024-03-11T17:27:19.668
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@ -700,7 +700,7 @@ F src/date.c 126ba2ab10aeb2e7ba6e089b5f07b747c0625b8287f78b60da346eda8d23c875
|
||||
F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782
|
||||
F src/dbstat.c 3b677254d512fcafd4d0b341bf267b38b235ccfddbef24f9154e19360fa22e43
|
||||
F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500
|
||||
F src/expr.c 05516e8b7d7d22f98160a0360fde69edce3304a430600567ed33e66d588ca59b
|
||||
F src/expr.c 7d0280860f8683fa1e81202304a5107f493fe9bd52be6590d0d0d6c3564c7a07
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c a47610f0a5c6cb0ad79f8fcef039c01833dec0c751bb695f28dc0ec6a4c3ba00
|
||||
F src/func.c 4204c56196847faefef57fa14e43b8e4d65eb8d7e65318abe463472e3fd148cb
|
||||
@ -709,7 +709,7 @@ F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220
|
||||
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
|
||||
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c eb33ea46dcab93e90f112fced343aaf41f59cbd2e951d5066f1f9302be1c2f34
|
||||
F src/insert.c 2c34cf51e9d8c00498ba68b7f130e448038bb31f624c9c1ca80fa8e3237b51fb
|
||||
F src/json.c e2e40760d6689134c3e2ece38c6a496b34ff5e2661a8f238444a119af666fdce
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
|
||||
@ -739,7 +739,7 @@ F src/os_win.c 6ff43bac175bd9ed79e7c0f96840b139f2f51d01689a638fd05128becf94908a
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c ff60e98138d2499082ac6230f01ac508aba545315debccfca2fd6042f5f10fcd
|
||||
F src/pager.h 4b1140d691860de0be1347474c51fee07d5420bd7f802d38cbab8ea4ab9f538a
|
||||
F src/parse.y 6209f01e8e7495379571454744fa82a5cfc2e7eeb89e46dee3f410d73ea6252d
|
||||
F src/parse.y 3d022ba4c68bf8c7c4c40b3e364d7a8226c4089fc9ff7a3a95f969f8f1bec959
|
||||
F src/pcache.c 040b165f30622a21b7a9a77c6f2e4877a32fb7f22d4c7f0d2a6fa6833a156a75
|
||||
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
|
||||
F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00
|
||||
@ -750,12 +750,12 @@ F src/printf.c 10e8bad30042f8bd6114a013b4afc229ec8ad255ab27518d7d9f52e8cbc5cd0a
|
||||
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
||||
F src/resolve.c ef87e3bc7700bfe761a7bbee2ce6084f1766dc816dd82a3ae77c133eec898432
|
||||
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
|
||||
F src/select.c 43fabfc01bf87addd15e39f112f1e2ade15b19594835ab8a9e5bd50839d4e1b1
|
||||
F src/select.c 2a12c6ed8131db7c49b6f8141c3420cab825cfc6bd222d347fa1382f36b174b7
|
||||
F src/shell.c.in cf80c636bccb0ff9db46995e39d69ca21fde2a8a331d1691e4d62a69d7841c8a
|
||||
F src/sqlite.h.in 19a2db3995a699bd7f6dfb423856242bfceb7ec849a93c91d241d19fc28d9f0f
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
|
||||
F src/sqliteInt.h 6123ce6ca6a1ef351c3b87189e92c92042728f16c088de56b9b5bc2552d0ae33
|
||||
F src/sqliteInt.h b3ac44ca090011813d5a07f63be59785a4558e74052eb94b686f52eef1af684b
|
||||
F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728
|
||||
F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
@ -835,7 +835,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c 887fc4ca3f020ebb2e376f222069570834ac63bf50111ef0cbf3ae417048ed89
|
||||
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
|
||||
F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2
|
||||
F src/where.c 33eaaeef3aef10c2b9e82096e70a174d6636e35cb0b180321b8ddf804590e5cd
|
||||
F src/where.c 8bb70b3caadcf35073f8857ecd83d33d97bf6aa03de3342287037bae43c6f364
|
||||
F src/whereInt.h 82a13766f13d1a53b05387c2e60726289ef26404bc7b9b1f7770204d97357fb8
|
||||
F src/wherecode.c 5d77db30a2a3dd532492ae882de114edba2fae672622056b1c7fd61f5917a8f1
|
||||
F src/whereexpr.c 6ebd90b553f4bb5c7df5a4b2f39b6a7c81a67484353827cdd2048f2514ec6f30
|
||||
@ -1921,6 +1921,8 @@ F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7
|
||||
F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2f48c
|
||||
F test/vacuum6.test b137b04bf3392d3f5c3b8fda0ce85a6775a70ca112f6559f74ff52dc9ce042fd
|
||||
F test/vacuummem.test 4b30f5b95a9ff86e9d5c20741e50a898b2dc10b0962a3211571eb165357003fb
|
||||
F test/values.test 8438dea6826738291ff2019993d62e1eae7a3efb66ea8312fa9ac9bfaf0f95cb
|
||||
F test/valuesfault.test 2ef23ed965e3bd08e268cdc38a0d11653390ddbbe1e8e2e98d16f55edd30f6e8
|
||||
F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62
|
||||
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
|
||||
F test/view.test d4c4281e1679245829db35597817282f60dc513fc39cc5439078f009bd118487
|
||||
@ -2177,8 +2179,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P cb8d9c269c01f78f09069a2361e15087d9aeac63e9f1fd63fbd96b951384e9aa
|
||||
R 9bba8f8b4bc3bf41627766fe1aa44b9c
|
||||
U drh
|
||||
Z 1d2e3bf230fd6cd6fbc6ff6c84cfd8fb
|
||||
P 95a9c88b258f18ac671a4c712603931167cc8bd0b86e41481b200c08043338b5
|
||||
R 62b6db11e5c879766b23978dd0871f55
|
||||
T *branch * exp-values-clause2
|
||||
T *sym-exp-values-clause2 *
|
||||
T -sym-trunk *
|
||||
U dan
|
||||
Z 521a450017e9a427470d7f09cc068c5e
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
@ -1 +1 @@
|
||||
95a9c88b258f18ac671a4c712603931167cc8bd0b86e41481b200c08043338b5
|
||||
17d1f7cfabc7593d0725051b0c7c9619a23a482265f30f15ab9493fef5caeeb0
|
@ -1869,6 +1869,7 @@ SrcList *sqlite3SrcListDup(sqlite3 *db, const SrcList *p, int flags){
|
||||
pNewItem->iCursor = pOldItem->iCursor;
|
||||
pNewItem->addrFillSub = pOldItem->addrFillSub;
|
||||
pNewItem->regReturn = pOldItem->regReturn;
|
||||
pNewItem->regResult = pOldItem->regResult;
|
||||
if( pNewItem->fg.isIndexedBy ){
|
||||
pNewItem->u1.zIndexedBy = sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy);
|
||||
}
|
||||
|
137
src/insert.c
137
src/insert.c
@ -577,6 +577,104 @@ void sqlite3AutoincrementEnd(Parse *pParse){
|
||||
# define autoIncStep(A,B,C)
|
||||
#endif /* SQLITE_OMIT_AUTOINCREMENT */
|
||||
|
||||
void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal){
|
||||
if( pVal->pSrc->nSrc>0 ){
|
||||
SrcItem *pItem = &pVal->pSrc->a[0];
|
||||
sqlite3VdbeEndCoroutine(pParse->pVdbe, pItem->regReturn);
|
||||
sqlite3VdbeJumpHere(pParse->pVdbe, pItem->addrFillSub - 1);
|
||||
}
|
||||
}
|
||||
|
||||
static int multiValueIsConstant(ExprList *pRow){
|
||||
int ii;
|
||||
for(ii=0; ii<pRow->nExpr; ii++){
|
||||
if( 0==sqlite3ExprIsConstant(pRow->a[ii].pExpr) ) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){
|
||||
SrcItem *p;
|
||||
SelectDest dest;
|
||||
Select *pSelect = 0;
|
||||
|
||||
if( pParse->db->init.busy
|
||||
|| pParse->pNewTrigger
|
||||
|| pParse->bHasWith
|
||||
|| multiValueIsConstant(pRow)==0
|
||||
|| pLeft->pPrior
|
||||
){
|
||||
int f = SF_Values | SF_MultiValue;
|
||||
if( pLeft->pPrior || pLeft->pSrc->nSrc ){
|
||||
sqlite3MultiValuesEnd(pParse, pLeft);
|
||||
f = SF_Values;
|
||||
}
|
||||
/* This VALUES clause is part of a VIEW or some other schema item. In
|
||||
** this case the co-routine cannot be coded immediately. */
|
||||
pSelect = sqlite3SelectNew(pParse,pRow,0,0,0,0,0,f,0);
|
||||
pLeft->selFlags &= ~SF_MultiValue;
|
||||
if( pSelect ){
|
||||
pSelect->op = TK_ALL;
|
||||
pSelect->pPrior = pLeft;
|
||||
pLeft = pSelect;
|
||||
}
|
||||
}else{
|
||||
|
||||
if( pLeft->pSrc->nSrc==0 ){
|
||||
/* Co-routine has not yet been started. */
|
||||
Vdbe *v = sqlite3GetVdbe(pParse);
|
||||
Select *pRet;
|
||||
|
||||
if( v==0 ) return pLeft;
|
||||
pRet = sqlite3SelectNew(pParse, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
if( pRet==0 ) return pLeft;
|
||||
p = &pRet->pSrc->a[0];
|
||||
pRet->pSrc->nSrc = 1;
|
||||
|
||||
p->pSelect = pLeft;
|
||||
p->fg.viaCoroutine = 1;
|
||||
p->addrFillSub = sqlite3VdbeCurrentAddr(v) + 1;
|
||||
p->regReturn = ++pParse->nMem;
|
||||
|
||||
sqlite3VdbeAddOp3(v,OP_InitCoroutine,p->regReturn,0,p->addrFillSub);
|
||||
sqlite3SelectDestInit(&dest, SRT_Coroutine, p->regReturn);
|
||||
sqlite3Select(pParse, pLeft, &dest);
|
||||
p->regResult = dest.iSdst;
|
||||
assert( pParse->nErr || dest.iSdst>0 );
|
||||
|
||||
pLeft = pRet;
|
||||
}else{
|
||||
p = &pLeft->pSrc->a[0];
|
||||
}
|
||||
|
||||
if( pParse->nErr==0 ){
|
||||
pSelect = sqlite3SelectNew(pParse, pRow, 0, 0, 0, 0, 0, SF_Values, 0);
|
||||
if( pSelect ){
|
||||
if( p->pSelect->pEList->nExpr!=pSelect->pEList->nExpr ){
|
||||
sqlite3SelectWrongNumTermsError(pParse, pSelect);
|
||||
}else{
|
||||
sqlite3SelectPrep(pParse, pSelect, 0);
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
if( pSelect->pWin ){
|
||||
sqlite3SelectDestInit(&dest, SRT_Coroutine, p->regReturn);
|
||||
dest.iSdst = p->regResult;
|
||||
dest.nSdst = pRow->nExpr;
|
||||
dest.iSDParm = p->regReturn;
|
||||
sqlite3Select(pParse, pSelect, &dest);
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
sqlite3ExprCodeExprList(pParse, pSelect->pEList,p->regResult,0,0);
|
||||
sqlite3VdbeAddOp1(pParse->pVdbe, OP_Yield, p->regReturn);
|
||||
}
|
||||
}
|
||||
sqlite3SelectDelete(pParse->db, pSelect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pLeft;
|
||||
}
|
||||
|
||||
/* Forward declaration */
|
||||
static int xferOptimization(
|
||||
@ -914,24 +1012,31 @@ void sqlite3Insert(
|
||||
/* Data is coming from a SELECT or from a multi-row VALUES clause.
|
||||
** Generate a co-routine to run the SELECT. */
|
||||
int regYield; /* Register holding co-routine entry-point */
|
||||
int addrTop; /* Top of the co-routine */
|
||||
int rc; /* Result code */
|
||||
|
||||
regYield = ++pParse->nMem;
|
||||
addrTop = sqlite3VdbeCurrentAddr(v) + 1;
|
||||
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
|
||||
sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield);
|
||||
dest.iSdst = bIdListInOrder ? regData : 0;
|
||||
dest.nSdst = pTab->nCol;
|
||||
rc = sqlite3Select(pParse, pSelect, &dest);
|
||||
regFromSelect = dest.iSdst;
|
||||
assert( db->pParse==pParse );
|
||||
if( rc || pParse->nErr ) goto insert_cleanup;
|
||||
assert( db->mallocFailed==0 );
|
||||
sqlite3VdbeEndCoroutine(v, regYield);
|
||||
sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */
|
||||
assert( pSelect->pEList );
|
||||
nColumn = pSelect->pEList->nExpr;
|
||||
if( pSelect->pSrc->nSrc==1 && pSelect->pSrc->a[0].fg.viaCoroutine ){
|
||||
SrcItem *pItem = &pSelect->pSrc->a[0];
|
||||
dest.iSDParm = regYield = pItem->regReturn;
|
||||
regFromSelect = pItem->regResult;
|
||||
nColumn = pItem->pSelect->pEList->nExpr;
|
||||
}else{
|
||||
int addrTop; /* Top of the co-routine */
|
||||
regYield = ++pParse->nMem;
|
||||
addrTop = sqlite3VdbeCurrentAddr(v) + 1;
|
||||
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
|
||||
sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield);
|
||||
dest.iSdst = bIdListInOrder ? regData : 0;
|
||||
dest.nSdst = pTab->nCol;
|
||||
rc = sqlite3Select(pParse, pSelect, &dest);
|
||||
regFromSelect = dest.iSdst;
|
||||
assert( db->pParse==pParse );
|
||||
if( rc || pParse->nErr ) goto insert_cleanup;
|
||||
assert( db->mallocFailed==0 );
|
||||
sqlite3VdbeEndCoroutine(v, regYield);
|
||||
sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */
|
||||
assert( pSelect->pEList );
|
||||
nColumn = pSelect->pEList->nExpr;
|
||||
}
|
||||
|
||||
/* Set useTempTable to TRUE if the result of the SELECT statement
|
||||
** should be written into a temporary table (template 4). Set to
|
||||
|
27
src/parse.y
27
src/parse.y
@ -562,9 +562,13 @@ cmd ::= select(X). {
|
||||
}
|
||||
|
||||
%ifndef SQLITE_OMIT_CTE
|
||||
select(A) ::= WITH wqlist(W) selectnowith(X). {A = attachWithToSelect(pParse,X,W);}
|
||||
select(A) ::= WITH RECURSIVE wqlist(W) selectnowith(X).
|
||||
select(A) ::= withkw wqlist(W) selectnowith(X). {A = attachWithToSelect(pParse,X,W);}
|
||||
select(A) ::= withkw RECURSIVE wqlist(W) selectnowith(X).
|
||||
{A = attachWithToSelect(pParse,X,W);}
|
||||
|
||||
withkw ::= WITH. {
|
||||
pParse->bHasWith = 1;
|
||||
}
|
||||
%endif /* SQLITE_OMIT_CTE */
|
||||
select(A) ::= selectnowith(A). {
|
||||
Select *p = A;
|
||||
@ -622,7 +626,9 @@ oneselect(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y)
|
||||
%endif
|
||||
|
||||
|
||||
oneselect(A) ::= values(A).
|
||||
oneselect(A) ::= values(A). {
|
||||
sqlite3MultiValuesEnd(pParse, A);
|
||||
}
|
||||
|
||||
%type values {Select*}
|
||||
%destructor values {sqlite3SelectDelete(pParse->db, $$);}
|
||||
@ -630,16 +636,7 @@ values(A) ::= VALUES LP nexprlist(X) RP. {
|
||||
A = sqlite3SelectNew(pParse,X,0,0,0,0,0,SF_Values,0);
|
||||
}
|
||||
values(A) ::= values(A) COMMA LP nexprlist(Y) RP. {
|
||||
Select *pRight, *pLeft = A;
|
||||
pRight = sqlite3SelectNew(pParse,Y,0,0,0,0,0,SF_Values|SF_MultiValue,0);
|
||||
if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue;
|
||||
if( pRight ){
|
||||
pRight->op = TK_ALL;
|
||||
pRight->pPrior = pLeft;
|
||||
A = pRight;
|
||||
}else{
|
||||
A = pLeft;
|
||||
}
|
||||
A = sqlite3MultiValues(pParse, A, Y);
|
||||
}
|
||||
|
||||
// The "distinct" nonterminal is true (1) if the DISTINCT keyword is
|
||||
@ -1754,8 +1751,8 @@ anylist ::= anylist ANY.
|
||||
|
||||
with ::= .
|
||||
%ifndef SQLITE_OMIT_CTE
|
||||
with ::= WITH wqlist(W). { sqlite3WithPush(pParse, W, 1); }
|
||||
with ::= WITH RECURSIVE wqlist(W). { sqlite3WithPush(pParse, W, 1); }
|
||||
with ::= withkw wqlist(W). { sqlite3WithPush(pParse, W, 1); }
|
||||
with ::= withkw RECURSIVE wqlist(W). { sqlite3WithPush(pParse, W, 1); }
|
||||
|
||||
%type wqas {u8}
|
||||
wqas(A) ::= AS. {A = M10d_Any;}
|
||||
|
@ -7636,7 +7636,7 @@ int sqlite3Select(
|
||||
/* Generate code for all sub-queries in the FROM clause
|
||||
*/
|
||||
pSub = pItem->pSelect;
|
||||
if( pSub==0 ) continue;
|
||||
if( pSub==0 || pItem->addrFillSub!=0 ) continue;
|
||||
|
||||
/* The code for a subquery should only be generated once. */
|
||||
assert( pItem->addrFillSub==0 );
|
||||
|
@ -3812,6 +3812,7 @@ struct Parse {
|
||||
u8 disableLookaside; /* Number of times lookaside has been disabled */
|
||||
u8 prepFlags; /* SQLITE_PREPARE_* flags */
|
||||
u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */
|
||||
u8 bHasWith; /* True if statement contains WITH */
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
|
||||
u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */
|
||||
#endif
|
||||
@ -4486,6 +4487,9 @@ struct Window {
|
||||
** due to the SQLITE_SUBTYPE flag */
|
||||
};
|
||||
|
||||
Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow);
|
||||
void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal);
|
||||
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
void sqlite3WindowDelete(sqlite3*, Window*);
|
||||
void sqlite3WindowUnlinkFromSelect(Window*);
|
||||
|
@ -6896,6 +6896,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
*/
|
||||
if( pTabItem->fg.viaCoroutine ){
|
||||
testcase( pParse->db->mallocFailed );
|
||||
assert( pTabItem->regResult>=0 );
|
||||
translateColumnToCopy(pParse, pLevel->addrBody, pLevel->iTabCur,
|
||||
pTabItem->regResult, 0);
|
||||
continue;
|
||||
|
256
test/values.test
Normal file
256
test/values.test
Normal file
@ -0,0 +1,256 @@
|
||||
# 2024 March 3
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix values
|
||||
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE x1(a, b, c);
|
||||
}
|
||||
|
||||
|
||||
explain_i {
|
||||
INSERT INTO x1(a, b, c) VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4);
|
||||
}
|
||||
do_execsql_test 1.1.1 {
|
||||
INSERT INTO x1 VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4);
|
||||
}
|
||||
do_execsql_test 1.1.2 {
|
||||
SELECT * FROM x1;
|
||||
} {
|
||||
1 1 1
|
||||
2 2 2
|
||||
3 3 3
|
||||
4 4 4
|
||||
}
|
||||
|
||||
do_execsql_test 1.2.0 {
|
||||
DELETE FROM x1
|
||||
}
|
||||
do_execsql_test 1.2.1 {
|
||||
INSERT INTO x1 VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3) UNION ALL SELECT 4, 4, 4;
|
||||
SELECT * FROM x1;
|
||||
} {1 1 1 2 2 2 3 3 3 4 4 4}
|
||||
|
||||
sqlite3_limit db SQLITE_LIMIT_COMPOUND_SELECT 4
|
||||
|
||||
do_execsql_test 1.2.2 {
|
||||
DELETE FROM x1;
|
||||
INSERT INTO x1
|
||||
VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4), (5, 5, 5)
|
||||
UNION ALL SELECT 6, 6, 6;
|
||||
SELECT * FROM x1;
|
||||
} {1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6}
|
||||
|
||||
do_execsql_test 1.2.3 {
|
||||
DELETE FROM x1;
|
||||
INSERT INTO x1
|
||||
VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4)
|
||||
UNION ALL SELECT 6, 6, 6;
|
||||
SELECT * FROM x1;
|
||||
} {1 1 1 2 2 2 3 3 3 4 4 4 6 6 6}
|
||||
|
||||
do_execsql_test 1.2.4 {
|
||||
DELETE FROM x1;
|
||||
INSERT INTO x1 VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3) UNION ALL SELECT 6, 6, 6;
|
||||
SELECT * FROM x1;
|
||||
} {
|
||||
1 1 1
|
||||
2 2 2
|
||||
3 3 3
|
||||
6 6 6
|
||||
}
|
||||
|
||||
set a 4
|
||||
set b 5
|
||||
set c 6
|
||||
do_execsql_test 1.2.5 {
|
||||
DELETE FROM x1;
|
||||
INSERT INTO x1
|
||||
VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3),
|
||||
(4, 4, $a), (5, 5, $b), (6, 6, $c)
|
||||
}
|
||||
|
||||
do_execsql_test 1.2.6 {
|
||||
SELECT * FROM x1;
|
||||
} {
|
||||
1 1 1
|
||||
2 2 2
|
||||
3 3 3
|
||||
4 4 4
|
||||
5 5 5
|
||||
6 6 6
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# SQLITE_LIMIT_COMPOUND_SELECT set to 0.
|
||||
#
|
||||
reset_db
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE x1(a, b, c);
|
||||
}
|
||||
|
||||
sqlite3_limit db SQLITE_LIMIT_COMPOUND_SELECT 3
|
||||
|
||||
do_catchsql_test 2.1.1 {
|
||||
INSERT INTO x1 VALUES
|
||||
(1, 1, 1),
|
||||
(2, 2, 2),
|
||||
(3, 3, 3),
|
||||
(4, 4, 4),
|
||||
(5, 5, 5),
|
||||
(6, 6, 6),
|
||||
(7, 7, 7),
|
||||
(8, 8, 8),
|
||||
(9, 9, 9),
|
||||
(10, 10, 10, 10)
|
||||
} {1 {all VALUES must have the same number of terms}}
|
||||
|
||||
do_catchsql_test 2.1.2 {
|
||||
INSERT INTO x1 VALUES
|
||||
(1, 1, 1),
|
||||
(2, 2, 2, 2),
|
||||
(3, 3, 3),
|
||||
(4, 4, 4),
|
||||
(5, 5, 5),
|
||||
(6, 6, 6),
|
||||
(7, 7, 7),
|
||||
(8, 8, 8),
|
||||
(9, 9, 9),
|
||||
(10, 10, 10)
|
||||
} {1 {all VALUES must have the same number of terms}}
|
||||
|
||||
sqlite3_limit db SQLITE_LIMIT_COMPOUND_SELECT 0
|
||||
|
||||
do_execsql_test 2.2 {
|
||||
INSERT INTO x1 VALUES
|
||||
(1, 1, 1),
|
||||
(2, 2, 2),
|
||||
(3, 3, 3),
|
||||
(4, 4, 4),
|
||||
(5, 5, 5),
|
||||
(6, 6, 6),
|
||||
(7, 7, 7),
|
||||
(8, 8, 8),
|
||||
(9, 9, 9),
|
||||
(10, 10, 10)
|
||||
} {}
|
||||
do_execsql_test 2.3 {
|
||||
INSERT INTO x1 VALUES
|
||||
(1, 1, 1),
|
||||
(2, 2, 2),
|
||||
(3, 3, 3),
|
||||
(4, 4, 4),
|
||||
(5, 5, 5),
|
||||
(6, 6, 6),
|
||||
(7, 7, 7),
|
||||
(8, 8, 8),
|
||||
(9, 9, 9),
|
||||
(10, 10, 10)
|
||||
UNION ALL
|
||||
SELECT 5, 12, 12
|
||||
ORDER BY 1
|
||||
} {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE y1(x, y);
|
||||
}
|
||||
|
||||
do_execsql_test 3.1.1 {
|
||||
DELETE FROM y1;
|
||||
INSERT INTO y1 VALUES(1, 2), (3, 4), (row_number() OVER (), 5);
|
||||
}
|
||||
do_execsql_test 3.1.2 {
|
||||
SELECT * FROM y1;
|
||||
} {1 2 3 4 1 5}
|
||||
do_execsql_test 3.2.1 {
|
||||
DELETE FROM y1;
|
||||
INSERT INTO y1 VALUES(1, 2), (3, 4), (row_number() OVER (), 6)
|
||||
, (row_number() OVER (), 7)
|
||||
}
|
||||
do_execsql_test 3.1.2 {
|
||||
SELECT * FROM y1;
|
||||
} {1 2 3 4 1 6 1 7}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 4.0 {
|
||||
CREATE TABLE x1(a PRIMARY KEY, b) WITHOUT ROWID;
|
||||
}
|
||||
|
||||
foreach {tn iLimit} {1 0 2 3} {
|
||||
sqlite3_limit db SQLITE_LIMIT_COMPOUND_SELECT $iLimit
|
||||
|
||||
do_execsql_test 4.1.1 {
|
||||
DELETE FROM x1;
|
||||
INSERT INTO x1 VALUES
|
||||
(1, 1),
|
||||
(2, (SELECT * FROM (VALUES('a'), ('b'), ('c'), ('d')) ))
|
||||
}
|
||||
do_execsql_test 4.1.2 {
|
||||
SELECT * FROM x1
|
||||
} {1 1 2 a}
|
||||
|
||||
do_execsql_test 4.2.1 {
|
||||
DELETE FROM x1;
|
||||
INSERT INTO x1 VALUES
|
||||
(1, 1),
|
||||
(2, 2),
|
||||
(3, 3),
|
||||
(4, 4),
|
||||
(5, (SELECT * FROM (VALUES('a'), ('b'), ('c'), ('d')) ))
|
||||
}
|
||||
do_execsql_test 4.2.2 {
|
||||
SELECT * FROM x1
|
||||
} {1 1 2 2 3 3 4 4 5 a}
|
||||
|
||||
do_execsql_test 4.3.1 {
|
||||
DELETE FROM x1;
|
||||
INSERT INTO x1 VALUES
|
||||
(1, (SELECT * FROM (VALUES('a'), ('b'), ('c'), ('d'), ('e')) ))
|
||||
}
|
||||
do_execsql_test 4.3.2 {
|
||||
SELECT * FROM x1
|
||||
} {1 a}
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 5.0 {
|
||||
CREATE VIEW v1 AS VALUES(1, 2, 3), (4, 5, 6), (7, 8, 9);
|
||||
}
|
||||
do_execsql_test 5.1 {
|
||||
SELECT * FROM v1
|
||||
} {1 2 3 4 5 6 7 8 9}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 6.0 {
|
||||
CREATE TABLE t1(x);
|
||||
INSERT INTO t1 VALUES(1), (2);
|
||||
}
|
||||
|
||||
do_execsql_test 6.1 {
|
||||
SELECT ( VALUES( x ), ( x ) ) FROM t1;
|
||||
} {1 2}
|
||||
|
||||
|
||||
finish_test
|
37
test/valuesfault.test
Normal file
37
test/valuesfault.test
Normal file
@ -0,0 +1,37 @@
|
||||
# 2024 March 3
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix valuesfault
|
||||
source $testdir/malloc_common.tcl
|
||||
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE x1(a, b, c);
|
||||
}
|
||||
faultsim_save_and_close
|
||||
|
||||
do_faultsim_test 1 -prep {
|
||||
faultsim_restore_and_reopen
|
||||
sqlite3_limit db SQLITE_LIMIT_COMPOUND_SELECT 2
|
||||
} -body {
|
||||
execsql {
|
||||
INSERT INTO x1 VALUES(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4);
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
Loading…
x
Reference in New Issue
Block a user