Browse Source

Update sqlite3

mingodad 7 years ago
parent
commit
5dd4386888
2 changed files with 253 additions and 74 deletions
  1. 213 69
      SquiLu-ext/sqlite3.c
  2. 40 5
      SquiLu-ext/sqlite3.h

+ 213 - 69
SquiLu-ext/sqlite3.c

@@ -1149,7 +1149,7 @@ extern "C" {
 */
 */
 #define SQLITE_VERSION        "3.23.0"
 #define SQLITE_VERSION        "3.23.0"
 #define SQLITE_VERSION_NUMBER 3023000
 #define SQLITE_VERSION_NUMBER 3023000
-#define SQLITE_SOURCE_ID      "2018-03-24 23:16:05 ccf734f7d2bf8f99f3c55124b05c1835e4371bc269f27700f40afc26e7c1alt1"
+#define SQLITE_SOURCE_ID      "2018-04-09 00:46:42 43c2c60caf0ba105f57e32fc7fe6938dc29538c04d477a35b9b8bba2fb8falt1"
 
 
 /*
 /*
 ** CAPI3REF: Run-Time Library Version Numbers
 ** CAPI3REF: Run-Time Library Version Numbers
@@ -2090,6 +2090,12 @@ struct sqlite3_io_methods {
 ** so that all subsequent write operations are independent.
 ** so that all subsequent write operations are independent.
 ** ^SQLite will never invoke SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE without
 ** ^SQLite will never invoke SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE without
 ** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE].
 ** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE].
+**
+** <li>[[SQLITE_FCNTL_LOCK_TIMEOUT]]
+** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode causes attempts to obtain
+** a file lock using the xLock or xShmLock methods of the VFS to wait
+** for up to M milliseconds before failing, where M is the single 
+** unsigned integer parameter.
 ** </ul>
 ** </ul>
 */
 */
 #define SQLITE_FCNTL_LOCKSTATE               1
 #define SQLITE_FCNTL_LOCKSTATE               1
@@ -2124,6 +2130,7 @@ struct sqlite3_io_methods {
 #define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE     31
 #define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE     31
 #define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE    32
 #define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE    32
 #define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE  33
 #define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE  33
+#define SQLITE_FCNTL_LOCK_TIMEOUT           34
 
 
 /* deprecated names */
 /* deprecated names */
 #define SQLITE_GET_LOCKPROXYFILE      SQLITE_FCNTL_GET_LOCKPROXYFILE
 #define SQLITE_GET_LOCKPROXYFILE      SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -13470,9 +13477,10 @@ typedef INT16_TYPE LogEst;
 */
 */
 typedef struct BusyHandler BusyHandler;
 typedef struct BusyHandler BusyHandler;
 struct BusyHandler {
 struct BusyHandler {
-  int (*xFunc)(void *,int);  /* The busy callback */
-  void *pArg;                /* First arg to busy callback */
-  int nBusy;                 /* Incremented with each busy call */
+  int (*xBusyHandler)(void *,int);  /* The busy callback */
+  void *pBusyArg;                   /* First arg to busy callback */
+  int nBusy;                        /* Incremented with each busy call */
+  u8 bExtraFileArg;                 /* Include sqlite3_file as callback arg */
 };
 };
 
 
 /*
 /*
@@ -14681,7 +14689,7 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3*);
 SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
 SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
 
 
 /* Functions used to configure a Pager object. */
 /* Functions used to configure a Pager object. */
-SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *);
+SQLITE_PRIVATE void sqlite3PagerSetBusyHandler(Pager*, int(*)(void *), void *);
 SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int);
 SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int);
 #ifdef SQLITE_HAS_CODEC
 #ifdef SQLITE_HAS_CODEC
 SQLITE_PRIVATE void sqlite3PagerAlignReserve(Pager*,Pager*);
 SQLITE_PRIVATE void sqlite3PagerAlignReserve(Pager*,Pager*);
@@ -14767,6 +14775,11 @@ SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*);
 SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *);
 SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *);
 SQLITE_PRIVATE void sqlite3PagerClearCache(Pager*);
 SQLITE_PRIVATE void sqlite3PagerClearCache(Pager*);
 SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *);
 SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *);
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+SQLITE_PRIVATE void sqlite3PagerResetLockTimeout(Pager *pPager);
+#else
+# define sqlite3PagerResetLockTimeout(X)
+#endif
 
 
 /* Functions used to truncate the database file. */
 /* Functions used to truncate the database file. */
 SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno);
 SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno);
@@ -18327,7 +18340,7 @@ SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
 SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
 SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
 SQLITE_PRIVATE char sqlite3AffinityType(const char*, u8*);
 SQLITE_PRIVATE char sqlite3AffinityType(const char*, u8*);
 SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*);
 SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*);
-SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*);
+SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*, sqlite3_file*);
 SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*);
 SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*);
 SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *);
 SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *);
 SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB);
 SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB);
