|
|
@@ -1149,7 +1149,7 @@ extern "C" {
|
|
|
*/
|
|
|
#define SQLITE_VERSION "3.23.0"
|
|
|
#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
|
|
|
@@ -2090,6 +2090,12 @@ struct sqlite3_io_methods {
|
|
|
** so that all subsequent write operations are independent.
|
|
|
** ^SQLite will never invoke SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE without
|
|
|
** 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>
|
|
|
*/
|
|
|
#define SQLITE_FCNTL_LOCKSTATE 1
|
|
|
@@ -2124,6 +2130,7 @@ struct sqlite3_io_methods {
|
|
|
#define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE 31
|
|
|
#define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32
|
|
|
#define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33
|
|
|
+#define SQLITE_FCNTL_LOCK_TIMEOUT 34
|
|
|
|
|
|
/* deprecated names */
|
|
|
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
|
|
|
@@ -13470,9 +13477,10 @@ typedef INT16_TYPE LogEst;
|
|
|
*/
|
|
|
typedef struct BusyHandler 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*);
|
|
|
|
|
|
/* 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);
|
|
|
#ifdef SQLITE_HAS_CODEC
|
|
|
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 sqlite3PagerClearCache(Pager*);
|
|
|
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. */
|
|
|
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 char sqlite3AffinityType(const char*, u8*);
|
|
|
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 sqlite3FindDbName(sqlite3 *, const char *);
|
|
|
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){
|
|
|
#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
|
|
|
** is using a regular VFS, it is called after the corresponding
|
|
|
** 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);
|
|
|
}
|
|
|
#endif
|
|
|
+ if( id->pMethods==0 ) return SQLITE_NOTFOUND;
|
|
|
return id->pMethods->xFileControl(id, op, 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){
|
|
|
@@ -31384,6 +31400,9 @@ struct unixFile {
|
|
|
#if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__)
|
|
|
unsigned fsFlags; /* cached details from statfs() */
|
|
|
#endif
|
|
|
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
|
+ unsigned iBusyTimeout; /* Wait this many millisec on locks */
|
|
|
+#endif
|
|
|
#if OS_VXWORKS
|
|
|
struct vxworksFileId *pId; /* Unique file ID */
|
|
|
#endif
|
|
|
@@ -32818,6 +32837,43 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
|
|
|
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
|
|
|
** described by pLock.
|
|
|
@@ -32850,7 +32906,7 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){
|
|
|
lock.l_start = SHARED_FIRST;
|
|
|
lock.l_len = SHARED_SIZE;
|
|
|
lock.l_type = F_WRLCK;
|
|
|
- rc = osFcntl(pFile->h, F_SETLK, &lock);
|
|
|
+ rc = osSetPosixAdvisoryLock(pFile->h, &lock, pFile);
|
|
|
if( rc<0 ) return rc;
|
|
|
pInode->bProcessLock = 1;
|
|
|
pInode->nLock++;
|
|
|
@@ -32858,7 +32914,7 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){
|
|
|
rc = 0;
|
|
|
}
|
|
|
}else{
|
|
|
- rc = osFcntl(pFile->h, F_SETLK, pLock);
|
|
|
+ rc = osSetPosixAdvisoryLock(pFile->h, pLock, pFile);
|
|
|
}
|
|
|
return rc;
|
|
|
}
|
|
|
@@ -35218,6 +35274,12 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
|
|
|
*(int*)pArg = fileHasMoved(pFile);
|
|
|
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
|
|
|
case SQLITE_FCNTL_MMAP_SIZE: {
|
|
|
i64 newLimit = *(i64*)pArg;
|
|
|
@@ -35537,7 +35599,7 @@ static int unixShmSystemLock(
|
|
|
f.l_whence = SEEK_SET;
|
|
|
f.l_start = ofst;
|
|
|
f.l_len = n;
|
|
|
- rc = osFcntl(pShmNode->h, F_SETLK, &f);
|
|
|
+ rc = osSetPosixAdvisoryLock(pShmNode->h, &f, pFile);
|
|
|
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.
|
|
|
**
|
|
|
** 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);
|
|
|
}
|
|
|
|
|
|
- if( rc==SQLITE_OK && bCommit && isOpen(pPager->fd) ){
|
|
|
+ if( rc==SQLITE_OK && bCommit ){
|
|
|
rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_COMMIT_PHASETWO, 0);
|
|
|
if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
|
|
|
}
|
|
|
@@ -52136,9 +52198,7 @@ end_playback:
|
|
|
** assertion that the transaction counter was modified.
|
|
|
*/
|
|
|
#ifdef SQLITE_DEBUG
|
|
|
- if( pPager->fd->pMethods ){
|
|
|
- sqlite3OsFileControlHint(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0);
|
|
|
- }
|
|
|
+ sqlite3OsFileControlHint(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0);
|
|
|
#endif
|
|
|
|
|
|
/* 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
|
|
|
** returned to the caller of the pager API function.
|
|
|
*/
|
|
|
-SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(
|
|
|
+SQLITE_PRIVATE void sqlite3PagerSetBusyHandler(
|
|
|
Pager *pPager, /* Pager object */
|
|
|
int (*xBusyHandler)(void *), /* Pointer to busy-handler function */
|
|
|
void *pBusyHandlerArg /* Argument to pass to xBusyHandler */
|
|
|
){
|
|
|
+ void **ap;
|
|
|
pPager->xBusyHandler = xBusyHandler;
|
|
|
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->flags & PGHDR_MMAP)==0 ); /* Page1 is never memory mapped */
|
|
|
pPager = pPg->pPager;
|
|
|
+ sqlite3PagerResetLockTimeout(pPager);
|
|
|
sqlite3PcacheRelease(pPg);
|
|
|
pagerUnlockIfUnused(pPager);
|
|
|
}
|
|
|
@@ -55475,12 +55534,9 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
|
|
|
*/
|
|
|
SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zMaster){
|
|
|
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 ){
|
|
|
assert( !MEMDB );
|
|
|
rc = sqlite3OsSync(pPager->fd, pPager->syncFlags);
|
|
|
@@ -56157,6 +56213,16 @@ SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){
|
|
|
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).
|
|
|
** 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,
|
|
|
pnLog, pnCkpt
|
|
|
);
|
|
|
+ sqlite3PagerResetLockTimeout(pPager);
|
|
|
}
|
|
|
return rc;
|
|
|
}
|
|
|
@@ -63893,7 +63960,8 @@ static int btreeInvokeBusyHandler(void *pArg){
|
|
|
BtShared *pBt = (BtShared*)pArg;
|
|
|
assert( pBt->db );
|
|
|
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->db = db;
|
|
|
- sqlite3PagerSetBusyhandler(pBt->pPager, btreeInvokeBusyHandler, pBt);
|
|
|
+ sqlite3PagerSetBusyHandler(pBt->pPager, btreeInvokeBusyHandler, pBt);
|
|
|
p->pBt = pBt;
|
|
|
|
|
|
pBt->pCursor = 0;
|
|
|
@@ -65034,6 +65102,7 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
|
|
|
}
|
|
|
}while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE &&
|
|
|
btreeInvokeBusyHandler(pBt) );
|
|
|
+ sqlite3PagerResetLockTimeout(pBt->pPager);
|
|
|
|
|
|
if( rc==SQLITE_OK ){
|
|
|
if( p->inTrans==TRANS_NONE ){
|
|
|
@@ -99110,6 +99179,27 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
|
|
|
return WRC_Abort;
|
|
|
}
|
|
|
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:
|
|
|
return WRC_Continue;
|
|
|
}
|
|
|
@@ -104454,7 +104544,7 @@ SQLITE_PRIVATE void sqlite3AddDefaultValue(
|
|
|
pCol->zName);
|
|
|
}else{
|
|
|
/* 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;
|
|
|
sqlite3ExprDelete(db, pCol->pDflt);
|
|
|
@@ -104698,7 +104788,7 @@ SQLITE_PRIVATE void sqlite3ChangeCookie(Parse *pParse, int iDb){
|
|
|
Vdbe *v = pParse->pVdbe;
|
|
|
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
|
|
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 n; /* Temporarily holds the number of cursors assigned */
|
|
|
sqlite3 *db = pParse->db; /* Database connection for malloc errors */
|
|
|
-#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
|
+#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
|
int rc;
|
|
|
#endif
|
|
|
#ifndef SQLITE_OMIT_AUTHORIZATION
|
|
|
@@ -124174,7 +124264,6 @@ static int flattenSubquery(
|
|
|
pOrderBy->a[i].u.x.iOrderByCol = 0;
|
|
|
}
|
|
|
assert( pParent->pOrderBy==0 );
|
|
|
- assert( pSub->pPrior==0 );
|
|
|
pParent->pOrderBy = pOrderBy;
|
|
|
pSub->pOrderBy = 0;
|
|
|
}
|
|
|
@@ -124258,8 +124347,9 @@ static int flattenSubquery(
|
|
|
** (3) The inner query has a LIMIT clause (since the changes to the WHERE
|
|
|
** 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
|
|
|
** 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) */
|
|
|
Select *pSubq, /* The subquery whose WHERE clause is to be augmented */
|
|
|
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;
|
|
|
int nChng = 0;
|
|
|
@@ -124305,9 +124396,16 @@ static int pushDownWhereTerms(
|
|
|
return 0; /* restriction (3) */
|
|
|
}
|
|
|
while( pWhere->op==TK_AND ){
|
|
|
- nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, iCursor);
|
|
|
+ nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight,
|
|
|
+ iCursor, isLeftJoin);
|
|
|
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 ){
|
|
|
return 0; /* restriction (5) */
|
|
|
}
|
|
|
@@ -125775,7 +125873,8 @@ SQLITE_PRIVATE int sqlite3Select(
|
|
|
** inside the subquery. This can help the subquery to run more efficiently.
|
|
|
*/
|
|
|
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( sqlite3SelectTrace & 0x100 ){
|
|
|
@@ -128243,7 +128342,7 @@ SQLITE_PRIVATE void sqlite3Update(
|
|
|
regKey = ++pParse->nMem;
|
|
|
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);
|
|
|
sqlite3VdbeSetP4KeyInfo(pParse, pPk);
|
|
|
}
|
|
|
@@ -130415,7 +130514,7 @@ SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){
|
|
|
** Trace output macros
|
|
|
*/
|
|
|
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
|
|
|
-/***/ int sqlite3WhereTrace;
|
|
|
+/***/ extern int sqlite3WhereTrace;
|
|
|
#endif
|
|
|
#if defined(SQLITE_DEBUG) \
|
|
|
&& (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
|
|
|
@@ -133064,7 +133163,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
|
|
|
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
|
|
|
** 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
|
|
|
@@ -133074,8 +133173,9 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
|
|
|
continue;
|
|
|
#else
|
|
|
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);
|
|
|
#endif
|
|
|
}
|
|
|
@@ -146658,21 +146758,40 @@ SQLITE_PRIVATE const char *sqlite3ErrStr(int rc){
|
|
|
** again until a timeout value is reached. The timeout value is
|
|
|
** an integer number of milliseconds passed in as the first
|
|
|
** argument.
|
|
|
+**
|
|
|
+** Return non-zero to retry the lock. Return zero to stop trying
|
|
|
+** and cause SQLite to return SQLITE_BUSY.
|
|
|
*/
|
|
|
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
|
|
|
+ /* 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[] =
|
|
|
{ 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100 };
|
|
|
static const u8 totals[] =
|
|
|
{ 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228 };
|
|
|
# define NDELAY ArraySize(delays)
|
|
|
sqlite3 *db = (sqlite3 *)ptr;
|
|
|
- int timeout = db->busyTimeout;
|
|
|
+ int tmout = db->busyTimeout;
|
|
|
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 );
|
|
|
if( count < NDELAY ){
|
|
|
delay = delays[count];
|
|
|
@@ -146681,16 +146800,19 @@ static int sqliteDefaultBusyCallback(
|
|
|
delay = delays[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;
|
|
|
}
|
|
|
sqlite3OsSleep(db->pVfs, delay*1000);
|
|
|
return 1;
|
|
|
#else
|
|
|
+ /* This case for unix systems that lack usleep() support. Sleeping
|
|
|
+ ** must be done in increments of whole seconds */
|
|
|
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;
|
|
|
}
|
|
|
sqlite3OsSleep(db->pVfs, 1000000);
|
|
|
@@ -146701,14 +146823,25 @@ static int sqliteDefaultBusyCallback(
|
|
|
/*
|
|
|
** 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
|
|
|
** 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;
|
|
|
- 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 ){
|
|
|
p->nBusy = -1;
|
|
|
}else{
|
|
|
@@ -146730,9 +146863,10 @@ SQLITE_API int sqlite3_busy_handler(
|
|
|
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
|
|
|
#endif
|
|
|
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.bExtraFileArg = 0;
|
|
|
db->busyTimeout = 0;
|
|
|
sqlite3_mutex_leave(db->mutex);
|
|
|
return SQLITE_OK;
|
|
|
@@ -146780,8 +146914,10 @@ SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){
|
|
|
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
|
|
|
#endif
|
|
|
if( ms>0 ){
|
|
|
- sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db);
|
|
|
+ sqlite3_busy_handler(db, (int(*)(void*,int))sqliteDefaultBusyCallback,
|
|
|
+ (void*)db);
|
|
|
db->busyTimeout = ms;
|
|
|
+ db->busyHandler.bExtraFileArg = 1;
|
|
|
}else{
|
|
|
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 ){
|
|
|
*(sqlite3_file**)pArg = sqlite3PagerJrnlFile(pPager);
|
|
|
rc = SQLITE_OK;
|
|
|
- }else if( fd->pMethods ){
|
|
|
- rc = sqlite3OsFileControl(fd, op, pArg);
|
|
|
}else{
|
|
|
- rc = SQLITE_NOTFOUND;
|
|
|
+ rc = sqlite3OsFileControl(fd, op, pArg);
|
|
|
}
|
|
|
sqlite3BtreeLeave(pBtree);
|
|
|
}
|
|
|
@@ -181366,7 +181500,7 @@ static void statSizeAndOffset(StatCursor *pCsr){
|
|
|
*/
|
|
|
fd = sqlite3PagerFile(pPager);
|
|
|
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->szPage = (int)x[1];
|
|
|
}
|
|
|
@@ -182132,7 +182266,7 @@ struct SessionBuffer {
|
|
|
** sqlite3changeset_start_strm()).
|
|
|
*/
|
|
|
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 iNext; /* Offset in aData[] of next change */
|
|
|
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.
|
|
|
*/
|
|
|
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;
|
|
|
assert( nMove>=0 );
|
|
|
if( nMove>0 ){
|
|
|
@@ -207249,7 +207383,7 @@ static void fts5SourceIdFunc(
|
|
|
){
|
|
|
assert( nArg==0 );
|
|
|
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){
|
|
|
@@ -217202,6 +217336,15 @@ static int seriesFilter(
|
|
|
}else{
|
|
|
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 ){
|
|
|
pCur->isDesc = 1;
|
|
|
pCur->iValue = pCur->mxValue;
|
|
|
@@ -217383,6 +217526,7 @@ struct EvalResult {
|
|
|
static int callback(void *pCtx, int argc, char **argv, char **colnames){
|
|
|
struct EvalResult *p = (struct EvalResult*)pCtx;
|
|
|
int i;
|
|
|
+ if( argv==0 ) return 0;
|
|
|
for(i=0; i<argc; i++){
|
|
|
const char *z = argv[i] ? argv[i] : "";
|
|
|
size_t sz = strlen(z);
|
|
|
@@ -221178,9 +221322,9 @@ static void print_elem(void *e, sqlite_int64 c, void* p){
|
|
|
#endif
|
|
|
|
|
|
/************** End of extension-functions.c *********************************/
|
|
|
-#if __LINE__!=221181
|
|
|
+#if __LINE__!=221325
|
|
|
#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
|
|
|
/* Return the source-id for this library */
|
|
|
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
|