Updated SQLite to 3.3.13 - why? I have no idea
This commit is contained in:
		@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -294,6 +294,9 @@
 | 
			
		||||
			<File
 | 
			
		||||
				RelativePath="..\sqlite-source\legacy.c">
 | 
			
		||||
			</File>
 | 
			
		||||
			<File
 | 
			
		||||
				RelativePath="..\sqlite-source\loadext.c">
 | 
			
		||||
			</File>
 | 
			
		||||
			<File
 | 
			
		||||
				RelativePath="..\sqlite-source\main.c">
 | 
			
		||||
			</File>
 | 
			
		||||
@@ -345,6 +348,9 @@
 | 
			
		||||
			<File
 | 
			
		||||
				RelativePath="..\sqlite-source\sqlite3.h">
 | 
			
		||||
			</File>
 | 
			
		||||
			<File
 | 
			
		||||
				RelativePath="..\sqlite-source\sqlite3ext.h">
 | 
			
		||||
			</File>
 | 
			
		||||
			<File
 | 
			
		||||
				RelativePath="..\sqlite-source\sqliteInt.h">
 | 
			
		||||
			</File>
 | 
			
		||||
@@ -390,6 +396,9 @@
 | 
			
		||||
			<File
 | 
			
		||||
				RelativePath="..\sqlite-source\vdbemem.c">
 | 
			
		||||
			</File>
 | 
			
		||||
			<File
 | 
			
		||||
				RelativePath="..\sqlite-source\vtab.c">
 | 
			
		||||
			</File>
 | 
			
		||||
			<File
 | 
			
		||||
				RelativePath="..\sqlite-source\where.c">
 | 
			
		||||
			</File>
 | 
			
		||||
 
 | 
			
		||||
@@ -407,6 +407,10 @@
 | 
			
		||||
				RelativePath="..\sqlite-source\legacy.c"
 | 
			
		||||
				>
 | 
			
		||||
			</File>
 | 
			
		||||
			<File
 | 
			
		||||
				RelativePath="..\sqlite-source\loadext.c"
 | 
			
		||||
				>
 | 
			
		||||
			</File>
 | 
			
		||||
			<File
 | 
			
		||||
				RelativePath="..\sqlite-source\main.c"
 | 
			
		||||
				>
 | 
			
		||||
@@ -475,6 +479,10 @@
 | 
			
		||||
				RelativePath="..\sqlite-source\sqlite3.h"
 | 
			
		||||
				>
 | 
			
		||||
			</File>
 | 
			
		||||
			<File
 | 
			
		||||
				RelativePath="..\sqlite-source\sqlite3ext.h"
 | 
			
		||||
				>
 | 
			
		||||
			</File>
 | 
			
		||||
			<File
 | 
			
		||||
				RelativePath="..\sqlite-source\sqliteInt.h"
 | 
			
		||||
				>
 | 
			
		||||
@@ -535,6 +543,10 @@
 | 
			
		||||
				RelativePath="..\sqlite-source\vdbemem.c"
 | 
			
		||||
				>
 | 
			
		||||
			</File>
 | 
			
		||||
			<File
 | 
			
		||||
				RelativePath="..\sqlite-source\vtab.c"
 | 
			
		||||
				>
 | 
			
		||||
			</File>
 | 
			
		||||
			<File
 | 
			
		||||
				RelativePath="..\sqlite-source\where.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");
 | 
			
		||||
 
 | 
			
		||||