@@ -21298,7 +21311,9 @@ SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){
 */
 */
 SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
 SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
 #ifdef SQLITE_TEST
 #ifdef SQLITE_TEST
-  if( op!=SQLITE_FCNTL_COMMIT_PHASETWO ){
+  if( op!=SQLITE_FCNTL_COMMIT_PHASETWO
+   && op!=SQLITE_FCNTL_LOCK_TIMEOUT
+  ){
     /* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite
     /* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite
     ** is using a regular VFS, it is called after the corresponding
     ** is using a regular VFS, it is called after the corresponding
     ** transaction has been committed. Injecting a fault at this point
     ** transaction has been committed. Injecting a fault at this point
@@ -21312,10 +21327,11 @@ SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
     DO_OS_MALLOC_TEST(id);
     DO_OS_MALLOC_TEST(id);
   }
   }
 #endif
 #endif
+  if( id->pMethods==0 ) return SQLITE_NOTFOUND;
   return id->pMethods->xFileControl(id, op, pArg);
   return id->pMethods->xFileControl(id, op, pArg);
 }
 }
 SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){
 SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){
-  (void)id->pMethods->xFileControl(id, op, pArg);
+  if( id->pMethods ) (void)id->pMethods->xFileControl(id, op, pArg);
 }
 }
 
 
 SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id){
 SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id){
@@ -31384,6 +31400,9 @@ struct unixFile {
 #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__)
 #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__)
   unsigned fsFlags;                   /* cached details from statfs() */
   unsigned fsFlags;                   /* cached details from statfs() */
 #endif
 #endif
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+  unsigned iBusyTimeout;              /* Wait this many millisec on locks */
+#endif
 #if OS_VXWORKS
 #if OS_VXWORKS
   struct vxworksFileId *pId;          /* Unique file ID */
   struct vxworksFileId *pId;          /* Unique file ID */
 #endif
 #endif
@@ -32818,6 +32837,43 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
   return rc;
   return rc;
 }
 }
 
 
+/*
+** Set a posix-advisory-lock.
+**
+** There are two versions of this routine.  If compiled with
+** SQLITE_ENABLE_SETLK_TIMEOUT then the routine has an extra parameter
+** which is a pointer to a unixFile.  If the unixFile->iBusyTimeout
+** value is set, then it is the number of milliseconds to wait before
+** failing the lock.  The iBusyTimeout value is always reset back to
+** zero on each call.
+**
+** If SQLITE_ENABLE_SETLK_TIMEOUT is not defined, then do a non-blocking
+** attempt to set the lock.
+*/
+#ifndef SQLITE_ENABLE_SETLK_TIMEOUT
+# define osSetPosixAdvisoryLock(h,x,t) osFcntl(h,F_SETLK,x)
+#else
+static int osSetPosixAdvisoryLock(
+  int h,                /* The file descriptor on which to take the lock */
+  struct flock *pLock,  /* The description of the lock */
+  unixFile *pFile       /* Structure holding timeout value */
+){
+  int rc = osFcntl(h,F_SETLK,pLock);
+  while( rc<0 && pFile->iBusyTimeout>0 ){
+    /* On systems that support some kind of blocking file lock with a timeout,
+    ** make appropriate changes here to invoke that blocking file lock.  On
+    ** generic posix, however, there is no such API.  So we simply try the
+    ** lock once every millisecond until either the timeout expires, or until
+    ** the lock is obtained. */
+    usleep(1000);
+    rc = osFcntl(h,F_SETLK,pLock);
+    pFile->iBusyTimeout--;
+  }
+  return rc;
+}
+#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */
+
+
 /*
 /*
 ** Attempt to set a system-lock on the file pFile.  The lock is 
 ** Attempt to set a system-lock on the file pFile.  The lock is 
 ** described by pLock.
 ** described by pLock.
@@ -32850,7 +32906,7 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){
       lock.l_start = SHARED_FIRST;
       lock.l_start = SHARED_FIRST;
       lock.l_len = SHARED_SIZE;
       lock.l_len = SHARED_SIZE;
       lock.l_type = F_WRLCK;
       lock.l_type = F_WRLCK;
-      rc = osFcntl(pFile->h, F_SETLK, &lock);
+      rc = osSetPosixAdvisoryLock(pFile->h, &lock, pFile);
       if( rc<0 ) return rc;
       if( rc<0 ) return rc;
       pInode->bProcessLock = 1;
       pInode->bProcessLock = 1;
       pInode->nLock++;
       pInode->nLock++;
@@ -32858,7 +32914,7 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){
       rc = 0;
       rc = 0;
     }
     }
   }else{
   }else{
-    rc = osFcntl(pFile->h, F_SETLK, pLock);
+    rc = osSetPosixAdvisoryLock(pFile->h, pLock, pFile);
   }
   }
   return rc;
   return rc;
 }
 }
@@ -35218,6 +35274,12 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
       *(int*)pArg = fileHasMoved(pFile);
       *(int*)pArg = fileHasMoved(pFile);
       return SQLITE_OK;
       return SQLITE_OK;
     }
     }
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+    case SQLITE_FCNTL_LOCK_TIMEOUT: {
+      pFile->iBusyTimeout = *(int*)pArg;
+      return SQLITE_OK;
+    }
+#endif
 #if SQLITE_MAX_MMAP_SIZE>0
 #if SQLITE_MAX_MMAP_SIZE>0
     case SQLITE_FCNTL_MMAP_SIZE: {
     case SQLITE_FCNTL_MMAP_SIZE: {
       i64 newLimit = *(i64*)pArg;
       i64 newLimit = *(i64*)pArg;
@@ -35537,7 +35599,7 @@ static int unixShmSystemLock(
     f.l_whence = SEEK_SET;
     f.l_whence = SEEK_SET;
     f.l_start = ofst;
     f.l_start = ofst;
     f.l_len = n;
     f.l_len = n;
-    rc = osFcntl(pShmNode->h, F_SETLK, &f);
+    rc = osSetPosixAdvisoryLock(pShmNode->h, &f, pFile);
     rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
     rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
   }
   }
 
 
@@ -45397,7 +45459,7 @@ SQLITE_API int sqlite3_os_end(void){
 **
 **
 ******************************************************************************
 ******************************************************************************
 **
 **
-** This file implements in-memory VFS.  A database is held as a contiguous
+** This file implements an in-memory VFS. A database is held as a contiguous
 ** block of memory.
 ** block of memory.
 **
 **
 ** This file also implements interface sqlite3_serialize() and
 ** This file also implements interface sqlite3_serialize() and
@@ -51317,7 +51379,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
     rc = pager_truncate(pPager, pPager->dbSize);
     rc = pager_truncate(pPager, pPager->dbSize);
   }
   }
 
 
-  if( rc==SQLITE_OK && bCommit && isOpen(pPager->fd) ){
+  if( rc==SQLITE_OK && bCommit ){
     rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_COMMIT_PHASETWO, 0);
     rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_COMMIT_PHASETWO, 0);
     if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
     if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
   }
   }
@@ -52136,9 +52198,7 @@ end_playback:
   ** assertion that the transaction counter was modified.
   ** assertion that the transaction counter was modified.
   */
   */
 #ifdef SQLITE_DEBUG
 #ifdef SQLITE_DEBUG
-  if( pPager->fd->pMethods ){
-    sqlite3OsFileControlHint(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0);
-  }
+  sqlite3OsFileControlHint(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0);
 #endif
 #endif
 
 
   /* If this playback is happening automatically as a result of an IO or 
   /* If this playback is happening automatically as a result of an IO or 
@@ -52891,20 +52951,18 @@ static int pagerOpentemp(
 ** retried. If it returns zero, then the SQLITE_BUSY error is
 ** retried. If it returns zero, then the SQLITE_BUSY error is
 ** returned to the caller of the pager API function.
 ** returned to the caller of the pager API function.
 */
 */
-SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(
+SQLITE_PRIVATE void sqlite3PagerSetBusyHandler(
   Pager *pPager,                       /* Pager object */
   Pager *pPager,                       /* Pager object */
   int (*xBusyHandler)(void *),         /* Pointer to busy-handler function */
   int (*xBusyHandler)(void *),         /* Pointer to busy-handler function */
   void *pBusyHandlerArg                /* Argument to pass to xBusyHandler */
   void *pBusyHandlerArg                /* Argument to pass to xBusyHandler */
 ){
 ){
+  void **ap;
   pPager->xBusyHandler = xBusyHandler;
   pPager->xBusyHandler = xBusyHandler;
   pPager->pBusyHandlerArg = pBusyHandlerArg;
   pPager->pBusyHandlerArg = pBusyHandlerArg;
-
-  if( isOpen(pPager->fd) ){
-    void **ap = (void **)&pPager->xBusyHandler;
-    assert( ((int(*)(void *))(ap[0]))==xBusyHandler );
-    assert( ap[1]==pBusyHandlerArg );
-    sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap);
-  }
+  ap = (void **)&pPager->xBusyHandler;
+  assert( ((int(*)(void *))(ap[0]))==xBusyHandler );
+  assert( ap[1]==pBusyHandlerArg );
+  sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap);
 }
 }
 
 
 /*
 /*
@@ -54880,6 +54938,7 @@ SQLITE_PRIVATE void sqlite3PagerUnrefPageOne(DbPage *pPg){
   assert( pPg->pgno==1 );
   assert( pPg->pgno==1 );
   assert( (pPg->flags & PGHDR_MMAP)==0 ); /* Page1 is never memory mapped */
   assert( (pPg->flags & PGHDR_MMAP)==0 ); /* Page1 is never memory mapped */
   pPager = pPg->pPager;
   pPager = pPg->pPager;
