mirror of
https://github.com/status-im/sqlcipher.git
synced 2026-08-31 06:21:07 +00:00
Merge branch 'master' into ditto
This commit is contained in:
+2
-2
@@ -479,9 +479,9 @@ void sqlite3AlterRenameTable(
|
||||
** for which the renamed table is the parent table. */
|
||||
if( (zWhere=whereForeignKeys(pParse, pTab))!=0 ){
|
||||
sqlite3NestedParse(pParse,
|
||||
"UPDATE sqlite_master SET "
|
||||
"UPDATE \"%w\".%s SET "
|
||||
"sql = sqlite_rename_parent(sql, %Q, %Q) "
|
||||
"WHERE %s;", zTabName, zName, zWhere);
|
||||
"WHERE %s;", zDb, SCHEMA_TABLE(iDb), zTabName, zName, zWhere);
|
||||
sqlite3DbFree(db, zWhere);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -559,9 +559,7 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
|
||||
if( zSql==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
(void)sqlite3SafetyOff(db);
|
||||
rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0);
|
||||
(void)sqlite3SafetyOn(db);
|
||||
sqlite3DbFree(db, zSql);
|
||||
}
|
||||
|
||||
@@ -579,14 +577,11 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
|
||||
if( !zSql ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
(void)sqlite3SafetyOff(db);
|
||||
rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
|
||||
(void)sqlite3SafetyOn(db);
|
||||
sqlite3DbFree(db, zSql);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
(void)sqlite3SafetyOff(db);
|
||||
while( sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
char *zIndex = (char *)sqlite3_column_text(pStmt, 0);
|
||||
Index *pIdx = sqlite3FindIndex(db, zIndex, sInfo.zDatabase);
|
||||
@@ -636,7 +631,6 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
|
||||
}
|
||||
}
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
(void)sqlite3SafetyOn(db);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
+8
-4
@@ -144,11 +144,17 @@ static void attachFunc(
|
||||
pPager = sqlite3BtreePager(aNew->pBt);
|
||||
sqlite3PagerLockingMode(pPager, db->dfltLockMode);
|
||||
sqlite3PagerJournalMode(pPager, db->dfltJournalMode);
|
||||
sqlite3BtreeSecureDelete(aNew->pBt,
|
||||
sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) );
|
||||
}
|
||||
aNew->zName = sqlite3DbStrDup(db, zName);
|
||||
aNew->safety_level = 3;
|
||||
aNew->zName = sqlite3DbStrDup(db, zName);
|
||||
if( rc==SQLITE_OK && aNew->zName==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
|
||||
#if SQLITE_HAS_CODEC
|
||||
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
if( rc==SQLITE_OK ){
|
||||
extern int sqlite3CodecAttach(sqlite3*, int, const void*, int);
|
||||
extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);
|
||||
@@ -184,11 +190,9 @@ static void attachFunc(
|
||||
** we found it.
|
||||
*/
|
||||
if( rc==SQLITE_OK ){
|
||||
(void)sqlite3SafetyOn(db);
|
||||
sqlite3BtreeEnterAll(db);
|
||||
rc = sqlite3Init(db, &zErrDyn);
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
(void)sqlite3SafetyOff(db);
|
||||
}
|
||||
if( rc ){
|
||||
int iDb = db->nDb - 1;
|
||||
|
||||
+1
-1
@@ -98,10 +98,10 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
|
||||
}else{
|
||||
pParse->db = pDb;
|
||||
if( sqlite3OpenTempDatabase(pParse) ){
|
||||
sqlite3ErrorClear(pParse);
|
||||
sqlite3Error(pErrorDb, pParse->rc, "%s", pParse->zErrMsg);
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
sqlite3DbFree(pErrorDb, pParse->zErrMsg);
|
||||
sqlite3StackFree(pErrorDb, pParse);
|
||||
}
|
||||
if( rc ){
|
||||
|
||||
+129
-35
@@ -1247,11 +1247,11 @@ static int freeSpace(MemPage *pPage, int start, int size){
|
||||
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||
assert( size>=0 ); /* Minimum cell size is 4 */
|
||||
|
||||
#ifdef SQLITE_SECURE_DELETE
|
||||
/* Overwrite deleted information with zeros when the SECURE_DELETE
|
||||
** option is enabled at compile-time */
|
||||
memset(&data[start], 0, size);
|
||||
#endif
|
||||
if( pPage->pBt->secureDelete ){
|
||||
/* Overwrite deleted information with zeros when the secure_delete
|
||||
** option is enabled */
|
||||
memset(&data[start], 0, size);
|
||||
}
|
||||
|
||||
/* Add the space back into the linked list of freeblocks. Note that
|
||||
** even though the freeblock list was checked by btreeInitPage(),
|
||||
@@ -1483,9 +1483,9 @@ static void zeroPage(MemPage *pPage, int flags){
|
||||
assert( sqlite3PagerGetData(pPage->pDbPage) == data );
|
||||
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
|
||||
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||
#ifdef SQLITE_SECURE_DELETE
|
||||
memset(&data[hdr], 0, pBt->usableSize - hdr);
|
||||
#endif
|
||||
if( pBt->secureDelete ){
|
||||
memset(&data[hdr], 0, pBt->usableSize - hdr);
|
||||
}
|
||||
data[hdr] = (char)flags;
|
||||
first = hdr + 8 + 4*((flags&PTF_LEAF)==0 ?1:0);
|
||||
memset(&data[hdr+1], 0, 4);
|
||||
@@ -1805,6 +1805,9 @@ int sqlite3BtreeOpen(
|
||||
pBt->pCursor = 0;
|
||||
pBt->pPage1 = 0;
|
||||
pBt->readOnly = sqlite3PagerIsreadonly(pBt->pPager);
|
||||
#ifdef SQLITE_SECURE_DELETE
|
||||
pBt->secureDelete = 1;
|
||||
#endif
|
||||
pBt->pageSize = get2byte(&zDbHeader[16]);
|
||||
if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE
|
||||
|| ((pBt->pageSize-1)&pBt->pageSize)!=0 ){
|
||||
@@ -2161,6 +2164,23 @@ int sqlite3BtreeMaxPageCount(Btree *p, int mxPage){
|
||||
sqlite3BtreeLeave(p);
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the secureDelete flag if newFlag is 0 or 1. If newFlag is -1,
|
||||
** then make no changes. Always return the value of the secureDelete
|
||||
** setting after the change.
|
||||
*/
|
||||
int sqlite3BtreeSecureDelete(Btree *p, int newFlag){
|
||||
int b;
|
||||
if( p==0 ) return 0;
|
||||
sqlite3BtreeEnter(p);
|
||||
if( newFlag>=0 ){
|
||||
p->pBt->secureDelete = (newFlag!=0) ? 1 : 0;
|
||||
}
|
||||
b = p->pBt->secureDelete;
|
||||
sqlite3BtreeLeave(p);
|
||||
return b;
|
||||
}
|
||||
#endif /* !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) */
|
||||
|
||||
/*
|
||||
@@ -4904,17 +4924,17 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
|
||||
nFree = get4byte(&pPage1->aData[36]);
|
||||
put4byte(&pPage1->aData[36], nFree+1);
|
||||
|
||||
#ifdef SQLITE_SECURE_DELETE
|
||||
/* If the SQLITE_SECURE_DELETE compile-time option is enabled, then
|
||||
** always fully overwrite deleted information with zeros.
|
||||
*/
|
||||
if( (!pPage && (rc = btreeGetPage(pBt, iPage, &pPage, 0)))
|
||||
|| (rc = sqlite3PagerWrite(pPage->pDbPage))
|
||||
){
|
||||
goto freepage_out;
|
||||
if( pBt->secureDelete ){
|
||||
/* If the secure_delete option is enabled, then
|
||||
** always fully overwrite deleted information with zeros.
|
||||
*/
|
||||
if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0) )
|
||||
|| ((rc = sqlite3PagerWrite(pPage->pDbPage))!=0)
|
||||
){
|
||||
goto freepage_out;
|
||||
}
|
||||
memset(pPage->aData, 0, pPage->pBt->pageSize);
|
||||
}
|
||||
memset(pPage->aData, 0, pPage->pBt->pageSize);
|
||||
#endif
|
||||
|
||||
/* If the database supports auto-vacuum, write an entry in the pointer-map
|
||||
** to indicate that the page is free.
|
||||
@@ -4965,11 +4985,9 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
|
||||
if( rc==SQLITE_OK ){
|
||||
put4byte(&pTrunk->aData[4], nLeaf+1);
|
||||
put4byte(&pTrunk->aData[8+nLeaf*4], iPage);
|
||||
#ifndef SQLITE_SECURE_DELETE
|
||||
if( pPage ){
|
||||
if( pPage && !pBt->secureDelete ){
|
||||
sqlite3PagerDontWrite(pPage->pDbPage);
|
||||
}
|
||||
#endif
|
||||
rc = btreeSetHasContent(pBt, iPage);
|
||||
}
|
||||
TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno));
|
||||
@@ -5043,7 +5061,25 @@ static int clearCell(MemPage *pPage, unsigned char *pCell){
|
||||
rc = getOverflowPage(pBt, ovflPgno, &pOvfl, &iNext);
|
||||
if( rc ) return rc;
|
||||
}
|
||||
rc = freePage2(pBt, pOvfl, ovflPgno);
|
||||
|
||||
if( ( pOvfl || ((pOvfl = btreePageLookup(pBt, ovflPgno))!=0) )
|
||||
&& sqlite3PagerPageRefcount(pOvfl->pDbPage)!=1
|
||||
){
|
||||
/* There is no reason any cursor should have an outstanding reference
|
||||
** to an overflow page belonging to a cell that is being deleted/updated.
|
||||
** So if there exists more than one reference to this page, then it
|
||||
** must not really be an overflow page and the database must be corrupt.
|
||||
** It is helpful to detect this before calling freePage2(), as
|
||||
** freePage2() may zero the page contents if secure-delete mode is
|
||||
** enabled. If this 'overflow' page happens to be a page that the
|
||||
** caller is iterating through or using in some other way, this
|
||||
** can be problematic.
|
||||
*/
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}else{
|
||||
rc = freePage2(pBt, pOvfl, ovflPgno);
|
||||
}
|
||||
|
||||
if( pOvfl ){
|
||||
sqlite3PagerUnref(pOvfl->pDbPage);
|
||||
}
|
||||
@@ -5287,7 +5323,7 @@ static void insertCell(
|
||||
Pgno iChild, /* If non-zero, replace first 4 bytes with this value */
|
||||
int *pRC /* Read and write return code from here */
|
||||
){
|
||||
int idx; /* Where to write new cell content in data[] */
|
||||
int idx = 0; /* Where to write new cell content in data[] */
|
||||
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 */
|
||||
@@ -5778,10 +5814,17 @@ static int balance_nonroot(
|
||||
** In this case, temporarily copy the cell into the aOvflSpace[]
|
||||
** buffer. It will be copied out again as soon as the aSpace[] buffer
|
||||
** is allocated. */
|
||||
#ifdef SQLITE_SECURE_DELETE
|
||||
memcpy(&aOvflSpace[apDiv[i]-pParent->aData], apDiv[i], szNew[i]);
|
||||
apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData];
|
||||
#endif
|
||||
if( pBt->secureDelete ){
|
||||
int iOff = SQLITE_PTR_TO_INT(apDiv[i]) - SQLITE_PTR_TO_INT(pParent->aData);
|
||||
if( (iOff+szNew[i])>pBt->usableSize ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
memset(apOld, 0, (i+1)*sizeof(MemPage*));
|
||||
goto balance_cleanup;
|
||||
}else{
|
||||
memcpy(&aOvflSpace[iOff], apDiv[i], szNew[i]);
|
||||
apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData];
|
||||
}
|
||||
}
|
||||
dropCell(pParent, i+nxDiv-pParent->nOverflow, szNew[i], &rc);
|
||||
}
|
||||
}
|
||||
@@ -5901,7 +5944,7 @@ static int balance_nonroot(
|
||||
if( leafData ){ i--; }
|
||||
subtotal = 0;
|
||||
k++;
|
||||
if( k>NB+1 ){ rc = SQLITE_CORRUPT; goto balance_cleanup; }
|
||||
if( k>NB+1 ){ rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; }
|
||||
}
|
||||
}
|
||||
szNew[k] = subtotal;
|
||||
@@ -5955,7 +5998,7 @@ static int balance_nonroot(
|
||||
** Allocate k new pages. Reuse old pages where possible.
|
||||
*/
|
||||
if( apOld[0]->pgno<=1 ){
|
||||
rc = SQLITE_CORRUPT;
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto balance_cleanup;
|
||||
}
|
||||
pageFlags = apOld[0]->aData[0];
|
||||
@@ -7393,7 +7436,9 @@ static void checkList(
|
||||
static int checkTreePage(
|
||||
IntegrityCk *pCheck, /* Context for the sanity check */
|
||||
int iPage, /* Page number of the page to check */
|
||||
char *zParentContext /* Parent context */
|
||||
char *zParentContext, /* Parent context */
|
||||
i64 *pnParentMinKey,
|
||||
i64 *pnParentMaxKey
|
||||
){
|
||||
MemPage *pPage;
|
||||
int i, rc, depth, d2, pgno, cnt;
|
||||
@@ -7404,6 +7449,8 @@ static int checkTreePage(
|
||||
int usableSize;
|
||||
char zContext[100];
|
||||
char *hit = 0;
|
||||
i64 nMinKey = 0;
|
||||
i64 nMaxKey = 0;
|
||||
|
||||
sqlite3_snprintf(sizeof(zContext), zContext, "Page %d: ", iPage);
|
||||
|
||||
@@ -7446,6 +7493,16 @@ static int checkTreePage(
|
||||
btreeParseCellPtr(pPage, pCell, &info);
|
||||
sz = info.nData;
|
||||
if( !pPage->intKey ) sz += (int)info.nKey;
|
||||
/* For intKey pages, check that the keys are in order.
|
||||
*/
|
||||
else if( i==0 ) nMinKey = nMaxKey = info.nKey;
|
||||
else{
|
||||
if( info.nKey <= nMaxKey ){
|
||||
checkAppendMsg(pCheck, zContext,
|
||||
"Rowid %lld out of order (previous was %lld)", info.nKey, nMaxKey);
|
||||
}
|
||||
nMaxKey = info.nKey;
|
||||
}
|
||||
assert( sz==info.nPayload );
|
||||
if( (sz>info.nLocal)
|
||||
&& (&pCell[info.iOverflow]<=&pPage->aData[pBt->usableSize])
|
||||
@@ -7469,25 +7526,62 @@ static int checkTreePage(
|
||||
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext);
|
||||
}
|
||||
#endif
|
||||
d2 = checkTreePage(pCheck, pgno, zContext);
|
||||
d2 = checkTreePage(pCheck, pgno, zContext, &nMinKey, i==0 ? NULL : &nMaxKey);
|
||||
if( i>0 && d2!=depth ){
|
||||
checkAppendMsg(pCheck, zContext, "Child page depth differs");
|
||||
}
|
||||
depth = d2;
|
||||
}
|
||||
}
|
||||
|
||||
if( !pPage->leaf ){
|
||||
pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
|
||||
sqlite3_snprintf(sizeof(zContext), zContext,
|
||||
"On page %d at right child: ", iPage);
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
if( pBt->autoVacuum ){
|
||||
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, 0);
|
||||
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext);
|
||||
}
|
||||
#endif
|
||||
checkTreePage(pCheck, pgno, zContext);
|
||||
checkTreePage(pCheck, pgno, zContext, NULL, !pPage->nCell ? NULL : &nMaxKey);
|
||||
}
|
||||
|
||||
/* For intKey leaf pages, check that the min/max keys are in order
|
||||
** with any left/parent/right pages.
|
||||
*/
|
||||
if( pPage->leaf && pPage->intKey ){
|
||||
/* if we are a left child page */
|
||||
if( pnParentMinKey ){
|
||||
/* if we are the left most child page */
|
||||
if( !pnParentMaxKey ){
|
||||
if( nMaxKey > *pnParentMinKey ){
|
||||
checkAppendMsg(pCheck, zContext,
|
||||
"Rowid %lld out of order (max larger than parent min of %lld)",
|
||||
nMaxKey, *pnParentMinKey);
|
||||
}
|
||||
}else{
|
||||
if( nMinKey <= *pnParentMinKey ){
|
||||
checkAppendMsg(pCheck, zContext,
|
||||
"Rowid %lld out of order (min less than parent min of %lld)",
|
||||
nMinKey, *pnParentMinKey);
|
||||
}
|
||||
if( nMaxKey > *pnParentMaxKey ){
|
||||
checkAppendMsg(pCheck, zContext,
|
||||
"Rowid %lld out of order (max larger than parent max of %lld)",
|
||||
nMaxKey, *pnParentMaxKey);
|
||||
}
|
||||
*pnParentMinKey = nMaxKey;
|
||||
}
|
||||
/* else if we're a right child page */
|
||||
} else if( pnParentMaxKey ){
|
||||
if( nMinKey <= *pnParentMaxKey ){
|
||||
checkAppendMsg(pCheck, zContext,
|
||||
"Rowid %lld out of order (min less than parent max of %lld)",
|
||||
nMinKey, *pnParentMaxKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for complete coverage of the page
|
||||
*/
|
||||
data = pPage->aData;
|
||||
@@ -7511,7 +7605,7 @@ static int checkTreePage(
|
||||
}
|
||||
if( (pc+size-1)>=usableSize ){
|
||||
checkAppendMsg(pCheck, 0,
|
||||
"Corruption detected in cell %d on page %d",i,iPage,0);
|
||||
"Corruption detected in cell %d on page %d",i,iPage);
|
||||
}else{
|
||||
for(j=pc+size-1; j>=pc; j--) hit[j]++;
|
||||
}
|
||||
@@ -7617,7 +7711,7 @@ char *sqlite3BtreeIntegrityCheck(
|
||||
checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0, 0);
|
||||
}
|
||||
#endif
|
||||
checkTreePage(&sCheck, aRoot[i], "List of tree roots: ");
|
||||
checkTreePage(&sCheck, aRoot[i], "List of tree roots: ", NULL, NULL);
|
||||
}
|
||||
|
||||
/* Make sure every page in the file is referenced
|
||||
|
||||
@@ -81,6 +81,7 @@ int sqlite3BtreeSyncDisabled(Btree*);
|
||||
int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
|
||||
int sqlite3BtreeGetPageSize(Btree*);
|
||||
int sqlite3BtreeMaxPageCount(Btree*,int);
|
||||
int sqlite3BtreeSecureDelete(Btree*,int);
|
||||
int sqlite3BtreeGetReserve(Btree*);
|
||||
int sqlite3BtreeSetAutoVacuum(Btree *, int);
|
||||
int sqlite3BtreeGetAutoVacuum(Btree *);
|
||||
|
||||
@@ -407,6 +407,7 @@ struct BtShared {
|
||||
MemPage *pPage1; /* First page of the database */
|
||||
u8 readOnly; /* True if the underlying file is readonly */
|
||||
u8 pageSizeFixed; /* True if the page size can no longer be changed */
|
||||
u8 secureDelete; /* True if secure_delete is enabled */
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
u8 autoVacuum; /* True if auto-vacuum is enabled */
|
||||
u8 incrVacuum; /* True if incr-vacuum is enabled */
|
||||
|
||||
+13
-10
@@ -202,7 +202,7 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
pParse->isMultiWrite && pParse->mayAbort);
|
||||
pParse->rc = SQLITE_DONE;
|
||||
pParse->colNamesSet = 0;
|
||||
}else if( pParse->rc==SQLITE_OK ){
|
||||
}else{
|
||||
pParse->rc = SQLITE_ERROR;
|
||||
}
|
||||
pParse->nTab = 0;
|
||||
@@ -549,7 +549,8 @@ void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){
|
||||
|
||||
assert( db!=0 );
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
assert( zTabName && zTabName[0] );
|
||||
assert( zTabName );
|
||||
testcase( zTabName[0]==0 ); /* Zero-length table names are allowed */
|
||||
pDb = &db->aDb[iDb];
|
||||
p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName,
|
||||
sqlite3Strlen30(zTabName),0);
|
||||
@@ -1973,13 +1974,12 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
|
||||
}
|
||||
assert( pParse->nErr==0 );
|
||||
assert( pName->nSrc==1 );
|
||||
if( noErr ) db->suppressErr++;
|
||||
pTab = sqlite3LocateTable(pParse, isView,
|
||||
pName->a[0].zName, pName->a[0].zDatabase);
|
||||
if( noErr ) db->suppressErr--;
|
||||
|
||||
if( pTab==0 ){
|
||||
if( noErr ){
|
||||
sqlite3ErrorClear(pParse);
|
||||
}
|
||||
goto exit_drop_table;
|
||||
}
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
@@ -3401,6 +3401,7 @@ int sqlite3OpenTempDatabase(Parse *pParse){
|
||||
sqlite3 *db = pParse->db;
|
||||
if( db->aDb[1].pBt==0 && !pParse->explain ){
|
||||
int rc;
|
||||
Btree *pBt;
|
||||
static const int flags =
|
||||
SQLITE_OPEN_READWRITE |
|
||||
SQLITE_OPEN_CREATE |
|
||||
@@ -3408,18 +3409,20 @@ int sqlite3OpenTempDatabase(Parse *pParse){
|
||||
SQLITE_OPEN_DELETEONCLOSE |
|
||||
SQLITE_OPEN_TEMP_DB;
|
||||
|
||||
rc = sqlite3BtreeFactory(db, 0, 0, SQLITE_DEFAULT_CACHE_SIZE, flags,
|
||||
&db->aDb[1].pBt);
|
||||
rc = sqlite3BtreeFactory(db, 0, 0, SQLITE_DEFAULT_CACHE_SIZE, flags, &pBt);
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3ErrorMsg(pParse, "unable to open a temporary database "
|
||||
"file for storing temporary tables");
|
||||
pParse->rc = rc;
|
||||
return 1;
|
||||
}
|
||||
assert( (db->flags & SQLITE_InTrans)==0 || db->autoCommit );
|
||||
db->aDb[1].pBt = pBt;
|
||||
assert( db->aDb[1].pSchema );
|
||||
sqlite3PagerJournalMode(sqlite3BtreePager(db->aDb[1].pBt),
|
||||
db->dfltJournalMode);
|
||||
if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){
|
||||
db->mallocFailed = 1;
|
||||
return 1;
|
||||
}
|
||||
sqlite3PagerJournalMode(sqlite3BtreePager(pBt), db->dfltJournalMode);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
+31
-24
@@ -40,11 +40,13 @@ extern const char sqlite3IsEbcdicIdChar[];
|
||||
#define tkSEMI 0
|
||||
#define tkWS 1
|
||||
#define tkOTHER 2
|
||||
#ifndef SQLITE_OMIT_TRIGGER
|
||||
#define tkEXPLAIN 3
|
||||
#define tkCREATE 4
|
||||
#define tkTEMP 5
|
||||
#define tkTRIGGER 6
|
||||
#define tkEND 7
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Return TRUE if the given SQL string ends in a semicolon.
|
||||
@@ -53,36 +55,38 @@ extern const char sqlite3IsEbcdicIdChar[];
|
||||
** Whenever the CREATE TRIGGER keywords are seen, the statement
|
||||
** must end with ";END;".
|
||||
**
|
||||
** This implementation uses a state machine with 7 states:
|
||||
** This implementation uses a state machine with 8 states:
|
||||
**
|
||||
** (0) START At the beginning or end of an SQL statement. This routine
|
||||
** (0) INVALID We have not yet seen a non-whitespace character.
|
||||
**
|
||||
** (1) START At the beginning or end of an SQL statement. This routine
|
||||
** returns 1 if it ends in the START state and 0 if it ends
|
||||
** in any other state.
|
||||
**
|
||||
** (1) NORMAL We are in the middle of statement which ends with a single
|
||||
** (2) NORMAL We are in the middle of statement which ends with a single
|
||||
** semicolon.
|
||||
**
|
||||
** (2) EXPLAIN The keyword EXPLAIN has been seen at the beginning of
|
||||
** (3) EXPLAIN The keyword EXPLAIN has been seen at the beginning of
|
||||
** a statement.
|
||||
**
|
||||
** (3) CREATE The keyword CREATE has been seen at the beginning of a
|
||||
** (4) CREATE The keyword CREATE has been seen at the beginning of a
|
||||
** statement, possibly preceeded by EXPLAIN and/or followed by
|
||||
** TEMP or TEMPORARY
|
||||
**
|
||||
** (4) TRIGGER We are in the middle of a trigger definition that must be
|
||||
** (5) TRIGGER We are in the middle of a trigger definition that must be
|
||||
** ended by a semicolon, the keyword END, and another semicolon.
|
||||
**
|
||||
** (5) SEMI We've seen the first semicolon in the ";END;" that occurs at
|
||||
** (6) SEMI We've seen the first semicolon in the ";END;" that occurs at
|
||||
** the end of a trigger definition.
|
||||
**
|
||||
** (6) END We've seen the ";END" of the ";END;" that occurs at the end
|
||||
** (7) END We've seen the ";END" of the ";END;" that occurs at the end
|
||||
** of a trigger difinition.
|
||||
**
|
||||
** Transitions between states above are determined by tokens extracted
|
||||
** from the input. The following tokens are significant:
|
||||
**
|
||||
** (0) tkSEMI A semicolon.
|
||||
** (1) tkWS Whitespace
|
||||
** (1) tkWS Whitespace.
|
||||
** (2) tkOTHER Any other SQL token.
|
||||
** (3) tkEXPLAIN The "explain" keyword.
|
||||
** (4) tkCREATE The "create" keyword.
|
||||
@@ -91,6 +95,7 @@ extern const char sqlite3IsEbcdicIdChar[];
|
||||
** (7) tkEND The "end" keyword.
|
||||
**
|
||||
** Whitespace never causes a state transition and is always ignored.
|
||||
** This means that a SQL string of all whitespace is invalid.
|
||||
**
|
||||
** If we compile with SQLITE_OMIT_TRIGGER, all of the computation needed
|
||||
** to recognize the end of a trigger can be omitted. All we have to do
|
||||
@@ -104,26 +109,28 @@ int sqlite3_complete(const char *zSql){
|
||||
/* A complex statement machine used to detect the end of a CREATE TRIGGER
|
||||
** statement. This is the normal case.
|
||||
*/
|
||||
static const u8 trans[7][8] = {
|
||||
static const u8 trans[8][8] = {
|
||||
/* Token: */
|
||||
/* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */
|
||||
/* 0 START: */ { 0, 0, 1, 2, 3, 1, 1, 1, },
|
||||
/* 1 NORMAL: */ { 0, 1, 1, 1, 1, 1, 1, 1, },
|
||||
/* 2 EXPLAIN: */ { 0, 2, 2, 1, 3, 1, 1, 1, },
|
||||
/* 3 CREATE: */ { 0, 3, 1, 1, 1, 3, 4, 1, },
|
||||
/* 4 TRIGGER: */ { 5, 4, 4, 4, 4, 4, 4, 4, },
|
||||
/* 5 SEMI: */ { 5, 5, 4, 4, 4, 4, 4, 6, },
|
||||
/* 6 END: */ { 0, 6, 4, 4, 4, 4, 4, 4, },
|
||||
/* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */
|
||||
/* 0 INVALID: */ { 1, 0, 2, 3, 4, 2, 2, 2, },
|
||||
/* 1 START: */ { 1, 1, 2, 3, 4, 2, 2, 2, },
|
||||
/* 2 NORMAL: */ { 1, 2, 2, 2, 2, 2, 2, 2, },
|
||||
/* 3 EXPLAIN: */ { 1, 3, 3, 2, 4, 2, 2, 2, },
|
||||
/* 4 CREATE: */ { 1, 4, 2, 2, 2, 4, 5, 2, },
|
||||
/* 5 TRIGGER: */ { 6, 5, 5, 5, 5, 5, 5, 5, },
|
||||
/* 6 SEMI: */ { 6, 6, 5, 5, 5, 5, 5, 7, },
|
||||
/* 7 END: */ { 1, 7, 5, 5, 5, 5, 5, 5, },
|
||||
};
|
||||
#else
|
||||
/* If triggers are not suppored by this compile then the statement machine
|
||||
/* If triggers are not supported by this compile then the statement machine
|
||||
** used to detect the end of a statement is much simplier
|
||||
*/
|
||||
static const u8 trans[2][3] = {
|
||||
static const u8 trans[3][3] = {
|
||||
/* Token: */
|
||||
/* State: ** SEMI WS OTHER */
|
||||
/* 0 START: */ { 0, 0, 1, },
|
||||
/* 1 NORMAL: */ { 0, 1, 1, },
|
||||
/* 0 INVALID: */ { 1, 0, 2, },
|
||||
/* 1 START: */ { 1, 1, 2, },
|
||||
/* 2 NORMAL: */ { 1, 2, 2, },
|
||||
};
|
||||
#endif /* SQLITE_OMIT_TRIGGER */
|
||||
|
||||
@@ -159,7 +166,7 @@ int sqlite3_complete(const char *zSql){
|
||||
break;
|
||||
}
|
||||
while( *zSql && *zSql!='\n' ){ zSql++; }
|
||||
if( *zSql==0 ) return state==0;
|
||||
if( *zSql==0 ) return state==1;
|
||||
token = tkWS;
|
||||
break;
|
||||
}
|
||||
@@ -243,7 +250,7 @@ int sqlite3_complete(const char *zSql){
|
||||
state = trans[state][token];
|
||||
zSql++;
|
||||
}
|
||||
return state==0;
|
||||
return state==1;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
|
||||
+385
@@ -0,0 +1,385 @@
|
||||
/*
|
||||
** 2010 February 23
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
**
|
||||
** This file implements routines used to report what compile-time options
|
||||
** SQLite was built with.
|
||||
*/
|
||||
|
||||
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
|
||||
|
||||
#include "sqliteInt.h"
|
||||
|
||||
/*
|
||||
** An array of names of all compile-time options. This array should
|
||||
** be sorted A-Z.
|
||||
**
|
||||
** This array looks large, but in a typical installation actually uses
|
||||
** only a handful of compile-time options, so most times this array is usually
|
||||
** rather short and uses little memory space.
|
||||
*/
|
||||
static const char * const azCompileOpt[] = {
|
||||
|
||||
/* These macros are provided to "stringify" the value of the define
|
||||
** for those options in which the value is meaningful. */
|
||||
#define CTIMEOPT_VAL_(opt) #opt
|
||||
#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
|
||||
|
||||
#ifdef SQLITE_32BIT_ROWID
|
||||
"32BIT_ROWID",
|
||||
#endif
|
||||
#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
|
||||
"4_BYTE_ALIGNED_MALLOC",
|
||||
#endif
|
||||
#ifdef SQLITE_CASE_SENSITIVE_LIKE
|
||||
"CASE_SENSITIVE_LIKE",
|
||||
#endif
|
||||
#ifdef SQLITE_CHECK_PAGES
|
||||
"CHECK_PAGES",
|
||||
#endif
|
||||
#ifdef SQLITE_COVERAGE_TEST
|
||||
"COVERAGE_TEST",
|
||||
#endif
|
||||
#ifdef SQLITE_DEBUG
|
||||
"DEBUG",
|
||||
#endif
|
||||
#ifdef SQLITE_DEFAULT_LOCKING_MODE
|
||||
"DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
|
||||
#endif
|
||||
#ifdef SQLITE_DISABLE_DIRSYNC
|
||||
"DISABLE_DIRSYNC",
|
||||
#endif
|
||||
#ifdef SQLITE_DISABLE_LFS
|
||||
"DISABLE_LFS",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
|
||||
"ENABLE_ATOMIC_WRITE",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_CEROD
|
||||
"ENABLE_CEROD",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
||||
"ENABLE_COLUMN_METADATA",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
|
||||
"ENABLE_EXPENSIVE_ASSERT",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_FTS1
|
||||
"ENABLE_FTS1",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_FTS2
|
||||
"ENABLE_FTS2",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_FTS3
|
||||
"ENABLE_FTS3",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_FTS3_PARENTHESIS
|
||||
"ENABLE_FTS3_PARENTHESIS",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_FTS4
|
||||
"ENABLE_FTS4",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_ICU
|
||||
"ENABLE_ICU",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_IOTRACE
|
||||
"ENABLE_IOTRACE",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_LOAD_EXTENSION
|
||||
"ENABLE_LOAD_EXTENSION",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_LOCKING_STYLE
|
||||
"ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
"ENABLE_MEMORY_MANAGEMENT",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_MEMSYS3
|
||||
"ENABLE_MEMSYS3",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_MEMSYS5
|
||||
"ENABLE_MEMSYS5",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
|
||||
"ENABLE_OVERSIZE_CELL_CHECK",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_RTREE
|
||||
"ENABLE_RTREE",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_STAT2
|
||||
"ENABLE_STAT2",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
|
||||
"ENABLE_UNLOCK_NOTIFY",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
|
||||
"ENABLE_UPDATE_DELETE_LIMIT",
|
||||
#endif
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
"HAS_CODEC",
|
||||
#endif
|
||||
#ifdef SQLITE_HAVE_ISNAN
|
||||
"HAVE_ISNAN",
|
||||
#endif
|
||||
#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
|
||||
"HOMEGROWN_RECURSIVE_MUTEX",
|
||||
#endif
|
||||
#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
|
||||
"IGNORE_AFP_LOCK_ERRORS",
|
||||
#endif
|
||||
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
|
||||
"IGNORE_FLOCK_LOCK_ERRORS",
|
||||
#endif
|
||||
#ifdef SQLITE_INT64_TYPE
|
||||
"INT64_TYPE",
|
||||
#endif
|
||||
#ifdef SQLITE_LOCK_TRACE
|
||||
"LOCK_TRACE",
|
||||
#endif
|
||||
#ifdef SQLITE_MEMDEBUG
|
||||
"MEMDEBUG",
|
||||
#endif
|
||||
#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
|
||||
"MIXED_ENDIAN_64BIT_FLOAT",
|
||||
#endif
|
||||
#ifdef SQLITE_NO_SYNC
|
||||
"NO_SYNC",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_ALTERTABLE
|
||||
"OMIT_ALTERTABLE",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_ANALYZE
|
||||
"OMIT_ANALYZE",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_ATTACH
|
||||
"OMIT_ATTACH",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_AUTHORIZATION
|
||||
"OMIT_AUTHORIZATION",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_AUTOINCREMENT
|
||||
"OMIT_AUTOINCREMENT",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_AUTOINIT
|
||||
"OMIT_AUTOINIT",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_AUTOVACUUM
|
||||
"OMIT_AUTOVACUUM",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION
|
||||
"OMIT_BETWEEN_OPTIMIZATION",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_BLOB_LITERAL
|
||||
"OMIT_BLOB_LITERAL",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_BTREECOUNT
|
||||
"OMIT_BTREECOUNT",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_BUILTIN_TEST
|
||||
"OMIT_BUILTIN_TEST",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_CAST
|
||||
"OMIT_CAST",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_CHECK
|
||||
"OMIT_CHECK",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_COMPILEOPTION_DIAGS
|
||||
"OMIT_COMPILEOPTION_DIAGS",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_COMPLETE
|
||||
"OMIT_COMPLETE",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_COMPOUND_SELECT
|
||||
"OMIT_COMPOUND_SELECT",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_DATETIME_FUNCS
|
||||
"OMIT_DATETIME_FUNCS",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_DECLTYPE
|
||||
"OMIT_DECLTYPE",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_DEPRECATED
|
||||
"OMIT_DEPRECATED",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_DISKIO
|
||||
"OMIT_DISKIO",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_EXPLAIN
|
||||
"OMIT_EXPLAIN",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_FLAG_PRAGMAS
|
||||
"OMIT_FLAG_PRAGMAS",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_FLOATING_POINT
|
||||
"OMIT_FLOATING_POINT",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_FOREIGN_KEY
|
||||
"OMIT_FOREIGN_KEY",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_GET_TABLE
|
||||
"OMIT_GET_TABLE",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_GLOBALRECOVER
|
||||
"OMIT_GLOBALRECOVER",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_INCRBLOB
|
||||
"OMIT_INCRBLOB",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_INTEGRITY_CHECK
|
||||
"OMIT_INTEGRITY_CHECK",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION
|
||||
"OMIT_LIKE_OPTIMIZATION",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_LOAD_EXTENSION
|
||||
"OMIT_LOAD_EXTENSION",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_LOCALTIME
|
||||
"OMIT_LOCALTIME",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_LOOKASIDE
|
||||
"OMIT_LOOKASIDE",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_MEMORYDB
|
||||
"OMIT_MEMORYDB",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_OR_OPTIMIZATION
|
||||
"OMIT_OR_OPTIMIZATION",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_PAGER_PRAGMAS
|
||||
"OMIT_PAGER_PRAGMAS",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_PRAGMA
|
||||
"OMIT_PRAGMA",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
|
||||
"OMIT_PROGRESS_CALLBACK",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_QUICKBALANCE
|
||||
"OMIT_QUICKBALANCE",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_REINDEX
|
||||
"OMIT_REINDEX",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
|
||||
"OMIT_SCHEMA_PRAGMAS",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
|
||||
"OMIT_SCHEMA_VERSION_PRAGMAS",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_SHARED_CACHE
|
||||
"OMIT_SHARED_CACHE",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_SUBQUERY
|
||||
"OMIT_SUBQUERY",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_TCL_VARIABLE
|
||||
"OMIT_TCL_VARIABLE",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_TEMPDB
|
||||
"OMIT_TEMPDB",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_TRACE
|
||||
"OMIT_TRACE",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_TRIGGER
|
||||
"OMIT_TRIGGER",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
|
||||
"OMIT_TRUNCATE_OPTIMIZATION",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_UTF16
|
||||
"OMIT_UTF16",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_VACUUM
|
||||
"OMIT_VACUUM",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_VIEW
|
||||
"OMIT_VIEW",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_VIRTUALTABLE
|
||||
"OMIT_VIRTUALTABLE",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_WSD
|
||||
"OMIT_WSD",
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_XFER_OPT
|
||||
"OMIT_XFER_OPT",
|
||||
#endif
|
||||
#ifdef SQLITE_PERFORMANCE_TRACE
|
||||
"PERFORMANCE_TRACE",
|
||||
#endif
|
||||
#ifdef SQLITE_PROXY_DEBUG
|
||||
"PROXY_DEBUG",
|
||||
#endif
|
||||
#ifdef SQLITE_SECURE_DELETE
|
||||
"SECURE_DELETE",
|
||||
#endif
|
||||
#ifdef SQLITE_SMALL_STACK
|
||||
"SMALL_STACK",
|
||||
#endif
|
||||
#ifdef SQLITE_SOUNDEX
|
||||
"SOUNDEX",
|
||||
#endif
|
||||
#ifdef SQLITE_TCL
|
||||
"TCL",
|
||||
#endif
|
||||
#ifdef SQLITE_TEMP_STORE
|
||||
"TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
|
||||
#endif
|
||||
#ifdef SQLITE_TEST
|
||||
"TEST",
|
||||
#endif
|
||||
#ifdef SQLITE_THREADSAFE
|
||||
"THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
|
||||
#endif
|
||||
#ifdef SQLITE_USE_ALLOCA
|
||||
"USE_ALLOCA",
|
||||
#endif
|
||||
#ifdef SQLITE_ZERO_MALLOC
|
||||
"ZERO_MALLOC"
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
** Given the name of a compile-time option, return true if that option
|
||||
** was used and false if not.
|
||||
**
|
||||
** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix
|
||||
** is not required for a match.
|
||||
*/
|
||||
int sqlite3_compileoption_used(const char *zOptName){
|
||||
int i, n;
|
||||
if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7;
|
||||
n = sqlite3Strlen30(zOptName);
|
||||
|
||||
/* Since ArraySize(azCompileOpt) is normally in single digits, a
|
||||
** linear search is adequate. No need for a binary search. */
|
||||
for(i=0; i<ArraySize(azCompileOpt); i++){
|
||||
if( (sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0)
|
||||
&& ( (azCompileOpt[i][n]==0) || (azCompileOpt[i][n]=='=') ) ) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the N-th compile-time option string. If N is out of range,
|
||||
** return a NULL pointer.
|
||||
*/
|
||||
const char *sqlite3_compileoption_get(int N){
|
||||
if( N>=0 && N<ArraySize(azCompileOpt) ){
|
||||
return azCompileOpt[N];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
|
||||
+2
-2
@@ -1092,8 +1092,8 @@ void sqlite3RegisterDateTimeFunctions(void){
|
||||
FUNCTION(current_date, 0, 0, 0, cdateFunc ),
|
||||
#else
|
||||
STR_FUNCTION(current_time, 0, "%H:%M:%S", 0, currentTimeFunc),
|
||||
STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d", 0, currentTimeFunc),
|
||||
STR_FUNCTION(current_date, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc),
|
||||
STR_FUNCTION(current_date, 0, "%Y-%m-%d", 0, currentTimeFunc),
|
||||
STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc),
|
||||
#endif
|
||||
};
|
||||
int i;
|
||||
|
||||
+1
-2
@@ -364,7 +364,7 @@ void sqlite3DeleteFrom(
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0,WHERE_DUPLICATES_OK);
|
||||
if( pWInfo==0 ) goto delete_from_cleanup;
|
||||
regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid, 0);
|
||||
regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid);
|
||||
sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
|
||||
if( db->flags & SQLITE_CountRows ){
|
||||
sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
|
||||
@@ -630,7 +630,6 @@ int sqlite3GenerateIndexKey(
|
||||
if( doMakeRec ){
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);
|
||||
sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), 0);
|
||||
sqlite3ExprCacheAffinityChange(pParse, regBase, nCol+1);
|
||||
}
|
||||
sqlite3ReleaseTempRange(pParse, regBase, nCol+1);
|
||||
return regBase;
|
||||
|
||||
+95
-104
@@ -227,30 +227,6 @@ CollSeq *sqlite3BinaryCompareCollSeq(
|
||||
return pColl;
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate the operands for a comparison operation. Before
|
||||
** generating the code for each operand, set the EP_AnyAff
|
||||
** flag on the expression so that it will be able to used a
|
||||
** cached column value that has previously undergone an
|
||||
** affinity change.
|
||||
*/
|
||||
static void codeCompareOperands(
|
||||
Parse *pParse, /* Parsing and code generating context */
|
||||
Expr *pLeft, /* The left operand */
|
||||
int *pRegLeft, /* Register where left operand is stored */
|
||||
int *pFreeLeft, /* Free this register when done */
|
||||
Expr *pRight, /* The right operand */
|
||||
int *pRegRight, /* Register where right operand is stored */
|
||||
int *pFreeRight /* Write temp register for right operand there */
|
||||
){
|
||||
while( pLeft->op==TK_UPLUS ) pLeft = pLeft->pLeft;
|
||||
pLeft->flags |= EP_AnyAff;
|
||||
*pRegLeft = sqlite3ExprCodeTemp(pParse, pLeft, pFreeLeft);
|
||||
while( pRight->op==TK_UPLUS ) pRight = pRight->pLeft;
|
||||
pRight->flags |= EP_AnyAff;
|
||||
*pRegRight = sqlite3ExprCodeTemp(pParse, pRight, pFreeRight);
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate code for a comparison operator.
|
||||
*/
|
||||
@@ -272,10 +248,6 @@ static int codeCompare(
|
||||
addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
|
||||
(void*)p4, P4_COLLSEQ);
|
||||
sqlite3VdbeChangeP5(pParse->pVdbe, (u8)p5);
|
||||
if( (p5 & SQLITE_AFF_MASK)!=SQLITE_AFF_NONE ){
|
||||
sqlite3ExprCacheAffinityChange(pParse, in1, 1);
|
||||
sqlite3ExprCacheAffinityChange(pParse, in2, 1);
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -1906,6 +1878,7 @@ static char *dup8bytes(Vdbe *v, const char *in){
|
||||
return out;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
/*
|
||||
** Generate an instruction that will put the floating point
|
||||
** value described by z[0..n-1] into register iMem.
|
||||
@@ -1925,6 +1898,7 @@ static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){
|
||||
sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
@@ -1935,7 +1909,8 @@ static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){
|
||||
** z[n] character is guaranteed to be something that does not look
|
||||
** like the continuation of the number.
|
||||
*/
|
||||
static void codeInteger(Vdbe *v, Expr *pExpr, int negFlag, int iMem){
|
||||
static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
if( pExpr->flags & EP_IntValue ){
|
||||
int i = pExpr->u.iValue;
|
||||
if( negFlag ) i = -i;
|
||||
@@ -1951,7 +1926,11 @@ static void codeInteger(Vdbe *v, Expr *pExpr, int negFlag, int iMem){
|
||||
zV = dup8bytes(v, (char*)&value);
|
||||
sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64);
|
||||
}else{
|
||||
#ifdef SQLITE_OMIT_FLOATING_POINT
|
||||
sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
|
||||
#else
|
||||
codeReal(v, z, negFlag, iMem);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1982,17 +1961,31 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
|
||||
assert( iReg>0 ); /* Register numbers are always positive */
|
||||
assert( iCol>=-1 && iCol<32768 ); /* Finite column numbers */
|
||||
|
||||
/* First replace any existing entry */
|
||||
/* The SQLITE_ColumnCache flag disables the column cache. This is used
|
||||
** for testing only - to verify that SQLite always gets the same answer
|
||||
** with and without the column cache.
|
||||
*/
|
||||
if( pParse->db->flags & SQLITE_ColumnCache ) return;
|
||||
|
||||
/* First replace any existing entry.
|
||||
**
|
||||
** Actually, the way the column cache is currently used, we are guaranteed
|
||||
** that the object will never already be in cache. Verify this guarantee.
|
||||
*/
|
||||
#ifndef NDEBUG
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
#if 0 /* This code wold remove the entry from the cache if it existed */
|
||||
if( p->iReg && p->iTable==iTab && p->iColumn==iCol ){
|
||||
cacheEntryClear(pParse, p);
|
||||
p->iLevel = pParse->iCacheLevel;
|
||||
p->iReg = iReg;
|
||||
p->affChange = 0;
|
||||
p->lru = pParse->iCacheCnt++;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
assert( p->iReg==0 || p->iTable!=iTab || p->iColumn!=iCol );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Find an empty slot and replace it */
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
@@ -2001,7 +1994,6 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
|
||||
p->iTable = iTab;
|
||||
p->iColumn = iCol;
|
||||
p->iReg = iReg;
|
||||
p->affChange = 0;
|
||||
p->tempReg = 0;
|
||||
p->lru = pParse->iCacheCnt++;
|
||||
return;
|
||||
@@ -2023,7 +2015,6 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
|
||||
p->iTable = iTab;
|
||||
p->iColumn = iCol;
|
||||
p->iReg = iReg;
|
||||
p->affChange = 0;
|
||||
p->tempReg = 0;
|
||||
p->lru = pParse->iCacheCnt++;
|
||||
return;
|
||||
@@ -2031,14 +2022,16 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
|
||||
}
|
||||
|
||||
/*
|
||||
** Indicate that a register is being overwritten. Purge the register
|
||||
** from the column cache.
|
||||
** Indicate that registers between iReg..iReg+nReg-1 are being overwritten.
|
||||
** Purge the range of registers from the column cache.
|
||||
*/
|
||||
void sqlite3ExprCacheRemove(Parse *pParse, int iReg){
|
||||
void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){
|
||||
int i;
|
||||
int iLast = iReg + nReg - 1;
|
||||
struct yColCache *p;
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
if( p->iReg==iReg ){
|
||||
int r = p->iReg;
|
||||
if( r>=iReg && r<=iLast ){
|
||||
cacheEntryClear(pParse, p);
|
||||
p->iReg = 0;
|
||||
}
|
||||
@@ -2097,28 +2090,20 @@ static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){
|
||||
**
|
||||
** There must be an open cursor to pTab in iTable when this routine
|
||||
** is called. If iColumn<0 then code is generated that extracts the rowid.
|
||||
**
|
||||
** This routine might attempt to reuse the value of the column that
|
||||
** has already been loaded into a register. The value will always
|
||||
** be used if it has not undergone any affinity changes. But if
|
||||
** an affinity change has occurred, then the cached value will only be
|
||||
** used if allowAffChng is true.
|
||||
*/
|
||||
int sqlite3ExprCodeGetColumn(
|
||||
Parse *pParse, /* Parsing and code generating context */
|
||||
Table *pTab, /* Description of the table we are reading from */
|
||||
int iColumn, /* Index of the table column */
|
||||
int iTable, /* The cursor pointing to the table */
|
||||
int iReg, /* Store results here */
|
||||
int allowAffChng /* True if prior affinity changes are OK */
|
||||
int iReg /* Store results here */
|
||||
){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
int i;
|
||||
struct yColCache *p;
|
||||
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
if( p->iReg>0 && p->iTable==iTable && p->iColumn==iColumn
|
||||
&& (!p->affChange || allowAffChng) ){
|
||||
if( p->iReg>0 && p->iTable==iTable && p->iColumn==iColumn ){
|
||||
p->lru = pParse->iCacheCnt++;
|
||||
sqlite3ExprCachePinRegister(pParse, p->iReg);
|
||||
return p->iReg;
|
||||
@@ -2156,15 +2141,7 @@ void sqlite3ExprCacheClear(Parse *pParse){
|
||||
** registers starting with iStart.
|
||||
*/
|
||||
void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){
|
||||
int iEnd = iStart + iCount - 1;
|
||||
int i;
|
||||
struct yColCache *p;
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
int r = p->iReg;
|
||||
if( r>=iStart && r<=iEnd ){
|
||||
p->affChange = 1;
|
||||
}
|
||||
}
|
||||
sqlite3ExprCacheRemove(pParse, iStart, iCount);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2196,19 +2173,24 @@ void sqlite3ExprCodeCopy(Parse *pParse, int iFrom, int iTo, int nReg){
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
|
||||
/*
|
||||
** Return true if any register in the range iFrom..iTo (inclusive)
|
||||
** is used as part of the column cache.
|
||||
**
|
||||
** This routine is used within assert() and testcase() macros only
|
||||
** and does not appear in a normal build.
|
||||
*/
|
||||
static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){
|
||||
int i;
|
||||
struct yColCache *p;
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
int r = p->iReg;
|
||||
if( r>=iFrom && r<=iTo ) return 1;
|
||||
if( r>=iFrom && r<=iTo ) return 1; /*NO_TEST*/
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* SQLITE_DEBUG || SQLITE_COVERAGE_TEST */
|
||||
|
||||
/*
|
||||
** If the last instruction coded is an ephemeral copy of any of
|
||||
@@ -2329,22 +2311,22 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
assert( pParse->ckBase>0 );
|
||||
inReg = pExpr->iColumn + pParse->ckBase;
|
||||
}else{
|
||||
testcase( (pExpr->flags & EP_AnyAff)!=0 );
|
||||
inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
|
||||
pExpr->iColumn, pExpr->iTable, target,
|
||||
pExpr->flags & EP_AnyAff);
|
||||
pExpr->iColumn, pExpr->iTable, target);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TK_INTEGER: {
|
||||
codeInteger(v, pExpr, 0, target);
|
||||
codeInteger(pParse, pExpr, 0, target);
|
||||
break;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
case TK_FLOAT: {
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
codeReal(v, pExpr->u.zToken, 0, target);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case TK_STRING: {
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0, pExpr->u.zToken, 0);
|
||||
@@ -2449,8 +2431,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
testcase( op==TK_GE );
|
||||
testcase( op==TK_EQ );
|
||||
testcase( op==TK_NE );
|
||||
codeCompareOperands(pParse, pExpr->pLeft, &r1, ®Free1,
|
||||
pExpr->pRight, &r2, ®Free2);
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
||||
r1, r2, inReg, SQLITE_STOREP2);
|
||||
testcase( regFree1==0 );
|
||||
@@ -2461,8 +2443,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
case TK_ISNOT: {
|
||||
testcase( op==TK_IS );
|
||||
testcase( op==TK_ISNOT );
|
||||
codeCompareOperands(pParse, pExpr->pLeft, &r1, ®Free1,
|
||||
pExpr->pRight, &r2, ®Free2);
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
op = (op==TK_IS) ? TK_EQ : TK_NE;
|
||||
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
||||
r1, r2, inReg, SQLITE_STOREP2 | SQLITE_NULLEQ);
|
||||
@@ -2514,11 +2496,13 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
case TK_UMINUS: {
|
||||
Expr *pLeft = pExpr->pLeft;
|
||||
assert( pLeft );
|
||||
if( pLeft->op==TK_FLOAT ){
|
||||
if( pLeft->op==TK_INTEGER ){
|
||||
codeInteger(pParse, pLeft, 1, target);
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
}else if( pLeft->op==TK_FLOAT ){
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
codeReal(v, pLeft->u.zToken, 1, target);
|
||||
}else if( pLeft->op==TK_INTEGER ){
|
||||
codeInteger(v, pLeft, 1, target);
|
||||
#endif
|
||||
}else{
|
||||
regFree1 = r1 = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, r1);
|
||||
@@ -2606,7 +2590,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target);
|
||||
for(i=1; i<nFarg; i++){
|
||||
sqlite3VdbeAddOp2(v, OP_NotNull, target, endCoalesce);
|
||||
sqlite3ExprCacheRemove(pParse, target);
|
||||
sqlite3ExprCacheRemove(pParse, target, 1);
|
||||
sqlite3ExprCachePush(pParse);
|
||||
sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target);
|
||||
sqlite3ExprCachePop(pParse, 1);
|
||||
@@ -2661,7 +2645,6 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
if( nFarg ){
|
||||
sqlite3ReleaseTempRange(pParse, r1, nFarg);
|
||||
}
|
||||
sqlite3ExprCacheAffinityChange(pParse, r1, nFarg);
|
||||
break;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_SUBQUERY
|
||||
@@ -2702,8 +2685,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
struct ExprList_item *pLItem = pExpr->x.pList->a;
|
||||
Expr *pRight = pLItem->pExpr;
|
||||
|
||||
codeCompareOperands(pParse, pLeft, &r1, ®Free1,
|
||||
pRight, &r2, ®Free2);
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pLeft, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pRight, ®Free2);
|
||||
testcase( regFree1==0 );
|
||||
testcase( regFree2==0 );
|
||||
r3 = sqlite3GetTempReg(pParse);
|
||||
@@ -2767,6 +2750,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
target
|
||||
));
|
||||
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
/* If the column has REAL affinity, it may currently be stored as an
|
||||
** integer. Use OP_RealAffinity to make sure it is really real. */
|
||||
if( pExpr->iColumn>=0
|
||||
@@ -2774,6 +2758,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
){
|
||||
sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3238,8 +3223,8 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
testcase( op==TK_EQ );
|
||||
testcase( op==TK_NE );
|
||||
testcase( jumpIfNull==0 );
|
||||
codeCompareOperands(pParse, pExpr->pLeft, &r1, ®Free1,
|
||||
pExpr->pRight, &r2, ®Free2);
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
||||
r1, r2, dest, jumpIfNull);
|
||||
testcase( regFree1==0 );
|
||||
@@ -3250,8 +3235,8 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
case TK_ISNOT: {
|
||||
testcase( op==TK_IS );
|
||||
testcase( op==TK_ISNOT );
|
||||
codeCompareOperands(pParse, pExpr->pLeft, &r1, ®Free1,
|
||||
pExpr->pRight, &r2, ®Free2);
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
op = (op==TK_IS) ? TK_EQ : TK_NE;
|
||||
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
||||
r1, r2, dest, SQLITE_NULLEQ);
|
||||
@@ -3381,8 +3366,8 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
testcase( op==TK_EQ );
|
||||
testcase( op==TK_NE );
|
||||
testcase( jumpIfNull==0 );
|
||||
codeCompareOperands(pParse, pExpr->pLeft, &r1, ®Free1,
|
||||
pExpr->pRight, &r2, ®Free2);
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
||||
r1, r2, dest, jumpIfNull);
|
||||
testcase( regFree1==0 );
|
||||
@@ -3393,8 +3378,8 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
case TK_ISNOT: {
|
||||
testcase( pExpr->op==TK_IS );
|
||||
testcase( pExpr->op==TK_ISNOT );
|
||||
codeCompareOperands(pParse, pExpr->pLeft, &r1, ®Free1,
|
||||
pExpr->pRight, &r2, ®Free2);
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
||||
op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ;
|
||||
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
||||
r1, r2, dest, SQLITE_NULLEQ);
|
||||
@@ -3439,57 +3424,61 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
}
|
||||
|
||||
/*
|
||||
** Do a deep comparison of two expression trees. Return TRUE (non-zero)
|
||||
** if they are identical and return FALSE if they differ in any way.
|
||||
** Do a deep comparison of two expression trees. Return 0 if the two
|
||||
** expressions are completely identical. Return 1 if they differ only
|
||||
** by a COLLATE operator at the top level. Return 2 if there are differences
|
||||
** other than the top-level COLLATE operator.
|
||||
**
|
||||
** Sometimes this routine will return FALSE even if the two expressions
|
||||
** Sometimes this routine will return 2 even if the two expressions
|
||||
** really are equivalent. If we cannot prove that the expressions are
|
||||
** identical, we return FALSE just to be safe. So if this routine
|
||||
** returns false, then you do not really know for certain if the two
|
||||
** expressions are the same. But if you get a TRUE return, then you
|
||||
** identical, we return 2 just to be safe. So if this routine
|
||||
** returns 2, then you do not really know for certain if the two
|
||||
** expressions are the same. But if you get a 0 or 1 return, then you
|
||||
** can be sure the expressions are the same. In the places where
|
||||
** this routine is used, it does not hurt to get an extra FALSE - that
|
||||
** this routine is used, it does not hurt to get an extra 2 - that
|
||||
** just might result in some slightly slower code. But returning
|
||||
** an incorrect TRUE could lead to a malfunction.
|
||||
** an incorrect 0 or 1 could lead to a malfunction.
|
||||
*/
|
||||
int sqlite3ExprCompare(Expr *pA, Expr *pB){
|
||||
int i;
|
||||
if( pA==0||pB==0 ){
|
||||
return pB==pA;
|
||||
return pB==pA ? 0 : 2;
|
||||
}
|
||||
assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) );
|
||||
assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) );
|
||||
if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){
|
||||
return 0;
|
||||
return 2;
|
||||
}
|
||||
if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 0;
|
||||
if( pA->op!=pB->op ) return 0;
|
||||
if( !sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 0;
|
||||
if( !sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 0;
|
||||
if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
|
||||
if( pA->op!=pB->op ) return 2;
|
||||
if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2;
|
||||
if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2;
|
||||
|
||||
if( pA->x.pList && pB->x.pList ){
|
||||
if( pA->x.pList->nExpr!=pB->x.pList->nExpr ) return 0;
|
||||
if( pA->x.pList->nExpr!=pB->x.pList->nExpr ) return 2;
|
||||
for(i=0; i<pA->x.pList->nExpr; i++){
|
||||
Expr *pExprA = pA->x.pList->a[i].pExpr;
|
||||
Expr *pExprB = pB->x.pList->a[i].pExpr;
|
||||
if( !sqlite3ExprCompare(pExprA, pExprB) ) return 0;
|
||||
if( sqlite3ExprCompare(pExprA, pExprB) ) return 2;
|
||||
}
|
||||
}else if( pA->x.pList || pB->x.pList ){
|
||||
return 0;
|
||||
return 2;
|
||||
}
|
||||
|
||||
if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0;
|
||||
if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2;
|
||||
if( ExprHasProperty(pA, EP_IntValue) ){
|
||||
if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){
|
||||
return 0;
|
||||
return 2;
|
||||
}
|
||||
}else if( pA->op!=TK_COLUMN && pA->u.zToken ){
|
||||
if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 0;
|
||||
if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2;
|
||||
if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ){
|
||||
return 0;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
if( (pA->flags & EP_ExpCollate)!=(pB->flags & EP_ExpCollate) ) return 1;
|
||||
if( (pA->flags & EP_ExpCollate)!=0 && pA->pColl!=pB->pColl ) return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -3620,7 +3609,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
|
||||
*/
|
||||
struct AggInfo_func *pItem = pAggInfo->aFunc;
|
||||
for(i=0; i<pAggInfo->nFunc; i++, pItem++){
|
||||
if( sqlite3ExprCompare(pItem->pExpr, pExpr) ){
|
||||
if( sqlite3ExprCompare(pItem->pExpr, pExpr)==0 ){
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -3741,7 +3730,8 @@ int sqlite3GetTempRange(Parse *pParse, int nReg){
|
||||
int i, n;
|
||||
i = pParse->iRangeReg;
|
||||
n = pParse->nRangeReg;
|
||||
if( nReg<=n && !usedAsColumnCache(pParse, i, i+n-1) ){
|
||||
if( nReg<=n ){
|
||||
assert( !usedAsColumnCache(pParse, i, i+n-1) );
|
||||
pParse->iRangeReg += nReg;
|
||||
pParse->nRangeReg -= nReg;
|
||||
}else{
|
||||
@@ -3751,6 +3741,7 @@ int sqlite3GetTempRange(Parse *pParse, int nReg){
|
||||
return i;
|
||||
}
|
||||
void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){
|
||||
sqlite3ExprCacheRemove(pParse, iReg, nReg);
|
||||
if( nReg>pParse->nRangeReg ){
|
||||
pParse->nRangeReg = nReg;
|
||||
pParse->iRangeReg = iReg;
|
||||
|
||||
+101
-11
@@ -117,7 +117,10 @@ static void lengthFunc(
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the abs() function
|
||||
** Implementation of the abs() function.
|
||||
**
|
||||
** IMP: R-23979-26855 The abs(X) function returns the absolute value of
|
||||
** the numeric argument X.
|
||||
*/
|
||||
static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
||||
assert( argc==1 );
|
||||
@@ -127,6 +130,9 @@ static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
||||
i64 iVal = sqlite3_value_int64(argv[0]);
|
||||
if( iVal<0 ){
|
||||
if( (iVal<<1)==0 ){
|
||||
/* IMP: R-35460-15084 If X is the integer -9223372036854775807 then
|
||||
** abs(X) throws an integer overflow error since there is no
|
||||
** equivalent positive 64-bit two complement value. */
|
||||
sqlite3_result_error(context, "integer overflow", -1);
|
||||
return;
|
||||
}
|
||||
@@ -136,10 +142,16 @@ static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
||||
break;
|
||||
}
|
||||
case SQLITE_NULL: {
|
||||
/* IMP: R-37434-19929 Abs(X) returns NULL if X is NULL. */
|
||||
sqlite3_result_null(context);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
/* Because sqlite3_value_double() returns 0.0 if the argument is not
|
||||
** something that can be converted into a number, we have:
|
||||
** IMP: R-57326-31541 Abs(X) return 0.0 if X is a string or blob that
|
||||
** cannot be converted to a numeric value.
|
||||
*/
|
||||
double rVal = sqlite3_value_double(argv[0]);
|
||||
if( rVal<0 ) rVal = -rVal;
|
||||
sqlite3_result_double(context, rVal);
|
||||
@@ -259,14 +271,24 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
||||
}
|
||||
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
|
||||
r = sqlite3_value_double(argv[0]);
|
||||
zBuf = sqlite3_mprintf("%.*f",n,r);
|
||||
if( zBuf==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
/* If Y==0 and X will fit in a 64-bit int,
|
||||
** handle the rounding directly,
|
||||
** otherwise use printf.
|
||||
*/
|
||||
if( n==0 && r>=0 && r<LARGEST_INT64-1 ){
|
||||
r = (double)((sqlite_int64)(r+0.5));
|
||||
}else if( n==0 && r<0 && (-r)<LARGEST_INT64-1 ){
|
||||
r = -(double)((sqlite_int64)((-r)+0.5));
|
||||
}else{
|
||||
zBuf = sqlite3_mprintf("%.*f",n,r);
|
||||
if( zBuf==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
return;
|
||||
}
|
||||
sqlite3AtoF(zBuf, &r);
|
||||
sqlite3_free(zBuf);
|
||||
sqlite3_result_double(context, r);
|
||||
}
|
||||
sqlite3_result_double(context, r);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -428,12 +450,18 @@ static void last_insert_rowid(
|
||||
){
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
||||
/* IMP: R-51513-12026 The last_insert_rowid() SQL function is a
|
||||
** wrapper around the sqlite3_last_insert_rowid() C/C++ interface
|
||||
** function. */
|
||||
sqlite3_result_int64(context, sqlite3_last_insert_rowid(db));
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the changes() SQL function. The return value is the
|
||||
** same as the sqlite3_changes() API function.
|
||||
** Implementation of the changes() SQL function.
|
||||
**
|
||||
** IMP: R-62073-11209 The changes() SQL function is a wrapper
|
||||
** around the sqlite3_changes() C/C++ function and hence follows the same
|
||||
** rules for counting changes.
|
||||
*/
|
||||
static void changes(
|
||||
sqlite3_context *context,
|
||||
@@ -456,6 +484,8 @@ static void total_changes(
|
||||
){
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
||||
/* IMP: R-52756-41993 This function is a wrapper around the
|
||||
** sqlite3_total_changes() C/C++ interface. */
|
||||
sqlite3_result_int(context, sqlite3_total_changes(db));
|
||||
}
|
||||
|
||||
@@ -723,7 +753,9 @@ static void versionFunc(
|
||||
sqlite3_value **NotUsed2
|
||||
){
|
||||
UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
||||
sqlite3_result_text(context, sqlite3_version, -1, SQLITE_STATIC);
|
||||
/* IMP: R-48699-48617 This function is an SQL wrapper around the
|
||||
** sqlite3_libversion() C-interface. */
|
||||
sqlite3_result_text(context, sqlite3_libversion(), -1, SQLITE_STATIC);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -737,9 +769,54 @@ static void sourceidFunc(
|
||||
sqlite3_value **NotUsed2
|
||||
){
|
||||
UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
||||
sqlite3_result_text(context, SQLITE_SOURCE_ID, -1, SQLITE_STATIC);
|
||||
/* IMP: R-24470-31136 This function is an SQL wrapper around the
|
||||
** sqlite3_sourceid() C interface. */
|
||||
sqlite3_result_text(context, sqlite3_sourceid(), -1, SQLITE_STATIC);
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the sqlite_compileoption_used() function.
|
||||
** The result is an integer that identifies if the compiler option
|
||||
** was used to build SQLite.
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
|
||||
static void compileoptionusedFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
const char *zOptName;
|
||||
assert( argc==1 );
|
||||
UNUSED_PARAMETER(argc);
|
||||
/* IMP: R-xxxx This function is an SQL wrapper around the
|
||||
** sqlite3_compileoption_used() C interface. */
|
||||
if( (zOptName = (const char*)sqlite3_value_text(argv[0]))!=0 ){
|
||||
sqlite3_result_int(context, sqlite3_compileoption_used(zOptName));
|
||||
}
|
||||
}
|
||||
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
|
||||
|
||||
/*
|
||||
** Implementation of the sqlite_compileoption_get() function.
|
||||
** The result is a string that identifies the compiler options
|
||||
** used to build SQLite.
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
|
||||
static void compileoptiongetFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
int n;
|
||||
assert( argc==1 );
|
||||
UNUSED_PARAMETER(argc);
|
||||
/* IMP: R-xxxx This function is an SQL wrapper around the
|
||||
** sqlite3_compileoption_get() C interface. */
|
||||
n = sqlite3_value_int(argv[0]);
|
||||
sqlite3_result_text(context, sqlite3_compileoption_get(n), -1, SQLITE_STATIC);
|
||||
}
|
||||
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
|
||||
|
||||
/* Array for converting from half-bytes (nybbles) into ASCII hex
|
||||
** digits. */
|
||||
static const char hexdigits[] = {
|
||||
@@ -866,7 +943,7 @@ static void zeroblobFunc(
|
||||
if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){
|
||||
sqlite3_result_error_toobig(context);
|
||||
}else{
|
||||
sqlite3_result_zeroblob(context, (int)n);
|
||||
sqlite3_result_zeroblob(context, (int)n); /* IMP: R-00293-64994 */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1041,9 +1118,16 @@ static void trimFunc(
|
||||
}
|
||||
|
||||
|
||||
/* IMP: R-25361-16150 This function is omitted from SQLite by default. It
|
||||
** is only available if the SQLITE_SOUNDEX compile-time option is used
|
||||
** when SQLite is built.
|
||||
*/
|
||||
#ifdef SQLITE_SOUNDEX
|
||||
/*
|
||||
** Compute the soundex encoding of a word.
|
||||
**
|
||||
** IMP: R-59782-00072 The soundex(X) function returns a string that is the
|
||||
** soundex encoding of the string X.
|
||||
*/
|
||||
static void soundexFunc(
|
||||
sqlite3_context *context,
|
||||
@@ -1087,10 +1171,12 @@ static void soundexFunc(
|
||||
zResult[j] = 0;
|
||||
sqlite3_result_text(context, zResult, 4, SQLITE_TRANSIENT);
|
||||
}else{
|
||||
/* IMP: R-64894-50321 The string "?000" is returned if the argument
|
||||
** is NULL or contains no ASCII alphabetic characters. */
|
||||
sqlite3_result_text(context, "?000", 4, SQLITE_STATIC);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* SQLITE_SOUNDEX */
|
||||
|
||||
#ifndef SQLITE_OMIT_LOAD_EXTENSION
|
||||
/*
|
||||
@@ -1464,6 +1550,10 @@ void sqlite3RegisterGlobalFunctions(void){
|
||||
FUNCTION(nullif, 2, 0, 1, nullifFunc ),
|
||||
FUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
|
||||
FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
|
||||
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
|
||||
FUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ),
|
||||
FUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ),
|
||||
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
|
||||
FUNCTION(quote, 1, 0, 0, quoteFunc ),
|
||||
FUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
|
||||
FUNCTION(changes, 0, 0, 0, changes ),
|
||||
|
||||
@@ -164,6 +164,8 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
|
||||
0, /* isPCacheInit */
|
||||
0, /* pInitMutex */
|
||||
0, /* nRefInitMutex */
|
||||
0, /* xLog */
|
||||
0, /* pLogArg */
|
||||
};
|
||||
|
||||
|
||||
|
||||
+20
-6
@@ -1261,19 +1261,33 @@ void sqlite3GenerateConstraintChecks(
|
||||
** the triggers and remove both the table and index b-tree entries.
|
||||
**
|
||||
** Otherwise, if there are no triggers or the recursive-triggers
|
||||
** flag is not set, call GenerateRowIndexDelete(). This removes
|
||||
** the index b-tree entries only. The table b-tree entry will be
|
||||
** replaced by the new entry when it is inserted. */
|
||||
** flag is not set, but the table has one or more indexes, call
|
||||
** GenerateRowIndexDelete(). This removes the index b-tree entries
|
||||
** only. The table b-tree entry will be replaced by the new entry
|
||||
** when it is inserted.
|
||||
**
|
||||
** If either GenerateRowDelete() or GenerateRowIndexDelete() is called,
|
||||
** also invoke MultiWrite() to indicate that this VDBE may require
|
||||
** statement rollback (if the statement is aborted after the delete
|
||||
** takes place). Earlier versions called sqlite3MultiWrite() regardless,
|
||||
** but being more selective here allows statements like:
|
||||
**
|
||||
** REPLACE INTO t(rowid) VALUES($newrowid)
|
||||
**
|
||||
** to run without a statement journal if there are no indexes on the
|
||||
** table.
|
||||
*/
|
||||
Trigger *pTrigger = 0;
|
||||
if( pParse->db->flags&SQLITE_RecTriggers ){
|
||||
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
|
||||
}
|
||||
sqlite3MultiWrite(pParse);
|
||||
if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
|
||||
sqlite3MultiWrite(pParse);
|
||||
sqlite3GenerateRowDelete(
|
||||
pParse, pTab, baseCur, regRowid, 0, pTrigger, OE_Replace
|
||||
);
|
||||
}else{
|
||||
}else if( pTab->pIndex ){
|
||||
sqlite3MultiWrite(pParse);
|
||||
sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0);
|
||||
}
|
||||
seenReplace = 1;
|
||||
@@ -1715,7 +1729,7 @@ static int xferOptimization(
|
||||
}
|
||||
}
|
||||
#ifndef SQLITE_OMIT_CHECK
|
||||
if( pDest->pCheck && !sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){
|
||||
if( pDest->pCheck && sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){
|
||||
return 0; /* Tables have different CHECK constraints. Ticket #2252 */
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -41,6 +41,7 @@ int sqlite3_exec(
|
||||
int nRetry = 0; /* Number of retry attempts */
|
||||
int callbackIsInit; /* True if callback data is initialized */
|
||||
|
||||
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
|
||||
if( zSql==0 ) zSql = "";
|
||||
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
|
||||
+83
-18
@@ -257,7 +257,7 @@ int sqlite3_config(int op, ...){
|
||||
|
||||
/* sqlite3_config() shall return SQLITE_MISUSE if it is invoked while
|
||||
** the SQLite library is in use. */
|
||||
if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE;
|
||||
if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE_BKPT;
|
||||
|
||||
va_start(ap, op);
|
||||
switch( op ){
|
||||
@@ -265,7 +265,7 @@ int sqlite3_config(int op, ...){
|
||||
/* Mutex configuration options are only available in a threadsafe
|
||||
** compile.
|
||||
*/
|
||||
#if SQLITE_THREADSAFE
|
||||
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0
|
||||
case SQLITE_CONFIG_SINGLETHREAD: {
|
||||
/* Disable all mutexing */
|
||||
sqlite3GlobalConfig.bCoreMutex = 0;
|
||||
@@ -378,6 +378,21 @@ int sqlite3_config(int op, ...){
|
||||
sqlite3GlobalConfig.nLookaside = va_arg(ap, int);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Record a pointer to the logger funcction and its first argument.
|
||||
** The default is NULL. Logging is disabled if the function pointer is
|
||||
** NULL.
|
||||
*/
|
||||
case SQLITE_CONFIG_LOG: {
|
||||
/* MSVC is picky about pulling func ptrs from va lists.
|
||||
** http://support.microsoft.com/kb/47961
|
||||
** sqlite3GlobalConfig.xLog = va_arg(ap, void(*)(void*,int,const char*));
|
||||
*/
|
||||
typedef void(*LOGFUNC_t)(void*,int,const char*);
|
||||
sqlite3GlobalConfig.xLog = va_arg(ap, LOGFUNC_t);
|
||||
sqlite3GlobalConfig.pLogArg = va_arg(ap, void*);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
rc = SQLITE_ERROR;
|
||||
@@ -591,7 +606,7 @@ int sqlite3_close(sqlite3 *db){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
if( !sqlite3SafetyCheckSickOrOk(db) ){
|
||||
return SQLITE_MISUSE;
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
|
||||
@@ -938,7 +953,7 @@ int sqlite3CreateFunc(
|
||||
(!xFunc && (!xFinal && xStep)) ||
|
||||
(nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) ||
|
||||
(255<(nName = sqlite3Strlen30( zFunctionName))) ){
|
||||
return SQLITE_MISUSE;
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
@@ -1035,7 +1050,7 @@ int sqlite3_create_function16(
|
||||
char *zFunc8;
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
assert( !db->mallocFailed );
|
||||
zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1);
|
||||
zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1, SQLITE_UTF16NATIVE);
|
||||
rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xFunc, xStep, xFinal);
|
||||
sqlite3DbFree(db, zFunc8);
|
||||
rc = sqlite3ApiExit(db, rc);
|
||||
@@ -1269,7 +1284,7 @@ const char *sqlite3_errmsg(sqlite3 *db){
|
||||
return sqlite3ErrStr(SQLITE_NOMEM);
|
||||
}
|
||||
if( !sqlite3SafetyCheckSickOrOk(db) ){
|
||||
return sqlite3ErrStr(SQLITE_MISUSE);
|
||||
return sqlite3ErrStr(SQLITE_MISUSE_BKPT);
|
||||
}
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
if( db->mallocFailed ){
|
||||
@@ -1338,7 +1353,7 @@ const void *sqlite3_errmsg16(sqlite3 *db){
|
||||
*/
|
||||
int sqlite3_errcode(sqlite3 *db){
|
||||
if( db && !sqlite3SafetyCheckSickOrOk(db) ){
|
||||
return SQLITE_MISUSE;
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
if( !db || db->mallocFailed ){
|
||||
return SQLITE_NOMEM;
|
||||
@@ -1347,7 +1362,7 @@ int sqlite3_errcode(sqlite3 *db){
|
||||
}
|
||||
int sqlite3_extended_errcode(sqlite3 *db){
|
||||
if( db && !sqlite3SafetyCheckSickOrOk(db) ){
|
||||
return SQLITE_MISUSE;
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
if( !db || db->mallocFailed ){
|
||||
return SQLITE_NOMEM;
|
||||
@@ -1385,7 +1400,7 @@ static int createCollation(
|
||||
enc2 = SQLITE_UTF16NATIVE;
|
||||
}
|
||||
if( enc2<SQLITE_UTF8 || enc2>SQLITE_UTF16BE ){
|
||||
return SQLITE_MISUSE;
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
|
||||
/* Check if this call is removing or replacing an existing collation
|
||||
@@ -1858,7 +1873,7 @@ int sqlite3_create_collation16(
|
||||
char *zName8;
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
assert( !db->mallocFailed );
|
||||
zName8 = sqlite3Utf16to8(db, zName, -1);
|
||||
zName8 = sqlite3Utf16to8(db, zName, -1, SQLITE_UTF16NATIVE);
|
||||
if( zName8 ){
|
||||
rc = createCollation(db, zName8, (u8)enc, SQLITE_COLL_USER, pCtx, xCompare, 0);
|
||||
sqlite3DbFree(db, zName8);
|
||||
@@ -1929,16 +1944,34 @@ int sqlite3_get_autocommit(sqlite3 *db){
|
||||
return db->autoCommit;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** The following routine is subtituted for constant SQLITE_CORRUPT in
|
||||
** debugging builds. This provides a way to set a breakpoint for when
|
||||
** corruption is first detected.
|
||||
** The following routines are subtitutes for constants SQLITE_CORRUPT,
|
||||
** SQLITE_MISUSE, SQLITE_CANTOPEN, SQLITE_IOERR and possibly other error
|
||||
** constants. They server two purposes:
|
||||
**
|
||||
** 1. Serve as a convenient place to set a breakpoint in a debugger
|
||||
** to detect when version error conditions occurs.
|
||||
**
|
||||
** 2. Invoke sqlite3_log() to provide the source code location where
|
||||
** a low-level error is first detected.
|
||||
*/
|
||||
int sqlite3Corrupt(void){
|
||||
int sqlite3CorruptError(int lineno){
|
||||
testcase( sqlite3GlobalConfig.xLog!=0 );
|
||||
sqlite3_log(SQLITE_CORRUPT,
|
||||
"database corruption found by source line %d", lineno);
|
||||
return SQLITE_CORRUPT;
|
||||
}
|
||||
#endif
|
||||
int sqlite3MisuseError(int lineno){
|
||||
testcase( sqlite3GlobalConfig.xLog!=0 );
|
||||
sqlite3_log(SQLITE_MISUSE, "misuse detected by source line %d", lineno);
|
||||
return SQLITE_MISUSE;
|
||||
}
|
||||
int sqlite3CantopenError(int lineno){
|
||||
testcase( sqlite3GlobalConfig.xLog!=0 );
|
||||
sqlite3_log(SQLITE_CANTOPEN, "cannot open file at source line %d", lineno);
|
||||
return SQLITE_CANTOPEN;
|
||||
}
|
||||
|
||||
|
||||
#ifndef SQLITE_OMIT_DEPRECATED
|
||||
/*
|
||||
@@ -1982,7 +2015,6 @@ int sqlite3_table_column_metadata(
|
||||
|
||||
/* Ensure the database schema has been loaded */
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
(void)sqlite3SafetyOn(db);
|
||||
sqlite3BtreeEnterAll(db);
|
||||
rc = sqlite3Init(db, &zErrMsg);
|
||||
if( SQLITE_OK!=rc ){
|
||||
@@ -2041,7 +2073,6 @@ int sqlite3_table_column_metadata(
|
||||
|
||||
error_out:
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
(void)sqlite3SafetyOff(db);
|
||||
|
||||
/* Whether the function call succeeded or failed, set the output parameters
|
||||
** to whatever their local counterparts contain. If an error did occur,
|
||||
@@ -2281,6 +2312,40 @@ int sqlite3_test_control(int op, ...){
|
||||
break;
|
||||
}
|
||||
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, sqlite3 *db, int N)
|
||||
**
|
||||
** Enable or disable various optimizations for testing purposes. The
|
||||
** argument N is a bitmask of optimizations to be disabled. For normal
|
||||
** operation N should be 0. The idea is that a test program (like the
|
||||
** SQL Logic Test or SLT test module) can run the same SQL multiple times
|
||||
** with various optimizations disabled to verify that the same answer
|
||||
** is obtained in every case.
|
||||
*/
|
||||
case SQLITE_TESTCTRL_OPTIMIZATIONS: {
|
||||
sqlite3 *db = va_arg(ap, sqlite3*);
|
||||
int x = va_arg(ap,int);
|
||||
db->flags = (x & SQLITE_OptMask) | (db->flags & ~SQLITE_OptMask);
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_N_KEYWORD
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_ISKEYWORD, const char *zWord)
|
||||
**
|
||||
** If zWord is a keyword recognized by the parser, then return the
|
||||
** number of keywords. Or if zWord is not a keyword, return 0.
|
||||
**
|
||||
** This test feature is only available in the amalgamation since
|
||||
** the SQLITE_N_KEYWORD macro is not defined in this file if SQLite
|
||||
** is built using separate source files.
|
||||
*/
|
||||
case SQLITE_TESTCTRL_ISKEYWORD: {
|
||||
const char *zWord = va_arg(ap, const char*);
|
||||
int n = sqlite3Strlen30(zWord);
|
||||
rc = (sqlite3KeywordCode((u8*)zWord, n)!=TK_ID) ? SQLITE_N_KEYWORD : 0;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
va_end(ap);
|
||||
#endif /* SQLITE_OMIT_BUILTIN_TEST */
|
||||
|
||||
+20
-13
@@ -42,6 +42,9 @@ static void *sqlite3MemMalloc(int nByte){
|
||||
if( p ){
|
||||
p[0] = nByte;
|
||||
p++;
|
||||
}else{
|
||||
testcase( sqlite3GlobalConfig.xLog!=0 );
|
||||
sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
|
||||
}
|
||||
return (void *)p;
|
||||
}
|
||||
@@ -61,6 +64,18 @@ static void sqlite3MemFree(void *pPrior){
|
||||
free(p);
|
||||
}
|
||||
|
||||
/*
|
||||
** Report the allocated size of a prior return from xMalloc()
|
||||
** or xRealloc().
|
||||
*/
|
||||
static int sqlite3MemSize(void *pPrior){
|
||||
sqlite3_int64 *p;
|
||||
if( pPrior==0 ) return 0;
|
||||
p = (sqlite3_int64*)pPrior;
|
||||
p--;
|
||||
return (int)p[0];
|
||||
}
|
||||
|
||||
/*
|
||||
** Like realloc(). Resize an allocation previously obtained from
|
||||
** sqlite3MemMalloc().
|
||||
@@ -75,28 +90,20 @@ static void *sqlite3MemRealloc(void *pPrior, int nByte){
|
||||
sqlite3_int64 *p = (sqlite3_int64*)pPrior;
|
||||
assert( pPrior!=0 && nByte>0 );
|
||||
nByte = ROUND8(nByte);
|
||||
p = (sqlite3_int64*)pPrior;
|
||||
p--;
|
||||
p = realloc(p, nByte+8 );
|
||||
if( p ){
|
||||
p[0] = nByte;
|
||||
p++;
|
||||
}else{
|
||||
testcase( sqlite3GlobalConfig.xLog!=0 );
|
||||
sqlite3_log(SQLITE_NOMEM,
|
||||
"failed memory resize %u to %u bytes",
|
||||
sqlite3MemSize(pPrior), nByte);
|
||||
}
|
||||
return (void*)p;
|
||||
}
|
||||
|
||||
/*
|
||||
** Report the allocated size of a prior return from xMalloc()
|
||||
** or xRealloc().
|
||||
*/
|
||||
static int sqlite3MemSize(void *pPrior){
|
||||
sqlite3_int64 *p;
|
||||
if( pPrior==0 ) return 0;
|
||||
p = (sqlite3_int64*)pPrior;
|
||||
p--;
|
||||
return (int)p[0];
|
||||
}
|
||||
|
||||
/*
|
||||
** Round up a request size to the next valid allocation size.
|
||||
*/
|
||||
|
||||
+32
-5
@@ -210,6 +210,31 @@ static int sqlite3MemRoundup(int n){
|
||||
return ROUND8(n);
|
||||
}
|
||||
|
||||
/*
|
||||
** Fill a buffer with pseudo-random bytes. This is used to preset
|
||||
** the content of a new memory allocation to unpredictable values and
|
||||
** to clear the content of a freed allocation to unpredictable values.
|
||||
*/
|
||||
static void randomFill(char *pBuf, int nByte){
|
||||
unsigned int x, y, r;
|
||||
x = SQLITE_PTR_TO_INT(pBuf);
|
||||
y = nByte | 1;
|
||||
while( nByte >= 4 ){
|
||||
x = (x>>1) ^ (-(x&1) & 0xd0000001);
|
||||
y = y*1103515245 + 12345;
|
||||
r = x ^ y;
|
||||
*(int*)pBuf = r;
|
||||
pBuf += 4;
|
||||
nByte -= 4;
|
||||
}
|
||||
while( nByte-- > 0 ){
|
||||
x = (x>>1) ^ (-(x&1) & 0xd0000001);
|
||||
y = y*1103515245 + 12345;
|
||||
r = x ^ y;
|
||||
*(pBuf++) = r & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate nByte bytes of memory.
|
||||
*/
|
||||
@@ -260,7 +285,8 @@ static void *sqlite3MemMalloc(int nByte){
|
||||
adjustStats(nByte, +1);
|
||||
pInt = (int*)&pHdr[1];
|
||||
pInt[nReserve/sizeof(int)] = REARGUARD;
|
||||
memset(pInt, 0x65, nReserve);
|
||||
randomFill((char*)pInt, nByte);
|
||||
memset(((char*)pInt)+nByte, 0x65, nReserve-nByte);
|
||||
p = (void*)pInt;
|
||||
}
|
||||
sqlite3_mutex_leave(mem.mutex);
|
||||
@@ -274,7 +300,8 @@ static void sqlite3MemFree(void *pPrior){
|
||||
struct MemBlockHdr *pHdr;
|
||||
void **pBt;
|
||||
char *z;
|
||||
assert( sqlite3GlobalConfig.bMemstat || mem.mutex!=0 );
|
||||
assert( sqlite3GlobalConfig.bMemstat || sqlite3GlobalConfig.bCoreMutex==0
|
||||
|| mem.mutex!=0 );
|
||||
pHdr = sqlite3MemsysGetHeader(pPrior);
|
||||
pBt = (void**)pHdr;
|
||||
pBt -= pHdr->nBacktraceSlots;
|
||||
@@ -296,8 +323,8 @@ static void sqlite3MemFree(void *pPrior){
|
||||
z = (char*)pBt;
|
||||
z -= pHdr->nTitle;
|
||||
adjustStats(pHdr->iSize, -1);
|
||||
memset(z, 0x2b, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) +
|
||||
pHdr->iSize + sizeof(int) + pHdr->nTitle);
|
||||
randomFill(z, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) +
|
||||
pHdr->iSize + sizeof(int) + pHdr->nTitle);
|
||||
free(z);
|
||||
sqlite3_mutex_leave(mem.mutex);
|
||||
}
|
||||
@@ -320,7 +347,7 @@ static void *sqlite3MemRealloc(void *pPrior, int nByte){
|
||||
if( pNew ){
|
||||
memcpy(pNew, pPrior, nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize);
|
||||
if( nByte>pOldHdr->iSize ){
|
||||
memset(&((char*)pNew)[pOldHdr->iSize], 0x2b, nByte - pOldHdr->iSize);
|
||||
randomFill(&((char*)pNew)[pOldHdr->iSize], nByte - pOldHdr->iSize);
|
||||
}
|
||||
sqlite3MemFree(pPrior);
|
||||
}
|
||||
|
||||
+5
-1
@@ -268,7 +268,11 @@ static void *memsys5MallocUnsafe(int nByte){
|
||||
** two in order to create a new free block of size iLogsize.
|
||||
*/
|
||||
for(iBin=iLogsize; mem5.aiFreelist[iBin]<0 && iBin<=LOGMAX; iBin++){}
|
||||
if( iBin>LOGMAX ) return 0;
|
||||
if( iBin>LOGMAX ){
|
||||
testcase( sqlite3GlobalConfig.xLog!=0 );
|
||||
sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte);
|
||||
return 0;
|
||||
}
|
||||
i = memsys5UnlinkFirst(iBin);
|
||||
while( iBin>iLogsize ){
|
||||
int newSize;
|
||||
|
||||
+49
-7
@@ -27,7 +27,16 @@ struct sqlite3_mutex {
|
||||
int id; /* Mutex type */
|
||||
int nRef; /* Number of enterances */
|
||||
DWORD owner; /* Thread holding this mutex */
|
||||
#ifdef SQLITE_DEBUG
|
||||
int trace; /* True to trace changes */
|
||||
#endif
|
||||
};
|
||||
#define SQLITE_W32_MUTEX_INITIALIZER { 0 }
|
||||
#ifdef SQLITE_DEBUG
|
||||
#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0, 0 }
|
||||
#else
|
||||
#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0 }
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
|
||||
@@ -71,8 +80,12 @@ struct sqlite3_mutex {
|
||||
static int winMutexHeld(sqlite3_mutex *p){
|
||||
return p->nRef!=0 && p->owner==GetCurrentThreadId();
|
||||
}
|
||||
static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){
|
||||
return p->nRef==0 || p->owner!=tid;
|
||||
}
|
||||
static int winMutexNotheld(sqlite3_mutex *p){
|
||||
return p->nRef==0 || p->owner!=GetCurrentThreadId();
|
||||
DWORD tid = GetCurrentThreadId();
|
||||
return winMutexNotheld2(p, tid);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -80,7 +93,14 @@ static int winMutexNotheld(sqlite3_mutex *p){
|
||||
/*
|
||||
** Initialize and deinitialize the mutex subsystem.
|
||||
*/
|
||||
static sqlite3_mutex winMutex_staticMutexes[6];
|
||||
static sqlite3_mutex winMutex_staticMutexes[6] = {
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER,
|
||||
SQLITE3_MUTEX_INITIALIZER
|
||||
};
|
||||
static int winMutex_isInit = 0;
|
||||
/* As winMutexInit() and winMutexEnd() are called as part
|
||||
** of the sqlite3_initialize and sqlite3_shutdown()
|
||||
@@ -214,14 +234,23 @@ static void winMutexFree(sqlite3_mutex *p){
|
||||
** more than once, the behavior is undefined.
|
||||
*/
|
||||
static void winMutexEnter(sqlite3_mutex *p){
|
||||
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) );
|
||||
DWORD tid = GetCurrentThreadId();
|
||||
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
|
||||
EnterCriticalSection(&p->mutex);
|
||||
p->owner = GetCurrentThreadId();
|
||||
p->owner = tid;
|
||||
p->nRef++;
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( p->trace ){
|
||||
printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
static int winMutexTry(sqlite3_mutex *p){
|
||||
#ifndef NDEBUG
|
||||
DWORD tid = GetCurrentThreadId();
|
||||
#endif
|
||||
int rc = SQLITE_BUSY;
|
||||
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) );
|
||||
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
|
||||
/*
|
||||
** The sqlite3_mutex_try() routine is very rarely used, and when it
|
||||
** is used it is merely an optimization. So it is OK for it to always
|
||||
@@ -235,12 +264,17 @@ static int winMutexTry(sqlite3_mutex *p){
|
||||
*/
|
||||
#if 0
|
||||
if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){
|
||||
p->owner = GetCurrentThreadId();
|
||||
p->owner = tid;
|
||||
p->nRef++;
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
#else
|
||||
UNUSED_PARAMETER(p);
|
||||
#endif
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( rc==SQLITE_OK && p->trace ){
|
||||
printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
@@ -252,11 +286,19 @@ static int winMutexTry(sqlite3_mutex *p){
|
||||
** is not currently allocated. SQLite will never do either.
|
||||
*/
|
||||
static void winMutexLeave(sqlite3_mutex *p){
|
||||
#ifndef NDEBUG
|
||||
DWORD tid = GetCurrentThreadId();
|
||||
#endif
|
||||
assert( p->nRef>0 );
|
||||
assert( p->owner==GetCurrentThreadId() );
|
||||
assert( p->owner==tid );
|
||||
p->nRef--;
|
||||
assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
|
||||
LeaveCriticalSection(&p->mutex);
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( p->trace ){
|
||||
printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
sqlite3_mutex_methods *sqlite3DefaultMutex(void){
|
||||
|
||||
@@ -112,11 +112,11 @@ int sqlite3OsOpen(
|
||||
){
|
||||
int rc;
|
||||
DO_OS_MALLOC_TEST(0);
|
||||
/* 0x7f1f is a mask of SQLITE_OPEN_ flags that are valid to be passed
|
||||
/* 0x7f3f is a mask of SQLITE_OPEN_ flags that are valid to be passed
|
||||
** down into the VFS layer. Some SQLITE_OPEN_ flags (for example,
|
||||
** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
|
||||
** reaching the VFS. */
|
||||
rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x7f1f, pFlagsOut);
|
||||
rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x7f3f, pFlagsOut);
|
||||
assert( rc==SQLITE_OK || pFile->pMethods==0 );
|
||||
return rc;
|
||||
}
|
||||
|
||||
+890
-465
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -1417,7 +1417,7 @@ static int winOpen(
|
||||
return winOpen(pVfs, zName, id,
|
||||
((flags|SQLITE_OPEN_READONLY)&~SQLITE_OPEN_READWRITE), pOutFlags);
|
||||
}else{
|
||||
return SQLITE_CANTOPEN;
|
||||
return SQLITE_CANTOPEN_BKPT;
|
||||
}
|
||||
}
|
||||
if( pOutFlags ){
|
||||
@@ -1439,7 +1439,7 @@ static int winOpen(
|
||||
){
|
||||
CloseHandle(h);
|
||||
free(zConverted);
|
||||
return SQLITE_CANTOPEN;
|
||||
return SQLITE_CANTOPEN_BKPT;
|
||||
}
|
||||
if( isTemp ){
|
||||
pFile->zDeleteOnClose = zConverted;
|
||||
|
||||
+42
-22
@@ -2019,6 +2019,9 @@ end_playback:
|
||||
rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
|
||||
testcase( rc!=SQLITE_OK );
|
||||
}
|
||||
if( rc==SQLITE_OK && pPager->noSync==0 && pPager->state>=PAGER_EXCLUSIVE ){
|
||||
rc = sqlite3OsSync(pPager->fd, pPager->sync_flags);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = pager_end_transaction(pPager, zMaster[0]!='\0');
|
||||
testcase( rc!=SQLITE_OK );
|
||||
@@ -2875,9 +2878,7 @@ static int pager_write_pagelist(PgHdr *pList){
|
||||
** any such pages to the file.
|
||||
**
|
||||
** Also, do not write out any page that has the PGHDR_DONT_WRITE flag
|
||||
** set (set by sqlite3PagerDontWrite()). Note that if compiled with
|
||||
** SQLITE_SECURE_DELETE the PGHDR_DONT_WRITE bit is never set and so
|
||||
** the second test is always true.
|
||||
** set (set by sqlite3PagerDontWrite()).
|
||||
*/
|
||||
if( pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){
|
||||
i64 offset = (pgno-1)*(i64)pPager->pageSize; /* Offset to write */
|
||||
@@ -3164,7 +3165,7 @@ int sqlite3PagerOpen(
|
||||
** as it will not be possible to open the journal file or even
|
||||
** check for a hot-journal before reading.
|
||||
*/
|
||||
rc = SQLITE_CANTOPEN;
|
||||
rc = SQLITE_CANTOPEN_BKPT;
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_free(zPathname);
|
||||
@@ -3341,6 +3342,7 @@ int sqlite3PagerOpen(
|
||||
/* pPager->pBusyHandlerArg = 0; */
|
||||
pPager->xReiniter = xReinit;
|
||||
/* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
|
||||
|
||||
*ppPager = pPager;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -3490,8 +3492,24 @@ static int readDbPage(PgHdr *pPg){
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
if( pgno==1 ){
|
||||
u8 *dbFileVers = &((u8*)pPg->pData)[24];
|
||||
memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers));
|
||||
if( rc ){
|
||||
/* If the read is unsuccessful, set the dbFileVers[] to something
|
||||
** that will never be a valid file version. dbFileVers[] is a copy
|
||||
** of bytes 24..39 of the database. Bytes 28..31 should always be
|
||||
** zero. Bytes 32..35 and 35..39 should be page numbers which are
|
||||
** never 0xffffffff. So filling pPager->dbFileVers[] with all 0xff
|
||||
** bytes should suffice.
|
||||
**
|
||||
** For an encrypted database, the situation is more complex: bytes
|
||||
** 24..39 of the database are white noise. But the probability of
|
||||
** white noising equaling 16 bytes of 0xff is vanishingly small so
|
||||
** we should still be ok.
|
||||
*/
|
||||
memset(pPager->dbFileVers, 0xff, sizeof(pPager->dbFileVers));
|
||||
}else{
|
||||
u8 *dbFileVers = &((u8*)pPg->pData)[24];
|
||||
memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers));
|
||||
}
|
||||
}
|
||||
CODEC1(pPager, pPg->pData, pgno, 3, rc = SQLITE_NOMEM);
|
||||
|
||||
@@ -3623,7 +3641,7 @@ int sqlite3PagerSharedLock(Pager *pPager){
|
||||
rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout);
|
||||
assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
|
||||
if( rc==SQLITE_OK && fout&SQLITE_OPEN_READONLY ){
|
||||
rc = SQLITE_CANTOPEN;
|
||||
rc = SQLITE_CANTOPEN_BKPT;
|
||||
sqlite3OsClose(pPager->jfd);
|
||||
}
|
||||
}else{
|
||||
@@ -3842,7 +3860,7 @@ int sqlite3PagerAcquire(
|
||||
goto pager_acquire_err;
|
||||
}
|
||||
|
||||
if( MEMDB || nMax<(int)pgno || noContent ){
|
||||
if( MEMDB || nMax<(int)pgno || noContent || !isOpen(pPager->fd) ){
|
||||
if( pgno>pPager->mxPgno ){
|
||||
rc = SQLITE_FULL;
|
||||
goto pager_acquire_err;
|
||||
@@ -3862,9 +3880,8 @@ int sqlite3PagerAcquire(
|
||||
TESTONLY( rc = ) addToSavepointBitvecs(pPager, pgno);
|
||||
testcase( rc==SQLITE_NOMEM );
|
||||
sqlite3EndBenignMalloc();
|
||||
}else{
|
||||
memset(pPg->pData, 0, pPager->pageSize);
|
||||
}
|
||||
memset(pPg->pData, 0, pPager->pageSize);
|
||||
IOTRACE(("ZERO %p %d\n", pPager, pgno));
|
||||
}else{
|
||||
assert( pPg->pPager==pPager );
|
||||
@@ -4386,7 +4403,6 @@ int sqlite3PagerIswriteable(DbPage *pPg){
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_SECURE_DELETE
|
||||
/*
|
||||
** A call to this routine tells the pager that it is not necessary to
|
||||
** write the information on page pPg back to the disk, even though
|
||||
@@ -4412,7 +4428,6 @@ void sqlite3PagerDontWrite(PgHdr *pPg){
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif /* !defined(SQLITE_SECURE_DELETE) */
|
||||
|
||||
/*
|
||||
** This routine is called to increment the value of the database file
|
||||
@@ -4982,30 +4997,35 @@ int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
|
||||
** operation. Store this value in nNew. Then free resources associated
|
||||
** with any savepoints that are destroyed by this operation.
|
||||
*/
|
||||
nNew = iSavepoint + (op==SAVEPOINT_ROLLBACK);
|
||||
nNew = iSavepoint + (( op==SAVEPOINT_RELEASE ) ? 0 : 1);
|
||||
for(ii=nNew; ii<pPager->nSavepoint; ii++){
|
||||
sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint);
|
||||
}
|
||||
pPager->nSavepoint = nNew;
|
||||
|
||||
/* If this is a rollback operation, playback the specified savepoint.
|
||||
/* If this is a release of the outermost savepoint, truncate
|
||||
** the sub-journal to zero bytes in size. */
|
||||
if( op==SAVEPOINT_RELEASE ){
|
||||
if( nNew==0 && isOpen(pPager->sjfd) ){
|
||||
/* Only truncate if it is an in-memory sub-journal. */
|
||||
if( sqlite3IsMemJournal(pPager->sjfd) ){
|
||||
rc = sqlite3OsTruncate(pPager->sjfd, 0);
|
||||
assert( rc==SQLITE_OK );
|
||||
}
|
||||
pPager->nSubRec = 0;
|
||||
}
|
||||
}
|
||||
/* Else this is a rollback operation, playback the specified savepoint.
|
||||
** If this is a temp-file, it is possible that the journal file has
|
||||
** not yet been opened. In this case there have been no changes to
|
||||
** the database file, so the playback operation can be skipped.
|
||||
*/
|
||||
if( op==SAVEPOINT_ROLLBACK && isOpen(pPager->jfd) ){
|
||||
else if( isOpen(pPager->jfd) ){
|
||||
PagerSavepoint *pSavepoint = (nNew==0)?0:&pPager->aSavepoint[nNew-1];
|
||||
rc = pagerPlaybackSavepoint(pPager, pSavepoint);
|
||||
assert(rc!=SQLITE_DONE);
|
||||
}
|
||||
|
||||
/* If this is a release of the outermost savepoint, truncate
|
||||
** the sub-journal to zero bytes in size. */
|
||||
if( nNew==0 && op==SAVEPOINT_RELEASE && isOpen(pPager->sjfd) ){
|
||||
assert( rc==SQLITE_OK );
|
||||
rc = sqlite3OsTruncate(pPager->sjfd, 0);
|
||||
pPager->nSubRec = 0;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -316,6 +316,7 @@ refargs(A) ::= . { A = OE_None*0x0101; /* EV: R-19803-45884 */}
|
||||
refargs(A) ::= refargs(X) refarg(Y). { A = (X & ~Y.mask) | Y.value; }
|
||||
%type refarg {struct {int value; int mask;}}
|
||||
refarg(A) ::= MATCH nm. { A.value = 0; A.mask = 0x000000; }
|
||||
refarg(A) ::= ON INSERT refact. { A.value = 0; A.mask = 0x000000; }
|
||||
refarg(A) ::= ON DELETE refact(X). { A.value = X; A.mask = 0x0000ff; }
|
||||
refarg(A) ::= ON UPDATE refact(X). { A.value = X<<8; A.mask = 0x00ff00; }
|
||||
%type refact {int}
|
||||
|
||||
@@ -189,6 +189,7 @@ void sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
|
||||
if( pCache->pCache ){
|
||||
sqlite3GlobalConfig.pcache.xDestroy(pCache->pCache);
|
||||
pCache->pCache = 0;
|
||||
pCache->pPage1 = 0;
|
||||
}
|
||||
pCache->szPage = szPage;
|
||||
}
|
||||
@@ -242,6 +243,7 @@ int sqlite3PcacheFetch(
|
||||
pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC));
|
||||
pPg=pPg->pDirtyPrev
|
||||
);
|
||||
pCache->pSynced = pPg;
|
||||
if( !pPg ){
|
||||
for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev);
|
||||
}
|
||||
|
||||
+49
-11
@@ -285,6 +285,7 @@ void sqlite3Pragma(
|
||||
Db *pDb;
|
||||
Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db);
|
||||
if( v==0 ) return;
|
||||
sqlite3VdbeRunOnlyOnce(v);
|
||||
pParse->nMem = 2;
|
||||
|
||||
/* Interpret the [database.] part of the pragma statement. iDb is the
|
||||
@@ -416,6 +417,31 @@ void sqlite3Pragma(
|
||||
returnSingleInt(pParse, "max_page_count", newMax);
|
||||
}else
|
||||
|
||||
/*
|
||||
** PRAGMA [database.]secure_delete
|
||||
** PRAGMA [database.]secure_delete=ON/OFF
|
||||
**
|
||||
** The first form reports the current setting for the
|
||||
** secure_delete flag. The second form changes the secure_delete
|
||||
** flag setting and reports thenew value.
|
||||
*/
|
||||
if( sqlite3StrICmp(zLeft,"secure_delete")==0 ){
|
||||
Btree *pBt = pDb->pBt;
|
||||
int b = -1;
|
||||
assert( pBt!=0 );
|
||||
if( zRight ){
|
||||
b = getBoolean(zRight);
|
||||
}
|
||||
if( pId2->n==0 && b>=0 ){
|
||||
int ii;
|
||||
for(ii=0; ii<db->nDb; ii++){
|
||||
sqlite3BtreeSecureDelete(db->aDb[ii].pBt, b);
|
||||
}
|
||||
}
|
||||
b = sqlite3BtreeSecureDelete(pBt, b);
|
||||
returnSingleInt(pParse, "secure_delete", b);
|
||||
}else
|
||||
|
||||
/*
|
||||
** PRAGMA [database.]page_count
|
||||
**
|
||||
@@ -1334,6 +1360,26 @@ void sqlite3Pragma(
|
||||
}else
|
||||
#endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */
|
||||
|
||||
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
|
||||
/*
|
||||
** PRAGMA compile_options
|
||||
**
|
||||
** Return the names of all compile-time options used in this build,
|
||||
** one option per row.
|
||||
*/
|
||||
if( sqlite3StrICmp(zLeft, "compile_options")==0 ){
|
||||
int i = 0;
|
||||
const char *zOpt;
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
pParse->nMem = 1;
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "compile_option", SQLITE_STATIC);
|
||||
while( (zOpt = sqlite3_compileoption_get(i++))!=0 ){
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zOpt, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
|
||||
}
|
||||
}else
|
||||
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
|
||||
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
||||
/*
|
||||
** Report the current state of file logs for all databases
|
||||
@@ -1368,7 +1414,7 @@ void sqlite3Pragma(
|
||||
}else
|
||||
#endif
|
||||
|
||||
#if SQLITE_HAS_CODEC
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
if( sqlite3StrICmp(zLeft, "key")==0 && zRight ){
|
||||
sqlite3_key(db, zRight, sqlite3Strlen30(zRight));
|
||||
}else
|
||||
@@ -1409,17 +1455,15 @@ void sqlite3Pragma(
|
||||
}else
|
||||
/** END CRYPTO **/
|
||||
#endif
|
||||
#if SQLITE_HAS_CODEC || defined(SQLITE_ENABLE_CEROD)
|
||||
#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
|
||||
if( sqlite3StrICmp(zLeft, "activate_extensions")==0 ){
|
||||
#if SQLITE_HAS_CODEC
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){
|
||||
extern void sqlite3_activate_see(const char*);
|
||||
sqlite3_activate_see(&zRight[4]);
|
||||
}
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_CEROD
|
||||
if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){
|
||||
extern void sqlite3_activate_cerod(const char*);
|
||||
sqlite3_activate_cerod(&zRight[6]);
|
||||
}
|
||||
#endif
|
||||
@@ -1429,12 +1473,6 @@ void sqlite3Pragma(
|
||||
|
||||
{/* Empty ELSE clause */}
|
||||
|
||||
/* Code an OP_Expire at the end of each PRAGMA program to cause
|
||||
** the VDBE implementing the pragma to expire. Most (all?) pragmas
|
||||
** are only valid for a single execution.
|
||||
*/
|
||||
sqlite3VdbeAddOp2(v, OP_Expire, 1, 0);
|
||||
|
||||
/*
|
||||
** Reset the safety level, in case the fullfsync flag or synchronous
|
||||
** setting changed.
|
||||
|
||||
+6
-21
@@ -192,9 +192,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
|
||||
initData.iDb = iDb;
|
||||
initData.rc = SQLITE_OK;
|
||||
initData.pzErrMsg = pzErrMsg;
|
||||
(void)sqlite3SafetyOff(db);
|
||||
sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
|
||||
(void)sqlite3SafetyOn(db);
|
||||
if( initData.rc ){
|
||||
rc = initData.rc;
|
||||
goto error_out;
|
||||
@@ -315,9 +313,8 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
|
||||
{
|
||||
char *zSql;
|
||||
zSql = sqlite3MPrintf(db,
|
||||
"SELECT name, rootpage, sql FROM '%q'.%s",
|
||||
"SELECT name, rootpage, sql FROM '%q'.%s ORDER BY rowid",
|
||||
db->aDb[iDb].zName, zMasterName);
|
||||
(void)sqlite3SafetyOff(db);
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
{
|
||||
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
|
||||
@@ -330,7 +327,6 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
|
||||
}
|
||||
#endif
|
||||
if( rc==SQLITE_OK ) rc = initData.rc;
|
||||
(void)sqlite3SafetyOn(db);
|
||||
sqlite3DbFree(db, zSql);
|
||||
#ifndef SQLITE_OMIT_ANALYZE
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -469,7 +465,7 @@ static void schemaIsValid(Parse *pParse){
|
||||
}
|
||||
|
||||
/* Read the schema cookie from the database. If it does not match the
|
||||
** value stored as part of the in the in-memory schema representation,
|
||||
** value stored as part of the in-memory schema representation,
|
||||
** set Parse.rc to SQLITE_SCHEMA. */
|
||||
sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&cookie);
|
||||
if( cookie!=db->aDb[iDb].pSchema->schema_cookie ){
|
||||
@@ -539,11 +535,6 @@ static int sqlite3Prepare(
|
||||
goto end_prepare;
|
||||
}
|
||||
pParse->pReprepare = pReprepare;
|
||||
|
||||
if( sqlite3SafetyOn(db) ){
|
||||
rc = SQLITE_MISUSE;
|
||||
goto end_prepare;
|
||||
}
|
||||
assert( ppStmt && *ppStmt==0 );
|
||||
assert( !db->mallocFailed );
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
@@ -579,7 +570,6 @@ static int sqlite3Prepare(
|
||||
if( rc ){
|
||||
const char *zDb = db->aDb[i].zName;
|
||||
sqlite3Error(db, rc, "database schema is locked: %s", zDb);
|
||||
(void)sqlite3SafetyOff(db);
|
||||
testcase( db->flags & SQLITE_ReadUncommitted );
|
||||
goto end_prepare;
|
||||
}
|
||||
@@ -596,7 +586,6 @@ static int sqlite3Prepare(
|
||||
testcase( nBytes==mxLen+1 );
|
||||
if( nBytes>mxLen ){
|
||||
sqlite3Error(db, SQLITE_TOOBIG, "statement too long");
|
||||
(void)sqlite3SafetyOff(db);
|
||||
rc = sqlite3ApiExit(db, SQLITE_TOOBIG);
|
||||
goto end_prepare;
|
||||
}
|
||||
@@ -653,10 +642,6 @@ static int sqlite3Prepare(
|
||||
}
|
||||
#endif
|
||||
|
||||
if( sqlite3SafetyOff(db) ){
|
||||
rc = SQLITE_MISUSE;
|
||||
}
|
||||
|
||||
assert( db->init.busy==0 || saveSqlFlag==0 );
|
||||
if( db->init.busy==0 ){
|
||||
Vdbe *pVdbe = pParse->pVdbe;
|
||||
@@ -704,7 +689,7 @@ static int sqlite3LockAndPrepare(
|
||||
assert( ppStmt!=0 );
|
||||
*ppStmt = 0;
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
return SQLITE_MISUSE;
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
sqlite3BtreeEnterAll(db);
|
||||
@@ -743,7 +728,7 @@ int sqlite3Reprepare(Vdbe *p){
|
||||
db->mallocFailed = 1;
|
||||
}
|
||||
assert( pNew==0 );
|
||||
return (rc==SQLITE_LOCKED) ? SQLITE_LOCKED : SQLITE_SCHEMA;
|
||||
return rc;
|
||||
}else{
|
||||
assert( pNew!=0 );
|
||||
}
|
||||
@@ -812,10 +797,10 @@ static int sqlite3Prepare16(
|
||||
assert( ppStmt );
|
||||
*ppStmt = 0;
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
return SQLITE_MISUSE;
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
zSql8 = sqlite3Utf16to8(db, zSql, nBytes);
|
||||
zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE);
|
||||
if( zSql8 ){
|
||||
rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, 0, ppStmt, &zTail8);
|
||||
}
|
||||
|
||||
+37
-3
@@ -460,7 +460,9 @@ void sqlite3VXPrintf(
|
||||
case etEXP:
|
||||
case etGENERIC:
|
||||
realvalue = va_arg(ap,double);
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
#ifdef SQLITE_OMIT_FLOATING_POINT
|
||||
length = 0;
|
||||
#else
|
||||
if( precision<0 ) precision = 6; /* Set default precision */
|
||||
if( precision>etBUFSIZE/2-10 ) precision = etBUFSIZE/2-10;
|
||||
if( realvalue<0.0 ){
|
||||
@@ -606,7 +608,7 @@ void sqlite3VXPrintf(
|
||||
while( nPad-- ) bufpt[i++] = '0';
|
||||
length = width;
|
||||
}
|
||||
#endif
|
||||
#endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */
|
||||
break;
|
||||
case etSIZE:
|
||||
*(va_arg(ap,int*)) = pAccum->nChar;
|
||||
@@ -653,7 +655,7 @@ void sqlite3VXPrintf(
|
||||
isnull = escarg==0;
|
||||
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
|
||||
k = precision;
|
||||
for(i=n=0; (ch=escarg[i])!=0 && k!=0; i++, k--){
|
||||
for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){
|
||||
if( ch==q ) n++;
|
||||
}
|
||||
needQuote = !isnull && xtype==etSQLESCAPE2;
|
||||
@@ -937,6 +939,38 @@ char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
|
||||
return z;
|
||||
}
|
||||
|
||||
/*
|
||||
** This is the routine that actually formats the sqlite3_log() message.
|
||||
** We house it in a separate routine from sqlite3_log() to avoid using
|
||||
** stack space on small-stack systems when logging is disabled.
|
||||
**
|
||||
** sqlite3_log() must render into a static buffer. It cannot dynamically
|
||||
** allocate memory because it might be called while the memory allocator
|
||||
** mutex is held.
|
||||
*/
|
||||
static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){
|
||||
StrAccum acc; /* String accumulator */
|
||||
char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */
|
||||
|
||||
sqlite3StrAccumInit(&acc, zMsg, sizeof(zMsg), 0);
|
||||
acc.useMalloc = 0;
|
||||
sqlite3VXPrintf(&acc, 0, zFormat, ap);
|
||||
sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode,
|
||||
sqlite3StrAccumFinish(&acc));
|
||||
}
|
||||
|
||||
/*
|
||||
** Format and write a message to the log if logging is enabled.
|
||||
*/
|
||||
void sqlite3_log(int iErrCode, const char *zFormat, ...){
|
||||
va_list ap; /* Vararg list */
|
||||
if( sqlite3GlobalConfig.xLog ){
|
||||
va_start(ap, zFormat);
|
||||
renderLogMsg(iErrCode, zFormat, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(SQLITE_DEBUG)
|
||||
/*
|
||||
** A version of printf() that understands %lld. Used for debugging.
|
||||
|
||||
+20
-16
@@ -243,19 +243,18 @@ static int lookupName(
|
||||
int iCol;
|
||||
pSchema = pTab->pSchema;
|
||||
cntTab++;
|
||||
if( sqlite3IsRowid(zCol) ){
|
||||
iCol = -1;
|
||||
}else{
|
||||
for(iCol=0; iCol<pTab->nCol; iCol++){
|
||||
Column *pCol = &pTab->aCol[iCol];
|
||||
if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
|
||||
if( iCol==pTab->iPKey ){
|
||||
iCol = -1;
|
||||
}
|
||||
break;
|
||||
for(iCol=0; iCol<pTab->nCol; iCol++){
|
||||
Column *pCol = &pTab->aCol[iCol];
|
||||
if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
|
||||
if( iCol==pTab->iPKey ){
|
||||
iCol = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) ){
|
||||
iCol = -1; /* IMP: R-44911-55124 */
|
||||
}
|
||||
if( iCol<pTab->nCol ){
|
||||
cnt++;
|
||||
if( iCol<0 ){
|
||||
@@ -282,7 +281,7 @@ static int lookupName(
|
||||
*/
|
||||
if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){
|
||||
cnt = 1;
|
||||
pExpr->iColumn = -1;
|
||||
pExpr->iColumn = -1; /* IMP: R-44911-55124 */
|
||||
pExpr->affinity = SQLITE_AFF_INTEGER;
|
||||
}
|
||||
|
||||
@@ -665,6 +664,9 @@ static int resolveOrderByTermToExprList(
|
||||
int i; /* Loop counter */
|
||||
ExprList *pEList; /* The columns of the result set */
|
||||
NameContext nc; /* Name context for resolving pE */
|
||||
sqlite3 *db; /* Database connection */
|
||||
int rc; /* Return code from subprocedures */
|
||||
u8 savedSuppErr; /* Saved value of db->suppressErr */
|
||||
|
||||
assert( sqlite3ExprIsInteger(pE, &i)==0 );
|
||||
pEList = pSelect->pEList;
|
||||
@@ -677,17 +679,19 @@ static int resolveOrderByTermToExprList(
|
||||
nc.pEList = pEList;
|
||||
nc.allowAgg = 1;
|
||||
nc.nErr = 0;
|
||||
if( sqlite3ResolveExprNames(&nc, pE) ){
|
||||
sqlite3ErrorClear(pParse);
|
||||
return 0;
|
||||
}
|
||||
db = pParse->db;
|
||||
savedSuppErr = db->suppressErr;
|
||||
db->suppressErr = 1;
|
||||
rc = sqlite3ResolveExprNames(&nc, pE);
|
||||
db->suppressErr = savedSuppErr;
|
||||
if( rc ) return 0;
|
||||
|
||||
/* Try to match the ORDER BY expression against an expression
|
||||
** in the result set. Return an 1-based index of the matching
|
||||
** result-set entry.
|
||||
*/
|
||||
for(i=0; i<pEList->nExpr; i++){
|
||||
if( sqlite3ExprCompare(pEList->a[i].pExpr, pE) ){
|
||||
if( sqlite3ExprCompare(pEList->a[i].pExpr, pE)<2 ){
|
||||
return i+1;
|
||||
}
|
||||
}
|
||||
|
||||
+85
-37
@@ -189,6 +189,39 @@ static int columnIndex(Table *pTab, const char *zCol){
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Search the first N tables in pSrc, from left to right, looking for a
|
||||
** table that has a column named zCol.
|
||||
**
|
||||
** When found, set *piTab and *piCol to the table index and column index
|
||||
** of the matching column and return TRUE.
|
||||
**
|
||||
** If not found, return FALSE.
|
||||
*/
|
||||
static int tableAndColumnIndex(
|
||||
SrcList *pSrc, /* Array of tables to search */
|
||||
int N, /* Number of tables in pSrc->a[] to search */
|
||||
const char *zCol, /* Name of the column we are looking for */
|
||||
int *piTab, /* Write index of pSrc->a[] here */
|
||||
int *piCol /* Write index of pSrc->a[*piTab].pTab->aCol[] here */
|
||||
){
|
||||
int i; /* For looping over tables in pSrc */
|
||||
int iCol; /* Index of column matching zCol */
|
||||
|
||||
assert( (piTab==0)==(piCol==0) ); /* Both or neither are NULL */
|
||||
for(i=0; i<N; i++){
|
||||
iCol = columnIndex(pSrc->a[i].pTab, zCol);
|
||||
if( iCol>=0 ){
|
||||
if( piTab ){
|
||||
*piTab = i;
|
||||
*piCol = iCol;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is used to add terms implied by JOIN syntax to the
|
||||
** WHERE clause expression of a SELECT statement. The new term, which
|
||||
@@ -203,8 +236,9 @@ static int columnIndex(Table *pTab, const char *zCol){
|
||||
static void addWhereTerm(
|
||||
Parse *pParse, /* Parsing context */
|
||||
SrcList *pSrc, /* List of tables in FROM clause */
|
||||
int iSrc, /* Index of first table to join in pSrc */
|
||||
int iLeft, /* Index of first table to join in pSrc */
|
||||
int iColLeft, /* Index of column in first table */
|
||||
int iRight, /* Index of second table in pSrc */
|
||||
int iColRight, /* Index of column in second table */
|
||||
int isOuterJoin, /* True if this is an OUTER join */
|
||||
Expr **ppWhere /* IN/OUT: The WHERE clause to add to */
|
||||
@@ -214,12 +248,13 @@ static void addWhereTerm(
|
||||
Expr *pE2;
|
||||
Expr *pEq;
|
||||
|
||||
assert( pSrc->nSrc>(iSrc+1) );
|
||||
assert( pSrc->a[iSrc].pTab );
|
||||
assert( pSrc->a[iSrc+1].pTab );
|
||||
assert( iLeft<iRight );
|
||||
assert( pSrc->nSrc>iRight );
|
||||
assert( pSrc->a[iLeft].pTab );
|
||||
assert( pSrc->a[iRight].pTab );
|
||||
|
||||
pE1 = sqlite3CreateColumnExpr(db, pSrc, iSrc, iColLeft);
|
||||
pE2 = sqlite3CreateColumnExpr(db, pSrc, iSrc+1, iColRight);
|
||||
pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iColLeft);
|
||||
pE2 = sqlite3CreateColumnExpr(db, pSrc, iRight, iColRight);
|
||||
|
||||
pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2, 0);
|
||||
if( pEq && isOuterJoin ){
|
||||
@@ -308,11 +343,15 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
|
||||
"an ON or USING clause", 0);
|
||||
return 1;
|
||||
}
|
||||
for(j=0; j<pLeftTab->nCol; j++){
|
||||
char *zName = pLeftTab->aCol[j].zName;
|
||||
int iRightCol = columnIndex(pRightTab, zName);
|
||||
if( iRightCol>=0 ){
|
||||
addWhereTerm(pParse, pSrc, i, j, iRightCol, isOuter, &p->pWhere);
|
||||
for(j=0; j<pRightTab->nCol; j++){
|
||||
char *zName; /* Name of column in the right table */
|
||||
int iLeft; /* Matching left table */
|
||||
int iLeftCol; /* Matching column in the left table */
|
||||
|
||||
zName = pRightTab->aCol[j].zName;
|
||||
if( tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol) ){
|
||||
addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, j,
|
||||
isOuter, &p->pWhere);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -344,15 +383,22 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
|
||||
if( pRight->pUsing ){
|
||||
IdList *pList = pRight->pUsing;
|
||||
for(j=0; j<pList->nId; j++){
|
||||
char *zName = pList->a[j].zName;
|
||||
int iLeftCol = columnIndex(pLeftTab, zName);
|
||||
int iRightCol = columnIndex(pRightTab, zName);
|
||||
if( iLeftCol<0 || iRightCol<0 ){
|
||||
char *zName; /* Name of the term in the USING clause */
|
||||
int iLeft; /* Table on the left with matching column name */
|
||||
int iLeftCol; /* Column number of matching column on the left */
|
||||
int iRightCol; /* Column number of matching column on the right */
|
||||
|
||||
zName = pList->a[j].zName;
|
||||
iRightCol = columnIndex(pRightTab, zName);
|
||||
if( iRightCol<0
|
||||
|| !tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol)
|
||||
){
|
||||
sqlite3ErrorMsg(pParse, "cannot join using column %s - column "
|
||||
"not present in both tables", zName);
|
||||
return 1;
|
||||
}
|
||||
addWhereTerm(pParse, pSrc, i, iLeftCol, iRightCol, isOuter, &p->pWhere);
|
||||
addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, iRightCol,
|
||||
isOuter, &p->pWhere);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -911,7 +957,7 @@ static const char *columnType(
|
||||
** of the SELECT statement. Return the declaration type and origin
|
||||
** data for the result-set column of the sub-select.
|
||||
*/
|
||||
if( ALWAYS(iCol>=0 && iCol<pS->pEList->nExpr) ){
|
||||
if( iCol>=0 && ALWAYS(iCol<pS->pEList->nExpr) ){
|
||||
/* If iCol is less than zero, then the expression requests the
|
||||
** rowid of the sub-select or view. This expression is legal (see
|
||||
** test case misc2.2.2) - it always evaluates to NULL.
|
||||
@@ -2472,7 +2518,7 @@ static void substSelect(
|
||||
**
|
||||
** (11) The subquery and the outer query do not both have ORDER BY clauses.
|
||||
**
|
||||
** (12) Not implemented. Subsumed into restriction (3). Was previously
|
||||
** (**) Not implemented. Subsumed into restriction (3). Was previously
|
||||
** a separate restriction deriving from ticket #350.
|
||||
**
|
||||
** (13) The subquery and outer query do not both use LIMIT
|
||||
@@ -2546,6 +2592,7 @@ static int flattenSubquery(
|
||||
*/
|
||||
assert( p!=0 );
|
||||
assert( p->pPrior==0 ); /* Unable to flatten compound queries */
|
||||
if( db->flags & SQLITE_QueryFlattener ) return 0;
|
||||
pSrc = p->pSrc;
|
||||
assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc );
|
||||
pSubitem = &pSrc->a[iFrom];
|
||||
@@ -3169,14 +3216,14 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
}
|
||||
|
||||
if( i>0 && zTName==0 ){
|
||||
struct SrcList_item *pLeft = &pTabList->a[i-1];
|
||||
if( (pLeft[1].jointype & JT_NATURAL)!=0 &&
|
||||
columnIndex(pLeft->pTab, zName)>=0 ){
|
||||
if( (pFrom->jointype & JT_NATURAL)!=0
|
||||
&& tableAndColumnIndex(pTabList, i, zName, 0, 0)
|
||||
){
|
||||
/* In a NATURAL join, omit the join columns from the
|
||||
** table on the right */
|
||||
** table to the right of the join */
|
||||
continue;
|
||||
}
|
||||
if( sqlite3IdListIndex(pLeft[1].pUsing, zName)>=0 ){
|
||||
if( sqlite3IdListIndex(pFrom->pUsing, zName)>=0 ){
|
||||
/* In a join with a USING clause, omit columns in the
|
||||
** using clause from the table on the right. */
|
||||
continue;
|
||||
@@ -3280,18 +3327,19 @@ static int selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
|
||||
struct SrcList_item *pFrom;
|
||||
|
||||
assert( p->selFlags & SF_Resolved );
|
||||
assert( (p->selFlags & SF_HasTypeInfo)==0 );
|
||||
p->selFlags |= SF_HasTypeInfo;
|
||||
pParse = pWalker->pParse;
|
||||
pTabList = p->pSrc;
|
||||
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
|
||||
Table *pTab = pFrom->pTab;
|
||||
if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){
|
||||
/* A sub-query in the FROM clause of a SELECT */
|
||||
Select *pSel = pFrom->pSelect;
|
||||
assert( pSel );
|
||||
while( pSel->pPrior ) pSel = pSel->pPrior;
|
||||
selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel);
|
||||
if( (p->selFlags & SF_HasTypeInfo)==0 ){
|
||||
p->selFlags |= SF_HasTypeInfo;
|
||||
pParse = pWalker->pParse;
|
||||
pTabList = p->pSrc;
|
||||
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
|
||||
Table *pTab = pFrom->pTab;
|
||||
if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){
|
||||
/* A sub-query in the FROM clause of a SELECT */
|
||||
Select *pSel = pFrom->pSelect;
|
||||
assert( pSel );
|
||||
while( pSel->pPrior ) pSel = pSel->pPrior;
|
||||
selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel);
|
||||
}
|
||||
}
|
||||
}
|
||||
return WRC_Continue;
|
||||
@@ -3443,8 +3491,8 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
|
||||
sqlite3VdbeAddOp4(v, OP_AggStep, 0, regAgg, pF->iMem,
|
||||
(void*)pF->pFunc, P4_FUNCDEF);
|
||||
sqlite3VdbeChangeP5(v, (u8)nArg);
|
||||
sqlite3ReleaseTempRange(pParse, regAgg, nArg);
|
||||
sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg);
|
||||
sqlite3ReleaseTempRange(pParse, regAgg, nArg);
|
||||
if( addrNext ){
|
||||
sqlite3VdbeResolveLabel(v, addrNext);
|
||||
sqlite3ExprCacheClear(pParse);
|
||||
@@ -3870,7 +3918,7 @@ int sqlite3Select(
|
||||
int r2;
|
||||
|
||||
r2 = sqlite3ExprCodeGetColumn(pParse,
|
||||
pCol->pTab, pCol->iColumn, pCol->iTable, r1, 0);
|
||||
pCol->pTab, pCol->iColumn, pCol->iTable, r1);
|
||||
if( r1!=r2 ){
|
||||
sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1);
|
||||
}
|
||||
|
||||
+51
-965
File diff suppressed because it is too large
Load Diff
+1445
-1488
File diff suppressed because it is too large
Load Diff
+110
-107
@@ -76,41 +76,43 @@
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The number of samples of an index that SQLite takes in order to
|
||||
** construct a histogram of the table content when running ANALYZE
|
||||
** and with SQLITE_ENABLE_STAT2
|
||||
*/
|
||||
#define SQLITE_INDEX_SAMPLES 10
|
||||
|
||||
/*
|
||||
** This macro is used to "hide" some ugliness in casting an int
|
||||
** value to a ptr value under the MSVC 64-bit compiler. Casting
|
||||
** non 64-bit values to ptr types results in a "hard" error with
|
||||
** the MSVC 64-bit compiler which this attempts to avoid.
|
||||
** The following macros are used to cast pointers to integers and
|
||||
** integers to pointers. The way you do this varies from one compiler
|
||||
** to the next, so we have developed the following set of #if statements
|
||||
** to generate appropriate macros for a wide range of compilers.
|
||||
**
|
||||
** A simple compiler pragma or casting sequence could not be found
|
||||
** to correct this in all situations, so this macro was introduced.
|
||||
**
|
||||
** It could be argued that the intptr_t type could be used in this
|
||||
** case, but that type is not available on all compilers, or
|
||||
** requires the #include of specific headers which differs between
|
||||
** platforms.
|
||||
** The correct "ANSI" way to do this is to use the intptr_t type.
|
||||
** Unfortunately, that typedef is not available on all compilers, or
|
||||
** if it is available, it requires an #include of specific headers
|
||||
** that very from one machine to the next.
|
||||
**
|
||||
** Ticket #3860: The llvm-gcc-4.2 compiler from Apple chokes on
|
||||
** the ((void*)&((char*)0)[X]) construct. But MSVC chokes on ((void*)(X)).
|
||||
** So we have to define the macros in different ways depending on the
|
||||
** compiler.
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
# if defined(HAVE_STDINT_H)
|
||||
# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X))
|
||||
# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X))
|
||||
# else
|
||||
# define SQLITE_INT_TO_PTR(X) ((void*)(X))
|
||||
# define SQLITE_PTR_TO_INT(X) ((int)(X))
|
||||
# endif
|
||||
#else
|
||||
# define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X])
|
||||
# define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0))
|
||||
#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */
|
||||
# define SQLITE_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X))
|
||||
# define SQLITE_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X))
|
||||
#elif !defined(__GNUC__) /* Works for compilers other than LLVM */
|
||||
# define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X])
|
||||
# define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0))
|
||||
#elif defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */
|
||||
# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X))
|
||||
# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X))
|
||||
#else /* Generates a warning - but it always works */
|
||||
# define SQLITE_INT_TO_PTR(X) ((void*)(X))
|
||||
# define SQLITE_PTR_TO_INT(X) ((int)(X))
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** The SQLITE_THREADSAFE macro must be defined as either 0 or 1.
|
||||
** Older versions of SQLite used an optional THREADSAFE macro.
|
||||
@@ -140,23 +142,18 @@
|
||||
**
|
||||
** SQLITE_SYSTEM_MALLOC // Use normal system malloc()
|
||||
** SQLITE_MEMDEBUG // Debugging version of system malloc()
|
||||
** SQLITE_MEMORY_SIZE // internal allocator #1
|
||||
** SQLITE_MMAP_HEAP_SIZE // internal mmap() allocator
|
||||
** SQLITE_POW2_MEMORY_SIZE // internal power-of-two allocator
|
||||
**
|
||||
** (Historical note: There used to be several other options, but we've
|
||||
** pared it down to just these two.)
|
||||
**
|
||||
** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
|
||||
** the default.
|
||||
*/
|
||||
#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+\
|
||||
defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+\
|
||||
defined(SQLITE_POW2_MEMORY_SIZE)>1
|
||||
#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)>1
|
||||
# error "At most one of the following compile-time configuration options\
|
||||
is allows: SQLITE_SYSTEM_MALLOC, SQLITE_MEMDEBUG, SQLITE_MEMORY_SIZE,\
|
||||
SQLITE_MMAP_HEAP_SIZE, SQLITE_POW2_MEMORY_SIZE"
|
||||
is allows: SQLITE_SYSTEM_MALLOC, SQLITE_MEMDEBUG"
|
||||
#endif
|
||||
#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+\
|
||||
defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+\
|
||||
defined(SQLITE_POW2_MEMORY_SIZE)==0
|
||||
#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)==0
|
||||
# define SQLITE_SYSTEM_MALLOC 1
|
||||
#endif
|
||||
|
||||
@@ -328,20 +325,6 @@
|
||||
#define OMIT_TEMPDB 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
** If the following macro is set to 1, then NULL values are considered
|
||||
** distinct when determining whether or not two entries are the same
|
||||
** in a UNIQUE index. This is the way PostgreSQL, Oracle, DB2, MySQL,
|
||||
** OCELOT, and Firebird all work. The SQL92 spec explicitly says this
|
||||
** is the way things are suppose to work.
|
||||
**
|
||||
** If the following macro is set to 0, the NULLs are indistinct for
|
||||
** a UNIQUE index. In this mode, you can only have a single NULL entry
|
||||
** for a column declared UNIQUE. This is the way Informix and SQL Server
|
||||
** work.
|
||||
*/
|
||||
#define NULL_DISTINCT_FOR_UNIQUE 1
|
||||
|
||||
/*
|
||||
** The "file format" number is an integer that is incremented whenever
|
||||
** the VDBE-level file format changes. The following macros define the
|
||||
@@ -353,6 +336,10 @@
|
||||
# define SQLITE_DEFAULT_FILE_FORMAT 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Determine whether triggers are recursive by default. This can be
|
||||
** changed at run-time using a pragma.
|
||||
*/
|
||||
#ifndef SQLITE_DEFAULT_RECURSIVE_TRIGGERS
|
||||
# define SQLITE_DEFAULT_RECURSIVE_TRIGGERS 0
|
||||
#endif
|
||||
@@ -597,7 +584,6 @@ typedef struct AggInfo AggInfo;
|
||||
typedef struct AuthContext AuthContext;
|
||||
typedef struct AutoincInfo AutoincInfo;
|
||||
typedef struct Bitvec Bitvec;
|
||||
typedef struct RowSet RowSet;
|
||||
typedef struct CollSeq CollSeq;
|
||||
typedef struct Column Column;
|
||||
typedef struct Db Db;
|
||||
@@ -618,6 +604,7 @@ typedef struct LookasideSlot LookasideSlot;
|
||||
typedef struct Module Module;
|
||||
typedef struct NameContext NameContext;
|
||||
typedef struct Parse Parse;
|
||||
typedef struct RowSet RowSet;
|
||||
typedef struct Savepoint Savepoint;
|
||||
typedef struct Select Select;
|
||||
typedef struct SrcList SrcList;
|
||||
@@ -625,9 +612,9 @@ typedef struct StrAccum StrAccum;
|
||||
typedef struct Table Table;
|
||||
typedef struct TableLock TableLock;
|
||||
typedef struct Token Token;
|
||||
typedef struct Trigger Trigger;
|
||||
typedef struct TriggerPrg TriggerPrg;
|
||||
typedef struct TriggerStep TriggerStep;
|
||||
typedef struct Trigger Trigger;
|
||||
typedef struct UnpackedRecord UnpackedRecord;
|
||||
typedef struct VTable VTable;
|
||||
typedef struct Walker Walker;
|
||||
@@ -693,7 +680,7 @@ struct Schema {
|
||||
|
||||
/*
|
||||
** These macros can be used to test, set, or clear bits in the
|
||||
** Db.flags field.
|
||||
** Db.pSchema->flags field.
|
||||
*/
|
||||
#define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))==(P))
|
||||
#define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))!=0)
|
||||
@@ -701,7 +688,7 @@ struct Schema {
|
||||
#define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->flags&=~(P)
|
||||
|
||||
/*
|
||||
** Allowed values for the DB.flags field.
|
||||
** Allowed values for the DB.pSchema->flags field.
|
||||
**
|
||||
** The DB_SchemaLoaded flag is set after the database schema has been
|
||||
** read into internal hash tables.
|
||||
@@ -765,7 +752,7 @@ struct FuncDefHash {
|
||||
};
|
||||
|
||||
/*
|
||||
** Each database is an instance of the following structure.
|
||||
** Each database connection is an instance of the following structure.
|
||||
**
|
||||
** The sqlite.lastRowid records the last insert rowid generated by an
|
||||
** insert statement. Inserts on views do not affect its value. Each
|
||||
@@ -804,6 +791,7 @@ struct sqlite3 {
|
||||
u8 dfltLockMode; /* Default locking-mode for attached dbs */
|
||||
u8 dfltJournalMode; /* Default journal mode for attached dbs */
|
||||
signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */
|
||||
u8 suppressErr; /* Do not issue error messages if true */
|
||||
int nextPagesize; /* Pagesize after VACUUM if >0 */
|
||||
int nTable; /* Number of tables in the database */
|
||||
CollSeq *pDfltColl; /* The default collating sequence (BINARY) */
|
||||
@@ -898,37 +886,43 @@ struct sqlite3 {
|
||||
#define ENC(db) ((db)->aDb[0].pSchema->enc)
|
||||
|
||||
/*
|
||||
** Possible values for the sqlite.flags and or Db.flags fields.
|
||||
**
|
||||
** On sqlite.flags, the SQLITE_InTrans value means that we have
|
||||
** executed a BEGIN. On Db.flags, SQLITE_InTrans means a statement
|
||||
** transaction is active on that particular database file.
|
||||
** Possible values for the sqlite3.flags.
|
||||
*/
|
||||
#define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */
|
||||
#define SQLITE_InTrans 0x00000008 /* True if in a transaction */
|
||||
#define SQLITE_InternChanges 0x00000010 /* Uncommitted Hash table changes */
|
||||
#define SQLITE_FullColNames 0x00000020 /* Show full column names on SELECT */
|
||||
#define SQLITE_ShortColNames 0x00000040 /* Show short columns names */
|
||||
#define SQLITE_CountRows 0x00000080 /* Count rows changed by INSERT, */
|
||||
#define SQLITE_VdbeTrace 0x00000100 /* True to trace VDBE execution */
|
||||
#define SQLITE_InternChanges 0x00000200 /* Uncommitted Hash table changes */
|
||||
#define SQLITE_FullColNames 0x00000400 /* Show full column names on SELECT */
|
||||
#define SQLITE_ShortColNames 0x00000800 /* Show short columns names */
|
||||
#define SQLITE_CountRows 0x00001000 /* Count rows changed by INSERT, */
|
||||
/* DELETE, or UPDATE and return */
|
||||
/* the count using a callback. */
|
||||
#define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */
|
||||
#define SQLITE_NullCallback 0x00002000 /* Invoke the callback once if the */
|
||||
/* result set is empty */
|
||||
#define SQLITE_SqlTrace 0x00000200 /* Debug print SQL as it executes */
|
||||
#define SQLITE_VdbeListing 0x00000400 /* Debug listings of VDBE programs */
|
||||
#define SQLITE_WriteSchema 0x00000800 /* OK to update SQLITE_MASTER */
|
||||
#define SQLITE_NoReadlock 0x00001000 /* Readlocks are omitted when
|
||||
#define SQLITE_SqlTrace 0x00004000 /* Debug print SQL as it executes */
|
||||
#define SQLITE_VdbeListing 0x00008000 /* Debug listings of VDBE programs */
|
||||
#define SQLITE_WriteSchema 0x00010000 /* OK to update SQLITE_MASTER */
|
||||
#define SQLITE_NoReadlock 0x00020000 /* Readlocks are omitted when
|
||||
** accessing read-only databases */
|
||||
#define SQLITE_IgnoreChecks 0x00002000 /* Do not enforce check constraints */
|
||||
#define SQLITE_ReadUncommitted 0x00004000 /* For shared-cache mode */
|
||||
#define SQLITE_LegacyFileFmt 0x00008000 /* Create new databases in format 1 */
|
||||
#define SQLITE_FullFSync 0x00010000 /* Use full fsync on the backend */
|
||||
#define SQLITE_LoadExtension 0x00020000 /* Enable load_extension */
|
||||
#define SQLITE_IgnoreChecks 0x00040000 /* Do not enforce check constraints */
|
||||
#define SQLITE_ReadUncommitted 0x0080000 /* For shared-cache mode */
|
||||
#define SQLITE_LegacyFileFmt 0x00100000 /* Create new databases in format 1 */
|
||||
#define SQLITE_FullFSync 0x00200000 /* Use full fsync on the backend */
|
||||
#define SQLITE_LoadExtension 0x00400000 /* Enable load_extension */
|
||||
#define SQLITE_RecoveryMode 0x00800000 /* Ignore schema errors */
|
||||
#define SQLITE_ReverseOrder 0x01000000 /* Reverse unordered SELECTs */
|
||||
#define SQLITE_RecTriggers 0x02000000 /* Enable recursive triggers */
|
||||
#define SQLITE_ForeignKeys 0x04000000 /* Enforce foreign key constraints */
|
||||
|
||||
#define SQLITE_RecoveryMode 0x00040000 /* Ignore schema errors */
|
||||
#define SQLITE_ReverseOrder 0x00100000 /* Reverse unordered SELECTs */
|
||||
#define SQLITE_RecTriggers 0x00200000 /* Enable recursive triggers */
|
||||
#define SQLITE_ForeignKeys 0x00400000 /* Enforce foreign key constraints */
|
||||
/*
|
||||
** Bits of the sqlite3.flags field that are used by the
|
||||
** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface.
|
||||
** These must be the low-order bits of the flags field.
|
||||
*/
|
||||
#define SQLITE_QueryFlattener 0x01 /* Disable query flattening */
|
||||
#define SQLITE_ColumnCache 0x02 /* Disable the column cache */
|
||||
#define SQLITE_IndexSort 0x04 /* Disable indexes for sorting */
|
||||
#define SQLITE_IndexSearch 0x08 /* Disable indexes for searching */
|
||||
#define SQLITE_IndexCover 0x10 /* Disable index covering table */
|
||||
#define SQLITE_OptMask 0x1f /* Mask of all disablable opts */
|
||||
|
||||
/*
|
||||
** Possible values for the sqlite.magic field.
|
||||
@@ -1642,14 +1636,13 @@ struct Expr {
|
||||
#define EP_DblQuoted 0x0040 /* token.z was originally in "..." */
|
||||
#define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */
|
||||
#define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */
|
||||
#define EP_AnyAff 0x0200 /* Can take a cached column of any affinity */
|
||||
#define EP_FixedDest 0x0400 /* Result needed in a specific register */
|
||||
#define EP_IntValue 0x0800 /* Integer value contained in u.iValue */
|
||||
#define EP_xIsSelect 0x1000 /* x.pSelect is valid (otherwise x.pList is) */
|
||||
#define EP_FixedDest 0x0200 /* Result needed in a specific register */
|
||||
#define EP_IntValue 0x0400 /* Integer value contained in u.iValue */
|
||||
#define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */
|
||||
|
||||
#define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */
|
||||
#define EP_TokenOnly 0x4000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */
|
||||
#define EP_Static 0x8000 /* Held in memory not obtained from malloc() */
|
||||
#define EP_Reduced 0x1000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */
|
||||
#define EP_TokenOnly 0x2000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */
|
||||
#define EP_Static 0x4000 /* Held in memory not obtained from malloc() */
|
||||
|
||||
/*
|
||||
** The following are the meanings of bits in the Expr.flags2 field.
|
||||
@@ -1894,6 +1887,7 @@ struct WhereLevel {
|
||||
#define WHERE_OMIT_OPEN 0x0010 /* Table cursor are already open */
|
||||
#define WHERE_OMIT_CLOSE 0x0020 /* Omit close of table & index cursors */
|
||||
#define WHERE_FORCE_TABLE 0x0040 /* Do not use an index-only search */
|
||||
#define WHERE_ONETABLE_ONLY 0x0080 /* Only code the 1st table in pTabList */
|
||||
|
||||
/*
|
||||
** The WHERE clause processing routine has two halves. The
|
||||
@@ -1906,6 +1900,7 @@ struct WhereInfo {
|
||||
Parse *pParse; /* Parsing and code generating context */
|
||||
u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
|
||||
u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE or DELETE */
|
||||
u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
|
||||
SrcList *pTabList; /* List of tables in the join */
|
||||
int iTop; /* The very beginning of the WHERE loop */
|
||||
int iContinue; /* Jump here to continue with next record */
|
||||
@@ -2125,7 +2120,6 @@ struct Parse {
|
||||
struct yColCache {
|
||||
int iTable; /* Table cursor number */
|
||||
int iColumn; /* Table column number */
|
||||
u8 affChange; /* True if this register has had an affinity change */
|
||||
u8 tempReg; /* iReg is a temp register that needs to be freed */
|
||||
int iLevel; /* Nesting level */
|
||||
int iReg; /* Reg with value of this column. 0 means none. */
|
||||
@@ -2374,6 +2368,8 @@ struct Sqlite3Config {
|
||||
int isPCacheInit; /* True after malloc is initialized */
|
||||
sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */
|
||||
int nRefInitMutex; /* Number of users of pInitMutex */
|
||||
void (*xLog)(void*,int,const char*); /* Function for logging */
|
||||
void *pLogArg; /* First argument to xLog() */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -2415,16 +2411,27 @@ int sqlite3WalkSelectFrom(Walker*, Select*);
|
||||
}
|
||||
|
||||
/*
|
||||
** The SQLITE_CORRUPT_BKPT macro can be either a constant (for production
|
||||
** builds) or a function call (for debugging). If it is a function call,
|
||||
** it allows the operator to set a breakpoint at the spot where database
|
||||
** corruption is first detected.
|
||||
** The SQLITE_*_BKPT macros are substitutes for the error codes with
|
||||
** the same name but without the _BKPT suffix. These macros invoke
|
||||
** routines that report the line-number on which the error originated
|
||||
** using sqlite3_log(). The routines also provide a convenient place
|
||||
** to set a debugger breakpoint.
|
||||
*/
|
||||
#ifdef SQLITE_DEBUG
|
||||
int sqlite3Corrupt(void);
|
||||
# define SQLITE_CORRUPT_BKPT sqlite3Corrupt()
|
||||
#else
|
||||
# define SQLITE_CORRUPT_BKPT SQLITE_CORRUPT
|
||||
int sqlite3CorruptError(int);
|
||||
int sqlite3MisuseError(int);
|
||||
int sqlite3CantopenError(int);
|
||||
#define SQLITE_CORRUPT_BKPT sqlite3CorruptError(__LINE__)
|
||||
#define SQLITE_MISUSE_BKPT sqlite3MisuseError(__LINE__)
|
||||
#define SQLITE_CANTOPEN_BKPT sqlite3CantopenError(__LINE__)
|
||||
|
||||
|
||||
/*
|
||||
** FTS4 is really an extension for FTS3. It is enabled using the
|
||||
** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also all
|
||||
** the SQLITE_ENABLE_FTS4 macro to serve as an alisse for SQLITE_ENABLE_FTS3.
|
||||
*/
|
||||
#if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3)
|
||||
# define SQLITE_ENABLE_FTS3
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -2526,7 +2533,11 @@ int sqlite3StatusValue(int);
|
||||
void sqlite3StatusAdd(int, int);
|
||||
void sqlite3StatusSet(int, int);
|
||||
|
||||
int sqlite3IsNaN(double);
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
int sqlite3IsNaN(double);
|
||||
#else
|
||||
# define sqlite3IsNaN(X) 0
|
||||
#endif
|
||||
|
||||
void sqlite3VXPrintf(StrAccum*, int, const char*, va_list);
|
||||
#ifndef SQLITE_OMIT_TRACE
|
||||
@@ -2543,7 +2554,6 @@ char *sqlite3MAppendf(sqlite3*,char*,const char*,...);
|
||||
#endif
|
||||
void sqlite3SetString(char **, sqlite3*, const char*, ...);
|
||||
void sqlite3ErrorMsg(Parse*, const char*, ...);
|
||||
void sqlite3ErrorClear(Parse*);
|
||||
int sqlite3Dequote(char*);
|
||||
int sqlite3KeywordCode(const unsigned char*, int);
|
||||
int sqlite3RunParser(Parse*, const char*, char **);
|
||||
@@ -2644,13 +2654,13 @@ void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
|
||||
void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
|
||||
WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u16);
|
||||
void sqlite3WhereEnd(WhereInfo*);
|
||||
int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, int);
|
||||
int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int);
|
||||
void sqlite3ExprCodeMove(Parse*, int, int, int);
|
||||
void sqlite3ExprCodeCopy(Parse*, int, int, int);
|
||||
void sqlite3ExprCacheStore(Parse*, int, int, int);
|
||||
void sqlite3ExprCachePush(Parse*);
|
||||
void sqlite3ExprCachePop(Parse*, int);
|
||||
void sqlite3ExprCacheRemove(Parse*, int);
|
||||
void sqlite3ExprCacheRemove(Parse*, int, int);
|
||||
void sqlite3ExprCacheClear(Parse*);
|
||||
void sqlite3ExprCacheAffinityChange(Parse*, int, int);
|
||||
void sqlite3ExprHardCopy(Parse*,int,int);
|
||||
@@ -2713,13 +2723,6 @@ FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,int);
|
||||
void sqlite3RegisterBuiltinFunctions(sqlite3*);
|
||||
void sqlite3RegisterDateTimeFunctions(void);
|
||||
void sqlite3RegisterGlobalFunctions(void);
|
||||
#ifdef SQLITE_DEBUG
|
||||
int sqlite3SafetyOn(sqlite3*);
|
||||
int sqlite3SafetyOff(sqlite3*);
|
||||
#else
|
||||
# define sqlite3SafetyOn(A) 0
|
||||
# define sqlite3SafetyOff(A) 0
|
||||
#endif
|
||||
int sqlite3SafetyCheckOk(sqlite3*);
|
||||
int sqlite3SafetyCheckSickOrOk(sqlite3*);
|
||||
void sqlite3ChangeCookie(Parse*, int);
|
||||
@@ -2855,7 +2858,7 @@ void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
|
||||
void(*)(void*));
|
||||
void sqlite3ValueFree(sqlite3_value*);
|
||||
sqlite3_value *sqlite3ValueNew(sqlite3 *);
|
||||
char *sqlite3Utf16to8(sqlite3 *, const void*, int);
|
||||
char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8);
|
||||
#ifdef SQLITE_ENABLE_STAT2
|
||||
char *sqlite3Utf8to16(sqlite3 *, u8, char *, int, int *);
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -83,7 +83,7 @@ void sqlite3StatusSet(int op, int X){
|
||||
int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
|
||||
wsdStatInit;
|
||||
if( op<0 || op>=ArraySize(wsdStat.nowValue) ){
|
||||
return SQLITE_MISUSE;
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
*pCurrent = wsdStat.nowValue[op];
|
||||
*pHighwater = wsdStat.mxValue[op];
|
||||
|
||||
+2
-2
@@ -4909,7 +4909,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
extern int sqlite3_open_file_count;
|
||||
extern int sqlite3_sort_count;
|
||||
extern int sqlite3_current_time;
|
||||
#if SQLITE_OS_UNIX && defined(__APPLE__)
|
||||
#if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
|
||||
extern int sqlite3_hostid_num;
|
||||
#endif
|
||||
extern int sqlite3_max_blobsize;
|
||||
@@ -5140,7 +5140,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
(char*)&sqlite3_open_file_count, TCL_LINK_INT);
|
||||
Tcl_LinkVar(interp, "sqlite_current_time",
|
||||
(char*)&sqlite3_current_time, TCL_LINK_INT);
|
||||
#if SQLITE_OS_UNIX && defined(__APPLE__)
|
||||
#if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
|
||||
Tcl_LinkVar(interp, "sqlite_hostid_num",
|
||||
(char*)&sqlite3_hostid_num, TCL_LINK_INT);
|
||||
#endif
|
||||
|
||||
+3
-1
@@ -219,7 +219,7 @@ static int btree_cursor(
|
||||
Btree *pBt;
|
||||
int iTable;
|
||||
BtCursor *pCur;
|
||||
int rc;
|
||||
int rc = SQLITE_OK;
|
||||
int wrFlag;
|
||||
char zBuf[30];
|
||||
|
||||
@@ -234,7 +234,9 @@ static int btree_cursor(
|
||||
pCur = (BtCursor *)ckalloc(sqlite3BtreeCursorSize());
|
||||
memset(pCur, 0, sqlite3BtreeCursorSize());
|
||||
sqlite3BtreeEnter(pBt);
|
||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||
rc = sqlite3BtreeLockTable(pBt, iTable, wrFlag);
|
||||
#endif
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3BtreeCursor(pBt, iTable, wrFlag, 0, pCur);
|
||||
}
|
||||
|
||||
+5
-1
@@ -183,7 +183,11 @@ static void set_options(Tcl_Interp *interp){
|
||||
TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef SQLITE_OMIT_COMPILEOPTION_DIAGS
|
||||
Tcl_SetVar2(interp, "sqlite_options", "compileoption_diags", "0", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp, "sqlite_options", "compileoption_diags", "1", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_OMIT_COMPLETE
|
||||
Tcl_SetVar2(interp, "sqlite_options", "complete", "0", TCL_GLOBAL_ONLY);
|
||||
|
||||
@@ -341,6 +341,7 @@ static void testHexToBin(const char *zIn, char *zOut){
|
||||
** Convert the input string from HEX into binary. Then return the
|
||||
** result using sqlite3_result_text16le().
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
static void testHexToUtf16be(
|
||||
sqlite3_context *pCtx,
|
||||
int nArg,
|
||||
@@ -360,6 +361,7 @@ static void testHexToUtf16be(
|
||||
sqlite3_result_text16be(pCtx, zOut, n/2, sqlite3_free);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** hex_to_utf8(HEX)
|
||||
@@ -393,6 +395,7 @@ static void testHexToUtf8(
|
||||
** Convert the input string from HEX into binary. Then return the
|
||||
** result using sqlite3_result_text16le().
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
static void testHexToUtf16le(
|
||||
sqlite3_context *pCtx,
|
||||
int nArg,
|
||||
@@ -412,6 +415,7 @@ static void testHexToUtf16le(
|
||||
sqlite3_result_text16le(pCtx, zOut, n/2, sqlite3_free);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int registerTestFunctions(sqlite3 *db){
|
||||
static const struct {
|
||||
|
||||
+3
-3
@@ -330,12 +330,12 @@ static int getFts3Varint(const char *p, sqlite_int64 *v){
|
||||
|
||||
|
||||
/*
|
||||
** USAGE: read_varint BLOB VARNAME
|
||||
** USAGE: read_fts3varint BLOB VARNAME
|
||||
**
|
||||
** Read a varint from the start of BLOB. Set variable VARNAME to contain
|
||||
** the interpreted value. Return the number of bytes of BLOB consumed.
|
||||
*/
|
||||
static int read_varint(
|
||||
static int read_fts3varint(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
@@ -373,7 +373,7 @@ int Sqlitetest_hexio_Init(Tcl_Interp *interp){
|
||||
{ "hexio_render_int16", hexio_render_int16 },
|
||||
{ "hexio_render_int32", hexio_render_int32 },
|
||||
{ "utf8_to_utf8", utf8_to_utf8 },
|
||||
{ "read_varint", read_varint },
|
||||
{ "read_fts3varint", read_fts3varint },
|
||||
};
|
||||
int i;
|
||||
for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
|
||||
|
||||
+5
-2
@@ -123,8 +123,9 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){
|
||||
}
|
||||
case '-': {
|
||||
if( z[1]=='-' ){
|
||||
/* IMP: R-15891-05542 -- syntax diagram for comments */
|
||||
for(i=2; (c=z[i])!=0 && c!='\n'; i++){}
|
||||
*tokenType = TK_SPACE;
|
||||
*tokenType = TK_SPACE; /* IMP: R-22934-25134 */
|
||||
return i;
|
||||
}
|
||||
*tokenType = TK_MINUS;
|
||||
@@ -155,9 +156,10 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){
|
||||
*tokenType = TK_SLASH;
|
||||
return 1;
|
||||
}
|
||||
/* IMP: R-15891-05542 -- syntax diagram for comments */
|
||||
for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){}
|
||||
if( c ) i++;
|
||||
*tokenType = TK_SPACE;
|
||||
*tokenType = TK_SPACE; /* IMP: R-22934-25134 */
|
||||
return i;
|
||||
}
|
||||
case '%': {
|
||||
@@ -478,6 +480,7 @@ abort_parse:
|
||||
assert( pzErrMsg!=0 );
|
||||
if( pParse->zErrMsg ){
|
||||
*pzErrMsg = pParse->zErrMsg;
|
||||
sqlite3_log(pParse->rc, "%s", *pzErrMsg);
|
||||
pParse->zErrMsg = 0;
|
||||
nErr++;
|
||||
}
|
||||
|
||||
+9
-8
@@ -126,7 +126,8 @@ void sqlite3BeginTrigger(
|
||||
goto trigger_cleanup;
|
||||
}
|
||||
pTab = sqlite3SrcListLookup(pParse, pTableName);
|
||||
if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){
|
||||
if( db->init.busy==0 && pName2->n==0 && pTab
|
||||
&& pTab->pSchema==db->aDb[1].pSchema ){
|
||||
iDb = 1;
|
||||
}
|
||||
|
||||
@@ -254,12 +255,12 @@ void sqlite3FinishTrigger(
|
||||
TriggerStep *pStepList, /* The triggered program */
|
||||
Token *pAll /* Token that describes the complete CREATE TRIGGER */
|
||||
){
|
||||
Trigger *pTrig = pParse->pNewTrigger; /* Trigger being finished */
|
||||
char *zName; /* Name of trigger */
|
||||
sqlite3 *db = pParse->db; /* The database */
|
||||
DbFixer sFix;
|
||||
int iDb; /* Database containing the trigger */
|
||||
Token nameToken; /* Trigger name for error reporting */
|
||||
Trigger *pTrig = pParse->pNewTrigger; /* Trigger being finished */
|
||||
char *zName; /* Name of trigger */
|
||||
sqlite3 *db = pParse->db; /* The database */
|
||||
DbFixer sFix; /* Fixer object */
|
||||
int iDb; /* Database containing the trigger */
|
||||
Token nameToken; /* Trigger name for error reporting */
|
||||
|
||||
pTrig = pParse->pNewTrigger;
|
||||
pParse->pNewTrigger = 0;
|
||||
@@ -278,7 +279,7 @@ void sqlite3FinishTrigger(
|
||||
goto triggerfinish_cleanup;
|
||||
}
|
||||
|
||||
/* if we are not initializing, and this trigger is not on a TEMP table,
|
||||
/* if we are not initializing,
|
||||
** build the sqlite_master entry
|
||||
*/
|
||||
if( !db->init.busy ){
|
||||
|
||||
@@ -437,11 +437,11 @@ int sqlite3Utf8To8(unsigned char *zIn){
|
||||
**
|
||||
** NULL is returned if there is an allocation error.
|
||||
*/
|
||||
char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte){
|
||||
char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 enc){
|
||||
Mem m;
|
||||
memset(&m, 0, sizeof(m));
|
||||
m.db = db;
|
||||
sqlite3VdbeMemSetStr(&m, z, nByte, SQLITE_UTF16NATIVE, SQLITE_STATIC);
|
||||
sqlite3VdbeMemSetStr(&m, z, nByte, enc, SQLITE_STATIC);
|
||||
sqlite3VdbeChangeEncoding(&m, SQLITE_UTF8);
|
||||
if( db->mallocFailed ){
|
||||
sqlite3VdbeMemRelease(&m);
|
||||
@@ -449,7 +449,9 @@ char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte){
|
||||
}
|
||||
assert( (m.flags & MEM_Term)!=0 || db->mallocFailed );
|
||||
assert( (m.flags & MEM_Str)!=0 || db->mallocFailed );
|
||||
return (m.flags & MEM_Dyn)!=0 ? m.z : sqlite3DbStrDup(db, m.z);
|
||||
assert( (m.flags & MEM_Dyn)!=0 || db->mallocFailed );
|
||||
assert( m.z || db->mallocFailed );
|
||||
return m.z;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+79
-89
@@ -31,6 +31,7 @@ void sqlite3Coverage(int x){
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
/*
|
||||
** Return true if the floating point value is Not a Number (NaN).
|
||||
**
|
||||
@@ -75,6 +76,7 @@ int sqlite3IsNaN(double x){
|
||||
testcase( rc );
|
||||
return rc;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_FLOATING_POINT */
|
||||
|
||||
/*
|
||||
** Compute a string length that is limited to what can be stored in
|
||||
@@ -146,23 +148,20 @@ void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){
|
||||
** (sqlite3_step() etc.).
|
||||
*/
|
||||
void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
|
||||
char *zMsg;
|
||||
va_list ap;
|
||||
sqlite3 *db = pParse->db;
|
||||
pParse->nErr++;
|
||||
sqlite3DbFree(db, pParse->zErrMsg);
|
||||
va_start(ap, zFormat);
|
||||
pParse->zErrMsg = sqlite3VMPrintf(db, zFormat, ap);
|
||||
zMsg = sqlite3VMPrintf(db, zFormat, ap);
|
||||
va_end(ap);
|
||||
pParse->rc = SQLITE_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
** Clear the error message in pParse, if any
|
||||
*/
|
||||
void sqlite3ErrorClear(Parse *pParse){
|
||||
sqlite3DbFree(pParse->db, pParse->zErrMsg);
|
||||
pParse->zErrMsg = 0;
|
||||
pParse->nErr = 0;
|
||||
if( db->suppressErr ){
|
||||
sqlite3DbFree(db, zMsg);
|
||||
}else{
|
||||
pParse->nErr++;
|
||||
sqlite3DbFree(db, pParse->zErrMsg);
|
||||
pParse->zErrMsg = zMsg;
|
||||
pParse->rc = SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -255,6 +254,7 @@ int sqlite3IsNumber(const char *z, int *realnum, u8 enc){
|
||||
z += incr;
|
||||
*realnum = 0;
|
||||
while( sqlite3Isdigit(*z) ){ z += incr; }
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
if( *z=='.' ){
|
||||
z += incr;
|
||||
if( !sqlite3Isdigit(*z) ) return 0;
|
||||
@@ -268,6 +268,7 @@ int sqlite3IsNumber(const char *z, int *realnum, u8 enc){
|
||||
while( sqlite3Isdigit(*z) ){ z += incr; }
|
||||
*realnum = 1;
|
||||
}
|
||||
#endif
|
||||
return *z==0;
|
||||
}
|
||||
|
||||
@@ -429,6 +430,9 @@ static int compare2pow63(const char *zNum){
|
||||
c = memcmp(zNum,"922337203685477580",18)*10;
|
||||
if( c==0 ){
|
||||
c = zNum[18] - '8';
|
||||
testcase( c==(-1) );
|
||||
testcase( c==0 );
|
||||
testcase( c==(+1) );
|
||||
}
|
||||
return c;
|
||||
}
|
||||
@@ -465,6 +469,9 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum){
|
||||
v = v*10 + c - '0';
|
||||
}
|
||||
*pNum = neg ? -v : v;
|
||||
testcase( i==18 );
|
||||
testcase( i==19 );
|
||||
testcase( i==20 );
|
||||
if( c!=0 || (i==0 && zStart==zNum) || i>19 ){
|
||||
/* zNum is empty or contains non-numeric text or is longer
|
||||
** than 19 digits (thus guaranting that it is too large) */
|
||||
@@ -508,6 +515,9 @@ int sqlite3FitsIn64Bits(const char *zNum, int negFlag){
|
||||
zNum++; /* Skip leading zeros. Ticket #2454 */
|
||||
}
|
||||
for(i=0; zNum[i]; i++){ assert( zNum[i]>='0' && zNum[i]<='9' ); }
|
||||
testcase( i==18 );
|
||||
testcase( i==19 );
|
||||
testcase( i==20 );
|
||||
if( i<19 ){
|
||||
/* Guaranteed to fit if less than 19 digits */
|
||||
return 1;
|
||||
@@ -548,9 +558,11 @@ int sqlite3GetInt32(const char *zNum, int *pValue){
|
||||
** 1234567890
|
||||
** 2^31 -> 2147483648
|
||||
*/
|
||||
testcase( i==10 );
|
||||
if( i>10 ){
|
||||
return 0;
|
||||
}
|
||||
testcase( v-neg==2147483647 );
|
||||
if( v-neg>2147483647 ){
|
||||
return 0;
|
||||
}
|
||||
@@ -638,6 +650,19 @@ int sqlite3PutVarint32(unsigned char *p, u32 v){
|
||||
return sqlite3PutVarint(p, v);
|
||||
}
|
||||
|
||||
/*
|
||||
** Bitmasks used by sqlite3GetVarint(). These precomputed constants
|
||||
** are defined here rather than simply putting the constant expressions
|
||||
** inline in order to work around bugs in the RVT compiler.
|
||||
**
|
||||
** SLOT_2_0 A mask for (0x7f<<14) | 0x7f
|
||||
**
|
||||
** SLOT_4_2_0 A mask for (0x7f<<28) | SLOT_2_0
|
||||
*/
|
||||
#define SLOT_2_0 0x001fc07f
|
||||
#define SLOT_4_2_0 0xf01fc07f
|
||||
|
||||
|
||||
/*
|
||||
** Read a 64-bit variable-length integer from memory starting at p[0].
|
||||
** Return the number of bytes read. The value is stored in *v.
|
||||
@@ -665,13 +690,17 @@ u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* Verify that constants are precomputed correctly */
|
||||
assert( SLOT_2_0 == ((0x7f<<14) | (0x7f)) );
|
||||
assert( SLOT_4_2_0 == ((0xfU<<28) | (0x7f<<14) | (0x7f)) );
|
||||
|
||||
p++;
|
||||
a = a<<14;
|
||||
a |= *p;
|
||||
/* a: p0<<14 | p2 (unmasked) */
|
||||
if (!(a&0x80))
|
||||
{
|
||||
a &= (0x7f<<14)|(0x7f);
|
||||
a &= SLOT_2_0;
|
||||
b &= 0x7f;
|
||||
b = b<<7;
|
||||
a |= b;
|
||||
@@ -680,14 +709,14 @@ u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
|
||||
}
|
||||
|
||||
/* CSE1 from below */
|
||||
a &= (0x7f<<14)|(0x7f);
|
||||
a &= SLOT_2_0;
|
||||
p++;
|
||||
b = b<<14;
|
||||
b |= *p;
|
||||
/* b: p1<<14 | p3 (unmasked) */
|
||||
if (!(b&0x80))
|
||||
{
|
||||
b &= (0x7f<<14)|(0x7f);
|
||||
b &= SLOT_2_0;
|
||||
/* moved CSE1 up */
|
||||
/* a &= (0x7f<<14)|(0x7f); */
|
||||
a = a<<7;
|
||||
@@ -701,7 +730,7 @@ u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
|
||||
/* 1:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
|
||||
/* moved CSE1 up */
|
||||
/* a &= (0x7f<<14)|(0x7f); */
|
||||
b &= (0x7f<<14)|(0x7f);
|
||||
b &= SLOT_2_0;
|
||||
s = a;
|
||||
/* s: p0<<14 | p2 (masked) */
|
||||
|
||||
@@ -734,7 +763,7 @@ u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
|
||||
{
|
||||
/* we can skip this cause it was (effectively) done above in calc'ing s */
|
||||
/* b &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
|
||||
a &= (0x7f<<14)|(0x7f);
|
||||
a &= SLOT_2_0;
|
||||
a = a<<7;
|
||||
a |= b;
|
||||
s = s>>18;
|
||||
@@ -748,8 +777,8 @@ u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
|
||||
/* a: p2<<28 | p4<<14 | p6 (unmasked) */
|
||||
if (!(a&0x80))
|
||||
{
|
||||
a &= (0x1f<<28)|(0x7f<<14)|(0x7f);
|
||||
b &= (0x7f<<14)|(0x7f);
|
||||
a &= SLOT_4_2_0;
|
||||
b &= SLOT_2_0;
|
||||
b = b<<7;
|
||||
a |= b;
|
||||
s = s>>11;
|
||||
@@ -758,14 +787,14 @@ u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
|
||||
}
|
||||
|
||||
/* CSE2 from below */
|
||||
a &= (0x7f<<14)|(0x7f);
|
||||
a &= SLOT_2_0;
|
||||
p++;
|
||||
b = b<<14;
|
||||
b |= *p;
|
||||
/* b: p3<<28 | p5<<14 | p7 (unmasked) */
|
||||
if (!(b&0x80))
|
||||
{
|
||||
b &= (0x1f<<28)|(0x7f<<14)|(0x7f);
|
||||
b &= SLOT_4_2_0;
|
||||
/* moved CSE2 up */
|
||||
/* a &= (0x7f<<14)|(0x7f); */
|
||||
a = a<<7;
|
||||
@@ -782,7 +811,7 @@ u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
|
||||
|
||||
/* moved CSE2 up */
|
||||
/* a &= (0x7f<<29)|(0x7f<<15)|(0xff); */
|
||||
b &= (0x7f<<14)|(0x7f);
|
||||
b &= SLOT_2_0;
|
||||
b = b<<8;
|
||||
a |= b;
|
||||
|
||||
@@ -902,9 +931,9 @@ u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){
|
||||
/* a: p0<<28 | p2<<14 | p4 (unmasked) */
|
||||
if (!(a&0x80))
|
||||
{
|
||||
/* Walues between 268435456 and 34359738367 */
|
||||
a &= (0x1f<<28)|(0x7f<<14)|(0x7f);
|
||||
b &= (0x1f<<28)|(0x7f<<14)|(0x7f);
|
||||
/* Values between 268435456 and 34359738367 */
|
||||
a &= SLOT_4_2_0;
|
||||
b &= SLOT_4_2_0;
|
||||
b = b<<7;
|
||||
*v = a | b;
|
||||
return 5;
|
||||
@@ -997,64 +1026,17 @@ void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){
|
||||
}
|
||||
#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */
|
||||
|
||||
|
||||
/*
|
||||
** Change the sqlite.magic from SQLITE_MAGIC_OPEN to SQLITE_MAGIC_BUSY.
|
||||
** Return an error (non-zero) if the magic was not SQLITE_MAGIC_OPEN
|
||||
** when this routine is called.
|
||||
**
|
||||
** This routine is called when entering an SQLite API. The SQLITE_MAGIC_OPEN
|
||||
** value indicates that the database connection passed into the API is
|
||||
** open and is not being used by another thread. By changing the value
|
||||
** to SQLITE_MAGIC_BUSY we indicate that the connection is in use.
|
||||
** sqlite3SafetyOff() below will change the value back to SQLITE_MAGIC_OPEN
|
||||
** when the API exits.
|
||||
**
|
||||
** This routine is a attempt to detect if two threads use the
|
||||
** same sqlite* pointer at the same time. There is a race
|
||||
** condition so it is possible that the error is not detected.
|
||||
** But usually the problem will be seen. The result will be an
|
||||
** error which can be used to debug the application that is
|
||||
** using SQLite incorrectly.
|
||||
**
|
||||
** Ticket #202: If db->magic is not a valid open value, take care not
|
||||
** to modify the db structure at all. It could be that db is a stale
|
||||
** pointer. In other words, it could be that there has been a prior
|
||||
** call to sqlite3_close(db) and db has been deallocated. And we do
|
||||
** not want to write into deallocated memory.
|
||||
** Log an error that is an API call on a connection pointer that should
|
||||
** not have been used. The "type" of connection pointer is given as the
|
||||
** argument. The zType is a word like "NULL" or "closed" or "invalid".
|
||||
*/
|
||||
#ifdef SQLITE_DEBUG
|
||||
int sqlite3SafetyOn(sqlite3 *db){
|
||||
if( db->magic==SQLITE_MAGIC_OPEN ){
|
||||
db->magic = SQLITE_MAGIC_BUSY;
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
return 0;
|
||||
}else if( db->magic==SQLITE_MAGIC_BUSY ){
|
||||
db->magic = SQLITE_MAGIC_ERROR;
|
||||
db->u1.isInterrupted = 1;
|
||||
}
|
||||
return 1;
|
||||
static void logBadConnection(const char *zType){
|
||||
sqlite3_log(SQLITE_MISUSE,
|
||||
"API call with %s database connection pointer",
|
||||
zType
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Change the magic from SQLITE_MAGIC_BUSY to SQLITE_MAGIC_OPEN.
|
||||
** Return an error (non-zero) if the magic was not SQLITE_MAGIC_BUSY
|
||||
** when this routine is called.
|
||||
*/
|
||||
#ifdef SQLITE_DEBUG
|
||||
int sqlite3SafetyOff(sqlite3 *db){
|
||||
if( db->magic==SQLITE_MAGIC_BUSY ){
|
||||
db->magic = SQLITE_MAGIC_OPEN;
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
return 0;
|
||||
}else{
|
||||
db->magic = SQLITE_MAGIC_ERROR;
|
||||
db->u1.isInterrupted = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Check to make sure we have a valid db pointer. This test is not
|
||||
@@ -1072,13 +1054,16 @@ int sqlite3SafetyOff(sqlite3 *db){
|
||||
*/
|
||||
int sqlite3SafetyCheckOk(sqlite3 *db){
|
||||
u32 magic;
|
||||
if( db==0 ) return 0;
|
||||
if( db==0 ){
|
||||
logBadConnection("NULL");
|
||||
return 0;
|
||||
}
|
||||
magic = db->magic;
|
||||
if( magic!=SQLITE_MAGIC_OPEN
|
||||
#ifdef SQLITE_DEBUG
|
||||
&& magic!=SQLITE_MAGIC_BUSY
|
||||
#endif
|
||||
){
|
||||
if( magic!=SQLITE_MAGIC_OPEN ){
|
||||
if( sqlite3SafetyCheckSickOrOk(db) ){
|
||||
testcase( sqlite3GlobalConfig.xLog!=0 );
|
||||
logBadConnection("unopened");
|
||||
}
|
||||
return 0;
|
||||
}else{
|
||||
return 1;
|
||||
@@ -1089,6 +1074,11 @@ int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
|
||||
magic = db->magic;
|
||||
if( magic!=SQLITE_MAGIC_SICK &&
|
||||
magic!=SQLITE_MAGIC_OPEN &&
|
||||
magic!=SQLITE_MAGIC_BUSY ) return 0;
|
||||
return 1;
|
||||
magic!=SQLITE_MAGIC_BUSY ){
|
||||
testcase( sqlite3GlobalConfig.xLog!=0 );
|
||||
logBadConnection("invalid");
|
||||
return 0;
|
||||
}else{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
+40
-19
@@ -18,28 +18,42 @@
|
||||
#include "vdbeInt.h"
|
||||
|
||||
#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH)
|
||||
/*
|
||||
** Finalize a prepared statement. If there was an error, store the
|
||||
** text of the error message in *pzErrMsg. Return the result code.
|
||||
*/
|
||||
static int vacuumFinalize(sqlite3 *db, sqlite3_stmt *pStmt, char **pzErrMsg){
|
||||
int rc;
|
||||
rc = sqlite3VdbeFinalize((Vdbe*)pStmt);
|
||||
if( rc ){
|
||||
sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db));
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Execute zSql on database db. Return an error code.
|
||||
*/
|
||||
static int execSql(sqlite3 *db, const char *zSql){
|
||||
static int execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
|
||||
sqlite3_stmt *pStmt;
|
||||
VVA_ONLY( int rc; )
|
||||
if( !zSql ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){
|
||||
sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db));
|
||||
return sqlite3_errcode(db);
|
||||
}
|
||||
VVA_ONLY( rc = ) sqlite3_step(pStmt);
|
||||
assert( rc!=SQLITE_ROW );
|
||||
return sqlite3_finalize(pStmt);
|
||||
return vacuumFinalize(db, pStmt, pzErrMsg);
|
||||
}
|
||||
|
||||
/*
|
||||
** Execute zSql on database db. The statement returns exactly
|
||||
** one column. Execute this as SQL on the same database.
|
||||
*/
|
||||
static int execExecSql(sqlite3 *db, const char *zSql){
|
||||
static int execExecSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
|
||||
sqlite3_stmt *pStmt;
|
||||
int rc;
|
||||
|
||||
@@ -47,14 +61,14 @@ static int execExecSql(sqlite3 *db, const char *zSql){
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
while( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
rc = execSql(db, (char*)sqlite3_column_text(pStmt, 0));
|
||||
rc = execSql(db, pzErrMsg, (char*)sqlite3_column_text(pStmt, 0));
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_finalize(pStmt);
|
||||
vacuumFinalize(db, pStmt, pzErrMsg);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return sqlite3_finalize(pStmt);
|
||||
return vacuumFinalize(db, pStmt, pzErrMsg);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -86,6 +100,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
|
||||
int saved_flags; /* Saved value of the db->flags */
|
||||
int saved_nChange; /* Saved value of db->nChange */
|
||||
int saved_nTotalChange; /* Saved value of db->nTotalChange */
|
||||
void (*saved_xTrace)(void*,const char*); /* Saved db->xTrace */
|
||||
Db *pDb = 0; /* Database to detach at end of vacuum */
|
||||
int isMemDb; /* True if vacuuming a :memory: database */
|
||||
int nRes;
|
||||
@@ -101,8 +116,10 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
|
||||
saved_flags = db->flags;
|
||||
saved_nChange = db->nChange;
|
||||
saved_nTotalChange = db->nTotalChange;
|
||||
saved_xTrace = db->xTrace;
|
||||
db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
|
||||
db->flags &= ~SQLITE_ForeignKeys;
|
||||
db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder);
|
||||
db->xTrace = 0;
|
||||
|
||||
pMain = db->aDb[0].pBt;
|
||||
isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain));
|
||||
@@ -121,8 +138,12 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
|
||||
** time to parse and run the PRAGMA to turn journalling off than it does
|
||||
** to write the journal header file.
|
||||
*/
|
||||
zSql = "ATTACH '' AS vacuum_db;";
|
||||
rc = execSql(db, zSql);
|
||||
if( sqlite3TempInMemory(db) ){
|
||||
zSql = "ATTACH ':memory:' AS vacuum_db;";
|
||||
}else{
|
||||
zSql = "ATTACH '' AS vacuum_db;";
|
||||
}
|
||||
rc = execSql(db, pzErrMsg, zSql);
|
||||
if( rc!=SQLITE_OK ) goto end_of_vacuum;
|
||||
pDb = &db->aDb[db->nDb-1];
|
||||
assert( strcmp(db->aDb[db->nDb-1].zName,"vacuum_db")==0 );
|
||||
@@ -154,7 +175,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
|
||||
rc = SQLITE_NOMEM;
|
||||
goto end_of_vacuum;
|
||||
}
|
||||
rc = execSql(db, "PRAGMA vacuum_db.synchronous=OFF");
|
||||
rc = execSql(db, pzErrMsg, "PRAGMA vacuum_db.synchronous=OFF");
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto end_of_vacuum;
|
||||
}
|
||||
@@ -165,23 +186,23 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
|
||||
#endif
|
||||
|
||||
/* Begin a transaction */
|
||||
rc = execSql(db, "BEGIN EXCLUSIVE;");
|
||||
rc = execSql(db, pzErrMsg, "BEGIN EXCLUSIVE;");
|
||||
if( rc!=SQLITE_OK ) goto end_of_vacuum;
|
||||
|
||||
/* Query the schema of the main database. Create a mirror schema
|
||||
** in the temporary database.
|
||||
*/
|
||||
rc = execExecSql(db,
|
||||
rc = execExecSql(db, pzErrMsg,
|
||||
"SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14) "
|
||||
" FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'"
|
||||
" AND rootpage>0"
|
||||
);
|
||||
if( rc!=SQLITE_OK ) goto end_of_vacuum;
|
||||
rc = execExecSql(db,
|
||||
rc = execExecSql(db, pzErrMsg,
|
||||
"SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14)"
|
||||
" FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %' ");
|
||||
if( rc!=SQLITE_OK ) goto end_of_vacuum;
|
||||
rc = execExecSql(db,
|
||||
rc = execExecSql(db, pzErrMsg,
|
||||
"SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21) "
|
||||
" FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'");
|
||||
if( rc!=SQLITE_OK ) goto end_of_vacuum;
|
||||
@@ -190,24 +211,23 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
|
||||
** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy
|
||||
** the contents to the temporary database.
|
||||
*/
|
||||
rc = execExecSql(db,
|
||||
rc = execExecSql(db, pzErrMsg,
|
||||
"SELECT 'INSERT INTO vacuum_db.' || quote(name) "
|
||||
"|| ' SELECT * FROM main.' || quote(name) || ';'"
|
||||
"FROM main.sqlite_master "
|
||||
"WHERE type = 'table' AND name!='sqlite_sequence' "
|
||||
" AND rootpage>0"
|
||||
|
||||
);
|
||||
if( rc!=SQLITE_OK ) goto end_of_vacuum;
|
||||
|
||||
/* Copy over the sequence table
|
||||
*/
|
||||
rc = execExecSql(db,
|
||||
rc = execExecSql(db, pzErrMsg,
|
||||
"SELECT 'DELETE FROM vacuum_db.' || quote(name) || ';' "
|
||||
"FROM vacuum_db.sqlite_master WHERE name='sqlite_sequence' "
|
||||
);
|
||||
if( rc!=SQLITE_OK ) goto end_of_vacuum;
|
||||
rc = execExecSql(db,
|
||||
rc = execExecSql(db, pzErrMsg,
|
||||
"SELECT 'INSERT INTO vacuum_db.' || quote(name) "
|
||||
"|| ' SELECT * FROM main.' || quote(name) || ';' "
|
||||
"FROM vacuum_db.sqlite_master WHERE name=='sqlite_sequence';"
|
||||
@@ -220,7 +240,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
|
||||
** associated storage, so all we have to do is copy their entries
|
||||
** from the SQLITE_MASTER table.
|
||||
*/
|
||||
rc = execSql(db,
|
||||
rc = execSql(db, pzErrMsg,
|
||||
"INSERT INTO vacuum_db.sqlite_master "
|
||||
" SELECT type, name, tbl_name, rootpage, sql"
|
||||
" FROM main.sqlite_master"
|
||||
@@ -283,6 +303,7 @@ end_of_vacuum:
|
||||
db->flags = saved_flags;
|
||||
db->nChange = saved_nChange;
|
||||
db->nTotalChange = saved_nTotalChange;
|
||||
db->xTrace = saved_xTrace;
|
||||
|
||||
/* Currently there is an SQL level transaction open on the vacuum
|
||||
** database. No locks are held on any other files (since the main file
|
||||
|
||||
+70
-59
@@ -239,17 +239,30 @@ static VdbeCursor *allocateCursor(
|
||||
static void applyNumericAffinity(Mem *pRec){
|
||||
if( (pRec->flags & (MEM_Real|MEM_Int))==0 ){
|
||||
int realnum;
|
||||
u8 enc = pRec->enc;
|
||||
sqlite3VdbeMemNulTerminate(pRec);
|
||||
if( (pRec->flags&MEM_Str)
|
||||
&& sqlite3IsNumber(pRec->z, &realnum, pRec->enc) ){
|
||||
if( (pRec->flags&MEM_Str) && sqlite3IsNumber(pRec->z, &realnum, enc) ){
|
||||
i64 value;
|
||||
sqlite3VdbeChangeEncoding(pRec, SQLITE_UTF8);
|
||||
if( !realnum && sqlite3Atoi64(pRec->z, &value) ){
|
||||
char *zUtf8 = pRec->z;
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
if( enc!=SQLITE_UTF8 ){
|
||||
assert( pRec->db );
|
||||
zUtf8 = sqlite3Utf16to8(pRec->db, pRec->z, pRec->n, enc);
|
||||
if( !zUtf8 ) return;
|
||||
}
|
||||
#endif
|
||||
if( !realnum && sqlite3Atoi64(zUtf8, &value) ){
|
||||
pRec->u.i = value;
|
||||
MemSetTypeFlag(pRec, MEM_Int);
|
||||
}else{
|
||||
sqlite3VdbeMemRealify(pRec);
|
||||
sqlite3AtoF(zUtf8, &pRec->r);
|
||||
MemSetTypeFlag(pRec, MEM_Real);
|
||||
}
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
if( enc!=SQLITE_UTF8 ){
|
||||
sqlite3DbFree(pRec->db, zUtf8);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -538,7 +551,7 @@ static int checkSavepointCount(sqlite3 *db){
|
||||
int sqlite3VdbeExec(
|
||||
Vdbe *p /* The VDBE */
|
||||
){
|
||||
int pc; /* The program counter */
|
||||
int pc=0; /* The program counter */
|
||||
Op *aOp = p->aOp; /* Copy of p->aOp */
|
||||
Op *pOp; /* Current operation */
|
||||
int rc = SQLITE_OK; /* Value to return */
|
||||
@@ -563,7 +576,6 @@ int sqlite3VdbeExec(
|
||||
/*** INSERT STACK UNION HERE ***/
|
||||
|
||||
assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */
|
||||
assert( db->magic==SQLITE_MAGIC_BUSY );
|
||||
sqlite3VdbeMutexArrayEnter(p);
|
||||
if( p->rc==SQLITE_NOMEM ){
|
||||
/* This happens if a malloc() inside a call to sqlite3_column_text() or
|
||||
@@ -648,9 +660,7 @@ int sqlite3VdbeExec(
|
||||
if( checkProgress ){
|
||||
if( db->nProgressOps==nProgressOps ){
|
||||
int prc;
|
||||
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
|
||||
prc =db->xProgress(db->pProgressArg);
|
||||
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
|
||||
prc = db->xProgress(db->pProgressArg);
|
||||
if( prc!=0 ){
|
||||
rc = SQLITE_INTERRUPT;
|
||||
goto vdbe_error_halt;
|
||||
@@ -850,7 +860,13 @@ case OP_Halt: {
|
||||
p->errorAction = (u8)pOp->p2;
|
||||
p->pc = pc;
|
||||
if( pOp->p4.z ){
|
||||
assert( p->rc!=SQLITE_OK );
|
||||
sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z);
|
||||
testcase( sqlite3GlobalConfig.xLog!=0 );
|
||||
sqlite3_log(pOp->p1, "abort at %d in [%s]: %s", pc, p->zSql, pOp->p4.z);
|
||||
}else if( p->rc ){
|
||||
testcase( sqlite3GlobalConfig.xLog!=0 );
|
||||
sqlite3_log(pOp->p1, "constraint failed at %d in [%s]", pc, p->zSql);
|
||||
}
|
||||
rc = sqlite3VdbeHalt(p);
|
||||
assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
|
||||
@@ -884,6 +900,7 @@ case OP_Int64: { /* out2-prerelease */
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
/* Opcode: Real * P2 * P4 *
|
||||
**
|
||||
** P4 is a pointer to a 64-bit floating point value.
|
||||
@@ -895,6 +912,7 @@ case OP_Real: { /* same as TK_FLOAT, out2-prerelease */
|
||||
pOut->r = *pOp->p4.pReal;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Opcode: String8 * P2 * P4 *
|
||||
**
|
||||
@@ -1295,6 +1313,10 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef SQLITE_OMIT_FLOATING_POINT
|
||||
pOut->u.i = rB;
|
||||
MemSetTypeFlag(pOut, MEM_Int);
|
||||
#else
|
||||
if( sqlite3IsNaN(rB) ){
|
||||
goto arithmetic_result_is_null;
|
||||
}
|
||||
@@ -1303,6 +1325,7 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
|
||||
if( (flags & MEM_Real)==0 ){
|
||||
sqlite3VdbeIntegerAffinity(pOut);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1393,21 +1416,12 @@ case OP_Function: {
|
||||
assert( pOp[-1].opcode==OP_CollSeq );
|
||||
ctx.pColl = pOp[-1].p4.pColl;
|
||||
}
|
||||
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
|
||||
(*ctx.pFunc->xFunc)(&ctx, n, apVal);
|
||||
if( sqlite3SafetyOn(db) ){
|
||||
sqlite3VdbeMemRelease(&ctx.s);
|
||||
goto abort_due_to_misuse;
|
||||
}
|
||||
if( db->mallocFailed ){
|
||||
/* Even though a malloc() has failed, the implementation of the
|
||||
** user function may have called an sqlite3_result_XXX() function
|
||||
** to return a value. The following call releases any resources
|
||||
** associated with such a value.
|
||||
**
|
||||
** Note: Maybe MemRelease() should be called if sqlite3SafetyOn()
|
||||
** fails also (the if(...) statement above). But if people are
|
||||
** misusing sqlite, they have bigger problems than a leaked value.
|
||||
*/
|
||||
sqlite3VdbeMemRelease(&ctx.s);
|
||||
goto no_mem;
|
||||
@@ -1530,6 +1544,7 @@ case OP_MustBeInt: { /* jump, in1 */
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
/* Opcode: RealAffinity P1 * * * *
|
||||
**
|
||||
** If register P1 holds an integer convert it to a real value.
|
||||
@@ -1546,6 +1561,7 @@ case OP_RealAffinity: { /* in1 */
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_CAST
|
||||
/* Opcode: ToText P1 * * * *
|
||||
@@ -1629,7 +1645,7 @@ case OP_ToInt: { /* same as TK_TO_INT, in1 */
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_CAST
|
||||
#if !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT)
|
||||
/* Opcode: ToReal P1 * * * *
|
||||
**
|
||||
** Force the value in register P1 to be a floating point number.
|
||||
@@ -1646,7 +1662,7 @@ case OP_ToReal: { /* same as TK_TO_REAL, in1 */
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_CAST */
|
||||
#endif /* !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT) */
|
||||
|
||||
/* Opcode: Lt P1 P2 P3 P4 P5
|
||||
**
|
||||
@@ -1728,9 +1744,13 @@ case OP_Gt: /* same as TK_GT, jump, in1, in3 */
|
||||
case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
||||
int res; /* Result of the comparison of pIn1 against pIn3 */
|
||||
char affinity; /* Affinity to use for comparison */
|
||||
u16 flags1; /* Copy of initial value of pIn1->flags */
|
||||
u16 flags3; /* Copy of initial value of pIn3->flags */
|
||||
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
pIn3 = &aMem[pOp->p3];
|
||||
flags1 = pIn1->flags;
|
||||
flags3 = pIn3->flags;
|
||||
if( (pIn1->flags | pIn3->flags)&MEM_Null ){
|
||||
/* One or both operands are NULL */
|
||||
if( pOp->p5 & SQLITE_NULLEQ ){
|
||||
@@ -1785,6 +1805,10 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
||||
}else if( res ){
|
||||
pc = pOp->p2-1;
|
||||
}
|
||||
|
||||
/* Undo any changes made by applyAffinity() to the input registers. */
|
||||
pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (flags1&MEM_TypeMask);
|
||||
pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (flags3&MEM_TypeMask);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2059,7 +2083,7 @@ case OP_Column: {
|
||||
u8 *zIdx; /* Index into header */
|
||||
u8 *zEndHdr; /* Pointer to first byte after the header */
|
||||
u32 offset; /* Offset into the data */
|
||||
u64 offset64; /* 64-bit offset. 64 bits needed to catch overflow */
|
||||
u32 szField; /* Number of bytes in the content of a field */
|
||||
int szHdr; /* Size of the header size field at start of record */
|
||||
int avail; /* Number of bytes of available data */
|
||||
Mem *pReg; /* PseudoTable input register */
|
||||
@@ -2234,12 +2258,16 @@ case OP_Column: {
|
||||
** column and aOffset[i] will contain the offset from the beginning
|
||||
** of the record to the start of the data for the i-th column
|
||||
*/
|
||||
offset64 = offset;
|
||||
for(i=0; i<nField; i++){
|
||||
if( zIdx<zEndHdr ){
|
||||
aOffset[i] = (u32)offset64;
|
||||
aOffset[i] = offset;
|
||||
zIdx += getVarint32(zIdx, aType[i]);
|
||||
offset64 += sqlite3VdbeSerialTypeLen(aType[i]);
|
||||
szField = sqlite3VdbeSerialTypeLen(aType[i]);
|
||||
offset += szField;
|
||||
if( offset<szField ){ /* True if offset overflows */
|
||||
zIdx = &zEndHdr[1]; /* Forces SQLITE_CORRUPT return below */
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
/* If i is less that nField, then there are less fields in this
|
||||
** record than SetNumColumns indicated there are columns in the
|
||||
@@ -2259,8 +2287,8 @@ case OP_Column: {
|
||||
** of the record (when all fields present), then we must be dealing
|
||||
** with a corrupt database.
|
||||
*/
|
||||
if( (zIdx > zEndHdr)|| (offset64 > payloadSize)
|
||||
|| (zIdx==zEndHdr && offset64!=(u64)payloadSize) ){
|
||||
if( (zIdx > zEndHdr) || (offset > payloadSize)
|
||||
|| (zIdx==zEndHdr && offset!=payloadSize) ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto op_column_out;
|
||||
}
|
||||
@@ -3106,7 +3134,7 @@ case OP_OpenEphemeral: {
|
||||
** register P2. In other words, cursor P1 becomes an alias for the
|
||||
** MEM_Blob content contained in register P2.
|
||||
**
|
||||
** A pseudo-table created by this opcode is used to hold the a single
|
||||
** A pseudo-table created by this opcode is used to hold a single
|
||||
** row output from the sorter so that the row can be decomposed into
|
||||
** individual columns using the OP_Column opcode. The OP_Column opcode
|
||||
** is the only cursor opcode that works with a pseudo-table.
|
||||
@@ -3663,7 +3691,7 @@ case OP_NewRowid: { /* out2-prerelease */
|
||||
goto abort_due_to_error;
|
||||
}
|
||||
if( res ){
|
||||
v = 1;
|
||||
v = 1; /* IMP: R-61914-48074 */
|
||||
}else{
|
||||
assert( sqlite3BtreeCursorIsValid(pC->pCursor) );
|
||||
rc = sqlite3BtreeKeySize(pC->pCursor, &v);
|
||||
@@ -3671,7 +3699,7 @@ case OP_NewRowid: { /* out2-prerelease */
|
||||
if( v==MAX_ROWID ){
|
||||
pC->useRandomRowid = 1;
|
||||
}else{
|
||||
v++;
|
||||
v++; /* IMP: R-29538-34987 */
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3695,7 +3723,7 @@ case OP_NewRowid: { /* out2-prerelease */
|
||||
sqlite3VdbeMemIntegerify(pMem);
|
||||
assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */
|
||||
if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){
|
||||
rc = SQLITE_FULL;
|
||||
rc = SQLITE_FULL; /* IMP: R-12275-61338 */
|
||||
goto abort_due_to_error;
|
||||
}
|
||||
if( v<pMem->u.i+1 ){
|
||||
@@ -3708,6 +3736,11 @@ case OP_NewRowid: { /* out2-prerelease */
|
||||
sqlite3BtreeSetCachedRowid(pC->pCursor, v<MAX_ROWID ? v+1 : 0);
|
||||
}
|
||||
if( pC->useRandomRowid ){
|
||||
/* IMPLEMENTATION-OF: R-48598-02938 If the largest ROWID is equal to the
|
||||
** largest possible integer (9223372036854775807) then the database
|
||||
** engine starts picking candidate ROWIDs at random until it finds one
|
||||
** that is not previously used.
|
||||
*/
|
||||
assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is
|
||||
** an AUTOINCREMENT table. */
|
||||
v = db->lastRowid;
|
||||
@@ -3723,7 +3756,7 @@ case OP_NewRowid: { /* out2-prerelease */
|
||||
cnt++;
|
||||
}while( cnt<100 && rc==SQLITE_OK && res==0 );
|
||||
if( rc==SQLITE_OK && res==0 ){
|
||||
rc = SQLITE_FULL;
|
||||
rc = SQLITE_FULL; /* IMP: R-38219-53002 */
|
||||
goto abort_due_to_error;
|
||||
}
|
||||
}
|
||||
@@ -4031,12 +4064,10 @@ case OP_Rowid: { /* out2-prerelease */
|
||||
pVtab = pC->pVtabCursor->pVtab;
|
||||
pModule = pVtab->pModule;
|
||||
assert( pModule->xRowid );
|
||||
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
|
||||
rc = pModule->xRowid(pC->pVtabCursor, &v);
|
||||
sqlite3DbFree(db, p->zErrMsg);
|
||||
p->zErrMsg = pVtab->zErrMsg;
|
||||
pVtab->zErrMsg = 0;
|
||||
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
}else{
|
||||
assert( pC->pCursor!=0 );
|
||||
@@ -4567,12 +4598,11 @@ case OP_ParseSchema: {
|
||||
initData.iDb = pOp->p1;
|
||||
initData.pzErrMsg = &p->zErrMsg;
|
||||
zSql = sqlite3MPrintf(db,
|
||||
"SELECT name, rootpage, sql FROM '%q'.%s WHERE %s",
|
||||
"SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
|
||||
db->aDb[iDb].zName, zMaster, pOp->p4.z);
|
||||
if( zSql==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
(void)sqlite3SafetyOff(db);
|
||||
assert( db->init.busy==0 );
|
||||
db->init.busy = 1;
|
||||
initData.rc = SQLITE_OK;
|
||||
@@ -4581,7 +4611,6 @@ case OP_ParseSchema: {
|
||||
if( rc==SQLITE_OK ) rc = initData.rc;
|
||||
sqlite3DbFree(db, zSql);
|
||||
db->init.busy = 0;
|
||||
(void)sqlite3SafetyOn(db);
|
||||
}
|
||||
}
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
@@ -5151,9 +5180,7 @@ case OP_AggFinal: {
|
||||
** a transaction.
|
||||
*/
|
||||
case OP_Vacuum: {
|
||||
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
|
||||
rc = sqlite3RunVacuum(&p->zErrMsg, db);
|
||||
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@@ -5297,12 +5324,10 @@ case OP_VOpen: {
|
||||
pVtab = pOp->p4.pVtab->pVtab;
|
||||
pModule = (sqlite3_module *)pVtab->pModule;
|
||||
assert(pVtab && pModule);
|
||||
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
|
||||
rc = pModule->xOpen(pVtab, &pVtabCursor);
|
||||
sqlite3DbFree(db, p->zErrMsg);
|
||||
p->zErrMsg = pVtab->zErrMsg;
|
||||
pVtab->zErrMsg = 0;
|
||||
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
|
||||
if( SQLITE_OK==rc ){
|
||||
/* Initialize sqlite3_vtab_cursor base class */
|
||||
pVtabCursor->pVtab = pVtab;
|
||||
@@ -5376,7 +5401,6 @@ case OP_VFilter: { /* jump */
|
||||
sqlite3VdbeMemStoreType(apArg[i]);
|
||||
}
|
||||
|
||||
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
|
||||
p->inVtabMethod = 1;
|
||||
rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg);
|
||||
p->inVtabMethod = 0;
|
||||
@@ -5386,7 +5410,6 @@ case OP_VFilter: { /* jump */
|
||||
if( rc==SQLITE_OK ){
|
||||
res = pModule->xEof(pVtabCursor);
|
||||
}
|
||||
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
|
||||
|
||||
if( res ){
|
||||
pc = pOp->p2 - 1;
|
||||
@@ -5432,7 +5455,6 @@ case OP_VColumn: {
|
||||
sqlite3VdbeMemMove(&sContext.s, pDest);
|
||||
MemSetTypeFlag(&sContext.s, MEM_Null);
|
||||
|
||||
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
|
||||
rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2);
|
||||
sqlite3DbFree(db, p->zErrMsg);
|
||||
p->zErrMsg = pVtab->zErrMsg;
|
||||
@@ -5450,9 +5472,6 @@ case OP_VColumn: {
|
||||
REGISTER_TRACE(pOp->p3, pDest);
|
||||
UPDATE_MAX_BLOBSIZE(pDest);
|
||||
|
||||
if( sqlite3SafetyOn(db) ){
|
||||
goto abort_due_to_misuse;
|
||||
}
|
||||
if( sqlite3VdbeMemTooBig(pDest) ){
|
||||
goto too_big;
|
||||
}
|
||||
@@ -5489,7 +5508,6 @@ case OP_VNext: { /* jump */
|
||||
** data is available) and the error code returned when xColumn or
|
||||
** some other method is next invoked on the save virtual table cursor.
|
||||
*/
|
||||
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
|
||||
p->inVtabMethod = 1;
|
||||
rc = pModule->xNext(pCur->pVtabCursor);
|
||||
p->inVtabMethod = 0;
|
||||
@@ -5499,7 +5517,6 @@ case OP_VNext: { /* jump */
|
||||
if( rc==SQLITE_OK ){
|
||||
res = pModule->xEof(pCur->pVtabCursor);
|
||||
}
|
||||
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
|
||||
|
||||
if( !res ){
|
||||
/* If there is data, jump to P2 */
|
||||
@@ -5525,12 +5542,10 @@ case OP_VRename: {
|
||||
assert( pVtab->pModule->xRename );
|
||||
REGISTER_TRACE(pOp->p1, pName);
|
||||
assert( pName->flags & MEM_Str );
|
||||
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
|
||||
rc = pVtab->pModule->xRename(pVtab, pName->z);
|
||||
sqlite3DbFree(db, p->zErrMsg);
|
||||
p->zErrMsg = pVtab->zErrMsg;
|
||||
pVtab->zErrMsg = 0;
|
||||
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -5581,12 +5596,10 @@ case OP_VUpdate: {
|
||||
apArg[i] = pX;
|
||||
pX++;
|
||||
}
|
||||
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
|
||||
rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid);
|
||||
sqlite3DbFree(db, p->zErrMsg);
|
||||
p->zErrMsg = pVtab->zErrMsg;
|
||||
pVtab->zErrMsg = 0;
|
||||
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
|
||||
if( rc==SQLITE_OK && pOp->p1 ){
|
||||
assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );
|
||||
db->lastRowid = rowid;
|
||||
@@ -5659,6 +5672,7 @@ case OP_Trace: {
|
||||
** the same as a no-op. This opcodesnever appears in a real VM program.
|
||||
*/
|
||||
default: { /* This is really OP_Noop and OP_Explain */
|
||||
assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain );
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -5710,6 +5724,9 @@ default: { /* This is really OP_Noop and OP_Explain */
|
||||
vdbe_error_halt:
|
||||
assert( rc );
|
||||
p->rc = rc;
|
||||
testcase( sqlite3GlobalConfig.xLog!=0 );
|
||||
sqlite3_log(rc, "statement aborts at %d: [%s] %s",
|
||||
pc, p->zSql, p->zErrMsg);
|
||||
sqlite3VdbeHalt(p);
|
||||
if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1;
|
||||
rc = SQLITE_ERROR;
|
||||
@@ -5738,12 +5755,6 @@ no_mem:
|
||||
rc = SQLITE_NOMEM;
|
||||
goto vdbe_error_halt;
|
||||
|
||||
/* Jump to here for an SQLITE_MISUSE error.
|
||||
*/
|
||||
abort_due_to_misuse:
|
||||
rc = SQLITE_MISUSE;
|
||||
/* Fall thru into abort_due_to_error */
|
||||
|
||||
/* Jump to here for any other kind of fatal error. The "rc" variable
|
||||
** should hold the error number.
|
||||
*/
|
||||
|
||||
@@ -182,6 +182,7 @@ void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
|
||||
void sqlite3VdbeUsesBtree(Vdbe*, int);
|
||||
VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
|
||||
int sqlite3VdbeMakeLabel(Vdbe*);
|
||||
void sqlite3VdbeRunOnlyOnce(Vdbe*);
|
||||
void sqlite3VdbeDelete(Vdbe*);
|
||||
void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int,int,int);
|
||||
int sqlite3VdbeFinalize(Vdbe*);
|
||||
|
||||
+6
-1
@@ -301,6 +301,7 @@ struct Vdbe {
|
||||
u8 explain; /* True if EXPLAIN present on SQL command */
|
||||
u8 changeCntOn; /* True to update the change-counter */
|
||||
u8 expired; /* True if the VM needs to be recompiled */
|
||||
u8 runOnlyOnce; /* Automatically expire on reset */
|
||||
u8 minWriteFileFormat; /* Minimum file format for writable database files */
|
||||
u8 inVtabMethod; /* See comments above */
|
||||
u8 usesStmtJournal; /* True if uses a statement journal */
|
||||
@@ -362,7 +363,11 @@ void sqlite3VdbeMemMove(Mem*, Mem*);
|
||||
int sqlite3VdbeMemNulTerminate(Mem*);
|
||||
int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*));
|
||||
void sqlite3VdbeMemSetInt64(Mem*, i64);
|
||||
void sqlite3VdbeMemSetDouble(Mem*, double);
|
||||
#ifdef SQLITE_OMIT_FLOATING_POINT
|
||||
# define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64
|
||||
#else
|
||||
void sqlite3VdbeMemSetDouble(Mem*, double);
|
||||
#endif
|
||||
void sqlite3VdbeMemSetNull(Mem*);
|
||||
void sqlite3VdbeMemSetZeroBlob(Mem*,int);
|
||||
void sqlite3VdbeMemSetRowSet(Mem*);
|
||||
|
||||
+78
-49
@@ -31,6 +31,28 @@ int sqlite3_expired(sqlite3_stmt *pStmt){
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Check on a Vdbe to make sure it has not been finalized. Log
|
||||
** an error and return true if it has been finalized (or is otherwise
|
||||
** invalid). Return false if it is ok.
|
||||
*/
|
||||
static int vdbeSafety(Vdbe *p){
|
||||
if( p->db==0 ){
|
||||
sqlite3_log(SQLITE_MISUSE, "API called with finalized prepared statement");
|
||||
return 1;
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
static int vdbeSafetyNotNull(Vdbe *p){
|
||||
if( p==0 ){
|
||||
sqlite3_log(SQLITE_MISUSE, "API called with NULL prepared statement");
|
||||
return 1;
|
||||
}else{
|
||||
return vdbeSafety(p);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** The following routine destroys a virtual machine that is created by
|
||||
** the sqlite3_compile() routine. The integer returned is an SQLITE_
|
||||
@@ -48,7 +70,11 @@ int sqlite3_finalize(sqlite3_stmt *pStmt){
|
||||
Vdbe *v = (Vdbe*)pStmt;
|
||||
sqlite3 *db = v->db;
|
||||
#if SQLITE_THREADSAFE
|
||||
sqlite3_mutex *mutex = v->db->mutex;
|
||||
sqlite3_mutex *mutex;
|
||||
#endif
|
||||
if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT;
|
||||
#if SQLITE_THREADSAFE
|
||||
mutex = v->db->mutex;
|
||||
#endif
|
||||
sqlite3_mutex_enter(mutex);
|
||||
rc = sqlite3VdbeFinalize(v);
|
||||
@@ -295,26 +321,23 @@ static int sqlite3Step(Vdbe *p){
|
||||
|
||||
assert(p);
|
||||
if( p->magic!=VDBE_MAGIC_RUN ){
|
||||
return SQLITE_MISUSE;
|
||||
sqlite3_log(SQLITE_MISUSE,
|
||||
"attempt to step a halted statement: [%s]", p->zSql);
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
|
||||
/* Assert that malloc() has not failed */
|
||||
/* Check that malloc() has not failed. If it has, return early. */
|
||||
db = p->db;
|
||||
if( db->mallocFailed ){
|
||||
p->rc = SQLITE_NOMEM;
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
|
||||
if( p->pc<=0 && p->expired ){
|
||||
if( ALWAYS(p->rc==SQLITE_OK || p->rc==SQLITE_SCHEMA) ){
|
||||
p->rc = SQLITE_SCHEMA;
|
||||
}
|
||||
p->rc = SQLITE_SCHEMA;
|
||||
rc = SQLITE_ERROR;
|
||||
goto end_of_step;
|
||||
}
|
||||
if( sqlite3SafetyOn(db) ){
|
||||
p->rc = SQLITE_MISUSE;
|
||||
return SQLITE_MISUSE;
|
||||
}
|
||||
if( p->pc<0 ){
|
||||
/* If there are no other statements currently running, then
|
||||
** reset the interrupt flag. This prevents a call to sqlite3_interrupt
|
||||
@@ -347,10 +370,6 @@ static int sqlite3Step(Vdbe *p){
|
||||
rc = sqlite3VdbeExec(p);
|
||||
}
|
||||
|
||||
if( sqlite3SafetyOff(db) ){
|
||||
rc = SQLITE_MISUSE;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_TRACE
|
||||
/* Invoke the profile callback if there is one
|
||||
*/
|
||||
@@ -397,39 +416,44 @@ end_of_step:
|
||||
** call sqlite3Reprepare() and try again.
|
||||
*/
|
||||
int sqlite3_step(sqlite3_stmt *pStmt){
|
||||
int rc = SQLITE_MISUSE;
|
||||
if( pStmt ){
|
||||
int cnt = 0;
|
||||
Vdbe *v = (Vdbe*)pStmt;
|
||||
sqlite3 *db = v->db;
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
|
||||
&& cnt++ < 5
|
||||
&& (rc = sqlite3Reprepare(v))==SQLITE_OK ){
|
||||
sqlite3_reset(pStmt);
|
||||
v->expired = 0;
|
||||
}
|
||||
if( rc==SQLITE_SCHEMA && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
|
||||
/* 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);
|
||||
sqlite3DbFree(db, v->zErrMsg);
|
||||
if( !db->mallocFailed ){
|
||||
v->zErrMsg = sqlite3DbStrDup(db, zErr);
|
||||
} else {
|
||||
v->zErrMsg = 0;
|
||||
v->rc = SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
rc = sqlite3ApiExit(db, rc);
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
int rc = SQLITE_OK; /* Result from sqlite3Step() */
|
||||
int rc2 = SQLITE_OK; /* Result from sqlite3Reprepare() */
|
||||
Vdbe *v = (Vdbe*)pStmt; /* the prepared statement */
|
||||
int cnt = 0; /* Counter to prevent infinite loop of reprepares */
|
||||
sqlite3 *db; /* The database connection */
|
||||
|
||||
if( vdbeSafetyNotNull(v) ){
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
db = v->db;
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
|
||||
&& cnt++ < 5
|
||||
&& (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){
|
||||
sqlite3_reset(pStmt);
|
||||
v->expired = 0;
|
||||
}
|
||||
if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
|
||||
/* 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);
|
||||
sqlite3DbFree(db, v->zErrMsg);
|
||||
if( !db->mallocFailed ){
|
||||
v->zErrMsg = sqlite3DbStrDup(db, zErr);
|
||||
v->rc = rc2;
|
||||
} else {
|
||||
v->zErrMsg = 0;
|
||||
v->rc = rc = SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
rc = sqlite3ApiExit(db, rc);
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -483,8 +507,9 @@ void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
|
||||
assert( p && p->pFunc && p->pFunc->xStep );
|
||||
assert( sqlite3_mutex_held(p->s.db->mutex) );
|
||||
pMem = p->pMem;
|
||||
testcase( nByte<0 );
|
||||
if( (pMem->flags & MEM_Agg)==0 ){
|
||||
if( nByte==0 ){
|
||||
if( nByte<=0 ){
|
||||
sqlite3VdbeMemReleaseExternal(pMem);
|
||||
pMem->flags = MEM_Null;
|
||||
pMem->z = 0;
|
||||
@@ -898,12 +923,16 @@ const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){
|
||||
*/
|
||||
static int vdbeUnbind(Vdbe *p, int i){
|
||||
Mem *pVar;
|
||||
if( p==0 ) return SQLITE_MISUSE;
|
||||
if( vdbeSafetyNotNull(p) ){
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
sqlite3_mutex_enter(p->db->mutex);
|
||||
if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){
|
||||
sqlite3Error(p->db, SQLITE_MISUSE, 0);
|
||||
sqlite3_mutex_leave(p->db->mutex);
|
||||
return SQLITE_MISUSE;
|
||||
sqlite3_log(SQLITE_MISUSE,
|
||||
"bind on a busy prepared statement: [%s]", p->zSql);
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
if( i<1 || i>p->nVar ){
|
||||
sqlite3Error(p->db, SQLITE_RANGE, 0);
|
||||
|
||||
+96
-49
@@ -66,7 +66,7 @@ void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){
|
||||
*/
|
||||
const char *sqlite3_sql(sqlite3_stmt *pStmt){
|
||||
Vdbe *p = (Vdbe *)pStmt;
|
||||
return (p->isPrepareV2 ? p->zSql : 0);
|
||||
return (p && p->isPrepareV2) ? p->zSql : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -255,6 +255,13 @@ void sqlite3VdbeResolveLabel(Vdbe *p, int x){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Mark the VDBE as one that can only be run one time.
|
||||
*/
|
||||
void sqlite3VdbeRunOnlyOnce(Vdbe *p){
|
||||
p->runOnlyOnce = 1;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_DEBUG /* sqlite3AssertMayAbort() logic */
|
||||
|
||||
/*
|
||||
@@ -1041,22 +1048,24 @@ void sqlite3VdbeFrameDelete(VdbeFrame *p){
|
||||
** p->explain==2, only OP_Explain instructions are listed and these
|
||||
** are shown in a different format. p->explain==2 is used to implement
|
||||
** EXPLAIN QUERY PLAN.
|
||||
**
|
||||
** When p->explain==1, first the main program is listed, then each of
|
||||
** the trigger subprograms are listed one by one.
|
||||
*/
|
||||
int sqlite3VdbeList(
|
||||
Vdbe *p /* The VDBE */
|
||||
){
|
||||
int nRow; /* Total number of rows to return */
|
||||
int nRow; /* Stop when row count reaches this */
|
||||
int nSub = 0; /* Number of sub-vdbes seen so far */
|
||||
SubProgram **apSub = 0; /* Array of sub-vdbes */
|
||||
Mem *pSub = 0;
|
||||
sqlite3 *db = p->db;
|
||||
int i;
|
||||
int rc = SQLITE_OK;
|
||||
Mem *pMem = p->pResultSet = &p->aMem[1];
|
||||
Mem *pSub = 0; /* Memory cell hold array of subprogs */
|
||||
sqlite3 *db = p->db; /* The database connection */
|
||||
int i; /* Loop counter */
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
Mem *pMem = p->pResultSet = &p->aMem[1]; /* First Mem of result set */
|
||||
|
||||
assert( p->explain );
|
||||
assert( p->magic==VDBE_MAGIC_RUN );
|
||||
assert( db->magic==SQLITE_MAGIC_BUSY );
|
||||
assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM );
|
||||
|
||||
/* Even though this opcode does not use dynamic strings for
|
||||
@@ -1072,12 +1081,24 @@ int sqlite3VdbeList(
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
/* Figure out total number of rows that will be returned by this
|
||||
** EXPLAIN program. */
|
||||
/* When the number of output rows reaches nRow, that means the
|
||||
** listing has finished and sqlite3_step() should return SQLITE_DONE.
|
||||
** nRow is the sum of the number of rows in the main program, plus
|
||||
** the sum of the number of rows in all trigger subprograms encountered
|
||||
** so far. The nRow value will increase as new trigger subprograms are
|
||||
** encountered, but p->pc will eventually catch up to nRow.
|
||||
*/
|
||||
nRow = p->nOp;
|
||||
if( p->explain==1 ){
|
||||
/* The first 8 memory cells are used for the result set. So we will
|
||||
** commandeer the 9th cell to use as storage for an array of pointers
|
||||
** to trigger subprograms. The VDBE is guaranteed to have at least 9
|
||||
** cells. */
|
||||
assert( p->nMem>9 );
|
||||
pSub = &p->aMem[9];
|
||||
if( pSub->flags&MEM_Blob ){
|
||||
/* On the first call to sqlite3_step(), pSub will hold a NULL. It is
|
||||
** initialized to a BLOB by the P4_SUBPROGRAM processing logic below */
|
||||
nSub = pSub->n/sizeof(Vdbe*);
|
||||
apSub = (SubProgram **)pSub->z;
|
||||
}
|
||||
@@ -1100,8 +1121,12 @@ int sqlite3VdbeList(
|
||||
char *z;
|
||||
Op *pOp;
|
||||
if( i<p->nOp ){
|
||||
/* The output line number is small enough that we are still in the
|
||||
** main program. */
|
||||
pOp = &p->aOp[i];
|
||||
}else{
|
||||
/* We are currently listing subprograms. Figure out which one and
|
||||
** pick up the appropriate opcode. */
|
||||
int j;
|
||||
i -= p->nOp;
|
||||
for(j=0; i>=apSub[j]->nOp; j++){
|
||||
@@ -1123,6 +1148,11 @@ int sqlite3VdbeList(
|
||||
pMem->enc = SQLITE_UTF8;
|
||||
pMem++;
|
||||
|
||||
/* When an OP_Program opcode is encounter (the only opcode that has
|
||||
** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
|
||||
** kept in p->aMem[9].z to hold the new program - assuming this subprogram
|
||||
** has not already been seen.
|
||||
*/
|
||||
if( pOp->p4type==P4_SUBPROGRAM ){
|
||||
int nByte = (nSub+1)*sizeof(SubProgram*);
|
||||
int j;
|
||||
@@ -1254,38 +1284,43 @@ void sqlite3VdbeIOTraceSql(Vdbe *p){
|
||||
#endif /* !SQLITE_OMIT_TRACE && SQLITE_ENABLE_IOTRACE */
|
||||
|
||||
/*
|
||||
** Allocate space from a fixed size buffer. Make *pp point to the
|
||||
** allocated space. (Note: pp is a char* rather than a void** to
|
||||
** work around the pointer aliasing rules of C.) *pp should initially
|
||||
** be zero. If *pp is not zero, that means that the space has already
|
||||
** been allocated and this routine is a noop.
|
||||
** Allocate space from a fixed size buffer and return a pointer to
|
||||
** that space. If insufficient space is available, return NULL.
|
||||
**
|
||||
** The pBuf parameter is the initial value of a pointer which will
|
||||
** receive the new memory. pBuf is normally NULL. If pBuf is not
|
||||
** NULL, it means that memory space has already been allocated and that
|
||||
** this routine should not allocate any new memory. When pBuf is not
|
||||
** NULL simply return pBuf. Only allocate new memory space when pBuf
|
||||
** is NULL.
|
||||
**
|
||||
** nByte is the number of bytes of space needed.
|
||||
**
|
||||
** *ppFrom point to available space and pEnd points to the end of the
|
||||
** available space.
|
||||
** *ppFrom points to available space and pEnd points to the end of the
|
||||
** available space. When space is allocated, *ppFrom is advanced past
|
||||
** the end of the allocated space.
|
||||
**
|
||||
** *pnByte is a counter of the number of bytes of space that have failed
|
||||
** to allocate. If there is insufficient space in *ppFrom to satisfy the
|
||||
** request, then increment *pnByte by the amount of the request.
|
||||
*/
|
||||
static void allocSpace(
|
||||
char *pp, /* IN/OUT: Set *pp to point to allocated buffer */
|
||||
static void *allocSpace(
|
||||
void *pBuf, /* Where return pointer will be stored */
|
||||
int nByte, /* Number of bytes to allocate */
|
||||
u8 **ppFrom, /* IN/OUT: Allocate from *ppFrom */
|
||||
u8 *pEnd, /* Pointer to 1 byte past the end of *ppFrom buffer */
|
||||
int *pnByte /* If allocation cannot be made, increment *pnByte */
|
||||
){
|
||||
assert( EIGHT_BYTE_ALIGNMENT(*ppFrom) );
|
||||
if( (*(void**)pp)==0 ){
|
||||
nByte = ROUND8(nByte);
|
||||
if( &(*ppFrom)[nByte] <= pEnd ){
|
||||
*(void**)pp = (void *)*ppFrom;
|
||||
*ppFrom += nByte;
|
||||
}else{
|
||||
*pnByte += nByte;
|
||||
}
|
||||
if( pBuf ) return pBuf;
|
||||
nByte = ROUND8(nByte);
|
||||
if( &(*ppFrom)[nByte] <= pEnd ){
|
||||
pBuf = (void*)*ppFrom;
|
||||
*ppFrom += nByte;
|
||||
}else{
|
||||
*pnByte += nByte;
|
||||
}
|
||||
return pBuf;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1344,9 +1379,10 @@ void sqlite3VdbeMakeReady(
|
||||
** being called from sqlite3_reset() to reset the virtual machine.
|
||||
*/
|
||||
if( nVar>=0 && ALWAYS(db->mallocFailed==0) ){
|
||||
u8 *zCsr = (u8 *)&p->aOp[p->nOp];
|
||||
u8 *zEnd = (u8 *)&p->aOp[p->nOpAlloc];
|
||||
int nByte;
|
||||
u8 *zCsr = (u8 *)&p->aOp[p->nOp]; /* Memory avaliable for alloation */
|
||||
u8 *zEnd = (u8 *)&p->aOp[p->nOpAlloc]; /* First byte past available mem */
|
||||
int nByte; /* How much extra memory needed */
|
||||
|
||||
resolveP2Values(p, &nArg);
|
||||
p->usesStmtJournal = (u8)usesStmtJournal;
|
||||
if( isExplain && nMem<10 ){
|
||||
@@ -1356,15 +1392,24 @@ void sqlite3VdbeMakeReady(
|
||||
zCsr += (zCsr - (u8*)0)&7;
|
||||
assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
|
||||
|
||||
/* Memory for registers, parameters, cursor, etc, is allocated in two
|
||||
** passes. On the first pass, we try to reuse unused space at the
|
||||
** end of the opcode array. If we are unable to satisfy all memory
|
||||
** requirements by reusing the opcode array tail, then the second
|
||||
** pass will fill in the rest using a fresh allocation.
|
||||
**
|
||||
** This two-pass approach that reuses as much memory as possible from
|
||||
** the leftover space at the end of the opcode array can significantly
|
||||
** reduce the amount of memory held by a prepared statement.
|
||||
*/
|
||||
do {
|
||||
nByte = 0;
|
||||
allocSpace((char*)&p->aMem, nMem*sizeof(Mem), &zCsr, zEnd, &nByte);
|
||||
allocSpace((char*)&p->aVar, nVar*sizeof(Mem), &zCsr, zEnd, &nByte);
|
||||
allocSpace((char*)&p->apArg, nArg*sizeof(Mem*), &zCsr, zEnd, &nByte);
|
||||
allocSpace((char*)&p->azVar, nVar*sizeof(char*), &zCsr, zEnd, &nByte);
|
||||
allocSpace((char*)&p->apCsr,
|
||||
nCursor*sizeof(VdbeCursor*), &zCsr, zEnd, &nByte
|
||||
);
|
||||
p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), &zCsr, zEnd, &nByte);
|
||||
p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), &zCsr, zEnd, &nByte);
|
||||
p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), &zCsr, zEnd, &nByte);
|
||||
p->azVar = allocSpace(p->azVar, nVar*sizeof(char*), &zCsr, zEnd, &nByte);
|
||||
p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*),
|
||||
&zCsr, zEnd, &nByte);
|
||||
if( nByte ){
|
||||
p->pFree = sqlite3DbMallocZero(db, nByte);
|
||||
}
|
||||
@@ -1435,9 +1480,7 @@ void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
|
||||
sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor;
|
||||
const sqlite3_module *pModule = pCx->pModule;
|
||||
p->inVtabMethod = 1;
|
||||
(void)sqlite3SafetyOff(p->db);
|
||||
pModule->xClose(pVtabCursor);
|
||||
(void)sqlite3SafetyOn(p->db);
|
||||
p->inVtabMethod = 0;
|
||||
}
|
||||
#endif
|
||||
@@ -1618,9 +1661,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
|
||||
|
||||
/* If there are any write-transactions at all, invoke the commit hook */
|
||||
if( needXcommit && db->xCommitCallback ){
|
||||
(void)sqlite3SafetyOff(db);
|
||||
rc = db->xCommitCallback(db->pCommitArg);
|
||||
(void)sqlite3SafetyOn(db);
|
||||
if( rc ){
|
||||
return SQLITE_CONSTRAINT;
|
||||
}
|
||||
@@ -1706,10 +1747,11 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
|
||||
*/
|
||||
for(i=0; i<db->nDb; i++){
|
||||
Btree *pBt = db->aDb[i].pBt;
|
||||
if( i==1 ) continue; /* Ignore the TEMP database */
|
||||
if( sqlite3BtreeIsInTrans(pBt) ){
|
||||
char const *zFile = sqlite3BtreeGetJournalname(pBt);
|
||||
if( zFile[0]==0 ) continue; /* Ignore :memory: databases */
|
||||
if( zFile==0 || zFile[0]==0 ){
|
||||
continue; /* Ignore TEMP and :memory: databases */
|
||||
}
|
||||
if( !needSync && !sqlite3BtreeSyncDisabled(pBt) ){
|
||||
needSync = 1;
|
||||
}
|
||||
@@ -2085,12 +2127,17 @@ int sqlite3VdbeHalt(Vdbe *p){
|
||||
/* If eStatementOp is non-zero, then a statement transaction needs to
|
||||
** be committed or rolled back. Call sqlite3VdbeCloseStatement() to
|
||||
** do so. If this operation returns an error, and the current statement
|
||||
** error code is SQLITE_OK or SQLITE_CONSTRAINT, then set the error
|
||||
** code to the new value.
|
||||
** error code is SQLITE_OK or SQLITE_CONSTRAINT, then promote the
|
||||
** current statement error code.
|
||||
**
|
||||
** Note that sqlite3VdbeCloseStatement() can only fail if eStatementOp
|
||||
** is SAVEPOINT_ROLLBACK. But if p->rc==SQLITE_OK then eStatementOp
|
||||
** must be SAVEPOINT_RELEASE. Hence the NEVER(p->rc==SQLITE_OK) in
|
||||
** the following code.
|
||||
*/
|
||||
if( eStatementOp ){
|
||||
rc = sqlite3VdbeCloseStatement(p, eStatementOp);
|
||||
if( rc && (p->rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT) ){
|
||||
if( rc && (NEVER(p->rc==SQLITE_OK) || p->rc==SQLITE_CONSTRAINT) ){
|
||||
p->rc = rc;
|
||||
sqlite3DbFree(db, p->zErrMsg);
|
||||
p->zErrMsg = 0;
|
||||
@@ -2173,9 +2220,7 @@ int sqlite3VdbeReset(Vdbe *p){
|
||||
** error, then it might not have been halted properly. So halt
|
||||
** it now.
|
||||
*/
|
||||
(void)sqlite3SafetyOn(db);
|
||||
sqlite3VdbeHalt(p);
|
||||
(void)sqlite3SafetyOff(db);
|
||||
|
||||
/* If the VDBE has be run even partially, then transfer the error code
|
||||
** and error message from the VDBE into the main database structure. But
|
||||
@@ -2195,6 +2240,7 @@ int sqlite3VdbeReset(Vdbe *p){
|
||||
}else{
|
||||
sqlite3Error(db, SQLITE_OK, 0);
|
||||
}
|
||||
if( p->runOnlyOnce ) p->expired = 1;
|
||||
}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
|
||||
@@ -2296,6 +2342,7 @@ void sqlite3VdbeDelete(Vdbe *p){
|
||||
sqlite3DbFree(db, p->zSql);
|
||||
p->magic = VDBE_MAGIC_DEAD;
|
||||
sqlite3DbFree(db, p->pFree);
|
||||
p->db = 0;
|
||||
sqlite3DbFree(db, p);
|
||||
}
|
||||
|
||||
@@ -2976,7 +3023,7 @@ int sqlite3VdbeIdxKeyCompare(
|
||||
** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */
|
||||
if( nCellKey<=0 || nCellKey>0x7fffffff ){
|
||||
*res = 0;
|
||||
return SQLITE_CORRUPT;
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
memset(&m, 0, sizeof(m));
|
||||
rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (int)nCellKey, 1, &m);
|
||||
|
||||
+2
-13
@@ -95,13 +95,6 @@ int sqlite3_blob_open(
|
||||
memset(pParse, 0, sizeof(Parse));
|
||||
pParse->db = db;
|
||||
|
||||
if( sqlite3SafetyOn(db) ){
|
||||
sqlite3DbFree(db, zErr);
|
||||
sqlite3StackFree(db, pParse);
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return SQLITE_MISUSE;
|
||||
}
|
||||
|
||||
sqlite3BtreeEnterAll(db);
|
||||
pTab = sqlite3LocateTable(pParse, 0, zTable, zDb);
|
||||
if( pTab && IsVirtual(pTab) ){
|
||||
@@ -121,7 +114,6 @@ int sqlite3_blob_open(
|
||||
pParse->zErrMsg = 0;
|
||||
}
|
||||
rc = SQLITE_ERROR;
|
||||
(void)sqlite3SafetyOff(db);
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
goto blob_open_out;
|
||||
}
|
||||
@@ -136,7 +128,6 @@ int sqlite3_blob_open(
|
||||
sqlite3DbFree(db, zErr);
|
||||
zErr = sqlite3MPrintf(db, "no such column: \"%s\"", zColumn);
|
||||
rc = SQLITE_ERROR;
|
||||
(void)sqlite3SafetyOff(db);
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
goto blob_open_out;
|
||||
}
|
||||
@@ -177,7 +168,6 @@ int sqlite3_blob_open(
|
||||
sqlite3DbFree(db, zErr);
|
||||
zErr = sqlite3MPrintf(db, "cannot open %s column for writing", zFault);
|
||||
rc = SQLITE_ERROR;
|
||||
(void)sqlite3SafetyOff(db);
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
goto blob_open_out;
|
||||
}
|
||||
@@ -227,8 +217,7 @@ int sqlite3_blob_open(
|
||||
}
|
||||
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
rc = sqlite3SafetyOff(db);
|
||||
if( NEVER(rc!=SQLITE_OK) || db->mallocFailed ){
|
||||
if( db->mallocFailed ){
|
||||
goto blob_open_out;
|
||||
}
|
||||
|
||||
@@ -329,7 +318,7 @@ static int blobReadWrite(
|
||||
Vdbe *v;
|
||||
sqlite3 *db;
|
||||
|
||||
if( p==0 ) return SQLITE_MISUSE;
|
||||
if( p==0 ) return SQLITE_MISUSE_BKPT;
|
||||
db = p->db;
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
v = (Vdbe*)p->pStmt;
|
||||
|
||||
+21
-9
@@ -315,6 +315,10 @@ void sqlite3VdbeMemRelease(Mem *p){
|
||||
** before attempting the conversion.
|
||||
*/
|
||||
static i64 doubleToInt64(double r){
|
||||
#ifdef SQLITE_OMIT_FLOATING_POINT
|
||||
/* When floating-point is omitted, double and int64 are the same thing */
|
||||
return r;
|
||||
#else
|
||||
/*
|
||||
** Many compilers we encounter do not define constants for the
|
||||
** minimum and maximum 64-bit integers, or they define them
|
||||
@@ -336,6 +340,7 @@ static i64 doubleToInt64(double r){
|
||||
}else{
|
||||
return (i64)r;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -463,21 +468,26 @@ int sqlite3VdbeMemRealify(Mem *pMem){
|
||||
/*
|
||||
** Convert pMem so that it has types MEM_Real or MEM_Int or both.
|
||||
** Invalidate any prior representations.
|
||||
**
|
||||
** Every effort is made to force the conversion, even if the input
|
||||
** is a string that does not look completely like a number. Convert
|
||||
** as much of the string as we can and ignore the rest.
|
||||
*/
|
||||
int sqlite3VdbeMemNumerify(Mem *pMem){
|
||||
double r1, r2;
|
||||
i64 i;
|
||||
int rc;
|
||||
assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 );
|
||||
assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
|
||||
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
||||
r1 = sqlite3VdbeRealValue(pMem);
|
||||
i = doubleToInt64(r1);
|
||||
r2 = (double)i;
|
||||
if( r1==r2 ){
|
||||
sqlite3VdbeMemIntegerify(pMem);
|
||||
rc = sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8);
|
||||
if( rc ) return rc;
|
||||
rc = sqlite3VdbeMemNulTerminate(pMem);
|
||||
if( rc ) return rc;
|
||||
if( sqlite3Atoi64(pMem->z, &pMem->u.i) ){
|
||||
MemSetTypeFlag(pMem, MEM_Int);
|
||||
}else{
|
||||
pMem->r = r1;
|
||||
pMem->r = sqlite3VdbeRealValue(pMem);
|
||||
MemSetTypeFlag(pMem, MEM_Real);
|
||||
sqlite3VdbeIntegerAffinity(pMem);
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -529,6 +539,7 @@ void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
|
||||
pMem->type = SQLITE_INTEGER;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
/*
|
||||
** Delete any previous value and set the value stored in *pMem to val,
|
||||
** manifest type REAL.
|
||||
@@ -543,6 +554,7 @@ void sqlite3VdbeMemSetDouble(Mem *pMem, double val){
|
||||
pMem->type = SQLITE_FLOAT;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Delete any previous value and set the value of pMem to be an
|
||||
@@ -597,7 +609,7 @@ void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
|
||||
sqlite3VdbeMemReleaseExternal(pTo);
|
||||
memcpy(pTo, pFrom, MEMCELLSIZE);
|
||||
pTo->xDel = 0;
|
||||
if( (pFrom->flags&MEM_Dyn)!=0 || pFrom->z==pFrom->zMalloc ){
|
||||
if( (pFrom->flags&MEM_Static)==0 ){
|
||||
pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem);
|
||||
assert( srcType==MEM_Ephem || srcType==MEM_Static );
|
||||
pTo->flags |= srcType;
|
||||
|
||||
+8
-28
@@ -123,16 +123,7 @@ void sqlite3VtabUnlock(VTable *pVTab){
|
||||
if( pVTab->nRef==0 ){
|
||||
sqlite3_vtab *p = pVTab->pVtab;
|
||||
if( p ){
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( pVTab->db->magic==SQLITE_MAGIC_BUSY ){
|
||||
(void)sqlite3SafetyOff(db);
|
||||
p->pModule->xDisconnect(p);
|
||||
(void)sqlite3SafetyOn(db);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
p->pModule->xDisconnect(p);
|
||||
}
|
||||
p->pModule->xDisconnect(p);
|
||||
}
|
||||
sqlite3DbFree(db, pVTab);
|
||||
}
|
||||
@@ -468,9 +459,7 @@ static int vtabCallConstructor(
|
||||
db->pVTab = pTab;
|
||||
|
||||
/* Invoke the virtual table constructor */
|
||||
(void)sqlite3SafetyOff(db);
|
||||
rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr);
|
||||
(void)sqlite3SafetyOn(db);
|
||||
if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
|
||||
|
||||
if( SQLITE_OK!=rc ){
|
||||
@@ -658,7 +647,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
|
||||
if( !pTab ){
|
||||
sqlite3Error(db, SQLITE_MISUSE, 0);
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return SQLITE_MISUSE;
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
assert( (pTab->tabFlags & TF_Virtual)!=0 );
|
||||
|
||||
@@ -669,11 +658,11 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
|
||||
pParse->declareVtab = 1;
|
||||
pParse->db = db;
|
||||
|
||||
if(
|
||||
SQLITE_OK == sqlite3RunParser(pParse, zCreateTable, &zErr) &&
|
||||
pParse->pNewTable &&
|
||||
!pParse->pNewTable->pSelect &&
|
||||
(pParse->pNewTable->tabFlags & TF_Virtual)==0
|
||||
if( SQLITE_OK==sqlite3RunParser(pParse, zCreateTable, &zErr)
|
||||
&& pParse->pNewTable
|
||||
&& !db->mallocFailed
|
||||
&& !pParse->pNewTable->pSelect
|
||||
&& (pParse->pNewTable->tabFlags & TF_Virtual)==0
|
||||
){
|
||||
if( !pTab->aCol ){
|
||||
pTab->aCol = pParse->pNewTable->aCol;
|
||||
@@ -682,7 +671,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
|
||||
pParse->pNewTable->aCol = 0;
|
||||
}
|
||||
db->pVTab = 0;
|
||||
} else {
|
||||
}else{
|
||||
sqlite3Error(db, SQLITE_ERROR, zErr);
|
||||
sqlite3DbFree(db, zErr);
|
||||
rc = SQLITE_ERROR;
|
||||
@@ -717,10 +706,8 @@ int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){
|
||||
if( ALWAYS(pTab!=0 && pTab->pVTable!=0) ){
|
||||
VTable *p = vtabDisconnectAll(db, pTab);
|
||||
|
||||
rc = sqlite3SafetyOff(db);
|
||||
assert( rc==SQLITE_OK );
|
||||
rc = p->pMod->pModule->xDestroy(p->pVtab);
|
||||
(void)sqlite3SafetyOn(db);
|
||||
|
||||
/* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -772,10 +759,8 @@ static void callFinaliser(sqlite3 *db, int offset){
|
||||
int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){
|
||||
int i;
|
||||
int rc = SQLITE_OK;
|
||||
int rcsafety;
|
||||
VTable **aVTrans = db->aVTrans;
|
||||
|
||||
rc = sqlite3SafetyOff(db);
|
||||
db->aVTrans = 0;
|
||||
for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
|
||||
int (*x)(sqlite3_vtab *);
|
||||
@@ -788,11 +773,6 @@ int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){
|
||||
}
|
||||
}
|
||||
db->aVTrans = aVTrans;
|
||||
rcsafety = sqlite3SafetyOn(db);
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = rcsafety;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
+78
-31
@@ -653,7 +653,7 @@ static int isLikeOrGlob(
|
||||
}
|
||||
assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */
|
||||
pColl = sqlite3ExprCollSeq(pParse, pLeft);
|
||||
assert( pColl!=0 ); /* Every non-IPK column has a collating sequence */
|
||||
if( pColl==0 ) return 0; /* Happens when LHS has an undefined collation */
|
||||
if( (pColl->type!=SQLITE_COLL_BINARY || *pnoCase) &&
|
||||
(pColl->type!=SQLITE_COLL_NOCASE || !*pnoCase) ){
|
||||
/* IMP: R-09003-32046 For the GLOB operator, the column must use the
|
||||
@@ -1096,7 +1096,7 @@ static void exprAnalyze(
|
||||
Expr *pExpr; /* The expression to be analyzed */
|
||||
Bitmask prereqLeft; /* Prerequesites of the pExpr->pLeft */
|
||||
Bitmask prereqAll; /* Prerequesites of pExpr */
|
||||
Bitmask extraRight = 0; /* */
|
||||
Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */
|
||||
Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */
|
||||
int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */
|
||||
int noCase = 0; /* LIKE/GLOB distinguishes case */
|
||||
@@ -1168,7 +1168,8 @@ static void exprAnalyze(
|
||||
pLeft = pDup->pLeft;
|
||||
pNew->leftCursor = pLeft->iTable;
|
||||
pNew->u.leftColumn = pLeft->iColumn;
|
||||
pNew->prereqRight = prereqLeft;
|
||||
testcase( (prereqLeft | extraRight) != prereqLeft );
|
||||
pNew->prereqRight = prereqLeft | extraRight;
|
||||
pNew->prereqAll = prereqAll;
|
||||
pNew->eOperator = operatorMask(pDup->op);
|
||||
}
|
||||
@@ -1758,12 +1759,10 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
|
||||
int i;
|
||||
int rc;
|
||||
|
||||
(void)sqlite3SafetyOff(pParse->db);
|
||||
WHERETRACE(("xBestIndex for %s\n", pTab->zName));
|
||||
TRACE_IDX_INPUTS(p);
|
||||
rc = pVtab->pModule->xBestIndex(pVtab, p);
|
||||
TRACE_IDX_OUTPUTS(p);
|
||||
(void)sqlite3SafetyOn(pParse->db);
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
if( rc==SQLITE_NOMEM ){
|
||||
@@ -3160,7 +3159,7 @@ static Bitmask codeOneLoopStart(
|
||||
nConstraint = nEq;
|
||||
if( pRangeEnd ){
|
||||
Expr *pRight = pRangeEnd->pExpr->pRight;
|
||||
sqlite3ExprCacheRemove(pParse, regBase+nEq);
|
||||
sqlite3ExprCacheRemove(pParse, regBase+nEq, 1);
|
||||
sqlite3ExprCode(pParse, pRight, regBase+nEq);
|
||||
sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt);
|
||||
if( zAff ){
|
||||
@@ -3265,13 +3264,14 @@ static Bitmask codeOneLoopStart(
|
||||
*/
|
||||
WhereClause *pOrWc; /* The OR-clause broken out into subterms */
|
||||
WhereTerm *pFinal; /* Final subterm within the OR-clause. */
|
||||
SrcList oneTab; /* Shortened table list */
|
||||
SrcList *pOrTab; /* Shortened table list or OR-clause generation */
|
||||
|
||||
int regReturn = ++pParse->nMem; /* Register used with OP_Gosub */
|
||||
int regRowset = 0; /* Register for RowSet object */
|
||||
int regRowid = 0; /* Register holding rowid */
|
||||
int iLoopBody = sqlite3VdbeMakeLabel(v); /* Start of loop body */
|
||||
int iRetInit; /* Address of regReturn init */
|
||||
int untestedTerms = 0; /* Some terms not completely tested */
|
||||
int ii;
|
||||
|
||||
pTerm = pLevel->plan.u.pTerm;
|
||||
@@ -3280,11 +3280,30 @@ static Bitmask codeOneLoopStart(
|
||||
assert( (pTerm->wtFlags & TERM_ORINFO)!=0 );
|
||||
pOrWc = &pTerm->u.pOrInfo->wc;
|
||||
pFinal = &pOrWc->a[pOrWc->nTerm-1];
|
||||
pLevel->op = OP_Return;
|
||||
pLevel->p1 = regReturn;
|
||||
|
||||
/* Set up a SrcList containing just the table being scanned by this loop. */
|
||||
oneTab.nSrc = 1;
|
||||
oneTab.nAlloc = 1;
|
||||
oneTab.a[0] = *pTabItem;
|
||||
/* Set up a new SrcList ni pOrTab containing the table being scanned
|
||||
** by this loop in the a[0] slot and all notReady tables in a[1..] slots.
|
||||
** This becomes the SrcList in the recursive call to sqlite3WhereBegin().
|
||||
*/
|
||||
if( pWInfo->nLevel>1 ){
|
||||
int nNotReady; /* The number of notReady tables */
|
||||
struct SrcList_item *origSrc; /* Original list of tables */
|
||||
nNotReady = pWInfo->nLevel - iLevel - 1;
|
||||
pOrTab = sqlite3StackAllocRaw(pParse->db,
|
||||
sizeof(*pOrTab)+ nNotReady*sizeof(pOrTab->a[0]));
|
||||
if( pOrTab==0 ) return notReady;
|
||||
pOrTab->nAlloc = (i16)(nNotReady + 1);
|
||||
pOrTab->nSrc = pOrTab->nAlloc;
|
||||
memcpy(pOrTab->a, pTabItem, sizeof(*pTabItem));
|
||||
origSrc = pWInfo->pTabList->a;
|
||||
for(k=1; k<=nNotReady; k++){
|
||||
memcpy(&pOrTab->a[k], &origSrc[pLevel[k].iFrom], sizeof(pOrTab->a[k]));
|
||||
}
|
||||
}else{
|
||||
pOrTab = pWInfo->pTabList;
|
||||
}
|
||||
|
||||
/* Initialize the rowset register to contain NULL. An SQL NULL is
|
||||
** equivalent to an empty rowset.
|
||||
@@ -3309,32 +3328,38 @@ static Bitmask codeOneLoopStart(
|
||||
if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){
|
||||
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
|
||||
/* Loop through table entries that match term pOrTerm. */
|
||||
pSubWInfo = sqlite3WhereBegin(pParse, &oneTab, pOrTerm->pExpr, 0,
|
||||
WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE | WHERE_FORCE_TABLE);
|
||||
pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrTerm->pExpr, 0,
|
||||
WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE |
|
||||
WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY);
|
||||
if( pSubWInfo ){
|
||||
if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
|
||||
int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
|
||||
int r;
|
||||
r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur,
|
||||
regRowid, 0);
|
||||
regRowid);
|
||||
sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset,
|
||||
sqlite3VdbeCurrentAddr(v)+2, r, iSet);
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody);
|
||||
|
||||
/* The pSubWInfo->untestedTerms flag means that this OR term
|
||||
** contained one or more AND term from a notReady table. The
|
||||
** terms from the notReady table could not be tested and will
|
||||
** need to be tested later.
|
||||
*/
|
||||
if( pSubWInfo->untestedTerms ) untestedTerms = 1;
|
||||
|
||||
/* Finish the loop through table entries that match term pOrTerm. */
|
||||
sqlite3WhereEnd(pSubWInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
|
||||
/* sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset); */
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
|
||||
sqlite3VdbeResolveLabel(v, iLoopBody);
|
||||
|
||||
pLevel->op = OP_Return;
|
||||
pLevel->p1 = regReturn;
|
||||
disableTerm(pLevel, pTerm);
|
||||
if( pWInfo->nLevel>1 ) sqlite3StackFree(pParse->db, pOrTab);
|
||||
if( !untestedTerms ) disableTerm(pLevel, pTerm);
|
||||
}else
|
||||
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
|
||||
|
||||
@@ -3362,7 +3387,12 @@ static Bitmask codeOneLoopStart(
|
||||
testcase( pTerm->wtFlags & TERM_VIRTUAL );
|
||||
testcase( pTerm->wtFlags & TERM_CODED );
|
||||
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
|
||||
if( (pTerm->prereqAll & notReady)!=0 ) continue;
|
||||
if( (pTerm->prereqAll & notReady)!=0 ){
|
||||
testcase( pWInfo->untestedTerms==0
|
||||
&& (pWInfo->wctrlFlags & WHERE_ONETABLE_ONLY)!=0 );
|
||||
pWInfo->untestedTerms = 1;
|
||||
continue;
|
||||
}
|
||||
pE = pTerm->pExpr;
|
||||
assert( pE!=0 );
|
||||
if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){
|
||||
@@ -3385,7 +3415,10 @@ static Bitmask codeOneLoopStart(
|
||||
testcase( pTerm->wtFlags & TERM_VIRTUAL );
|
||||
testcase( pTerm->wtFlags & TERM_CODED );
|
||||
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
|
||||
if( (pTerm->prereqAll & notReady)!=0 ) continue;
|
||||
if( (pTerm->prereqAll & notReady)!=0 ){
|
||||
assert( pWInfo->untestedTerms );
|
||||
continue;
|
||||
}
|
||||
assert( pTerm->pExpr );
|
||||
sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
|
||||
pTerm->wtFlags |= TERM_CODED;
|
||||
@@ -3528,6 +3561,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
){
|
||||
int i; /* Loop counter */
|
||||
int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */
|
||||
int nTabList; /* Number of elements in pTabList */
|
||||
WhereInfo *pWInfo; /* Will become the return value of this function */
|
||||
Vdbe *v = pParse->pVdbe; /* The virtual database engine */
|
||||
Bitmask notReady; /* Cursors that are not yet positioned */
|
||||
@@ -3547,6 +3581,13 @@ WhereInfo *sqlite3WhereBegin(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function normally generates a nested loop for all tables in
|
||||
** pTabList. But if the WHERE_ONETABLE_ONLY flag is set, then we should
|
||||
** only generate code for the first table in pTabList and assume that
|
||||
** any cursors associated with subsequent tables are uninitialized.
|
||||
*/
|
||||
nTabList = (wctrlFlags & WHERE_ONETABLE_ONLY) ? 1 : pTabList->nSrc;
|
||||
|
||||
/* Allocate and initialize the WhereInfo structure that will become the
|
||||
** return value. A single allocation is used to store the WhereInfo
|
||||
** struct, the contents of WhereInfo.a[], the WhereClause structure
|
||||
@@ -3555,7 +3596,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
** some architectures. Hence the ROUND8() below.
|
||||
*/
|
||||
db = pParse->db;
|
||||
nByteWInfo = ROUND8(sizeof(WhereInfo)+(pTabList->nSrc-1)*sizeof(WhereLevel));
|
||||
nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
|
||||
pWInfo = sqlite3DbMallocZero(db,
|
||||
nByteWInfo +
|
||||
sizeof(WhereClause) +
|
||||
@@ -3564,7 +3605,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
if( db->mallocFailed ){
|
||||
goto whereBeginError;
|
||||
}
|
||||
pWInfo->nLevel = pTabList->nSrc;
|
||||
pWInfo->nLevel = nTabList;
|
||||
pWInfo->pParse = pParse;
|
||||
pWInfo->pTabList = pTabList;
|
||||
pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
|
||||
@@ -3583,7 +3624,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
/* Special case: a WHERE clause that is constant. Evaluate the
|
||||
** expression and either jump over all of the code or fall thru.
|
||||
*/
|
||||
if( pWhere && (pTabList->nSrc==0 || sqlite3ExprIsConstantNotJoin(pWhere)) ){
|
||||
if( pWhere && (nTabList==0 || sqlite3ExprIsConstantNotJoin(pWhere)) ){
|
||||
sqlite3ExprIfFalse(pParse, pWhere, pWInfo->iBreak, SQLITE_JUMPIFNULL);
|
||||
pWhere = 0;
|
||||
}
|
||||
@@ -3603,6 +3644,11 @@ WhereInfo *sqlite3WhereBegin(
|
||||
** to virtual table cursors are set. This is used to selectively disable
|
||||
** the OR-to-IN transformation in exprAnalyzeOrTerm(). It is not helpful
|
||||
** with virtual tables.
|
||||
**
|
||||
** Note that bitmasks are created for all pTabList->nSrc tables in
|
||||
** pTabList, not just the first nTabList tables. nTabList is normally
|
||||
** equal to pTabList->nSrc but might be shortened to 1 if the
|
||||
** WHERE_ONETABLE_ONLY flag is set.
|
||||
*/
|
||||
assert( pWC->vmask==0 && pMaskSet->n==0 );
|
||||
for(i=0; i<pTabList->nSrc; i++){
|
||||
@@ -3654,7 +3700,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
pLevel = pWInfo->a;
|
||||
andFlags = ~0;
|
||||
WHERETRACE(("*** Optimizer Start ***\n"));
|
||||
for(i=iFrom=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
|
||||
for(i=iFrom=0, pLevel=pWInfo->a; i<nTabList; i++, pLevel++){
|
||||
WhereCost bestPlan; /* Most efficient plan seen so far */
|
||||
Index *pIdx; /* Index for FROM table at pTabItem */
|
||||
int j; /* For looping over FROM tables */
|
||||
@@ -3699,8 +3745,8 @@ WhereInfo *sqlite3WhereBegin(
|
||||
*/
|
||||
for(isOptimal=1; isOptimal>=0 && bestJ<0; isOptimal--){
|
||||
Bitmask mask = (isOptimal ? 0 : notReady);
|
||||
assert( (pTabList->nSrc-iFrom)>1 || isOptimal );
|
||||
for(j=iFrom, pTabItem=&pTabList->a[j]; j<pTabList->nSrc; j++, pTabItem++){
|
||||
assert( (nTabList-iFrom)>1 || isOptimal );
|
||||
for(j=iFrom, pTabItem=&pTabList->a[j]; j<nTabList; j++, pTabItem++){
|
||||
int doNotReorder; /* True if this table should not be reordered */
|
||||
WhereCost sCost; /* Cost information from best[Virtual]Index() */
|
||||
ExprList *pOrderBy; /* ORDER BY clause for index to optimize */
|
||||
@@ -3797,7 +3843,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
** searching those tables.
|
||||
*/
|
||||
sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
|
||||
for(i=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
|
||||
for(i=0, pLevel=pWInfo->a; i<nTabList; i++, pLevel++){
|
||||
Table *pTab; /* Table to open */
|
||||
int iDb; /* Index of database containing table/index */
|
||||
|
||||
@@ -3876,7 +3922,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
** program.
|
||||
*/
|
||||
notReady = ~(Bitmask)0;
|
||||
for(i=0; i<pTabList->nSrc; i++){
|
||||
for(i=0; i<nTabList; i++){
|
||||
notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady);
|
||||
pWInfo->iContinue = pWInfo->a[i].addrCont;
|
||||
}
|
||||
@@ -3888,7 +3934,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
** the index is listed as "{}". If the primary key is used the
|
||||
** index name is '*'.
|
||||
*/
|
||||
for(i=0; i<pTabList->nSrc; i++){
|
||||
for(i=0; i<nTabList; i++){
|
||||
char *z;
|
||||
int n;
|
||||
pLevel = &pWInfo->a[i];
|
||||
@@ -3956,7 +4002,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
/* Generate loop termination code.
|
||||
*/
|
||||
sqlite3ExprCacheClear(pParse);
|
||||
for(i=pTabList->nSrc-1; i>=0; i--){
|
||||
for(i=pWInfo->nLevel-1; i>=0; i--){
|
||||
pLevel = &pWInfo->a[i];
|
||||
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
|
||||
if( pLevel->op!=OP_Noop ){
|
||||
@@ -4002,7 +4048,8 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
|
||||
/* Close all of the cursors that were opened by sqlite3WhereBegin.
|
||||
*/
|
||||
for(i=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
|
||||
assert( pWInfo->nLevel==1 || pWInfo->nLevel==pTabList->nSrc );
|
||||
for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){
|
||||
struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
|
||||
Table *pTab = pTabItem->pTab;
|
||||
assert( pTab!=0 );
|
||||
|
||||
Reference in New Issue
Block a user