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:
dan 2024-03-11 17:27:19 +00:00
parent 5dfff386e5
commit 815e055bff
10 changed files with 451 additions and 45 deletions

View File

@ -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.

View File

@ -1 +1 @@
95a9c88b258f18ac671a4c712603931167cc8bd0b86e41481b200c08043338b5
17d1f7cfabc7593d0725051b0c7c9619a23a482265f30f15ab9493fef5caeeb0

View File

@ -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);
}

View File

@ -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

View File

@ -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;}

View File

@ -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 );

View File

@ -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*);

View File

@ -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
View 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
View 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