+  sqlite3PagerResetLockTimeout(pPager);
   sqlite3PcacheRelease(pPg);
   sqlite3PcacheRelease(pPg);
   pagerUnlockIfUnused(pPager);
   pagerUnlockIfUnused(pPager);
 }
 }
@@ -55475,12 +55534,9 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
 */
 */
 SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zMaster){
 SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zMaster){
   int rc = SQLITE_OK;
   int rc = SQLITE_OK;
-
-  if( isOpen(pPager->fd) ){
-    void *pArg = (void*)zMaster;
-    rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, pArg);
-    if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
-  }
+  void *pArg = (void*)zMaster;
+  rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, pArg);
+  if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
   if( rc==SQLITE_OK && !pPager->noSync ){
   if( rc==SQLITE_OK && !pPager->noSync ){
     assert( !MEMDB );
     assert( !MEMDB );
     rc = sqlite3OsSync(pPager->fd, pPager->syncFlags);
     rc = sqlite3OsSync(pPager->fd, pPager->syncFlags);
@@ -56157,6 +56213,16 @@ SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){
   return pPager->fd;
   return pPager->fd;
 }
 }
 
 
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+/*
+** Reset the lock timeout for pager.
+*/
+SQLITE_PRIVATE void sqlite3PagerResetLockTimeout(Pager *pPager){
+  int x = 0;
+  sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_LOCK_TIMEOUT, &x);
+}
+#endif
+
 /*
 /*
 ** Return the file handle for the journal file (if it exists).
 ** Return the file handle for the journal file (if it exists).
 ** This will be either the rollback journal or the WAL file.
 ** This will be either the rollback journal or the WAL file.
@@ -56617,6 +56683,7 @@ SQLITE_PRIVATE int sqlite3PagerCheckpoint(
         pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
         pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
         pnLog, pnCkpt
         pnLog, pnCkpt
     );
     );
+    sqlite3PagerResetLockTimeout(pPager);
   }
   }
   return rc;
   return rc;
 }
 }
@@ -63893,7 +63960,8 @@ static int btreeInvokeBusyHandler(void *pArg){
   BtShared *pBt = (BtShared*)pArg;
   BtShared *pBt = (BtShared*)pArg;
   assert( pBt->db );
   assert( pBt->db );
   assert( sqlite3_mutex_held(pBt->db->mutex) );
   assert( sqlite3_mutex_held(pBt->db->mutex) );
-  return sqlite3InvokeBusyHandler(&pBt->db->busyHandler);
+  return sqlite3InvokeBusyHandler(&pBt->db->busyHandler,
+                                  sqlite3PagerFile(pBt->pPager));
 }
 }
 
 
 /*
 /*
@@ -64071,7 +64139,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
     }
     }
     pBt->openFlags = (u8)flags;
     pBt->openFlags = (u8)flags;
     pBt->db = db;
     pBt->db = db;
-    sqlite3PagerSetBusyhandler(pBt->pPager, btreeInvokeBusyHandler, pBt);
+    sqlite3PagerSetBusyHandler(pBt->pPager, btreeInvokeBusyHandler, pBt);
     p->pBt = pBt;
     p->pBt = pBt;
   
   
     pBt->pCursor = 0;
     pBt->pCursor = 0;
@@ -65034,6 +65102,7 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
     }
     }
   }while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE &&
   }while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE &&
           btreeInvokeBusyHandler(pBt) );
           btreeInvokeBusyHandler(pBt) );
+  sqlite3PagerResetLockTimeout(pBt->pPager);
 
 
   if( rc==SQLITE_OK ){
   if( rc==SQLITE_OK ){
     if( p->inTrans==TRANS_NONE ){
     if( p->inTrans==TRANS_NONE ){
@@ -99110,6 +99179,27 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
         return WRC_Abort;
         return WRC_Abort;
       }
       }
       return WRC_Prune;
       return WRC_Prune;
+
+    /* Virtual tables are allowed to use constraints like x=NULL.  So
+    ** a term of the form x=y does not prove that y is not null if x
+    ** is the column of a virtual table */
+    case TK_EQ:
+    case TK_NE:
+    case TK_LT:
+    case TK_LE:
+    case TK_GT:
+    case TK_GE:
+      testcase( pExpr->op==TK_EQ );
+      testcase( pExpr->op==TK_NE );
+      testcase( pExpr->op==TK_LT );
+      testcase( pExpr->op==TK_LE );
+      testcase( pExpr->op==TK_GT );
+      testcase( pExpr->op==TK_GE );
+      if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->pTab))
+       || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->pTab))
+      ){
+       return WRC_Prune;
+      }
     default:
     default:
       return WRC_Continue;
       return WRC_Continue;
   }
   }
