Index: Makefile.in ================================================================== --- Makefile.in +++ Makefile.in @@ -815,11 +815,12 @@ mv vdbe.new tsrc/vdbe.c cp fts5.c fts5.h tsrc touch .target_source sqlite3.c: .target_source $(TOP)/tool/mksqlite3c.tcl src-verify has_tclsh84 - $(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl $(AMALGAMATION_LINE_MACROS) $(EXTRA_SRC) + $(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl $(AMALGAMATION_LINE_MACROS) \ + $(EXTRA_SRC) cp tsrc/sqlite3ext.h . cp $(TOP)/ext/session/sqlite3session.h . sqlite3r.h: sqlite3.h has_tclsh84 $(TCLSH_CMD) $(TOP)/tool/mksqlite3h.tcl $(TOP) --enable-recover >sqlite3r.h @@ -826,11 +827,12 @@ sqlite3r.c: sqlite3.c sqlite3r.h has_tclsh84 cp $(TOP)/ext/recover/sqlite3recover.c tsrc/ cp $(TOP)/ext/recover/sqlite3recover.h tsrc/ cp $(TOP)/ext/recover/dbdata.c tsrc/ - $(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl --enable-recover $(AMALGAMATION_LINE_MACROS) $(EXTRA_SRC) + $(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl --enable-recover \ + $(AMALGAMATION_LINE_MACROS) $(EXTRA_SRC) sqlite3ext.h: .target_source cp tsrc/sqlite3ext.h . tclsqlite3.c: sqlite3.c Index: doc/testrunner.md ================================================================== --- doc/testrunner.md +++ doc/testrunner.md @@ -15,10 +15,11 @@
  • 3.1. Commands to Run SQLite Tests
  • 3.2. Running ZipVFS Tests
  • 3.3. Investigating Source Code Test Failures
  • 4. Extra testrunner.tcl Options +# 4. Extra testrunner.tcl Options
  • 5. Controlling CPU Core Utilization # 1. Overview @@ -26,22 +27,16 @@ testrunner.tcl is a Tcl script used to run multiple SQLite tests using multiple jobs. It supports the following types of tests: * Tcl test scripts. - * Tests run with `make` commands. Examples: - - `make mdevtest` - - `make releasetest` - - `make sdevtest` - - `make testrunner` + * Tests run with [make] commands. Specifically, at time of writing, + [make fuzztest], [make mptest], [make sourcetest] and [make threadtest]. testrunner.tcl pipes the output of all tests and builds run into log file -**testrunner.log**, created in the current working directory. Search this -file to find details of errors. Suggested search commands: - - * `grep "^!" testrunner.log` - * `grep failed testrunner.log` +**testrunner.log**, created in the cwd directory. Searching this file for +"failed" is a good way to find the output of a failed test. testrunner.tcl also populates SQLite database **testrunner.db**. This database contains details of all tests run, running and to be run. A useful query might be: @@ -63,21 +58,21 @@ watch ./testfixture $(TESTDIR)/testrunner.tcl status ``` in another terminal is a good way to keep an eye on a long running test. -Sometimes testrunner.tcl uses the `testfixture` binary that it is run with +Sometimes testrunner.tcl uses the [testfixture] binary that it is run with to run tests (see "Binary Tests" below). Sometimes it builds testfixture and other binaries in specific configurations to test (see "Source Tests"). # 2. Binary Tests The commands described in this section all run various combinations of the Tcl -test scripts using the `testfixture` binary used to run the testrunner.tcl +test scripts using the [testfixture] binary used to run the testrunner.tcl script (i.e. they do not invoke the compiler to build new binaries, or the -`make` command to run tests that are not Tcl scripts). The procedure to run +[make] command to run tests that are not Tcl scripts). The procedure to run these tests is therefore: 1. Build the "testfixture" (or "testfixture.exe" for windows) binary using whatever method seems convenient. @@ -196,11 +191,11 @@ ## 3.1. Commands to Run SQLite Tests The **mdevtest** command is equivalent to running the veryquick tests and -the `make fuzztest` target once for each of two --enable-all builds - one +the [make fuzztest] target once for each of two --enable-all builds - one with debugging enabled and one without: ``` tclsh $TESTDIR/testrunner.tcl mdevtest ``` @@ -286,11 +281,11 @@ # Create a script that recreates build configuration "Have-Not" on Windows: tclsh $TESTDIR/testrunner.tcl script Have-Not > make.bat ``` The generated bash or \*.bat file script accepts a single argument - a makefile -target to build. This may be used either to run a `make` command test directly, +target to build. This may be used either to run a [make] command test directly, or else to build a testfixture (or testfixture.exe) binary with which to run a Tcl test script, as described above. # 4. Extra testrunner.tcl Options @@ -313,20 +308,10 @@ ``` # Log the shell commmands that make up the mdevtest test. tclsh $TESTDIR/testrunner.tcl --dryrun mdevtest" ``` -The **--explain** option is similar to --dryrun in that it prevents testrunner.tcl -from building any binaries or running any tests. The difference is that --explain -prints on standard output a human-readable summary of all the builds and tests that -would have been run. - -``` - # Show what builds and tests would have been run - tclsh $TESTDIR/testrunner.tcl --explain mdevtest -``` - # 5. Controlling CPU Core Utilization When running either binary or source code tests, testrunner.tcl reports the number of jobs it intends to use to stdout. e.g. @@ -352,5 +337,8 @@ testrunner.log and testrunner.db files: ``` $ ./testfixture $TESTDIR/testrunner.tcl njob $NEW_NUMBER_OF_JOBS ``` + + + Index: ext/misc/cksumvfs.c ================================================================== --- ext/misc/cksumvfs.c +++ ext/misc/cksumvfs.c @@ -444,13 +444,13 @@ ** (1) the size indicates that we are dealing with a complete ** database page ** (2) checksum verification is enabled ** (3) we are not in the middle of checkpoint */ - if( iAmt>=512 && (iAmt & (iAmt-1))==0 /* (1) */ - && p->verifyCksm /* (2) */ - && !p->inCkpt /* (3) */ + if( iAmt>=512 /* (1) */ + && p->verifyCksm /* (2) */ + && !p->inCkpt /* (3) */ ){ u8 cksum[8]; cksmCompute((u8*)zBuf, iAmt-8, cksum); if( memcmp((u8*)zBuf+iAmt-8, cksum, 8)!=0 ){ sqlite3_log(SQLITE_IOERR_DATA, Index: ext/rbu/sqlite3rbu.c ================================================================== --- ext/rbu/sqlite3rbu.c +++ ext/rbu/sqlite3rbu.c @@ -197,11 +197,10 @@ #if !defined(SQLITE_AMALGAMATION) typedef unsigned int u32; typedef unsigned short u16; typedef unsigned char u8; typedef sqlite3_int64 i64; -typedef sqlite3_uint64 u64; #endif /* ** These values must match the values defined in wal.c for the equivalent ** locks. These are not magic numbers as they are part of the SQLite file @@ -884,11 +883,10 @@ pIter->bCleanup = 0; rc = sqlite3_step(pIter->pTblIter); if( rc!=SQLITE_ROW ){ rc = resetAndCollectError(pIter->pTblIter, &p->zErrmsg); pIter->zTbl = 0; - pIter->zDataTbl = 0; }else{ pIter->zTbl = (const char*)sqlite3_column_text(pIter->pTblIter, 0); pIter->zDataTbl = (const char*)sqlite3_column_text(pIter->pTblIter,1); rc = (pIter->zDataTbl && pIter->zTbl) ? SQLITE_OK : SQLITE_NOMEM; } @@ -2979,11 +2977,11 @@ if( p->rc==SQLITE_OK ){ sqlite3_file *pDb = p->pTargetFd->pReal; u32 volatile *ptr; p->rc = pDb->pMethods->xShmMap(pDb, 0, 32*1024, 0, (void volatile**)&ptr); if( p->rc==SQLITE_OK ){ - iRet = (i64)(((u64)ptr[10] << 32) + ptr[11]); + iRet = ((i64)ptr[10] << 32) + ptr[11]; } } return iRet; } Index: ext/wasm/api/sqlite3-opfs-async-proxy.js ================================================================== --- ext/wasm/api/sqlite3-opfs-async-proxy.js +++ ext/wasm/api/sqlite3-opfs-async-proxy.js @@ -49,11 +49,11 @@ versions (approximately) 104-107 are extinct) should change our usage of those methods to remove the "await". */ "use strict"; const wPost = (type,...args)=>postMessage({type, payload:args}); -const installAsyncProxy = function(){ +const installAsyncProxy = function(self){ const toss = function(...args){throw new Error(args.join(' '))}; if(globalThis.window === globalThis){ toss("This code cannot run from the main thread.", "Load it as a Worker from a separate Worker."); }else if(!navigator?.storage?.getDirectory){ @@ -561,13 +561,16 @@ mTimeEnd(); wTimeEnd(); return; } if( state.opfsFlags.OPFS_UNLINK_BEFORE_OPEN & opfsFlags ){ + //log("async proxy opfsFlags =",opfsFlags); try{ await hDir.removeEntry(filenamePart); - }catch(e){ + //log("Unlinked",filename,hDir,filenamePart); + } + catch(e){ /* ignoring */ //warn("Ignoring failed Unlink of",filename,":",e); } } const hFile = await hDir.getFileHandle(filenamePart, {create}); @@ -917,7 +920,7 @@ !globalThis.FileSystemFileHandle || !globalThis.FileSystemFileHandle.prototype.createSyncAccessHandle || !navigator?.storage?.getDirectory){ wPost('opfs-unavailable',"Missing required OPFS APIs."); }else{ - installAsyncProxy(); + installAsyncProxy(self); } Index: src/build.c ================================================================== --- src/build.c +++ src/build.c @@ -3004,16 +3004,13 @@ /* Legacy versions of SQLite allowed the use of the magic "rowid" column ** on a view, even though views do not have rowids. The following flag ** setting fixes this problem. But the fix can be disabled by compiling ** with -DSQLITE_ALLOW_ROWID_IN_VIEW in case there are legacy apps that - ** depend upon the old buggy behavior. The ability can also be toggled - ** using SQLITE_TESTCTRL_ROWID_IN_VIEW */ -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - p->tabFlags |= sqlite3Config.mNoVisibleRowid; /* Optional. Allow by default */ -#else - p->tabFlags |= TF_NoVisibleRowid; /* Never allow rowid in view */ + ** depend upon the old buggy behavior. */ +#ifndef SQLITE_ALLOW_ROWID_IN_VIEW + p->tabFlags |= TF_NoVisibleRowid; #endif sqlite3TwoPartName(pParse, pName1, pName2, &pName); iDb = sqlite3SchemaToIndex(db, p->pSchema); sqlite3FixInit(&sFix, pParse, iDb, "view", pName); Index: src/expr.c ================================================================== --- src/expr.c +++ src/expr.c @@ -216,14 +216,13 @@ if( ExprHasProperty(pExpr, EP_Unlikely) ){ assert( ExprUseXList(pExpr) ); assert( pExpr->x.pList->nExpr>0 ); assert( pExpr->op==TK_FUNCTION ); pExpr = pExpr->x.pList->a[0].pExpr; - }else if( pExpr->op==TK_COLLATE ){ - pExpr = pExpr->pLeft; }else{ - break; + assert( pExpr->op==TK_COLLATE ); + pExpr = pExpr->pLeft; } } return pExpr; } @@ -1868,11 +1867,10 @@ pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias); pNewItem->fg = pOldItem->fg; 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); } pNewItem->u2 = pOldItem->u2; if( pNewItem->fg.isCte ){ @@ -2345,58 +2343,10 @@ } } return pExpr; } -/* -** pExpr is a TK_FUNCTION node. Try to determine whether or not the -** function is a constant function. A function is constant if all of -** the following are true: -** -** (1) It is a scalar function (not an aggregate or window function) -** (2) It has either the SQLITE_FUNC_CONSTANT or SQLITE_FUNC_SLOCHNG -** property. -** (3) All of its arguments are constants -** -** This routine sets pWalker->eCode to 0 if pExpr is not a constant. -** It makes no changes to pWalker->eCode if pExpr is constant. In -** every case, it returns WRC_Abort. -** -** Called as a service subroutine from exprNodeIsConstant(). -*/ -static SQLITE_NOINLINE int exprNodeIsConstantFunction( - Walker *pWalker, - Expr *pExpr -){ - int n; /* Number of arguments */ - ExprList *pList; /* List of arguments */ - FuncDef *pDef; /* The function */ - sqlite3 *db; /* The database */ - - assert( pExpr->op==TK_FUNCTION ); - if( ExprHasProperty(pExpr, EP_TokenOnly) - || (pList = pExpr->x.pList)==0 - ){; - n = 0; - }else{ - n = pList->nExpr; - sqlite3WalkExprList(pWalker, pList); - if( pWalker->eCode==0 ) return WRC_Abort; - } - db = pWalker->pParse->db; - pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0); - if( pDef==0 - || pDef->xFinalize!=0 - || (pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0 - || ExprHasProperty(pExpr, EP_WinFunc) - ){ - pWalker->eCode = 0; - return WRC_Abort; - } - return WRC_Continue; -} - /* ** These routines are Walker callbacks used to check expressions to ** see if they are "constant" for some definition of constant. The ** Walker.eCode value determines the type of "constant" we are looking @@ -2421,11 +2371,10 @@ ** contain a bound parameter because they were generated by older versions ** of SQLite to be parsed by newer versions of SQLite without raising a ** malformed schema error. */ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ - assert( pWalker->eCode>0 ); /* If pWalker->eCode is 2 then any term of the expression that comes from ** the ON or USING clauses of an outer join disqualifies the expression ** from being considered constant. */ if( pWalker->eCode==2 && ExprHasProperty(pExpr, EP_OuterON) ){ @@ -2441,12 +2390,10 @@ if( (pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_ConstFunc)) && !ExprHasProperty(pExpr, EP_WinFunc) ){ if( pWalker->eCode==5 ) ExprSetProperty(pExpr, EP_FromDDL); return WRC_Continue; - }else if( pWalker->pParse ){ - return exprNodeIsConstantFunction(pWalker, pExpr); }else{ pWalker->eCode = 0; return WRC_Abort; } case TK_ID: @@ -2495,14 +2442,13 @@ testcase( pExpr->op==TK_SELECT ); /* sqlite3SelectWalkFail() disallows */ testcase( pExpr->op==TK_EXISTS ); /* sqlite3SelectWalkFail() disallows */ return WRC_Continue; } } -static int exprIsConst(Parse *pParse, Expr *p, int initFlag, int iCur){ +static int exprIsConst(Expr *p, int initFlag, int iCur){ Walker w; w.eCode = initFlag; - w.pParse = pParse; w.xExprCallback = exprNodeIsConstant; w.xSelectCallback = sqlite3SelectWalkFail; #ifdef SQLITE_DEBUG w.xSelectCallback2 = sqlite3SelectWalkAssert2; #endif @@ -2516,19 +2462,13 @@ ** and 0 if it involves variables or function calls. ** ** For the purposes of this function, a double-quoted string (ex: "abc") ** is considered a variable but a single-quoted string (ex: 'abc') is ** a constant. -** -** The pParse parameter may be NULL. But if it is NULL, there is no way -** to determine if function calls are constant or not, and hence all -** function calls will be considered to be non-constant. If pParse is -** not NULL, then a function call might be constant, depending on the -** function and on its parameters. */ -int sqlite3ExprIsConstant(Parse *pParse, Expr *p){ - return exprIsConst(pParse, p, 1, 0); +int sqlite3ExprIsConstant(Expr *p){ + return exprIsConst(p, 1, 0); } /* ** Walk an expression tree. Return non-zero if ** @@ -2540,22 +2480,22 @@ ** ** When this routine returns true, it indicates that the expression ** can be added to the pParse->pConstExpr list and evaluated once when ** the prepared statement starts up. See sqlite3ExprCodeRunJustOnce(). */ -static int sqlite3ExprIsConstantNotJoin(Parse *pParse, Expr *p){ - return exprIsConst(pParse, p, 2, 0); +int sqlite3ExprIsConstantNotJoin(Expr *p){ + return exprIsConst(p, 2, 0); } /* ** Walk an expression tree. Return non-zero if the expression is constant ** for any single row of the table with cursor iCur. In other words, the ** expression must not refer to any non-deterministic function nor any ** table other than iCur. */ int sqlite3ExprIsTableConstant(Expr *p, int iCur){ - return exprIsConst(0, p, 3, iCur); + return exprIsConst(p, 3, iCur); } /* ** Check pExpr to see if it is an constraint on the single data source ** pSrc = &pSrcList->a[iSrc]. In other words, check to see if pExpr @@ -2708,11 +2648,11 @@ ** is considered a variable but a single-quoted string (ex: 'abc') is ** a constant. */ int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){ assert( isInit==0 || isInit==1 ); - return exprIsConst(0, p, 4+isInit, 0); + return exprIsConst(p, 4+isInit, 0); } #ifdef SQLITE_ENABLE_CURSOR_HINTS /* ** Walk an expression tree. Return 1 if the expression contains a @@ -2953,17 +2893,17 @@ #ifndef SQLITE_OMIT_SUBQUERY /* ** The argument is an IN operator with a list (not a subquery) on the ** right-hand side. Return TRUE if that list is constant. */ -static int sqlite3InRhsIsConstant(Parse *pParse, Expr *pIn){ +static int sqlite3InRhsIsConstant(Expr *pIn){ Expr *pLHS; int res; assert( !ExprHasProperty(pIn, EP_xIsSelect) ); pLHS = pIn->pLeft; pIn->pLeft = 0; - res = sqlite3ExprIsConstant(pParse, pIn); + res = sqlite3ExprIsConstant(pIn); pIn->pLeft = pLHS; return res; } #endif @@ -3228,11 +3168,11 @@ ** the IN operator so return IN_INDEX_NOOP. */ if( eType==0 && (inFlags & IN_INDEX_NOOP_OK) && ExprUseXList(pX) - && (!sqlite3InRhsIsConstant(pParse,pX) || pX->x.pList->nExpr<=2) + && (!sqlite3InRhsIsConstant(pX) || pX->x.pList->nExpr<=2) ){ pParse->nTab--; /* Back out the allocation of the unused cursor */ iTab = -1; /* Cursor is not allocated */ eType = IN_INDEX_NOOP; } @@ -3511,11 +3451,11 @@ /* If the expression is not constant then we will need to ** disable the test that was generated above that makes sure ** this code only executes once. Because for a non-constant ** expression we need to rerun this code each time. */ - if( addrOnce && !sqlite3ExprIsConstant(pParse, pE2) ){ + if( addrOnce && !sqlite3ExprIsConstant(pE2) ){ sqlite3VdbeChangeToNoop(v, addrOnce-1); sqlite3VdbeChangeToNoop(v, addrOnce); ExprClearProperty(pExpr, EP_Subrtn); addrOnce = 0; } @@ -4848,13 +4788,11 @@ if( ExprHasProperty(pExpr, EP_WinFunc) ){ return pExpr->y.pWin->regResult; } #endif - if( ConstFactorOk(pParse) - && sqlite3ExprIsConstantNotJoin(pParse,pExpr) - ){ + if( ConstFactorOk(pParse) && sqlite3ExprIsConstantNotJoin(pExpr) ){ /* SQL functions can be expensive. So try to avoid running them ** multiple times if we know they always give the same result */ return sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1); } assert( !ExprHasProperty(pExpr, EP_TokenOnly) ); @@ -4881,11 +4819,11 @@ }else if( pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE) ){ sqlite3ExprFunctionUsable(pParse, pExpr, pDef); } for(i=0; ia[i].pExpr) ){ + if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){ testcase( i==31 ); constMask |= MASKBIT32(i); } if( (pDef->funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){ pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr); @@ -5348,11 +5286,11 @@ int r2; pExpr = sqlite3ExprSkipCollateAndLikely(pExpr); if( ConstFactorOk(pParse) && ALWAYS(pExpr!=0) && pExpr->op!=TK_REGISTER - && sqlite3ExprIsConstantNotJoin(pParse, pExpr) + && sqlite3ExprIsConstantNotJoin(pExpr) ){ *pReg = 0; r2 = sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1); }else{ int r1 = sqlite3GetTempReg(pParse); @@ -5412,11 +5350,11 @@ ** results in register target. The results are guaranteed to appear ** in register target. If the expression is constant, then this routine ** might choose to code the expression at initialization time. */ void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){ - if( pParse->okConstFactor && sqlite3ExprIsConstantNotJoin(pParse,pExpr) ){ + if( pParse->okConstFactor && sqlite3ExprIsConstantNotJoin(pExpr) ){ sqlite3ExprCodeRunJustOnce(pParse, pExpr, target); }else{ sqlite3ExprCodeCopy(pParse, pExpr, target); } } @@ -5471,11 +5409,11 @@ n--; }else{ sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i); } }else if( (flags & SQLITE_ECEL_FACTOR)!=0 - && sqlite3ExprIsConstantNotJoin(pParse,pExpr) + && sqlite3ExprIsConstantNotJoin(pExpr) ){ sqlite3ExprCodeRunJustOnce(pParse, pExpr, target+i); }else{ int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i); if( inReg!=target+i ){ Index: src/global.c ================================================================== --- src/global.c +++ src/global.c @@ -287,13 +287,10 @@ SQLITE_MEMDB_DEFAULT_MAXSIZE, /* mxMemdbSize */ #endif #ifndef SQLITE_UNTESTABLE 0, /* xTestCallback */ #endif -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - 0, /* mNoVisibleRowid. 0 == allow rowid-in-view */ -#endif 0, /* bLocaltimeFault */ 0, /* xAltLocaltime */ 0x7ffffffe, /* iOnceResetThreshold */ SQLITE_DEFAULT_SORTERREF_SIZE, /* szSorterRef */ 0, /* iPrngSeed */ Index: src/insert.c ================================================================== --- src/insert.c +++ src/insert.c @@ -575,197 +575,10 @@ */ # define autoIncBegin(A,B,C) (0) # define autoIncStep(A,B,C) #endif /* SQLITE_OMIT_AUTOINCREMENT */ -/* -** If argument pVal is a Select object returned by an sqlite3MultiValues() -** that was able to use the co-routine optimization, finish coding the -** co-routine. -*/ -void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal){ - if( ALWAYS(pVal) && pVal->pSrc->nSrc>0 ){ - SrcItem *pItem = &pVal->pSrc->a[0]; - sqlite3VdbeEndCoroutine(pParse->pVdbe, pItem->regReturn); - sqlite3VdbeJumpHere(pParse->pVdbe, pItem->addrFillSub - 1); - } -} - -/* -** Return true if all expressions in the expression-list passed as the -** only argument are constant. -*/ -static int exprListIsConstant(Parse *pParse, ExprList *pRow){ - int ii; - for(ii=0; iinExpr; ii++){ - if( 0==sqlite3ExprIsConstant(pParse, pRow->a[ii].pExpr) ) return 0; - } - return 1; -} - -/* -** Return true if all expressions in the expression-list passed as the -** only argument are both constant and have no affinity. -*/ -static int exprListIsNoAffinity(Parse *pParse, ExprList *pRow){ - int ii; - if( exprListIsConstant(pParse,pRow)==0 ) return 0; - for(ii=0; iinExpr; ii++){ - assert( pRow->a[ii].pExpr->affExpr==0 ); - if( 0!=sqlite3ExprAffinity(pRow->a[ii].pExpr) ) return 0; - } - return 1; - -} - -/* -** This function is called by the parser for the second and subsequent -** rows of a multi-row VALUES clause. Argument pLeft is the part of -** the VALUES clause already parsed, argument pRow is the vector of values -** for the new row. The Select object returned represents the complete -** VALUES clause, including the new row. -** -** There are two ways in which this may be achieved - by incremental -** coding of a co-routine (the "co-routine" method) or by returning a -** Select object equivalent to the following (the "UNION ALL" method): -** -** "pLeft UNION ALL SELECT pRow" -** -** If the VALUES clause contains a lot of rows, this compound Select -** object may consume a lot of memory. -** -** When the co-routine method is used, each row that will be returned -** by the VALUES clause is coded into part of a co-routine as it is -** passed to this function. The returned Select object is equivalent to: -** -** SELECT * FROM ( -** Select object to read co-routine -** ) -** -** The co-routine method is used in most cases. Exceptions are: -** -** a) If the current statement has a WITH clause. This is to avoid -** statements like: -** -** WITH cte AS ( VALUES('x'), ('y') ... ) -** SELECT * FROM cte AS a, cte AS b; -** -** This will not work, as the co-routine uses a hard-coded register -** for its OP_Yield instructions, and so it is not possible for two -** cursors to iterate through it concurrently. -** -** b) The schema is currently being parsed (i.e. the VALUES clause is part -** of a schema item like a VIEW or TRIGGER). In this case there is no VM -** being generated when parsing is taking place, and so generating -** a co-routine is not possible. -** -** c) There are non-constant expressions in the VALUES clause (e.g. -** the VALUES clause is part of a correlated sub-query). -** -** d) One or more of the values in the first row of the VALUES clause -** has an affinity (i.e. is a CAST expression). This causes problems -** because the complex rules SQLite uses (see function -** sqlite3SubqueryColumnTypes() in select.c) to determine the effective -** affinity of such a column for all rows require access to all values in -** the column simultaneously. -*/ -Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){ - - if( pParse->bHasWith /* condition (a) above */ - || pParse->db->init.busy /* condition (b) above */ - || exprListIsConstant(pParse,pRow)==0 /* condition (c) above */ - || (pLeft->pSrc->nSrc==0 && - exprListIsNoAffinity(pParse,pLeft->pEList)==0) /* condition (d) above */ - || IN_SPECIAL_PARSE - ){ - /* The co-routine method cannot be used. Fall back to UNION ALL. */ - Select *pSelect = 0; - int f = SF_Values | SF_MultiValue; - if( pLeft->pSrc->nSrc ){ - sqlite3MultiValuesEnd(pParse, pLeft); - f = SF_Values; - }else if( pLeft->pPrior ){ - /* In this case set the SF_MultiValue flag only if it was set on pLeft */ - f = (f & pLeft->selFlags); - } - 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{ - SrcItem *p = 0; /* SrcItem that reads from co-routine */ - - if( pLeft->pSrc->nSrc==0 ){ - /* Co-routine has not yet been started and the special Select object - ** that accesses the co-routine has not yet been created. This block - ** does both those things. */ - Vdbe *v = sqlite3GetVdbe(pParse); - Select *pRet = sqlite3SelectNew(pParse, 0, 0, 0, 0, 0, 0, 0, 0); - - /* Ensure the database schema has been read. This is to ensure we have - ** the correct text encoding. */ - if( (pParse->db->mDbFlags & DBFLAG_SchemaKnownOk)==0 ){ - sqlite3ReadSchema(pParse); - } - - if( pRet ){ - SelectDest dest; - pRet->pSrc->nSrc = 1; - pRet->pPrior = pLeft->pPrior; - pRet->op = pLeft->op; - pLeft->pPrior = 0; - pLeft->op = TK_SELECT; - assert( pLeft->pNext==0 ); - assert( pRet->pNext==0 ); - p = &pRet->pSrc->a[0]; - p->pSelect = pLeft; - p->fg.viaCoroutine = 1; - p->addrFillSub = sqlite3VdbeCurrentAddr(v) + 1; - p->regReturn = ++pParse->nMem; - p->iCursor = -1; - p->u1.nRow = 2; - sqlite3VdbeAddOp3(v,OP_InitCoroutine,p->regReturn,0,p->addrFillSub); - sqlite3SelectDestInit(&dest, SRT_Coroutine, p->regReturn); - - /* Allocate registers for the output of the co-routine. Do so so - ** that there are two unused registers immediately before those - ** used by the co-routine. This allows the code in sqlite3Insert() - ** to use these registers directly, instead of copying the output - ** of the co-routine to a separate array for processing. */ - dest.iSdst = pParse->nMem + 3; - dest.nSdst = pLeft->pEList->nExpr; - pParse->nMem += 2 + dest.nSdst; - - pLeft->selFlags |= SF_MultiValue; - sqlite3Select(pParse, pLeft, &dest); - p->regResult = dest.iSdst; - assert( pParse->nErr || dest.iSdst>0 ); - pLeft = pRet; - } - }else{ - p = &pLeft->pSrc->a[0]; - assert( !p->fg.isTabFunc && !p->fg.isIndexedBy ); - p->u1.nRow++; - } - - if( pParse->nErr==0 ){ - assert( p!=0 ); - if( p->pSelect->pEList->nExpr!=pRow->nExpr ){ - sqlite3SelectWrongNumTermsError(pParse, p->pSelect); - }else{ - sqlite3ExprCodeExprList(pParse, pRow, p->regResult, 0, 0); - sqlite3VdbeAddOp1(pParse->pVdbe, OP_Yield, p->regReturn); - } - } - sqlite3ExprListDelete(pParse->db, pRow); - } - - return pLeft; -} /* Forward declaration */ static int xferOptimization( Parse *pParse, /* Parser context */ Table *pDest, /* The table we are inserting into */ @@ -1098,44 +911,29 @@ ** co-routine is the common header to the 3rd and 4th templates. */ if( pSelect ){ /* 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 */ - if( pSelect->pSrc->nSrc==1 - && pSelect->pSrc->a[0].fg.viaCoroutine - && pSelect->pPrior==0 - ){ - SrcItem *pItem = &pSelect->pSrc->a[0]; - dest.iSDParm = pItem->regReturn; - regFromSelect = pItem->regResult; - nColumn = pItem->pSelect->pEList->nExpr; - ExplainQueryPlan((pParse, 0, "SCAN %S", pItem)); - if( bIdListInOrder && nColumn==pTab->nCol ){ - regData = regFromSelect; - regRowid = regData - 1; - regIns = regRowid - (IsVirtual(pTab) ? 1 : 0); - } - }else{ - int addrTop; /* Top of the co-routine */ - int 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; - } + 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 ** FALSE if each output row of the SELECT can be written directly into ** the destination table (template 3). Index: src/main.c ================================================================== --- src/main.c +++ src/main.c @@ -4400,43 +4400,10 @@ typedef int(*sqlite3LocaltimeType)(const void*,void*); sqlite3GlobalConfig.xAltLocaltime = va_arg(ap, sqlite3LocaltimeType); }else{ sqlite3GlobalConfig.xAltLocaltime = 0; } - break; - } - - /* sqlite3_test_control(SQLITE_TESTCTRL_ROWID_IN_VIEW, int *pVal); - ** - ** Query or set the sqlite3Config.mNoVisibleRowid flag. Cases: - ** - ** *pVal==1 Allow ROWID in VIEWs - ** *pVal==0 Disallow ROWID in VIEWs - ** *pVal<0 No change - ** - ** In every case *pVal is written with 1 if ROWID is allowd in VIEWs and - ** 0 if not. Changes to the setting only occur if SQLite is compiled - ** with -DSQLITE_ALLOW_ROWID_IN_VIEW (hereafter: "SARIV"). With the - ** "SARIV" compile-time option the default value for this setting is 1. - ** Otherwise this setting defaults to 0. This setting may only be changed - ** if SQLite is compiled with "SARIV". Hence, in the normal case when - ** SQLite is compiled without "SARIV", this test-control is a no-op - ** that always leaves *pVal set to 0. - ** - ** IMPORTANT: If you change this setting while a database connection - ** is option, it is very important to run "PRAGMA writable_schema=RESET" - ** afterwards in order to reparse all VIEW definitions in the schema. - */ - case SQLITE_TESTCTRL_ROWID_IN_VIEW: { - int *pVal = va_arg(ap, int*); -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - if( *pVal==0 ) sqlite3Config.mNoVisibleRowid = TF_NoVisibleRowid; - if( *pVal==1 ) sqlite3Config.mNoVisibleRowid = 0; - *pVal = (sqlite3Config.mNoVisibleRowid==0); -#else - *pVal = 0; -#endif break; } /* sqlite3_test_control(SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, sqlite3*); ** Index: src/parse.y ================================================================== --- src/parse.y +++ src/parse.y @@ -563,11 +563,10 @@ %ifndef SQLITE_OMIT_CTE select(A) ::= WITH wqlist(W) selectnowith(X). {A = attachWithToSelect(pParse,X,W);} select(A) ::= WITH RECURSIVE wqlist(W) selectnowith(X). {A = attachWithToSelect(pParse,X,W);} - %endif /* SQLITE_OMIT_CTE */ select(A) ::= selectnowith(A). { Select *p = A; if( p ){ parserDoubleLinkSelect(pParse, p); @@ -621,31 +620,28 @@ } } %endif -// Single row VALUES clause. -// -%type values {Select*} oneselect(A) ::= values(A). + +%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); } - -// Multiple row VALUES clause. -// -%type mvalues {Select*} -oneselect(A) ::= mvalues(A). { - sqlite3MultiValuesEnd(pParse, A); -} -%destructor mvalues {sqlite3SelectDelete(pParse->db, $$);} -mvalues(A) ::= values(A) COMMA LP nexprlist(Y) RP. { - A = sqlite3MultiValues(pParse, A, Y); -} -mvalues(A) ::= mvalues(A) COMMA LP nexprlist(Y) RP. { - A = sqlite3MultiValues(pParse, A, Y); +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; + } } // The "distinct" nonterminal is true (1) if the DISTINCT keyword is // present and false (0) if it is not. // @@ -1323,11 +1319,11 @@ sqlite3ExprUnmapAndDelete(pParse, A); A = sqlite3Expr(pParse->db, TK_STRING, N ? "true" : "false"); if( A ) sqlite3ExprIdToTrueFalse(A); }else{ Expr *pRHS = Y->a[0].pExpr; - if( Y->nExpr==1 && sqlite3ExprIsConstant(pParse,pRHS) && A->op!=TK_VECTOR ){ + if( Y->nExpr==1 && sqlite3ExprIsConstant(pRHS) && A->op!=TK_VECTOR ){ Y->a[0].pExpr = 0; sqlite3ExprListDelete(pParse->db, Y); pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0); A = sqlite3PExpr(pParse, TK_EQ, A, pRHS); }else if( Y->nExpr==1 && pRHS->op==TK_SELECT ){ @@ -1763,14 +1759,13 @@ %type wqas {u8} wqas(A) ::= AS. {A = M10d_Any;} wqas(A) ::= AS MATERIALIZED. {A = M10d_Yes;} wqas(A) ::= AS NOT MATERIALIZED. {A = M10d_No;} -wqitem(A) ::= withnm(X) eidlist_opt(Y) wqas(M) LP select(Z) RP. { +wqitem(A) ::= nm(X) eidlist_opt(Y) wqas(M) LP select(Z) RP. { A = sqlite3CteNew(pParse, &X, Y, Z, M); /*A-overwrites-X*/ } -withnm(A) ::= nm(A). {pParse->bHasWith = 1;} wqlist(A) ::= wqitem(X). { A = sqlite3WithAdd(pParse, 0, X); /*A-overwrites-X*/ } wqlist(A) ::= wqlist(A) COMMA wqitem(X). { A = sqlite3WithAdd(pParse, A, X); Index: src/printf.c ================================================================== --- src/printf.c +++ src/printf.c @@ -858,14 +858,10 @@ }else{ Select *pSel = pItem->pSelect; assert( pSel!=0 ); if( pSel->selFlags & SF_NestedFrom ){ sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId); - }else if( pSel->selFlags & SF_MultiValue ){ - assert( !pItem->fg.isTabFunc && !pItem->fg.isIndexedBy ); - sqlite3_str_appendf(pAccum, "%u-ROW VALUES CLAUSE", - pItem->u1.nRow); }else{ sqlite3_str_appendf(pAccum, "(subquery-%u)", pSel->selId); } } length = width = 0; Index: src/select.c ================================================================== --- src/select.c +++ src/select.c @@ -1951,11 +1951,15 @@ /* The "table" is actually a sub-select or a view in the FROM clause ** of the SELECT statement. Return the declaration type and origin ** data for the result-set column of the sub-select. */ if( iColpEList->nExpr - && (!ViewCanHaveRowid || iCol>=0) +#ifdef SQLITE_ALLOW_ROWID_IN_VIEW + && iCol>=0 +#else + && ALWAYS(iCol>=0) +#endif ){ /* If iCol is less than zero, then the expression requests the ** rowid of the sub-select or view. This expression is legal (see ** test case misc2.2.2) - it always evaluates to NULL. */ @@ -4770,11 +4774,11 @@ Expr *pValue, /* The VALUE part of the constraint */ Expr *pExpr /* Overall expression: COLUMN=VALUE or VALUE=COLUMN */ ){ int i; assert( pColumn->op==TK_COLUMN ); - assert( sqlite3ExprIsConstant(pConst->pParse, pValue) ); + assert( sqlite3ExprIsConstant(pValue) ); if( ExprHasProperty(pColumn, EP_FixedCol) ) return; if( sqlite3ExprAffinity(pValue)!=0 ) return; if( !sqlite3IsBinary(sqlite3ExprCompareCollSeq(pConst->pParse,pExpr)) ){ return; @@ -4828,14 +4832,14 @@ if( pExpr->op!=TK_EQ ) return; pRight = pExpr->pRight; pLeft = pExpr->pLeft; assert( pRight!=0 ); assert( pLeft!=0 ); - if( pRight->op==TK_COLUMN && sqlite3ExprIsConstant(pConst->pParse, pLeft) ){ + if( pRight->op==TK_COLUMN && sqlite3ExprIsConstant(pLeft) ){ constInsert(pConst,pRight,pLeft,pExpr); } - if( pLeft->op==TK_COLUMN && sqlite3ExprIsConstant(pConst->pParse, pRight) ){ + if( pLeft->op==TK_COLUMN && sqlite3ExprIsConstant(pRight) ){ constInsert(pConst,pLeft,pRight,pExpr); } } /* @@ -5868,12 +5872,11 @@ pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); #ifndef SQLITE_ALLOW_ROWID_IN_VIEW /* The usual case - do not allow ROWID on a subquery */ pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid; #else - /* Legacy compatibility mode */ - pTab->tabFlags |= TF_Ephemeral | sqlite3Config.mNoVisibleRowid; + pTab->tabFlags |= TF_Ephemeral; /* Legacy compatibility mode */ #endif return pParse->nErr ? SQLITE_ERROR : SQLITE_OK; } @@ -6137,11 +6140,11 @@ if( pFrom->fg.isNestedFrom ){ assert( pFrom->pSelect!=0 ); pNestedFrom = pFrom->pSelect->pEList; assert( pNestedFrom!=0 ); assert( pNestedFrom->nExpr==pTab->nCol ); - assert( VisibleRowid(pTab)==0 || ViewCanHaveRowid ); + assert( VisibleRowid(pTab)==0 ); }else{ if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ continue; } pNestedFrom = 0; @@ -6169,17 +6172,11 @@ } }else{ pUsing = 0; } - nAdd = pTab->nCol; - if( VisibleRowid(pTab) - && !ViewCanHaveRowid - && (selFlags & SF_NestedFrom)!=0 - ){ - nAdd++; - } + nAdd = pTab->nCol + (VisibleRowid(pTab) && (selFlags&SF_NestedFrom)); for(j=0; jnCol ){ @@ -7637,11 +7634,11 @@ #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) /* Generate code for all sub-queries in the FROM clause */ pSub = pItem->pSelect; - if( pSub==0 || pItem->addrFillSub!=0 ) continue; + if( pSub==0 ) continue; /* The code for a subquery should only be generated once. */ assert( pItem->addrFillSub==0 ); /* Increment Parse.nHeight by the height of the largest expression Index: src/shell.c.in ================================================================== --- src/shell.c.in +++ src/shell.c.in @@ -10891,11 +10891,10 @@ #endif {"pending_byte", SQLITE_TESTCTRL_PENDING_BYTE,0, "OFFSET " }, {"prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE,0, "" }, {"prng_save", SQLITE_TESTCTRL_PRNG_SAVE, 0, "" }, {"prng_seed", SQLITE_TESTCTRL_PRNG_SEED, 0, "SEED ?db?" }, - {"rowid_in_view", SQLITE_TESTCTRL_ROWID_IN_VIEW,0,"?BOOLEAN?" }, {"seek_count", SQLITE_TESTCTRL_SEEK_COUNT, 0, "" }, {"sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX" }, {"tune", SQLITE_TESTCTRL_TUNE, 1, "ID VALUE" }, {"uselongdouble", SQLITE_TESTCTRL_USELONGDOUBLE,0,"?BOOLEAN|\"default\"?"}, }; @@ -11066,24 +11065,10 @@ isOk = 3; } break; } #endif - case SQLITE_TESTCTRL_ROWID_IN_VIEW: { - rc2 = -1; - if( nArg>=3 ){ - if( !ShellHasFlag(p,SHFLG_TestingMode) ){ - eputz("The --unsafe-testing option is required to change " - "this setting\n"); - }else{ - rc2 = booleanValue(azArg[2]); - } - } - sqlite3_test_control(testctrl, &rc2); - isOk = 1; - break; - } #ifdef SQLITE_DEBUG case SQLITE_TESTCTRL_TUNE: { if( nArg==4 ){ int id = (int)integerValue(azArg[2]); int val = (int)integerValue(azArg[3]); Index: src/sqlite.h.in ================================================================== --- src/sqlite.h.in +++ src/sqlite.h.in @@ -8305,11 +8305,10 @@ #define SQLITE_TESTCTRL_ALWAYS 13 #define SQLITE_TESTCTRL_RESERVE 14 /* NOT USED */ #define SQLITE_TESTCTRL_JSON_SELFCHECK 14 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 #define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ -#define SQLITE_TESTCTRL_ROWID_IN_VIEW 16 #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ #define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ #define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19 Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -2533,19 +2533,10 @@ /* Does the table have a rowid */ #define HasRowid(X) (((X)->tabFlags & TF_WithoutRowid)==0) #define VisibleRowid(X) (((X)->tabFlags & TF_NoVisibleRowid)==0) -/* Macro is true if the SQLITE_ALLOW_ROWID_IN_VIEW (mis-)feature is -** available. By default, this macro is false -*/ -#ifndef SQLITE_ALLOW_ROWID_IN_VIEW -# define ViewCanHaveRowid 0 -#else -# define ViewCanHaveRowid (sqlite3Config.mNoVisibleRowid==0) -#endif - /* ** Each foreign key constraint is an instance of the following structure. ** ** A foreign key is associated with two tables. The "from" table is ** the table that contains the REFERENCES clause that creates the foreign @@ -3277,16 +3268,14 @@ ** In the colUsed field, the high-order bit (bit 63) is set if the table ** contains more than 63 columns and the 64-th or later column is used. ** ** Union member validity: ** -** u1.zIndexedBy fg.isIndexedBy && !fg.isTabFunc -** u1.pFuncArg fg.isTabFunc && !fg.isIndexedBy -** u1.nRow !fg.isTabFunc && !fg.isIndexedBy -** -** u2.pIBIndex fg.isIndexedBy && !fg.isCte -** u2.pCteUse fg.isCte && !fg.isIndexedBy +** u1.zIndexedBy fg.isIndexedBy && !fg.isTabFunc +** u1.pFuncArg fg.isTabFunc && !fg.isIndexedBy +** u2.pIBIndex fg.isIndexedBy && !fg.isCte +** u2.pCteUse fg.isCte && !fg.isIndexedBy */ struct SrcItem { Schema *pSchema; /* Schema to which this item is fixed */ char *zDatabase; /* Name of database holding this table */ char *zName; /* Name of the table */ @@ -3320,11 +3309,10 @@ } u3; Bitmask colUsed; /* Bit N set if column N used. Details above for N>62 */ union { char *zIndexedBy; /* Identifier from "INDEXED BY " clause */ ExprList *pFuncArg; /* Arguments to table-valued-function */ - u32 nRow; /* Number of rows in a VALUES clause */ } u1; union { Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */ CteUse *pCteUse; /* CTE Usage info when fg.isCte is true */ } u2; @@ -3822,11 +3810,10 @@ u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ u8 okConstFactor; /* OK to factor out constants */ 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 #ifdef SQLITE_DEBUG u8 ifNotExists; /* Might be true if IF NOT EXISTS. Assert()s only */ @@ -4261,15 +4248,10 @@ sqlite3_int64 mxMemdbSize; /* Default max memdb size */ #endif #ifndef SQLITE_UNTESTABLE int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */ #endif -#ifdef SQLITE_ALLOW_ROWID_IN_VIEW - u32 mNoVisibleRowid; /* TF_NoVisibleRowid if the ROWID_IN_VIEW - ** feature is disabled. 0 if rowids can - ** occur in views. */ -#endif int bLocaltimeFault; /* True to fail localtime() calls */ int (*xAltLocaltime)(const void*,void*); /* Alternative localtime() routine */ int iOnceResetThreshold; /* When to reset OP_Once counters */ u32 szSorterRef; /* Min size in bytes to use sorter-refs */ unsigned int iPrngSeed; /* Alternative fixed seed for the PRNG */ @@ -4502,13 +4484,10 @@ int regEndRowid; u8 bExprArgs; /* Defer evaluation of window function arguments ** 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*); void sqlite3WindowListDelete(sqlite3 *db, Window *p); Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*, u8); @@ -5073,11 +5052,12 @@ void sqlite3CloseSavepoints(sqlite3 *); void sqlite3LeaveMutexAndCloseZombie(sqlite3*); u32 sqlite3IsTrueOrFalse(const char*); int sqlite3ExprIdToTrueFalse(Expr*); int sqlite3ExprTruthValue(const Expr*); -int sqlite3ExprIsConstant(Parse*,Expr*); +int sqlite3ExprIsConstant(Expr*); +int sqlite3ExprIsConstantNotJoin(Expr*); int sqlite3ExprIsConstantOrFunction(Expr*, u8); int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*); int sqlite3ExprIsTableConstant(Expr*,int); int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int); #ifdef SQLITE_ENABLE_CURSOR_HINTS Index: src/where.c ================================================================== --- src/where.c +++ src/where.c @@ -1327,11 +1327,11 @@ for(i=0; ia[i].pExpr; Expr *pE2; /* Skip over constant terms in the ORDER BY clause */ - if( sqlite3ExprIsConstant(0, pExpr) ){ + if( sqlite3ExprIsConstant(pExpr) ){ continue; } /* Virtual tables are unable to deal with NULLS FIRST */ if( pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_BIGNULL ) break; @@ -1439,11 +1439,11 @@ } assert( j==nTerm ); pIdxInfo->nConstraint = j; for(i=j=0; ia[i].pExpr; - if( sqlite3ExprIsConstant(0, pExpr) ) continue; + if( sqlite3ExprIsConstant(pExpr) ) continue; assert( pExpr->op==TK_COLUMN || (pExpr->op==TK_COLLATE && pExpr->pLeft->op==TK_COLUMN && pExpr->iColumn==pExpr->pLeft->iColumn) ); pIdxOrderBy[j].iColumn = pExpr->iColumn; pIdxOrderBy[j].desc = pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_DESC; @@ -3621,11 +3621,11 @@ Expr *pLeft = pPart->pLeft; Expr *pRight = pPart->pRight; u8 aff; if( pLeft->op!=TK_COLUMN ) return; - if( !sqlite3ExprIsConstant(0, pRight) ) return; + if( !sqlite3ExprIsConstant(pRight) ) return; if( !sqlite3IsBinary(sqlite3ExprCompareCollSeq(pParse, pPart)) ) return; if( pLeft->iColumn<0 ) return; aff = pIdx->pTable->aCol[pLeft->iColumn].affinity; if( aff>=SQLITE_AFF_TEXT ){ if( pItem ){ @@ -4995,11 +4995,11 @@ Expr *p; Bitmask mTerm; if( MASKBIT(i) & obSat ) continue; p = pOrderBy->a[i].pExpr; mTerm = sqlite3WhereExprUsage(&pWInfo->sMaskSet,p); - if( mTerm==0 && !sqlite3ExprIsConstant(0,p) ) continue; + if( mTerm==0 && !sqlite3ExprIsConstant(p) ) continue; if( (mTerm&~orderDistinctMask)==0 ){ obSat |= MASKBIT(i); } } } @@ -5864,11 +5864,11 @@ pExpr = sqlite3ColumnExpr(pTab, &pTab->aCol[j]); bMaybeNullRow = 0; }else{ continue; } - if( sqlite3ExprIsConstant(0,pExpr) ) continue; + if( sqlite3ExprIsConstant(pExpr) ) continue; if( pExpr->op==TK_FUNCTION ){ /* Functions that might set a subtype should not be replaced by the ** value taken from an expression index since the index omits the ** subtype. https://sqlite.org/forum/forumpost/68d284c86b082c3e */ int n; @@ -6142,15 +6142,11 @@ if( (wctrlFlags & WHERE_WANT_DISTINCT)!=0 && OptimizationEnabled(db, SQLITE_DistinctOpt) ){ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; } - if( ALWAYS(pWInfo->pSelect) - && (pWInfo->pSelect->selFlags & SF_MultiValue)==0 - ){ - ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW")); - } + ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW")); }else{ /* Assign a bit from the bitmask to every term in the FROM clause. ** ** The N-th term of the FROM clause is assigned a bitmask of 1<fg.viaCoroutine ){ testcase( pParse->db->mallocFailed ); - assert( pTabItem->regResult>=0 ); translateColumnToCopy(pParse, pLevel->addrBody, pLevel->iTabCur, pTabItem->regResult, 0); continue; } Index: src/whereexpr.c ================================================================== --- src/whereexpr.c +++ src/whereexpr.c @@ -987,11 +987,11 @@ if( pIdx->aColExpr==0 ) continue; for(i=0; inKeyCol; i++){ if( pIdx->aiColumn[i]!=XN_EXPR ) continue; assert( pIdx->bHasExpr ); if( sqlite3ExprCompareSkip(pExpr,pIdx->aColExpr->a[i].pExpr,iCur)==0 - && !sqlite3ExprIsConstant(0,pIdx->aColExpr->a[i].pExpr) + && !sqlite3ExprIsConstant(pIdx->aColExpr->a[i].pExpr) ){ aiCurCol[0] = iCur; aiCurCol[1] = XN_EXPR; return 1; } Index: src/window.c ================================================================== --- src/window.c +++ src/window.c @@ -1162,11 +1162,11 @@ ** constant, change it to NULL. The fact that it is then a non-negative ** integer will be caught later. But it is important not to leave ** variable values in the expression tree. */ static Expr *sqlite3WindowOffsetExpr(Parse *pParse, Expr *pExpr){ - if( 0==sqlite3ExprIsConstant(0,pExpr) ){ + if( 0==sqlite3ExprIsConstant(pExpr) ){ if( IN_RENAME_OBJECT ) sqlite3RenameExprUnmap(pParse, pExpr); sqlite3ExprDelete(pParse->db, pExpr); pExpr = sqlite3ExprAlloc(pParse->db, TK_NULL, 0, 0); } return pExpr; Index: test/altertab3.test ================================================================== --- test/altertab3.test +++ test/altertab3.test @@ -734,33 +734,6 @@ SELECT "t3".* FROM "t3" ); END} } -#------------------------------------------------------------------------- -reset_db -do_execsql_test 30.0 { - CREATE TABLE t1(a, b); - CREATE VIEW v1 AS - SELECT ( VALUES(a), (b) ) FROM ( - SELECT a, b FROM t1 - ) - ; -} - -do_execsql_test 30.1 { - SELECT * FROM v1 -} - -do_execsql_test 30.1 { - ALTER TABLE t1 RENAME TO t2; -} -do_execsql_test 30.2 { - SELECT sql FROM sqlite_schema WHERE type='view' -} { - {CREATE VIEW v1 AS - SELECT ( VALUES(a), (b) ) FROM ( - SELECT a, b FROM "t2" - )} -} - finish_test DELETED test/cksumvfs.test Index: test/cksumvfs.test ================================================================== --- test/cksumvfs.test +++ /dev/null @@ -1,33 +0,0 @@ -# 2024 March 19 -# -# 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. -# -#*********************************************************************** -# - -set testdir [file dirname $argv0] -source $testdir/tester.tcl -set testprefix cksumvfs - -sqlite3_register_cksumvfs -db close -sqlite3 db test.db -file_control_reservebytes db 8 - -set text [db one "SELECT hex(randomblob(5000))"] - -do_execsql_test 1.0 { - CREATE TABLE t1(a INTEGER PRIMARY KEY, b); - INSERT INTO t1 VALUES(1, $text); -} - -do_execsql_test 1.1 { - SELECT * FROM t1; -} [list 1 $text] - -finish_test Index: test/func4.test ================================================================== --- test/func4.test +++ test/func4.test @@ -1,6 +1,6 @@ -# 2023-03-10 +# 2013 March 10 # # 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. @@ -7,14 +7,11 @@ # 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. The focus of -# this file is testing the tointeger() and toreal() functions that are -# part of the "totype.c" extension. This file does not test the core -# SQLite library. Failures of tests in this file are related to the -# ext/misc/totype.c extension. +# this file is testing the tointeger() and toreal() functions. # # Several of the toreal() tests are disabled on platforms where floating # point precision is not high enough to represent their constant integer # expression arguments as double precision floating point values. # @@ -24,24 +21,10 @@ set tcl_precision 0 load_static_extension db totype set highPrecision(1) [expr \ {[db eval {SELECT tointeger(9223372036854775807 + 1);}] eq {{}}}] -set highPrecision(2) [expr \ - {[db eval {SELECT toreal(-9223372036854775808 + 1);}] eq {{}}}] - -# highPrecision(3) is only known to be false on i586 with gcc-13 and -O2. -# It is true on the exact same platform with -O0. Both results seem -# reasonable, so we'll just very the expectation accordingly. -# -set highPrecision(3) [expr \ - {[db eval {SELECT toreal(9007199254740992 + 1);}] eq {{}}}] - -if {!$highPrecision(1) || !$highPrecision(2) || !$highPrecision(3)} { - puts "NOTICE: use_long_double: [use_long_double] \ - highPrecision: $highPrecision(1) $highPrecision(2) $highPrecision(3)" -} do_execsql_test func4-1.1 { SELECT tointeger(NULL); } {{}} do_execsql_test func4-1.2 { @@ -210,10 +193,12 @@ do_execsql_test func4-1.55 { SELECT tointeger(18446744073709551616 + 1); } {{}} ifcapable floatingpoint { + set highPrecision(2) [expr \ + {[db eval {SELECT toreal(-9223372036854775808 + 1);}] eq {{}}}] do_execsql_test func4-2.1 { SELECT toreal(NULL); } {{}} do_execsql_test func4-2.2 { @@ -354,18 +339,14 @@ SELECT toreal(9007199254740992 - 1); } {9007199254740991.0} do_execsql_test func4-2.45 { SELECT toreal(9007199254740992); } {9007199254740992.0} - if {$highPrecision(3)} { + if {$highPrecision(2)} { do_execsql_test func4-2.46 { SELECT toreal(9007199254740992 + 1); } {{}} - } else { - do_execsql_test func4-2.46 { - SELECT toreal(9007199254740992 + 1); - } {9007199254740992.0} } do_execsql_test func4-2.47 { SELECT toreal(9007199254740992 + 2); } {9007199254740994.0} do_execsql_test func4-2.48 { @@ -643,18 +624,14 @@ SELECT tointeger(toreal(9007199254740992 - 1)); } {9007199254740991} do_execsql_test func4-5.22 { SELECT tointeger(toreal(9007199254740992)); } {9007199254740992} - if {$highPrecision(3)} { + if {$highPrecision(2)} { do_execsql_test func4-5.23 { SELECT tointeger(toreal(9007199254740992 + 1)); } {{}} - } else { - do_execsql_test func4-5.23 { - SELECT tointeger(toreal(9007199254740992 + 1)); - } {9007199254740992} } do_execsql_test func4-5.24 { SELECT tointeger(toreal(9007199254740992 + 2)); } {9007199254740994} if {$highPrecision(1)} { Index: test/in4.test ================================================================== --- test/in4.test +++ test/in4.test @@ -456,18 +456,18 @@ ANALYZE sqlite_schema; } {} do_execsql_test 11.1 { SELECT * FROM t1 WHERE b IN (345, (SELECT 1 FROM t1 - WHERE b IN (coalesce(1,random())) + WHERE b IN (345 NOT GLOB 510) AND c GLOB 'abc*xyz')) AND c BETWEEN 'abc' AND 'xyz'; } {xyz 1 abcdefxyz 99} do_execsql_test 11.2 { EXPLAIN SELECT * FROM t1 WHERE b IN (345, (SELECT 1 FROM t1 - WHERE b IN (coalesce(1,random())) + WHERE b IN (345 NOT GLOB 510) AND c GLOB 'abc*xyz')) AND c BETWEEN 'abc' AND 'xyz'; } {/ SeekScan /} # 2021-06-25 ticket 6dcbfd11cf666e21 Index: test/sqllimits1.test ================================================================== --- test/sqllimits1.test +++ test/sqllimits1.test @@ -920,11 +920,11 @@ } {0 {}} do_catchsql_test sqllimits1-18.2 { INSERT INTO b1 VALUES(1), (2), (3), (4), (5), (6), (7), (8), (9), (10) UNION VALUES(11); -} {0 {}} +} {1 {too many terms in compound SELECT}} #------------------------------------------------------------------------- # reset_db ifcapable utf16 { Index: test/testrunner.tcl ================================================================== --- test/testrunner.tcl +++ test/testrunner.tcl @@ -60,29 +60,20 @@ $a0 status where SWITCHES are: --buildonly --dryrun - --explain --jobs NUMBER-OF-JOBS - --stop-on-coredump - --stop-on-error --zipvfs ZIPVFS-SOURCE-DIR -Special values for PERMUTATION that work with plain tclsh: - - list - show all allowed PERMUTATION arguments. - mdevtest - tests recommended prior to normal development check-ins. - release - full release test with various builds. - sdevtest - like mdevtest but using ASAN and UBSAN. - -Other PERMUTATION arguments must be run using testfixture, not tclsh: - +Interesting values for PERMUTATION are: + + veryquick - a fast subset of the tcl test scripts. This is the default. + full - all tcl test scripts. all - all tcl test scripts, plus a subset of test scripts rerun with various permutations. - full - all tcl test scripts. - veryquick - a fast subset of the tcl test scripts. This is the default. + release - full release test with various builds. If no PATTERN arguments are present, all tests specified by the PERMUTATION are run. Otherwise, each pattern is interpreted as a glob pattern. Only those tcl tests for which the final component of the filename matches at least one specified pattern are run. @@ -102,12 +93,10 @@ of sub-processes the test script uses to run tests. The "script" command outputs the script used to build a configuration. Add the "-msvc" option for a Windows-compatible script. For a list of available configurations enter "$a0 script help". - -Full documentation here: https://sqlite.org/src/doc/trunk/doc/testrunner.md }]] exit 1 } #------------------------------------------------------------------------- @@ -141,14 +130,10 @@ } return $ret } proc default_njob {} { - global env - if {[info exists env(NJOB)] && $env(NJOB)>=1} { - return $env(NJOB) - } set nCore [guess_number_of_cores] if {$nCore<=2} { set nHelper 1 } else { set nHelper [expr int($nCore*0.5)] @@ -171,13 +156,10 @@ set TRG(reporttime) 2000 set TRG(fuzztest) 0 ;# is the fuzztest option present. set TRG(zipvfs) "" ;# -zipvfs option, if any set TRG(buildonly) 0 ;# True if --buildonly option set TRG(dryrun) 0 ;# True if --dryrun option -set TRG(explain) 0 ;# True for the --explain option -set TRG(stopOnError) 0 ;# Stop running at first failure -set TRG(stopOnCore) 0 ;# Stop on a core-dump switch -nocase -glob -- $tcl_platform(os) { *darwin* { set TRG(platform) osx set TRG(make) make.sh @@ -468,16 +450,10 @@ if {$isLast} { usage } } elseif {($n>2 && [string match "$a*" --buildonly]) || $a=="-b"} { set TRG(buildonly) 1 } elseif {($n>2 && [string match "$a*" --dryrun]) || $a=="-d"} { set TRG(dryrun) 1 - } elseif {($n>2 && [string match "$a*" --explain]) || $a=="-e"} { - set TRG(explain) 1 - } elseif {[string match "$a*" --stop-on-error]} { - set TRG(stopOnError) 1 - } elseif {[string match "$a*" --stop-on-coredump]} { - set TRG(stopOnCore) 1 } else { usage } } else { lappend TRG(patternlist) [string map {% *} $a] @@ -856,21 +832,10 @@ } } } -# Check to ensure that the interpreter is a full-blown "testfixture" -# build and not just a "tclsh". If this is not the case, issue an -# error message and exit. -# -proc must_be_testfixture {} { - if {[lsearch [info commands] sqlite3_soft_heap_limit]<0} { - puts "Use testfixture, not tclsh, for these arguments." - exit 1 - } -} - proc add_jobs_from_cmdline {patternlist} { global TRG if {$TRG(zipvfs)!=""} { add_zipvfs_jobs @@ -882,32 +847,23 @@ } set first [lindex $patternlist 0] switch -- $first { all { - must_be_testfixture set patternlist [lrange $patternlist 1 end] set clist [trd_all_configs] foreach c $clist { add_tcl_jobs "" $c $patternlist } } mdevtest { - set config_set { - All-O0 - All-Debug - } - add_devtest_jobs $config_set [lrange $patternlist 1 end] + add_devtest_jobs {All-O0 All-Debug} [lrange $patternlist 1 end] } sdevtest { - set config_set { - All-Sanitize - All-Debug - } - add_devtest_jobs $config_set [lrange $patternlist 1 end] + add_devtest_jobs {All-Sanitize All-Debug} [lrange $patternlist 1 end] } release { set patternlist [lrange $patternlist 1 end] foreach b [trd_builds $TRG(platform)] { @@ -926,19 +882,11 @@ } } } } - list { - set allperm [array names ::testspec] - lappend allperm all mdevtest sdevtest release list - puts "Allowed values for the PERMUTATION argument: [lsort $allperm]" - exit 0 - } - default { - must_be_testfixture if {[info exists ::testspec($first)]} { add_tcl_jobs "" $first [lrange $patternlist 1 end] } else { add_tcl_jobs "" full $patternlist } @@ -998,18 +946,10 @@ if {[info exists TRG(reportlength)]} { puts -nonewline "[string repeat " " $TRG(reportlength)]\r" } puts "FAILED: $job(displayname) ($iJob)" set state "failed" - if {$TRG(stopOnError)} { - puts "OUTPUT: $O($iJob)" - exit 1 - } - if {$TRG(stopOnCore) && [string first {core dumped} $O($iJob)]>0} { - puts "OUTPUT: $O($iJob)" - exit 1 - } } set tm [clock_milliseconds] set jobtm [expr {$tm - $job(starttime)}] @@ -1066,18 +1006,13 @@ set fd [open [file join $dir $TRG(make)] w] puts $fd $script close $fd } - # Add a batch/shell file command to set the directory used for temp - # files to the test's working directory. Otherwise, tests that use - # large numbers of temp files (e.g. zipvfs), might generate temp - # filename collisions. - if {$TRG(platform)=="win"} { - set set_tmp_dir "SET SQLITE_TMPDIR=[file normalize $dir]" - } else { - set set_tmp_dir "export SQLITE_TMPDIR=\"[file normalize $dir]\"" + set job_cmd $job(cmd) + if {$TRG(platform)!="win"} { + set job_cmd "export SQLITE_TMPDIR=\"[file normalize $dir]\"\n$job_cmd" } if { $TRG(dryrun) } { mark_job_as_finished $job(jobid) "" done 0 @@ -1090,12 +1025,11 @@ } else { set pwd [pwd] cd $dir set fd [open $TRG(run) w] - puts $fd $set_tmp_dir - puts $fd $job(cmd) + puts $fd $job_cmd close $fd set fd [open "|$TRG(runcmd) 2>@1" r] cd $pwd fconfigure $fd -blocking false @@ -1207,44 +1141,17 @@ trdb eval { DELETE FROM jobs WHERE displaytype!='bld' } } } } -# Handle the --explain option. Provide a human-readable -# explanation of all the tests that are in the trdb database jobs -# table. -# -proc explain_layer {indent depid} { - global TRG - if {$TRG(buildonly)} { - set showtests 0 - } else { - set showtests 1 - } - trdb eval {SELECT jobid, displayname, displaytype, dirname - FROM jobs WHERE depid=$depid ORDER BY displayname} { - if {$displaytype=="bld"} { - puts "${indent}$displayname in $dirname" - explain_layer "${indent} " $jobid - } elseif {$showtests} { - puts "${indent}[lindex $displayname end]" - } - } -} -proc explain_tests {} { - explain_layer "" "" -} - sqlite3 trdb $TRG(dbname) trdb timeout $TRG(timeout) set tm [lindex [time { make_new_testset }] 0] -if {$TRG(explain)} { - explain_tests -} else { - if {$TRG(nJob)>1} { - puts "splitting work across $TRG(nJob) jobs" - } - puts "built testset in [expr $tm/1000]ms.." - handle_buildonly - run_testset -} +if {$TRG(nJob)>1} { + puts "splitting work across $TRG(nJob) jobs" +} +puts "built testset in [expr $tm/1000]ms.." + +handle_buildonly +run_testset trdb close +#puts [pwd] Index: test/testrunner_data.tcl ================================================================== --- test/testrunner_data.tcl +++ test/testrunner_data.tcl @@ -106,11 +106,10 @@ set build(Sanitize) { CC=clang -fsanitize=address,undefined -fno-sanitize-recover=undefined -DSQLITE_ENABLE_STAT4 -DSQLITE_OMIT_LOOKASIDE=1 -DCONFIG_SLOWDOWN_FACTOR=5.0 - -DSQLITE_ENABLE_RBU --enable-debug --enable-all } set build(Stdcall) { -DUSE_STDCALL=1 DELETED test/values.test Index: test/values.test ================================================================== --- test/values.test +++ /dev/null @@ -1,583 +0,0 @@ -# 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} - -#------------------------------------------------------------------------- -reset_db -do_execsql_test 6.0 { - CREATE TABLE t1(x); - INSERT INTO t1 VALUES('x'), ('y'); -} - -do_execsql_test 6.1 { - SELECT * FROM t1, (VALUES(1), (2)) -} {x 1 x 2 y 1 y 2} - -do_execsql_test 6.2 { - VALUES(CAST(44 AS REAL)),(55); -} {44.0 55} - -#------------------------------------------------------------------------ -do_execsql_test 7.1 { - WITH x1(a, b) AS ( - VALUES(1, 2), ('a', 'b') - ) - SELECT * FROM x1 one, x1 two -} { - 1 2 1 2 - 1 2 a b - a b 1 2 - a b a b -} - -#------------------------------------------------------------------------- -reset_db - -set VVV { - ( VALUES('a', 'b'), ('c', 'd'), (123, NULL) ) -} -set VVV2 { - ( - SELECT 'a' AS column1, 'b' AS column2 - UNION ALL SELECT 'c', 'd' UNION ALL SELECT 123, NULL - ) -} - -do_execsql_test 8.0 { - CREATE TABLE t1(x); - INSERT INTO t1 VALUES('d'), (NULL), (123) -} -foreach {tn q res} { - 1 "SELECT * FROM t1 LEFT JOIN VVV" { - d a b d c d d 123 {} - {} a b {} c d {} 123 {} - 123 a b 123 c d 123 123 {} - } - - 2 "SELECT * FROM t1 LEFT JOIN VVV ON (column1=x)" { - d {} {} - {} {} {} - 123 123 {} - } - - 3 "SELECT * FROM t1 RIGHT JOIN VVV" { - d a b d c d d 123 {} - {} a b {} c d {} 123 {} - 123 a b 123 c d 123 123 {} - } - - 4 "SELECT * FROM t1 RIGHT JOIN VVV ON (column1=x)" { - 123 123 {} - {} a b - {} c d - } - - 5 "SELECT * FROM t1 FULL OUTER JOIN VVV ON (column1=x)" { - d {} {} - {} {} {} - 123 123 {} - {} a b - {} c d - } - - 6 "SELECT count(*) FROM VVV" { 3 } - - 7 "SELECT (SELECT column1 FROM VVV)" { a } - - 8 "SELECT * FROM VVV UNION ALL SELECT * FROM VVV" { - a b c d 123 {} - a b c d 123 {} - } - - 9 "SELECT * FROM VVV INTERSECT SELECT * FROM VVV" { - 123 {} a b c d - } - - 10 "SELECT * FROM VVV eXCEPT SELECT * FROM VVV" { } - - 11 "SELECT * FROM VVV eXCEPT SELECT 'a', 'b'" { 123 {} c d } - -} { - set q1 [string map [list VVV $VVV] $q] - set q2 [string map [list VVV $VVV2] $q] - set q3 "WITH VVV AS $VVV $q" - - do_execsql_test 8.1.$tn.1 $q1 $res - do_execsql_test 8.1.$tn.2 $q2 $res - do_execsql_test 8.1.$tn.3 $q3 $res -} - -#------------------------------------------------------------------------- -reset_db - -do_execsql_test 9.1 { - VALUES(456), (123), (NULL) UNION ALL SELECT 122 ORDER BY 1 -} { {} 122 123 456 } - -do_execsql_test 9.2 { - VALUES (1, 2), (3, 4), ( - ( SELECT column1 FROM ( VALUES (5, 6), (7, 8) ) ), - ( SELECT max(column2) FROM ( VALUES (5, 1), (7, 6) ) ) - ) -} { 1 2 3 4 5 6 } - -do_execsql_test 10.1 { - CREATE TABLE a2(a, b, c DEFAULT 'xyz'); -} -do_execsql_test 10.2 { - INSERT INTO a2(a) VALUES(3),(4); -} - -#------------------------------------------------------------------------- -reset_db -ifcapable fts5 { - do_execsql_test 11.0 { - CREATE VIRTUAL TABLE ft USING fts3(x); - } - do_execsql_test 11.1 { - INSERT INTO ft VALUES('one'), ('two'); - } -} - -#------------------------------------------------------------------------- -reset_db -do_execsql_test 12.0 { - CREATE TABLE t1(a, b); -} -do_execsql_test 12.1 { - INSERT INTO t1 SELECT 1, 2 UNION ALL VALUES(3, 4), (5, 6); -} -do_execsql_test 12.2 { - SELECT * FROM t1 -} {1 2 3 4 5 6} - -#------------------------------------------------------------------------- -reset_db -do_execsql_test 13.0 { - CREATE TABLE t1(x); - INSERT INTO t1 VALUES('xyz'); - - SELECT ( - VALUES( (max(substr('abc', 1, 1), x)) ), - (123), - (456) - ) - FROM t1; -} {xyz} - -do_catchsql_test 13.1 { - VALUES(300), (zeroblob(300) OVER win); -} {1 {zeroblob() may not be used as a window function}} - -#-------------------------------------------------------------------------- -reset_db -do_execsql_test 14.1 { - PRAGMA encoding = utf16; - CREATE TABLE t1(a, b); -} {} - -db close -sqlite3 db test.db - -do_execsql_test 14.2 { - INSERT INTO t1 VALUES - (17, 'craft'), - (16, 'urtlek' IN(1,2,3)); -} - -#-------------------------------------------------------------------------- -# -reset_db -do_eqp_test 15.1 { - VALUES(1),(2),(3),(4),(5); -} { - QUERY PLAN - `--SCAN 5-ROW VALUES CLAUSE -} -do_execsql_test 15.2 { - CREATE TABLE t1(a,b); -} -do_eqp_test 15.3 { - INSERT INTO t1 VALUES - (1,2),(3,4),(7,8); -} { - QUERY PLAN - `--SCAN 3-ROW VALUES CLAUSE -} -do_eqp_test 15.4 { - INSERT INTO t1 VALUES - (1,2),(3,4),(7,8), - (5,row_number()OVER()); -} { - QUERY PLAN - `--COMPOUND QUERY - |--LEFT-MOST SUBQUERY - | `--SCAN 3-ROW VALUES CLAUSE - `--UNION ALL - |--CO-ROUTINE (subquery-xxxxxx) - | `--SCAN CONSTANT ROW - `--SCAN (subquery-xxxxxx) -} -do_eqp_test 15.5 { - SELECT * FROM (VALUES(1),(2),(3),(4),(5),(6)), (VALUES('a'),('b'),('c')); -} { - QUERY PLAN - |--SCAN 6-ROW VALUES CLAUSE - `--SCAN 3-ROW VALUES CLAUSE -} -do_execsql_test 15.6 { - CREATE TABLE t2(x,y); -} -do_eqp_test 15.7 { - SELECT * FROM t2 UNION ALL VALUES(1,2),(3,4),(5,6),(7,8); -} { - QUERY PLAN - `--COMPOUND QUERY - |--LEFT-MOST SUBQUERY - | `--SCAN t2 - `--UNION ALL - `--SCAN 4-ROW VALUES CLAUSE -} - -#-------------------------------------------------------------------------- -# The VALUES-as-coroutine optimization can be applied to later rows of -# a VALUES clause even if earlier rows do not qualify. -# -reset_db -do_execsql_test 16.1 { - CREATE TABLE t1(a,b); -} -do_execsql_test 16.2 { - BEGIN; - INSERT INTO t1 VALUES(1,2),(3,4),(5,6), - (7,row_number()OVER()), - (9,10), (11,12), (13,14), (15,16); - SELECT * FROM t1 ORDER BY a, b; - ROLLBACK; -} {1 2 3 4 5 6 7 1 9 10 11 12 13 14 15 16} -do_eqp_test 16.3 { - INSERT INTO t1 VALUES(1,2),(3,4),(5,6), - (7,row_number()OVER()), - (9,10), (11,12), (13,14), (15,16); -} { - QUERY PLAN - `--COMPOUND QUERY - |--LEFT-MOST SUBQUERY - | `--SCAN 3-ROW VALUES CLAUSE - |--UNION ALL - | |--CO-ROUTINE (subquery-xxxxxx) - | | `--SCAN CONSTANT ROW - | `--SCAN (subquery-xxxxxx) - `--UNION ALL - `--SCAN 4-ROW VALUES CLAUSE -} -do_execsql_test 16.4 { - BEGIN; - INSERT INTO t1 VALUES - (1,row_number()OVER()), - (2,3), (4,5), (6,7); - SELECT * FROM t1 ORDER BY a, b; - ROLLBACK; -} {1 1 2 3 4 5 6 7} -do_eqp_test 16.5 { - INSERT INTO t1 VALUES - (1,row_number()OVER()), - (2,3), (4,5), (6,7); -} { - QUERY PLAN - `--COMPOUND QUERY - |--LEFT-MOST SUBQUERY - | |--CO-ROUTINE (subquery-xxxxxx) - | | `--SCAN CONSTANT ROW - | `--SCAN (subquery-xxxxxx) - `--UNION ALL - `--SCAN 3-ROW VALUES CLAUSE -} -do_execsql_test 16.6 { - BEGIN; - INSERT INTO t1 VALUES - (1,2),(3,4), - (5,row_number()OVER()), - (7,8),(9,10),(11,12), - (13,row_number()OVER()), - (15,16),(17,18),(19,20),(21,22); - SELECT * FROM t1 ORDER BY a, b; - ROLLBACK; -} { 1 2 3 4 5 1 7 8 9 10 11 12 13 1 15 16 17 18 19 20 21 22} -do_eqp_test 16.7 { - INSERT INTO t1 VALUES - (1,2),(3,4), - (5,row_number()OVER()), - (7,8),(9,10),(11,12), - (13,row_number()OVER()), - (15,16),(17,18),(19,20),(21,22); -} { - QUERY PLAN - `--COMPOUND QUERY - |--LEFT-MOST SUBQUERY - | `--SCAN 2-ROW VALUES CLAUSE - |--UNION ALL - | |--CO-ROUTINE (subquery-xxxxxx) - | | `--SCAN CONSTANT ROW - | `--SCAN (subquery-xxxxxx) - |--UNION ALL - | `--SCAN 3-ROW VALUES CLAUSE - |--UNION ALL - | |--CO-ROUTINE (subquery-xxxxxx) - | | `--SCAN CONSTANT ROW - | `--SCAN (subquery-xxxxxx) - `--UNION ALL - `--SCAN 4-ROW VALUES CLAUSE -} - -finish_test DELETED test/valuesfault.test Index: test/valuesfault.test ================================================================== --- test/valuesfault.test +++ /dev/null @@ -1,37 +0,0 @@ -# 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 Index: test/whereL.test ================================================================== --- test/whereL.test +++ test/whereL.test @@ -47,37 +47,10 @@ QUERY PLAN |--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (a=?) |--SEARCH t2 USING INDEX sqlite_autoindex_t2_1 (a=?) `--SCAN t3 } -do_eqp_test 121 { - SELECT * FROM t1, t2, t3 - WHERE t1.a=t2.a AND t2.a=t3.j AND t3.j=abs(5) - ORDER BY t1.a; -} { - QUERY PLAN - |--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (a=?) - |--SEARCH t2 USING INDEX sqlite_autoindex_t2_1 (a=?) - `--SCAN t3 -} - -# The sqlite3ExprIsConstant() routine does not believe that -# the expression "coalesce(5,random())" is constant. So the -# optimization does not apply in this case. -# -sqlite3_create_function db -do_eqp_test 122 { - SELECT * FROM t1, t2, t3 - WHERE t1.a=t2.a AND t2.a=t3.j AND t3.j=coalesce(5,random()) - ORDER BY t1.a; -} { - QUERY PLAN - |--SCAN t3 - |--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (a=?) - |--SEARCH t2 USING INDEX sqlite_autoindex_t2_1 (a=?) - `--USE TEMP B-TREE FOR ORDER BY -} # Constant propagation in the face of collating sequences: # do_execsql_test 200 { CREATE TABLE c3(x COLLATE binary, y COLLATE nocase, z COLLATE binary); Index: tool/lemon.c ================================================================== --- tool/lemon.c +++ tool/lemon.c @@ -57,86 +57,10 @@ ** as C evolves ever closer to Ada.... To work around the latest problems ** we have to define the following variant of strlen(). */ #define lemonStrlen(X) ((int)strlen(X)) -/* -** Header on the linked list of memory allocations. -*/ -typedef struct MemChunk MemChunk; -struct MemChunk { - MemChunk *pNext; - size_t sz; - /* Actually memory follows */ -}; - -/* -** Global linked list of all memory allocations. -*/ -static MemChunk *memChunkList = 0; - -/* -** Wrappers around malloc(), calloc(), realloc() and free(). -** -** All memory allocations are kept on a doubly-linked list. The -** lemon_free_all() function can be called prior to exit to clean -** up any memory leaks. -** -** This is not necessary. But compilers and getting increasingly -** fussy about memory leaks, even in command-line programs like Lemon -** where they do not matter. So this code is provided to hush the -** warnings. -*/ -static void *lemon_malloc(size_t nByte){ - MemChunk *p; - if( nByte<0 ) return 0; - p = malloc( nByte + sizeof(MemChunk) ); - if( p==0 ){ - fprintf(stderr, "Out of memory. Failed to allocate %lld bytes.\n", - (long long int)nByte); - exit(1); - } - p->pNext = memChunkList; - p->sz = nByte; - memChunkList = p; - return (void*)&p[1]; -} -static void *lemon_calloc(size_t nElem, size_t sz){ - void *p = lemon_malloc(nElem*sz); - memset(p, 0, nElem*sz); - return p; -} -static void lemon_free(void *pOld){ - if( pOld ){ - MemChunk *p = (MemChunk*)pOld; - p--; - memset(pOld, 0, p->sz); - } -} -static void *lemon_realloc(void *pOld, size_t nNew){ - void *pNew; - MemChunk *p; - if( pOld==0 ) return lemon_malloc(nNew); - p = (MemChunk*)pOld; - p--; - if( p->sz>=nNew ) return pOld; - pNew = lemon_malloc( nNew ); - memcpy(pNew, pOld, p->sz); - return pNew; -} - -/* Free all outstanding memory allocations. -** Do this right before exiting. -*/ -static void lemon_free_all(void){ - while( memChunkList ){ - MemChunk *pNext = memChunkList->pNext; - free( memChunkList ); - memChunkList = pNext; - } -} - /* ** Compilers are starting to complain about the use of sprintf() and strcpy(), ** saying they are unsafe. So we define our own versions of those routines too. ** ** There are three routines here: lemon_sprintf(), lemon_vsprintf(), and @@ -571,11 +495,11 @@ struct action *newaction; if( actionfreelist==0 ){ int i; int amt = 100; - actionfreelist = (struct action *)lemon_calloc(amt, sizeof(struct action)); + actionfreelist = (struct action *)calloc(amt, sizeof(struct action)); if( actionfreelist==0 ){ fprintf(stderr,"Unable to allocate memory for a new parser action."); exit(1); } for(i=0; iaAction[N].lookahead) /* Free all memory associated with the given acttab */ void acttab_free(acttab *p){ - lemon_free( p->aAction ); - lemon_free( p->aLookahead ); - lemon_free( p ); + free( p->aAction ); + free( p->aLookahead ); + free( p ); } /* Allocate a new acttab structure */ acttab *acttab_alloc(int nsymbol, int nterminal){ - acttab *p = (acttab *) lemon_calloc( 1, sizeof(*p) ); + acttab *p = (acttab *) calloc( 1, sizeof(*p) ); if( p==0 ){ fprintf(stderr,"Unable to allocate memory for a new acttab."); exit(1); } memset(p, 0, sizeof(*p)); @@ -716,11 +640,11 @@ ** state. */ void acttab_action(acttab *p, int lookahead, int action){ if( p->nLookahead>=p->nLookaheadAlloc ){ p->nLookaheadAlloc += 25; - p->aLookahead = (struct lookahead_action *) lemon_realloc( p->aLookahead, + p->aLookahead = (struct lookahead_action *) realloc( p->aLookahead, sizeof(p->aLookahead[0])*p->nLookaheadAlloc ); if( p->aLookahead==0 ){ fprintf(stderr,"malloc failed\n"); exit(1); } @@ -766,11 +690,11 @@ */ n = p->nsymbol + 1; if( p->nAction + n >= p->nActionAlloc ){ int oldAlloc = p->nActionAlloc; p->nActionAlloc = p->nAction + n + p->nActionAlloc + 20; - p->aAction = (struct lookahead_action *) lemon_realloc( p->aAction, + p->aAction = (struct lookahead_action *) realloc( p->aAction, sizeof(p->aAction[0])*p->nActionAlloc); if( p->aAction==0 ){ fprintf(stderr,"malloc failed\n"); exit(1); } @@ -1388,11 +1312,11 @@ static struct config *basis = 0; /* Top of list of basis configs */ static struct config **basisend = 0; /* End of list of basis configs */ /* Return a pointer to a new configuration */ PRIVATE struct config *newconfig(void){ - return (struct config*)lemon_calloc(1, sizeof(struct config)); + return (struct config*)calloc(1, sizeof(struct config)); } /* The configuration "old" is no longer used */ PRIVATE void deleteconfig(struct config *old) { @@ -1604,23 +1528,23 @@ ** Add the macro defined to the azDefine array. */ static void handle_D_option(char *z){ char **paz; nDefine++; - azDefine = (char **) lemon_realloc(azDefine, sizeof(azDefine[0])*nDefine); + azDefine = (char **) realloc(azDefine, sizeof(azDefine[0])*nDefine); if( azDefine==0 ){ fprintf(stderr,"out of memory\n"); exit(1); } - bDefineUsed = (char*)lemon_realloc(bDefineUsed, nDefine); + bDefineUsed = (char*)realloc(bDefineUsed, nDefine); if( bDefineUsed==0 ){ fprintf(stderr,"out of memory\n"); exit(1); } bDefineUsed[nDefine-1] = 0; paz = &azDefine[nDefine-1]; - *paz = (char *) lemon_malloc( lemonStrlen(z)+1 ); + *paz = (char *) malloc( lemonStrlen(z)+1 ); if( *paz==0 ){ fprintf(stderr,"out of memory\n"); exit(1); } lemon_strcpy(*paz, z); @@ -1630,21 +1554,21 @@ /* Rember the name of the output directory */ static char *outputDir = NULL; static void handle_d_option(char *z){ - outputDir = (char *) lemon_malloc( lemonStrlen(z)+1 ); + outputDir = (char *) malloc( lemonStrlen(z)+1 ); if( outputDir==0 ){ fprintf(stderr,"out of memory\n"); exit(1); } lemon_strcpy(outputDir, z); } static char *user_templatename = NULL; static void handle_T_option(char *z){ - user_templatename = (char *) lemon_malloc( lemonStrlen(z)+1 ); + user_templatename = (char *) malloc( lemonStrlen(z)+1 ); if( user_templatename==0 ){ memory_error(); } lemon_strcpy(user_templatename, z); } @@ -1877,11 +1801,10 @@ fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict); } /* return 0 on success, 1 on failure. */ exitcode = ((lem.errorcnt > 0) || (lem.nconflict > 0)) ? 1 : 0; - lemon_free_all(); exit(exitcode); return (exitcode); } /******************** From the file "msort.c" *******************************/ /* @@ -2466,11 +2389,11 @@ } break; case IN_RHS: if( x[0]=='.' ){ struct rule *rp; - rp = (struct rule *)lemon_calloc( sizeof(struct rule) + + rp = (struct rule *)calloc( sizeof(struct rule) + sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs, 1); if( rp==0 ){ ErrorMsg(psp->filename,psp->tokenlineno, "Can't allocate enough memory for this rule."); psp->errorcnt++; @@ -2518,21 +2441,21 @@ } }else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 && ISUPPER(x[1]) ){ struct symbol *msp = psp->rhs[psp->nrhs-1]; if( msp->type!=MULTITERMINAL ){ struct symbol *origsp = msp; - msp = (struct symbol *) lemon_calloc(1,sizeof(*msp)); + msp = (struct symbol *) calloc(1,sizeof(*msp)); memset(msp, 0, sizeof(*msp)); msp->type = MULTITERMINAL; msp->nsubsym = 1; - msp->subsym = (struct symbol**)lemon_calloc(1,sizeof(struct symbol*)); + msp->subsym = (struct symbol **) calloc(1,sizeof(struct symbol*)); msp->subsym[0] = origsp; msp->name = origsp->name; psp->rhs[psp->nrhs-1] = msp; } msp->nsubsym++; - msp->subsym = (struct symbol **) lemon_realloc(msp->subsym, + msp->subsym = (struct symbol **) realloc(msp->subsym, sizeof(struct symbol*)*msp->nsubsym); msp->subsym[msp->nsubsym-1] = Symbol_new(&x[1]); if( ISLOWER(x[1]) || ISLOWER(msp->subsym[0]->name[0]) ){ ErrorMsg(psp->filename,psp->tokenlineno, "Cannot form a compound containing a non-terminal"); @@ -2744,11 +2667,11 @@ } lemon_sprintf(zLine, "#line %d ", psp->tokenlineno); nLine = lemonStrlen(zLine); n += nLine + lemonStrlen(psp->filename) + nBack; } - *psp->declargslot = (char *) lemon_realloc(*psp->declargslot, n); + *psp->declargslot = (char *) realloc(*psp->declargslot, n); zBuf = *psp->declargslot + nOld; if( addLineMacro ){ if( nOld && zBuf[-1]!='\n' ){ *(zBuf++) = '\n'; } @@ -2858,11 +2781,11 @@ if( x[0]=='.' ){ psp->state = WAITING_FOR_DECL_OR_RULE; }else if( ISUPPER(x[0]) || ((x[0]=='|' || x[0]=='/') && ISUPPER(x[1])) ){ struct symbol *msp = psp->tkclass; msp->nsubsym++; - msp->subsym = (struct symbol **) lemon_realloc(msp->subsym, + msp->subsym = (struct symbol **) realloc(msp->subsym, sizeof(struct symbol*)*msp->nsubsym); if( !ISUPPER(x[0]) ) x++; msp->subsym[msp->nsubsym-1] = Symbol_new(x); }else{ ErrorMsg(psp->filename, psp->tokenlineno, @@ -3073,22 +2996,22 @@ return; } fseek(fp,0,2); filesize = ftell(fp); rewind(fp); - filebuf = (char *)lemon_malloc( filesize+1 ); + filebuf = (char *)malloc( filesize+1 ); if( filesize>100000000 || filebuf==0 ){ ErrorMsg(ps.filename,0,"Input file too large."); - lemon_free(filebuf); + free(filebuf); gp->errorcnt++; fclose(fp); return; } if( fread(filebuf,1,filesize,fp)!=filesize ){ ErrorMsg(ps.filename,0,"Can't read in all %d bytes of this file.", filesize); - lemon_free(filebuf); + free(filebuf); gp->errorcnt++; fclose(fp); return; } fclose(fp); @@ -3196,11 +3119,11 @@ *cp = 0; /* Null terminate the token */ parseonetoken(&ps); /* Parse the token */ *cp = (char)c; /* Restore the buffer */ cp = nextcp; } - lemon_free(filebuf); /* Release the buffer after parsing */ + free(filebuf); /* Release the buffer after parsing */ gp->rule = ps.firstrule; gp->errorcnt = ps.errorcnt; } /*************************** From the file "plink.c" *********************/ /* @@ -3214,11 +3137,11 @@ struct plink *newlink; if( plink_freelist==0 ){ int i; int amt = 100; - plink_freelist = (struct plink *)lemon_calloc( amt, sizeof(struct plink) ); + plink_freelist = (struct plink *)calloc( amt, sizeof(struct plink) ); if( plink_freelist==0 ){ fprintf(stderr, "Unable to allocate memory for a new follow-set propagation link.\n"); exit(1); } @@ -3267,11 +3190,13 @@ /*********************** From the file "report.c" **************************/ /* ** Procedures for generating reports and tables in the LEMON parser generator. */ -/* Generate a filename with the given suffix. +/* Generate a filename with the given suffix. Space to hold the +** name comes from malloc() and must be freed by the calling +** function. */ PRIVATE char *file_makename(struct lemon *lemp, const char *suffix) { char *name; char *cp; @@ -3284,11 +3209,11 @@ } sz = lemonStrlen(filename); sz += lemonStrlen(suffix); if( outputDir ) sz += lemonStrlen(outputDir) + 1; sz += 5; - name = (char*)lemon_malloc( sz ); + name = (char*)malloc( sz ); if( name==0 ){ fprintf(stderr,"Can't allocate space for a filename.\n"); exit(1); } name[0] = 0; @@ -3311,11 +3236,11 @@ const char *suffix, const char *mode ){ FILE *fp; - if( lemp->outname ) lemon_free(lemp->outname); + if( lemp->outname ) free(lemp->outname); lemp->outname = file_makename(lemp, suffix); fp = fopen(lemp->outname,mode); if( fp==0 && *mode=='w' ){ fprintf(stderr,"Can't open file \"%s\".\n",lemp->outname); lemp->errorcnt++; @@ -3627,18 +3552,18 @@ cp = strrchr(argv0,'/'); #endif if( cp ){ c = *cp; *cp = 0; - path = (char *)lemon_malloc( lemonStrlen(argv0) + lemonStrlen(name) + 2 ); + path = (char *)malloc( lemonStrlen(argv0) + lemonStrlen(name) + 2 ); if( path ) lemon_sprintf(path,"%s/%s",argv0,name); *cp = c; }else{ pathlist = getenv("PATH"); if( pathlist==0 ) pathlist = ".:/bin:/usr/bin"; - pathbuf = (char *) lemon_malloc( lemonStrlen(pathlist) + 1 ); - path = (char *)lemon_malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 ); + pathbuf = (char *) malloc( lemonStrlen(pathlist) + 1 ); + path = (char *)malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 ); if( (pathbuf != 0) && (path!=0) ){ pathbufptr = pathbuf; lemon_strcpy(pathbuf, pathlist); while( *pathbuf ){ cp = strchr(pathbuf,':'); @@ -3650,11 +3575,11 @@ if( c==0 ) pathbuf[0] = 0; else pathbuf = &cp[1]; if( access(path,modemask)==0 ) break; } } - lemon_free(pathbufptr); + free(pathbufptr); } return path; } /* Given an action, compute the integer value for that action @@ -3781,11 +3706,11 @@ in = fopen(tpltname,"rb"); if( in==0 ){ fprintf(stderr,"Can't open the template file \"%s\".\n",tpltname); lemp->errorcnt++; } - lemon_free(toFree); + free(toFree); return in; } /* Print a #line directive line to the output file. */ PRIVATE void tplt_linedir(FILE *out, int lineno, char *filename) @@ -3910,11 +3835,11 @@ } n = lemonStrlen(zText); } if( (int) (n+sizeof(zInt)*2+used) >= alloced ){ alloced = n + sizeof(zInt)*2 + used + 200; - z = (char *) lemon_realloc(z, alloced); + z = (char *) realloc(z, alloced); } if( z==0 ) return empty; while( n-- > 0 ){ c = *(zText++); if( c=='%' && n>0 && zText[0]=='d' ){ @@ -4200,11 +4125,11 @@ unsigned hash; /* For hashing the name of a type */ const char *name; /* Name of the parser */ /* Allocate and initialize types[] and allocate stddt[] */ arraysize = lemp->nsymbol * 2; - types = (char**)lemon_calloc( arraysize, sizeof(char*) ); + types = (char**)calloc( arraysize, sizeof(char*) ); if( types==0 ){ fprintf(stderr,"Out of memory.\n"); exit(1); } for(i=0; isymbols[i]; if( sp->datatype==0 ) continue; len = lemonStrlen(sp->datatype); if( len>maxdtlength ) maxdtlength = len; } - stddt = (char*)lemon_malloc( maxdtlength*2 + 1 ); + stddt = (char*)malloc( maxdtlength*2 + 1 ); if( stddt==0 ){ fprintf(stderr,"Out of memory.\n"); exit(1); } @@ -4266,11 +4191,11 @@ hash++; if( hash>=(unsigned)arraysize ) hash = 0; } if( types[hash]==0 ){ sp->dtnum = hash + 1; - types[hash] = (char*)lemon_malloc( lemonStrlen(stddt)+1 ); + types[hash] = (char*)malloc( lemonStrlen(stddt)+1 ); if( types[hash]==0 ){ fprintf(stderr,"Out of memory.\n"); exit(1); } lemon_strcpy(types[hash],stddt); @@ -4288,17 +4213,17 @@ fprintf(out," int yyinit;\n"); lineno++; fprintf(out," %sTOKENTYPE yy0;\n",name); lineno++; for(i=0; ierrsym && lemp->errsym->useCnt ){ fprintf(out," int yy%d;\n",lemp->errsym->dtnum); lineno++; } - lemon_free(stddt); - lemon_free(types); + free(stddt); + free(types); fprintf(out,"} YYMINORTYPE;\n"); lineno++; *plineno = lineno; } /* @@ -4523,11 +4448,11 @@ /* Generate the include code, if any */ tplt_print(out,lemp,lemp->include,&lineno); if( mhflag ){ char *incName = file_makename(lemp, ".h"); fprintf(out,"#include \"%s\"\n", incName); lineno++; - lemon_free(incName); + free(incName); } tplt_xfer(lemp->name,in,out,&lineno); /* Generate #defines for all tokens */ if( lemp->tokenprefix ) prefix = lemp->tokenprefix; @@ -4630,11 +4555,11 @@ /* Compute the action table, but do not output it yet. The action ** table must be computed before generating the YYNSTATE macro because ** we need to know how many states can be eliminated. */ - ax = (struct axset *) lemon_calloc(lemp->nxstate*2, sizeof(ax[0])); + ax = (struct axset *) calloc(lemp->nxstate*2, sizeof(ax[0])); if( ax==0 ){ fprintf(stderr,"malloc failed\n"); exit(1); } for(i=0; inxstate; i++){ @@ -4688,11 +4613,11 @@ i, stp->statenum, ax[i].isTkn ? "Token" : "Var ", ax[i].nAction, pActtab->nAction, nn); } #endif } - lemon_free(ax); + free(ax); /* Mark rules that are actually used for reduce actions after all ** optimizations have been applied */ for(rp=lemp->rule; rp; rp=rp->next) rp->doesReduce = LEMON_FALSE; @@ -5314,21 +5239,21 @@ } /* Allocate a new set */ char *SetNew(void){ char *s; - s = (char*)lemon_calloc( size, 1); + s = (char*)calloc( size, 1); if( s==0 ){ memory_error(); } return s; } /* Deallocate a set */ void SetFree(char *s) { - lemon_free(s); + free(s); } /* Add a new element to the set. Return TRUE if the element was added ** and FALSE if it was already there. */ int SetAdd(char *s, int e) @@ -5383,11 +5308,11 @@ const char *z; char *cpy; if( y==0 ) return 0; z = Strsafe_find(y); - if( z==0 && (cpy=(char *)lemon_malloc( lemonStrlen(y)+1 ))!=0 ){ + if( z==0 && (cpy=(char *)malloc( lemonStrlen(y)+1 ))!=0 ){ lemon_strcpy(cpy,y); z = cpy; Strsafe_insert(z); } MemoryCheck(z); @@ -5419,17 +5344,17 @@ static struct s_x1 *x1a; /* Allocate a new associative array */ void Strsafe_init(void){ if( x1a ) return; - x1a = (struct s_x1*)lemon_malloc( sizeof(struct s_x1) ); + x1a = (struct s_x1*)malloc( sizeof(struct s_x1) ); if( x1a ){ x1a->size = 1024; x1a->count = 0; - x1a->tbl = (x1node*)lemon_calloc(1024, sizeof(x1node) + sizeof(x1node*)); + x1a->tbl = (x1node*)calloc(1024, sizeof(x1node) + sizeof(x1node*)); if( x1a->tbl==0 ){ - lemon_free(x1a); + free(x1a); x1a = 0; }else{ int i; x1a->ht = (x1node**)&(x1a->tbl[1024]); for(i=0; i<1024; i++) x1a->ht[i] = 0; @@ -5460,11 +5385,11 @@ /* Need to make the hash table bigger */ int i,arrSize; struct s_x1 array; array.size = arrSize = x1a->size*2; array.count = x1a->count; - array.tbl = (x1node*)lemon_calloc(arrSize, sizeof(x1node)+sizeof(x1node*)); + array.tbl = (x1node*)calloc(arrSize, sizeof(x1node) + sizeof(x1node*)); if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ array.ht = (x1node**)&(array.tbl[arrSize]); for(i=0; icount; i++){ x1node *oldnp, *newnp; @@ -5475,11 +5400,11 @@ newnp->next = array.ht[h]; newnp->data = oldnp->data; newnp->from = &(array.ht[h]); array.ht[h] = newnp; } - /* lemon_free(x1a->tbl); // This program was originally for 16-bit machines. + /* free(x1a->tbl); // This program was originally for 16-bit machines. ** Don't worry about freeing memory on modern platforms. */ *x1a = array; } /* Insert the new data */ h = ph & (x1a->size-1); @@ -5516,11 +5441,11 @@ { struct symbol *sp; sp = Symbol_find(x); if( sp==0 ){ - sp = (struct symbol *)lemon_calloc(1, sizeof(struct symbol) ); + sp = (struct symbol *)calloc(1, sizeof(struct symbol) ); MemoryCheck(sp); sp->name = Strsafe(x); sp->type = ISUPPER(*x) ? TERMINAL : NONTERMINAL; sp->rule = 0; sp->fallback = 0; @@ -5587,17 +5512,17 @@ static struct s_x2 *x2a; /* Allocate a new associative array */ void Symbol_init(void){ if( x2a ) return; - x2a = (struct s_x2*)lemon_malloc( sizeof(struct s_x2) ); + x2a = (struct s_x2*)malloc( sizeof(struct s_x2) ); if( x2a ){ x2a->size = 128; x2a->count = 0; - x2a->tbl = (x2node*)lemon_calloc(128, sizeof(x2node) + sizeof(x2node*)); + x2a->tbl = (x2node*)calloc(128, sizeof(x2node) + sizeof(x2node*)); if( x2a->tbl==0 ){ - lemon_free(x2a); + free(x2a); x2a = 0; }else{ int i; x2a->ht = (x2node**)&(x2a->tbl[128]); for(i=0; i<128; i++) x2a->ht[i] = 0; @@ -5628,11 +5553,11 @@ /* Need to make the hash table bigger */ int i,arrSize; struct s_x2 array; array.size = arrSize = x2a->size*2; array.count = x2a->count; - array.tbl = (x2node*)lemon_calloc(arrSize, sizeof(x2node)+sizeof(x2node*)); + array.tbl = (x2node*)calloc(arrSize, sizeof(x2node) + sizeof(x2node*)); if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ array.ht = (x2node**)&(array.tbl[arrSize]); for(i=0; icount; i++){ x2node *oldnp, *newnp; @@ -5644,11 +5569,11 @@ newnp->key = oldnp->key; newnp->data = oldnp->data; newnp->from = &(array.ht[h]); array.ht[h] = newnp; } - /* lemon_free(x2a->tbl); // This program was originally written for 16-bit + /* free(x2a->tbl); // This program was originally written for 16-bit ** machines. Don't worry about freeing this trivial amount of memory ** on modern platforms. Just leak it. */ *x2a = array; } /* Insert the new data */ @@ -5705,11 +5630,11 @@ { struct symbol **array; int i,arrSize; if( x2a==0 ) return 0; arrSize = x2a->count; - array = (struct symbol **)lemon_calloc(arrSize, sizeof(struct symbol *)); + array = (struct symbol **)calloc(arrSize, sizeof(struct symbol *)); if( array ){ for(i=0; itbl[i].data; } return array; } @@ -5753,11 +5678,11 @@ /* Allocate a new state structure */ struct state *State_new() { struct state *newstate; - newstate = (struct state *)lemon_calloc(1, sizeof(struct state) ); + newstate = (struct state *)calloc(1, sizeof(struct state) ); MemoryCheck(newstate); return newstate; } /* There is one instance of the following structure for each @@ -5786,17 +5711,17 @@ static struct s_x3 *x3a; /* Allocate a new associative array */ void State_init(void){ if( x3a ) return; - x3a = (struct s_x3*)lemon_malloc( sizeof(struct s_x3) ); + x3a = (struct s_x3*)malloc( sizeof(struct s_x3) ); if( x3a ){ x3a->size = 128; x3a->count = 0; - x3a->tbl = (x3node*)lemon_calloc(128, sizeof(x3node) + sizeof(x3node*)); + x3a->tbl = (x3node*)calloc(128, sizeof(x3node) + sizeof(x3node*)); if( x3a->tbl==0 ){ - lemon_free(x3a); + free(x3a); x3a = 0; }else{ int i; x3a->ht = (x3node**)&(x3a->tbl[128]); for(i=0; i<128; i++) x3a->ht[i] = 0; @@ -5827,11 +5752,11 @@ /* Need to make the hash table bigger */ int i,arrSize; struct s_x3 array; array.size = arrSize = x3a->size*2; array.count = x3a->count; - array.tbl = (x3node*)lemon_calloc(arrSize, sizeof(x3node)+sizeof(x3node*)); + array.tbl = (x3node*)calloc(arrSize, sizeof(x3node) + sizeof(x3node*)); if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ array.ht = (x3node**)&(array.tbl[arrSize]); for(i=0; icount; i++){ x3node *oldnp, *newnp; @@ -5843,11 +5768,11 @@ newnp->key = oldnp->key; newnp->data = oldnp->data; newnp->from = &(array.ht[h]); array.ht[h] = newnp; } - lemon_free(x3a->tbl); + free(x3a->tbl); *x3a = array; } /* Insert the new data */ h = ph & (x3a->size-1); np = &(x3a->tbl[x3a->count++]); @@ -5884,11 +5809,11 @@ { struct state **array; int i,arrSize; if( x3a==0 ) return 0; arrSize = x3a->count; - array = (struct state **)lemon_calloc(arrSize, sizeof(struct state *)); + array = (struct state **)calloc(arrSize, sizeof(struct state *)); if( array ){ for(i=0; itbl[i].data; } return array; } @@ -5926,17 +5851,17 @@ static struct s_x4 *x4a; /* Allocate a new associative array */ void Configtable_init(void){ if( x4a ) return; - x4a = (struct s_x4*)lemon_malloc( sizeof(struct s_x4) ); + x4a = (struct s_x4*)malloc( sizeof(struct s_x4) ); if( x4a ){ x4a->size = 64; x4a->count = 0; - x4a->tbl = (x4node*)lemon_calloc(64, sizeof(x4node) + sizeof(x4node*)); + x4a->tbl = (x4node*)calloc(64, sizeof(x4node) + sizeof(x4node*)); if( x4a->tbl==0 ){ - lemon_free(x4a); + free(x4a); x4a = 0; }else{ int i; x4a->ht = (x4node**)&(x4a->tbl[64]); for(i=0; i<64; i++) x4a->ht[i] = 0; @@ -5967,12 +5892,11 @@ /* Need to make the hash table bigger */ int i,arrSize; struct s_x4 array; array.size = arrSize = x4a->size*2; array.count = x4a->count; - array.tbl = (x4node*)lemon_calloc(arrSize, - sizeof(x4node) + sizeof(x4node*)); + array.tbl = (x4node*)calloc(arrSize, sizeof(x4node) + sizeof(x4node*)); if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ array.ht = (x4node**)&(array.tbl[arrSize]); for(i=0; icount; i++){ x4node *oldnp, *newnp; @@ -5983,10 +5907,13 @@ newnp->next = array.ht[h]; newnp->data = oldnp->data; newnp->from = &(array.ht[h]); array.ht[h] = newnp; } + /* free(x4a->tbl); // This code was originall written for 16-bit machines. + ** on modern machines, don't worry about freeing this trival amount of + ** memory. */ *x4a = array; } /* Insert the new data */ h = ph & (x4a->size-1); np = &(x4a->tbl[x4a->count++]);