Index: Makefile.in ================================================================== --- Makefile.in +++ Makefile.in @@ -541,11 +541,11 @@ .target_source: $(SRC) $(TOP)/tool/vdbe-compress.tcl rm -rf tsrc mkdir tsrc cp -f $(SRC) tsrc rm tsrc/sqlite.h.in tsrc/parse.y - $(TCLSH_CMD) $(TOP)/tool/vdbe-compress.tcl vdbe.new + $(TCLSH_CMD) $(TOP)/tool/vdbe-compress.tcl $(OPTS) vdbe.new mv vdbe.new tsrc/vdbe.c touch .target_source sqlite3.c: .target_source $(TOP)/tool/mksqlite3c.tcl $(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl Index: Makefile.msc ================================================================== --- Makefile.msc +++ Makefile.msc @@ -928,11 +928,11 @@ .target_source: $(SRC) $(TOP)\tool\vdbe-compress.tcl -rmdir /S/Q tsrc -mkdir tsrc for %i in ($(SRC)) do copy /Y %i tsrc del /Q tsrc\sqlite.h.in tsrc\parse.y - $(TCLSH_CMD) $(TOP)\tool\vdbe-compress.tcl < tsrc\vdbe.c > vdbe.new + $(TCLSH_CMD) $(TOP)\tool\vdbe-compress.tcl $(OPTS) < tsrc\vdbe.c > vdbe.new move vdbe.new tsrc\vdbe.c echo > .target_source sqlite3.c: .target_source $(TOP)\tool\mksqlite3c.tcl $(TCLSH_CMD) $(TOP)\tool\mksqlite3c.tcl Index: VERSION ================================================================== --- VERSION +++ VERSION @@ -1,1 +1,1 @@ -3.8.2 +3.8.3 Index: configure ================================================================== --- configure +++ configure @@ -1,8 +1,8 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.62 for sqlite 3.8.2. +# Generated by GNU Autoconf 2.62 for sqlite 3.8.3. # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. @@ -741,12 +741,12 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' -PACKAGE_VERSION='3.8.2' -PACKAGE_STRING='sqlite 3.8.2' +PACKAGE_VERSION='3.8.3' +PACKAGE_STRING='sqlite 3.8.3' PACKAGE_BUGREPORT='' # Factoring default headers for most tests. ac_includes_default="\ #include @@ -1481,11 +1481,11 @@ # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures sqlite 3.8.2 to adapt to many kinds of systems. +\`configure' configures sqlite 3.8.3 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. @@ -1546,11 +1546,11 @@ _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sqlite 3.8.2:";; + short | recursive ) echo "Configuration of sqlite 3.8.3:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options @@ -1662,11 +1662,11 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sqlite configure 3.8.2 +sqlite configure 3.8.3 generated by GNU Autoconf 2.62 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation @@ -1676,11 +1676,11 @@ fi cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by sqlite $as_me 3.8.2, which was +It was created by sqlite $as_me 3.8.3, which was generated by GNU Autoconf 2.62. Invocation command line was $ $0 $@ _ACEOF @@ -14019,11 +14019,11 @@ # Save the log message, to keep $[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by sqlite $as_me 3.8.2, which was +This file was extended by sqlite $as_me 3.8.3, which was generated by GNU Autoconf 2.62. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS @@ -14072,11 +14072,11 @@ Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_version="\\ -sqlite config.status 3.8.2 +sqlite config.status 3.8.3 configured by $0, generated by GNU Autoconf 2.62, with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2008 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation Index: main.mk ================================================================== --- main.mk +++ main.mk @@ -406,11 +406,11 @@ target_source: $(SRC) $(TOP)/tool/vdbe-compress.tcl rm -rf tsrc mkdir tsrc cp -f $(SRC) tsrc rm tsrc/sqlite.h.in tsrc/parse.y - tclsh $(TOP)/tool/vdbe-compress.tcl vdbe.new + tclsh $(TOP)/tool/vdbe-compress.tcl $(OPTS) vdbe.new mv vdbe.new tsrc/vdbe.c touch target_source sqlite3.c: target_source $(TOP)/tool/mksqlite3c.tcl tclsh $(TOP)/tool/mksqlite3c.tcl Index: src/backup.c ================================================================== --- src/backup.c +++ src/backup.c @@ -524,11 +524,11 @@ rc = backupTruncateFile(pFile, iSize); } /* Sync the database file to disk. */ if( rc==SQLITE_OK ){ - rc = sqlite3PagerSync(pDestPager); + rc = sqlite3PagerSync(pDestPager, 0); } }else{ sqlite3PagerTruncateImage(pDestPager, nDestTruncate); rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0); } @@ -599,14 +599,14 @@ /* If a transaction is still open on the Btree, roll it back. */ sqlite3BtreeRollback(p->pDest, SQLITE_OK); /* Set the error code of the destination database handle. */ rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc; - sqlite3Error(p->pDestDb, rc, 0); - - /* Exit the mutexes and free the backup context structure. */ if( p->pDestDb ){ + sqlite3Error(p->pDestDb, rc, 0); + + /* Exit the mutexes and free the backup context structure. */ sqlite3LeaveMutexAndCloseZombie(p->pDestDb); } sqlite3BtreeLeave(p->pSrc); if( p->pDestDb ){ /* EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a Index: src/btree.c ================================================================== --- src/btree.c +++ src/btree.c @@ -1650,11 +1650,11 @@ if( pgno>btreePagecount(pBt) ){ rc = SQLITE_CORRUPT_BKPT; }else{ rc = btreeGetPage(pBt, pgno, ppPage, bReadonly); - if( rc==SQLITE_OK ){ + if( rc==SQLITE_OK && (*ppPage)->isInit==0 ){ rc = btreeInitPage(*ppPage); if( rc!=SQLITE_OK ){ releasePage(*ppPage); } } @@ -1671,14 +1671,15 @@ */ static void releasePage(MemPage *pPage){ if( pPage ){ assert( pPage->aData ); assert( pPage->pBt ); + assert( pPage->pDbPage!=0 ); assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - sqlite3PagerUnref(pPage->pDbPage); + sqlite3PagerUnrefNotNull(pPage->pDbPage); } } /* ** During a rollback, when the pager reloads information into the cache @@ -4190,14 +4191,14 @@ } /* ** Return a pointer to payload information from the entry that the ** pCur cursor is pointing to. The pointer is to the beginning of -** the key if skipKey==0 and it points to the beginning of data if -** skipKey==1. The number of bytes of available key/data is written -** into *pAmt. If *pAmt==0, then the value returned will not be -** a valid pointer. +** the key if index btrees (pPage->intKey==0) and is the data for +** table btrees (pPage->intKey==1). The number of bytes of available +** key/data is written into *pAmt. If *pAmt==0, then the value +** returned will not be a valid pointer. ** ** This routine is an optimization. It is common for the entire key ** and data to fit on the local page and for there to be no overflow ** pages. When that is so, this routine can be used to access the ** key and data without making a copy. If the key and/or data spills @@ -4206,45 +4207,25 @@ ** ** The pointer returned by this routine looks directly into the cached ** page of the database. The data might change or move the next time ** any btree routine is called. */ -static const unsigned char *fetchPayload( +static const void *fetchPayload( BtCursor *pCur, /* Cursor pointing to entry to read from */ - u32 *pAmt, /* Write the number of available bytes here */ - int skipKey /* read beginning at data if this is true */ + u32 *pAmt /* Write the number of available bytes here */ ){ - unsigned char *aPayload; - MemPage *pPage; - u32 nKey; - u32 nLocal; - assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]); assert( pCur->eState==CURSOR_VALID ); + assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); assert( cursorHoldsMutex(pCur) ); - pPage = pCur->apPage[pCur->iPage]; - assert( pCur->aiIdx[pCur->iPage]nCell ); + assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); if( pCur->info.nSize==0 ){ btreeParseCell(pCur->apPage[pCur->iPage], pCur->aiIdx[pCur->iPage], &pCur->info); } - aPayload = pCur->info.pCell; - aPayload += pCur->info.nHeader; - if( pPage->intKey ){ - nKey = 0; - }else{ - nKey = (int)pCur->info.nKey; - } - if( skipKey ){ - aPayload += nKey; - nLocal = pCur->info.nLocal - nKey; - }else{ - nLocal = pCur->info.nLocal; - assert( nLocal<=nKey ); - } - *pAmt = nLocal; - return aPayload; + *pAmt = pCur->info.nLocal; + return (void*)(pCur->info.pCell + pCur->info.nHeader); } /* ** For the entry that cursor pCur is point to, return as @@ -4259,26 +4240,14 @@ ** ** These routines is used to get quick access to key and data ** in the common case where no overflow pages are used. */ const void *sqlite3BtreeKeyFetch(BtCursor *pCur, u32 *pAmt){ - const void *p = 0; - assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); - assert( cursorHoldsMutex(pCur) ); - if( ALWAYS(pCur->eState==CURSOR_VALID) ){ - p = (const void*)fetchPayload(pCur, pAmt, 0); - } - return p; + return fetchPayload(pCur, pAmt); } const void *sqlite3BtreeDataFetch(BtCursor *pCur, u32 *pAmt){ - const void *p = 0; - assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); - assert( cursorHoldsMutex(pCur) ); - if( ALWAYS(pCur->eState==CURSOR_VALID) ){ - p = (const void*)fetchPayload(pCur, pAmt, 1); - } - return p; + return fetchPayload(pCur, pAmt); } /* ** Move the cursor down to a new child page. The newPgno argument is the @@ -4393,12 +4362,10 @@ ** b-tree). */ static int moveToRoot(BtCursor *pCur){ MemPage *pRoot; int rc = SQLITE_OK; - Btree *p = pCur->pBtree; - BtShared *pBt = p->pBt; assert( cursorHoldsMutex(pCur) ); assert( CURSOR_INVALID < CURSOR_REQUIRESEEK ); assert( CURSOR_VALID < CURSOR_REQUIRESEEK ); assert( CURSOR_FAULT > CURSOR_REQUIRESEEK ); @@ -4409,20 +4376,16 @@ } sqlite3BtreeClearCursor(pCur); } if( pCur->iPage>=0 ){ - int i; - for(i=1; i<=pCur->iPage; i++){ - releasePage(pCur->apPage[i]); - } - pCur->iPage = 0; + while( pCur->iPage ) releasePage(pCur->apPage[pCur->iPage--]); }else if( pCur->pgnoRoot==0 ){ pCur->eState = CURSOR_INVALID; return SQLITE_OK; }else{ - rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0], + rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0], pCur->wrFlag==0 ? PAGER_GET_READONLY : 0); if( rc!=SQLITE_OK ){ pCur->eState = CURSOR_INVALID; return rc; } @@ -4451,18 +4414,20 @@ pCur->aiIdx[0] = 0; pCur->info.nSize = 0; pCur->atLast = 0; pCur->validNKey = 0; - if( pRoot->nCell==0 && !pRoot->leaf ){ + if( pRoot->nCell>0 ){ + pCur->eState = CURSOR_VALID; + }else if( !pRoot->leaf ){ Pgno subpage; if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT; subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]); pCur->eState = CURSOR_VALID; rc = moveToChild(pCur, subpage); }else{ - pCur->eState = ((pRoot->nCell>0)?CURSOR_VALID:CURSOR_INVALID); + pCur->eState = CURSOR_INVALID; } return rc; } /* @@ -4714,21 +4679,18 @@ ** the entire cell by checking for the cases where the record is ** stored entirely within the b-tree page by inspecting the first ** 2 bytes of the cell. */ nCell = pCell[0]; - if( nCell<=pPage->max1bytePayload - /* && (pCell+nCell)aDataEnd */ - ){ + if( nCell<=pPage->max1bytePayload ){ /* This branch runs if the record-size field of the cell is a ** single byte varint and the record fits entirely on the main ** b-tree page. */ testcase( pCell+nCell+1==pPage->aDataEnd ); c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[1], pIdxKey); }else if( !(pCell[1] & 0x80) && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal - /* && (pCell+nCell+2)<=pPage->aDataEnd */ ){ /* The record-size field is a 2 byte varint and the record ** fits entirely on the main b-tree page. */ testcase( pCell+nCell+2==pPage->aDataEnd ); c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[2], pIdxKey); @@ -5548,11 +5510,11 @@ nHeader = 0; if( !pPage->leaf ){ nHeader += 4; } if( pPage->hasData ){ - nHeader += putVarint(&pCell[nHeader], nData+nZero); + nHeader += putVarint32(&pCell[nHeader], nData+nZero); }else{ nData = nZero = 0; } nHeader += putVarint(&pCell[nHeader], *(u64*)&nKey); btreeParseCellPtr(pPage, pCell, &info); @@ -5676,11 +5638,10 @@ */ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ u32 pc; /* Offset to cell content of cell being deleted */ u8 *data; /* pPage->aData */ u8 *ptr; /* Used to move bytes around within data[] */ - u8 *endPtr; /* End of loop */ int rc; /* The return code */ int hdr; /* Beginning of the header. 0 most pages. 100 page 1 */ if( *pRC ) return; @@ -5701,17 +5662,12 @@ rc = freeSpace(pPage, pc, sz); if( rc ){ *pRC = rc; return; } - endPtr = &pPage->aCellIdx[2*pPage->nCell - 2]; - assert( (SQLITE_PTR_TO_INT(ptr)&1)==0 ); /* ptr is always 2-byte aligned */ - while( ptrnCell--; + memmove(ptr, ptr+2, 2*(pPage->nCell - idx)); put2byte(&data[hdr+3], pPage->nCell); pPage->nFree += 2; } /* @@ -5744,13 +5700,10 @@ int j; /* Loop counter */ int end; /* First byte past the last cell pointer in data[] */ int ins; /* Index in data[] where new cell pointer is inserted */ int cellOffset; /* Address of first cell pointer in data[] */ u8 *data; /* The content of the whole page */ - u8 *ptr; /* Used for moving information around in data[] */ - u8 *endPtr; /* End of the loop */ - int nSkip = (iChild ? 4 : 0); if( *pRC ) return; assert( i>=0 && i<=pPage->nCell+pPage->nOverflow ); @@ -5797,17 +5750,11 @@ pPage->nFree -= (u16)(2 + sz); memcpy(&data[idx+nSkip], pCell+nSkip, sz-nSkip); if( iChild ){ put4byte(&data[idx], iChild); } - ptr = &data[end]; - endPtr = &data[ins]; - assert( (SQLITE_PTR_TO_INT(ptr)&1)==0 ); /* ptr is always 2-byte aligned */ - while( ptr>endPtr ){ - *(u16*)ptr = *(u16*)&ptr[-2]; - ptr -= 2; - } + memmove(&data[ins+2], &data[ins], end-ins); put2byte(&data[ins], idx); put2byte(&data[pPage->hdrOffset+3], pPage->nCell); #ifndef SQLITE_OMIT_AUTOVACUUM if( pPage->pBt->autoVacuum ){ /* The cell may contain a pointer to an overflow page. If so, write @@ -7765,11 +7712,11 @@ va_start(ap, zFormat); if( pCheck->errMsg.nChar ){ sqlite3StrAccumAppend(&pCheck->errMsg, "\n", 1); } if( zMsg1 ){ - sqlite3StrAccumAppend(&pCheck->errMsg, zMsg1, -1); + sqlite3StrAccumAppendAll(&pCheck->errMsg, zMsg1); } sqlite3VXPrintf(&pCheck->errMsg, 1, zFormat, ap); va_end(ap); if( pCheck->errMsg.accError==STRACCUM_NOMEM ){ pCheck->mallocFailed = 1; Index: src/build.c ================================================================== --- src/build.c +++ src/build.c @@ -3987,13 +3987,13 @@ sqlite3StrAccumInit(&errMsg, 0, 0, 200); errMsg.db = pParse->db; for(j=0; jnKeyCol; j++){ char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName; if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2); - sqlite3StrAccumAppend(&errMsg, pTab->zName, -1); + sqlite3StrAccumAppendAll(&errMsg, pTab->zName); sqlite3StrAccumAppend(&errMsg, ".", 1); - sqlite3StrAccumAppend(&errMsg, zCol, -1); + sqlite3StrAccumAppendAll(&errMsg, zCol); } zErr = sqlite3StrAccumFinish(&errMsg); sqlite3HaltConstraint(pParse, (pIdx->autoIndex==2)?SQLITE_CONSTRAINT_PRIMARYKEY:SQLITE_CONSTRAINT_UNIQUE, onError, zErr, P4_DYNAMIC, P5_ConstraintUnique); @@ -4181,12 +4181,13 @@ } if( pKey ){ assert( sqlite3KeyInfoIsWriteable(pKey) ); for(i=0; iazColl[i]; - if( NEVER(zColl==0) ) zColl = "BINARY"; - pKey->aColl[i] = sqlite3LocateCollSeq(pParse, zColl); + assert( zColl!=0 ); + pKey->aColl[i] = strcmp(zColl,"BINARY")==0 ? 0 : + sqlite3LocateCollSeq(pParse, zColl); pKey->aSortOrder[i] = pIdx->aSortOrder[i]; } if( pParse->nErr ){ sqlite3KeyInfoUnref(pKey); }else{ Index: src/callback.c ================================================================== --- src/callback.c +++ src/callback.c @@ -355,11 +355,10 @@ int bestScore = 0; /* Score of best match */ int h; /* Hash value */ assert( nArg>=(-2) ); assert( nArg>=(-1) || createFlag==0 ); - assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % ArraySize(db->aFunc.a); /* First search for a match amongst the application-defined functions. */ p = functionSearch(&db->aFunc, h, zName, nName); Index: src/func.c ================================================================== --- src/func.c +++ src/func.c @@ -1509,15 +1509,15 @@ nSep = sqlite3_value_bytes(argv[1]); }else{ zSep = ","; nSep = 1; } - sqlite3StrAccumAppend(pAccum, zSep, nSep); + if( nSep ) sqlite3StrAccumAppend(pAccum, zSep, nSep); } zVal = (char*)sqlite3_value_text(argv[0]); nVal = sqlite3_value_bytes(argv[0]); - sqlite3StrAccumAppend(pAccum, zVal, nVal); + if( nVal ) sqlite3StrAccumAppend(pAccum, zVal, nVal); } } static void groupConcatFinalize(sqlite3_context *context){ StrAccum *pAccum; pAccum = sqlite3_aggregate_context(context, 0); Index: src/main.c ================================================================== --- src/main.c +++ src/main.c @@ -586,11 +586,12 @@ } db->lookaside.pEnd = p; db->lookaside.bEnabled = 1; db->lookaside.bMalloced = pBuf==0 ?1:0; }else{ - db->lookaside.pEnd = 0; + db->lookaside.pStart = db; + db->lookaside.pEnd = db; db->lookaside.bEnabled = 0; db->lookaside.bMalloced = 0; } return SQLITE_OK; } @@ -984,13 +985,11 @@ } sqlite3HashClear(&db->aModule); #endif sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */ - if( db->pErr ){ - sqlite3ValueFree(db->pErr); - } + sqlite3ValueFree(db->pErr); sqlite3CloseExtensions(db); db->magic = SQLITE_MAGIC_ERROR; /* The temp-database schema is allocated differently from the other schema @@ -1084,10 +1083,11 @@ case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break; case SQLITE_READONLY: zName = "SQLITE_READONLY"; break; case SQLITE_READONLY_RECOVERY: zName = "SQLITE_READONLY_RECOVERY"; break; case SQLITE_READONLY_CANTLOCK: zName = "SQLITE_READONLY_CANTLOCK"; break; case SQLITE_READONLY_ROLLBACK: zName = "SQLITE_READONLY_ROLLBACK"; break; + case SQLITE_READONLY_DBMOVED: zName = "SQLITE_READONLY_DBMOVED"; break; case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break; case SQLITE_IOERR: zName = "SQLITE_IOERR"; break; case SQLITE_IOERR_READ: zName = "SQLITE_IOERR_READ"; break; case SQLITE_IOERR_SHORT_READ: zName = "SQLITE_IOERR_SHORT_READ"; break; case SQLITE_IOERR_WRITE: zName = "SQLITE_IOERR_WRITE"; break; @@ -1368,10 +1368,11 @@ void (*xFinal)(sqlite3_context*), FuncDestructor *pDestructor ){ FuncDef *p; int nName; + int extraFlags; assert( sqlite3_mutex_held(db->mutex) ); if( zFunctionName==0 || (xFunc && (xFinal || xStep)) || (!xFunc && (xFinal && !xStep)) || @@ -1378,10 +1379,14 @@ (!xFunc && (!xFinal && xStep)) || (nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) || (255<(nName = sqlite3Strlen30( zFunctionName))) ){ return SQLITE_MISUSE_BKPT; } + + assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC ); + extraFlags = enc & SQLITE_DETERMINISTIC; + enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY); #ifndef SQLITE_OMIT_UTF16 /* If SQLITE_UTF16 is specified as the encoding type, transform this ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally. @@ -1391,14 +1396,14 @@ */ if( enc==SQLITE_UTF16 ){ enc = SQLITE_UTF16NATIVE; }else if( enc==SQLITE_ANY ){ int rc; - rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8, + rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8|extraFlags, pUserData, xFunc, xStep, xFinal, pDestructor); if( rc==SQLITE_OK ){ - rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE, + rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE|extraFlags, pUserData, xFunc, xStep, xFinal, pDestructor); } if( rc!=SQLITE_OK ){ return rc; } @@ -1437,11 +1442,12 @@ if( pDestructor ){ pDestructor->nRef++; } p->pDestructor = pDestructor; - p->funcFlags &= SQLITE_FUNC_ENCMASK; + p->funcFlags = (p->funcFlags & SQLITE_FUNC_ENCMASK) | extraFlags; + testcase( p->funcFlags & SQLITE_DETERMINISTIC ); p->xFunc = xFunc; p->xStep = xStep; p->xFinalize = xFinal; p->pUserData = pUserData; p->nArg = (u16)nArg; @@ -1888,10 +1894,11 @@ } sqlite3_mutex_enter(db->mutex); if( db->mallocFailed ){ z = sqlite3ErrStr(SQLITE_NOMEM); }else{ + testcase( db->pErr==0 ); z = (char*)sqlite3_value_text(db->pErr); assert( !db->mallocFailed ); if( z==0 ){ z = sqlite3ErrStr(db->errCode); } @@ -1929,12 +1936,11 @@ if( db->mallocFailed ){ z = (void *)outOfMem; }else{ z = sqlite3_value_text16(db->pErr); if( z==0 ){ - sqlite3ValueSetStr(db->pErr, -1, sqlite3ErrStr(db->errCode), - SQLITE_UTF8, SQLITE_STATIC); + sqlite3Error(db, db->errCode, sqlite3ErrStr(db->errCode)); z = sqlite3_value_text16(db->pErr); } /* A malloc() may have failed within the call to sqlite3_value_text16() ** above. If this is the case, then the db->mallocFailed flag needs to ** be cleared before returning. Do this directly, instead of via @@ -2644,12 +2650,10 @@ if( !db->mallocFailed && rc==SQLITE_OK){ rc = sqlite3RtreeInit(db); } #endif - sqlite3Error(db, rc, 0); - /* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking ** mode. -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking ** mode. Doing nothing at all also makes NORMAL the default. */ #ifdef SQLITE_DEFAULT_LOCKING_MODE Index: src/malloc.c ================================================================== --- src/malloc.c +++ src/malloc.c @@ -431,11 +431,11 @@ /* ** TRUE if p is a lookaside memory allocation from db */ #ifndef SQLITE_OMIT_LOOKASIDE static int isLookaside(sqlite3 *db, void *p){ - return p && p>=db->lookaside.pStart && plookaside.pEnd; + return p>=db->lookaside.pStart && plookaside.pEnd; } #else #define isLookaside(A,B) 0 #endif @@ -447,12 +447,13 @@ assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) ); return sqlite3GlobalConfig.m.xSize(p); } int sqlite3DbMallocSize(sqlite3 *db, void *p){ - assert( db==0 || sqlite3_mutex_held(db->mutex) ); - if( db && isLookaside(db, p) ){ + assert( db!=0 ); + assert( sqlite3_mutex_held(db->mutex) ); + if( isLookaside(db, p) ){ return db->lookaside.sz; }else{ assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) ); assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) ); assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) ); Index: src/os_unix.c ================================================================== --- src/os_unix.c +++ src/os_unix.c @@ -1313,10 +1313,19 @@ } *ppInode = pInode; return SQLITE_OK; } +/* +** Return TRUE if pFile has been renamed or unlinked since it was first opened. +*/ +static int fileHasMoved(unixFile *pFile){ + struct stat buf; + return pFile->pInode!=0 && + (osStat(pFile->zPath, &buf)!=0 || buf.st_ino!=pFile->pInode->fileId.ino); +} + /* ** Check a unixFile that is a database. Verify the following: ** ** (1) There is exactly one hard link on the file @@ -1347,14 +1356,11 @@ if( buf.st_nlink>1 ){ sqlite3_log(SQLITE_WARNING, "multiple links to file: %s", pFile->zPath); pFile->ctrlFlags |= UNIXFILE_WARNED; return; } - if( pFile->pInode!=0 - && ((rc = osStat(pFile->zPath, &buf))!=0 - || buf.st_ino!=pFile->pInode->fileId.ino) - ){ + if( fileHasMoved(pFile) ){ sqlite3_log(SQLITE_WARNING, "file renamed while open: %s", pFile->zPath); pFile->ctrlFlags |= UNIXFILE_WARNED; return; } } @@ -3798,10 +3804,14 @@ if( zTFile ){ unixGetTempname(pFile->pVfs->mxPathname, zTFile); *(char**)pArg = zTFile; } return SQLITE_OK; + } + case SQLITE_FCNTL_HAS_MOVED: { + *(int*)pArg = fileHasMoved(pFile); + return SQLITE_OK; } #if SQLITE_MAX_MMAP_SIZE>0 case SQLITE_FCNTL_MMAP_SIZE: { i64 newLimit = *(i64*)pArg; int rc = SQLITE_OK; Index: src/os_win.c ================================================================== --- src/os_win.c +++ src/os_win.c @@ -3117,11 +3117,11 @@ winModeBit(pFile, WINFILE_PSOW, (int*)pArg); OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); return SQLITE_OK; } case SQLITE_FCNTL_VFSNAME: { - *(char**)pArg = sqlite3_mprintf("win32"); + *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName); OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); return SQLITE_OK; } case SQLITE_FCNTL_WIN32_AV_RETRY: { int *a = (int*)pArg; Index: src/pager.c ================================================================== --- src/pager.c +++ src/pager.c @@ -1022,29 +1022,26 @@ ** PagerSavepoint.pInSavepoint. */ static int subjRequiresPage(PgHdr *pPg){ Pager *pPager = pPg->pPager; PagerSavepoint *p; - Pgno pgno; + Pgno pgno = pPg->pgno; int i; - if( pPager->nSavepoint ){ - pgno = pPg->pgno; - for(i=0; inSavepoint; i++){ - p = &pPager->aSavepoint[i]; - if( p->nOrig>=pgno && 0==sqlite3BitvecTest(p->pInSavepoint, pgno) ){ - return 1; - } + for(i=0; inSavepoint; i++){ + p = &pPager->aSavepoint[i]; + if( p->nOrig>=pgno && 0==sqlite3BitvecTest(p->pInSavepoint, pgno) ){ + return 1; } } return 0; } /* ** Return true if the page is already in the journal file. */ -static int pageInJournal(PgHdr *pPg){ - return sqlite3BitvecTest(pPg->pPager->pInJournal, pPg->pgno); +static int pageInJournal(Pager *pPager, PgHdr *pPg){ + return sqlite3BitvecTest(pPager->pInJournal, pPg->pgno); } /* ** Read a 32-bit integer from the given file descriptor. Store the integer ** that is read in *pRes. Return SQLITE_OK if everything worked, or an @@ -1247,10 +1244,11 @@ if( SQLITE_OK!=(rc = sqlite3OsFileSize(pJrnl, &szJ)) || szJ<16 || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len)) || len>=nMaster + || len==0 || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum)) || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8)) || memcmp(aMagic, aJournalMagic, 8) || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zMaster, len, szJ-16-len)) ){ @@ -1987,11 +1985,11 @@ sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash); if( pPager->dbSize==0 && sqlite3PcacheRefCount(pPager->pPCache)>0 ){ PgHdr *p = pager_lookup(pPager, 1); if( p ){ p->pageHash = 0; - sqlite3PagerUnref(p); + sqlite3PagerUnrefNotNull(p); } } #endif sqlite3BitvecDestroy(pPager->pInJournal); @@ -2015,10 +2013,15 @@ ** file. So it is safe to truncate the database file to its minimum ** required size. */ assert( pPager->eLock==EXCLUSIVE_LOCK ); rc = pager_truncate(pPager, pPager->dbSize); } + + if( rc==SQLITE_OK && bCommit && isOpen(pPager->fd) ){ + rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_COMMIT_PHASETWO, 0); + if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; + } if( !pPager->exclusiveMode && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0)) ){ rc2 = pagerUnlockDb(pPager, SHARED_LOCK); @@ -2829,11 +2832,11 @@ testcase( rc!=SQLITE_OK ); } if( rc==SQLITE_OK && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) ){ - rc = sqlite3PagerSync(pPager); + rc = sqlite3PagerSync(pPager, 0); } if( rc==SQLITE_OK ){ rc = pager_end_transaction(pPager, zMaster[0]!='\0', 0); testcase( rc!=SQLITE_OK ); } @@ -2975,11 +2978,11 @@ rc = readDbPage(pPg, iFrame); } if( rc==SQLITE_OK ){ pPager->xReiniter(pPg); } - sqlite3PagerUnref(pPg); + sqlite3PagerUnrefNotNull(pPg); } } /* Normally, if a transaction is rolled back, any backup processes are ** updated as data is copied out of the rollback journal and into the @@ -4330,11 +4333,11 @@ /* Open the sub-journal, if it has not already been opened */ assert( pPager->useJournal ); assert( isOpen(pPager->jfd) || pagerUseWal(pPager) ); assert( isOpen(pPager->sjfd) || pPager->nSubRec==0 ); assert( pagerUseWal(pPager) - || pageInJournal(pPg) + || pageInJournal(pPager, pPg) || pPg->pgno>pPager->dbOrigSize ); rc = openSubJournal(pPager); /* If the sub-journal was opened successfully (or was already open), @@ -4794,10 +4797,34 @@ *ppPager = pPager; return SQLITE_OK; } + +/* Verify that the database file has not be deleted or renamed out from +** under the pager. Return SQLITE_OK if the database is still were it ought +** to be on disk. Return non-zero (SQLITE_READONLY_DBMOVED or some other error +** code from sqlite3OsAccess()) if the database has gone missing. +*/ +static int databaseIsUnmoved(Pager *pPager){ + int bHasMoved = 0; + int rc; + + if( pPager->tempFile ) return SQLITE_OK; + if( pPager->dbSize==0 ) return SQLITE_OK; + assert( pPager->zFilename && pPager->zFilename[0] ); + rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_HAS_MOVED, &bHasMoved); + if( rc==SQLITE_NOTFOUND ){ + /* If the HAS_MOVED file-control is unimplemented, assume that the file + ** has not been moved. That is the historical behavior of SQLite: prior to + ** version 3.8.3, it never checked */ + rc = SQLITE_OK; + }else if( rc==SQLITE_OK && bHasMoved ){ + rc = SQLITE_READONLY_DBMOVED; + } + return rc; +} /* ** This function is called after transitioning from PAGER_UNLOCK to ** PAGER_SHARED state. It tests if there is a hot journal present in @@ -5266,11 +5293,11 @@ if( bMmapOk && pagerUseWal(pPager) ){ rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame); if( rc!=SQLITE_OK ) goto pager_acquire_err; } - if( iFrame==0 && bMmapOk ){ + if( bMmapOk && iFrame==0 ){ void *pData = 0; rc = sqlite3OsFetch(pPager->fd, (i64)(pgno-1) * pPager->pageSize, pPager->pageSize, &pData ); @@ -5407,20 +5434,23 @@ ** If the number of references to the page drop to zero, then the ** page is added to the LRU list. When all references to all pages ** are released, a rollback occurs and the lock on the database is ** removed. */ +void sqlite3PagerUnrefNotNull(DbPage *pPg){ + Pager *pPager; + assert( pPg!=0 ); + pPager = pPg->pPager; + if( pPg->flags & PGHDR_MMAP ){ + pagerReleaseMapPage(pPg); + }else{ + sqlite3PcacheRelease(pPg); + } + pagerUnlockIfUnused(pPager); +} void sqlite3PagerUnref(DbPage *pPg){ - if( pPg ){ - Pager *pPager = pPg->pPager; - if( pPg->flags & PGHDR_MMAP ){ - pagerReleaseMapPage(pPg); - }else{ - sqlite3PcacheRelease(pPg); - } - pagerUnlockIfUnused(pPager); - } + if( pPg ) sqlite3PagerUnrefNotNull(pPg); } /* ** This function is called at the start of every write transaction. ** There must already be a RESERVED or EXCLUSIVE lock on the database @@ -5471,17 +5501,23 @@ SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE| (pPager->tempFile ? (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL): (SQLITE_OPEN_MAIN_JOURNAL) ); - #ifdef SQLITE_ENABLE_ATOMIC_WRITE - rc = sqlite3JournalOpen( - pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager) - ); - #else - rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0); - #endif + + /* Verify that the database still has the same name as it did when + ** it was originally opened. */ + rc = databaseIsUnmoved(pPager); + if( rc==SQLITE_OK ){ +#ifdef SQLITE_ENABLE_ATOMIC_WRITE + rc = sqlite3JournalOpen( + pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager) + ); +#else + rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0); +#endif + } } assert( rc!=SQLITE_OK || isOpen(pPager->jfd) ); } @@ -5598,13 +5634,13 @@ ** one of the journals, the corresponding bit is set in the ** Pager.pInJournal bitvec and the PagerSavepoint.pInSavepoint bitvecs ** of any open savepoints as appropriate. */ static int pager_write(PgHdr *pPg){ - void *pData = pPg->pData; Pager *pPager = pPg->pPager; int rc = SQLITE_OK; + int inJournal; /* This routine is not called unless a write-transaction has already ** been started. The journal file may or may not be open at this point. ** It is never called in the ERROR state. */ @@ -5611,18 +5647,12 @@ assert( pPager->eState==PAGER_WRITER_LOCKED || pPager->eState==PAGER_WRITER_CACHEMOD || pPager->eState==PAGER_WRITER_DBMOD ); assert( assert_pager_state(pPager) ); - - /* If an error has been previously detected, report the same error - ** again. This should not happen, but the check provides robustness. */ - if( NEVER(pPager->errCode) ) return pPager->errCode; - - /* Higher-level routines never call this function if database is not - ** writable. But check anyway, just for robustness. */ - if( NEVER(pPager->readOnly) ) return SQLITE_PERM; + assert( pPager->errCode==0 ); + assert( pPager->readOnly==0 ); CHECK_PAGE(pPg); /* The journal file needs to be opened. Higher level routines have already ** obtained the necessary locks to begin the write-transaction, but the @@ -5642,19 +5672,20 @@ /* Mark the page as dirty. If the page has already been written ** to the journal then we can return right away. */ sqlite3PcacheMakeDirty(pPg); - if( pageInJournal(pPg) && !subjRequiresPage(pPg) ){ + inJournal = pageInJournal(pPager, pPg); + if( inJournal && (pPager->nSavepoint==0 || !subjRequiresPage(pPg)) ){ assert( !pagerUseWal(pPager) ); }else{ /* The transaction journal now exists and we have a RESERVED or an ** EXCLUSIVE lock on the main database file. Write the current page to ** the transaction journal if it is not there already. */ - if( !pageInJournal(pPg) && !pagerUseWal(pPager) ){ + if( !inJournal && !pagerUseWal(pPager) ){ assert( pagerUseWal(pPager)==0 ); if( pPg->pgno<=pPager->dbOrigSize && isOpen(pPager->jfd) ){ u32 cksum; char *pData2; i64 iOff = pPager->journalOff; @@ -5663,11 +5694,11 @@ ** contains the database locks. The following assert verifies ** that we do not. */ assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) ); assert( pPager->journalHdr<=pPager->journalOff ); - CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2); + CODEC2(pPager, pPg->pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2); cksum = pager_cksum(pPager, (u8*)pData2); /* Even if an IO or diskfull error occurs while journalling the ** page in the block above, set the need-sync flag for the page. ** Otherwise, when the transaction is rolled back, the logic in @@ -5715,11 +5746,11 @@ /* If the statement journal is open and the page is not in it, ** then write the current page to the statement journal. Note that ** the statement journal format differs from the standard journal format ** in that it omits the checksums and the header. */ - if( subjRequiresPage(pPg) ){ + if( pPager->nSavepoint>0 && subjRequiresPage(pPg) ){ rc = subjournalPage(pPg); } } /* Update the database size and return. @@ -5747,23 +5778,23 @@ int sqlite3PagerWrite(DbPage *pDbPage){ int rc = SQLITE_OK; PgHdr *pPg = pDbPage; Pager *pPager = pPg->pPager; - Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); assert( (pPg->flags & PGHDR_MMAP)==0 ); assert( pPager->eState>=PAGER_WRITER_LOCKED ); assert( pPager->eState!=PAGER_ERROR ); assert( assert_pager_state(pPager) ); - if( nPagePerSector>1 ){ + if( pPager->sectorSize > (u32)pPager->pageSize ){ Pgno nPageCount; /* Total number of pages in database file */ Pgno pg1; /* First page of the sector pPg is located on. */ int nPage = 0; /* Number of pages starting at pg1 to journal */ int ii; /* Loop counter */ int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */ + Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); /* Set the doNotSpill NOSYNC bit to 1. This is because we cannot allow ** a journal header to be written between the pages journaled by ** this function. */ @@ -5798,18 +5829,18 @@ if( rc==SQLITE_OK ){ rc = pager_write(pPage); if( pPage->flags&PGHDR_NEED_SYNC ){ needSync = 1; } - sqlite3PagerUnref(pPage); + sqlite3PagerUnrefNotNull(pPage); } } }else if( (pPage = pager_lookup(pPager, pg))!=0 ){ if( pPage->flags&PGHDR_NEED_SYNC ){ needSync = 1; } - sqlite3PagerUnref(pPage); + sqlite3PagerUnrefNotNull(pPage); } } /* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages ** starting at pg1, then it needs to be set for all of them. Because @@ -5821,11 +5852,11 @@ assert( !MEMDB ); for(ii=0; iiflags |= PGHDR_NEED_SYNC; - sqlite3PagerUnref(pPage); + sqlite3PagerUnrefNotNull(pPage); } } } assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)!=0 ); @@ -5974,21 +6005,21 @@ ** or pages with the Pager.noSync flag set. ** ** If successful, or if called on a pager for which it is a no-op, this ** function returns SQLITE_OK. Otherwise, an IO error code is returned. */ -int sqlite3PagerSync(Pager *pPager){ +int sqlite3PagerSync(Pager *pPager, const char *zMaster){ int rc = SQLITE_OK; - if( !pPager->noSync ){ + + if( isOpen(pPager->fd) ){ + void *pArg = (void*)zMaster; + rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, pArg); + if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; + } + if( rc==SQLITE_OK && !pPager->noSync ){ assert( !MEMDB ); rc = sqlite3OsSync(pPager->fd, pPager->syncFlags); - }else if( isOpen(pPager->fd) ){ - assert( !MEMDB ); - rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC_OMITTED, 0); - if( rc==SQLITE_NOTFOUND ){ - rc = SQLITE_OK; - } } return rc; } /* @@ -6183,11 +6214,11 @@ if( rc!=SQLITE_OK ) goto commit_phase_one_exit; } /* Finally, sync the database file. */ if( !noSync ){ - rc = sqlite3PagerSync(pPager); + rc = sqlite3PagerSync(pPager, zMaster); } IOTRACE(("DBSYNC %p\n", pPager)) } } @@ -6312,11 +6343,13 @@ rc = pager_playback(pPager, 0); } assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK ); assert( rc==SQLITE_OK || rc==SQLITE_FULL || rc==SQLITE_CORRUPT - || rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR ); + || rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR + || rc==SQLITE_CANTOPEN + ); /* If an error occurs during a ROLLBACK, we can no longer trust the pager ** cache. So call pager_error() on the way out to make any error persistent. */ return pager_error(pPager, rc); @@ -6715,11 +6748,11 @@ ** can be written to. The caller has already promised not to write to it. */ if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){ needSyncPgno = pPg->pgno; assert( pPager->journalMode==PAGER_JOURNALMODE_OFF || - pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize ); + pageInJournal(pPager, pPg) || pPg->pgno>pPager->dbOrigSize ); assert( pPg->flags&PGHDR_DIRTY ); } /* If the cache contains a page with page-number pgno, remove it ** from its hash chain. Also, if the PGHDR_NEED_SYNC flag was set for @@ -6749,11 +6782,11 @@ ** as the original page since it has already been allocated. */ if( MEMDB ){ assert( pPgOld ); sqlite3PcacheMove(pPgOld, origPgno); - sqlite3PagerUnref(pPgOld); + sqlite3PagerUnrefNotNull(pPgOld); } if( needSyncPgno ){ /* If needSyncPgno is non-zero, then the journal file needs to be ** sync()ed before any data is written to database file page needSyncPgno. @@ -6778,11 +6811,11 @@ } return rc; } pPgHdr->flags |= PGHDR_NEED_SYNC; sqlite3PcacheMakeDirty(pPgHdr); - sqlite3PagerUnref(pPgHdr); + sqlite3PagerUnrefNotNull(pPgHdr); } return SQLITE_OK; } #endif Index: src/pager.h ================================================================== --- src/pager.h +++ src/pager.h @@ -134,10 +134,11 @@ int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag); #define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0) DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno); void sqlite3PagerRef(DbPage*); void sqlite3PagerUnref(DbPage*); +void sqlite3PagerUnrefNotNull(DbPage*); /* Operations on page references. */ int sqlite3PagerWrite(DbPage*); void sqlite3PagerDontWrite(DbPage*); int sqlite3PagerMovepage(Pager*,DbPage*,Pgno,int); @@ -148,11 +149,11 @@ /* Functions used to manage pager transactions and savepoints. */ void sqlite3PagerPagecount(Pager*, int*); int sqlite3PagerBegin(Pager*, int exFlag, int); int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, int); int sqlite3PagerExclusiveLock(Pager*); -int sqlite3PagerSync(Pager *pPager); +int sqlite3PagerSync(Pager *pPager, const char *zMaster); int sqlite3PagerCommitPhaseTwo(Pager*); int sqlite3PagerRollback(Pager*); int sqlite3PagerOpenSavepoint(Pager *pPager, int n); int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint); int sqlite3PagerSharedLock(Pager *pPager); Index: src/pcache1.c ================================================================== --- src/pcache1.c +++ src/pcache1.c @@ -94,10 +94,11 @@ ** in memory. */ struct PgHdr1 { sqlite3_pcache_page page; unsigned int iKey; /* Key value (page number) */ + u8 isPinned; /* Page in use, not on the LRU list */ PgHdr1 *pNext; /* Next in hash table chain */ PCache1 *pCache; /* Cache that currently owns this page */ PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */ PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */ }; @@ -422,38 +423,36 @@ ** This function is used internally to remove the page pPage from the ** PGroup LRU list, if is part of it. If pPage is not part of the PGroup ** LRU list, then this function is a no-op. ** ** The PGroup mutex must be held when this function is called. -** -** If pPage is NULL then this routine is a no-op. */ static void pcache1PinPage(PgHdr1 *pPage){ PCache1 *pCache; PGroup *pGroup; - if( pPage==0 ) return; + assert( pPage!=0 ); + assert( pPage->isPinned==0 ); pCache = pPage->pCache; pGroup = pCache->pGroup; + assert( pPage->pLruNext || pPage==pGroup->pLruTail ); + assert( pPage->pLruPrev || pPage==pGroup->pLruHead ); assert( sqlite3_mutex_held(pGroup->mutex) ); - if( pPage->pLruNext || pPage==pGroup->pLruTail ){ - if( pPage->pLruPrev ){ - pPage->pLruPrev->pLruNext = pPage->pLruNext; - } - if( pPage->pLruNext ){ - pPage->pLruNext->pLruPrev = pPage->pLruPrev; - } - if( pGroup->pLruHead==pPage ){ - pGroup->pLruHead = pPage->pLruNext; - } - if( pGroup->pLruTail==pPage ){ - pGroup->pLruTail = pPage->pLruPrev; - } - pPage->pLruNext = 0; - pPage->pLruPrev = 0; - pPage->pCache->nRecyclable--; - } + if( pPage->pLruPrev ){ + pPage->pLruPrev->pLruNext = pPage->pLruNext; + }else{ + pGroup->pLruHead = pPage->pLruNext; + } + if( pPage->pLruNext ){ + pPage->pLruNext->pLruPrev = pPage->pLruPrev; + }else{ + pGroup->pLruTail = pPage->pLruPrev; + } + pPage->pLruNext = 0; + pPage->pLruPrev = 0; + pPage->isPinned = 1; + pCache->nRecyclable--; } /* ** Remove the page supplied as an argument from the hash table @@ -481,10 +480,11 @@ static void pcache1EnforceMaxPage(PGroup *pGroup){ assert( sqlite3_mutex_held(pGroup->mutex) ); while( pGroup->nCurrentPage>pGroup->nMaxPage && pGroup->pLruTail ){ PgHdr1 *p = pGroup->pLruTail; assert( p->pCache->pGroup==pGroup ); + assert( p->isPinned==0 ); pcache1PinPage(p); pcache1RemoveFromHash(p); pcache1FreePage(p); } } @@ -508,11 +508,11 @@ PgHdr1 *pPage; while( (pPage = *pp)!=0 ){ if( pPage->iKey>=iLimit ){ pCache->nPage--; *pp = pPage->pNext; - pcache1PinPage(pPage); + if( !pPage->isPinned ) pcache1PinPage(pPage); pcache1FreePage(pPage); }else{ pp = &pPage->pNext; TESTONLY( nPage++; ) } @@ -731,12 +731,15 @@ unsigned int h = iKey % pCache->nHash; for(pPage=pCache->apHash[h]; pPage&&pPage->iKey!=iKey; pPage=pPage->pNext); } /* Step 2: Abort if no existing page is found and createFlag is 0 */ - if( pPage || createFlag==0 ){ - pcache1PinPage(pPage); + if( pPage ){ + if( !pPage->isPinned ) pcache1PinPage(pPage); + goto fetch_out; + } + if( createFlag==0 ){ goto fetch_out; } /* The pGroup local variable will normally be initialized by the ** pcache1EnterMutex() macro above. But if SQLITE_MUTEX_OMIT is defined, @@ -773,10 +776,11 @@ || pGroup->nCurrentPage>=pGroup->nMaxPage || pcache1UnderMemoryPressure(pCache) )){ PCache1 *pOther; pPage = pGroup->pLruTail; + assert( pPage->isPinned==0 ); pcache1RemoveFromHash(pPage); pcache1PinPage(pPage); pOther = pPage->pCache; /* We want to verify that szPage and szExtra are the same for pOther @@ -809,10 +813,11 @@ pPage->iKey = iKey; pPage->pNext = pCache->apHash[h]; pPage->pCache = pCache; pPage->pLruPrev = 0; pPage->pLruNext = 0; + pPage->isPinned = 1; *(void **)pPage->page.pExtra = 0; pCache->apHash[h] = pPage; } fetch_out: @@ -844,10 +849,11 @@ /* It is an error to call this function if the page is already ** part of the PGroup LRU list. */ assert( pPage->pLruPrev==0 && pPage->pLruNext==0 ); assert( pGroup->pLruHead!=pPage && pGroup->pLruTail!=pPage ); + assert( pPage->isPinned==1 ); if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){ pcache1RemoveFromHash(pPage); pcache1FreePage(pPage); }else{ @@ -859,10 +865,11 @@ }else{ pGroup->pLruTail = pPage; pGroup->pLruHead = pPage; } pCache->nRecyclable++; + pPage->isPinned = 0; } pcache1LeaveMutex(pCache->pGroup); } @@ -985,10 +992,11 @@ while( (nReq<0 || nFreepage.pBuf); #ifdef SQLITE_PCACHE_SEPARATE_HEADER nFree += sqlite3MemSize(p); #endif + assert( p->isPinned==0 ); pcache1PinPage(p); pcache1RemoveFromHash(p); pcache1FreePage(p); } pcache1LeaveMutex(&pcache1.grp); @@ -1009,13 +1017,14 @@ int *pnRecyclable /* OUT: Total number of pages available for recycling */ ){ PgHdr1 *p; int nRecyclable = 0; for(p=pcache1.grp.pLruHead; p; p=p->pLruNext){ + assert( p->isPinned==0 ); nRecyclable++; } *pnCurrent = pcache1.grp.nCurrentPage; *pnMax = (int)pcache1.grp.nMaxPage; *pnMin = (int)pcache1.grp.nMinPage; *pnRecyclable = nRecyclable; } #endif Index: src/printf.c ================================================================== --- src/printf.c +++ src/printf.c @@ -145,10 +145,18 @@ } if( N>0 ){ sqlite3StrAccumAppend(pAccum, zSpaces, N); } } + +/* +** Set the StrAccum object to an error mode. +*/ +void setStrAccumError(StrAccum *p, u8 eError){ + p->accError = eError; + p->nAlloc = 0; +} /* ** On machines with a small stack size, you can redefine the ** SQLITE_PRINT_BUF_SIZE to be something smaller, if desired. */ @@ -357,11 +365,11 @@ zOut = buf; }else{ nOut = precision + 10; zOut = zExtra = sqlite3Malloc( nOut ); if( zOut==0 ){ - pAccum->accError = STRACCUM_NOMEM; + setStrAccumError(pAccum, STRACCUM_NOMEM); return; } } bufpt = &zOut[nOut-1]; if( xtype==etORDINAL ){ @@ -469,11 +477,11 @@ e2 = exp; } if( MAX(e2,0)+precision+width > etBUFSIZE - 15 ){ bufpt = zExtra = sqlite3Malloc( MAX(e2,0)+precision+width+15 ); if( bufpt==0 ){ - pAccum->accError = STRACCUM_NOMEM; + setStrAccumError(pAccum, STRACCUM_NOMEM); return; } } zOut = bufpt; nsd = 16 + flag_altform2*10; @@ -604,11 +612,11 @@ needQuote = !isnull && xtype==etSQLESCAPE2; n += i + 1 + needQuote*2; if( n>etBUFSIZE ){ bufpt = zExtra = sqlite3Malloc( n ); if( bufpt==0 ){ - pAccum->accError = STRACCUM_NOMEM; + setStrAccumError(pAccum, STRACCUM_NOMEM); return; } }else{ bufpt = buf; } @@ -627,11 +635,11 @@ ** if( precision>=0 && precisionn ){ sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n); } length = width = 0; break; } @@ -639,14 +647,14 @@ SrcList *pSrc = va_arg(ap, SrcList*); int k = va_arg(ap, int); struct SrcList_item *pItem = &pSrc->a[k]; assert( k>=0 && knSrc ); if( pItem->zDatabase ){ - sqlite3StrAccumAppend(pAccum, pItem->zDatabase, -1); + sqlite3StrAccumAppendAll(pAccum, pItem->zDatabase); sqlite3StrAccumAppend(pAccum, ".", 1); } - sqlite3StrAccumAppend(pAccum, pItem->zName, -1); + sqlite3StrAccumAppendAll(pAccum, pItem->zName); length = width = 0; break; } default: { assert( xtype==etINVALID ); @@ -673,44 +681,42 @@ nspace = width-length; if( nspace>0 ){ sqlite3AppendSpace(pAccum, nspace); } } - sqlite3_free(zExtra); + if( zExtra ) sqlite3_free(zExtra); }/* End for loop over the format string */ } /* End of function */ /* ** Append N bytes of text from z to the StrAccum object. */ void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){ - assert( z!=0 || N==0 ); - if( p->accError ){ - testcase(p->accError==STRACCUM_TOOBIG); - testcase(p->accError==STRACCUM_NOMEM); - return; - } - assert( p->zText!=0 || p->nChar==0 ); - if( N<=0 ){ - if( N==0 || z[0]==0 ) return; - N = sqlite3Strlen30(z); - } + assert( z!=0 ); + assert( p->zText!=0 || p->nChar==0 || p->accError ); + assert( N>=0 ); + assert( p->accError==0 || p->nAlloc==0 ); if( p->nChar+N >= p->nAlloc ){ char *zNew; + if( p->accError ){ + testcase(p->accError==STRACCUM_TOOBIG); + testcase(p->accError==STRACCUM_NOMEM); + return; + } if( !p->useMalloc ){ - p->accError = STRACCUM_TOOBIG; N = p->nAlloc - p->nChar - 1; + setStrAccumError(p, STRACCUM_TOOBIG); if( N<=0 ){ return; } }else{ char *zOld = (p->zText==p->zBase ? 0 : p->zText); i64 szNew = p->nChar; szNew += N + 1; if( szNew > p->mxAlloc ){ sqlite3StrAccumReset(p); - p->accError = STRACCUM_TOOBIG; + setStrAccumError(p, STRACCUM_TOOBIG); return; }else{ p->nAlloc = (int)szNew; } if( p->useMalloc==1 ){ @@ -720,20 +726,28 @@ } if( zNew ){ if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar); p->zText = zNew; }else{ - p->accError = STRACCUM_NOMEM; sqlite3StrAccumReset(p); + setStrAccumError(p, STRACCUM_NOMEM); return; } } } assert( p->zText ); memcpy(&p->zText[p->nChar], z, N); p->nChar += N; } + +/* +** Append the complete text of zero-terminated string z[] to the p string. +*/ +void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){ + sqlite3StrAccumAppend(p, z, sqlite3Strlen30(z)); +} + /* ** Finish off a string by making sure it is zero-terminated. ** Return a pointer to the resulting string. Return a NULL ** pointer if any kind of error was encountered. @@ -748,11 +762,11 @@ p->zText = sqlite3_malloc(p->nChar+1); } if( p->zText ){ memcpy(p->zText, p->zBase, p->nChar+1); }else{ - p->accError = STRACCUM_NOMEM; + setStrAccumError(p, STRACCUM_NOMEM); } } } return p->zText; } Index: src/shell.c ================================================================== --- src/shell.c +++ src/shell.c @@ -1834,11 +1834,11 @@ ** + Store the character that terminates the field in p->cTerm. Store ** EOF on end-of-file. ** + Report syntax errors on stderr */ static char *csv_read_one_field(CSVReader *p){ - int c, pc; + int c, pc, ppc; int cSep = p->cSeparator; p->n = 0; c = fgetc(p->in); if( c==EOF || seenInterrupt ){ p->cTerm = EOF; @@ -1845,11 +1845,11 @@ return 0; } if( c=='"' ){ int startLine = p->nLine; int cQuote = c; - pc = 0; + pc = ppc = 0; while( 1 ){ c = fgetc(p->in); if( c=='\n' ) p->nLine++; if( c==cQuote ){ if( pc==cQuote ){ @@ -1857,11 +1857,11 @@ continue; } } if( (c==cSep && pc==cQuote) || (c=='\n' && pc==cQuote) - || (c=='\n' && pc=='\r' && p->n>=2 && p->z[p->n-2]==cQuote) + || (c=='\n' && pc=='\r' && ppc==cQuote) || (c==EOF && pc==cQuote) ){ do{ p->n--; }while( p->z[p->n]!=cQuote ); p->cTerm = c; break; @@ -1875,10 +1875,11 @@ p->zFile, startLine, cQuote); p->cTerm = EOF; break; } csv_append_char(p, c); + ppc = pc; pc = c; } }else{ while( c!=EOF && c!=cSep && c!='\n' ){ csv_append_char(p, c); Index: src/sqlite.h.in ================================================================== --- src/sqlite.h.in +++ src/sqlite.h.in @@ -484,10 +484,11 @@ #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) +#define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8)) #define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) #define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8)) #define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8)) #define SQLITE_CONSTRAINT_FOREIGNKEY (SQLITE_CONSTRAINT | (3<<8)) #define SQLITE_CONSTRAINT_FUNCTION (SQLITE_CONSTRAINT | (4<<8)) @@ -551,11 +552,12 @@ ** information is written to disk in the same order as calls ** to xWrite(). The SQLITE_IOCAP_POWERSAFE_OVERWRITE property means that ** after reboot following a crash or power loss, the only bytes in a ** file that were written at the application level might have changed ** and that adjacent bytes, even bytes within the same sector are -** guaranteed to be unchanged. +** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN +** flag indicate that a file cannot be deleted when open. */ #define SQLITE_IOCAP_ATOMIC 0x00000001 #define SQLITE_IOCAP_ATOMIC512 0x00000002 #define SQLITE_IOCAP_ATOMIC1K 0x00000004 #define SQLITE_IOCAP_ATOMIC2K 0x00000008 @@ -782,19 +784,33 @@ ** to the [sqlite3_file] object associated with a particular database ** connection. See the [sqlite3_file_control()] documentation for ** additional information. ** **
  • [[SQLITE_FCNTL_SYNC_OMITTED]] -** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by -** SQLite and sent to all VFSes in place of a call to the xSync method -** when the database connection has [PRAGMA synchronous] set to OFF.)^ -** Some specialized VFSes need this signal in order to operate correctly -** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most -** VFSes do not need this signal and should silently ignore this opcode. -** Applications should not call [sqlite3_file_control()] with this -** opcode as doing so may disrupt the operation of the specialized VFSes -** that do require it. +** No longer in use. +** +**
  • [[SQLITE_FCNTL_SYNC]] +** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and +** sent to the VFS immediately before the xSync method is invoked on a +** database file descriptor. Or, if the xSync method is not invoked +** because the user has configured SQLite with +** [PRAGMA synchronous | PRAGMA synchronous=OFF] it is invoked in place +** of the xSync method. In most cases, the pointer argument passed with +** this file-control is NULL. However, if the database file is being synced +** as part of a multi-database commit, the argument points to a nul-terminated +** string containing the transactions master-journal file name. VFSes that +** do not need this signal should silently ignore this opcode. Applications +** should not call [sqlite3_file_control()] with this opcode as doing so may +** disrupt the operation of the specialized VFSes that do require it. +** +**
  • [[SQLITE_FCNTL_COMMIT_PHASETWO]] +** The [SQLITE_FCNTL_COMMIT_PHASETWO] opcode is generated internally by SQLite +** and sent to the VFS after a transaction has been committed immediately +** but before the database is unlocked. VFSes that do not need this signal +** should silently ignore this opcode. Applications should not call +** [sqlite3_file_control()] with this opcode as doing so may disrupt the +** operation of the specialized VFSes that do require it. ** **
  • [[SQLITE_FCNTL_WIN32_AV_RETRY]] ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic ** retry counts and intervals for certain disk I/O operations for the ** windows [VFS] in order to provide robustness in the presence of @@ -914,10 +930,16 @@ ** This file control is used by some VFS activity tracing [shims]. ** The argument is a zero-terminated string. Higher layers in the ** SQLite stack may generate instances of this file control if ** the [SQLITE_USE_FCNTL_TRACE] compile-time option is enabled. ** +**
  • [[SQLITE_FCNTL_HAS_MOVED]] +** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a +** pointer to an integer and it writes a boolean into that integer depending +** on whether or not the file has been renamed, moved, or deleted since it +** was first opened. +** ** */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_GET_LOCKPROXYFILE 2 #define SQLITE_SET_LOCKPROXYFILE 3 @@ -934,10 +956,13 @@ #define SQLITE_FCNTL_PRAGMA 14 #define SQLITE_FCNTL_BUSYHANDLER 15 #define SQLITE_FCNTL_TEMPFILENAME 16 #define SQLITE_FCNTL_MMAP_SIZE 18 #define SQLITE_FCNTL_TRACE 19 +#define SQLITE_FCNTL_HAS_MOVED 20 +#define SQLITE_FCNTL_SYNC 21 +#define SQLITE_FCNTL_COMMIT_PHASETWO 22 /* ** CAPI3REF: Mutex Handle ** ** The mutex module within SQLite defines [sqlite3_mutex] to be an @@ -3950,19 +3975,28 @@ ** parameter is less than -1 or greater than 127 then the behavior is ** undefined. ** ** ^The fourth parameter, eTextRep, specifies what ** [SQLITE_UTF8 | text encoding] this SQL function prefers for -** its parameters. Every SQL function implementation must be able to work -** with UTF-8, UTF-16le, or UTF-16be. But some implementations may be -** more efficient with one encoding than another. ^An application may -** invoke sqlite3_create_function() or sqlite3_create_function16() multiple -** times with the same function but with different values of eTextRep. +** its parameters. The application should set this parameter to +** [SQLITE_UTF16LE] if the function implementation invokes +** [sqlite3_value_text16le()] on an input, or [SQLITE_UTF16BE] if the +** implementation invokes [sqlite3_value_text16be()] on an input, or +** [SQLITE_UTF16] if [sqlite3_value_text16()] is used, or [SQLITE_UTF8] +** otherwise. ^The same SQL function may be registered multiple times using +** different preferred text encodings, with different implementations for +** each encoding. ** ^When multiple implementations of the same function are available, SQLite ** will pick the one that involves the least amount of data conversion. -** If there is only a single implementation which does not care what text -** encoding is used, then the fourth argument should be [SQLITE_ANY]. +** +** ^The fourth parameter may optionally be ORed with [SQLITE_DETERMINISTIC] +** to signal that the function will always return the same result given +** the same inputs within a single SQL statement. Most SQL functions are +** deterministic. The built-in [random()] SQL function is an example of a +** function that is not deterministic. The SQLite query planner is able to +** perform additional optimizations on deterministic functions, so use +** of the [SQLITE_DETERMINISTIC] flag is recommended where possible. ** ** ^(The fifth parameter is an arbitrary pointer. The implementation of the ** function can gain access to this pointer using [sqlite3_user_data()].)^ ** ** ^The sixth, seventh and eighth parameters, xFunc, xStep and xFinal, are @@ -4044,13 +4078,23 @@ */ #define SQLITE_UTF8 1 #define SQLITE_UTF16LE 2 #define SQLITE_UTF16BE 3 #define SQLITE_UTF16 4 /* Use native byte order */ -#define SQLITE_ANY 5 /* sqlite3_create_function only */ +#define SQLITE_ANY 5 /* Deprecated */ #define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ +/* +** CAPI3REF: Function Flags +** +** These constants may be ORed together with the +** [SQLITE_UTF8 | preferred text encoding] as the fourth argument +** to [sqlite3_create_function()], [sqlite3_create_function16()], or +** [sqlite3_create_function_v2()]. +*/ +#define SQLITE_DETERMINISTIC 0x800 + /* ** CAPI3REF: Deprecated Functions ** DEPRECATED ** ** These functions are [deprecated]. In order to maintain Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -3167,10 +3167,11 @@ const void *sqlite3ValueText(sqlite3_value*, u8); int sqlite3ValueBytes(sqlite3_value*, u8); void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, void(*)(void*)); +void sqlite3ValueSetNull(sqlite3_value*); void sqlite3ValueFree(sqlite3_value*); sqlite3_value *sqlite3ValueNew(sqlite3 *); char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8); int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **); void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8); @@ -3232,10 +3233,11 @@ int sqlite3ApiExit(sqlite3 *db, int); int sqlite3OpenTempDatabase(Parse *); void sqlite3StrAccumInit(StrAccum*, char*, int, int); void sqlite3StrAccumAppend(StrAccum*,const char*,int); +void sqlite3StrAccumAppendAll(StrAccum*,const char*); void sqlite3AppendSpace(StrAccum*,int); char *sqlite3StrAccumFinish(StrAccum*); void sqlite3StrAccumReset(StrAccum*); void sqlite3SelectDestInit(SelectDest*,int,int); Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int); Index: src/test1.c ================================================================== --- src/test1.c +++ src/test1.c @@ -940,13 +940,25 @@ return; } sqlite3_result_int(context, p1!=p2); } +/* +** This SQL function returns a different answer each time it is called, even if +** the arguments are the same. +*/ +static void nondeterministicFunction( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + static int cnt = 0; + sqlite3_result_int(context, cnt++); +} /* -** Usage: sqlite_test_create_function DB +** Usage: sqlite3_create_function DB ** ** Call the sqlite3_create_function API on the given database in order ** to create a function named "x_coalesce". This function does the same thing ** as the "coalesce" function. This function also registers an SQL function ** named "x_sqlite_exec" that invokes sqlite3_exec(). Invoking sqlite3_exec() @@ -971,20 +983,20 @@ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0); return TCL_ERROR; } if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; - rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_ANY, 0, + rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_UTF8, 0, t1_ifnullFunc, 0, 0); if( rc==SQLITE_OK ){ - rc = sqlite3_create_function(db, "hex8", 1, SQLITE_ANY, 0, - hex8Func, 0, 0); + rc = sqlite3_create_function(db, "hex8", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC, + 0, hex8Func, 0, 0); } #ifndef SQLITE_OMIT_UTF16 if( rc==SQLITE_OK ){ - rc = sqlite3_create_function(db, "hex16", 1, SQLITE_ANY, 0, - hex16Func, 0, 0); + rc = sqlite3_create_function(db, "hex16", 1, SQLITE_UTF16 | SQLITE_DETERMINISTIC, + 0, hex16Func, 0, 0); } #endif if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "tkt2213func", 1, SQLITE_ANY, 0, tkt2213Function, 0, 0); @@ -991,10 +1003,23 @@ } if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "pointer_change", 4, SQLITE_ANY, 0, ptrChngFunction, 0, 0); } + + /* Functions counter1() and counter2() have the same implementation - they + ** both return an ascending integer with each call. But counter1() is marked + ** as non-deterministic and counter2() is marked as deterministic. + */ + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "counter1", -1, SQLITE_UTF8, + 0, nondeterministicFunction, 0, 0); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "counter2", -1, SQLITE_UTF8|SQLITE_DETERMINISTIC, + 0, nondeterministicFunction, 0, 0); + } #ifndef SQLITE_OMIT_UTF16 /* Use the sqlite3_create_function16() API here. Mainly for fun, but also ** because it is not tested anywhere else. */ if( rc==SQLITE_OK ){ Index: src/test6.c ================================================================== --- src/test6.c +++ src/test6.c @@ -171,13 +171,10 @@ ** 512 byte block begining at offset PENDING_BYTE. */ static int writeDbFile(CrashFile *p, u8 *z, i64 iAmt, i64 iOff){ int rc = SQLITE_OK; int iSkip = 0; - if( iOff==PENDING_BYTE && (p->flags&SQLITE_OPEN_MAIN_DB) ){ - iSkip = 512; - } if( (iAmt-iSkip)>0 ){ rc = sqlite3OsWrite(p->pRealFile, &z[iSkip], (int)(iAmt-iSkip), iOff+iSkip); } return rc; } @@ -407,17 +404,21 @@ void *zBuf, int iAmt, sqlite_int64 iOfst ){ CrashFile *pCrash = (CrashFile *)pFile; + int nCopy = (int)MIN((i64)iAmt, (pCrash->iSize - iOfst)); + + if( nCopy>0 ){ + memcpy(zBuf, &pCrash->zData[iOfst], nCopy); + } /* Check the file-size to see if this is a short-read */ - if( pCrash->iSize<(iOfst+iAmt) ){ + if( nCopyzData[iOfst], iAmt); return SQLITE_OK; } /* ** Write data to a crash-file. @@ -630,18 +631,16 @@ ** never contains valid data anyhow. So avoid doing such a read here. ** ** UPDATE: It also contains an assert() verifying that each call ** to the xRead() method reads less than 128KB of data. */ - const int isDb = (flags&SQLITE_OPEN_MAIN_DB); i64 iOff; memset(pWrapper->zData, 0, pWrapper->nData); for(iOff=0; iOffiSize; iOff += 512){ int nRead = (int)(pWrapper->iSize - iOff); if( nRead>512 ) nRead = 512; - if( isDb && iOff==PENDING_BYTE ) continue; rc = sqlite3OsRead(pReal, &pWrapper->zData[iOff], nRead, iOff); } }else{ rc = SQLITE_NOMEM; } Index: src/test_vfstrace.c ================================================================== --- src/test_vfstrace.c +++ src/test_vfstrace.c @@ -256,10 +256,15 @@ case SQLITE_IOERR_CLOSE: zVal = "SQLITE_IOERR_CLOSE"; break; case SQLITE_IOERR_DIR_CLOSE: zVal = "SQLITE_IOERR_DIR_CLOSE"; break; case SQLITE_IOERR_SHMOPEN: zVal = "SQLITE_IOERR_SHMOPEN"; break; case SQLITE_IOERR_SHMSIZE: zVal = "SQLITE_IOERR_SHMSIZE"; break; case SQLITE_IOERR_SHMLOCK: zVal = "SQLITE_IOERR_SHMLOCK"; break; + case SQLITE_IOERR_SHMMAP: zVal = "SQLITE_IOERR_SHMMAP"; break; + case SQLITE_IOERR_SEEK: zVal = "SQLITE_IOERR_SEEK"; break; + case SQLITE_IOERR_GETTEMPPATH: zVal = "SQLITE_IOERR_GETTEMPPATH"; break; + case SQLITE_IOERR_CONVPATH: zVal = "SQLITE_IOERR_CONVPATH"; break; + case SQLITE_READONLY_DBMOVED: zVal = "SQLITE_READONLY_DBMOVED"; break; case SQLITE_LOCKED_SHAREDCACHE: zVal = "SQLITE_LOCKED_SHAREDCACHE"; break; case SQLITE_BUSY_RECOVERY: zVal = "SQLITE_BUSY_RECOVERY"; break; case SQLITE_CANTOPEN_NOTEMPDIR: zVal = "SQLITE_CANTOPEN_NOTEMPDIR"; break; default: { sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc); Index: src/util.c ================================================================== --- src/util.c +++ src/util.c @@ -113,22 +113,21 @@ ** To clear the most recent error for sqlite handle "db", sqlite3Error ** should be called with err_code set to SQLITE_OK and zFormat set ** to NULL. */ void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){ - if( db && (db->pErr || (db->pErr = sqlite3ValueNew(db))!=0) ){ - db->errCode = err_code; - if( zFormat ){ - char *z; - va_list ap; - va_start(ap, zFormat); - z = sqlite3VMPrintf(db, zFormat, ap); - va_end(ap); - sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC); - }else{ - sqlite3ValueSetStr(db->pErr, 0, 0, SQLITE_UTF8, SQLITE_STATIC); - } + assert( db!=0 ); + db->errCode = err_code; + if( zFormat && (db->pErr || (db->pErr = sqlite3ValueNew(db))!=0) ){ + char *z; + va_list ap; + va_start(ap, zFormat); + z = sqlite3VMPrintf(db, zFormat, ap); + va_end(ap); + sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC); + }else if( db->pErr ){ + sqlite3ValueSetNull(db->pErr); } } /* ** Add an error message to pParse->zErrMsg and increment pParse->nErr. Index: src/vdbe.c ================================================================== --- src/vdbe.c +++ src/vdbe.c @@ -2504,11 +2504,11 @@ } } pDest->enc = encoding; op_column_out: - rc = sqlite3VdbeMemMakeWriteable(pDest); + Deephemeralize(pDest); op_column_error: UPDATE_MAX_BLOBSIZE(pDest); REGISTER_TRACE(pOp->p3, pDest); break; } @@ -2568,11 +2568,12 @@ Mem *pData0; /* First field to be combined into the record */ Mem *pLast; /* Last field of the record */ int nField; /* Number of fields in the record */ char *zAffinity; /* The affinity string for the record */ int file_format; /* File format to use for encoding */ - int i; /* Space used in zNewRecord[] */ + int i; /* Space used in zNewRecord[] header */ + int j; /* Space used in zNewRecord[] content */ int len; /* Length of a field */ /* Assuming the record contains N fields, the record format looks ** like this: ** @@ -2601,41 +2602,56 @@ /* Identify the output register */ assert( pOp->p3p1 || pOp->p3>=pOp->p1+pOp->p2 ); pOut = &aMem[pOp->p3]; memAboutToChange(p, pOut); + + /* Apply the requested affinity to all inputs + */ + assert( pData0<=pLast ); + if( zAffinity ){ + pRec = pData0; + do{ + applyAffinity(pRec, *(zAffinity++), encoding); + }while( (++pRec)<=pLast ); + } /* Loop through the elements that will make up the record to figure ** out how much space is required for the new record. */ - for(pRec=pData0; pRec<=pLast; pRec++){ + pRec = pLast; + do{ assert( memIsValid(pRec) ); - if( zAffinity ){ - applyAffinity(pRec, zAffinity[pRec-pData0], encoding); - } - if( pRec->flags&MEM_Zero && pRec->n>0 ){ - sqlite3VdbeMemExpandBlob(pRec); - } serial_type = sqlite3VdbeSerialType(pRec, file_format); len = sqlite3VdbeSerialTypeLen(serial_type); - nData += len; - nHdr += sqlite3VarintLen(serial_type); if( pRec->flags & MEM_Zero ){ - /* Only pure zero-filled BLOBs can be input to this Opcode. - ** We do not allow blobs with a prefix and a zero-filled tail. */ - nZero += pRec->u.nZero; - }else if( len ){ - nZero = 0; + if( nData ){ + sqlite3VdbeMemExpandBlob(pRec); + }else{ + nZero += pRec->u.nZero; + len -= pRec->u.nZero; + } } - } + nData += len; + testcase( serial_type==127 ); + testcase( serial_type==128 ); + nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type); + }while( (--pRec)>=pData0 ); /* Add the initial header varint and total the size */ - nHdr += nVarint = sqlite3VarintLen(nHdr); - if( nVarintdb->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } /* Make sure the output register has a buffer large enough to store @@ -2648,18 +2664,20 @@ } zNewRecord = (u8 *)pOut->z; /* Write the record */ i = putVarint32(zNewRecord, nHdr); - for(pRec=pData0; pRec<=pLast; pRec++){ + j = nHdr; + assert( pData0<=pLast ); + pRec = pData0; + do{ serial_type = sqlite3VdbeSerialType(pRec, file_format); - i += putVarint32(&zNewRecord[i], serial_type); /* serial type */ - } - for(pRec=pData0; pRec<=pLast; pRec++){ /* serial data */ - i += sqlite3VdbeSerialPut(&zNewRecord[i], (int)(nByte-i), pRec,file_format); - } - assert( i==nByte ); + i += putVarint32(&zNewRecord[i], serial_type); /* serial type */ + j += sqlite3VdbeSerialPut(&zNewRecord[j], pRec, serial_type); /* content */ + }while( (++pRec)<=pLast ); + assert( i==nHdr ); + assert( j==nByte ); assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) ); pOut->n = (int)nByte; pOut->flags = MEM_Blob | MEM_Dyn; pOut->xDel = 0; @@ -2684,10 +2702,11 @@ i64 nEntry; BtCursor *pCrsr; pCrsr = p->apCsr[pOp->p1]->pCursor; assert( pCrsr ); + nEntry = 0; /* Not needed. Only used to silence a warning. */ rc = sqlite3BtreeCount(pCrsr, &nEntry); pOut->u.i = nEntry; break; } #endif @@ -3704,18 +3723,18 @@ #ifdef SQLITE_TEST if( pOp->opcode!=OP_NoConflict ) sqlite3_found_count++; #endif - alreadyExists = 0; assert( pOp->p1>=0 && pOp->p1nCursor ); assert( pOp->p4type==P4_INT32 ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); pIn3 = &aMem[pOp->p3]; assert( pC->pCursor!=0 ); assert( pC->isTable==0 ); + pFree = 0; /* Not needed. Only used to suppress a compiler warning. */ if( pOp->p4.i>0 ){ r.pKeyInfo = pC->pKeyInfo; r.nField = (u16)pOp->p4.i; r.aMem = pIn3; #ifdef SQLITE_DEBUG @@ -4695,10 +4714,11 @@ rc = sqlite3VdbeCursorMoveto(pC); if( NEVER(rc) ) goto abort_due_to_error; assert( pC->deferredMoveto==0 ); assert( pC->isTable==0 ); if( !pC->nullRow ){ + rowid = 0; /* Not needed. Only used to silence a warning. */ rc = sqlite3VdbeIdxRowid(db, pCrsr, &rowid); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } pOut->u.i = rowid; @@ -4758,10 +4778,11 @@ } r.aMem = &aMem[pOp->p3]; #ifdef SQLITE_DEBUG { int i; for(i=0; iopcode==OP_IdxLT ){ res = -res; }else{ assert( pOp->opcode==OP_IdxGE ); @@ -4818,10 +4839,11 @@ p->errorAction = OE_Abort; }else{ iDb = pOp->p3; assert( iCnt==1 ); assert( (p->btreeMask & (((yDbMask)1)<aDb[iDb].pBt, pOp->p1, &iMoved); pOut->flags = MEM_Int; pOut->u.i = iMoved; #ifndef SQLITE_OMIT_AUTOVACUUM if( rc==SQLITE_OK && iMoved!=0 ){ @@ -5390,11 +5412,10 @@ ** ** This instruction throws an error if the memory cell is not initially ** an integer. */ case OP_MemMax: { /* in2 */ - Mem *pIn1; VdbeFrame *pFrame; if( p->pFrame ){ for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent); pIn1 = &pFrame->aMem[pOp->p1]; }else{ Index: src/vdbeInt.h ================================================================== --- src/vdbeInt.h +++ src/vdbeInt.h @@ -406,11 +406,11 @@ #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) void sqlite3VdbePrintOp(FILE*, int, Op*); #endif u32 sqlite3VdbeSerialTypeLen(u32); u32 sqlite3VdbeSerialType(Mem*, int); -u32 sqlite3VdbeSerialPut(unsigned char*, int, Mem*, int); +u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32); u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); void sqlite3VdbeDeleteAuxData(Vdbe*, int, int); int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *); int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*); Index: src/vdbeapi.c ================================================================== --- src/vdbeapi.c +++ src/vdbeapi.c @@ -484,20 +484,21 @@ && (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){ sqlite3_reset(pStmt); v->doingRerun = 1; assert( v->expired==0 ); } - if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){ + if( rc2!=SQLITE_OK ){ /* This case occurs after failing to recompile an sql statement. ** The error message from the SQL compiler has already been loaded ** into the database handle. This block copies the error message ** from the database handle into the statement and sets the statement ** program counter to 0 to ensure that when the statement is ** finalized or reset the parser error message is available via ** sqlite3_errmsg() and sqlite3_errcode(). */ const char *zErr = (const char *)sqlite3_value_text(db->pErr); + assert( zErr!=0 || db->mallocFailed ); sqlite3DbFree(db, v->zErrMsg); if( !db->mallocFailed ){ v->zErrMsg = sqlite3DbStrDup(db, zErr); v->rc = rc2; } else { @@ -1330,10 +1331,11 @@ char *dummy; /* Dummy argument for AllocUnpackedRecord() */ UnpackedRecord *pRet; /* Return value */ pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo, 0, 0, &dummy); if( pRet ){ + memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nField+1)); sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, pRet); } return pRet; } Index: src/vdbeaux.c ================================================================== --- src/vdbeaux.c +++ src/vdbeaux.c @@ -2419,10 +2419,11 @@ sqlite3 *db = p->db; int rc = p->rc; if( p->zErrMsg ){ u8 mallocFailed = db->mallocFailed; sqlite3BeginBenignMalloc(); + if( db->pErr==0 ) db->pErr = sqlite3ValueNew(db); sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT); sqlite3EndBenignMalloc(); db->mallocFailed = mallocFailed; db->errCode = rc; }else{ @@ -2487,12 +2488,11 @@ }else if( p->rc && p->expired ){ /* The expired flag was set on the VDBE before the first call ** to sqlite3_step(). For consistency (since sqlite3_step() was ** called), set the database error in this case as well. */ - sqlite3Error(db, p->rc, 0); - sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT); + sqlite3Error(db, p->rc, p->zErrMsg ? "%s" : 0, p->zErrMsg); sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = 0; } /* Reclaim all memory used by the VDBE @@ -2826,25 +2826,19 @@ /* ** Write the serialized data blob for the value stored in pMem into ** buf. It is assumed that the caller has allocated sufficient space. ** Return the number of bytes written. ** -** nBuf is the amount of space left in buf[]. nBuf must always be -** large enough to hold the entire field. Except, if the field is -** a blob with a zero-filled tail, then buf[] might be just the right -** size to hold everything except for the zero-filled tail. If buf[] -** is only big enough to hold the non-zero prefix, then only write that -** prefix into buf[]. But if buf[] is large enough to hold both the -** prefix and the tail then write the prefix and set the tail to all -** zeros. +** nBuf is the amount of space left in buf[]. The caller is responsible +** for allocating enough space to buf[] to hold the entire field, exclusive +** of the pMem->u.nZero bytes for a MEM_Zero value. ** ** Return the number of bytes actually written into buf[]. The number ** of bytes in the zero-filled tail is included in the return value only ** if those bytes were zeroed in buf[]. */ -u32 sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_format){ - u32 serial_type = sqlite3VdbeSerialType(pMem, file_format); +u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){ u32 len; /* Integer and Real */ if( serial_type<=7 && serial_type>0 ){ u64 v; @@ -2855,11 +2849,10 @@ swapMixedEndianFloat(v); }else{ v = pMem->u.i; } len = i = sqlite3VdbeSerialTypeLen(serial_type); - assert( len<=(u32)nBuf ); while( i-- ){ buf[i] = (u8)(v&0xFF); v >>= 8; } return len; @@ -2867,21 +2860,12 @@ /* String or blob */ if( serial_type>=12 ){ assert( pMem->n + ((pMem->flags & MEM_Zero)?pMem->u.nZero:0) == (int)sqlite3VdbeSerialTypeLen(serial_type) ); - assert( pMem->n<=nBuf ); len = pMem->n; memcpy(buf, pMem->z, len); - if( pMem->flags & MEM_Zero ){ - len += pMem->u.nZero; - assert( nBuf>=0 ); - if( len > (u32)nBuf ){ - len = (u32)nBuf; - } - memset(&buf[pMem->n], 0, len-pMem->n); - } return len; } /* NULL or constants 0 or 1 */ return 0; Index: src/vdbemem.c ================================================================== --- src/vdbemem.c +++ src/vdbemem.c @@ -57,61 +57,59 @@ #endif } /* ** Make sure pMem->z points to a writable allocation of at least -** n bytes. -** -** If the third argument passed to this function is true, then memory -** cell pMem must contain a string or blob. In this case the content is -** preserved. Otherwise, if the third parameter to this function is false, -** any current string or blob value may be discarded. -** -** This function sets the MEM_Dyn flag and clears any xDel callback. -** It also clears MEM_Ephem and MEM_Static. If the preserve flag is -** not set, Mem.n is zeroed. -*/ -int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){ +** min(n,32) bytes. +** +** If the bPreserve argument is true, then copy of the content of +** pMem->z into the new allocation. pMem must be either a string or +** blob if bPreserve is true. If bPreserve is false, any prior content +** in pMem->z is discarded. +*/ +int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ assert( 1 >= ((pMem->zMalloc && pMem->zMalloc==pMem->z) ? 1 : 0) + (((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) + ((pMem->flags&MEM_Ephem) ? 1 : 0) + ((pMem->flags&MEM_Static) ? 1 : 0) ); assert( (pMem->flags&MEM_RowSet)==0 ); - /* If the preserve flag is set to true, then the memory cell must already + /* If the bPreserve flag is set to true, then the memory cell must already ** contain a valid string or blob value. */ - assert( preserve==0 || pMem->flags&(MEM_Blob|MEM_Str) ); + assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) ); + testcase( bPreserve && pMem->z==0 ); - if( n<32 ) n = 32; - if( sqlite3DbMallocSize(pMem->db, pMem->zMalloc)z==pMem->zMalloc ){ + if( pMem->zMalloc==0 || sqlite3DbMallocSize(pMem->db, pMem->zMalloc)z==pMem->zMalloc ){ pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n); - preserve = 0; + bPreserve = 0; }else{ sqlite3DbFree(pMem->db, pMem->zMalloc); pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n); } + if( pMem->zMalloc==0 ){ + sqlite3VdbeMemRelease(pMem); + pMem->flags = MEM_Null; + return SQLITE_NOMEM; + } } - if( pMem->z && preserve && pMem->zMalloc && pMem->z!=pMem->zMalloc ){ + if( pMem->z && bPreserve && pMem->z!=pMem->zMalloc ){ memcpy(pMem->zMalloc, pMem->z, pMem->n); } - if( pMem->flags&MEM_Dyn && pMem->xDel ){ + if( (pMem->flags&MEM_Dyn)!=0 && pMem->xDel ){ assert( pMem->xDel!=SQLITE_DYNAMIC ); pMem->xDel((void *)(pMem->z)); } pMem->z = pMem->zMalloc; - if( pMem->z==0 ){ - pMem->flags = MEM_Null; - }else{ - pMem->flags &= ~(MEM_Ephem|MEM_Static); - } + pMem->flags &= ~(MEM_Ephem|MEM_Static); pMem->xDel = 0; - return (pMem->z ? SQLITE_OK : SQLITE_NOMEM); + return SQLITE_OK; } /* ** Make the given Mem object MEM_Dyn. In other words, make it so ** that any TEXT or BLOB content is stored in memory obtained from @@ -293,14 +291,16 @@ ** inconsistent state, for example with (Mem.z==0) and ** (Mem.type==SQLITE_TEXT). */ void sqlite3VdbeMemRelease(Mem *p){ VdbeMemRelease(p); - sqlite3DbFree(p->db, p->zMalloc); + if( p->zMalloc ){ + sqlite3DbFree(p->db, p->zMalloc); + p->zMalloc = 0; + } p->z = 0; - p->zMalloc = 0; - p->xDel = 0; + assert( p->xDel==0 ); /* Zeroed by VdbeMemRelease() above */ } /* ** Convert a 64-bit IEEE double into a 64-bit signed integer. ** If the double is out of range of a 64-bit signed integer then @@ -479,10 +479,13 @@ if( pMem->flags & MEM_RowSet ){ sqlite3RowSetClear(pMem->u.pRowSet); } MemSetTypeFlag(pMem, MEM_Null); pMem->type = SQLITE_NULL; +} +void sqlite3ValueSetNull(sqlite3_value *p){ + sqlite3VdbeMemSetNull((Mem*)p); } /* ** Delete any previous value and set the value to be a BLOB of length ** n containing all zeros. @@ -1217,11 +1220,11 @@ if( aRet==0 ){ sqlite3_result_error_nomem(context); }else{ aRet[0] = nSerial+1; sqlite3PutVarint(&aRet[1], iSerial); - sqlite3VdbeSerialPut(&aRet[1+nSerial], nVal, argv[0], file_format); + sqlite3VdbeSerialPut(&aRet[1+nSerial], argv[0], iSerial); sqlite3_result_blob(context, aRet, nRet, SQLITE_TRANSIENT); sqlite3DbFree(db, aRet); } } Index: src/vdbetrace.c ================================================================== --- src/vdbetrace.c +++ src/vdbetrace.c @@ -90,10 +90,11 @@ if( db->nVdbeExec>1 ){ while( *zRawSql ){ const char *zStart = zRawSql; while( *(zRawSql++)!='\n' && *zRawSql ); sqlite3StrAccumAppend(&out, "-- ", 3); + assert( (zRawSql - zStart) > 0 ); sqlite3StrAccumAppend(&out, zStart, (int)(zRawSql-zStart)); } }else{ while( zRawSql[0] ){ n = findNextHostParameter(zRawSql, &nToken); Index: src/where.c ================================================================== --- src/where.c +++ src/where.c @@ -2566,11 +2566,11 @@ int iTerm, /* Index of this term. First is zero */ const char *zColumn, /* Name of the column */ const char *zOp /* Name of the operator */ ){ if( iTerm ) sqlite3StrAccumAppend(pStr, " AND ", 5); - sqlite3StrAccumAppend(pStr, zColumn, -1); + sqlite3StrAccumAppendAll(pStr, zColumn); sqlite3StrAccumAppend(pStr, zOp, 1); sqlite3StrAccumAppend(pStr, "?", 1); } /* @@ -2612,11 +2612,11 @@ if( i>=nSkip ){ explainAppendTerm(&txt, i, z, "="); }else{ if( i ) sqlite3StrAccumAppend(&txt, " AND ", 5); sqlite3StrAccumAppend(&txt, "ANY(", 4); - sqlite3StrAccumAppend(&txt, z, -1); + sqlite3StrAccumAppendAll(&txt, z); sqlite3StrAccumAppend(&txt, ")", 1); } } j = i; Index: test/capi3.test ================================================================== --- test/capi3.test +++ test/capi3.test @@ -1189,10 +1189,11 @@ } {SQLITE_ERROR} do_test capi3-18.2 { sqlite3_reset $STMT sqlite3_errcode db } {SQLITE_SCHEMA} +breakpoint do_test capi3-18.3 { sqlite3_errmsg db } {database schema has changed} # The error persist on retry when sqlite3_prepare() has been used. do_test capi3-18.4 { Index: test/func5.test ================================================================== --- test/func5.test +++ test/func5.test @@ -7,17 +7,19 @@ # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #************************************************************************* # -# Verify that constant string expressions that get factored into initializing -# code are not reused between function parameters and other values in the -# VDBE program, as the function might have changed the encoding. +# Testing of function factoring and the SQLITE_DETERMINISTIC flag. # set testdir [file dirname $argv0] source $testdir/tester.tcl +# Verify that constant string expressions that get factored into initializing +# code are not reused between function parameters and other values in the +# VDBE program, as the function might have changed the encoding. +# do_execsql_test func5-1.1 { PRAGMA encoding=UTF16le; CREATE TABLE t1(x,a,b,c); INSERT INTO t1 VALUES(1,'ab','cd',1); INSERT INTO t1 VALUES(2,'gh','ef',5); @@ -27,7 +29,35 @@ SELECT x FROM t1 WHERE c=instr('abcdefg',b) OR a='abcdefg' ORDER BY +x; } {2 4} do_execsql_test func5-1.2 { SELECT x FROM t1 WHERE a='abcdefg' OR c=instr('abcdefg',b) ORDER BY +x; } {2 4} + +# Verify that SQLITE_DETERMINISTIC functions get factored out of the +# evaluation loop whereas non-deterministic functions do not. counter1() +# is marked as non-deterministic and so is not factored out of the loop, +# and it really is non-deterministic, returning a different result each +# time. But counter2() is marked as deterministic, so it does get factored +# out of the loop. counter2() has the same implementation as counter1(), +# returning a different result on each invocation, but because it is +# only invoked once outside of the loop, it appears to return the same +# result multiple times. +# +do_execsql_test func5-2.1 { + CREATE TABLE t2(x,y); + INSERT INTO t2 VALUES(1,2),(3,4),(5,6),(7,8); + SELECT x, y FROM t2 WHERE x+5=5+x ORDER BY +x; +} {1 2 3 4 5 6 7 8} +sqlite3_create_function db +do_execsql_test func5-2.2 { + SELECT x, y FROM t2 + WHERE x+counter1('hello')=counter1('hello')+x + ORDER BY +x; +} {} +do_execsql_test func5-2.3 { + SELECT x, y FROM t2 + WHERE x+counter2('hello')=counter2('hello')+x + ORDER BY +x; +} {1 2 3 4 5 6 7 8} + finish_test ADDED test/pager4.test Index: test/pager4.test ================================================================== --- /dev/null +++ test/pager4.test @@ -0,0 +1,94 @@ +# 2013-12-06 +# +# 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. +# +#*********************************************************************** +# +# Tests for the SQLITE_IOERR_NODB error condition: the database file file +# is unlinked or renamed out from under SQLite. +# + +if {$tcl_platform(platform)!="unix"} return + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +# Create a database file for testing +# +do_execsql_test pager4-1.1 { + CREATE TABLE t1(a,b,c); + INSERT INTO t1 VALUES(673,'stone','philips'); + SELECT * FROM t1; +} {673 stone philips} + +# After renaming the database file while it is open, one can still +# read from the database, but writing returns a READONLY error. +# +file delete -force test-xyz.db +file rename test.db test-xyz.db +do_catchsql_test pager4-1.2 { + SELECT * FROM t1; +} {0 {673 stone philips}} +do_catchsql_test pager4-1.3 { + UPDATE t1 SET a=537; +} {1 {attempt to write a readonly database}} + +# Creating a different database file with the same name of the original +# is detected and still leaves the database read-only. +# +sqlite3 db2 test.db +db2 eval {CREATE TABLE t2(x,y,z)} +do_catchsql_test pager4-1.4 { + UPDATE t1 SET a=948; +} {1 {attempt to write a readonly database}} + +# Changing the name back clears the READONLY error +# +db2 close +file delete -force test.db +file rename test-xyz.db test.db +do_catchsql_test pager4-1.5 { + SELECT * FROM t1; +} {0 {673 stone philips}} +do_catchsql_test pager4-1.6 { + UPDATE t1 SET a=537; + SELECT * FROM t1; +} {0 {537 stone philips}} + +# We can write to a renamed database if journal_mode=OFF or +# journal_mode=MEMORY. +# +file rename test.db test-xyz.db +do_catchsql_test pager4-1.7 { + PRAGMA journal_mode=OFF; + UPDATE t1 SET a=107; + SELECT * FROM t1; +} {0 {off 107 stone philips}} +do_catchsql_test pager4-1.8 { + PRAGMA journal_mode=MEMORY; + UPDATE t1 SET b='magpie'; + SELECT * FROM t1; +} {0 {memory 107 magpie philips}} + +# Any other journal mode gives a READONLY error +# +do_catchsql_test pager4-1.9 { + PRAGMA journal_mode=DELETE; + UPDATE t1 SET c='jaguar'; +} {1 {attempt to write a readonly database}} +do_catchsql_test pager4-1.10 { + PRAGMA journal_mode=TRUNCATE; + UPDATE t1 SET c='jaguar'; +} {1 {attempt to write a readonly database}} +do_catchsql_test pager4-1.11 { + PRAGMA journal_mode=PERSIST; + UPDATE t1 SET c='jaguar'; +} {1 {attempt to write a readonly database}} + + +finish_test Index: test/shell5.test ================================================================== --- test/shell5.test +++ test/shell5.test @@ -264,8 +264,27 @@ .import shell5.csv t1 } sqlite3 db test.db db eval {SELECT *, '|' FROM t1 ORDER BY rowid} } {1 {} 11 | 2 x 22 | 3 {"} 33 | 4 hello 44 | 5 55 {} | 6 66 x | 7 77 {"} | 8 88 hello | {} 9 99 | x 10 110 | {"} 11 121 | hello 12 132 |} +db close + +# Import columns containing quoted strings +do_test shell5-1.10 { + set out [open shell5.csv w] + fconfigure $out -translation lf + puts $out {column1,column2,column3,column4} + puts $out "field1,field2,\"x3 \"\"\r\ndata\"\" 3\",field4" + puts $out "x1,x2,\"x3 \"\"\ndata\"\" 3\",x4" + close $out + forcedelete test.db + catchcmd test.db {.mode csv + CREATE TABLE t1(a,b,c,d); +.import shell5.csv t1 + } + sqlite3 db test.db + db eval {SELECT hex(c) FROM t1 ORDER BY rowid} +} {636F6C756D6E33 783320220D0A64617461222033 783320220A64617461222033} + db close finish_test Index: test/speedtest1.c ================================================================== --- test/speedtest1.c +++ test/speedtest1.c @@ -663,11 +663,11 @@ speedtest1_exec("REPLACE INTO t3(a,b,c) SELECT a,b,c FROM t1"); speedtest1_end_test(); n = sz/5; - speedtest1_begin_test(290, "%d four-ways joins", n); + speedtest1_begin_test(300, "%d four-ways joins", n); speedtest1_exec("BEGIN"); speedtest1_prepare( "SELECT t1.c FROM t1, t2, t3, t4\n" " WHERE t4.a BETWEEN ?1 AND ?2\n" " AND t3.a=t4.b\n" Index: test/tester.tcl ================================================================== --- test/tester.tcl +++ test/tester.tcl @@ -1255,10 +1255,11 @@ proc crashsql {args} { set blocksize "" set crashdelay 1 set prngseed 0 + set opendb { sqlite3 db test.db -vfs crash } set tclbody {} set crashfile "" set dc "" set sql [lindex $args end] @@ -1266,10 +1267,11 @@ set z [lindex $args $ii] set n [string length $z] set z2 [lindex $args [expr $ii+1]] if {$n>1 && [string first $z -delay]==0} {set crashdelay $z2} \ + elseif {$n>1 && [string first $z -opendb]==0} {set opendb $z2} \ elseif {$n>1 && [string first $z -seed]==0} {set prngseed $z2} \ elseif {$n>1 && [string first $z -file]==0} {set crashfile $z2} \ elseif {$n>1 && [string first $z -tclbody]==0} {set tclbody $z2} \ elseif {$n>1 && [string first $z -blocksize]==0} {set blocksize "-s $z2" } \ elseif {$n>1 && [string first $z -characteristics]==0} {set dc "-c {$z2}" } \ @@ -1287,18 +1289,19 @@ set f [open crash.tcl w] puts $f "sqlite3_crash_enable 1" puts $f "sqlite3_crashparams $blocksize $dc $crashdelay $cfile" puts $f "sqlite3_test_control_pending_byte $::sqlite_pending_byte" - puts $f "sqlite3 db test.db -vfs crash" + puts $f $opendb # This block sets the cache size of the main database to 10 # pages. This is done in case the build is configured to omit # "PRAGMA cache_size". puts $f {db eval {SELECT * FROM sqlite_master;}} puts $f {set bt [btree_from_db db]} puts $f {btree_set_cache_size $bt 10} + if {$prngseed} { set seed [expr {$prngseed%10007+1}] # puts seed=$seed puts $f "db eval {SELECT randomblob($seed)}" } Index: test/win32longpath.test ================================================================== --- test/win32longpath.test +++ test/win32longpath.test @@ -16,16 +16,24 @@ if {$tcl_platform(platform)!="windows"} return set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix win32longpath + +do_test 1.0 { + file_control_vfsname db +} win32 db close set path [file nativename [get_pwd]] sqlite3 db [file join $path test.db] -vfs win32-longpath do_test 1.1 { + file_control_vfsname db +} win32-longpath + +do_test 1.2 { db eval { BEGIN EXCLUSIVE; CREATE TABLE t1(x); INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(2); @@ -45,17 +53,17 @@ set longPath(3) $longPath(2)\\[string repeat Y 255] make_win32_dir $longPath(3) set fileName $longPath(3)\\test.db -do_test 1.2 { +do_test 1.3 { list [catch {sqlite3 db2 [string range $fileName 4 end]} msg] $msg } {1 {unable to open database file}} sqlite3 db3 $fileName -vfs win32-longpath -do_test 1.3 { +do_test 1.4 { db3 eval { BEGIN EXCLUSIVE; CREATE TABLE t1(x); INSERT INTO t1 VALUES(5); INSERT INTO t1 VALUES(6); @@ -69,17 +77,17 @@ db3 close # puts " Database exists \{[exists_win32_path $fileName]\}" sqlite3 db3 $fileName -vfs win32-longpath -do_test 1.4 { +do_test 1.5 { db3 eval { PRAGMA journal_mode = WAL; } } {wal} -do_test 1.5 { +do_test 1.6 { db3 eval { BEGIN EXCLUSIVE; INSERT INTO t1 VALUES(9); INSERT INTO t1 VALUES(10); INSERT INTO t1 VALUES(11); Index: tool/vdbe-compress.tcl ================================================================== --- tool/vdbe-compress.tcl +++ tool/vdbe-compress.tcl @@ -11,11 +11,11 @@ # stack space. # # Script usage: # # mv vdbe.c vdbe.c.template -# tclsh vdbe-compress.tcl vdbe.c +# tclsh vdbe-compress.tcl $CFLAGS vdbe.c # # Modifications made: # # All modifications are within the sqlite3VdbeExec() function. The # modifications seek to reduce the amount of stack space allocated by @@ -39,10 +39,20 @@ # set beforeUnion {} ;# C code before union set unionDef {} ;# C code of the union set afterUnion {} ;# C code after the union set sCtr 0 ;# Context counter + +# If the SQLITE_SMALL_STACK compile-time option is missing, then +# this transformation becomes a no-op. +# +if {![regexp {SQLITE_SMALL_STACK} $argv]} { + while {![eof stdin]} { + puts [gets stdin] + } + exit +} # Read program text up to the spot where the union should be # inserted. # while {![eof stdin]} {