@@ -104454,7 +104544,7 @@ SQLITE_PRIVATE void sqlite3AddDefaultValue(
           pCol->zName);
           pCol->zName);
     }else{
     }else{
       /* A copy of pExpr is used instead of the original, as pExpr contains
       /* A copy of pExpr is used instead of the original, as pExpr contains
-      ** tokens that point to volatile memory.	
+      ** tokens that point to volatile memory.
       */
       */
       Expr x;
       Expr x;
       sqlite3ExprDelete(db, pCol->pDflt);
       sqlite3ExprDelete(db, pCol->pDflt);
@@ -104698,7 +104788,7 @@ SQLITE_PRIVATE void sqlite3ChangeCookie(Parse *pParse, int iDb){
   Vdbe *v = pParse->pVdbe;
   Vdbe *v = pParse->pVdbe;
   assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
   assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
   sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION, 
   sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION, 
-                    db->aDb[iDb].pSchema->schema_cookie+1);
+                   (int)(1+(unsigned)db->aDb[iDb].pSchema->schema_cookie));
 }
 }
 
 
 /*
 /*
@@ -105376,7 +105466,7 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
   int nErr = 0;     /* Number of errors encountered */
   int nErr = 0;     /* Number of errors encountered */
   int n;            /* Temporarily holds the number of cursors assigned */
   int n;            /* Temporarily holds the number of cursors assigned */
   sqlite3 *db = pParse->db;  /* Database connection for malloc errors */
   sqlite3 *db = pParse->db;  /* Database connection for malloc errors */
-#ifndef SQLITE_OMIT_VIRTUALTABLE	
+#ifndef SQLITE_OMIT_VIRTUALTABLE
   int rc;
   int rc;
 #endif
 #endif
 #ifndef SQLITE_OMIT_AUTHORIZATION
 #ifndef SQLITE_OMIT_AUTHORIZATION
@@ -124174,7 +124264,6 @@ static int flattenSubquery(
         pOrderBy->a[i].u.x.iOrderByCol = 0;
         pOrderBy->a[i].u.x.iOrderByCol = 0;
       }
       }
       assert( pParent->pOrderBy==0 );
       assert( pParent->pOrderBy==0 );
-      assert( pSub->pPrior==0 );
       pParent->pOrderBy = pOrderBy;
       pParent->pOrderBy = pOrderBy;
       pSub->pOrderBy = 0;
       pSub->pOrderBy = 0;
     }
     }
@@ -124258,8 +124347,9 @@ static int flattenSubquery(
 **   (3) The inner query has a LIMIT clause (since the changes to the WHERE
 **   (3) The inner query has a LIMIT clause (since the changes to the WHERE
 **       close would change the meaning of the LIMIT).
 **       close would change the meaning of the LIMIT).
 **
 **
-**   (4) (** This restriction was removed on 2018-03-21.  It used to read:
-**       The inner query is the right operand of a LEFT JOIN. **)
+**   (4) The inner query is the right operand of a LEFT JOIN and the
+**       expression to be pushed down does not come from the ON clause
+**       on that LEFT JOIN.
 **
 **
 **   (5) The WHERE clause expression originates in the ON or USING clause
 **   (5) The WHERE clause expression originates in the ON or USING clause
 **       of a LEFT JOIN where iCursor is not the right-hand table of that
 **       of a LEFT JOIN where iCursor is not the right-hand table of that
@@ -124281,7 +124371,8 @@ static int pushDownWhereTerms(
   Parse *pParse,        /* Parse context (for malloc() and error reporting) */
   Parse *pParse,        /* Parse context (for malloc() and error reporting) */
   Select *pSubq,        /* The subquery whose WHERE clause is to be augmented */
   Select *pSubq,        /* The subquery whose WHERE clause is to be augmented */
   Expr *pWhere,         /* The WHERE clause of the outer query */
   Expr *pWhere,         /* The WHERE clause of the outer query */
-  int iCursor           /* Cursor number of the subquery */
+  int iCursor,          /* Cursor number of the subquery */
+  int isLeftJoin        /* True if pSubq is the right term of a LEFT JOIN */
 ){
 ){
   Expr *pNew;
   Expr *pNew;
   int nChng = 0;
   int nChng = 0;
@@ -124305,9 +124396,16 @@ static int pushDownWhereTerms(
     return 0; /* restriction (3) */
     return 0; /* restriction (3) */
   }
   }
   while( pWhere->op==TK_AND ){
   while( pWhere->op==TK_AND ){
-    nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, iCursor);
+    nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight,
+                                iCursor, isLeftJoin);
     pWhere = pWhere->pLeft;
     pWhere = pWhere->pLeft;
   }
   }