@@ -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; i<db->nDb; 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; i<db->nDb; 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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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; i<hdr+10-pPage->leaf*4; i++) used[i] = 1;
 | 
			
		||||
  nFree = 0;
 | 
			
		||||
  pc = get2byte(&data[hdr+1]);
 | 
			
		||||
  while( pc ){
 | 
			
		||||
    int size;
 | 
			
		||||
    assert( pc>0 && pc<usableSize-4 );
 | 
			
		||||
    size = get2byte(&data[pc+2]);
 | 
			
		||||
    assert( pc+size<=usableSize );
 | 
			
		||||
    nFree += size;
 | 
			
		||||
    for(i=pc; i<pc+size; i++){
 | 
			
		||||
      assert( used[i]==0 );
 | 
			
		||||
      used[i] = 1;
 | 
			
		||||
    }
 | 
			
		||||
    pc = get2byte(&data[pc]);
 | 
			
		||||
  }
 | 
			
		||||
  idx = 0;
 | 
			
		||||
  nCell = get2byte(&data[hdr+3]);
 | 
			
		||||
  cellLimit = get2byte(&data[hdr+5]);
 | 
			
		||||
  assert( pPage->isInit==0 
 | 
			
		||||
         || pPage->nFree==nFree+data[hdr+7]+cellLimit-(cellOffset+2*nCell) );
 | 
			
		||||
  cellOffset = pPage->cellOffset;
 | 
			
		||||
  for(i=0; i<nCell; i++){
 | 
			
		||||
    int size;
 | 
			
		||||
    pc = get2byte(&data[cellOffset+2*i]);
 | 
			
		||||
    assert( pc>0 && pc<usableSize-4 );
 | 
			
		||||
    size = cellSize(pPage, &data[pc]);
 | 
			
		||||
    assert( pc+size<=usableSize );
 | 
			
		||||
    for(j=pc; j<pc+size; j++){
 | 
			
		||||
      assert( used[j]==0 );
 | 
			
		||||
      used[j] = 1;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  for(i=cellOffset+2*nCell; i<cellimit; i++){
 | 
			
		||||
    assert( used[i]==0 );
 | 
			
		||||
    used[i] = 1;
 | 
			
		||||
  }
 | 
			
		||||
  nFree = 0;
 | 
			
		||||
  for(i=0; i<usableSize; i++){
 | 
			
		||||
    assert( used[i]<=1 );
 | 
			
		||||
    if( used[i]==0 ) nFree++;
 | 
			
		||||
  }
 | 
			
		||||
  assert( nFree==data[hdr+7] );
 | 
			
		||||
  sqliteFree(used);
 | 
			
		||||
}
 | 
			
		||||
#define pageIntegrity(X) _pageIntegrity(X)
 | 
			
		||||
#else
 | 
			
		||||
# define pageIntegrity(X)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* A bunch of assert() statements to check the transaction state variables
 | 
			
		||||
** of handle p (type Btree*) are internally consistent.
 | 
			
		||||
*/
 | 
			
		||||
@@ -1439,7 +1346,6 @@ static int initPage(
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  pPage->isInit = 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->idx<pPage->nCell );
 | 
			
		||||
  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->idx<pPage->nCell );
 | 
			
		||||
  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; i<pPage->nCell; i++){
 | 
			
		||||
  for(i=0; i<pPage->nCell && 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; i<nRoot; i++){
 | 
			
		||||
  for(i=0; i<nRoot && sCheck.mxErr; i++){
 | 
			
		||||
    if( aRoot[i]==0 ) continue;
 | 
			
		||||
#ifndef SQLITE_OMIT_AUTOVACUUM
 | 
			
		||||
    if( pBt->autoVacuum && 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.
 | 
			
		||||
**
 | 
			
		||||
 
 | 
			
		||||
@@ -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*);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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; j<pTab->nCol; 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
 | 
			
		||||
*/
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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; k<pUsing->nId; k++){
 | 
			
		||||
                if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ){
 | 
			
		||||
                  pItem++;
 | 
			
		||||
                  i++;
 | 
			
		||||
                  break;
 | 
			
		||||
            if( i<pSrcList->nSrc-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; k<pUsing->nId; 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<<n;
 | 
			
		||||
    pMatch->colUsed |= ((Bitmask)1)<<n;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
lookupname_end:
 | 
			
		||||
@@ -1148,6 +1205,7 @@ static int nameResolverStep(void *pArg, Expr *pExpr){
 | 
			
		||||
      int wrong_num_args = 0;     /* True if wrong number of arguments */
 | 
			
		||||
      int is_agg = 0;             /* True if is an aggregate function */
 | 
			
		||||
      int i;
 | 
			
		||||
      int auth;                   /* Authorization to use the function */
 | 
			
		||||
      int nId;                    /* Number of characters in function name */
 | 
			
		||||
      const char *zId;            /* The function name. */
 | 
			
		||||
      FuncDef *pDef;              /* Information about the function */
 | 
			
		||||
@@ -1166,6 +1224,20 @@ static int nameResolverStep(void *pArg, Expr *pExpr){
 | 
			
		||||
      }else{
 | 
			
		||||
        is_agg = pDef->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; i<nExpr && i<32; i++){
 | 
			
		||||
        if( sqlite3ExprIsConstant(pList->a[i].pExpr) ){
 | 
			
		||||
          constMask |= (1<<i);
 | 
			
		||||
@@ -2157,6 +2251,7 @@ static int analyzeAggregate(void *pArg, Expr *pExpr){
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  switch( pExpr->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 */
 | 
			
		||||
 
 | 
			
		||||
@@ -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<n; i++, pBlob++){
 | 
			
		||||
    unsigned char c = *pBlob;
 | 
			
		||||
    *(z++) = hexdigits[(c>>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
 | 
			
		||||
 
 | 
			
		||||
@@ -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; i<nColumn; i++){
 | 
			
		||||
      if( sqlite3ExprResolveNames(&sNC, pList->a[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++){
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										422
									
								
								dlls/sqlite/sqlite-source/loadext.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										422
									
								
								dlls/sqlite/sqlite-source/loadext.c
									
									
									
									
									
										Normal file
									
								
							@@ -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 <string.h>
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
** 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; i<db->nExtension; 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; i++){
 | 
			
		||||
    if( aAutoExtension[i]==xInit ) break;
 | 
			
		||||
  }
 | 
			
		||||
  if( i==nAutoExtension ){
 | 
			
		||||
    nAutoExtension++;
 | 
			
		||||
    aAutoExtension = sqlite3Realloc( aAutoExtension,
 | 
			
		||||
                                     nAutoExtension*sizeof(aAutoExtension[0]) );
 | 
			
		||||
    if( aAutoExtension==0 ){
 | 
			
		||||
      nAutoExtension = 0;
 | 
			
		||||
      rc = SQLITE_NOMEM;
 | 
			
		||||
    }else{
 | 
			
		||||
      aAutoExtension[nAutoExtension-1] = xInit;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  sqlite3OsLeaveMutex();
 | 
			
		||||
  assert( (rc&0xff)==rc );
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
** Reset the automatic extension loading mechanism.
 | 
			
		||||
*/
 | 
			
		||||
void sqlite3_reset_auto_extension(void){
 | 
			
		||||
  sqlite3OsEnterMutex();
 | 
			
		||||
  sqliteFree(aAutoExtension);
 | 
			
		||||
  aAutoExtension = 0;
 | 
			
		||||
  nAutoExtension = 0;
 | 
			
		||||
  sqlite3OsLeaveMutex();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
** Load all automatic extensions.
 | 
			
		||||
*/
 | 
			
		||||
int sqlite3AutoLoadExtensions(sqlite3 *db){
 | 
			
		||||
  int i;
 | 
			
		||||
  int go = 1;
 | 
			
		||||
  int rc = SQLITE_OK;
 | 
			
		||||
  int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*);
 | 
			
		||||
 | 
			
		||||
  if( nAutoExtension==0 ){
 | 
			
		||||
    /* Common case: early out without every having to acquire a mutex */
 | 
			
		||||
    return SQLITE_OK;
 | 
			
		||||
  }
 | 
			
		||||
  for(i=0; go; i++){
 | 
			
		||||
    char *zErrmsg = 0;
 | 
			
		||||
    sqlite3OsEnterMutex();
 | 
			
		||||
    if( 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 */
 | 
			
		||||
@@ -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; j<db->nDb; 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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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 <windows.h>
 | 
			
		||||
# 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 <os2.h>
 | 
			
		||||
# 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
 | 
			
		||||
  /*
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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 && n<pPager->pageSize ){
 | 
			
		||||
@@ -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->pgno<pB->pgno ){
 | 
			
		||||
      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; i<N_SORT_BUCKET-1; i++){
 | 
			
		||||
      if( a[i]==0 ){
 | 
			
		||||
        a[i] = p;
 | 
			
		||||
        break;
 | 
			
		||||
      }else{
 | 
			
		||||
        p = merge_pagelist(a[i], p);
 | 
			
		||||
        a[i] = 0;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if( i==N_SORT_BUCKET-1 ){
 | 
			
		||||
      a[i] = merge_pagelist(a[i], p);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  p = a[0];
 | 
			
		||||
  for(i=1; i<N_SORT_BUCKET; i++){
 | 
			
		||||
    p = merge_pagelist(p, a[i]);
 | 
			
		||||
  }
 | 
			
		||||
  return p;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
** Given a list of pages (connected by the PgHdr.pDirty pointer) write
 | 
			
		||||
** every one of those pages out to the database file and mark them all
 | 
			
		||||
@@ -2256,6 +2364,7 @@ static int pager_write_pagelist(PgHdr *pList){
 | 
			
		||||
    return rc;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  pList = sort_pagelist(pList);
 | 
			
		||||
  while( pList ){
 | 
			
		||||
    assert( pList->dirty );
 | 
			
		||||
    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->nPage<pPager->mxPage || 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->origDbSize<pPager->dbSize ){
 | 
			
		||||
      /* 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);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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*);
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -482,12 +482,17 @@ void sqlite3Pragma(
 | 
			
		||||
      sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "pk", P3_STATIC);
 | 
			
		||||
      sqlite3ViewGetColumnNames(pParse, pTab);
 | 
			
		||||
      for(i=0, pCol=pTab->aCol; i<pTab->nCol; 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; i<db->nDb; 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
 | 
			
		||||
 | 
			
		||||
  {}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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 && iDb<db->nDb );
 | 
			
		||||
  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 */
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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.
 | 
			
		||||
 
 | 
			
		||||
@@ -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; j<pList->nId; 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; j<i; j++){
 | 
			
		||||
      if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){
 | 
			
		||||
        zName = sqlite3MPrintf("%s:%d", zBasename, ++cnt);
 | 
			
		||||
        zName[nName] = 0;
 | 
			
		||||
        zName = sqlite3MPrintf("%z:%d", zName, ++cnt);
 | 
			
		||||
        j = -1;
 | 
			
		||||
        if( zName==0 ) break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if( zBasename!=zName ){
 | 
			
		||||
      sqliteFree(zBasename);
 | 
			
		||||
    }
 | 
			
		||||
    pCol->zName = 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( nSetP2<sizeof(aSetP2)/sizeof(aSetP2[0]) );
 | 
			
		||||
    aSetP2[nSetP2++] = sqlite3VdbeAddOp(v, OP_OpenVirtual, iParm, 0);
 | 
			
		||||
    aSetP2[nSetP2++] = sqlite3VdbeAddOp(v, OP_OpenEphemeral, iParm, 0);
 | 
			
		||||
    eDest = SRT_Table;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -1711,14 +1712,14 @@ static int multiSelect(
 | 
			
		||||
          rc = 1;
 | 
			
		||||
          goto multi_select_end;
 | 
			
		||||
        }
 | 
			
		||||
        addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, unionTab, 0);
 | 
			
		||||
        addr = sqlite3VdbeAddOp(v, OP_OpenEphemeral, unionTab, 0);
 | 
			
		||||
        if( priorOp==SRT_Table ){
 | 
			
		||||
          assert( nSetP2<sizeof(aSetP2)/sizeof(aSetP2[0]) );
 | 
			
		||||
          aSetP2[nSetP2++] = addr;
 | 
			
		||||
        }else{
 | 
			
		||||
          assert( p->addrOpenVirt[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; i<nOrderByExpr; i++, pOTerm++, apColl++, pSortOrder++){
 | 
			
		||||
        Expr *pExpr = pOTerm->pExpr;
 | 
			
		||||
        char *zName = pOTerm->zName;
 | 
			
		||||
        assert( pExpr->op==TK_COLUMN && pExpr->iColumn<nCol );
 | 
			
		||||
        if( zName ){
 | 
			
		||||
          *apColl = sqlite3LocateCollSeq(pParse, zName, -1);
 | 
			
		||||
        if( (pExpr->flags & 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; i<pOrderBy->nExpr; 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; i<pList->nExpr; i++){
 | 
			
		||||
    sqlite3PrintExpr(pList->a[i].pExpr);
 | 
			
		||||
    if( i<pList->nExpr-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; i<p->pSrc->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( i<p->pSrc->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) */
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@
 | 
			
		||||
#include "sqlite3.h"
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
 | 
			
		||||
#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__)
 | 
			
		||||
#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__) && !defined(__OS2__)
 | 
			
		||||
# include <signal.h>
 | 
			
		||||
# include <pwd.h>
 | 
			
		||||
# include <unistd.h>
 | 
			
		||||
@@ -37,6 +37,10 @@
 | 
			
		||||
# include <Folders.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __OS2__
 | 
			
		||||
# include <unistd.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(HAVE_READLINE) && HAVE_READLINE==1
 | 
			
		||||
# include <readline/readline.h>
 | 
			
		||||
# include <readline/history.h>
 | 
			
		||||
@@ -48,9 +52,25 @@
 | 
			
		||||
# define stifle_history(X)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(_WIN32) || defined(WIN32)
 | 
			
		||||
# include <io.h>
 | 
			
		||||
#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; i<nArg; i++){
 | 
			
		||||
        int len = strlen(azCol[i]);
 | 
			
		||||
        int len = strlen(azCol[i] ? azCol[i] : "");
 | 
			
		||||
        if( len>w ) w = len;
 | 
			
		||||
      }
 | 
			
		||||
      if( p->cnt++>0 ) fprintf(p->out,"\n");
 | 
			
		||||
      for(i=0; i<nArg; i++){
 | 
			
		||||
        fprintf(p->out,"%*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; i<nArg; i++){
 | 
			
		||||
          output_c_string(p->out,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; i<nArg; i++){
 | 
			
		||||
          output_csv(p, azCol[i], i<nArg-1);
 | 
			
		||||
          output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
 | 
			
		||||
        }
 | 
			
		||||
        fprintf(p->out,"\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<argc-1; i++){
 | 
			
		||||
    char *z;
 | 
			
		||||
    if( argv[i][0]!='-' ) break;
 | 
			
		||||
    z = argv[i];
 | 
			
		||||
    if( z[0]=='-' && z[1]=='-' ) z++;
 | 
			
		||||
    if( strcmp(argv[i],"-separator")==0 || strcmp(argv[i],"-nullvalue")==0 ){
 | 
			
		||||
      i++;
 | 
			
		||||
    }else if( strcmp(argv[i],"-init")==0 ){
 | 
			
		||||
      i++;
 | 
			
		||||
      zInitFile = argv[i];
 | 
			
		||||
    }else if( strcmp(argv[i],"-key")==0 ){
 | 
			
		||||
      i++;
 | 
			
		||||
      data.zKey = sqlite3_mprintf("%s",argv[i]);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if( i<argc ){
 | 
			
		||||
@@ -1712,7 +1856,8 @@ int main(int argc, char **argv){
 | 
			
		||||
  */
 | 
			
		||||
  for(i=1; i<argc && argv[i][0]=='-'; i++){
 | 
			
		||||
    char *z = argv[i];
 | 
			
		||||
    if( strcmp(z,"-init")==0 || strcmp(z,"-key")==0 ){
 | 
			
		||||
    if( z[1]=='-' ){ z++; }
 | 
			
		||||
    if( strcmp(z,"-init")==0 ){
 | 
			
		||||
      i++;
 | 
			
		||||
    }else if( strcmp(z,"-html")==0 ){
 | 
			
		||||
      data.mode = MODE_Html;
 | 
			
		||||
@@ -1722,6 +1867,9 @@ int main(int argc, char **argv){
 | 
			
		||||
      data.mode = MODE_Line;
 | 
			
		||||
    }else if( strcmp(z,"-column")==0 ){
 | 
			
		||||
      data.mode = MODE_Column;
 | 
			
		||||
    }else if( strcmp(z,"-csv")==0 ){
 | 
			
		||||
      data.mode = MODE_Csv;
 | 
			
		||||
      strcpy(data.separator,",");
 | 
			
		||||
    }else if( strcmp(z,"-separator")==0 ){
 | 
			
		||||
      i++;
 | 
			
		||||
      sprintf(data.separator,"%.*s",(int)sizeof(data.separator)-1,argv[i]);
 | 
			
		||||
@@ -1734,10 +1882,16 @@ int main(int argc, char **argv){
 | 
			
		||||
      data.showHeader = 0;
 | 
			
		||||
    }else if( strcmp(z,"-echo")==0 ){
 | 
			
		||||
      data.echoOn = 1;
 | 
			
		||||
    }else if( strcmp(z,"-bail")==0 ){
 | 
			
		||||
      bail_on_error = 1;
 | 
			
		||||
    }else if( strcmp(z,"-version")==0 ){
 | 
			
		||||
      printf("%s\n", sqlite3_libversion());
 | 
			
		||||
      return 1;
 | 
			
		||||
    }else if( strcmp(z,"-help")==0 ){
 | 
			
		||||
      return 0;
 | 
			
		||||
    }else if( strcmp(z,"-interactive")==0 ){
 | 
			
		||||
      stdin_is_interactive = 1;
 | 
			
		||||
    }else if( strcmp(z,"-batch")==0 ){
 | 
			
		||||
      stdin_is_interactive = 0;
 | 
			
		||||
    }else if( strcmp(z,"-help")==0 || strcmp(z, "--help")==0 ){
 | 
			
		||||
      usage(1);
 | 
			
		||||
    }else{
 | 
			
		||||
      fprintf(stderr,"%s: unknown option: %s\n", Argv0, z);
 | 
			
		||||
@@ -1764,7 +1918,7 @@ int main(int argc, char **argv){
 | 
			
		||||
  }else{
 | 
			
		||||
    /* Run commands received from standard input
 | 
			
		||||
    */
 | 
			
		||||
    if( isatty(fileno(stdout)) && isatty(fileno(stdin)) ){
 | 
			
		||||
    if( stdin_is_interactive ){
 | 
			
		||||
      char *zHome;
 | 
			
		||||
      char *zHistory = 0;
 | 
			
		||||
      printf(
 | 
			
		||||
@@ -1779,16 +1933,22 @@ int main(int argc, char **argv){
 | 
			
		||||
#if defined(HAVE_READLINE) && HAVE_READLINE==1
 | 
			
		||||
      if( zHistory ) read_history(zHistory);
 | 
			
		||||
#endif
 | 
			
		||||
      process_input(&data, 0);
 | 
			
		||||
      rc = process_input(&data, 0);
 | 
			
		||||
      if( zHistory ){
 | 
			
		||||
        stifle_history(100);
 | 
			
		||||
        write_history(zHistory);
 | 
			
		||||
        free(zHistory);
 | 
			
		||||
      }
 | 
			
		||||
      free(zHome);
 | 
			
		||||
    }else{
 | 
			
		||||
      process_input(&data, stdin);
 | 
			
		||||
      rc = process_input(&data, stdin);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  set_table_name(&data, 0);
 | 
			
		||||
  if( db ) sqlite3_close(db);
 | 
			
		||||
  return 0;
 | 
			
		||||
  if( db ){
 | 
			
		||||
    if( sqlite3_close(db)!=SQLITE_OK ){
 | 
			
		||||
      fprintf(stderr,"error closing database: %s\n", sqlite3_errmsg(db));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,101 +0,0 @@
 | 
			
		||||
EXPORTS
 | 
			
		||||
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_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_decltype
 | 
			
		||||
sqlite3_column_decltype16
 | 
			
		||||
sqlite3_column_double
 | 
			
		||||
sqlite3_column_int
 | 
			
		||||
sqlite3_column_int64
 | 
			
		||||
sqlite3_column_name
 | 
			
		||||
sqlite3_column_name16
 | 
			
		||||
sqlite3_column_text
 | 
			
		||||
sqlite3_column_text16
 | 
			
		||||
sqlite3_column_type
 | 
			
		||||
sqlite3_commit_hook
 | 
			
		||||
sqlite3_complete
 | 
			
		||||
sqlite3_complete16
 | 
			
		||||
sqlite3_create_collation
 | 
			
		||||
sqlite3_create_collation16
 | 
			
		||||
sqlite3_create_function
 | 
			
		||||
sqlite3_create_function16
 | 
			
		||||
sqlite3_data_count
 | 
			
		||||
sqlite3_db_handle
 | 
			
		||||
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
 | 
			
		||||
sqlite3_global_recover
 | 
			
		||||
sqlite3_interrupt
 | 
			
		||||
sqlite3_last_insert_rowid
 | 
			
		||||
sqlite3_libversion
 | 
			
		||||
sqlite3_libversion_number
 | 
			
		||||
sqlite3_mprintf
 | 
			
		||||
sqlite3_open
 | 
			
		||||
sqlite3_open16
 | 
			
		||||
sqlite3_prepare
 | 
			
		||||
sqlite3_prepare16
 | 
			
		||||
sqlite3_progress_handler
 | 
			
		||||
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_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_text
 | 
			
		||||
sqlite3_value_text16
 | 
			
		||||
sqlite3_value_text16be
 | 
			
		||||
sqlite3_value_text16le
 | 
			
		||||
sqlite3_value_type
 | 
			
		||||
sqlite3_vmprintf
 | 
			
		||||
@@ -31,7 +31,7 @@ extern "C" {
 | 
			
		||||
#ifdef SQLITE_VERSION
 | 
			
		||||
# undef SQLITE_VERSION
 | 
			
		||||
#endif
 | 
			
		||||
#define SQLITE_VERSION         "3.3.5"
 | 
			
		||||
#define SQLITE_VERSION         "3.3.13"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
** The format of the version string is "X.Y.Z<trailing string>", 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.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										282
									
								
								dlls/sqlite/sqlite-source/sqlite3ext.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										282
									
								
								dlls/sqlite/sqlite-source/sqlite3ext.h
									
									
									
									
									
										Normal file
									
								
							@@ -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_ */
 | 
			
		||||
@@ -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<<N) set if column N or pTab is used */
 | 
			
		||||
@@ -1087,6 +1140,19 @@ struct SrcList {
 | 
			
		||||
** structure contains a single instance of this structure.  This structure
 | 
			
		||||
** is intended to be private the the where.c module and should not be
 | 
			
		||||
** access or modified by other modules.
 | 
			
		||||
**
 | 
			
		||||
** The pIdxInfo and pBestIdx fields are used to help pick the best
 | 
			
		||||
** index on a virtual table.  The pIdxInfo pointer contains indexing
 | 
			
		||||
** information for the i-th table in the FROM clause before reordering.
 | 
			
		||||
** All the pIdxInfo pointers are freed by whereInfoFree() in where.c.
 | 
			
		||||
** The pBestIdx pointer is a copy of pIdxInfo for the i-th table after
 | 
			
		||||
** FROM clause ordering.  This is a little confusing so I will repeat
 | 
			
		||||
** it in different words.  WhereInfo.a[i].pIdxInfo is index information 
 | 
			
		||||
** for WhereInfo.pTabList.a[i].  WhereInfo.a[i].pBestInfo is the
 | 
			
		||||
** index information for the i-th loop of the join.  pBestInfo is always
 | 
			
		||||
** either NULL or a copy of some pIdxInfo.  So for cleanup it is 
 | 
			
		||||
** sufficient to free all of the pIdxInfo pointers.
 | 
			
		||||
** 
 | 
			
		||||
*/
 | 
			
		||||
struct WhereLevel {
 | 
			
		||||
  int iFrom;            /* Which entry in the FROM clause */
 | 
			
		||||
@@ -1103,6 +1169,13 @@ struct WhereLevel {
 | 
			
		||||
  int nEq;              /* Number of == or IN constraints on this loop */
 | 
			
		||||
  int nIn;              /* Number of IN operators constraining this loop */
 | 
			
		||||
  int *aInLoop;         /* Loop terminators for IN operators */
 | 
			
		||||
  sqlite3_index_info *pBestIdx;  /* Index information for this level */
 | 
			
		||||
 | 
			
		||||
  /* The following field is really not part of the current level.  But
 | 
			
		||||
  ** we need a place to cache index information for each table in the
 | 
			
		||||
  ** FROM clause and the WhereLevel structure is a convenient place.
 | 
			
		||||
  */
 | 
			
		||||
  sqlite3_index_info *pIdxInfo;  /* Index info for n-th source table */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -1119,6 +1192,7 @@ struct WhereInfo {
 | 
			
		||||
  int iContinue;       /* Jump here to continue with next record */
 | 
			
		||||
  int iBreak;          /* Jump here to break out of the loop */
 | 
			
		||||
  int nLevel;          /* Number of nested loop */
 | 
			
		||||
  sqlite3_index_info **apInfo;  /* Array of pointers to index info structures */
 | 
			
		||||
  WhereLevel a[1];     /* Information about each nest loop in the WHERE */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -1167,14 +1241,14 @@ struct NameContext {
 | 
			
		||||
** offset).  But later on, nLimit and nOffset become the memory locations
 | 
			
		||||
** in the VDBE that record the limit and offset counters.
 | 
			
		||||
**
 | 
			
		||||
** addrOpenVirt[] entries contain the address of OP_OpenVirtual opcodes.
 | 
			
		||||
** addrOpenEphm[] entries contain the address of OP_OpenEphemeral opcodes.
 | 
			
		||||
** These addresses must be stored so that we can go back and fill in
 | 
			
		||||
** the P3_KEYINFO and P2 parameters later.  Neither the KeyInfo nor
 | 
			
		||||
** the number of columns in P2 can be computed at the same time
 | 
			
		||||
** as the OP_OpenVirtual instruction is coded because not
 | 
			
		||||
** as the OP_OpenEphm instruction is coded because not
 | 
			
		||||
** enough information about the compound query is known at that point.
 | 
			
		||||
** The KeyInfo for addrOpenVirt[0] and [1] contains collating sequences
 | 
			
		||||
** for the result set.  The KeyInfo for addrOpenVirt[2] contains collating
 | 
			
		||||
** The KeyInfo for addrOpenTran[0] and [1] contains collating sequences
 | 
			
		||||
** for the result set.  The KeyInfo for addrOpenTran[2] contains collating
 | 
			
		||||
** sequences for the ORDER BY clause.
 | 
			
		||||
*/
 | 
			
		||||
struct Select {
 | 
			
		||||
@@ -1183,7 +1257,7 @@ struct Select {
 | 
			
		||||
  u8 isDistinct;         /* True if the DISTINCT keyword is present */
 | 
			
		||||
  u8 isResolved;         /* True once sqlite3SelectResolve() has run. */
 | 
			
		||||
  u8 isAgg;              /* True if this is an aggregate query */
 | 
			
		||||
  u8 usesVirt;           /* True if uses an OpenVirtual opcode */
 | 
			
		||||
  u8 usesEphm;           /* True if uses an OpenEphemeral opcode */
 | 
			
		||||
  u8 disallowOrderBy;    /* Do not allow an ORDER BY to be attached if TRUE */
 | 
			
		||||
  SrcList *pSrc;         /* The FROM clause */
 | 
			
		||||
  Expr *pWhere;          /* The WHERE clause */
 | 
			
		||||
@@ -1195,7 +1269,7 @@ struct Select {
 | 
			
		||||
  Expr *pLimit;          /* LIMIT expression. NULL means not used. */
 | 
			
		||||
  Expr *pOffset;         /* OFFSET expression. NULL means not used. */
 | 
			
		||||
  int iLimit, iOffset;   /* Memory registers holding LIMIT & OFFSET counters */
 | 
			
		||||
  int addrOpenVirt[3];   /* OP_OpenVirtual opcodes related to this select */
 | 
			
		||||
  int addrOpenEphm[3];   /* OP_OpenEphem opcodes related to this select */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -1212,7 +1286,7 @@ struct Select {
 | 
			
		||||
#define SRT_Mem          5  /* Store result in a memory cell */
 | 
			
		||||
#define SRT_Set          6  /* Store non-null results as keys in an index */
 | 
			
		||||
#define SRT_Table        7  /* Store result as data with an automatic rowid */
 | 
			
		||||
#define SRT_VirtualTab   8  /* Create virtual table and store like SRT_Table */
 | 
			
		||||
#define SRT_EphemTab     8  /* Create transient tab and store like SRT_Table */
 | 
			
		||||
#define SRT_Subroutine   9  /* Call a subroutine to handle results */
 | 
			
		||||
#define SRT_Exists      10  /* Store 1 if the result is not empty */
 | 
			
		||||
 | 
			
		||||
@@ -1241,6 +1315,7 @@ struct Parse {
 | 
			
		||||
  u8 nameClash;        /* A permanent table name clashes with temp table name */
 | 
			
		||||
  u8 checkSchema;      /* Causes schema cookie check after an error */
 | 
			
		||||
  u8 nested;           /* Number of nested calls to the parser/code generator */
 | 
			
		||||
  u8 parseError;       /* True if a parsing error has been seen */
 | 
			
		||||
  int nErr;            /* Number of errors seen */
 | 
			
		||||
  int nTab;            /* Number of previously allocated VDBE cursors */
 | 
			
		||||
  int nMem;            /* Number of memory cells used so far */
 | 
			
		||||
@@ -1272,8 +1347,19 @@ struct Parse {
 | 
			
		||||
  Trigger *pNewTrigger;     /* Trigger under construct by a CREATE TRIGGER */
 | 
			
		||||
  TriggerStack *trigStack;  /* Trigger actions being coded */
 | 
			
		||||
  const char *zAuthContext; /* The 6th parameter to db->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
 | 
			
		||||
 
 | 
			
		||||
@@ -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; i<nCol; i++){
 | 
			
		||||
      if( colv[i]==0 ){
 | 
			
		||||
        z = 0;
 | 
			
		||||
        z = sqlite3_mprintf("");
 | 
			
		||||
      }else{
 | 
			
		||||
        z = malloc( strlen(colv[i])+1 );
 | 
			
		||||
        if( z==0 ) goto malloc_failed;
 | 
			
		||||
        strcpy(z, colv[i]);
 | 
			
		||||
        z = sqlite3_mprintf("%s", colv[i]);
 | 
			
		||||
      }
 | 
			
		||||
      p->azResult[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<n; i++){ if( azResult[i] ) free(azResult[i]); }
 | 
			
		||||
    free(azResult);
 | 
			
		||||
    n = (int)azResult[0];
 | 
			
		||||
    for(i=1; i<n; i++){ if( azResult[i] ) sqlite3_free(azResult[i]); }
 | 
			
		||||
    sqlite3_free(azResult);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,14 @@
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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; i<argc; i++){
 | 
			
		||||
 
 | 
			
		||||
@@ -285,6 +285,10 @@ static int getToken(const unsigned char *z, int *tokenType){
 | 
			
		||||
        *tokenType = TK_FLOAT;
 | 
			
		||||
      }
 | 
			
		||||
#endif
 | 
			
		||||
      while( IdChar(z[i]) ){
 | 
			
		||||
        *tokenType = TK_ILLEGAL;
 | 
			
		||||
        i++;
 | 
			
		||||
      }
 | 
			
		||||
      return i;
 | 
			
		||||
    }
 | 
			
		||||
    case '[': {
 | 
			
		||||
@@ -390,14 +394,16 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
 | 
			
		||||
  int tokenType;
 | 
			
		||||
  int lastTokenParsed = -1;
 | 
			
		||||
  sqlite3 *db = pParse->db;
 | 
			
		||||
  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) ){
 | 
			
		||||
 
 | 
			
		||||
@@ -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: {
 | 
			
		||||
 
 | 
			
		||||
@@ -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; i<pTab->nCol; 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; i<pTab->nCol; 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 */
 | 
			
		||||
 
 | 
			
		||||
@@ -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++){
 | 
			
		||||
 
 | 
			
		||||
@@ -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; i<n; i+=2){
 | 
			
		||||
    zBlob[i/2] = (hexToInt(z[i])<<4) | hexToInt(z[i+1]);
 | 
			
		||||
  if( zBlob ){
 | 
			
		||||
    for(i=0; i<n; i+=2){
 | 
			
		||||
      zBlob[i/2] = (hexToInt(z[i])<<4) | hexToInt(z[i+1]);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return zBlob;
 | 
			
		||||
}
 | 
			
		||||
@@ -1443,7 +1446,7 @@ int sqlite3ApiExit(sqlite3* db, int rc){
 | 
			
		||||
    sqlite3Error(db, SQLITE_NOMEM, 0);
 | 
			
		||||
    rc = SQLITE_NOMEM;
 | 
			
		||||
  }
 | 
			
		||||
  return rc;
 | 
			
		||||
  return rc & (db ? db->errMask : 0xff);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 
 | 
			
		||||
 
 | 
			
		||||
@@ -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 */
 | 
			
		||||
 
 | 
			
		||||
@@ -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( iCur<p->nCursor );
 | 
			
		||||
  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; i<p->nOp; 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 && pc<p->nOp );
 | 
			
		||||
    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; i<cnt; i++, pTerm++){
 | 
			
		||||
    if( pTerm->flags & 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 && i<p->nCursor ){
 | 
			
		||||
    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 && i<p->nCursor );
 | 
			
		||||
  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(; k<n && i>0; 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 && iDb<db->nDb );
 | 
			
		||||
  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 && j<p->nMem );
 | 
			
		||||
  pnErr = &p->aMem[j];
 | 
			
		||||
  assert( (pnErr->flags & MEM_Int)!=0 );
 | 
			
		||||
  for(j=0; j<nRoot; j++){
 | 
			
		||||
    Mem *pMem = &pTos[-j];
 | 
			
		||||
    aRoot[j] = (int)pMem->i;
 | 
			
		||||
@@ -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; i<nArg; i++){
 | 
			
		||||
      apArg[i] = &pTos[i+1-2-nArg];
 | 
			
		||||
      storeTypeInfo(apArg[i], 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
 | 
			
		||||
    p->inVtabMethod = 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; i<nArg; i++, pX++){
 | 
			
		||||
      storeTypeInfo(pX, 0);
 | 
			
		||||
      apArg[i] = pX;
 | 
			
		||||
    }
 | 
			
		||||
    if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
 | 
			
		||||
    sqlite3VtabLock(pVtab);
 | 
			
		||||
    rc = pModule->xUpdate(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 && pc<p->nOp );
 | 
			
		||||
@@ -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{
 | 
			
		||||
 
 | 
			
		||||
@@ -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*, ...);
 | 
			
		||||
 
 | 
			
		||||
@@ -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_) */
 | 
			
		||||
 
 | 
			
		||||
@@ -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)<SQLITE_ROW ){
 | 
			
		||||
    /* This behavior occurs if sqlite3_prepare_v2() was used to build
 | 
			
		||||
    ** the prepared statement.  Return error codes directly */
 | 
			
		||||
    return p->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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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( nStack<p->nOp );
 | 
			
		||||
    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; i<p->nOp; 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; i<p->nCursor; 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; i<db->nDb; 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; i<db->nDb; i++){ 
 | 
			
		||||
    for(i=0; rc==SQLITE_OK && i<db->nDb; 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, i<nField ? pKeyInfo->aColl[i] : 0);
 | 
			
		||||
    if( mem1.flags & MEM_Dyn ) sqlite3VdbeMemRelease(&mem1);
 | 
			
		||||
    if( mem2.flags & MEM_Dyn ) sqlite3VdbeMemRelease(&mem2);
 | 
			
		||||
 
 | 
			
		||||
@@ -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) );
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										693
									
								
								dlls/sqlite/sqlite-source/vtab.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										693
									
								
								dlls/sqlite/sqlite-source/vtab.c
									
									
									
									
									
										Normal file
									
								
							@@ -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; i<p->nModuleArg; 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; j<i; j++){
 | 
			
		||||
      sqliteFree(pTable->azModuleArg[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; i<db->nVTrans && 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 && i<db->nVTrans && 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; (i<db->nVTrans) && 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 */
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user