diff options
author | stephan <stephan@noemail.net> | 2023-01-21 12:18:28 +0000 |
---|---|---|
committer | stephan <stephan@noemail.net> | 2023-01-21 12:18:28 +0000 |
commit | cdcb84ef00da4a9b367e6536149634f633c41c71 (patch) | |
tree | 45826b1e478212df2dab3e0dacc8305a4f364c0a /src | |
parent | a7c498599f917607542bcd7003c445723aba9127 (diff) | |
parent | 3fdb05e883ce0a6fc610474eaa37d79fd7ac67e1 (diff) | |
download | sqlite-cdcb84ef00da4a9b367e6536149634f633c41c71.tar.gz sqlite-cdcb84ef00da4a9b367e6536149634f633c41c71.zip |
Merge trunk into wasi-patches branch.
FossilOrigin-Name: 6fc20d75d49310aedbc3351a4a5f1aa9ef5b4100501c7bfbe556aca2be2e44d7
Diffstat (limited to 'src')
-rw-r--r-- | src/attach.c | 29 | ||||
-rw-r--r-- | src/json.c | 11 | ||||
-rw-r--r-- | src/prepare.c | 7 | ||||
-rw-r--r-- | src/resolve.c | 1 | ||||
-rw-r--r-- | src/select.c | 13 | ||||
-rw-r--r-- | src/shell.c.in | 43 | ||||
-rw-r--r-- | src/sqlite.h.in | 15 | ||||
-rw-r--r-- | src/sqliteInt.h | 4 | ||||
-rw-r--r-- | src/tclsqlite.c | 3 | ||||
-rw-r--r-- | src/test1.c | 46 | ||||
-rw-r--r-- | src/test_bestindex.c | 6 | ||||
-rw-r--r-- | src/util.c | 20 | ||||
-rw-r--r-- | src/vdbe.c | 2 | ||||
-rw-r--r-- | src/vdbeaux.c | 3 | ||||
-rw-r--r-- | src/where.c | 11 |
15 files changed, 172 insertions, 42 deletions
diff --git a/src/attach.c b/src/attach.c index 1732be27b..4a6a25bf0 100644 --- a/src/attach.c +++ b/src/attach.c @@ -85,7 +85,7 @@ static void attachFunc( char *zErr = 0; unsigned int flags; Db *aNew; /* New array of Db pointers */ - Db *pNew; /* Db object for the newly attached database */ + Db *pNew = 0; /* Db object for the newly attached database */ char *zErrDyn = 0; sqlite3_vfs *pVfs; @@ -105,13 +105,26 @@ static void attachFunc( /* This is not a real ATTACH. Instead, this routine is being called ** from sqlite3_deserialize() to close database db->init.iDb and ** reopen it as a MemDB */ + Btree *pNewBt = 0; pVfs = sqlite3_vfs_find("memdb"); if( pVfs==0 ) return; - pNew = &db->aDb[db->init.iDb]; - if( pNew->pBt ) sqlite3BtreeClose(pNew->pBt); - pNew->pBt = 0; - pNew->pSchema = 0; - rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNew->pBt, 0, SQLITE_OPEN_MAIN_DB); + rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNewBt, 0, SQLITE_OPEN_MAIN_DB); + if( rc==SQLITE_OK ){ + Schema *pNewSchema = sqlite3SchemaGet(db, pNewBt); + if( pNewSchema ){ + /* Both the Btree and the new Schema were allocated successfully. + ** Close the old db and update the aDb[] slot with the new memdb + ** values. */ + pNew = &db->aDb[db->init.iDb]; + if( ALWAYS(pNew->pBt) ) sqlite3BtreeClose(pNew->pBt); + pNew->pBt = pNewBt; + pNew->pSchema = pNewSchema; + }else{ + sqlite3BtreeClose(pNewBt); + rc = SQLITE_NOMEM; + } + } + if( rc ) goto attach_error; }else{ /* This is a real ATTACH ** @@ -224,7 +237,7 @@ static void attachFunc( } #endif if( rc ){ - if( !REOPEN_AS_MEMDB(db) ){ + if( ALWAYS(!REOPEN_AS_MEMDB(db)) ){ int iDb = db->nDb - 1; assert( iDb>=2 ); if( db->aDb[iDb].pBt ){ @@ -341,6 +354,8 @@ static void codeAttach( sqlite3* db = pParse->db; int regArgs; + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto attach_end; + if( pParse->nErr ) goto attach_end; memset(&sName, 0, sizeof(NameContext)); sName.pParse = pParse; diff --git a/src/json.c b/src/json.c index 3636d3665..67448421b 100644 --- a/src/json.c +++ b/src/json.c @@ -2473,6 +2473,13 @@ static int jsonEachBestIndex( idxMask |= iMask; } } + if( pIdxInfo->nOrderBy>0 + && pIdxInfo->aOrderBy[0].iColumn<0 + && pIdxInfo->aOrderBy[0].desc==0 + ){ + pIdxInfo->orderByConsumed = 1; + } + if( (unusableMask & ~idxMask)!=0 ){ /* If there are any unusable constraints on JSON or ROOT, then reject ** this entire plan */ @@ -2668,10 +2675,10 @@ void sqlite3RegisterJsonFunctions(void){ #endif WAGGREGATE(json_group_array, 1, 0, 0, jsonArrayStep, jsonArrayFinal, jsonArrayValue, jsonGroupInverse, - SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS), + SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC), WAGGREGATE(json_group_object, 2, 0, 0, jsonObjectStep, jsonObjectFinal, jsonObjectValue, jsonGroupInverse, - SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS) + SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC) }; sqlite3InsertBuiltinFuncs(aJsonFunc, ArraySize(aJsonFunc)); #endif diff --git a/src/prepare.c b/src/prepare.c index 760738740..b2613e2c1 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -306,7 +306,12 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){ #else encoding = SQLITE_UTF8; #endif - sqlite3SetTextEncoding(db, encoding); + if( db->nVdbeActive>0 && encoding!=ENC(db) ){ + rc = SQLITE_LOCKED; + goto initone_error_out; + }else{ + sqlite3SetTextEncoding(db, encoding); + } }else{ /* If opening an attached database, the encoding much match ENC(db) */ if( (meta[BTREE_TEXT_ENCODING-1] & 3)!=ENC(db) ){ diff --git a/src/resolve.c b/src/resolve.c index 1c3a9d909..0d196ac37 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -506,6 +506,7 @@ static int lookupName( if( pParse->bReturning ){ eNewExprOp = TK_REGISTER; pExpr->op2 = TK_COLUMN; + pExpr->iColumn = iCol; pExpr->iTable = pNC->uNC.iBaseReg + (pTab->nCol+1)*pExpr->iTable + sqlite3TableColumnToStorage(pTab, iCol) + 1; }else{ diff --git a/src/select.c b/src/select.c index 2288858ea..d27bed026 100644 --- a/src/select.c +++ b/src/select.c @@ -2211,7 +2211,7 @@ int sqlite3ColumnsFromExprList( *pnCol = nCol; *paCol = aCol; - for(i=0, pCol=aCol; i<nCol && !db->mallocFailed; i++, pCol++){ + for(i=0, pCol=aCol; i<nCol && !pParse->nErr; i++, pCol++){ struct ExprList_item *pX = &pEList->a[i]; struct ExprList_item *pCollide; /* Get an appropriate name for the column @@ -2261,7 +2261,10 @@ int sqlite3ColumnsFromExprList( if( zName[j]==':' ) nName = j; } zName = sqlite3MPrintf(db, "%.*z:%u", nName, zName, ++cnt); - if( cnt>3 ) sqlite3_randomness(sizeof(cnt), &cnt); + sqlite3ProgressCheck(pParse); + if( cnt>3 ){ + sqlite3_randomness(sizeof(cnt), &cnt); + } } pCol->zCnName = zName; pCol->hName = sqlite3StrIHash(zName); @@ -2274,14 +2277,14 @@ int sqlite3ColumnsFromExprList( } } sqlite3HashClear(&ht); - if( db->mallocFailed ){ + if( pParse->nErr ){ for(j=0; j<i; j++){ sqlite3DbFree(db, aCol[j].zCnName); } sqlite3DbFree(db, aCol); *paCol = 0; *pnCol = 0; - return SQLITE_NOMEM_BKPT; + return pParse->rc; } return SQLITE_OK; } @@ -2313,7 +2316,7 @@ void sqlite3SubqueryColumnTypes( assert( pSelect!=0 ); assert( (pSelect->selFlags & SF_Resolved)!=0 ); - assert( pTab->nCol==pSelect->pEList->nExpr || db->mallocFailed ); + assert( pTab->nCol==pSelect->pEList->nExpr || pParse->nErr>0 ); assert( aff==SQLITE_AFF_NONE || aff==SQLITE_AFF_BLOB ); if( db->mallocFailed ) return; while( pSelect->pPrior ) pSelect = pSelect->pPrior; diff --git a/src/shell.c.in b/src/shell.c.in index 2c2bd557e..70774938a 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -481,6 +481,18 @@ static char mainPrompt[PROMPT_LEN_MAX]; /* Continuation prompt. default: " ...> " */ static char continuePrompt[PROMPT_LEN_MAX]; +/* This is variant of the standard-library strncpy() routine with the +** one change that the destination string is always zero-terminated, even +** if there is no zero-terminator in the first n-1 characters of the source +** string. +*/ +static char *shell_strncpy(char *dest, const char *src, size_t n){ + size_t i; + for(i=0; i<n-1 && src[i]!=0; i++) dest[i] = src[i]; + dest[i] = 0; + return dest; +} + /* ** Optionally disable dynamic continuation prompt. ** Unless disabled, the continuation prompt shows open SQL lexemes if any, @@ -548,18 +560,18 @@ static char *dynamicContinuePrompt(void){ if( ndp > ncp-3 ) return continuePrompt; strcpy(dynPrompt.dynamicPrompt, dynPrompt.zScannerAwaits); while( ndp<3 ) dynPrompt.dynamicPrompt[ndp++] = ' '; - strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3, + shell_strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3, PROMPT_LEN_MAX-4); }else{ if( dynPrompt.inParenLevel>9 ){ - strncpy(dynPrompt.dynamicPrompt, "(..", 4); + shell_strncpy(dynPrompt.dynamicPrompt, "(..", 4); }else if( dynPrompt.inParenLevel<0 ){ - strncpy(dynPrompt.dynamicPrompt, ")x!", 4); + shell_strncpy(dynPrompt.dynamicPrompt, ")x!", 4); }else{ - strncpy(dynPrompt.dynamicPrompt, "(x.", 4); + shell_strncpy(dynPrompt.dynamicPrompt, "(x.", 4); dynPrompt.dynamicPrompt[2] = (char)('0'+dynPrompt.inParenLevel); } - strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3, PROMPT_LEN_MAX-4); + shell_strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3, PROMPT_LEN_MAX-4); } } return dynPrompt.dynamicPrompt; @@ -5974,7 +5986,7 @@ static void tryToCloneSchema( char *zErrMsg = 0; zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema" - " WHERE %s", zWhere); + " WHERE %s ORDER BY rowid ASC", zWhere); shell_check_oom(zQuery); rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0); if( rc ){ @@ -5987,12 +5999,14 @@ static void tryToCloneSchema( zName = sqlite3_column_text(pQuery, 0); zSql = sqlite3_column_text(pQuery, 1); if( zName==0 || zSql==0 ) continue; - printf("%s... ", zName); fflush(stdout); - sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg); - if( zErrMsg ){ - utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql); - sqlite3_free(zErrMsg); - zErrMsg = 0; + if( sqlite3_stricmp((char*)zName, "sqlite_sequence")!=0 ){ + printf("%s... ", zName); fflush(stdout); + sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg); + if( zErrMsg ){ + utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql); + sqlite3_free(zErrMsg); + zErrMsg = 0; + } } if( xForEach ){ xForEach(p, newDb, (const char*)zName); @@ -6016,6 +6030,7 @@ static void tryToCloneSchema( zName = sqlite3_column_text(pQuery, 0); zSql = sqlite3_column_text(pQuery, 1); if( zName==0 || zSql==0 ) continue; + if( sqlite3_stricmp((char*)zName, "sqlite_sequence")!=0 ) continue; printf("%s... ", zName); fflush(stdout); sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg); if( zErrMsg ){ @@ -9631,10 +9646,10 @@ static int do_meta_command(char *zLine, ShellState *p){ if( c=='p' && cli_strncmp(azArg[0], "prompt", n)==0 ){ if( nArg >= 2) { - strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1); + shell_strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1); } if( nArg >= 3) { - strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1); + shell_strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1); } }else diff --git a/src/sqlite.h.in b/src/sqlite.h.in index bf1477ef2..2ee27898d 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -3366,7 +3366,7 @@ int sqlite3_trace_v2( ** ** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback ** function X to be invoked periodically during long running calls to -** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for +** [sqlite3_step()] and [sqlite3_prepare()] and similar for ** database connection D. An example use for this ** interface is to keep a GUI updated during a large query. ** @@ -3391,6 +3391,13 @@ int sqlite3_trace_v2( ** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their ** database connections for the meaning of "modify" in this paragraph. ** +** The progress handler callback would originally only be invoked from the +** bytecode engine. It still might be invoked during [sqlite3_prepare()] +** and similar because those routines might force a reparse of the schema +** which involves running the bytecode engine. However, beginning with +** SQLite version 3.41.0, the progress handler callback might also be +** invoked directly from [sqlite3_prepare()] while analyzing and generating +** code for complex queries. */ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); @@ -7157,10 +7164,10 @@ struct sqlite3_module { ** when the omit flag is true there is no guarantee that the constraint will ** not be checked again using byte code.)^ ** -** ^The idxNum and idxPtr values are recorded and passed into the +** ^The idxNum and idxStr values are recorded and passed into the ** [xFilter] method. -** ^[sqlite3_free()] is used to free idxPtr if and only if -** needToFreeIdxPtr is true. +** ^[sqlite3_free()] is used to free idxStr if and only if +** needToFreeIdxStr is true. ** ** ^The orderByConsumed means that output from [xFilter]/[xNext] will occur in ** the correct order to satisfy the ORDER BY clause so that no separate diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 09e817406..3da5f13d5 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3754,6 +3754,9 @@ struct Parse { u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */ u32 oldmask; /* Mask of old.* columns referenced */ u32 newmask; /* Mask of new.* columns referenced */ +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK + u32 nProgressSteps; /* xProgress steps taken during sqlite3_prepare() */ +#endif u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */ u8 bReturning; /* Coding a RETURNING trigger */ u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ @@ -4631,6 +4634,7 @@ char *sqlite3VMPrintf(sqlite3*,const char*, va_list); #endif void sqlite3SetString(char **, sqlite3*, const char*); +void sqlite3ProgressCheck(Parse*); void sqlite3ErrorMsg(Parse*, const char*, ...); int sqlite3ErrorToParser(sqlite3*,int); void sqlite3Dequote(char*); diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 4e25a6501..c455c29f1 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -3054,6 +3054,9 @@ deserialize_error: if( pDb->zProgress ){ Tcl_AppendResult(interp, pDb->zProgress, (char*)0); } +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK + sqlite3_progress_handler(pDb->db, 0, 0, 0); +#endif }else if( objc==4 ){ char *zProgress; int len; diff --git a/src/test1.c b/src/test1.c index dda77a90a..b1f0baafc 100644 --- a/src/test1.c +++ b/src/test1.c @@ -4137,6 +4137,14 @@ static int SQLITE_TCLAPI test_bind_value_from_select( return TCL_OK; } +#ifdef _WIN32 + struct iovec { + void *iov_base; + size_t iov_len; + }; +#else +# include <sys/uio.h> +#endif #ifndef SQLITE_OMIT_VIRTUALTABLE /* @@ -4149,6 +4157,7 @@ static int SQLITE_TCLAPI test_bind_value_from_select( ** -int64 ** -double ** -text +** -blob ** ** Each call clears static data. Called with no options does nothing ** but clear static data. @@ -4188,6 +4197,11 @@ static int SQLITE_TCLAPI test_carray_bind( sqlite3_free(((char**)aStaticData)[i]); } } + if( eStaticType==4 ){ + for(i=0; i<nStaticData; i++){ + sqlite3_free(((struct iovec*)aStaticData)[i].iov_base); + } + } sqlite3_free(aStaticData); aStaticData = 0; nStaticData = 0; @@ -4217,6 +4231,9 @@ static int SQLITE_TCLAPI test_carray_bind( if( strcmp(z, "-text")==0 ){ eType = 3; /* CARRAY_TEXT */ }else + if( strcmp(z, "-blob")==0 ){ + eType = 4; /* CARRAY_BLOB */ + }else if( strcmp(z, "--")==0 ){ break; }else @@ -4230,6 +4247,11 @@ static int SQLITE_TCLAPI test_carray_bind( (char*)0); return TCL_ERROR; } + if( eType==4 && !isStatic && !isTransient ){ + Tcl_AppendResult(interp, "blob data must be either -static or -transient", + (char*)0); + return TCL_ERROR; + } if( isStatic && isTransient ){ Tcl_AppendResult(interp, "cannot be both -static and -transient", (char*)0); @@ -4244,7 +4266,7 @@ static int SQLITE_TCLAPI test_carray_bind( if( Tcl_GetIntFromObj(interp, objv[i], &idx) ) return TCL_ERROR; i++; nData = objc - i; - switch( eType + 4*(nData<=0) ){ + switch( eType + 5*(nData<=0) ){ case 0: { /* INT32 */ int *a = sqlite3_malloc( sizeof(int)*nData ); if( a==0 ){ rc = SQLITE_NOMEM; goto carray_bind_done; } @@ -4297,7 +4319,24 @@ static int SQLITE_TCLAPI test_carray_bind( aData = a; break; } - case 4: { /* nData==0 */ + case 4: { /* BLOB */ + struct iovec *a = sqlite3_malloc( sizeof(struct iovec)*nData ); + if( a==0 ){ rc = SQLITE_NOMEM; goto carray_bind_done; } + for(j=0; j<nData; j++){ + int n = 0; + unsigned char *v = Tcl_GetByteArrayFromObj(objv[i+i], &n); + a[j].iov_len = n; + a[j].iov_base = sqlite3_malloc64( n ); + if( a[j].iov_base==0 ){ + a[j].iov_len = 0; + }else{ + memcpy(a[j].iov_base, v, n); + } + } + aData = a; + break; + } + case 5: { /* nData==0 */ aData = ""; xDel = SQLITE_STATIC; isTransient = 0; @@ -4315,6 +4354,9 @@ static int SQLITE_TCLAPI test_carray_bind( if( eType==3 ){ for(i=0; i<nData; i++) sqlite3_free(((char**)aData)[i]); } + if( eType==4 ){ + for(i=0; i<nData; i++) sqlite3_free(((struct iovec*)aData)[i].iov_base); + } sqlite3_free(aData); } carray_bind_done: diff --git a/src/test_bestindex.c b/src/test_bestindex.c index 65f063e50..f6e0678ce 100644 --- a/src/test_bestindex.c +++ b/src/test_bestindex.c @@ -766,11 +766,11 @@ static int tclFindFunction( if( Tcl_GetIntFromObj(interp, pObj, &iRet) ){ rc = SQLITE_ERROR; }else if( iRet>0 ){ - int nName = strlen(zName); - int nByte = nName + 1 + sizeof(TestFindFunction); + sqlite3_int64 nName = strlen(zName); + sqlite3_int64 nByte = nName + 1 + sizeof(TestFindFunction); TestFindFunction *pNew = 0; - pNew = (TestFindFunction*)sqlite3_malloc(nByte); + pNew = (TestFindFunction*)sqlite3_malloc64(nByte); if( pNew==0 ){ iRet = 0; }else{ diff --git a/src/util.c b/src/util.c index 23c6b1a66..632d317e3 100644 --- a/src/util.c +++ b/src/util.c @@ -176,6 +176,26 @@ void sqlite3ErrorWithMsg(sqlite3 *db, int err_code, const char *zFormat, ...){ } /* +** Check for interrupts and invoke progress callback. +*/ +void sqlite3ProgressCheck(Parse *p){ + sqlite3 *db = p->db; + if( AtomicLoad(&db->u1.isInterrupted) ){ + p->nErr++; + p->rc = SQLITE_INTERRUPT; + } +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK + if( db->xProgress && (++p->nProgressSteps)>=db->nProgressOps ){ + if( db->xProgress(db->pProgressArg) ){ + p->nErr++; + p->rc = SQLITE_INTERRUPT; + } + p->nProgressSteps = 0; + } +#endif +} + +/* ** Add an error message to pParse->zErrMsg and increment pParse->nErr. ** ** This function should be used to report any error that occurs while diff --git a/src/vdbe.c b/src/vdbe.c index 92dc1e1ed..db6086233 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2194,7 +2194,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ if( (flags1 | flags3)&MEM_Str ){ if( (flags1 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){ applyNumericAffinity(pIn1,0); - testcase( flags3==pIn3->flags ); + assert( flags3==pIn3->flags || CORRUPT_DB ); flags3 = pIn3->flags; } if( (flags3 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){ diff --git a/src/vdbeaux.c b/src/vdbeaux.c index ca9e5112a..d04d8f1e1 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -574,6 +574,9 @@ static SQLITE_NOINLINE void resizeResolveLabel(Parse *p, Vdbe *v, int j){ int i; for(i=p->nLabelAlloc; i<nNewSize; i++) p->aLabel[i] = -1; #endif + if( nNewSize>=100 && (nNewSize/100)>(p->nLabelAlloc/100) ){ + sqlite3ProgressCheck(p); + } p->nLabelAlloc = nNewSize; p->aLabel[j] = v->nOp; } diff --git a/src/where.c b/src/where.c index 890c3bf52..205f24762 100644 --- a/src/where.c +++ b/src/where.c @@ -2698,6 +2698,7 @@ static void whereLoopOutputAdjust( if( pX->iParent>=0 && (&pWC->a[pX->iParent])==pTerm ) break; } if( j<0 ){ + sqlite3ProgressCheck(pWC->pWInfo->pParse); if( pLoop->maskSelf==pTerm->prereqAll ){ /* If there are extra terms in the WHERE clause not used by an index ** that depend only on the table being scanned, and that will tend to @@ -2865,7 +2866,10 @@ static int whereLoopAddBtreeIndex( WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */ pNew = pBuilder->pNew; - if( db->mallocFailed ) return SQLITE_NOMEM_BKPT; + assert( db->mallocFailed==0 || pParse->nErr>0 ); + if( pParse->nErr ){ + return pParse->rc; + } WHERETRACE(0x800, ("BEGIN %s.addBtreeIdx(%s), nEq=%d, nSkip=%d, rRun=%d\n", pProbe->pTable->zName,pProbe->zName, pNew->u.btree.nEq, pNew->nSkip, pNew->rRun)); @@ -3181,6 +3185,9 @@ static int whereLoopAddBtreeIndex( && (pNew->u.btree.nEq<pProbe->nKeyCol || pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY) ){ + if( pNew->u.btree.nEq>3 ){ + sqlite3ProgressCheck(pParse); + } whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn); } pNew->nOut = saved_nOut; @@ -4340,8 +4347,6 @@ static int whereLoopAddOr( if( rc==SQLITE_OK ){ rc = whereLoopAddOr(&sSubBuild, mPrereq, mUnusable); } - assert( rc==SQLITE_OK || rc==SQLITE_DONE || sCur.n==0 - || rc==SQLITE_NOMEM ); testcase( rc==SQLITE_NOMEM && sCur.n>0 ); testcase( rc==SQLITE_DONE ); if( sCur.n==0 ){ |