diff --git a/dlls/sqlite/Makefile b/dlls/sqlite/Makefile
index e8262309..57d14c51 100755
--- a/dlls/sqlite/Makefile
+++ b/dlls/sqlite/Makefile
@@ -20,16 +20,13 @@ CPP_OBJECTS = basic_sql.cpp handles.cpp module.cpp threading.cpp sdk/amxxmodule.
CPP_OBJECTS += thread/BaseWorker.cpp thread/ThreadWorker.cpp thread/PosixThreads.cpp
CPP_OBJECTS += sqlitepp/SqliteQuery.cpp sqlitepp/SqliteResultSet.cpp sqlitepp/SqliteDatabase.cpp sqlitepp/SqliteDriver.cpp
-C_OBJECTS = $(SQL)/attach.c $(SQL)/auth.c $(SQL)/btree.c $(SQL)/build.c \
- $(SQL)/date.c $(SQL)/delete.c $(SQL)/func.c $(SQL)/hash.c \
- $(SQL)/insert.c $(SQL)/legacy.c $(SQL)/main.c $(SQL)/opcodes.c \
- $(SQL)/os.c $(SQL)/os_unix.c $(SQL)/pager.c $(SQL)/parse.c \
- $(SQL)/pragma.c $(SQL)/printf.c $(SQL)/random.c $(SQL)/select.c \
- $(SQL)/table.c $(SQL)/tokenize.c $(SQL)/trigger.c $(SQL)/update.c \
- $(SQL)/utf.c $(SQL)/util.c $(SQL)/vacuum.c $(SQL)/vdbe.c \
- $(SQL)/vdbeapi.c $(SQL)/vdbeaux.c $(SQL)/vdbemem.c $(SQL)/where.c \
- $(SQL)/prepare.c $(SQL)/expr.c $(SQL)/callback.c $(SQL)/alter.c \
- $(SQL)/vdbefifo.c $(SQL)/complete.c $(SQL)/analyze.c
+C_OBJECTS = $(SQL)/alter.c $(SQL)/analyze.c $(SQL)/attach.c $(SQL)/auth.c $(SQL)/btree.c $(SQL)/build.c \
+ $(SQL)/callback.c $(SQL)/complete.c $(SQL)/date.c $(SQL)/delete.c $(SQL)/expr.c $(SQL)/func.c \
+ $(SQL)/hash.c $(SQL)/insert.c $(SQL)/legacy.c $(SQL)/loadext.c $(SQL)/main.c $(SQL)/opcodes.c \
+ $(SQL)/os.c $(SQL)/os_unix.c $(SQL)/pager.c $(SQL)/parse.c $(SQL)/pragma.c $(SQL)/prepare.c \
+ $(SQL)/printf.c $(SQL)/random.c $(SQL)/select.c $(SQL)/table.c $(SQL)/tokenize.c $(SQL)/trigger.c \
+ $(SQL)/update.c $(SQL)/utf.c $(SQL)/util.c $(SQL)/vacuum.c $(SQL)/vdbe.c $(SQL)/vdbeapi.c \
+ $(SQL)/vdbeaux.c $(SQL)/vdbefifo.c $(SQL)/vdbemem.c $(SQL)/vtab.c $(SQL)/where.c \
CFLAGS = -Wall -Werror
CPPFLAGS = -Wall -Wno-non-virtual-dtor -Werror
diff --git a/dlls/sqlite/msvc7/sqlite.vcproj b/dlls/sqlite/msvc7/sqlite.vcproj
index 1a9bfdb6..e0ee8bf4 100644
--- a/dlls/sqlite/msvc7/sqlite.vcproj
+++ b/dlls/sqlite/msvc7/sqlite.vcproj
@@ -294,6 +294,9 @@
+
+
@@ -345,6 +348,9 @@
+
+
@@ -390,6 +396,9 @@
+
+
diff --git a/dlls/sqlite/msvc8/sqlite.vcproj b/dlls/sqlite/msvc8/sqlite.vcproj
index 683c8c81..8224fdd8 100644
--- a/dlls/sqlite/msvc8/sqlite.vcproj
+++ b/dlls/sqlite/msvc8/sqlite.vcproj
@@ -407,6 +407,10 @@
RelativePath="..\sqlite-source\legacy.c"
>
+
+
@@ -475,6 +479,10 @@
RelativePath="..\sqlite-source\sqlite3.h"
>
+
+
@@ -535,6 +543,10 @@
RelativePath="..\sqlite-source\vdbemem.c"
>
+
+
diff --git a/dlls/sqlite/sqlite-source/alter.c b/dlls/sqlite/sqlite-source/alter.c
index 2b48157d..81c53ffb 100644
--- a/dlls/sqlite/sqlite-source/alter.c
+++ b/dlls/sqlite/sqlite-source/alter.c
@@ -28,7 +28,7 @@
** This function is used by SQL generated to implement the
** ALTER TABLE command. The first argument is the text of a CREATE TABLE or
** CREATE INDEX command. The second is a table name. The table name in
-** the CREATE TABLE or CREATE INDEX statement is replaced with the second
+** the CREATE TABLE or CREATE INDEX statement is replaced with the third
** argument and the result returned. Examples:
**
** sqlite_rename_table('CREATE TABLE abc(a, b, c)', 'def')
@@ -78,10 +78,10 @@ static void renameTableFunc(
}
#ifndef SQLITE_OMIT_TRIGGER
-/* This function is used by SQL generated to implement the ALTER TABLE
+/* This function is used by SQL generated to implement the
** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER
** statement. The second is a table name. The table name in the CREATE
-** TRIGGER statement is replaced with the second argument and the result
+** TRIGGER statement is replaced with the third argument and the result
** returned. This is analagous to renameTableFunc() above, except for CREATE
** TRIGGER, not CREATE INDEX and CREATE TABLE.
*/
@@ -272,6 +272,12 @@ void sqlite3AlterRenameTable(
pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
if( !pTab ) goto exit_rename_table;
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( IsVirtual(pTab) ){
+ sqlite3ErrorMsg(pParse, "virtual tables may not be altered");
+ goto exit_rename_table;
+ }
+#endif
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
zDb = db->aDb[iDb].zName;
@@ -512,6 +518,13 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
if( !pTab ) goto exit_begin_add_column;
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( IsVirtual(pTab) ){
+ sqlite3ErrorMsg(pParse, "virtual tables may not be altered");
+ goto exit_begin_add_column;
+ }
+#endif
+
/* Make sure this is not an attempt to ALTER a view. */
if( pTab->pSelect ){
sqlite3ErrorMsg(pParse, "Cannot add a column to a view");
diff --git a/dlls/sqlite/sqlite-source/attach.c b/dlls/sqlite/sqlite-source/attach.c
index 5bd46ad6..10abc490 100644
--- a/dlls/sqlite/sqlite-source/attach.c
+++ b/dlls/sqlite/sqlite-source/attach.c
@@ -73,6 +73,8 @@ static void attachFunc(
zFile = (const char *)sqlite3_value_text(argv[0]);
zName = (const char *)sqlite3_value_text(argv[1]);
+ if( zFile==0 ) zFile = "";
+ if( zName==0 ) zName = "";
/* Check for the following errors:
**
@@ -82,7 +84,7 @@ static void attachFunc(
*/
if( db->nDb>=MAX_ATTACHED+2 ){
sqlite3_snprintf(
- 127, zErr, "too many attached databases - max %d", MAX_ATTACHED
+ sizeof(zErr), zErr, "too many attached databases - max %d", MAX_ATTACHED
);
goto attach_error;
}
@@ -92,8 +94,8 @@ static void attachFunc(
}
for(i=0; inDb; i++){
char *z = db->aDb[i].zName;
- if( z && sqlite3StrICmp(z, zName)==0 ){
- sqlite3_snprintf(127, zErr, "database %s is already in use", zName);
+ if( z && zName && sqlite3StrICmp(z, zName)==0 ){
+ sqlite3_snprintf(sizeof(zErr), zErr, "database %s is already in use", zName);
goto attach_error;
}
}
@@ -186,10 +188,10 @@ static void attachFunc(
sqlite3ResetInternalSchema(db, 0);
db->nDb = iDb;
if( rc==SQLITE_NOMEM ){
- sqlite3MallocFailed();
- sqlite3_snprintf(127, zErr, "out of memory");
+ if( !sqlite3MallocFailed() ) sqlite3FailedMalloc();
+ sqlite3_snprintf(sizeof(zErr),zErr, "out of memory");
}else{
- sqlite3_snprintf(127, zErr, "unable to open database: %s", zFile);
+ sqlite3_snprintf(sizeof(zErr),zErr, "unable to open database: %s", zFile);
}
goto attach_error;
}
@@ -226,7 +228,7 @@ static void detachFunc(
Db *pDb = 0;
char zErr[128];
- assert(zName);
+ if( zName==0 ) zName = "";
for(i=0; inDb; i++){
pDb = &db->aDb[i];
if( pDb->pBt==0 ) continue;
@@ -234,17 +236,21 @@ static void detachFunc(
}
if( i>=db->nDb ){
- sqlite3_snprintf(sizeof(zErr), zErr, "no such database: %s", zName);
+ sqlite3_snprintf(sizeof(zErr),zErr, "no such database: %s", zName);
goto detach_error;
}
if( i<2 ){
- sqlite3_snprintf(sizeof(zErr), zErr, "cannot detach database %s", zName);
+ sqlite3_snprintf(sizeof(zErr),zErr, "cannot detach database %s", zName);
goto detach_error;
}
if( !db->autoCommit ){
strcpy(zErr, "cannot DETACH database within transaction");
goto detach_error;
}
+ if( sqlite3BtreeIsInReadTrans(pDb->pBt) ){
+ sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName);
+ goto detach_error;
+ }
sqlite3BtreeClose(pDb->pBt);
pDb->pBt = 0;
diff --git a/dlls/sqlite/sqlite-source/auth.c b/dlls/sqlite/sqlite-source/auth.c
index dbed6a52..3983c1bc 100644
--- a/dlls/sqlite/sqlite-source/auth.c
+++ b/dlls/sqlite/sqlite-source/auth.c
@@ -182,8 +182,10 @@ int sqlite3AuthCheck(
sqlite3 *db = pParse->db;
int rc;
- /* Don't do any authorization checks if the database is initialising. */
- if( db->init.busy ){
+ /* Don't do any authorization checks if the database is initialising
+ ** or if the parser is being invoked from within sqlite3_declare_vtab.
+ */
+ if( db->init.busy || IN_DECLARE_VTAB ){
return SQLITE_OK;
}
diff --git a/dlls/sqlite/sqlite-source/btree.c b/dlls/sqlite/sqlite-source/btree.c
index 5c84c5bf..91bdac8a 100644
--- a/dlls/sqlite/sqlite-source/btree.c
+++ b/dlls/sqlite/sqlite-source/btree.c
@@ -387,17 +387,13 @@ struct BtCursor {
CellInfo info; /* A parse of the cell we are pointing at */
u8 wrFlag; /* True if writable */
u8 eState; /* One of the CURSOR_XXX constants (see below) */
-#ifndef SQLITE_OMIT_SHARED_CACHE
void *pKey; /* Saved key that was cursor's last known position */
i64 nKey; /* Size of pKey, or last integer key */
int skip; /* (skip<0) -> Prev() is a no-op. (skip>0) -> Next() is */
-#endif
};
/*
-** Potential values for BtCursor.eState. The first two values (VALID and
-** INVALID) may occur in any build. The third (REQUIRESEEK) may only occur
-** if sqlite was compiled without the OMIT_SHARED_CACHE symbol defined.
+** Potential values for BtCursor.eState.
**
** CURSOR_VALID:
** Cursor points to a valid entry. getPayload() etc. may be called.
@@ -425,16 +421,17 @@ struct BtCursor {
*/
#if SQLITE_TEST
# define TRACE(X) if( sqlite3_btree_trace )\
- { sqlite3DebugPrintf X; fflush(stdout); }
+/* { sqlite3DebugPrintf X; fflush(stdout); } */ \
+{ printf X; fflush(stdout); }
+int sqlite3_btree_trace=0; /* True to enable tracing */
#else
# define TRACE(X)
#endif
-int sqlite3_btree_trace=0; /* True to enable tracing */
/*
** Forward declaration
*/
-static int checkReadLocks(BtShared*,Pgno,BtCursor*);
+static int checkReadLocks(Btree*,Pgno,BtCursor*);
/*
** Read or write a two- and four-byte big-endian integer values.
@@ -509,105 +506,8 @@ struct BtLock {
#define queryTableLock(a,b,c) SQLITE_OK
#define lockTable(a,b,c) SQLITE_OK
#define unlockAllTables(a)
- #define restoreOrClearCursorPosition(a,b) SQLITE_OK
- #define saveAllCursors(a,b,c) SQLITE_OK
-
#else
-static void releasePage(MemPage *pPage);
-
-/*
-** Save the current cursor position in the variables BtCursor.nKey
-** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK.
-*/
-static int saveCursorPosition(BtCursor *pCur){
- int rc;
-
- assert( CURSOR_VALID==pCur->eState );
- assert( 0==pCur->pKey );
-
- rc = sqlite3BtreeKeySize(pCur, &pCur->nKey);
-
- /* If this is an intKey table, then the above call to BtreeKeySize()
- ** stores the integer key in pCur->nKey. In this case this value is
- ** all that is required. Otherwise, if pCur is not open on an intKey
- ** table, then malloc space for and store the pCur->nKey bytes of key
- ** data.
- */
- if( rc==SQLITE_OK && 0==pCur->pPage->intKey){
- void *pKey = sqliteMalloc((int)pCur->nKey);
- if( pKey ){
- rc = sqlite3BtreeKey(pCur, 0, (u32)pCur->nKey, pKey);
- if( rc==SQLITE_OK ){
- pCur->pKey = pKey;
- }else{
- sqliteFree(pKey);
- }
- }else{
- rc = SQLITE_NOMEM;
- }
- }
- assert( !pCur->pPage->intKey || !pCur->pKey );
-
- if( rc==SQLITE_OK ){
- releasePage(pCur->pPage);
- pCur->pPage = 0;
- pCur->eState = CURSOR_REQUIRESEEK;
- }
-
- return rc;
-}
-
-/*
-** Save the positions of all cursors except pExcept open on the table
-** with root-page iRoot. Usually, this is called just before cursor
-** pExcept is used to modify the table (BtreeDelete() or BtreeInsert()).
-*/
-static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){
- BtCursor *p;
- if( sqlite3ThreadDataReadOnly()->useSharedData ){
- for(p=pBt->pCursor; p; p=p->pNext){
- if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) &&
- p->eState==CURSOR_VALID ){
- int rc = saveCursorPosition(p);
- if( SQLITE_OK!=rc ){
- return rc;
- }
- }
- }
- }
- return SQLITE_OK;
-}
-
-/*
-** Restore the cursor to the position it was in (or as close to as possible)
-** when saveCursorPosition() was called. Note that this call deletes the
-** saved position info stored by saveCursorPosition(), so there can be
-** at most one effective restoreOrClearCursorPosition() call after each
-** saveCursorPosition().
-**
-** If the second argument argument - doSeek - is false, then instead of
-** returning the cursor to it's saved position, any saved position is deleted
-** and the cursor state set to CURSOR_INVALID.
-*/
-static int restoreOrClearCursorPositionX(BtCursor *pCur, int doSeek){
- int rc = SQLITE_OK;
- assert( sqlite3ThreadDataReadOnly()->useSharedData );
- assert( pCur->eState==CURSOR_REQUIRESEEK );
- pCur->eState = CURSOR_INVALID;
- if( doSeek ){
- rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, &pCur->skip);
- }
- if( rc==SQLITE_OK ){
- sqliteFree(pCur->pKey);
- pCur->pKey = 0;
- assert( CURSOR_VALID==pCur->eState || CURSOR_INVALID==pCur->eState );
- }
- return rc;
-}
-
-#define restoreOrClearCursorPosition(p,x) \
- (p->eState==CURSOR_REQUIRESEEK?restoreOrClearCursorPositionX(p,x):SQLITE_OK)
/*
** Query to see if btree handle p may obtain a lock of type eLock
@@ -747,6 +647,98 @@ static void unlockAllTables(Btree *p){
}
#endif /* SQLITE_OMIT_SHARED_CACHE */
+static void releasePage(MemPage *pPage); /* Forward reference */
+
+/*
+** Save the current cursor position in the variables BtCursor.nKey
+** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK.
+*/
+static int saveCursorPosition(BtCursor *pCur){
+ int rc;
+
+ assert( CURSOR_VALID==pCur->eState );
+ assert( 0==pCur->pKey );
+
+ rc = sqlite3BtreeKeySize(pCur, &pCur->nKey);
+
+ /* If this is an intKey table, then the above call to BtreeKeySize()
+ ** stores the integer key in pCur->nKey. In this case this value is
+ ** all that is required. Otherwise, if pCur is not open on an intKey
+ ** table, then malloc space for and store the pCur->nKey bytes of key
+ ** data.
+ */
+ if( rc==SQLITE_OK && 0==pCur->pPage->intKey){
+ void *pKey = sqliteMalloc((int)pCur->nKey);
+ if( pKey ){
+ rc = sqlite3BtreeKey(pCur, 0, (u32)pCur->nKey, pKey);
+ if( rc==SQLITE_OK ){
+ pCur->pKey = pKey;
+ }else{
+ sqliteFree(pKey);
+ }
+ }else{
+ rc = SQLITE_NOMEM;
+ }
+ }
+ assert( !pCur->pPage->intKey || !pCur->pKey );
+
+ if( rc==SQLITE_OK ){
+ releasePage(pCur->pPage);
+ pCur->pPage = 0;
+ pCur->eState = CURSOR_REQUIRESEEK;
+ }
+
+ return rc;
+}
+
+/*
+** Save the positions of all cursors except pExcept open on the table
+** with root-page iRoot. Usually, this is called just before cursor
+** pExcept is used to modify the table (BtreeDelete() or BtreeInsert()).
+*/
+static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){
+ BtCursor *p;
+ for(p=pBt->pCursor; p; p=p->pNext){
+ if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) &&
+ p->eState==CURSOR_VALID ){
+ int rc = saveCursorPosition(p);
+ if( SQLITE_OK!=rc ){
+ return rc;
+ }
+ }
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Restore the cursor to the position it was in (or as close to as possible)
+** when saveCursorPosition() was called. Note that this call deletes the
+** saved position info stored by saveCursorPosition(), so there can be
+** at most one effective restoreOrClearCursorPosition() call after each
+** saveCursorPosition().
+**
+** If the second argument argument - doSeek - is false, then instead of
+** returning the cursor to it's saved position, any saved position is deleted
+** and the cursor state set to CURSOR_INVALID.
+*/
+static int restoreOrClearCursorPositionX(BtCursor *pCur, int doSeek){
+ int rc = SQLITE_OK;
+ assert( pCur->eState==CURSOR_REQUIRESEEK );
+ pCur->eState = CURSOR_INVALID;
+ if( doSeek ){
+ rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, &pCur->skip);
+ }
+ if( rc==SQLITE_OK ){
+ sqliteFree(pCur->pKey);
+ pCur->pKey = 0;
+ assert( CURSOR_VALID==pCur->eState || CURSOR_INVALID==pCur->eState );
+ }
+ return rc;
+}
+
+#define restoreOrClearCursorPosition(p,x) \
+ (p->eState==CURSOR_REQUIRESEEK?restoreOrClearCursorPositionX(p,x):SQLITE_OK)
+
#ifndef SQLITE_OMIT_AUTOVACUUM
/*
** These macros define the location of the pointer-map entry for a
@@ -1048,91 +1040,6 @@ static int ptrmapPutOvfl(MemPage *pPage, int iCell){
#endif
-/*
-** Do sanity checking on a page. Throw an exception if anything is
-** not right.
-**
-** This routine is used for internal error checking only. It is omitted
-** from most builds.
-*/
-#if defined(BTREE_DEBUG) && !defined(NDEBUG) && 0
-static void _pageIntegrity(MemPage *pPage){
- int usableSize;
- u8 *data;
- int i, j, idx, c, pc, hdr, nFree;
- int cellOffset;
- int nCell, cellLimit;
- u8 *used;
-
- used = sqliteMallocRaw( pPage->pBt->pageSize );
- if( used==0 ) return;
- usableSize = pPage->pBt->usableSize;
- assert( pPage->aData==&((unsigned char*)pPage)[-pPage->pBt->pageSize] );
- hdr = pPage->hdrOffset;
- assert( hdr==(pPage->pgno==1 ? 100 : 0) );
- assert( pPage->pgno==sqlite3pager_pagenumber(pPage->aData) );
- c = pPage->aData[hdr];
- if( pPage->isInit ){
- assert( pPage->leaf == ((c & PTF_LEAF)!=0) );
- assert( pPage->zeroData == ((c & PTF_ZERODATA)!=0) );
- assert( pPage->leafData == ((c & PTF_LEAFDATA)!=0) );
- assert( pPage->intKey == ((c & (PTF_INTKEY|PTF_LEAFDATA))!=0) );
- assert( pPage->hasData ==
- !(pPage->zeroData || (!pPage->leaf && pPage->leafData)) );
- assert( pPage->cellOffset==pPage->hdrOffset+12-4*pPage->leaf );
- assert( pPage->nCell = get2byte(&pPage->aData[hdr+3]) );
- }
- data = pPage->aData;
- memset(used, 0, usableSize);
- for(i=0; ileaf*4; i++) used[i] = 1;
- nFree = 0;
- pc = get2byte(&data[hdr+1]);
- while( pc ){
- int size;
- assert( pc>0 && pcisInit==0
- || pPage->nFree==nFree+data[hdr+7]+cellLimit-(cellOffset+2*nCell) );
- cellOffset = pPage->cellOffset;
- for(i=0; i0 && pcisInit = 1;
- pageIntegrity(pPage);
return SQLITE_OK;
}
@@ -1470,7 +1376,6 @@ static void zeroPage(MemPage *pPage, int flags){
pPage->idxShift = 0;
pPage->nCell = 0;
pPage->isInit = 1;
- pageIntegrity(pPage);
}
/*
@@ -1591,9 +1496,9 @@ int sqlite3BtreeOpen(
*/
#if !defined(SQLITE_OMIT_SHARED_CACHE) || !defined(SQLITE_OMIT_AUTOVACUUM)
#ifdef SQLITE_OMIT_MEMORYDB
- const int isMemdb = !zFilename;
+ const int isMemdb = 0;
#else
- const int isMemdb = !zFilename || (strcmp(zFilename, ":memory:")?0:1);
+ const int isMemdb = zFilename && !strcmp(zFilename, ":memory:");
#endif
#endif
@@ -1645,8 +1550,13 @@ int sqlite3BtreeOpen(
return SQLITE_NOMEM;
}
rc = sqlite3pager_open(&pBt->pPager, zFilename, EXTRA_SIZE, flags);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3pager_read_fileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader);
+ }
if( rc!=SQLITE_OK ){
- if( pBt->pPager ) sqlite3pager_close(pBt->pPager);
+ if( pBt->pPager ){
+ sqlite3pager_close(pBt->pPager);
+ }
sqliteFree(pBt);
sqliteFree(p);
*ppBtree = 0;
@@ -1659,7 +1569,6 @@ int sqlite3BtreeOpen(
pBt->pCursor = 0;
pBt->pPage1 = 0;
pBt->readOnly = sqlite3pager_isreadonly(pBt->pPager);
- sqlite3pager_read_fileheader(pBt->pPager, sizeof(zDbHeader), zDbHeader);
pBt->pageSize = get2byte(&zDbHeader[16]);
if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE
|| ((pBt->pageSize-1)&pBt->pageSize)!=0 ){
@@ -2022,13 +1931,15 @@ static int lockBtreeWithRetry(Btree *pRef){
*/
static void unlockBtreeIfUnused(BtShared *pBt){
if( pBt->inTransaction==TRANS_NONE && pBt->pCursor==0 && pBt->pPage1!=0 ){
- if( pBt->pPage1->aData==0 ){
- MemPage *pPage = pBt->pPage1;
- pPage->aData = &((u8*)pPage)[-pBt->pageSize];
- pPage->pBt = pBt;
- pPage->pgno = 1;
+ if( sqlite3pager_refcount(pBt->pPager)>=1 ){
+ if( pBt->pPage1->aData==0 ){
+ MemPage *pPage = pBt->pPage1;
+ pPage->aData = &((u8*)pPage)[-pBt->pageSize];
+ pPage->pBt = pBt;
+ pPage->pgno = 1;
+ }
+ releasePage(pBt->pPage1);
}
- releasePage(pBt->pPage1);
pBt->pPage1 = 0;
pBt->inStmt = 0;
}
@@ -2367,7 +2278,7 @@ static int autoVacuumCommit(BtShared *pBt, Pgno *nTrunc){
MemPage *pFreeMemPage = 0; /* "" */
#ifndef NDEBUG
- int nRef = *sqlite3pager_stats(pPager);
+ int nRef = sqlite3pager_refcount(pPager);
#endif
assert( pBt->autoVacuum );
@@ -2475,7 +2386,7 @@ static int autoVacuumCommit(BtShared *pBt, Pgno *nTrunc){
assert( finSize!=PENDING_BYTE_PAGE(pBt) );
autovacuum_out:
- assert( nRef==*sqlite3pager_stats(pPager) );
+ assert( nRef==sqlite3pager_refcount(pPager) );
if( rc!=SQLITE_OK ){
sqlite3pager_rollback(pPager);
}
@@ -2548,7 +2459,7 @@ static int countWriteCursors(BtShared *pBt){
}
#endif
-#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
+#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
/*
** Print debugging information about all cursors to standard output.
*/
@@ -2778,7 +2689,7 @@ int sqlite3BtreeCursor(
if( pBt->readOnly ){
return SQLITE_READONLY;
}
- if( checkReadLocks(pBt, iTable, 0) ){
+ if( checkReadLocks(p, iTable, 0) ){
return SQLITE_LOCKED;
}
}
@@ -2980,7 +2891,6 @@ static int getPayload(
assert( pCur->eState==CURSOR_VALID );
pBt = pCur->pBtree->pBt;
pPage = pCur->pPage;
- pageIntegrity(pPage);
assert( pCur->idx>=0 && pCur->idxnCell );
getCellInfo(pCur);
aPayload = pCur->info.pCell + pCur->info.nHeader;
@@ -3118,7 +3028,6 @@ static const unsigned char *fetchPayload(
assert( pCur!=0 && pCur->pPage!=0 );
assert( pCur->eState==CURSOR_VALID );
pPage = pCur->pPage;
- pageIntegrity(pPage);
assert( pCur->idx>=0 && pCur->idxnCell );
getCellInfo(pCur);
aPayload = pCur->info.pCell;
@@ -3180,7 +3089,6 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
assert( pCur->eState==CURSOR_VALID );
rc = getAndInitPage(pBt, newPgno, &pNewPage, pCur->pPage);
if( rc ) return rc;
- pageIntegrity(pNewPage);
pNewPage->idxParent = pCur->idx;
pOldPage = pCur->pPage;
pOldPage->idxShift = 0;
@@ -3228,10 +3136,8 @@ static void moveToParent(BtCursor *pCur){
pPage = pCur->pPage;
assert( pPage!=0 );
assert( !isRootPage(pPage) );
- pageIntegrity(pPage);
pParent = pPage->pParent;
assert( pParent!=0 );
- pageIntegrity(pParent);
idxParent = pPage->idxParent;
sqlite3pager_ref(pParent->aData);
releasePage(pPage);
@@ -3261,7 +3167,6 @@ static int moveToRoot(BtCursor *pCur){
return rc;
}
releasePage(pCur->pPage);
- pageIntegrity(pRoot);
pCur->pPage = pRoot;
}
pCur->idx = 0;
@@ -3405,7 +3310,7 @@ int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, i64 nKey, int *pRes){
assert( pCur->pPage->nCell==0 );
return SQLITE_OK;
}
- for(;;){
+ for(;;){
int lwr, upr;
Pgno chldPg;
MemPage *pPage = pCur->pPage;
@@ -3415,7 +3320,6 @@ int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, i64 nKey, int *pRes){
if( !pPage->intKey && pKey==0 ){
return SQLITE_CORRUPT_BKPT;
}
- pageIntegrity(pPage);
while( lwr<=upr ){
void *pCellKey;
i64 nCellKey;
@@ -3668,14 +3572,14 @@ static int allocatePage(
int rc;
int n; /* Number of pages on the freelist */
int k; /* Number of leaves on the trunk of the freelist */
+ MemPage *pTrunk = 0;
+ MemPage *pPrevTrunk = 0;
pPage1 = pBt->pPage1;
n = get4byte(&pPage1->aData[36]);
if( n>0 ){
/* There are pages on the freelist. Reuse one of those pages. */
- MemPage *pTrunk = 0;
Pgno iTrunk;
- MemPage *pPrevTrunk = 0;
u8 searchList = 0; /* If the free-list must be searched for 'nearby' */
/* If the 'exact' parameter was true and a query of the pointer-map
@@ -3716,16 +3620,8 @@ static int allocatePage(
}
rc = getPage(pBt, iTrunk, &pTrunk);
if( rc ){
- releasePage(pPrevTrunk);
- return rc;
- }
-
- /* TODO: This should move to after the loop? */
- rc = sqlite3pager_write(pTrunk->aData);
- if( rc ){
- releasePage(pTrunk);
- releasePage(pPrevTrunk);
- return rc;
+ pTrunk = 0;
+ goto end_allocate_page;
}
k = get4byte(&pTrunk->aData[4]);
@@ -3734,6 +3630,10 @@ static int allocatePage(
** So extract the trunk page itself and use it as the newly
** allocated page */
assert( pPrevTrunk==0 );
+ rc = sqlite3pager_write(pTrunk->aData);
+ if( rc ){
+ goto end_allocate_page;
+ }
*pPgno = iTrunk;
memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4);
*ppPage = pTrunk;
@@ -3741,7 +3641,8 @@ static int allocatePage(
TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1));
}else if( k>pBt->usableSize/4 - 8 ){
/* Value of k is out of range. Database corruption */
- return SQLITE_CORRUPT_BKPT;
+ rc = SQLITE_CORRUPT_BKPT;
+ goto end_allocate_page;
#ifndef SQLITE_OMIT_AUTOVACUUM
}else if( searchList && nearby==iTrunk ){
/* The list is being searched and this trunk page is the page
@@ -3750,6 +3651,10 @@ static int allocatePage(
assert( *pPgno==iTrunk );
*ppPage = pTrunk;
searchList = 0;
+ rc = sqlite3pager_write(pTrunk->aData);
+ if( rc ){
+ goto end_allocate_page;
+ }
if( k==0 ){
if( !pPrevTrunk ){
memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4);
@@ -3765,26 +3670,26 @@ static int allocatePage(
Pgno iNewTrunk = get4byte(&pTrunk->aData[8]);
rc = getPage(pBt, iNewTrunk, &pNewTrunk);
if( rc!=SQLITE_OK ){
- releasePage(pTrunk);
- releasePage(pPrevTrunk);
- return rc;
+ goto end_allocate_page;
}
rc = sqlite3pager_write(pNewTrunk->aData);
if( rc!=SQLITE_OK ){
releasePage(pNewTrunk);
- releasePage(pTrunk);
- releasePage(pPrevTrunk);
- return rc;
+ goto end_allocate_page;
}
memcpy(&pNewTrunk->aData[0], &pTrunk->aData[0], 4);
put4byte(&pNewTrunk->aData[4], k-1);
memcpy(&pNewTrunk->aData[8], &pTrunk->aData[12], (k-1)*4);
+ releasePage(pNewTrunk);
if( !pPrevTrunk ){
put4byte(&pPage1->aData[32], iNewTrunk);
}else{
+ rc = sqlite3pager_write(pPrevTrunk->aData);
+ if( rc ){
+ goto end_allocate_page;
+ }
put4byte(&pPrevTrunk->aData[0], iNewTrunk);
}
- releasePage(pNewTrunk);
}
pTrunk = 0;
TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1));
@@ -3794,6 +3699,10 @@ static int allocatePage(
int closest;
Pgno iPage;
unsigned char *aData = pTrunk->aData;
+ rc = sqlite3pager_write(aData);
+ if( rc ){
+ goto end_allocate_page;
+ }
if( nearby>0 ){
int i, dist;
closest = 0;
@@ -3837,8 +3746,8 @@ static int allocatePage(
}
}
releasePage(pPrevTrunk);
+ pPrevTrunk = 0;
}while( searchList );
- releasePage(pTrunk);
}else{
/* There are no pages on the freelist, so create a new page at the
** end of the file */
@@ -3867,6 +3776,10 @@ static int allocatePage(
}
assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
+
+end_allocate_page:
+ releasePage(pTrunk);
+ releasePage(pPrevTrunk);
return rc;
}
@@ -4267,7 +4180,6 @@ static int insertCell(
put2byte(&data[ins], idx);
put2byte(&data[hdr+3], pPage->nCell);
pPage->idxShift = 1;
- pageIntegrity(pPage);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pPage->pBt->autoVacuum ){
/* The cell may contain a pointer to an overflow page. If so, write
@@ -5007,8 +4919,6 @@ static int balance_nonroot(MemPage *pPage){
** But the parent page will always be initialized.
*/
assert( pParent->isInit );
- /* assert( pPage->isInit ); // No! pPage might have been added to freelist */
- /* pageIntegrity(pPage); // No! pPage might have been added to freelist */
rc = balance(pParent, 0);
/*
@@ -5215,27 +5125,35 @@ static int balance(MemPage *pPage, int insert){
/*
** This routine checks all cursors that point to table pgnoRoot.
-** If any of those cursors other than pExclude were opened with
-** wrFlag==0 then this routine returns SQLITE_LOCKED. If all
-** cursors that point to pgnoRoot were opened with wrFlag==1
-** then this routine returns SQLITE_OK.
+** If any of those cursors were opened with wrFlag==0 in a different
+** database connection (a database connection that shares the pager
+** cache with the current connection) and that other connection
+** is not in the ReadUncommmitted state, then this routine returns
+** SQLITE_LOCKED.
**
** In addition to checking for read-locks (where a read-lock
** means a cursor opened with wrFlag==0) this routine also moves
-** all cursors other than pExclude so that they are pointing to the
-** first Cell on root page. This is necessary because an insert
+** all cursors write cursors so that they are pointing to the
+** first Cell on the root page. This is necessary because an insert
** or delete might change the number of cells on a page or delete
** a page entirely and we do not want to leave any cursors
** pointing to non-existant pages or cells.
*/
-static int checkReadLocks(BtShared *pBt, Pgno pgnoRoot, BtCursor *pExclude){
+static int checkReadLocks(Btree *pBtree, Pgno pgnoRoot, BtCursor *pExclude){
BtCursor *p;
+ BtShared *pBt = pBtree->pBt;
+ sqlite3 *db = pBtree->pSqlite;
for(p=pBt->pCursor; p; p=p->pNext){
- u32 flags = (p->pBtree->pSqlite ? p->pBtree->pSqlite->flags : 0);
- if( p->pgnoRoot!=pgnoRoot || p==pExclude ) continue;
- if( p->wrFlag==0 && flags&SQLITE_ReadUncommitted ) continue;
- if( p->wrFlag==0 ) return SQLITE_LOCKED;
- if( p->pPage->pgno!=p->pgnoRoot ){
+ if( p==pExclude ) continue;
+ if( p->eState!=CURSOR_VALID ) continue;
+ if( p->pgnoRoot!=pgnoRoot ) continue;
+ if( p->wrFlag==0 ){
+ sqlite3 *dbOther = p->pBtree->pSqlite;
+ if( dbOther==0 ||
+ (dbOther!=db && (dbOther->flags & SQLITE_ReadUncommitted)==0) ){
+ return SQLITE_LOCKED;
+ }
+ }else if( p->pPage->pgno!=p->pgnoRoot ){
moveToRoot(p);
}
}
@@ -5272,7 +5190,7 @@ int sqlite3BtreeInsert(
if( !pCur->wrFlag ){
return SQLITE_PERM; /* Cursor not open for writing */
}
- if( checkReadLocks(pBt, pCur->pgnoRoot, pCur) ){
+ if( checkReadLocks(pCur->pBtree, pCur->pgnoRoot, pCur) ){
return SQLITE_LOCKED; /* The table pCur points to has a read lock */
}
@@ -5354,7 +5272,7 @@ int sqlite3BtreeDelete(BtCursor *pCur){
if( !pCur->wrFlag ){
return SQLITE_PERM; /* Did not open this cursor for writing */
}
- if( checkReadLocks(pBt, pCur->pgnoRoot, pCur) ){
+ if( checkReadLocks(pCur->pBtree, pCur->pgnoRoot, pCur) ){
return SQLITE_LOCKED; /* The table pCur points to has a read lock */
}
@@ -5393,8 +5311,8 @@ int sqlite3BtreeDelete(BtCursor *pCur){
BtCursor leafCur;
unsigned char *pNext;
int szNext = 0; /* The compiler warning is wrong: szNext is always
- ** initialized before use. Adding an extra initialization
- ** to silence the compiler slows down the code. */
+ ** initialized before use. Adding an extra initialization
+ ** to silence the compiler slows down the code. */
int notUsed;
unsigned char *tempCell = 0;
assert( !pPage->leafData );
@@ -5631,25 +5549,13 @@ cleardatabasepage_out:
*/
int sqlite3BtreeClearTable(Btree *p, int iTable){
int rc;
- BtCursor *pCur;
BtShared *pBt = p->pBt;
- sqlite3 *db = p->pSqlite;
if( p->inTrans!=TRANS_WRITE ){
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
}
-
- /* If this connection is not in read-uncommitted mode and currently has
- ** a read-cursor open on the table being cleared, return SQLITE_LOCKED.
- */
- if( 0==db || 0==(db->flags&SQLITE_ReadUncommitted) ){
- for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
- if( pCur->pBtree==p && pCur->pgnoRoot==(Pgno)iTable ){
- if( 0==pCur->wrFlag ){
- return SQLITE_LOCKED;
- }
- moveToRoot(pCur);
- }
- }
+ rc = checkReadLocks(p, iTable, 0);
+ if( rc ){
+ return rc;
}
/* Save the position of all cursors open on this table */
@@ -5969,7 +5875,7 @@ int sqlite3BtreePageDump(Btree *p, int pgno, int recursive){
}
#endif
-#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
+#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
/*
** Fill aResult[] with information about the entry and page that the
** cursor is pointing to.
@@ -5984,6 +5890,7 @@ int sqlite3BtreePageDump(Btree *p, int pgno, int recursive){
** aResult[7] = Header size in bytes
** aResult[8] = Local payload size
** aResult[9] = Parent page number
+** aResult[10]= Page number of the first overflow page
**
** This routine is used for testing and debugging only.
*/
@@ -5997,14 +5904,12 @@ int sqlite3BtreeCursorInfo(BtCursor *pCur, int *aResult, int upCnt){
return rc;
}
- pageIntegrity(pPage);
assert( pPage->isInit );
getTempCursor(pCur, &tmpCur);
while( upCnt-- ){
moveToParent(&tmpCur);
}
pPage = tmpCur.pPage;
- pageIntegrity(pPage);
aResult[0] = sqlite3pager_pagenumber(pPage->aData);
assert( aResult[0]==pPage->pgno );
aResult[1] = tmpCur.idx;
@@ -6034,6 +5939,11 @@ int sqlite3BtreeCursorInfo(BtCursor *pCur, int *aResult, int upCnt){
}else{
aResult[9] = pPage->pParent->pgno;
}
+ if( tmpCur.info.iOverflow ){
+ aResult[10] = get4byte(&tmpCur.info.pCell[tmpCur.info.iOverflow]);
+ }else{
+ aResult[10] = 0;
+ }
releaseTempCursor(&tmpCur);
return SQLITE_OK;
}
@@ -6054,10 +5964,12 @@ Pager *sqlite3BtreePager(Btree *p){
typedef struct IntegrityCk IntegrityCk;
struct IntegrityCk {
BtShared *pBt; /* The tree being checked out */
- Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */
- int nPage; /* Number of pages in the database */
- int *anRef; /* Number of times each page is referenced */
- char *zErrMsg; /* An error message. NULL of no errors seen. */
+ Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */
+ int nPage; /* Number of pages in the database */
+ int *anRef; /* Number of times each page is referenced */
+ int mxErr; /* Stop accumulating errors when this reaches zero */
+ char *zErrMsg; /* An error message. NULL if no errors seen. */
+ int nErr; /* Number of messages written to zErrMsg so far */
};
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
@@ -6072,6 +5984,9 @@ static void checkAppendMsg(
){
va_list ap;
char *zMsg2;
+ if( !pCheck->mxErr ) return;
+ pCheck->mxErr--;
+ pCheck->nErr++;
va_start(ap, zFormat);
zMsg2 = sqlite3VMPrintf(zFormat, ap);
va_end(ap);
@@ -6155,7 +6070,7 @@ static void checkList(
int i;
int expected = N;
int iFirst = iPage;
- while( N-- > 0 ){
+ while( N-- > 0 && pCheck->mxErr ){
unsigned char *pOvfl;
if( iPage<1 ){
checkAppendMsg(pCheck, zContext,
@@ -6267,7 +6182,7 @@ static int checkTreePage(
/* Check out all the cells.
*/
depth = 0;
- for(i=0; inCell; i++){
+ for(i=0; inCell && pCheck->mxErr; i++){
u8 *pCell;
int sz;
CellInfo info;
@@ -6382,19 +6297,28 @@ static int checkTreePage(
** and a pointer to that error message is returned. The calling function
** is responsible for freeing the error message when it is done.
*/
-char *sqlite3BtreeIntegrityCheck(Btree *p, int *aRoot, int nRoot){
+char *sqlite3BtreeIntegrityCheck(
+ Btree *p, /* The btree to be checked */
+ int *aRoot, /* An array of root pages numbers for individual trees */
+ int nRoot, /* Number of entries in aRoot[] */
+ int mxErr, /* Stop reporting errors after this many */
+ int *pnErr /* Write number of errors seen to this variable */
+){
int i;
int nRef;
IntegrityCk sCheck;
BtShared *pBt = p->pBt;
- nRef = *sqlite3pager_stats(pBt->pPager);
+ nRef = sqlite3pager_refcount(pBt->pPager);
if( lockBtreeWithRetry(p)!=SQLITE_OK ){
return sqliteStrDup("Unable to acquire a read lock on the database");
}
sCheck.pBt = pBt;
sCheck.pPager = pBt->pPager;
sCheck.nPage = sqlite3pager_pagecount(sCheck.pPager);
+ sCheck.mxErr = mxErr;
+ sCheck.nErr = 0;
+ *pnErr = 0;
if( sCheck.nPage==0 ){
unlockBtreeIfUnused(pBt);
return 0;
@@ -6402,6 +6326,7 @@ char *sqlite3BtreeIntegrityCheck(Btree *p, int *aRoot, int nRoot){
sCheck.anRef = sqliteMallocRaw( (sCheck.nPage+1)*sizeof(sCheck.anRef[0]) );
if( !sCheck.anRef ){
unlockBtreeIfUnused(pBt);
+ *pnErr = 1;
return sqlite3MPrintf("Unable to malloc %d bytes",
(sCheck.nPage+1)*sizeof(sCheck.anRef[0]));
}
@@ -6419,7 +6344,7 @@ char *sqlite3BtreeIntegrityCheck(Btree *p, int *aRoot, int nRoot){
/* Check all the tables.
*/
- for(i=0; iautoVacuum && aRoot[i]>1 ){
@@ -6431,7 +6356,7 @@ char *sqlite3BtreeIntegrityCheck(Btree *p, int *aRoot, int nRoot){
/* Make sure every page in the file is referenced
*/
- for(i=1; i<=sCheck.nPage; i++){
+ for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){
#ifdef SQLITE_OMIT_AUTOVACUUM
if( sCheck.anRef[i]==0 ){
checkAppendMsg(&sCheck, 0, "Page %d is never used", i);
@@ -6454,16 +6379,17 @@ char *sqlite3BtreeIntegrityCheck(Btree *p, int *aRoot, int nRoot){
/* Make sure this analysis did not leave any unref() pages
*/
unlockBtreeIfUnused(pBt);
- if( nRef != *sqlite3pager_stats(pBt->pPager) ){
+ if( nRef != sqlite3pager_refcount(pBt->pPager) ){
checkAppendMsg(&sCheck, 0,
"Outstanding page count goes from %d to %d during this analysis",
- nRef, *sqlite3pager_stats(pBt->pPager)
+ nRef, sqlite3pager_refcount(pBt->pPager)
);
}
/* Clean up and report errors.
*/
sqliteFree(sCheck.anRef);
+ *pnErr = sCheck.nErr;
return sCheck.zErrMsg;
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
@@ -6522,7 +6448,6 @@ int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
rc = sqlite3pager_get(pBtFrom->pPager, i, &pPage);
if( rc ) break;
rc = sqlite3pager_overwrite(pBtTo->pPager, i, pPage);
- if( rc ) break;
sqlite3pager_unref(pPage);
}
for(i=nPage+1; rc==SQLITE_OK && i<=nToPage; i++){
@@ -6558,6 +6483,13 @@ int sqlite3BtreeIsInStmt(Btree *p){
return (p->pBt && p->pBt->inStmt);
}
+/*
+** Return non-zero if a read (or write) transaction is active.
+*/
+int sqlite3BtreeIsInReadTrans(Btree *p){
+ return (p && (p->inTrans!=TRANS_NONE));
+}
+
/*
** This call is a no-op if no write-transaction is currently active on pBt.
**
diff --git a/dlls/sqlite/sqlite-source/btree.h b/dlls/sqlite/sqlite-source/btree.h
index 4faf23ef..2f573e27 100644
--- a/dlls/sqlite/sqlite-source/btree.h
+++ b/dlls/sqlite/sqlite-source/btree.h
@@ -75,6 +75,7 @@ int sqlite3BtreeRollbackStmt(Btree*);
int sqlite3BtreeCreateTable(Btree*, int*, int flags);
int sqlite3BtreeIsInTrans(Btree*);
int sqlite3BtreeIsInStmt(Btree*);
+int sqlite3BtreeIsInReadTrans(Btree*);
int sqlite3BtreeSync(Btree*, const char *zMaster);
void *sqlite3BtreeSchema(Btree *, int, void(*)(void *));
int sqlite3BtreeSchemaLocked(Btree *);
@@ -130,7 +131,7 @@ const void *sqlite3BtreeDataFetch(BtCursor*, int *pAmt);
int sqlite3BtreeDataSize(BtCursor*, u32 *pSize);
int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*);
-char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot);
+char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
struct Pager *sqlite3BtreePager(Btree*);
diff --git a/dlls/sqlite/sqlite-source/build.c b/dlls/sqlite/sqlite-source/build.c
index 1fc80eeb..b2da7fb5 100644
--- a/dlls/sqlite/sqlite-source/build.c
+++ b/dlls/sqlite/sqlite-source/build.c
@@ -164,6 +164,12 @@ void sqlite3FinishCoding(Parse *pParse){
sqlite3VdbeAddOp(v, OP_Transaction, iDb, (mask & pParse->writeMask)!=0);
sqlite3VdbeAddOp(v, OP_VerifyCookie, iDb, pParse->cookieValue[iDb]);
}
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( pParse->pVirtualLock ){
+ char *vtab = (char *)pParse->pVirtualLock->pVtab;
+ sqlite3VdbeOp3(v, OP_VBegin, 0, 0, vtab, P3_VTAB);
+ }
+#endif
/* Once all the cookies have been verified and transactions opened,
** obtain the required table-locks. This is a no-op unless the
@@ -533,6 +539,7 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
#ifndef SQLITE_OMIT_CHECK
sqlite3ExprDelete(pTable->pCheck);
#endif
+ sqlite3VtabClear(pTable);
sqliteFree(pTable);
}
@@ -710,6 +717,7 @@ void sqlite3StartTable(
Token *pName2, /* Second part of the name of the table or view */
int isTemp, /* True if this is a TEMP table */
int isView, /* True if this is a VIEW */
+ int isVirtual, /* True if this is a VIRTUAL table */
int noErr /* Do nothing if table already exists */
){
Table *pTable;
@@ -773,7 +781,7 @@ void sqlite3StartTable(
code = SQLITE_CREATE_TABLE;
}
}
- if( sqlite3AuthCheck(pParse, code, zName, 0, zDb) ){
+ if( !isVirtual && sqlite3AuthCheck(pParse, code, zName, 0, zDb) ){
goto begin_table_error;
}
}
@@ -781,22 +789,28 @@ void sqlite3StartTable(
/* Make sure the new table name does not collide with an existing
** index or table name in the same database. Issue an error message if
- ** it does.
+ ** it does. The exception is if the statement being parsed was passed
+ ** to an sqlite3_declare_vtab() call. In that case only the column names
+ ** and types will be used, so there is no need to test for namespace
+ ** collisions.
*/
- if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
- goto begin_table_error;
- }
- pTable = sqlite3FindTable(db, zName, db->aDb[iDb].zName);
- if( pTable ){
- if( !noErr ){
- sqlite3ErrorMsg(pParse, "table %T already exists", pName);
+ if( !IN_DECLARE_VTAB ){
+ if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
+ goto begin_table_error;
+ }
+ pTable = sqlite3FindTable(db, zName, db->aDb[iDb].zName);
+ if( pTable ){
+ if( !noErr ){
+ sqlite3ErrorMsg(pParse, "table %T already exists", pName);
+ }
+ goto begin_table_error;
+ }
+ if( sqlite3FindIndex(db, zName, 0)!=0 && (iDb==0 || !db->init.busy) ){
+ sqlite3ErrorMsg(pParse, "there is already an index named %s", zName);
+ goto begin_table_error;
}
- goto begin_table_error;
- }
- if( sqlite3FindIndex(db, zName, 0)!=0 && (iDb==0 || !db->init.busy) ){
- sqlite3ErrorMsg(pParse, "there is already an index named %s", zName);
- goto begin_table_error;
}
+
pTable = sqliteMalloc( sizeof(Table) );
if( pTable==0 ){
pParse->rc = SQLITE_NOMEM;
@@ -804,10 +818,7 @@ void sqlite3StartTable(
goto begin_table_error;
}
pTable->zName = zName;
- pTable->nCol = 0;
- pTable->aCol = 0;
pTable->iPKey = -1;
- pTable->pIndex = 0;
pTable->pSchema = db->aDb[iDb].pSchema;
pTable->nRef = 1;
if( pParse->pNewTable ) sqlite3DeleteTable(db, pParse->pNewTable);
@@ -836,6 +847,12 @@ void sqlite3StartTable(
int fileFormat;
sqlite3BeginWriteOperation(pParse, 0, iDb);
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( isVirtual ){
+ sqlite3VdbeAddOp(v, OP_VBegin, 0, 0);
+ }
+#endif
+
/* If the file format and encoding in the database have not been set,
** set them now.
*/
@@ -843,7 +860,7 @@ void sqlite3StartTable(
lbl = sqlite3VdbeMakeLabel(v);
sqlite3VdbeAddOp(v, OP_If, 0, lbl);
fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ?
- 1 : SQLITE_DEFAULT_FILE_FORMAT;
+ 1 : SQLITE_MAX_FILE_FORMAT;
sqlite3VdbeAddOp(v, OP_Integer, fileFormat, 0);
sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1);
sqlite3VdbeAddOp(v, OP_Integer, ENC(db), 0);
@@ -858,8 +875,8 @@ void sqlite3StartTable(
** The rowid value is needed by the code that sqlite3EndTable will
** generate.
*/
-#ifndef SQLITE_OMIT_VIEW
- if( isView ){
+#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
+ if( isView || isVirtual ){
sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
}else
#endif
@@ -1060,8 +1077,12 @@ void sqlite3AddDefaultValue(Parse *pParse, Expr *pExpr){
sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
pCol->zName);
}else{
+ Expr *pCopy;
sqlite3ExprDelete(pCol->pDflt);
- pCol->pDflt = sqlite3ExprDup(pExpr);
+ pCol->pDflt = pCopy = sqlite3ExprDup(pExpr);
+ if( pCopy ){
+ sqlite3TokenCopy(&pCopy->span, &pExpr->span);
+ }
}
}
sqlite3ExprDelete(pExpr);
@@ -1095,7 +1116,7 @@ void sqlite3AddPrimaryKey(
Table *pTab = pParse->pNewTable;
char *zType = 0;
int iCol = -1, i;
- if( pTab==0 ) goto primary_key_exit;
+ if( pTab==0 || IN_DECLARE_VTAB ) goto primary_key_exit;
if( pTab->hasPrimKey ){
sqlite3ErrorMsg(pParse,
"table \"%s\" has more than one primary key", pTab->zName);
@@ -1150,7 +1171,7 @@ void sqlite3AddCheckConstraint(
){
#ifndef SQLITE_OMIT_CHECK
Table *pTab = pParse->pNewTable;
- if( pTab ){
+ if( pTab && !IN_DECLARE_VTAB ){
/* The CHECK expression must be duplicated so that tokens refer
** to malloced space and not the (ephemeral) text of the CREATE TABLE
** statement */
@@ -1201,6 +1222,10 @@ void sqlite3AddCollateType(Parse *pParse, const char *zType, int nType){
** If no versions of the requested collations sequence are available, or
** another error occurs, NULL is returned and an error message written into
** pParse.
+**
+** This routine is a wrapper around sqlite3FindCollSeq(). This routine
+** invokes the collation factory if the named collation cannot be found
+** and generates an error message.
*/
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName){
sqlite3 *db = pParse->db;
@@ -1372,7 +1397,7 @@ void sqlite3EndTable(
assert( !db->init.busy || !pSelect );
- iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
+ iDb = sqlite3SchemaToIndex(db, p->pSchema);
#ifndef SQLITE_OMIT_CHECK
/* Resolve names in all CHECK constraint expressions.
@@ -1569,7 +1594,8 @@ void sqlite3CreateView(
Token *pName1, /* The token that holds the name of the view */
Token *pName2, /* The token that holds the name of the view */
Select *pSelect, /* A SELECT statement that will become the new view */
- int isTemp /* TRUE for a TEMPORARY view */
+ int isTemp, /* TRUE for a TEMPORARY view */
+ int noErr /* Suppress error messages if VIEW already exists */
){
Table *p;
int n;
@@ -1584,7 +1610,7 @@ void sqlite3CreateView(
sqlite3SelectDelete(pSelect);
return;
}
- sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0);
+ sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr);
p = pParse->pNewTable;
if( p==0 || pParse->nErr ){
sqlite3SelectDelete(pSelect);
@@ -1633,7 +1659,7 @@ void sqlite3CreateView(
}
#endif /* SQLITE_OMIT_VIEW */
-#ifndef SQLITE_OMIT_VIEW
+#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
/*
** The Table structure pTable is really a VIEW. Fill in the names of
** the columns of the view in the pTable structure. Return the number
@@ -1647,6 +1673,14 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
assert( pTable );
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( sqlite3VtabCallConnect(pParse, pTable) ){
+ return SQLITE_ERROR;
+ }
+ if( IsVirtual(pTable) ) return 0;
+#endif
+
+#ifndef SQLITE_OMIT_VIEW
/* A positive nCol means the columns names for this view are
** already known.
*/
@@ -1699,9 +1733,10 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
} else {
nErr++;
}
+#endif /* SQLITE_OMIT_VIEW */
return nErr;
}
-#endif /* SQLITE_OMIT_VIEW */
+#endif /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */
#ifndef SQLITE_OMIT_VIEW
/*
@@ -1873,6 +1908,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
int code;
const char *zTab = SCHEMA_TABLE(iDb);
const char *zDb = db->aDb[iDb].zName;
+ const char *zArg2 = 0;
if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){
goto exit_drop_table;
}
@@ -1882,6 +1918,14 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
}else{
code = SQLITE_DROP_VIEW;
}
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ }else if( IsVirtual(pTab) ){
+ if( sqlite3ViewGetColumnNames(pParse, pTab) ){
+ goto exit_drop_table;
+ }
+ code = SQLITE_DROP_VTABLE;
+ zArg2 = pTab->pMod->zName;
+#endif
}else{
if( !OMIT_TEMPDB && iDb==1 ){
code = SQLITE_DROP_TEMP_TABLE;
@@ -1889,7 +1933,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
code = SQLITE_DROP_TABLE;
}
}
- if( sqlite3AuthCheck(pParse, code, pTab->zName, 0, zDb) ){
+ if( sqlite3AuthCheck(pParse, code, pTab->zName, zArg2, zDb) ){
goto exit_drop_table;
}
if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
@@ -1925,6 +1969,15 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
Db *pDb = &db->aDb[iDb];
sqlite3BeginWriteOperation(pParse, 0, iDb);
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( IsVirtual(pTab) ){
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ if( v ){
+ sqlite3VdbeAddOp(v, OP_VBegin, 0, 0);
+ }
+ }
+#endif
+
/* Drop all triggers associated with the table being dropped. Code
** is generated to remove entries from sqlite_master and/or
** sqlite_temp_master if required.
@@ -1961,13 +2014,16 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
sqlite3NestedParse(pParse,
"DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
pDb->zName, SCHEMA_TABLE(iDb), pTab->zName);
- if( !isView ){
+ if( !isView && !IsVirtual(pTab) ){
destroyTable(pParse, pTab);
}
/* Remove the table entry from SQLite's internal schema and modify
** the schema cookie.
*/
+ if( IsVirtual(pTab) ){
+ sqlite3VdbeOp3(v, OP_VDestroy, iDb, 0, pTab->zName, 0);
+ }
sqlite3VdbeOp3(v, OP_DropTable, iDb, 0, pTab->zName, 0);
sqlite3ChangeCookie(db, v, iDb);
}
@@ -2011,7 +2067,7 @@ void sqlite3CreateForeignKey(
char *z;
assert( pTo!=0 );
- if( p==0 || pParse->nErr ) goto fk_end;
+ if( p==0 || pParse->nErr || IN_DECLARE_VTAB ) goto fk_end;
if( pFromCol==0 ){
int iCol = p->nCol-1;
if( iCol<0 ) goto fk_end;
@@ -2215,7 +2271,7 @@ void sqlite3CreateIndex(
int nExtra = 0;
char *zExtra;
- if( pParse->nErr || sqlite3MallocFailed() ){
+ if( pParse->nErr || sqlite3MallocFailed() || IN_DECLARE_VTAB ){
goto exit_create_index;
}
@@ -2272,6 +2328,12 @@ void sqlite3CreateIndex(
goto exit_create_index;
}
#endif
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( IsVirtual(pTab) ){
+ sqlite3ErrorMsg(pParse, "virtual tables may not be indexed");
+ goto exit_create_index;
+ }
+#endif
/*
** Find the name of the index. Make sure there is not already another
@@ -2399,7 +2461,7 @@ void sqlite3CreateIndex(
const char *zColName = pListItem->zName;
Column *pTabCol;
int requestedSortOrder;
- char *zColl; /* Collation sequence */
+ char *zColl; /* Collation sequence name */
for(j=0, pTabCol=pTab->aCol; jnCol; j++, pTabCol++){
if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break;
@@ -2409,6 +2471,12 @@ void sqlite3CreateIndex(
pTab->zName, zColName);
goto exit_create_index;
}
+ /* TODO: Add a test to make sure that the same column is not named
+ ** more than once within the same index. Only the first instance of
+ ** the column will ever be used by the optimizer. Note that using the
+ ** same column more than once cannot be an error because that would
+ ** break backwards compatibility - it needs to be a warning.
+ */
pIndex->aiColumn[i] = j;
if( pListItem->pExpr ){
assert( pListItem->pExpr->pColl );
@@ -2638,8 +2706,12 @@ void sqlite3DefaultRowEst(Index *pIdx){
int i;
assert( a!=0 );
a[0] = 1000000;
- for(i=pIdx->nColumn; i>=1; i--){
- a[i] = 10;
+ for(i=pIdx->nColumn; i>=5; i--){
+ a[i] = 5;
+ }
+ while( i>=1 ){
+ a[i] = 11 - i;
+ i--;
}
if( pIdx->onError!=OE_None ){
a[pIdx->nColumn] = 1;
@@ -2878,15 +2950,6 @@ void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
}
}
-/*
-** Add an alias to the last identifier on the given identifier list.
-*/
-void sqlite3SrcListAddAlias(SrcList *pList, Token *pToken){
- if( pList && pList->nSrc>0 ){
- pList->a[pList->nSrc-1].zAlias = sqlite3NameFromToken(pToken);
- }
-}
-
/*
** Delete an entire SrcList including all its substructure.
*/
@@ -2906,6 +2969,74 @@ void sqlite3SrcListDelete(SrcList *pList){
sqliteFree(pList);
}
+/*
+** This routine is called by the parser to add a new term to the
+** end of a growing FROM clause. The "p" parameter is the part of
+** the FROM clause that has already been constructed. "p" is NULL
+** if this is the first term of the FROM clause. pTable and pDatabase
+** are the name of the table and database named in the FROM clause term.
+** pDatabase is NULL if the database name qualifier is missing - the
+** usual case. If the term has a alias, then pAlias points to the
+** alias token. If the term is a subquery, then pSubquery is the
+** SELECT statement that the subquery encodes. The pTable and
+** pDatabase parameters are NULL for subqueries. The pOn and pUsing
+** parameters are the content of the ON and USING clauses.
+**
+** Return a new SrcList which encodes is the FROM with the new
+** term added.
+*/
+SrcList *sqlite3SrcListAppendFromTerm(
+ SrcList *p, /* The left part of the FROM clause already seen */
+ Token *pTable, /* Name of the table to add to the FROM clause */
+ Token *pDatabase, /* Name of the database containing pTable */
+ Token *pAlias, /* The right-hand side of the AS subexpression */
+ Select *pSubquery, /* A subquery used in place of a table name */
+ Expr *pOn, /* The ON clause of a join */
+ IdList *pUsing /* The USING clause of a join */
+){
+ struct SrcList_item *pItem;
+ p = sqlite3SrcListAppend(p, pTable, pDatabase);
+ if( p==0 || p->nSrc==0 ){
+ sqlite3ExprDelete(pOn);
+ sqlite3IdListDelete(pUsing);
+ sqlite3SelectDelete(pSubquery);
+ return p;
+ }
+ pItem = &p->a[p->nSrc-1];
+ if( pAlias && pAlias->n ){
+ pItem->zAlias = sqlite3NameFromToken(pAlias);
+ }
+ pItem->pSelect = pSubquery;
+ pItem->pOn = pOn;
+ pItem->pUsing = pUsing;
+ return p;
+}
+
+/*
+** When building up a FROM clause in the parser, the join operator
+** is initially attached to the left operand. But the code generator
+** expects the join operator to be on the right operand. This routine
+** Shifts all join operators from left to right for an entire FROM
+** clause.
+**
+** Example: Suppose the join is like this:
+**
+** A natural cross join B
+**
+** The operator is "natural cross join". The A and B operands are stored
+** in p->a[0] and p->a[1], respectively. The parser initially stores the
+** operator with A. This routine shifts that operator over to B.
+*/
+void sqlite3SrcListShiftJoinType(SrcList *p){
+ if( p && p->a ){
+ int i;
+ for(i=p->nSrc-1; i>0; i--){
+ p->a[i].jointype = p->a[i-1].jointype;
+ }
+ p->a[0].jointype = 0;
+ }
+}
+
/*
** Begin a transaction
*/
diff --git a/dlls/sqlite/sqlite-source/callback.c b/dlls/sqlite/sqlite-source/callback.c
index c59df06a..788b6221 100644
--- a/dlls/sqlite/sqlite-source/callback.c
+++ b/dlls/sqlite/sqlite-source/callback.c
@@ -195,6 +195,11 @@ static CollSeq *findCollSeqEntry(
**
** If the entry specified is not found and 'create' is true, then create a
** new entry. Otherwise return NULL.
+**
+** A separate function sqlite3LocateCollSeq() is a wrapper around
+** this routine. sqlite3LocateCollSeq() invokes the collation factory
+** if necessary and generates an error message if the collating sequence
+** cannot be found.
*/
CollSeq *sqlite3FindCollSeq(
sqlite3 *db,
@@ -362,6 +367,7 @@ Schema *sqlite3SchemaGet(Btree *pBt){
sqlite3HashInit(&p->idxHash, SQLITE_HASH_STRING, 0);
sqlite3HashInit(&p->trigHash, SQLITE_HASH_STRING, 0);
sqlite3HashInit(&p->aFKey, SQLITE_HASH_STRING, 1);
+ p->enc = SQLITE_UTF8;
}
return p;
}
diff --git a/dlls/sqlite/sqlite-source/date.c b/dlls/sqlite/sqlite-source/date.c
index da7c7d70..5298aab9 100644
--- a/dlls/sqlite/sqlite-source/date.c
+++ b/dlls/sqlite/sqlite-source/date.c
@@ -23,7 +23,7 @@
** SQLite processes all times and dates as Julian Day numbers. The
** dates and times are stored as the number of days since noon
** in Greenwich on November 24, 4714 B.C. according to the Gregorian
-** calendar system.
+** calendar system.
**
** 1970-01-01 00:00:00 is JD 2440587.5
** 2000-01-01 00:00:00 is JD 2451544.5
@@ -231,14 +231,14 @@ static void computeJD(DateTime *p){
A = Y/100;
B = 2 - A + (A/4);
X1 = (int)(365.25*(Y+4716));
- X2 = (int)30.6001*(M+1);
+ X2 = (int)(30.6001*(M+1));
p->rJD = X1 + X2 + D + B - 1524.5;
p->validJD = 1;
- p->validYMD = 0;
if( p->validHMS ){
p->rJD += (p->h*3600.0 + p->m*60.0 + p->s)/86400.0;
if( p->validTZ ){
p->rJD -= p->tz*60/86400.0;
+ p->validYMD = 0;
p->validHMS = 0;
p->validTZ = 0;
}
@@ -357,10 +357,11 @@ static void computeYMD(DateTime *p){
static void computeHMS(DateTime *p){
int Z, s;
if( p->validHMS ) return;
+ computeJD(p);
Z = (int)(p->rJD + 0.5);
s = (int)((p->rJD + 0.5 - Z)*86400000.0 + 0.5);
p->s = 0.001*s;
- s = (int)(p->s);
+ s = (int)p->s;
p->s -= s;
p->h = s/3600;
s -= p->h*3600;
@@ -393,7 +394,6 @@ static void clearYMD_HMS_TZ(DateTime *p){
static double localtimeOffset(DateTime *p){
DateTime x, y;
time_t t;
- struct tm *pTm;
x = *p;
computeYMD_HMS(&x);
if( x.Y<1971 || x.Y>=2038 ){
@@ -411,15 +411,31 @@ static double localtimeOffset(DateTime *p){
x.validJD = 0;
computeJD(&x);
t = (time_t)((x.rJD-2440587.5)*86400.0 + 0.5);
- sqlite3OsEnterMutex();
- pTm = localtime(&t);
- y.Y = pTm->tm_year + 1900;
- y.M = pTm->tm_mon + 1;
- y.D = pTm->tm_mday;
- y.h = pTm->tm_hour;
- y.m = pTm->tm_min;
- y.s = pTm->tm_sec;
- sqlite3OsLeaveMutex();
+#ifdef HAVE_LOCALTIME_R
+ {
+ struct tm sLocal;
+ localtime_r(&t, &sLocal);
+ y.Y = sLocal.tm_year + 1900;
+ y.M = sLocal.tm_mon + 1;
+ y.D = sLocal.tm_mday;
+ y.h = sLocal.tm_hour;
+ y.m = sLocal.tm_min;
+ y.s = sLocal.tm_sec;
+ }
+#else
+ {
+ struct tm *pTm;
+ sqlite3OsEnterMutex();
+ pTm = localtime(&t);
+ y.Y = pTm->tm_year + 1900;
+ y.M = pTm->tm_mon + 1;
+ y.D = pTm->tm_mday;
+ y.h = pTm->tm_hour;
+ y.m = pTm->tm_min;
+ y.s = pTm->tm_sec;
+ sqlite3OsLeaveMutex();
+ }
+#endif
y.validYMD = 1;
y.validHMS = 1;
y.validJD = 0;
@@ -581,7 +597,7 @@ static int parseModifier(const char *zMod, DateTime *p){
if( z[0]=='-' ) tx.rJD = -tx.rJD;
computeJD(p);
clearYMD_HMS_TZ(p);
- p->rJD += tx.rJD;
+ p->rJD += tx.rJD;
rc = 0;
break;
}
@@ -809,9 +825,9 @@ static void strftimeFunc(
switch( zFmt[i] ){
case 'd': sprintf(&z[j],"%02d",x.D); j+=2; break;
case 'f': {
- int s = (int)x.s;
- int ms = (int)((x.s - s)*1000.0);
- sprintf(&z[j],"%02d.%03d",s,ms);
+ double s = x.s;
+ if( s>59.999 ) s = 59.999;
+ sqlite3_snprintf(7, &z[j],"%02.3f", s);
j += strlen(&z[j]);
break;
}
@@ -824,7 +840,7 @@ static void strftimeFunc(
y.M = 1;
y.D = 1;
computeJD(&y);
- nDay = (int)(x.rJD - y.rJD);
+ nDay = (int)(x.rJD - y.rJD + 0.5);
if( zFmt[i]=='W' ){
int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */
wd = ((int)(x.rJD+0.5)) % 7;
@@ -844,7 +860,7 @@ static void strftimeFunc(
j += strlen(&z[j]);
break;
}
- case 'S': sprintf(&z[j],"%02d",(int)(x.s+0.5)); j+=2; break;
+ case 'S': sprintf(&z[j],"%02d",(int)x.s); j+=2; break;
case 'w': z[j++] = (((int)(x.rJD+1.5)) % 7) + '0'; break;
case 'Y': sprintf(&z[j],"%04d",x.Y); j+=strlen(&z[j]); break;
case '%': z[j++] = '%'; break;
@@ -944,9 +960,21 @@ static void currentTimeFunc(
}
#endif
- sqlite3OsEnterMutex();
- strftime(zBuf, 20, zFormat, gmtime(&t));
- sqlite3OsLeaveMutex();
+#ifdef HAVE_GMTIME_R
+ {
+ struct tm sNow;
+ gmtime_r(&t, &sNow);
+ strftime(zBuf, 20, zFormat, &sNow);
+ }
+#else
+ {
+ struct tm *pTm;
+ sqlite3OsEnterMutex();
+ pTm = gmtime(&t);
+ strftime(zBuf, 20, zFormat, pTm);
+ sqlite3OsLeaveMutex();
+ }
+#endif
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
}
diff --git a/dlls/sqlite/sqlite-source/delete.c b/dlls/sqlite/sqlite-source/delete.c
index 275c52ae..ea9e99b8 100644
--- a/dlls/sqlite/sqlite-source/delete.c
+++ b/dlls/sqlite/sqlite-source/delete.c
@@ -42,8 +42,12 @@ Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
** writable return 0;
*/
int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
- if( pTab->readOnly && (pParse->db->flags & SQLITE_WriteSchema)==0
- && pParse->nested==0 ){
+ if( (pTab->readOnly && (pParse->db->flags & SQLITE_WriteSchema)==0
+ && pParse->nested==0)
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ || (pTab->pMod && pTab->pMod->pModule->xUpdate==0)
+#endif
+ ){
sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName);
return 1;
}
@@ -66,7 +70,9 @@ void sqlite3OpenTable(
Table *pTab, /* The table to be opened */
int opcode /* OP_OpenRead or OP_OpenWrite */
){
- Vdbe *v = sqlite3GetVdbe(p);
+ Vdbe *v;
+ if( IsVirtual(pTab) ) return;
+ v = sqlite3GetVdbe(p);
assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite), pTab->zName);
sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
@@ -100,7 +106,8 @@ void sqlite3DeleteFrom(
AuthContext sContext; /* Authorization context */
int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */
NameContext sNC; /* Name context to resolve expressions in */
- int iDb;
+ int iDb; /* Database number */
+ int memCnt = 0; /* Memory cell used for change counting */
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* True if attempting to delete from a view */
@@ -149,7 +156,7 @@ void sqlite3DeleteFrom(
/* If pTab is really a view, make sure it has been initialized.
*/
- if( isView && sqlite3ViewGetColumnNames(pParse, pTab) ){
+ if( sqlite3ViewGetColumnNames(pParse, pTab) ){
goto delete_from_cleanup;
}
@@ -190,7 +197,7 @@ void sqlite3DeleteFrom(
*/
if( isView ){
Select *pView = sqlite3SelectDup(pTab->pSelect);
- sqlite3Select(pParse, pView, SRT_VirtualTab, iCur, 0, 0, 0, 0);
+ sqlite3Select(pParse, pView, SRT_EphemTab, iCur, 0, 0, 0, 0);
sqlite3SelectDelete(pView);
}
@@ -198,14 +205,15 @@ void sqlite3DeleteFrom(
** we are counting rows.
*/
if( db->flags & SQLITE_CountRows ){
- sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
+ memCnt = pParse->nMem++;
+ sqlite3VdbeAddOp(v, OP_MemInt, 0, memCnt);
}
/* Special case: A DELETE without a WHERE clause deletes everything.
** It is easier just to erase the whole table. Note, however, that
** this means that the row change count will be incorrect.
*/
- if( pWhere==0 && !triggers_exist ){
+ if( pWhere==0 && !triggers_exist && !IsVirtual(pTab) ){
if( db->flags & SQLITE_CountRows ){
/* If counting rows deleted, just count the total number of
** entries in the table. */
@@ -215,7 +223,7 @@ void sqlite3DeleteFrom(
sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
}
sqlite3VdbeAddOp(v, OP_Rewind, iCur, sqlite3VdbeCurrentAddr(v)+2);
- addr2 = sqlite3VdbeAddOp(v, OP_AddImm, 1, 0);
+ addr2 = sqlite3VdbeAddOp(v, OP_MemIncr, 1, memCnt);
sqlite3VdbeAddOp(v, OP_Next, iCur, addr2);
sqlite3VdbeResolveLabel(v, endOfLoop);
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
@@ -230,8 +238,7 @@ void sqlite3DeleteFrom(
sqlite3VdbeAddOp(v, OP_Clear, pIdx->tnum, iDb);
}
}
- }
-
+ }
/* The usual case: There is a WHERE clause so we have to scan through
** the table and pick which records to delete.
*/
@@ -243,10 +250,10 @@ void sqlite3DeleteFrom(
/* Remember the rowid of every item to be deleted.
*/
- sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
+ sqlite3VdbeAddOp(v, IsVirtual(pTab) ? OP_VRowid : OP_Rowid, iCur, 0);
sqlite3VdbeAddOp(v, OP_FifoWrite, 0, 0);
if( db->flags & SQLITE_CountRows ){
- sqlite3VdbeAddOp(v, OP_AddImm, 1, 0);
+ sqlite3VdbeAddOp(v, OP_MemIncr, 1, memCnt);
}
/* End the database scan loop.
@@ -304,7 +311,15 @@ void sqlite3DeleteFrom(
}
/* Delete the row */
- sqlite3GenerateRowDelete(db, v, pTab, iCur, pParse->nested==0);
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( IsVirtual(pTab) ){
+ pParse->pVirtualLock = pTab;
+ sqlite3VdbeOp3(v, OP_VUpdate, 0, 1, (const char*)pTab->pVtab, P3_VTAB);
+ }else
+#endif
+ {
+ sqlite3GenerateRowDelete(db, v, pTab, iCur, pParse->nested==0);
+ }
}
/* If there are row triggers, close all cursors then invoke
@@ -327,7 +342,7 @@ void sqlite3DeleteFrom(
sqlite3VdbeResolveLabel(v, end);
/* Close the cursors after the loop if there are no row triggers */
- if( !triggers_exist ){
+ if( !triggers_exist && !IsVirtual(pTab) ){
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
}
@@ -341,6 +356,7 @@ void sqlite3DeleteFrom(
** invoke the callback function.
*/
if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){
+ sqlite3VdbeAddOp(v, OP_MemLoad, memCnt, 0);
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", P3_STATIC);
diff --git a/dlls/sqlite/sqlite-source/expr.c b/dlls/sqlite/sqlite-source/expr.c
index fde7db45..6d21918c 100644
--- a/dlls/sqlite/sqlite-source/expr.c
+++ b/dlls/sqlite/sqlite-source/expr.c
@@ -49,6 +49,24 @@ char sqlite3ExprAffinity(Expr *pExpr){
return pExpr->affinity;
}
+/*
+** Set the collating sequence for expression pExpr to be the collating
+** sequence named by pToken. Return a pointer to the revised expression.
+** The collating sequence is marked as "explicit" using the EP_ExpCollate
+** flag. An explicit collating sequence will override implicit
+** collating sequences.
+*/
+Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pName){
+ CollSeq *pColl;
+ if( pExpr==0 ) return 0;
+ pColl = sqlite3LocateCollSeq(pParse, (char*)pName->z, pName->n);
+ if( pColl ){
+ pExpr->pColl = pColl;
+ pExpr->flags |= EP_ExpCollate;
+ }
+ return pExpr;
+}
+
/*
** Return the default collation sequence for the expression pExpr. If
** there is no default collation type, return 0.
@@ -158,9 +176,20 @@ static int binaryCompareP1(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){
** type.
*/
static CollSeq* binaryCompareCollSeq(Parse *pParse, Expr *pLeft, Expr *pRight){
- CollSeq *pColl = sqlite3ExprCollSeq(pParse, pLeft);
- if( !pColl ){
- pColl = sqlite3ExprCollSeq(pParse, pRight);
+ CollSeq *pColl;
+ assert( pLeft );
+ assert( pRight );
+ if( pLeft->flags & EP_ExpCollate ){
+ assert( pLeft->pColl );
+ pColl = pLeft->pColl;
+ }else if( pRight->flags & EP_ExpCollate ){
+ assert( pRight->pColl );
+ pColl = pRight->pColl;
+ }else{
+ pColl = sqlite3ExprCollSeq(pParse, pLeft);
+ if( !pColl ){
+ pColl = sqlite3ExprCollSeq(pParse, pRight);
+ }
}
return pColl;
}
@@ -205,8 +234,31 @@ Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, const Token *pToken){
if( pToken ){
assert( pToken->dyn==0 );
pNew->span = pNew->token = *pToken;
- }else if( pLeft && pRight ){
- sqlite3ExprSpan(pNew, &pLeft->span, &pRight->span);
+ }else if( pLeft ){
+ if( pRight ){
+ sqlite3ExprSpan(pNew, &pLeft->span, &pRight->span);
+ if( pRight->flags && EP_ExpCollate ){
+ pNew->flags |= EP_ExpCollate;
+ pNew->pColl = pRight->pColl;
+ }
+ }
+ if( pLeft->flags && EP_ExpCollate ){
+ pNew->flags |= EP_ExpCollate;
+ pNew->pColl = pLeft->pColl;
+ }
+ }
+ return pNew;
+}
+
+/*
+** Works like sqlite3Expr() but frees its pLeft and pRight arguments
+** if it fails due to a malloc problem.
+*/
+Expr *sqlite3ExprOrFree(int op, Expr *pLeft, Expr *pRight, const Token *pToken){
+ Expr *pNew = sqlite3Expr(op, pLeft, pRight, pToken);
+ if( pNew==0 ){
+ sqlite3ExprDelete(pLeft);
+ sqlite3ExprDelete(pRight);
}
return pNew;
}
@@ -547,12 +599,12 @@ Select *sqlite3SelectDup(Select *p){
pNew->iOffset = -1;
pNew->isResolved = p->isResolved;
pNew->isAgg = p->isAgg;
- pNew->usesVirt = 0;
+ pNew->usesEphm = 0;
pNew->disallowOrderBy = 0;
pNew->pRightmost = 0;
- pNew->addrOpenVirt[0] = -1;
- pNew->addrOpenVirt[1] = -1;
- pNew->addrOpenVirt[2] = -1;
+ pNew->addrOpenEphm[0] = -1;
+ pNew->addrOpenEphm[1] = -1;
+ pNew->addrOpenEphm[2] = -1;
return pNew;
}
#else
@@ -877,23 +929,26 @@ static int lookupName(
/* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
pExpr->iColumn = j==pTab->iPKey ? -1 : j;
pExpr->affinity = pTab->aCol[j].affinity;
- pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0);
- if( pItem->jointype & JT_NATURAL ){
- /* If this match occurred in the left table of a natural join,
- ** then skip the right table to avoid a duplicate match */
- pItem++;
- i++;
+ if( (pExpr->flags & EP_ExpCollate)==0 ){
+ pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0);
}
- if( (pUsing = pItem->pUsing)!=0 ){
- /* If this match occurs on a column that is in the USING clause
- ** of a join, skip the search of the right table of the join
- ** to avoid a duplicate match there. */
- int k;
- for(k=0; knId; k++){
- if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ){
- pItem++;
- i++;
- break;
+ if( inSrc-1 ){
+ if( pItem[1].jointype & JT_NATURAL ){
+ /* If this match occurred in the left table of a natural join,
+ ** then skip the right table to avoid a duplicate match */
+ pItem++;
+ i++;
+ }else if( (pUsing = pItem[1].pUsing)!=0 ){
+ /* If this match occurs on a column that is in the USING clause
+ ** of a join, skip the search of the right table of the join
+ ** to avoid a duplicate match there. */
+ int k;
+ for(k=0; knId; k++){
+ if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ){
+ pItem++;
+ i++;
+ break;
+ }
}
}
}
@@ -932,7 +987,9 @@ static int lookupName(
cnt++;
pExpr->iColumn = iCol==pTab->iPKey ? -1 : iCol;
pExpr->affinity = pTab->aCol[iCol].affinity;
- pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0);
+ if( (pExpr->flags & EP_ExpCollate)==0 ){
+ pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0);
+ }
pExpr->pTab = pTab;
break;
}
@@ -1032,7 +1089,7 @@ static int lookupName(
n = sizeof(Bitmask)*8-1;
}
assert( pMatch->iCursor==pExpr->iTable );
- pMatch->colUsed |= 1<colUsed |= ((Bitmask)1)<xFunc==0;
}
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ if( pDef ){
+ auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0);
+ if( auth!=SQLITE_OK ){
+ if( auth==SQLITE_DENY ){
+ sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
+ pDef->zName);
+ pNC->nErr++;
+ }
+ pExpr->op = TK_NULL;
+ return 1;
+ }
+ }
+#endif
if( is_agg && !pNC->allowAgg ){
sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
pNC->nErr++;
@@ -1316,7 +1388,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
case TK_IN: {
char affinity;
KeyInfo keyInfo;
- int addr; /* Address of OP_OpenVirtual instruction */
+ int addr; /* Address of OP_OpenEphemeral instruction */
affinity = sqlite3ExprAffinity(pExpr->pLeft);
@@ -1334,7 +1406,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
** is used.
*/
pExpr->iTable = pParse->nTab++;
- addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, pExpr->iTable, 0);
+ addr = sqlite3VdbeAddOp(v, OP_OpenEphemeral, pExpr->iTable, 0);
memset(&keyInfo, 0, sizeof(keyInfo));
keyInfo.nField = 1;
sqlite3VdbeAddOp(v, OP_SetNumColumns, pExpr->iTable, 1);
@@ -1367,7 +1439,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
struct ExprList_item *pItem;
if( !affinity ){
- affinity = SQLITE_AFF_NUMERIC;
+ affinity = SQLITE_AFF_NONE;
}
keyInfo.aColl[0] = pExpr->pLeft->pColl;
@@ -1489,7 +1561,8 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
}else if( pExpr->iColumn>=0 ){
Table *pTab = pExpr->pTab;
int iCol = pExpr->iColumn;
- sqlite3VdbeAddOp(v, OP_Column, pExpr->iTable, iCol);
+ int op = (pTab && IsVirtual(pTab)) ? OP_VColumn : OP_Column;
+ sqlite3VdbeAddOp(v, op, pExpr->iTable, iCol);
sqlite3ColumnDefault(v, pTab, iCol);
#ifndef SQLITE_OMIT_FLOATING_POINT
if( pTab && pTab->aCol[iCol].affinity==SQLITE_AFF_REAL ){
@@ -1497,7 +1570,9 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
}
#endif
}else{
- sqlite3VdbeAddOp(v, OP_Rowid, pExpr->iTable, 0);
+ Table *pTab = pExpr->pTab;
+ int op = (pTab && IsVirtual(pTab)) ? OP_VRowid : OP_Rowid;
+ sqlite3VdbeAddOp(v, op, pExpr->iTable, 0);
}
break;
}
@@ -1671,6 +1746,25 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0);
assert( pDef!=0 );
nExpr = sqlite3ExprCodeExprList(pParse, pList);
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ /* Possibly overload the function if the first argument is
+ ** a virtual table column.
+ **
+ ** For infix functions (LIKE, GLOB, REGEXP, and MATCH) use the
+ ** second argument, not the first, as the argument to test to
+ ** see if it is a column in a virtual table. This is done because
+ ** the left operand of infix functions (the operand we want to
+ ** control overloading) ends up as the second argument to the
+ ** function. The expression "A glob B" is equivalent to
+ ** "glob(B,A). We want to use the A in "A glob B" to test
+ ** for function overloading. But we use the B term in "glob(B,A)".
+ */
+ if( nExpr>=2 && (pExpr->flags & EP_InfixFunc) ){
+ pDef = sqlite3VtabOverloadFunction(pDef, nExpr, pList->a[1].pExpr);
+ }else if( nExpr>0 ){
+ pDef = sqlite3VtabOverloadFunction(pDef, nExpr, pList->a[0].pExpr);
+ }
+#endif
for(i=0; ia[i].pExpr) ){
constMask |= (1<op ){
+ case TK_AGG_COLUMN:
case TK_COLUMN: {
/* Check to see if the column is in one of the tables in the FROM
** clause of the aggregate query */
diff --git a/dlls/sqlite/sqlite-source/func.c b/dlls/sqlite/sqlite-source/func.c
index 7668c412..eb0ca8b2 100644
--- a/dlls/sqlite/sqlite-source/func.c
+++ b/dlls/sqlite/sqlite-source/func.c
@@ -204,7 +204,8 @@ 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]);
sqlite3_snprintf(sizeof(zBuf),zBuf,"%.*f",n,r);
- sqlite3_result_double(context, atof(zBuf));
+ sqlite3AtoF(zBuf, &r);
+ sqlite3_result_double(context, r);
}
/*
@@ -271,6 +272,25 @@ static void randomFunc(
sqlite3_result_int64(context, r);
}
+/*
+** Implementation of randomblob(N). Return a random blob
+** that is N bytes long.
+*/
+static void randomBlob(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ int n;
+ unsigned char *p;
+ assert( argc==1 );
+ n = sqlite3_value_int(argv[0]);
+ if( n<1 ) n = 1;
+ p = sqlite3_malloc(n);
+ sqlite3Randomness(n, p);
+ sqlite3_result_blob(context, (char*)p, n, sqlite3_free);
+}
+
/*
** Implementation of the last_insert_rowid() SQL function. The return
** value is the same as the sqlite3_last_insert_rowid() API function.
@@ -547,6 +567,12 @@ static void versionFunc(
sqlite3_result_text(context, sqlite3_version, -1, SQLITE_STATIC);
}
+/* Array for converting from half-bytes (nybbles) into ASCII hex
+** digits. */
+static const char hexdigits[] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+};
/*
** EXPERIMENTAL - This is not an official function. The interface may
@@ -572,10 +598,6 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
break;
}
case SQLITE_BLOB: {
- static const char hexdigits[] = {
- '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
- };
char *zText = 0;
int nBlob = sqlite3_value_bytes(argv[0]);
char const *zBlob = sqlite3_value_blob(argv[0]);
@@ -621,11 +643,41 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
}
}
+/*
+** The hex() function. Interpret the argument as a blob. Return
+** a hexadecimal rendering as text.
+*/
+static void hexFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ int i, n;
+ const unsigned char *pBlob;
+ char *zHex, *z;
+ assert( argc==1 );
+ pBlob = sqlite3_value_blob(argv[0]);
+ n = sqlite3_value_bytes(argv[0]);
+ z = zHex = sqlite3_malloc(n*2 + 1);
+ if( zHex==0 ) return;
+ for(i=0; i>4)&0xf];
+ *(z++) = hexdigits[c&0xf];
+ }
+ *z = 0;
+ sqlite3_result_text(context, zHex, n*2, sqlite3_free);
+}
+
#ifdef SQLITE_SOUNDEX
/*
** Compute the soundex encoding of a word.
*/
-static void soundexFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+static void soundexFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
char zResult[8];
const u8 *zIn;
int i, j;
@@ -641,13 +693,20 @@ static void soundexFunc(sqlite3_context *context, int argc, sqlite3_value **argv
};
assert( argc==1 );
zIn = (u8*)sqlite3_value_text(argv[0]);
+ if( zIn==0 ) zIn = (u8*)"";
for(i=0; zIn[i] && !isalpha(zIn[i]); i++){}
if( zIn[i] ){
+ u8 prevcode = iCode[zIn[i]&0x7f];
zResult[0] = toupper(zIn[i]);
for(j=1; j<4 && zIn[i]; i++){
int code = iCode[zIn[i]&0x7f];
if( code>0 ){
- zResult[j++] = code + '0';
+ if( code!=prevcode ){
+ prevcode = code;
+ zResult[j++] = code + '0';
+ }
+ }else{
+ prevcode = 0;
}
}
while( j<4 ){
@@ -661,6 +720,26 @@ static void soundexFunc(sqlite3_context *context, int argc, sqlite3_value **argv
}
#endif
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+/*
+** A function that loads a shared-library extension then returns NULL.
+*/
+static void loadExt(sqlite3_context *context, int argc, sqlite3_value **argv){
+ const char *zFile = (const char *)sqlite3_value_text(argv[0]);
+ const char *zProc = 0;
+ sqlite3 *db = sqlite3_user_data(context);
+ char *zErrMsg = 0;
+
+ if( argc==2 ){
+ zProc = (const char *)sqlite3_value_text(argv[1]);
+ }
+ if( sqlite3_load_extension(db, zFile, zProc, &zErrMsg) ){
+ sqlite3_result_error(context, zErrMsg, -1);
+ sqlite3_free(zErrMsg);
+ }
+}
+#endif
+
#ifdef SQLITE_TEST
/*
** This function generates a string of random characters. Used for
@@ -839,16 +918,8 @@ struct SumCtx {
** that it returns NULL if it sums over no inputs. TOTAL returns
** 0.0 in that case. In addition, TOTAL always returns a float where
** SUM might return an integer if it never encounters a floating point
-** value.
-**
-** I am told that SUM() should raise an exception if it encounters
-** a integer overflow. But after pondering this, I decided that
-** behavior leads to brittle programs. So instead, I have coded
-** SUM() to revert to using floating point if it encounters an
-** integer overflow. The answer may not be exact, but it will be
-** close. If the SUM() function returns an integer, the value is
-** exact. If SUM() returns a floating point value, it means the
-** value might be approximated.
+** value. TOTAL never fails, but SUM might through an exception if
+** it overflows an integer.
*/
static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){
SumCtx *p;
@@ -864,7 +935,7 @@ static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){
if( (p->approx|p->overflow)==0 ){
i64 iNewSum = p->iSum + v;
int s1 = (int)(p->iSum >> (sizeof(i64)*8-1));
- int s2 = (int)(v >> (sizeof(i64)*8-1));
+ int s2 = (int)(v >> (sizeof(i64)*8-1));
int s3 = (int)(iNewSum >> (sizeof(i64)*8-1));
p->overflow = (s1&s2&~s3) | (~s1&~s2&s3);
p->iSum = iNewSum;
@@ -1002,8 +1073,10 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
{ "coalesce", -1, 0, SQLITE_UTF8, 0, ifnullFunc },
{ "coalesce", 0, 0, SQLITE_UTF8, 0, 0 },
{ "coalesce", 1, 0, SQLITE_UTF8, 0, 0 },
+ { "hex", 1, 0, SQLITE_UTF8, 0, hexFunc },
{ "ifnull", 2, 0, SQLITE_UTF8, 1, ifnullFunc },
{ "random", -1, 0, SQLITE_UTF8, 0, randomFunc },
+ { "randomblob", 1, 0, SQLITE_UTF8, 0, randomBlob },
{ "nullif", 2, 0, SQLITE_UTF8, 1, nullifFunc },
{ "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc},
{ "quote", 1, 0, SQLITE_UTF8, 0, quoteFunc },
@@ -1013,6 +1086,10 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
#ifdef SQLITE_SOUNDEX
{ "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc},
#endif
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+ { "load_extension", 1, 1, SQLITE_UTF8, 0, loadExt },
+ { "load_extension", 2, 1, SQLITE_UTF8, 0, loadExt },
+#endif
#ifdef SQLITE_TEST
{ "randstr", 2, 0, SQLITE_UTF8, 0, randStr },
{ "test_destructor", 1, 1, SQLITE_UTF8, 0, test_destructor},
@@ -1078,6 +1155,7 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
}
}
sqlite3RegisterDateTimeFunctions(db);
+ sqlite3_overload_function(db, "MATCH", 2);
#ifdef SQLITE_SSE
(void)sqlite3SseFunctions(db);
#endif
diff --git a/dlls/sqlite/sqlite-source/insert.c b/dlls/sqlite/sqlite-source/insert.c
index c3f1387d..adcc37a4 100644
--- a/dlls/sqlite/sqlite-source/insert.c
+++ b/dlls/sqlite/sqlite-source/insert.c
@@ -272,8 +272,10 @@ void sqlite3Insert(
assert( pTab!=0 );
/* If pTab is really a view, make sure it has been initialized.
+ ** ViewGetColumnNames() is a no-op if pTab is not a view (or virtual
+ ** module table).
*/
- if( isView && sqlite3ViewGetColumnNames(pParse, pTab) ){
+ if( sqlite3ViewGetColumnNames(pParse, pTab) ){
goto insert_cleanup;
}
@@ -371,7 +373,7 @@ void sqlite3Insert(
** back up and execute the SELECT code above.
*/
sqlite3VdbeJumpHere(v, iInitCode);
- sqlite3VdbeAddOp(v, OP_OpenVirtual, srcTab, 0);
+ sqlite3VdbeAddOp(v, OP_OpenEphemeral, srcTab, 0);
sqlite3VdbeAddOp(v, OP_SetNumColumns, srcTab, nColumn);
sqlite3VdbeAddOp(v, OP_Goto, 0, iSelectLoop);
sqlite3VdbeResolveLabel(v, iCleanup);
@@ -385,11 +387,9 @@ void sqlite3Insert(
NameContext sNC;
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
- assert( pList!=0 );
srcTab = -1;
useTempTable = 0;
- assert( pList );
- nColumn = pList->nExpr;
+ nColumn = pList ? pList->nExpr : 0;
for(i=0; ia[i].pExpr) ){
goto insert_cleanup;
@@ -400,7 +400,7 @@ void sqlite3Insert(
/* Make sure the number of columns in the source data matches the number
** of columns to be inserted into the table.
*/
- if( pColumn==0 && nColumn!=pTab->nCol ){
+ if( pColumn==0 && nColumn && nColumn!=pTab->nCol ){
sqlite3ErrorMsg(pParse,
"table %S has %d columns but %d values were supplied",
pTabList, 0, pTab->nCol, nColumn);
@@ -453,7 +453,7 @@ void sqlite3Insert(
** key, the set the keyColumn variable to the primary key column index
** in the original table definition.
*/
- if( pColumn==0 ){
+ if( pColumn==0 && nColumn>0 ){
keyColumn = pTab->iPKey;
}
@@ -567,6 +567,10 @@ void sqlite3Insert(
** case the record number is the same as that column.
*/
if( !isView ){
+ if( IsVirtual(pTab) ){
+ /* The row that the VUpdate opcode will delete: none */
+ sqlite3VdbeAddOp(v, OP_Null, 0, 0);
+ }
if( keyColumn>=0 ){
if( useTempTable ){
sqlite3VdbeAddOp(v, OP_Column, srcTab, keyColumn);
@@ -582,6 +586,8 @@ void sqlite3Insert(
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem);
sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
+ }else if( IsVirtual(pTab) ){
+ sqlite3VdbeAddOp(v, OP_Null, 0, 0);
}else{
sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem);
}
@@ -610,12 +616,12 @@ void sqlite3Insert(
if( pColumn->a[j].idx==i ) break;
}
}
- if( pColumn && j>=pColumn->nId ){
+ if( nColumn==0 || (pColumn && j>=pColumn->nId) ){
sqlite3ExprCode(pParse, pTab->aCol[i].pDflt);
}else if( useTempTable ){
sqlite3VdbeAddOp(v, OP_Column, srcTab, j);
}else if( pSelect ){
- sqlite3VdbeAddOp(v, OP_Dup, i+nColumn-j, 1);
+ sqlite3VdbeAddOp(v, OP_Dup, i+nColumn-j+IsVirtual(pTab), 1);
}else{
sqlite3ExprCode(pParse, pList->a[j].pExpr);
}
@@ -624,10 +630,19 @@ void sqlite3Insert(
/* Generate code to check constraints and generate index keys and
** do the insertion.
*/
- sqlite3GenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0,
- 0, onError, endOfLoop);
- sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0,
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( IsVirtual(pTab) ){
+ pParse->pVirtualLock = pTab;
+ sqlite3VdbeOp3(v, OP_VUpdate, 1, pTab->nCol+2,
+ (const char*)pTab->pVtab, P3_VTAB);
+ }else
+#endif
+ {
+ sqlite3GenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0,
+ 0, onError, endOfLoop);
+ sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0,
(triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1);
+ }
}
/* Update the count of rows that are inserted
@@ -665,7 +680,7 @@ void sqlite3Insert(
sqlite3VdbeResolveLabel(v, iCleanup);
}
- if( !triggers_exist ){
+ if( !triggers_exist && !IsVirtual(pTab) ){
/* Close all tables opened */
sqlite3VdbeAddOp(v, OP_Close, base, 0);
for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
@@ -1105,9 +1120,13 @@ void sqlite3OpenTableAndIndices(
int op /* OP_OpenRead or OP_OpenWrite */
){
int i;
- int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
+ int iDb;
Index *pIdx;
- Vdbe *v = sqlite3GetVdbe(pParse);
+ Vdbe *v;
+
+ if( IsVirtual(pTab) ) return;
+ iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
+ v = sqlite3GetVdbe(pParse);
assert( v!=0 );
sqlite3OpenTable(pParse, base, iDb, pTab, op);
for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
diff --git a/dlls/sqlite/sqlite-source/keywordhash.h b/dlls/sqlite/sqlite-source/keywordhash.h
index 53a4bf19..bc0898f3 100644
--- a/dlls/sqlite/sqlite-source/keywordhash.h
+++ b/dlls/sqlite/sqlite-source/keywordhash.h
@@ -1,6 +1,6 @@
-/* Hash score: 159 */
+/* Hash score: 167 */
static int keywordCode(const char *z, int n){
- static const char zText[537] =
+ static const char zText[544] =
"ABORTABLEFTEMPORARYADDATABASELECTHENDEFAULTRANSACTIONATURALTER"
"AISEACHECKEYAFTEREFERENCESCAPELSEXCEPTRIGGEREGEXPLAINITIALLYANALYZE"
"XCLUSIVEXISTSTATEMENTANDEFERRABLEATTACHAVINGLOBEFOREIGNOREINDEX"
@@ -9,11 +9,11 @@ static int keywordCode(const char *z, int n){
"CURRENT_DATECURRENT_TIMESTAMPLANDESCDETACHDISTINCTDROPRAGMATCH"
"FAILIMITFROMFULLGROUPDATEIFIMMEDIATEINSERTINSTEADINTOFFSETISNULL"
"JOINORDEREPLACEOUTERESTRICTPRIMARYQUERYRIGHTROLLBACKROWHENUNION"
- "UNIQUEUSINGVACUUMVALUESVIEWHERE";
+ "UNIQUEUSINGVACUUMVALUESVIEWHEREVIRTUAL";
static const unsigned char aHash[127] = {
92, 80, 107, 91, 0, 4, 0, 0, 114, 0, 83, 0, 0,
95, 44, 76, 93, 0, 106, 109, 97, 90, 0, 10, 0, 0,
- 113, 0, 110, 103, 0, 28, 48, 0, 41, 0, 0, 65, 71,
+ 113, 0, 117, 103, 0, 28, 48, 0, 41, 0, 0, 65, 71,
0, 63, 19, 0, 105, 36, 104, 0, 108, 74, 0, 0, 33,
0, 61, 37, 0, 8, 0, 115, 38, 12, 0, 77, 40, 25,
66, 0, 0, 31, 81, 53, 30, 50, 20, 88, 0, 34, 0,
@@ -22,7 +22,7 @@ static int keywordCode(const char *z, int n){
54, 6, 85, 0, 0, 49, 94, 0, 102, 0, 70, 0, 0,
15, 0, 116, 51, 56, 0, 2, 55, 0, 111,
};
- static const unsigned char aNext[116] = {
+ static const unsigned char aNext[117] = {
0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0,
0, 11, 0, 0, 0, 0, 5, 13, 0, 7, 0, 0, 0,
@@ -31,9 +31,9 @@ static int keywordCode(const char *z, int n){
0, 0, 0, 0, 0, 0, 0, 0, 73, 42, 0, 24, 60,
21, 0, 79, 0, 0, 68, 0, 0, 84, 46, 0, 0, 0,
0, 0, 0, 0, 0, 39, 96, 98, 0, 0, 100, 0, 32,
- 0, 14, 27, 78, 0, 57, 89, 0, 35, 0, 62, 0,
+ 0, 14, 27, 78, 0, 57, 89, 0, 35, 0, 62, 0, 110,
};
- static const unsigned char aLen[116] = {
+ static const unsigned char aLen[117] = {
5, 5, 4, 4, 9, 2, 3, 8, 2, 6, 4, 3, 7,
11, 2, 7, 5, 5, 4, 5, 3, 5, 10, 6, 4, 6,
7, 6, 7, 9, 3, 7, 9, 6, 9, 3, 10, 6, 6,
@@ -42,9 +42,9 @@ static int keywordCode(const char *z, int n){
6, 6, 8, 10, 9, 6, 5, 12, 12, 17, 4, 4, 6,
8, 2, 4, 6, 5, 4, 5, 4, 4, 5, 6, 2, 9,
6, 7, 4, 2, 6, 3, 6, 4, 5, 7, 5, 8, 7,
- 5, 5, 8, 3, 4, 5, 6, 5, 6, 6, 4, 5,
+ 5, 5, 8, 3, 4, 5, 6, 5, 6, 6, 4, 5, 7,
};
- static const unsigned short int aOffset[116] = {
+ static const unsigned short int aOffset[117] = {
0, 4, 7, 10, 10, 14, 19, 21, 26, 27, 32, 34, 36,
42, 51, 52, 57, 61, 65, 67, 71, 74, 78, 86, 91, 94,
99, 105, 108, 113, 118, 122, 128, 136, 141, 150, 152, 162, 167,
@@ -53,9 +53,9 @@ static int keywordCode(const char *z, int n){
269, 275, 281, 289, 296, 305, 311, 316, 328, 328, 344, 348, 352,
358, 359, 366, 369, 373, 378, 381, 386, 390, 394, 397, 403, 405,
414, 420, 427, 430, 430, 433, 436, 442, 446, 450, 457, 461, 469,
- 476, 481, 486, 494, 496, 500, 505, 511, 516, 522, 528, 531,
+ 476, 481, 486, 494, 496, 500, 505, 511, 516, 522, 528, 531, 536,
};
- static const unsigned char aCode[116] = {
+ static const unsigned char aCode[117] = {
TK_ABORT, TK_TABLE, TK_JOIN_KW, TK_TEMP, TK_TEMP,
TK_OR, TK_ADD, TK_DATABASE, TK_AS, TK_SELECT,
TK_THEN, TK_END, TK_DEFAULT, TK_TRANSACTION,TK_ON,
@@ -79,7 +79,7 @@ static int keywordCode(const char *z, int n){
TK_REPLACE, TK_JOIN_KW, TK_RESTRICT, TK_PRIMARY, TK_QUERY,
TK_JOIN_KW, TK_ROLLBACK, TK_ROW, TK_WHEN, TK_UNION,
TK_UNIQUE, TK_USING, TK_VACUUM, TK_VALUES, TK_VIEW,
- TK_WHERE,
+ TK_WHERE, TK_VIRTUAL,
};
int h, i;
if( n<2 ) return TK_ID;
diff --git a/dlls/sqlite/sqlite-source/legacy.c b/dlls/sqlite/sqlite-source/legacy.c
index 72e354f0..00c0f9ee 100644
--- a/dlls/sqlite/sqlite-source/legacy.c
+++ b/dlls/sqlite/sqlite-source/legacy.c
@@ -123,7 +123,7 @@ exec_out:
rc = sqlite3ApiExit(0, rc);
if( rc!=SQLITE_OK && rc==sqlite3_errcode(db) && pzErrMsg ){
- *pzErrMsg = malloc(1+strlen(sqlite3_errmsg(db)));
+ *pzErrMsg = sqlite3_malloc(1+strlen(sqlite3_errmsg(db)));
if( *pzErrMsg ){
strcpy(*pzErrMsg, sqlite3_errmsg(db));
}
@@ -131,5 +131,6 @@ exec_out:
*pzErrMsg = 0;
}
+ assert( (rc&db->errMask)==rc );
return rc;
}
diff --git a/dlls/sqlite/sqlite-source/loadext.c b/dlls/sqlite/sqlite-source/loadext.c
new file mode 100644
index 00000000..6af99a64
--- /dev/null
+++ b/dlls/sqlite/sqlite-source/loadext.c
@@ -0,0 +1,422 @@
+/*
+** 2006 June 7
+**
+** 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 contains code used to dynamically load extensions into
+** the SQLite library.
+*/
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+
+#define SQLITE_CORE 1 /* Disable the API redefinition in sqlite3ext.h */
+#include "sqlite3ext.h"
+#include "sqliteInt.h"
+#include "os.h"
+#include
+#include
+
+/*
+** Some API routines are omitted when various features are
+** excluded from a build of SQLite. Substitute a NULL pointer
+** for any missing APIs.
+*/
+#ifndef SQLITE_ENABLE_COLUMN_METADATA
+# define sqlite3_column_database_name 0
+# define sqlite3_column_database_name16 0
+# define sqlite3_column_table_name 0
+# define sqlite3_column_table_name16 0
+# define sqlite3_column_origin_name 0
+# define sqlite3_column_origin_name16 0
+# define sqlite3_table_column_metadata 0
+#endif
+
+#ifdef SQLITE_OMIT_AUTHORIZATION
+# define sqlite3_set_authorizer 0
+#endif
+
+#ifdef SQLITE_OMIT_UTF16
+# define sqlite3_bind_text16 0
+# define sqlite3_collation_needed16 0
+# define sqlite3_column_decltype16 0
+# define sqlite3_column_name16 0
+# define sqlite3_column_text16 0
+# define sqlite3_complete16 0
+# define sqlite3_create_collation16 0
+# define sqlite3_create_function16 0
+# define sqlite3_errmsg16 0
+# define sqlite3_open16 0
+# define sqlite3_prepare16 0
+# define sqlite3_result_error16 0
+# define sqlite3_result_text16 0
+# define sqlite3_result_text16be 0
+# define sqlite3_result_text16le 0
+# define sqlite3_value_text16 0
+# define sqlite3_value_text16be 0
+# define sqlite3_value_text16le 0
+#endif
+
+#ifdef SQLITE_OMIT_COMPLETE
+# define sqlite3_complete 0
+# define sqlite3_complete16 0
+#endif
+
+#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
+# define sqlite3_progress_handler 0
+#endif
+
+#ifdef SQLITE_OMIT_VIRTUALTABLE
+# define sqlite3_create_module 0
+# define sqlite3_declare_vtab 0
+#endif
+
+#ifdef SQLITE_OMIT_SHARED_CACHE
+# define sqlite3_enable_shared_cache 0
+#endif
+
+#ifdef SQLITE_OMIT_TRACE
+# define sqlite3_profile 0
+# define sqlite3_trace 0
+#endif
+
+#ifdef SQLITE_OMIT_GET_TABLE
+# define sqlite3_free_table 0
+# define sqlite3_get_table 0
+#endif
+
+/*
+** The following structure contains pointers to all SQLite API routines.
+** A pointer to this structure is passed into extensions when they are
+** loaded so that the extension can make calls back into the SQLite
+** library.
+**
+** When adding new APIs, add them to the bottom of this structure
+** in order to preserve backwards compatibility.
+**
+** Extensions that use newer APIs should first call the
+** sqlite3_libversion_number() to make sure that the API they
+** intend to use is supported by the library. Extensions should
+** also check to make sure that the pointer to the function is
+** not NULL before calling it.
+*/
+const sqlite3_api_routines sqlite3_apis = {
+ sqlite3_aggregate_context,
+ sqlite3_aggregate_count,
+ sqlite3_bind_blob,
+ sqlite3_bind_double,
+ sqlite3_bind_int,
+ sqlite3_bind_int64,
+ sqlite3_bind_null,
+ sqlite3_bind_parameter_count,
+ sqlite3_bind_parameter_index,
+ sqlite3_bind_parameter_name,
+ sqlite3_bind_text,
+ sqlite3_bind_text16,
+ sqlite3_bind_value,
+ sqlite3_busy_handler,
+ sqlite3_busy_timeout,
+ sqlite3_changes,
+ sqlite3_close,
+ sqlite3_collation_needed,
+ sqlite3_collation_needed16,
+ sqlite3_column_blob,
+ sqlite3_column_bytes,
+ sqlite3_column_bytes16,
+ sqlite3_column_count,
+ sqlite3_column_database_name,
+ sqlite3_column_database_name16,
+ sqlite3_column_decltype,
+ sqlite3_column_decltype16,
+ sqlite3_column_double,
+ sqlite3_column_int,
+ sqlite3_column_int64,
+ sqlite3_column_name,
+ sqlite3_column_name16,
+ sqlite3_column_origin_name,
+ sqlite3_column_origin_name16,
+ sqlite3_column_table_name,
+ sqlite3_column_table_name16,
+ sqlite3_column_text,
+ sqlite3_column_text16,
+ sqlite3_column_type,
+ sqlite3_column_value,
+ sqlite3_commit_hook,
+ sqlite3_complete,
+ sqlite3_complete16,
+ sqlite3_create_collation,
+ sqlite3_create_collation16,
+ sqlite3_create_function,
+ sqlite3_create_function16,
+ sqlite3_create_module,
+ sqlite3_data_count,
+ sqlite3_db_handle,
+ sqlite3_declare_vtab,
+ sqlite3_enable_shared_cache,
+ sqlite3_errcode,
+ sqlite3_errmsg,
+ sqlite3_errmsg16,
+ sqlite3_exec,
+ sqlite3_expired,
+ sqlite3_finalize,
+ sqlite3_free,
+ sqlite3_free_table,
+ sqlite3_get_autocommit,
+ sqlite3_get_auxdata,
+ sqlite3_get_table,
+ 0, /* Was sqlite3_global_recover(), but that function is deprecated */
+ sqlite3_interrupt,
+ sqlite3_last_insert_rowid,
+ sqlite3_libversion,
+ sqlite3_libversion_number,
+ sqlite3_malloc,
+ sqlite3_mprintf,
+ sqlite3_open,
+ sqlite3_open16,
+ sqlite3_prepare,
+ sqlite3_prepare16,
+ sqlite3_profile,
+ sqlite3_progress_handler,
+ sqlite3_realloc,
+ sqlite3_reset,
+ sqlite3_result_blob,
+ sqlite3_result_double,
+ sqlite3_result_error,
+ sqlite3_result_error16,
+ sqlite3_result_int,
+ sqlite3_result_int64,
+ sqlite3_result_null,
+ sqlite3_result_text,
+ sqlite3_result_text16,
+ sqlite3_result_text16be,
+ sqlite3_result_text16le,
+ sqlite3_result_value,
+ sqlite3_rollback_hook,
+ sqlite3_set_authorizer,
+ sqlite3_set_auxdata,
+ sqlite3_snprintf,
+ sqlite3_step,
+ sqlite3_table_column_metadata,
+ sqlite3_thread_cleanup,
+ sqlite3_total_changes,
+ sqlite3_trace,
+ sqlite3_transfer_bindings,
+ sqlite3_update_hook,
+ sqlite3_user_data,
+ sqlite3_value_blob,
+ sqlite3_value_bytes,
+ sqlite3_value_bytes16,
+ sqlite3_value_double,
+ sqlite3_value_int,
+ sqlite3_value_int64,
+ sqlite3_value_numeric_type,
+ sqlite3_value_text,
+ sqlite3_value_text16,
+ sqlite3_value_text16be,
+ sqlite3_value_text16le,
+ sqlite3_value_type,
+ sqlite3_vmprintf,
+ /*
+ ** The original API set ends here. All extensions can call any
+ ** of the APIs above provided that the pointer is not NULL. But
+ ** before calling APIs that follow, extension should check the
+ ** sqlite3_libversion_number() to make sure they are dealing with
+ ** a library that is new enough to support that API.
+ *************************************************************************
+ */
+ sqlite3_overload_function,
+};
+
+/*
+** Attempt to load an SQLite extension library contained in the file
+** zFile. The entry point is zProc. zProc may be 0 in which case a
+** default entry point name (sqlite3_extension_init) is used. Use
+** of the default name is recommended.
+**
+** Return SQLITE_OK on success and SQLITE_ERROR if something goes wrong.
+**
+** If an error occurs and pzErrMsg is not 0, then fill *pzErrMsg with
+** error message text. The calling function should free this memory
+** by calling sqlite3_free().
+*/
+int sqlite3_load_extension(
+ sqlite3 *db, /* Load the extension into this database connection */
+ const char *zFile, /* Name of the shared library containing extension */
+ const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */
+ char **pzErrMsg /* Put error message here if not 0 */
+){
+ void *handle;
+ int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*);
+ char *zErrmsg = 0;
+ void **aHandle;
+
+ /* Ticket #1863. To avoid a creating security problems for older
+ ** applications that relink against newer versions of SQLite, the
+ ** ability to run load_extension is turned off by default. One
+ ** must call sqlite3_enable_load_extension() to turn on extension
+ ** loading. Otherwise you get the following error.
+ */
+ if( (db->flags & SQLITE_LoadExtension)==0 ){
+ if( pzErrMsg ){
+ *pzErrMsg = sqlite3_mprintf("not authorized");
+ }
+ return SQLITE_ERROR;
+ }
+
+ if( zProc==0 ){
+ zProc = "sqlite3_extension_init";
+ }
+
+ handle = sqlite3OsDlopen(zFile);
+ if( handle==0 ){
+ if( pzErrMsg ){
+ *pzErrMsg = sqlite3_mprintf("unable to open shared library [%s]", zFile);
+ }
+ return SQLITE_ERROR;
+ }
+ xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*))
+ sqlite3OsDlsym(handle, zProc);
+ if( xInit==0 ){
+ if( pzErrMsg ){
+ *pzErrMsg = sqlite3_mprintf("no entry point [%s] in shared library [%s]",
+ zProc, zFile);
+ }
+ sqlite3OsDlclose(handle);
+ return SQLITE_ERROR;
+ }else if( xInit(db, &zErrmsg, &sqlite3_apis) ){
+ if( pzErrMsg ){
+ *pzErrMsg = sqlite3_mprintf("error during initialization: %s", zErrmsg);
+ }
+ sqlite3_free(zErrmsg);
+ sqlite3OsDlclose(handle);
+ return SQLITE_ERROR;
+ }
+
+ /* Append the new shared library handle to the db->aExtension array. */
+ db->nExtension++;
+ aHandle = sqliteMalloc(sizeof(handle)*db->nExtension);
+ if( aHandle==0 ){
+ return SQLITE_NOMEM;
+ }
+ if( db->nExtension>0 ){
+ memcpy(aHandle, db->aExtension, sizeof(handle)*(db->nExtension-1));
+ }
+ sqliteFree(db->aExtension);
+ db->aExtension = aHandle;
+
+ db->aExtension[db->nExtension-1] = handle;
+ return SQLITE_OK;
+}
+
+/*
+** Call this routine when the database connection is closing in order
+** to clean up loaded extensions
+*/
+void sqlite3CloseExtensions(sqlite3 *db){
+ int i;
+ for(i=0; inExtension; i++){
+ sqlite3OsDlclose(db->aExtension[i]);
+ }
+ sqliteFree(db->aExtension);
+}
+
+/*
+** Enable or disable extension loading. Extension loading is disabled by
+** default so as not to open security holes in older applications.
+*/
+int sqlite3_enable_load_extension(sqlite3 *db, int onoff){
+ if( onoff ){
+ db->flags |= SQLITE_LoadExtension;
+ }else{
+ db->flags &= ~SQLITE_LoadExtension;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** A list of automatically loaded extensions.
+**
+** This list is shared across threads, so be sure to hold the
+** mutex while accessing or changing it.
+*/
+static int nAutoExtension = 0;
+static void **aAutoExtension = 0;
+
+
+/*
+** Register a statically linked extension that is automatically
+** loaded by every new database connection.
+*/
+int sqlite3_auto_extension(void *xInit){
+ int i;
+ int rc = SQLITE_OK;
+ sqlite3OsEnterMutex();
+ for(i=0; i=nAutoExtension ){
+ xInit = 0;
+ go = 0;
+ }else{
+ xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*))
+ aAutoExtension[i];
+ }
+ sqlite3OsLeaveMutex();
+ if( xInit && xInit(db, &zErrmsg, &sqlite3_apis) ){
+ sqlite3Error(db, SQLITE_ERROR,
+ "automatic extension loading failed: %s", zErrmsg);
+ go = 0;
+ rc = SQLITE_ERROR;
+ }
+ }
+ return rc;
+}
+
+#endif /* SQLITE_OMIT_LOAD_EXTENSION */
diff --git a/dlls/sqlite/sqlite-source/main.c b/dlls/sqlite/sqlite-source/main.c
index 4ca733e7..c1f8f9ed 100644
--- a/dlls/sqlite/sqlite-source/main.c
+++ b/dlls/sqlite/sqlite-source/main.c
@@ -116,6 +116,7 @@ int sqlite3_close(sqlite3 *db){
#endif
/* If there are any outstanding VMs, return SQLITE_BUSY. */
+ sqlite3ResetInternalSchema(db, 0);
if( db->pVdbe ){
sqlite3Error(db, SQLITE_BUSY,
"Unable to close due to unfinalised statements");
@@ -133,6 +134,8 @@ int sqlite3_close(sqlite3 *db){
return SQLITE_ERROR;
}
+ sqlite3VtabRollback(db);
+
for(j=0; jnDb; j++){
struct Db *pDb = &db->aDb[j];
if( pDb->pBt ){
@@ -159,12 +162,20 @@ int sqlite3_close(sqlite3 *db){
sqliteFree(pColl);
}
sqlite3HashClear(&db->aCollSeq);
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ for(i=sqliteHashFirst(&db->aModule); i; i=sqliteHashNext(i)){
+ Module *pMod = (Module *)sqliteHashData(i);
+ sqliteFree(pMod);
+ }
+ sqlite3HashClear(&db->aModule);
+#endif
sqlite3HashClear(&db->aFunc);
sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */
if( db->pErr ){
sqlite3ValueFree(db->pErr);
}
+ sqlite3CloseExtensions(db);
db->magic = SQLITE_MAGIC_ERROR;
@@ -195,6 +206,7 @@ void sqlite3RollbackAll(sqlite3 *db){
db->aDb[i].inTrans = 0;
}
}
+ sqlite3VtabRollback(db);
if( db->flags&SQLITE_InternChanges ){
sqlite3ResetInternalSchema(db, 0);
}
@@ -211,7 +223,7 @@ void sqlite3RollbackAll(sqlite3 *db){
*/
const char *sqlite3ErrStr(int rc){
const char *z;
- switch( rc ){
+ switch( rc & 0xff ){
case SQLITE_ROW:
case SQLITE_DONE:
case SQLITE_OK: z = "not an error"; break;
@@ -355,6 +367,9 @@ void sqlite3_progress_handler(
** specified number of milliseconds before returning 0.
*/
int sqlite3_busy_timeout(sqlite3 *db, int ms){
+ if( sqlite3SafetyCheck(db) ){
+ return SQLITE_MISUSE;
+ }
if( ms>0 ){
db->busyTimeout = ms;
sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db);
@@ -368,20 +383,35 @@ int sqlite3_busy_timeout(sqlite3 *db, int ms){
** Cause any pending operation to stop at its earliest opportunity.
*/
void sqlite3_interrupt(sqlite3 *db){
- if( !sqlite3SafetyCheck(db) ){
- db->flags |= SQLITE_Interrupt;
+ if( db && (db->magic==SQLITE_MAGIC_OPEN || db->magic==SQLITE_MAGIC_BUSY) ){
+ db->u1.isInterrupted = 1;
}
}
/*
-** Windows systems should call this routine to free memory that
-** is returned in the in the errmsg parameter of sqlite3_open() when
-** SQLite is a DLL. For some reason, it does not work to call free()
-** directly.
+** Memory allocation routines that use SQLites internal memory
+** memory allocator. Depending on how SQLite is compiled, the
+** internal memory allocator might be just an alias for the
+** system default malloc/realloc/free. Or the built-in allocator
+** might do extra stuff like put sentinals around buffers to
+** check for overruns or look for memory leaks.
**
-** Note that we need to call free() not sqliteFree() here.
+** Use sqlite3_free() to free memory returned by sqlite3_mprintf().
*/
-void sqlite3_free(char *p){ free(p); }
+void sqlite3_free(void *p){ if( p ) sqlite3OsFree(p); }
+void *sqlite3_malloc(int nByte){ return nByte>0 ? sqlite3OsMalloc(nByte) : 0; }
+void *sqlite3_realloc(void *pOld, int nByte){
+ if( pOld ){
+ if( nByte>0 ){
+ return sqlite3OsRealloc(pOld, nByte);
+ }else{
+ sqlite3OsFree(pOld);
+ return 0;
+ }
+ }else{
+ return sqlite3_malloc(nByte);
+ }
+}
/*
** This function is exactly the same as sqlite3_create_function(), except
@@ -411,6 +441,7 @@ int sqlite3CreateFunc(
(!xFunc && (!xFinal && xStep)) ||
(nArg<-1 || nArg>127) ||
(255<(nName = strlen(zFunctionName))) ){
+ sqlite3Error(db, SQLITE_ERROR, "bad parameters");
return SQLITE_ERROR;
}
@@ -462,6 +493,7 @@ int sqlite3CreateFunc(
p->xStep = xStep;
p->xFinalize = xFinal;
p->pUserData = pUserData;
+ p->nArg = nArg;
}
return SQLITE_OK;
}
@@ -509,6 +541,32 @@ int sqlite3_create_function16(
}
#endif
+
+/*
+** Declare that a function has been overloaded by a virtual table.
+**
+** If the function already exists as a regular global function, then
+** this routine is a no-op. If the function does not exist, then create
+** a new one that always throws a run-time error.
+**
+** When virtual tables intend to provide an overloaded function, they
+** should call this routine to make sure the global function exists.
+** A global function must exist in order for name resolution to work
+** properly.
+*/
+int sqlite3_overload_function(
+ sqlite3 *db,
+ const char *zName,
+ int nArg
+){
+ int nName = strlen(zName);
+ if( sqlite3FindFunction(db, zName, nName, nArg, SQLITE_UTF8, 0)==0 ){
+ sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8,
+ 0, sqlite3InvalidFunction, 0, 0);
+ }
+ return sqlite3ApiExit(db, SQLITE_OK);
+}
+
#ifndef SQLITE_OMIT_TRACE
/*
** Register a trace function. The pArg from the previously registered trace
@@ -731,7 +789,7 @@ int sqlite3_errcode(sqlite3 *db){
if( sqlite3SafetyCheck(db) ){
return SQLITE_MISUSE;
}
- return db->errCode;
+ return db->errCode & db->errMask;
}
/*
@@ -809,14 +867,22 @@ static int openDatabase(
/* Allocate the sqlite data structure */
db = sqliteMalloc( sizeof(sqlite3) );
if( db==0 ) goto opendb_out;
+ db->errMask = 0xff;
db->priorNewRowid = 0;
db->magic = SQLITE_MAGIC_BUSY;
db->nDb = 2;
db->aDb = db->aDbStatic;
db->autoCommit = 1;
- db->flags |= SQLITE_ShortColNames;
+ db->flags |= SQLITE_ShortColNames
+#if SQLITE_DEFAULT_FILE_FORMAT<4
+ | SQLITE_LegacyFileFmt
+#endif
+ ;
sqlite3HashInit(&db->aFunc, SQLITE_HASH_STRING, 0);
sqlite3HashInit(&db->aCollSeq, SQLITE_HASH_STRING, 0);
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ sqlite3HashInit(&db->aModule, SQLITE_HASH_STRING, 0);
+#endif
/* Add the default collation sequence BINARY. BINARY works for both UTF-8
** and UTF-16, so add a version for each to avoid any unnecessary
@@ -851,9 +917,6 @@ static int openDatabase(
}
db->aDb[0].pSchema = sqlite3SchemaGet(db->aDb[0].pBt);
db->aDb[1].pSchema = sqlite3SchemaGet(0);
- if( db->aDb[0].pSchema ){
- ENC(db) = SQLITE_UTF8;
- }
/* The default safety_level for the main database is 'full'; for the temp
@@ -871,11 +934,30 @@ static int openDatabase(
** is accessed.
*/
if( !sqlite3MallocFailed() ){
- sqlite3RegisterBuiltinFunctions(db);
sqlite3Error(db, SQLITE_OK, 0);
+ sqlite3RegisterBuiltinFunctions(db);
}
db->magic = SQLITE_MAGIC_OPEN;
+ /* Load automatic extensions - extensions that have been registered
+ ** using the sqlite3_automatic_extension() API.
+ */
+ (void)sqlite3AutoLoadExtensions(db);
+
+#ifdef SQLITE_ENABLE_FTS1
+ {
+ extern int sqlite3Fts1Init(sqlite3*);
+ sqlite3Fts1Init(db);
+ }
+#endif
+
+#ifdef SQLITE_ENABLE_FTS2
+ {
+ extern int sqlite3Fts2Init(sqlite3*);
+ sqlite3Fts2Init(db);
+ }
+#endif
+
opendb_out:
if( SQLITE_NOMEM==(rc = sqlite3_errcode(db)) ){
sqlite3_close(db);
@@ -963,6 +1045,7 @@ int sqlite3_reset(sqlite3_stmt *pStmt){
}else{
rc = sqlite3VdbeReset((Vdbe*)pStmt);
sqlite3VdbeMakeReady((Vdbe*)pStmt, -1, 0, 0, 0);
+ assert( (rc & (sqlite3_db_handle(pStmt)->errMask))==rc );
}
return rc;
}
@@ -1230,3 +1313,30 @@ error_out:
return sqlite3ApiExit(db, rc);
}
#endif
+
+/*
+** Set all the parameters in the compiled SQL statement to NULL.
+*/
+int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
+ int i;
+ int rc = SQLITE_OK;
+ for(i=1; rc==SQLITE_OK && i<=sqlite3_bind_parameter_count(pStmt); i++){
+ rc = sqlite3_bind_null(pStmt, i);
+ }
+ return rc;
+}
+
+/*
+** Sleep for a little while. Return the amount of time slept.
+*/
+int sqlite3_sleep(int ms){
+ return sqlite3OsSleep(ms);
+}
+
+/*
+** Enable or disable the extended result codes.
+*/
+int sqlite3_extended_result_codes(sqlite3 *db, int onoff){
+ db->errMask = onoff ? 0xffffffff : 0xff;
+ return SQLITE_OK;
+}
diff --git a/dlls/sqlite/sqlite-source/opcodes.c b/dlls/sqlite/sqlite-source/opcodes.c
index 9f1bdbaa..4f796476 100644
--- a/dlls/sqlite/sqlite-source/opcodes.c
+++ b/dlls/sqlite/sqlite-source/opcodes.c
@@ -3,145 +3,147 @@
#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
const char *const sqlite3OpcodeNames[] = { "?",
/* 1 */ "MemLoad",
- /* 2 */ "Column",
- /* 3 */ "SetCookie",
- /* 4 */ "IfMemPos",
- /* 5 */ "Sequence",
- /* 6 */ "MoveGt",
- /* 7 */ "RowKey",
- /* 8 */ "OpenWrite",
- /* 9 */ "If",
- /* 10 */ "Pop",
- /* 11 */ "CollSeq",
- /* 12 */ "OpenRead",
- /* 13 */ "Expire",
- /* 14 */ "AutoCommit",
- /* 15 */ "IntegrityCk",
+ /* 2 */ "VNext",
+ /* 3 */ "Column",
+ /* 4 */ "SetCookie",
+ /* 5 */ "IfMemPos",
+ /* 6 */ "Sequence",
+ /* 7 */ "MoveGt",
+ /* 8 */ "RowKey",
+ /* 9 */ "OpenWrite",
+ /* 10 */ "If",
+ /* 11 */ "Pop",
+ /* 12 */ "VRowid",
+ /* 13 */ "CollSeq",
+ /* 14 */ "OpenRead",
+ /* 15 */ "Expire",
/* 16 */ "Not",
- /* 17 */ "Sort",
- /* 18 */ "Function",
- /* 19 */ "Noop",
- /* 20 */ "Return",
- /* 21 */ "NewRowid",
- /* 22 */ "IfMemNeg",
- /* 23 */ "Variable",
- /* 24 */ "String",
- /* 25 */ "RealAffinity",
- /* 26 */ "ParseSchema",
- /* 27 */ "Close",
- /* 28 */ "CreateIndex",
- /* 29 */ "IsUnique",
- /* 30 */ "IdxIsNull",
- /* 31 */ "NotFound",
- /* 32 */ "Int64",
- /* 33 */ "MustBeInt",
- /* 34 */ "Halt",
- /* 35 */ "Rowid",
- /* 36 */ "IdxLT",
- /* 37 */ "AddImm",
- /* 38 */ "Statement",
- /* 39 */ "RowData",
- /* 40 */ "MemMax",
- /* 41 */ "Push",
- /* 42 */ "NotExists",
- /* 43 */ "MemIncr",
- /* 44 */ "Gosub",
- /* 45 */ "Integer",
- /* 46 */ "MemInt",
- /* 47 */ "Prev",
- /* 48 */ "CreateTable",
- /* 49 */ "Last",
- /* 50 */ "IdxRowid",
- /* 51 */ "MakeIdxRec",
- /* 52 */ "ResetCount",
- /* 53 */ "FifoWrite",
- /* 54 */ "Callback",
- /* 55 */ "ContextPush",
- /* 56 */ "DropTrigger",
- /* 57 */ "DropIndex",
- /* 58 */ "IdxGE",
- /* 59 */ "Or",
- /* 60 */ "And",
- /* 61 */ "IdxDelete",
- /* 62 */ "Vacuum",
- /* 63 */ "MoveLe",
- /* 64 */ "IsNull",
- /* 65 */ "NotNull",
- /* 66 */ "Ne",
- /* 67 */ "Eq",
- /* 68 */ "Gt",
- /* 69 */ "Le",
- /* 70 */ "Lt",
- /* 71 */ "Ge",
- /* 72 */ "IfNot",
- /* 73 */ "BitAnd",
- /* 74 */ "BitOr",
- /* 75 */ "ShiftLeft",
- /* 76 */ "ShiftRight",
- /* 77 */ "Add",
- /* 78 */ "Subtract",
- /* 79 */ "Multiply",
- /* 80 */ "Divide",
- /* 81 */ "Remainder",
- /* 82 */ "Concat",
- /* 83 */ "Negative",
- /* 84 */ "DropTable",
- /* 85 */ "BitNot",
- /* 86 */ "String8",
- /* 87 */ "MakeRecord",
- /* 88 */ "Delete",
- /* 89 */ "AggFinal",
- /* 90 */ "Dup",
- /* 91 */ "Goto",
- /* 92 */ "TableLock",
- /* 93 */ "FifoRead",
- /* 94 */ "Clear",
- /* 95 */ "IdxGT",
- /* 96 */ "MoveLt",
- /* 97 */ "VerifyCookie",
- /* 98 */ "AggStep",
- /* 99 */ "Pull",
- /* 100 */ "SetNumColumns",
- /* 101 */ "AbsValue",
- /* 102 */ "Transaction",
- /* 103 */ "ContextPop",
- /* 104 */ "Next",
- /* 105 */ "IdxInsert",
- /* 106 */ "Distinct",
- /* 107 */ "Insert",
- /* 108 */ "Destroy",
- /* 109 */ "ReadCookie",
- /* 110 */ "ForceInt",
- /* 111 */ "LoadAnalysis",
- /* 112 */ "OpenVirtual",
- /* 113 */ "Explain",
- /* 114 */ "IfMemZero",
- /* 115 */ "OpenPseudo",
- /* 116 */ "Null",
- /* 117 */ "Blob",
- /* 118 */ "MemStore",
- /* 119 */ "Rewind",
- /* 120 */ "MoveGe",
- /* 121 */ "MemMove",
- /* 122 */ "MemNull",
- /* 123 */ "Found",
- /* 124 */ "Real",
- /* 125 */ "HexBlob",
- /* 126 */ "NullRow",
- /* 127 */ "NotUsed_127",
- /* 128 */ "NotUsed_128",
- /* 129 */ "NotUsed_129",
- /* 130 */ "NotUsed_130",
- /* 131 */ "NotUsed_131",
- /* 132 */ "NotUsed_132",
- /* 133 */ "NotUsed_133",
- /* 134 */ "NotUsed_134",
+ /* 17 */ "AutoCommit",
+ /* 18 */ "IntegrityCk",
+ /* 19 */ "Sort",
+ /* 20 */ "Function",
+ /* 21 */ "Noop",
+ /* 22 */ "Return",
+ /* 23 */ "NewRowid",
+ /* 24 */ "IfMemNeg",
+ /* 25 */ "Variable",
+ /* 26 */ "String",
+ /* 27 */ "RealAffinity",
+ /* 28 */ "ParseSchema",
+ /* 29 */ "VOpen",
+ /* 30 */ "Close",
+ /* 31 */ "CreateIndex",
+ /* 32 */ "IsUnique",
+ /* 33 */ "NotFound",
+ /* 34 */ "Int64",
+ /* 35 */ "MustBeInt",
+ /* 36 */ "Halt",
+ /* 37 */ "Rowid",
+ /* 38 */ "IdxLT",
+ /* 39 */ "AddImm",
+ /* 40 */ "Statement",
+ /* 41 */ "RowData",
+ /* 42 */ "MemMax",
+ /* 43 */ "Push",
+ /* 44 */ "NotExists",
+ /* 45 */ "MemIncr",
+ /* 46 */ "Gosub",
+ /* 47 */ "Integer",
+ /* 48 */ "MemInt",
+ /* 49 */ "Prev",
+ /* 50 */ "VColumn",
+ /* 51 */ "CreateTable",
+ /* 52 */ "Last",
+ /* 53 */ "IdxRowid",
+ /* 54 */ "MakeIdxRec",
+ /* 55 */ "ResetCount",
+ /* 56 */ "FifoWrite",
+ /* 57 */ "Callback",
+ /* 58 */ "ContextPush",
+ /* 59 */ "DropTrigger",
+ /* 60 */ "DropIndex",
+ /* 61 */ "Or",
+ /* 62 */ "And",
+ /* 63 */ "IdxGE",
+ /* 64 */ "IdxDelete",
+ /* 65 */ "Vacuum",
+ /* 66 */ "IsNull",
+ /* 67 */ "NotNull",
+ /* 68 */ "Ne",
+ /* 69 */ "Eq",
+ /* 70 */ "Gt",
+ /* 71 */ "Le",
+ /* 72 */ "Lt",
+ /* 73 */ "Ge",
+ /* 74 */ "MoveLe",
+ /* 75 */ "BitAnd",
+ /* 76 */ "BitOr",
+ /* 77 */ "ShiftLeft",
+ /* 78 */ "ShiftRight",
+ /* 79 */ "Add",
+ /* 80 */ "Subtract",
+ /* 81 */ "Multiply",
+ /* 82 */ "Divide",
+ /* 83 */ "Remainder",
+ /* 84 */ "Concat",
+ /* 85 */ "IfNot",
+ /* 86 */ "Negative",
+ /* 87 */ "DropTable",
+ /* 88 */ "BitNot",
+ /* 89 */ "String8",
+ /* 90 */ "MakeRecord",
+ /* 91 */ "Delete",
+ /* 92 */ "AggFinal",
+ /* 93 */ "Dup",
+ /* 94 */ "Goto",
+ /* 95 */ "TableLock",
+ /* 96 */ "FifoRead",
+ /* 97 */ "Clear",
+ /* 98 */ "IdxGT",
+ /* 99 */ "MoveLt",
+ /* 100 */ "VerifyCookie",
+ /* 101 */ "AggStep",
+ /* 102 */ "Pull",
+ /* 103 */ "SetNumColumns",
+ /* 104 */ "AbsValue",
+ /* 105 */ "Transaction",
+ /* 106 */ "VFilter",
+ /* 107 */ "VDestroy",
+ /* 108 */ "ContextPop",
+ /* 109 */ "Next",
+ /* 110 */ "IdxInsert",
+ /* 111 */ "Distinct",
+ /* 112 */ "Insert",
+ /* 113 */ "Destroy",
+ /* 114 */ "ReadCookie",
+ /* 115 */ "ForceInt",
+ /* 116 */ "LoadAnalysis",
+ /* 117 */ "Explain",
+ /* 118 */ "IfMemZero",
+ /* 119 */ "OpenPseudo",
+ /* 120 */ "OpenEphemeral",
+ /* 121 */ "Null",
+ /* 122 */ "Blob",
+ /* 123 */ "MemStore",
+ /* 124 */ "Rewind",
+ /* 125 */ "MoveGe",
+ /* 126 */ "Real",
+ /* 127 */ "HexBlob",
+ /* 128 */ "VBegin",
+ /* 129 */ "VUpdate",
+ /* 130 */ "VCreate",
+ /* 131 */ "MemMove",
+ /* 132 */ "MemNull",
+ /* 133 */ "Found",
+ /* 134 */ "NullRow",
/* 135 */ "NotUsed_135",
/* 136 */ "NotUsed_136",
- /* 137 */ "ToText",
- /* 138 */ "ToBlob",
- /* 139 */ "ToNumeric",
- /* 140 */ "ToInt",
- /* 141 */ "ToReal",
+ /* 137 */ "NotUsed_137",
+ /* 138 */ "NotUsed_138",
+ /* 139 */ "ToText",
+ /* 140 */ "ToBlob",
+ /* 141 */ "ToNumeric",
+ /* 142 */ "ToInt",
+ /* 143 */ "ToReal",
};
#endif
diff --git a/dlls/sqlite/sqlite-source/opcodes.h b/dlls/sqlite/sqlite-source/opcodes.h
index e768d603..69ffced3 100644
--- a/dlls/sqlite/sqlite-source/opcodes.h
+++ b/dlls/sqlite/sqlite-source/opcodes.h
@@ -1,159 +1,161 @@
/* Automatically generated. Do not edit */
/* See the mkopcodeh.awk script for details */
#define OP_MemLoad 1
-#define OP_HexBlob 125 /* same as TK_BLOB */
-#define OP_Column 2
-#define OP_SetCookie 3
-#define OP_IfMemPos 4
-#define OP_Real 124 /* same as TK_FLOAT */
-#define OP_Sequence 5
-#define OP_MoveGt 6
-#define OP_Ge 71 /* same as TK_GE */
-#define OP_RowKey 7
-#define OP_Eq 67 /* same as TK_EQ */
-#define OP_OpenWrite 8
-#define OP_NotNull 65 /* same as TK_NOTNULL */
-#define OP_If 9
-#define OP_ToInt 140 /* same as TK_TO_INT */
-#define OP_String8 86 /* same as TK_STRING */
-#define OP_Pop 10
-#define OP_CollSeq 11
-#define OP_OpenRead 12
-#define OP_Expire 13
-#define OP_AutoCommit 14
-#define OP_Gt 68 /* same as TK_GT */
-#define OP_IntegrityCk 15
-#define OP_Sort 17
-#define OP_Function 18
-#define OP_And 60 /* same as TK_AND */
-#define OP_Subtract 78 /* same as TK_MINUS */
-#define OP_Noop 19
-#define OP_Return 20
-#define OP_Remainder 81 /* same as TK_REM */
-#define OP_NewRowid 21
-#define OP_Multiply 79 /* same as TK_STAR */
-#define OP_IfMemNeg 22
-#define OP_Variable 23
-#define OP_String 24
-#define OP_RealAffinity 25
-#define OP_ParseSchema 26
-#define OP_Close 27
-#define OP_CreateIndex 28
-#define OP_IsUnique 29
-#define OP_IdxIsNull 30
-#define OP_NotFound 31
-#define OP_Int64 32
-#define OP_MustBeInt 33
-#define OP_Halt 34
-#define OP_Rowid 35
-#define OP_IdxLT 36
-#define OP_AddImm 37
-#define OP_Statement 38
-#define OP_RowData 39
-#define OP_MemMax 40
-#define OP_Push 41
-#define OP_Or 59 /* same as TK_OR */
-#define OP_NotExists 42
-#define OP_MemIncr 43
-#define OP_Gosub 44
-#define OP_Divide 80 /* same as TK_SLASH */
-#define OP_Integer 45
-#define OP_ToNumeric 139 /* same as TK_TO_NUMERIC*/
-#define OP_MemInt 46
-#define OP_Prev 47
-#define OP_Concat 82 /* same as TK_CONCAT */
-#define OP_BitAnd 73 /* same as TK_BITAND */
-#define OP_CreateTable 48
-#define OP_Last 49
-#define OP_IsNull 64 /* same as TK_ISNULL */
-#define OP_IdxRowid 50
-#define OP_MakeIdxRec 51
-#define OP_ShiftRight 76 /* same as TK_RSHIFT */
-#define OP_ResetCount 52
-#define OP_FifoWrite 53
-#define OP_Callback 54
-#define OP_ContextPush 55
-#define OP_DropTrigger 56
-#define OP_DropIndex 57
-#define OP_IdxGE 58
-#define OP_IdxDelete 61
-#define OP_Vacuum 62
-#define OP_MoveLe 63
-#define OP_IfNot 72
-#define OP_DropTable 84
-#define OP_MakeRecord 87
-#define OP_ToBlob 138 /* same as TK_TO_BLOB */
-#define OP_Delete 88
-#define OP_AggFinal 89
-#define OP_ShiftLeft 75 /* same as TK_LSHIFT */
-#define OP_Dup 90
-#define OP_Goto 91
-#define OP_TableLock 92
-#define OP_FifoRead 93
-#define OP_Clear 94
-#define OP_IdxGT 95
-#define OP_MoveLt 96
-#define OP_Le 69 /* same as TK_LE */
-#define OP_VerifyCookie 97
-#define OP_AggStep 98
-#define OP_Pull 99
-#define OP_ToText 137 /* same as TK_TO_TEXT */
+#define OP_VNext 2
+#define OP_HexBlob 127 /* same as TK_BLOB */
+#define OP_Column 3
+#define OP_SetCookie 4
+#define OP_IfMemPos 5
+#define OP_Real 126 /* same as TK_FLOAT */
+#define OP_Sequence 6
+#define OP_MoveGt 7
+#define OP_Ge 73 /* same as TK_GE */
+#define OP_RowKey 8
+#define OP_Eq 69 /* same as TK_EQ */
+#define OP_OpenWrite 9
+#define OP_NotNull 67 /* same as TK_NOTNULL */
+#define OP_If 10
+#define OP_ToInt 142 /* same as TK_TO_INT */
+#define OP_String8 89 /* same as TK_STRING */
+#define OP_Pop 11
+#define OP_VRowid 12
+#define OP_CollSeq 13
+#define OP_OpenRead 14
+#define OP_Expire 15
+#define OP_AutoCommit 17
+#define OP_Gt 70 /* same as TK_GT */
+#define OP_IntegrityCk 18
+#define OP_Sort 19
+#define OP_Function 20
+#define OP_And 62 /* same as TK_AND */
+#define OP_Subtract 80 /* same as TK_MINUS */
+#define OP_Noop 21
+#define OP_Return 22
+#define OP_Remainder 83 /* same as TK_REM */
+#define OP_NewRowid 23
+#define OP_Multiply 81 /* same as TK_STAR */
+#define OP_IfMemNeg 24
+#define OP_Variable 25
+#define OP_String 26
+#define OP_RealAffinity 27
+#define OP_ParseSchema 28
+#define OP_VOpen 29
+#define OP_Close 30
+#define OP_CreateIndex 31
+#define OP_IsUnique 32
+#define OP_NotFound 33
+#define OP_Int64 34
+#define OP_MustBeInt 35
+#define OP_Halt 36
+#define OP_Rowid 37
+#define OP_IdxLT 38
+#define OP_AddImm 39
+#define OP_Statement 40
+#define OP_RowData 41
+#define OP_MemMax 42
+#define OP_Push 43
+#define OP_Or 61 /* same as TK_OR */
+#define OP_NotExists 44
+#define OP_MemIncr 45
+#define OP_Gosub 46
+#define OP_Divide 82 /* same as TK_SLASH */
+#define OP_Integer 47
+#define OP_ToNumeric 141 /* same as TK_TO_NUMERIC*/
+#define OP_MemInt 48
+#define OP_Prev 49
+#define OP_Concat 84 /* same as TK_CONCAT */
+#define OP_BitAnd 75 /* same as TK_BITAND */
+#define OP_VColumn 50
+#define OP_CreateTable 51
+#define OP_Last 52
+#define OP_IsNull 66 /* same as TK_ISNULL */
+#define OP_IdxRowid 53
+#define OP_MakeIdxRec 54
+#define OP_ShiftRight 78 /* same as TK_RSHIFT */
+#define OP_ResetCount 55
+#define OP_FifoWrite 56
+#define OP_Callback 57
+#define OP_ContextPush 58
+#define OP_DropTrigger 59
+#define OP_DropIndex 60
+#define OP_IdxGE 63
+#define OP_IdxDelete 64
+#define OP_Vacuum 65
+#define OP_MoveLe 74
+#define OP_IfNot 85
+#define OP_DropTable 87
+#define OP_MakeRecord 90
+#define OP_ToBlob 140 /* same as TK_TO_BLOB */
+#define OP_Delete 91
+#define OP_AggFinal 92
+#define OP_ShiftLeft 77 /* same as TK_LSHIFT */
+#define OP_Dup 93
+#define OP_Goto 94
+#define OP_TableLock 95
+#define OP_FifoRead 96
+#define OP_Clear 97
+#define OP_IdxGT 98
+#define OP_MoveLt 99
+#define OP_Le 71 /* same as TK_LE */
+#define OP_VerifyCookie 100
+#define OP_AggStep 101
+#define OP_Pull 102
+#define OP_ToText 139 /* same as TK_TO_TEXT */
#define OP_Not 16 /* same as TK_NOT */
-#define OP_ToReal 141 /* same as TK_TO_REAL */
-#define OP_SetNumColumns 100
-#define OP_AbsValue 101
-#define OP_Transaction 102
-#define OP_Negative 83 /* same as TK_UMINUS */
-#define OP_Ne 66 /* same as TK_NE */
-#define OP_ContextPop 103
-#define OP_BitOr 74 /* same as TK_BITOR */
-#define OP_Next 104
-#define OP_IdxInsert 105
-#define OP_Distinct 106
-#define OP_Lt 70 /* same as TK_LT */
-#define OP_Insert 107
-#define OP_Destroy 108
-#define OP_ReadCookie 109
-#define OP_ForceInt 110
-#define OP_LoadAnalysis 111
-#define OP_OpenVirtual 112
-#define OP_Explain 113
-#define OP_IfMemZero 114
-#define OP_OpenPseudo 115
-#define OP_Null 116
-#define OP_Blob 117
-#define OP_Add 77 /* same as TK_PLUS */
-#define OP_MemStore 118
-#define OP_Rewind 119
-#define OP_MoveGe 120
-#define OP_BitNot 85 /* same as TK_BITNOT */
-#define OP_MemMove 121
-#define OP_MemNull 122
-#define OP_Found 123
-#define OP_NullRow 126
+#define OP_ToReal 143 /* same as TK_TO_REAL */
+#define OP_SetNumColumns 103
+#define OP_AbsValue 104
+#define OP_Transaction 105
+#define OP_VFilter 106
+#define OP_Negative 86 /* same as TK_UMINUS */
+#define OP_Ne 68 /* same as TK_NE */
+#define OP_VDestroy 107
+#define OP_ContextPop 108
+#define OP_BitOr 76 /* same as TK_BITOR */
+#define OP_Next 109
+#define OP_IdxInsert 110
+#define OP_Distinct 111
+#define OP_Lt 72 /* same as TK_LT */
+#define OP_Insert 112
+#define OP_Destroy 113
+#define OP_ReadCookie 114
+#define OP_ForceInt 115
+#define OP_LoadAnalysis 116
+#define OP_Explain 117
+#define OP_IfMemZero 118
+#define OP_OpenPseudo 119
+#define OP_OpenEphemeral 120
+#define OP_Null 121
+#define OP_Blob 122
+#define OP_Add 79 /* same as TK_PLUS */
+#define OP_MemStore 123
+#define OP_Rewind 124
+#define OP_MoveGe 125
+#define OP_VBegin 128
+#define OP_VUpdate 129
+#define OP_BitNot 88 /* same as TK_BITNOT */
+#define OP_VCreate 130
+#define OP_MemMove 131
+#define OP_MemNull 132
+#define OP_Found 133
+#define OP_NullRow 134
/* The following opcode values are never used */
-#define OP_NotUsed_127 127
-#define OP_NotUsed_128 128
-#define OP_NotUsed_129 129
-#define OP_NotUsed_130 130
-#define OP_NotUsed_131 131
-#define OP_NotUsed_132 132
-#define OP_NotUsed_133 133
-#define OP_NotUsed_134 134
#define OP_NotUsed_135 135
#define OP_NotUsed_136 136
+#define OP_NotUsed_137 137
+#define OP_NotUsed_138 138
/* Opcodes that are guaranteed to never push a value onto the stack
** contain a 1 their corresponding position of the following mask
** set. See the opcodeNoPush() function in vdbeaux.c */
-#define NOPUSH_MASK_0 0x7f58
-#define NOPUSH_MASK_1 0xee5b
-#define NOPUSH_MASK_2 0x9f76
-#define NOPUSH_MASK_3 0xfff2
+#define NOPUSH_MASK_0 0xeeb4
+#define NOPUSH_MASK_1 0x796b
+#define NOPUSH_MASK_2 0x7ddb
+#define NOPUSH_MASK_3 0xff92
#define NOPUSH_MASK_4 0xffff
-#define NOPUSH_MASK_5 0xdb3b
-#define NOPUSH_MASK_6 0xcfdf
-#define NOPUSH_MASK_7 0x49cd
-#define NOPUSH_MASK_8 0x3e00
+#define NOPUSH_MASK_5 0xd9ef
+#define NOPUSH_MASK_6 0xfefe
+#define NOPUSH_MASK_7 0x39d9
+#define NOPUSH_MASK_8 0xf867
#define NOPUSH_MASK_9 0x0000
diff --git a/dlls/sqlite/sqlite-source/os.h b/dlls/sqlite/sqlite-source/os.h
index b294346b..0fe7b156 100644
--- a/dlls/sqlite/sqlite-source/os.h
+++ b/dlls/sqlite/sqlite-source/os.h
@@ -27,12 +27,19 @@
# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
# define OS_WIN 1
# define OS_UNIX 0
+# define OS_OS2 0
+# elif defined(_EMX_) || defined(_OS2) || defined(OS2) || defined(_OS2_) || defined(__OS2__)
+# define OS_WIN 0
+# define OS_UNIX 0
+# define OS_OS2 1
# else
# define OS_WIN 0
# define OS_UNIX 1
+# define OS_OS2 0
# endif
# else
# define OS_UNIX 0
+# define OS_OS2 0
# endif
#else
# ifndef OS_WIN
@@ -47,6 +54,14 @@
#if OS_WIN
# include
# define SQLITE_TEMPNAME_SIZE (MAX_PATH+50)
+#elif OS_OS2
+# define INCL_DOSDATETIME
+# define INCL_DOSFILEMGR
+# define INCL_DOSERRORS
+# define INCL_DOSMISC
+# define INCL_DOSPROCESS
+# include
+# define SQLITE_TEMPNAME_SIZE (CCHMAXPATHCOMP)
#else
# define SQLITE_TEMPNAME_SIZE 200
#endif
@@ -66,13 +81,25 @@
** prefix to reflect your program's name, so that if your program exits
** prematurely, old temporary files can be easily identified. This can be done
** using -DTEMP_FILE_PREFIX=myprefix_ on the compiler command line.
+**
+** 2006-10-31: The default prefix used to be "sqlite_". But then
+** Mcafee started using SQLite in their anti-virus product and it
+** started putting files with the "sqlite" name in the c:/temp folder.
+** This annoyed many windows users. Those users would then do a
+** Google search for "sqlite", find the telephone numbers of the
+** developers and call to wake them up at night and complain.
+** For this reason, the default name prefix is changed to be "sqlite"
+** spelled backwards. So the temp files are still identified, but
+** anybody smart enough to figure out the code is also likely smart
+** enough to know that calling the developer will not help get rid
+** of the file.
*/
#ifndef TEMP_FILE_PREFIX
-# define TEMP_FILE_PREFIX "sqlite_"
+# define TEMP_FILE_PREFIX "etilqs_"
#endif
/*
-** Define the interfaces for Unix and for Windows.
+** Define the interfaces for Unix, Windows, and OS/2.
*/
#if OS_UNIX
#define sqlite3OsOpenReadWrite sqlite3UnixOpenReadWrite
@@ -95,6 +122,9 @@
#define sqlite3OsRealloc sqlite3GenericRealloc
#define sqlite3OsFree sqlite3GenericFree
#define sqlite3OsAllocationSize sqlite3GenericAllocationSize
+#define sqlite3OsDlopen sqlite3UnixDlopen
+#define sqlite3OsDlsym sqlite3UnixDlsym
+#define sqlite3OsDlclose sqlite3UnixDlclose
#endif
#if OS_WIN
#define sqlite3OsOpenReadWrite sqlite3WinOpenReadWrite
@@ -117,7 +147,38 @@
#define sqlite3OsRealloc sqlite3GenericRealloc
#define sqlite3OsFree sqlite3GenericFree
#define sqlite3OsAllocationSize sqlite3GenericAllocationSize
+#define sqlite3OsDlopen sqlite3WinDlopen
+#define sqlite3OsDlsym sqlite3WinDlsym
+#define sqlite3OsDlclose sqlite3WinDlclose
#endif
+#if OS_OS2
+#define sqlite3OsOpenReadWrite sqlite3Os2OpenReadWrite
+#define sqlite3OsOpenExclusive sqlite3Os2OpenExclusive
+#define sqlite3OsOpenReadOnly sqlite3Os2OpenReadOnly
+#define sqlite3OsDelete sqlite3Os2Delete
+#define sqlite3OsFileExists sqlite3Os2FileExists
+#define sqlite3OsFullPathname sqlite3Os2FullPathname
+#define sqlite3OsIsDirWritable sqlite3Os2IsDirWritable
+#define sqlite3OsSyncDirectory sqlite3Os2SyncDirectory
+#define sqlite3OsTempFileName sqlite3Os2TempFileName
+#define sqlite3OsRandomSeed sqlite3Os2RandomSeed
+#define sqlite3OsSleep sqlite3Os2Sleep
+#define sqlite3OsCurrentTime sqlite3Os2CurrentTime
+#define sqlite3OsEnterMutex sqlite3Os2EnterMutex
+#define sqlite3OsLeaveMutex sqlite3Os2LeaveMutex
+#define sqlite3OsInMutex sqlite3Os2InMutex
+#define sqlite3OsThreadSpecificData sqlite3Os2ThreadSpecificData
+#define sqlite3OsMalloc sqlite3GenericMalloc
+#define sqlite3OsRealloc sqlite3GenericRealloc
+#define sqlite3OsFree sqlite3GenericFree
+#define sqlite3OsAllocationSize sqlite3GenericAllocationSize
+#define sqlite3OsDlopen sqlite3Os2Dlopen
+#define sqlite3OsDlsym sqlite3Os2Dlsym
+#define sqlite3OsDlclose sqlite3Os2Dlclose
+#endif
+
+
+
/*
** If using an alternative OS interface, then we must have an "os_other.h"
@@ -297,6 +358,9 @@ void *sqlite3OsMalloc(int);
void *sqlite3OsRealloc(void *, int);
void sqlite3OsFree(void *);
int sqlite3OsAllocationSize(void *);
+void *sqlite3OsDlopen(const char*);
+void *sqlite3OsDlsym(void*, const char*);
+int sqlite3OsDlclose(void*);
/*
** If the SQLITE_ENABLE_REDEF_IO macro is defined, then the OS-layer
@@ -341,16 +405,26 @@ struct sqlite3OsVtbl {
void *(*xRealloc)(void *, int);
void (*xFree)(void *);
int (*xAllocationSize)(void *);
+
+ void *(*xDlopen)(const char*);
+ void *(*xDlsym)(void*, const char*);
+ int (*xDlclose)(void*);
};
/* Macro used to comment out routines that do not exists when there is
-** no disk I/O
+** no disk I/O or extension loading
*/
#ifdef SQLITE_OMIT_DISKIO
# define IF_DISKIO(X) 0
#else
# define IF_DISKIO(X) X
#endif
+#ifdef SQLITE_OMIT_LOAD_EXTENSION
+# define IF_DLOPEN(X) 0
+#else
+# define IF_DLOPEN(X) X
+#endif
+
#ifdef _SQLITE_OS_C_
/*
@@ -376,7 +450,10 @@ struct sqlite3OsVtbl {
sqlite3OsMalloc,
sqlite3OsRealloc,
sqlite3OsFree,
- sqlite3OsAllocationSize
+ sqlite3OsAllocationSize,
+ IF_DLOPEN( sqlite3OsDlopen ),
+ IF_DLOPEN( sqlite3OsDlsym ),
+ IF_DLOPEN( sqlite3OsDlclose ),
};
#else
/*
diff --git a/dlls/sqlite/sqlite-source/os_common.h b/dlls/sqlite/sqlite-source/os_common.h
index d65c352d..863e3cde 100644
--- a/dlls/sqlite/sqlite-source/os_common.h
+++ b/dlls/sqlite/sqlite-source/os_common.h
@@ -92,25 +92,25 @@ int sqlite3_io_error_hit = 0;
int sqlite3_io_error_pending = 0;
int sqlite3_diskfull_pending = 0;
int sqlite3_diskfull = 0;
-#define SimulateIOError(A) \
+#define SimulateIOError(CODE) \
if( sqlite3_io_error_pending ) \
- if( sqlite3_io_error_pending-- == 1 ){ local_ioerr(); return A; }
+ if( sqlite3_io_error_pending-- == 1 ){ local_ioerr(); CODE; }
static void local_ioerr(){
sqlite3_io_error_hit = 1; /* Really just a place to set a breakpoint */
}
-#define SimulateDiskfullError \
+#define SimulateDiskfullError(CODE) \
if( sqlite3_diskfull_pending ){ \
if( sqlite3_diskfull_pending == 1 ){ \
local_ioerr(); \
sqlite3_diskfull = 1; \
- return SQLITE_FULL; \
+ CODE; \
}else{ \
sqlite3_diskfull_pending--; \
} \
}
#else
#define SimulateIOError(A)
-#define SimulateDiskfullError
+#define SimulateDiskfullError(A)
#endif
/*
diff --git a/dlls/sqlite/sqlite-source/os_unix.c b/dlls/sqlite/sqlite-source/os_unix.c
index 6dcc43eb..0bb8a90e 100644
--- a/dlls/sqlite/sqlite-source/os_unix.c
+++ b/dlls/sqlite/sqlite-source/os_unix.c
@@ -16,6 +16,8 @@
#include "os.h"
#if OS_UNIX /* This file is used on unix only */
+/* #define SQLITE_ENABLE_LOCKING_STYLE 0 */
+
/*
** These #defines should enable >2GB file support on Posix if the
** underlying operating system supports it. If the OS lacks
@@ -47,6 +49,11 @@
#include
#include
#include
+#ifdef SQLITE_ENABLE_LOCKING_STYLE
+#include
+#include
+#include
+#endif /* SQLITE_ENABLE_LOCKING_STYLE */
/*
** If we are to be thread-safe, include the pthreads header and define
@@ -75,6 +82,9 @@ struct unixFile {
IoMethod const *pMethod; /* Always the first entry */
struct openCnt *pOpen; /* Info about all open fd's on this inode */
struct lockInfo *pLock; /* Info about locks on this inode */
+#ifdef SQLITE_ENABLE_LOCKING_STYLE
+ void *lockingContext; /* Locking style specific state */
+#endif /* SQLITE_ENABLE_LOCKING_STYLE */
int h; /* The file descriptor */
unsigned char locktype; /* The type of lock held on this fd */
unsigned char isOpen; /* True if needs to be closed */
@@ -346,6 +356,32 @@ static Hash lockHash = {SQLITE_HASH_BINARY, 0, 0, 0,
static Hash openHash = {SQLITE_HASH_BINARY, 0, 0, 0,
sqlite3ThreadSafeMalloc, sqlite3ThreadSafeFree, 0, 0};
+#ifdef SQLITE_ENABLE_LOCKING_STYLE
+/*
+** The locking styles are associated with the different file locking
+** capabilities supported by different file systems.
+**
+** POSIX locking style fully supports shared and exclusive byte-range locks
+** ADP locking only supports exclusive byte-range locks
+** FLOCK only supports a single file-global exclusive lock
+** DOTLOCK isn't a true locking style, it refers to the use of a special
+** file named the same as the database file with a '.lock' extension, this
+** can be used on file systems that do not offer any reliable file locking
+** NO locking means that no locking will be attempted, this is only used for
+** read-only file systems currently
+** UNSUPPORTED means that no locking will be attempted, this is only used for
+** file systems that are known to be unsupported
+*/
+typedef enum {
+ posixLockingStyle = 0, /* standard posix-advisory locks */
+ afpLockingStyle, /* use afp locks */
+ flockLockingStyle, /* use flock() */
+ dotlockLockingStyle, /* use .lock files */
+ noLockingStyle, /* useful for read-only file system */
+ unsupportedLockingStyle /* indicates unsupported file system */
+} sqlite3LockingStyle;
+#endif /* SQLITE_ENABLE_LOCKING_STYLE */
+
#ifdef SQLITE_UNIX_THREADS
/*
** This variable records whether or not threads can override each others
@@ -490,6 +526,8 @@ static void testThreadLockingBehavior(int fd_orig){
*/
static void releaseLockInfo(struct lockInfo *pLock){
assert( sqlite3OsInMutex(1) );
+ if (pLock == NULL)
+ return;
pLock->nRef--;
if( pLock->nRef==0 ){
sqlite3HashInsert(&lockHash, &pLock->key, sizeof(pLock->key), 0);
@@ -502,6 +540,8 @@ static void releaseLockInfo(struct lockInfo *pLock){
*/
static void releaseOpenCnt(struct openCnt *pOpen){
assert( sqlite3OsInMutex(1) );
+ if (pOpen == NULL)
+ return;
pOpen->nRef--;
if( pOpen->nRef==0 ){
sqlite3HashInsert(&openHash, &pOpen->key, sizeof(pOpen->key), 0);
@@ -510,6 +550,77 @@ static void releaseOpenCnt(struct openCnt *pOpen){
}
}
+#ifdef SQLITE_ENABLE_LOCKING_STYLE
+/*
+** Tests a byte-range locking query to see if byte range locks are
+** supported, if not we fall back to dotlockLockingStyle.
+*/
+static sqlite3LockingStyle sqlite3TestLockingStyle(const char *filePath,
+ int fd) {
+ /* test byte-range lock using fcntl */
+ struct flock lockInfo;
+
+ lockInfo.l_len = 1;
+ lockInfo.l_start = 0;
+ lockInfo.l_whence = SEEK_SET;
+ lockInfo.l_type = F_RDLCK;
+
+ if (fcntl(fd, F_GETLK, &lockInfo) != -1) {
+ return posixLockingStyle;
+ }
+
+ /* testing for flock can give false positives. So if if the above test
+ ** fails, then we fall back to using dot-lock style locking.
+ */
+ return dotlockLockingStyle;
+}
+
+/*
+** Examines the f_fstypename entry in the statfs structure as returned by
+** stat() for the file system hosting the database file, assigns the
+** appropriate locking style based on it's value. These values and
+** assignments are based on Darwin/OSX behavior and have not been tested on
+** other systems.
+*/
+static sqlite3LockingStyle sqlite3DetectLockingStyle(const char *filePath,
+ int fd) {
+
+#ifdef SQLITE_FIXED_LOCKING_STYLE
+ return (sqlite3LockingStyle)SQLITE_FIXED_LOCKING_STYLE;
+#else
+ struct statfs fsInfo;
+
+ if (statfs(filePath, &fsInfo) == -1)
+ return sqlite3TestLockingStyle(filePath, fd);
+
+ if (fsInfo.f_flags & MNT_RDONLY)
+ return noLockingStyle;
+
+ if( (!strcmp(fsInfo.f_fstypename, "hfs")) ||
+ (!strcmp(fsInfo.f_fstypename, "ufs")) )
+ return posixLockingStyle;
+
+ if(!strcmp(fsInfo.f_fstypename, "afpfs"))
+ return afpLockingStyle;
+
+ if(!strcmp(fsInfo.f_fstypename, "nfs"))
+ return sqlite3TestLockingStyle(filePath, fd);
+
+ if(!strcmp(fsInfo.f_fstypename, "smbfs"))
+ return flockLockingStyle;
+
+ if(!strcmp(fsInfo.f_fstypename, "msdos"))
+ return dotlockLockingStyle;
+
+ if(!strcmp(fsInfo.f_fstypename, "webdav"))
+ return unsupportedLockingStyle;
+
+ return sqlite3TestLockingStyle(filePath, fd);
+#endif // SQLITE_FIXED_LOCKING_STYLE
+}
+
+#endif /* SQLITE_ENABLE_LOCKING_STYLE */
+
/*
** Given a file descriptor, locate lockInfo and openCnt structures that
** describes that file descriptor. Create new ones if necessary. The
@@ -651,12 +762,16 @@ static int transferOwnership(unixFile *pFile){
}
TRACE4("Transfer ownership of %d from %d to %d\n", pFile->h,pFile->tid,hSelf);
pFile->tid = hSelf;
- releaseLockInfo(pFile->pLock);
- rc = findLockInfo(pFile->h, &pFile->pLock, 0);
- TRACE5("LOCK %d is now %s(%s,%d)\n", pFile->h,
- locktypeName(pFile->locktype),
- locktypeName(pFile->pLock->locktype), pFile->pLock->cnt);
- return rc;
+ if (pFile->pLock != NULL) {
+ releaseLockInfo(pFile->pLock);
+ rc = findLockInfo(pFile->h, &pFile->pLock, 0);
+ TRACE5("LOCK %d is now %s(%s,%d)\n", pFile->h,
+ locktypeName(pFile->locktype),
+ locktypeName(pFile->pLock->locktype), pFile->pLock->cnt);
+ return rc;
+ } else {
+ return SQLITE_OK;
+ }
}
#else
/* On single-threaded builds, ownership transfer is a no-op */
@@ -679,7 +794,12 @@ int sqlite3UnixFileExists(const char *zFilename){
}
/* Forward declaration */
-static int allocateUnixFile(unixFile *pInit, OsFile **pId);
+static int allocateUnixFile(
+ int h, /* File descriptor of the open file */
+ OsFile **pId, /* Write the real file descriptor here */
+ const char *zFilename, /* Name of the file being opened */
+ int delFlag /* If true, make sure the file deletes on close */
+);
/*
** Attempt to open a file for both reading and writing. If that
@@ -699,36 +819,27 @@ int sqlite3UnixOpenReadWrite(
OsFile **pId,
int *pReadonly
){
- int rc;
- unixFile f;
-
+ int h;
+
CRASH_TEST_OVERRIDE(sqlite3CrashOpenReadWrite, zFilename, pId, pReadonly);
assert( 0==*pId );
- f.h = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY,
- SQLITE_DEFAULT_FILE_PERMISSIONS);
- if( f.h<0 ){
+ h = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY,
+ SQLITE_DEFAULT_FILE_PERMISSIONS);
+ if( h<0 ){
#ifdef EISDIR
if( errno==EISDIR ){
return SQLITE_CANTOPEN;
}
#endif
- f.h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
- if( f.h<0 ){
+ h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
+ if( h<0 ){
return SQLITE_CANTOPEN;
}
*pReadonly = 1;
}else{
*pReadonly = 0;
}
- sqlite3OsEnterMutex();
- rc = findLockInfo(f.h, &f.pLock, &f.pOpen);
- sqlite3OsLeaveMutex();
- if( rc ){
- close(f.h);
- return SQLITE_NOMEM;
- }
- TRACE3("OPEN %-3d %s\n", f.h, zFilename);
- return allocateUnixFile(&f, pId);
+ return allocateUnixFile(h, pId, zFilename, 0);
}
@@ -747,33 +858,17 @@ int sqlite3UnixOpenReadWrite(
** On failure, return SQLITE_CANTOPEN.
*/
int sqlite3UnixOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){
- int rc;
- unixFile f;
+ int h;
CRASH_TEST_OVERRIDE(sqlite3CrashOpenExclusive, zFilename, pId, delFlag);
assert( 0==*pId );
- if( access(zFilename, 0)==0 ){
- return SQLITE_CANTOPEN;
- }
- f.h = open(zFilename,
+ h = open(zFilename,
O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY,
SQLITE_DEFAULT_FILE_PERMISSIONS);
- if( f.h<0 ){
+ if( h<0 ){
return SQLITE_CANTOPEN;
}
- sqlite3OsEnterMutex();
- rc = findLockInfo(f.h, &f.pLock, &f.pOpen);
- sqlite3OsLeaveMutex();
- if( rc ){
- close(f.h);
- unlink(zFilename);
- return SQLITE_NOMEM;
- }
- if( delFlag ){
- unlink(zFilename);
- }
- TRACE3("OPEN-EX %-3d %s\n", f.h, zFilename);
- return allocateUnixFile(&f, pId);
+ return allocateUnixFile(h, pId, zFilename, delFlag);
}
/*
@@ -784,24 +879,15 @@ int sqlite3UnixOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){
** On failure, return SQLITE_CANTOPEN.
*/
int sqlite3UnixOpenReadOnly(const char *zFilename, OsFile **pId){
- int rc;
- unixFile f;
-
+ int h;
+
CRASH_TEST_OVERRIDE(sqlite3CrashOpenReadOnly, zFilename, pId, 0);
assert( 0==*pId );
- f.h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
- if( f.h<0 ){
+ h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
+ if( h<0 ){
return SQLITE_CANTOPEN;
}
- sqlite3OsEnterMutex();
- rc = findLockInfo(f.h, &f.pLock, &f.pOpen);
- sqlite3OsLeaveMutex();
- if( rc ){
- close(f.h);
- return SQLITE_NOMEM;
- }
- TRACE3("OPEN-RO %-3d %s\n", f.h, zFilename);
- return allocateUnixFile(&f, pId);
+ return allocateUnixFile(h, pId, zFilename, 0);
}
/*
@@ -813,6 +899,9 @@ int sqlite3UnixOpenReadOnly(const char *zFilename, OsFile **pId){
** This routine is only meaningful for Unix. It is a no-op under
** windows since windows does not support hard links.
**
+** If FULL_FSYNC is enabled, this function is not longer useful,
+** a FULL_FSYNC sync applies to all pending disk operations.
+**
** On success, a handle for a previously open file at *id is
** updated with the new directory file descriptor and SQLITE_OK is
** returned.
@@ -911,10 +1000,14 @@ int sqlite3UnixIsDirWritable(char *zBuf){
*/
static int seekAndRead(unixFile *id, void *pBuf, int cnt){
int got;
+ i64 newOffset;
#ifdef USE_PREAD
got = pread(id->h, pBuf, cnt, id->offset);
#else
- lseek(id->h, id->offset, SEEK_SET);
+ newOffset = lseek(id->h, id->offset, SEEK_SET);
+ if( newOffset!=id->offset ){
+ return -1;
+ }
got = read(id->h, pBuf, cnt);
#endif
if( got>0 ){
@@ -931,18 +1024,20 @@ static int seekAndRead(unixFile *id, void *pBuf, int cnt){
static int unixRead(OsFile *id, void *pBuf, int amt){
int got;
assert( id );
- SimulateIOError(SQLITE_IOERR);
TIMER_START;
got = seekAndRead((unixFile*)id, pBuf, amt);
TIMER_END;
TRACE5("READ %-3d %5d %7d %d\n", ((unixFile*)id)->h, got,
last_page, TIMER_ELAPSED);
SEEK(0);
- /* if( got<0 ) got = 0; */
+ SimulateIOError( got = -1 );
if( got==amt ){
return SQLITE_OK;
+ }else if( got<0 ){
+ return SQLITE_IOERR_READ;
}else{
- return SQLITE_IOERR;
+ memset(&((char*)pBuf)[got], 0, amt-got);
+ return SQLITE_IOERR_SHORT_READ;
}
}
@@ -952,10 +1047,14 @@ static int unixRead(OsFile *id, void *pBuf, int amt){
*/
static int seekAndWrite(unixFile *id, const void *pBuf, int cnt){
int got;
+ i64 newOffset;
#ifdef USE_PREAD
got = pwrite(id->h, pBuf, cnt, id->offset);
#else
- lseek(id->h, id->offset, SEEK_SET);
+ newOffset = lseek(id->h, id->offset, SEEK_SET);
+ if( newOffset!=id->offset ){
+ return -1;
+ }
got = write(id->h, pBuf, cnt);
#endif
if( got>0 ){
@@ -973,8 +1072,6 @@ static int unixWrite(OsFile *id, const void *pBuf, int amt){
int wrote = 0;
assert( id );
assert( amt>0 );
- SimulateIOError(SQLITE_IOERR);
- SimulateDiskfullError;
TIMER_START;
while( amt>0 && (wrote = seekAndWrite((unixFile*)id, pBuf, amt))>0 ){
amt -= wrote;
@@ -984,8 +1081,14 @@ static int unixWrite(OsFile *id, const void *pBuf, int amt){
TRACE5("WRITE %-3d %5d %7d %d\n", ((unixFile*)id)->h, wrote,
last_page, TIMER_ELAPSED);
SEEK(0);
+ SimulateIOError(( wrote=(-1), amt=1 ));
+ SimulateDiskfullError(( wrote=0, amt=1 ));
if( amt>0 ){
- return SQLITE_FULL;
+ if( wrote<0 ){
+ return SQLITE_IOERR_WRITE;
+ }else{
+ return SQLITE_FULL;
+ }
}
return SQLITE_OK;
}
@@ -997,7 +1100,7 @@ static int unixSeek(OsFile *id, i64 offset){
assert( id );
SEEK(offset/1024 + 1);
#ifdef SQLITE_TEST
- if( offset ) SimulateDiskfullError
+ if( offset ) SimulateDiskfullError(return SQLITE_FULL);
#endif
((unixFile*)id)->offset = offset;
return SQLITE_OK;
@@ -1068,16 +1171,23 @@ static int full_fsync(int fd, int fullSync, int dataOnly){
}else{
rc = 1;
}
- /* If the FULLSYNC failed, try to do a normal fsync() */
+ /* If the FULLFSYNC failed, fall back to attempting an fsync().
+ * It shouldn't be possible for fullfsync to fail on the local
+ * file system (on OSX), so failure indicates that FULLFSYNC
+ * isn't supported for this file system. So, attempt an fsync
+ * and (for now) ignore the overhead of a superfluous fcntl call.
+ * It'd be better to detect fullfsync support once and avoid
+ * the fcntl call every time sync is called.
+ */
if( rc ) rc = fsync(fd);
-#else /* if !defined(F_FULLSYNC) */
+#else
if( dataOnly ){
rc = fdatasync(fd);
}else{
rc = fsync(fd);
}
-#endif /* defined(F_FULLFSYNC) */
+#endif /* HAVE_FULLFSYNC */
#endif /* defined(SQLITE_NO_SYNC) */
return rc;
@@ -1099,12 +1209,14 @@ static int full_fsync(int fd, int fullSync, int dataOnly){
** will not roll back - possibly leading to database corruption.
*/
static int unixSync(OsFile *id, int dataOnly){
+ int rc;
unixFile *pFile = (unixFile*)id;
assert( pFile );
- SimulateIOError(SQLITE_IOERR);
TRACE2("SYNC %-3d\n", pFile->h);
- if( full_fsync(pFile->h, pFile->fullSync, dataOnly) ){
- return SQLITE_IOERR;
+ rc = full_fsync(pFile->h, pFile->fullSync, dataOnly);
+ SimulateIOError( rc=1 );
+ if( rc ){
+ return SQLITE_IOERR_FSYNC;
}
if( pFile->dirfd>=0 ){
TRACE4("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd,
@@ -1144,7 +1256,6 @@ int sqlite3UnixSyncDirectory(const char *zDirname){
#else
int fd;
int r;
- SimulateIOError(SQLITE_IOERR);
fd = open(zDirname, O_RDONLY|O_BINARY, 0);
TRACE3("DIRSYNC %-3d (%s)\n", fd, zDirname);
if( fd<0 ){
@@ -1152,7 +1263,12 @@ int sqlite3UnixSyncDirectory(const char *zDirname){
}
r = fsync(fd);
close(fd);
- return ((r==0)?SQLITE_OK:SQLITE_IOERR);
+ SimulateIOError( r=1 );
+ if( r ){
+ return SQLITE_IOERR_DIR_FSYNC;
+ }else{
+ return SQLITE_OK;
+ }
#endif
}
@@ -1160,20 +1276,28 @@ int sqlite3UnixSyncDirectory(const char *zDirname){
** Truncate an open file to a specified size
*/
static int unixTruncate(OsFile *id, i64 nByte){
+ int rc;
assert( id );
- SimulateIOError(SQLITE_IOERR);
- return ftruncate(((unixFile*)id)->h, nByte)==0 ? SQLITE_OK : SQLITE_IOERR;
+ rc = ftruncate(((unixFile*)id)->h, nByte);
+ SimulateIOError( rc=1 );
+ if( rc ){
+ return SQLITE_IOERR_TRUNCATE;
+ }else{
+ return SQLITE_OK;
+ }
}
/*
** Determine the current size of a file in bytes
*/
static int unixFileSize(OsFile *id, i64 *pSize){
+ int rc;
struct stat buf;
assert( id );
- SimulateIOError(SQLITE_IOERR);
- if( fstat(((unixFile*)id)->h, &buf)!=0 ){
- return SQLITE_IOERR;
+ rc = fstat(((unixFile*)id)->h, &buf);
+ SimulateIOError( rc=1 );
+ if( rc!=0 ){
+ return SQLITE_IOERR_FSTAT;
}
*pSize = buf.st_size;
return SQLITE_OK;
@@ -1383,7 +1507,7 @@ static int unixLock(OsFile *id, int locktype){
lock.l_len = 1L;
lock.l_type = F_UNLCK;
if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){
- rc = SQLITE_IOERR; /* This should never happen */
+ rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
goto end_lock;
}
if( s ){
@@ -1472,7 +1596,7 @@ static int unixUnlock(OsFile *id, int locktype){
lock.l_len = SHARED_SIZE;
if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){
/* This should never happen */
- rc = SQLITE_IOERR;
+ rc = SQLITE_IOERR_RDLOCK;
}
}
lock.l_type = F_UNLCK;
@@ -1482,7 +1606,7 @@ static int unixUnlock(OsFile *id, int locktype){
if( fcntl(pFile->h, F_SETLK, &lock)==0 ){
pLock->locktype = SHARED_LOCK;
}else{
- rc = SQLITE_IOERR; /* This should never happen */
+ rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
}
}
if( locktype==NO_LOCK ){
@@ -1500,7 +1624,7 @@ static int unixUnlock(OsFile *id, int locktype){
if( fcntl(pFile->h, F_SETLK, &lock)==0 ){
pLock->locktype = NO_LOCK;
}else{
- rc = SQLITE_IOERR; /* This should never happen */
+ rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
}
}
@@ -1570,6 +1694,581 @@ static int unixClose(OsFile **pId){
return SQLITE_OK;
}
+
+#ifdef SQLITE_ENABLE_LOCKING_STYLE
+#pragma mark AFP Support
+
+/*
+ ** The afpLockingContext structure contains all afp lock specific state
+ */
+typedef struct afpLockingContext afpLockingContext;
+struct afpLockingContext {
+ unsigned long long sharedLockByte;
+ char *filePath;
+};
+
+struct ByteRangeLockPB2
+{
+ unsigned long long offset; /* offset to first byte to lock */
+ unsigned long long length; /* nbr of bytes to lock */
+ unsigned long long retRangeStart; /* nbr of 1st byte locked if successful */
+ unsigned char unLockFlag; /* 1 = unlock, 0 = lock */
+ unsigned char startEndFlag; /* 1=rel to end of fork, 0=rel to start */
+ int fd; /* file desc to assoc this lock with */
+};
+
+#define afpfsByteRangeLock2FSCTL _IOWR('z', 23, struct ByteRangeLockPB2)
+
+/* return 0 on success, 1 on failure. To match the behavior of the
+ normal posix file locking (used in unixLock for example), we should
+ provide 'richer' return codes - specifically to differentiate between
+ 'file busy' and 'file system error' results */
+static int _AFPFSSetLock(const char *path, int fd, unsigned long long offset,
+ unsigned long long length, int setLockFlag)
+{
+ struct ByteRangeLockPB2 pb;
+ int err;
+
+ pb.unLockFlag = setLockFlag ? 0 : 1;
+ pb.startEndFlag = 0;
+ pb.offset = offset;
+ pb.length = length;
+ pb.fd = fd;
+ TRACE5("AFPLOCK setting lock %s for %d in range %llx:%llx\n",
+ (setLockFlag?"ON":"OFF"), fd, offset, length);
+ err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0);
+ if ( err==-1 ) {
+ TRACE4("AFPLOCK failed to fsctl() '%s' %d %s\n", path, errno,
+ strerror(errno));
+ return 1; // error
+ } else {
+ return 0;
+ }
+}
+
+/*
+ ** This routine checks if there is a RESERVED lock held on the specified
+ ** file by this or any other process. If such a lock is held, return
+ ** non-zero. If the file is unlocked or holds only SHARED locks, then
+ ** return zero.
+ */
+static int afpUnixCheckReservedLock(OsFile *id){
+ int r = 0;
+ unixFile *pFile = (unixFile*)id;
+
+ assert( pFile );
+ afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
+
+ /* Check if a thread in this process holds such a lock */
+ if( pFile->locktype>SHARED_LOCK ){
+ r = 1;
+ }
+
+ /* Otherwise see if some other process holds it.
+ */
+ if ( !r ) {
+ // lock the byte
+ int failed = _AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1,1);
+ if (failed) {
+ /* if we failed to get the lock then someone else must have it */
+ r = 1;
+ } else {
+ /* if we succeeded in taking the reserved lock, unlock it to restore
+ ** the original state */
+ _AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1, 0);
+ }
+ }
+ TRACE3("TEST WR-LOCK %d %d\n", pFile->h, r);
+
+ return r;
+}
+
+/* AFP-style locking following the behavior of unixLock, see the unixLock
+** function comments for details of lock management. */
+static int afpUnixLock(OsFile *id, int locktype)
+{
+ int rc = SQLITE_OK;
+ unixFile *pFile = (unixFile*)id;
+ afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
+ int gotPendingLock = 0;
+
+ assert( pFile );
+ TRACE5("LOCK %d %s was %s pid=%d\n", pFile->h,
+ locktypeName(locktype), locktypeName(pFile->locktype), getpid());
+ /* If there is already a lock of this type or more restrictive on the
+ ** OsFile, do nothing. Don't use the afp_end_lock: exit path, as
+ ** sqlite3OsEnterMutex() hasn't been called yet.
+ */
+ if( pFile->locktype>=locktype ){
+ TRACE3("LOCK %d %s ok (already held)\n", pFile->h,
+ locktypeName(locktype));
+ return SQLITE_OK;
+ }
+
+ /* Make sure the locking sequence is correct
+ */
+ assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
+ assert( locktype!=PENDING_LOCK );
+ assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
+
+ /* This mutex is needed because pFile->pLock is shared across threads
+ */
+ sqlite3OsEnterMutex();
+
+ /* Make sure the current thread owns the pFile.
+ */
+ rc = transferOwnership(pFile);
+ if( rc!=SQLITE_OK ){
+ sqlite3OsLeaveMutex();
+ return rc;
+ }
+
+ /* A PENDING lock is needed before acquiring a SHARED lock and before
+ ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will
+ ** be released.
+ */
+ if( locktype==SHARED_LOCK
+ || (locktype==EXCLUSIVE_LOCK && pFile->locktypefilePath, pFile->h,
+ PENDING_BYTE, 1, 1);
+ if (failed) {
+ rc = SQLITE_BUSY;
+ goto afp_end_lock;
+ }
+ }
+
+ /* If control gets to this point, then actually go ahead and make
+ ** operating system calls for the specified lock.
+ */
+ if( locktype==SHARED_LOCK ){
+ int lk, failed;
+ int tries = 0;
+
+ /* Now get the read-lock */
+ /* note that the quality of the randomness doesn't matter that much */
+ lk = random();
+ context->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1);
+ failed = _AFPFSSetLock(context->filePath, pFile->h,
+ SHARED_FIRST+context->sharedLockByte, 1, 1);
+
+ /* Drop the temporary PENDING lock */
+ if (_AFPFSSetLock(context->filePath, pFile->h, PENDING_BYTE, 1, 0)) {
+ rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
+ goto afp_end_lock;
+ }
+
+ if( failed ){
+ rc = SQLITE_BUSY;
+ } else {
+ pFile->locktype = SHARED_LOCK;
+ }
+ }else{
+ /* The request was for a RESERVED or EXCLUSIVE lock. It is
+ ** assumed that there is a SHARED or greater lock on the file
+ ** already.
+ */
+ int failed = 0;
+ assert( 0!=pFile->locktype );
+ if (locktype >= RESERVED_LOCK && pFile->locktype < RESERVED_LOCK) {
+ /* Acquire a RESERVED lock */
+ failed = _AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1,1);
+ }
+ if (!failed && locktype == EXCLUSIVE_LOCK) {
+ /* Acquire an EXCLUSIVE lock */
+
+ /* Remove the shared lock before trying the range. we'll need to
+ ** reestablish the shared lock if we can't get the afpUnixUnlock
+ */
+ if (!_AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST +
+ context->sharedLockByte, 1, 0)) {
+ /* now attemmpt to get the exclusive lock range */
+ failed = _AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST,
+ SHARED_SIZE, 1);
+ if (failed && _AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST +
+ context->sharedLockByte, 1, 1)) {
+ rc = SQLITE_IOERR_RDLOCK; /* this should never happen */
+ }
+ } else {
+ /* */
+ rc = SQLITE_IOERR_UNLOCK; /* this should never happen */
+ }
+ }
+ if( failed && rc == SQLITE_OK){
+ rc = SQLITE_BUSY;
+ }
+ }
+
+ if( rc==SQLITE_OK ){
+ pFile->locktype = locktype;
+ }else if( locktype==EXCLUSIVE_LOCK ){
+ pFile->locktype = PENDING_LOCK;
+ }
+
+afp_end_lock:
+ sqlite3OsLeaveMutex();
+ TRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype),
+ rc==SQLITE_OK ? "ok" : "failed");
+ return rc;
+}
+
+/*
+ ** Lower the locking level on file descriptor pFile to locktype. locktype
+ ** must be either NO_LOCK or SHARED_LOCK.
+ **
+ ** If the locking level of the file descriptor is already at or below
+ ** the requested locking level, this routine is a no-op.
+ */
+static int afpUnixUnlock(OsFile *id, int locktype) {
+ struct flock lock;
+ int rc = SQLITE_OK;
+ unixFile *pFile = (unixFile*)id;
+ afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
+
+ assert( pFile );
+ TRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype,
+ pFile->locktype, getpid());
+
+ assert( locktype<=SHARED_LOCK );
+ if( pFile->locktype<=locktype ){
+ return SQLITE_OK;
+ }
+ if( CHECK_THREADID(pFile) ){
+ return SQLITE_MISUSE;
+ }
+ sqlite3OsEnterMutex();
+ if( pFile->locktype>SHARED_LOCK ){
+ if( locktype==SHARED_LOCK ){
+ int failed = 0;
+
+ /* unlock the exclusive range - then re-establish the shared lock */
+ if (pFile->locktype==EXCLUSIVE_LOCK) {
+ failed = _AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST,
+ SHARED_SIZE, 0);
+ if (!failed) {
+ /* successfully removed the exclusive lock */
+ if (_AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST+
+ context->sharedLockByte, 1, 1)) {
+ /* failed to re-establish our shared lock */
+ rc = SQLITE_IOERR_RDLOCK; /* This should never happen */
+ }
+ } else {
+ /* This should never happen - failed to unlock the exclusive range */
+ rc = SQLITE_IOERR_UNLOCK;
+ }
+ }
+ }
+ if (rc == SQLITE_OK && pFile->locktype>=PENDING_LOCK) {
+ if (_AFPFSSetLock(context->filePath, pFile->h, PENDING_BYTE, 1, 0)){
+ /* failed to release the pending lock */
+ rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
+ }
+ }
+ if (rc == SQLITE_OK && pFile->locktype>=RESERVED_LOCK) {
+ if (_AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1, 0)) {
+ /* failed to release the reserved lock */
+ rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
+ }
+ }
+ }
+ if( locktype==NO_LOCK ){
+ int failed = _AFPFSSetLock(context->filePath, pFile->h,
+ SHARED_FIRST + context->sharedLockByte, 1, 0);
+ if (failed) {
+ rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
+ }
+ }
+ if (rc == SQLITE_OK)
+ pFile->locktype = locktype;
+ sqlite3OsLeaveMutex();
+ return rc;
+}
+
+/*
+ ** Close a file & cleanup AFP specific locking context
+ */
+static int afpUnixClose(OsFile **pId) {
+ unixFile *id = (unixFile*)*pId;
+
+ if( !id ) return SQLITE_OK;
+ afpUnixUnlock(*pId, NO_LOCK);
+ /* free the AFP locking structure */
+ if (id->lockingContext != NULL) {
+ if (((afpLockingContext *)id->lockingContext)->filePath != NULL)
+ sqlite3ThreadSafeFree(((afpLockingContext*)id->lockingContext)->filePath);
+ sqlite3ThreadSafeFree(id->lockingContext);
+ }
+
+ if( id->dirfd>=0 ) close(id->dirfd);
+ id->dirfd = -1;
+ close(id->h);
+ id->isOpen = 0;
+ TRACE2("CLOSE %-3d\n", id->h);
+ OpenCounter(-1);
+ sqlite3ThreadSafeFree(id);
+ *pId = 0;
+ return SQLITE_OK;
+}
+
+
+#pragma mark flock() style locking
+
+/*
+ ** The flockLockingContext is not used
+ */
+typedef void flockLockingContext;
+
+static int flockUnixCheckReservedLock(OsFile *id) {
+ unixFile *pFile = (unixFile*)id;
+
+ if (pFile->locktype == RESERVED_LOCK) {
+ return 1; // already have a reserved lock
+ } else {
+ // attempt to get the lock
+ int rc = flock(pFile->h, LOCK_EX | LOCK_NB);
+ if (!rc) {
+ // got the lock, unlock it
+ flock(pFile->h, LOCK_UN);
+ return 0; // no one has it reserved
+ }
+ return 1; // someone else might have it reserved
+ }
+}
+
+static int flockUnixLock(OsFile *id, int locktype) {
+ unixFile *pFile = (unixFile*)id;
+
+ // if we already have a lock, it is exclusive.
+ // Just adjust level and punt on outta here.
+ if (pFile->locktype > NO_LOCK) {
+ pFile->locktype = locktype;
+ return SQLITE_OK;
+ }
+
+ // grab an exclusive lock
+ int rc = flock(pFile->h, LOCK_EX | LOCK_NB);
+ if (rc) {
+ // didn't get, must be busy
+ return SQLITE_BUSY;
+ } else {
+ // got it, set the type and return ok
+ pFile->locktype = locktype;
+ return SQLITE_OK;
+ }
+}
+
+static int flockUnixUnlock(OsFile *id, int locktype) {
+ unixFile *pFile = (unixFile*)id;
+
+ assert( locktype<=SHARED_LOCK );
+
+ // no-op if possible
+ if( pFile->locktype==locktype ){
+ return SQLITE_OK;
+ }
+
+ // shared can just be set because we always have an exclusive
+ if (locktype==SHARED_LOCK) {
+ pFile->locktype = locktype;
+ return SQLITE_OK;
+ }
+
+ // no, really, unlock.
+ int rc = flock(pFile->h, LOCK_UN);
+ if (rc)
+ return SQLITE_IOERR_UNLOCK;
+ else {
+ pFile->locktype = NO_LOCK;
+ return SQLITE_OK;
+ }
+}
+
+/*
+ ** Close a file.
+ */
+static int flockUnixClose(OsFile **pId) {
+ unixFile *id = (unixFile*)*pId;
+
+ if( !id ) return SQLITE_OK;
+ flockUnixUnlock(*pId, NO_LOCK);
+
+ if( id->dirfd>=0 ) close(id->dirfd);
+ id->dirfd = -1;
+ sqlite3OsEnterMutex();
+
+ close(id->h);
+ sqlite3OsLeaveMutex();
+ id->isOpen = 0;
+ TRACE2("CLOSE %-3d\n", id->h);
+ OpenCounter(-1);
+ sqlite3ThreadSafeFree(id);
+ *pId = 0;
+ return SQLITE_OK;
+}
+
+#pragma mark Old-School .lock file based locking
+
+/*
+ ** The dotlockLockingContext structure contains all dotlock (.lock) lock
+ ** specific state
+ */
+typedef struct dotlockLockingContext dotlockLockingContext;
+struct dotlockLockingContext {
+ char *lockPath;
+};
+
+
+static int dotlockUnixCheckReservedLock(OsFile *id) {
+ unixFile *pFile = (unixFile*)id;
+ dotlockLockingContext *context =
+ (dotlockLockingContext *) pFile->lockingContext;
+
+ if (pFile->locktype == RESERVED_LOCK) {
+ return 1; // already have a reserved lock
+ } else {
+ struct stat statBuf;
+ if (lstat(context->lockPath,&statBuf) == 0)
+ // file exists, someone else has the lock
+ return 1;
+ else
+ // file does not exist, we could have it if we want it
+ return 0;
+ }
+}
+
+static int dotlockUnixLock(OsFile *id, int locktype) {
+ unixFile *pFile = (unixFile*)id;
+ dotlockLockingContext *context =
+ (dotlockLockingContext *) pFile->lockingContext;
+
+ // if we already have a lock, it is exclusive.
+ // Just adjust level and punt on outta here.
+ if (pFile->locktype > NO_LOCK) {
+ pFile->locktype = locktype;
+
+ /* Always update the timestamp on the old file */
+ utimes(context->lockPath,NULL);
+ return SQLITE_OK;
+ }
+
+ // check to see if lock file already exists
+ struct stat statBuf;
+ if (lstat(context->lockPath,&statBuf) == 0){
+ return SQLITE_BUSY; // it does, busy
+ }
+
+ // grab an exclusive lock
+ int fd = open(context->lockPath,O_RDONLY|O_CREAT|O_EXCL,0600);
+ if (fd < 0) {
+ // failed to open/create the file, someone else may have stolen the lock
+ return SQLITE_BUSY;
+ }
+ close(fd);
+
+ // got it, set the type and return ok
+ pFile->locktype = locktype;
+ return SQLITE_OK;
+}
+
+static int dotlockUnixUnlock(OsFile *id, int locktype) {
+ unixFile *pFile = (unixFile*)id;
+ dotlockLockingContext *context =
+ (dotlockLockingContext *) pFile->lockingContext;
+
+ assert( locktype<=SHARED_LOCK );
+
+ // no-op if possible
+ if( pFile->locktype==locktype ){
+ return SQLITE_OK;
+ }
+
+ // shared can just be set because we always have an exclusive
+ if (locktype==SHARED_LOCK) {
+ pFile->locktype = locktype;
+ return SQLITE_OK;
+ }
+
+ // no, really, unlock.
+ unlink(context->lockPath);
+ pFile->locktype = NO_LOCK;
+ return SQLITE_OK;
+}
+
+/*
+ ** Close a file.
+ */
+static int dotlockUnixClose(OsFile **pId) {
+ unixFile *id = (unixFile*)*pId;
+
+ if( !id ) return SQLITE_OK;
+ dotlockUnixUnlock(*pId, NO_LOCK);
+ /* free the dotlock locking structure */
+ if (id->lockingContext != NULL) {
+ if (((dotlockLockingContext *)id->lockingContext)->lockPath != NULL)
+ sqlite3ThreadSafeFree( ( (dotlockLockingContext *)
+ id->lockingContext)->lockPath);
+ sqlite3ThreadSafeFree(id->lockingContext);
+ }
+
+ if( id->dirfd>=0 ) close(id->dirfd);
+ id->dirfd = -1;
+ sqlite3OsEnterMutex();
+
+ close(id->h);
+
+ sqlite3OsLeaveMutex();
+ id->isOpen = 0;
+ TRACE2("CLOSE %-3d\n", id->h);
+ OpenCounter(-1);
+ sqlite3ThreadSafeFree(id);
+ *pId = 0;
+ return SQLITE_OK;
+}
+
+
+#pragma mark No locking
+
+/*
+ ** The nolockLockingContext is void
+ */
+typedef void nolockLockingContext;
+
+static int nolockUnixCheckReservedLock(OsFile *id) {
+ return 0;
+}
+
+static int nolockUnixLock(OsFile *id, int locktype) {
+ return SQLITE_OK;
+}
+
+static int nolockUnixUnlock(OsFile *id, int locktype) {
+ return SQLITE_OK;
+}
+
+/*
+ ** Close a file.
+ */
+static int nolockUnixClose(OsFile **pId) {
+ unixFile *id = (unixFile*)*pId;
+
+ if( !id ) return SQLITE_OK;
+ if( id->dirfd>=0 ) close(id->dirfd);
+ id->dirfd = -1;
+ sqlite3OsEnterMutex();
+
+ close(id->h);
+
+ sqlite3OsLeaveMutex();
+ id->isOpen = 0;
+ TRACE2("CLOSE %-3d\n", id->h);
+ OpenCounter(-1);
+ sqlite3ThreadSafeFree(id);
+ *pId = 0;
+ return SQLITE_OK;
+}
+
+#endif /* SQLITE_ENABLE_LOCKING_STYLE */
+
/*
** Turn a relative pathname into a full pathname. Return a pointer
** to the full pathname stored in space obtained from sqliteMalloc().
@@ -1663,36 +2362,243 @@ static const IoMethod sqlite3UnixIoMethod = {
unixCheckReservedLock,
};
+#ifdef SQLITE_ENABLE_LOCKING_STYLE
/*
-** Allocate memory for a unixFile. Initialize the new unixFile
-** to the value given in pInit and return a pointer to the new
-** OsFile. If we run out of memory, close the file and return NULL.
+ ** This vector defines all the methods that can operate on an OsFile
+ ** for unix with AFP style file locking.
+ */
+static const IoMethod sqlite3AFPLockingUnixIoMethod = {
+ afpUnixClose,
+ unixOpenDirectory,
+ unixRead,
+ unixWrite,
+ unixSeek,
+ unixTruncate,
+ unixSync,
+ unixSetFullSync,
+ unixFileHandle,
+ unixFileSize,
+ afpUnixLock,
+ afpUnixUnlock,
+ unixLockState,
+ afpUnixCheckReservedLock,
+};
+
+/*
+ ** This vector defines all the methods that can operate on an OsFile
+ ** for unix with flock() style file locking.
+ */
+static const IoMethod sqlite3FlockLockingUnixIoMethod = {
+ flockUnixClose,
+ unixOpenDirectory,
+ unixRead,
+ unixWrite,
+ unixSeek,
+ unixTruncate,
+ unixSync,
+ unixSetFullSync,
+ unixFileHandle,
+ unixFileSize,
+ flockUnixLock,
+ flockUnixUnlock,
+ unixLockState,
+ flockUnixCheckReservedLock,
+};
+
+/*
+ ** This vector defines all the methods that can operate on an OsFile
+ ** for unix with dotlock style file locking.
+ */
+static const IoMethod sqlite3DotlockLockingUnixIoMethod = {
+ dotlockUnixClose,
+ unixOpenDirectory,
+ unixRead,
+ unixWrite,
+ unixSeek,
+ unixTruncate,
+ unixSync,
+ unixSetFullSync,
+ unixFileHandle,
+ unixFileSize,
+ dotlockUnixLock,
+ dotlockUnixUnlock,
+ unixLockState,
+ dotlockUnixCheckReservedLock,
+};
+
+/*
+ ** This vector defines all the methods that can operate on an OsFile
+ ** for unix with dotlock style file locking.
+ */
+static const IoMethod sqlite3NolockLockingUnixIoMethod = {
+ nolockUnixClose,
+ unixOpenDirectory,
+ unixRead,
+ unixWrite,
+ unixSeek,
+ unixTruncate,
+ unixSync,
+ unixSetFullSync,
+ unixFileHandle,
+ unixFileSize,
+ nolockUnixLock,
+ nolockUnixUnlock,
+ unixLockState,
+ nolockUnixCheckReservedLock,
+};
+
+#endif /* SQLITE_ENABLE_LOCKING_STYLE */
+
+/*
+** Allocate memory for a new unixFile and initialize that unixFile.
+** Write a pointer to the new unixFile into *pId.
+** If we run out of memory, close the file and return an error.
*/
-static int allocateUnixFile(unixFile *pInit, OsFile **pId){
+#ifdef SQLITE_ENABLE_LOCKING_STYLE
+/*
+ ** When locking extensions are enabled, the filepath and locking style
+ ** are needed to determine the unixFile pMethod to use for locking operations.
+ ** The locking-style specific lockingContext data structure is created
+ ** and assigned here also.
+ */
+static int allocateUnixFile(
+ int h, /* Open file descriptor of file being opened */
+ OsFile **pId, /* Write completed initialization here */
+ const char *zFilename, /* Name of the file being opened */
+ int delFlag /* Delete-on-or-before-close flag */
+){
+ sqlite3LockingStyle lockingStyle;
unixFile *pNew;
- pInit->dirfd = -1;
- pInit->fullSync = 0;
- pInit->locktype = 0;
- pInit->offset = 0;
- SET_THREADID(pInit);
+ unixFile f;
+ int rc;
+
+ lockingStyle = sqlite3DetectLockingStyle(zFilename, h);
+ if ( lockingStyle == posixLockingStyle ) {
+ sqlite3OsEnterMutex();
+ rc = findLockInfo(h, &f.pLock, &f.pOpen);
+ sqlite3OsLeaveMutex();
+ if( rc ){
+ close(h);
+ unlink(zFilename);
+ return SQLITE_NOMEM;
+ }
+ } else {
+ // pLock and pOpen are only used for posix advisory locking
+ f.pLock = NULL;
+ f.pOpen = NULL;
+ }
+ if( delFlag ){
+ unlink(zFilename);
+ }
+ f.dirfd = -1;
+ f.fullSync = 0;
+ f.locktype = 0;
+ f.offset = 0;
+ f.h = h;
+ SET_THREADID(&f);
pNew = sqlite3ThreadSafeMalloc( sizeof(unixFile) );
if( pNew==0 ){
- close(pInit->h);
+ close(h);
sqlite3OsEnterMutex();
- releaseLockInfo(pInit->pLock);
- releaseOpenCnt(pInit->pOpen);
+ releaseLockInfo(f.pLock);
+ releaseOpenCnt(f.pOpen);
sqlite3OsLeaveMutex();
*pId = 0;
return SQLITE_NOMEM;
}else{
- *pNew = *pInit;
+ *pNew = f;
+ switch(lockingStyle) {
+ case afpLockingStyle:
+ /* afp locking uses the file path so it needs to be included in
+ ** the afpLockingContext */
+ pNew->pMethod = &sqlite3AFPLockingUnixIoMethod;
+ pNew->lockingContext =
+ sqlite3ThreadSafeMalloc(sizeof(afpLockingContext));
+ ((afpLockingContext *)pNew->lockingContext)->filePath =
+ sqlite3ThreadSafeMalloc(strlen(zFilename) + 1);
+ strcpy(((afpLockingContext *)pNew->lockingContext)->filePath,
+ zFilename);
+ srandomdev();
+ break;
+ case flockLockingStyle:
+ /* flock locking doesn't need additional lockingContext information */
+ pNew->pMethod = &sqlite3FlockLockingUnixIoMethod;
+ break;
+ case dotlockLockingStyle:
+ /* dotlock locking uses the file path so it needs to be included in
+ ** the dotlockLockingContext */
+ pNew->pMethod = &sqlite3DotlockLockingUnixIoMethod;
+ pNew->lockingContext = sqlite3ThreadSafeMalloc(
+ sizeof(dotlockLockingContext));
+ ((dotlockLockingContext *)pNew->lockingContext)->lockPath =
+ sqlite3ThreadSafeMalloc(strlen(zFilename) + strlen(".lock") + 1);
+ sprintf(((dotlockLockingContext *)pNew->lockingContext)->lockPath,
+ "%s.lock", zFilename);
+ break;
+ case posixLockingStyle:
+ /* posix locking doesn't need additional lockingContext information */
+ pNew->pMethod = &sqlite3UnixIoMethod;
+ break;
+ case noLockingStyle:
+ case unsupportedLockingStyle:
+ default:
+ pNew->pMethod = &sqlite3NolockLockingUnixIoMethod;
+ }
+ *pId = (OsFile*)pNew;
+ OpenCounter(+1);
+ return SQLITE_OK;
+ }
+}
+#else /* SQLITE_ENABLE_LOCKING_STYLE */
+static int allocateUnixFile(
+ int h, /* Open file descriptor on file being opened */
+ OsFile **pId, /* Write the resul unixFile structure here */
+ const char *zFilename, /* Name of the file being opened */
+ int delFlag /* If true, delete the file on or before closing */
+){
+ unixFile *pNew;
+ unixFile f;
+ f.pLock = NULL;
+ f.pOpen = NULL;
+ f.pMethod = NULL;
+ f.isOpen = 0;
+ int rc;
+
+ sqlite3OsEnterMutex();
+ rc = findLockInfo(h, &f.pLock, &f.pOpen);
+ sqlite3OsLeaveMutex();
+ if( delFlag ){
+ unlink(zFilename);
+ }
+ if( rc ){
+ close(h);
+ return SQLITE_NOMEM;
+ }
+ TRACE3("OPEN %-3d %s\n", h, zFilename);
+ f.dirfd = -1;
+ f.fullSync = 0;
+ f.locktype = 0;
+ f.offset = 0;
+ f.h = h;
+ SET_THREADID(&f);
+ pNew = sqlite3ThreadSafeMalloc( sizeof(unixFile) );
+ if( pNew==0 ){
+ close(h);
+ sqlite3OsEnterMutex();
+ releaseLockInfo(f.pLock);
+ releaseOpenCnt(f.pOpen);
+ sqlite3OsLeaveMutex();
+ *pId = 0;
+ return SQLITE_NOMEM;
+ }else{
+ *pNew = f;
pNew->pMethod = &sqlite3UnixIoMethod;
*pId = (OsFile*)pNew;
OpenCounter(+1);
return SQLITE_OK;
}
}
-
+#endif /* SQLITE_ENABLE_LOCKING_STYLE */
#endif /* SQLITE_OMIT_DISKIO */
/***************************************************************************
@@ -1701,6 +2607,23 @@ static int allocateUnixFile(unixFile *pInit, OsFile **pId){
****************************************************************************/
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+/*
+** Interfaces for opening a shared library, finding entry points
+** within the shared library, and closing the shared library.
+*/
+#include
+void *sqlite3UnixDlopen(const char *zFilename){
+ return dlopen(zFilename, RTLD_NOW | RTLD_GLOBAL);
+}
+void *sqlite3UnixDlsym(void *pHandle, const char *zSymbol){
+ return dlsym(pHandle, zSymbol);
+}
+int sqlite3UnixDlclose(void *pHandle){
+ return dlclose(pHandle);
+}
+#endif /* SQLITE_OMIT_LOAD_EXTENSION */
+
/*
** Get information to seed the random number generator. The seed
** is written into the buffer zBuf[256]. The calling function must
diff --git a/dlls/sqlite/sqlite-source/os_win.c b/dlls/sqlite/sqlite-source/os_win.c
index d6b6310e..b3c4771b 100644
--- a/dlls/sqlite/sqlite-source/os_win.c
+++ b/dlls/sqlite/sqlite-source/os_win.c
@@ -40,6 +40,7 @@
*/
#if defined(_WIN32_WCE)
# define OS_WINCE 1
+# define AreFileApisANSI() 1
#else
# define OS_WINCE 0
#endif
@@ -124,16 +125,14 @@ int sqlite3_os_type = 0;
#endif /* OS_WINCE */
/*
-** Convert a UTF-8 string to UTF-32. Space to hold the returned string
-** is obtained from sqliteMalloc.
+** Convert a UTF-8 string to microsoft unicode (UTF-16?).
+**
+** Space to hold the returned string is obtained from sqliteMalloc.
*/
static WCHAR *utf8ToUnicode(const char *zFilename){
int nChar;
WCHAR *zWideFilename;
- if( !isNT() ){
- return 0;
- }
nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
zWideFilename = sqliteMalloc( nChar*sizeof(zWideFilename[0]) );
if( zWideFilename==0 ){
@@ -148,7 +147,7 @@ static WCHAR *utf8ToUnicode(const char *zFilename){
}
/*
-** Convert UTF-32 to UTF-8. Space to hold the returned string is
+** Convert microsoft unicode to UTF-8. Space to hold the returned string is
** obtained from sqliteMalloc().
*/
static char *unicodeToUtf8(const WCHAR *zWideFilename){
@@ -169,6 +168,91 @@ static char *unicodeToUtf8(const WCHAR *zWideFilename){
return zFilename;
}
+/*
+** Convert an ansi string to microsoft unicode, based on the
+** current codepage settings for file apis.
+**
+** Space to hold the returned string is obtained
+** from sqliteMalloc.
+*/
+static WCHAR *mbcsToUnicode(const char *zFilename){
+ int nByte;
+ WCHAR *zMbcsFilename;
+ int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
+
+ nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, NULL,0)*sizeof(WCHAR);
+ zMbcsFilename = sqliteMalloc( nByte*sizeof(zMbcsFilename[0]) );
+ if( zMbcsFilename==0 ){
+ return 0;
+ }
+ nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename, nByte);
+ if( nByte==0 ){
+ sqliteFree(zMbcsFilename);
+ zMbcsFilename = 0;
+ }
+ return zMbcsFilename;
+}
+
+/*
+** Convert microsoft unicode to multibyte character string, based on the
+** user's Ansi codepage.
+**
+** Space to hold the returned string is obtained from
+** sqliteMalloc().
+*/
+static char *unicodeToMbcs(const WCHAR *zWideFilename){
+ int nByte;
+ char *zFilename;
+ int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
+
+ nByte = WideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0);
+ zFilename = sqliteMalloc( nByte );
+ if( zFilename==0 ){
+ return 0;
+ }
+ nByte = WideCharToMultiByte(codepage, 0, zWideFilename, -1, zFilename, nByte,
+ 0, 0);
+ if( nByte == 0 ){
+ sqliteFree(zFilename);
+ zFilename = 0;
+ }
+ return zFilename;
+}
+
+/*
+** Convert multibyte character string to UTF-8. Space to hold the
+** returned string is obtained from sqliteMalloc().
+*/
+static char *mbcsToUtf8(const char *zFilename){
+ char *zFilenameUtf8;
+ WCHAR *zTmpWide;
+
+ zTmpWide = mbcsToUnicode(zFilename);
+ if( zTmpWide==0 ){
+ return 0;
+ }
+ zFilenameUtf8 = unicodeToUtf8(zTmpWide);
+ sqliteFree(zTmpWide);
+ return zFilenameUtf8;
+}
+
+/*
+** Convert UTF-8 to multibyte character string. Space to hold the
+** returned string is obtained from sqliteMalloc().
+*/
+static char *utf8ToMbcs(const char *zFilename){
+ char *zFilenameMbcs;
+ WCHAR *zTmpWide;
+
+ zTmpWide = utf8ToUnicode(zFilename);
+ if( zTmpWide==0 ){
+ return 0;
+ }
+ zFilenameMbcs = unicodeToMbcs(zTmpWide);
+ sqliteFree(zTmpWide);
+ return zFilenameMbcs;
+}
+
#if OS_WINCE
/*************************************************************************
** This section contains code for WinCE only.
@@ -476,22 +560,60 @@ static BOOL winceLockFileEx(
#endif /* OS_WINCE */
/*
-** Delete the named file
+** Convert a UTF-8 filename into whatever form the underlying
+** operating system wants filenames in. Space to hold the result
+** is obtained from sqliteMalloc and must be freed by the calling
+** function.
*/
+static void *convertUtf8Filename(const char *zFilename){
+ void *zConverted = 0;
+ if( isNT() ){
+ zConverted = utf8ToUnicode(zFilename);
+ }else{
+ zConverted = utf8ToMbcs(zFilename);
+ }
+ /* caller will handle out of memory */
+ return zConverted;
+}
+
+/*
+** Delete the named file.
+**
+** Note that windows does not allow a file to be deleted if some other
+** process has it open. Sometimes a virus scanner or indexing program
+** will open a journal file shortly after it is created in order to do
+** whatever it is it does. While this other process is holding the
+** file open, we will be unable to delete it. To work around this
+** problem, we delay 100 milliseconds and try to delete again. Up
+** to MX_DELETION_ATTEMPTs deletion attempts are run before giving
+** up and returning an error.
+*/
+#define MX_DELETION_ATTEMPTS 3
int sqlite3WinDelete(const char *zFilename){
- WCHAR *zWide = utf8ToUnicode(zFilename);
- if( zWide ){
- DeleteFileW(zWide);
- sqliteFree(zWide);
+ int cnt = 0;
+ int rc;
+ void *zConverted = convertUtf8Filename(zFilename);
+ if( zConverted==0 ){
+ return SQLITE_NOMEM;
+ }
+ if( isNT() ){
+ do{
+ rc = DeleteFileW(zConverted);
+ }while( rc==0 && GetFileAttributesW(zConverted)!=0xffffffff
+ && cnt++ < MX_DELETION_ATTEMPTS && (Sleep(100), 1) );
}else{
#if OS_WINCE
return SQLITE_NOMEM;
#else
- DeleteFileA(zFilename);
+ do{
+ rc = DeleteFileA(zConverted);
+ }while( rc==0 && GetFileAttributesA(zConverted)!=0xffffffff
+ && cnt++ < MX_DELETION_ATTEMPTS && (Sleep(100), 1) );
#endif
}
+ sqliteFree(zConverted);
TRACE2("DELETE \"%s\"\n", zFilename);
- return SQLITE_OK;
+ return rc!=0 ? SQLITE_OK : SQLITE_IOERR;
}
/*
@@ -499,17 +621,20 @@ int sqlite3WinDelete(const char *zFilename){
*/
int sqlite3WinFileExists(const char *zFilename){
int exists = 0;
- WCHAR *zWide = utf8ToUnicode(zFilename);
- if( zWide ){
- exists = GetFileAttributesW(zWide) != 0xffffffff;
- sqliteFree(zWide);
+ void *zConverted = convertUtf8Filename(zFilename);
+ if( zConverted==0 ){
+ return SQLITE_NOMEM;
+ }
+ if( isNT() ){
+ exists = GetFileAttributesW((WCHAR*)zConverted) != 0xffffffff;
}else{
#if OS_WINCE
return SQLITE_NOMEM;
#else
- exists = GetFileAttributesA(zFilename) != 0xffffffff;
+ exists = GetFileAttributesA((char*)zConverted) != 0xffffffff;
#endif
}
+ sqliteFree(zConverted);
return exists;
}
@@ -536,10 +661,14 @@ int sqlite3WinOpenReadWrite(
){
winFile f;
HANDLE h;
- WCHAR *zWide = utf8ToUnicode(zFilename);
+ void *zConverted = convertUtf8Filename(zFilename);
+ if( zConverted==0 ){
+ return SQLITE_NOMEM;
+ }
assert( *pId==0 );
- if( zWide ){
- h = CreateFileW(zWide,
+
+ if( isNT() ){
+ h = CreateFileW((WCHAR*)zConverted,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
@@ -548,16 +677,16 @@ int sqlite3WinOpenReadWrite(
NULL
);
if( h==INVALID_HANDLE_VALUE ){
- h = CreateFileW(zWide,
+ h = CreateFileW((WCHAR*)zConverted,
GENERIC_READ,
- FILE_SHARE_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL
);
if( h==INVALID_HANDLE_VALUE ){
- sqliteFree(zWide);
+ sqliteFree(zConverted);
return SQLITE_CANTOPEN;
}
*pReadonly = 1;
@@ -567,16 +696,15 @@ int sqlite3WinOpenReadWrite(
#if OS_WINCE
if (!winceCreateLock(zFilename, &f)){
CloseHandle(h);
- sqliteFree(zWide);
+ sqliteFree(zConverted);
return SQLITE_CANTOPEN;
}
#endif
- sqliteFree(zWide);
}else{
#if OS_WINCE
return SQLITE_NOMEM;
#else
- h = CreateFileA(zFilename,
+ h = CreateFileA((char*)zConverted,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
@@ -585,15 +713,16 @@ int sqlite3WinOpenReadWrite(
NULL
);
if( h==INVALID_HANDLE_VALUE ){
- h = CreateFileA(zFilename,
+ h = CreateFileA((char*)zConverted,
GENERIC_READ,
- FILE_SHARE_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL
);
if( h==INVALID_HANDLE_VALUE ){
+ sqliteFree(zConverted);
return SQLITE_CANTOPEN;
}
*pReadonly = 1;
@@ -602,6 +731,9 @@ int sqlite3WinOpenReadWrite(
}
#endif /* OS_WINCE */
}
+
+ sqliteFree(zConverted);
+
f.h = h;
#if OS_WINCE
f.zDeleteOnClose = 0;
@@ -624,12 +756,21 @@ int sqlite3WinOpenReadWrite(
** On success, write the file handle into *id and return SQLITE_OK.
**
** On failure, return SQLITE_CANTOPEN.
+**
+** Sometimes if we have just deleted a prior journal file, windows
+** will fail to open a new one because there is a "pending delete".
+** To work around this bug, we pause for 100 milliseconds and attempt
+** a second open after the first one fails. The whole operation only
+** fails if both open attempts are unsuccessful.
*/
int sqlite3WinOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){
winFile f;
HANDLE h;
- int fileflags;
- WCHAR *zWide = utf8ToUnicode(zFilename);
+ DWORD fileflags;
+ void *zConverted = convertUtf8Filename(zFilename);
+ if( zConverted==0 ){
+ return SQLITE_NOMEM;
+ }
assert( *pId == 0 );
fileflags = FILE_FLAG_RANDOM_ACCESS;
#if !OS_WINCE
@@ -637,38 +778,47 @@ int sqlite3WinOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){
fileflags |= FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE;
}
#endif
- if( zWide ){
- h = CreateFileW(zWide,
- GENERIC_READ | GENERIC_WRITE,
- 0,
- NULL,
- CREATE_ALWAYS,
- fileflags,
- NULL
- );
- sqliteFree(zWide);
+ if( isNT() ){
+ int cnt = 0;
+ do{
+ h = CreateFileW((WCHAR*)zConverted,
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ CREATE_ALWAYS,
+ fileflags,
+ NULL
+ );
+ }while( h==INVALID_HANDLE_VALUE && cnt++ < 2 && (Sleep(100), 1) );
}else{
#if OS_WINCE
return SQLITE_NOMEM;
#else
- h = CreateFileA(zFilename,
- GENERIC_READ | GENERIC_WRITE,
- 0,
- NULL,
- CREATE_ALWAYS,
- fileflags,
- NULL
- );
+ int cnt = 0;
+ do{
+ h = CreateFileA((char*)zConverted,
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ CREATE_ALWAYS,
+ fileflags,
+ NULL
+ );
+ }while( h==INVALID_HANDLE_VALUE && cnt++ < 2 && (Sleep(100), 1) );
#endif /* OS_WINCE */
}
+#if OS_WINCE
+ if( delFlag && h!=INVALID_HANDLE_VALUE ){
+ f.zDeleteOnClose = zConverted;
+ zConverted = 0;
+ }
+ f.hMutex = NULL;
+#endif
+ sqliteFree(zConverted);
if( h==INVALID_HANDLE_VALUE ){
return SQLITE_CANTOPEN;
}
f.h = h;
-#if OS_WINCE
- f.zDeleteOnClose = delFlag ? utf8ToUnicode(zFilename) : 0;
- f.hMutex = NULL;
-#endif
TRACE3("OPEN EX %d \"%s\"\n", h, zFilename);
return allocateWinFile(&f, pId);
}
@@ -683,10 +833,13 @@ int sqlite3WinOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){
int sqlite3WinOpenReadOnly(const char *zFilename, OsFile **pId){
winFile f;
HANDLE h;
- WCHAR *zWide = utf8ToUnicode(zFilename);
+ void *zConverted = convertUtf8Filename(zFilename);
+ if( zConverted==0 ){
+ return SQLITE_NOMEM;
+ }
assert( *pId==0 );
- if( zWide ){
- h = CreateFileW(zWide,
+ if( isNT() ){
+ h = CreateFileW((WCHAR*)zConverted,
GENERIC_READ,
0,
NULL,
@@ -694,12 +847,11 @@ int sqlite3WinOpenReadOnly(const char *zFilename, OsFile **pId){
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL
);
- sqliteFree(zWide);
}else{
#if OS_WINCE
return SQLITE_NOMEM;
#else
- h = CreateFileA(zFilename,
+ h = CreateFileA((char*)zConverted,
GENERIC_READ,
0,
NULL,
@@ -709,6 +861,7 @@ int sqlite3WinOpenReadOnly(const char *zFilename, OsFile **pId){
);
#endif
}
+ sqliteFree(zConverted);
if( h==INVALID_HANDLE_VALUE ){
return SQLITE_CANTOPEN;
}
@@ -774,9 +927,21 @@ int sqlite3WinTempFileName(char *zBuf){
strncpy(zTempPath, zMulti, SQLITE_TEMPNAME_SIZE-30);
zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0;
sqliteFree(zMulti);
+ }else{
+ return SQLITE_NOMEM;
}
}else{
- GetTempPathA(SQLITE_TEMPNAME_SIZE-30, zTempPath);
+ char *zUtf8;
+ char zMbcsPath[SQLITE_TEMPNAME_SIZE];
+ GetTempPathA(SQLITE_TEMPNAME_SIZE-30, zMbcsPath);
+ zUtf8 = mbcsToUtf8(zMbcsPath);
+ if( zUtf8 ){
+ strncpy(zTempPath, zUtf8, SQLITE_TEMPNAME_SIZE-30);
+ zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0;
+ sqliteFree(zUtf8);
+ }else{
+ return SQLITE_NOMEM;
+ }
}
for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
zTempPath[i] = 0;
@@ -796,12 +961,24 @@ int sqlite3WinTempFileName(char *zBuf){
/*
** Close a file.
+**
+** It is reported that an attempt to close a handle might sometimes
+** fail. This is a very unreasonable result, but windows is notorious
+** for being unreasonable so I do not doubt that it might happen. If
+** the close fails, we pause for 100 milliseconds and try again. As
+** many as MX_CLOSE_ATTEMPT attempts to close the handle are made before
+** giving up and returning an error.
*/
+#define MX_CLOSE_ATTEMPT 3
static int winClose(OsFile **pId){
winFile *pFile;
+ int rc = 1;
if( pId && (pFile = (winFile*)*pId)!=0 ){
+ int rc, cnt = 0;
TRACE2("CLOSE %d\n", pFile->h);
- CloseHandle(pFile->h);
+ do{
+ rc = CloseHandle(pFile->h);
+ }while( rc==0 && cnt++ < MX_CLOSE_ATTEMPT && (Sleep(100), 1) );
#if OS_WINCE
winceDestroyLock(pFile);
if( pFile->zDeleteOnClose ){
@@ -813,7 +990,7 @@ static int winClose(OsFile **pId){
sqliteFree(pFile);
*pId = 0;
}
- return SQLITE_OK;
+ return rc ? SQLITE_OK : SQLITE_IOERR;
}
/*
@@ -824,15 +1001,16 @@ static int winClose(OsFile **pId){
static int winRead(OsFile *id, void *pBuf, int amt){
DWORD got;
assert( id!=0 );
- SimulateIOError(SQLITE_IOERR);
+ SimulateIOError(return SQLITE_IOERR_READ);
TRACE3("READ %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype);
if( !ReadFile(((winFile*)id)->h, pBuf, amt, &got, 0) ){
- got = 0;
+ return SQLITE_IOERR_READ;
}
if( got==(DWORD)amt ){
return SQLITE_OK;
}else{
- return SQLITE_IOERR;
+ memset(&((char*)pBuf)[got], 0, amt-got);
+ return SQLITE_IOERR_SHORT_READ;
}
}
@@ -844,8 +1022,8 @@ static int winWrite(OsFile *id, const void *pBuf, int amt){
int rc = 0;
DWORD wrote;
assert( id!=0 );
- SimulateIOError(SQLITE_IOERR);
- SimulateDiskfullError;
+ SimulateIOError(return SQLITE_IOERR_READ);
+ SimulateDiskfullError(return SQLITE_FULL);
TRACE3("WRITE %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype);
assert( amt>0 );
while( amt>0 && (rc = WriteFile(((winFile*)id)->h, pBuf, amt, &wrote, 0))!=0
@@ -871,11 +1049,11 @@ static int winWrite(OsFile *id, const void *pBuf, int amt){
*/
static int winSeek(OsFile *id, i64 offset){
LONG upperBits = (LONG)(offset>>32);
- LONG lowerBits = (LONG)(offset) & 0xffffffff;
+ LONG lowerBits = (LONG)(offset & 0xffffffff);
DWORD rc;
assert( id!=0 );
#ifdef SQLITE_TEST
- if( offset ) SimulateDiskfullError
+ if( offset ) SimulateDiskfullError(return SQLITE_FULL);
#endif
SEEK(offset/1024 + 1);
rc = SetFilePointer(((winFile*)id)->h, lowerBits, &upperBits, FILE_BEGIN);
@@ -904,7 +1082,7 @@ static int winSync(OsFile *id, int dataOnly){
** than UNIX.
*/
int sqlite3WinSyncDirectory(const char *zDirname){
- SimulateIOError(SQLITE_IOERR);
+ SimulateIOError(return SQLITE_IOERR_READ);
return SQLITE_OK;
}
@@ -915,7 +1093,7 @@ static int winTruncate(OsFile *id, i64 nByte){
LONG upperBits = (LONG)(nByte>>32);
assert( id!=0 );
TRACE3("TRUNCATE %d %lld\n", ((winFile*)id)->h, nByte);
- SimulateIOError(SQLITE_IOERR);
+ SimulateIOError(return SQLITE_IOERR_TRUNCATE);
SetFilePointer(((winFile*)id)->h, (LONG)nByte, &upperBits, FILE_BEGIN);
SetEndOfFile(((winFile*)id)->h);
return SQLITE_OK;
@@ -927,7 +1105,7 @@ static int winTruncate(OsFile *id, i64 nByte){
static int winFileSize(OsFile *id, i64 *pSize){
DWORD upperBits, lowerBits;
assert( id!=0 );
- SimulateIOError(SQLITE_IOERR);
+ SimulateIOError(return SQLITE_IOERR_FSTAT);
lowerBits = GetFileSize(((winFile*)id)->h, &upperBits);
*pSize = (((i64)upperBits)<<32) + lowerBits;
return SQLITE_OK;
@@ -982,20 +1160,24 @@ static int unlockReadLock(winFile *pFile){
*/
int sqlite3WinIsDirWritable(char *zDirname){
int fileAttr;
- WCHAR *zWide;
+ void *zConverted;
if( zDirname==0 ) return 0;
if( !isNT() && strlen(zDirname)>MAX_PATH ) return 0;
- zWide = utf8ToUnicode(zDirname);
- if( zWide ){
- fileAttr = GetFileAttributesW(zWide);
- sqliteFree(zWide);
+
+ zConverted = convertUtf8Filename(zDirname);
+ if( zConverted==0 ){
+ return SQLITE_NOMEM;
+ }
+ if( isNT() ){
+ fileAttr = GetFileAttributesW((WCHAR*)zConverted);
}else{
#if OS_WINCE
return 0;
#else
- fileAttr = GetFileAttributesA(zDirname);
+ fileAttr = GetFileAttributesA((char*)zConverted);
#endif
}
+ sqliteFree(zConverted);
if( fileAttr == 0xffffffff ) return 0;
if( (fileAttr & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY ){
return 0;
@@ -1184,7 +1366,7 @@ static int winUnlock(OsFile *id, int locktype){
if( locktype==SHARED_LOCK && !getReadLock(pFile) ){
/* This should never happen. We should always be able to
** reacquire the read lock */
- rc = SQLITE_IOERR;
+ rc = SQLITE_IOERR_UNLOCK;
}
}
if( type>=RESERVED_LOCK ){
@@ -1218,24 +1400,33 @@ char *sqlite3WinFullPathname(const char *zRelative){
/* WinCE has no concept of a relative pathname, or so I am told. */
zFull = sqliteStrDup(zRelative);
#else
- char *zNotUsed;
- WCHAR *zWide;
int nByte;
- zWide = utf8ToUnicode(zRelative);
- if( zWide ){
- WCHAR *zTemp, *zNotUsedW;
- nByte = GetFullPathNameW(zWide, 0, 0, &zNotUsedW) + 1;
+ void *zConverted;
+ zConverted = convertUtf8Filename(zRelative);
+ if( isNT() ){
+ WCHAR *zTemp;
+ nByte = GetFullPathNameW((WCHAR*)zConverted, 0, 0, 0) + 3;
zTemp = sqliteMalloc( nByte*sizeof(zTemp[0]) );
- if( zTemp==0 ) return 0;
- GetFullPathNameW(zWide, nByte, zTemp, &zNotUsedW);
- sqliteFree(zWide);
+ if( zTemp==0 ){
+ sqliteFree(zConverted);
+ return 0;
+ }
+ GetFullPathNameW((WCHAR*)zConverted, nByte, zTemp, 0);
+ sqliteFree(zConverted);
zFull = unicodeToUtf8(zTemp);
sqliteFree(zTemp);
}else{
- nByte = GetFullPathNameA(zRelative, 0, 0, &zNotUsed) + 1;
- zFull = sqliteMalloc( nByte*sizeof(zFull[0]) );
- if( zFull==0 ) return 0;
- GetFullPathNameA(zRelative, nByte, zFull, &zNotUsed);
+ char *zTemp;
+ nByte = GetFullPathNameA((char*)zConverted, 0, 0, 0) + 3;
+ zTemp = sqliteMalloc( nByte*sizeof(zTemp[0]) );
+ if( zTemp==0 ){
+ sqliteFree(zConverted);
+ return 0;
+ }
+ GetFullPathNameA((char*)zConverted, nByte, zTemp, 0);
+ sqliteFree(zConverted);
+ zFull = mbcsToUtf8(zTemp);
+ sqliteFree(zTemp);
}
#endif
return zFull;
@@ -1317,6 +1508,45 @@ static int allocateWinFile(winFile *pInit, OsFile **pId){
** with other miscellanous aspects of the operating system interface
****************************************************************************/
+#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
+/*
+** Interfaces for opening a shared library, finding entry points
+** within the shared library, and closing the shared library.
+*/
+void *sqlite3WinDlopen(const char *zFilename){
+ HANDLE h;
+ void *zConverted = convertUtf8Filename(zFilename);
+ if( zConverted==0 ){
+ return 0;
+ }
+ if( isNT() ){
+ h = LoadLibraryW((WCHAR*)zConverted);
+ }else{
+#if OS_WINCE
+ return 0;
+#else
+ h = LoadLibraryA((char*)zConverted);
+#endif
+ }
+ sqliteFree(zConverted);
+ return (void*)h;
+
+}
+void *sqlite3WinDlsym(void *pHandle, const char *zSymbol){
+#if OS_WINCE
+ /* The GetProcAddressA() routine is only available on wince. */
+ return GetProcAddressA((HANDLE)pHandle, zSymbol);
+#else
+ /* All other windows platforms expect GetProcAddress() to take
+ ** an Ansi string regardless of the _UNICODE setting */
+ return GetProcAddress((HANDLE)pHandle, zSymbol);
+#endif
+}
+int sqlite3WinDlclose(void *pHandle){
+ return FreeLibrary((HANDLE)pHandle);
+}
+#endif /* !SQLITE_OMIT_LOAD_EXTENSION */
+
/*
** Get information to seed the random number generator. The seed
** is written into the buffer zBuf[256]. The calling function must
diff --git a/dlls/sqlite/sqlite-source/pager.c b/dlls/sqlite/sqlite-source/pager.c
index 8ccbb587..8e47694f 100644
--- a/dlls/sqlite/sqlite-source/pager.c
+++ b/dlls/sqlite/sqlite-source/pager.c
@@ -31,6 +31,7 @@
** Macros for troubleshooting. Normally turned off
*/
#if 0
+#define sqlite3DebugPrintf printf
#define TRACE1(X) sqlite3DebugPrintf(X)
#define TRACE2(X,Y) sqlite3DebugPrintf(X,Y)
#define TRACE3(X,Y,Z) sqlite3DebugPrintf(X,Y,Z)
@@ -161,7 +162,8 @@ struct PgHdr {
u8 needSync; /* Sync journal before writing this page */
u8 alwaysRollback; /* Disable dont_rollback() for this page */
short int nRef; /* Number of users of this page */
- PgHdr *pDirty; /* Dirty pages sorted by PgHdr.pgno */
+ PgHdr *pDirty, *pPrevDirty; /* Dirty pages */
+ u32 notUsed; /* Buffer space */
#ifdef SQLITE_CHECK_PAGES
u32 pageHash;
#endif
@@ -207,24 +209,6 @@ struct PgHistory {
#define PGHDR_TO_HIST(P,PGR) \
((PgHistory*)&((char*)(&(P)[1]))[(PGR)->pageSize+(PGR)->nExtra])
-/*
-** How big to make the hash table used for locating in-memory pages
-** by page number. This macro looks a little silly, but is evaluated
-** at compile-time, not run-time (at least for gcc this is true).
-*/
-#define N_PG_HASH (\
- (MAX_PAGES>1024)?2048: \
- (MAX_PAGES>512)?1024: \
- (MAX_PAGES>256)?512: \
- (MAX_PAGES>128)?256: \
- (MAX_PAGES>64)?128:64 \
-)
-
-/*
-** Hash a page number
-*/
-#define pager_hash(PN) ((PN)&(N_PG_HASH-1))
-
/*
** A open page cache is an instance of the following structure.
**
@@ -248,7 +232,6 @@ struct Pager {
u8 fullSync; /* Do extra syncs of the journal for robustness */
u8 full_fsync; /* Use F_FULLFSYNC when available */
u8 state; /* PAGER_UNLOCK, _SHARED, _RESERVED, etc. */
- u8 errCode; /* One of several kinds of errors */
u8 tempFile; /* zFilename is a temporary file */
u8 readOnly; /* True for a read-only database */
u8 needSync; /* True if an fsync() is needed on the journal */
@@ -256,6 +239,7 @@ struct Pager {
u8 alwaysRollback; /* Disable dont_rollback() for all pages */
u8 memDb; /* True to inhibit all file I/O */
u8 setMaster; /* True if a m-j name has been written to jrnl */
+ int errCode; /* One of several kinds of errors */
int dbSize; /* Number of pages in the file */
int origDbSize; /* dbSize before the current change */
int stmtSize; /* Size of database (in pages) at stmt_begin() */
@@ -280,6 +264,7 @@ struct Pager {
PgHdr *pFirstSynced; /* First free page with PgHdr.needSync==0 */
PgHdr *pAll; /* List of all pages */
PgHdr *pStmt; /* List of pages in the statement subjournal */
+ PgHdr *pDirty; /* List of all dirty pages */
i64 journalOff; /* Current byte offset in the journal file */
i64 journalHdr; /* Byte offset to previous journal header */
i64 stmtHdrOff; /* First journal header written this statement */
@@ -294,7 +279,8 @@ struct Pager {
void (*xReiniter)(void*,int); /* Call this routine when reloading pages */
void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
void *pCodecArg; /* First argument to xCodec() */
- PgHdr *aHash[N_PG_HASH]; /* Hash table to map page number to PgHdr */
+ int nHash; /* Size of the pager hash table */
+ PgHdr **aHash; /* Hash table to map page number to PgHdr */
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
Pager *pNext; /* Linked list of pagers in this thread */
#endif
@@ -365,7 +351,9 @@ static const unsigned char aJournalMagic[] = {
/*
** The default size of a disk sector
*/
-#define PAGER_SECTOR_SIZE 512
+#ifndef PAGER_SECTOR_SIZE
+# define PAGER_SECTOR_SIZE 512
+#endif
/*
** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is
@@ -385,14 +373,14 @@ static const unsigned char aJournalMagic[] = {
/*
** Enable reference count tracking (for debugging) here:
*/
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_TEST
int pager3_refinfo_enable = 0;
static void pager_refinfo(PgHdr *p){
static int cnt = 0;
if( !pager3_refinfo_enable ) return;
sqlite3DebugPrintf(
- "REFCNT: %4d addr=%p nRef=%d\n",
- p->pgno, PGHDR_TO_DATA(p), p->nRef
+ "REFCNT: %4d addr=%p nRef=%-3d total=%d\n",
+ p->pgno, PGHDR_TO_DATA(p), p->nRef, p->pPager->nRef
);
cnt++; /* Something to set a breakpoint on */
}
@@ -401,6 +389,38 @@ static const unsigned char aJournalMagic[] = {
# define REFINFO(X)
#endif
+
+/*
+** Change the size of the pager hash table to N. N must be a power
+** of two.
+*/
+static void pager_resize_hash_table(Pager *pPager, int N){
+ PgHdr **aHash, *pPg;
+ assert( N>0 && (N&(N-1))==0 );
+ aHash = sqliteMalloc( sizeof(aHash[0])*N );
+ if( aHash==0 ){
+ /* Failure to rehash is not an error. It is only a performance hit. */
+ return;
+ }
+ sqliteFree(pPager->aHash);
+ pPager->nHash = N;
+ pPager->aHash = aHash;
+ for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
+ int h;
+ if( pPg->pgno==0 ){
+ assert( pPg->pNextHash==0 && pPg->pPrevHash==0 );
+ continue;
+ }
+ h = pPg->pgno & (N-1);
+ pPg->pNextHash = aHash[h];
+ if( aHash[h] ){
+ aHash[h]->pPrevHash = pPg;
+ }
+ aHash[h] = pPg;
+ pPg->pPrevHash = 0;
+ }
+}
+
/*
** Read a 32-bit integer from the given file descriptor. Store the integer
** that is read in *pRes. Return SQLITE_OK if everything worked, or an
@@ -459,12 +479,13 @@ static u32 retrieve32bits(PgHdr *p, int offset){
** will immediately return the same error code.
*/
static int pager_error(Pager *pPager, int rc){
+ int rc2 = rc & 0xff;
assert( pPager->errCode==SQLITE_FULL || pPager->errCode==SQLITE_OK );
if(
- rc==SQLITE_FULL ||
- rc==SQLITE_IOERR ||
- rc==SQLITE_CORRUPT ||
- rc==SQLITE_PROTOCOL
+ rc2==SQLITE_FULL ||
+ rc2==SQLITE_IOERR ||
+ rc2==SQLITE_CORRUPT ||
+ rc2==SQLITE_PROTOCOL
){
pPager->errCode = rc;
}
@@ -820,13 +841,32 @@ static void page_remove_from_stmt_list(PgHdr *pPg){
** a pointer to the page or NULL if not found.
*/
static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
- PgHdr *p = pPager->aHash[pager_hash(pgno)];
+ PgHdr *p;
+ if( pPager->aHash==0 ) return 0;
+ p = pPager->aHash[pgno & (pPager->nHash-1)];
while( p && p->pgno!=pgno ){
p = p->pNextHash;
}
return p;
}
+/*
+** Unlock the database file.
+**
+** Once all locks have been removed from the database file, other
+** processes or threads might change the file. So make sure all of
+** our internal cache is invalidated.
+*/
+static void pager_unlock(Pager *pPager){
+ if( !MEMDB ){
+ sqlite3OsUnlock(pPager->fd, NO_LOCK);
+ pPager->dbSize = -1;
+ }
+ pPager->state = PAGER_UNLOCK;
+ assert( pPager->pAll==0 );
+}
+
+
/*
** Unlock the database and clear the in-memory cache. This routine
** sets the state of the pager back to what it was when it was first
@@ -844,16 +884,16 @@ static void pager_reset(Pager *pPager){
pPager->pFirstSynced = 0;
pPager->pLast = 0;
pPager->pAll = 0;
- memset(pPager->aHash, 0, sizeof(pPager->aHash));
+ pPager->nHash = 0;
+ sqliteFree(pPager->aHash);
pPager->nPage = 0;
+ pPager->aHash = 0;
if( pPager->state>=PAGER_RESERVED ){
sqlite3pager_rollback(pPager);
}
- sqlite3OsUnlock(pPager->fd, NO_LOCK);
- pPager->state = PAGER_UNLOCK;
- pPager->dbSize = -1;
+ pager_unlock(pPager);
pPager->nRef = 0;
- assert( pPager->journalOpen==0 );
+ assert( pPager->errCode || (pPager->journalOpen==0 && pPager->stmtOpen==0) );
}
/*
@@ -892,6 +932,7 @@ static int pager_unwritelock(Pager *pPager){
pPg->pageHash = pager_pagehash(pPg);
#endif
}
+ pPager->pDirty = 0;
pPager->dirtyCache = 0;
pPager->nRec = 0;
}else{
@@ -904,6 +945,7 @@ static int pager_unwritelock(Pager *pPager){
pPager->setMaster = 0;
pPager->needSync = 0;
pPager->pFirstSynced = pPager->pFirst;
+ pPager->dbSize = -1;
return rc;
}
@@ -937,6 +979,9 @@ static u32 pager_cksum(Pager *pPager, const u8 *aData){
return cksum;
}
+/* Forward declaration */
+static void makeClean(PgHdr*);
+
/*
** Read a single page from the journal file opened on file descriptor
** jfd. Playback this one page.
@@ -1014,7 +1059,9 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){
if( rc==SQLITE_OK ){
rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize);
}
- if( pPg ) pPg->dirty = 0;
+ if( pPg ){
+ makeClean(pPg);
+ }
}
if( pPg ){
/* No page should ever be explicitly rolled back that is in use, except
@@ -1164,6 +1211,7 @@ static int pager_reload_cache(Pager *pPager){
pPg->pageHash = pager_pagehash(pPg);
#endif
}
+ pPager->pDirty = 0;
return rc;
}
@@ -1312,6 +1360,10 @@ static int pager_playback(Pager *pPager){
pPager->journalOff = szJ;
break;
}else{
+ /* If we are unable to rollback a hot journal, then the database
+ ** is probably not recoverable. Return CORRUPT.
+ */
+ rc = SQLITE_CORRUPT;
goto end_playback;
}
}
@@ -1388,6 +1440,7 @@ static int pager_stmt_playback(Pager *pPager){
if( pPager->state>=PAGER_EXCLUSIVE ){
rc = pager_truncate(pPager, pPager->stmtSize);
}
+ assert( pPager->state>=PAGER_SHARED );
pPager->dbSize = pPager->stmtSize;
/* Figure out how many records are in the statement journal.
@@ -1507,7 +1560,9 @@ void sqlite3pager_set_safety_level(Pager *pPager, int level, int full_fsync){
** attempts to open a temporary file. This information is used for
** testing and analysis only.
*/
+#ifdef SQLITE_TEST
int sqlite3_opentemp_count = 0;
+#endif
/*
** Open a temporary file. Write the name of the file into zFile
@@ -1521,7 +1576,9 @@ int sqlite3_opentemp_count = 0;
static int sqlite3pager_opentemp(char *zFile, OsFile **pFd){
int cnt = 8;
int rc;
+#ifdef SQLITE_TEST
sqlite3_opentemp_count++; /* Used for testing and analysis only */
+#endif
do{
cnt--;
sqlite3OsTempFileName(zFile);
@@ -1552,7 +1609,7 @@ int sqlite3pager_open(
){
Pager *pPager = 0;
char *zFullPathname = 0;
- int nameLen = 0; /* Compiler is wrong. This is always initialized before use */
+ int nameLen; /* Compiler is wrong. This is always initialized before use */
OsFile *fd;
int rc = SQLITE_OK;
int i;
@@ -1761,14 +1818,19 @@ void enable_simulated_io_errors(void){
** response is to zero the memory at pDest and continue. A real IO error
** will presumably recur and be picked up later (Todo: Think about this).
*/
-void sqlite3pager_read_fileheader(Pager *pPager, int N, unsigned char *pDest){
+int sqlite3pager_read_fileheader(Pager *pPager, int N, unsigned char *pDest){
+ int rc = SQLITE_OK;
memset(pDest, 0, N);
if( MEMDB==0 ){
disable_simulated_io_errors();
sqlite3OsSeek(pPager->fd, 0);
- sqlite3OsRead(pPager->fd, pDest, N);
enable_simulated_io_errors();
+ rc = sqlite3OsRead(pPager->fd, pDest, N);
+ if( rc==SQLITE_IOERR_SHORT_READ ){
+ rc = SQLITE_OK;
+ }
}
+ return rc;
}
/*
@@ -1782,12 +1844,13 @@ void sqlite3pager_read_fileheader(Pager *pPager, int N, unsigned char *pDest){
*/
int sqlite3pager_pagecount(Pager *pPager){
i64 n;
+ int rc;
assert( pPager!=0 );
if( pPager->dbSize>=0 ){
n = pPager->dbSize;
} else {
- if( sqlite3OsFileSize(pPager->fd, &n)!=SQLITE_OK ){
- pager_error(pPager, SQLITE_IOERR);
+ if( (rc = sqlite3OsFileSize(pPager->fd, &n))!=SQLITE_OK ){
+ pager_error(pPager, rc);
return 0;
}
if( n>0 && npageSize ){
@@ -1805,12 +1868,25 @@ int sqlite3pager_pagecount(Pager *pPager){
return (int)n;
}
+
+#ifndef SQLITE_OMIT_MEMORYDB
+/*
+** Clear a PgHistory block
+*/
+static void clearHistory(PgHistory *pHist){
+ sqliteFree(pHist->pOrig);
+ sqliteFree(pHist->pStmt);
+ pHist->pOrig = 0;
+ pHist->pStmt = 0;
+}
+#else
+#define clearHistory(x)
+#endif
+
/*
** Forward declaration
*/
static int syncJournal(Pager*);
-static void clearHistory(PgHistory*);
-
/*
** Unlink pPg from it's hash chain. Also set the page number to 0 to indicate
@@ -1820,18 +1896,17 @@ static void clearHistory(PgHistory*);
*/
static void unlinkHashChain(Pager *pPager, PgHdr *pPg){
if( pPg->pgno==0 ){
- /* If the page number is zero, then this page is not in any hash chain. */
+ assert( pPg->pNextHash==0 && pPg->pPrevHash==0 );
return;
}
if( pPg->pNextHash ){
pPg->pNextHash->pPrevHash = pPg->pPrevHash;
}
if( pPg->pPrevHash ){
- assert( pPager->aHash[pager_hash(pPg->pgno)]!=pPg );
+ assert( pPager->aHash[pPg->pgno & (pPager->nHash-1)]!=pPg );
pPg->pPrevHash->pNextHash = pPg->pNextHash;
}else{
- int h = pager_hash(pPg->pgno);
- assert( pPager->aHash[h]==pPg );
+ int h = pPg->pgno & (pPager->nHash-1);
pPager->aHash[h] = pPg->pNextHash;
}
if( MEMDB ){
@@ -1895,6 +1970,7 @@ static void memoryTruncate(Pager *pPager){
}else{
*ppPg = pPg->pNextAll;
unlinkPage(pPg);
+ makeClean(pPg);
sqliteFree(pPg);
pPager->nPage--;
}
@@ -1914,9 +1990,15 @@ static void memoryTruncate(Pager *pPager){
*/
static int pager_wait_on_lock(Pager *pPager, int locktype){
int rc;
+
+ /* The OS lock values must be the same as the Pager lock values */
assert( PAGER_SHARED==SHARED_LOCK );
assert( PAGER_RESERVED==RESERVED_LOCK );
assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK );
+
+ /* If the file is currently unlocked then the size must be unknown */
+ assert( pPager->state>=PAGER_SHARED || pPager->dbSize<0 || MEMDB );
+
if( pPager->state>=locktype ){
rc = SQLITE_OK;
}else{
@@ -1935,6 +2017,7 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
*/
int sqlite3pager_truncate(Pager *pPager, Pgno nPage){
int rc;
+ assert( pPager->state>=PAGER_SHARED || MEMDB );
sqlite3pager_pagecount(pPager);
if( pPager->errCode ){
rc = pPager->errCode;
@@ -1981,7 +2064,6 @@ int sqlite3pager_truncate(Pager *pPager, Pgno nPage){
** to the caller.
*/
int sqlite3pager_close(Pager *pPager){
- PgHdr *pPg, *pNext;
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
/* A malloc() cannot fail in sqlite3ThreadData() as one or more calls to
** malloc() must have already been made by this thread before it gets
@@ -1993,46 +2075,10 @@ int sqlite3pager_close(Pager *pPager){
assert( pTsd && pTsd->nAlloc );
#endif
- switch( pPager->state ){
- case PAGER_RESERVED:
- case PAGER_SYNCED:
- case PAGER_EXCLUSIVE: {
- /* We ignore any IO errors that occur during the rollback
- ** operation. So disable IO error simulation so that testing
- ** works more easily.
- */
- disable_simulated_io_errors();
- sqlite3pager_rollback(pPager);
- enable_simulated_io_errors();
- if( !MEMDB ){
- sqlite3OsUnlock(pPager->fd, NO_LOCK);
- }
- assert( pPager->errCode || pPager->journalOpen==0 );
- break;
- }
- case PAGER_SHARED: {
- if( !MEMDB ){
- sqlite3OsUnlock(pPager->fd, NO_LOCK);
- }
- break;
- }
- default: {
- /* Do nothing */
- break;
- }
- }
- for(pPg=pPager->pAll; pPg; pPg=pNext){
-#ifndef NDEBUG
- if( MEMDB ){
- PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
- assert( !pPg->alwaysRollback );
- assert( !pHist->pOrig );
- assert( !pHist->pStmt );
- }
-#endif
- pNext = pPg->pNextAll;
- sqliteFree(pPg);
- }
+ disable_simulated_io_errors();
+ pPager->errCode = 0;
+ pager_reset(pPager);
+ enable_simulated_io_errors();
TRACE2("CLOSE %d\n", PAGERID(pPager));
assert( pPager->errCode || (pPager->journalOpen==0 && pPager->stmtOpen==0) );
if( pPager->journalOpen ){
@@ -2061,7 +2107,7 @@ int sqlite3pager_close(Pager *pPager){
pTmp->pNext = pPager->pNext;
}
#endif
-
+ sqliteFree(pPager->aHash);
sqliteFree(pPager);
return SQLITE_OK;
}
@@ -2223,6 +2269,68 @@ static int syncJournal(Pager *pPager){
return rc;
}
+/*
+** Merge two lists of pages connected by pDirty and in pgno order.
+** Do not both fixing the pPrevDirty pointers.
+*/
+static PgHdr *merge_pagelist(PgHdr *pA, PgHdr *pB){
+ PgHdr result, *pTail;
+ pTail = &result;
+ while( pA && pB ){
+ if( pA->pgnopgno ){
+ pTail->pDirty = pA;
+ pTail = pA;
+ pA = pA->pDirty;
+ }else{
+ pTail->pDirty = pB;
+ pTail = pB;
+ pB = pB->pDirty;
+ }
+ }
+ if( pA ){
+ pTail->pDirty = pA;
+ }else if( pB ){
+ pTail->pDirty = pB;
+ }else{
+ pTail->pDirty = 0;
+ }
+ return result.pDirty;
+}
+
+/*
+** Sort the list of pages in accending order by pgno. Pages are
+** connected by pDirty pointers. The pPrevDirty pointers are
+** corrupted by this sort.
+*/
+#define N_SORT_BUCKET 25
+static PgHdr *sort_pagelist(PgHdr *pIn){
+ PgHdr *a[N_SORT_BUCKET], *p;
+ int i;
+ memset(a, 0, sizeof(a));
+ while( pIn ){
+ p = pIn;
+ pIn = p->pDirty;
+ p->pDirty = 0;
+ for(i=0; idirty );
rc = sqlite3OsSeek(pPager->fd, (pList->pgno-1)*(i64)pPager->pageSize);
@@ -2292,15 +2401,7 @@ static int pager_write_pagelist(PgHdr *pList){
** collected even if they are still in use.
*/
static PgHdr *pager_get_all_dirty_pages(Pager *pPager){
- PgHdr *p, *pList;
- pList = 0;
- for(p=pPager->pAll; p; p=p->pNextAll){
- if( p->dirty ){
- p->pDirty = pList;
- pList = p;
- }
- }
- return pList;
+ return pPager->pDirty;
}
/*
@@ -2375,6 +2476,8 @@ static int pager_recycle(Pager *pPager, int syncOk, PgHdr **ppPg){
if( pPg->dirty ){
int rc;
assert( pPg->needSync==0 );
+ makeClean(pPg);
+ pPg->dirty = 1;
pPg->pDirty = 0;
rc = pager_write_pagelist( pPg );
if( rc!=SQLITE_OK ){
@@ -2476,7 +2579,7 @@ int sqlite3pager_release_memory(int nReq){
** The error will be returned to the user (or users, in the case
** of a shared pager cache) of the pager for which the error occured.
*/
- assert( rc==SQLITE_IOERR || rc==SQLITE_FULL );
+ assert( (rc&0xff)==SQLITE_IOERR || rc==SQLITE_FULL );
assert( p->state>=PAGER_RESERVED );
pager_error(p, rc);
}
@@ -2557,8 +2660,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
*/
rc = sqlite3OsLock(pPager->fd, EXCLUSIVE_LOCK);
if( rc!=SQLITE_OK ){
- sqlite3OsUnlock(pPager->fd, NO_LOCK);
- pPager->state = PAGER_UNLOCK;
+ pager_unlock(pPager);
return pager_error(pPager, rc);
}
pPager->state = PAGER_EXCLUSIVE;
@@ -2573,8 +2675,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
*/
rc = sqlite3OsOpenReadOnly(pPager->zJournal, &pPager->jfd);
if( rc!=SQLITE_OK ){
- sqlite3OsUnlock(pPager->fd, NO_LOCK);
- pPager->state = PAGER_UNLOCK;
+ pager_unlock(pPager);
return SQLITE_BUSY;
}
pPager->journalOpen = 1;
@@ -2605,6 +2706,13 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
TEST_INCR(pPager->nMiss);
if( pPager->nPagemxPage || pPager->pFirst==0 || MEMDB ){
/* Create a new page */
+ if( pPager->nPage>=pPager->nHash ){
+ pager_resize_hash_table(pPager,
+ pPager->nHash<256 ? 256 : pPager->nHash*2);
+ if( pPager->nHash==0 ){
+ return SQLITE_NOMEM;
+ }
+ }
pPg = sqliteMallocRaw( sizeof(*pPg) + pPager->pageSize
+ sizeof(u32) + pPager->nExtra
+ MEMDB*sizeof(PgHistory) );
@@ -2646,7 +2754,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
}else{
page_remove_from_stmt_list(pPg);
}
- pPg->dirty = 0;
+ makeClean(pPg);
pPg->nRef = 1;
REFINFO(pPg);
@@ -2674,26 +2782,18 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
}
TRACE3("FETCH %d page %d\n", PAGERID(pPager), pPg->pgno);
CODEC1(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3);
- if( rc!=SQLITE_OK ){
- i64 fileSize;
- int rc2 = sqlite3OsFileSize(pPager->fd, &fileSize);
- if( rc2!=SQLITE_OK || fileSize>=pgno*pPager->pageSize ){
- /* An IO error occured in one of the the sqlite3OsSeek() or
- ** sqlite3OsRead() calls above. */
- pPg->pgno = 0;
- sqlite3pager_unref(PGHDR_TO_DATA(pPg));
- return rc;
- }else{
- clear_simulated_io_error();
- memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize);
- }
+ if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
+ pPg->pgno = 0;
+ sqlite3pager_unref(PGHDR_TO_DATA(pPg));
+ return rc;
}else{
TEST_INCR(pPager->nRead);
}
}
/* Link the page into the page hash table */
- h = pager_hash(pgno);
+ h = pgno & (pPager->nHash-1);
+ assert( pgno!=0 );
pPg->pNextHash = pPager->aHash[h];
pPager->aHash[h] = pPg;
if( pPg->pNextHash ){
@@ -2857,8 +2957,7 @@ failed_to_open_journal:
*/
sqlite3OsDelete(pPager->zJournal);
}else{
- sqlite3OsUnlock(pPager->fd, NO_LOCK);
- pPager->state = PAGER_UNLOCK;
+ pager_reset(pPager);
}
return rc;
}
@@ -2922,6 +3021,42 @@ int sqlite3pager_begin(void *pData, int exFlag){
return rc;
}
+/*
+** Make a page dirty. Set its dirty flag and add it to the dirty
+** page list.
+*/
+static void makeDirty(PgHdr *pPg){
+ if( pPg->dirty==0 ){
+ Pager *pPager = pPg->pPager;
+ pPg->dirty = 1;
+ pPg->pDirty = pPager->pDirty;
+ if( pPager->pDirty ){
+ pPager->pDirty->pPrevDirty = pPg;
+ }
+ pPg->pPrevDirty = 0;
+ pPager->pDirty = pPg;
+ }
+}
+
+/*
+** Make a page clean. Clear its dirty bit and remove it from the
+** dirty page list.
+*/
+static void makeClean(PgHdr *pPg){
+ if( pPg->dirty ){
+ pPg->dirty = 0;
+ if( pPg->pDirty ){
+ pPg->pDirty->pPrevDirty = pPg->pPrevDirty;
+ }
+ if( pPg->pPrevDirty ){
+ pPg->pPrevDirty->pDirty = pPg->pDirty;
+ }else{
+ pPg->pPager->pDirty = pPg->pDirty;
+ }
+ }
+}
+
+
/*
** Mark a data page as writeable. The page is written into the journal
** if it is not there already. This routine must be called before making
@@ -2960,7 +3095,7 @@ int sqlite3pager_write(void *pData){
/* Mark the page as dirty. If the page has already been written
** to the journal then we can return right away.
*/
- pPg->dirty = 1;
+ makeDirty(pPg);
if( pPg->inJournal && (pPg->inStmt || pPager->stmtInUse==0) ){
pPager->dirtyCache = 1;
}else{
@@ -3081,6 +3216,7 @@ int sqlite3pager_write(void *pData){
/* Update the database size and return.
*/
+ assert( pPager->state>=PAGER_SHARED );
if( pPager->dbSize<(int)pPg->pgno ){
pPager->dbSize = pPg->pgno;
if( !MEMDB && pPager->dbSize==PENDING_BYTE/pPager->pageSize ){
@@ -3156,6 +3292,7 @@ void sqlite3pager_dont_write(Pager *pPager, Pgno pgno){
assert( pPg!=0 ); /* We never call _dont_write unless the page is in mem */
pPg->alwaysRollback = 1;
if( pPg->dirty && !pPager->stmtInUse ){
+ assert( pPager->state>=PAGER_SHARED );
if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSizedbSize ){
/* If this pages is the last page in the file and the file has grown
** during the current transaction, then do NOT mark the page as clean.
@@ -3167,7 +3304,7 @@ void sqlite3pager_dont_write(Pager *pPager, Pgno pgno){
*/
}else{
TRACE3("DONT_WRITE page %d of %d\n", pgno, PAGERID(pPager));
- pPg->dirty = 0;
+ makeClean(pPg);
#ifdef SQLITE_CHECK_PAGES
pPg->pageHash = pager_pagehash(pPg);
#endif
@@ -3185,7 +3322,8 @@ void sqlite3pager_dont_rollback(void *pData){
PgHdr *pPg = DATA_TO_PGHDR(pData);
Pager *pPager = pPg->pPager;
- if( pPager->state!=PAGER_EXCLUSIVE || pPager->journalOpen==0 ) return;
+ assert( pPager->state>=PAGER_RESERVED );
+ if( pPager->journalOpen==0 ) return;
if( pPg->alwaysRollback || pPager->alwaysRollback || MEMDB ) return;
if( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ){
assert( pPager->aInJournal!=0 );
@@ -3206,20 +3344,6 @@ void sqlite3pager_dont_rollback(void *pData){
}
-#ifndef SQLITE_OMIT_MEMORYDB
-/*
-** Clear a PgHistory block
-*/
-static void clearHistory(PgHistory *pHist){
- sqliteFree(pHist->pOrig);
- sqliteFree(pHist->pStmt);
- pHist->pOrig = 0;
- pHist->pStmt = 0;
-}
-#else
-#define clearHistory(x)
-#endif
-
/*
** Commit all changes to the database and release the write lock.
**
@@ -3249,6 +3373,7 @@ int sqlite3pager_commit(Pager *pPager){
pPg->pPrevStmt = pPg->pNextStmt = 0;
pPg = pPg->pDirty;
}
+ pPager->pDirty = 0;
#ifndef NDEBUG
for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
@@ -3266,14 +3391,12 @@ int sqlite3pager_commit(Pager *pPager){
** if there have been no changes to the database file. */
assert( pPager->needSync==0 );
rc = pager_unwritelock(pPager);
- pPager->dbSize = -1;
return rc;
}
assert( pPager->journalOpen );
rc = sqlite3pager_sync(pPager, 0, 0);
if( rc==SQLITE_OK ){
rc = pager_unwritelock(pPager);
- pPager->dbSize = -1;
}
return rc;
}
@@ -3316,12 +3439,11 @@ int sqlite3pager_rollback(Pager *pPager){
p->inJournal = 0;
p->inStmt = 0;
p->pPrevStmt = p->pNextStmt = 0;
-
if( pPager->xReiniter ){
pPager->xReiniter(PGHDR_TO_DATA(p), pPager->pageSize);
}
-
}
+ pPager->pDirty = 0;
pPager->pStmt = 0;
pPager->dbSize = pPager->origDbSize;
memoryTruncate(pPager);
@@ -3332,7 +3454,6 @@ int sqlite3pager_rollback(Pager *pPager){
if( !pPager->dirtyCache || !pPager->journalOpen ){
rc = pager_unwritelock(pPager);
- pPager->dbSize = -1;
return rc;
}
@@ -3369,6 +3490,14 @@ int sqlite3pager_isreadonly(Pager *pPager){
return pPager->readOnly;
}
+/*
+** Return the number of references to the pager.
+*/
+int sqlite3pager_refcount(Pager *pPager){
+ return pPager->nRef;
+}
+
+#ifdef SQLITE_TEST
/*
** This routine is used for testing and analysis only.
*/
@@ -3380,15 +3509,14 @@ int *sqlite3pager_stats(Pager *pPager){
a[3] = pPager->dbSize;
a[4] = pPager->state;
a[5] = pPager->errCode;
-#ifdef SQLITE_TEST
a[6] = pPager->nHit;
a[7] = pPager->nMiss;
a[8] = pPager->nOvfl;
a[9] = pPager->nRead;
a[10] = pPager->nWrite;
-#endif
return a;
}
+#endif
/*
** Set the statement rollback point.
@@ -3401,6 +3529,7 @@ int sqlite3pager_stmt_begin(Pager *pPager){
int rc;
char zTemp[SQLITE_TEMPNAME_SIZE];
assert( !pPager->stmtInUse );
+ assert( pPager->state>=PAGER_SHARED );
assert( pPager->dbSize>=0 );
TRACE2("STMT-BEGIN %d\n", PAGERID(pPager));
if( MEMDB ){
@@ -3716,7 +3845,7 @@ int sqlite3pager_movepage(Pager *pPager, void *pData, Pgno pgno){
if( pPgOld ){
assert( pPgOld->nRef==0 );
unlinkHashChain(pPager, pPgOld);
- pPgOld->dirty = 0;
+ makeClean(pPgOld);
if( pPgOld->needSync ){
assert( pPgOld->inJournal );
pPg->inJournal = 1;
@@ -3726,8 +3855,9 @@ int sqlite3pager_movepage(Pager *pPager, void *pData, Pgno pgno){
}
/* Change the page number for pPg and insert it into the new hash-chain. */
+ assert( pgno!=0 );
pPg->pgno = pgno;
- h = pager_hash(pgno);
+ h = pgno & (pPager->nHash-1);
if( pPager->aHash[h] ){
assert( pPager->aHash[h]->pPrevHash==0 );
pPager->aHash[h]->pPrevHash = pPg;
@@ -3736,7 +3866,7 @@ int sqlite3pager_movepage(Pager *pPager, void *pData, Pgno pgno){
pPager->aHash[h] = pPg;
pPg->pPrevHash = 0;
- pPg->dirty = 1;
+ makeDirty(pPg);
pPager->dirtyCache = 1;
if( needSyncPgno ){
@@ -3757,7 +3887,7 @@ int sqlite3pager_movepage(Pager *pPager, void *pData, Pgno pgno){
pPager->needSync = 1;
DATA_TO_PGHDR(pNeedSync)->needSync = 1;
DATA_TO_PGHDR(pNeedSync)->inJournal = 1;
- DATA_TO_PGHDR(pNeedSync)->dirty = 1;
+ makeDirty(DATA_TO_PGHDR(pNeedSync));
sqlite3pager_unref(pNeedSync);
}
diff --git a/dlls/sqlite/sqlite-source/pager.h b/dlls/sqlite/sqlite-source/pager.h
index b1775c6b..7626ff6b 100644
--- a/dlls/sqlite/sqlite-source/pager.h
+++ b/dlls/sqlite/sqlite-source/pager.h
@@ -75,7 +75,7 @@ void sqlite3pager_set_busyhandler(Pager*, BusyHandler *pBusyHandler);
void sqlite3pager_set_destructor(Pager*, void(*)(void*,int));
void sqlite3pager_set_reiniter(Pager*, void(*)(void*,int));
int sqlite3pager_set_pagesize(Pager*, int);
-void sqlite3pager_read_fileheader(Pager*, int, unsigned char*);
+int sqlite3pager_read_fileheader(Pager*, int, unsigned char*);
void sqlite3pager_set_cachesize(Pager*, int);
int sqlite3pager_close(Pager *pPager);
int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage);
@@ -98,6 +98,7 @@ int sqlite3pager_stmt_commit(Pager*);
int sqlite3pager_stmt_rollback(Pager*);
void sqlite3pager_dont_rollback(void*);
void sqlite3pager_dont_write(Pager*, Pgno);
+int sqlite3pager_refcount(Pager*);
int *sqlite3pager_stats(Pager*);
void sqlite3pager_set_safety_level(Pager*,int,int);
const char *sqlite3pager_filename(Pager*);
diff --git a/dlls/sqlite/sqlite-source/parse.c b/dlls/sqlite/sqlite-source/parse.c
index 9b07d8cd..52480394 100644
--- a/dlls/sqlite/sqlite-source/parse.c
+++ b/dlls/sqlite/sqlite-source/parse.c
@@ -4,7 +4,7 @@
/* First off, code is include which follows the "include" declaration
** in the input file. */
#include
-#line 54 "parse.y"
+#line 56 "parse.y"
#include "sqliteInt.h"
#include "parse.h"
@@ -93,35 +93,36 @@ struct AttachKey { int type; Token key; };
** defined, then do no error processing.
*/
#define YYCODETYPE unsigned char
-#define YYNOCODE 240
+#define YYNOCODE 249
#define YYACTIONTYPE unsigned short int
+#define YYWILDCARD 60
#define sqlite3ParserTOKENTYPE Token
typedef union {
sqlite3ParserTOKENTYPE yy0;
- struct {int value; int mask;} yy13;
- struct TrigEvent yy132;
- IdList* yy160;
- Expr* yy178;
- int yy230;
- Select* yy239;
- TriggerStep* yy247;
- struct LimitVal yy270;
- SrcList* yy285;
- Expr * yy292;
- Token yy384;
- struct LikeOp yy440;
- ExprList* yy462;
- int yy479;
+ Select* yy43;
+ TriggerStep* yy75;
+ struct LimitVal yy84;
+ struct LikeOp yy86;
+ Expr * yy158;
+ Token yy178;
+ struct {int value; int mask;} yy207;
+ ExprList* yy242;
+ int yy316;
+ IdList* yy352;
+ struct TrigEvent yy354;
+ SrcList* yy419;
+ Expr* yy450;
+ int yy497;
} YYMINORTYPE;
#define YYSTACKDEPTH 100
#define sqlite3ParserARG_SDECL Parse *pParse;
#define sqlite3ParserARG_PDECL ,Parse *pParse
#define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse
#define sqlite3ParserARG_STORE yypParser->pParse = pParse
-#define YYNSTATE 559
-#define YYNRULE 295
-#define YYERRORSYMBOL 137
-#define YYERRSYMDT yy479
+#define YYNSTATE 587
+#define YYNRULE 312
+#define YYERRORSYMBOL 139
+#define YYERRSYMDT yy497
#define YYFALLBACK 1
#define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
@@ -175,397 +176,417 @@ typedef union {
** yy_default[] Default action for each state.
*/
static const YYACTIONTYPE yy_action[] = {
- /* 0 */ 279, 67, 283, 69, 147, 165, 545, 418, 61, 61,
- /* 10 */ 61, 61, 201, 63, 63, 63, 63, 64, 64, 65,
- /* 20 */ 65, 65, 66, 66, 547, 548, 431, 68, 63, 63,
- /* 30 */ 63, 63, 64, 64, 65, 65, 65, 66, 67, 453,
- /* 40 */ 69, 147, 498, 60, 58, 287, 439, 440, 436, 436,
- /* 50 */ 62, 62, 61, 61, 61, 61, 500, 63, 63, 63,
- /* 60 */ 63, 64, 64, 65, 65, 65, 66, 279, 370, 283,
- /* 70 */ 418, 2, 376, 79, 157, 114, 219, 304, 224, 305,
- /* 80 */ 169, 244, 855, 118, 558, 503, 203, 2, 245, 388,
- /* 90 */ 495, 218, 21, 431, 513, 20, 418, 57, 492, 511,
- /* 100 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66,
- /* 110 */ 60, 58, 287, 439, 440, 436, 436, 62, 62, 61,
- /* 120 */ 61, 61, 61, 530, 63, 63, 63, 63, 64, 64,
- /* 130 */ 65, 65, 65, 66, 279, 377, 378, 174, 371, 368,
- /* 140 */ 330, 333, 334, 219, 304, 224, 305, 169, 244, 510,
- /* 150 */ 479, 19, 335, 138, 376, 245, 509, 301, 372, 418,
- /* 160 */ 431, 529, 91, 199, 65, 65, 65, 66, 504, 167,
- /* 170 */ 191, 64, 64, 65, 65, 65, 66, 60, 58, 287,
- /* 180 */ 439, 440, 436, 436, 62, 62, 61, 61, 61, 61,
- /* 190 */ 254, 63, 63, 63, 63, 64, 64, 65, 65, 65,
- /* 200 */ 66, 279, 250, 410, 410, 430, 109, 395, 426, 204,
- /* 210 */ 357, 260, 259, 308, 145, 168, 153, 377, 378, 396,
- /* 220 */ 327, 201, 67, 189, 69, 147, 225, 431, 546, 361,
- /* 230 */ 465, 365, 397, 499, 318, 409, 40, 413, 428, 312,
- /* 240 */ 161, 180, 550, 178, 60, 58, 287, 439, 440, 436,
- /* 250 */ 436, 62, 62, 61, 61, 61, 61, 410, 63, 63,
- /* 260 */ 63, 63, 64, 64, 65, 65, 65, 66, 279, 471,
- /* 270 */ 415, 415, 415, 282, 308, 322, 235, 426, 204, 308,
- /* 280 */ 174, 367, 308, 330, 333, 334, 67, 308, 69, 147,
- /* 290 */ 148, 559, 371, 368, 431, 335, 409, 34, 165, 465,
- /* 300 */ 418, 409, 34, 275, 409, 34, 428, 502, 161, 409,
- /* 310 */ 35, 60, 58, 287, 439, 440, 436, 436, 62, 62,
- /* 320 */ 61, 61, 61, 61, 410, 63, 63, 63, 63, 64,
- /* 330 */ 64, 65, 65, 65, 66, 308, 503, 395, 237, 290,
- /* 340 */ 279, 391, 392, 146, 324, 387, 20, 288, 347, 396,
- /* 350 */ 174, 450, 350, 330, 333, 334, 450, 409, 27, 450,
- /* 360 */ 474, 231, 397, 418, 393, 335, 431, 501, 354, 144,
- /* 370 */ 512, 503, 524, 232, 394, 465, 496, 410, 527, 392,
- /* 380 */ 555, 20, 75, 60, 58, 287, 439, 440, 436, 436,
- /* 390 */ 62, 62, 61, 61, 61, 61, 220, 63, 63, 63,
- /* 400 */ 63, 64, 64, 65, 65, 65, 66, 308, 221, 185,
- /* 410 */ 338, 254, 279, 308, 239, 443, 475, 308, 319, 308,
- /* 420 */ 389, 444, 286, 421, 422, 379, 380, 381, 492, 409,
- /* 430 */ 34, 311, 421, 422, 212, 409, 48, 170, 431, 409,
- /* 440 */ 40, 409, 48, 410, 122, 314, 526, 442, 442, 1,
- /* 450 */ 376, 469, 255, 376, 78, 60, 58, 287, 439, 440,
- /* 460 */ 436, 436, 62, 62, 61, 61, 61, 61, 355, 63,
- /* 470 */ 63, 63, 63, 64, 64, 65, 65, 65, 66, 279,
- /* 480 */ 233, 152, 298, 478, 449, 203, 792, 192, 299, 351,
- /* 490 */ 376, 281, 376, 9, 203, 376, 245, 376, 201, 432,
- /* 500 */ 314, 376, 442, 442, 490, 431, 314, 325, 442, 442,
- /* 510 */ 418, 356, 289, 377, 378, 354, 377, 378, 403, 434,
- /* 520 */ 435, 410, 60, 58, 287, 439, 440, 436, 436, 62,
- /* 530 */ 62, 61, 61, 61, 61, 263, 63, 63, 63, 63,
- /* 540 */ 64, 64, 65, 65, 65, 66, 279, 433, 328, 236,
- /* 550 */ 497, 473, 490, 377, 378, 377, 378, 484, 377, 378,
- /* 560 */ 377, 378, 308, 522, 377, 378, 314, 521, 442, 442,
- /* 570 */ 409, 3, 431, 418, 130, 254, 264, 485, 309, 346,
- /* 580 */ 461, 213, 462, 242, 409, 28, 469, 292, 214, 60,
- /* 590 */ 58, 287, 439, 440, 436, 436, 62, 62, 61, 61,
- /* 600 */ 61, 61, 308, 63, 63, 63, 63, 64, 64, 65,
- /* 610 */ 65, 65, 66, 279, 308, 458, 536, 248, 5, 308,
- /* 620 */ 201, 308, 469, 308, 409, 23, 308, 202, 291, 308,
- /* 630 */ 375, 243, 308, 362, 54, 115, 409, 32, 74, 431,
- /* 640 */ 76, 409, 53, 409, 24, 409, 51, 345, 409, 96,
- /* 650 */ 149, 409, 93, 265, 409, 98, 60, 58, 287, 439,
- /* 660 */ 440, 436, 436, 62, 62, 61, 61, 61, 61, 308,
- /* 670 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66,
- /* 680 */ 279, 308, 404, 297, 410, 90, 308, 176, 308, 405,
- /* 690 */ 308, 409, 99, 308, 419, 308, 22, 308, 520, 344,
- /* 700 */ 520, 164, 153, 409, 110, 141, 431, 313, 409, 111,
- /* 710 */ 409, 16, 409, 97, 254, 409, 33, 409, 94, 409,
- /* 720 */ 52, 410, 187, 60, 58, 287, 439, 440, 436, 436,
- /* 730 */ 62, 62, 61, 61, 61, 61, 308, 63, 63, 63,
- /* 740 */ 63, 64, 64, 65, 65, 65, 66, 279, 308, 490,
- /* 750 */ 490, 414, 308, 320, 308, 538, 308, 460, 409, 112,
- /* 760 */ 308, 171, 172, 173, 308, 408, 308, 424, 424, 407,
- /* 770 */ 409, 113, 427, 431, 409, 25, 409, 36, 409, 37,
- /* 780 */ 170, 437, 409, 26, 211, 293, 409, 38, 409, 39,
- /* 790 */ 60, 58, 287, 439, 440, 436, 436, 62, 62, 61,
- /* 800 */ 61, 61, 61, 308, 63, 63, 63, 63, 64, 64,
- /* 810 */ 65, 65, 65, 66, 279, 308, 490, 490, 451, 308,
- /* 820 */ 81, 308, 151, 308, 459, 409, 41, 308, 243, 243,
- /* 830 */ 400, 401, 308, 448, 281, 12, 464, 409, 42, 468,
- /* 840 */ 431, 409, 43, 409, 29, 409, 30, 241, 460, 409,
- /* 850 */ 44, 294, 296, 480, 409, 45, 329, 60, 70, 287,
- /* 860 */ 439, 440, 436, 436, 62, 62, 61, 61, 61, 61,
- /* 870 */ 308, 63, 63, 63, 63, 64, 64, 65, 65, 65,
- /* 880 */ 66, 279, 308, 408, 483, 482, 308, 407, 308, 467,
- /* 890 */ 308, 166, 409, 46, 308, 243, 243, 476, 488, 12,
- /* 900 */ 122, 518, 519, 179, 409, 47, 481, 431, 409, 31,
- /* 910 */ 409, 10, 409, 49, 505, 486, 409, 50, 254, 249,
- /* 920 */ 254, 254, 254, 158, 279, 58, 287, 439, 440, 436,
- /* 930 */ 436, 62, 62, 61, 61, 61, 61, 410, 63, 63,
- /* 940 */ 63, 63, 64, 64, 65, 65, 65, 66, 487, 247,
- /* 950 */ 431, 122, 254, 337, 525, 122, 122, 251, 533, 539,
- /* 960 */ 166, 540, 266, 360, 534, 543, 88, 88, 252, 287,
- /* 970 */ 439, 440, 436, 436, 62, 62, 61, 61, 61, 61,
- /* 980 */ 195, 63, 63, 63, 63, 64, 64, 65, 65, 65,
- /* 990 */ 66, 71, 315, 268, 4, 253, 182, 258, 285, 349,
- /* 1000 */ 342, 352, 353, 261, 262, 544, 310, 71, 315, 269,
- /* 1010 */ 4, 222, 363, 272, 285, 593, 273, 554, 140, 226,
- /* 1020 */ 385, 423, 310, 317, 425, 316, 532, 542, 18, 156,
- /* 1030 */ 479, 454, 457, 430, 332, 489, 374, 382, 383, 317,
- /* 1040 */ 384, 8, 302, 303, 491, 390, 398, 284, 403, 430,
- /* 1050 */ 223, 406, 73, 72, 402, 81, 411, 399, 323, 56,
- /* 1060 */ 71, 306, 307, 205, 321, 413, 80, 227, 73, 72,
- /* 1070 */ 472, 77, 452, 163, 234, 455, 71, 306, 307, 71,
- /* 1080 */ 315, 413, 4, 229, 201, 456, 285, 412, 228, 82,
- /* 1090 */ 119, 326, 230, 206, 310, 207, 101, 276, 415, 415,
- /* 1100 */ 415, 416, 417, 11, 238, 494, 466, 470, 240, 209,
- /* 1110 */ 210, 317, 493, 506, 415, 415, 415, 416, 417, 11,
- /* 1120 */ 507, 430, 155, 339, 508, 514, 177, 215, 216, 217,
- /* 1130 */ 105, 277, 341, 181, 516, 83, 343, 85, 256, 455,
- /* 1140 */ 73, 72, 517, 197, 183, 270, 348, 117, 71, 306,
- /* 1150 */ 307, 528, 271, 413, 186, 126, 535, 358, 127, 128,
- /* 1160 */ 541, 135, 300, 132, 194, 136, 529, 551, 552, 553,
- /* 1170 */ 129, 193, 89, 196, 430, 556, 208, 100, 95, 373,
- /* 1180 */ 386, 116, 200, 55, 17, 594, 415, 415, 415, 416,
- /* 1190 */ 417, 11, 92, 142, 143, 595, 159, 108, 160, 59,
- /* 1200 */ 438, 420, 499, 429, 137, 441, 413, 445, 150, 162,
- /* 1210 */ 446, 447, 6, 7, 13, 359, 267, 259, 463, 12,
- /* 1220 */ 120, 280, 121, 154, 477, 102, 201, 246, 331, 103,
- /* 1230 */ 84, 104, 336, 175, 221, 340, 139, 515, 123, 415,
- /* 1240 */ 415, 415, 184, 124, 295, 166, 257, 106, 523, 278,
- /* 1250 */ 364, 531, 125, 86, 188, 14, 190, 537, 131, 133,
- /* 1260 */ 87, 134, 15, 107, 198, 549, 366, 369, 536, 557,
- /* 1270 */ 274,
+ /* 0 */ 289, 900, 121, 586, 205, 169, 2, 435, 61, 61,
+ /* 10 */ 61, 61, 435, 63, 63, 63, 63, 64, 64, 65,
+ /* 20 */ 65, 65, 66, 230, 198, 299, 420, 426, 68, 63,
+ /* 30 */ 63, 63, 63, 64, 64, 65, 65, 65, 66, 230,
+ /* 40 */ 67, 447, 69, 151, 230, 60, 59, 294, 430, 431,
+ /* 50 */ 427, 427, 62, 62, 61, 61, 61, 61, 411, 63,
+ /* 60 */ 63, 63, 63, 64, 64, 65, 65, 65, 66, 230,
+ /* 70 */ 289, 487, 515, 435, 570, 415, 80, 67, 435, 69,
+ /* 80 */ 151, 63, 63, 63, 63, 64, 64, 65, 65, 65,
+ /* 90 */ 66, 230, 569, 568, 248, 386, 420, 426, 2, 572,
+ /* 100 */ 58, 115, 238, 340, 243, 341, 173, 417, 417, 417,
+ /* 110 */ 570, 387, 384, 249, 289, 60, 59, 294, 430, 431,
+ /* 120 */ 427, 427, 62, 62, 61, 61, 61, 61, 569, 63,
+ /* 130 */ 63, 63, 63, 64, 64, 65, 65, 65, 66, 230,
+ /* 140 */ 420, 426, 92, 64, 64, 65, 65, 65, 66, 230,
+ /* 150 */ 245, 392, 56, 171, 566, 207, 406, 443, 208, 60,
+ /* 160 */ 59, 294, 430, 431, 427, 427, 62, 62, 61, 61,
+ /* 170 */ 61, 61, 205, 63, 63, 63, 63, 64, 64, 65,
+ /* 180 */ 65, 65, 66, 230, 289, 368, 522, 411, 522, 111,
+ /* 190 */ 378, 207, 447, 467, 223, 403, 21, 532, 21, 172,
+ /* 200 */ 157, 317, 66, 230, 336, 404, 520, 443, 208, 486,
+ /* 210 */ 420, 426, 146, 147, 517, 488, 489, 393, 394, 148,
+ /* 220 */ 531, 224, 487, 410, 41, 407, 415, 567, 289, 60,
+ /* 230 */ 59, 294, 430, 431, 427, 427, 62, 62, 61, 61,
+ /* 240 */ 61, 61, 476, 63, 63, 63, 63, 64, 64, 65,
+ /* 250 */ 65, 65, 66, 230, 420, 426, 491, 492, 417, 417,
+ /* 260 */ 417, 155, 549, 331, 211, 65, 65, 65, 66, 230,
+ /* 270 */ 546, 492, 289, 60, 59, 294, 430, 431, 427, 427,
+ /* 280 */ 62, 62, 61, 61, 61, 61, 467, 63, 63, 63,
+ /* 290 */ 63, 64, 64, 65, 65, 65, 66, 230, 420, 426,
+ /* 300 */ 548, 299, 178, 297, 522, 342, 345, 346, 472, 67,
+ /* 310 */ 460, 69, 151, 577, 21, 338, 347, 60, 59, 294,
+ /* 320 */ 430, 431, 427, 427, 62, 62, 61, 61, 61, 61,
+ /* 330 */ 530, 63, 63, 63, 63, 64, 64, 65, 65, 65,
+ /* 340 */ 66, 230, 409, 523, 76, 289, 408, 478, 452, 482,
+ /* 350 */ 392, 369, 266, 265, 283, 149, 405, 445, 521, 165,
+ /* 360 */ 453, 317, 205, 67, 517, 69, 151, 529, 503, 152,
+ /* 370 */ 248, 420, 426, 454, 528, 493, 161, 115, 238, 340,
+ /* 380 */ 243, 341, 173, 410, 35, 494, 580, 288, 79, 249,
+ /* 390 */ 60, 59, 294, 430, 431, 427, 427, 62, 62, 61,
+ /* 400 */ 61, 61, 61, 411, 63, 63, 63, 63, 64, 64,
+ /* 410 */ 65, 65, 65, 66, 230, 289, 393, 394, 178, 485,
+ /* 420 */ 508, 342, 345, 346, 178, 296, 317, 342, 345, 346,
+ /* 430 */ 366, 317, 347, 20, 317, 141, 317, 457, 347, 150,
+ /* 440 */ 509, 420, 426, 22, 295, 438, 439, 435, 410, 35,
+ /* 450 */ 328, 260, 472, 410, 28, 232, 410, 35, 410, 36,
+ /* 460 */ 60, 59, 294, 430, 431, 427, 427, 62, 62, 61,
+ /* 470 */ 61, 61, 61, 411, 63, 63, 63, 63, 64, 64,
+ /* 480 */ 65, 65, 65, 66, 230, 289, 436, 481, 23, 502,
+ /* 490 */ 298, 234, 380, 301, 317, 217, 317, 476, 333, 317,
+ /* 500 */ 392, 317, 457, 337, 168, 157, 421, 422, 207, 231,
+ /* 510 */ 457, 420, 426, 435, 313, 388, 410, 35, 410, 49,
+ /* 520 */ 204, 410, 41, 410, 49, 410, 3, 197, 424, 425,
+ /* 530 */ 60, 59, 294, 430, 431, 427, 427, 62, 62, 61,
+ /* 540 */ 61, 61, 61, 382, 63, 63, 63, 63, 64, 64,
+ /* 550 */ 65, 65, 65, 66, 230, 289, 443, 423, 357, 252,
+ /* 560 */ 434, 411, 210, 292, 308, 350, 393, 394, 448, 309,
+ /* 570 */ 456, 322, 438, 439, 320, 1, 433, 433, 19, 392,
+ /* 580 */ 541, 420, 426, 191, 540, 375, 584, 891, 543, 891,
+ /* 590 */ 584, 890, 174, 890, 472, 392, 358, 445, 323, 165,
+ /* 600 */ 60, 59, 294, 430, 431, 427, 427, 62, 62, 61,
+ /* 610 */ 61, 61, 61, 383, 63, 63, 63, 63, 64, 64,
+ /* 620 */ 65, 65, 65, 66, 230, 289, 370, 581, 9, 452,
+ /* 630 */ 91, 581, 10, 236, 409, 207, 392, 359, 408, 392,
+ /* 640 */ 156, 453, 169, 362, 435, 393, 394, 320, 291, 433,
+ /* 650 */ 433, 420, 426, 249, 454, 320, 327, 433, 433, 260,
+ /* 660 */ 462, 393, 394, 515, 515, 545, 515, 463, 270, 289,
+ /* 670 */ 60, 59, 294, 430, 431, 427, 427, 62, 62, 61,
+ /* 680 */ 61, 61, 61, 82, 63, 63, 63, 63, 64, 64,
+ /* 690 */ 65, 65, 65, 66, 230, 420, 426, 480, 302, 216,
+ /* 700 */ 261, 303, 393, 394, 822, 393, 394, 273, 515, 271,
+ /* 710 */ 435, 515, 334, 289, 60, 59, 294, 430, 431, 427,
+ /* 720 */ 427, 62, 62, 61, 61, 61, 61, 233, 63, 63,
+ /* 730 */ 63, 63, 64, 64, 65, 65, 65, 66, 230, 420,
+ /* 740 */ 426, 247, 247, 304, 247, 318, 306, 587, 387, 384,
+ /* 750 */ 395, 396, 397, 320, 219, 433, 433, 289, 60, 70,
+ /* 760 */ 294, 430, 431, 427, 427, 62, 62, 61, 61, 61,
+ /* 770 */ 61, 317, 63, 63, 63, 63, 64, 64, 65, 65,
+ /* 780 */ 65, 66, 230, 420, 426, 476, 247, 391, 272, 247,
+ /* 790 */ 539, 356, 539, 410, 29, 175, 176, 177, 162, 260,
+ /* 800 */ 260, 289, 5, 59, 294, 430, 431, 427, 427, 62,
+ /* 810 */ 62, 61, 61, 61, 61, 377, 63, 63, 63, 63,
+ /* 820 */ 64, 64, 65, 65, 65, 66, 230, 420, 426, 392,
+ /* 830 */ 311, 120, 392, 319, 205, 260, 366, 465, 254, 189,
+ /* 840 */ 556, 558, 260, 75, 260, 77, 307, 376, 294, 430,
+ /* 850 */ 431, 427, 427, 62, 62, 61, 61, 61, 61, 260,
+ /* 860 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66,
+ /* 870 */ 230, 72, 324, 411, 4, 260, 559, 258, 293, 256,
+ /* 880 */ 174, 125, 317, 560, 317, 274, 321, 72, 324, 193,
+ /* 890 */ 4, 153, 621, 180, 293, 393, 394, 367, 393, 394,
+ /* 900 */ 374, 218, 321, 326, 410, 24, 410, 33, 183, 317,
+ /* 910 */ 428, 206, 441, 441, 447, 317, 276, 317, 55, 326,
+ /* 920 */ 363, 468, 239, 411, 469, 411, 455, 411, 13, 144,
+ /* 930 */ 447, 410, 53, 240, 74, 73, 291, 410, 52, 410,
+ /* 940 */ 96, 116, 411, 72, 315, 316, 582, 474, 415, 170,
+ /* 950 */ 74, 73, 479, 317, 507, 506, 317, 500, 416, 72,
+ /* 960 */ 315, 316, 72, 324, 415, 4, 205, 317, 329, 293,
+ /* 970 */ 317, 458, 483, 444, 13, 410, 94, 321, 410, 99,
+ /* 980 */ 417, 417, 417, 418, 419, 12, 583, 466, 317, 410,
+ /* 990 */ 100, 471, 410, 110, 326, 475, 417, 417, 417, 418,
+ /* 1000 */ 419, 12, 497, 498, 512, 447, 125, 159, 244, 317,
+ /* 1010 */ 410, 112, 220, 221, 222, 102, 537, 538, 317, 251,
+ /* 1020 */ 317, 125, 317, 504, 505, 74, 73, 349, 202, 125,
+ /* 1030 */ 278, 410, 17, 510, 72, 315, 316, 279, 524, 415,
+ /* 1040 */ 410, 97, 410, 34, 410, 95, 317, 511, 544, 200,
+ /* 1050 */ 125, 548, 552, 253, 170, 317, 199, 255, 317, 201,
+ /* 1060 */ 553, 257, 89, 317, 259, 563, 317, 89, 410, 25,
+ /* 1070 */ 317, 417, 417, 417, 418, 419, 12, 410, 54, 186,
+ /* 1080 */ 410, 113, 354, 317, 264, 410, 114, 317, 410, 26,
+ /* 1090 */ 361, 364, 410, 37, 579, 365, 287, 317, 267, 317,
+ /* 1100 */ 143, 317, 373, 275, 265, 410, 38, 268, 290, 410,
+ /* 1110 */ 27, 317, 269, 205, 555, 565, 317, 277, 317, 410,
+ /* 1120 */ 39, 410, 40, 410, 42, 317, 280, 317, 281, 317,
+ /* 1130 */ 576, 317, 225, 410, 43, 401, 503, 379, 410, 44,
+ /* 1140 */ 410, 30, 317, 325, 440, 317, 461, 410, 31, 410,
+ /* 1150 */ 45, 410, 46, 410, 47, 442, 317, 551, 317, 464,
+ /* 1160 */ 317, 241, 513, 516, 410, 48, 344, 410, 32, 562,
+ /* 1170 */ 160, 390, 398, 399, 400, 8, 314, 412, 410, 11,
+ /* 1180 */ 410, 50, 410, 51, 82, 332, 226, 81, 330, 227,
+ /* 1190 */ 57, 406, 414, 228, 78, 167, 229, 209, 83, 413,
+ /* 1200 */ 459, 122, 335, 339, 500, 490, 235, 495, 242, 473,
+ /* 1210 */ 237, 300, 477, 499, 496, 501, 103, 284, 246, 514,
+ /* 1220 */ 518, 519, 525, 526, 527, 351, 533, 181, 285, 182,
+ /* 1230 */ 184, 214, 353, 185, 535, 187, 215, 355, 86, 118,
+ /* 1240 */ 360, 547, 190, 129, 139, 371, 262, 372, 130, 536,
+ /* 1250 */ 554, 310, 131, 132, 573, 90, 133, 135, 93, 138,
+ /* 1260 */ 578, 574, 575, 109, 213, 561, 101, 119, 389, 18,
+ /* 1270 */ 98, 402, 622, 623, 163, 164, 429, 312, 432, 71,
+ /* 1280 */ 449, 437, 446, 140, 154, 166, 450, 6, 451, 470,
+ /* 1290 */ 7, 123, 14, 13, 124, 158, 484, 212, 84, 343,
+ /* 1300 */ 104, 348, 250, 105, 85, 117, 106, 240, 179, 352,
+ /* 1310 */ 142, 534, 126, 305, 170, 263, 188, 107, 286, 550,
+ /* 1320 */ 127, 128, 15, 542, 192, 87, 194, 88, 195, 557,
+ /* 1330 */ 196, 136, 137, 134, 16, 108, 571, 282, 381, 564,
+ /* 1340 */ 203, 145, 385, 901, 585,
};
static const YYCODETYPE yy_lookahead[] = {
- /* 0 */ 16, 216, 16, 218, 219, 21, 146, 23, 68, 69,
- /* 10 */ 70, 71, 109, 73, 74, 75, 76, 77, 78, 79,
- /* 20 */ 80, 81, 82, 82, 164, 165, 42, 72, 73, 74,
- /* 30 */ 75, 76, 77, 78, 79, 80, 81, 82, 216, 217,
- /* 40 */ 218, 219, 168, 59, 60, 61, 62, 63, 64, 65,
- /* 50 */ 66, 67, 68, 69, 70, 71, 168, 73, 74, 75,
- /* 60 */ 76, 77, 78, 79, 80, 81, 82, 16, 140, 16,
- /* 70 */ 86, 143, 23, 22, 88, 89, 90, 91, 92, 93,
- /* 80 */ 94, 95, 138, 139, 140, 146, 226, 143, 102, 166,
- /* 90 */ 167, 152, 19, 42, 155, 156, 23, 46, 175, 180,
- /* 100 */ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
- /* 110 */ 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
- /* 120 */ 69, 70, 71, 11, 73, 74, 75, 76, 77, 78,
- /* 130 */ 79, 80, 81, 82, 16, 86, 87, 88, 1, 2,
- /* 140 */ 91, 92, 93, 90, 91, 92, 93, 94, 95, 175,
- /* 150 */ 176, 19, 103, 21, 23, 102, 182, 141, 142, 86,
- /* 160 */ 42, 49, 44, 147, 79, 80, 81, 82, 180, 154,
- /* 170 */ 154, 77, 78, 79, 80, 81, 82, 59, 60, 61,
- /* 180 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
- /* 190 */ 146, 73, 74, 75, 76, 77, 78, 79, 80, 81,
- /* 200 */ 82, 16, 14, 188, 188, 58, 21, 12, 77, 78,
- /* 210 */ 98, 99, 100, 146, 22, 200, 201, 86, 87, 24,
- /* 220 */ 205, 109, 216, 154, 218, 219, 189, 42, 97, 213,
- /* 230 */ 160, 187, 37, 86, 39, 168, 169, 90, 160, 161,
- /* 240 */ 162, 53, 236, 55, 59, 60, 61, 62, 63, 64,
- /* 250 */ 65, 66, 67, 68, 69, 70, 71, 188, 73, 74,
- /* 260 */ 75, 76, 77, 78, 79, 80, 81, 82, 16, 199,
- /* 270 */ 123, 124, 125, 149, 146, 208, 209, 77, 78, 146,
- /* 280 */ 88, 237, 146, 91, 92, 93, 216, 146, 218, 219,
- /* 290 */ 154, 0, 1, 2, 42, 103, 168, 169, 21, 160,
- /* 300 */ 23, 168, 169, 157, 168, 169, 160, 161, 162, 168,
- /* 310 */ 169, 59, 60, 61, 62, 63, 64, 65, 66, 67,
- /* 320 */ 68, 69, 70, 71, 188, 73, 74, 75, 76, 77,
- /* 330 */ 78, 79, 80, 81, 82, 146, 146, 12, 199, 211,
- /* 340 */ 16, 184, 185, 154, 211, 155, 156, 211, 224, 24,
- /* 350 */ 88, 223, 228, 91, 92, 93, 223, 168, 169, 223,
- /* 360 */ 20, 220, 37, 86, 39, 103, 42, 159, 146, 179,
- /* 370 */ 180, 146, 18, 146, 49, 160, 168, 188, 184, 185,
- /* 380 */ 155, 156, 130, 59, 60, 61, 62, 63, 64, 65,
- /* 390 */ 66, 67, 68, 69, 70, 71, 90, 73, 74, 75,
- /* 400 */ 76, 77, 78, 79, 80, 81, 82, 146, 102, 154,
- /* 410 */ 16, 146, 16, 146, 199, 20, 20, 146, 185, 146,
- /* 420 */ 167, 20, 163, 164, 165, 7, 8, 9, 175, 168,
- /* 430 */ 169, 163, 164, 165, 212, 168, 169, 43, 42, 168,
- /* 440 */ 169, 168, 169, 188, 22, 105, 92, 107, 108, 19,
- /* 450 */ 23, 146, 187, 23, 130, 59, 60, 61, 62, 63,
- /* 460 */ 64, 65, 66, 67, 68, 69, 70, 71, 213, 73,
- /* 470 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 16,
- /* 480 */ 209, 146, 215, 20, 223, 226, 132, 154, 215, 234,
- /* 490 */ 23, 97, 23, 19, 226, 23, 102, 23, 109, 42,
- /* 500 */ 105, 23, 107, 108, 146, 42, 105, 146, 107, 108,
- /* 510 */ 23, 122, 207, 86, 87, 146, 86, 87, 96, 62,
- /* 520 */ 63, 188, 59, 60, 61, 62, 63, 64, 65, 66,
- /* 530 */ 67, 68, 69, 70, 71, 14, 73, 74, 75, 76,
- /* 540 */ 77, 78, 79, 80, 81, 82, 16, 90, 146, 146,
- /* 550 */ 20, 79, 146, 86, 87, 86, 87, 30, 86, 87,
- /* 560 */ 86, 87, 146, 25, 86, 87, 105, 29, 107, 108,
- /* 570 */ 168, 169, 42, 86, 53, 146, 55, 50, 146, 41,
- /* 580 */ 113, 212, 113, 225, 168, 169, 146, 181, 144, 59,
- /* 590 */ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
- /* 600 */ 70, 71, 146, 73, 74, 75, 76, 77, 78, 79,
- /* 610 */ 80, 81, 82, 16, 146, 22, 187, 20, 190, 146,
- /* 620 */ 109, 146, 146, 146, 168, 169, 146, 191, 101, 146,
- /* 630 */ 146, 225, 146, 122, 198, 146, 168, 169, 129, 42,
- /* 640 */ 131, 168, 169, 168, 169, 168, 169, 207, 168, 169,
- /* 650 */ 154, 168, 169, 132, 168, 169, 59, 60, 61, 62,
- /* 660 */ 63, 64, 65, 66, 67, 68, 69, 70, 71, 146,
- /* 670 */ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
- /* 680 */ 16, 146, 27, 207, 188, 21, 146, 154, 146, 34,
- /* 690 */ 146, 168, 169, 146, 20, 146, 22, 146, 98, 99,
- /* 700 */ 100, 200, 201, 168, 169, 112, 42, 16, 168, 169,
- /* 710 */ 168, 169, 168, 169, 146, 168, 169, 168, 169, 168,
- /* 720 */ 169, 188, 22, 59, 60, 61, 62, 63, 64, 65,
- /* 730 */ 66, 67, 68, 69, 70, 71, 146, 73, 74, 75,
- /* 740 */ 76, 77, 78, 79, 80, 81, 82, 16, 146, 146,
- /* 750 */ 146, 146, 146, 146, 146, 187, 146, 22, 168, 169,
- /* 760 */ 146, 98, 99, 100, 146, 106, 146, 123, 124, 110,
- /* 770 */ 168, 169, 160, 42, 168, 169, 168, 169, 168, 169,
- /* 780 */ 43, 90, 168, 169, 181, 181, 168, 169, 168, 169,
- /* 790 */ 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
- /* 800 */ 69, 70, 71, 146, 73, 74, 75, 76, 77, 78,
- /* 810 */ 79, 80, 81, 82, 16, 146, 146, 146, 146, 146,
- /* 820 */ 120, 146, 87, 146, 202, 168, 169, 146, 225, 225,
- /* 830 */ 7, 8, 146, 20, 97, 22, 146, 168, 169, 146,
- /* 840 */ 42, 168, 169, 168, 169, 168, 169, 146, 113, 168,
- /* 850 */ 169, 181, 181, 146, 168, 169, 79, 59, 60, 61,
- /* 860 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
- /* 870 */ 146, 73, 74, 75, 76, 77, 78, 79, 80, 81,
- /* 880 */ 82, 16, 146, 106, 89, 90, 146, 110, 146, 20,
- /* 890 */ 146, 22, 168, 169, 146, 225, 225, 20, 20, 22,
- /* 900 */ 22, 51, 52, 154, 168, 169, 177, 42, 168, 169,
- /* 910 */ 168, 169, 168, 169, 146, 177, 168, 169, 146, 146,
- /* 920 */ 146, 146, 146, 19, 16, 60, 61, 62, 63, 64,
- /* 930 */ 65, 66, 67, 68, 69, 70, 71, 188, 73, 74,
- /* 940 */ 75, 76, 77, 78, 79, 80, 81, 82, 177, 20,
- /* 950 */ 42, 22, 146, 20, 20, 22, 22, 146, 20, 187,
- /* 960 */ 22, 187, 187, 187, 20, 20, 22, 22, 146, 61,
- /* 970 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
- /* 980 */ 19, 73, 74, 75, 76, 77, 78, 79, 80, 81,
- /* 990 */ 82, 16, 17, 187, 19, 146, 230, 146, 23, 146,
- /* 1000 */ 231, 146, 146, 146, 146, 146, 31, 16, 17, 146,
- /* 1010 */ 19, 171, 146, 146, 23, 111, 146, 146, 190, 192,
- /* 1020 */ 148, 227, 31, 48, 227, 222, 193, 193, 67, 6,
- /* 1030 */ 176, 171, 171, 58, 172, 171, 145, 145, 145, 48,
- /* 1040 */ 145, 22, 153, 97, 171, 170, 170, 40, 96, 58,
- /* 1050 */ 170, 170, 77, 78, 172, 120, 188, 178, 117, 119,
- /* 1060 */ 85, 86, 87, 221, 115, 90, 118, 193, 77, 78,
- /* 1070 */ 79, 129, 151, 111, 95, 23, 85, 86, 87, 16,
- /* 1080 */ 17, 90, 19, 195, 109, 159, 23, 197, 194, 97,
- /* 1090 */ 151, 114, 196, 210, 31, 210, 19, 173, 123, 124,
- /* 1100 */ 125, 126, 127, 128, 203, 178, 204, 204, 203, 210,
- /* 1110 */ 210, 48, 159, 170, 123, 124, 125, 126, 127, 128,
- /* 1120 */ 170, 58, 5, 15, 170, 151, 150, 10, 11, 12,
- /* 1130 */ 13, 173, 151, 151, 151, 19, 38, 129, 232, 23,
- /* 1140 */ 77, 78, 233, 26, 150, 28, 151, 59, 85, 86,
- /* 1150 */ 87, 183, 35, 90, 183, 19, 193, 15, 186, 186,
- /* 1160 */ 193, 214, 151, 183, 47, 214, 49, 33, 151, 151,
- /* 1170 */ 186, 54, 235, 56, 58, 136, 174, 174, 158, 1,
- /* 1180 */ 20, 32, 44, 19, 229, 111, 123, 124, 125, 126,
- /* 1190 */ 127, 128, 235, 77, 78, 111, 111, 238, 111, 19,
- /* 1200 */ 90, 20, 86, 20, 19, 106, 90, 11, 19, 22,
- /* 1210 */ 20, 20, 116, 116, 22, 98, 99, 100, 113, 22,
- /* 1220 */ 19, 104, 20, 111, 20, 19, 109, 20, 44, 19,
- /* 1230 */ 19, 19, 44, 94, 102, 16, 21, 17, 97, 123,
- /* 1240 */ 124, 125, 97, 45, 36, 22, 132, 19, 45, 5,
- /* 1250 */ 133, 1, 101, 67, 121, 19, 112, 17, 112, 101,
- /* 1260 */ 67, 121, 19, 14, 134, 20, 57, 3, 239, 4,
- /* 1270 */ 135,
+ /* 0 */ 16, 140, 141, 142, 111, 21, 145, 23, 70, 71,
+ /* 10 */ 72, 73, 23, 75, 76, 77, 78, 79, 80, 81,
+ /* 20 */ 82, 83, 84, 85, 156, 16, 42, 43, 74, 75,
+ /* 30 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ /* 40 */ 217, 59, 219, 220, 85, 61, 62, 63, 64, 65,
+ /* 50 */ 66, 67, 68, 69, 70, 71, 72, 73, 190, 75,
+ /* 60 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ /* 70 */ 16, 89, 148, 89, 148, 93, 22, 217, 89, 219,
+ /* 80 */ 220, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+ /* 90 */ 84, 85, 166, 167, 85, 142, 42, 43, 145, 239,
+ /* 100 */ 46, 92, 93, 94, 95, 96, 97, 125, 126, 127,
+ /* 110 */ 148, 1, 2, 104, 16, 61, 62, 63, 64, 65,
+ /* 120 */ 66, 67, 68, 69, 70, 71, 72, 73, 166, 75,
+ /* 130 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
+ /* 140 */ 42, 43, 44, 79, 80, 81, 82, 83, 84, 85,
+ /* 150 */ 226, 23, 19, 156, 228, 229, 23, 79, 80, 61,
+ /* 160 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+ /* 170 */ 72, 73, 111, 75, 76, 77, 78, 79, 80, 81,
+ /* 180 */ 82, 83, 84, 85, 16, 124, 148, 190, 148, 21,
+ /* 190 */ 228, 229, 59, 22, 154, 157, 158, 157, 158, 202,
+ /* 200 */ 203, 148, 84, 85, 207, 168, 169, 79, 80, 170,
+ /* 210 */ 42, 43, 79, 80, 177, 170, 161, 89, 90, 181,
+ /* 220 */ 182, 191, 89, 170, 171, 170, 93, 99, 16, 61,
+ /* 230 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+ /* 240 */ 72, 73, 148, 75, 76, 77, 78, 79, 80, 81,
+ /* 250 */ 82, 83, 84, 85, 42, 43, 186, 187, 125, 126,
+ /* 260 */ 127, 90, 11, 210, 211, 81, 82, 83, 84, 85,
+ /* 270 */ 186, 187, 16, 61, 62, 63, 64, 65, 66, 67,
+ /* 280 */ 68, 69, 70, 71, 72, 73, 115, 75, 76, 77,
+ /* 290 */ 78, 79, 80, 81, 82, 83, 84, 85, 42, 43,
+ /* 300 */ 49, 16, 91, 209, 148, 94, 95, 96, 162, 217,
+ /* 310 */ 218, 219, 220, 157, 158, 81, 105, 61, 62, 63,
+ /* 320 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ /* 330 */ 182, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+ /* 340 */ 84, 85, 108, 182, 132, 16, 112, 201, 12, 20,
+ /* 350 */ 23, 100, 101, 102, 159, 22, 169, 162, 163, 164,
+ /* 360 */ 24, 148, 111, 217, 177, 219, 220, 177, 178, 156,
+ /* 370 */ 85, 42, 43, 37, 184, 39, 91, 92, 93, 94,
+ /* 380 */ 95, 96, 97, 170, 171, 49, 245, 246, 132, 104,
+ /* 390 */ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
+ /* 400 */ 71, 72, 73, 190, 75, 76, 77, 78, 79, 80,
+ /* 410 */ 81, 82, 83, 84, 85, 16, 89, 90, 91, 20,
+ /* 420 */ 30, 94, 95, 96, 91, 212, 148, 94, 95, 96,
+ /* 430 */ 148, 148, 105, 19, 148, 21, 148, 224, 105, 156,
+ /* 440 */ 50, 42, 43, 19, 165, 166, 167, 23, 170, 171,
+ /* 450 */ 187, 148, 162, 170, 171, 148, 170, 171, 170, 171,
+ /* 460 */ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
+ /* 470 */ 71, 72, 73, 190, 75, 76, 77, 78, 79, 80,
+ /* 480 */ 81, 82, 83, 84, 85, 16, 20, 20, 22, 20,
+ /* 490 */ 212, 201, 189, 103, 148, 213, 148, 148, 212, 148,
+ /* 500 */ 23, 148, 224, 148, 202, 203, 42, 43, 229, 221,
+ /* 510 */ 224, 42, 43, 89, 143, 144, 170, 171, 170, 171,
+ /* 520 */ 149, 170, 171, 170, 171, 170, 171, 156, 64, 65,
+ /* 530 */ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
+ /* 540 */ 71, 72, 73, 240, 75, 76, 77, 78, 79, 80,
+ /* 550 */ 81, 82, 83, 84, 85, 16, 79, 93, 209, 20,
+ /* 560 */ 20, 190, 211, 151, 216, 16, 89, 90, 20, 216,
+ /* 570 */ 224, 165, 166, 167, 107, 19, 109, 110, 19, 23,
+ /* 580 */ 25, 42, 43, 22, 29, 214, 19, 20, 18, 22,
+ /* 590 */ 19, 20, 43, 22, 162, 23, 41, 162, 163, 164,
+ /* 600 */ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
+ /* 610 */ 71, 72, 73, 242, 75, 76, 77, 78, 79, 80,
+ /* 620 */ 81, 82, 83, 84, 85, 16, 56, 60, 69, 12,
+ /* 630 */ 21, 60, 19, 201, 108, 229, 23, 225, 112, 23,
+ /* 640 */ 148, 24, 21, 231, 23, 89, 90, 107, 99, 109,
+ /* 650 */ 110, 42, 43, 104, 37, 107, 39, 109, 110, 148,
+ /* 660 */ 27, 89, 90, 148, 148, 95, 148, 34, 14, 16,
+ /* 670 */ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
+ /* 680 */ 71, 72, 73, 122, 75, 76, 77, 78, 79, 80,
+ /* 690 */ 81, 82, 83, 84, 85, 42, 43, 81, 183, 183,
+ /* 700 */ 189, 183, 89, 90, 134, 89, 90, 53, 148, 55,
+ /* 710 */ 89, 148, 148, 16, 61, 62, 63, 64, 65, 66,
+ /* 720 */ 67, 68, 69, 70, 71, 72, 73, 148, 75, 76,
+ /* 730 */ 77, 78, 79, 80, 81, 82, 83, 84, 85, 42,
+ /* 740 */ 43, 226, 226, 183, 226, 148, 183, 0, 1, 2,
+ /* 750 */ 7, 8, 9, 107, 146, 109, 110, 16, 61, 62,
+ /* 760 */ 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+ /* 770 */ 73, 148, 75, 76, 77, 78, 79, 80, 81, 82,
+ /* 780 */ 83, 84, 85, 42, 43, 148, 226, 148, 134, 226,
+ /* 790 */ 100, 101, 102, 170, 171, 100, 101, 102, 19, 148,
+ /* 800 */ 148, 16, 192, 62, 63, 64, 65, 66, 67, 68,
+ /* 810 */ 69, 70, 71, 72, 73, 92, 75, 76, 77, 78,
+ /* 820 */ 79, 80, 81, 82, 83, 84, 85, 42, 43, 23,
+ /* 830 */ 243, 244, 23, 16, 111, 148, 148, 22, 14, 156,
+ /* 840 */ 189, 189, 148, 131, 148, 133, 209, 124, 63, 64,
+ /* 850 */ 65, 66, 67, 68, 69, 70, 71, 72, 73, 148,
+ /* 860 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
+ /* 870 */ 85, 16, 17, 190, 19, 148, 189, 53, 23, 55,
+ /* 880 */ 43, 22, 148, 189, 148, 189, 31, 16, 17, 156,
+ /* 890 */ 19, 156, 113, 156, 23, 89, 90, 214, 89, 90,
+ /* 900 */ 189, 213, 31, 48, 170, 171, 170, 171, 156, 148,
+ /* 910 */ 93, 193, 125, 126, 59, 148, 189, 148, 200, 48,
+ /* 920 */ 237, 115, 93, 190, 115, 190, 20, 190, 22, 114,
+ /* 930 */ 59, 170, 171, 104, 79, 80, 99, 170, 171, 170,
+ /* 940 */ 171, 148, 190, 88, 89, 90, 20, 20, 93, 22,
+ /* 950 */ 79, 80, 81, 148, 92, 93, 148, 98, 148, 88,
+ /* 960 */ 89, 90, 16, 17, 93, 19, 111, 148, 148, 23,
+ /* 970 */ 148, 148, 20, 162, 22, 170, 171, 31, 170, 171,
+ /* 980 */ 125, 126, 127, 128, 129, 130, 60, 204, 148, 170,
+ /* 990 */ 171, 148, 170, 171, 48, 148, 125, 126, 127, 128,
+ /* 1000 */ 129, 130, 7, 8, 20, 59, 22, 5, 148, 148,
+ /* 1010 */ 170, 171, 10, 11, 12, 13, 51, 52, 148, 20,
+ /* 1020 */ 148, 22, 148, 148, 179, 79, 80, 20, 26, 22,
+ /* 1030 */ 28, 170, 171, 179, 88, 89, 90, 35, 148, 93,
+ /* 1040 */ 170, 171, 170, 171, 170, 171, 148, 179, 20, 47,
+ /* 1050 */ 22, 49, 20, 148, 22, 148, 54, 148, 148, 57,
+ /* 1060 */ 20, 148, 22, 148, 148, 20, 148, 22, 170, 171,
+ /* 1070 */ 148, 125, 126, 127, 128, 129, 130, 170, 171, 233,
+ /* 1080 */ 170, 171, 234, 148, 148, 170, 171, 148, 170, 171,
+ /* 1090 */ 148, 148, 170, 171, 20, 148, 22, 148, 148, 148,
+ /* 1100 */ 192, 148, 100, 101, 102, 170, 171, 148, 106, 170,
+ /* 1110 */ 171, 148, 148, 111, 148, 148, 148, 148, 148, 170,
+ /* 1120 */ 171, 170, 171, 170, 171, 148, 148, 148, 148, 148,
+ /* 1130 */ 148, 148, 194, 170, 171, 150, 178, 135, 170, 171,
+ /* 1140 */ 170, 171, 148, 223, 230, 148, 173, 170, 171, 170,
+ /* 1150 */ 171, 170, 171, 170, 171, 230, 148, 195, 148, 173,
+ /* 1160 */ 148, 173, 173, 173, 170, 171, 174, 170, 171, 195,
+ /* 1170 */ 6, 147, 147, 147, 147, 22, 155, 190, 170, 171,
+ /* 1180 */ 170, 171, 170, 171, 122, 119, 195, 120, 117, 196,
+ /* 1190 */ 121, 23, 161, 197, 131, 113, 198, 222, 99, 199,
+ /* 1200 */ 153, 153, 116, 99, 98, 172, 205, 172, 172, 206,
+ /* 1210 */ 205, 40, 206, 174, 180, 172, 19, 175, 85, 161,
+ /* 1220 */ 161, 180, 172, 172, 172, 15, 153, 152, 175, 152,
+ /* 1230 */ 152, 227, 153, 153, 153, 152, 227, 38, 131, 61,
+ /* 1240 */ 153, 185, 185, 19, 215, 153, 235, 15, 188, 236,
+ /* 1250 */ 195, 153, 188, 188, 33, 238, 188, 185, 238, 215,
+ /* 1260 */ 138, 153, 153, 241, 176, 195, 176, 244, 1, 232,
+ /* 1270 */ 160, 20, 113, 113, 113, 113, 93, 247, 108, 19,
+ /* 1280 */ 11, 20, 20, 19, 19, 22, 20, 118, 20, 115,
+ /* 1290 */ 118, 19, 22, 22, 20, 113, 20, 44, 19, 44,
+ /* 1300 */ 19, 44, 20, 19, 19, 32, 19, 104, 97, 16,
+ /* 1310 */ 21, 17, 99, 36, 22, 134, 99, 19, 5, 1,
+ /* 1320 */ 45, 103, 19, 45, 123, 69, 114, 69, 14, 17,
+ /* 1330 */ 116, 103, 123, 114, 19, 14, 20, 137, 58, 124,
+ /* 1340 */ 136, 19, 3, 248, 4,
};
-#define YY_SHIFT_USE_DFLT (-98)
-#define YY_SHIFT_MAX 369
+#define YY_SHIFT_USE_DFLT (-108)
+#define YY_SHIFT_MAX 385
static const short yy_shift_ofst[] = {
- /* 0 */ 137, 975, 1117, -16, 975, 1063, 1063, 1063, 49, -97,
- /* 10 */ 118, 1063, 1063, 1063, 1063, 1063, -45, 112, 131, 478,
- /* 20 */ 487, 200, 200, 51, 185, 252, 324, 396, 463, 530,
- /* 30 */ 597, 664, 731, 798, 731, 731, 731, 731, 731, 731,
- /* 40 */ 731, 731, 731, 731, 731, 731, 731, 731, 731, 731,
- /* 50 */ 731, 865, 908, 908, 991, 1063, 1063, 1063, 1063, 1063,
- /* 60 */ 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063,
- /* 70 */ 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063,
- /* 80 */ 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063,
- /* 90 */ 1063, 1063, 1063, -60, -60, -14, 27, 27, 94, 85,
- /* 100 */ 394, 478, 478, 478, 478, 354, 478, 478, 478, 487,
- /* 110 */ -59, -98, -98, -98, 1116, 53, 325, 325, 291, 277,
- /* 120 */ 478, 277, 478, 478, 478, 478, 478, 478, 478, 478,
- /* 130 */ 478, 478, 478, 478, 478, 389, 511, -97, -97, -97,
- /* 140 */ -98, -98, 147, 147, 192, 262, 340, 430, 395, 401,
- /* 150 */ 195, 467, 469, 474, 472, 418, 427, 427, 777, 427,
- /* 160 */ 427, 73, 427, 427, 735, 427, 427, 461, 735, 427,
- /* 170 */ 427, 527, 527, 527, 427, 427, 461, 427, 427, 461,
- /* 180 */ 427, 538, 600, 427, 427, 461, 427, 427, 427, 461,
- /* 190 */ 427, 461, 461, 427, 427, 427, 427, 427, 427, 132,
- /* 200 */ 655, 659, 593, 644, 644, 509, 655, 655, 737, 655,
- /* 210 */ 655, 422, 700, 700, 1023, 1023, 1023, 1023, 1019, 946,
- /* 220 */ 946, 1007, 946, 952, 946, -97, 935, 941, 948, 949,
- /* 230 */ 940, 942, 962, 979, 1052, 979, 962, 992, 977, 992,
- /* 240 */ 977, 1077, 979, 979, 1052, 1007, 946, 946, 946, 1077,
- /* 250 */ 1108, 962, 962, 962, 962, 1098, 1008, 1108, 962, 1088,
- /* 260 */ 1088, 1136, 935, 1142, 1142, 1142, 935, 1088, 1136, 962,
- /* 270 */ 1134, 1134, 962, 962, 1039, -98, -98, -98, -98, 457,
- /* 280 */ 521, 663, 188, 306, 823, 904, 674, 691, 813, 869,
- /* 290 */ 877, 795, 878, 929, 933, 850, 934, 938, 944, 945,
- /* 300 */ 961, 1178, 1160, 1149, 1138, 1164, 1074, 1084, 1085, 1087,
- /* 310 */ 1180, 1181, 1183, 1110, 1099, 1185, 1196, 1189, 1190, 1187,
- /* 320 */ 1191, 1096, 1192, 1097, 1197, 1105, 1201, 1202, 1112, 1204,
- /* 330 */ 1184, 1206, 1207, 1210, 1211, 1188, 1212, 1139, 1132, 1219,
- /* 340 */ 1220, 1215, 1141, 1208, 1198, 1223, 1203, 1114, 1145, 1228,
- /* 350 */ 1244, 1250, 1151, 1186, 1193, 1133, 1236, 1144, 1240, 1146,
- /* 360 */ 1158, 1140, 1243, 1245, 1249, 1209, 1130, 1135, 1264, 1265,
+ /* 0 */ 110, 855, 1002, -16, 855, 946, 946, 946, 327, 128,
+ /* 10 */ -107, 98, 946, 946, 946, 946, 946, -46, 251, 477,
+ /* 20 */ 572, -11, 78, 78, 54, 168, 212, 256, 329, 399,
+ /* 30 */ 469, 539, 609, 653, 697, 653, 653, 653, 653, 653,
+ /* 40 */ 653, 653, 653, 653, 653, 653, 653, 653, 653, 653,
+ /* 50 */ 653, 653, 741, 785, 785, 871, 946, 946, 946, 946,
+ /* 60 */ 946, 946, 946, 946, 946, 946, 946, 946, 946, 946,
+ /* 70 */ 946, 946, 946, 946, 946, 946, 946, 946, 946, 946,
+ /* 80 */ 946, 946, 946, 946, 946, 946, 946, 946, 946, 946,
+ /* 90 */ 946, 946, 946, 946, -62, -62, 6, 6, 285, 64,
+ /* 100 */ 184, 549, 570, 572, 572, 572, 572, 572, 572, 572,
+ /* 110 */ 118, -11, -41, -108, -108, 133, 9, 336, 336, 567,
+ /* 120 */ 571, 747, 621, 572, 621, 572, 572, 572, 572, 572,
+ /* 130 */ 572, 572, 572, 572, 572, 572, 572, 572, 723, 61,
+ /* 140 */ -107, -107, -107, -108, -108, -108, -18, -18, 333, 211,
+ /* 150 */ 467, 556, 540, 548, 617, 806, 809, 613, 616, 743,
+ /* 160 */ 572, 572, 234, 572, 572, 424, 572, 572, 171, 572,
+ /* 170 */ 572, 646, 171, 572, 572, 390, 390, 390, 572, 572,
+ /* 180 */ 646, 572, 572, 646, 572, 555, 690, 572, 572, 646,
+ /* 190 */ 572, 572, 572, 646, 572, 572, 572, 646, 646, 572,
+ /* 200 */ 572, 572, 572, 572, 414, 526, 815, 787, 787, 712,
+ /* 210 */ 633, 633, 633, 837, 633, 633, 859, 561, 561, 1164,
+ /* 220 */ 1164, 1164, 1164, 1153, -107, 1062, 1066, 1067, 1071, 1069,
+ /* 230 */ 1168, 1063, 1082, 1082, 1099, 1086, 1099, 1086, 1104, 1104,
+ /* 240 */ 1171, 1104, 1106, 1104, 1197, 1133, 1168, 1133, 1168, 1171,
+ /* 250 */ 1104, 1104, 1104, 1197, 1210, 1082, 1210, 1082, 1210, 1082,
+ /* 260 */ 1082, 1199, 1107, 1210, 1082, 1178, 1178, 1224, 1062, 1082,
+ /* 270 */ 1232, 1232, 1232, 1232, 1062, 1178, 1224, 1082, 1221, 1221,
+ /* 280 */ 1082, 1082, 1122, -108, -108, -108, -108, -108, -108, 464,
+ /* 290 */ 654, 695, 824, 779, 817, 466, 906, 927, 952, 829,
+ /* 300 */ 995, 862, 984, 999, 1007, 965, 1028, 1032, 1040, 1045,
+ /* 310 */ 559, 1074, 926, 1267, 1251, 1159, 1160, 1161, 1162, 1183,
+ /* 320 */ 1170, 1260, 1261, 1262, 1264, 1269, 1265, 1266, 1263, 1268,
+ /* 330 */ 1169, 1270, 1172, 1271, 1174, 1272, 1274, 1182, 1276, 1273,
+ /* 340 */ 1253, 1279, 1255, 1281, 1282, 1284, 1285, 1257, 1287, 1211,
+ /* 350 */ 1203, 1293, 1294, 1289, 1213, 1277, 1275, 1292, 1278, 1181,
+ /* 360 */ 1217, 1298, 1313, 1318, 1218, 1256, 1258, 1201, 1303, 1212,
+ /* 370 */ 1314, 1214, 1312, 1219, 1228, 1209, 1315, 1215, 1316, 1321,
+ /* 380 */ 1280, 1204, 1200, 1322, 1339, 1340,
};
-#define YY_REDUCE_USE_DFLT (-216)
-#define YY_REDUCE_MAX 278
+#define YY_REDUCE_USE_DFLT (-178)
+#define YY_REDUCE_MAX 288
static const short yy_reduce_ofst[] = {
- /* 0 */ -56, 136, 16, 70, 189, 128, 67, 133, 190, 15,
- /* 10 */ 6, 141, 261, 271, 267, 273, -178, 255, -140, -61,
- /* 20 */ 146, 259, 268, -215, -215, -215, -215, -215, -215, -215,
- /* 30 */ -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
- /* 40 */ -215, -215, -215, -215, -215, -215, -215, -215, -215, -215,
- /* 50 */ -215, -215, -215, -215, 402, 416, 456, 468, 473, 475,
- /* 60 */ 477, 480, 483, 486, 523, 535, 540, 542, 544, 547,
- /* 70 */ 549, 551, 590, 602, 606, 608, 610, 614, 618, 620,
- /* 80 */ 657, 669, 673, 675, 677, 681, 686, 724, 736, 740,
- /* 90 */ 742, 744, 748, -215, -215, -77, -215, -215, -215, -215,
- /* 100 */ -26, 406, 603, 604, 670, 124, 671, 44, 225, 78,
- /* 110 */ -215, -215, -215, -215, 208, 253, 157, 194, -72, 139,
- /* 120 */ 305, 215, 358, 265, 440, 222, 476, 429, 568, 772,
- /* 130 */ 774, 775, 776, 369, 806, 69, 333, 496, 533, 749,
- /* 140 */ 436, 501, -126, -112, -81, -12, 37, 227, 37, 37,
- /* 150 */ 233, 335, 361, 403, 432, 444, 484, 489, 428, 432,
- /* 160 */ 605, 612, 607, 672, 622, 690, 693, 37, 622, 701,
- /* 170 */ 707, 729, 738, 771, 768, 773, 37, 811, 822, 37,
- /* 180 */ 849, 766, 769, 851, 853, 37, 855, 856, 857, 37,
- /* 190 */ 858, 37, 37, 859, 863, 866, 867, 870, 871, 872,
- /* 200 */ 840, 828, 827, 794, 797, 803, 860, 861, 854, 864,
- /* 210 */ 873, 862, 833, 834, 891, 892, 893, 895, 889, 875,
- /* 220 */ 876, 879, 880, 882, 881, 868, 874, 894, 888, 896,
- /* 230 */ 890, 842, 921, 883, 926, 885, 939, 901, 902, 905,
- /* 240 */ 903, 924, 899, 900, 953, 927, 943, 950, 954, 958,
- /* 250 */ 976, 974, 981, 982, 983, 906, 909, 994, 995, 968,
- /* 260 */ 971, 947, 963, 972, 973, 984, 967, 980, 951, 1011,
- /* 270 */ 937, 957, 1017, 1018, 959, 1020, 1002, 1003, 955,
+ /* 0 */ -139, 213, 371, 146, 283, 278, 53, 286, 38, -74,
+ /* 10 */ -3, -140, 288, 346, 351, 348, 353, 92, 683, -38,
+ /* 20 */ 40, 195, 279, 406, -177, -177, -177, -177, -177, -177,
+ /* 30 */ -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+ /* 40 */ -177, -177, -177, -177, -177, -177, -177, -177, -177, -177,
+ /* 50 */ -177, -177, -177, -177, -177, 355, 623, 734, 736, 761,
+ /* 60 */ 767, 769, 805, 808, 819, 822, 840, 861, 870, 872,
+ /* 70 */ 874, 898, 907, 910, 915, 918, 922, 935, 939, 949,
+ /* 80 */ 951, 953, 963, 968, 970, 977, 979, 981, 983, 994,
+ /* 90 */ 997, 1008, 1010, 1012, -177, -177, -177, -177, 37, -177,
+ /* 100 */ -177, 190, 412, 515, 516, 518, 560, 563, 303, 156,
+ /* 110 */ -177, 435, -177, -177, -177, 55, 187, 70, 84, 141,
+ /* 120 */ 141, -47, 290, 94, 432, -76, 511, 349, 282, 637,
+ /* 130 */ 651, 652, 687, 694, 696, 711, 688, 727, -132, 733,
+ /* 140 */ 735, 737, 752, 718, 302, 587, 39, 45, 148, 161,
+ /* 150 */ 30, 307, 30, 30, 263, 492, 564, 579, 597, 608,
+ /* 160 */ 639, 793, 610, 597, 810, 811, 820, 823, 783, 843,
+ /* 170 */ 847, 30, 783, 860, 875, 845, 854, 868, 890, 905,
+ /* 180 */ 30, 909, 913, 30, 916, 846, 848, 936, 942, 30,
+ /* 190 */ 943, 947, 950, 30, 959, 964, 966, 30, 30, 967,
+ /* 200 */ 969, 978, 980, 982, 985, 908, 938, 914, 925, 920,
+ /* 210 */ 973, 986, 988, 958, 989, 990, 992, 962, 974, 1024,
+ /* 220 */ 1025, 1026, 1027, 1021, 987, 991, 993, 996, 998, 1000,
+ /* 230 */ 1031, 975, 1047, 1048, 1001, 1003, 1005, 1006, 1033, 1035,
+ /* 240 */ 1034, 1036, 1039, 1043, 1042, 1004, 1058, 1009, 1059, 1041,
+ /* 250 */ 1050, 1051, 1052, 1053, 1075, 1073, 1077, 1079, 1078, 1080,
+ /* 260 */ 1081, 1011, 1013, 1083, 1087, 1056, 1057, 1029, 1055, 1092,
+ /* 270 */ 1060, 1064, 1065, 1068, 1070, 1072, 1044, 1098, 1017, 1020,
+ /* 280 */ 1108, 1109, 1022, 1110, 1088, 1090, 1037, 1023, 1030,
};
static const YYACTIONTYPE yy_default[] = {
- /* 0 */ 565, 789, 854, 680, 854, 789, 854, 789, 854, 684,
- /* 10 */ 840, 785, 789, 854, 854, 854, 760, 854, 811, 854,
- /* 20 */ 596, 811, 811, 715, 854, 854, 854, 854, 854, 854,
- /* 30 */ 854, 854, 716, 854, 788, 784, 780, 782, 781, 717,
- /* 40 */ 704, 713, 720, 696, 825, 722, 723, 728, 729, 841,
- /* 50 */ 844, 750, 766, 749, 854, 854, 854, 854, 854, 854,
- /* 60 */ 854, 854, 854, 854, 854, 854, 854, 854, 854, 854,
- /* 70 */ 854, 854, 854, 854, 854, 854, 854, 854, 854, 854,
- /* 80 */ 854, 854, 854, 854, 854, 854, 854, 854, 854, 854,
- /* 90 */ 854, 854, 854, 752, 771, 589, 751, 759, 753, 754,
- /* 100 */ 649, 854, 854, 854, 854, 584, 854, 854, 854, 854,
- /* 110 */ 755, 756, 767, 768, 854, 854, 854, 854, 565, 680,
- /* 120 */ 854, 680, 854, 854, 854, 854, 854, 854, 854, 854,
- /* 130 */ 854, 854, 854, 854, 854, 854, 854, 854, 854, 854,
- /* 140 */ 674, 684, 854, 854, 640, 854, 854, 854, 854, 854,
- /* 150 */ 854, 854, 854, 854, 854, 572, 570, 854, 672, 854,
- /* 160 */ 854, 598, 854, 854, 682, 854, 854, 687, 688, 854,
- /* 170 */ 854, 854, 854, 854, 854, 854, 586, 854, 854, 661,
- /* 180 */ 854, 817, 854, 854, 854, 832, 854, 854, 854, 830,
- /* 190 */ 854, 663, 725, 799, 854, 854, 845, 847, 854, 854,
- /* 200 */ 707, 672, 681, 854, 854, 783, 707, 707, 619, 707,
- /* 210 */ 707, 622, 719, 719, 569, 569, 569, 569, 639, 651,
- /* 220 */ 651, 636, 651, 622, 651, 854, 719, 710, 712, 700,
- /* 230 */ 714, 854, 689, 708, 854, 708, 689, 697, 699, 697,
- /* 240 */ 699, 793, 708, 708, 854, 636, 651, 651, 651, 793,
- /* 250 */ 581, 689, 689, 689, 689, 821, 824, 581, 689, 653,
- /* 260 */ 653, 730, 719, 660, 660, 660, 719, 653, 730, 689,
- /* 270 */ 843, 843, 689, 689, 852, 606, 624, 624, 827, 854,
- /* 280 */ 854, 854, 854, 854, 854, 737, 854, 854, 854, 854,
- /* 290 */ 854, 854, 854, 854, 854, 854, 854, 854, 854, 854,
- /* 300 */ 806, 854, 854, 854, 854, 854, 742, 738, 854, 739,
- /* 310 */ 854, 854, 854, 854, 666, 854, 854, 854, 854, 854,
- /* 320 */ 854, 854, 701, 854, 711, 854, 854, 854, 854, 854,
- /* 330 */ 854, 854, 854, 854, 854, 854, 854, 854, 854, 854,
- /* 340 */ 854, 854, 854, 854, 819, 820, 854, 854, 854, 854,
- /* 350 */ 854, 854, 854, 854, 854, 854, 854, 854, 854, 854,
- /* 360 */ 854, 854, 854, 854, 854, 851, 854, 854, 566, 854,
- /* 370 */ 560, 563, 562, 564, 568, 571, 593, 594, 595, 573,
- /* 380 */ 574, 575, 576, 577, 578, 579, 585, 587, 605, 607,
- /* 390 */ 614, 652, 655, 656, 657, 835, 836, 837, 615, 634,
- /* 400 */ 637, 638, 616, 623, 705, 706, 617, 670, 671, 734,
- /* 410 */ 664, 665, 669, 736, 740, 741, 743, 744, 592, 599,
- /* 420 */ 600, 603, 604, 807, 809, 808, 810, 602, 601, 745,
- /* 430 */ 748, 757, 758, 764, 770, 773, 762, 763, 765, 769,
- /* 440 */ 772, 667, 668, 776, 778, 779, 833, 834, 774, 786,
- /* 450 */ 787, 690, 777, 761, 702, 591, 709, 703, 673, 683,
- /* 460 */ 692, 693, 694, 695, 678, 679, 685, 698, 732, 733,
- /* 470 */ 686, 675, 676, 677, 775, 735, 746, 747, 618, 625,
- /* 480 */ 626, 627, 630, 631, 632, 633, 628, 629, 794, 795,
- /* 490 */ 797, 796, 620, 621, 635, 608, 609, 610, 611, 742,
- /* 500 */ 612, 613, 597, 590, 641, 644, 645, 646, 647, 648,
- /* 510 */ 650, 642, 643, 588, 580, 582, 691, 813, 822, 823,
- /* 520 */ 818, 814, 815, 816, 583, 790, 791, 654, 726, 727,
- /* 530 */ 812, 826, 828, 731, 829, 831, 658, 659, 662, 798,
- /* 540 */ 838, 718, 721, 724, 800, 801, 802, 803, 804, 805,
- /* 550 */ 839, 842, 846, 848, 849, 850, 853, 567, 561,
+ /* 0 */ 593, 819, 899, 708, 899, 819, 899, 819, 899, 844,
+ /* 10 */ 712, 873, 815, 819, 899, 899, 899, 790, 899, 844,
+ /* 20 */ 899, 624, 844, 844, 741, 899, 899, 899, 899, 899,
+ /* 30 */ 899, 899, 899, 742, 899, 818, 814, 810, 812, 811,
+ /* 40 */ 743, 732, 739, 746, 724, 858, 748, 749, 755, 756,
+ /* 50 */ 874, 877, 778, 777, 796, 899, 899, 899, 899, 899,
+ /* 60 */ 899, 899, 899, 899, 899, 899, 899, 899, 899, 899,
+ /* 70 */ 899, 899, 899, 899, 899, 899, 899, 899, 899, 899,
+ /* 80 */ 899, 899, 899, 899, 899, 899, 899, 899, 899, 899,
+ /* 90 */ 899, 899, 899, 899, 780, 801, 779, 789, 617, 781,
+ /* 100 */ 782, 677, 612, 899, 899, 899, 899, 899, 899, 899,
+ /* 110 */ 783, 899, 784, 797, 798, 899, 899, 899, 899, 899,
+ /* 120 */ 899, 593, 708, 899, 708, 899, 899, 899, 899, 899,
+ /* 130 */ 899, 899, 899, 899, 899, 899, 899, 899, 899, 899,
+ /* 140 */ 899, 899, 899, 702, 712, 892, 899, 899, 668, 899,
+ /* 150 */ 899, 899, 899, 899, 899, 899, 899, 899, 899, 600,
+ /* 160 */ 598, 899, 700, 899, 899, 626, 899, 899, 710, 899,
+ /* 170 */ 899, 715, 716, 899, 899, 899, 899, 899, 899, 899,
+ /* 180 */ 614, 899, 899, 689, 899, 850, 899, 899, 899, 865,
+ /* 190 */ 899, 899, 899, 863, 899, 899, 899, 691, 751, 831,
+ /* 200 */ 899, 878, 880, 899, 899, 700, 709, 899, 899, 813,
+ /* 210 */ 735, 735, 735, 647, 735, 735, 650, 745, 745, 597,
+ /* 220 */ 597, 597, 597, 667, 899, 745, 736, 738, 728, 740,
+ /* 230 */ 899, 899, 717, 717, 725, 727, 725, 727, 679, 679,
+ /* 240 */ 664, 679, 650, 679, 823, 828, 899, 828, 899, 664,
+ /* 250 */ 679, 679, 679, 823, 609, 717, 609, 717, 609, 717,
+ /* 260 */ 717, 854, 857, 609, 717, 681, 681, 757, 745, 717,
+ /* 270 */ 688, 688, 688, 688, 745, 681, 757, 717, 876, 876,
+ /* 280 */ 717, 717, 885, 634, 652, 652, 860, 892, 897, 899,
+ /* 290 */ 899, 899, 899, 764, 899, 899, 899, 899, 899, 899,
+ /* 300 */ 899, 899, 899, 899, 899, 899, 899, 899, 899, 899,
+ /* 310 */ 837, 899, 899, 899, 899, 769, 765, 899, 766, 899,
+ /* 320 */ 694, 899, 899, 899, 899, 899, 899, 899, 899, 899,
+ /* 330 */ 899, 729, 899, 737, 899, 899, 899, 899, 899, 899,
+ /* 340 */ 899, 899, 899, 899, 899, 899, 899, 899, 899, 899,
+ /* 350 */ 899, 899, 899, 899, 899, 899, 852, 853, 899, 899,
+ /* 360 */ 899, 899, 899, 899, 899, 899, 899, 899, 899, 899,
+ /* 370 */ 899, 899, 899, 899, 899, 899, 899, 899, 899, 899,
+ /* 380 */ 884, 899, 899, 887, 594, 899, 588, 591, 590, 592,
+ /* 390 */ 596, 599, 621, 622, 623, 601, 602, 603, 604, 605,
+ /* 400 */ 606, 607, 613, 615, 633, 635, 619, 637, 698, 699,
+ /* 410 */ 761, 692, 693, 697, 772, 763, 767, 768, 770, 771,
+ /* 420 */ 785, 786, 788, 794, 800, 803, 787, 792, 793, 795,
+ /* 430 */ 799, 802, 695, 696, 806, 620, 627, 628, 631, 632,
+ /* 440 */ 840, 842, 841, 843, 630, 629, 773, 776, 808, 809,
+ /* 450 */ 866, 867, 868, 869, 870, 804, 816, 817, 718, 807,
+ /* 460 */ 791, 730, 733, 734, 731, 701, 711, 720, 721, 722,
+ /* 470 */ 723, 706, 707, 713, 726, 759, 760, 714, 703, 704,
+ /* 480 */ 705, 805, 762, 774, 775, 638, 639, 769, 640, 641,
+ /* 490 */ 642, 680, 683, 684, 685, 643, 662, 665, 666, 644,
+ /* 500 */ 651, 645, 646, 653, 654, 655, 658, 659, 660, 661,
+ /* 510 */ 656, 657, 824, 825, 829, 827, 826, 648, 649, 663,
+ /* 520 */ 636, 625, 618, 669, 672, 673, 674, 675, 676, 678,
+ /* 530 */ 670, 671, 616, 608, 610, 719, 846, 855, 856, 851,
+ /* 540 */ 847, 848, 849, 611, 820, 821, 682, 753, 754, 845,
+ /* 550 */ 859, 861, 758, 862, 864, 889, 686, 687, 690, 830,
+ /* 560 */ 871, 744, 747, 750, 752, 832, 833, 834, 835, 838,
+ /* 570 */ 839, 836, 872, 875, 879, 881, 882, 883, 886, 888,
+ /* 580 */ 893, 894, 895, 898, 896, 595, 589,
};
-#define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))
+#define YY_SZ_ACTTAB (int)(sizeof(yy_action)/sizeof(yy_action[0]))
/* The next table maps tokens into fallback tokens. If a construct
** like the following:
@@ -635,9 +656,11 @@ static const YYCODETYPE yyFallback[] = {
23, /* TRIGGER => ID */
23, /* VACUUM => ID */
23, /* VIEW => ID */
+ 23, /* VIRTUAL => ID */
23, /* REINDEX => ID */
23, /* RENAME => ID */
23, /* CTIME_KW => ID */
+ 0, /* ANY => nothing */
0, /* OR => nothing */
0, /* AND => nothing */
0, /* IS => nothing */
@@ -662,6 +685,7 @@ static const YYCODETYPE yyFallback[] = {
0, /* SLASH => nothing */
0, /* REM => nothing */
0, /* CONCAT => nothing */
+ 0, /* COLLATE => nothing */
0, /* UMINUS => nothing */
0, /* UPLUS => nothing */
0, /* BITNOT => nothing */
@@ -674,7 +698,6 @@ static const YYCODETYPE yyFallback[] = {
0, /* UNIQUE => nothing */
0, /* CHECK => nothing */
0, /* REFERENCES => nothing */
- 0, /* COLLATE => nothing */
0, /* AUTOINCR => nothing */
0, /* ON => nothing */
0, /* DELETE => nothing */
@@ -800,52 +823,54 @@ static const char *const yyTokenName[] = {
"KEY", "OF", "OFFSET", "PRAGMA",
"RAISE", "REPLACE", "RESTRICT", "ROW",
"STATEMENT", "TRIGGER", "VACUUM", "VIEW",
- "REINDEX", "RENAME", "CTIME_KW", "OR",
- "AND", "IS", "BETWEEN", "IN",
- "ISNULL", "NOTNULL", "NE", "EQ",
- "GT", "LE", "LT", "GE",
- "ESCAPE", "BITAND", "BITOR", "LSHIFT",
- "RSHIFT", "PLUS", "MINUS", "STAR",
- "SLASH", "REM", "CONCAT", "UMINUS",
- "UPLUS", "BITNOT", "STRING", "JOIN_KW",
- "CONSTRAINT", "DEFAULT", "NULL", "PRIMARY",
- "UNIQUE", "CHECK", "REFERENCES", "COLLATE",
- "AUTOINCR", "ON", "DELETE", "UPDATE",
- "INSERT", "SET", "DEFERRABLE", "FOREIGN",
- "DROP", "UNION", "ALL", "EXCEPT",
- "INTERSECT", "SELECT", "DISTINCT", "DOT",
- "FROM", "JOIN", "USING", "ORDER",
- "BY", "GROUP", "HAVING", "LIMIT",
- "WHERE", "INTO", "VALUES", "INTEGER",
- "FLOAT", "BLOB", "REGISTER", "VARIABLE",
- "CASE", "WHEN", "THEN", "ELSE",
- "INDEX", "ALTER", "TO", "ADD",
- "COLUMNKW", "error", "input", "cmdlist",
- "ecmd", "cmdx", "cmd", "explain",
- "transtype", "trans_opt", "nm", "create_table",
- "create_table_args", "temp", "ifnotexists", "dbnm",
- "columnlist", "conslist_opt", "select", "column",
- "columnid", "type", "carglist", "id",
- "ids", "typetoken", "typename", "signed",
- "plus_num", "minus_num", "carg", "ccons",
- "term", "expr", "onconf", "sortorder",
- "autoinc", "idxlist_opt", "refargs", "defer_subclause",
- "refarg", "refact", "init_deferred_pred_opt", "conslist",
- "tcons", "idxlist", "defer_subclause_opt", "orconf",
- "resolvetype", "raisetype", "ifexists", "fullname",
- "oneselect", "multiselect_op", "distinct", "selcollist",
- "from", "where_opt", "groupby_opt", "having_opt",
- "orderby_opt", "limit_opt", "sclp", "as",
- "seltablist", "stl_prefix", "joinop", "on_opt",
- "using_opt", "seltablist_paren", "joinop2", "inscollist",
- "sortlist", "sortitem", "collate", "exprlist",
- "setlist", "insert_cmd", "inscollist_opt", "itemlist",
- "likeop", "escape", "between_op", "in_op",
- "case_operand", "case_exprlist", "case_else", "expritem",
- "uniqueflag", "idxitem", "plus_opt", "number",
- "trigger_decl", "trigger_cmd_list", "trigger_time", "trigger_event",
- "foreach_clause", "when_clause", "trigger_cmd", "database_kw_opt",
- "key_opt", "add_column_fullname", "kwcolumn_opt",
+ "VIRTUAL", "REINDEX", "RENAME", "CTIME_KW",
+ "ANY", "OR", "AND", "IS",
+ "BETWEEN", "IN", "ISNULL", "NOTNULL",
+ "NE", "EQ", "GT", "LE",
+ "LT", "GE", "ESCAPE", "BITAND",
+ "BITOR", "LSHIFT", "RSHIFT", "PLUS",
+ "MINUS", "STAR", "SLASH", "REM",
+ "CONCAT", "COLLATE", "UMINUS", "UPLUS",
+ "BITNOT", "STRING", "JOIN_KW", "CONSTRAINT",
+ "DEFAULT", "NULL", "PRIMARY", "UNIQUE",
+ "CHECK", "REFERENCES", "AUTOINCR", "ON",
+ "DELETE", "UPDATE", "INSERT", "SET",
+ "DEFERRABLE", "FOREIGN", "DROP", "UNION",
+ "ALL", "EXCEPT", "INTERSECT", "SELECT",
+ "DISTINCT", "DOT", "FROM", "JOIN",
+ "USING", "ORDER", "BY", "GROUP",
+ "HAVING", "LIMIT", "WHERE", "INTO",
+ "VALUES", "INTEGER", "FLOAT", "BLOB",
+ "REGISTER", "VARIABLE", "CASE", "WHEN",
+ "THEN", "ELSE", "INDEX", "ALTER",
+ "TO", "ADD", "COLUMNKW", "error",
+ "input", "cmdlist", "ecmd", "cmdx",
+ "cmd", "explain", "transtype", "trans_opt",
+ "nm", "create_table", "create_table_args", "temp",
+ "ifnotexists", "dbnm", "columnlist", "conslist_opt",
+ "select", "column", "columnid", "type",
+ "carglist", "id", "ids", "typetoken",
+ "typename", "signed", "plus_num", "minus_num",
+ "carg", "ccons", "term", "expr",
+ "onconf", "sortorder", "autoinc", "idxlist_opt",
+ "refargs", "defer_subclause", "refarg", "refact",
+ "init_deferred_pred_opt", "conslist", "tcons", "idxlist",
+ "defer_subclause_opt", "orconf", "resolvetype", "raisetype",
+ "ifexists", "fullname", "oneselect", "multiselect_op",
+ "distinct", "selcollist", "from", "where_opt",
+ "groupby_opt", "having_opt", "orderby_opt", "limit_opt",
+ "sclp", "as", "seltablist", "stl_prefix",
+ "joinop", "on_opt", "using_opt", "seltablist_paren",
+ "joinop2", "inscollist", "sortlist", "sortitem",
+ "exprlist", "setlist", "insert_cmd", "inscollist_opt",
+ "itemlist", "likeop", "escape", "between_op",
+ "in_op", "case_operand", "case_exprlist", "case_else",
+ "expritem", "uniqueflag", "idxitem", "collate",
+ "nmnum", "plus_opt", "number", "trigger_decl",
+ "trigger_cmd_list", "trigger_time", "trigger_event", "foreach_clause",
+ "when_clause", "trigger_cmd", "database_kw_opt", "key_opt",
+ "add_column_fullname", "kwcolumn_opt", "create_vtab", "vtabarglist",
+ "vtabarg", "vtabargtoken", "lp", "anylist",
};
#endif /* NDEBUG */
@@ -903,11 +928,11 @@ static const char *const yyRuleName[] = {
/* 47 */ "carglist ::=",
/* 48 */ "carg ::= CONSTRAINT nm ccons",
/* 49 */ "carg ::= ccons",
- /* 50 */ "carg ::= DEFAULT term",
- /* 51 */ "carg ::= DEFAULT LP expr RP",
- /* 52 */ "carg ::= DEFAULT PLUS term",
- /* 53 */ "carg ::= DEFAULT MINUS term",
- /* 54 */ "carg ::= DEFAULT id",
+ /* 50 */ "ccons ::= DEFAULT term",
+ /* 51 */ "ccons ::= DEFAULT LP expr RP",
+ /* 52 */ "ccons ::= DEFAULT PLUS term",
+ /* 53 */ "ccons ::= DEFAULT MINUS term",
+ /* 54 */ "ccons ::= DEFAULT id",
/* 55 */ "ccons ::= NULL onconf",
/* 56 */ "ccons ::= NOT NULL onconf",
/* 57 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc",
@@ -955,7 +980,7 @@ static const char *const yyRuleName[] = {
/* 99 */ "cmd ::= DROP TABLE ifexists fullname",
/* 100 */ "ifexists ::= IF EXISTS",
/* 101 */ "ifexists ::=",
- /* 102 */ "cmd ::= CREATE temp VIEW nm dbnm AS select",
+ /* 102 */ "cmd ::= CREATE temp VIEW ifnotexists nm dbnm AS select",
/* 103 */ "cmd ::= DROP VIEW ifexists fullname",
/* 104 */ "cmd ::= select",
/* 105 */ "select ::= oneselect",
@@ -996,49 +1021,49 @@ static const char *const yyRuleName[] = {
/* 140 */ "using_opt ::=",
/* 141 */ "orderby_opt ::=",
/* 142 */ "orderby_opt ::= ORDER BY sortlist",
- /* 143 */ "sortlist ::= sortlist COMMA sortitem collate sortorder",
- /* 144 */ "sortlist ::= sortitem collate sortorder",
+ /* 143 */ "sortlist ::= sortlist COMMA sortitem sortorder",
+ /* 144 */ "sortlist ::= sortitem sortorder",
/* 145 */ "sortitem ::= expr",
/* 146 */ "sortorder ::= ASC",
/* 147 */ "sortorder ::= DESC",
/* 148 */ "sortorder ::=",
- /* 149 */ "collate ::=",
- /* 150 */ "collate ::= COLLATE id",
- /* 151 */ "groupby_opt ::=",
- /* 152 */ "groupby_opt ::= GROUP BY exprlist",
- /* 153 */ "having_opt ::=",
- /* 154 */ "having_opt ::= HAVING expr",
- /* 155 */ "limit_opt ::=",
- /* 156 */ "limit_opt ::= LIMIT expr",
- /* 157 */ "limit_opt ::= LIMIT expr OFFSET expr",
- /* 158 */ "limit_opt ::= LIMIT expr COMMA expr",
- /* 159 */ "cmd ::= DELETE FROM fullname where_opt",
- /* 160 */ "where_opt ::=",
- /* 161 */ "where_opt ::= WHERE expr",
- /* 162 */ "cmd ::= UPDATE orconf fullname SET setlist where_opt",
- /* 163 */ "setlist ::= setlist COMMA nm EQ expr",
- /* 164 */ "setlist ::= nm EQ expr",
- /* 165 */ "cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP",
- /* 166 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select",
- /* 167 */ "insert_cmd ::= INSERT orconf",
- /* 168 */ "insert_cmd ::= REPLACE",
- /* 169 */ "itemlist ::= itemlist COMMA expr",
- /* 170 */ "itemlist ::= expr",
- /* 171 */ "inscollist_opt ::=",
- /* 172 */ "inscollist_opt ::= LP inscollist RP",
- /* 173 */ "inscollist ::= inscollist COMMA nm",
- /* 174 */ "inscollist ::= nm",
- /* 175 */ "expr ::= term",
- /* 176 */ "expr ::= LP expr RP",
- /* 177 */ "term ::= NULL",
- /* 178 */ "expr ::= ID",
- /* 179 */ "expr ::= JOIN_KW",
- /* 180 */ "expr ::= nm DOT nm",
- /* 181 */ "expr ::= nm DOT nm DOT nm",
- /* 182 */ "term ::= INTEGER|FLOAT|BLOB",
- /* 183 */ "term ::= STRING",
- /* 184 */ "expr ::= REGISTER",
- /* 185 */ "expr ::= VARIABLE",
+ /* 149 */ "groupby_opt ::=",
+ /* 150 */ "groupby_opt ::= GROUP BY exprlist",
+ /* 151 */ "having_opt ::=",
+ /* 152 */ "having_opt ::= HAVING expr",
+ /* 153 */ "limit_opt ::=",
+ /* 154 */ "limit_opt ::= LIMIT expr",
+ /* 155 */ "limit_opt ::= LIMIT expr OFFSET expr",
+ /* 156 */ "limit_opt ::= LIMIT expr COMMA expr",
+ /* 157 */ "cmd ::= DELETE FROM fullname where_opt",
+ /* 158 */ "where_opt ::=",
+ /* 159 */ "where_opt ::= WHERE expr",
+ /* 160 */ "cmd ::= UPDATE orconf fullname SET setlist where_opt",
+ /* 161 */ "setlist ::= setlist COMMA nm EQ expr",
+ /* 162 */ "setlist ::= nm EQ expr",
+ /* 163 */ "cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP",
+ /* 164 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select",
+ /* 165 */ "cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES",
+ /* 166 */ "insert_cmd ::= INSERT orconf",
+ /* 167 */ "insert_cmd ::= REPLACE",
+ /* 168 */ "itemlist ::= itemlist COMMA expr",
+ /* 169 */ "itemlist ::= expr",
+ /* 170 */ "inscollist_opt ::=",
+ /* 171 */ "inscollist_opt ::= LP inscollist RP",
+ /* 172 */ "inscollist ::= inscollist COMMA nm",
+ /* 173 */ "inscollist ::= nm",
+ /* 174 */ "expr ::= term",
+ /* 175 */ "expr ::= LP expr RP",
+ /* 176 */ "term ::= NULL",
+ /* 177 */ "expr ::= ID",
+ /* 178 */ "expr ::= JOIN_KW",
+ /* 179 */ "expr ::= nm DOT nm",
+ /* 180 */ "expr ::= nm DOT nm DOT nm",
+ /* 181 */ "term ::= INTEGER|FLOAT|BLOB",
+ /* 182 */ "term ::= STRING",
+ /* 183 */ "expr ::= REGISTER",
+ /* 184 */ "expr ::= VARIABLE",
+ /* 185 */ "expr ::= expr COLLATE id",
/* 186 */ "expr ::= CAST LP expr AS typetoken RP",
/* 187 */ "expr ::= ID LP distinct exprlist RP",
/* 188 */ "expr ::= ID LP STAR RP",
@@ -1053,101 +1078,118 @@ static const char *const yyRuleName[] = {
/* 197 */ "expr ::= expr CONCAT expr",
/* 198 */ "likeop ::= LIKE_KW",
/* 199 */ "likeop ::= NOT LIKE_KW",
- /* 200 */ "escape ::= ESCAPE expr",
- /* 201 */ "escape ::=",
- /* 202 */ "expr ::= expr likeop expr escape",
- /* 203 */ "expr ::= expr ISNULL|NOTNULL",
- /* 204 */ "expr ::= expr IS NULL",
- /* 205 */ "expr ::= expr NOT NULL",
- /* 206 */ "expr ::= expr IS NOT NULL",
- /* 207 */ "expr ::= NOT|BITNOT expr",
- /* 208 */ "expr ::= MINUS expr",
- /* 209 */ "expr ::= PLUS expr",
- /* 210 */ "between_op ::= BETWEEN",
- /* 211 */ "between_op ::= NOT BETWEEN",
- /* 212 */ "expr ::= expr between_op expr AND expr",
- /* 213 */ "in_op ::= IN",
- /* 214 */ "in_op ::= NOT IN",
- /* 215 */ "expr ::= expr in_op LP exprlist RP",
- /* 216 */ "expr ::= LP select RP",
- /* 217 */ "expr ::= expr in_op LP select RP",
- /* 218 */ "expr ::= expr in_op nm dbnm",
- /* 219 */ "expr ::= EXISTS LP select RP",
- /* 220 */ "expr ::= CASE case_operand case_exprlist case_else END",
- /* 221 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
- /* 222 */ "case_exprlist ::= WHEN expr THEN expr",
- /* 223 */ "case_else ::= ELSE expr",
- /* 224 */ "case_else ::=",
- /* 225 */ "case_operand ::= expr",
- /* 226 */ "case_operand ::=",
- /* 227 */ "exprlist ::= exprlist COMMA expritem",
- /* 228 */ "exprlist ::= expritem",
- /* 229 */ "expritem ::= expr",
- /* 230 */ "expritem ::=",
- /* 231 */ "cmd ::= CREATE uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP",
- /* 232 */ "uniqueflag ::= UNIQUE",
- /* 233 */ "uniqueflag ::=",
- /* 234 */ "idxlist_opt ::=",
- /* 235 */ "idxlist_opt ::= LP idxlist RP",
- /* 236 */ "idxlist ::= idxlist COMMA idxitem collate sortorder",
- /* 237 */ "idxlist ::= idxitem collate sortorder",
- /* 238 */ "idxitem ::= nm",
- /* 239 */ "cmd ::= DROP INDEX ifexists fullname",
- /* 240 */ "cmd ::= VACUUM",
- /* 241 */ "cmd ::= VACUUM nm",
- /* 242 */ "cmd ::= PRAGMA nm dbnm EQ nm",
- /* 243 */ "cmd ::= PRAGMA nm dbnm EQ ON",
- /* 244 */ "cmd ::= PRAGMA nm dbnm EQ plus_num",
- /* 245 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
- /* 246 */ "cmd ::= PRAGMA nm dbnm LP nm RP",
- /* 247 */ "cmd ::= PRAGMA nm dbnm",
- /* 248 */ "plus_num ::= plus_opt number",
- /* 249 */ "minus_num ::= MINUS number",
- /* 250 */ "number ::= INTEGER|FLOAT",
- /* 251 */ "plus_opt ::= PLUS",
- /* 252 */ "plus_opt ::=",
- /* 253 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END",
- /* 254 */ "trigger_decl ::= temp TRIGGER nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
- /* 255 */ "trigger_time ::= BEFORE",
- /* 256 */ "trigger_time ::= AFTER",
- /* 257 */ "trigger_time ::= INSTEAD OF",
- /* 258 */ "trigger_time ::=",
- /* 259 */ "trigger_event ::= DELETE|INSERT",
- /* 260 */ "trigger_event ::= UPDATE",
- /* 261 */ "trigger_event ::= UPDATE OF inscollist",
- /* 262 */ "foreach_clause ::=",
- /* 263 */ "foreach_clause ::= FOR EACH ROW",
- /* 264 */ "foreach_clause ::= FOR EACH STATEMENT",
- /* 265 */ "when_clause ::=",
- /* 266 */ "when_clause ::= WHEN expr",
- /* 267 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
- /* 268 */ "trigger_cmd_list ::=",
- /* 269 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt",
- /* 270 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP",
- /* 271 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select",
- /* 272 */ "trigger_cmd ::= DELETE FROM nm where_opt",
- /* 273 */ "trigger_cmd ::= select",
- /* 274 */ "expr ::= RAISE LP IGNORE RP",
- /* 275 */ "expr ::= RAISE LP raisetype COMMA nm RP",
- /* 276 */ "raisetype ::= ROLLBACK",
- /* 277 */ "raisetype ::= ABORT",
- /* 278 */ "raisetype ::= FAIL",
- /* 279 */ "cmd ::= DROP TRIGGER fullname",
- /* 280 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
- /* 281 */ "key_opt ::=",
- /* 282 */ "key_opt ::= KEY expr",
- /* 283 */ "database_kw_opt ::= DATABASE",
- /* 284 */ "database_kw_opt ::=",
- /* 285 */ "cmd ::= DETACH database_kw_opt expr",
- /* 286 */ "cmd ::= REINDEX",
- /* 287 */ "cmd ::= REINDEX nm dbnm",
- /* 288 */ "cmd ::= ANALYZE",
- /* 289 */ "cmd ::= ANALYZE nm dbnm",
- /* 290 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
- /* 291 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
- /* 292 */ "add_column_fullname ::= fullname",
- /* 293 */ "kwcolumn_opt ::=",
- /* 294 */ "kwcolumn_opt ::= COLUMNKW",
+ /* 200 */ "likeop ::= MATCH",
+ /* 201 */ "likeop ::= NOT MATCH",
+ /* 202 */ "escape ::= ESCAPE expr",
+ /* 203 */ "escape ::=",
+ /* 204 */ "expr ::= expr likeop expr escape",
+ /* 205 */ "expr ::= expr ISNULL|NOTNULL",
+ /* 206 */ "expr ::= expr IS NULL",
+ /* 207 */ "expr ::= expr NOT NULL",
+ /* 208 */ "expr ::= expr IS NOT NULL",
+ /* 209 */ "expr ::= NOT|BITNOT expr",
+ /* 210 */ "expr ::= MINUS expr",
+ /* 211 */ "expr ::= PLUS expr",
+ /* 212 */ "between_op ::= BETWEEN",
+ /* 213 */ "between_op ::= NOT BETWEEN",
+ /* 214 */ "expr ::= expr between_op expr AND expr",
+ /* 215 */ "in_op ::= IN",
+ /* 216 */ "in_op ::= NOT IN",
+ /* 217 */ "expr ::= expr in_op LP exprlist RP",
+ /* 218 */ "expr ::= LP select RP",
+ /* 219 */ "expr ::= expr in_op LP select RP",
+ /* 220 */ "expr ::= expr in_op nm dbnm",
+ /* 221 */ "expr ::= EXISTS LP select RP",
+ /* 222 */ "expr ::= CASE case_operand case_exprlist case_else END",
+ /* 223 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
+ /* 224 */ "case_exprlist ::= WHEN expr THEN expr",
+ /* 225 */ "case_else ::= ELSE expr",
+ /* 226 */ "case_else ::=",
+ /* 227 */ "case_operand ::= expr",
+ /* 228 */ "case_operand ::=",
+ /* 229 */ "exprlist ::= exprlist COMMA expritem",
+ /* 230 */ "exprlist ::= expritem",
+ /* 231 */ "expritem ::= expr",
+ /* 232 */ "expritem ::=",
+ /* 233 */ "cmd ::= CREATE uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP",
+ /* 234 */ "uniqueflag ::= UNIQUE",
+ /* 235 */ "uniqueflag ::=",
+ /* 236 */ "idxlist_opt ::=",
+ /* 237 */ "idxlist_opt ::= LP idxlist RP",
+ /* 238 */ "idxlist ::= idxlist COMMA idxitem collate sortorder",
+ /* 239 */ "idxlist ::= idxitem collate sortorder",
+ /* 240 */ "idxitem ::= nm",
+ /* 241 */ "collate ::=",
+ /* 242 */ "collate ::= COLLATE id",
+ /* 243 */ "cmd ::= DROP INDEX ifexists fullname",
+ /* 244 */ "cmd ::= VACUUM",
+ /* 245 */ "cmd ::= VACUUM nm",
+ /* 246 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
+ /* 247 */ "cmd ::= PRAGMA nm dbnm EQ ON",
+ /* 248 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
+ /* 249 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
+ /* 250 */ "cmd ::= PRAGMA nm dbnm",
+ /* 251 */ "nmnum ::= plus_num",
+ /* 252 */ "nmnum ::= nm",
+ /* 253 */ "plus_num ::= plus_opt number",
+ /* 254 */ "minus_num ::= MINUS number",
+ /* 255 */ "number ::= INTEGER|FLOAT",
+ /* 256 */ "plus_opt ::= PLUS",
+ /* 257 */ "plus_opt ::=",
+ /* 258 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END",
+ /* 259 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
+ /* 260 */ "trigger_time ::= BEFORE",
+ /* 261 */ "trigger_time ::= AFTER",
+ /* 262 */ "trigger_time ::= INSTEAD OF",
+ /* 263 */ "trigger_time ::=",
+ /* 264 */ "trigger_event ::= DELETE|INSERT",
+ /* 265 */ "trigger_event ::= UPDATE",
+ /* 266 */ "trigger_event ::= UPDATE OF inscollist",
+ /* 267 */ "foreach_clause ::=",
+ /* 268 */ "foreach_clause ::= FOR EACH ROW",
+ /* 269 */ "foreach_clause ::= FOR EACH STATEMENT",
+ /* 270 */ "when_clause ::=",
+ /* 271 */ "when_clause ::= WHEN expr",
+ /* 272 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
+ /* 273 */ "trigger_cmd_list ::=",
+ /* 274 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt",
+ /* 275 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP",
+ /* 276 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select",
+ /* 277 */ "trigger_cmd ::= DELETE FROM nm where_opt",
+ /* 278 */ "trigger_cmd ::= select",
+ /* 279 */ "expr ::= RAISE LP IGNORE RP",
+ /* 280 */ "expr ::= RAISE LP raisetype COMMA nm RP",
+ /* 281 */ "raisetype ::= ROLLBACK",
+ /* 282 */ "raisetype ::= ABORT",
+ /* 283 */ "raisetype ::= FAIL",
+ /* 284 */ "cmd ::= DROP TRIGGER ifexists fullname",
+ /* 285 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
+ /* 286 */ "key_opt ::=",
+ /* 287 */ "key_opt ::= KEY expr",
+ /* 288 */ "database_kw_opt ::= DATABASE",
+ /* 289 */ "database_kw_opt ::=",
+ /* 290 */ "cmd ::= DETACH database_kw_opt expr",
+ /* 291 */ "cmd ::= REINDEX",
+ /* 292 */ "cmd ::= REINDEX nm dbnm",
+ /* 293 */ "cmd ::= ANALYZE",
+ /* 294 */ "cmd ::= ANALYZE nm dbnm",
+ /* 295 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
+ /* 296 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
+ /* 297 */ "add_column_fullname ::= fullname",
+ /* 298 */ "kwcolumn_opt ::=",
+ /* 299 */ "kwcolumn_opt ::= COLUMNKW",
+ /* 300 */ "cmd ::= create_vtab",
+ /* 301 */ "cmd ::= create_vtab LP vtabarglist RP",
+ /* 302 */ "create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm",
+ /* 303 */ "vtabarglist ::= vtabarg",
+ /* 304 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
+ /* 305 */ "vtabarg ::=",
+ /* 306 */ "vtabarg ::= vtabarg vtabargtoken",
+ /* 307 */ "vtabargtoken ::= ANY",
+ /* 308 */ "vtabargtoken ::= lp anylist RP",
+ /* 309 */ "lp ::= LP",
+ /* 310 */ "anylist ::=",
+ /* 311 */ "anylist ::= anylist ANY",
};
#endif /* NDEBUG */
@@ -1205,81 +1247,81 @@ static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){
** which appear on the RHS of the rule, but which are not used
** inside the C code.
*/
- case 154:
- case 188:
- case 205:
-#line 371 "parse.y"
-{sqlite3SelectDelete((yypminor->yy239));}
-#line 1215 "parse.c"
+ case 156:
+ case 190:
+ case 207:
+#line 375 "parse.y"
+{sqlite3SelectDelete((yypminor->yy43));}
+#line 1257 "parse.c"
break;
- case 168:
- case 169:
- case 193:
+ case 170:
+ case 171:
case 195:
- case 203:
- case 209:
- case 217:
- case 220:
- case 222:
+ case 197:
+ case 205:
+ case 211:
+ case 218:
+ case 221:
case 223:
- case 233:
-#line 628 "parse.y"
-{sqlite3ExprDelete((yypminor->yy178));}
-#line 1230 "parse.c"
+ case 224:
+ case 236:
+#line 616 "parse.y"
+{sqlite3ExprDelete((yypminor->yy450));}
+#line 1272 "parse.c"
break;
- case 173:
- case 181:
- case 191:
- case 194:
+ case 175:
+ case 183:
+ case 193:
case 196:
case 198:
- case 208:
- case 211:
- case 212:
- case 215:
- case 221:
-#line 859 "parse.y"
-{sqlite3ExprListDelete((yypminor->yy462));}
-#line 1245 "parse.c"
- break;
- case 187:
- case 192:
case 200:
- case 201:
-#line 499 "parse.y"
-{sqlite3SrcListDelete((yypminor->yy285));}
-#line 1253 "parse.c"
+ case 210:
+ case 212:
+ case 213:
+ case 216:
+ case 222:
+#line 856 "parse.y"
+{sqlite3ExprListDelete((yypminor->yy242));}
+#line 1287 "parse.c"
break;
- case 197:
-#line 560 "parse.y"
+ case 189:
+ case 194:
+ case 202:
+ case 203:
+#line 488 "parse.y"
+{sqlite3SrcListDelete((yypminor->yy419));}
+#line 1295 "parse.c"
+ break;
+ case 199:
+#line 546 "parse.y"
{
- sqlite3ExprDelete((yypminor->yy270).pLimit);
- sqlite3ExprDelete((yypminor->yy270).pOffset);
+ sqlite3ExprDelete((yypminor->yy84).pLimit);
+ sqlite3ExprDelete((yypminor->yy84).pOffset);
}
-#line 1261 "parse.c"
+#line 1303 "parse.c"
break;
- case 204:
- case 207:
- case 214:
-#line 516 "parse.y"
-{sqlite3IdListDelete((yypminor->yy160));}
-#line 1268 "parse.c"
+ case 206:
+ case 209:
+ case 215:
+#line 505 "parse.y"
+{sqlite3IdListDelete((yypminor->yy352));}
+#line 1310 "parse.c"
+ break;
+ case 232:
+ case 237:
+#line 957 "parse.y"
+{sqlite3DeleteTriggerStep((yypminor->yy75));}
+#line 1316 "parse.c"
break;
- case 229:
case 234:
-#line 953 "parse.y"
-{sqlite3DeleteTriggerStep((yypminor->yy247));}
-#line 1274 "parse.c"
+#line 941 "parse.y"
+{sqlite3IdListDelete((yypminor->yy354).b);}
+#line 1321 "parse.c"
break;
- case 231:
-#line 937 "parse.y"
-{sqlite3IdListDelete((yypminor->yy132).b);}
-#line 1279 "parse.c"
- break;
- case 236:
-#line 1021 "parse.y"
-{sqlite3ExprDelete((yypminor->yy292));}
-#line 1284 "parse.c"
+ case 239:
+#line 1025 "parse.y"
+{sqlite3ExprDelete((yypminor->yy158));}
+#line 1326 "parse.c"
break;
default: break; /* If no destructor action specified: do nothing */
}
@@ -1343,7 +1385,7 @@ void sqlite3ParserFree(
*/
static int yy_find_shift_action(
yyParser *pParser, /* The parser */
- int iLookAhead /* The look-ahead token */
+ YYCODETYPE iLookAhead /* The look-ahead token */
){
int i;
int stateno = pParser->yystack[pParser->yyidx].stateno;
@@ -1356,19 +1398,35 @@ static int yy_find_shift_action(
}
i += iLookAhead;
if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
+ if( iLookAhead>0 ){
#ifdef YYFALLBACK
- int iFallback; /* Fallback token */
- if( iLookAhead %s\n",
- yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
+ if( yyTraceFILE ){
+ fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
+ yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
+ }
+#endif
+ return yy_find_shift_action(pParser, iFallback);
}
#endif
- return yy_find_shift_action(pParser, iFallback);
+#ifdef YYWILDCARD
+ {
+ int j = i - iLookAhead + YYWILDCARD;
+ if( j>=0 && j %s\n",
+ yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[YYWILDCARD]);
+ }
+#endif /* NDEBUG */
+ return yy_action[j];
+ }
+ }
+#endif /* YYWILDCARD */
}
-#endif
return yy_default[stateno];
}else{
return yy_action[i];
@@ -1385,7 +1443,7 @@ static int yy_find_shift_action(
*/
static int yy_find_reduce_action(
int stateno, /* Current state number */
- int iLookAhead /* The look-ahead token */
+ YYCODETYPE iLookAhead /* The look-ahead token */
){
int i;
/* int stateno = pParser->yystack[pParser->yyidx].stateno; */
@@ -1427,10 +1485,11 @@ static void yy_shift(
while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
/* Here code is inserted which will execute if the parser
** stack every overflows */
-#line 43 "parse.y"
+#line 44 "parse.y"
sqlite3ErrorMsg(pParse, "parser stack overflow");
-#line 1436 "parse.c"
+ pParse->parseError = 1;
+#line 1495 "parse.c"
sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument var */
return;
}
@@ -1457,301 +1516,318 @@ static const struct {
YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
unsigned char nrhs; /* Number of right-hand side symbols in the rule */
} yyRuleInfo[] = {
- { 138, 1 },
- { 139, 2 },
- { 139, 1 },
- { 141, 1 },
{ 140, 1 },
- { 140, 3 },
- { 143, 0 },
+ { 141, 2 },
+ { 141, 1 },
{ 143, 1 },
- { 143, 3 },
+ { 142, 1 },
{ 142, 3 },
{ 145, 0 },
{ 145, 1 },
- { 145, 2 },
- { 144, 0 },
- { 144, 1 },
- { 144, 1 },
- { 144, 1 },
- { 142, 2 },
- { 142, 2 },
- { 142, 2 },
- { 142, 2 },
- { 147, 6 },
- { 150, 0 },
- { 150, 3 },
- { 149, 1 },
- { 149, 0 },
- { 148, 4 },
- { 148, 2 },
+ { 145, 3 },
+ { 144, 3 },
+ { 147, 0 },
+ { 147, 1 },
+ { 147, 2 },
+ { 146, 0 },
+ { 146, 1 },
+ { 146, 1 },
+ { 146, 1 },
+ { 144, 2 },
+ { 144, 2 },
+ { 144, 2 },
+ { 144, 2 },
+ { 149, 6 },
+ { 152, 0 },
{ 152, 3 },
- { 152, 1 },
- { 155, 3 },
- { 156, 1 },
- { 159, 1 },
- { 160, 1 },
- { 146, 1 },
- { 146, 1 },
- { 146, 1 },
- { 157, 0 },
- { 157, 1 },
+ { 151, 1 },
+ { 151, 0 },
+ { 150, 4 },
+ { 150, 2 },
+ { 154, 3 },
+ { 154, 1 },
+ { 157, 3 },
+ { 158, 1 },
{ 161, 1 },
- { 161, 4 },
- { 161, 6 },
{ 162, 1 },
- { 162, 2 },
+ { 148, 1 },
+ { 148, 1 },
+ { 148, 1 },
+ { 159, 0 },
+ { 159, 1 },
{ 163, 1 },
- { 163, 1 },
- { 158, 2 },
- { 158, 0 },
- { 166, 3 },
- { 166, 1 },
- { 166, 2 },
- { 166, 4 },
- { 166, 3 },
- { 166, 3 },
- { 166, 2 },
- { 167, 2 },
- { 167, 3 },
- { 167, 5 },
- { 167, 2 },
- { 167, 4 },
- { 167, 4 },
- { 167, 1 },
- { 167, 2 },
- { 172, 0 },
- { 172, 1 },
+ { 163, 4 },
+ { 163, 6 },
+ { 164, 1 },
+ { 164, 2 },
+ { 165, 1 },
+ { 165, 1 },
+ { 160, 2 },
+ { 160, 0 },
+ { 168, 3 },
+ { 168, 1 },
+ { 169, 2 },
+ { 169, 4 },
+ { 169, 3 },
+ { 169, 3 },
+ { 169, 2 },
+ { 169, 2 },
+ { 169, 3 },
+ { 169, 5 },
+ { 169, 2 },
+ { 169, 4 },
+ { 169, 4 },
+ { 169, 1 },
+ { 169, 2 },
{ 174, 0 },
- { 174, 2 },
+ { 174, 1 },
+ { 176, 0 },
{ 176, 2 },
- { 176, 3 },
- { 176, 3 },
- { 176, 3 },
- { 177, 2 },
- { 177, 2 },
- { 177, 1 },
- { 177, 1 },
- { 175, 3 },
- { 175, 2 },
- { 178, 0 },
{ 178, 2 },
- { 178, 2 },
- { 153, 0 },
- { 153, 2 },
- { 179, 3 },
+ { 178, 3 },
+ { 178, 3 },
+ { 178, 3 },
+ { 179, 2 },
{ 179, 2 },
{ 179, 1 },
+ { 179, 1 },
+ { 177, 3 },
+ { 177, 2 },
+ { 180, 0 },
{ 180, 2 },
- { 180, 7 },
- { 180, 5 },
- { 180, 5 },
- { 180, 10 },
- { 182, 0 },
- { 182, 1 },
- { 170, 0 },
- { 170, 3 },
- { 183, 0 },
- { 183, 2 },
+ { 180, 2 },
+ { 155, 0 },
+ { 155, 2 },
+ { 181, 3 },
+ { 181, 2 },
+ { 181, 1 },
+ { 182, 2 },
+ { 182, 7 },
+ { 182, 5 },
+ { 182, 5 },
+ { 182, 10 },
+ { 184, 0 },
{ 184, 1 },
- { 184, 1 },
- { 184, 1 },
- { 142, 4 },
- { 186, 2 },
- { 186, 0 },
- { 142, 7 },
- { 142, 4 },
- { 142, 1 },
- { 154, 1 },
- { 154, 3 },
- { 189, 1 },
- { 189, 2 },
- { 189, 1 },
- { 188, 9 },
- { 190, 1 },
- { 190, 1 },
- { 190, 0 },
- { 198, 2 },
- { 198, 0 },
- { 191, 3 },
+ { 172, 0 },
+ { 172, 3 },
+ { 185, 0 },
+ { 185, 2 },
+ { 186, 1 },
+ { 186, 1 },
+ { 186, 1 },
+ { 144, 4 },
+ { 188, 2 },
+ { 188, 0 },
+ { 144, 8 },
+ { 144, 4 },
+ { 144, 1 },
+ { 156, 1 },
+ { 156, 3 },
+ { 191, 1 },
{ 191, 2 },
- { 191, 4 },
- { 199, 2 },
- { 199, 1 },
- { 199, 0 },
+ { 191, 1 },
+ { 190, 9 },
+ { 192, 1 },
+ { 192, 1 },
{ 192, 0 },
- { 192, 2 },
+ { 200, 2 },
+ { 200, 0 },
+ { 193, 3 },
+ { 193, 2 },
+ { 193, 4 },
{ 201, 2 },
+ { 201, 1 },
{ 201, 0 },
- { 200, 6 },
- { 200, 7 },
- { 205, 1 },
- { 205, 1 },
- { 151, 0 },
- { 151, 2 },
- { 187, 2 },
- { 202, 1 },
- { 202, 2 },
- { 202, 3 },
- { 202, 4 },
+ { 194, 0 },
+ { 194, 2 },
{ 203, 2 },
{ 203, 0 },
+ { 202, 6 },
+ { 202, 7 },
+ { 207, 1 },
+ { 207, 1 },
+ { 153, 0 },
+ { 153, 2 },
+ { 189, 2 },
+ { 204, 1 },
+ { 204, 2 },
+ { 204, 3 },
{ 204, 4 },
- { 204, 0 },
+ { 205, 2 },
+ { 205, 0 },
+ { 206, 4 },
+ { 206, 0 },
+ { 198, 0 },
+ { 198, 3 },
+ { 210, 4 },
+ { 210, 2 },
+ { 211, 1 },
+ { 173, 1 },
+ { 173, 1 },
+ { 173, 0 },
{ 196, 0 },
{ 196, 3 },
- { 208, 5 },
- { 208, 3 },
- { 209, 1 },
- { 171, 1 },
- { 171, 1 },
- { 171, 0 },
- { 210, 0 },
- { 210, 2 },
- { 194, 0 },
- { 194, 3 },
- { 195, 0 },
- { 195, 2 },
{ 197, 0 },
{ 197, 2 },
- { 197, 4 },
- { 197, 4 },
- { 142, 4 },
- { 193, 0 },
- { 193, 2 },
- { 142, 6 },
- { 212, 5 },
- { 212, 3 },
- { 142, 8 },
- { 142, 5 },
- { 213, 2 },
- { 213, 1 },
- { 215, 3 },
- { 215, 1 },
- { 214, 0 },
- { 214, 3 },
- { 207, 3 },
- { 207, 1 },
- { 169, 1 },
- { 169, 3 },
- { 168, 1 },
- { 169, 1 },
- { 169, 1 },
- { 169, 3 },
- { 169, 5 },
- { 168, 1 },
- { 168, 1 },
- { 169, 1 },
- { 169, 1 },
- { 169, 6 },
- { 169, 5 },
- { 169, 4 },
- { 168, 1 },
- { 169, 3 },
- { 169, 3 },
- { 169, 3 },
- { 169, 3 },
- { 169, 3 },
- { 169, 3 },
- { 169, 3 },
- { 169, 3 },
+ { 199, 0 },
+ { 199, 2 },
+ { 199, 4 },
+ { 199, 4 },
+ { 144, 4 },
+ { 195, 0 },
+ { 195, 2 },
+ { 144, 6 },
+ { 213, 5 },
+ { 213, 3 },
+ { 144, 8 },
+ { 144, 5 },
+ { 144, 6 },
+ { 214, 2 },
+ { 214, 1 },
+ { 216, 3 },
{ 216, 1 },
- { 216, 2 },
+ { 215, 0 },
+ { 215, 3 },
+ { 209, 3 },
+ { 209, 1 },
+ { 171, 1 },
+ { 171, 3 },
+ { 170, 1 },
+ { 171, 1 },
+ { 171, 1 },
+ { 171, 3 },
+ { 171, 5 },
+ { 170, 1 },
+ { 170, 1 },
+ { 171, 1 },
+ { 171, 1 },
+ { 171, 3 },
+ { 171, 6 },
+ { 171, 5 },
+ { 171, 4 },
+ { 170, 1 },
+ { 171, 3 },
+ { 171, 3 },
+ { 171, 3 },
+ { 171, 3 },
+ { 171, 3 },
+ { 171, 3 },
+ { 171, 3 },
+ { 171, 3 },
+ { 217, 1 },
+ { 217, 2 },
+ { 217, 1 },
{ 217, 2 },
- { 217, 0 },
- { 169, 4 },
- { 169, 2 },
- { 169, 3 },
- { 169, 3 },
- { 169, 4 },
- { 169, 2 },
- { 169, 2 },
- { 169, 2 },
- { 218, 1 },
{ 218, 2 },
- { 169, 5 },
+ { 218, 0 },
+ { 171, 4 },
+ { 171, 2 },
+ { 171, 3 },
+ { 171, 3 },
+ { 171, 4 },
+ { 171, 2 },
+ { 171, 2 },
+ { 171, 2 },
{ 219, 1 },
{ 219, 2 },
- { 169, 5 },
- { 169, 3 },
- { 169, 5 },
- { 169, 4 },
- { 169, 4 },
- { 169, 5 },
- { 221, 5 },
- { 221, 4 },
- { 222, 2 },
- { 222, 0 },
+ { 171, 5 },
{ 220, 1 },
- { 220, 0 },
- { 211, 3 },
- { 211, 1 },
- { 223, 1 },
+ { 220, 2 },
+ { 171, 5 },
+ { 171, 3 },
+ { 171, 5 },
+ { 171, 4 },
+ { 171, 4 },
+ { 171, 5 },
+ { 222, 5 },
+ { 222, 4 },
+ { 223, 2 },
{ 223, 0 },
- { 142, 11 },
+ { 221, 1 },
+ { 221, 0 },
+ { 212, 3 },
+ { 212, 1 },
{ 224, 1 },
{ 224, 0 },
- { 173, 0 },
- { 173, 3 },
- { 181, 5 },
- { 181, 3 },
+ { 144, 11 },
{ 225, 1 },
- { 142, 4 },
- { 142, 1 },
- { 142, 2 },
- { 142, 5 },
- { 142, 5 },
- { 142, 5 },
- { 142, 5 },
- { 142, 6 },
- { 142, 3 },
- { 164, 2 },
- { 165, 2 },
- { 227, 1 },
+ { 225, 0 },
+ { 175, 0 },
+ { 175, 3 },
+ { 183, 5 },
+ { 183, 3 },
{ 226, 1 },
- { 226, 0 },
- { 142, 5 },
- { 228, 10 },
+ { 227, 0 },
+ { 227, 2 },
+ { 144, 4 },
+ { 144, 1 },
+ { 144, 2 },
+ { 144, 5 },
+ { 144, 5 },
+ { 144, 5 },
+ { 144, 6 },
+ { 144, 3 },
+ { 228, 1 },
+ { 228, 1 },
+ { 166, 2 },
+ { 167, 2 },
{ 230, 1 },
- { 230, 1 },
- { 230, 2 },
- { 230, 0 },
- { 231, 1 },
- { 231, 1 },
- { 231, 3 },
- { 232, 0 },
- { 232, 3 },
- { 232, 3 },
- { 233, 0 },
- { 233, 2 },
- { 229, 3 },
+ { 229, 1 },
{ 229, 0 },
- { 234, 6 },
- { 234, 8 },
- { 234, 5 },
- { 234, 4 },
+ { 144, 5 },
+ { 231, 11 },
+ { 233, 1 },
+ { 233, 1 },
+ { 233, 2 },
+ { 233, 0 },
{ 234, 1 },
- { 169, 4 },
- { 169, 6 },
- { 185, 1 },
- { 185, 1 },
- { 185, 1 },
- { 142, 3 },
- { 142, 6 },
+ { 234, 1 },
+ { 234, 3 },
+ { 235, 0 },
+ { 235, 3 },
+ { 235, 3 },
{ 236, 0 },
{ 236, 2 },
- { 235, 1 },
- { 235, 0 },
- { 142, 3 },
- { 142, 1 },
- { 142, 3 },
- { 142, 1 },
- { 142, 3 },
- { 142, 6 },
- { 142, 6 },
+ { 232, 3 },
+ { 232, 0 },
+ { 237, 6 },
+ { 237, 8 },
+ { 237, 5 },
+ { 237, 4 },
{ 237, 1 },
- { 238, 0 },
+ { 171, 4 },
+ { 171, 6 },
+ { 187, 1 },
+ { 187, 1 },
+ { 187, 1 },
+ { 144, 4 },
+ { 144, 6 },
+ { 239, 0 },
+ { 239, 2 },
{ 238, 1 },
+ { 238, 0 },
+ { 144, 3 },
+ { 144, 1 },
+ { 144, 3 },
+ { 144, 1 },
+ { 144, 3 },
+ { 144, 6 },
+ { 144, 6 },
+ { 240, 1 },
+ { 241, 0 },
+ { 241, 1 },
+ { 144, 1 },
+ { 144, 4 },
+ { 242, 7 },
+ { 243, 1 },
+ { 243, 3 },
+ { 244, 0 },
+ { 244, 2 },
+ { 245, 1 },
+ { 245, 3 },
+ { 246, 1 },
+ { 247, 0 },
+ { 247, 2 },
};
static void yy_accept(yyParser*); /* Forward Declaration */
@@ -1773,13 +1849,12 @@ static void yy_reduce(
yymsp = &yypParser->yystack[yypParser->yyidx];
#ifndef NDEBUG
if( yyTraceFILE && yyruleno>=0
- && yyrulenosLastToken.z-yymsp[-2].minor.yy384.z) + pParse->sLastToken.n;
+ yygotominor.yy178.z = yymsp[-2].minor.yy178.z;
+ yygotominor.yy178.n = (pParse->sLastToken.z-yymsp[-2].minor.yy178.z) + pParse->sLastToken.n;
}
-#line 1911 "parse.c"
+#line 1992 "parse.c"
break;
case 31:
-#line 156 "parse.y"
+#line 158 "parse.y"
{
- sqlite3AddColumn(pParse,&yymsp[0].minor.yy384);
- yygotominor.yy384 = yymsp[0].minor.yy384;
+ sqlite3AddColumn(pParse,&yymsp[0].minor.yy178);
+ yygotominor.yy178 = yymsp[0].minor.yy178;
}
-#line 1919 "parse.c"
+#line 2000 "parse.c"
break;
case 32:
case 33:
case 34:
case 35:
case 36:
- case 250:
-#line 166 "parse.y"
-{yygotominor.yy384 = yymsp[0].minor.yy0;}
-#line 1929 "parse.c"
+ case 255:
+#line 168 "parse.y"
+{yygotominor.yy178 = yymsp[0].minor.yy0;}
+#line 2010 "parse.c"
break;
case 38:
-#line 225 "parse.y"
-{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy384);}
-#line 1934 "parse.c"
+#line 229 "parse.y"
+{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy178);}
+#line 2015 "parse.c"
break;
case 39:
case 42:
case 119:
case 120:
case 131:
- case 150:
- case 238:
- case 248:
- case 249:
-#line 226 "parse.y"
-{yygotominor.yy384 = yymsp[0].minor.yy384;}
-#line 1947 "parse.c"
+ case 240:
+ case 242:
+ case 251:
+ case 252:
+ case 253:
+ case 254:
+#line 230 "parse.y"
+{yygotominor.yy178 = yymsp[0].minor.yy178;}
+#line 2030 "parse.c"
break;
case 40:
-#line 227 "parse.y"
-{
- yygotominor.yy384.z = yymsp[-3].minor.yy384.z;
- yygotominor.yy384.n = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy384.z;
-}
-#line 1955 "parse.c"
- break;
- case 41:
#line 231 "parse.y"
{
- yygotominor.yy384.z = yymsp[-5].minor.yy384.z;
- yygotominor.yy384.n = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy384.z;
+ yygotominor.yy178.z = yymsp[-3].minor.yy178.z;
+ yygotominor.yy178.n = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy178.z;
}
-#line 1963 "parse.c"
+#line 2038 "parse.c"
+ break;
+ case 41:
+#line 235 "parse.y"
+{
+ yygotominor.yy178.z = yymsp[-5].minor.yy178.z;
+ yygotominor.yy178.n = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy178.z;
+}
+#line 2046 "parse.c"
break;
case 43:
-#line 237 "parse.y"
-{yygotominor.yy384.z=yymsp[-1].minor.yy384.z; yygotominor.yy384.n=yymsp[0].minor.yy384.n+(yymsp[0].minor.yy384.z-yymsp[-1].minor.yy384.z);}
-#line 1968 "parse.c"
+#line 241 "parse.y"
+{yygotominor.yy178.z=yymsp[-1].minor.yy178.z; yygotominor.yy178.n=yymsp[0].minor.yy178.n+(yymsp[0].minor.yy178.z-yymsp[-1].minor.yy178.z);}
+#line 2051 "parse.c"
break;
case 44:
-#line 239 "parse.y"
-{ yygotominor.yy230 = atoi((char*)yymsp[0].minor.yy384.z); }
-#line 1973 "parse.c"
+#line 243 "parse.y"
+{ yygotominor.yy316 = atoi((char*)yymsp[0].minor.yy178.z); }
+#line 2056 "parse.c"
break;
case 45:
-#line 240 "parse.y"
-{ yygotominor.yy230 = -atoi((char*)yymsp[0].minor.yy384.z); }
-#line 1978 "parse.c"
+#line 244 "parse.y"
+{ yygotominor.yy316 = -atoi((char*)yymsp[0].minor.yy178.z); }
+#line 2061 "parse.c"
break;
case 50:
case 52:
-#line 249 "parse.y"
-{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy178);}
-#line 1984 "parse.c"
+#line 253 "parse.y"
+{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy450);}
+#line 2067 "parse.c"
break;
case 51:
-#line 250 "parse.y"
-{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy178);}
-#line 1989 "parse.c"
+#line 254 "parse.y"
+{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy450);}
+#line 2072 "parse.c"
break;
case 53:
-#line 252 "parse.y"
-{
- Expr *p = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy178, 0, 0);
- sqlite3AddDefaultValue(pParse,p);
-}
-#line 1997 "parse.c"
- break;
- case 54:
#line 256 "parse.y"
{
- Expr *p = sqlite3Expr(TK_STRING, 0, 0, &yymsp[0].minor.yy384);
+ Expr *p = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy450, 0, 0);
sqlite3AddDefaultValue(pParse,p);
}
-#line 2005 "parse.c"
- break;
- case 56:
-#line 265 "parse.y"
-{sqlite3AddNotNull(pParse, yymsp[0].minor.yy230);}
-#line 2010 "parse.c"
- break;
- case 57:
-#line 267 "parse.y"
-{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy230,yymsp[0].minor.yy230,yymsp[-2].minor.yy230);}
-#line 2015 "parse.c"
- break;
- case 58:
-#line 268 "parse.y"
-{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy230,0,0,0,0);}
-#line 2020 "parse.c"
- break;
- case 59:
-#line 269 "parse.y"
-{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy178);}
-#line 2025 "parse.c"
- break;
- case 60:
-#line 271 "parse.y"
-{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy384,yymsp[-1].minor.yy462,yymsp[0].minor.yy230);}
-#line 2030 "parse.c"
- break;
- case 61:
-#line 272 "parse.y"
-{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy230);}
-#line 2035 "parse.c"
- break;
- case 62:
-#line 273 "parse.y"
-{sqlite3AddCollateType(pParse, (char*)yymsp[0].minor.yy384.z, yymsp[0].minor.yy384.n);}
-#line 2040 "parse.c"
- break;
- case 65:
-#line 286 "parse.y"
-{ yygotominor.yy230 = OE_Restrict * 0x010101; }
-#line 2045 "parse.c"
- break;
- case 66:
-#line 287 "parse.y"
-{ yygotominor.yy230 = (yymsp[-1].minor.yy230 & yymsp[0].minor.yy13.mask) | yymsp[0].minor.yy13.value; }
-#line 2050 "parse.c"
- break;
- case 67:
-#line 289 "parse.y"
-{ yygotominor.yy13.value = 0; yygotominor.yy13.mask = 0x000000; }
-#line 2055 "parse.c"
- break;
- case 68:
-#line 290 "parse.y"
-{ yygotominor.yy13.value = yymsp[0].minor.yy230; yygotominor.yy13.mask = 0x0000ff; }
-#line 2060 "parse.c"
- break;
- case 69:
-#line 291 "parse.y"
-{ yygotominor.yy13.value = yymsp[0].minor.yy230<<8; yygotominor.yy13.mask = 0x00ff00; }
-#line 2065 "parse.c"
- break;
- case 70:
-#line 292 "parse.y"
-{ yygotominor.yy13.value = yymsp[0].minor.yy230<<16; yygotominor.yy13.mask = 0xff0000; }
-#line 2070 "parse.c"
- break;
- case 71:
-#line 294 "parse.y"
-{ yygotominor.yy230 = OE_SetNull; }
-#line 2075 "parse.c"
- break;
- case 72:
-#line 295 "parse.y"
-{ yygotominor.yy230 = OE_SetDflt; }
#line 2080 "parse.c"
break;
- case 73:
+ case 54:
+#line 260 "parse.y"
+{
+ Expr *p = sqlite3Expr(TK_STRING, 0, 0, &yymsp[0].minor.yy178);
+ sqlite3AddDefaultValue(pParse,p);
+}
+#line 2088 "parse.c"
+ break;
+ case 56:
+#line 269 "parse.y"
+{sqlite3AddNotNull(pParse, yymsp[0].minor.yy316);}
+#line 2093 "parse.c"
+ break;
+ case 57:
+#line 271 "parse.y"
+{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy316,yymsp[0].minor.yy316,yymsp[-2].minor.yy316);}
+#line 2098 "parse.c"
+ break;
+ case 58:
+#line 272 "parse.y"
+{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy316,0,0,0,0);}
+#line 2103 "parse.c"
+ break;
+ case 59:
+#line 273 "parse.y"
+{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy450);}
+#line 2108 "parse.c"
+ break;
+ case 60:
+#line 275 "parse.y"
+{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy178,yymsp[-1].minor.yy242,yymsp[0].minor.yy316);}
+#line 2113 "parse.c"
+ break;
+ case 61:
+#line 276 "parse.y"
+{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy316);}
+#line 2118 "parse.c"
+ break;
+ case 62:
+#line 277 "parse.y"
+{sqlite3AddCollateType(pParse, (char*)yymsp[0].minor.yy178.z, yymsp[0].minor.yy178.n);}
+#line 2123 "parse.c"
+ break;
+ case 65:
+#line 290 "parse.y"
+{ yygotominor.yy316 = OE_Restrict * 0x010101; }
+#line 2128 "parse.c"
+ break;
+ case 66:
+#line 291 "parse.y"
+{ yygotominor.yy316 = (yymsp[-1].minor.yy316 & yymsp[0].minor.yy207.mask) | yymsp[0].minor.yy207.value; }
+#line 2133 "parse.c"
+ break;
+ case 67:
+#line 293 "parse.y"
+{ yygotominor.yy207.value = 0; yygotominor.yy207.mask = 0x000000; }
+#line 2138 "parse.c"
+ break;
+ case 68:
+#line 294 "parse.y"
+{ yygotominor.yy207.value = yymsp[0].minor.yy316; yygotominor.yy207.mask = 0x0000ff; }
+#line 2143 "parse.c"
+ break;
+ case 69:
+#line 295 "parse.y"
+{ yygotominor.yy207.value = yymsp[0].minor.yy316<<8; yygotominor.yy207.mask = 0x00ff00; }
+#line 2148 "parse.c"
+ break;
+ case 70:
#line 296 "parse.y"
-{ yygotominor.yy230 = OE_Cascade; }
-#line 2085 "parse.c"
+{ yygotominor.yy207.value = yymsp[0].minor.yy316<<16; yygotominor.yy207.mask = 0xff0000; }
+#line 2153 "parse.c"
+ break;
+ case 71:
+#line 298 "parse.y"
+{ yygotominor.yy316 = OE_SetNull; }
+#line 2158 "parse.c"
+ break;
+ case 72:
+#line 299 "parse.y"
+{ yygotominor.yy316 = OE_SetDflt; }
+#line 2163 "parse.c"
+ break;
+ case 73:
+#line 300 "parse.y"
+{ yygotominor.yy316 = OE_Cascade; }
+#line 2168 "parse.c"
break;
case 74:
-#line 297 "parse.y"
-{ yygotominor.yy230 = OE_Restrict; }
-#line 2090 "parse.c"
+#line 301 "parse.y"
+{ yygotominor.yy316 = OE_Restrict; }
+#line 2173 "parse.c"
break;
case 75:
case 76:
@@ -2092,488 +2175,483 @@ static void yy_reduce(
case 93:
case 95:
case 96:
- case 167:
-#line 299 "parse.y"
-{yygotominor.yy230 = yymsp[0].minor.yy230;}
-#line 2101 "parse.c"
+ case 166:
+#line 303 "parse.y"
+{yygotominor.yy316 = yymsp[0].minor.yy316;}
+#line 2184 "parse.c"
break;
case 80:
-#line 309 "parse.y"
-{yygotominor.yy384.n = 0; yygotominor.yy384.z = 0;}
-#line 2106 "parse.c"
+#line 313 "parse.y"
+{yygotominor.yy178.n = 0; yygotominor.yy178.z = 0;}
+#line 2189 "parse.c"
break;
case 81:
-#line 310 "parse.y"
-{yygotominor.yy384 = yymsp[-1].minor.yy0;}
-#line 2111 "parse.c"
+#line 314 "parse.y"
+{yygotominor.yy178 = yymsp[-1].minor.yy0;}
+#line 2194 "parse.c"
break;
case 86:
-#line 316 "parse.y"
-{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy462,yymsp[0].minor.yy230,yymsp[-2].minor.yy230,0);}
-#line 2116 "parse.c"
+#line 320 "parse.y"
+{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy242,yymsp[0].minor.yy316,yymsp[-2].minor.yy316,0);}
+#line 2199 "parse.c"
break;
case 87:
-#line 318 "parse.y"
-{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy462,yymsp[0].minor.yy230,0,0,0,0);}
-#line 2121 "parse.c"
+#line 322 "parse.y"
+{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy242,yymsp[0].minor.yy316,0,0,0,0);}
+#line 2204 "parse.c"
break;
case 88:
-#line 319 "parse.y"
-{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy178);}
-#line 2126 "parse.c"
+#line 323 "parse.y"
+{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy450);}
+#line 2209 "parse.c"
break;
case 89:
-#line 321 "parse.y"
+#line 325 "parse.y"
{
- sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy462, &yymsp[-3].minor.yy384, yymsp[-2].minor.yy462, yymsp[-1].minor.yy230);
- sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy230);
+ sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy242, &yymsp[-3].minor.yy178, yymsp[-2].minor.yy242, yymsp[-1].minor.yy316);
+ sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy316);
}
-#line 2134 "parse.c"
+#line 2217 "parse.c"
break;
case 92:
case 94:
-#line 335 "parse.y"
-{yygotominor.yy230 = OE_Default;}
-#line 2140 "parse.c"
+#line 339 "parse.y"
+{yygotominor.yy316 = OE_Default;}
+#line 2223 "parse.c"
break;
case 97:
-#line 340 "parse.y"
-{yygotominor.yy230 = OE_Ignore;}
-#line 2145 "parse.c"
+#line 344 "parse.y"
+{yygotominor.yy316 = OE_Ignore;}
+#line 2228 "parse.c"
break;
case 98:
- case 168:
-#line 341 "parse.y"
-{yygotominor.yy230 = OE_Replace;}
-#line 2151 "parse.c"
+ case 167:
+#line 345 "parse.y"
+{yygotominor.yy316 = OE_Replace;}
+#line 2234 "parse.c"
break;
case 99:
-#line 345 "parse.y"
+#line 349 "parse.y"
{
- sqlite3DropTable(pParse, yymsp[0].minor.yy285, 0, yymsp[-1].minor.yy230);
+ sqlite3DropTable(pParse, yymsp[0].minor.yy419, 0, yymsp[-1].minor.yy316);
}
-#line 2158 "parse.c"
+#line 2241 "parse.c"
break;
case 102:
-#line 355 "parse.y"
+#line 359 "parse.y"
{
- sqlite3CreateView(pParse, &yymsp[-6].minor.yy0, &yymsp[-3].minor.yy384, &yymsp[-2].minor.yy384, yymsp[0].minor.yy239, yymsp[-5].minor.yy230);
+ sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy178, &yymsp[-2].minor.yy178, yymsp[0].minor.yy43, yymsp[-6].minor.yy316, yymsp[-4].minor.yy316);
}
-#line 2165 "parse.c"
+#line 2248 "parse.c"
break;
case 103:
-#line 358 "parse.y"
+#line 362 "parse.y"
{
- sqlite3DropTable(pParse, yymsp[0].minor.yy285, 1, yymsp[-1].minor.yy230);
+ sqlite3DropTable(pParse, yymsp[0].minor.yy419, 1, yymsp[-1].minor.yy316);
}
-#line 2172 "parse.c"
+#line 2255 "parse.c"
break;
case 104:
-#line 365 "parse.y"
+#line 369 "parse.y"
{
- sqlite3Select(pParse, yymsp[0].minor.yy239, SRT_Callback, 0, 0, 0, 0, 0);
- sqlite3SelectDelete(yymsp[0].minor.yy239);
+ sqlite3Select(pParse, yymsp[0].minor.yy43, SRT_Callback, 0, 0, 0, 0, 0);
+ sqlite3SelectDelete(yymsp[0].minor.yy43);
}
-#line 2180 "parse.c"
+#line 2263 "parse.c"
break;
case 105:
case 128:
-#line 375 "parse.y"
-{yygotominor.yy239 = yymsp[0].minor.yy239;}
-#line 2186 "parse.c"
+#line 379 "parse.y"
+{yygotominor.yy43 = yymsp[0].minor.yy43;}
+#line 2269 "parse.c"
break;
case 106:
-#line 377 "parse.y"
+#line 381 "parse.y"
{
- if( yymsp[0].minor.yy239 ){
- yymsp[0].minor.yy239->op = yymsp[-1].minor.yy230;
- yymsp[0].minor.yy239->pPrior = yymsp[-2].minor.yy239;
+ if( yymsp[0].minor.yy43 ){
+ yymsp[0].minor.yy43->op = yymsp[-1].minor.yy316;
+ yymsp[0].minor.yy43->pPrior = yymsp[-2].minor.yy43;
}
- yygotominor.yy239 = yymsp[0].minor.yy239;
+ yygotominor.yy43 = yymsp[0].minor.yy43;
}
-#line 2197 "parse.c"
+#line 2280 "parse.c"
break;
case 108:
-#line 386 "parse.y"
-{yygotominor.yy230 = TK_ALL;}
-#line 2202 "parse.c"
+#line 390 "parse.y"
+{yygotominor.yy316 = TK_ALL;}
+#line 2285 "parse.c"
break;
case 110:
-#line 390 "parse.y"
+#line 394 "parse.y"
{
- yygotominor.yy239 = sqlite3SelectNew(yymsp[-6].minor.yy462,yymsp[-5].minor.yy285,yymsp[-4].minor.yy178,yymsp[-3].minor.yy462,yymsp[-2].minor.yy178,yymsp[-1].minor.yy462,yymsp[-7].minor.yy230,yymsp[0].minor.yy270.pLimit,yymsp[0].minor.yy270.pOffset);
+ yygotominor.yy43 = sqlite3SelectNew(yymsp[-6].minor.yy242,yymsp[-5].minor.yy419,yymsp[-4].minor.yy450,yymsp[-3].minor.yy242,yymsp[-2].minor.yy450,yymsp[-1].minor.yy242,yymsp[-7].minor.yy316,yymsp[0].minor.yy84.pLimit,yymsp[0].minor.yy84.pOffset);
}
-#line 2209 "parse.c"
+#line 2292 "parse.c"
break;
case 114:
- case 235:
-#line 411 "parse.y"
-{yygotominor.yy462 = yymsp[-1].minor.yy462;}
-#line 2215 "parse.c"
+ case 237:
+#line 415 "parse.y"
+{yygotominor.yy242 = yymsp[-1].minor.yy242;}
+#line 2298 "parse.c"
break;
case 115:
case 141:
- case 151:
- case 234:
-#line 412 "parse.y"
-{yygotominor.yy462 = 0;}
-#line 2223 "parse.c"
+ case 149:
+ case 236:
+#line 416 "parse.y"
+{yygotominor.yy242 = 0;}
+#line 2306 "parse.c"
break;
case 116:
-#line 413 "parse.y"
+#line 417 "parse.y"
{
- yygotominor.yy462 = sqlite3ExprListAppend(yymsp[-2].minor.yy462,yymsp[-1].minor.yy178,yymsp[0].minor.yy384.n?&yymsp[0].minor.yy384:0);
+ yygotominor.yy242 = sqlite3ExprListAppend(yymsp[-2].minor.yy242,yymsp[-1].minor.yy450,yymsp[0].minor.yy178.n?&yymsp[0].minor.yy178:0);
}
-#line 2230 "parse.c"
+#line 2313 "parse.c"
break;
case 117:
-#line 416 "parse.y"
+#line 420 "parse.y"
{
- yygotominor.yy462 = sqlite3ExprListAppend(yymsp[-1].minor.yy462, sqlite3Expr(TK_ALL, 0, 0, 0), 0);
+ yygotominor.yy242 = sqlite3ExprListAppend(yymsp[-1].minor.yy242, sqlite3Expr(TK_ALL, 0, 0, 0), 0);
}
-#line 2237 "parse.c"
+#line 2320 "parse.c"
break;
case 118:
-#line 419 "parse.y"
+#line 423 "parse.y"
{
Expr *pRight = sqlite3Expr(TK_ALL, 0, 0, 0);
- Expr *pLeft = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy384);
- yygotominor.yy462 = sqlite3ExprListAppend(yymsp[-3].minor.yy462, sqlite3Expr(TK_DOT, pLeft, pRight, 0), 0);
+ Expr *pLeft = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy178);
+ yygotominor.yy242 = sqlite3ExprListAppend(yymsp[-3].minor.yy242, sqlite3Expr(TK_DOT, pLeft, pRight, 0), 0);
}
-#line 2246 "parse.c"
- break;
- case 121:
-#line 431 "parse.y"
-{yygotominor.yy384.n = 0;}
-#line 2251 "parse.c"
- break;
- case 122:
-#line 443 "parse.y"
-{yygotominor.yy285 = sqliteMalloc(sizeof(*yygotominor.yy285));}
-#line 2256 "parse.c"
- break;
- case 123:
-#line 444 "parse.y"
-{yygotominor.yy285 = yymsp[0].minor.yy285;}
-#line 2261 "parse.c"
- break;
- case 124:
-#line 449 "parse.y"
-{
- yygotominor.yy285 = yymsp[-1].minor.yy285;
- if( yygotominor.yy285 && yygotominor.yy285->nSrc>0 ) yygotominor.yy285->a[yygotominor.yy285->nSrc-1].jointype = yymsp[0].minor.yy230;
-}
-#line 2269 "parse.c"
- break;
- case 125:
-#line 453 "parse.y"
-{yygotominor.yy285 = 0;}
-#line 2274 "parse.c"
- break;
- case 126:
-#line 454 "parse.y"
-{
- yygotominor.yy285 = sqlite3SrcListAppend(yymsp[-5].minor.yy285,&yymsp[-4].minor.yy384,&yymsp[-3].minor.yy384);
- if( yymsp[-2].minor.yy384.n ) sqlite3SrcListAddAlias(yygotominor.yy285,&yymsp[-2].minor.yy384);
- if( yymsp[-1].minor.yy178 ){
- if( yygotominor.yy285 && yygotominor.yy285->nSrc>1 ){ yygotominor.yy285->a[yygotominor.yy285->nSrc-2].pOn = yymsp[-1].minor.yy178; }
- else { sqlite3ExprDelete(yymsp[-1].minor.yy178); }
- }
- if( yymsp[0].minor.yy160 ){
- if( yygotominor.yy285 && yygotominor.yy285->nSrc>1 ){ yygotominor.yy285->a[yygotominor.yy285->nSrc-2].pUsing = yymsp[0].minor.yy160; }
- else { sqlite3IdListDelete(yymsp[0].minor.yy160); }
- }
-}
-#line 2290 "parse.c"
- break;
- case 127:
-#line 468 "parse.y"
-{
- yygotominor.yy285 = sqlite3SrcListAppend(yymsp[-6].minor.yy285,0,0);
- yygotominor.yy285->a[yygotominor.yy285->nSrc-1].pSelect = yymsp[-4].minor.yy239;
- if( yymsp[-2].minor.yy384.n ) sqlite3SrcListAddAlias(yygotominor.yy285,&yymsp[-2].minor.yy384);
- if( yymsp[-1].minor.yy178 ){
- if( yygotominor.yy285 && yygotominor.yy285->nSrc>1 ){ yygotominor.yy285->a[yygotominor.yy285->nSrc-2].pOn = yymsp[-1].minor.yy178; }
- else { sqlite3ExprDelete(yymsp[-1].minor.yy178); }
- }
- if( yymsp[0].minor.yy160 ){
- if( yygotominor.yy285 && yygotominor.yy285->nSrc>1 ){ yygotominor.yy285->a[yygotominor.yy285->nSrc-2].pUsing = yymsp[0].minor.yy160; }
- else { sqlite3IdListDelete(yymsp[0].minor.yy160); }
- }
- }
-#line 2307 "parse.c"
- break;
- case 129:
-#line 489 "parse.y"
-{
- yygotominor.yy239 = sqlite3SelectNew(0,yymsp[0].minor.yy285,0,0,0,0,0,0,0);
- }
-#line 2314 "parse.c"
- break;
- case 130:
-#line 495 "parse.y"
-{yygotominor.yy384.z=0; yygotominor.yy384.n=0;}
-#line 2319 "parse.c"
- break;
- case 132:
-#line 500 "parse.y"
-{yygotominor.yy285 = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy384,&yymsp[0].minor.yy384);}
-#line 2324 "parse.c"
- break;
- case 133:
-#line 504 "parse.y"
-{ yygotominor.yy230 = JT_INNER; }
#line 2329 "parse.c"
break;
- case 134:
-#line 505 "parse.y"
-{ yygotominor.yy230 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
+ case 121:
+#line 435 "parse.y"
+{yygotominor.yy178.n = 0;}
#line 2334 "parse.c"
break;
- case 135:
-#line 506 "parse.y"
-{ yygotominor.yy230 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy384,0); }
+ case 122:
+#line 447 "parse.y"
+{yygotominor.yy419 = sqliteMalloc(sizeof(*yygotominor.yy419));}
#line 2339 "parse.c"
break;
+ case 123:
+#line 448 "parse.y"
+{
+ yygotominor.yy419 = yymsp[0].minor.yy419;
+ sqlite3SrcListShiftJoinType(yygotominor.yy419);
+}
+#line 2347 "parse.c"
+ break;
+ case 124:
+#line 456 "parse.y"
+{
+ yygotominor.yy419 = yymsp[-1].minor.yy419;
+ if( yygotominor.yy419 && yygotominor.yy419->nSrc>0 ) yygotominor.yy419->a[yygotominor.yy419->nSrc-1].jointype = yymsp[0].minor.yy316;
+}
+#line 2355 "parse.c"
+ break;
+ case 125:
+#line 460 "parse.y"
+{yygotominor.yy419 = 0;}
+#line 2360 "parse.c"
+ break;
+ case 126:
+#line 461 "parse.y"
+{
+ yygotominor.yy419 = sqlite3SrcListAppendFromTerm(yymsp[-5].minor.yy419,&yymsp[-4].minor.yy178,&yymsp[-3].minor.yy178,&yymsp[-2].minor.yy178,0,yymsp[-1].minor.yy450,yymsp[0].minor.yy352);
+}
+#line 2367 "parse.c"
+ break;
+ case 127:
+#line 466 "parse.y"
+{
+ yygotominor.yy419 = sqlite3SrcListAppendFromTerm(yymsp[-6].minor.yy419,0,0,&yymsp[-2].minor.yy178,yymsp[-4].minor.yy43,yymsp[-1].minor.yy450,yymsp[0].minor.yy352);
+ }
+#line 2374 "parse.c"
+ break;
+ case 129:
+#line 477 "parse.y"
+{
+ sqlite3SrcListShiftJoinType(yymsp[0].minor.yy419);
+ yygotominor.yy43 = sqlite3SelectNew(0,yymsp[0].minor.yy419,0,0,0,0,0,0,0);
+ }
+#line 2382 "parse.c"
+ break;
+ case 130:
+#line 484 "parse.y"
+{yygotominor.yy178.z=0; yygotominor.yy178.n=0;}
+#line 2387 "parse.c"
+ break;
+ case 132:
+#line 489 "parse.y"
+{yygotominor.yy419 = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy178,&yymsp[0].minor.yy178);}
+#line 2392 "parse.c"
+ break;
+ case 133:
+#line 493 "parse.y"
+{ yygotominor.yy316 = JT_INNER; }
+#line 2397 "parse.c"
+ break;
+ case 134:
+#line 494 "parse.y"
+{ yygotominor.yy316 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
+#line 2402 "parse.c"
+ break;
+ case 135:
+#line 495 "parse.y"
+{ yygotominor.yy316 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy178,0); }
+#line 2407 "parse.c"
+ break;
case 136:
-#line 508 "parse.y"
-{ yygotominor.yy230 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy384,&yymsp[-1].minor.yy384); }
-#line 2344 "parse.c"
+#line 497 "parse.y"
+{ yygotominor.yy316 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy178,&yymsp[-1].minor.yy178); }
+#line 2412 "parse.c"
break;
case 137:
case 145:
- case 154:
- case 161:
- case 175:
- case 200:
- case 223:
+ case 152:
+ case 159:
+ case 174:
+ case 202:
case 225:
- case 229:
-#line 512 "parse.y"
-{yygotominor.yy178 = yymsp[0].minor.yy178;}
-#line 2357 "parse.c"
+ case 227:
+ case 231:
+#line 501 "parse.y"
+{yygotominor.yy450 = yymsp[0].minor.yy450;}
+#line 2425 "parse.c"
break;
case 138:
- case 153:
- case 160:
- case 201:
- case 224:
+ case 151:
+ case 158:
+ case 203:
case 226:
- case 230:
-#line 513 "parse.y"
-{yygotominor.yy178 = 0;}
-#line 2368 "parse.c"
+ case 228:
+ case 232:
+#line 502 "parse.y"
+{yygotominor.yy450 = 0;}
+#line 2436 "parse.c"
break;
case 139:
- case 172:
-#line 517 "parse.y"
-{yygotominor.yy160 = yymsp[-1].minor.yy160;}
-#line 2374 "parse.c"
+ case 171:
+#line 506 "parse.y"
+{yygotominor.yy352 = yymsp[-1].minor.yy352;}
+#line 2442 "parse.c"
break;
case 140:
- case 171:
-#line 518 "parse.y"
-{yygotominor.yy160 = 0;}
-#line 2380 "parse.c"
+ case 170:
+#line 507 "parse.y"
+{yygotominor.yy352 = 0;}
+#line 2448 "parse.c"
break;
case 142:
- case 152:
-#line 529 "parse.y"
-{yygotominor.yy462 = yymsp[0].minor.yy462;}
-#line 2386 "parse.c"
+ case 150:
+#line 518 "parse.y"
+{yygotominor.yy242 = yymsp[0].minor.yy242;}
+#line 2454 "parse.c"
break;
case 143:
-#line 530 "parse.y"
+#line 519 "parse.y"
{
- yygotominor.yy462 = sqlite3ExprListAppend(yymsp[-4].minor.yy462,yymsp[-2].minor.yy178,yymsp[-1].minor.yy384.n>0?&yymsp[-1].minor.yy384:0);
- if( yygotominor.yy462 ) yygotominor.yy462->a[yygotominor.yy462->nExpr-1].sortOrder = yymsp[0].minor.yy230;
+ yygotominor.yy242 = sqlite3ExprListAppend(yymsp[-3].minor.yy242,yymsp[-1].minor.yy450,0);
+ if( yygotominor.yy242 ) yygotominor.yy242->a[yygotominor.yy242->nExpr-1].sortOrder = yymsp[0].minor.yy316;
}
-#line 2394 "parse.c"
+#line 2462 "parse.c"
break;
case 144:
-#line 534 "parse.y"
+#line 523 "parse.y"
{
- yygotominor.yy462 = sqlite3ExprListAppend(0,yymsp[-2].minor.yy178,yymsp[-1].minor.yy384.n>0?&yymsp[-1].minor.yy384:0);
- if( yygotominor.yy462 && yygotominor.yy462->a ) yygotominor.yy462->a[0].sortOrder = yymsp[0].minor.yy230;
+ yygotominor.yy242 = sqlite3ExprListAppend(0,yymsp[-1].minor.yy450,0);
+ if( yygotominor.yy242 && yygotominor.yy242->a ) yygotominor.yy242->a[0].sortOrder = yymsp[0].minor.yy316;
}
-#line 2402 "parse.c"
+#line 2470 "parse.c"
break;
case 146:
case 148:
-#line 543 "parse.y"
-{yygotominor.yy230 = SQLITE_SO_ASC;}
-#line 2408 "parse.c"
+#line 531 "parse.y"
+{yygotominor.yy316 = SQLITE_SO_ASC;}
+#line 2476 "parse.c"
break;
case 147:
-#line 544 "parse.y"
-{yygotominor.yy230 = SQLITE_SO_DESC;}
-#line 2413 "parse.c"
+#line 532 "parse.y"
+{yygotominor.yy316 = SQLITE_SO_DESC;}
+#line 2481 "parse.c"
break;
- case 149:
-#line 546 "parse.y"
-{yygotominor.yy384.z = 0; yygotominor.yy384.n = 0;}
-#line 2418 "parse.c"
+ case 153:
+#line 550 "parse.y"
+{yygotominor.yy84.pLimit = 0; yygotominor.yy84.pOffset = 0;}
+#line 2486 "parse.c"
+ break;
+ case 154:
+#line 551 "parse.y"
+{yygotominor.yy84.pLimit = yymsp[0].minor.yy450; yygotominor.yy84.pOffset = 0;}
+#line 2491 "parse.c"
break;
case 155:
-#line 564 "parse.y"
-{yygotominor.yy270.pLimit = 0; yygotominor.yy270.pOffset = 0;}
-#line 2423 "parse.c"
+#line 553 "parse.y"
+{yygotominor.yy84.pLimit = yymsp[-2].minor.yy450; yygotominor.yy84.pOffset = yymsp[0].minor.yy450;}
+#line 2496 "parse.c"
break;
case 156:
-#line 565 "parse.y"
-{yygotominor.yy270.pLimit = yymsp[0].minor.yy178; yygotominor.yy270.pOffset = 0;}
-#line 2428 "parse.c"
+#line 555 "parse.y"
+{yygotominor.yy84.pOffset = yymsp[-2].minor.yy450; yygotominor.yy84.pLimit = yymsp[0].minor.yy450;}
+#line 2501 "parse.c"
break;
case 157:
-#line 567 "parse.y"
-{yygotominor.yy270.pLimit = yymsp[-2].minor.yy178; yygotominor.yy270.pOffset = yymsp[0].minor.yy178;}
-#line 2433 "parse.c"
+#line 559 "parse.y"
+{sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy419,yymsp[0].minor.yy450);}
+#line 2506 "parse.c"
break;
- case 158:
-#line 569 "parse.y"
-{yygotominor.yy270.pOffset = yymsp[-2].minor.yy178; yygotominor.yy270.pLimit = yymsp[0].minor.yy178;}
-#line 2438 "parse.c"
+ case 160:
+#line 570 "parse.y"
+{sqlite3Update(pParse,yymsp[-3].minor.yy419,yymsp[-1].minor.yy242,yymsp[0].minor.yy450,yymsp[-4].minor.yy316);}
+#line 2511 "parse.c"
break;
- case 159:
-#line 573 "parse.y"
-{sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy285,yymsp[0].minor.yy178);}
-#line 2443 "parse.c"
+ case 161:
+#line 576 "parse.y"
+{yygotominor.yy242 = sqlite3ExprListAppend(yymsp[-4].minor.yy242,yymsp[0].minor.yy450,&yymsp[-2].minor.yy178);}
+#line 2516 "parse.c"
break;
case 162:
-#line 584 "parse.y"
-{sqlite3Update(pParse,yymsp[-3].minor.yy285,yymsp[-1].minor.yy462,yymsp[0].minor.yy178,yymsp[-4].minor.yy230);}
-#line 2448 "parse.c"
+#line 577 "parse.y"
+{yygotominor.yy242 = sqlite3ExprListAppend(0,yymsp[0].minor.yy450,&yymsp[-2].minor.yy178);}
+#line 2521 "parse.c"
break;
case 163:
-#line 590 "parse.y"
-{yygotominor.yy462 = sqlite3ExprListAppend(yymsp[-4].minor.yy462,yymsp[0].minor.yy178,&yymsp[-2].minor.yy384);}
-#line 2453 "parse.c"
+#line 583 "parse.y"
+{sqlite3Insert(pParse, yymsp[-5].minor.yy419, yymsp[-1].minor.yy242, 0, yymsp[-4].minor.yy352, yymsp[-7].minor.yy316);}
+#line 2526 "parse.c"
break;
case 164:
-#line 591 "parse.y"
-{yygotominor.yy462 = sqlite3ExprListAppend(0,yymsp[0].minor.yy178,&yymsp[-2].minor.yy384);}
-#line 2458 "parse.c"
+#line 585 "parse.y"
+{sqlite3Insert(pParse, yymsp[-2].minor.yy419, 0, yymsp[0].minor.yy43, yymsp[-1].minor.yy352, yymsp[-4].minor.yy316);}
+#line 2531 "parse.c"
break;
case 165:
+#line 587 "parse.y"
+{sqlite3Insert(pParse, yymsp[-3].minor.yy419, 0, 0, yymsp[-2].minor.yy352, yymsp[-5].minor.yy316);}
+#line 2536 "parse.c"
+ break;
+ case 168:
+ case 229:
#line 597 "parse.y"
-{sqlite3Insert(pParse, yymsp[-5].minor.yy285, yymsp[-1].minor.yy462, 0, yymsp[-4].minor.yy160, yymsp[-7].minor.yy230);}
-#line 2463 "parse.c"
- break;
- case 166:
-#line 599 "parse.y"
-{sqlite3Insert(pParse, yymsp[-2].minor.yy285, 0, yymsp[0].minor.yy239, yymsp[-1].minor.yy160, yymsp[-4].minor.yy230);}
-#line 2468 "parse.c"
- break;
- case 169:
- case 227:
-#line 609 "parse.y"
-{yygotominor.yy462 = sqlite3ExprListAppend(yymsp[-2].minor.yy462,yymsp[0].minor.yy178,0);}
-#line 2474 "parse.c"
- break;
- case 170:
- case 228:
-#line 610 "parse.y"
-{yygotominor.yy462 = sqlite3ExprListAppend(0,yymsp[0].minor.yy178,0);}
-#line 2480 "parse.c"
- break;
- case 173:
-#line 619 "parse.y"
-{yygotominor.yy160 = sqlite3IdListAppend(yymsp[-2].minor.yy160,&yymsp[0].minor.yy384);}
-#line 2485 "parse.c"
- break;
- case 174:
-#line 620 "parse.y"
-{yygotominor.yy160 = sqlite3IdListAppend(0,&yymsp[0].minor.yy384);}
-#line 2490 "parse.c"
- break;
- case 176:
-#line 631 "parse.y"
-{yygotominor.yy178 = yymsp[-1].minor.yy178; sqlite3ExprSpan(yygotominor.yy178,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); }
-#line 2495 "parse.c"
- break;
- case 177:
- case 182:
- case 183:
-#line 632 "parse.y"
-{yygotominor.yy178 = sqlite3Expr(yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);}
-#line 2502 "parse.c"
- break;
- case 178:
- case 179:
-#line 633 "parse.y"
-{yygotominor.yy178 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy0);}
-#line 2508 "parse.c"
- break;
- case 180:
-#line 635 "parse.y"
-{
- Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy384);
- Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy384);
- yygotominor.yy178 = sqlite3Expr(TK_DOT, temp1, temp2, 0);
-}
-#line 2517 "parse.c"
- break;
- case 181:
-#line 640 "parse.y"
-{
- Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-4].minor.yy384);
- Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy384);
- Expr *temp3 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy384);
- Expr *temp4 = sqlite3Expr(TK_DOT, temp2, temp3, 0);
- yygotominor.yy178 = sqlite3Expr(TK_DOT, temp1, temp4, 0);
-}
-#line 2528 "parse.c"
- break;
- case 184:
-#line 649 "parse.y"
-{yygotominor.yy178 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);}
-#line 2533 "parse.c"
- break;
- case 185:
-#line 650 "parse.y"
-{
- Token *pToken = &yymsp[0].minor.yy0;
- Expr *pExpr = yygotominor.yy178 = sqlite3Expr(TK_VARIABLE, 0, 0, pToken);
- sqlite3ExprAssignVarNumber(pParse, pExpr);
-}
+{yygotominor.yy242 = sqlite3ExprListAppend(yymsp[-2].minor.yy242,yymsp[0].minor.yy450,0);}
#line 2542 "parse.c"
break;
- case 186:
-#line 656 "parse.y"
+ case 169:
+ case 230:
+#line 598 "parse.y"
+{yygotominor.yy242 = sqlite3ExprListAppend(0,yymsp[0].minor.yy450,0);}
+#line 2548 "parse.c"
+ break;
+ case 172:
+#line 607 "parse.y"
+{yygotominor.yy352 = sqlite3IdListAppend(yymsp[-2].minor.yy352,&yymsp[0].minor.yy178);}
+#line 2553 "parse.c"
+ break;
+ case 173:
+#line 608 "parse.y"
+{yygotominor.yy352 = sqlite3IdListAppend(0,&yymsp[0].minor.yy178);}
+#line 2558 "parse.c"
+ break;
+ case 175:
+#line 619 "parse.y"
+{yygotominor.yy450 = yymsp[-1].minor.yy450; sqlite3ExprSpan(yygotominor.yy450,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); }
+#line 2563 "parse.c"
+ break;
+ case 176:
+ case 181:
+ case 182:
+#line 620 "parse.y"
+{yygotominor.yy450 = sqlite3Expr(yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);}
+#line 2570 "parse.c"
+ break;
+ case 177:
+ case 178:
+#line 621 "parse.y"
+{yygotominor.yy450 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy0);}
+#line 2576 "parse.c"
+ break;
+ case 179:
+#line 623 "parse.y"
{
- yygotominor.yy178 = sqlite3Expr(TK_CAST, yymsp[-3].minor.yy178, 0, &yymsp[-1].minor.yy384);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);
+ Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy178);
+ Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy178);
+ yygotominor.yy450 = sqlite3Expr(TK_DOT, temp1, temp2, 0);
}
-#line 2550 "parse.c"
+#line 2585 "parse.c"
+ break;
+ case 180:
+#line 628 "parse.y"
+{
+ Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-4].minor.yy178);
+ Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy178);
+ Expr *temp3 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy178);
+ Expr *temp4 = sqlite3Expr(TK_DOT, temp2, temp3, 0);
+ yygotominor.yy450 = sqlite3Expr(TK_DOT, temp1, temp4, 0);
+}
+#line 2596 "parse.c"
+ break;
+ case 183:
+#line 637 "parse.y"
+{yygotominor.yy450 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);}
+#line 2601 "parse.c"
+ break;
+ case 184:
+#line 638 "parse.y"
+{
+ Token *pToken = &yymsp[0].minor.yy0;
+ Expr *pExpr = yygotominor.yy450 = sqlite3Expr(TK_VARIABLE, 0, 0, pToken);
+ sqlite3ExprAssignVarNumber(pParse, pExpr);
+}
+#line 2610 "parse.c"
+ break;
+ case 185:
+#line 643 "parse.y"
+{
+ yygotominor.yy450 = sqlite3ExprSetColl(pParse, yymsp[-2].minor.yy450, &yymsp[0].minor.yy178);
+}
+#line 2617 "parse.c"
+ break;
+ case 186:
+#line 647 "parse.y"
+{
+ yygotominor.yy450 = sqlite3Expr(TK_CAST, yymsp[-3].minor.yy450, 0, &yymsp[-1].minor.yy178);
+ sqlite3ExprSpan(yygotominor.yy450,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);
+}
+#line 2625 "parse.c"
break;
case 187:
-#line 661 "parse.y"
+#line 652 "parse.y"
{
- yygotominor.yy178 = sqlite3ExprFunction(yymsp[-1].minor.yy462, &yymsp[-4].minor.yy0);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
- if( yymsp[-2].minor.yy230 && yygotominor.yy178 ){
- yygotominor.yy178->flags |= EP_Distinct;
+ yygotominor.yy450 = sqlite3ExprFunction(yymsp[-1].minor.yy242, &yymsp[-4].minor.yy0);
+ sqlite3ExprSpan(yygotominor.yy450,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
+ if( yymsp[-2].minor.yy316 && yygotominor.yy450 ){
+ yygotominor.yy450->flags |= EP_Distinct;
}
}
-#line 2561 "parse.c"
+#line 2636 "parse.c"
break;
case 188:
-#line 668 "parse.y"
+#line 659 "parse.y"
{
- yygotominor.yy178 = sqlite3ExprFunction(0, &yymsp[-3].minor.yy0);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
+ yygotominor.yy450 = sqlite3ExprFunction(0, &yymsp[-3].minor.yy0);
+ sqlite3ExprSpan(yygotominor.yy450,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
}
-#line 2569 "parse.c"
+#line 2644 "parse.c"
break;
case 189:
-#line 672 "parse.y"
+#line 663 "parse.y"
{
/* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are
** treated as functions that return constants */
- yygotominor.yy178 = sqlite3ExprFunction(0,&yymsp[0].minor.yy0);
- if( yygotominor.yy178 ) yygotominor.yy178->op = TK_CONST_FUNC;
+ yygotominor.yy450 = sqlite3ExprFunction(0,&yymsp[0].minor.yy0);
+ if( yygotominor.yy450 ){
+ yygotominor.yy450->op = TK_CONST_FUNC;
+ yygotominor.yy450->span = yymsp[0].minor.yy0;
+ }
}
-#line 2579 "parse.c"
+#line 2657 "parse.c"
break;
case 190:
case 191:
@@ -2583,501 +2661,538 @@ static void yy_reduce(
case 195:
case 196:
case 197:
-#line 678 "parse.y"
-{yygotominor.yy178 = sqlite3Expr(yymsp[-1].major, yymsp[-2].minor.yy178, yymsp[0].minor.yy178, 0);}
-#line 2591 "parse.c"
+#line 672 "parse.y"
+{yygotominor.yy450 = sqlite3Expr(yymsp[-1].major, yymsp[-2].minor.yy450, yymsp[0].minor.yy450, 0);}
+#line 2669 "parse.c"
break;
case 198:
-#line 688 "parse.y"
-{yygotominor.yy440.eOperator = yymsp[0].minor.yy0; yygotominor.yy440.not = 0;}
-#line 2596 "parse.c"
+ case 200:
+#line 682 "parse.y"
+{yygotominor.yy86.eOperator = yymsp[0].minor.yy0; yygotominor.yy86.not = 0;}
+#line 2675 "parse.c"
break;
case 199:
-#line 689 "parse.y"
-{yygotominor.yy440.eOperator = yymsp[0].minor.yy0; yygotominor.yy440.not = 1;}
-#line 2601 "parse.c"
- break;
- case 202:
-#line 694 "parse.y"
-{
- ExprList *pList;
- pList = sqlite3ExprListAppend(0, yymsp[-1].minor.yy178, 0);
- pList = sqlite3ExprListAppend(pList, yymsp[-3].minor.yy178, 0);
- if( yymsp[0].minor.yy178 ){
- pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy178, 0);
- }
- yygotominor.yy178 = sqlite3ExprFunction(pList, &yymsp[-2].minor.yy440.eOperator);
- if( yymsp[-2].minor.yy440.not ) yygotominor.yy178 = sqlite3Expr(TK_NOT, yygotominor.yy178, 0, 0);
- sqlite3ExprSpan(yygotominor.yy178, &yymsp[-3].minor.yy178->span, &yymsp[-1].minor.yy178->span);
-}
-#line 2616 "parse.c"
- break;
- case 203:
-#line 706 "parse.y"
-{
- yygotominor.yy178 = sqlite3Expr(yymsp[0].major, yymsp[-1].minor.yy178, 0, 0);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-1].minor.yy178->span,&yymsp[0].minor.yy0);
-}
-#line 2624 "parse.c"
+ case 201:
+#line 683 "parse.y"
+{yygotominor.yy86.eOperator = yymsp[0].minor.yy0; yygotominor.yy86.not = 1;}
+#line 2681 "parse.c"
break;
case 204:
-#line 710 "parse.y"
+#line 690 "parse.y"
{
- yygotominor.yy178 = sqlite3Expr(TK_ISNULL, yymsp[-2].minor.yy178, 0, 0);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-2].minor.yy178->span,&yymsp[0].minor.yy0);
+ ExprList *pList;
+ pList = sqlite3ExprListAppend(0, yymsp[-1].minor.yy450, 0);
+ pList = sqlite3ExprListAppend(pList, yymsp[-3].minor.yy450, 0);
+ if( yymsp[0].minor.yy450 ){
+ pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy450, 0);
+ }
+ yygotominor.yy450 = sqlite3ExprFunction(pList, &yymsp[-2].minor.yy86.eOperator);
+ if( yymsp[-2].minor.yy86.not ) yygotominor.yy450 = sqlite3Expr(TK_NOT, yygotominor.yy450, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy450, &yymsp[-3].minor.yy450->span, &yymsp[-1].minor.yy450->span);
+ if( yygotominor.yy450 ) yygotominor.yy450->flags |= EP_InfixFunc;
}
-#line 2632 "parse.c"
+#line 2697 "parse.c"
break;
case 205:
-#line 714 "parse.y"
+#line 703 "parse.y"
{
- yygotominor.yy178 = sqlite3Expr(TK_NOTNULL, yymsp[-2].minor.yy178, 0, 0);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-2].minor.yy178->span,&yymsp[0].minor.yy0);
+ yygotominor.yy450 = sqlite3Expr(yymsp[0].major, yymsp[-1].minor.yy450, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy450,&yymsp[-1].minor.yy450->span,&yymsp[0].minor.yy0);
}
-#line 2640 "parse.c"
+#line 2705 "parse.c"
break;
case 206:
-#line 718 "parse.y"
+#line 707 "parse.y"
{
- yygotominor.yy178 = sqlite3Expr(TK_NOTNULL, yymsp[-3].minor.yy178, 0, 0);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-3].minor.yy178->span,&yymsp[0].minor.yy0);
+ yygotominor.yy450 = sqlite3Expr(TK_ISNULL, yymsp[-2].minor.yy450, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy450,&yymsp[-2].minor.yy450->span,&yymsp[0].minor.yy0);
}
-#line 2648 "parse.c"
+#line 2713 "parse.c"
break;
case 207:
-#line 722 "parse.y"
+#line 711 "parse.y"
{
- yygotominor.yy178 = sqlite3Expr(yymsp[-1].major, yymsp[0].minor.yy178, 0, 0);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy178->span);
+ yygotominor.yy450 = sqlite3Expr(TK_NOTNULL, yymsp[-2].minor.yy450, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy450,&yymsp[-2].minor.yy450->span,&yymsp[0].minor.yy0);
}
-#line 2656 "parse.c"
+#line 2721 "parse.c"
break;
case 208:
-#line 726 "parse.y"
+#line 715 "parse.y"
{
- yygotominor.yy178 = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy178, 0, 0);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy178->span);
+ yygotominor.yy450 = sqlite3Expr(TK_NOTNULL, yymsp[-3].minor.yy450, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy450,&yymsp[-3].minor.yy450->span,&yymsp[0].minor.yy0);
}
-#line 2664 "parse.c"
+#line 2729 "parse.c"
break;
case 209:
-#line 730 "parse.y"
+#line 719 "parse.y"
{
- yygotominor.yy178 = sqlite3Expr(TK_UPLUS, yymsp[0].minor.yy178, 0, 0);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy178->span);
+ yygotominor.yy450 = sqlite3Expr(yymsp[-1].major, yymsp[0].minor.yy450, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy450,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy450->span);
}
-#line 2672 "parse.c"
+#line 2737 "parse.c"
break;
- case 212:
-#line 737 "parse.y"
+ case 210:
+#line 723 "parse.y"
{
- ExprList *pList = sqlite3ExprListAppend(0, yymsp[-2].minor.yy178, 0);
- pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy178, 0);
- yygotominor.yy178 = sqlite3Expr(TK_BETWEEN, yymsp[-4].minor.yy178, 0, 0);
- if( yygotominor.yy178 ){
- yygotominor.yy178->pList = pList;
+ yygotominor.yy450 = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy450, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy450,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy450->span);
+}
+#line 2745 "parse.c"
+ break;
+ case 211:
+#line 727 "parse.y"
+{
+ yygotominor.yy450 = sqlite3Expr(TK_UPLUS, yymsp[0].minor.yy450, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy450,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy450->span);
+}
+#line 2753 "parse.c"
+ break;
+ case 214:
+#line 734 "parse.y"
+{
+ ExprList *pList = sqlite3ExprListAppend(0, yymsp[-2].minor.yy450, 0);
+ pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy450, 0);
+ yygotominor.yy450 = sqlite3Expr(TK_BETWEEN, yymsp[-4].minor.yy450, 0, 0);
+ if( yygotominor.yy450 ){
+ yygotominor.yy450->pList = pList;
}else{
sqlite3ExprListDelete(pList);
}
- if( yymsp[-3].minor.yy230 ) yygotominor.yy178 = sqlite3Expr(TK_NOT, yygotominor.yy178, 0, 0);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-4].minor.yy178->span,&yymsp[0].minor.yy178->span);
+ if( yymsp[-3].minor.yy316 ) yygotominor.yy450 = sqlite3Expr(TK_NOT, yygotominor.yy450, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy450,&yymsp[-4].minor.yy450->span,&yymsp[0].minor.yy450->span);
}
-#line 2688 "parse.c"
- break;
- case 215:
-#line 753 "parse.y"
-{
- yygotominor.yy178 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy178, 0, 0);
- if( yygotominor.yy178 ){
- yygotominor.yy178->pList = yymsp[-1].minor.yy462;
- }else{
- sqlite3ExprListDelete(yymsp[-1].minor.yy462);
- }
- if( yymsp[-3].minor.yy230 ) yygotominor.yy178 = sqlite3Expr(TK_NOT, yygotominor.yy178, 0, 0);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-4].minor.yy178->span,&yymsp[0].minor.yy0);
- }
-#line 2702 "parse.c"
- break;
- case 216:
-#line 763 "parse.y"
-{
- yygotominor.yy178 = sqlite3Expr(TK_SELECT, 0, 0, 0);
- if( yygotominor.yy178 ){
- yygotominor.yy178->pSelect = yymsp[-1].minor.yy239;
- }else{
- sqlite3SelectDelete(yymsp[-1].minor.yy239);
- }
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
- }
-#line 2715 "parse.c"
+#line 2769 "parse.c"
break;
case 217:
-#line 772 "parse.y"
+#line 750 "parse.y"
{
- yygotominor.yy178 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy178, 0, 0);
- if( yygotominor.yy178 ){
- yygotominor.yy178->pSelect = yymsp[-1].minor.yy239;
+ yygotominor.yy450 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy450, 0, 0);
+ if( yygotominor.yy450 ){
+ yygotominor.yy450->pList = yymsp[-1].minor.yy242;
}else{
- sqlite3SelectDelete(yymsp[-1].minor.yy239);
+ sqlite3ExprListDelete(yymsp[-1].minor.yy242);
}
- if( yymsp[-3].minor.yy230 ) yygotominor.yy178 = sqlite3Expr(TK_NOT, yygotominor.yy178, 0, 0);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-4].minor.yy178->span,&yymsp[0].minor.yy0);
+ if( yymsp[-3].minor.yy316 ) yygotominor.yy450 = sqlite3Expr(TK_NOT, yygotominor.yy450, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy450,&yymsp[-4].minor.yy450->span,&yymsp[0].minor.yy0);
}
-#line 2729 "parse.c"
+#line 2783 "parse.c"
break;
case 218:
-#line 782 "parse.y"
+#line 760 "parse.y"
{
- SrcList *pSrc = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy384,&yymsp[0].minor.yy384);
- yygotominor.yy178 = sqlite3Expr(TK_IN, yymsp[-3].minor.yy178, 0, 0);
- if( yygotominor.yy178 ){
- yygotominor.yy178->pSelect = sqlite3SelectNew(0,pSrc,0,0,0,0,0,0,0);
+ yygotominor.yy450 = sqlite3Expr(TK_SELECT, 0, 0, 0);
+ if( yygotominor.yy450 ){
+ yygotominor.yy450->pSelect = yymsp[-1].minor.yy43;
+ }else{
+ sqlite3SelectDelete(yymsp[-1].minor.yy43);
+ }
+ sqlite3ExprSpan(yygotominor.yy450,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
+ }
+#line 2796 "parse.c"
+ break;
+ case 219:
+#line 769 "parse.y"
+{
+ yygotominor.yy450 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy450, 0, 0);
+ if( yygotominor.yy450 ){
+ yygotominor.yy450->pSelect = yymsp[-1].minor.yy43;
+ }else{
+ sqlite3SelectDelete(yymsp[-1].minor.yy43);
+ }
+ if( yymsp[-3].minor.yy316 ) yygotominor.yy450 = sqlite3Expr(TK_NOT, yygotominor.yy450, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy450,&yymsp[-4].minor.yy450->span,&yymsp[0].minor.yy0);
+ }
+#line 2810 "parse.c"
+ break;
+ case 220:
+#line 779 "parse.y"
+{
+ SrcList *pSrc = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy178,&yymsp[0].minor.yy178);
+ yygotominor.yy450 = sqlite3Expr(TK_IN, yymsp[-3].minor.yy450, 0, 0);
+ if( yygotominor.yy450 ){
+ yygotominor.yy450->pSelect = sqlite3SelectNew(0,pSrc,0,0,0,0,0,0,0);
}else{
sqlite3SrcListDelete(pSrc);
}
- if( yymsp[-2].minor.yy230 ) yygotominor.yy178 = sqlite3Expr(TK_NOT, yygotominor.yy178, 0, 0);
- sqlite3ExprSpan(yygotominor.yy178,&yymsp[-3].minor.yy178->span,yymsp[0].minor.yy384.z?&yymsp[0].minor.yy384:&yymsp[-1].minor.yy384);
+ if( yymsp[-2].minor.yy316 ) yygotominor.yy450 = sqlite3Expr(TK_NOT, yygotominor.yy450, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy450,&yymsp[-3].minor.yy450->span,yymsp[0].minor.yy178.z?&yymsp[0].minor.yy178:&yymsp[-1].minor.yy178);
}
-#line 2744 "parse.c"
- break;
- case 219:
-#line 793 "parse.y"
-{
- Expr *p = yygotominor.yy178 = sqlite3Expr(TK_EXISTS, 0, 0, 0);
- if( p ){
- p->pSelect = yymsp[-1].minor.yy239;
- sqlite3ExprSpan(p,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
- }else{
- sqlite3SelectDelete(yymsp[-1].minor.yy239);
- }
- }
-#line 2757 "parse.c"
- break;
- case 220:
-#line 805 "parse.y"
-{
- yygotominor.yy178 = sqlite3Expr(TK_CASE, yymsp[-3].minor.yy178, yymsp[-1].minor.yy178, 0);
- if( yygotominor.yy178 ){
- yygotominor.yy178->pList = yymsp[-2].minor.yy462;
- }else{
- sqlite3ExprListDelete(yymsp[-2].minor.yy462);
- }
- sqlite3ExprSpan(yygotominor.yy178, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0);
-}
-#line 2770 "parse.c"
+#line 2825 "parse.c"
break;
case 221:
-#line 816 "parse.y"
+#line 790 "parse.y"
{
- yygotominor.yy462 = sqlite3ExprListAppend(yymsp[-4].minor.yy462, yymsp[-2].minor.yy178, 0);
- yygotominor.yy462 = sqlite3ExprListAppend(yygotominor.yy462, yymsp[0].minor.yy178, 0);
-}
-#line 2778 "parse.c"
+ Expr *p = yygotominor.yy450 = sqlite3Expr(TK_EXISTS, 0, 0, 0);
+ if( p ){
+ p->pSelect = yymsp[-1].minor.yy43;
+ sqlite3ExprSpan(p,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
+ }else{
+ sqlite3SelectDelete(yymsp[-1].minor.yy43);
+ }
+ }
+#line 2838 "parse.c"
break;
case 222:
-#line 820 "parse.y"
+#line 802 "parse.y"
{
- yygotominor.yy462 = sqlite3ExprListAppend(0, yymsp[-2].minor.yy178, 0);
- yygotominor.yy462 = sqlite3ExprListAppend(yygotominor.yy462, yymsp[0].minor.yy178, 0);
+ yygotominor.yy450 = sqlite3Expr(TK_CASE, yymsp[-3].minor.yy450, yymsp[-1].minor.yy450, 0);
+ if( yygotominor.yy450 ){
+ yygotominor.yy450->pList = yymsp[-2].minor.yy242;
+ }else{
+ sqlite3ExprListDelete(yymsp[-2].minor.yy242);
+ }
+ sqlite3ExprSpan(yygotominor.yy450, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0);
}
-#line 2786 "parse.c"
+#line 2851 "parse.c"
break;
- case 231:
-#line 847 "parse.y"
+ case 223:
+#line 813 "parse.y"
{
- sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy384, &yymsp[-5].minor.yy384, sqlite3SrcListAppend(0,&yymsp[-3].minor.yy384,0), yymsp[-1].minor.yy462, yymsp[-9].minor.yy230,
- &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy230);
+ yygotominor.yy242 = sqlite3ExprListAppend(yymsp[-4].minor.yy242, yymsp[-2].minor.yy450, 0);
+ yygotominor.yy242 = sqlite3ExprListAppend(yygotominor.yy242, yymsp[0].minor.yy450, 0);
}
-#line 2794 "parse.c"
+#line 2859 "parse.c"
break;
- case 232:
- case 277:
-#line 853 "parse.y"
-{yygotominor.yy230 = OE_Abort;}
-#line 2800 "parse.c"
+ case 224:
+#line 817 "parse.y"
+{
+ yygotominor.yy242 = sqlite3ExprListAppend(0, yymsp[-2].minor.yy450, 0);
+ yygotominor.yy242 = sqlite3ExprListAppend(yygotominor.yy242, yymsp[0].minor.yy450, 0);
+}
+#line 2867 "parse.c"
break;
case 233:
-#line 854 "parse.y"
-{yygotominor.yy230 = OE_None;}
-#line 2805 "parse.c"
+#line 844 "parse.y"
+{
+ sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy178, &yymsp[-5].minor.yy178, sqlite3SrcListAppend(0,&yymsp[-3].minor.yy178,0), yymsp[-1].minor.yy242, yymsp[-9].minor.yy316,
+ &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy316);
+}
+#line 2875 "parse.c"
break;
- case 236:
-#line 864 "parse.y"
+ case 234:
+ case 282:
+#line 850 "parse.y"
+{yygotominor.yy316 = OE_Abort;}
+#line 2881 "parse.c"
+ break;
+ case 235:
+#line 851 "parse.y"
+{yygotominor.yy316 = OE_None;}
+#line 2886 "parse.c"
+ break;
+ case 238:
+#line 861 "parse.y"
{
Expr *p = 0;
- if( yymsp[-1].minor.yy384.n>0 ){
+ if( yymsp[-1].minor.yy178.n>0 ){
p = sqlite3Expr(TK_COLUMN, 0, 0, 0);
- if( p ) p->pColl = sqlite3LocateCollSeq(pParse, (char*)yymsp[-1].minor.yy384.z, yymsp[-1].minor.yy384.n);
+ if( p ) p->pColl = sqlite3LocateCollSeq(pParse, (char*)yymsp[-1].minor.yy178.z, yymsp[-1].minor.yy178.n);
}
- yygotominor.yy462 = sqlite3ExprListAppend(yymsp[-4].minor.yy462, p, &yymsp[-2].minor.yy384);
- if( yygotominor.yy462 ) yygotominor.yy462->a[yygotominor.yy462->nExpr-1].sortOrder = yymsp[0].minor.yy230;
+ yygotominor.yy242 = sqlite3ExprListAppend(yymsp[-4].minor.yy242, p, &yymsp[-2].minor.yy178);
+ if( yygotominor.yy242 ) yygotominor.yy242->a[yygotominor.yy242->nExpr-1].sortOrder = yymsp[0].minor.yy316;
}
-#line 2818 "parse.c"
- break;
- case 237:
-#line 873 "parse.y"
-{
- Expr *p = 0;
- if( yymsp[-1].minor.yy384.n>0 ){
- p = sqlite3Expr(TK_COLUMN, 0, 0, 0);
- if( p ) p->pColl = sqlite3LocateCollSeq(pParse, (char*)yymsp[-1].minor.yy384.z, yymsp[-1].minor.yy384.n);
- }
- yygotominor.yy462 = sqlite3ExprListAppend(0, p, &yymsp[-2].minor.yy384);
- if( yygotominor.yy462 ) yygotominor.yy462->a[yygotominor.yy462->nExpr-1].sortOrder = yymsp[0].minor.yy230;
-}
-#line 2831 "parse.c"
- break;
- case 239:
-#line 887 "parse.y"
-{sqlite3DropIndex(pParse, yymsp[0].minor.yy285, yymsp[-1].minor.yy230);}
-#line 2836 "parse.c"
- break;
- case 240:
- case 241:
-#line 891 "parse.y"
-{sqlite3Vacuum(pParse);}
-#line 2842 "parse.c"
- break;
- case 242:
- case 244:
-#line 897 "parse.y"
-{sqlite3Pragma(pParse,&yymsp[-3].minor.yy384,&yymsp[-2].minor.yy384,&yymsp[0].minor.yy384,0);}
-#line 2848 "parse.c"
- break;
- case 243:
-#line 898 "parse.y"
-{sqlite3Pragma(pParse,&yymsp[-3].minor.yy384,&yymsp[-2].minor.yy384,&yymsp[0].minor.yy0,0);}
-#line 2853 "parse.c"
- break;
- case 245:
-#line 900 "parse.y"
-{
- sqlite3Pragma(pParse,&yymsp[-3].minor.yy384,&yymsp[-2].minor.yy384,&yymsp[0].minor.yy384,1);
-}
-#line 2860 "parse.c"
- break;
- case 246:
-#line 903 "parse.y"
-{sqlite3Pragma(pParse,&yymsp[-4].minor.yy384,&yymsp[-3].minor.yy384,&yymsp[-1].minor.yy384,0);}
-#line 2865 "parse.c"
- break;
- case 247:
-#line 904 "parse.y"
-{sqlite3Pragma(pParse,&yymsp[-1].minor.yy384,&yymsp[0].minor.yy384,0,0);}
-#line 2870 "parse.c"
- break;
- case 253:
-#line 916 "parse.y"
-{
- Token all;
- all.z = yymsp[-3].minor.yy384.z;
- all.n = (yymsp[0].minor.yy0.z - yymsp[-3].minor.yy384.z) + yymsp[0].minor.yy0.n;
- sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy247, &all);
-}
-#line 2880 "parse.c"
- break;
- case 254:
-#line 925 "parse.y"
-{
- sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy384, &yymsp[-6].minor.yy384, yymsp[-5].minor.yy230, yymsp[-4].minor.yy132.a, yymsp[-4].minor.yy132.b, yymsp[-2].minor.yy285, yymsp[-1].minor.yy230, yymsp[0].minor.yy178, yymsp[-9].minor.yy230);
- yygotominor.yy384 = (yymsp[-6].minor.yy384.n==0?yymsp[-7].minor.yy384:yymsp[-6].minor.yy384);
-}
-#line 2888 "parse.c"
- break;
- case 255:
- case 258:
-#line 931 "parse.y"
-{ yygotominor.yy230 = TK_BEFORE; }
-#line 2894 "parse.c"
- break;
- case 256:
-#line 932 "parse.y"
-{ yygotominor.yy230 = TK_AFTER; }
#line 2899 "parse.c"
break;
- case 257:
-#line 933 "parse.y"
-{ yygotominor.yy230 = TK_INSTEAD;}
-#line 2904 "parse.c"
+ case 239:
+#line 870 "parse.y"
+{
+ Expr *p = 0;
+ if( yymsp[-1].minor.yy178.n>0 ){
+ p = sqlite3Expr(TK_COLUMN, 0, 0, 0);
+ if( p ) p->pColl = sqlite3LocateCollSeq(pParse, (char*)yymsp[-1].minor.yy178.z, yymsp[-1].minor.yy178.n);
+ }
+ yygotominor.yy242 = sqlite3ExprListAppend(0, p, &yymsp[-2].minor.yy178);
+ if( yygotominor.yy242 ) yygotominor.yy242->a[yygotominor.yy242->nExpr-1].sortOrder = yymsp[0].minor.yy316;
+}
+#line 2912 "parse.c"
+ break;
+ case 241:
+#line 882 "parse.y"
+{yygotominor.yy178.z = 0; yygotominor.yy178.n = 0;}
+#line 2917 "parse.c"
+ break;
+ case 243:
+#line 888 "parse.y"
+{sqlite3DropIndex(pParse, yymsp[0].minor.yy419, yymsp[-1].minor.yy316);}
+#line 2922 "parse.c"
+ break;
+ case 244:
+ case 245:
+#line 893 "parse.y"
+{sqlite3Vacuum(pParse);}
+#line 2928 "parse.c"
+ break;
+ case 246:
+#line 900 "parse.y"
+{sqlite3Pragma(pParse,&yymsp[-3].minor.yy178,&yymsp[-2].minor.yy178,&yymsp[0].minor.yy178,0);}
+#line 2933 "parse.c"
+ break;
+ case 247:
+#line 901 "parse.y"
+{sqlite3Pragma(pParse,&yymsp[-3].minor.yy178,&yymsp[-2].minor.yy178,&yymsp[0].minor.yy0,0);}
+#line 2938 "parse.c"
+ break;
+ case 248:
+#line 902 "parse.y"
+{
+ sqlite3Pragma(pParse,&yymsp[-3].minor.yy178,&yymsp[-2].minor.yy178,&yymsp[0].minor.yy178,1);
+}
+#line 2945 "parse.c"
+ break;
+ case 249:
+#line 905 "parse.y"
+{sqlite3Pragma(pParse,&yymsp[-4].minor.yy178,&yymsp[-3].minor.yy178,&yymsp[-1].minor.yy178,0);}
+#line 2950 "parse.c"
+ break;
+ case 250:
+#line 906 "parse.y"
+{sqlite3Pragma(pParse,&yymsp[-1].minor.yy178,&yymsp[0].minor.yy178,0,0);}
+#line 2955 "parse.c"
+ break;
+ case 258:
+#line 920 "parse.y"
+{
+ Token all;
+ all.z = yymsp[-3].minor.yy178.z;
+ all.n = (yymsp[0].minor.yy0.z - yymsp[-3].minor.yy178.z) + yymsp[0].minor.yy0.n;
+ sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy75, &all);
+}
+#line 2965 "parse.c"
break;
case 259:
- case 260:
-#line 938 "parse.y"
-{yygotominor.yy132.a = yymsp[0].major; yygotominor.yy132.b = 0;}
-#line 2910 "parse.c"
- break;
- case 261:
-#line 940 "parse.y"
-{yygotominor.yy132.a = TK_UPDATE; yygotominor.yy132.b = yymsp[0].minor.yy160;}
-#line 2915 "parse.c"
- break;
- case 262:
- case 263:
-#line 943 "parse.y"
-{ yygotominor.yy230 = TK_ROW; }
-#line 2921 "parse.c"
- break;
- case 264:
-#line 945 "parse.y"
-{ yygotominor.yy230 = TK_STATEMENT; }
-#line 2926 "parse.c"
- break;
- case 265:
-#line 949 "parse.y"
-{ yygotominor.yy178 = 0; }
-#line 2931 "parse.c"
- break;
- case 266:
-#line 950 "parse.y"
-{ yygotominor.yy178 = yymsp[0].minor.yy178; }
-#line 2936 "parse.c"
- break;
- case 267:
-#line 954 "parse.y"
+#line 929 "parse.y"
{
- if( yymsp[-2].minor.yy247 ){
- yymsp[-2].minor.yy247->pLast->pNext = yymsp[-1].minor.yy247;
- }else{
- yymsp[-2].minor.yy247 = yymsp[-1].minor.yy247;
- }
- yymsp[-2].minor.yy247->pLast = yymsp[-1].minor.yy247;
- yygotominor.yy247 = yymsp[-2].minor.yy247;
+ sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy178, &yymsp[-6].minor.yy178, yymsp[-5].minor.yy316, yymsp[-4].minor.yy354.a, yymsp[-4].minor.yy354.b, yymsp[-2].minor.yy419, yymsp[-1].minor.yy316, yymsp[0].minor.yy450, yymsp[-10].minor.yy316, yymsp[-8].minor.yy316);
+ yygotominor.yy178 = (yymsp[-6].minor.yy178.n==0?yymsp[-7].minor.yy178:yymsp[-6].minor.yy178);
}
-#line 2949 "parse.c"
+#line 2973 "parse.c"
break;
- case 268:
-#line 963 "parse.y"
-{ yygotominor.yy247 = 0; }
-#line 2954 "parse.c"
- break;
- case 269:
-#line 969 "parse.y"
-{ yygotominor.yy247 = sqlite3TriggerUpdateStep(&yymsp[-3].minor.yy384, yymsp[-1].minor.yy462, yymsp[0].minor.yy178, yymsp[-4].minor.yy230); }
-#line 2959 "parse.c"
- break;
- case 270:
-#line 974 "parse.y"
-{yygotominor.yy247 = sqlite3TriggerInsertStep(&yymsp[-5].minor.yy384, yymsp[-4].minor.yy160, yymsp[-1].minor.yy462, 0, yymsp[-7].minor.yy230);}
-#line 2964 "parse.c"
- break;
- case 271:
-#line 977 "parse.y"
-{yygotominor.yy247 = sqlite3TriggerInsertStep(&yymsp[-2].minor.yy384, yymsp[-1].minor.yy160, 0, yymsp[0].minor.yy239, yymsp[-4].minor.yy230);}
-#line 2969 "parse.c"
- break;
- case 272:
-#line 981 "parse.y"
-{yygotominor.yy247 = sqlite3TriggerDeleteStep(&yymsp[-1].minor.yy384, yymsp[0].minor.yy178);}
-#line 2974 "parse.c"
- break;
- case 273:
-#line 984 "parse.y"
-{yygotominor.yy247 = sqlite3TriggerSelectStep(yymsp[0].minor.yy239); }
+ case 260:
+ case 263:
+#line 935 "parse.y"
+{ yygotominor.yy316 = TK_BEFORE; }
#line 2979 "parse.c"
break;
- case 274:
-#line 987 "parse.y"
-{
- yygotominor.yy178 = sqlite3Expr(TK_RAISE, 0, 0, 0);
- if( yygotominor.yy178 ){
- yygotominor.yy178->iColumn = OE_Ignore;
- sqlite3ExprSpan(yygotominor.yy178, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0);
- }
-}
-#line 2990 "parse.c"
+ case 261:
+#line 936 "parse.y"
+{ yygotominor.yy316 = TK_AFTER; }
+#line 2984 "parse.c"
break;
- case 275:
-#line 994 "parse.y"
-{
- yygotominor.yy178 = sqlite3Expr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy384);
- if( yygotominor.yy178 ) {
- yygotominor.yy178->iColumn = yymsp[-3].minor.yy230;
- sqlite3ExprSpan(yygotominor.yy178, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
- }
-}
-#line 3001 "parse.c"
+ case 262:
+#line 937 "parse.y"
+{ yygotominor.yy316 = TK_INSTEAD;}
+#line 2989 "parse.c"
break;
- case 276:
-#line 1004 "parse.y"
-{yygotominor.yy230 = OE_Rollback;}
+ case 264:
+ case 265:
+#line 942 "parse.y"
+{yygotominor.yy354.a = yymsp[0].major; yygotominor.yy354.b = 0;}
+#line 2995 "parse.c"
+ break;
+ case 266:
+#line 944 "parse.y"
+{yygotominor.yy354.a = TK_UPDATE; yygotominor.yy354.b = yymsp[0].minor.yy352;}
+#line 3000 "parse.c"
+ break;
+ case 267:
+ case 268:
+#line 947 "parse.y"
+{ yygotominor.yy316 = TK_ROW; }
#line 3006 "parse.c"
break;
- case 278:
-#line 1006 "parse.y"
-{yygotominor.yy230 = OE_Fail;}
+ case 269:
+#line 949 "parse.y"
+{ yygotominor.yy316 = TK_STATEMENT; }
#line 3011 "parse.c"
break;
- case 279:
-#line 1011 "parse.y"
+ case 270:
+#line 953 "parse.y"
+{ yygotominor.yy450 = 0; }
+#line 3016 "parse.c"
+ break;
+ case 271:
+#line 954 "parse.y"
+{ yygotominor.yy450 = yymsp[0].minor.yy450; }
+#line 3021 "parse.c"
+ break;
+ case 272:
+#line 958 "parse.y"
{
- sqlite3DropTrigger(pParse,yymsp[0].minor.yy285);
+ if( yymsp[-2].minor.yy75 ){
+ yymsp[-2].minor.yy75->pLast->pNext = yymsp[-1].minor.yy75;
+ }else{
+ yymsp[-2].minor.yy75 = yymsp[-1].minor.yy75;
+ }
+ yymsp[-2].minor.yy75->pLast = yymsp[-1].minor.yy75;
+ yygotominor.yy75 = yymsp[-2].minor.yy75;
}
-#line 3018 "parse.c"
+#line 3034 "parse.c"
+ break;
+ case 273:
+#line 967 "parse.y"
+{ yygotominor.yy75 = 0; }
+#line 3039 "parse.c"
+ break;
+ case 274:
+#line 973 "parse.y"
+{ yygotominor.yy75 = sqlite3TriggerUpdateStep(&yymsp[-3].minor.yy178, yymsp[-1].minor.yy242, yymsp[0].minor.yy450, yymsp[-4].minor.yy316); }
+#line 3044 "parse.c"
+ break;
+ case 275:
+#line 978 "parse.y"
+{yygotominor.yy75 = sqlite3TriggerInsertStep(&yymsp[-5].minor.yy178, yymsp[-4].minor.yy352, yymsp[-1].minor.yy242, 0, yymsp[-7].minor.yy316);}
+#line 3049 "parse.c"
+ break;
+ case 276:
+#line 981 "parse.y"
+{yygotominor.yy75 = sqlite3TriggerInsertStep(&yymsp[-2].minor.yy178, yymsp[-1].minor.yy352, 0, yymsp[0].minor.yy43, yymsp[-4].minor.yy316);}
+#line 3054 "parse.c"
+ break;
+ case 277:
+#line 985 "parse.y"
+{yygotominor.yy75 = sqlite3TriggerDeleteStep(&yymsp[-1].minor.yy178, yymsp[0].minor.yy450);}
+#line 3059 "parse.c"
+ break;
+ case 278:
+#line 988 "parse.y"
+{yygotominor.yy75 = sqlite3TriggerSelectStep(yymsp[0].minor.yy43); }
+#line 3064 "parse.c"
+ break;
+ case 279:
+#line 991 "parse.y"
+{
+ yygotominor.yy450 = sqlite3Expr(TK_RAISE, 0, 0, 0);
+ if( yygotominor.yy450 ){
+ yygotominor.yy450->iColumn = OE_Ignore;
+ sqlite3ExprSpan(yygotominor.yy450, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0);
+ }
+}
+#line 3075 "parse.c"
break;
case 280:
-#line 1017 "parse.y"
+#line 998 "parse.y"
{
- sqlite3Attach(pParse, yymsp[-3].minor.yy178, yymsp[-1].minor.yy178, yymsp[0].minor.yy292);
+ yygotominor.yy450 = sqlite3Expr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy178);
+ if( yygotominor.yy450 ) {
+ yygotominor.yy450->iColumn = yymsp[-3].minor.yy316;
+ sqlite3ExprSpan(yygotominor.yy450, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
+ }
}
-#line 3025 "parse.c"
+#line 3086 "parse.c"
break;
case 281:
-#line 1022 "parse.y"
-{ yygotominor.yy292 = 0; }
-#line 3030 "parse.c"
+#line 1008 "parse.y"
+{yygotominor.yy316 = OE_Rollback;}
+#line 3091 "parse.c"
break;
- case 282:
-#line 1023 "parse.y"
-{ yygotominor.yy292 = yymsp[0].minor.yy178; }
-#line 3035 "parse.c"
+ case 283:
+#line 1010 "parse.y"
+{yygotominor.yy316 = OE_Fail;}
+#line 3096 "parse.c"
+ break;
+ case 284:
+#line 1015 "parse.y"
+{
+ sqlite3DropTrigger(pParse,yymsp[0].minor.yy419,yymsp[-1].minor.yy316);
+}
+#line 3103 "parse.c"
break;
case 285:
-#line 1029 "parse.y"
+#line 1021 "parse.y"
{
- sqlite3Detach(pParse, yymsp[0].minor.yy178);
+ sqlite3Attach(pParse, yymsp[-3].minor.yy450, yymsp[-1].minor.yy450, yymsp[0].minor.yy158);
}
-#line 3042 "parse.c"
+#line 3110 "parse.c"
break;
case 286:
-#line 1035 "parse.y"
-{sqlite3Reindex(pParse, 0, 0);}
-#line 3047 "parse.c"
+#line 1026 "parse.y"
+{ yygotominor.yy158 = 0; }
+#line 3115 "parse.c"
break;
case 287:
-#line 1036 "parse.y"
-{sqlite3Reindex(pParse, &yymsp[-1].minor.yy384, &yymsp[0].minor.yy384);}
-#line 3052 "parse.c"
- break;
- case 288:
-#line 1041 "parse.y"
-{sqlite3Analyze(pParse, 0, 0);}
-#line 3057 "parse.c"
- break;
- case 289:
-#line 1042 "parse.y"
-{sqlite3Analyze(pParse, &yymsp[-1].minor.yy384, &yymsp[0].minor.yy384);}
-#line 3062 "parse.c"
+#line 1027 "parse.y"
+{ yygotominor.yy158 = yymsp[0].minor.yy450; }
+#line 3120 "parse.c"
break;
case 290:
-#line 1047 "parse.y"
+#line 1033 "parse.y"
{
- sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy285,&yymsp[0].minor.yy384);
+ sqlite3Detach(pParse, yymsp[0].minor.yy450);
}
-#line 3069 "parse.c"
+#line 3127 "parse.c"
break;
case 291:
-#line 1050 "parse.y"
-{
- sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy384);
-}
-#line 3076 "parse.c"
+#line 1039 "parse.y"
+{sqlite3Reindex(pParse, 0, 0);}
+#line 3132 "parse.c"
break;
case 292:
-#line 1053 "parse.y"
+#line 1040 "parse.y"
+{sqlite3Reindex(pParse, &yymsp[-1].minor.yy178, &yymsp[0].minor.yy178);}
+#line 3137 "parse.c"
+ break;
+ case 293:
+#line 1045 "parse.y"
+{sqlite3Analyze(pParse, 0, 0);}
+#line 3142 "parse.c"
+ break;
+ case 294:
+#line 1046 "parse.y"
+{sqlite3Analyze(pParse, &yymsp[-1].minor.yy178, &yymsp[0].minor.yy178);}
+#line 3147 "parse.c"
+ break;
+ case 295:
+#line 1051 "parse.y"
{
- sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy285);
+ sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy419,&yymsp[0].minor.yy178);
}
-#line 3083 "parse.c"
+#line 3154 "parse.c"
+ break;
+ case 296:
+#line 1054 "parse.y"
+{
+ sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy178);
+}
+#line 3161 "parse.c"
+ break;
+ case 297:
+#line 1057 "parse.y"
+{
+ sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy419);
+}
+#line 3168 "parse.c"
+ break;
+ case 300:
+#line 1066 "parse.y"
+{sqlite3VtabFinishParse(pParse,0);}
+#line 3173 "parse.c"
+ break;
+ case 301:
+#line 1067 "parse.y"
+{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);}
+#line 3178 "parse.c"
+ break;
+ case 302:
+#line 1068 "parse.y"
+{
+ sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy178, &yymsp[-2].minor.yy178, &yymsp[0].minor.yy178);
+}
+#line 3185 "parse.c"
+ break;
+ case 305:
+#line 1073 "parse.y"
+{sqlite3VtabArgInit(pParse);}
+#line 3190 "parse.c"
+ break;
+ case 307:
+ case 308:
+ case 309:
+ case 311:
+#line 1075 "parse.y"
+{sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
+#line 3198 "parse.c"
break;
};
yygoto = yyRuleInfo[yyruleno].lhs;
@@ -3136,14 +3251,15 @@ static void yy_syntax_error(
#define TOKEN (yyminor.yy0)
#line 34 "parse.y"
- if( pParse->zErrMsg==0 ){
+ if( !pParse->parseError ){
if( TOKEN.z[0] ){
sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN);
}else{
sqlite3ErrorMsg(pParse, "incomplete SQL statement");
}
+ pParse->parseError = 1;
}
-#line 3150 "parse.c"
+#line 3266 "parse.c"
sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */
}
@@ -3271,7 +3387,9 @@ void sqlite3Parser(
while(
yypParser->yyidx >= 0 &&
yymx != YYERRORSYMBOL &&
- (yyact = yy_find_shift_action(yypParser,YYERRORSYMBOL)) >= YYNSTATE
+ (yyact = yy_find_reduce_action(
+ yypParser->yystack[yypParser->yyidx].stateno,
+ YYERRORSYMBOL)) >= YYNSTATE
){
yy_pop_parser_stack(yypParser);
}
diff --git a/dlls/sqlite/sqlite-source/parse.h b/dlls/sqlite/sqlite-source/parse.h
index 116e7f5b..3a71be19 100644
--- a/dlls/sqlite/sqlite-source/parse.h
+++ b/dlls/sqlite/sqlite-source/parse.h
@@ -53,99 +53,101 @@
#define TK_TRIGGER 53
#define TK_VACUUM 54
#define TK_VIEW 55
-#define TK_REINDEX 56
-#define TK_RENAME 57
-#define TK_CTIME_KW 58
-#define TK_OR 59
-#define TK_AND 60
-#define TK_IS 61
-#define TK_BETWEEN 62
-#define TK_IN 63
-#define TK_ISNULL 64
-#define TK_NOTNULL 65
-#define TK_NE 66
-#define TK_EQ 67
-#define TK_GT 68
-#define TK_LE 69
-#define TK_LT 70
-#define TK_GE 71
-#define TK_ESCAPE 72
-#define TK_BITAND 73
-#define TK_BITOR 74
-#define TK_LSHIFT 75
-#define TK_RSHIFT 76
-#define TK_PLUS 77
-#define TK_MINUS 78
-#define TK_STAR 79
-#define TK_SLASH 80
-#define TK_REM 81
-#define TK_CONCAT 82
-#define TK_UMINUS 83
-#define TK_UPLUS 84
-#define TK_BITNOT 85
-#define TK_STRING 86
-#define TK_JOIN_KW 87
-#define TK_CONSTRAINT 88
-#define TK_DEFAULT 89
-#define TK_NULL 90
-#define TK_PRIMARY 91
-#define TK_UNIQUE 92
-#define TK_CHECK 93
-#define TK_REFERENCES 94
-#define TK_COLLATE 95
-#define TK_AUTOINCR 96
-#define TK_ON 97
-#define TK_DELETE 98
-#define TK_UPDATE 99
-#define TK_INSERT 100
-#define TK_SET 101
-#define TK_DEFERRABLE 102
-#define TK_FOREIGN 103
-#define TK_DROP 104
-#define TK_UNION 105
-#define TK_ALL 106
-#define TK_EXCEPT 107
-#define TK_INTERSECT 108
-#define TK_SELECT 109
-#define TK_DISTINCT 110
-#define TK_DOT 111
-#define TK_FROM 112
-#define TK_JOIN 113
-#define TK_USING 114
-#define TK_ORDER 115
-#define TK_BY 116
-#define TK_GROUP 117
-#define TK_HAVING 118
-#define TK_LIMIT 119
-#define TK_WHERE 120
-#define TK_INTO 121
-#define TK_VALUES 122
-#define TK_INTEGER 123
-#define TK_FLOAT 124
-#define TK_BLOB 125
-#define TK_REGISTER 126
-#define TK_VARIABLE 127
-#define TK_CASE 128
-#define TK_WHEN 129
-#define TK_THEN 130
-#define TK_ELSE 131
-#define TK_INDEX 132
-#define TK_ALTER 133
-#define TK_TO 134
-#define TK_ADD 135
-#define TK_COLUMNKW 136
-#define TK_TO_TEXT 137
-#define TK_TO_BLOB 138
-#define TK_TO_NUMERIC 139
-#define TK_TO_INT 140
-#define TK_TO_REAL 141
-#define TK_END_OF_FILE 142
-#define TK_ILLEGAL 143
-#define TK_SPACE 144
-#define TK_UNCLOSED_STRING 145
-#define TK_COMMENT 146
-#define TK_FUNCTION 147
-#define TK_COLUMN 148
-#define TK_AGG_FUNCTION 149
-#define TK_AGG_COLUMN 150
-#define TK_CONST_FUNC 151
+#define TK_VIRTUAL 56
+#define TK_REINDEX 57
+#define TK_RENAME 58
+#define TK_CTIME_KW 59
+#define TK_ANY 60
+#define TK_OR 61
+#define TK_AND 62
+#define TK_IS 63
+#define TK_BETWEEN 64
+#define TK_IN 65
+#define TK_ISNULL 66
+#define TK_NOTNULL 67
+#define TK_NE 68
+#define TK_EQ 69
+#define TK_GT 70
+#define TK_LE 71
+#define TK_LT 72
+#define TK_GE 73
+#define TK_ESCAPE 74
+#define TK_BITAND 75
+#define TK_BITOR 76
+#define TK_LSHIFT 77
+#define TK_RSHIFT 78
+#define TK_PLUS 79
+#define TK_MINUS 80
+#define TK_STAR 81
+#define TK_SLASH 82
+#define TK_REM 83
+#define TK_CONCAT 84
+#define TK_COLLATE 85
+#define TK_UMINUS 86
+#define TK_UPLUS 87
+#define TK_BITNOT 88
+#define TK_STRING 89
+#define TK_JOIN_KW 90
+#define TK_CONSTRAINT 91
+#define TK_DEFAULT 92
+#define TK_NULL 93
+#define TK_PRIMARY 94
+#define TK_UNIQUE 95
+#define TK_CHECK 96
+#define TK_REFERENCES 97
+#define TK_AUTOINCR 98
+#define TK_ON 99
+#define TK_DELETE 100
+#define TK_UPDATE 101
+#define TK_INSERT 102
+#define TK_SET 103
+#define TK_DEFERRABLE 104
+#define TK_FOREIGN 105
+#define TK_DROP 106
+#define TK_UNION 107
+#define TK_ALL 108
+#define TK_EXCEPT 109
+#define TK_INTERSECT 110
+#define TK_SELECT 111
+#define TK_DISTINCT 112
+#define TK_DOT 113
+#define TK_FROM 114
+#define TK_JOIN 115
+#define TK_USING 116
+#define TK_ORDER 117
+#define TK_BY 118
+#define TK_GROUP 119
+#define TK_HAVING 120
+#define TK_LIMIT 121
+#define TK_WHERE 122
+#define TK_INTO 123
+#define TK_VALUES 124
+#define TK_INTEGER 125
+#define TK_FLOAT 126
+#define TK_BLOB 127
+#define TK_REGISTER 128
+#define TK_VARIABLE 129
+#define TK_CASE 130
+#define TK_WHEN 131
+#define TK_THEN 132
+#define TK_ELSE 133
+#define TK_INDEX 134
+#define TK_ALTER 135
+#define TK_TO 136
+#define TK_ADD 137
+#define TK_COLUMNKW 138
+#define TK_TO_TEXT 139
+#define TK_TO_BLOB 140
+#define TK_TO_NUMERIC 141
+#define TK_TO_INT 142
+#define TK_TO_REAL 143
+#define TK_END_OF_FILE 144
+#define TK_ILLEGAL 145
+#define TK_SPACE 146
+#define TK_UNCLOSED_STRING 147
+#define TK_COMMENT 148
+#define TK_FUNCTION 149
+#define TK_COLUMN 150
+#define TK_AGG_FUNCTION 151
+#define TK_AGG_COLUMN 152
+#define TK_CONST_FUNC 153
diff --git a/dlls/sqlite/sqlite-source/pragma.c b/dlls/sqlite/sqlite-source/pragma.c
index fd114909..b1c5954d 100644
--- a/dlls/sqlite/sqlite-source/pragma.c
+++ b/dlls/sqlite/sqlite-source/pragma.c
@@ -482,12 +482,17 @@ void sqlite3Pragma(
sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "pk", P3_STATIC);
sqlite3ViewGetColumnNames(pParse, pTab);
for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){
+ const Token *pDflt;
sqlite3VdbeAddOp(v, OP_Integer, i, 0);
sqlite3VdbeOp3(v, OP_String8, 0, 0, pCol->zName, 0);
sqlite3VdbeOp3(v, OP_String8, 0, 0,
pCol->zType ? pCol->zType : "", 0);
sqlite3VdbeAddOp(v, OP_Integer, pCol->notNull, 0);
- sqlite3ExprCode(pParse, pCol->pDflt);
+ if( pCol->pDflt && (pDflt = &pCol->pDflt->span)->z ){
+ sqlite3VdbeOp3(v, OP_String8, 0, 0, (char*)pDflt->z, pDflt->n);
+ }else{
+ sqlite3VdbeAddOp(v, OP_Null, 0, 0);
+ }
sqlite3VdbeAddOp(v, OP_Integer, pCol->isPrimKey, 0);
sqlite3VdbeAddOp(v, OP_Callback, 6, 0);
}
@@ -635,9 +640,13 @@ void sqlite3Pragma(
}
}else
+#ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX
+# define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100
+#endif
+
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
if( sqlite3StrICmp(zLeft, "integrity_check")==0 ){
- int i, j, addr;
+ int i, j, addr, mxErr;
/* Code that appears at the end of the integrity check. If no error
** messages have been generated, output OK. Otherwise output the
@@ -655,7 +664,16 @@ void sqlite3Pragma(
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", P3_STATIC);
- sqlite3VdbeAddOp(v, OP_MemInt, 0, 0); /* Initialize error count to 0 */
+
+ /* Set the maximum error count */
+ mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
+ if( zRight ){
+ mxErr = atoi(zRight);
+ if( mxErr<=0 ){
+ mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
+ }
+ }
+ sqlite3VdbeAddOp(v, OP_MemInt, mxErr, 0);
/* Do an integrity check on each database file */
for(i=0; inDb; i++){
@@ -666,6 +684,9 @@ void sqlite3Pragma(
if( OMIT_TEMPDB && i==1 ) continue;
sqlite3CodeVerifySchema(pParse, i);
+ addr = sqlite3VdbeAddOp(v, OP_IfMemPos, 0, 0);
+ sqlite3VdbeAddOp(v, OP_Halt, 0, 0);
+ sqlite3VdbeJumpHere(v, addr);
/* Do an integrity check of the B-Tree
*/
@@ -680,28 +701,28 @@ void sqlite3Pragma(
cnt++;
}
}
- assert( cnt>0 );
- sqlite3VdbeAddOp(v, OP_IntegrityCk, cnt, i);
- sqlite3VdbeAddOp(v, OP_Dup, 0, 1);
- addr = sqlite3VdbeOp3(v, OP_String8, 0, 0, "ok", P3_STATIC);
- sqlite3VdbeAddOp(v, OP_Eq, 0, addr+7);
+ if( cnt==0 ) continue;
+ sqlite3VdbeAddOp(v, OP_IntegrityCk, 0, i);
+ addr = sqlite3VdbeAddOp(v, OP_IsNull, -1, 0);
sqlite3VdbeOp3(v, OP_String8, 0, 0,
sqlite3MPrintf("*** in database %s ***\n", db->aDb[i].zName),
P3_DYNAMIC);
sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
- sqlite3VdbeAddOp(v, OP_Concat, 0, 1);
+ sqlite3VdbeAddOp(v, OP_Concat, 0, 0);
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
- sqlite3VdbeAddOp(v, OP_MemIncr, 1, 0);
+ sqlite3VdbeJumpHere(v, addr);
/* Make sure all the indices are constructed correctly.
*/
- sqlite3CodeVerifySchema(pParse, i);
for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
Table *pTab = sqliteHashData(x);
Index *pIdx;
int loopTop;
if( pTab->pIndex==0 ) continue;
+ addr = sqlite3VdbeAddOp(v, OP_IfMemPos, 0, 0);
+ sqlite3VdbeAddOp(v, OP_Halt, 0, 0);
+ sqlite3VdbeJumpHere(v, addr);
sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead);
sqlite3VdbeAddOp(v, OP_MemInt, 0, 1);
loopTop = sqlite3VdbeAddOp(v, OP_Rewind, 1, 0);
@@ -709,7 +730,7 @@ void sqlite3Pragma(
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
int jmp2;
static const VdbeOpList idxErr[] = {
- { OP_MemIncr, 1, 0, 0},
+ { OP_MemIncr, -1, 0, 0},
{ OP_String8, 0, 0, "rowid "},
{ OP_Rowid, 1, 0, 0},
{ OP_String8, 0, 0, " missing from index "},
@@ -734,13 +755,16 @@ void sqlite3Pragma(
{ OP_MemLoad, 1, 0, 0},
{ OP_MemLoad, 2, 0, 0},
{ OP_Eq, 0, 0, 0}, /* 6 */
- { OP_MemIncr, 1, 0, 0},
+ { OP_MemIncr, -1, 0, 0},
{ OP_String8, 0, 0, "wrong # of entries in index "},
{ OP_String8, 0, 0, 0}, /* 9 */
{ OP_Concat, 0, 0, 0},
{ OP_Callback, 1, 0, 0},
};
if( pIdx->tnum==0 ) continue;
+ addr = sqlite3VdbeAddOp(v, OP_IfMemPos, 0, 0);
+ sqlite3VdbeAddOp(v, OP_Halt, 0, 0);
+ sqlite3VdbeJumpHere(v, addr);
addr = sqlite3VdbeAddOpList(v, ArraySize(cntIdx), cntIdx);
sqlite3VdbeChangeP1(v, addr+1, j+2);
sqlite3VdbeChangeP2(v, addr+1, addr+4);
@@ -752,6 +776,7 @@ void sqlite3Pragma(
}
}
addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode);
+ sqlite3VdbeChangeP1(v, addr+1, mxErr);
sqlite3VdbeJumpHere(v, addr+2);
}else
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
@@ -780,7 +805,7 @@ void sqlite3Pragma(
** useful if invoked immediately after the main database i
*/
if( sqlite3StrICmp(zLeft, "encoding")==0 ){
- static struct EncName {
+ static const struct EncName {
char *zName;
u8 enc;
} encnames[] = {
@@ -790,12 +815,11 @@ void sqlite3Pragma(
{ "UTF16le", SQLITE_UTF16LE },
{ "UTF-16be", SQLITE_UTF16BE },
{ "UTF16be", SQLITE_UTF16BE },
- { "UTF-16", 0 /* Filled in at run-time */ },
- { "UTF16", 0 /* Filled in at run-time */ },
+ { "UTF-16", 0 }, /* SQLITE_UTF16NATIVE */
+ { "UTF16", 0 }, /* SQLITE_UTF16NATIVE */
{ 0, 0 }
};
- struct EncName *pEnc;
- encnames[6].enc = encnames[7].enc = SQLITE_UTF16NATIVE;
+ const struct EncName *pEnc;
if( !zRight ){ /* "PRAGMA encoding" */
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
sqlite3VdbeSetNumCols(v, 1);
@@ -820,7 +844,7 @@ void sqlite3Pragma(
){
for(pEnc=&encnames[0]; pEnc->zName; pEnc++){
if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){
- ENC(pParse->db) = pEnc->enc;
+ ENC(pParse->db) = pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE;
break;
}
}
@@ -890,6 +914,7 @@ void sqlite3Pragma(
sqlite3VdbeChangeP1(v, addr, iDb);
sqlite3VdbeChangeP2(v, addr, iCookie);
sqlite3VdbeSetNumCols(v, 1);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, P3_TRANSIENT);
}
}
#endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */
@@ -941,6 +966,22 @@ void sqlite3Pragma(
sqlite3_key(db, zRight, strlen(zRight));
}else
#endif
+#if SQLITE_HAS_CODEC || defined(SQLITE_ENABLE_CEROD)
+ if( sqlite3StrICmp(zLeft, "activate_extensions")==0 ){
+#if 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
+ }
+#endif
{}
diff --git a/dlls/sqlite/sqlite-source/prepare.c b/dlls/sqlite/sqlite-source/prepare.c
index 8abfb907..e584f789 100644
--- a/dlls/sqlite/sqlite-source/prepare.c
+++ b/dlls/sqlite/sqlite-source/prepare.c
@@ -28,6 +28,7 @@ static void corruptSchema(InitData *pData, const char *zExtra){
sqlite3SetString(pData->pzErrMsg, "malformed database schema",
zExtra!=0 && zExtra[0]!=0 ? " - " : (char*)0, zExtra, (char*)0);
}
+ pData->rc = SQLITE_CORRUPT;
}
/*
@@ -38,28 +39,28 @@ static void corruptSchema(InitData *pData, const char *zExtra){
** Each callback contains the following information:
**
** argv[0] = name of thing being created
-** argv[1] = root page number for table or index. NULL for trigger or view.
+** argv[1] = root page number for table or index. 0 for trigger or view.
** argv[2] = SQL text for the CREATE statement.
-** argv[3] = "1" for temporary files, "0" for main database, "2" or more
-** for auxiliary database files.
**
*/
int sqlite3InitCallback(void *pInit, int argc, char **argv, char **azColName){
InitData *pData = (InitData*)pInit;
sqlite3 *db = pData->db;
- int iDb;
+ int iDb = pData->iDb;
+ pData->rc = SQLITE_OK;
+ DbClearProperty(db, iDb, DB_Empty);
if( sqlite3MallocFailed() ){
+ corruptSchema(pData, 0);
return SQLITE_NOMEM;
}
- assert( argc==4 );
+ assert( argc==3 );
if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
- if( argv[1]==0 || argv[3]==0 ){
+ if( argv[1]==0 ){
corruptSchema(pData, 0);
return 1;
}
- iDb = atoi(argv[3]);
assert( iDb>=0 && iDbnDb );
if( argv[2] && argv[2][0] ){
/* Call the parser to process a CREATE TABLE, INDEX or VIEW.
@@ -76,13 +77,14 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **azColName){
db->init.iDb = 0;
assert( rc!=SQLITE_OK || zErr==0 );
if( SQLITE_OK!=rc ){
+ pData->rc = rc;
if( rc==SQLITE_NOMEM ){
sqlite3FailedMalloc();
- }else{
+ }else if( rc!=SQLITE_INTERRUPT ){
corruptSchema(pData, zErr);
}
sqlite3_free(zErr);
- return rc;
+ return 1;
}
}else{
/* If the SQL column is blank it means this is an index that
@@ -121,8 +123,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
int size;
Table *pTab;
Db *pDb;
- char const *azArg[5];
- char zDbNum[30];
+ char const *azArg[4];
int meta[10];
InitData initData;
char const *zMasterSchema;
@@ -173,15 +174,14 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
azArg[0] = zMasterName;
azArg[1] = "1";
azArg[2] = zMasterSchema;
- sprintf(zDbNum, "%d", iDb);
- azArg[3] = zDbNum;
- azArg[4] = 0;
+ azArg[3] = 0;
initData.db = db;
+ initData.iDb = iDb;
initData.pzErrMsg = pzErrMsg;
- rc = sqlite3InitCallback(&initData, 4, (char **)azArg, 0);
- if( rc!=SQLITE_OK ){
+ rc = sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
+ if( rc ){
sqlite3SafetyOn(db);
- return rc;
+ return initData.rc;
}
pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName);
if( pTab ){
@@ -211,7 +211,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
** meta[1] File format of schema layer.
** meta[2] Size of the page cache.
** meta[3] Use freelist if 0. Autovacuum if greater than zero.
- ** meta[4] Db text encoding. 1:UTF-8 3:UTF-16 LE 4:UTF-16 BE
+ ** meta[4] Db text encoding. 1:UTF-8 2:UTF-16LE 3:UTF-16BE
** meta[5] The user cookie. Used by the application.
** meta[6]
** meta[7]
@@ -291,10 +291,11 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
}else{
char *zSql;
zSql = sqlite3MPrintf(
- "SELECT name, rootpage, sql, '%s' FROM '%q'.%s",
- zDbNum, db->aDb[iDb].zName, zMasterName);
+ "SELECT name, rootpage, sql FROM '%q'.%s",
+ db->aDb[iDb].zName, zMasterName);
sqlite3SafetyOff(db);
rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
+ if( rc==SQLITE_ABORT ) rc = initData.rc;
sqlite3SafetyOn(db);
sqliteFree(zSql);
#ifndef SQLITE_OMIT_ANALYZE
@@ -444,12 +445,13 @@ int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
/*
** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
*/
-int sqlite3_prepare(
+int sqlite3Prepare(
sqlite3 *db, /* Database handle. */
const char *zSql, /* UTF-8 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
+ int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
- const char** pzTail /* OUT: End of parsed string */
+ const char **pzTail /* OUT: End of parsed string */
){
Parse sParse;
char *zErrMsg = 0;
@@ -499,7 +501,12 @@ int sqlite3_prepare(
if( sParse.rc==SQLITE_SCHEMA ){
sqlite3ResetInternalSchema(db, 0);
}
- if( pzTail ) *pzTail = sParse.zTail;
+ if( sqlite3MallocFailed() ){
+ sParse.rc = SQLITE_NOMEM;
+ }
+ if( pzTail ){
+ *pzTail = sParse.zTail;
+ }
rc = sParse.rc;
#ifndef SQLITE_OMIT_EXPLAIN
@@ -517,13 +524,16 @@ int sqlite3_prepare(
sqlite3VdbeSetColName(sParse.pVdbe, 3, COLNAME_NAME, "p2", P3_STATIC);
sqlite3VdbeSetColName(sParse.pVdbe, 4, COLNAME_NAME, "p3", P3_STATIC);
}
- }
+ }
#endif
if( sqlite3SafetyOff(db) ){
rc = SQLITE_MISUSE;
}
if( rc==SQLITE_OK ){
+ if( saveSqlFlag ){
+ sqlite3VdbeSetSql(sParse.pVdbe, zSql, sParse.zTail - zSql);
+ }
*ppStmt = (sqlite3_stmt*)sParse.pVdbe;
}else if( sParse.pVdbe ){
sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe);
@@ -538,17 +548,78 @@ int sqlite3_prepare(
rc = sqlite3ApiExit(db, rc);
sqlite3ReleaseThreadData();
+ assert( (rc&db->errMask)==rc );
return rc;
}
+/*
+** Rerun the compilation of a statement after a schema change.
+** Return true if the statement was recompiled successfully.
+** Return false if there is an error of some kind.
+*/
+int sqlite3Reprepare(Vdbe *p){
+ int rc;
+ Vdbe *pNew;
+ const char *zSql;
+ sqlite3 *db;
+
+ zSql = sqlite3VdbeGetSql(p);
+ if( zSql==0 ){
+ return 0;
+ }
+ db = sqlite3VdbeDb(p);
+ rc = sqlite3Prepare(db, zSql, -1, 0, (sqlite3_stmt**)&pNew, 0);
+ if( rc ){
+ assert( pNew==0 );
+ return 0;
+ }else{
+ assert( pNew!=0 );
+ }
+ sqlite3VdbeSwap(pNew, p);
+ sqlite3_transfer_bindings((sqlite3_stmt*)pNew, (sqlite3_stmt*)p);
+ sqlite3VdbeResetStepResult(pNew);
+ sqlite3VdbeFinalize(pNew);
+ return 1;
+}
+
+
+/*
+** Two versions of the official API. Legacy and new use. In the legacy
+** version, the original SQL text is not saved in the prepared statement
+** and so if a schema change occurs, SQLITE_SCHEMA is returned by
+** sqlite3_step(). In the new version, the original SQL text is retained
+** and the statement is automatically recompiled if an schema change
+** occurs.
+*/
+int sqlite3_prepare(
+ sqlite3 *db, /* Database handle. */
+ const char *zSql, /* UTF-8 encoded SQL statement. */
+ int nBytes, /* Length of zSql in bytes. */
+ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
+ const char **pzTail /* OUT: End of parsed string */
+){
+ return sqlite3Prepare(db,zSql,nBytes,0,ppStmt,pzTail);
+}
+int sqlite3_prepare_v2(
+ sqlite3 *db, /* Database handle. */
+ const char *zSql, /* UTF-8 encoded SQL statement. */
+ int nBytes, /* Length of zSql in bytes. */
+ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
+ const char **pzTail /* OUT: End of parsed string */
+){
+ return sqlite3Prepare(db,zSql,nBytes,1,ppStmt,pzTail);
+}
+
+
#ifndef SQLITE_OMIT_UTF16
/*
** Compile the UTF-16 encoded SQL statement zSql into a statement handle.
*/
-int sqlite3_prepare16(
+static int sqlite3Prepare16(
sqlite3 *db, /* Database handle. */
const void *zSql, /* UTF-8 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
+ int saveSqlFlag, /* True to save SQL text into the sqlite3_stmt */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const void **pzTail /* OUT: End of parsed string */
){
@@ -565,7 +636,7 @@ int sqlite3_prepare16(
}
zSql8 = sqlite3utf16to8(zSql, nBytes);
if( zSql8 ){
- rc = sqlite3_prepare(db, zSql8, -1, ppStmt, &zTail8);
+ rc = sqlite3Prepare(db, zSql8, -1, saveSqlFlag, ppStmt, &zTail8);
}
if( zTail8 && pzTail ){
@@ -580,4 +651,32 @@ int sqlite3_prepare16(
sqliteFree(zSql8);
return sqlite3ApiExit(db, rc);
}
+
+/*
+** Two versions of the official API. Legacy and new use. In the legacy
+** version, the original SQL text is not saved in the prepared statement
+** and so if a schema change occurs, SQLITE_SCHEMA is returned by
+** sqlite3_step(). In the new version, the original SQL text is retained
+** and the statement is automatically recompiled if an schema change
+** occurs.
+*/
+int sqlite3_prepare16(
+ sqlite3 *db, /* Database handle. */
+ const void *zSql, /* UTF-8 encoded SQL statement. */
+ int nBytes, /* Length of zSql in bytes. */
+ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
+ const void **pzTail /* OUT: End of parsed string */
+){
+ return sqlite3Prepare16(db,zSql,nBytes,0,ppStmt,pzTail);
+}
+int sqlite3_prepare16_v2(
+ sqlite3 *db, /* Database handle. */
+ const void *zSql, /* UTF-8 encoded SQL statement. */
+ int nBytes, /* Length of zSql in bytes. */
+ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
+ const void **pzTail /* OUT: End of parsed string */
+){
+ return sqlite3Prepare16(db,zSql,nBytes,1,ppStmt,pzTail);
+}
+
#endif /* SQLITE_OMIT_UTF16 */
diff --git a/dlls/sqlite/sqlite-source/printf.c b/dlls/sqlite/sqlite-source/printf.c
index 43b353b0..a05fec21 100644
--- a/dlls/sqlite/sqlite-source/printf.c
+++ b/dlls/sqlite/sqlite-source/printf.c
@@ -230,7 +230,7 @@ static int vxprintf(
char buf[etBUFSIZE]; /* Conversion buffer */
char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
etByte errorflag = 0; /* True if an error is encountered */
- etByte xtype = 0; /* Conversion paradigm */
+ etByte xtype; /* Conversion paradigm */
char *zExtra; /* Extra memory used for etTCLESCAPE conversions */
static const char spaces[] =
" ";
@@ -333,6 +333,8 @@ static int vxprintf(
infop = &fmtinfo[idx];
if( useExtended || (infop->flags & FLAG_INTERN)==0 ){
xtype = infop->type;
+ }else{
+ return -1;
}
break;
}
@@ -804,29 +806,28 @@ char *sqlite3MPrintf(const char *zFormat, ...){
}
/*
-** Print into memory obtained from malloc(). Do not use the internal
-** %-conversion extensions. This routine is for use by external users.
+** Print into memory obtained from sqlite3_malloc(). Omit the internal
+** %-conversion extensions.
+*/
+char *sqlite3_vmprintf(const char *zFormat, va_list ap){
+ char zBase[SQLITE_PRINT_BUF_SIZE];
+ return base_vprintf(sqlite3_realloc, 0, zBase, sizeof(zBase), zFormat, ap);
+}
+
+/*
+** Print into memory obtained from sqlite3_malloc()(). Omit the internal
+** %-conversion extensions.
*/
char *sqlite3_mprintf(const char *zFormat, ...){
va_list ap;
char *z;
- char zBuf[200];
-
- va_start(ap,zFormat);
- z = base_vprintf((void*(*)(void*,int))realloc, 0,
- zBuf, sizeof(zBuf), zFormat, ap);
+ char zBase[SQLITE_PRINT_BUF_SIZE];
+ va_start(ap, zFormat);
+ z = base_vprintf(sqlite3_realloc, 0, zBase, sizeof(zBase), zFormat, ap);
va_end(ap);
return z;
}
-/* This is the varargs version of sqlite3_mprintf.
-*/
-char *sqlite3_vmprintf(const char *zFormat, va_list ap){
- char zBuf[200];
- return base_vprintf((void*(*)(void*,int))realloc, 0,
- zBuf, sizeof(zBuf), zFormat, ap);
-}
-
/*
** sqlite3_snprintf() works like snprintf() except that it ignores the
** current locale settings. This is important for SQLite because we
@@ -856,7 +857,7 @@ void sqlite3DebugPrintf(const char *zFormat, ...){
va_start(ap, zFormat);
base_vprintf(0, 0, zBuf, sizeof(zBuf), zFormat, ap);
va_end(ap);
- fprintf(stdout,"%d: %s", getpid(), zBuf);
+ fprintf(stdout,"%s", zBuf);
fflush(stdout);
}
#endif
diff --git a/dlls/sqlite/sqlite-source/random.c b/dlls/sqlite/sqlite-source/random.c
index 51d5d72e..5adc84aa 100644
--- a/dlls/sqlite/sqlite-source/random.c
+++ b/dlls/sqlite/sqlite-source/random.c
@@ -37,7 +37,7 @@
** (Later): Actually, OP_NewRowid does not depend on a good source of
** randomness any more. But we will leave this code in all the same.
*/
-static int randomByte(){
+static int randomByte(void){
unsigned char t;
/* All threads share a single random number generator.
diff --git a/dlls/sqlite/sqlite-source/select.c b/dlls/sqlite/sqlite-source/select.c
index 96e6c938..a7715218 100644
--- a/dlls/sqlite/sqlite-source/select.c
+++ b/dlls/sqlite/sqlite-source/select.c
@@ -72,9 +72,9 @@ Select *sqlite3SelectNew(
pNew->pOffset = pOffset;
pNew->iLimit = -1;
pNew->iOffset = -1;
- pNew->addrOpenVirt[0] = -1;
- pNew->addrOpenVirt[1] = -1;
- pNew->addrOpenVirt[2] = -1;
+ pNew->addrOpenEphm[0] = -1;
+ pNew->addrOpenEphm[1] = -1;
+ pNew->addrOpenEphm[2] = -1;
if( pNew==&standin) {
clearSelect(pNew);
pNew = 0;
@@ -187,7 +187,7 @@ static void setToken(Token *p, const char *z){
/*
** Create an expression node for an identifier with the name of zName
*/
-static Expr *createIdExpr(const char *zName){
+Expr *sqlite3CreateIdExpr(const char *zName){
Token dummy;
setToken(&dummy, zName);
return sqlite3Expr(TK_ID, 0, 0, &dummy);
@@ -211,22 +211,27 @@ static void addWhereTerm(
Expr *pE2a, *pE2b, *pE2c;
Expr *pE;
- pE1a = createIdExpr(zCol);
- pE2a = createIdExpr(zCol);
+ pE1a = sqlite3CreateIdExpr(zCol);
+ pE2a = sqlite3CreateIdExpr(zCol);
if( zAlias1==0 ){
zAlias1 = pTab1->zName;
}
- pE1b = createIdExpr(zAlias1);
+ pE1b = sqlite3CreateIdExpr(zAlias1);
if( zAlias2==0 ){
zAlias2 = pTab2->zName;
}
- pE2b = createIdExpr(zAlias2);
- pE1c = sqlite3Expr(TK_DOT, pE1b, pE1a, 0);
- pE2c = sqlite3Expr(TK_DOT, pE2b, pE2a, 0);
- pE = sqlite3Expr(TK_EQ, pE1c, pE2c, 0);
- ExprSetProperty(pE, EP_FromJoin);
- pE->iRightJoinTable = iRightJoinTable;
- *ppExpr = sqlite3ExprAnd(*ppExpr, pE);
+ pE2b = sqlite3CreateIdExpr(zAlias2);
+ pE1c = sqlite3ExprOrFree(TK_DOT, pE1b, pE1a, 0);
+ pE2c = sqlite3ExprOrFree(TK_DOT, pE2b, pE2a, 0);
+ pE = sqlite3ExprOrFree(TK_EQ, pE1c, pE2c, 0);
+ if( pE ){
+ ExprSetProperty(pE, EP_FromJoin);
+ pE->iRightJoinTable = iRightJoinTable;
+ }
+ pE = sqlite3ExprAnd(*ppExpr, pE);
+ if( pE ){
+ *ppExpr = pE;
+ }
}
/*
@@ -296,8 +301,8 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
/* When the NATURAL keyword is present, add WHERE clause terms for
** every column that the two tables have in common.
*/
- if( pLeft->jointype & JT_NATURAL ){
- if( pLeft->pOn || pLeft->pUsing ){
+ if( pRight->jointype & JT_NATURAL ){
+ if( pRight->pOn || pRight->pUsing ){
sqlite3ErrorMsg(pParse, "a NATURAL join may not have "
"an ON or USING clause", 0);
return 1;
@@ -315,7 +320,7 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
/* Disallow both ON and USING clauses in the same join
*/
- if( pLeft->pOn && pLeft->pUsing ){
+ if( pRight->pOn && pRight->pUsing ){
sqlite3ErrorMsg(pParse, "cannot have both ON and USING "
"clauses in the same join");
return 1;
@@ -324,10 +329,10 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
/* Add the ON clause to the end of the WHERE clause, connected by
** an AND operator.
*/
- if( pLeft->pOn ){
- setJoinExpr(pLeft->pOn, pRight->iCursor);
- p->pWhere = sqlite3ExprAnd(p->pWhere, pLeft->pOn);
- pLeft->pOn = 0;
+ if( pRight->pOn ){
+ setJoinExpr(pRight->pOn, pRight->iCursor);
+ p->pWhere = sqlite3ExprAnd(p->pWhere, pRight->pOn);
+ pRight->pOn = 0;
}
/* Create extra terms on the WHERE clause for each column named
@@ -337,8 +342,8 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
** Report an error if any column mentioned in the USING clause is
** not contained in both tables to be joined.
*/
- if( pLeft->pUsing ){
- IdList *pList = pLeft->pUsing;
+ if( pRight->pUsing ){
+ IdList *pList = pRight->pUsing;
for(j=0; jnId; j++){
char *zName = pList->a[j].zName;
if( columnIndex(pLeftTab, zName)<0 || columnIndex(pRightTab, zName)<0 ){
@@ -522,7 +527,7 @@ static int selectInnerLoop(
/* Store the result as data using a unique key.
*/
case SRT_Table:
- case SRT_VirtualTab: {
+ case SRT_EphemTab: {
sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);
if( pOrderBy ){
pushOntoSorter(pParse, pOrderBy, p);
@@ -705,7 +710,7 @@ static void generateSortTail(
sqlite3VdbeAddOp(v, OP_Column, iTab, pOrderBy->nExpr + 1);
switch( eDest ){
case SRT_Table:
- case SRT_VirtualTab: {
+ case SRT_EphemTab: {
sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0);
sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
sqlite3VdbeAddOp(v, OP_Insert, iParm, 0);
@@ -805,6 +810,7 @@ static const char *columnType(
assert( pExpr->op!=TK_AS );
switch( pExpr->op ){
+ case TK_AGG_COLUMN:
case TK_COLUMN: {
/* The expression is a column. Locate the table the column is being
** extracted from in NameContext.pSrcList. This table may be real
@@ -840,7 +846,6 @@ static const char *columnType(
}
assert( pTab );
-#ifndef SQLITE_OMIT_SUBQUERY
if( pS ){
/* The "table" is actually a sub-select or a view in the FROM clause
** of the SELECT statement. Return the declaration type and origin
@@ -858,9 +863,7 @@ static const char *columnType(
sNC.pParse = pNC->pParse;
zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
}
- }else
-#endif
- if( pTab->pSchema ){
+ }else if( pTab->pSchema ){
/* A real table */
assert( !pS );
if( iCol<0 ) iCol = pTab->iPKey;
@@ -1068,7 +1071,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
Expr *p, *pR;
char *zType;
char *zName;
- char *zBasename;
+ int nName;
CollSeq *pColl;
int cnt;
NameContext sNC;
@@ -1101,17 +1104,15 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
/* Make sure the column name is unique. If the name is not unique,
** append a integer to the name so that it becomes unique.
*/
- zBasename = zName;
+ nName = strlen(zName);
for(j=cnt=0; jzName = zName;
/* Get the typename, type affinity, and collating sequence for the
@@ -1200,11 +1201,11 @@ static int prepSelectStmt(Parse *pParse, Select *p){
if( pTab==0 ){
return 1;
}
- /* The isTransient flag indicates that the Table structure has been
+ /* The isEphem flag indicates that the Table structure has been
** dynamically allocated and may be freed at any time. In other words,
** pTab is not pointing to a persistent table structure that defines
** part of the schema. */
- pTab->isTransient = 1;
+ pTab->isEphem = 1;
#endif
}else{
/* An ordinary table or view name in the FROM clause */
@@ -1215,8 +1216,8 @@ static int prepSelectStmt(Parse *pParse, Select *p){
return 1;
}
pTab->nRef++;
-#ifndef SQLITE_OMIT_VIEW
- if( pTab->pSelect ){
+#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
+ if( pTab->pSelect || IsVirtual(pTab) ){
/* We reach here if the named table is a really a view */
if( sqlite3ViewGetColumnNames(pParse, pTab) ){
return 1;
@@ -1308,13 +1309,13 @@ static int prepSelectStmt(Parse *pParse, Select *p){
if( i>0 ){
struct SrcList_item *pLeft = &pTabList->a[i-1];
- if( (pLeft->jointype & JT_NATURAL)!=0 &&
+ if( (pLeft[1].jointype & JT_NATURAL)!=0 &&
columnIndex(pLeft->pTab, zName)>=0 ){
/* In a NATURAL join, omit the join columns from the
** table on the right */
continue;
}
- if( sqlite3IdListIndex(pLeft->pUsing, zName)>=0 ){
+ if( sqlite3IdListIndex(pLeft[1].pUsing, zName)>=0 ){
/* In a join with a USING clause, omit columns in the
** using clause from the table on the right. */
continue;
@@ -1537,10 +1538,10 @@ static void createSortingIndex(Parse *pParse, Select *p, ExprList *pOrderBy){
int addr;
assert( pOrderBy->iECursor==0 );
pOrderBy->iECursor = pParse->nTab++;
- addr = sqlite3VdbeAddOp(pParse->pVdbe, OP_OpenVirtual,
+ addr = sqlite3VdbeAddOp(pParse->pVdbe, OP_OpenEphemeral,
pOrderBy->iECursor, pOrderBy->nExpr+1);
- assert( p->addrOpenVirt[2] == -1 );
- p->addrOpenVirt[2] = addr;
+ assert( p->addrOpenEphm[2] == -1 );
+ p->addrOpenEphm[2] = addr;
}
}
@@ -1646,10 +1647,10 @@ static int multiSelect(
/* Create the destination temporary table if necessary
*/
- if( eDest==SRT_VirtualTab ){
+ if( eDest==SRT_EphemTab ){
assert( p->pEList );
assert( nSetP2addrOpenVirt[0] == -1 );
- p->addrOpenVirt[0] = addr;
- p->pRightmost->usesVirt = 1;
+ assert( p->addrOpenEphm[0] == -1 );
+ p->addrOpenEphm[0] = addr;
+ p->pRightmost->usesEphm = 1;
}
createSortingIndex(pParse, p, pOrderBy);
assert( p->pEList );
@@ -1807,10 +1808,10 @@ static int multiSelect(
}
createSortingIndex(pParse, p, pOrderBy);
- addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, tab1, 0);
- assert( p->addrOpenVirt[0] == -1 );
- p->addrOpenVirt[0] = addr;
- p->pRightmost->usesVirt = 1;
+ addr = sqlite3VdbeAddOp(v, OP_OpenEphemeral, tab1, 0);
+ assert( p->addrOpenEphm[0] == -1 );
+ p->addrOpenEphm[0] = addr;
+ p->pRightmost->usesEphm = 1;
assert( p->pEList );
/* Code the SELECTs to our left into temporary table "tab1".
@@ -1822,9 +1823,9 @@ static int multiSelect(
/* Code the current SELECT into temporary table "tab2"
*/
- addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, tab2, 0);
- assert( p->addrOpenVirt[1] == -1 );
- p->addrOpenVirt[1] = addr;
+ addr = sqlite3VdbeAddOp(v, OP_OpenEphemeral, tab2, 0);
+ assert( p->addrOpenEphm[1] == -1 );
+ p->addrOpenEphm[1] = addr;
p->pPrior = 0;
pLimit = p->pLimit;
p->pLimit = 0;
@@ -1898,15 +1899,17 @@ static int multiSelect(
** SELECT might also skip this part if it has no ORDER BY clause and
** no temp tables are required.
*/
- if( pOrderBy || p->usesVirt ){
+ if( pOrderBy || p->usesEphm ){
int i; /* Loop counter */
KeyInfo *pKeyInfo; /* Collating sequence for the result set */
Select *pLoop; /* For looping through SELECT statements */
+ int nKeyCol; /* Number of entries in pKeyInfo->aCol[] */
CollSeq **apColl;
CollSeq **aCopy;
assert( p->pRightmost==p );
- pKeyInfo = sqliteMalloc(sizeof(*pKeyInfo)+nCol*2*sizeof(CollSeq*) + nCol);
+ nKeyCol = nCol + (pOrderBy ? pOrderBy->nExpr : 0);
+ pKeyInfo = sqliteMalloc(sizeof(*pKeyInfo)+nKeyCol*(sizeof(CollSeq*) + 1));
if( !pKeyInfo ){
rc = SQLITE_NOMEM;
goto multi_select_end;
@@ -1924,15 +1927,16 @@ static int multiSelect(
for(pLoop=p; pLoop; pLoop=pLoop->pPrior){
for(i=0; i<2; i++){
- int addr = pLoop->addrOpenVirt[i];
+ int addr = pLoop->addrOpenEphm[i];
if( addr<0 ){
/* If [0] is unused then [1] is also unused. So we can
** always safely abort as soon as the first unused slot is found */
- assert( pLoop->addrOpenVirt[1]<0 );
+ assert( pLoop->addrOpenEphm[1]<0 );
break;
}
sqlite3VdbeChangeP2(v, addr, nCol);
sqlite3VdbeChangeP3(v, addr, (char*)pKeyInfo, P3_KEYINFO);
+ pLoop->addrOpenEphm[i] = -1;
}
}
@@ -1942,24 +1946,23 @@ static int multiSelect(
int addr;
u8 *pSortOrder;
- aCopy = &pKeyInfo->aColl[nCol];
+ aCopy = &pKeyInfo->aColl[nOrderByExpr];
pSortOrder = pKeyInfo->aSortOrder = (u8*)&aCopy[nCol];
memcpy(aCopy, pKeyInfo->aColl, nCol*sizeof(CollSeq*));
apColl = pKeyInfo->aColl;
for(i=0; ipExpr;
- char *zName = pOTerm->zName;
- assert( pExpr->op==TK_COLUMN && pExpr->iColumnflags & EP_ExpCollate) ){
+ assert( pExpr->pColl!=0 );
+ *apColl = pExpr->pColl;
}else{
*apColl = aCopy[pExpr->iColumn];
}
*pSortOrder = pOTerm->sortOrder;
}
assert( p->pRightmost==p );
- assert( p->addrOpenVirt[2]>=0 );
- addr = p->addrOpenVirt[2];
+ assert( p->addrOpenEphm[2]>=0 );
+ addr = p->addrOpenEphm[2];
sqlite3VdbeChangeP2(v, addr, p->pEList->nExpr+2);
pKeyInfo->nField = nOrderByExpr;
sqlite3VdbeChangeP3(v, addr, (char*)pKeyInfo, P3_KEYINFO_HANDOFF);
@@ -2010,6 +2013,7 @@ static void substExpr(Expr *pExpr, int iTable, ExprList *pEList){
assert( pExpr->pList==0 );
pExpr->pList = sqlite3ExprListDup(pNew->pList);
pExpr->iTable = pNew->iTable;
+ pExpr->pTab = pNew->pTab;
pExpr->iColumn = pNew->iColumn;
pExpr->iAgg = pNew->iAgg;
sqlite3TokenCopy(&pExpr->token, &pNew->token);
@@ -2171,7 +2175,7 @@ static int flattenSubquery(
**
** which is not at all the same thing.
*/
- if( pSubSrc->nSrc>1 && iFrom>0 && (pSrc->a[iFrom-1].jointype & JT_OUTER)!=0 ){
+ if( pSubSrc->nSrc>1 && (pSubitem->jointype & JT_OUTER)!=0 ){
return 0;
}
@@ -2188,8 +2192,7 @@ static int flattenSubquery(
** But the t2.x>0 test will always fail on a NULL row of t2, which
** effectively converts the OUTER JOIN into an INNER JOIN.
*/
- if( iFrom>0 && (pSrc->a[iFrom-1].jointype & JT_OUTER)!=0
- && pSub->pWhere!=0 ){
+ if( (pSubitem->jointype & JT_OUTER)!=0 && pSub->pWhere!=0 ){
return 0;
}
@@ -2228,7 +2231,7 @@ static int flattenSubquery(
pSrc->a[i+iFrom] = pSubSrc->a[i];
memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
}
- pSrc->a[iFrom+nSubSrc-1].jointype = jointype;
+ pSrc->a[iFrom].jointype = jointype;
}
/* Now begin substituting subquery result set expressions for
@@ -2374,6 +2377,7 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
pIdx = 0;
}else{
CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr);
+ if( pColl==0 ) return 0;
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
assert( pIdx->nColumn>=1 );
if( pIdx->aiColumn[0]==iCol &&
@@ -2393,8 +2397,8 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
/* If the output is destined for a temporary table, open that table.
*/
- if( eDest==SRT_VirtualTab ){
- sqlite3VdbeAddOp(v, OP_OpenVirtual, iParm, 1);
+ if( eDest==SRT_EphemTab ){
+ sqlite3VdbeAddOp(v, OP_OpenEphemeral, iParm, 1);
}
/* Generating code to find the min or the max. Basically all we have
@@ -2403,7 +2407,7 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
** or last entry in the main table.
*/
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- assert( iDb>=0 || pTab->isTransient );
+ assert( iDb>=0 || pTab->isEphem );
sqlite3CodeVerifySchema(pParse, iDb);
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
base = pSrc->a[0].iCursor;
@@ -2473,8 +2477,14 @@ static int processOrderGroupBy(
Expr *pE = pOrderBy->a[i].pExpr;
if( sqlite3ExprIsInteger(pE, &iCol) ){
if( iCol>0 && iCol<=pEList->nExpr ){
+ CollSeq *pColl = pE->pColl;
+ int flags = pE->flags & EP_ExpCollate;
sqlite3ExprDelete(pE);
pE = pOrderBy->a[i].pExpr = sqlite3ExprDup(pEList->a[iCol-1].pExpr);
+ if( pColl && flags ){
+ pE->pColl = pColl;
+ pE->flags |= flags;
+ }
}else{
sqlite3ErrorMsg(pParse,
"%s BY column number %d out of range - should be "
@@ -2485,11 +2495,6 @@ static int processOrderGroupBy(
if( sqlite3ExprResolveNames(pNC, pE) ){
return 1;
}
- if( sqlite3ExprIsConstant(pE) ){
- sqlite3ErrorMsg(pParse,
- "%s BY terms must not be non-integer constants", zType);
- return 1;
- }
}
return 0;
}
@@ -2605,7 +2610,14 @@ int sqlite3SelectResolve(
}
}
- return SQLITE_OK;
+ /* If this is one SELECT of a compound, be sure to resolve names
+ ** in the other SELECTs.
+ */
+ if( p->pPrior ){
+ return sqlite3SelectResolve(pParse, p->pPrior, pOuterNC);
+ }else{
+ return SQLITE_OK;
+ }
}
/*
@@ -2635,7 +2647,7 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
pFunc->iDistinct = -1;
}else{
KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->pList);
- sqlite3VdbeOp3(v, OP_OpenVirtual, pFunc->iDistinct, 0,
+ sqlite3VdbeOp3(v, OP_OpenEphemeral, pFunc->iDistinct, 0,
(char*)pKeyInfo, P3_KEYINFO_HANDOFF);
}
}
@@ -2775,8 +2787,8 @@ int sqlite3Select(
WhereInfo *pWInfo; /* Return from sqlite3WhereBegin() */
Vdbe *v; /* The virtual machine under construction */
int isAgg; /* True for select lists like "count(*)" */
- ExprList *pEList=NULL; /* List of columns to extract. */
- SrcList *pTabList=NULL; /* List of tables to select from */
+ ExprList *pEList; /* List of columns to extract. */
+ SrcList *pTabList; /* List of tables to select from */
Expr *pWhere; /* The WHERE clause. May be NULL */
ExprList *pOrderBy; /* The ORDER BY clause. May be NULL */
ExprList *pGroupBy; /* The GROUP BY clause. May be NULL */
@@ -2784,7 +2796,7 @@ int sqlite3Select(
int isDistinct; /* True if the DISTINCT keyword is present */
int distinct; /* Table to use for the distinct set */
int rc = 1; /* Value to return from this function */
- int addrSortIndex; /* Address of an OP_OpenVirtual instruction */
+ int addrSortIndex; /* Address of an OP_OpenEphemeral instruction */
AggInfo sAggInfo; /* Information used by aggregate queries */
int iEnd; /* Address of the end of the query */
@@ -2872,7 +2884,7 @@ int sqlite3Select(
}else{
needRestoreContext = 0;
}
- sqlite3Select(pParse, pItem->pSelect, SRT_VirtualTab,
+ sqlite3Select(pParse, pItem->pSelect, SRT_EphemTab,
pItem->iCursor, p, i, &isAgg, 0);
if( needRestoreContext ){
pParse->zAuthContext = zSavedAuthContext;
@@ -2907,53 +2919,44 @@ int sqlite3Select(
}
#endif
- /* If there is an ORDER BY clause, resolve any collation sequences
- ** names that have been explicitly specified and create a sorting index.
- **
- ** This sorting index might end up being unused if the data can be
+ /* If there is an ORDER BY clause, then this sorting
+ ** index might end up being unused if the data can be
** extracted in pre-sorted order. If that is the case, then the
- ** OP_OpenVirtual instruction will be changed to an OP_Noop once
+ ** OP_OpenEphemeral instruction will be changed to an OP_Noop once
** we figure out that the sorting index is not needed. The addrSortIndex
** variable is used to facilitate that change.
*/
if( pOrderBy ){
- struct ExprList_item *pTerm;
KeyInfo *pKeyInfo;
- for(i=0, pTerm=pOrderBy->a; inExpr; i++, pTerm++){
- if( pTerm->zName ){
- pTerm->pExpr->pColl = sqlite3LocateCollSeq(pParse, pTerm->zName, -1);
- }
- }
if( pParse->nErr ){
goto select_end;
}
pKeyInfo = keyInfoFromExprList(pParse, pOrderBy);
pOrderBy->iECursor = pParse->nTab++;
- p->addrOpenVirt[2] = addrSortIndex =
- sqlite3VdbeOp3(v, OP_OpenVirtual, pOrderBy->iECursor, pOrderBy->nExpr+2,
- (char*)pKeyInfo, P3_KEYINFO_HANDOFF);
+ p->addrOpenEphm[2] = addrSortIndex =
+ sqlite3VdbeOp3(v, OP_OpenEphemeral, pOrderBy->iECursor, pOrderBy->nExpr+2, (char*)pKeyInfo, P3_KEYINFO_HANDOFF);
}else{
addrSortIndex = -1;
}
+ /* If the output is destined for a temporary table, open that table.
+ */
+ if( eDest==SRT_EphemTab ){
+ sqlite3VdbeAddOp(v, OP_OpenEphemeral, iParm, pEList->nExpr);
+ }
+
/* Set the limiter.
*/
iEnd = sqlite3VdbeMakeLabel(v);
computeLimitRegisters(pParse, p, iEnd);
- /* If the output is destined for a temporary table, open that table.
- */
- if( eDest==SRT_VirtualTab ){
- sqlite3VdbeAddOp(v, OP_OpenVirtual, iParm, pEList->nExpr);
- }
-
/* Open a virtual index to use for the distinct set.
*/
if( isDistinct ){
KeyInfo *pKeyInfo;
distinct = pParse->nTab++;
pKeyInfo = keyInfoFromExprList(pParse, p->pEList);
- sqlite3VdbeOp3(v, OP_OpenVirtual, distinct, 0,
+ sqlite3VdbeOp3(v, OP_OpenEphemeral, distinct, 0,
(char*)pKeyInfo, P3_KEYINFO_HANDOFF);
}else{
distinct = -1;
@@ -2967,13 +2970,13 @@ int sqlite3Select(
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy);
if( pWInfo==0 ) goto select_end;
- /* If sorting index that was created by a prior OP_OpenVirtual
- ** instruction ended up not being needed, then change the OP_OpenVirtual
+ /* If sorting index that was created by a prior OP_OpenEphemeral
+ ** instruction ended up not being needed, then change the OP_OpenEphemeral
** into an OP_Noop.
*/
if( addrSortIndex>=0 && pOrderBy==0 ){
sqlite3VdbeChangeToNoop(v, addrSortIndex, 1);
- p->addrOpenVirt[2] = -1;
+ p->addrOpenEphm[2] = -1;
}
/* Use the standard inner loop
@@ -3007,7 +3010,7 @@ int sqlite3Select(
int addrGroupByChange; /* Code that runs when any GROUP BY term changes */
int addrProcessRow; /* Code to process a single input row */
int addrEnd; /* End of all processing */
- int addrSortingIdx; /* The OP_OpenVirtual for the sorting index */
+ int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
int addrReset; /* Subroutine for resetting the accumulator */
addrEnd = sqlite3VdbeMakeLabel(v);
@@ -3054,13 +3057,13 @@ int sqlite3Select(
/* If there is a GROUP BY clause we might need a sorting index to
** implement it. Allocate that sorting index now. If it turns out
- ** that we do not need it after all, the OpenVirtual instruction
+ ** that we do not need it after all, the OpenEphemeral instruction
** will be converted into a Noop.
*/
sAggInfo.sortingIdx = pParse->nTab++;
pKeyInfo = keyInfoFromExprList(pParse, pGroupBy);
addrSortingIdx =
- sqlite3VdbeOp3(v, OP_OpenVirtual, sAggInfo.sortingIdx,
+ sqlite3VdbeOp3(v, OP_OpenEphemeral, sAggInfo.sortingIdx,
sAggInfo.nSortingColumn,
(char*)pKeyInfo, P3_KEYINFO_HANDOFF);
@@ -3123,7 +3126,7 @@ int sqlite3Select(
if( pWInfo==0 ) goto select_end;
if( pGroupBy==0 ){
/* The optimizer is able to deliver rows in group by order so
- ** we do not have to sort. The OP_OpenVirtual table will be
+ ** we do not have to sort. The OP_OpenEphemeral table will be
** cancelled later because we still need to use the pKeyInfo
*/
pGroupBy = p->pGroupBy;
@@ -3294,3 +3297,99 @@ select_end:
sqliteFree(sAggInfo.aFunc);
return rc;
}
+
+#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
+/*
+*******************************************************************************
+** The following code is used for testing and debugging only. The code
+** that follows does not appear in normal builds.
+**
+** These routines are used to print out the content of all or part of a
+** parse structures such as Select or Expr. Such printouts are useful
+** for helping to understand what is happening inside the code generator
+** during the execution of complex SELECT statements.
+**
+** These routine are not called anywhere from within the normal
+** code base. Then are intended to be called from within the debugger
+** or from temporary "printf" statements inserted for debugging.
+*/
+void sqlite3PrintExpr(Expr *p){
+ if( p->token.z && p->token.n>0 ){
+ sqlite3DebugPrintf("(%.*s", p->token.n, p->token.z);
+ }else{
+ sqlite3DebugPrintf("(%d", p->op);
+ }
+ if( p->pLeft ){
+ sqlite3DebugPrintf(" ");
+ sqlite3PrintExpr(p->pLeft);
+ }
+ if( p->pRight ){
+ sqlite3DebugPrintf(" ");
+ sqlite3PrintExpr(p->pRight);
+ }
+ sqlite3DebugPrintf(")");
+}
+void sqlite3PrintExprList(ExprList *pList){
+ int i;
+ for(i=0; inExpr; i++){
+ sqlite3PrintExpr(pList->a[i].pExpr);
+ if( inExpr-1 ){
+ sqlite3DebugPrintf(", ");
+ }
+ }
+}
+void sqlite3PrintSelect(Select *p, int indent){
+ sqlite3DebugPrintf("%*sSELECT(%p) ", indent, "", p);
+ sqlite3PrintExprList(p->pEList);
+ sqlite3DebugPrintf("\n");
+ if( p->pSrc ){
+ char *zPrefix;
+ int i;
+ zPrefix = "FROM";
+ for(i=0; ipSrc->nSrc; i++){
+ struct SrcList_item *pItem = &p->pSrc->a[i];
+ sqlite3DebugPrintf("%*s ", indent+6, zPrefix);
+ zPrefix = "";
+ if( pItem->pSelect ){
+ sqlite3DebugPrintf("(\n");
+ sqlite3PrintSelect(pItem->pSelect, indent+10);
+ sqlite3DebugPrintf("%*s)", indent+8, "");
+ }else if( pItem->zName ){
+ sqlite3DebugPrintf("%s", pItem->zName);
+ }
+ if( pItem->pTab ){
+ sqlite3DebugPrintf("(table: %s)", pItem->pTab->zName);
+ }
+ if( pItem->zAlias ){
+ sqlite3DebugPrintf(" AS %s", pItem->zAlias);
+ }
+ if( ipSrc->nSrc-1 ){
+ sqlite3DebugPrintf(",");
+ }
+ sqlite3DebugPrintf("\n");
+ }
+ }
+ if( p->pWhere ){
+ sqlite3DebugPrintf("%*s WHERE ", indent, "");
+ sqlite3PrintExpr(p->pWhere);
+ sqlite3DebugPrintf("\n");
+ }
+ if( p->pGroupBy ){
+ sqlite3DebugPrintf("%*s GROUP BY ", indent, "");
+ sqlite3PrintExprList(p->pGroupBy);
+ sqlite3DebugPrintf("\n");
+ }
+ if( p->pHaving ){
+ sqlite3DebugPrintf("%*s HAVING ", indent, "");
+ sqlite3PrintExpr(p->pHaving);
+ sqlite3DebugPrintf("\n");
+ }
+ if( p->pOrderBy ){
+ sqlite3DebugPrintf("%*s ORDER BY ", indent, "");
+ sqlite3PrintExprList(p->pOrderBy);
+ sqlite3DebugPrintf("\n");
+ }
+}
+/* End of the structure debug printing code
+*****************************************************************************/
+#endif /* defined(SQLITE_TEST) || defined(SQLITE_DEBUG) */
diff --git a/dlls/sqlite/sqlite-source/shell.c b/dlls/sqlite/sqlite-source/shell.c
index 8aafed42..0cf75e20 100644
--- a/dlls/sqlite/sqlite-source/shell.c
+++ b/dlls/sqlite/sqlite-source/shell.c
@@ -21,7 +21,7 @@
#include "sqlite3.h"
#include
-#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__)
+#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__) && !defined(__OS2__)
# include
# include
# include
@@ -37,6 +37,10 @@
# include
#endif
+#ifdef __OS2__
+# include
+#endif
+
#if defined(HAVE_READLINE) && HAVE_READLINE==1
# include
# include
@@ -48,9 +52,25 @@
# define stifle_history(X)
#endif
+#if defined(_WIN32) || defined(WIN32)
+# include
+#else
/* Make sure isatty() has a prototype.
*/
extern int isatty();
+#endif
+
+/*
+** If the following flag is set, then command execution stops
+** at an error if we are not interactive.
+*/
+static int bail_on_error = 0;
+
+/*
+** Threat stdin as an interactive input if the following variable
+** is true. Otherwise, assume stdin is connected to a file or pipe.
+*/
+static int stdin_is_interactive = 1;
/*
** The following is the open SQLite database. We make a pointer
@@ -176,10 +196,7 @@ static char *local_getline(char *zPrompt, FILE *in){
}
/*
-** Retrieve a single line of input text. "isatty" is true if text
-** is coming from a terminal. In that case, we issue a prompt and
-** attempt to use "readline" for command-line editing. If "isatty"
-** is false, use "local_getline" instead of "readline" and issue no prompt.
+** Retrieve a single line of input text.
**
** zPrior is a string of prior text retrieved. If not the empty
** string, then issue a continuation prompt.
@@ -197,7 +214,7 @@ static char *one_input_line(const char *zPrior, FILE *in){
}
zResult = readline(zPrompt);
#if defined(HAVE_READLINE) && HAVE_READLINE==1
- if( zResult ) add_history(zResult);
+ if( zResult && *zResult ) add_history(zResult);
#endif
return zResult;
}
@@ -208,6 +225,7 @@ struct previous_mode_data {
int showHeader;
int colWidth[100];
};
+
/*
** An pointer to an instance of this structure is passed from
** the main program to the callback. This is used to communicate
@@ -219,6 +237,7 @@ struct callback_data {
int cnt; /* Number of records displayed so far */
FILE *out; /* Write results here */
int mode; /* An output mode setting */
+ int writableSchema; /* True if PRAGMA writable_schema=ON */
int showHeader; /* True to show column names in List or Column mode */
char *zDestTable; /* Name of destination table when MODE_Insert */
char separator[20]; /* Separator character for MODE_List */
@@ -231,7 +250,6 @@ struct callback_data {
** .explain ON */
char outfile[FILENAME_MAX]; /* Filename for *out */
const char *zDbFilename; /* name of the database file */
- char *zKey; /* Encryption key */
};
/*
@@ -343,6 +361,29 @@ static void output_html_string(FILE *out, const char *z){
}
}
+/*
+** If a field contains any character identified by a 1 in the following
+** array, then the string must be quoted for CSV.
+*/
+static const char needCsvQuote[] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+};
+
/*
** Output a single term of CSV. Actually, p->separator is used for
** the separator, which may or may not be a comma. p->nullvalue is
@@ -350,12 +391,27 @@ static void output_html_string(FILE *out, const char *z){
** appear outside of quotes.
*/
static void output_csv(struct callback_data *p, const char *z, int bSep){
+ FILE *out = p->out;
if( z==0 ){
- fprintf(p->out,"%s",p->nullvalue);
- }else if( isNumber(z, 0) ){
- fprintf(p->out,"%s",z);
+ fprintf(out,"%s",p->nullvalue);
}else{
- output_c_string(p->out, z);
+ int i;
+ for(i=0; z[i]; i++){
+ if( needCsvQuote[((unsigned char*)z)[i]] ){
+ i = 0;
+ break;
+ }
+ }
+ if( i==0 ){
+ putc('"', out);
+ for(i=0; z[i]; i++){
+ if( z[i]=='"' ) putc('"', out);
+ putc(z[i], out);
+ }
+ putc('"', out);
+ }else{
+ fprintf(out, "%s", z);
+ }
}
if( bSep ){
fprintf(p->out, p->separator);
@@ -384,12 +440,12 @@ static int callback(void *pArg, int nArg, char **azArg, char **azCol){
int w = 5;
if( azArg==0 ) break;
for(i=0; iw ) w = len;
}
if( p->cnt++>0 ) fprintf(p->out,"\n");
for(i=0; iout,"%*s = %s\n", w, azCol[i],
+ fprintf(p->out,"%*s = %s\n", w, azCol[i],
azArg[i] ? azArg[i] : p->nullvalue);
}
break;
@@ -486,7 +542,7 @@ static int callback(void *pArg, int nArg, char **azArg, char **azCol){
case MODE_Tcl: {
if( p->cnt++==0 && p->showHeader ){
for(i=0; iout,azCol[i]);
+ output_c_string(p->out,azCol[i] ? azCol[i] : "");
fprintf(p->out, "%s", p->separator);
}
fprintf(p->out,"\n");
@@ -502,7 +558,7 @@ static int callback(void *pArg, int nArg, char **azArg, char **azCol){
case MODE_Csv: {
if( p->cnt++==0 && p->showHeader ){
for(i=0; iout,"\n");
}
@@ -580,7 +636,7 @@ static void set_table_name(struct callback_data *p, const char *zName){
** If the third argument, quote, is not '\0', then it is used as a
** quote character for zAppend.
*/
-static char * appendText(char *zIn, char const *zAppend, char quote){
+static char *appendText(char *zIn, char const *zAppend, char quote){
int len;
int i;
int nAppend = strlen(zAppend);
@@ -621,6 +677,9 @@ static char * appendText(char *zIn, char const *zAppend, char quote){
/*
** Execute a query statement that has a single result column. Print
** that result column on a line by itself with a semicolon terminator.
+**
+** This is used, for example, to show the schema of the database by
+** querying the SQLITE_MASTER table.
*/
static int run_table_dump_query(FILE *out, sqlite3 *db, const char *zSelect){
sqlite3_stmt *pSelect;
@@ -662,6 +721,19 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
fprintf(p->out, "ANALYZE sqlite_master;\n");
}else if( strncmp(zTable, "sqlite_", 7)==0 ){
return 0;
+ }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
+ char *zIns;
+ if( !p->writableSchema ){
+ fprintf(p->out, "PRAGMA writable_schema=ON;\n");
+ p->writableSchema = 1;
+ }
+ zIns = sqlite3_mprintf(
+ "INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"
+ "VALUES('table','%q','%q',0,'%q');",
+ zTable, zTable, zSql);
+ fprintf(p->out, "%s\n", zIns);
+ sqlite3_free(zIns);
+ return 0;
}else{
fprintf(p->out, "%s;\n", zSql);
}
@@ -695,7 +767,7 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
zSelect = appendText(zSelect, zText, '"');
rc = sqlite3_step(pTableInfo);
if( rc==SQLITE_ROW ){
- zSelect = appendText(zSelect, ") || ', ' || ", 0);
+ zSelect = appendText(zSelect, ") || ',' || ", 0);
}else{
zSelect = appendText(zSelect, ") ", 0);
}
@@ -714,15 +786,14 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
rc = run_table_dump_query(p->out, p->db, zSelect);
}
if( zSelect ) free(zSelect);
- if( rc!=SQLITE_OK ){
- return 1;
- }
}
return 0;
}
/*
-** Run zQuery. Update dump_callback() as the callback routine.
+** Run zQuery. Use dump_callback() as the callback routine so that
+** the contents of the query are output as SQL statements.
+**
** If we get a SQLITE_CORRUPT error, rerun the query after appending
** "ORDER BY rowid DESC" to the end.
*/
@@ -750,6 +821,7 @@ static int run_schema_dump_query(
** Text of a help message
*/
static char zHelp[] =
+ ".bail ON|OFF Stop after hitting an error. Default OFF\n"
".databases List names and files of attached databases\n"
".dump ?TABLE? ... Dump the database in an SQL text format\n"
".echo ON|OFF Turn command echo on or off\n"
@@ -759,6 +831,9 @@ static char zHelp[] =
".help Show this message\n"
".import FILE TABLE Import data from FILE into TABLE\n"
".indices TABLE Show names of all indices on TABLE\n"
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+ ".load FILE ?ENTRY? Load an extension library\n"
+#endif
".mode MODE ?TABLE? Set output mode where MODE is one of:\n"
" csv Comma-separated values\n"
" column Left-aligned columns. (See .width)\n"
@@ -783,7 +858,7 @@ static char zHelp[] =
;
/* Forward reference */
-static void process_input(struct callback_data *p, FILE *in);
+static int process_input(struct callback_data *p, FILE *in);
/*
** Make sure the database is open. If it is not, then open it. If
@@ -800,6 +875,9 @@ static void open_db(struct callback_data *p){
p->zDbFilename, sqlite3_errmsg(db));
exit(1);
}
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+ sqlite3_enable_load_extension(p->db, 1);
+#endif
}
}
@@ -840,11 +918,28 @@ static void resolve_backslashes(char *z){
z[j] = 0;
}
+/*
+** Interpret zArg as a boolean value. Return either 0 or 1.
+*/
+static int booleanValue(char *zArg){
+ int val = atoi(zArg);
+ int j;
+ for(j=0; zArg[j]; j++){
+ zArg[j] = tolower(zArg[j]);
+ }
+ if( strcmp(zArg,"on")==0 ){
+ val = 1;
+ }else if( strcmp(zArg,"yes")==0 ){
+ val = 1;
+ }
+ return val;
+}
+
/*
** If an input line begins with "." then invoke this routine to
** process that line.
**
-** Return 1 to exit and 0 to continue.
+** Return 1 on error, 2 to exit, and 0 otherwise.
*/
static int do_meta_command(char *zLine, struct callback_data *p){
int i = 1;
@@ -879,6 +974,10 @@ static int do_meta_command(char *zLine, struct callback_data *p){
if( nArg==0 ) return rc;
n = strlen(azArg[0]);
c = azArg[0][0];
+ if( c=='b' && n>1 && strncmp(azArg[0], "bail", n)==0 && nArg>1 ){
+ bail_on_error = booleanValue(azArg[1]);
+ }else
+
if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
struct callback_data data;
char *zErrMsg = 0;
@@ -901,14 +1000,15 @@ static int do_meta_command(char *zLine, struct callback_data *p){
char *zErrMsg = 0;
open_db(p);
fprintf(p->out, "BEGIN TRANSACTION;\n");
+ p->writableSchema = 0;
if( nArg==1 ){
run_schema_dump_query(p,
"SELECT name, type, sql FROM sqlite_master "
"WHERE sql NOT NULL AND type=='table'", 0
);
- run_schema_dump_query(p,
- "SELECT name, type, sql FROM sqlite_master "
- "WHERE sql NOT NULL AND type!='table' AND type!='meta'", 0
+ run_table_dump_query(p->out, p->db,
+ "SELECT sql FROM sqlite_master "
+ "WHERE sql NOT NULL AND type IN ('index','trigger','view')"
);
}else{
int i;
@@ -918,13 +1018,19 @@ static int do_meta_command(char *zLine, struct callback_data *p){
"SELECT name, type, sql FROM sqlite_master "
"WHERE tbl_name LIKE shellstatic() AND type=='table'"
" AND sql NOT NULL", 0);
- run_schema_dump_query(p,
- "SELECT name, type, sql FROM sqlite_master "
- "WHERE tbl_name LIKE shellstatic() AND type!='table'"
- " AND type!='meta' AND sql NOT NULL", 0);
+ run_table_dump_query(p->out, p->db,
+ "SELECT sql FROM sqlite_master "
+ "WHERE sql NOT NULL"
+ " AND type IN ('index','trigger','view')"
+ " AND tbl_name LIKE shellstatic()"
+ );
zShellStatic = 0;
}
}
+ if( p->writableSchema ){
+ fprintf(p->out, "PRAGMA writable_schema=OFF;\n");
+ p->writableSchema = 0;
+ }
if( zErrMsg ){
fprintf(stderr,"Error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
@@ -934,37 +1040,15 @@ static int do_meta_command(char *zLine, struct callback_data *p){
}else
if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 ){
- int j;
- char *z = azArg[1];
- int val = atoi(azArg[1]);
- for(j=0; z[j]; j++){
- z[j] = tolower((unsigned char)z[j]);
- }
- if( strcmp(z,"on")==0 ){
- val = 1;
- }else if( strcmp(z,"yes")==0 ){
- val = 1;
- }
- p->echoOn = val;
+ p->echoOn = booleanValue(azArg[1]);
}else
if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
- rc = 1;
+ rc = 2;
}else
if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
- int j;
- static char zOne[] = "1";
- char *z = nArg>=2 ? azArg[1] : zOne;
- int val = atoi(z);
- for(j=0; z[j]; j++){
- z[j] = tolower((unsigned char)z[j]);
- }
- if( strcmp(z,"on")==0 ){
- val = 1;
- }else if( strcmp(z,"yes")==0 ){
- val = 1;
- }
+ int val = nArg>=2 ? booleanValue(azArg[1]) : 1;
if(val == 1) {
if(!p->explainPrev.valid) {
p->explainPrev.valid = 1;
@@ -995,21 +1079,9 @@ static int do_meta_command(char *zLine, struct callback_data *p){
}
}else
- if( c=='h' && (strncmp(azArg[0], "header", n)==0
- ||
+ if( c=='h' && (strncmp(azArg[0], "header", n)==0 ||
strncmp(azArg[0], "headers", n)==0 )&& nArg>1 ){
- int j;
- char *z = azArg[1];
- int val = atoi(azArg[1]);
- for(j=0; z[j]; j++){
- z[j] = tolower((unsigned char)z[j]);
- }
- if( strcmp(z,"on")==0 ){
- val = 1;
- }else if( strcmp(z,"yes")==0 ){
- val = 1;
- }
- p->showHeader = val;
+ p->showHeader = booleanValue(azArg[1]);
}else
if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
@@ -1032,6 +1104,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
FILE *in; /* The input file */
int lineno = 0; /* Line number of input file */
+ open_db(p);
nSep = strlen(p->separator);
if( nSep==0 ){
fprintf(stderr, "non-null separator required for import\n");
@@ -1045,6 +1118,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
if( rc ){
fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db));
nCol = 0;
+ rc = 1;
}else{
nCol = sqlite3_column_count(pStmt);
}
@@ -1065,7 +1139,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
if( rc ){
fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
sqlite3_finalize(pStmt);
- return 0;
+ return 1;
}
in = fopen(zFile, "rb");
if( in==0 ){
@@ -1111,6 +1185,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
if( rc!=SQLITE_OK ){
fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db));
zCommit = "ROLLBACK";
+ rc = 1;
break;
}
}
@@ -1144,6 +1219,23 @@ static int do_meta_command(char *zLine, struct callback_data *p){
}
}else
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+ if( c=='l' && strncmp(azArg[0], "load", n)==0 && nArg>=2 ){
+ const char *zFile, *zProc;
+ char *zErrMsg = 0;
+ int rc;
+ zFile = azArg[1];
+ zProc = nArg>=3 ? azArg[2] : 0;
+ open_db(p);
+ rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
+ if( rc!=SQLITE_OK ){
+ fprintf(stderr, "%s\n", zErrMsg);
+ sqlite3_free(zErrMsg);
+ rc = 1;
+ }
+ }else
+#endif
+
if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg>=2 ){
int n2 = strlen(azArg[1]);
if( strncmp(azArg[1],"line",n2)==0
@@ -1174,7 +1266,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
set_table_name(p, "table");
}
}else {
- fprintf(stderr,"mode should be on of: "
+ fprintf(stderr,"mode should be one of: "
"column csv html insert line list tabs tcl\n");
}
}else
@@ -1211,7 +1303,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
}else
if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
- rc = 1;
+ rc = 2;
}else
if( c=='r' && strncmp(azArg[0], "read", n)==0 && nArg==2 ){
@@ -1363,6 +1455,8 @@ static int do_meta_command(char *zLine, struct callback_data *p){
}
printf("\n");
}
+ }else{
+ rc = 1;
}
sqlite3_free_table(azResult);
}else
@@ -1442,24 +1536,40 @@ static int _is_command_terminator(const char *zLine){
** is coming from a file or device. A prompt is issued and history
** is saved only if input is interactive. An interrupt signal will
** cause this routine to exit immediately, unless input is interactive.
+**
+** Return the number of errors.
*/
-static void process_input(struct callback_data *p, FILE *in){
+static int process_input(struct callback_data *p, FILE *in){
char *zLine;
char *zSql = 0;
int nSql = 0;
char *zErrMsg;
int rc;
- while( fflush(p->out), (zLine = one_input_line(zSql, in))!=0 ){
+ int errCnt = 0;
+ int lineno = 0;
+ int startline = 0;
+
+ while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){
+ fflush(p->out);
+ zLine = one_input_line(zSql, in);
+ if( zLine==0 ){
+ break; /* We have reached EOF */
+ }
if( seenInterrupt ){
if( in!=0 ) break;
seenInterrupt = 0;
}
+ lineno++;
if( p->echoOn ) printf("%s\n", zLine);
if( (zSql==0 || zSql[0]==0) && _all_whitespace(zLine) ) continue;
if( zLine && zLine[0]=='.' && nSql==0 ){
- int rc = do_meta_command(zLine, p);
+ rc = do_meta_command(zLine, p);
free(zLine);
- if( rc ) break;
+ if( rc==2 ){
+ break;
+ }else if( rc ){
+ errCnt++;
+ }
continue;
}
if( _is_command_terminator(zLine) ){
@@ -1471,7 +1581,12 @@ static void process_input(struct callback_data *p, FILE *in){
if( zLine[i]!=0 ){
nSql = strlen(zLine);
zSql = malloc( nSql+1 );
+ if( zSql==0 ){
+ fprintf(stderr, "out of memory\n");
+ exit(1);
+ }
strcpy(zSql, zLine);
+ startline = lineno;
}
}else{
int len = strlen(zLine);
@@ -1490,14 +1605,20 @@ static void process_input(struct callback_data *p, FILE *in){
open_db(p);
rc = sqlite3_exec(p->db, zSql, callback, p, &zErrMsg);
if( rc || zErrMsg ){
- /* if( in!=0 && !p->echoOn ) printf("%s\n",zSql); */
+ char zPrefix[100];
+ if( in!=0 || !stdin_is_interactive ){
+ sprintf(zPrefix, "SQL error near line %d:", startline);
+ }else{
+ sprintf(zPrefix, "SQL error:");
+ }
if( zErrMsg!=0 ){
- printf("SQL error: %s\n", zErrMsg);
+ printf("%s %s\n", zPrefix, zErrMsg);
sqlite3_free(zErrMsg);
zErrMsg = 0;
}else{
- printf("SQL error: %s\n", sqlite3_errmsg(p->db));
+ printf("%s %s\n", zPrefix, sqlite3_errmsg(p->db));
}
+ errCnt++;
}
free(zSql);
zSql = 0;
@@ -1508,6 +1629,7 @@ static void process_input(struct callback_data *p, FILE *in){
if( !_all_whitespace(zSql) ) printf("Incomplete SQL: %s\n", zSql);
free(zSql);
}
+ return errCnt;
}
/*
@@ -1519,7 +1641,7 @@ static void process_input(struct callback_data *p, FILE *in){
static char *find_home_dir(void){
char *home_dir = NULL;
-#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__)
+#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__) && !defined(__OS2__)
struct passwd *pwent;
uid_t uid = getuid();
if( (pwent=getpwuid(uid)) != NULL) {
@@ -1532,16 +1654,30 @@ static char *find_home_dir(void){
home_dir = getcwd(home_path, _MAX_PATH);
#endif
+#if defined(_WIN32) || defined(WIN32) || defined(__OS2__)
+ if (!home_dir) {
+ home_dir = getenv("USERPROFILE");
+ }
+#endif
+
if (!home_dir) {
home_dir = getenv("HOME");
- if (!home_dir) {
- home_dir = getenv("HOMEPATH"); /* Windows? */
- }
}
-#if defined(_WIN32) || defined(WIN32)
+#if defined(_WIN32) || defined(WIN32) || defined(__OS2__)
if (!home_dir) {
- home_dir = "c:";
+ char *zDrive, *zPath;
+ int n;
+ zDrive = getenv("HOMEDRIVE");
+ zPath = getenv("HOMEPATH");
+ if( zDrive && zPath ){
+ n = strlen(zDrive) + strlen(zPath) + 1;
+ home_dir = malloc( n );
+ if( home_dir==0 ) return 0;
+ sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath);
+ return home_dir;
+ }
+ home_dir = "c:\\";
}
#endif
@@ -1584,7 +1720,7 @@ static void process_sqliterc(
}
in = fopen(sqliterc,"rb");
if( in ){
- if( isatty(fileno(stdout)) ){
+ if( stdin_is_interactive ){
printf("Loading resources from %s\n",sqliterc);
}
process_input(p,in);
@@ -1601,19 +1737,25 @@ static const char zOptions[] =
" -init filename read/process named file\n"
" -echo print commands before execution\n"
" -[no]header turn headers on or off\n"
+ " -bail stop after hitting an error\n"
+ " -interactive force interactive I/O\n"
+ " -batch force batch I/O\n"
" -column set output mode to 'column'\n"
+ " -csv set output mode to 'csv'\n"
" -html set output mode to HTML\n"
" -line set output mode to 'line'\n"
" -list set output mode to 'list'\n"
" -separator 'x' set output field separator (|)\n"
" -nullvalue 'text' set text string for NULL values\n"
" -version show SQLite version\n"
- " -help show this text, also show dot-commands\n"
;
static void usage(int showDetail){
- fprintf(stderr, "Usage: %s [OPTIONS] FILENAME [SQL]\n", Argv0);
+ fprintf(stderr,
+ "Usage: %s [OPTIONS] FILENAME [SQL]\n"
+ "FILENAME is the name of an SQLite database. A new database is created\n"
+ "if the file does not previously exist.\n", Argv0);
if( showDetail ){
- fprintf(stderr, "Options are:\n%s", zOptions);
+ fprintf(stderr, "OPTIONS include:\n%s", zOptions);
}else{
fprintf(stderr, "Use the -help option for additional information\n");
}
@@ -1638,6 +1780,7 @@ int main(int argc, char **argv){
const char *zInitFile = 0;
char *zFirstCmd = 0;
int i;
+ int rc = 0;
#ifdef __MACOS__
argc = ccommand(&argv);
@@ -1645,6 +1788,7 @@ int main(int argc, char **argv){
Argv0 = argv[0];
main_init(&data);
+ stdin_is_interactive = isatty(0);
/* Make sure we have a valid signal handler early, before anything
** else is done.
@@ -1658,15 +1802,15 @@ int main(int argc, char **argv){
** and the first command to execute.
*/
for(i=1; i", where
@@ -48,7 +48,7 @@ extern "C" {
#ifdef SQLITE_VERSION_NUMBER
# undef SQLITE_VERSION_NUMBER
#endif
-#define SQLITE_VERSION_NUMBER 3003005
+#define SQLITE_VERSION_NUMBER 3003013
/*
** The version string is also compiled into the library so that a program
@@ -125,7 +125,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
** value then the query is aborted, all subsequent SQL statements
** are skipped and the sqlite3_exec() function returns the SQLITE_ABORT.
**
-** The 4th parameter is an arbitrary pointer that is passed
+** The 1st parameter is an arbitrary pointer that is passed
** to the callback function as its first parameter.
**
** The 2nd parameter to the callback function is the number of
@@ -198,6 +198,44 @@ int sqlite3_exec(
#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */
/* end-of-error-codes */
+/*
+** Using the sqlite3_extended_result_codes() API, you can cause
+** SQLite to return result codes with additional information in
+** their upper bits. The lower 8 bits will be the same as the
+** primary result codes above. But the upper bits might contain
+** more specific error information.
+**
+** To extract the primary result code from an extended result code,
+** simply mask off the lower 8 bits.
+**
+** primary = extended & 0xff;
+**
+** New result error codes may be added from time to time. Software
+** that uses the extended result codes should plan accordingly and be
+** sure to always handle new unknown codes gracefully.
+**
+** The SQLITE_OK result code will never be extended. It will always
+** be exactly zero.
+**
+** The extended result codes always have the primary result code
+** as a prefix. Primary result codes only contain a single "_"
+** character. Extended result codes contain two or more "_" characters.
+*/
+#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
+#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
+#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8))
+#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8))
+#define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8))
+#define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8))
+#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8))
+#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8))
+#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8))
+
+/*
+** Enable or disable the extended result codes.
+*/
+int sqlite3_extended_result_codes(sqlite3*, int onoff);
+
/*
** Each entry in an SQLite table has a unique integer key. (The key is
** the value of the INTEGER PRIMARY KEY column if there is such a column,
@@ -277,13 +315,30 @@ int sqlite3_complete16(const void *sql);
** currently locked by another process or thread. If the busy callback
** is NULL, then sqlite3_exec() returns SQLITE_BUSY immediately if
** it finds a locked table. If the busy callback is not NULL, then
-** sqlite3_exec() invokes the callback with three arguments. The
-** second argument is the name of the locked table and the third
-** argument is the number of times the table has been busy. If the
+** sqlite3_exec() invokes the callback with two arguments. The
+** first argument to the handler is a copy of the void* pointer which
+** is the third argument to this routine. The second argument to
+** the handler is the number of times that the busy handler has
+** been invoked for this locking event. If the
** busy callback returns 0, then sqlite3_exec() immediately returns
** SQLITE_BUSY. If the callback returns non-zero, then sqlite3_exec()
** tries to open the table again and the cycle repeats.
**
+** The presence of a busy handler does not guarantee that
+** it will be invoked when there is lock contention.
+** If SQLite determines that invoking the busy handler could result in
+** a deadlock, it will return SQLITE_BUSY instead.
+** Consider a scenario where one process is holding a read lock that
+** it is trying to promote to a reserved lock and
+** a second process is holding a reserved lock that it is trying
+** to promote to an exclusive lock. The first process cannot proceed
+** because it is blocked by the second and the second process cannot
+** proceed because it is blocked by the first. If both processes
+** invoke the busy handlers, neither will make any progress. Therefore,
+** SQLite returns SQLITE_BUSY for the first process, hoping that this
+** will induce the first process to release its read lock and allow
+** the second process to proceed.
+**
** The default busy callback is NULL.
**
** Sqlite is re-entrant, so the busy handler may start a new query.
@@ -405,9 +460,19 @@ void sqlite3_free_table(char **result);
*/
char *sqlite3_mprintf(const char*,...);
char *sqlite3_vmprintf(const char*, va_list);
-void sqlite3_free(char *z);
char *sqlite3_snprintf(int,char*,const char*, ...);
+/*
+** SQLite uses its own memory allocator. On many installations, this
+** memory allocator is identical to the standard malloc()/realloc()/free()
+** and can be used interchangable. On others, the implementations are
+** different. For maximum portability, it is best not to mix calls
+** to the standard malloc/realloc/free with the sqlite versions.
+*/
+void *sqlite3_malloc(int);
+void *sqlite3_realloc(void*, int);
+void sqlite3_free(void*);
+
#ifndef SQLITE_OMIT_AUTHORIZATION
/*
** This routine registers a callback with the SQLite library. The
@@ -466,7 +531,9 @@ int sqlite3_set_authorizer(
#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */
#define SQLITE_REINDEX 27 /* Index Name NULL */
#define SQLITE_ANALYZE 28 /* Table Name NULL */
-
+#define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */
+#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */
+#define SQLITE_FUNCTION 31 /* Function Name NULL */
/*
** The return value of the authorization function should be one of the
@@ -642,6 +709,31 @@ int sqlite3_prepare16(
const void **pzTail /* OUT: Pointer to unused portion of zSql */
);
+/*
+** Newer versions of the prepare API work just like the legacy versions
+** but with one exception: The a copy of the SQL text is saved in the
+** sqlite3_stmt structure that is returned. If this copy exists, it
+** modifieds the behavior of sqlite3_step() slightly. First, sqlite3_step()
+** will no longer return an SQLITE_SCHEMA error but will instead automatically
+** rerun the compiler to rebuild the prepared statement. Secondly,
+** sqlite3_step() now turns a full result code - the result code that
+** use used to have to call sqlite3_reset() to get.
+*/
+int sqlite3_prepare_v2(
+ sqlite3 *db, /* Database handle */
+ const char *zSql, /* SQL statement, UTF-8 encoded */
+ int nBytes, /* Length of zSql in bytes. */
+ sqlite3_stmt **ppStmt, /* OUT: Statement handle */
+ const char **pzTail /* OUT: Pointer to unused portion of zSql */
+);
+int sqlite3_prepare16_v2(
+ sqlite3 *db, /* Database handle */
+ const void *zSql, /* SQL statement, UTF-16 encoded */
+ int nBytes, /* Length of zSql in bytes. */
+ sqlite3_stmt **ppStmt, /* OUT: Statement handle */
+ const void **pzTail /* OUT: Pointer to unused portion of zSql */
+);
+
/*
** Pointers to the following two opaque structures are used to communicate
** with the implementations of user-defined functions.
@@ -926,6 +1018,7 @@ const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
int sqlite3_column_type(sqlite3_stmt*, int iCol);
int sqlite3_column_numeric_type(sqlite3_stmt*, int iCol);
+sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
/*
** The sqlite3_finalize() function is called to delete a compiled
@@ -1092,9 +1185,13 @@ void sqlite3_set_auxdata(sqlite3_context*, int, void*, void (*)(void*));
** SQLITE_TRANSIENT value means that the content will likely change in
** the near future and that SQLite should make its own private copy of
** the content before returning.
+**
+** The typedef is necessary to work around problems in certain
+** C++ compilers. See ticket #2191.
*/
-#define SQLITE_STATIC ((void(*)(void *))0)
-#define SQLITE_TRANSIENT ((void(*)(void *))-1)
+typedef void (*sqlite3_destructor_type)(void*);
+#define SQLITE_STATIC ((sqlite3_destructor_type)0)
+#define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1)
/*
** User-defined functions invoke the following routines in order to
@@ -1468,6 +1565,299 @@ int sqlite3_table_column_metadata(
int *pAutoinc /* OUTPUT: True if colums is auto-increment */
);
+/*
+****** EXPERIMENTAL - subject to change without notice **************
+**
+** Attempt to load an SQLite extension library contained in the file
+** zFile. The entry point is zProc. zProc may be 0 in which case the
+** name of the entry point defaults to "sqlite3_extension_init".
+**
+** Return SQLITE_OK on success and SQLITE_ERROR if something goes wrong.
+**
+** If an error occurs and pzErrMsg is not 0, then fill *pzErrMsg with
+** error message text. The calling function should free this memory
+** by calling sqlite3_free().
+**
+** Extension loading must be enabled using sqlite3_enable_load_extension()
+** prior to calling this API or an error will be returned.
+**
+****** EXPERIMENTAL - subject to change without notice **************
+*/
+int sqlite3_load_extension(
+ sqlite3 *db, /* Load the extension into this database connection */
+ const char *zFile, /* Name of the shared library containing extension */
+ const char *zProc, /* Entry point. Derived from zFile if 0 */
+ char **pzErrMsg /* Put error message here if not 0 */
+);
+
+/*
+** So as not to open security holes in older applications that are
+** unprepared to deal with extension load, and as a means of disabling
+** extension loading while executing user-entered SQL, the following
+** API is provided to turn the extension loading mechanism on and
+** off. It is off by default. See ticket #1863.
+**
+** Call this routine with onoff==1 to turn extension loading on
+** and call it with onoff==0 to turn it back off again.
+*/
+int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
+
+/*
+****** EXPERIMENTAL - subject to change without notice **************
+**
+** Register an extension entry point that is automatically invoked
+** whenever a new database connection is opened.
+**
+** This API can be invoked at program startup in order to register
+** one or more statically linked extensions that will be available
+** to all new database connections.
+**
+** Duplicate extensions are detected so calling this routine multiple
+** times with the same extension is harmless.
+**
+** This routine stores a pointer to the extension in an array
+** that is obtained from malloc(). If you run a memory leak
+** checker on your program and it reports a leak because of this
+** array, then invoke sqlite3_automatic_extension_reset() prior
+** to shutdown to free the memory.
+**
+** Automatic extensions apply across all threads.
+*/
+int sqlite3_auto_extension(void *xEntryPoint);
+
+
+/*
+****** EXPERIMENTAL - subject to change without notice **************
+**
+** Disable all previously registered automatic extensions. This
+** routine undoes the effect of all prior sqlite3_automatic_extension()
+** calls.
+**
+** This call disabled automatic extensions in all threads.
+*/
+void sqlite3_reset_auto_extension(void);
+
+
+/*
+****** EXPERIMENTAL - subject to change without notice **************
+**
+** The interface to the virtual-table mechanism is currently considered
+** to be experimental. The interface might change in incompatible ways.
+** If this is a problem for you, do not use the interface at this time.
+**
+** When the virtual-table mechanism stablizes, we will declare the
+** interface fixed, support it indefinitely, and remove this comment.
+*/
+
+/*
+** Structures used by the virtual table interface
+*/
+typedef struct sqlite3_vtab sqlite3_vtab;
+typedef struct sqlite3_index_info sqlite3_index_info;
+typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor;
+typedef struct sqlite3_module sqlite3_module;
+
+/*
+** A module is a class of virtual tables. Each module is defined
+** by an instance of the following structure. This structure consists
+** mostly of methods for the module.
+*/
+struct sqlite3_module {
+ int iVersion;
+ int (*xCreate)(sqlite3*, void *pAux,
+ int argc, const char *const*argv,
+ sqlite3_vtab **ppVTab, char**);
+ int (*xConnect)(sqlite3*, void *pAux,
+ int argc, const char *const*argv,
+ sqlite3_vtab **ppVTab, char**);
+ int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*);
+ int (*xDisconnect)(sqlite3_vtab *pVTab);
+ int (*xDestroy)(sqlite3_vtab *pVTab);
+ int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);
+ int (*xClose)(sqlite3_vtab_cursor*);
+ int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr,
+ int argc, sqlite3_value **argv);
+ int (*xNext)(sqlite3_vtab_cursor*);
+ int (*xEof)(sqlite3_vtab_cursor*);
+ int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int);
+ int (*xRowid)(sqlite3_vtab_cursor*, sqlite_int64 *pRowid);
+ int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite_int64 *);
+ int (*xBegin)(sqlite3_vtab *pVTab);
+ int (*xSync)(sqlite3_vtab *pVTab);
+ int (*xCommit)(sqlite3_vtab *pVTab);
+ int (*xRollback)(sqlite3_vtab *pVTab);
+ int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
+ void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
+ void **ppArg);
+};
+
+/*
+** The sqlite3_index_info structure and its substructures is used to
+** pass information into and receive the reply from the xBestIndex
+** method of an sqlite3_module. The fields under **Inputs** are the
+** inputs to xBestIndex and are read-only. xBestIndex inserts its
+** results into the **Outputs** fields.
+**
+** The aConstraint[] array records WHERE clause constraints of the
+** form:
+**
+** column OP expr
+**
+** Where OP is =, <, <=, >, or >=. The particular operator is stored
+** in aConstraint[].op. The index of the column is stored in
+** aConstraint[].iColumn. aConstraint[].usable is TRUE if the
+** expr on the right-hand side can be evaluated (and thus the constraint
+** is usable) and false if it cannot.
+**
+** The optimizer automatically inverts terms of the form "expr OP column"
+** and makes other simplificatinos to the WHERE clause in an attempt to
+** get as many WHERE clause terms into the form shown above as possible.
+** The aConstraint[] array only reports WHERE clause terms in the correct
+** form that refer to the particular virtual table being queried.
+**
+** Information about the ORDER BY clause is stored in aOrderBy[].
+** Each term of aOrderBy records a column of the ORDER BY clause.
+**
+** The xBestIndex method must fill aConstraintUsage[] with information
+** about what parameters to pass to xFilter. If argvIndex>0 then
+** the right-hand side of the corresponding aConstraint[] is evaluated
+** and becomes the argvIndex-th entry in argv. If aConstraintUsage[].omit
+** is true, then the constraint is assumed to be fully handled by the
+** virtual table and is not checked again by SQLite.
+**
+** The idxNum and idxPtr values are recorded and passed into xFilter.
+** sqlite3_free() is used to free idxPtr if needToFreeIdxPtr is true.
+**
+** The orderByConsumed means that output from xFilter will occur in
+** the correct order to satisfy the ORDER BY clause so that no separate
+** sorting step is required.
+**
+** The estimatedCost value is an estimate of the cost of doing the
+** particular lookup. A full scan of a table with N entries should have
+** a cost of N. A binary search of a table of N entries should have a
+** cost of approximately log(N).
+*/
+struct sqlite3_index_info {
+ /* Inputs */
+ const int nConstraint; /* Number of entries in aConstraint */
+ const struct sqlite3_index_constraint {
+ int iColumn; /* Column on left-hand side of constraint */
+ unsigned char op; /* Constraint operator */
+ unsigned char usable; /* True if this constraint is usable */
+ int iTermOffset; /* Used internally - xBestIndex should ignore */
+ } *const aConstraint; /* Table of WHERE clause constraints */
+ const int nOrderBy; /* Number of terms in the ORDER BY clause */
+ const struct sqlite3_index_orderby {
+ int iColumn; /* Column number */
+ unsigned char desc; /* True for DESC. False for ASC. */
+ } *const aOrderBy; /* The ORDER BY clause */
+
+ /* Outputs */
+ struct sqlite3_index_constraint_usage {
+ int argvIndex; /* if >0, constraint is part of argv to xFilter */
+ unsigned char omit; /* Do not code a test for this constraint */
+ } *const aConstraintUsage;
+ int idxNum; /* Number used to identify the index */
+ char *idxStr; /* String, possibly obtained from sqlite3_malloc */
+ int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */
+ int orderByConsumed; /* True if output is already ordered */
+ double estimatedCost; /* Estimated cost of using this index */
+};
+#define SQLITE_INDEX_CONSTRAINT_EQ 2
+#define SQLITE_INDEX_CONSTRAINT_GT 4
+#define SQLITE_INDEX_CONSTRAINT_LE 8
+#define SQLITE_INDEX_CONSTRAINT_LT 16
+#define SQLITE_INDEX_CONSTRAINT_GE 32
+#define SQLITE_INDEX_CONSTRAINT_MATCH 64
+
+/*
+** This routine is used to register a new module name with an SQLite
+** connection. Module names must be registered before creating new
+** virtual tables on the module, or before using preexisting virtual
+** tables of the module.
+*/
+int sqlite3_create_module(
+ sqlite3 *db, /* SQLite connection to register module with */
+ const char *zName, /* Name of the module */
+ const sqlite3_module *, /* Methods for the module */
+ void * /* Client data for xCreate/xConnect */
+);
+
+/*
+** Every module implementation uses a subclass of the following structure
+** to describe a particular instance of the module. Each subclass will
+** be taylored to the specific needs of the module implementation. The
+** purpose of this superclass is to define certain fields that are common
+** to all module implementations.
+**
+** Virtual tables methods can set an error message by assigning a
+** string obtained from sqlite3_mprintf() to zErrMsg. The method should
+** take care that any prior string is freed by a call to sqlite3_free()
+** prior to assigning a new string to zErrMsg. After the error message
+** is delivered up to the client application, the string will be automatically
+** freed by sqlite3_free() and the zErrMsg field will be zeroed. Note
+** that sqlite3_mprintf() and sqlite3_free() are used on the zErrMsg field
+** since virtual tables are commonly implemented in loadable extensions which
+** do not have access to sqlite3MPrintf() or sqlite3Free().
+*/
+struct sqlite3_vtab {
+ const sqlite3_module *pModule; /* The module for this virtual table */
+ int nRef; /* Used internally */
+ char *zErrMsg; /* Error message from sqlite3_mprintf() */
+ /* Virtual table implementations will typically add additional fields */
+};
+
+/* Every module implementation uses a subclass of the following structure
+** to describe cursors that point into the virtual table and are used
+** to loop through the virtual table. Cursors are created using the
+** xOpen method of the module. Each module implementation will define
+** the content of a cursor structure to suit its own needs.
+**
+** This superclass exists in order to define fields of the cursor that
+** are common to all implementations.
+*/
+struct sqlite3_vtab_cursor {
+ sqlite3_vtab *pVtab; /* Virtual table of this cursor */
+ /* Virtual table implementations will typically add additional fields */
+};
+
+/*
+** The xCreate and xConnect methods of a module use the following API
+** to declare the format (the names and datatypes of the columns) of
+** the virtual tables they implement.
+*/
+int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable);
+
+/*
+** Virtual tables can provide alternative implementations of functions
+** using the xFindFunction method. But global versions of those functions
+** must exist in order to be overloaded.
+**
+** This API makes sure a global version of a function with a particular
+** name and number of parameters exists. If no such function exists
+** before this API is called, a new function is created. The implementation
+** of the new function always causes an exception to be thrown. So
+** the new function is not good for anything by itself. Its only
+** purpose is to be a place-holder function that can be overloaded
+** by virtual tables.
+**
+** This API should be considered part of the virtual table interface,
+** which is experimental and subject to change.
+*/
+int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
+
+/*
+** The interface to the virtual-table mechanism defined above (back up
+** to a comment remarkably similar to this one) is currently considered
+** to be experimental. The interface might change in incompatible ways.
+** If this is a problem for you, do not use the interface at this time.
+**
+** When the virtual-table mechanism stablizes, we will declare the
+** interface fixed, support it indefinitely, and remove this comment.
+**
+****** EXPERIMENTAL - subject to change without notice **************
+*/
+
/*
** Undo the hack that converts floating point types to integer for
** builds on processors without floating point support.
diff --git a/dlls/sqlite/sqlite-source/sqlite3ext.h b/dlls/sqlite/sqlite-source/sqlite3ext.h
new file mode 100644
index 00000000..1df21d6a
--- /dev/null
+++ b/dlls/sqlite/sqlite-source/sqlite3ext.h
@@ -0,0 +1,282 @@
+/*
+** 2006 June 7
+**
+** 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 header file defines the SQLite interface for use by
+** shared libraries that want to be imported as extensions into
+** an SQLite instance. Shared libraries that intend to be loaded
+** as extensions by SQLite should #include this file instead of
+** sqlite3.h.
+**
+** @(#) $Id$
+*/
+#ifndef _SQLITE3EXT_H_
+#define _SQLITE3EXT_H_
+#include "sqlite3.h"
+
+typedef struct sqlite3_api_routines sqlite3_api_routines;
+
+/*
+** The following structure hold pointers to all of the SQLite API
+** routines.
+*/
+struct sqlite3_api_routines {
+ void * (*aggregate_context)(sqlite3_context*,int nBytes);
+ int (*aggregate_count)(sqlite3_context*);
+ int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*));
+ int (*bind_double)(sqlite3_stmt*,int,double);
+ int (*bind_int)(sqlite3_stmt*,int,int);
+ int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64);
+ int (*bind_null)(sqlite3_stmt*,int);
+ int (*bind_parameter_count)(sqlite3_stmt*);
+ int (*bind_parameter_index)(sqlite3_stmt*,const char*zName);
+ const char * (*bind_parameter_name)(sqlite3_stmt*,int);
+ int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*));
+ int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*));
+ int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*);
+ int (*busy_handler)(sqlite3*,int(*)(void*,int),void*);
+ int (*busy_timeout)(sqlite3*,int ms);
+ int (*changes)(sqlite3*);
+ int (*close)(sqlite3*);
+ int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,int eTextRep,const char*));
+ int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,int eTextRep,const void*));
+ const void * (*column_blob)(sqlite3_stmt*,int iCol);
+ int (*column_bytes)(sqlite3_stmt*,int iCol);
+ int (*column_bytes16)(sqlite3_stmt*,int iCol);
+ int (*column_count)(sqlite3_stmt*pStmt);
+ const char * (*column_database_name)(sqlite3_stmt*,int);
+ const void * (*column_database_name16)(sqlite3_stmt*,int);
+ const char * (*column_decltype)(sqlite3_stmt*,int i);
+ const void * (*column_decltype16)(sqlite3_stmt*,int);
+ double (*column_double)(sqlite3_stmt*,int iCol);
+ int (*column_int)(sqlite3_stmt*,int iCol);
+ sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol);
+ const char * (*column_name)(sqlite3_stmt*,int);
+ const void * (*column_name16)(sqlite3_stmt*,int);
+ const char * (*column_origin_name)(sqlite3_stmt*,int);
+ const void * (*column_origin_name16)(sqlite3_stmt*,int);
+ const char * (*column_table_name)(sqlite3_stmt*,int);
+ const void * (*column_table_name16)(sqlite3_stmt*,int);
+ const unsigned char * (*column_text)(sqlite3_stmt*,int iCol);
+ const void * (*column_text16)(sqlite3_stmt*,int iCol);
+ int (*column_type)(sqlite3_stmt*,int iCol);
+ sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol);
+ void * (*commit_hook)(sqlite3*,int(*)(void*),void*);
+ int (*complete)(const char*sql);
+ int (*complete16)(const void*sql);
+ int (*create_collation)(sqlite3*,const char*,int,void*,int(*)(void*,int,const void*,int,const void*));
+ int (*create_collation16)(sqlite3*,const char*,int,void*,int(*)(void*,int,const void*,int,const void*));
+ int (*create_function)(sqlite3*,const char*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*));
+ int (*create_function16)(sqlite3*,const void*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*));
+ int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*);
+ int (*data_count)(sqlite3_stmt*pStmt);
+ sqlite3 * (*db_handle)(sqlite3_stmt*);
+ int (*declare_vtab)(sqlite3*,const char*);
+ int (*enable_shared_cache)(int);
+ int (*errcode)(sqlite3*db);
+ const char * (*errmsg)(sqlite3*);
+ const void * (*errmsg16)(sqlite3*);
+ int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**);
+ int (*expired)(sqlite3_stmt*);
+ int (*finalize)(sqlite3_stmt*pStmt);
+ void (*free)(void*);
+ void (*free_table)(char**result);
+ int (*get_autocommit)(sqlite3*);
+ void * (*get_auxdata)(sqlite3_context*,int);
+ int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**);
+ int (*global_recover)(void);
+ void (*interruptx)(sqlite3*);
+ sqlite_int64 (*last_insert_rowid)(sqlite3*);
+ const char * (*libversion)(void);
+ int (*libversion_number)(void);
+ void *(*malloc)(int);
+ char * (*mprintf)(const char*,...);
+ int (*open)(const char*,sqlite3**);
+ int (*open16)(const void*,sqlite3**);
+ int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
+ int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
+ void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*);
+ void (*progress_handler)(sqlite3*,int,int(*)(void*),void*);
+ void *(*realloc)(void*,int);
+ int (*reset)(sqlite3_stmt*pStmt);
+ void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*));
+ void (*result_double)(sqlite3_context*,double);
+ void (*result_error)(sqlite3_context*,const char*,int);
+ void (*result_error16)(sqlite3_context*,const void*,int);
+ void (*result_int)(sqlite3_context*,int);
+ void (*result_int64)(sqlite3_context*,sqlite_int64);
+ void (*result_null)(sqlite3_context*);
+ void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*));
+ void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*));
+ void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*));
+ void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*));
+ void (*result_value)(sqlite3_context*,sqlite3_value*);
+ void * (*rollback_hook)(sqlite3*,void(*)(void*),void*);
+ int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,const char*,const char*),void*);
+ void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
+ char * (*snprintf)(int,char*,const char*,...);
+ int (*step)(sqlite3_stmt*);
+ int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,char const**,char const**,int*,int*,int*);
+ void (*thread_cleanup)(void);
+ int (*total_changes)(sqlite3*);
+ void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*);
+ int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*);
+ void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,sqlite_int64),void*);
+ void * (*user_data)(sqlite3_context*);
+ const void * (*value_blob)(sqlite3_value*);
+ int (*value_bytes)(sqlite3_value*);
+ int (*value_bytes16)(sqlite3_value*);
+ double (*value_double)(sqlite3_value*);
+ int (*value_int)(sqlite3_value*);
+ sqlite_int64 (*value_int64)(sqlite3_value*);
+ int (*value_numeric_type)(sqlite3_value*);
+ const unsigned char * (*value_text)(sqlite3_value*);
+ const void * (*value_text16)(sqlite3_value*);
+ const void * (*value_text16be)(sqlite3_value*);
+ const void * (*value_text16le)(sqlite3_value*);
+ int (*value_type)(sqlite3_value*);
+ char * (*vmprintf)(const char*,va_list);
+ int (*overload_function)(sqlite3*, const char *zFuncName, int nArg);
+};
+
+/*
+** The following macros redefine the API routines so that they are
+** redirected throught the global sqlite3_api structure.
+**
+** This header file is also used by the loadext.c source file
+** (part of the main SQLite library - not an extension) so that
+** it can get access to the sqlite3_api_routines structure
+** definition. But the main library does not want to redefine
+** the API. So the redefinition macros are only valid if the
+** SQLITE_CORE macros is undefined.
+*/
+#ifndef SQLITE_CORE
+#define sqlite3_aggregate_context sqlite3_api->aggregate_context
+#define sqlite3_aggregate_count sqlite3_api->aggregate_count
+#define sqlite3_bind_blob sqlite3_api->bind_blob
+#define sqlite3_bind_double sqlite3_api->bind_double
+#define sqlite3_bind_int sqlite3_api->bind_int
+#define sqlite3_bind_int64 sqlite3_api->bind_int64
+#define sqlite3_bind_null sqlite3_api->bind_null
+#define sqlite3_bind_parameter_count sqlite3_api->bind_parameter_count
+#define sqlite3_bind_parameter_index sqlite3_api->bind_parameter_index
+#define sqlite3_bind_parameter_name sqlite3_api->bind_parameter_name
+#define sqlite3_bind_text sqlite3_api->bind_text
+#define sqlite3_bind_text16 sqlite3_api->bind_text16
+#define sqlite3_bind_value sqlite3_api->bind_value
+#define sqlite3_busy_handler sqlite3_api->busy_handler
+#define sqlite3_busy_timeout sqlite3_api->busy_timeout
+#define sqlite3_changes sqlite3_api->changes
+#define sqlite3_close sqlite3_api->close
+#define sqlite3_collation_needed sqlite3_api->collation_needed
+#define sqlite3_collation_needed16 sqlite3_api->collation_needed16
+#define sqlite3_column_blob sqlite3_api->column_blob
+#define sqlite3_column_bytes sqlite3_api->column_bytes
+#define sqlite3_column_bytes16 sqlite3_api->column_bytes16
+#define sqlite3_column_count sqlite3_api->column_count
+#define sqlite3_column_database_name sqlite3_api->column_database_name
+#define sqlite3_column_database_name16 sqlite3_api->column_database_name16
+#define sqlite3_column_decltype sqlite3_api->column_decltype
+#define sqlite3_column_decltype16 sqlite3_api->column_decltype16
+#define sqlite3_column_double sqlite3_api->column_double
+#define sqlite3_column_int sqlite3_api->column_int
+#define sqlite3_column_int64 sqlite3_api->column_int64
+#define sqlite3_column_name sqlite3_api->column_name
+#define sqlite3_column_name16 sqlite3_api->column_name16
+#define sqlite3_column_origin_name sqlite3_api->column_origin_name
+#define sqlite3_column_origin_name16 sqlite3_api->column_origin_name16
+#define sqlite3_column_table_name sqlite3_api->column_table_name
+#define sqlite3_column_table_name16 sqlite3_api->column_table_name16
+#define sqlite3_column_text sqlite3_api->column_text
+#define sqlite3_column_text16 sqlite3_api->column_text16
+#define sqlite3_column_type sqlite3_api->column_type
+#define sqlite3_column_value sqlite3_api->column_value
+#define sqlite3_commit_hook sqlite3_api->commit_hook
+#define sqlite3_complete sqlite3_api->complete
+#define sqlite3_complete16 sqlite3_api->complete16
+#define sqlite3_create_collation sqlite3_api->create_collation
+#define sqlite3_create_collation16 sqlite3_api->create_collation16
+#define sqlite3_create_function sqlite3_api->create_function
+#define sqlite3_create_function16 sqlite3_api->create_function16
+#define sqlite3_create_module sqlite3_api->create_module
+#define sqlite3_data_count sqlite3_api->data_count
+#define sqlite3_db_handle sqlite3_api->db_handle
+#define sqlite3_declare_vtab sqlite3_api->declare_vtab
+#define sqlite3_enable_shared_cache sqlite3_api->enable_shared_cache
+#define sqlite3_errcode sqlite3_api->errcode
+#define sqlite3_errmsg sqlite3_api->errmsg
+#define sqlite3_errmsg16 sqlite3_api->errmsg16
+#define sqlite3_exec sqlite3_api->exec
+#define sqlite3_expired sqlite3_api->expired
+#define sqlite3_finalize sqlite3_api->finalize
+#define sqlite3_free sqlite3_api->free
+#define sqlite3_free_table sqlite3_api->free_table
+#define sqlite3_get_autocommit sqlite3_api->get_autocommit
+#define sqlite3_get_auxdata sqlite3_api->get_auxdata
+#define sqlite3_get_table sqlite3_api->get_table
+#define sqlite3_global_recover sqlite3_api->global_recover
+#define sqlite3_interrupt sqlite3_api->interruptx
+#define sqlite3_last_insert_rowid sqlite3_api->last_insert_rowid
+#define sqlite3_libversion sqlite3_api->libversion
+#define sqlite3_libversion_number sqlite3_api->libversion_number
+#define sqlite3_malloc sqlite3_api->malloc
+#define sqlite3_mprintf sqlite3_api->mprintf
+#define sqlite3_open sqlite3_api->open
+#define sqlite3_open16 sqlite3_api->open16
+#define sqlite3_prepare sqlite3_api->prepare
+#define sqlite3_prepare16 sqlite3_api->prepare16
+#define sqlite3_profile sqlite3_api->profile
+#define sqlite3_progress_handler sqlite3_api->progress_handler
+#define sqlite3_realloc sqlite3_api->realloc
+#define sqlite3_reset sqlite3_api->reset
+#define sqlite3_result_blob sqlite3_api->result_blob
+#define sqlite3_result_double sqlite3_api->result_double
+#define sqlite3_result_error sqlite3_api->result_error
+#define sqlite3_result_error16 sqlite3_api->result_error16
+#define sqlite3_result_int sqlite3_api->result_int
+#define sqlite3_result_int64 sqlite3_api->result_int64
+#define sqlite3_result_null sqlite3_api->result_null
+#define sqlite3_result_text sqlite3_api->result_text
+#define sqlite3_result_text16 sqlite3_api->result_text16
+#define sqlite3_result_text16be sqlite3_api->result_text16be
+#define sqlite3_result_text16le sqlite3_api->result_text16le
+#define sqlite3_result_value sqlite3_api->result_value
+#define sqlite3_rollback_hook sqlite3_api->rollback_hook
+#define sqlite3_set_authorizer sqlite3_api->set_authorizer
+#define sqlite3_set_auxdata sqlite3_api->set_auxdata
+#define sqlite3_snprintf sqlite3_api->snprintf
+#define sqlite3_step sqlite3_api->step
+#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata
+#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup
+#define sqlite3_total_changes sqlite3_api->total_changes
+#define sqlite3_trace sqlite3_api->trace
+#define sqlite3_transfer_bindings sqlite3_api->transfer_bindings
+#define sqlite3_update_hook sqlite3_api->update_hook
+#define sqlite3_user_data sqlite3_api->user_data
+#define sqlite3_value_blob sqlite3_api->value_blob
+#define sqlite3_value_bytes sqlite3_api->value_bytes
+#define sqlite3_value_bytes16 sqlite3_api->value_bytes16
+#define sqlite3_value_double sqlite3_api->value_double
+#define sqlite3_value_int sqlite3_api->value_int
+#define sqlite3_value_int64 sqlite3_api->value_int64
+#define sqlite3_value_numeric_type sqlite3_api->value_numeric_type
+#define sqlite3_value_text sqlite3_api->value_text
+#define sqlite3_value_text16 sqlite3_api->value_text16
+#define sqlite3_value_text16be sqlite3_api->value_text16be
+#define sqlite3_value_text16le sqlite3_api->value_text16le
+#define sqlite3_value_type sqlite3_api->value_type
+#define sqlite3_vmprintf sqlite3_api->vmprintf
+#define sqlite3_overload_function sqlite3_api->overload_function
+#endif /* SQLITE_CORE */
+
+#define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api;
+#define SQLITE_EXTENSION_INIT2(v) sqlite3_api = v;
+
+#endif /* _SQLITE3EXT_H_ */
diff --git a/dlls/sqlite/sqlite-source/sqliteInt.h b/dlls/sqlite/sqlite-source/sqliteInt.h
index dd06a6ea..cceee77f 100644
--- a/dlls/sqlite/sqlite-source/sqliteInt.h
+++ b/dlls/sqlite/sqlite-source/sqliteInt.h
@@ -17,7 +17,7 @@
#define _SQLITEINT_H_
#if defined _MSC_VER && _MSC_VER >= 1400
- #define _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE
#endif
/*
@@ -152,7 +152,7 @@
*/
#define SQLITE_MAX_FILE_FORMAT 4
#ifndef SQLITE_DEFAULT_FILE_FORMAT
-# define SQLITE_DEFAULT_FILE_FORMAT 4
+# define SQLITE_DEFAULT_FILE_FORMAT 1
#endif
/*
@@ -347,6 +347,7 @@ typedef struct IdList IdList;
typedef struct Index Index;
typedef struct KeyClass KeyClass;
typedef struct KeyInfo KeyInfo;
+typedef struct Module Module;
typedef struct NameContext NameContext;
typedef struct Parse Parse;
typedef struct Select Select;
@@ -450,6 +451,7 @@ struct sqlite3 {
Db *aDb; /* All backends */
int flags; /* Miscellanous flags. See below */
int errCode; /* Most recent error code (SQLITE_*) */
+ int errMask; /* & result codes with this before returning */
u8 autoCommit; /* The auto-commit flag. */
u8 temp_store; /* 1: file 2: memory 0: default */
int nTable; /* Number of tables in the database */
@@ -464,6 +466,8 @@ struct sqlite3 {
int newTnum; /* Rootpage of table being initialized */
u8 busy; /* TRUE if currently initializing */
} init;
+ int nExtension; /* Number of loaded extensions */
+ void **aExtension; /* Array of shared libraray handles */
struct Vdbe *pVdbe; /* List of active virtual machines */
int activeVdbeCnt; /* Number of vdbes currently executing */
void (*xTrace)(void*,const char*); /* Trace function */
@@ -482,6 +486,10 @@ struct sqlite3 {
sqlite3_value *pErr; /* Most recent error message */
char *zErrMsg; /* Most recent error message (UTF-8 encoded) */
char *zErrMsg16; /* Most recent error message (UTF-16 encoded) */
+ union {
+ int isInterrupted; /* True if sqlite3_interrupt has been called */
+ double notUsed1; /* Spacer */
+ } u1;
#ifndef SQLITE_OMIT_AUTHORIZATION
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
/* Access authorization function */
@@ -492,13 +500,16 @@ struct sqlite3 {
void *pProgressArg; /* Argument to the progress callback */
int nProgressOps; /* Number of opcodes for progress callback */
#endif
-#ifndef SQLITE_OMIT_GLOBALRECOVER
- sqlite3 *pNext; /* Linked list of open db handles. */
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ Hash aModule; /* populated by sqlite3_create_module() */
+ Table *pVTab; /* vtab with active Connect/Create method */
+ sqlite3_vtab **aVTrans; /* Virtual tables with open transactions */
+ int nVTrans; /* Allocated size of aVTrans */
#endif
Hash aFunc; /* All functions that can be in SQL exprs */
Hash aCollSeq; /* All collating sequences */
BusyHandler busyHandler; /* Busy callback */
- int busyTimeout; /* Busy handler timeout, in msec */
+ int busyTimeout; /* Busy handler timeout, in msec */
Db aDbStatic[2]; /* Static space for the 2 default backends */
#ifdef SQLITE_SSE
sqlite3_stmt *pFetch; /* Used by SSE to fetch stored statements */
@@ -518,7 +529,6 @@ struct sqlite3 {
** transaction is active on that particular database file.
*/
#define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */
-#define SQLITE_Interrupt 0x00000004 /* Cancel current operation */
#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 */
@@ -534,9 +544,10 @@ struct sqlite3 {
#define SQLITE_NoReadlock 0x00001000 /* 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_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 */
/*
** Possible values for the sqlite.magic field.
@@ -567,11 +578,23 @@ struct FuncDef {
char zName[1]; /* SQL name of the function. MUST BE LAST */
};
+/*
+** Each SQLite module (virtual table definition) is defined by an
+** instance of the following structure, stored in the sqlite3.aModule
+** hash table.
+*/
+struct Module {
+ const sqlite3_module *pModule; /* Callback pointers */
+ const char *zName; /* Name passed to create_module() */
+ void *pAux; /* pAux passed to create_module() */
+};
+
/*
** Possible values for FuncDef.flags
*/
#define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */
#define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */
+#define SQLITE_FUNC_EPHEM 0x04 /* Ephermeral. Delete with VDBE */
/*
** information about each column of an SQL table is held in an instance
@@ -674,7 +697,7 @@ struct CollSeq {
** Table.tnum is the page number for the root BTree page of the table in the
** database file. If Table.iDb is the index of the database table backend
** in sqlite.aDb[]. 0 is for the main database and 1 is for the file that
-** holds temporary tables and indices. If Table.isTransient
+** holds temporary tables and indices. If Table.isEphem
** is true, then the table is stored in a file that is automatically deleted
** when the VDBE cursor to the table is closed. In this case Table.tnum
** refers VDBE cursor number that holds the table open, not to the root
@@ -690,11 +713,6 @@ struct Table {
Index *pIndex; /* List of SQL indexes on this table. */
int tnum; /* Root BTree node for this table (see note above) */
Select *pSelect; /* NULL for tables. Points to definition if a view. */
- u8 readOnly; /* True if this table should not be written by the user */
- u8 isTransient; /* True if automatically deleted when VDBE finishes */
- u8 hasPrimKey; /* True if there exists a primary key */
- u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
- u8 autoInc; /* True if the integer primary key is autoincrement */
int nRef; /* Number of pointers to this Table */
Trigger *pTrigger; /* List of SQL triggers on this table */
FKey *pFKey; /* Linked list of all foreign keys in this table */
@@ -704,10 +722,34 @@ struct Table {
#endif
#ifndef SQLITE_OMIT_ALTERTABLE
int addColOffset; /* Offset in CREATE TABLE statement to add a new column */
+#endif
+ u8 readOnly; /* True if this table should not be written by the user */
+ u8 isEphem; /* True if created using OP_OpenEphermeral */
+ u8 hasPrimKey; /* True if there exists a primary key */
+ u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
+ u8 autoInc; /* True if the integer primary key is autoincrement */
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ u8 isVirtual; /* True if this is a virtual table */
+ u8 isCommit; /* True once the CREATE TABLE has been committed */
+ Module *pMod; /* Pointer to the implementation of the module */
+ sqlite3_vtab *pVtab; /* Pointer to the module instance */
+ int nModuleArg; /* Number of arguments to the module */
+ char **azModuleArg; /* Text of all module args. [0] is module name */
#endif
Schema *pSchema;
};
+/*
+** Test to see whether or not a table is a virtual table. This is
+** done as a macro so that it will be optimized out when virtual
+** table support is omitted from the build.
+*/
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+# define IsVirtual(X) ((X)->isVirtual)
+#else
+# define IsVirtual(X) 0
+#endif
+
/*
** Each foreign key constraint is an instance of the following structure.
**
@@ -899,7 +941,7 @@ struct AggInfo {
Expr *pExpr; /* Expression encoding the function */
FuncDef *pFunc; /* The aggregate function implementation */
int iMem; /* Memory location that acts as accumulator */
- int iDistinct; /* Virtual table used to enforce DISTINCT */
+ int iDistinct; /* Ephermeral table used to enforce DISTINCT */
} *aFunc;
int nFunc; /* Number of entries in aFunc[] */
int nFuncAlloc; /* Number of slots allocated for aFunc[] */
@@ -954,7 +996,7 @@ struct AggInfo {
struct Expr {
u8 op; /* Operation performed by this node */
char affinity; /* The affinity of the column or 0 if not a column */
- u8 flags; /* Various flags. See below */
+ u16 flags; /* Various flags. See below */
CollSeq *pColl; /* The collation type of the column or 0 */
Expr *pLeft, *pRight; /* Left and right subnodes */
ExprList *pList; /* A list of expressions used as function arguments
@@ -982,6 +1024,8 @@ struct Expr {
#define EP_Distinct 0x10 /* Aggregate function with DISTINCT keyword */
#define EP_VarSelect 0x20 /* pSelect is correlated, not constant */
#define EP_Dequoted 0x40 /* True if the string has been dequoted */
+#define EP_InfixFunc 0x80 /* True for an infix function: LIKE, GLOB, etc */
+#define EP_ExpCollate 0x100 /* Collating sequence specified explicitly */
/*
** These macros can be used to test, set, or clear bits in the
@@ -1039,8 +1083,12 @@ struct IdList {
/*
** The bitmask datatype defined below is used for various optimizations.
+**
+** Changing this from a 64-bit to a 32-bit type limits the number of
+** tables in a join to 32 instead of 64. But it also reduces the size
+** of the library by 738 bytes on ix86.
*/
-typedef unsigned int Bitmask;
+typedef u64 Bitmask;
/*
** The following structure describes the FROM clause of a SELECT statement.
@@ -1052,6 +1100,11 @@ typedef unsigned int Bitmask;
** is modified by an INSERT, DELETE, or UPDATE statement. In standard SQL,
** such a table must be a simple name: ID. But in SQLite, the table can
** now be identified by a database name, a dot, then the table name: ID.ID.
+**
+** The jointype starts out showing the join type between the current table
+** and the next table on the list. The parser builds the list this way.
+** But sqlite3SrcListShiftJoinType() later shifts the jointypes so that each
+** jointype expresses the join between the table and the previous table.
*/
struct SrcList {
i16 nSrc; /* Number of tables or subqueries in the FROM clause */
@@ -1063,8 +1116,8 @@ struct SrcList {
Table *pTab; /* An SQL table corresponding to zName */
Select *pSelect; /* A SELECT statement used in place of a table name */
u8 isPopulated; /* Temporary table associated with SELECT is populated */
- u8 jointype; /* Type of join between this table and the next */
- i16 iCursor; /* The VDBE cursor number used to access this table */
+ u8 jointype; /* Type of join between this able and the previous */
+ int iCursor; /* The VDBE cursor number used to access this table */
Expr *pOn; /* The ON clause of a join */
IdList *pUsing; /* The USING clause of a join */
Bitmask colUsed; /* Bit N (1<xAuth callbacks */
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ Token sArg; /* Complete text of a module argument */
+ u8 declareVtab; /* True if inside sqlite3_declare_vtab() */
+ Table *pVirtualLock; /* Require virtual table lock on this table */
+#endif
};
+#ifdef SQLITE_OMIT_VIRTUALTABLE
+ #define IN_DECLARE_VTAB 0
+#else
+ #define IN_DECLARE_VTAB (pParse->declareVtab)
+#endif
+
/*
** An instance of the following structure can be declared on a stack and used
** to save the Parse.zAuthContext value so that it can be restored later.
@@ -1441,7 +1527,9 @@ struct DbFixer {
*/
typedef struct {
sqlite3 *db; /* The database being initialized */
+ int iDb; /* 0 for main database. 1 for TEMP, 2.. for ATTACHed */
char **pzErrMsg; /* Error message stored here */
+ int rc; /* Result code stored here */
} InitData;
/*
@@ -1500,6 +1588,7 @@ int sqlite3KeywordCode(const unsigned char*, int);
int sqlite3RunParser(Parse*, const char*, char **);
void sqlite3FinishCoding(Parse*);
Expr *sqlite3Expr(int, Expr*, Expr*, const Token*);
+Expr *sqlite3ExprOrFree(int, Expr*, Expr*, const Token*);
Expr *sqlite3RegisterExpr(Parse*,Token*);
Expr *sqlite3ExprAnd(Expr*, Expr*);
void sqlite3ExprSpan(Expr*,Token*,Token*);
@@ -1517,7 +1606,7 @@ void sqlite3RollbackInternalChanges(sqlite3*);
void sqlite3CommitInternalChanges(sqlite3*);
Table *sqlite3ResultSetOfSelect(Parse*,char*,Select*);
void sqlite3OpenMasterTable(Parse *, int);
-void sqlite3StartTable(Parse*,Token*,Token*,int,int,int);
+void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int);
void sqlite3AddColumn(Parse*,Token*);
void sqlite3AddNotNull(Parse*, int);
void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
@@ -1527,8 +1616,9 @@ void sqlite3AddDefaultValue(Parse*,Expr*);
void sqlite3AddCollateType(Parse*, const char*, int);
void sqlite3EndTable(Parse*,Token*,Token*,Select*);
-#ifndef SQLITE_OMIT_VIEW
- void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int);
+void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int);
+
+#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
int sqlite3ViewGetColumnNames(Parse*,Table*);
#else
# define sqlite3ViewGetColumnNames(A,B) 0
@@ -1541,7 +1631,9 @@ int sqlite3ArrayAllocate(void**,int,int);
IdList *sqlite3IdListAppend(IdList*, Token*);
int sqlite3IdListIndex(IdList*,const char*);
SrcList *sqlite3SrcListAppend(SrcList*, Token*, Token*);
-void sqlite3SrcListAddAlias(SrcList*, Token*);
+SrcList *sqlite3SrcListAppendFromTerm(SrcList*, Token*, Token*, Token*,
+ Select*, Expr*, IdList*);
+void sqlite3SrcListShiftJoinType(SrcList*);
void sqlite3SrcListAssignCursors(Parse*, SrcList*);
void sqlite3IdListDelete(IdList*);
void sqlite3SrcListDelete(SrcList*);
@@ -1583,6 +1675,7 @@ int sqlite3ExprResolveNames(NameContext *, Expr *);
int sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
int sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
Vdbe *sqlite3GetVdbe(Parse*);
+Expr *sqlite3CreateIdExpr(const char*);
void sqlite3Randomness(int, void*);
void sqlite3RollbackAll(sqlite3*);
void sqlite3CodeVerifySchema(Parse*, int);
@@ -1616,9 +1709,9 @@ void sqlite3ChangeCookie(sqlite3*, Vdbe*, int);
#ifndef SQLITE_OMIT_TRIGGER
void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
- int,Expr*,int);
+ int,Expr*,int, int);
void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*);
- void sqlite3DropTrigger(Parse*, SrcList*);
+ void sqlite3DropTrigger(Parse*, SrcList*, int);
void sqlite3DropTriggerPtr(Parse*, Trigger*);
int sqlite3TriggersExist(Parse*, Table*, int, ExprList*);
int sqlite3CodeRowTrigger(Parse*, int, ExprList*, int, Table *, int, int,
@@ -1689,6 +1782,7 @@ int sqlite3ReadSchema(Parse *pParse);
CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char *,int,int);
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName);
CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
+Expr *sqlite3ExprSetColl(Parse *pParse, Expr *, Token *);
int sqlite3CheckCollSeq(Parse *, CollSeq *);
int sqlite3CheckIndexCollSeq(Parse *, Index *);
int sqlite3CheckObjectName(Parse *, const char *);
@@ -1744,6 +1838,14 @@ void sqlite3FailedMalloc(void);
void sqlite3AbortOtherActiveVdbes(sqlite3 *, Vdbe *);
int sqlite3OpenTempDatabase(Parse *);
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+ void sqlite3CloseExtensions(sqlite3*);
+ int sqlite3AutoLoadExtensions(sqlite3*);
+#else
+# define sqlite3CloseExtensions(X)
+# define sqlite3AutoLoadExtensions(X) SQLITE_OK
+#endif
+
#ifndef SQLITE_OMIT_SHARED_CACHE
void sqlite3TableLock(Parse *, int, int, u8, const char *);
#else
@@ -1768,6 +1870,31 @@ int sqlite3OpenTempDatabase(Parse *);
#define sqlite3ThreadSafeFree sqlite3FreeX
#endif
+#ifdef SQLITE_OMIT_VIRTUALTABLE
+# define sqlite3VtabClear(X)
+# define sqlite3VtabSync(X,Y) (Y)
+# define sqlite3VtabRollback(X)
+# define sqlite3VtabCommit(X)
+#else
+ void sqlite3VtabClear(Table*);
+ int sqlite3VtabSync(sqlite3 *db, int rc);
+ int sqlite3VtabRollback(sqlite3 *db);
+ int sqlite3VtabCommit(sqlite3 *db);
+#endif
+void sqlite3VtabLock(sqlite3_vtab*);
+void sqlite3VtabUnlock(sqlite3_vtab*);
+void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*);
+void sqlite3VtabFinishParse(Parse*, Token*);
+void sqlite3VtabArgInit(Parse*);
+void sqlite3VtabArgExtend(Parse*, Token*);
+int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **);
+int sqlite3VtabCallConnect(Parse*, Table*);
+int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
+int sqlite3VtabBegin(sqlite3 *, sqlite3_vtab *);
+FuncDef *sqlite3VtabOverloadFunction(FuncDef*, int nArg, Expr*);
+void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**);
+int sqlite3Reprepare(Vdbe*);
+
#ifdef SQLITE_SSE
#include "sseInt.h"
#endif
diff --git a/dlls/sqlite/sqlite-source/table.c b/dlls/sqlite/sqlite-source/table.c
index 25b83dd0..30c14848 100644
--- a/dlls/sqlite/sqlite-source/table.c
+++ b/dlls/sqlite/sqlite-source/table.c
@@ -59,7 +59,7 @@ static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
if( p->nData + need >= p->nAlloc ){
char **azNew;
p->nAlloc = p->nAlloc*2 + need + 1;
- azNew = realloc( p->azResult, sizeof(char*)*p->nAlloc );
+ azNew = sqlite3_realloc( p->azResult, sizeof(char*)*p->nAlloc );
if( azNew==0 ) goto malloc_failed;
p->azResult = azNew;
}
@@ -71,11 +71,9 @@ static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
p->nColumn = nCol;
for(i=0; iazResult[p->nData++] = z;
}
@@ -94,7 +92,7 @@ static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
if( argv[i]==0 ){
z = 0;
}else{
- z = malloc( strlen(argv[i])+1 );
+ z = sqlite3_malloc( strlen(argv[i])+1 );
if( z==0 ) goto malloc_failed;
strcpy(z, argv[i]);
}
@@ -140,34 +138,34 @@ int sqlite3_get_table(
res.nData = 1;
res.nAlloc = 20;
res.rc = SQLITE_OK;
- res.azResult = malloc( sizeof(char*)*res.nAlloc );
+ res.azResult = sqlite3_malloc( sizeof(char*)*res.nAlloc );
if( res.azResult==0 ) return SQLITE_NOMEM;
res.azResult[0] = 0;
rc = sqlite3_exec(db, zSql, sqlite3_get_table_cb, &res, pzErrMsg);
if( res.azResult ){
assert( sizeof(res.azResult[0])>= sizeof(res.nData) );
- res.azResult[0] = (void *)(long)res.nData;
+ res.azResult[0] = (char*)res.nData;
}
- if( rc==SQLITE_ABORT ){
+ if( (rc&0xff)==SQLITE_ABORT ){
sqlite3_free_table(&res.azResult[1]);
if( res.zErrMsg ){
if( pzErrMsg ){
- free(*pzErrMsg);
+ sqlite3_free(*pzErrMsg);
*pzErrMsg = sqlite3_mprintf("%s",res.zErrMsg);
}
sqliteFree(res.zErrMsg);
}
db->errCode = res.rc;
- return res.rc;
+ return res.rc & db->errMask;
}
sqliteFree(res.zErrMsg);
if( rc!=SQLITE_OK ){
sqlite3_free_table(&res.azResult[1]);
- return rc;
+ return rc & db->errMask;
}
if( res.nAlloc>res.nData ){
char **azNew;
- azNew = realloc( res.azResult, sizeof(char*)*(res.nData+1) );
+ azNew = sqlite3_realloc( res.azResult, sizeof(char*)*(res.nData+1) );
if( azNew==0 ){
sqlite3_free_table(&res.azResult[1]);
return SQLITE_NOMEM;
@@ -178,7 +176,7 @@ int sqlite3_get_table(
*pazResult = &res.azResult[1];
if( pnColumn ) *pnColumn = res.nColumn;
if( pnRow ) *pnRow = res.nRow;
- return rc;
+ return rc & db->errMask;
}
/*
@@ -191,9 +189,9 @@ void sqlite3_free_table(
int i, n;
azResult--;
if( azResult==0 ) return;
- n = (int)(long)azResult[0];
- for(i=1; i
#include
+/*
+ * Windows needs to know which symbols to export. Unix does not.
+ * BUILD_sqlite should be undefined for Unix.
+ */
+#ifdef BUILD_sqlite
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLEXPORT
+#endif /* BUILD_sqlite */
#define NUM_PREPARED_STMTS 10
#define MAX_PREPARED_STMTS 100
@@ -543,6 +551,9 @@ static int auth_callback(
case SQLITE_ALTER_TABLE : zCode="SQLITE_ALTER_TABLE"; break;
case SQLITE_REINDEX : zCode="SQLITE_REINDEX"; break;
case SQLITE_ANALYZE : zCode="SQLITE_ANALYZE"; break;
+ case SQLITE_CREATE_VTABLE : zCode="SQLITE_CREATE_VTABLE"; break;
+ case SQLITE_DROP_VTABLE : zCode="SQLITE_DROP_VTABLE"; break;
+ case SQLITE_FUNCTION : zCode="SQLITE_FUNCTION"; break;
default : zCode="????"; break;
}
Tcl_DStringInit(&str);
@@ -657,24 +668,25 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
"authorizer", "busy", "cache",
"changes", "close", "collate",
"collation_needed", "commit_hook", "complete",
- "copy", "errorcode", "eval",
- "exists", "function", "last_insert_rowid",
- "nullvalue", "onecolumn", "profile",
- "progress", "rekey", "rollback_hook",
- "timeout", "total_changes", "trace",
- "transaction", "update_hook", "version",
- 0
+ "copy", "enable_load_extension","errorcode",
+ "eval", "exists", "function",
+ "interrupt", "last_insert_rowid", "nullvalue",
+ "onecolumn", "profile", "progress",
+ "rekey", "rollback_hook", "timeout",
+ "total_changes", "trace", "transaction",
+ "update_hook", "version", 0
};
enum DB_enum {
DB_AUTHORIZER, DB_BUSY, DB_CACHE,
DB_CHANGES, DB_CLOSE, DB_COLLATE,
DB_COLLATION_NEEDED, DB_COMMIT_HOOK, DB_COMPLETE,
- DB_COPY, DB_ERRORCODE, DB_EVAL,
- DB_EXISTS, DB_FUNCTION, DB_LAST_INSERT_ROWID,
- DB_NULLVALUE, DB_ONECOLUMN, DB_PROFILE,
- DB_PROGRESS, DB_REKEY, DB_ROLLBACK_HOOK,
- DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE,
- DB_TRANSACTION, DB_UPDATE_HOOK, DB_VERSION
+ DB_COPY, DB_ENABLE_LOAD_EXTENSION,DB_ERRORCODE,
+ DB_EVAL, DB_EXISTS, DB_FUNCTION,
+ DB_INTERRUPT, DB_LAST_INSERT_ROWID,DB_NULLVALUE,
+ DB_ONECOLUMN, DB_PROFILE, DB_PROGRESS,
+ DB_REKEY, DB_ROLLBACK_HOOK, DB_TIMEOUT,
+ DB_TOTAL_CHANGES, DB_TRACE, DB_TRANSACTION,
+ DB_UPDATE_HOOK, DB_VERSION,
};
/* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */
@@ -1024,7 +1036,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
nSep = strlen(zSep);
nNull = strlen(zNull);
if( nSep==0 ){
- Tcl_AppendResult(interp, "Error: non-null separator required for copy", 0);
+ Tcl_AppendResult(interp,"Error: non-null separator required for copy",0);
return TCL_ERROR;
}
if(sqlite3StrICmp(zConflict, "rollback") != 0 &&
@@ -1043,7 +1055,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
return TCL_ERROR;
}
nByte = strlen(zSql);
- rc = sqlite3_prepare(pDb->db, zSql, 0, &pStmt, 0);
+ rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
if( rc ){
Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), 0);
@@ -1069,7 +1081,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
}
zSql[j++] = ')';
zSql[j] = 0;
- rc = sqlite3_prepare(pDb->db, zSql, 0, &pStmt, 0);
+ rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0);
free(zSql);
if( rc ){
Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), 0);
@@ -1108,11 +1120,13 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
if( i+1!=nCol ){
char *zErr;
zErr = malloc(200 + strlen(zFile));
- sprintf(zErr,
- "Error: %s line %d: expected %d columns of data but found %d",
- zFile, lineno, nCol, i+1);
- Tcl_AppendResult(interp, zErr, 0);
- free(zErr);
+ if( zErr ){
+ sprintf(zErr,
+ "Error: %s line %d: expected %d columns of data but found %d",
+ zFile, lineno, nCol, i+1);
+ Tcl_AppendResult(interp, zErr, 0);
+ free(zErr);
+ }
zCommit = "ROLLBACK";
break;
}
@@ -1152,6 +1166,31 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
break;
}
+ /*
+ ** $db enable_load_extension BOOLEAN
+ **
+ ** Turn the extension loading feature on or off. It if off by
+ ** default.
+ */
+ case DB_ENABLE_LOAD_EXTENSION: {
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+ int onoff;
+ if( objc!=3 ){
+ Tcl_WrongNumArgs(interp, 2, objv, "BOOLEAN");
+ return TCL_ERROR;
+ }
+ if( Tcl_GetBooleanFromObj(interp, objv[2], &onoff) ){
+ return TCL_ERROR;
+ }
+ sqlite3_enable_load_extension(pDb->db, onoff);
+ break;
+#else
+ Tcl_AppendResult(interp, "extension loading is turned off at compile-time",
+ 0);
+ return TCL_ERROR;
+#endif
+ }
+
/*
** $db errorcode
**
@@ -1536,6 +1575,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
Tcl_SetObjResult(interp, pRet);
}
Tcl_DecrRefCount(pRet);
+ }else if( rc==TCL_OK ){
+ Tcl_ResetResult(interp);
}
break;
}
@@ -1576,6 +1617,17 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
break;
}
+ /*
+ ** $db interrupt
+ **
+ ** Interrupt the execution of the inner-most SQL interpreter. This
+ ** causes the SQL statement to return an error of SQLITE_INTERRUPT.
+ */
+ case DB_INTERRUPT: {
+ sqlite3_interrupt(pDb->db);
+ break;
+ }
+
/*
** $db nullvalue ?STRING?
**
@@ -1614,14 +1666,14 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
*/
case DB_LAST_INSERT_ROWID: {
Tcl_Obj *pResult;
- int rowid;
+ Tcl_WideInt rowid;
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 2, objv, "");
return TCL_ERROR;
}
rowid = sqlite3_last_insert_rowid(pDb->db);
pResult = Tcl_GetObjResult(interp);
- Tcl_SetIntObj(pResult, rowid);
+ Tcl_SetWideIntObj(pResult, rowid);
break;
}
@@ -1956,6 +2008,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
const char *zArg;
char *zErrMsg;
const char *zFile;
+ Tcl_DString translatedFilename;
if( objc==2 ){
zArg = Tcl_GetStringFromObj(objv[1], 0);
if( strcmp(zArg,"-version")==0 ){
@@ -2004,9 +2057,11 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
}
memset(p, 0, sizeof(*p));
zFile = Tcl_GetStringFromObj(objv[2], 0);
+ zFile = Tcl_TranslateFileName(interp, zFile, &translatedFilename);
sqlite3_open(zFile, &p->db);
+ Tcl_DStringFree(&translatedFilename);
if( SQLITE_OK!=sqlite3_errcode(p->db) ){
- zErrMsg = strdup(sqlite3_errmsg(p->db));
+ zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(p->db));
sqlite3_close(p->db);
p->db = 0;
}
@@ -2016,10 +2071,11 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
if( p->db==0 ){
Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);
Tcl_Free((char*)p);
- free(zErrMsg);
+ sqlite3_free(zErrMsg);
return TCL_ERROR;
}
p->maxStmt = NUM_PREPARED_STMTS;
+ p->interp = interp;
zArg = Tcl_GetStringFromObj(objv[1], 0);
Tcl_CreateObjCommand(interp, zArg, DbObjCmd, (char*)p, DbDeleteCmd);
@@ -2039,7 +2095,6 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
#endif
}
#endif
- p->interp = interp;
return TCL_OK;
}
@@ -2070,7 +2125,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
** used to open a new SQLite database. See the DbMain() routine above
** for additional information.
*/
-extern int Sqlite3_Init(Tcl_Interp *interp){
+EXTERN int Sqlite3_Init(Tcl_Interp *interp){
Tcl_InitStubs(interp, "8.4", 0);
Tcl_CreateObjCommand(interp, "sqlite3", (Tcl_ObjCmdProc*)DbMain, 0, 0);
Tcl_PkgProvide(interp, "sqlite3", PACKAGE_VERSION);
@@ -2078,15 +2133,15 @@ extern int Sqlite3_Init(Tcl_Interp *interp){
Tcl_PkgProvide(interp, "sqlite", PACKAGE_VERSION);
return TCL_OK;
}
-extern int Tclsqlite3_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
-extern int Sqlite3_SafeInit(Tcl_Interp *interp){ return TCL_OK; }
-extern int Tclsqlite3_SafeInit(Tcl_Interp *interp){ return TCL_OK; }
+EXTERN int Tclsqlite3_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
+EXTERN int Sqlite3_SafeInit(Tcl_Interp *interp){ return TCL_OK; }
+EXTERN int Tclsqlite3_SafeInit(Tcl_Interp *interp){ return TCL_OK; }
#ifndef SQLITE_3_SUFFIX_ONLY
-extern int Sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
-extern int Tclsqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
-extern int Sqlite_SafeInit(Tcl_Interp *interp){ return TCL_OK; }
-extern int Tclsqlite_SafeInit(Tcl_Interp *interp){ return TCL_OK; }
+EXTERN int Sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
+EXTERN int Tclsqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
+EXTERN int Sqlite_SafeInit(Tcl_Interp *interp){ return TCL_OK; }
+EXTERN int Tclsqlite_SafeInit(Tcl_Interp *interp){ return TCL_OK; }
#endif
#ifdef TCLSH
@@ -2149,9 +2204,13 @@ int TCLSH_MAIN(int argc, char **argv){
extern int Sqlitetest5_Init(Tcl_Interp*);
extern int Sqlitetest6_Init(Tcl_Interp*);
extern int Sqlitetest7_Init(Tcl_Interp*);
+ extern int Sqlitetest8_Init(Tcl_Interp*);
extern int Md5_Init(Tcl_Interp*);
extern int Sqlitetestsse_Init(Tcl_Interp*);
extern int Sqlitetestasync_Init(Tcl_Interp*);
+ extern int Sqlitetesttclvar_Init(Tcl_Interp*);
+ extern int Sqlitetestschema_Init(Tcl_Interp*);
+ extern int Sqlitetest_autoext_Init(Tcl_Interp*);
Sqlitetest1_Init(interp);
Sqlitetest2_Init(interp);
@@ -2160,7 +2219,11 @@ int TCLSH_MAIN(int argc, char **argv){
Sqlitetest5_Init(interp);
Sqlitetest6_Init(interp);
Sqlitetest7_Init(interp);
+ Sqlitetest8_Init(interp);
Sqlitetestasync_Init(interp);
+ Sqlitetesttclvar_Init(interp);
+ Sqlitetestschema_Init(interp);
+ Sqlitetest_autoext_Init(interp);
Md5_Init(interp);
#ifdef SQLITE_SSE
Sqlitetestsse_Init(interp);
@@ -2169,6 +2232,9 @@ int TCLSH_MAIN(int argc, char **argv){
#endif
if( argc>=2 || TCLSH==2 ){
int i;
+ char zArgc[32];
+ sqlite3_snprintf(sizeof(zArgc), zArgc, "%d", argc-(3-TCLSH));
+ Tcl_SetVar(interp,"argc", zArgc, TCL_GLOBAL_ONLY);
Tcl_SetVar(interp,"argv0",argv[1],TCL_GLOBAL_ONLY);
Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY);
for(i=3-TCLSH; idb;
- extern void *sqlite3ParserAlloc(void*(*)(int));
+ extern void *sqlite3ParserAlloc(void*(*)(size_t));
extern void sqlite3ParserFree(void*, void(*)(void*));
- extern int sqlite3Parser(void*, int, Token, Parse*);
+ extern void sqlite3Parser(void*, int, Token, Parse*);
- db->flags &= ~SQLITE_Interrupt;
+ if( db->activeVdbeCnt==0 ){
+ db->u1.isInterrupted = 0;
+ }
pParse->rc = SQLITE_OK;
i = 0;
- pEngine = sqlite3ParserAlloc((void*(*)(int))sqlite3MallocX);
+ pEngine = sqlite3ParserAlloc((void*(*)(size_t))sqlite3MallocX);
if( pEngine==0 ){
return SQLITE_NOMEM;
}
@@ -418,7 +424,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
switch( tokenType ){
case TK_SPACE:
case TK_COMMENT: {
- if( (db->flags & SQLITE_Interrupt)!=0 ){
+ if( db->u1.isInterrupted ){
pParse->rc = SQLITE_INTERRUPT;
sqlite3SetString(pzErrMsg, "interrupt", (char*)0);
goto abort_parse;
@@ -483,7 +489,15 @@ abort_parse:
pParse->nTableLock = 0;
}
#endif
- sqlite3DeleteTable(pParse->db, pParse->pNewTable);
+
+ if( !IN_DECLARE_VTAB ){
+ /* If the pParse->declareVtab flag is set, do not delete any table
+ ** structure built up in pParse->pNewTable. The calling code (see vtab.c)
+ ** will take responsibility for freeing the Table structure.
+ */
+ sqlite3DeleteTable(pParse->db, pParse->pNewTable);
+ }
+
sqlite3DeleteTrigger(pParse->pNewTrigger);
sqliteFree(pParse->apVarExpr);
if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){
diff --git a/dlls/sqlite/sqlite-source/trigger.c b/dlls/sqlite/sqlite-source/trigger.c
index d670e527..a6eabbf6 100644
--- a/dlls/sqlite/sqlite-source/trigger.c
+++ b/dlls/sqlite/sqlite-source/trigger.c
@@ -49,7 +49,8 @@ void sqlite3BeginTrigger(
SrcList *pTableName,/* The name of the table/view the trigger applies to */
int foreach, /* One of TK_ROW or TK_STATEMENT */
Expr *pWhen, /* WHEN clause */
- int isTemp /* True if the TEMPORARY keyword is present */
+ int isTemp, /* True if the TEMPORARY keyword is present */
+ int noErr /* Suppress errors if the trigger already exists */
){
Trigger *pTrigger = 0;
Table *pTab;
@@ -103,6 +104,10 @@ void sqlite3BeginTrigger(
/* The table does not exist. */
goto trigger_cleanup;
}
+ if( IsVirtual(pTab) ){
+ sqlite3ErrorMsg(pParse, "cannot create triggers on virtual tables");
+ goto trigger_cleanup;
+ }
/* Check that the trigger name is not reserved and that no trigger of the
** specified name exists */
@@ -111,7 +116,9 @@ void sqlite3BeginTrigger(
goto trigger_cleanup;
}
if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash), zName,strlen(zName)) ){
- sqlite3ErrorMsg(pParse, "trigger %T already exists", pName);
+ if( !noErr ){
+ sqlite3ErrorMsg(pParse, "trigger %T already exists", pName);
+ }
goto trigger_cleanup;
}
@@ -435,7 +442,7 @@ void sqlite3DeleteTrigger(Trigger *pTrigger){
** same job as this routine except it takes a pointer to the trigger
** instead of the trigger name.
**/
-void sqlite3DropTrigger(Parse *pParse, SrcList *pName){
+void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){
Trigger *pTrigger = 0;
int i;
const char *zDb;
@@ -459,7 +466,9 @@ void sqlite3DropTrigger(Parse *pParse, SrcList *pName){
if( pTrigger ) break;
}
if( !pTrigger ){
- sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0);
+ if( !noErr ){
+ sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0);
+ }
goto drop_trigger_cleanup;
}
sqlite3DropTriggerPtr(pParse, pTrigger);
@@ -594,9 +603,10 @@ int sqlite3TriggersExist(
int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
ExprList *pChanges /* Columns that change in an UPDATE statement */
){
- Trigger *pTrigger = pTab->pTrigger;
+ Trigger *pTrigger;
int mask = 0;
+ pTrigger = IsVirtual(pTab) ? 0 : pTab->pTrigger;
while( pTrigger ){
if( pTrigger->op==op && checkColumnOverLap(pTrigger->pColumns, pChanges) ){
mask |= pTrigger->tr_tm;
@@ -658,12 +668,12 @@ static int codeTriggerProgram(
pParse->trigStack->orconf = orconf;
switch( pTriggerStep->op ){
case TK_SELECT: {
- Select * ss = sqlite3SelectDup(pTriggerStep->pSelect);
- assert(ss);
- assert(ss->pSrc);
- sqlite3SelectResolve(pParse, ss, 0);
- sqlite3Select(pParse, ss, SRT_Discard, 0, 0, 0, 0, 0);
- sqlite3SelectDelete(ss);
+ Select *ss = sqlite3SelectDup(pTriggerStep->pSelect);
+ if( ss ){
+ sqlite3SelectResolve(pParse, ss, 0);
+ sqlite3Select(pParse, ss, SRT_Discard, 0, 0, 0, 0, 0);
+ sqlite3SelectDelete(ss);
+ }
break;
}
case TK_UPDATE: {
diff --git a/dlls/sqlite/sqlite-source/update.c b/dlls/sqlite/sqlite-source/update.c
index e61ac8b1..f1cd038b 100644
--- a/dlls/sqlite/sqlite-source/update.c
+++ b/dlls/sqlite/sqlite-source/update.c
@@ -16,6 +16,19 @@
*/
#include "sqliteInt.h"
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Forward declaration */
+static void updateVirtualTable(
+ Parse *pParse, /* The parsing context */
+ SrcList *pSrc, /* The virtual table to be modified */
+ Table *pTab, /* The virtual table */
+ ExprList *pChanges, /* The columns to change in the UPDATE statement */
+ Expr *pRowidExpr, /* Expression used to recompute the rowid */
+ int *aXRef, /* Mapping from columns of pTab to entries in pChanges */
+ Expr *pWhere /* WHERE clause of the UPDATE statement */
+);
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
/*
** The most recently coded instruction was an OP_Column to retrieve the
** i-th column of table pTab. This routine sets the P3 parameter of the
@@ -90,6 +103,7 @@ void sqlite3Update(
AuthContext sContext; /* The authorization context */
NameContext sNC; /* The name-context to resolve expressions in */
int iDb; /* Database containing the table being updated */
+ int memCnt = 0; /* Memory cell used for counting rows changed */
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* Trying to update a view */
@@ -130,10 +144,8 @@ void sqlite3Update(
if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){
goto update_cleanup;
}
- if( isView ){
- if( sqlite3ViewGetColumnNames(pParse, pTab) ){
- goto update_cleanup;
- }
+ if( sqlite3ViewGetColumnNames(pParse, pTab) ){
+ goto update_cleanup;
}
aXRef = sqliteMallocRaw( sizeof(int) * pTab->nCol );
if( aXRef==0 ) goto update_cleanup;
@@ -242,6 +254,24 @@ void sqlite3Update(
}
}
+ /* Begin generating code.
+ */
+ v = sqlite3GetVdbe(pParse);
+ if( v==0 ) goto update_cleanup;
+ if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
+ sqlite3BeginWriteOperation(pParse, 1, iDb);
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ /* Virtual tables must be handled separately */
+ if( IsVirtual(pTab) ){
+ updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef,
+ pWhere);
+ pWhere = 0;
+ pTabList = 0;
+ goto update_cleanup;
+ }
+#endif
+
/* Resolve the column names in all the expressions in the
** WHERE clause.
*/
@@ -255,20 +285,13 @@ void sqlite3Update(
sqlite3AuthContextPush(pParse, &sContext, pTab->zName);
}
- /* Begin generating code.
- */
- v = sqlite3GetVdbe(pParse);
- if( v==0 ) goto update_cleanup;
- if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
- sqlite3BeginWriteOperation(pParse, 1, iDb);
-
/* If we are trying to update a view, realize that view into
** a ephemeral table.
*/
if( isView ){
Select *pView;
pView = sqlite3SelectDup(pTab->pSelect);
- sqlite3Select(pParse, pView, SRT_VirtualTab, iCur, 0, 0, 0, 0);
+ sqlite3Select(pParse, pView, SRT_EphemTab, iCur, 0, 0, 0, 0);
sqlite3SelectDelete(pView);
}
@@ -277,9 +300,9 @@ void sqlite3Update(
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0);
if( pWInfo==0 ) goto update_cleanup;
- /* Remember the index of every item to be updated.
+ /* Remember the rowid of every item to be updated.
*/
- sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
+ sqlite3VdbeAddOp(v, IsVirtual(pTab) ? OP_VRowid : OP_Rowid, iCur, 0);
sqlite3VdbeAddOp(v, OP_FifoWrite, 0, 0);
/* End the database scan loop.
@@ -289,7 +312,8 @@ void sqlite3Update(
/* Initialize the count of updated rows
*/
if( db->flags & SQLITE_CountRows && !pParse->trigStack ){
- sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
+ memCnt = pParse->nMem++;
+ sqlite3VdbeAddOp(v, OP_MemInt, 0, memCnt);
}
if( triggers_exist ){
@@ -358,7 +382,7 @@ void sqlite3Update(
}
}
- if( !isView ){
+ if( !isView && !IsVirtual(pTab) ){
/*
** Open every index that needs updating. Note that if any
** index could potentially invoke a REPLACE conflict resolution
@@ -390,7 +414,7 @@ void sqlite3Update(
/* Loop over every record that needs updating. We have to load
** the old data for each record to be updated because some columns
** might not change and we will need to copy the old value.
- ** Also, the old data is needed to delete the old index entires.
+ ** Also, the old data is needed to delete the old index entries.
** So make the cursor point at the old record.
*/
if( !triggers_exist ){
@@ -447,7 +471,7 @@ void sqlite3Update(
/* Increment the row counter
*/
if( db->flags & SQLITE_CountRows && !pParse->trigStack){
- sqlite3VdbeAddOp(v, OP_AddImm, 1, 0);
+ sqlite3VdbeAddOp(v, OP_MemIncr, 1, memCnt);
}
/* If there are triggers, close all the cursors after each iteration
@@ -492,6 +516,7 @@ void sqlite3Update(
** invoke the callback function.
*/
if( db->flags & SQLITE_CountRows && !pParse->trigStack && pParse->nested==0 ){
+ sqlite3VdbeAddOp(v, OP_MemLoad, memCnt, 0);
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", P3_STATIC);
@@ -506,3 +531,95 @@ update_cleanup:
sqlite3ExprDelete(pWhere);
return;
}
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/*
+** Generate code for an UPDATE of a virtual table.
+**
+** The strategy is that we create an ephemerial table that contains
+** for each row to be changed:
+**
+** (A) The original rowid of that row.
+** (B) The revised rowid for the row. (note1)
+** (C) The content of every column in the row.
+**
+** Then we loop over this ephemeral table and for each row in
+** the ephermeral table call VUpdate.
+**
+** When finished, drop the ephemeral table.
+**
+** (note1) Actually, if we know in advance that (A) is always the same
+** as (B) we only store (A), then duplicate (A) when pulling
+** it out of the ephemeral table before calling VUpdate.
+*/
+static void updateVirtualTable(
+ Parse *pParse, /* The parsing context */
+ SrcList *pSrc, /* The virtual table to be modified */
+ Table *pTab, /* The virtual table */
+ ExprList *pChanges, /* The columns to change in the UPDATE statement */
+ Expr *pRowid, /* Expression used to recompute the rowid */
+ int *aXRef, /* Mapping from columns of pTab to entries in pChanges */
+ Expr *pWhere /* WHERE clause of the UPDATE statement */
+){
+ Vdbe *v = pParse->pVdbe; /* Virtual machine under construction */
+ ExprList *pEList = 0; /* The result set of the SELECT statement */
+ Select *pSelect = 0; /* The SELECT statement */
+ Expr *pExpr; /* Temporary expression */
+ int ephemTab; /* Table holding the result of the SELECT */
+ int i; /* Loop counter */
+ int addr; /* Address of top of loop */
+
+ /* Construct the SELECT statement that will find the new values for
+ ** all updated rows.
+ */
+ pEList = sqlite3ExprListAppend(0, sqlite3CreateIdExpr("_rowid_"), 0);
+ if( pRowid ){
+ pEList = sqlite3ExprListAppend(pEList, sqlite3ExprDup(pRowid), 0);
+ }
+ assert( pTab->iPKey<0 );
+ for(i=0; inCol; i++){
+ if( aXRef[i]>=0 ){
+ pExpr = sqlite3ExprDup(pChanges->a[aXRef[i]].pExpr);
+ }else{
+ pExpr = sqlite3CreateIdExpr(pTab->aCol[i].zName);
+ }
+ pEList = sqlite3ExprListAppend(pEList, pExpr, 0);
+ }
+ pSelect = sqlite3SelectNew(pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0);
+
+ /* Create the ephemeral table into which the update results will
+ ** be stored.
+ */
+ assert( v );
+ ephemTab = pParse->nTab++;
+ sqlite3VdbeAddOp(v, OP_OpenEphemeral, ephemTab, pTab->nCol+1+(pRowid!=0));
+
+ /* fill the ephemeral table
+ */
+ sqlite3Select(pParse, pSelect, SRT_Table, ephemTab, 0, 0, 0, 0);
+
+ /*
+ ** Generate code to scan the ephemeral table and call VDelete and
+ ** VInsert
+ */
+ sqlite3VdbeAddOp(v, OP_Rewind, ephemTab, 0);
+ addr = sqlite3VdbeCurrentAddr(v);
+ sqlite3VdbeAddOp(v, OP_Column, ephemTab, 0);
+ if( pRowid ){
+ sqlite3VdbeAddOp(v, OP_Column, ephemTab, 1);
+ }else{
+ sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
+ }
+ for(i=0; inCol; i++){
+ sqlite3VdbeAddOp(v, OP_Column, ephemTab, i+1+(pRowid!=0));
+ }
+ pParse->pVirtualLock = pTab;
+ sqlite3VdbeOp3(v, OP_VUpdate, 0, pTab->nCol+2,
+ (const char*)pTab->pVtab, P3_VTAB);
+ sqlite3VdbeAddOp(v, OP_Next, ephemTab, addr);
+ sqlite3VdbeAddOp(v, OP_Close, ephemTab, 0);
+
+ /* Cleanup */
+ sqlite3SelectDelete(pSelect);
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
diff --git a/dlls/sqlite/sqlite-source/utf.c b/dlls/sqlite/sqlite-source/utf.c
index 5df00dad..6b78a6de 100644
--- a/dlls/sqlite/sqlite-source/utf.c
+++ b/dlls/sqlite/sqlite-source/utf.c
@@ -64,7 +64,7 @@
/*
** This table maps from the first byte of a UTF-8 character to the number
-** of trailing bytes expected. A value '255' indicates that the table key
+** of trailing bytes expected. A value '4' indicates that the table key
** is not a legal first byte for a UTF-8 character.
*/
static const u8 xtra_utf8_bytes[256] = {
@@ -79,10 +79,10 @@ static const u8 xtra_utf8_bytes[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 10wwwwww */
-255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
/* 110yyyyy */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -92,7 +92,7 @@ static const u8 xtra_utf8_bytes[256] = {
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* 11110yyy */
-3, 3, 3, 3, 3, 3, 3, 3, 255, 255, 255, 255, 255, 255, 255, 255,
+3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
};
/*
@@ -101,11 +101,24 @@ static const u8 xtra_utf8_bytes[256] = {
** read by a naive implementation of a UTF-8 character reader. The code
** in the READ_UTF8 macro explains things best.
*/
-static const int xtra_utf8_bits[4] = {
-0,
-12416, /* (0xC0 << 6) + (0x80) */
-925824, /* (0xE0 << 12) + (0x80 << 6) + (0x80) */
-63447168 /* (0xF0 << 18) + (0x80 << 12) + (0x80 << 6) + 0x80 */
+static const int xtra_utf8_bits[] = {
+ 0,
+ 12416, /* (0xC0 << 6) + (0x80) */
+ 925824, /* (0xE0 << 12) + (0x80 << 6) + (0x80) */
+ 63447168 /* (0xF0 << 18) + (0x80 << 12) + (0x80 << 6) + 0x80 */
+};
+
+/*
+** If a UTF-8 character contains N bytes extra bytes (N bytes follow
+** the initial byte so that the total character length is N+1) then
+** masking the character with utf8_mask[N] must produce a non-zero
+** result. Otherwise, we have an (illegal) overlong encoding.
+*/
+static const int utf_mask[] = {
+ 0x00000000,
+ 0xffffff80,
+ 0xfffff800,
+ 0xffff0000,
};
#define READ_UTF8(zIn, c) { \
@@ -113,11 +126,14 @@ static const int xtra_utf8_bits[4] = {
c = *(zIn)++; \
xtra = xtra_utf8_bytes[c]; \
switch( xtra ){ \
- case 255: c = (int)0xFFFD; break; \
+ case 4: c = (int)0xFFFD; break; \
case 3: c = (c<<6) + *(zIn)++; \
case 2: c = (c<<6) + *(zIn)++; \
case 1: c = (c<<6) + *(zIn)++; \
c -= xtra_utf8_bits[xtra]; \
+ if( (utf_mask[xtra]&c)==0 \
+ || (c&0xFFFFF800)==0xD800 \
+ || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \
} \
}
int sqlite3ReadUtf8(const unsigned char *z){
@@ -181,6 +197,7 @@ int sqlite3ReadUtf8(const unsigned char *z){
int c2 = (*zIn++); \
c2 += ((*zIn++)<<8); \
c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \
+ if( (c & 0xFFFF0000)==0 ) c = 0xFFFD; \
} \
}
@@ -191,6 +208,7 @@ int sqlite3ReadUtf8(const unsigned char *z){
int c2 = ((*zIn++)<<8); \
c2 += (*zIn++); \
c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \
+ if( (c & 0xFFFF0000)==0 ) c = 0xFFFD; \
} \
}
@@ -245,7 +263,7 @@ int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
unsigned char *zIn; /* Input iterator */
unsigned char *zTerm; /* End of input */
unsigned char *z; /* Output iterator */
- int c;
+ unsigned int c;
assert( pMem->flags&MEM_Str );
assert( pMem->enc!=desiredEnc );
@@ -287,11 +305,11 @@ int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
/* Set len to the maximum number of bytes required in the output buffer. */
if( desiredEnc==SQLITE_UTF8 ){
/* When converting from UTF-16, the maximum growth results from
- ** translating a 2-byte character to a 3-byte UTF-8 character (i.e.
- ** code-point 0xFFFC). A single byte is required for the output string
+ ** translating a 2-byte character to a 4-byte UTF-8 character.
+ ** A single byte is required for the output string
** nul-terminator.
*/
- len = (pMem->n/2) * 3 + 1;
+ len = pMem->n * 2 + 1;
}else{
/* When converting from UTF-8 to UTF-16 the maximum growth is caused
** when a 1-byte UTF-8 character is translated into a 2-byte UTF-16
@@ -462,8 +480,8 @@ char *sqlite3utf16to8(const void *z, int nByte){
memset(&m, 0, sizeof(m));
sqlite3VdbeMemSetStr(&m, z, nByte, SQLITE_UTF16NATIVE, SQLITE_STATIC);
sqlite3VdbeChangeEncoding(&m, SQLITE_UTF8);
- assert( m.flags & MEM_Term );
- assert( m.flags & MEM_Str );
+ assert( (m.flags & MEM_Term)!=0 || sqlite3MallocFailed() );
+ assert( (m.flags & MEM_Str)!=0 || sqlite3MallocFailed() );
return (m.flags & MEM_Dyn)!=0 ? m.z : sqliteStrDup(m.z);
}
@@ -475,7 +493,7 @@ char *sqlite3utf16to8(const void *z, int nByte){
** in pZ (or up until the first pair of 0x00 bytes, whichever comes first).
*/
int sqlite3utf16ByteLen(const void *zIn, int nChar){
- int c = 1;
+ unsigned int c = 1;
char const *z = zIn;
int n = 0;
if( SQLITE_UTF16NATIVE==SQLITE_UTF16BE ){
@@ -556,11 +574,11 @@ void sqlite3utf16Substr(
** characters in each encoding are inverses of each other.
*/
void sqlite3utfSelfTest(){
- int i;
+ unsigned int i, t;
unsigned char zBuf[20];
unsigned char *z;
int n;
- int c;
+ unsigned int c;
for(i=0; i<0x00110000; i++){
z = zBuf;
@@ -568,7 +586,10 @@ void sqlite3utfSelfTest(){
n = z-zBuf;
z = zBuf;
READ_UTF8(z, c);
- assert( c==i );
+ t = i;
+ if( i>=0xD800 && i<=0xDFFF ) t = 0xFFFD;
+ if( (i&0xFFFFFFFE)==0xFFFE ) t = 0xFFFD;
+ assert( c==t );
assert( (z-zBuf)==n );
}
for(i=0; i<0x00110000; i++){
diff --git a/dlls/sqlite/sqlite-source/util.c b/dlls/sqlite/sqlite-source/util.c
index e30401ee..4d8b214e 100644
--- a/dlls/sqlite/sqlite-source/util.c
+++ b/dlls/sqlite/sqlite-source/util.c
@@ -476,8 +476,9 @@ static int OSSIZEOF(void *p){
** pointer to the space allocated for the application to use.
*/
static void OSFREE(void *pFree){
+ u32 *p; /* Pointer to the OS-layer allocation */
sqlite3OsEnterMutex();
- u32 *p = (u32 *)getOsPointer(pFree); /* p points to Os level allocation */
+ p = (u32 *)getOsPointer(pFree);
checkGuards(p);
unlinkAlloc(p);
memset(pFree, 0x55, OSSIZEOF(pFree));
@@ -683,11 +684,11 @@ void sqlite3ReallocOrFree(void **pp, int n){
*/
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
void *sqlite3ThreadSafeMalloc(int n){
- ENTER_MALLOC;
+ (void)ENTER_MALLOC;
return sqlite3Malloc(n, 0);
}
void sqlite3ThreadSafeFree(void *p){
- ENTER_MALLOC;
+ (void)ENTER_MALLOC;
if( p ){
OSFREE(p);
}
@@ -1150,7 +1151,7 @@ int sqlite3SafetyOn(sqlite3 *db){
return 0;
}else if( db->magic==SQLITE_MAGIC_BUSY ){
db->magic = SQLITE_MAGIC_ERROR;
- db->flags |= SQLITE_Interrupt;
+ db->u1.isInterrupted = 1;
}
return 1;
}
@@ -1166,7 +1167,7 @@ int sqlite3SafetyOff(sqlite3 *db){
return 0;
}else if( db->magic==SQLITE_MAGIC_OPEN ){
db->magic = SQLITE_MAGIC_ERROR;
- db->flags |= SQLITE_Interrupt;
+ db->u1.isInterrupted = 1;
}
return 1;
}
@@ -1356,8 +1357,10 @@ void *sqlite3HexToBlob(const char *z){
if( n%2 ) return 0;
zBlob = (char *)sqliteMalloc(n/2);
- for(i=0; ierrMask : 0xff);
}
/*
diff --git a/dlls/sqlite/sqlite-source/vacuum.c b/dlls/sqlite/sqlite-source/vacuum.c
index 336df67c..07f62ae7 100644
--- a/dlls/sqlite/sqlite-source/vacuum.c
+++ b/dlls/sqlite/sqlite-source/vacuum.c
@@ -21,20 +21,6 @@
#include "os.h"
#ifndef SQLITE_OMIT_VACUUM
-/*
-** Generate a random name of 20 character in length.
-*/
-static void randomName(unsigned char *zBuf){
- static const unsigned char zChars[] =
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789";
- int i;
- sqlite3Randomness(20, zBuf);
- for(i=0; i<20; i++){
- zBuf[i] = zChars[ zBuf[i]%(sizeof(zChars)-1) ];
- }
-}
-
/*
** Execute zSql on database db. Return an error code.
*/
@@ -69,8 +55,6 @@ static int execExecSql(sqlite3 *db, const char *zSql){
return sqlite3_finalize(pStmt);
}
-#endif
-
/*
** The non-standard VACUUM command is used to clean up the database,
** collapse free space, etc. It is modelled after the VACUUM command
@@ -94,60 +78,25 @@ void sqlite3Vacuum(Parse *pParse){
*/
int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
int rc = SQLITE_OK; /* Return code from service routines */
-#ifndef SQLITE_OMIT_VACUUM
- const char *zFilename; /* full pathname of the database file */
- int nFilename; /* number of characters in zFilename[] */
- char *zTemp = 0; /* a temporary file in same directory as zFilename */
Btree *pMain; /* The database being vacuumed */
- Btree *pTemp;
- char *zSql = 0;
- int saved_flags; /* Saved value of the db->flags */
- Db *pDb = 0; /* Database to detach at end of vacuum */
+ Btree *pTemp; /* The temporary database we vacuum into */
+ char *zSql = 0; /* SQL statements */
+ int saved_flags; /* Saved value of the db->flags */
+ Db *pDb = 0; /* Database to detach at end of vacuum */
+ char zTemp[SQLITE_TEMPNAME_SIZE+20]; /* Name of the TEMP file */
/* Save the current value of the write-schema flag before setting it. */
saved_flags = db->flags;
db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
+ sqlite3OsTempFileName(zTemp);
if( !db->autoCommit ){
sqlite3SetString(pzErrMsg, "cannot VACUUM from within a transaction",
(char*)0);
rc = SQLITE_ERROR;
goto end_of_vacuum;
}
-
- /* Get the full pathname of the database file and create a
- ** temporary filename in the same directory as the original file.
- */
pMain = db->aDb[0].pBt;
- zFilename = sqlite3BtreeGetFilename(pMain);
- assert( zFilename );
- if( zFilename[0]=='\0' ){
- /* The in-memory database. Do nothing. Return directly to avoid causing
- ** an error trying to DETACH the vacuum_db (which never got attached)
- ** in the exit-handler.
- */
- return SQLITE_OK;
- }
- nFilename = strlen(zFilename);
- zTemp = sqliteMalloc( nFilename+100 );
- if( zTemp==0 ){
- rc = SQLITE_NOMEM;
- goto end_of_vacuum;
- }
- strcpy(zTemp, zFilename);
-
- /* The randomName() procedure in the following loop uses an excellent
- ** source of randomness to generate a name from a space of 1.3e+31
- ** possibilities. So unless the directory already contains on the order
- ** of 1.3e+31 files, the probability that the following loop will
- ** run more than once or twice is vanishingly small. We are certain
- ** enough that this loop will always terminate (and terminate quickly)
- ** that we don't even bother to set a maximum loop count.
- */
- do {
- zTemp[nFilename] = '-';
- randomName((unsigned char*)&zTemp[nFilename+1]);
- } while( sqlite3OsFileExists(zTemp) );
/* Attach the temporary database as 'vacuum_db'. The synchronous pragma
** can be set to 'off' for this file, as it is not recovered if a crash
@@ -190,7 +139,9 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
*/
rc = execExecSql(db,
"SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14,100000000) "
- " FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'");
+ " FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'"
+ " AND rootpage>0"
+ );
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = execExecSql(db,
"SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14,100000000)"
@@ -200,11 +151,6 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
"SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21,100000000) "
" FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
- rc = execExecSql(db,
- "SELECT 'CREATE VIEW vacuum_db.' || substr(sql,13,100000000) "
- " FROM sqlite_master WHERE type='view'"
- );
- if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Loop through the tables in the main database. For each, do
** an "INSERT INTO vacuum_db.xxx SELECT * FROM xxx;" to copy
@@ -214,7 +160,9 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
"SELECT 'INSERT INTO vacuum_db.' || quote(name) "
"|| ' SELECT * FROM ' || quote(name) || ';'"
"FROM sqlite_master "
- "WHERE type = 'table' AND name!='sqlite_sequence';"
+ "WHERE type = 'table' AND name!='sqlite_sequence' "
+ " AND rootpage>0"
+
);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
@@ -233,17 +181,19 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
if( rc!=SQLITE_OK ) goto end_of_vacuum;
- /* Copy the triggers from the main database to the temporary database.
- ** This was deferred before in case the triggers interfered with copying
- ** the data. It's possible the indices should be deferred until this
- ** point also.
+ /* Copy the triggers, views, and virtual tables from the main database
+ ** over to the temporary database. None of these objects has any
+ ** associated storage, so all we have to do is copy their entries
+ ** from the SQLITE_MASTER table.
*/
- rc = execExecSql(db,
- "SELECT 'CREATE TRIGGER vacuum_db.' || substr(sql, 16, 1000000) "
- "FROM sqlite_master WHERE type='trigger'"
+ rc = execSql(db,
+ "INSERT INTO vacuum_db.sqlite_master "
+ " SELECT type, name, tbl_name, rootpage, sql"
+ " FROM sqlite_master"
+ " WHERE type='view' OR type='trigger'"
+ " OR (type='table' AND rootpage=0)"
);
- if( rc!=SQLITE_OK ) goto end_of_vacuum;
-
+ if( rc ) goto end_of_vacuum;
/* At this point, unless the main db was completely empty, there is now a
** transaction open on the vacuum database, but not on the main database.
@@ -309,21 +259,12 @@ end_of_vacuum:
pDb->pSchema = 0;
}
- /* If one of the execSql() calls above returned SQLITE_NOMEM, then the
- ** mallocFailed flag will be clear (because execSql() calls sqlite3_exec()).
- ** Fix this so the flag and return code match.
- */
- if( rc==SQLITE_NOMEM ){
- sqlite3MallocFailed();
- }
-
- if( zTemp ){
- sqlite3OsDelete(zTemp);
- sqliteFree(zTemp);
- }
+ sqlite3OsDelete(zTemp);
+ strcat(zTemp, "-journal");
+ sqlite3OsDelete(zTemp);
sqliteFree( zSql );
sqlite3ResetInternalSchema(db, 0);
-#endif
return rc;
}
+#endif /* SQLITE_OMIT_VACUUM */
diff --git a/dlls/sqlite/sqlite-source/vdbe.c b/dlls/sqlite/sqlite-source/vdbe.c
index 6a5aed89..2e0fa78a 100644
--- a/dlls/sqlite/sqlite-source/vdbe.c
+++ b/dlls/sqlite/sqlite-source/vdbe.c
@@ -57,17 +57,21 @@
** working correctly. This variable has no function other than to
** help verify the correct operation of the library.
*/
+#ifdef SQLITE_TEST
int sqlite3_search_count = 0;
+#endif
/*
** When this global variable is positive, it gets decremented once before
-** each instruction in the VDBE. When reaches zero, the SQLITE_Interrupt
-** of the db.flags field is set in order to simulate and interrupt.
+** each instruction in the VDBE. When reaches zero, the u1.isInterrupted
+** field of the sqlite3 structure is set in order to simulate and interrupt.
**
** This facility is used for testing purposes only. It does not function
** in an ordinary build.
*/
+#ifdef SQLITE_TEST
int sqlite3_interrupt_count = 0;
+#endif
/*
** The next global variable is incremented each type the OP_Sort opcode
@@ -76,7 +80,9 @@ int sqlite3_interrupt_count = 0;
** has no function other than to help verify the correct operation of the
** library.
*/
+#ifdef SQLITE_TEST
int sqlite3_sort_count = 0;
+#endif
/*
** Release the memory associated with the given stack level. This
@@ -180,7 +186,7 @@ static Cursor *allocateCursor(Vdbe *p, int iCur, int iDb){
Cursor *pCx;
assert( iCurnCursor );
if( p->apCsr[iCur] ){
- sqlite3VdbeFreeCursor(p->apCsr[iCur]);
+ sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
}
p->apCsr[iCur] = pCx = sqliteMalloc( sizeof(Cursor) );
if( pCx ){
@@ -376,7 +382,7 @@ __inline__ unsigned long long int hwtime(void){
** flag on jump instructions, we get a (small) speed improvement.
*/
#define CHECK_FOR_INTERRUPT \
- if( db->flags & SQLITE_Interrupt ) goto abort_due_to_interrupt;
+ if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
/*
@@ -448,6 +454,21 @@ int sqlite3VdbeExec(
p->resOnStack = 0;
db->busyHandler.nBusy = 0;
CHECK_FOR_INTERRUPT;
+#ifdef SQLITE_DEBUG
+ if( (p->db->flags & SQLITE_VdbeListing)!=0
+ || sqlite3OsFileExists("vdbe_explain")
+ ){
+ int i;
+ printf("VDBE Program Listing:\n");
+ sqlite3VdbePrintSql(p);
+ for(i=0; inOp; i++){
+ sqlite3VdbePrintOp(stdout, i, &p->aOp[i]);
+ }
+ }
+ if( sqlite3OsFileExists("vdbe_trace") ){
+ p->trace = stdout;
+ }
+#endif
for(pc=p->pc; rc==SQLITE_OK; pc++){
assert( pc>=0 && pcnOp );
assert( pTos<=&p->aStack[pc] );
@@ -495,11 +516,14 @@ int sqlite3VdbeExec(
*/
if( db->xProgress ){
if( db->nProgressOps==nProgressOps ){
+ if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
if( db->xProgress(db->pProgressArg)!=0 ){
+ sqlite3SafetyOn(db);
rc = SQLITE_ABORT;
continue; /* skip to the next iteration of the for loop */
}
nProgressOps = 0;
+ if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
}
nProgressOps++;
}
@@ -1803,32 +1827,31 @@ case OP_IfNot: { /* no-push */
/* Opcode: IsNull P1 P2 *
**
-** If any of the top abs(P1) values on the stack are NULL, then jump
-** to P2. Pop the stack P1 times if P1>0. If P1<0 leave the stack
-** unchanged.
+** Check the top of the stack and jump to P2 if the top of the stack
+** is NULL. If P1 is positive, then pop P1 elements from the stack
+** regardless of whether or not the jump is taken. If P1 is negative,
+** pop -P1 elements from the stack only if the jump is taken and leave
+** the stack unchanged if the jump is not taken.
*/
case OP_IsNull: { /* same as TK_ISNULL, no-push */
- int i, cnt;
- Mem *pTerm;
- cnt = pOp->p1;
- if( cnt<0 ) cnt = -cnt;
- pTerm = &pTos[1-cnt];
- assert( pTerm>=p->aStack );
- for(i=0; iflags & MEM_Null ){
- pc = pOp->p2-1;
- break;
+ if( pTos->flags & MEM_Null ){
+ pc = pOp->p2-1;
+ if( pOp->p1<0 ){
+ popStack(&pTos, -pOp->p1);
}
}
- if( pOp->p1>0 ) popStack(&pTos, cnt);
+ if( pOp->p1>0 ){
+ popStack(&pTos, pOp->p1);
+ }
break;
}
/* Opcode: NotNull P1 P2 *
**
-** Jump to P2 if the top P1 values on the stack are all not NULL. Pop the
-** stack if P1 times if P1 is greater than zero. If P1 is less than
-** zero then leave the stack unchanged.
+** Jump to P2 if the top abs(P1) values on the stack are all not NULL.
+** Regardless of whether or not the jump is taken, pop the stack
+** P1 times if P1 is greater than zero. But if P1 is negative,
+** leave the stack unchanged.
*/
case OP_NotNull: { /* same as TK_NOTNULL, no-push */
int i, cnt;
@@ -2001,7 +2024,9 @@ case OP_Column: {
pC->aRow = 0;
}
}
- assert( zRec!=0 || avail>=payloadSize || avail>=9 );
+ /* The following assert is true in all cases accept when
+ ** the database file has been corrupted externally.
+ ** assert( zRec!=0 || avail>=payloadSize || avail>=9 ); */
szHdrSz = GetVarint((u8*)zData, offset);
/* The KeyFetch() or DataFetch() above are fast and will get the entire
@@ -2492,6 +2517,8 @@ case OP_VerifyCookie: { /* no-push */
}
if( rc==SQLITE_OK && iMeta!=pOp->p2 ){
sqlite3SetString(&p->zErrMsg, "database schema has changed", (char*)0);
+ sqlite3ResetInternalSchema(db, pOp->p1);
+ sqlite3ExpirePreparedStatements(db);
rc = SQLITE_SCHEMA;
}
break;
@@ -2637,9 +2664,9 @@ case OP_OpenWrite: { /* no-push */
break;
}
-/* Opcode: OpenVirtual P1 P2 P3
+/* Opcode: OpenEphemeral P1 P2 P3
**
-** Open a new cursor P1 to a transient or virtual table.
+** Open a new cursor P1 to a transient table.
** The cursor is always opened read/write even if
** the main database is read-only. The transient or virtual
** table is deleted automatically when the cursor is closed.
@@ -2648,8 +2675,14 @@ case OP_OpenWrite: { /* no-push */
** The cursor points to a BTree table if P3==0 and to a BTree index
** if P3 is not 0. If P3 is not NULL, it points to a KeyInfo structure
** that defines the format of keys in the index.
+**
+** This opcode was once called OpenTemp. But that created
+** confusion because the term "temp table", might refer either
+** to a TEMP table at the SQL level, or to a table opened by
+** this opcode. Then this opcode was call OpenVirtual. But
+** that created confusion with the whole virtual-table idea.
*/
-case OP_OpenVirtual: { /* no-push */
+case OP_OpenEphemeral: { /* no-push */
int i = pOp->p1;
Cursor *pCx;
assert( i>=0 );
@@ -2724,7 +2757,7 @@ case OP_OpenPseudo: { /* no-push */
case OP_Close: { /* no-push */
int i = pOp->p1;
if( i>=0 && inCursor ){
- sqlite3VdbeFreeCursor(p->apCsr[i]);
+ sqlite3VdbeFreeCursor(p, p->apCsr[i]);
p->apCsr[i] = 0;
}
break;
@@ -2815,7 +2848,9 @@ case OP_MoveGt: { /* no-push */
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
*pC->pIncrKey = 0;
+#ifdef SQLITE_TEST
sqlite3_search_count++;
+#endif
if( oc==OP_MoveGe || oc==OP_MoveGt ){
if( res<0 ){
rc = sqlite3BtreeNext(pC->pCursor, &res);
@@ -2890,7 +2925,7 @@ case OP_MoveGt: { /* no-push */
**
** The top of the stack holds a blob constructed by MakeRecord. P1 is
** an index. If no entry exists in P1 that matches the blob then jump
-** to P1. If an entry does existing, fall through. The cursor is left
+** to P2. If an entry does existing, fall through. The cursor is left
** pointing to the entry that matches. The blob is popped from the stack.
**
** The difference between this operation and Distinct is that
@@ -2963,7 +2998,7 @@ case OP_IsUnique: { /* no-push */
R = pTos->i;
assert( (pTos->flags & MEM_Dyn)==0 );
pTos--;
- assert( i>=0 && i<=p->nCursor );
+ assert( i>=0 && inCursor );
pCx = p->apCsr[i];
assert( pCx!=0 );
pCrsr = pCx->pCursor;
@@ -3064,6 +3099,9 @@ case OP_NotExists: { /* no-push */
pC->rowidIsValid = res==0;
pC->nullRow = 0;
pC->cacheStatus = CACHE_STALE;
+ /* res might be uninitialized if rc!=SQLITE_OK. But if rc!=SQLITE_OK
+ ** processing is about to abort so we really do not care whether or not
+ ** the following jump is taken. */
if( res!=0 ){
pc = pOp->p2 - 1;
pC->rowidIsValid = 0;
@@ -3260,6 +3298,10 @@ case OP_NewRowid: {
** then rowid is stored for subsequent return by the
** sqlite3_last_insert_rowid() function (otherwise it's unmodified).
**
+** Parameter P3 may point to a string containing the table-name, or
+** may be NULL. If it is not NULL, then the update-hook
+** (sqlite3.xUpdateCallback) is invoked following a successful insert.
+**
** This instruction only works on tables. The equivalent instruction
** for indices is OP_IdxInsert.
*/
@@ -3569,8 +3611,10 @@ case OP_Last: { /* no-push */
** correctly optimizing out sorts.
*/
case OP_Sort: { /* no-push */
+#ifdef SQLITE_TEST
sqlite3_sort_count++;
sqlite3_search_count--;
+#endif
/* Fall through into OP_Rewind */
}
/* Opcode: Rewind P1 P2 *
@@ -3643,7 +3687,9 @@ case OP_Next: { /* no-push */
}
if( res==0 ){
pc = pOp->p2 - 1;
+#ifdef SQLITE_TEST
sqlite3_search_count++;
+#endif
}
}else{
pC->nullRow = 1;
@@ -3827,38 +3873,6 @@ case OP_IdxGE: { /* no-push */
break;
}
-/* Opcode: IdxIsNull P1 P2 *
-**
-** The top of the stack contains an index entry such as might be generated
-** by the MakeIdxRec opcode. This routine looks at the first P1 fields of
-** that key. If any of the first P1 fields are NULL, then a jump is made
-** to address P2. Otherwise we fall straight through.
-**
-** The index entry is always popped from the stack.
-*/
-case OP_IdxIsNull: { /* no-push */
- int i = pOp->p1;
- int k, n;
- const char *z;
- u32 serial_type;
-
- assert( pTos>=p->aStack );
- assert( pTos->flags & MEM_Blob );
- z = pTos->z;
- n = pTos->n;
- k = sqlite3GetVarint32((u8*)z, &serial_type);
- for(; k0; i--){
- k += sqlite3GetVarint32((u8*)&z[k], &serial_type);
- if( serial_type==0 ){ /* Serial type 0 is a NULL */
- pc = pOp->p2-1;
- break;
- }
- }
- Release(pTos);
- pTos--;
- break;
-}
-
/* Opcode: Destroy P1 P2 *
**
** Delete an entire database table or index whose root page in the database
@@ -3881,19 +3895,31 @@ case OP_IdxIsNull: { /* no-push */
*/
case OP_Destroy: {
int iMoved;
- if( db->activeVdbeCnt>1 ){
+ int iCnt;
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ Vdbe *pVdbe;
+ iCnt = 0;
+ for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
+ if( pVdbe->magic==VDBE_MAGIC_RUN && pVdbe->inVtabMethod<2 && pVdbe->pc>=0 ){
+ iCnt++;
+ }
+ }
+#else
+ iCnt = db->activeVdbeCnt;
+#endif
+ if( iCnt>1 ){
rc = SQLITE_LOCKED;
}else{
- assert( db->activeVdbeCnt==1 );
+ assert( iCnt==1 );
rc = sqlite3BtreeDropTable(db->aDb[pOp->p2].pBt, pOp->p1, &iMoved);
pTos++;
pTos->flags = MEM_Int;
pTos->i = iMoved;
- #ifndef SQLITE_OMIT_AUTOVACUUM
+#ifndef SQLITE_OMIT_AUTOVACUUM
if( rc==SQLITE_OK && iMoved!=0 ){
sqlite3RootPageMoved(&db->aDb[pOp->p2], iMoved, pOp->p1);
}
- #endif
+#endif
}
break;
}
@@ -3995,10 +4021,14 @@ case OP_CreateTable: {
break;
}
-/* Opcode: ParseSchema P1 * P3
+/* Opcode: ParseSchema P1 P2 P3
**
** Read and parse all entries from the SQLITE_MASTER table of database P1
-** that match the WHERE clause P3.
+** that match the WHERE clause P3. P2 is the "force" flag. Always do
+** the parsing if P2 is true. If P2 is false, then this routine is a
+** no-op if the schema is not currently loaded. In other words, if P2
+** is false, the SQLITE_MASTER table is only parsed if the rest of the
+** schema is already loaded into the symbol table.
**
** This opcode invokes the parser to create a new virtual machine,
** then runs the new virtual machine. It is thus a reentrant opcode.
@@ -4010,19 +4040,23 @@ case OP_ParseSchema: { /* no-push */
InitData initData;
assert( iDb>=0 && iDbnDb );
- if( !DbHasProperty(db, iDb, DB_SchemaLoaded) ) break;
+ if( !pOp->p2 && !DbHasProperty(db, iDb, DB_SchemaLoaded) ){
+ break;
+ }
zMaster = SCHEMA_TABLE(iDb);
initData.db = db;
+ initData.iDb = pOp->p1;
initData.pzErrMsg = &p->zErrMsg;
zSql = sqlite3MPrintf(
- "SELECT name, rootpage, sql, %d FROM '%q'.%s WHERE %s",
- pOp->p1, db->aDb[iDb].zName, zMaster, pOp->p3);
+ "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s",
+ db->aDb[iDb].zName, zMaster, pOp->p3);
if( zSql==0 ) goto no_mem;
sqlite3SafetyOff(db);
assert( db->init.busy==0 );
db->init.busy = 1;
assert( !sqlite3MallocFailed() );
rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
+ if( rc==SQLITE_ABORT ) rc = initData.rc;
sqliteFree(zSql);
db->init.busy = 0;
sqlite3SafetyOn(db);
@@ -4086,11 +4120,16 @@ case OP_DropTrigger: { /* no-push */
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
-/* Opcode: IntegrityCk * P2 *
+/* Opcode: IntegrityCk P1 P2 *
**
** Do an analysis of the currently open database. Push onto the
** stack the text of an error message describing any problems.
-** If there are no errors, push a "ok" onto the stack.
+** If no problems are found, push a NULL onto the stack.
+**
+** P1 is the address of a memory cell that contains the maximum
+** number of allowed errors. At most mem[P1] errors will be reported.
+** In other words, the analysis stops as soon as mem[P1] errors are
+** seen. Mem[P1] is updated with the number of errors remaining.
**
** The root page numbers of all tables in the database are integer
** values on the stack. This opcode pulls as many integers as it
@@ -4099,13 +4138,15 @@ case OP_DropTrigger: { /* no-push */
** If P2 is not zero, the check is done on the auxiliary database
** file, not the main database file.
**
-** This opcode is used for testing purposes only.
+** This opcode is used to implement the integrity_check pragma.
*/
case OP_IntegrityCk: {
int nRoot;
int *aRoot;
int j;
+ int nErr;
char *z;
+ Mem *pnErr;
for(nRoot=0; &pTos[-nRoot]>=p->aStack; nRoot++){
if( (pTos[-nRoot].flags & MEM_Int)==0 ) break;
@@ -4113,6 +4154,10 @@ case OP_IntegrityCk: {
assert( nRoot>0 );
aRoot = sqliteMallocRaw( sizeof(int*)*(nRoot+1) );
if( aRoot==0 ) goto no_mem;
+ j = pOp->p1;
+ assert( j>=0 && jnMem );
+ pnErr = &p->aMem[j];
+ assert( (pnErr->flags & MEM_Int)!=0 );
for(j=0; ji;
@@ -4120,12 +4165,12 @@ case OP_IntegrityCk: {
aRoot[j] = 0;
popStack(&pTos, nRoot);
pTos++;
- z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p2].pBt, aRoot, nRoot);
- if( z==0 || z[0]==0 ){
- if( z ) sqliteFree(z);
- pTos->z = "ok";
- pTos->n = 2;
- pTos->flags = MEM_Str | MEM_Static | MEM_Term;
+ z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p2].pBt, aRoot, nRoot,
+ (int)pnErr->i, &nErr);
+ pnErr->i -= nErr;
+ if( nErr==0 ){
+ assert( z==0 );
+ pTos->flags = MEM_Null;
}else{
pTos->z = z;
pTos->n = strlen(z);
@@ -4461,6 +4506,7 @@ case OP_AggFinal: { /* no-push */
}
+#ifndef SQLITE_OMIT_VACUUM
/* Opcode: Vacuum * * *
**
** Vacuum the entire database. This opcode will cause other virtual
@@ -4473,6 +4519,7 @@ case OP_Vacuum: { /* no-push */
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
break;
}
+#endif
/* Opcode: Expire P1 * *
**
@@ -4522,7 +4569,316 @@ case OP_TableLock: { /* no-push */
}
break;
}
-#endif /* SHARED_OMIT_SHARED_CACHE */
+#endif /* SQLITE_OMIT_SHARED_CACHE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VBegin * * P3
+**
+** P3 a pointer to an sqlite3_vtab structure. Call the xBegin method
+** for that table.
+*/
+case OP_VBegin: { /* no-push */
+ rc = sqlite3VtabBegin(db, (sqlite3_vtab *)pOp->p3);
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VCreate P1 * P3
+**
+** P3 is the name of a virtual table in database P1. Call the xCreate method
+** for that table.
+*/
+case OP_VCreate: { /* no-push */
+ rc = sqlite3VtabCallCreate(db, pOp->p1, pOp->p3, &p->zErrMsg);
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VDestroy P1 * P3
+**
+** P3 is the name of a virtual table in database P1. Call the xDestroy method
+** of that table.
+*/
+case OP_VDestroy: { /* no-push */
+ p->inVtabMethod = 2;
+ rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p3);
+ p->inVtabMethod = 0;
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VOpen P1 * P3
+**
+** P3 is a pointer to a virtual table object, an sqlite3_vtab structure.
+** P1 is a cursor number. This opcode opens a cursor to the virtual
+** table and stores that cursor in P1.
+*/
+case OP_VOpen: { /* no-push */
+ Cursor *pCur = 0;
+ sqlite3_vtab_cursor *pVtabCursor = 0;
+
+ sqlite3_vtab *pVtab = (sqlite3_vtab *)(pOp->p3);
+ sqlite3_module *pModule = (sqlite3_module *)pVtab->pModule;
+
+ assert(pVtab && pModule);
+ if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
+ rc = pModule->xOpen(pVtab, &pVtabCursor);
+ if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
+ if( SQLITE_OK==rc ){
+ /* Initialise sqlite3_vtab_cursor base class */
+ pVtabCursor->pVtab = pVtab;
+
+ /* Initialise vdbe cursor object */
+ pCur = allocateCursor(p, pOp->p1, -1);
+ if( pCur ){
+ pCur->pVtabCursor = pVtabCursor;
+ pCur->pModule = pVtabCursor->pVtab->pModule;
+ }else{
+ pModule->xClose(pVtabCursor);
+ }
+ }
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VFilter P1 P2 P3
+**
+** P1 is a cursor opened using VOpen. P2 is an address to jump to if
+** the filtered result set is empty.
+**
+** P3 is either NULL or a string that was generated by the xBestIndex
+** method of the module. The interpretation of the P3 string is left
+** to the module implementation.
+**
+** This opcode invokes the xFilter method on the virtual table specified
+** by P1. The integer query plan parameter to xFilter is the top of the
+** stack. Next down on the stack is the argc parameter. Beneath the
+** next of stack are argc additional parameters which are passed to
+** xFilter as argv. The topmost parameter (i.e. 3rd element popped from
+** the stack) becomes argv[argc-1] when passed to xFilter.
+**
+** The integer query plan parameter, argc, and all argv stack values
+** are popped from the stack before this instruction completes.
+**
+** A jump is made to P2 if the result set after filtering would be
+** empty.
+*/
+case OP_VFilter: { /* no-push */
+ int nArg;
+
+ const sqlite3_module *pModule;
+
+ Cursor *pCur = p->apCsr[pOp->p1];
+ assert( pCur->pVtabCursor );
+ pModule = pCur->pVtabCursor->pVtab->pModule;
+
+ /* Grab the index number and argc parameters off the top of the stack. */
+ assert( (&pTos[-1])>=p->aStack );
+ assert( (pTos[0].flags&MEM_Int)!=0 && pTos[-1].flags==MEM_Int );
+ nArg = (int)pTos[-1].i;
+
+ /* Invoke the xFilter method */
+ {
+ int res = 0;
+ int i;
+ Mem **apArg = p->apArg;
+ for(i = 0; iinVtabMethod = 1;
+ rc = pModule->xFilter(pCur->pVtabCursor, (int)pTos->i, pOp->p3, nArg, apArg);
+ p->inVtabMethod = 0;
+ if( rc==SQLITE_OK ){
+ res = pModule->xEof(pCur->pVtabCursor);
+ }
+ if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
+
+ if( res ){
+ pc = pOp->p2 - 1;
+ }
+ }
+
+ /* Pop the index number, argc value and parameters off the stack */
+ popStack(&pTos, 2+nArg);
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VRowid P1 * *
+**
+** Push an integer onto the stack which is the rowid of
+** the virtual-table that the P1 cursor is pointing to.
+*/
+case OP_VRowid: {
+ const sqlite3_module *pModule;
+
+ Cursor *pCur = p->apCsr[pOp->p1];
+ assert( pCur->pVtabCursor );
+ pModule = pCur->pVtabCursor->pVtab->pModule;
+ if( pModule->xRowid==0 ){
+ sqlite3SetString(&p->zErrMsg, "Unsupported module operation: xRowid", 0);
+ rc = SQLITE_ERROR;
+ } else {
+ sqlite_int64 iRow;
+
+ if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
+ rc = pModule->xRowid(pCur->pVtabCursor, &iRow);
+ if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
+
+ pTos++;
+ pTos->flags = MEM_Int;
+ pTos->i = iRow;
+ }
+
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VColumn P1 P2 *
+**
+** Push onto the stack the value of the P2-th column of
+** the row of the virtual-table that the P1 cursor is pointing to.
+*/
+case OP_VColumn: {
+ const sqlite3_module *pModule;
+
+ Cursor *pCur = p->apCsr[pOp->p1];
+ assert( pCur->pVtabCursor );
+ pModule = pCur->pVtabCursor->pVtab->pModule;
+ if( pModule->xColumn==0 ){
+ sqlite3SetString(&p->zErrMsg, "Unsupported module operation: xColumn", 0);
+ rc = SQLITE_ERROR;
+ } else {
+ sqlite3_context sContext;
+ memset(&sContext, 0, sizeof(sContext));
+ sContext.s.flags = MEM_Null;
+ if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
+ rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2);
+
+ /* Copy the result of the function to the top of the stack. We
+ ** do this regardless of whether or not an error occured to ensure any
+ ** dynamic allocation in sContext.s (a Mem struct) is released.
+ */
+ sqlite3VdbeChangeEncoding(&sContext.s, encoding);
+ pTos++;
+ pTos->flags = 0;
+ sqlite3VdbeMemMove(pTos, &sContext.s);
+
+ if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
+ }
+
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VNext P1 P2 *
+**
+** Advance virtual table P1 to the next row in its result set and
+** jump to instruction P2. Or, if the virtual table has reached
+** the end of its result set, then fall through to the next instruction.
+*/
+case OP_VNext: { /* no-push */
+ const sqlite3_module *pModule;
+ int res = 0;
+
+ Cursor *pCur = p->apCsr[pOp->p1];
+ assert( pCur->pVtabCursor );
+ pModule = pCur->pVtabCursor->pVtab->pModule;
+ if( pModule->xNext==0 ){
+ sqlite3SetString(&p->zErrMsg, "Unsupported module operation: xNext", 0);
+ rc = SQLITE_ERROR;
+ } else {
+ /* Invoke the xNext() method of the module. There is no way for the
+ ** underlying implementation to return an error if one occurs during
+ ** xNext(). Instead, if an error occurs, true is returned (indicating that
+ ** 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;
+ 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 */
+ pc = pOp->p2 - 1;
+ }
+ }
+
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VUpdate P1 P2 P3
+**
+** P3 is a pointer to a virtual table object, an sqlite3_vtab structure.
+** This opcode invokes the corresponding xUpdate method. P2 values
+** are taken from the stack to pass to the xUpdate invocation. The
+** value on the top of the stack corresponds to the p2th element
+** of the argv array passed to xUpdate.
+**
+** The xUpdate method will do a DELETE or an INSERT or both.
+** The argv[0] element (which corresponds to the P2-th element down
+** on the stack) is the rowid of a row to delete. If argv[0] is
+** NULL then no deletion occurs. The argv[1] element is the rowid
+** of the new row. This can be NULL to have the virtual table
+** select the new rowid for itself. The higher elements in the
+** stack are the values of columns in the new row.
+**
+** If P2==1 then no insert is performed. argv[0] is the rowid of
+** a row to delete.
+**
+** P1 is a boolean flag. If it is set to true and the xUpdate call
+** is successful, then the value returned by sqlite3_last_insert_rowid()
+** is set to the value of the rowid for the row just inserted.
+*/
+case OP_VUpdate: { /* no-push */
+ sqlite3_vtab *pVtab = (sqlite3_vtab *)(pOp->p3);
+ sqlite3_module *pModule = (sqlite3_module *)pVtab->pModule;
+ int nArg = pOp->p2;
+ assert( pOp->p3type==P3_VTAB );
+ if( pModule->xUpdate==0 ){
+ sqlite3SetString(&p->zErrMsg, "read-only table", 0);
+ rc = SQLITE_ERROR;
+ }else{
+ int i;
+ sqlite_int64 rowid;
+ Mem **apArg = p->apArg;
+ Mem *pX = &pTos[1-nArg];
+ for(i = 0; ixUpdate(pVtab, nArg, apArg, &rowid);
+ sqlite3VtabUnlock(pVtab);
+ if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
+ if( pOp->p1 && rc==SQLITE_OK ){
+ assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );
+ db->lastRowid = rowid;
+ }
+ }
+ popStack(&pTos, nArg);
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
/* An other opcode is illegal...
*/
@@ -4560,8 +4916,12 @@ default: {
** the evaluator loop. So we can leave it out when NDEBUG is defined.
*/
#ifndef NDEBUG
- /* Sanity checking on the top element of the stack */
- if( pTos>=p->aStack ){
+ /* Sanity checking on the top element of the stack. If the previous
+ ** instruction was VNoChange, then the flags field of the top
+ ** of the stack is set to 0. This is technically invalid for a memory
+ ** cell, so avoid calling MemSanity() in this case.
+ */
+ if( pTos>=p->aStack && pTos->flags ){
sqlite3VdbeMemSanity(pTos);
}
assert( pc>=-1 && pcnOp );
@@ -4634,8 +4994,7 @@ abort_due_to_error:
** flag.
*/
abort_due_to_interrupt:
- assert( db->flags & SQLITE_Interrupt );
- db->flags &= ~SQLITE_Interrupt;
+ assert( db->u1.isInterrupted );
if( db->magic!=SQLITE_MAGIC_BUSY ){
rc = SQLITE_MISUSE;
}else{
diff --git a/dlls/sqlite/sqlite-source/vdbe.h b/dlls/sqlite/sqlite-source/vdbe.h
index 11f8aff5..385a60bd 100644
--- a/dlls/sqlite/sqlite-source/vdbe.h
+++ b/dlls/sqlite/sqlite-source/vdbe.h
@@ -69,7 +69,9 @@ typedef struct VdbeOpList VdbeOpList;
#define P3_KEYINFO (-6) /* P3 is a pointer to a KeyInfo structure */
#define P3_VDBEFUNC (-7) /* P3 is a pointer to a VdbeFunc structure */
#define P3_MEM (-8) /* P3 is a pointer to a Mem* structure */
-#define P3_TRANSIENT (-9) /* P3 is a pointer to a transient string */
+#define P3_TRANSIENT (-9) /* P3 is a pointer to a transient string */
+#define P3_VTAB (-10) /* P3 is a pointer to an sqlite3_vtab structure */
+#define P3_MPRINTF (-11) /* P3 is a string obtained from sqlite3_mprintf() */
/* When adding a P3 argument using P3_KEYINFO, a copy of the KeyInfo structure
** is made. That copy is freed when the Vdbe is finalized. But if the
@@ -127,12 +129,16 @@ int sqlite3VdbeFinalize(Vdbe*);
void sqlite3VdbeResolveLabel(Vdbe*, int);
int sqlite3VdbeCurrentAddr(Vdbe*);
void sqlite3VdbeTrace(Vdbe*,FILE*);
+void sqlite3VdbeResetStepResult(Vdbe*);
int sqlite3VdbeReset(Vdbe*);
int sqliteVdbeSetVariables(Vdbe*,int,const char**);
void sqlite3VdbeSetNumCols(Vdbe*,int);
int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, int);
void sqlite3VdbeCountChanges(Vdbe*);
sqlite3 *sqlite3VdbeDb(Vdbe*);
+void sqlite3VdbeSetSql(Vdbe*, const char *z, int n);
+const char *sqlite3VdbeGetSql(Vdbe*);
+void sqlite3VdbeSwap(Vdbe*,Vdbe*);
#ifndef NDEBUG
void sqlite3VdbeComment(Vdbe*, const char*, ...);
diff --git a/dlls/sqlite/sqlite-source/vdbeInt.h b/dlls/sqlite/sqlite-source/vdbeInt.h
index 01d6a61f..d2f737c9 100644
--- a/dlls/sqlite/sqlite-source/vdbeInt.h
+++ b/dlls/sqlite/sqlite-source/vdbeInt.h
@@ -15,6 +15,8 @@
** 6000 lines long) it was split up into several smaller files and
** this header information was factored out.
*/
+#ifndef _VDBEINT_H_
+#define _VDBEINT_H_
/*
** intToKey() and keyToInt() used to transform the rowid. But with
@@ -83,6 +85,8 @@ struct Cursor {
KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
int nField; /* Number of fields in the header */
i64 seqCount; /* Sequence counter */
+ sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
+ const sqlite3_module *pModule; /* Module for cursor pVtabCursor */
/* Cached information about the header for the data record that the
** cursor is currently pointing to. Only valid if cacheValid is true.
@@ -268,6 +272,14 @@ struct Context {
**
** The "sqlite3_stmt" structure pointer that is returned by sqlite3_compile()
** is really a pointer to an instance of this structure.
+**
+** The Vdbe.inVtabMethod variable is set to non-zero for the duration of
+** any virtual table method invocations made by the vdbe program. It is
+** set to 2 for xDestroy method calls and 1 for all other methods. This
+** variable is used for two purposes: to allow xDestroy methods to execute
+** "DROP TABLE" statements and to prevent some nasty side effects of
+** malloc failure when SQLite is invoked recursively by a virtual table
+** method function.
*/
struct Vdbe {
sqlite3 *db; /* The whole database */
@@ -315,8 +327,11 @@ struct Vdbe {
u8 aborted; /* True if ROLLBACK in another VM causes an abort */
u8 expired; /* True if the VM needs to be recompiled */
u8 minWriteFileFormat; /* Minimum file format for writable database files */
+ u8 inVtabMethod; /* See comments above */
int nChange; /* Number of db changes made since last reset */
i64 startTime; /* Time when query started - used for profiling */
+ int nSql; /* Number of bytes in zSql */
+ char *zSql; /* Text of the SQL statement that generated this */
#ifdef SQLITE_SSE
int fetchId; /* Statement number used by sqlite3_fetch_statement */
int lru; /* Counter used for LRU cache replacement */
@@ -334,7 +349,7 @@ struct Vdbe {
/*
** Function prototypes
*/
-void sqlite3VdbeFreeCursor(Cursor*);
+void sqlite3VdbeFreeCursor(Vdbe *, Cursor*);
void sqliteVdbePopStack(Vdbe*,int);
int sqlite3VdbeCursorMoveto(Cursor*);
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
@@ -390,3 +405,5 @@ void sqlite3VdbeFifoInit(Fifo*);
int sqlite3VdbeFifoPush(Fifo*, i64);
int sqlite3VdbeFifoPop(Fifo*, i64*);
void sqlite3VdbeFifoClear(Fifo*);
+
+#endif /* !defined(_VDBEINT_H_) */
diff --git a/dlls/sqlite/sqlite-source/vdbeapi.c b/dlls/sqlite/sqlite-source/vdbeapi.c
index f25cdcee..b01f5c46 100644
--- a/dlls/sqlite/sqlite-source/vdbeapi.c
+++ b/dlls/sqlite/sqlite-source/vdbeapi.c
@@ -153,9 +153,13 @@ void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){
/*
** Execute the statement pStmt, either until a row of data is ready, the
** statement is completely executed or an error occurs.
+**
+** This routine implements the bulk of the logic behind the sqlite_step()
+** API. The only thing omitted is the automatic recompile if a
+** schema change has occurred. That detail is handled by the
+** outer sqlite3_step() wrapper procedure.
*/
-int sqlite3_step(sqlite3_stmt *pStmt){
- Vdbe *p = (Vdbe*)pStmt;
+static int sqlite3Step(Vdbe *p){
sqlite3 *db;
int rc;
@@ -172,7 +176,8 @@ int sqlite3_step(sqlite3_stmt *pStmt){
if( p->rc==SQLITE_OK ){
p->rc = SQLITE_SCHEMA;
}
- return SQLITE_ERROR;
+ rc = SQLITE_ERROR;
+ goto end_of_step;
}
db = p->db;
if( sqlite3SafetyOn(db) ){
@@ -180,6 +185,14 @@ int sqlite3_step(sqlite3_stmt *pStmt){
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
+ ** from interrupting a statement that has not yet started.
+ */
+ if( db->activeVdbeCnt==0 ){
+ db->u1.isInterrupted = 0;
+ }
+
#ifndef SQLITE_OMIT_TRACE
/* Invoke the trace callback if there is one
*/
@@ -198,7 +211,7 @@ int sqlite3_step(sqlite3_stmt *pStmt){
if( db->xProfile && !db->init.busy ){
double rNow;
sqlite3OsCurrentTime(&rNow);
- p->startTime = (int)((rNow - (int)rNow)*3600.0*24.0*1000000000.0);
+ p->startTime = (i64)((rNow - (int)rNow)*3600.0*24.0*1000000000.0);
}
#endif
@@ -246,8 +259,42 @@ int sqlite3_step(sqlite3_stmt *pStmt){
sqlite3Error(p->db, rc, 0);
p->rc = sqlite3ApiExit(p->db, p->rc);
+end_of_step:
+ assert( (rc&0xff)==rc );
+ if( p->zSql && (rc&0xff)rc;
+ }else{
+ /* This is for legacy sqlite3_prepare() builds and when the code
+ ** is SQLITE_ROW or SQLITE_DONE */
+ return rc;
+ }
+}
+
+/*
+** This is the top-level implementation of sqlite3_step(). Call
+** sqlite3Step() to do most of the work. If a schema error occurs,
+** call sqlite3Reprepare() and try again.
+*/
+#ifdef SQLITE_OMIT_PARSER
+int sqlite3_step(sqlite3_stmt *pStmt){
+ return sqlite3Step((Vdbe*)pStmt);
+}
+#else
+int sqlite3_step(sqlite3_stmt *pStmt){
+ int cnt = 0;
+ int rc;
+ Vdbe *v = (Vdbe*)pStmt;
+ while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
+ && cnt++ < 5
+ && sqlite3Reprepare(v) ){
+ sqlite3_reset(pStmt);
+ v->expired = 0;
+ }
return rc;
}
+#endif
/*
** Extract the user data from a sqlite3_context structure and return a
@@ -258,6 +305,27 @@ void *sqlite3_user_data(sqlite3_context *p){
return p->pFunc->pUserData;
}
+/*
+** The following is the implementation of an SQL function that always
+** fails with an error message stating that the function is used in the
+** wrong context. The sqlite3_overload_function() API might construct
+** SQL function that use this routine so that the functions will exist
+** for name resolution but are actually overloaded by the xFindFunction
+** method of virtual tables.
+*/
+void sqlite3InvalidFunction(
+ sqlite3_context *context, /* The function calling context */
+ int argc, /* Number of arguments to the function */
+ sqlite3_value **argv /* Value of each argument */
+){
+ const char *zName = context->pFunc->zName;
+ char *zErr;
+ zErr = sqlite3MPrintf(
+ "unable to use function %s in the requested context", zName);
+ sqlite3_result_error(context, zErr, -1);
+ sqliteFree(zErr);
+}
+
/*
** Allocate or return the aggregate context for a user function. A new
** context is allocated on the first call. Subsequent calls return the
@@ -375,10 +443,9 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){
Vdbe *pVm = (Vdbe *)pStmt;
int vals = sqlite3_data_count(pStmt);
if( i>=vals || i<0 ){
- static Mem nullMem;
- if( nullMem.flags==0 ){ nullMem.flags = MEM_Null; }
+ static const Mem nullMem = {0, 0.0, "", 0, MEM_Null, MEM_Null };
sqlite3Error(pVm->db, SQLITE_RANGE, 0);
- return &nullMem;
+ return (Mem*)&nullMem;
}
return &pVm->pTos[(1-vals)+i];
}
@@ -454,11 +521,9 @@ const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int i){
columnMallocFailure(pStmt);
return val;
}
-#if 0
sqlite3_value *sqlite3_column_value(sqlite3_stmt *pStmt, int i){
return columnMem(pStmt, i);
}
-#endif
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){
const void *val = sqlite3_value_text16( columnMem(pStmt,i) );
@@ -713,6 +778,15 @@ int sqlite3_bind_text16(
return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE);
}
#endif /* SQLITE_OMIT_UTF16 */
+int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){
+ int rc;
+ Vdbe *p = (Vdbe *)pStmt;
+ rc = vdbeUnbind(p, i);
+ if( rc==SQLITE_OK ){
+ sqlite3VdbeMemCopy(&p->aVar[i-1], pValue);
+ }
+ return rc;
+}
/*
** Return the number of wildcards that can be potentially bound to.
@@ -801,6 +875,7 @@ int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
rc = sqlite3VdbeMemMove(&pTo->aVar[i], &pFrom->aVar[i]);
sqlite3MallocAllow();
}
+ assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
return rc;
}
diff --git a/dlls/sqlite/sqlite-source/vdbeaux.c b/dlls/sqlite/sqlite-source/vdbeaux.c
index f96a280c..2ebcd84e 100644
--- a/dlls/sqlite/sqlite-source/vdbeaux.c
+++ b/dlls/sqlite/sqlite-source/vdbeaux.c
@@ -48,6 +48,46 @@ Vdbe *sqlite3VdbeCreate(sqlite3 *db){
return p;
}
+/*
+** Remember the SQL string for a prepared statement.
+*/
+void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n){
+ if( p==0 ) return;
+ assert( p->zSql==0 );
+ p->zSql = sqlite3StrNDup(z, n);
+}
+
+/*
+** Return the SQL associated with a prepared statement
+*/
+const char *sqlite3VdbeGetSql(Vdbe *p){
+ return p->zSql;
+}
+
+/*
+** Swap all content between two VDBE structures.
+*/
+void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
+ Vdbe tmp, *pTmp;
+ char *zTmp;
+ int nTmp;
+ tmp = *pA;
+ *pA = *pB;
+ *pB = tmp;
+ pTmp = pA->pNext;
+ pA->pNext = pB->pNext;
+ pB->pNext = pTmp;
+ pTmp = pA->pPrev;
+ pA->pPrev = pB->pPrev;
+ pB->pPrev = pTmp;
+ zTmp = pA->zSql;
+ pA->zSql = pB->zSql;
+ pB->zSql = zTmp;
+ nTmp = pA->nSql;
+ pA->nSql = pB->nSql;
+ pB->nSql = nTmp;
+}
+
/*
** Turn tracing on or off
*/
@@ -228,7 +268,7 @@ int sqlite3VdbeOpcodeNoPush(u8 op){
** This routine is called once after all opcodes have been inserted.
**
** Variable *pMaxFuncArgs is set to the maximum value of any P2 argument
-** to an OP_Function or OP_AggStep opcode. This is used by
+** to an OP_Function, OP_AggStep or OP_VFilter opcode. This is used by
** sqlite3VdbeMakeReady() to size the Vdbe.apArg[] array.
**
** The integer *pMaxStack is set to the maximum number of vdbe stack
@@ -251,20 +291,25 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs, int *pMaxStack){
for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
u8 opcode = pOp->opcode;
- if( opcode==OP_Function || opcode==OP_AggStep ){
+ if( opcode==OP_Function || opcode==OP_AggStep
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ || opcode==OP_VUpdate
+#endif
+ ){
if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
}else if( opcode==OP_Halt ){
if( pOp->p1==SQLITE_CONSTRAINT && pOp->p2==OE_Abort ){
doesStatementRollback = 1;
}
- }else if( opcode==OP_IdxInsert ){
- if( pOp->p2 ){
- doesStatementRollback = 1;
- }
}else if( opcode==OP_Statement ){
hasStatementBegin = 1;
+ }else if( opcode==OP_VFilter ){
+ int n;
+ assert( p->nOp - i >= 3 );
+ assert( pOp[-2].opcode==OP_Integer );
+ n = pOp[-2].p1;
+ if( n>nMaxArgs ) nMaxArgs = n;
}
-
if( opcodeNoPush(opcode) ){
nMaxStack--;
}
@@ -368,6 +413,17 @@ void sqlite3VdbeJumpHere(Vdbe *p, int addr){
sqlite3VdbeChangeP2(p, addr, p->nOp);
}
+
+/*
+** If the input FuncDef structure is ephemeral, then free it. If
+** the FuncDef is not ephermal, then do nothing.
+*/
+static void freeEphemeralFunction(FuncDef *pDef){
+ if( pDef && (pDef->flags & SQLITE_FUNC_EPHEM)!=0 ){
+ sqliteFree(pDef);
+ }
+}
+
/*
** Delete a P3 value if necessary.
*/
@@ -380,12 +436,21 @@ static void freeP3(int p3type, void *p3){
sqliteFree(p3);
break;
}
+ case P3_MPRINTF: {
+ sqlite3_free(p3);
+ break;
+ }
case P3_VDBEFUNC: {
VdbeFunc *pVdbeFunc = (VdbeFunc *)p3;
+ freeEphemeralFunction(pVdbeFunc->pFunc);
sqlite3VdbeDeleteAuxData(pVdbeFunc, 0);
sqliteFree(pVdbeFunc);
break;
}
+ case P3_FUNCDEF: {
+ freeEphemeralFunction((FuncDef*)p3);
+ break;
+ }
case P3_MEM: {
sqlite3ValueFree((sqlite3_value*)p3);
break;
@@ -558,15 +623,18 @@ static char *displayP3(Op *pOp, char *zTemp, int nTemp){
}
case P3_FUNCDEF: {
FuncDef *pDef = (FuncDef*)pOp->p3;
- char zNum[30];
- sprintf(zTemp, "%.*s", nTemp, pDef->zName);
- sprintf(zNum,"(%d)", pDef->nArg);
- if( strlen(zTemp)+strlen(zNum)+1<=(size_t)nTemp ){
- strcat(zTemp, zNum);
- }
+ sqlite3_snprintf(nTemp, zTemp, "%s(%d)", pDef->zName, pDef->nArg);
zP3 = zTemp;
break;
}
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ case P3_VTAB: {
+ sqlite3_vtab *pVtab = (sqlite3_vtab*)pOp->p3;
+ sqlite3_snprintf(nTemp, zTemp, "vtab:%p:%p", pVtab, pVtab->pModule);
+ zP3 = zTemp;
+ break;
+ }
+#endif
default: {
zP3 = pOp->p3;
if( zP3==0 || pOp->opcode==OP_Noop ){
@@ -574,6 +642,7 @@ static char *displayP3(Op *pOp, char *zTemp, int nTemp){
}
}
}
+ assert( zP3!=0 );
return zP3;
}
#endif
@@ -641,8 +710,7 @@ int sqlite3VdbeList(
if( i>=p->nOp ){
p->rc = SQLITE_OK;
rc = SQLITE_DONE;
- }else if( db->flags & SQLITE_Interrupt ){
- db->flags &= ~SQLITE_Interrupt;
+ }else if( db->u1.isInterrupted ){
p->rc = SQLITE_INTERRUPT;
rc = SQLITE_ERROR;
sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(p->rc), (char*)0);
@@ -656,6 +724,7 @@ int sqlite3VdbeList(
pMem->flags = MEM_Static|MEM_Str|MEM_Term;
pMem->z = sqlite3OpcodeNames[pOp->opcode]; /* Opcode */
+ assert( pMem->z!=0 );
pMem->n = strlen(pMem->z);
pMem->type = SQLITE_TEXT;
pMem->enc = SQLITE_UTF8;
@@ -673,6 +742,7 @@ int sqlite3VdbeList(
pMem->flags = MEM_Ephem|MEM_Str|MEM_Term; /* P3 */
pMem->z = displayP3(pOp, pMem->zShort, sizeof(pMem->zShort));
+ assert( pMem->z!=0 );
pMem->n = strlen(pMem->z);
pMem->type = SQLITE_TEXT;
pMem->enc = SQLITE_UTF8;
@@ -752,7 +822,9 @@ void sqlite3VdbeMakeReady(
resizeOpArray(p, p->nOp);
assert( nVar>=0 );
assert( nStacknOp );
- nStack = isExplain ? 10 : nStack;
+ if( isExplain ){
+ nStack = 10;
+ }
p->aStack = sqliteMalloc(
nStack*sizeof(p->aStack[0]) /* aStack */
+ nArg*sizeof(Mem*) /* apArg */
@@ -780,21 +852,6 @@ void sqlite3VdbeMakeReady(
p->aMem[n].flags = MEM_Null;
}
-#ifdef SQLITE_DEBUG
- if( (p->db->flags & SQLITE_VdbeListing)!=0
- || sqlite3OsFileExists("vdbe_explain")
- ){
- int i;
- printf("VDBE Program Listing:\n");
- sqlite3VdbePrintSql(p);
- for(i=0; inOp; i++){
- sqlite3VdbePrintOp(stdout, i, &p->aOp[i]);
- }
- }
- if( sqlite3OsFileExists("vdbe_trace") ){
- p->trace = stdout;
- }
-#endif
p->pTos = &p->aStack[-1];
p->pc = -1;
p->rc = SQLITE_OK;
@@ -822,7 +879,7 @@ void sqlite3VdbeMakeReady(
** Close a cursor and release all the resources that cursor happens
** to hold.
*/
-void sqlite3VdbeFreeCursor(Cursor *pCx){
+void sqlite3VdbeFreeCursor(Vdbe *p, Cursor *pCx){
if( pCx==0 ){
return;
}
@@ -832,6 +889,17 @@ void sqlite3VdbeFreeCursor(Cursor *pCx){
if( pCx->pBt ){
sqlite3BtreeClose(pCx->pBt);
}
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( pCx->pVtabCursor ){
+ sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor;
+ const sqlite3_module *pModule = pCx->pModule;
+ p->inVtabMethod = 1;
+ sqlite3SafetyOff(p->db);
+ pModule->xClose(pVtabCursor);
+ sqlite3SafetyOn(p->db);
+ p->inVtabMethod = 0;
+ }
+#endif
sqliteFree(pCx->pData);
sqliteFree(pCx->aType);
sqliteFree(pCx);
@@ -844,8 +912,10 @@ static void closeAllCursors(Vdbe *p){
int i;
if( p->apCsr==0 ) return;
for(i=0; inCursor; i++){
- sqlite3VdbeFreeCursor(p->apCsr[i]);
- p->apCsr[i] = 0;
+ if( !p->inVtabMethod || (p->apCsr[i] && !p->apCsr[i]->pVtabCursor) ){
+ sqlite3VdbeFreeCursor(p, p->apCsr[i]);
+ p->apCsr[i] = 0;
+ }
}
}
@@ -941,6 +1011,23 @@ static int vdbeCommit(sqlite3 *db){
int rc = SQLITE_OK;
int needXcommit = 0;
+ /* Before doing anything else, call the xSync() callback for any
+ ** virtual module tables written in this transaction. This has to
+ ** be done before determining whether a master journal file is
+ ** required, as an xSync() callback may add an attached database
+ ** to the transaction.
+ */
+ rc = sqlite3VtabSync(db, rc);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+
+ /* This loop determines (a) if the commit hook should be invoked and
+ ** (b) how many database files have open write transactions, not
+ ** including the temp database. (b) is important because if more than
+ ** one database file has an open write transaction, a master journal
+ ** file is required for an atomic commit.
+ */
for(i=0; inDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( pBt && sqlite3BtreeIsInTrans(pBt) ){
@@ -984,6 +1071,7 @@ static int vdbeCommit(sqlite3 *db){
sqlite3BtreeCommit(pBt);
}
}
+ sqlite3VtabCommit(db);
}
}
@@ -1065,25 +1153,26 @@ static int vdbeCommit(sqlite3 *db){
** file name was written into the journal file before the failure
** occured.
*/
- for(i=0; inDb; i++){
+ for(i=0; rc==SQLITE_OK && inDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( pBt && sqlite3BtreeIsInTrans(pBt) ){
rc = sqlite3BtreeSync(pBt, zMaster);
- if( rc!=SQLITE_OK ){
- sqlite3OsClose(&master);
- sqliteFree(zMaster);
- return rc;
- }
}
}
sqlite3OsClose(&master);
+ if( rc!=SQLITE_OK ){
+ sqliteFree(zMaster);
+ return rc;
+ }
/* Delete the master journal file. This commits the transaction. After
** doing this the directory is synced again before any individual
** transaction files are deleted.
*/
rc = sqlite3OsDelete(zMaster);
- assert( rc==SQLITE_OK );
+ if( rc ){
+ return rc;
+ }
sqliteFree(zMaster);
zMaster = 0;
rc = sqlite3OsSyncDirectory(zMainFile);
@@ -1111,29 +1200,13 @@ static int vdbeCommit(sqlite3 *db){
sqlite3BtreeCommit(pBt);
}
}
+ sqlite3VtabCommit(db);
}
#endif
return rc;
}
-/*
-** Find every active VM other than pVdbe and change its status to
-** aborted. This happens when one VM causes a rollback due to an
-** ON CONFLICT ROLLBACK clause (for example). The other VMs must be
-** aborted so that they do not have data rolled out from underneath
-** them leading to a segfault.
-*/
-void sqlite3AbortOtherActiveVdbes(sqlite3 *db, Vdbe *pExcept){
- Vdbe *pOther;
- for(pOther=db->pVdbe; pOther; pOther=pOther->pNext){
- if( pOther==pExcept ) continue;
- if( pOther->magic!=VDBE_MAGIC_RUN || pOther->pc<0 ) continue;
- closeAllCursors(pOther);
- pOther->aborted = 1;
- }
-}
-
/*
** This routine checks that the sqlite3.activeVdbeCnt count variable
** matches the number of vdbe's in the list sqlite3.pVdbe that are
@@ -1160,6 +1233,25 @@ static void checkActiveVdbeCnt(sqlite3 *db){
#define checkActiveVdbeCnt(x)
#endif
+/*
+** Find every active VM other than pVdbe and change its status to
+** aborted. This happens when one VM causes a rollback due to an
+** ON CONFLICT ROLLBACK clause (for example). The other VMs must be
+** aborted so that they do not have data rolled out from underneath
+** them leading to a segfault.
+*/
+void sqlite3AbortOtherActiveVdbes(sqlite3 *db, Vdbe *pExcept){
+ Vdbe *pOther;
+ for(pOther=db->pVdbe; pOther; pOther=pOther->pNext){
+ if( pOther==pExcept ) continue;
+ if( pOther->magic!=VDBE_MAGIC_RUN || pOther->pc<0 ) continue;
+ checkActiveVdbeCnt(db);
+ closeAllCursors(pOther);
+ checkActiveVdbeCnt(db);
+ pOther->aborted = 1;
+ }
+}
+
/*
** This routine is called the when a VDBE tries to halt. If the VDBE
** has made changes and is in autocommit mode, then commit those
@@ -1212,6 +1304,9 @@ int sqlite3VdbeHalt(Vdbe *p){
if( p->magic!=VDBE_MAGIC_RUN ){
/* Already halted. Nothing to do. */
assert( p->magic==VDBE_MAGIC_HALT );
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ closeAllCursors(p);
+#endif
return SQLITE_OK;
}
closeAllCursors(p);
@@ -1219,9 +1314,10 @@ int sqlite3VdbeHalt(Vdbe *p){
/* No commit or rollback needed if the program never started */
if( p->pc>=0 ){
-
+ int mrc; /* Primary error code from p->rc */
/* Check for one of the special errors - SQLITE_NOMEM or SQLITE_IOERR */
- isSpecialError = ((p->rc==SQLITE_NOMEM || p->rc==SQLITE_IOERR)?1:0);
+ mrc = p->rc & 0xff;
+ isSpecialError = ((mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR)?1:0);
if( isSpecialError ){
/* This loop does static analysis of the query to see which of the
** following three categories it falls into:
@@ -1353,6 +1449,14 @@ int sqlite3VdbeHalt(Vdbe *p){
return SQLITE_OK;
}
+/*
+** Each VDBE holds the result of the most recent sqlite3_step() call
+** in p->rc. This routine sets that result back to SQLITE_OK.
+*/
+void sqlite3VdbeResetStepResult(Vdbe *p){
+ p->rc = SQLITE_OK;
+}
+
/*
** Clean up a VDBE after execution but do not delete the VDBE just yet.
** Write any error messages into *pzErrMsg. Return the result code.
@@ -1365,16 +1469,20 @@ int sqlite3VdbeHalt(Vdbe *p){
** VDBE_MAGIC_INIT.
*/
int sqlite3VdbeReset(Vdbe *p){
+ sqlite3 *db;
if( p->magic!=VDBE_MAGIC_RUN && p->magic!=VDBE_MAGIC_HALT ){
sqlite3Error(p->db, SQLITE_MISUSE, 0);
return SQLITE_MISUSE;
}
+ db = p->db;
/* If the VM did not run to completion or if it encountered an
** error, then it might not have been halted properly. So halt
** it now.
*/
+ sqlite3SafetyOn(db);
sqlite3VdbeHalt(p);
+ 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
@@ -1383,21 +1491,20 @@ int sqlite3VdbeReset(Vdbe *p){
*/
if( p->pc>=0 ){
if( p->zErrMsg ){
- sqlite3* db = p->db;
sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, sqlite3FreeX);
db->errCode = p->rc;
p->zErrMsg = 0;
}else if( p->rc ){
- sqlite3Error(p->db, p->rc, 0);
+ sqlite3Error(db, p->rc, 0);
}else{
- sqlite3Error(p->db, SQLITE_OK, 0);
+ sqlite3Error(db, SQLITE_OK, 0);
}
}else if( p->rc && p->expired ){
/* The expired flag was set on the VDBE before the first call
** to sqlite3_step(). For consistency (since sqlite3_step() was
** called), set the database error in this case as well.
*/
- sqlite3Error(p->db, p->rc, 0);
+ sqlite3Error(db, p->rc, 0);
}
/* Reclaim all memory used by the VDBE
@@ -1432,9 +1539,9 @@ int sqlite3VdbeReset(Vdbe *p){
p->magic = VDBE_MAGIC_INIT;
p->aborted = 0;
if( p->rc==SQLITE_SCHEMA ){
- sqlite3ResetInternalSchema(p->db, 0);
+ sqlite3ResetInternalSchema(db, 0);
}
- return p->rc;
+ return p->rc & db->errMask;
}
/*
@@ -1443,9 +1550,9 @@ int sqlite3VdbeReset(Vdbe *p){
*/
int sqlite3VdbeFinalize(Vdbe *p){
int rc = SQLITE_OK;
-
if( p->magic==VDBE_MAGIC_RUN || p->magic==VDBE_MAGIC_HALT ){
rc = sqlite3VdbeReset(p);
+ assert( (rc & p->db->errMask)==rc );
}else if( p->magic!=VDBE_MAGIC_INIT ){
return SQLITE_MISUSE;
}
@@ -1500,6 +1607,7 @@ void sqlite3VdbeDelete(Vdbe *p){
sqliteFree(p->aStack);
releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
sqliteFree(p->aColName);
+ sqliteFree(p->zSql);
p->magic = VDBE_MAGIC_DEAD;
sqliteFree(p);
}
@@ -1512,7 +1620,9 @@ void sqlite3VdbeDelete(Vdbe *p){
int sqlite3VdbeCursorMoveto(Cursor *p){
if( p->deferredMoveto ){
int res, rc;
+#ifdef SQLITE_TEST
extern int sqlite3_search_count;
+#endif
assert( p->isTable );
if( p->isTable ){
rc = sqlite3BtreeMoveto(p->pCursor, 0, p->movetoTarget, &res);
@@ -1528,7 +1638,9 @@ int sqlite3VdbeCursorMoveto(Cursor *p){
rc = sqlite3BtreeNext(p->pCursor, &res);
if( rc ) return rc;
}
+#ifdef SQLITE_TEST
sqlite3_search_count++;
+#endif
p->deferredMoveto = 0;
p->cacheStatus = CACHE_STALE;
}
@@ -1592,7 +1704,7 @@ u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){
i64 i = pMem->i;
u64 u;
if( file_format>=4 && (i&1)==i ){
- return 8+(u32)i;
+ return (u32)(8+i);
}
u = i<0 ? -i : i;
if( u<=127 ) return 1;
@@ -1648,7 +1760,7 @@ int sqlite3VdbeSerialPut(unsigned char *buf, Mem *pMem, int file_format){
}
len = i = sqlite3VdbeSerialTypeLen(serial_type);
while( i-- ){
- buf[i] = (char)(v&0xFF);
+ buf[i] = (unsigned char)(v&0xFF);
v >>= 8;
}
return len;
@@ -1814,14 +1926,13 @@ int sqlite3VdbeRecordCompare(
idx2 += GetVarint( aKey2+idx2, serial_type2 );
if( d2>=(u32)nKey2 && sqlite3VdbeSerialTypeLen(serial_type2)>0 ) break;
- /* Assert that there is enough space left in each key for the blob of
- ** data to go with the serial type just read. This assert may fail if
- ** the file is corrupted. Then read the value from each key into mem1
- ** and mem2 respectively.
+ /* Extract the values to be compared.
*/
d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1);
d2 += sqlite3VdbeSerialGet(&aKey2[d2], serial_type2, &mem2);
+ /* Do the comparison
+ */
rc = sqlite3MemCompare(&mem1, &mem2, iaColl[i] : 0);
if( mem1.flags & MEM_Dyn ) sqlite3VdbeMemRelease(&mem1);
if( mem2.flags & MEM_Dyn ) sqlite3VdbeMemRelease(&mem2);
diff --git a/dlls/sqlite/sqlite-source/vdbemem.c b/dlls/sqlite/sqlite-source/vdbemem.c
index 279b45c5..73a69018 100644
--- a/dlls/sqlite/sqlite-source/vdbemem.c
+++ b/dlls/sqlite/sqlite-source/vdbemem.c
@@ -50,14 +50,6 @@ int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
assert(rc==SQLITE_OK || rc==SQLITE_NOMEM);
assert(rc==SQLITE_OK || pMem->enc!=desiredEnc);
assert(rc==SQLITE_NOMEM || pMem->enc==desiredEnc);
-
- if( rc==SQLITE_NOMEM ){
-/*
- sqlite3VdbeMemRelease(pMem);
- pMem->flags = MEM_Null;
- pMem->z = 0;
-*/
- }
return rc;
#endif
}
@@ -127,22 +119,9 @@ int sqlite3VdbeMemMakeWriteable(Mem *pMem){
** Make sure the given Mem is \u0000 terminated.
*/
int sqlite3VdbeMemNulTerminate(Mem *pMem){
- /* In SQLite, a string without a nul terminator occurs when a string
- ** is loaded from disk (in this case the memory management is ephemeral),
- ** or when it is supplied by the user as a bound variable or function
- ** return value. Therefore, the memory management of the string must be
- ** either ephemeral, static or controlled by a user-supplied destructor.
- */
- assert(
- !(pMem->flags&MEM_Str) || /* it's not a string, or */
- (pMem->flags&MEM_Term) || /* it's nul term. already, or */
- (pMem->flags&(MEM_Ephem|MEM_Static)) || /* it's static or ephem, or */
- (pMem->flags&MEM_Dyn && pMem->xDel) /* external management */
- );
if( (pMem->flags & MEM_Term)!=0 || (pMem->flags & MEM_Str)==0 ){
return SQLITE_OK; /* Nothing to do */
}
-
if( pMem->flags & (MEM_Static|MEM_Ephem) ){
return sqlite3VdbeMemMakeWriteable(pMem);
}else{
@@ -151,9 +130,14 @@ int sqlite3VdbeMemNulTerminate(Mem *pMem){
memcpy(z, pMem->z, pMem->n);
z[pMem->n] = 0;
z[pMem->n+1] = 0;
- pMem->xDel(pMem->z);
+ if( pMem->xDel ){
+ pMem->xDel(pMem->z);
+ }else{
+ sqliteFree(pMem->z);
+ }
pMem->xDel = 0;
pMem->z = z;
+ pMem->flags |= MEM_Term;
}
return SQLITE_OK;
}
@@ -776,13 +760,15 @@ const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){
pVal->flags |= (pVal->flags & MEM_Blob)>>3;
if( pVal->flags&MEM_Str ){
sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED);
- if( (enc & SQLITE_UTF16_ALIGNED)!=0 && 1==(1&(long)pVal->z) ){
+ if( (enc & SQLITE_UTF16_ALIGNED)!=0 && 1==(1&(int)pVal->z) ){
assert( (pVal->flags & (MEM_Ephem|MEM_Static))!=0 );
if( sqlite3VdbeMemMakeWriteable(pVal)!=SQLITE_OK ){
return 0;
}
}
- }else if( !(pVal->flags&MEM_Blob) ){
+ sqlite3VdbeMemNulTerminate(pVal);
+ }else{
+ assert( (pVal->flags&MEM_Blob)==0 );
sqlite3VdbeMemStringify(pVal, enc);
assert( 0==(1&(int)pVal->z) );
}
diff --git a/dlls/sqlite/sqlite-source/vtab.c b/dlls/sqlite/sqlite-source/vtab.c
new file mode 100644
index 00000000..5f1d5602
--- /dev/null
+++ b/dlls/sqlite/sqlite-source/vtab.c
@@ -0,0 +1,693 @@
+/*
+** 2006 June 10
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains code used to help implement virtual tables.
+**
+** $Id$
+*/
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+#include "sqliteInt.h"
+
+/*
+** External API function used to create a new virtual-table module.
+*/
+int sqlite3_create_module(
+ sqlite3 *db, /* Database in which module is registered */
+ const char *zName, /* Name assigned to this module */
+ const sqlite3_module *pModule, /* The definition of the module */
+ void *pAux /* Context pointer for xCreate/xConnect */
+){
+ int nName = strlen(zName);
+ Module *pMod = (Module *)sqliteMallocRaw(sizeof(Module) + nName + 1);
+ if( pMod ){
+ char *zCopy = (char *)(&pMod[1]);
+ strcpy(zCopy, zName);
+ pMod->zName = zCopy;
+ pMod->pModule = pModule;
+ pMod->pAux = pAux;
+ pMod = (Module *)sqlite3HashInsert(&db->aModule, zCopy, nName, (void*)pMod);
+ sqliteFree(pMod);
+ sqlite3ResetInternalSchema(db, 0);
+ }
+ return sqlite3ApiExit(db, SQLITE_OK);
+}
+
+/*
+** Lock the virtual table so that it cannot be disconnected.
+** Locks nest. Every lock should have a corresponding unlock.
+** If an unlock is omitted, resources leaks will occur.
+**
+** If a disconnect is attempted while a virtual table is locked,
+** the disconnect is deferred until all locks have been removed.
+*/
+void sqlite3VtabLock(sqlite3_vtab *pVtab){
+ pVtab->nRef++;
+}
+
+/*
+** Unlock a virtual table. When the last lock is removed,
+** disconnect the virtual table.
+*/
+void sqlite3VtabUnlock(sqlite3_vtab *pVtab){
+ pVtab->nRef--;
+ if( pVtab->nRef==0 ){
+ pVtab->pModule->xDisconnect(pVtab);
+ }
+}
+
+/*
+** Clear any and all virtual-table information from the Table record.
+** This routine is called, for example, just before deleting the Table
+** record.
+*/
+void sqlite3VtabClear(Table *p){
+ sqlite3_vtab *pVtab = p->pVtab;
+ if( pVtab ){
+ assert( p->pMod && p->pMod->pModule );
+ sqlite3VtabUnlock(pVtab);
+ p->pVtab = 0;
+ }
+ if( p->azModuleArg ){
+ int i;
+ for(i=0; inModuleArg; i++){
+ sqliteFree(p->azModuleArg[i]);
+ }
+ sqliteFree(p->azModuleArg);
+ }
+}
+
+/*
+** Add a new module argument to pTable->azModuleArg[].
+** The string is not copied - the pointer is stored. The
+** string will be freed automatically when the table is
+** deleted.
+*/
+static void addModuleArgument(Table *pTable, char *zArg){
+ int i = pTable->nModuleArg++;
+ int nBytes = sizeof(char *)*(1+pTable->nModuleArg);
+ char **azModuleArg;
+ azModuleArg = sqliteRealloc(pTable->azModuleArg, nBytes);
+ if( azModuleArg==0 ){
+ int j;
+ for(j=0; jazModuleArg[j]);
+ }
+ sqliteFree(zArg);
+ sqliteFree(pTable->azModuleArg);
+ pTable->nModuleArg = 0;
+ }else{
+ azModuleArg[i] = zArg;
+ azModuleArg[i+1] = 0;
+ }
+ pTable->azModuleArg = azModuleArg;
+}
+
+/*
+** The parser calls this routine when it first sees a CREATE VIRTUAL TABLE
+** statement. The module name has been parsed, but the optional list
+** of parameters that follow the module name are still pending.
+*/
+void sqlite3VtabBeginParse(
+ Parse *pParse, /* Parsing context */
+ Token *pName1, /* Name of new table, or database name */
+ Token *pName2, /* Name of new table or NULL */
+ Token *pModuleName /* Name of the module for the virtual table */
+){
+ int iDb; /* The database the table is being created in */
+ Table *pTable; /* The new virtual table */
+
+ sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, 0);
+ pTable = pParse->pNewTable;
+ if( pTable==0 || pParse->nErr ) return;
+ assert( 0==pTable->pIndex );
+
+ iDb = sqlite3SchemaToIndex(pParse->db, pTable->pSchema);
+ assert( iDb>=0 );
+
+ pTable->isVirtual = 1;
+ pTable->nModuleArg = 0;
+ addModuleArgument(pTable, sqlite3NameFromToken(pModuleName));
+ addModuleArgument(pTable, sqlite3StrDup(pParse->db->aDb[iDb].zName));
+ addModuleArgument(pTable, sqlite3StrDup(pTable->zName));
+ pParse->sNameToken.n = pModuleName->z + pModuleName->n - pName1->z;
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ /* Creating a virtual table invokes the authorization callback twice.
+ ** The first invocation, to obtain permission to INSERT a row into the
+ ** sqlite_master table, has already been made by sqlite3StartTable().
+ ** The second call, to obtain permission to create the table, is made now.
+ */
+ if( pTable->azModuleArg ){
+ sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName,
+ pTable->azModuleArg[0], pParse->db->aDb[iDb].zName);
+ }
+#endif
+}
+
+/*
+** This routine takes the module argument that has been accumulating
+** in pParse->zArg[] and appends it to the list of arguments on the
+** virtual table currently under construction in pParse->pTable.
+*/
+static void addArgumentToVtab(Parse *pParse){
+ if( pParse->sArg.z && pParse->pNewTable ){
+ const char *z = (const char*)pParse->sArg.z;
+ int n = pParse->sArg.n;
+ addModuleArgument(pParse->pNewTable, sqliteStrNDup(z, n));
+ }
+}
+
+/*
+** The parser calls this routine after the CREATE VIRTUAL TABLE statement
+** has been completely parsed.
+*/
+void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
+ Table *pTab; /* The table being constructed */
+ sqlite3 *db; /* The database connection */
+ char *zModule; /* The module name of the table: USING modulename */
+ Module *pMod = 0;
+
+ addArgumentToVtab(pParse);
+ pParse->sArg.z = 0;
+
+ /* Lookup the module name. */
+ pTab = pParse->pNewTable;
+ if( pTab==0 ) return;
+ db = pParse->db;
+ if( pTab->nModuleArg<1 ) return;
+ zModule = pTab->azModuleArg[0];
+ pMod = (Module *)sqlite3HashFind(&db->aModule, zModule, strlen(zModule));
+ pTab->pMod = pMod;
+
+ /* If the CREATE VIRTUAL TABLE statement is being entered for the
+ ** first time (in other words if the virtual table is actually being
+ ** created now instead of just being read out of sqlite_master) then
+ ** do additional initialization work and store the statement text
+ ** in the sqlite_master table.
+ */
+ if( !db->init.busy ){
+ char *zStmt;
+ char *zWhere;
+ int iDb;
+ Vdbe *v;
+
+ /* Compute the complete text of the CREATE VIRTUAL TABLE statement */
+ if( pEnd ){
+ pParse->sNameToken.n = pEnd->z - pParse->sNameToken.z + pEnd->n;
+ }
+ zStmt = sqlite3MPrintf("CREATE VIRTUAL TABLE %T", &pParse->sNameToken);
+
+ /* A slot for the record has already been allocated in the
+ ** SQLITE_MASTER table. We just need to update that slot with all
+ ** the information we've collected.
+ **
+ ** The top of the stack is the rootpage allocated by sqlite3StartTable().
+ ** This value is always 0 and is ignored, a virtual table does not have a
+ ** rootpage. The next entry on the stack is the rowid of the record
+ ** in the sqlite_master table.
+ */
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ sqlite3NestedParse(pParse,
+ "UPDATE %Q.%s "
+ "SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q "
+ "WHERE rowid=#1",
+ db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
+ pTab->zName,
+ pTab->zName,
+ zStmt
+ );
+ sqliteFree(zStmt);
+ v = sqlite3GetVdbe(pParse);
+ sqlite3ChangeCookie(db, v, iDb);
+
+ sqlite3VdbeAddOp(v, OP_Expire, 0, 0);
+ zWhere = sqlite3MPrintf("name='%q'", pTab->zName);
+ sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 1, zWhere, P3_DYNAMIC);
+ sqlite3VdbeOp3(v, OP_VCreate, iDb, 0, pTab->zName, strlen(pTab->zName) + 1);
+ }
+
+ /* If we are rereading the sqlite_master table create the in-memory
+ ** record of the table. If the module has already been registered,
+ ** also call the xConnect method here.
+ */
+ else {
+ Table *pOld;
+ Schema *pSchema = pTab->pSchema;
+ const char *zName = pTab->zName;
+ int nName = strlen(zName) + 1;
+ pOld = sqlite3HashInsert(&pSchema->tblHash, zName, nName, pTab);
+ if( pOld ){
+ assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */
+ return;
+ }
+ pParse->pNewTable = 0;
+ }
+}
+
+/*
+** The parser calls this routine when it sees the first token
+** of an argument to the module name in a CREATE VIRTUAL TABLE statement.
+*/
+void sqlite3VtabArgInit(Parse *pParse){
+ addArgumentToVtab(pParse);
+ pParse->sArg.z = 0;
+ pParse->sArg.n = 0;
+}
+
+/*
+** The parser calls this routine for each token after the first token
+** in an argument to the module name in a CREATE VIRTUAL TABLE statement.
+*/
+void sqlite3VtabArgExtend(Parse *pParse, Token *p){
+ Token *pArg = &pParse->sArg;
+ if( pArg->z==0 ){
+ pArg->z = p->z;
+ pArg->n = p->n;
+ }else{
+ assert(pArg->z < p->z);
+ pArg->n = (p->z + p->n - pArg->z);
+ }
+}
+
+/*
+** Invoke a virtual table constructor (either xCreate or xConnect). The
+** pointer to the function to invoke is passed as the fourth parameter
+** to this procedure.
+*/
+static int vtabCallConstructor(
+ sqlite3 *db,
+ Table *pTab,
+ Module *pMod,
+ int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**),
+ char **pzErr
+){
+ int rc;
+ int rc2;
+ sqlite3_vtab *pVtab;
+ const char *const*azArg = (const char *const*)pTab->azModuleArg;
+ int nArg = pTab->nModuleArg;
+ char *zErr = 0;
+ char *zModuleName = sqlite3MPrintf("%s", pTab->zName);
+
+ assert( !db->pVTab );
+ assert( xConstruct );
+
+ db->pVTab = pTab;
+ rc = sqlite3SafetyOff(db);
+ assert( rc==SQLITE_OK );
+ rc = xConstruct(db, pMod->pAux, nArg, azArg, &pTab->pVtab, &zErr);
+ rc2 = sqlite3SafetyOn(db);
+ pVtab = pTab->pVtab;
+ if( rc==SQLITE_OK && pVtab ){
+ pVtab->pModule = pMod->pModule;
+ pVtab->nRef = 1;
+ }
+
+ if( SQLITE_OK!=rc ){
+ if( zErr==0 ){
+ *pzErr = sqlite3MPrintf("vtable constructor failed: %s", zModuleName);
+ }else {
+ *pzErr = sqlite3MPrintf("%s", zErr);
+ sqlite3_free(zErr);
+ }
+ }else if( db->pVTab ){
+ const char *zFormat = "vtable constructor did not declare schema: %s";
+ *pzErr = sqlite3MPrintf(zFormat, pTab->zName);
+ rc = SQLITE_ERROR;
+ }
+ if( rc==SQLITE_OK ){
+ rc = rc2;
+ }
+ db->pVTab = 0;
+ sqliteFree(zModuleName);
+ return rc;
+}
+
+/*
+** This function is invoked by the parser to call the xConnect() method
+** of the virtual table pTab. If an error occurs, an error code is returned
+** and an error left in pParse.
+**
+** This call is a no-op if table pTab is not a virtual table.
+*/
+int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
+ Module *pMod;
+ int rc = SQLITE_OK;
+
+ if( !pTab || !pTab->isVirtual || pTab->pVtab ){
+ return SQLITE_OK;
+ }
+
+ pMod = pTab->pMod;
+ if( !pMod ){
+ const char *zModule = pTab->azModuleArg[0];
+ sqlite3ErrorMsg(pParse, "no such module: %s", zModule);
+ rc = SQLITE_ERROR;
+ } else {
+ char *zErr = 0;
+ sqlite3 *db = pParse->db;
+ rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr);
+ if( rc!=SQLITE_OK ){
+ sqlite3ErrorMsg(pParse, "%s", zErr);
+ }
+ sqliteFree(zErr);
+ }
+
+ return rc;
+}
+
+/*
+** Add the virtual table pVtab to the array sqlite3.aVTrans[].
+*/
+static int addToVTrans(sqlite3 *db, sqlite3_vtab *pVtab){
+ const int ARRAY_INCR = 5;
+
+ /* Grow the sqlite3.aVTrans array if required */
+ if( (db->nVTrans%ARRAY_INCR)==0 ){
+ sqlite3_vtab **aVTrans;
+ int nBytes = sizeof(sqlite3_vtab *) * (db->nVTrans + ARRAY_INCR);
+ aVTrans = sqliteRealloc((void *)db->aVTrans, nBytes);
+ if( !aVTrans ){
+ return SQLITE_NOMEM;
+ }
+ memset(&aVTrans[db->nVTrans], 0, sizeof(sqlite3_vtab *)*ARRAY_INCR);
+ db->aVTrans = aVTrans;
+ }
+
+ /* Add pVtab to the end of sqlite3.aVTrans */
+ db->aVTrans[db->nVTrans++] = pVtab;
+ sqlite3VtabLock(pVtab);
+ return SQLITE_OK;
+}
+
+/*
+** This function is invoked by the vdbe to call the xCreate method
+** of the virtual table named zTab in database iDb.
+**
+** If an error occurs, *pzErr is set to point an an English language
+** description of the error and an SQLITE_XXX error code is returned.
+** In this case the caller must call sqliteFree() on *pzErr.
+*/
+int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
+ int rc = SQLITE_OK;
+ Table *pTab;
+ Module *pMod;
+ const char *zModule;
+
+ pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
+ assert(pTab && pTab->isVirtual && !pTab->pVtab);
+ pMod = pTab->pMod;
+ zModule = pTab->azModuleArg[0];
+
+ /* If the module has been registered and includes a Create method,
+ ** invoke it now. If the module has not been registered, return an
+ ** error. Otherwise, do nothing.
+ */
+ if( !pMod ){
+ *pzErr = sqlite3MPrintf("no such module: %s", zModule);
+ rc = SQLITE_ERROR;
+ }else{
+ rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xCreate, pzErr);
+ }
+
+ if( rc==SQLITE_OK && pTab->pVtab ){
+ rc = addToVTrans(db, pTab->pVtab);
+ }
+
+ return rc;
+}
+
+/*
+** This function is used to set the schema of a virtual table. It is only
+** valid to call this function from within the xCreate() or xConnect() of a
+** virtual table module.
+*/
+int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
+ Parse sParse;
+
+ int rc = SQLITE_OK;
+ Table *pTab = db->pVTab;
+ char *zErr = 0;
+
+ if( !pTab ){
+ sqlite3Error(db, SQLITE_MISUSE, 0);
+ return SQLITE_MISUSE;
+ }
+ assert(pTab->isVirtual && pTab->nCol==0 && pTab->aCol==0);
+
+ memset(&sParse, 0, sizeof(Parse));
+ sParse.declareVtab = 1;
+ sParse.db = db;
+
+ if(
+ SQLITE_OK == sqlite3RunParser(&sParse, zCreateTable, &zErr) &&
+ sParse.pNewTable &&
+ !sParse.pNewTable->pSelect &&
+ !sParse.pNewTable->isVirtual
+ ){
+ pTab->aCol = sParse.pNewTable->aCol;
+ pTab->nCol = sParse.pNewTable->nCol;
+ sParse.pNewTable->nCol = 0;
+ sParse.pNewTable->aCol = 0;
+ } else {
+ sqlite3Error(db, SQLITE_ERROR, zErr);
+ sqliteFree(zErr);
+ rc = SQLITE_ERROR;
+ }
+ sParse.declareVtab = 0;
+
+ sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe);
+ sqlite3DeleteTable(0, sParse.pNewTable);
+ sParse.pNewTable = 0;
+ db->pVTab = 0;
+
+ assert( (rc&0xff)==rc );
+ return rc;
+}
+
+/*
+** This function is invoked by the vdbe to call the xDestroy method
+** of the virtual table named zTab in database iDb. This occurs
+** when a DROP TABLE is mentioned.
+**
+** This call is a no-op if zTab is not a virtual table.
+*/
+int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab)
+{
+ int rc = SQLITE_OK;
+ Table *pTab;
+
+ pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
+ assert(pTab);
+ if( pTab->pVtab ){
+ int (*xDestroy)(sqlite3_vtab *pVTab) = pTab->pMod->pModule->xDestroy;
+ rc = sqlite3SafetyOff(db);
+ assert( rc==SQLITE_OK );
+ if( xDestroy ){
+ rc = xDestroy(pTab->pVtab);
+ }
+ sqlite3SafetyOn(db);
+ if( rc==SQLITE_OK ){
+ pTab->pVtab = 0;
+ }
+ }
+
+ return rc;
+}
+
+/*
+** This function invokes either the xRollback or xCommit method
+** of each of the virtual tables in the sqlite3.aVTrans array. The method
+** called is identified by the second argument, "offset", which is
+** the offset of the method to call in the sqlite3_module structure.
+**
+** The array is cleared after invoking the callbacks.
+*/
+static void callFinaliser(sqlite3 *db, int offset){
+ int i;
+ for(i=0; inVTrans && db->aVTrans[i]; i++){
+ sqlite3_vtab *pVtab = db->aVTrans[i];
+ int (*x)(sqlite3_vtab *);
+ x = *(int (**)(sqlite3_vtab *))((char *)pVtab->pModule + offset);
+ if( x ) x(pVtab);
+ sqlite3VtabUnlock(pVtab);
+ }
+ sqliteFree(db->aVTrans);
+ db->nVTrans = 0;
+ db->aVTrans = 0;
+}
+
+/*
+** If argument rc2 is not SQLITE_OK, then return it and do nothing.
+** Otherwise, invoke the xSync method of all virtual tables in the
+** sqlite3.aVTrans array. Return the error code for the first error
+** that occurs, or SQLITE_OK if all xSync operations are successful.
+*/
+int sqlite3VtabSync(sqlite3 *db, int rc2){
+ int i;
+ int rc = SQLITE_OK;
+ int rcsafety;
+ sqlite3_vtab **aVTrans = db->aVTrans;
+ if( rc2!=SQLITE_OK ) return rc2;
+
+ rc = sqlite3SafetyOff(db);
+ db->aVTrans = 0;
+ for(i=0; rc==SQLITE_OK && inVTrans && aVTrans[i]; i++){
+ sqlite3_vtab *pVtab = aVTrans[i];
+ int (*x)(sqlite3_vtab *);
+ x = pVtab->pModule->xSync;
+ if( x ){
+ rc = x(pVtab);
+ }
+ }
+ db->aVTrans = aVTrans;
+ rcsafety = sqlite3SafetyOn(db);
+
+ if( rc==SQLITE_OK ){
+ rc = rcsafety;
+ }
+ return rc;
+}
+
+/*
+** Invoke the xRollback method of all virtual tables in the
+** sqlite3.aVTrans array. Then clear the array itself.
+*/
+int sqlite3VtabRollback(sqlite3 *db){
+ callFinaliser(db, (int)(&((sqlite3_module *)0)->xRollback));
+ return SQLITE_OK;
+}
+
+/*
+** Invoke the xCommit method of all virtual tables in the
+** sqlite3.aVTrans array. Then clear the array itself.
+*/
+int sqlite3VtabCommit(sqlite3 *db){
+ callFinaliser(db, (int)(&((sqlite3_module *)0)->xCommit));
+ return SQLITE_OK;
+}
+
+/*
+** If the virtual table pVtab supports the transaction interface
+** (xBegin/xRollback/xCommit and optionally xSync) and a transaction is
+** not currently open, invoke the xBegin method now.
+**
+** If the xBegin call is successful, place the sqlite3_vtab pointer
+** in the sqlite3.aVTrans array.
+*/
+int sqlite3VtabBegin(sqlite3 *db, sqlite3_vtab *pVtab){
+ int rc = SQLITE_OK;
+ const sqlite3_module *pModule;
+
+ /* Special case: If db->aVTrans is NULL and db->nVTrans is greater
+ ** than zero, then this function is being called from within a
+ ** virtual module xSync() callback. It is illegal to write to
+ ** virtual module tables in this case, so return SQLITE_LOCKED.
+ */
+ if( 0==db->aVTrans && db->nVTrans>0 ){
+ return SQLITE_LOCKED;
+ }
+ if( !pVtab ){
+ return SQLITE_OK;
+ }
+ pModule = pVtab->pModule;
+
+ if( pModule->xBegin ){
+ int i;
+
+
+ /* If pVtab is already in the aVTrans array, return early */
+ for(i=0; (inVTrans) && 0!=db->aVTrans[i]; i++){
+ if( db->aVTrans[i]==pVtab ){
+ return SQLITE_OK;
+ }
+ }
+
+ /* Invoke the xBegin method */
+ rc = pModule->xBegin(pVtab);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+
+ rc = addToVTrans(db, pVtab);
+ }
+ return rc;
+}
+
+/*
+** The first parameter (pDef) is a function implementation. The
+** second parameter (pExpr) is the first argument to this function.
+** If pExpr is a column in a virtual table, then let the virtual
+** table implementation have an opportunity to overload the function.
+**
+** This routine is used to allow virtual table implementations to
+** overload MATCH, LIKE, GLOB, and REGEXP operators.
+**
+** Return either the pDef argument (indicating no change) or a
+** new FuncDef structure that is marked as ephemeral using the
+** SQLITE_FUNC_EPHEM flag.
+*/
+FuncDef *sqlite3VtabOverloadFunction(
+ FuncDef *pDef, /* Function to possibly overload */
+ int nArg, /* Number of arguments to the function */
+ Expr *pExpr /* First argument to the function */
+){
+ Table *pTab;
+ sqlite3_vtab *pVtab;
+ sqlite3_module *pMod;
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
+ void *pArg;
+ FuncDef *pNew;
+ int rc;
+ char *zLowerName;
+ unsigned char *z;
+
+
+ /* Check to see the left operand is a column in a virtual table */
+ if( pExpr==0 ) return pDef;
+ if( pExpr->op!=TK_COLUMN ) return pDef;
+ pTab = pExpr->pTab;
+ if( pTab==0 ) return pDef;
+ if( !pTab->isVirtual ) return pDef;
+ pVtab = pTab->pVtab;
+ assert( pVtab!=0 );
+ assert( pVtab->pModule!=0 );
+ pMod = (sqlite3_module *)pVtab->pModule;
+ if( pMod->xFindFunction==0 ) return pDef;
+
+ /* Call the xFuncFunction method on the virtual table implementation
+ ** to see if the implementation wants to overload this function
+ */
+ zLowerName = sqlite3StrDup(pDef->zName);
+ for(z=(unsigned char*)zLowerName; *z; z++){
+ *z = sqlite3UpperToLower[*z];
+ }
+ rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xFunc, &pArg);
+ sqliteFree(zLowerName);
+ if( rc==0 ){
+ return pDef;
+ }
+
+ /* Create a new ephemeral function definition for the overloaded
+ ** function */
+ pNew = sqliteMalloc( sizeof(*pNew) + strlen(pDef->zName) );
+ if( pNew==0 ){
+ return pDef;
+ }
+ *pNew = *pDef;
+ strcpy(pNew->zName, pDef->zName);
+ pNew->xFunc = xFunc;
+ pNew->pUserData = pArg;
+ pNew->flags |= SQLITE_FUNC_EPHEM;
+ return pNew;
+}
+
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
diff --git a/dlls/sqlite/sqlite-source/where.c b/dlls/sqlite/sqlite-source/where.c
index 1056e71e..d62c37d5 100644
--- a/dlls/sqlite/sqlite-source/where.c
+++ b/dlls/sqlite/sqlite-source/where.c
@@ -43,6 +43,7 @@ int sqlite3_where_trace = 0;
/* Forward reference
*/
typedef struct WhereClause WhereClause;
+typedef struct ExprMaskSet ExprMaskSet;
/*
** The query generator uses an array of instances of this structure to
@@ -106,6 +107,7 @@ struct WhereTerm {
*/
struct WhereClause {
Parse *pParse; /* The parser context */
+ ExprMaskSet *pMaskSet; /* Mapping of table indices to bitmasks */
int nTerm; /* Number of terms */
int nSlot; /* Number of entries in a[] */
WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */
@@ -138,7 +140,6 @@ struct WhereClause {
** numbers all get mapped into bit numbers that begin with 0 and contain
** no gaps.
*/
-typedef struct ExprMaskSet ExprMaskSet;
struct ExprMaskSet {
int n; /* Number of assigned cursor values */
int ix[sizeof(Bitmask)*8]; /* Cursor assigned to each bit */
@@ -156,27 +157,43 @@ struct ExprMaskSet {
#define WO_LE (WO_EQ<<(TK_LE-TK_EQ))
#define WO_GT (WO_EQ<<(TK_GT-TK_EQ))
#define WO_GE (WO_EQ<<(TK_GE-TK_EQ))
+#define WO_MATCH 64
+#define WO_ISNULL 128
/*
-** Value for flags returned by bestIndex()
+** Value for flags returned by bestIndex().
+**
+** The least significant byte is reserved as a mask for WO_ values above.
+** The WhereLevel.flags field is usually set to WO_IN|WO_EQ|WO_ISNULL.
+** But if the table is the right table of a left join, WhereLevel.flags
+** is set to WO_IN|WO_EQ. The WhereLevel.flags field can then be used as
+** the "op" parameter to findTerm when we are resolving equality constraints.
+** ISNULL constraints will then not be used on the right table of a left
+** join. Tickets #2177 and #2189.
*/
-#define WHERE_ROWID_EQ 0x0001 /* rowid=EXPR or rowid IN (...) */
-#define WHERE_ROWID_RANGE 0x0002 /* rowidEXPR */
-#define WHERE_COLUMN_EQ 0x0010 /* x=EXPR or x IN (...) */
-#define WHERE_COLUMN_RANGE 0x0020 /* xEXPR */
-#define WHERE_COLUMN_IN 0x0040 /* x IN (...) */
-#define WHERE_TOP_LIMIT 0x0100 /* xEXPR or x>=EXPR constraint */
-#define WHERE_IDX_ONLY 0x0800 /* Use index only - omit table */
-#define WHERE_ORDERBY 0x1000 /* Output will appear in correct order */
-#define WHERE_REVERSE 0x2000 /* Scan in reverse order */
-#define WHERE_UNIQUE 0x4000 /* Selects no more than one row */
+#define WHERE_ROWID_EQ 0x000100 /* rowid=EXPR or rowid IN (...) */
+#define WHERE_ROWID_RANGE 0x000200 /* rowidEXPR */
+#define WHERE_COLUMN_EQ 0x001000 /* x=EXPR or x IN (...) */
+#define WHERE_COLUMN_RANGE 0x002000 /* xEXPR */
+#define WHERE_COLUMN_IN 0x004000 /* x IN (...) */
+#define WHERE_TOP_LIMIT 0x010000 /* xEXPR or x>=EXPR constraint */
+#define WHERE_IDX_ONLY 0x080000 /* Use index only - omit table */
+#define WHERE_ORDERBY 0x100000 /* Output will appear in correct order */
+#define WHERE_REVERSE 0x200000 /* Scan in reverse order */
+#define WHERE_UNIQUE 0x400000 /* Selects no more than one row */
+#define WHERE_VIRTUALTABLE 0x800000 /* Use virtual-table processing */
/*
** Initialize a preallocated WhereClause structure.
*/
-static void whereClauseInit(WhereClause *pWC, Parse *pParse){
+static void whereClauseInit(
+ WhereClause *pWC, /* The WhereClause to be initialized */
+ Parse *pParse, /* The parsing context */
+ ExprMaskSet *pMaskSet /* Mapping from table indices to bitmasks */
+){
pWC->pParse = pParse;
+ pWC->pMaskSet = pMaskSet;
pWC->nTerm = 0;
pWC->nSlot = ARRAYSIZE(pWC->aStatic);
pWC->a = pWC->aStatic;
@@ -352,7 +369,7 @@ static int allowedOp(int op){
assert( TK_LT>TK_EQ && TK_LTTK_EQ && TK_LE=TK_EQ && op<=TK_GE);
+ return op==TK_IN || (op>=TK_EQ && op<=TK_GE) || op==TK_ISNULL;
}
/*
@@ -386,9 +403,12 @@ static int operatorMask(int op){
assert( allowedOp(op) );
if( op==TK_IN ){
c = WO_IN;
+ }else if( op==TK_ISNULL ){
+ c = WO_ISNULL;
}else{
c = WO_EQ<<(op-TK_EQ);
}
+ assert( op!=TK_ISNULL || c==WO_ISNULL );
assert( op!=TK_IN || c==WO_IN );
assert( op!=TK_EQ || c==WO_EQ );
assert( op!=TK_LT || c==WO_LT );
@@ -420,7 +440,7 @@ static WhereTerm *findTerm(
&& pTerm->leftColumn==iColumn
&& (pTerm->eOperator & op)!=0
){
- if( iCur>=0 && pIdx ){
+ if( iCur>=0 && pIdx && pTerm->eOperator!=WO_ISNULL ){
Expr *pX = pTerm->pExpr;
CollSeq *pColl;
char idxaff;
@@ -449,7 +469,7 @@ static WhereTerm *findTerm(
}
/* Forward reference */
-static void exprAnalyze(SrcList*, ExprMaskSet*, WhereClause*, int);
+static void exprAnalyze(SrcList*, WhereClause*, int);
/*
** Call exprAnalyze on all terms in a WHERE clause.
@@ -458,12 +478,11 @@ static void exprAnalyze(SrcList*, ExprMaskSet*, WhereClause*, int);
*/
static void exprAnalyzeAll(
SrcList *pTabList, /* the FROM clause */
- ExprMaskSet *pMaskSet, /* table masks */
WhereClause *pWC /* the WHERE clause to be analyzed */
){
int i;
for(i=pWC->nTerm-1; i>=0; i--){
- exprAnalyze(pTabList, pMaskSet, pWC, i);
+ exprAnalyze(pTabList, pWC, i);
}
}
@@ -522,6 +541,38 @@ static int isLikeOrGlob(
}
#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/*
+** Check to see if the given expression is of the form
+**
+** column MATCH expr
+**
+** If it is then return TRUE. If not, return FALSE.
+*/
+static int isMatchOfColumn(
+ Expr *pExpr /* Test this expression */
+){
+ ExprList *pList;
+
+ if( pExpr->op!=TK_FUNCTION ){
+ return 0;
+ }
+ if( pExpr->token.n!=5 ||
+ sqlite3StrNICmp((const char*)pExpr->token.z,"match",5)!=0 ){
+ return 0;
+ }
+ pList = pExpr->pList;
+ if( pList->nExpr!=2 ){
+ return 0;
+ }
+ if( pList->a[1].pExpr->op != TK_COLUMN ){
+ return 0;
+ }
+ return 1;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
/*
** If the pBase expression originated in the ON or USING clause of
** a join, then transfer the appropriate markings over to derived.
@@ -546,23 +597,27 @@ static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
*/
static void exprAnalyze(
SrcList *pSrc, /* the FROM clause */
- ExprMaskSet *pMaskSet, /* table masks */
WhereClause *pWC, /* the WHERE clause */
int idxTerm /* Index of the term to be analyzed */
){
WhereTerm *pTerm = &pWC->a[idxTerm];
+ ExprMaskSet *pMaskSet = pWC->pMaskSet;
Expr *pExpr = pTerm->pExpr;
Bitmask prereqLeft;
Bitmask prereqAll;
int nPattern;
int isComplete;
+ int op;
if( sqlite3MallocFailed() ) return;
prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);
- if( pExpr->op==TK_IN ){
+ op = pExpr->op;
+ if( op==TK_IN ){
assert( pExpr->pRight==0 );
pTerm->prereqRight = exprListTableUsage(pMaskSet, pExpr->pList)
| exprSelectTableUsage(pMaskSet, pExpr->pSelect);
+ }else if( op==TK_ISNULL ){
+ pTerm->prereqRight = 0;
}else{
pTerm->prereqRight = exprTableUsage(pMaskSet, pExpr->pRight);
}
@@ -574,13 +629,13 @@ static void exprAnalyze(
pTerm->leftCursor = -1;
pTerm->iParent = -1;
pTerm->eOperator = 0;
- if( allowedOp(pExpr->op) && (pTerm->prereqRight & prereqLeft)==0 ){
+ if( allowedOp(op) && (pTerm->prereqRight & prereqLeft)==0 ){
Expr *pLeft = pExpr->pLeft;
Expr *pRight = pExpr->pRight;
if( pLeft->op==TK_COLUMN ){
pTerm->leftCursor = pLeft->iTable;
pTerm->leftColumn = pLeft->iColumn;
- pTerm->eOperator = operatorMask(pExpr->op);
+ pTerm->eOperator = operatorMask(op);
}
if( pRight && pRight->op==TK_COLUMN ){
WhereTerm *pNew;
@@ -588,6 +643,10 @@ static void exprAnalyze(
if( pTerm->leftCursor>=0 ){
int idxNew;
pDup = sqlite3ExprDup(pExpr);
+ if( sqlite3MallocFailed() ){
+ sqliteFree(pDup);
+ return;
+ }
idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC);
if( idxNew==0 ) return;
pNew = &pWC->a[idxNew];
@@ -625,7 +684,7 @@ static void exprAnalyze(
pNewExpr = sqlite3Expr(ops[i], sqlite3ExprDup(pExpr->pLeft),
sqlite3ExprDup(pList->a[i].pExpr), 0);
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
- exprAnalyze(pSrc, pMaskSet, pWC, idxNew);
+ exprAnalyze(pSrc, pWC, idxNew);
pTerm = &pWC->a[idxTerm];
pWC->a[idxNew].iParent = idxTerm;
}
@@ -654,9 +713,9 @@ static void exprAnalyze(
WhereTerm *pOrTerm;
assert( (pTerm->flags & TERM_DYNAMIC)==0 );
- whereClauseInit(&sOr, pWC->pParse);
+ whereClauseInit(&sOr, pWC->pParse, pMaskSet);
whereSplit(&sOr, pExpr, TK_OR);
- exprAnalyzeAll(pSrc, pMaskSet, &sOr);
+ exprAnalyzeAll(pSrc, &sOr);
assert( sOr.nTerm>0 );
j = 0;
do{
@@ -681,23 +740,22 @@ static void exprAnalyze(
if( ok ){
ExprList *pList = 0;
Expr *pNew, *pDup;
+ Expr *pLeft = 0;
for(i=sOr.nTerm-1, pOrTerm=sOr.a; i>=0 && ok; i--, pOrTerm++){
if( (pOrTerm->flags & TERM_OR_OK)==0 ) continue;
pDup = sqlite3ExprDup(pOrTerm->pExpr->pRight);
pList = sqlite3ExprListAppend(pList, pDup, 0);
+ pLeft = pOrTerm->pExpr->pLeft;
}
- pDup = sqlite3Expr(TK_COLUMN, 0, 0, 0);
- if( pDup ){
- pDup->iTable = iCursor;
- pDup->iColumn = iColumn;
- }
+ assert( pLeft!=0 );
+ pDup = sqlite3ExprDup(pLeft);
pNew = sqlite3Expr(TK_IN, pDup, 0, 0);
if( pNew ){
int idxNew;
transferJoinMarkings(pNew, pExpr);
pNew->pList = pList;
idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
- exprAnalyze(pSrc, pMaskSet, pWC, idxNew);
+ exprAnalyze(pSrc, pWC, idxNew);
pTerm = &pWC->a[idxTerm];
pWC->a[idxNew].iParent = idxTerm;
pTerm->nChild = 1;
@@ -734,10 +792,10 @@ or_not_possible:
}
pNewExpr1 = sqlite3Expr(TK_GE, sqlite3ExprDup(pLeft), pStr1, 0);
idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
- exprAnalyze(pSrc, pMaskSet, pWC, idxNew1);
+ exprAnalyze(pSrc, pWC, idxNew1);
pNewExpr2 = sqlite3Expr(TK_LT, sqlite3ExprDup(pLeft), pStr2, 0);
idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
- exprAnalyze(pSrc, pMaskSet, pWC, idxNew2);
+ exprAnalyze(pSrc, pWC, idxNew2);
pTerm = &pWC->a[idxTerm];
if( isComplete ){
pWC->a[idxNew1].iParent = idxTerm;
@@ -746,6 +804,60 @@ or_not_possible:
}
}
#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ /* Add a WO_MATCH auxiliary term to the constraint set if the
+ ** current expression is of the form: column MATCH expr.
+ ** This information is used by the xBestIndex methods of
+ ** virtual tables. The native query optimizer does not attempt
+ ** to do anything with MATCH functions.
+ */
+ if( isMatchOfColumn(pExpr) ){
+ int idxNew;
+ Expr *pRight, *pLeft;
+ WhereTerm *pNewTerm;
+ Bitmask prereqColumn, prereqExpr;
+
+ pRight = pExpr->pList->a[0].pExpr;
+ pLeft = pExpr->pList->a[1].pExpr;
+ prereqExpr = exprTableUsage(pMaskSet, pRight);
+ prereqColumn = exprTableUsage(pMaskSet, pLeft);
+ if( (prereqExpr & prereqColumn)==0 ){
+ Expr *pNewExpr;
+ pNewExpr = sqlite3Expr(TK_MATCH, 0, sqlite3ExprDup(pRight), 0);
+ idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
+ pNewTerm = &pWC->a[idxNew];
+ pNewTerm->prereqRight = prereqExpr;
+ pNewTerm->leftCursor = pLeft->iTable;
+ pNewTerm->leftColumn = pLeft->iColumn;
+ pNewTerm->eOperator = WO_MATCH;
+ pNewTerm->iParent = idxTerm;
+ pTerm = &pWC->a[idxTerm];
+ pTerm->nChild = 1;
+ pTerm->flags |= TERM_COPIED;
+ pNewTerm->prereqAll = pTerm->prereqAll;
+ }
+ }
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+}
+
+/*
+** Return TRUE if any of the expressions in pList->a[iFirst...] contain
+** a reference to any table other than the iBase table.
+*/
+static int referencesOtherTables(
+ ExprList *pList, /* Search expressions in ths list */
+ ExprMaskSet *pMaskSet, /* Mapping from tables to bitmaps */
+ int iFirst, /* Be searching with the iFirst-th expression */
+ int iBase /* Ignore references to this table */
+){
+ Bitmask allowed = ~getMask(pMaskSet, iBase);
+ while( iFirstnExpr ){
+ if( (exprTableUsage(pMaskSet, pList->a[iFirst++].pExpr)&allowed)!=0 ){
+ return 1;
+ }
+ }
+ return 0;
}
@@ -770,6 +882,7 @@ or_not_possible:
*/
static int isSortingIndex(
Parse *pParse, /* Parsing context */
+ ExprMaskSet *pMaskSet, /* Mapping from table indices to bitmaps */
Index *pIdx, /* The index we are testing */
int base, /* Cursor number for the table to be sorted */
ExprList *pOrderBy, /* The ORDER BY clause */
@@ -788,22 +901,43 @@ static int isSortingIndex(
/* Match terms of the ORDER BY clause against columns of
** the index.
+ **
+ ** Note that indices have pIdx->nColumn regular columns plus
+ ** one additional column containing the rowid. The rowid column
+ ** of the index is also allowed to match against the ORDER BY
+ ** clause.
*/
- for(i=j=0, pTerm=pOrderBy->a; jnColumn; i++){
+ for(i=j=0, pTerm=pOrderBy->a; jnColumn; i++){
Expr *pExpr; /* The expression of the ORDER BY pTerm */
CollSeq *pColl; /* The collating sequence of pExpr */
int termSortOrder; /* Sort order for this term */
+ int iColumn; /* The i-th column of the index. -1 for rowid */
+ int iSortOrder; /* 1 for DESC, 0 for ASC on the i-th index term */
+ const char *zColl; /* Name of the collating sequence for i-th index term */
pExpr = pTerm->pExpr;
if( pExpr->op!=TK_COLUMN || pExpr->iTable!=base ){
/* Can not use an index sort on anything that is not a column in the
** left-most table of the FROM clause */
- return 0;
+ break;
}
pColl = sqlite3ExprCollSeq(pParse, pExpr);
- if( !pColl ) pColl = db->pDfltColl;
- if( pExpr->iColumn!=pIdx->aiColumn[i] ||
- sqlite3StrICmp(pColl->zName, pIdx->azColl[i]) ){
+ if( !pColl ){
+ pColl = db->pDfltColl;
+ }
+ if( inColumn ){
+ iColumn = pIdx->aiColumn[i];
+ if( iColumn==pIdx->pTable->iPKey ){
+ iColumn = -1;
+ }
+ iSortOrder = pIdx->aSortOrder[i];
+ zColl = pIdx->azColl[i];
+ }else{
+ iColumn = -1;
+ iSortOrder = 0;
+ zColl = pColl->zName;
+ }
+ if( pExpr->iColumn!=iColumn || sqlite3StrICmp(pColl->zName, zColl) ){
/* Term j of the ORDER BY clause does not match column i of the index */
if( iaSortOrder!=0 );
assert( pTerm->sortOrder==0 || pTerm->sortOrder==1 );
- assert( pIdx->aSortOrder[i]==0 || pIdx->aSortOrder[i]==1 );
- termSortOrder = pIdx->aSortOrder[i] ^ pTerm->sortOrder;
+ assert( iSortOrder==0 || iSortOrder==1 );
+ termSortOrder = iSortOrder ^ pTerm->sortOrder;
if( i>nEqCol ){
if( termSortOrder!=sortOrder ){
/* Indices can only be used if all ORDER BY terms past the
@@ -832,13 +966,29 @@ static int isSortingIndex(
}
j++;
pTerm++;
+ if( iColumn<0 && !referencesOtherTables(pOrderBy, pMaskSet, j, base) ){
+ /* If the indexed column is the primary key and everything matches
+ ** so far and none of the ORDER BY terms to the right reference other
+ ** tables in the join, then we are assured that the index can be used
+ ** to sort because the primary key is unique and so none of the other
+ ** columns will make any difference
+ */
+ j = nTerm;
+ }
}
- /* The index can be used for sorting if all terms of the ORDER BY clause
- ** are covered.
- */
+ *pbRev = sortOrder!=0;
if( j>=nTerm ){
- *pbRev = sortOrder!=0;
+ /* All terms of the ORDER BY clause are covered by this index so
+ ** this index can be used for sorting. */
+ return 1;
+ }
+ if( pIdx->onError!=OE_None && i==pIdx->nColumn
+ && !referencesOtherTables(pOrderBy, pMaskSet, j, base) ){
+ /* All terms of this index match some prefix of the ORDER BY clause
+ ** and the index is UNIQUE and no terms on the tail of the ORDER BY
+ ** clause reference other tables in a join. If this is all true then
+ ** the order by clause is superfluous. */
return 1;
}
return 0;
@@ -852,6 +1002,7 @@ static int isSortingIndex(
static int sortableByRowid(
int base, /* Cursor number for table to be sorted */
ExprList *pOrderBy, /* The ORDER BY clause */
+ ExprMaskSet *pMaskSet, /* Mapping from tables to bitmaps */
int *pbRev /* Set to 1 if ORDER BY is DESC */
){
Expr *p;
@@ -859,8 +1010,8 @@ static int sortableByRowid(
assert( pOrderBy!=0 );
assert( pOrderBy->nExpr>0 );
p = pOrderBy->a[0].pExpr;
- if( pOrderBy->nExpr==1 && p->op==TK_COLUMN && p->iTable==base
- && p->iColumn==-1 ){
+ if( p->op==TK_COLUMN && p->iTable==base && p->iColumn==-1
+ && !referencesOtherTables(pOrderBy, pMaskSet, 1, base) ){
*pbRev = pOrderBy->a[0].sortOrder;
return 1;
}
@@ -884,6 +1035,247 @@ static double estLog(double N){
return logN;
}
+/*
+** Two routines for printing the content of an sqlite3_index_info
+** structure. Used for testing and debugging only. If neither
+** SQLITE_TEST or SQLITE_DEBUG are defined, then these routines
+** are no-ops.
+*/
+#if !defined(SQLITE_OMIT_VIRTUALTABLE) && \
+ (defined(SQLITE_TEST) || defined(SQLITE_DEBUG))
+static void TRACE_IDX_INPUTS(sqlite3_index_info *p){
+ int i;
+ if( !sqlite3_where_trace ) return;
+ for(i=0; inConstraint; i++){
+ sqlite3DebugPrintf(" constraint[%d]: col=%d termid=%d op=%d usabled=%d\n",
+ i,
+ p->aConstraint[i].iColumn,
+ p->aConstraint[i].iTermOffset,
+ p->aConstraint[i].op,
+ p->aConstraint[i].usable);
+ }
+ for(i=0; inOrderBy; i++){
+ sqlite3DebugPrintf(" orderby[%d]: col=%d desc=%d\n",
+ i,
+ p->aOrderBy[i].iColumn,
+ p->aOrderBy[i].desc);
+ }
+}
+static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){
+ int i;
+ if( !sqlite3_where_trace ) return;
+ for(i=0; inConstraint; i++){
+ sqlite3DebugPrintf(" usage[%d]: argvIdx=%d omit=%d\n",
+ i,
+ p->aConstraintUsage[i].argvIndex,
+ p->aConstraintUsage[i].omit);
+ }
+ sqlite3DebugPrintf(" idxNum=%d\n", p->idxNum);
+ sqlite3DebugPrintf(" idxStr=%s\n", p->idxStr);
+ sqlite3DebugPrintf(" orderByConsumed=%d\n", p->orderByConsumed);
+ sqlite3DebugPrintf(" estimatedCost=%g\n", p->estimatedCost);
+}
+#else
+#define TRACE_IDX_INPUTS(A)
+#define TRACE_IDX_OUTPUTS(A)
+#endif
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/*
+** Compute the best index for a virtual table.
+**
+** The best index is computed by the xBestIndex method of the virtual
+** table module. This routine is really just a wrapper that sets up
+** the sqlite3_index_info structure that is used to communicate with
+** xBestIndex.
+**
+** In a join, this routine might be called multiple times for the
+** same virtual table. The sqlite3_index_info structure is created
+** and initialized on the first invocation and reused on all subsequent
+** invocations. The sqlite3_index_info structure is also used when
+** code is generated to access the virtual table. The whereInfoDelete()
+** routine takes care of freeing the sqlite3_index_info structure after
+** everybody has finished with it.
+*/
+static double bestVirtualIndex(
+ Parse *pParse, /* The parsing context */
+ WhereClause *pWC, /* The WHERE clause */
+ struct SrcList_item *pSrc, /* The FROM clause term to search */
+ Bitmask notReady, /* Mask of cursors that are not available */
+ ExprList *pOrderBy, /* The order by clause */
+ int orderByUsable, /* True if we can potential sort */
+ sqlite3_index_info **ppIdxInfo /* Index information passed to xBestIndex */
+){
+ Table *pTab = pSrc->pTab;
+ sqlite3_index_info *pIdxInfo;
+ struct sqlite3_index_constraint *pIdxCons;
+ struct sqlite3_index_orderby *pIdxOrderBy;
+ struct sqlite3_index_constraint_usage *pUsage;
+ WhereTerm *pTerm;
+ int i, j;
+ int nOrderBy;
+ int rc;
+
+ /* If the sqlite3_index_info structure has not been previously
+ ** allocated and initialized for this virtual table, then allocate
+ ** and initialize it now
+ */
+ pIdxInfo = *ppIdxInfo;
+ if( pIdxInfo==0 ){
+ WhereTerm *pTerm;
+ int nTerm;
+ TRACE(("Recomputing index info for %s...\n", pTab->zName));
+
+ /* Count the number of possible WHERE clause constraints referring
+ ** to this virtual table */
+ for(i=nTerm=0, pTerm=pWC->a; inTerm; i++, pTerm++){
+ if( pTerm->leftCursor != pSrc->iCursor ) continue;
+ if( pTerm->eOperator==WO_IN ) continue;
+ nTerm++;
+ }
+
+ /* If the ORDER BY clause contains only columns in the current
+ ** virtual table then allocate space for the aOrderBy part of
+ ** the sqlite3_index_info structure.
+ */
+ nOrderBy = 0;
+ if( pOrderBy ){
+ for(i=0; inExpr; i++){
+ Expr *pExpr = pOrderBy->a[i].pExpr;
+ if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break;
+ }
+ if( i==pOrderBy->nExpr ){
+ nOrderBy = pOrderBy->nExpr;
+ }
+ }
+
+ /* Allocate the sqlite3_index_info structure
+ */
+ pIdxInfo = sqliteMalloc( sizeof(*pIdxInfo)
+ + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm
+ + sizeof(*pIdxOrderBy)*nOrderBy );
+ if( pIdxInfo==0 ){
+ sqlite3ErrorMsg(pParse, "out of memory");
+ return 0.0;
+ }
+ *ppIdxInfo = pIdxInfo;
+
+ /* Initialize the structure. The sqlite3_index_info structure contains
+ ** many fields that are declared "const" to prevent xBestIndex from
+ ** changing them. We have to do some funky casting in order to
+ ** initialize those fields.
+ */
+ pIdxCons = (struct sqlite3_index_constraint*)&pIdxInfo[1];
+ pIdxOrderBy = (struct sqlite3_index_orderby*)&pIdxCons[nTerm];
+ pUsage = (struct sqlite3_index_constraint_usage*)&pIdxOrderBy[nOrderBy];
+ *(int*)&pIdxInfo->nConstraint = nTerm;
+ *(int*)&pIdxInfo->nOrderBy = nOrderBy;
+ *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint = pIdxCons;
+ *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy;
+ *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage =
+ pUsage;
+
+ for(i=j=0, pTerm=pWC->a; inTerm; i++, pTerm++){
+ if( pTerm->leftCursor != pSrc->iCursor ) continue;
+ if( pTerm->eOperator==WO_IN ) continue;
+ pIdxCons[j].iColumn = pTerm->leftColumn;
+ pIdxCons[j].iTermOffset = i;
+ pIdxCons[j].op = (unsigned char)pTerm->eOperator;
+ /* The direct assignment in the previous line is possible only because
+ ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
+ ** following asserts verify this fact. */
+ assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
+ assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
+ assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
+ assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
+ assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
+ assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH );
+ assert( pTerm->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
+ j++;
+ }
+ for(i=0; ia[i].pExpr;
+ pIdxOrderBy[i].iColumn = pExpr->iColumn;
+ pIdxOrderBy[i].desc = pOrderBy->a[i].sortOrder;
+ }
+ }
+
+ /* At this point, the sqlite3_index_info structure that pIdxInfo points
+ ** to will have been initialized, either during the current invocation or
+ ** during some prior invocation. Now we just have to customize the
+ ** details of pIdxInfo for the current invocation and pass it to
+ ** xBestIndex.
+ */
+
+ /* The module name must be defined */
+ assert( pTab->azModuleArg && pTab->azModuleArg[0] );
+ if( pTab->pVtab==0 ){
+ sqlite3ErrorMsg(pParse, "undefined module %s for table %s",
+ pTab->azModuleArg[0], pTab->zName);
+ return 0.0;
+ }
+
+ /* Set the aConstraint[].usable fields and initialize all
+ ** output variables to zero.
+ **
+ ** aConstraint[].usable is true for constraints where the right-hand
+ ** side contains only references to tables to the left of the current
+ ** table. In other words, if the constraint is of the form:
+ **
+ ** column = expr
+ **
+ ** and we are evaluating a join, then the constraint on column is
+ ** only valid if all tables referenced in expr occur to the left
+ ** of the table containing column.
+ **
+ ** The aConstraints[] array contains entries for all constraints
+ ** on the current table. That way we only have to compute it once
+ ** even though we might try to pick the best index multiple times.
+ ** For each attempt at picking an index, the order of tables in the
+ ** join might be different so we have to recompute the usable flag
+ ** each time.
+ */
+ pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
+ pUsage = pIdxInfo->aConstraintUsage;
+ for(i=0; inConstraint; i++, pIdxCons++){
+ j = pIdxCons->iTermOffset;
+ pTerm = &pWC->a[j];
+ pIdxCons->usable = (pTerm->prereqRight & notReady)==0;
+ }
+ memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
+ if( pIdxInfo->needToFreeIdxStr ){
+ sqlite3_free(pIdxInfo->idxStr);
+ }
+ pIdxInfo->idxStr = 0;
+ pIdxInfo->idxNum = 0;
+ pIdxInfo->needToFreeIdxStr = 0;
+ pIdxInfo->orderByConsumed = 0;
+ pIdxInfo->estimatedCost = SQLITE_BIG_DBL / 2.0;
+ nOrderBy = pIdxInfo->nOrderBy;
+ if( pIdxInfo->nOrderBy && !orderByUsable ){
+ *(int*)&pIdxInfo->nOrderBy = 0;
+ }
+
+ sqlite3SafetyOff(pParse->db);
+ TRACE(("xBestIndex for %s\n", pTab->zName));
+ TRACE_IDX_INPUTS(pIdxInfo);
+ rc = pTab->pVtab->pModule->xBestIndex(pTab->pVtab, pIdxInfo);
+ TRACE_IDX_OUTPUTS(pIdxInfo);
+ if( rc!=SQLITE_OK ){
+ if( rc==SQLITE_NOMEM ){
+ sqlite3FailedMalloc();
+ }else {
+ sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc));
+ }
+ sqlite3SafetyOn(pParse->db);
+ }else{
+ rc = sqlite3SafetyOn(pParse->db);
+ }
+ *(int*)&pIdxInfo->nOrderBy = nOrderBy;
+ return pIdxInfo->estimatedCost;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
/*
** Find the best index for accessing a particular table. Return a pointer
** to the index, flags that describe how the index should be used, the
@@ -922,6 +1314,7 @@ static double bestIndex(
int rev; /* True to scan in reverse order */
int flags; /* Flags associated with pProbe */
int nEq; /* Number of == or IN constraints */
+ int eqTermMask; /* Mask of valid equality operators */
double cost; /* Cost of using pProbe */
TRACE(("bestIndex: tbl=%s notReady=%x\n", pSrc->pTab->zName, notReady));
@@ -936,7 +1329,7 @@ static double bestIndex(
*/
if( pProbe==0 &&
findTerm(pWC, iCur, -1, 0, WO_EQ|WO_IN|WO_LT|WO_LE|WO_GT|WO_GE,0)==0 &&
- (pOrderBy==0 || !sortableByRowid(iCur, pOrderBy, &rev)) ){
+ (pOrderBy==0 || !sortableByRowid(iCur, pOrderBy, pWC->pMaskSet, &rev)) ){
*pFlags = 0;
*ppIndex = 0;
*pnEq = 0;
@@ -998,7 +1391,7 @@ static double bestIndex(
/* If the table scan does not satisfy the ORDER BY clause, increase
** the cost by NlogN to cover the expense of sorting. */
if( pOrderBy ){
- if( sortableByRowid(iCur, pOrderBy, &rev) ){
+ if( sortableByRowid(iCur, pOrderBy, pWC->pMaskSet, &rev) ){
flags |= WHERE_ORDERBY|WHERE_ROWID_RANGE;
if( rev ){
flags |= WHERE_REVERSE;
@@ -1013,6 +1406,17 @@ static double bestIndex(
bestFlags = flags;
}
+ /* If the pSrc table is the right table of a LEFT JOIN then we may not
+ ** use an index to satisfy IS NULL constraints on that table. This is
+ ** because columns might end up being NULL if the table does not match -
+ ** a circumstance which the index cannot help us discover. Ticket #2177.
+ */
+ if( (pSrc->jointype & JT_LEFT)!=0 ){
+ eqTermMask = WO_EQ|WO_IN;
+ }else{
+ eqTermMask = WO_EQ|WO_IN|WO_ISNULL;
+ }
+
/* Look at each index.
*/
for(; pProbe; pProbe=pProbe->pNext){
@@ -1027,14 +1431,14 @@ static double bestIndex(
flags = 0;
for(i=0; inColumn; i++){
int j = pProbe->aiColumn[i];
- pTerm = findTerm(pWC, iCur, j, notReady, WO_EQ|WO_IN, pProbe);
+ pTerm = findTerm(pWC, iCur, j, notReady, eqTermMask, pProbe);
if( pTerm==0 ) break;
flags |= WHERE_COLUMN_EQ;
if( pTerm->eOperator & WO_IN ){
Expr *pExpr = pTerm->pExpr;
flags |= WHERE_COLUMN_IN;
if( pExpr->pSelect!=0 ){
- inMultiplier *= 100;
+ inMultiplier *= 25;
}else if( pExpr->pList!=0 ){
inMultiplier *= pExpr->pList->nExpr + 1;
}
@@ -1071,7 +1475,7 @@ static double bestIndex(
*/
if( pOrderBy ){
if( (flags & WHERE_COLUMN_IN)==0 &&
- isSortingIndex(pParse,pProbe,iCur,pOrderBy,nEq,&rev) ){
+ isSortingIndex(pParse,pWC->pMaskSet,pProbe,iCur,pOrderBy,nEq,&rev) ){
if( flags==0 ){
flags = WHERE_COLUMN_RANGE;
}
@@ -1121,7 +1525,7 @@ static double bestIndex(
*ppIndex = bestIdx;
TRACE(("best index is %s, cost=%.9g, flags=%x, nEq=%d\n",
bestIdx ? bestIdx->zName : "(none)", lowestCost, bestFlags, bestNEq));
- *pFlags = bestFlags;
+ *pFlags = bestFlags | eqTermMask;
*pnEq = bestNEq;
return lowestCost;
}
@@ -1166,30 +1570,18 @@ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
}
/*
-** Generate code that builds a probe for an index. Details:
-**
-** * Check the top nColumn entries on the stack. If any
-** of those entries are NULL, jump immediately to brk,
-** which is the loop exit, since no index entry will match
-** if any part of the key is NULL. Pop (nColumn+nExtra)
-** elements from the stack.
-**
-** * Construct a probe entry from the top nColumn entries in
-** the stack with affinities appropriate for index pIdx.
-** Only nColumn elements are popped from the stack in this case
-** (by OP_MakeRecord).
+** Generate code that builds a probe for an index.
**
+** There should be nColumn values on the stack. The index
+** to be probed is pIdx. Pop the values from the stack and
+** replace them all with a single record that is the index
+** problem.
*/
static void buildIndexProbe(
- Vdbe *v,
- int nColumn,
- int nExtra,
- int brk,
- Index *pIdx
+ Vdbe *v, /* Generate code into this VM */
+ int nColumn, /* The number of columns to check for NULL */
+ Index *pIdx /* Index that we will be searching */
){
- sqlite3VdbeAddOp(v, OP_NotNull, -nColumn, sqlite3VdbeCurrentAddr(v)+3);
- sqlite3VdbeAddOp(v, OP_Pop, nColumn+nExtra, 0);
- sqlite3VdbeAddOp(v, OP_Goto, 0, brk);
sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);
sqlite3IndexAffinityStr(v, pIdx);
}
@@ -1213,28 +1605,29 @@ static void codeEqualityTerm(
WhereLevel *pLevel /* When level of the FROM clause we are working on */
){
Expr *pX = pTerm->pExpr;
- if( pX->op!=TK_IN ){
- assert( pX->op==TK_EQ );
+ Vdbe *v = pParse->pVdbe;
+ if( pX->op==TK_EQ ){
sqlite3ExprCode(pParse, pX->pRight);
+ }else if( pX->op==TK_ISNULL ){
+ sqlite3VdbeAddOp(v, OP_Null, 0, 0);
#ifndef SQLITE_OMIT_SUBQUERY
}else{
int iTab;
int *aIn;
- Vdbe *v = pParse->pVdbe;
+ assert( pX->op==TK_IN );
sqlite3CodeSubselect(pParse, pX);
iTab = pX->iTable;
- sqlite3VdbeAddOp(v, OP_Rewind, iTab, brk);
+ sqlite3VdbeAddOp(v, OP_Rewind, iTab, 0);
VdbeComment((v, "# %.*s", pX->span.n, pX->span.z));
pLevel->nIn++;
sqliteReallocOrFree((void**)&pLevel->aInLoop,
- sizeof(pLevel->aInLoop[0])*3*pLevel->nIn);
+ sizeof(pLevel->aInLoop[0])*2*pLevel->nIn);
aIn = pLevel->aInLoop;
if( aIn ){
- aIn += pLevel->nIn*3 - 3;
- aIn[0] = OP_Next;
- aIn[1] = iTab;
- aIn[2] = sqlite3VdbeAddOp(v, OP_Column, iTab, 0);
+ aIn += pLevel->nIn*2 - 2;
+ aIn[0] = iTab;
+ aIn[1] = sqlite3VdbeAddOp(v, OP_Column, iTab, 0);
}else{
pLevel->nIn = 0;
}
@@ -1294,17 +1687,20 @@ static void codeAllEqualityTerms(
/* Evaluate the equality constraints
*/
- for(j=0; jnColumn; j++){
+ assert( pIdx->nColumn>=nEq );
+ for(j=0; jaiColumn[j];
- pTerm = findTerm(pWC, iCur, k, notReady, WO_EQ|WO_IN, pIdx);
+ pTerm = findTerm(pWC, iCur, k, notReady, pLevel->flags, pIdx);
if( pTerm==0 ) break;
assert( (pTerm->flags & TERM_CODED)==0 );
codeEqualityTerm(pParse, pTerm, brk, pLevel);
+ if( (pTerm->eOperator & WO_ISNULL)==0 ){
+ sqlite3VdbeAddOp(v, OP_IsNull, termsInMem ? -1 : -(j+1), brk);
+ }
if( termsInMem ){
sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem+j+1, 1);
}
}
- assert( j==nEq );
/* Make sure all the constraint values are on the top of the stack
*/
@@ -1328,6 +1724,25 @@ static int nQPlan = 0; /* Next free slow in _query_plan[] */
#endif /* SQLITE_TEST */
+/*
+** Free a WhereInfo structure
+*/
+static void whereInfoFree(WhereInfo *pWInfo){
+ if( pWInfo ){
+ int i;
+ for(i=0; inLevel; i++){
+ sqlite3_index_info *pInfo = pWInfo->a[i].pIdxInfo;
+ if( pInfo ){
+ if( pInfo->needToFreeIdxStr ){
+ sqlite3_free(pInfo->idxStr);
+ }
+ sqliteFree(pInfo);
+ }
+ }
+ sqliteFree(pWInfo);
+ }
+}
+
/*
** Generate the beginning of the loop used for WHERE clause processing.
@@ -1448,7 +1863,7 @@ WhereInfo *sqlite3WhereBegin(
** subexpression is separated by an AND operator.
*/
initMaskSet(&maskSet);
- whereClauseInit(&wc, pParse);
+ whereClauseInit(&wc, pParse, &maskSet);
whereSplit(&wc, pWhere, TK_AND);
/* Allocate and initialize the WhereInfo structure that will become the
@@ -1458,6 +1873,7 @@ WhereInfo *sqlite3WhereBegin(
if( sqlite3MallocFailed() ){
goto whereBeginNoMem;
}
+ pWInfo->nLevel = pTabList->nSrc;
pWInfo->pParse = pParse;
pWInfo->pTabList = pTabList;
pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
@@ -1478,7 +1894,7 @@ WhereInfo *sqlite3WhereBegin(
for(i=0; inSrc; i++){
createMask(&maskSet, pTabList->a[i].iCursor);
}
- exprAnalyzeAll(pTabList, &maskSet, &wc);
+ exprAnalyzeAll(pTabList, &wc);
if( sqlite3MallocFailed() ){
goto whereBeginNoMem;
}
@@ -1515,23 +1931,41 @@ WhereInfo *sqlite3WhereBegin(
int bestJ = 0; /* The value of j */
Bitmask m; /* Bitmask value for j or bestJ */
int once = 0; /* True when first table is seen */
+ sqlite3_index_info *pIndex; /* Current virtual index */
lowestCost = SQLITE_BIG_DBL;
for(j=iFrom, pTabItem=&pTabList->a[j]; jnSrc; j++, pTabItem++){
- if( once &&
- ((pTabItem->jointype & (JT_LEFT|JT_CROSS))!=0
- || (j>0 && (pTabItem[-1].jointype & (JT_LEFT|JT_CROSS))!=0))
- ){
- break;
- }
+ int doNotReorder; /* True if this table should not be reordered */
+
+ doNotReorder = (pTabItem->jointype & (JT_LEFT|JT_CROSS))!=0;
+ if( once && doNotReorder ) break;
m = getMask(&maskSet, pTabItem->iCursor);
if( (m & notReady)==0 ){
if( j==iFrom ) iFrom++;
continue;
}
- cost = bestIndex(pParse, &wc, pTabItem, notReady,
- (i==0 && ppOrderBy) ? *ppOrderBy : 0,
- &pIdx, &flags, &nEq);
+ assert( pTabItem->pTab );
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( IsVirtual(pTabItem->pTab) ){
+ sqlite3_index_info **ppIdxInfo = &pWInfo->a[j].pIdxInfo;
+ cost = bestVirtualIndex(pParse, &wc, pTabItem, notReady,
+ ppOrderBy ? *ppOrderBy : 0, i==0,
+ ppIdxInfo);
+ flags = WHERE_VIRTUALTABLE;
+ pIndex = *ppIdxInfo;
+ if( pIndex && pIndex->orderByConsumed ){
+ flags = WHERE_VIRTUALTABLE | WHERE_ORDERBY;
+ }
+ pIdx = 0;
+ nEq = 0;
+ }else
+#endif
+ {
+ cost = bestIndex(pParse, &wc, pTabItem, notReady,
+ (i==0 && ppOrderBy) ? *ppOrderBy : 0,
+ &pIdx, &flags, &nEq);
+ pIndex = 0;
+ }
if( costpBestIdx = pIndex;
}
+ if( doNotReorder ) break;
}
TRACE(("*** Optimizer choose table %d for loop %d\n", bestJ,
pLevel-pWInfo->a));
@@ -1573,7 +2009,6 @@ WhereInfo *sqlite3WhereBegin(
** searching those tables.
*/
sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
- pLevel = pWInfo->a;
for(i=0, pLevel=pWInfo->a; inSrc; i++, pLevel++){
Table *pTab; /* Table to open */
Index *pIx; /* Index used to access pTab (if any) */
@@ -1593,13 +2028,29 @@ WhereInfo *sqlite3WhereBegin(
}else if( pLevel->flags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
zMsg = sqlite3MPrintf("%z USING PRIMARY KEY", zMsg);
}
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ else if( pLevel->pBestIdx ){
+ sqlite3_index_info *pBestIdx = pLevel->pBestIdx;
+ zMsg = sqlite3MPrintf("%z VIRTUAL TABLE INDEX %d:%s", zMsg,
+ pBestIdx->idxNum, pBestIdx->idxStr);
+ }
+#endif
+ if( pLevel->flags & WHERE_ORDERBY ){
+ zMsg = sqlite3MPrintf("%z ORDER BY", zMsg);
+ }
sqlite3VdbeOp3(v, OP_Explain, i, pLevel->iFrom, zMsg, P3_DYNAMIC);
}
#endif /* SQLITE_OMIT_EXPLAIN */
pTabItem = &pTabList->a[pLevel->iFrom];
pTab = pTabItem->pTab;
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- if( pTab->isTransient || pTab->pSelect ) continue;
+ if( pTab->isEphem || pTab->pSelect ) continue;
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( pLevel->pBestIdx ){
+ int iCur = pTabItem->iCursor;
+ sqlite3VdbeOp3(v, OP_VOpen, iCur, 0, (const char*)pTab->pVtab, P3_VTAB);
+ }else
+#endif
if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){
sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, OP_OpenRead);
if( pTab->nCol<(sizeof(Bitmask)*8) ){
@@ -1621,7 +2072,9 @@ WhereInfo *sqlite3WhereBegin(
sqlite3VdbeOp3(v, OP_OpenRead, iIdxCur, pIx->tnum,
(char*)pKey, P3_KEYINFO_HANDOFF);
}
- if( (pLevel->flags & WHERE_IDX_ONLY)!=0 ){
+ if( (pLevel->flags & (WHERE_IDX_ONLY|WHERE_COLUMN_RANGE))!=0 ){
+ /* Only call OP_SetNumColumns on the index if we might later use
+ ** OP_Column on the index. */
sqlite3VdbeAddOp(v, OP_SetNumColumns, iIdxCur, pIx->nColumn+1);
}
sqlite3CodeVerifySchema(pParse, iDb);
@@ -1660,13 +2113,54 @@ WhereInfo *sqlite3WhereBegin(
** initialize a memory cell that records if this table matches any
** row of the left table of the join.
*/
- if( pLevel->iFrom>0 && (pTabItem[-1].jointype & JT_LEFT)!=0 ){
+ if( pLevel->iFrom>0 && (pTabItem[0].jointype & JT_LEFT)!=0 ){
if( !pParse->nMem ) pParse->nMem++;
pLevel->iLeftJoin = pParse->nMem++;
sqlite3VdbeAddOp(v, OP_MemInt, 0, pLevel->iLeftJoin);
VdbeComment((v, "# init LEFT JOIN no-match flag"));
}
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( pLevel->pBestIdx ){
+ /* Case 0: The table is a virtual-table. Use the VFilter and VNext
+ ** to access the data.
+ */
+ int j;
+ sqlite3_index_info *pBestIdx = pLevel->pBestIdx;
+ int nConstraint = pBestIdx->nConstraint;
+ struct sqlite3_index_constraint_usage *aUsage =
+ pBestIdx->aConstraintUsage;
+ const struct sqlite3_index_constraint *aConstraint =
+ pBestIdx->aConstraint;
+
+ for(j=1; j<=nConstraint; j++){
+ int k;
+ for(k=0; kpRight);
+ break;
+ }
+ }
+ if( k==nConstraint ) break;
+ }
+ sqlite3VdbeAddOp(v, OP_Integer, j-1, 0);
+ sqlite3VdbeAddOp(v, OP_Integer, pBestIdx->idxNum, 0);
+ sqlite3VdbeOp3(v, OP_VFilter, iCur, brk, pBestIdx->idxStr,
+ pBestIdx->needToFreeIdxStr ? P3_MPRINTF : P3_STATIC);
+ pBestIdx->needToFreeIdxStr = 0;
+ for(j=0; jnConstraint; j++){
+ if( aUsage[j].omit ){
+ int iTerm = aConstraint[j].iTermOffset;
+ disableTerm(pLevel, &wc.a[iTerm]);
+ }
+ }
+ pLevel->op = OP_VNext;
+ pLevel->p1 = iCur;
+ pLevel->p2 = sqlite3VdbeCurrentAddr(v);
+ }else
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
if( pLevel->flags & WHERE_ROWID_EQ ){
/* Case 1: We can directly reference a single row using an
** equality comparison against the ROWID field. Or
@@ -1753,7 +2247,6 @@ WhereInfo *sqlite3WhereBegin(
int btmEq=0; /* True if btm limit uses ==. False if strictly > */
int topOp, btmOp; /* Operators for the top and bottom search bounds */
int testOp;
- int nNotNull; /* Number of rows of index that must be non-NULL */
int topLimit = (pLevel->flags & WHERE_TOP_LIMIT)!=0;
int btmLimit = (pLevel->flags & WHERE_BTM_LIMIT)!=0;
@@ -1775,7 +2268,6 @@ WhereInfo *sqlite3WhereBegin(
** operator and the top bound is a < or <= operator. For a descending
** index the operators are reversed.
*/
- nNotNull = nEq + topLimit;
if( pIdx->aSortOrder[nEq]==SQLITE_SO_ASC ){
topOp = WO_LT|WO_LE;
btmOp = WO_GT|WO_GE;
@@ -1800,6 +2292,7 @@ WhereInfo *sqlite3WhereBegin(
pX = pTerm->pExpr;
assert( (pTerm->flags & TERM_CODED)==0 );
sqlite3ExprCode(pParse, pX->pRight);
+ sqlite3VdbeAddOp(v, OP_IsNull, -(nEq+1), brk);
topEq = pTerm->eOperator & (WO_LE|WO_GE);
disableTerm(pLevel, pTerm);
testOp = OP_IdxGE;
@@ -1810,7 +2303,7 @@ WhereInfo *sqlite3WhereBegin(
if( testOp!=OP_Noop ){
int nCol = nEq + topLimit;
pLevel->iMem = pParse->nMem++;
- buildIndexProbe(v, nCol, nEq, brk, pIdx);
+ buildIndexProbe(v, nCol, pIdx);
if( bRev ){
int op = topEq ? OP_MoveLe : OP_MoveLt;
sqlite3VdbeAddOp(v, op, iIdxCur, brk);
@@ -1838,6 +2331,7 @@ WhereInfo *sqlite3WhereBegin(
pX = pTerm->pExpr;
assert( (pTerm->flags & TERM_CODED)==0 );
sqlite3ExprCode(pParse, pX->pRight);
+ sqlite3VdbeAddOp(v, OP_IsNull, -(nEq+1), brk);
btmEq = pTerm->eOperator & (WO_LE|WO_GE);
disableTerm(pLevel, pTerm);
}else{
@@ -1845,7 +2339,7 @@ WhereInfo *sqlite3WhereBegin(
}
if( nEq>0 || btmLimit ){
int nCol = nEq + btmLimit;
- buildIndexProbe(v, nCol, 0, brk, pIdx);
+ buildIndexProbe(v, nCol, pIdx);
if( bRev ){
pLevel->iMem = pParse->nMem++;
sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
@@ -1872,8 +2366,10 @@ WhereInfo *sqlite3WhereBegin(
sqlite3VdbeChangeP3(v, -1, "+", P3_STATIC);
}
}
- sqlite3VdbeAddOp(v, OP_RowKey, iIdxCur, 0);
- sqlite3VdbeAddOp(v, OP_IdxIsNull, nNotNull, cont);
+ if( topLimit | btmLimit ){
+ sqlite3VdbeAddOp(v, OP_Column, iIdxCur, nEq);
+ sqlite3VdbeAddOp(v, OP_IsNull, 1, cont);
+ }
if( !omitTable ){
sqlite3VdbeAddOp(v, OP_IdxRowid, iIdxCur, 0);
sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
@@ -1899,7 +2395,7 @@ WhereInfo *sqlite3WhereBegin(
/* Generate a single key that will be used to both start and terminate
** the search
*/
- buildIndexProbe(v, nEq, 0, brk, pIdx);
+ buildIndexProbe(v, nEq, pIdx);
sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 0);
/* Generate code (1) to move to the first matching element of the table.
@@ -1920,8 +2416,6 @@ WhereInfo *sqlite3WhereBegin(
sqlite3VdbeOp3(v, OP_IdxGE, iIdxCur, brk, "+", P3_STATIC);
pLevel->op = OP_Next;
}
- sqlite3VdbeAddOp(v, OP_RowKey, iIdxCur, 0);
- sqlite3VdbeAddOp(v, OP_IdxIsNull, nEq, cont);
if( !omitTable ){
sqlite3VdbeAddOp(v, OP_IdxRowid, iIdxCur, 0);
sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
@@ -2030,7 +2524,7 @@ WhereInfo *sqlite3WhereBegin(
/* Jump here if malloc fails */
whereBeginNoMem:
whereClauseClear(&wc);
- sqliteFree(pWInfo);
+ whereInfoFree(pWInfo);
return 0;
}
@@ -2056,8 +2550,9 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
if( pLevel->nIn ){
int *a;
int j;
- for(j=pLevel->nIn, a=&pLevel->aInLoop[j*3-3]; j>0; j--, a-=3){
- sqlite3VdbeAddOp(v, a[0], a[1], a[2]);
+ for(j=pLevel->nIn, a=&pLevel->aInLoop[j*2-2]; j>0; j--, a-=2){
+ sqlite3VdbeAddOp(v, OP_Next, a[0], a[1]);
+ sqlite3VdbeJumpHere(v, a[1]-1);
}
sqliteFree(pLevel->aInLoop);
}
@@ -2084,7 +2579,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
Table *pTab = pTabItem->pTab;
assert( pTab!=0 );
- if( pTab->isTransient || pTab->pSelect ) continue;
+ if( pTab->isEphem || pTab->pSelect ) continue;
if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){
sqlite3VdbeAddOp(v, OP_Close, pTabItem->iCursor, 0);
}
@@ -2131,6 +2626,6 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
/* Final cleanup
*/
- sqliteFree(pWInfo);
+ whereInfoFree(pWInfo);
return;
}