+  if( isLeftJoin
+   && (ExprHasProperty(pWhere,EP_FromJoin)==0
+         || pWhere->iRightJoinTable!=iCursor)
+  ){
+    return 0; /* restriction (4) */
+  }
   if( ExprHasProperty(pWhere,EP_FromJoin) && pWhere->iRightJoinTable!=iCursor ){
   if( ExprHasProperty(pWhere,EP_FromJoin) && pWhere->iRightJoinTable!=iCursor ){
     return 0; /* restriction (5) */
     return 0; /* restriction (5) */
   }
   }
@@ -125775,7 +125873,8 @@ SQLITE_PRIVATE int sqlite3Select(
     ** inside the subquery.  This can help the subquery to run more efficiently.
     ** inside the subquery.  This can help the subquery to run more efficiently.
     */
     */
     if( OptimizationEnabled(db, SQLITE_PushDown)
     if( OptimizationEnabled(db, SQLITE_PushDown)
-     && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor)
+     && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor,
+                           (pItem->fg.jointype & JT_OUTER)!=0)
     ){
     ){
 #if SELECTTRACE_ENABLED
 #if SELECTTRACE_ENABLED
       if( sqlite3SelectTrace & 0x100 ){
       if( sqlite3SelectTrace & 0x100 ){
@@ -128243,7 +128342,7 @@ SQLITE_PRIVATE void sqlite3Update(
     regKey = ++pParse->nMem;
     regKey = ++pParse->nMem;
     iEph = pParse->nTab++;
     iEph = pParse->nTab++;
 
 
-    sqlite3VdbeAddOp2(v, OP_Null, 0, iPk);
+    sqlite3VdbeAddOp3(v, OP_Null, 0, iPk, iPk+nPk-1);
     addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk);
     addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk);
     sqlite3VdbeSetP4KeyInfo(pParse, pPk);
     sqlite3VdbeSetP4KeyInfo(pParse, pPk);
   }
   }
@@ -130415,7 +130514,7 @@ SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){
 ** Trace output macros
 ** Trace output macros
 */
 */
 #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
 #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
-/***/ int sqlite3WhereTrace;
+/***/ extern int sqlite3WhereTrace;
 #endif
 #endif
 #if defined(SQLITE_DEBUG) \
 #if defined(SQLITE_DEBUG) \
     && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
     && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
@@ -133064,7 +133163,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
         continue;
         continue;
       }
       }
 
 
-      if( pTerm->wtFlags & TERM_LIKECOND ){
+      if( (pTerm->wtFlags & TERM_LIKECOND)!=0 ){
         /* If the TERM_LIKECOND flag is set, that means that the range search
         /* If the TERM_LIKECOND flag is set, that means that the range search
         ** is sufficient to guarantee that the LIKE operator is true, so we
         ** is sufficient to guarantee that the LIKE operator is true, so we
         ** can skip the call to the like(A,B) function.  But this only works
         ** can skip the call to the like(A,B) function.  But this only works
@@ -133074,8 +133173,9 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
         continue;
         continue;
 #else
 #else
         u32 x = pLevel->iLikeRepCntr;
         u32 x = pLevel->iLikeRepCntr;
-        assert( x>0 );
-        skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)?OP_IfNot:OP_If, (int)(x>>1));
+        if( x>0 ){
+          skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)?OP_IfNot:OP_If,(int)(x>>1));
+        }
         VdbeCoverage(v);
         VdbeCoverage(v);
 #endif
 #endif
       }
       }
@@ -146658,21 +146758,40 @@ SQLITE_PRIVATE const char *sqlite3ErrStr(int rc){
 ** again until a timeout value is reached.  The timeout value is
 ** again until a timeout value is reached.  The timeout value is
 ** an integer number of milliseconds passed in as the first
 ** an integer number of milliseconds passed in as the first
 ** argument.
 ** argument.
+**
+** Return non-zero to retry the lock.  Return zero to stop trying
+** and cause SQLite to return SQLITE_BUSY.
 */
 */
 static int sqliteDefaultBusyCallback(
 static int sqliteDefaultBusyCallback(
- void *ptr,               /* Database connection */
- int count                /* Number of times table has been busy */
+  void *ptr,               /* Database connection */
+  int count,               /* Number of times table has been busy */
+  sqlite3_file *pFile      /* The file on which the lock occurred */
 ){
 ){
 #if SQLITE_OS_WIN || HAVE_USLEEP
 #if SQLITE_OS_WIN || HAVE_USLEEP
+  /* This case is for systems that have support for sleeping for fractions of
+  ** a second.  Examples:  All windows systems, unix systems with usleep() */
   static const u8 delays[] =
   static const u8 delays[] =
      { 1, 2, 5, 10, 15, 20, 25, 25,  25,  50,  50, 100 };
      { 1, 2, 5, 10, 15, 20, 25, 25,  25,  50,  50, 100 };
   static const u8 totals[] =
   static const u8 totals[] =
      { 0, 1, 3,  8, 18, 33, 53, 78, 103, 128, 178, 228 };
      { 0, 1, 3,  8, 18, 33, 53, 78, 103, 128, 178, 228 };
 # define NDELAY ArraySize(delays)
 # define NDELAY ArraySize(delays)
   sqlite3 *db = (sqlite3 *)ptr;
   sqlite3 *db = (sqlite3 *)ptr;
-  int timeout = db->busyTimeout;
+  int tmout = db->busyTimeout;
   int delay, prior;
   int delay, prior;
 
 
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+  if( sqlite3OsFileControl(pFile,SQLITE_FCNTL_LOCK_TIMEOUT,&tmout)==SQLITE_OK ){
+    if( count ){
+      tmout = 0;
+      sqlite3OsFileControl(pFile, SQLITE_FCNTL_LOCK_TIMEOUT, &tmout);
+      return 0;
+    }else{
+      return 1;
+    }
+  }
+#else
+  UNUSED_PARAMETER(pFile);
+#endif
   assert( count>=0 );
   assert( count>=0 );
   if( count < NDELAY ){
   if( count < NDELAY ){
     delay = delays[count];
     delay = delays[count];
@@ -146681,16 +146800,19 @@ static int sqliteDefaultBusyCallback(
     delay = delays[NDELAY-1];
     delay = delays[NDELAY-1];
     prior = totals[NDELAY-1] + delay*(count-(NDELAY-1));
     prior = totals[NDELAY-1] + delay*(count-(NDELAY-1));
   }
   }
-  if( prior + delay > timeout ){
-    delay = timeout - prior;
+  if( prior + delay > tmout ){
+    delay = tmout - prior;
     if( delay<=0 ) return 0;
     if( delay<=0 ) return 0;
   }
   }
   sqlite3OsSleep(db->pVfs, delay*1000);
   sqlite3OsSleep(db->pVfs, delay*1000);
   return 1;
   return 1;
 #else
 #else
+  /* This case for unix systems that lack usleep() support.  Sleeping
+  ** must be done in increments of whole seconds */
   sqlite3 *db = (sqlite3 *)ptr;
   sqlite3 *db = (sqlite3 *)ptr;
-  int timeout = ((sqlite3 *)ptr)->busyTimeout;
-  if( (count+1)*1000 > timeout ){
+  int tmout = ((sqlite3 *)ptr)->busyTimeout;
+  UNUSED_PARAMETER(pFile);
+  if( (count+1)*1000 > tmout ){
     return 0;
     return 0;
   }
   }
   sqlite3OsSleep(db->pVfs, 1000000);
   sqlite3OsSleep(db->pVfs, 1000000);
@@ -146701,14 +146823,25 @@ static int sqliteDefaultBusyCallback(
 /*
 /*
 ** Invoke the given busy handler.
 ** Invoke the given busy handler.
 **
 **
-** This routine is called when an operation failed with a lock.
+** This routine is called when an operation failed to acquire a
+** lock on VFS file pFile.
+**
 ** If this routine returns non-zero, the lock is retried.  If it
 ** If this routine returns non-zero, the lock is retried.  If it
 ** returns 0, the operation aborts with an SQLITE_BUSY error.
 ** returns 0, the operation aborts with an SQLITE_BUSY error.
 */
 */
-SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p){
+SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p, sqlite3_file *pFile){
   int rc;
   int rc;
-  if( NEVER(p==0) || p->xFunc==0 || p->nBusy<0 ) return 0;
-  rc = p->xFunc(p->pArg, p->nBusy);
+  if( p->xBusyHandler==0 || p->nBusy<0 ) return 0;
+  if( p->bExtraFileArg ){
+    /* Add an extra parameter with the pFile pointer to the end of the
+    ** callback argument list */
+    int (*xTra)(void*,int,sqlite3_file*);
+    xTra = (int(*)(void*,int,sqlite3_file*))p->xBusyHandler;
+    rc = xTra(p->pBusyArg, p->nBusy, pFile);
+  }else{
+    /* Legacy style busy handler callback */
+    rc = p->xBusyHandler(p->pBusyArg, p->nBusy);
+  }
   if( rc==0 ){
   if( rc==0 ){
     p->nBusy = -1;
     p->nBusy = -1;
   }else{
   }else{
@@ -146730,9 +146863,10 @@ SQLITE_API int sqlite3_busy_handler(
   if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
   if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
 #endif
 #endif
   sqlite3_mutex_enter(db->mutex);
   sqlite3_mutex_enter(db->mutex);
-  db->busyHandler.xFunc = xBusy;
-  db->busyHandler.pArg = pArg;
+  db->busyHandler.xBusyHandler = xBusy;
+  db->busyHandler.pBusyArg = pArg;
   db->busyHandler.nBusy = 0;
   db->busyHandler.nBusy = 0;
+  db->busyHandler.bExtraFileArg = 0;
   db->busyTimeout = 0;
   db->busyTimeout = 0;
   sqlite3_mutex_leave(db->mutex);
   sqlite3_mutex_leave(db->mutex);
   return SQLITE_OK;
   return SQLITE_OK;
@@ -146780,8 +146914,10 @@ SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){
   if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
   if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
 #endif
 #endif
   if( ms>0 ){
   if( ms>0 ){
-    sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db);
+    sqlite3_busy_handler(db, (int(*)(void*,int))sqliteDefaultBusyCallback,
+                             (void*)db);
     db->busyTimeout = ms;
     db->busyTimeout = ms;
+    db->busyHandler.bExtraFileArg = 1;
   }else{
   }else{
     sqlite3_busy_handler(db, 0, 0);
     sqlite3_busy_handler(db, 0, 0);
   }
   }
@@ -148821,10 +148957,8 @@ SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, vo
     }else if( op==SQLITE_FCNTL_JOURNAL_POINTER ){
     }else if( op==SQLITE_FCNTL_JOURNAL_POINTER ){
       *(sqlite3_file**)pArg = sqlite3PagerJrnlFile(pPager);
       *(sqlite3_file**)pArg = sqlite3PagerJrnlFile(pPager);
       rc = SQLITE_OK;
       rc = SQLITE_OK;
-    }else if( fd->pMethods ){
-      rc = sqlite3OsFileControl(fd, op, pArg);
     }else{
     }else{
-      rc = SQLITE_NOTFOUND;
+      rc = sqlite3OsFileControl(fd, op, pArg);
     }
     }
     sqlite3BtreeLeave(pBtree);
     sqlite3BtreeLeave(pBtree);
   }
   }
@@ -181366,7 +181500,7 @@ static void statSizeAndOffset(StatCursor *pCsr){
   */
   */
   fd = sqlite3PagerFile(pPager);
   fd = sqlite3PagerFile(pPager);
   x[0] = pCsr->iPageno;
   x[0] = pCsr->iPageno;
-  if( fd->pMethods!=0 && sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){
+  if( sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){
     pCsr->iOffset = x[0];
     pCsr->iOffset = x[0];
     pCsr->szPage = (int)x[1];
     pCsr->szPage = (int)x[1];
   }
   }
@@ -182132,7 +182266,7 @@ struct SessionBuffer {
 **  sqlite3changeset_start_strm()).
 **  sqlite3changeset_start_strm()).
 */
 */
 struct SessionInput {
 struct SessionInput {
-  int bNoDiscard;                 /* If true, discard no data */
+  int bNoDiscard;                 /* If true, do not discard in InputBuffer() */
   int iCurrent;                   /* Offset in aData[] of current change */
   int iCurrent;                   /* Offset in aData[] of current change */
   int iNext;                      /* Offset in aData[] of next change */
   int iNext;                      /* Offset in aData[] of next change */
   u8 *aData;                      /* Pointer to buffer containing changeset */
   u8 *aData;                      /* Pointer to buffer containing changeset */
@@ -184657,7 +184791,7 @@ SQLITE_API int sqlite3changeset_start_strm(
 ** object and the buffer is full, discard some data to free up space.
 ** object and the buffer is full, discard some data to free up space.
 */
 */
 static void sessionDiscardData(SessionInput *pIn){
 static void sessionDiscardData(SessionInput *pIn){
-  if( pIn->bEof && pIn->xInput && pIn->iNext>=SESSIONS_STRM_CHUNK_SIZE ){
+  if( pIn->xInput && pIn->iNext>=SESSIONS_STRM_CHUNK_SIZE ){
     int nMove = pIn->buf.nBuf - pIn->iNext;
     int nMove = pIn->buf.nBuf - pIn->iNext;
     assert( nMove>=0 );
     assert( nMove>=0 );
     if( nMove>0 ){
     if( nMove>0 ){
@@ -207249,7 +207383,7 @@ static void fts5SourceIdFunc(
 ){
 ){
   assert( nArg==0 );
   assert( nArg==0 );
   UNUSED_PARAM2(nArg, apUnused);
   UNUSED_PARAM2(nArg, apUnused);
-  sqlite3_result_text(pCtx, "fts5: 2018-03-08 19:56:52 0798c91aa9d5d347680a9d80d420224297360e03341365d48aca829cd7c423db", -1, SQLITE_TRANSIENT);
+  sqlite3_result_text(pCtx, "fts5: 2018-04-06 19:12:55 602fbd8149b53d8f0e9a223cc1aec912e7df03fca35071e8d707776ce225371c", -1, SQLITE_TRANSIENT);
 }
 }
 
 
 static int fts5Init(sqlite3 *db){
 static int fts5Init(sqlite3 *db){
@@ -217202,6 +217336,15 @@ static int seriesFilter(
   }else{
   }else{
     pCur->iStep = 1;
     pCur->iStep = 1;
   }
   }
+  for(i=0; i<argc; i++){
+    if( sqlite3_value_type(argv[i])==SQLITE_NULL ){
+      /* If any of the constraints have a NULL value, then return no rows.
+      ** See ticket https://www.sqlite.org/src/info/fac496b61722daf2 */
+      pCur->mnValue = 1;
+      pCur->mxValue = 0;
+      break;
+    }
+  }
   if( idxNum & 8 ){
   if( idxNum & 8 ){
     pCur->isDesc = 1;
     pCur->isDesc = 1;
     pCur->iValue = pCur->mxValue;
     pCur->iValue = pCur->mxValue;
@@ -217383,6 +217526,7 @@ struct EvalResult {
 static int callback(void *pCtx, int argc, char **argv, char **colnames){
 static int callback(void *pCtx, int argc, char **argv, char **colnames){
   struct EvalResult *p = (struct EvalResult*)pCtx;
   struct EvalResult *p = (struct EvalResult*)pCtx;
   int i; 
   int i; 
+  if( argv==0 ) return 0;
   for(i=0; i<argc; i++){
   for(i=0; i<argc; i++){
     const char *z = argv[i] ? argv[i] : "";
     const char *z = argv[i] ? argv[i] : "";
     size_t sz = strlen(z);
     size_t sz = strlen(z);
@@ -221178,9 +221322,9 @@ static void print_elem(void *e, sqlite_int64 c, void* p){
 #endif
 #endif
 
 
 /************** End of extension-functions.c *********************************/
 /************** End of extension-functions.c *********************************/
-#if __LINE__!=221181
+#if __LINE__!=221325
 #undef SQLITE_SOURCE_ID
 #undef SQLITE_SOURCE_ID
-#define SQLITE_SOURCE_ID      "2018-03-24 23:16:05 ccf734f7d2bf8f99f3c55124b05c1835e4371bc269f27700f40afc26e7c1alt2"
+#define SQLITE_SOURCE_ID      "2018-04-09 00:46:42 43c2c60caf0ba105f57e32fc7fe6938dc29538c04d477a35b9b8bba2fb8falt2"
 #endif
 #endif
 /* Return the source-id for this library */
 /* Return the source-id for this library */
 SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
 SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }

+ 40 - 5
SquiLu-ext/sqlite3.h

@@ -123,9 +123,9 @@ extern "C" {
 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
 ** [sqlite_version()] and [sqlite_source_id()].
 ** [sqlite_version()] and [sqlite_source_id()].
 */
 */
-#define SQLITE_VERSION        "3.23.0"
-#define SQLITE_VERSION_NUMBER 3023000
-#define SQLITE_SOURCE_ID      "2018-03-24 23:16:05 ccf734f7d2bf8f99f3c55124b05c1835e4371bc269f27700f40afc26e7c1alt1"
+#define SQLITE_VERSION        "3.23.1"
+#define SQLITE_VERSION_NUMBER 3023001
+#define SQLITE_SOURCE_ID      "2018-04-10 18:56:21 56e4965f7ac850c59596120878434f5ef023e77919ef9416d20812eac764alt1"
 
 
 /*
 /*
 ** CAPI3REF: Run-Time Library Version Numbers
 ** CAPI3REF: Run-Time Library Version Numbers
@@ -1066,6 +1066,12 @@ struct sqlite3_io_methods {
 ** so that all subsequent write operations are independent.
 ** so that all subsequent write operations are independent.
 ** ^SQLite will never invoke SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE without
 ** ^SQLite will never invoke SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE without
 ** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE].
 ** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE].
+**
+** <li>[[SQLITE_FCNTL_LOCK_TIMEOUT]]
+** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode causes attempts to obtain
+** a file lock using the xLock or xShmLock methods of the VFS to wait
+** for up to M milliseconds before failing, where M is the single 
+** unsigned integer parameter.
 ** </ul>
 ** </ul>
 */
 */
 #define SQLITE_FCNTL_LOCKSTATE               1
 #define SQLITE_FCNTL_LOCKSTATE               1
@@ -1100,6 +1106,7 @@ struct sqlite3_io_methods {
 #define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE     31
 #define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE     31
 #define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE    32
 #define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE    32
 #define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE  33
 #define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE  33
+#define SQLITE_FCNTL_LOCK_TIMEOUT           34
 
 
 /* deprecated names */
 /* deprecated names */
 #define SQLITE_GET_LOCKPROXYFILE      SQLITE_FCNTL_GET_LOCKPROXYFILE
 #define SQLITE_GET_LOCKPROXYFILE      SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -10119,6 +10126,13 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*);
 ** is only allocated and populated if one or more conflicts were encountered
 ** is only allocated and populated if one or more conflicts were encountered
 ** while applying the patchset. See comments surrounding the sqlite3_rebaser
 ** while applying the patchset. See comments surrounding the sqlite3_rebaser
 ** APIs for further details.
 ** APIs for further details.
+**
+** The behavior of sqlite3changeset_apply_v2() and its streaming equivalent
+** may be modified by passing a combination of
+** [SQLITE_CHANGESETAPPLY_NOSAVEPOINT | supported flags] as the 9th parameter.
+**
+** Note that the sqlite3changeset_apply_v2() API is still <b>experimental</b>
+** and therefore subject to change.
 */
 */
 SQLITE_API int sqlite3changeset_apply(
 SQLITE_API int sqlite3changeset_apply(
   sqlite3 *db,                    /* Apply change to "main" db of this handle */
   sqlite3 *db,                    /* Apply change to "main" db of this handle */
@@ -10149,9 +10163,28 @@ SQLITE_API int sqlite3changeset_apply_v2(
     sqlite3_changeset_iter *p     /* Handle describing change and conflict */
     sqlite3_changeset_iter *p     /* Handle describing change and conflict */
   ),
   ),
   void *pCtx,                     /* First argument passed to xConflict */
   void *pCtx,                     /* First argument passed to xConflict */
-  void **ppRebase, int *pnRebase
+  void **ppRebase, int *pnRebase, /* OUT: Rebase data */
+  int flags                       /* Combination of SESSION_APPLY_* flags */
 );
 );
 
 
+/*
+** CAPI3REF: Flags for sqlite3changeset_apply_v2
+**
+** The following flags may passed via the 9th parameter to
+** [sqlite3changeset_apply_v2] and [sqlite3changeset_apply_v2_strm]:
+**
+** <dl>
+** <dt>SQLITE_CHANGESETAPPLY_NOSAVEPOINT <dd>
+**   Usually, the sessions module encloses all operations performed by
+**   a single call to apply_v2() or apply_v2_strm() in a [SAVEPOINT]. The
+**   SAVEPOINT is committed if the changeset or patchset is successfully
+**   applied, or rolled back if an error occurs. Specifying this flag
+**   causes the sessions module to omit this savepoint. In this case, if the
+**   caller has an open transaction or savepoint when apply_v2() is called, 
+**   it may revert the partially applied changeset by rolling it back.
+*/
+#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT   0x0001
+
 /* 
 /* 
 ** CAPI3REF: Constants Passed To The Conflict Handler
 ** CAPI3REF: Constants Passed To The Conflict Handler
 **
 **
@@ -10412,6 +10445,7 @@ SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p);
 ** <table border=1 style="margin-left:8ex;margin-right:8ex">
 ** <table border=1 style="margin-left:8ex;margin-right:8ex">
 **   <tr><th>Streaming function<th>Non-streaming equivalent</th>
 **   <tr><th>Streaming function<th>Non-streaming equivalent</th>
 **   <tr><td>sqlite3changeset_apply_strm<td>[sqlite3changeset_apply] 
 **   <tr><td>sqlite3changeset_apply_strm<td>[sqlite3changeset_apply] 
+**   <tr><td>sqlite3changeset_apply_strm_v2<td>[sqlite3changeset_apply_v2] 
 **   <tr><td>sqlite3changeset_concat_strm<td>[sqlite3changeset_concat] 
 **   <tr><td>sqlite3changeset_concat_strm<td>[sqlite3changeset_concat] 
 **   <tr><td>sqlite3changeset_invert_strm<td>[sqlite3changeset_invert] 
 **   <tr><td>sqlite3changeset_invert_strm<td>[sqlite3changeset_invert] 
 **   <tr><td>sqlite3changeset_start_strm<td>[sqlite3changeset_start] 
 **   <tr><td>sqlite3changeset_start_strm<td>[sqlite3changeset_start] 
@@ -10521,7 +10555,8 @@ SQLITE_API int sqlite3changeset_apply_v2_strm(
     sqlite3_changeset_iter *p     /* Handle describing change and conflict */
     sqlite3_changeset_iter *p     /* Handle describing change and conflict */
   ),
   ),
   void *pCtx,                     /* First argument passed to xConflict */
   void *pCtx,                     /* First argument passed to xConflict */
-  void **ppRebase, int *pnRebase
+  void **ppRebase, int *pnRebase,
+  int flags
 );
 );
 SQLITE_API int sqlite3changeset_concat_strm(
 SQLITE_API int sqlite3changeset_concat_strm(
   int (*xInputA)(void *pIn, void *pData, int *pnData),
   int (*xInputA)(void *pIn, void *pData, int *pnData),