mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-21 09:00:59 +03:00
Merge the trunk changes for 3.8.6 beta3 into the sessions branch.
FossilOrigin-Name: d49455d9a972fc2224d9beb97165a998ca56e838
This commit is contained in:
@@ -96,6 +96,9 @@ int sqlite3_exec(
|
||||
}
|
||||
}
|
||||
if( xCallback(pArg, nCol, azVals, azCols) ){
|
||||
/* EVIDENCE-OF: R-38229-40159 If the callback function to
|
||||
** sqlite3_exec() returns non-zero, then sqlite3_exec() will
|
||||
** return SQLITE_ABORT. */
|
||||
rc = SQLITE_ABORT;
|
||||
sqlite3VdbeFinalize((Vdbe *)pStmt);
|
||||
pStmt = 0;
|
||||
|
||||
@@ -827,6 +827,8 @@ static int connectionIsBusy(sqlite3 *db){
|
||||
*/
|
||||
static int sqlite3Close(sqlite3 *db, int forceZombie){
|
||||
if( !db ){
|
||||
/* EVIDENCE-OF: R-63257-11740 Calling sqlite3_close() or
|
||||
** sqlite3_close_v2() with a NULL pointer argument is a harmless no-op. */
|
||||
return SQLITE_OK;
|
||||
}
|
||||
if( !sqlite3SafetyCheckSickOrOk(db) ){
|
||||
@@ -1056,7 +1058,7 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){
|
||||
** Return a static string containing the name corresponding to the error code
|
||||
** specified in the argument.
|
||||
*/
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
||||
#if (defined(SQLITE_DEBUG) && SQLITE_OS_WIN) || defined(SQLITE_TEST)
|
||||
const char *sqlite3ErrName(int rc){
|
||||
const char *zName = 0;
|
||||
int i, origRc = rc;
|
||||
@@ -1091,7 +1093,6 @@ const char *sqlite3ErrName(int rc){
|
||||
case SQLITE_IOERR_UNLOCK: zName = "SQLITE_IOERR_UNLOCK"; break;
|
||||
case SQLITE_IOERR_RDLOCK: zName = "SQLITE_IOERR_RDLOCK"; break;
|
||||
case SQLITE_IOERR_DELETE: zName = "SQLITE_IOERR_DELETE"; break;
|
||||
case SQLITE_IOERR_BLOCKED: zName = "SQLITE_IOERR_BLOCKED"; break;
|
||||
case SQLITE_IOERR_NOMEM: zName = "SQLITE_IOERR_NOMEM"; break;
|
||||
case SQLITE_IOERR_ACCESS: zName = "SQLITE_IOERR_ACCESS"; break;
|
||||
case SQLITE_IOERR_CHECKRESERVEDLOCK:
|
||||
@@ -2097,7 +2098,7 @@ static const int aHardLimit[] = {
|
||||
SQLITE_MAX_FUNCTION_ARG,
|
||||
SQLITE_MAX_ATTACHED,
|
||||
SQLITE_MAX_LIKE_PATTERN_LENGTH,
|
||||
SQLITE_MAX_VARIABLE_NUMBER,
|
||||
SQLITE_MAX_VARIABLE_NUMBER, /* IMP: R-38091-32352 */
|
||||
SQLITE_MAX_TRIGGER_DEPTH,
|
||||
};
|
||||
|
||||
|
||||
@@ -94,11 +94,10 @@
|
||||
#include <sys/time.h>
|
||||
#include <errno.h>
|
||||
#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
|
||||
#include <sys/mman.h>
|
||||
# include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
|
||||
#if SQLITE_ENABLE_LOCKING_STYLE
|
||||
#if SQLITE_ENABLE_LOCKING_STYLE || OS_VXWORKS
|
||||
# include <sys/ioctl.h>
|
||||
# if OS_VXWORKS
|
||||
# include <semaphore.h>
|
||||
@@ -318,7 +317,11 @@ static int posixOpen(const char *zFile, int flags, int mode){
|
||||
** we are not running as root.
|
||||
*/
|
||||
static int posixFchown(int fd, uid_t uid, gid_t gid){
|
||||
#if OS_VXWORKS
|
||||
return 0;
|
||||
#else
|
||||
return geteuid() ? 0 : fchown(fd,uid,gid);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Forward reference */
|
||||
@@ -374,7 +377,7 @@ static struct unix_syscall {
|
||||
{ "read", (sqlite3_syscall_ptr)read, 0 },
|
||||
#define osRead ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent)
|
||||
|
||||
#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
|
||||
#if defined(USE_PREAD) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
|
||||
{ "pread", (sqlite3_syscall_ptr)pread, 0 },
|
||||
#else
|
||||
{ "pread", (sqlite3_syscall_ptr)0, 0 },
|
||||
@@ -391,7 +394,7 @@ static struct unix_syscall {
|
||||
{ "write", (sqlite3_syscall_ptr)write, 0 },
|
||||
#define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)
|
||||
|
||||
#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
|
||||
#if defined(USE_PREAD) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
|
||||
{ "pwrite", (sqlite3_syscall_ptr)pwrite, 0 },
|
||||
#else
|
||||
{ "pwrite", (sqlite3_syscall_ptr)0, 0 },
|
||||
@@ -761,16 +764,6 @@ static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
|
||||
case EPERM:
|
||||
return SQLITE_PERM;
|
||||
|
||||
/* EDEADLK is only possible if a call to fcntl(F_SETLKW) is made. And
|
||||
** this module never makes such a call. And the code in SQLite itself
|
||||
** asserts that SQLITE_IOERR_BLOCKED is never returned. For these reasons
|
||||
** this case is also commented out. If the system does set errno to EDEADLK,
|
||||
** the default SQLITE_IOERR_XXX code will be returned. */
|
||||
#if 0
|
||||
case EDEADLK:
|
||||
return SQLITE_IOERR_BLOCKED;
|
||||
#endif
|
||||
|
||||
#if EOPNOTSUPP!=ENOTSUP
|
||||
case EOPNOTSUPP:
|
||||
/* something went terribly awry, unless during file system support
|
||||
@@ -1303,9 +1296,13 @@ static int findInodeInfo(
|
||||
** Return TRUE if pFile has been renamed or unlinked since it was first opened.
|
||||
*/
|
||||
static int fileHasMoved(unixFile *pFile){
|
||||
#if OS_VXWORKS
|
||||
return pFile->pInode!=0 && pFile->pId!=pFile->pInode->fileId.pId;
|
||||
#else
|
||||
struct stat buf;
|
||||
return pFile->pInode!=0 &&
|
||||
(osStat(pFile->zPath, &buf)!=0 || buf.st_ino!=pFile->pInode->fileId.ino);
|
||||
(osStat(pFile->zPath, &buf)!=0 || buf.st_ino!=pFile->pInode->fileId.ino);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -2448,7 +2445,6 @@ static int semCheckReservedLock(sqlite3_file *id, int *pResOut) {
|
||||
/* Otherwise see if some other process holds it. */
|
||||
if( !reserved ){
|
||||
sem_t *pSem = pFile->pInode->pSem;
|
||||
struct stat statBuf;
|
||||
|
||||
if( sem_trywait(pSem)==-1 ){
|
||||
int tErrno = errno;
|
||||
@@ -2501,7 +2497,6 @@ static int semCheckReservedLock(sqlite3_file *id, int *pResOut) {
|
||||
*/
|
||||
static int semLock(sqlite3_file *id, int eFileLock) {
|
||||
unixFile *pFile = (unixFile*)id;
|
||||
int fd;
|
||||
sem_t *pSem = pFile->pInode->pSem;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
@@ -5888,7 +5883,11 @@ static int unixDelete(
|
||||
UNUSED_PARAMETER(NotUsed);
|
||||
SimulateIOError(return SQLITE_IOERR_DELETE);
|
||||
if( osUnlink(zPath)==(-1) ){
|
||||
if( errno==ENOENT ){
|
||||
if( errno==ENOENT
|
||||
#if OS_VXWORKS
|
||||
|| errno==0x380003
|
||||
#endif
|
||||
){
|
||||
rc = SQLITE_IOERR_DELETE_NOENT;
|
||||
}else{
|
||||
rc = unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
|
||||
|
||||
40
src/os_win.c
40
src/os_win.c
@@ -72,18 +72,14 @@
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Check if the GetVersionEx[AW] functions should be considered deprecated
|
||||
** and avoid using them in that case. It should be noted here that if the
|
||||
** value of the SQLITE_WIN32_GETVERSIONEX pre-processor macro is zero
|
||||
** (whether via this block or via being manually specified), that implies
|
||||
** the underlying operating system will always be based on the Windows NT
|
||||
** Kernel.
|
||||
** Check to see if the GetVersionEx[AW] functions are deprecated on the
|
||||
** target system. GetVersionEx was first deprecated in Win8.1.
|
||||
*/
|
||||
#ifndef SQLITE_WIN32_GETVERSIONEX
|
||||
# if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WINBLUE
|
||||
# define SQLITE_WIN32_GETVERSIONEX 0
|
||||
# define SQLITE_WIN32_GETVERSIONEX 0 /* GetVersionEx() is deprecated */
|
||||
# else
|
||||
# define SQLITE_WIN32_GETVERSIONEX 1
|
||||
# define SQLITE_WIN32_GETVERSIONEX 1 /* GetVersionEx() is current */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@@ -155,7 +151,7 @@
|
||||
** [sometimes] not used by the code (e.g. via conditional compilation).
|
||||
*/
|
||||
#ifndef UNUSED_VARIABLE_VALUE
|
||||
# define UNUSED_VARIABLE_VALUE(x) (void)(x)
|
||||
# define UNUSED_VARIABLE_VALUE(x) (void)(x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -1052,7 +1048,16 @@ static struct win_syscall {
|
||||
** is really just a macro that uses a compiler intrinsic (e.g. x64).
|
||||
** So do not try to make this is into a redefinable interface.
|
||||
*/
|
||||
#if defined(InterlockedCompareExchange)
|
||||
{ "InterlockedCompareExchange", (SYSCALL)0, 0 },
|
||||
|
||||
#define osInterlockedCompareExchange InterlockedCompareExchange
|
||||
#else
|
||||
{ "InterlockedCompareExchange", (SYSCALL)InterlockedCompareExchange, 0 },
|
||||
|
||||
#define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG volatile*, \
|
||||
LONG,LONG))aSyscall[76].pCurrent)
|
||||
#endif /* defined(InterlockedCompareExchange) */
|
||||
|
||||
}; /* End of the overrideable system calls */
|
||||
|
||||
@@ -1312,20 +1317,29 @@ void sqlite3_win32_sleep(DWORD milliseconds){
|
||||
** based on the NT kernel.
|
||||
*/
|
||||
int sqlite3_win32_is_nt(void){
|
||||
#if defined(SQLITE_WIN32_GETVERSIONEX) && SQLITE_WIN32_GETVERSIONEX
|
||||
if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){
|
||||
#if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WIN8
|
||||
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
|
||||
defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WIN8
|
||||
OSVERSIONINFOW sInfo;
|
||||
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
|
||||
osGetVersionExW(&sInfo);
|
||||
#else
|
||||
osInterlockedCompareExchange(&sqlite3_os_type,
|
||||
(sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
|
||||
#elif defined(SQLITE_WIN32_HAS_ANSI)
|
||||
OSVERSIONINFOA sInfo;
|
||||
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
|
||||
osGetVersionExA(&sInfo);
|
||||
#endif
|
||||
osInterlockedCompareExchange(&sqlite3_os_type,
|
||||
(sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
|
||||
#endif
|
||||
}
|
||||
return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
|
||||
#elif SQLITE_TEST
|
||||
return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SQLITE_WIN32_MALLOC
|
||||
@@ -5482,7 +5496,7 @@ int sqlite3_os_init(void){
|
||||
|
||||
/* Double-check that the aSyscall[] array has been constructed
|
||||
** correctly. See ticket [bb3a86e890c8e96ab] */
|
||||
assert( ArraySize(aSyscall)==76 );
|
||||
assert( ArraySize(aSyscall)==77 );
|
||||
|
||||
/* get memory map allocation granularity */
|
||||
memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
|
||||
|
||||
@@ -354,7 +354,7 @@ static int lookupName(
|
||||
}
|
||||
}
|
||||
if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) && HasRowid(pTab) ){
|
||||
/* IMP: R-24309-18625 */
|
||||
/* IMP: R-51414-32910 */
|
||||
/* IMP: R-44911-55124 */
|
||||
iCol = -1;
|
||||
}
|
||||
@@ -710,7 +710,11 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
/* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is equivalent to
|
||||
** likelihood(X, 0.0625).
|
||||
** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is short-hand for
|
||||
** likelihood(X,0.0625). */
|
||||
** likelihood(X,0.0625).
|
||||
** EVIDENCE-OF: R-36850-34127 The likely(X) function is short-hand for
|
||||
** likelihood(X,0.9375).
|
||||
** EVIDENCE-OF: R-53436-40973 The likely(X) function is equivalent to
|
||||
** likelihood(X,0.9375). */
|
||||
/* TUNING: unlikely() probability is 0.0625. likely() is 0.9375 */
|
||||
pExpr->iTable = pDef->zName[0]=='u' ? 62 : 938;
|
||||
}
|
||||
|
||||
@@ -706,7 +706,7 @@ static void selectInnerLoop(
|
||||
sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
|
||||
sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
|
||||
}
|
||||
assert( sqlite3VdbeCurrentAddr(v)==iJump );
|
||||
assert( sqlite3VdbeCurrentAddr(v)==iJump || pParse->db->mallocFailed );
|
||||
sqlite3VdbeAddOp3(v, OP_Copy, regResult, regPrev, nResultCol-1);
|
||||
break;
|
||||
}
|
||||
|
||||
10
src/shell.c
10
src/shell.c
@@ -1694,7 +1694,6 @@ static void writefileFunc(
|
||||
){
|
||||
FILE *out;
|
||||
const char *z;
|
||||
int n;
|
||||
sqlite3_int64 rc;
|
||||
const char *zFile;
|
||||
|
||||
@@ -1704,11 +1703,9 @@ static void writefileFunc(
|
||||
if( out==0 ) return;
|
||||
z = (const char*)sqlite3_value_blob(argv[1]);
|
||||
if( z==0 ){
|
||||
n = 0;
|
||||
rc = 0;
|
||||
}else{
|
||||
n = sqlite3_value_bytes(argv[1]);
|
||||
rc = fwrite(z, 1, n, out);
|
||||
rc = fwrite(z, 1, sqlite3_value_bytes(argv[1]), out);
|
||||
}
|
||||
fclose(out);
|
||||
sqlite3_result_int64(context, rc);
|
||||
@@ -3126,7 +3123,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
&& (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
|
||||
){
|
||||
char *zCmd;
|
||||
int i;
|
||||
int i, x;
|
||||
if( nArg<2 ){
|
||||
fprintf(stderr, "Usage: .system COMMAND\n");
|
||||
rc = 1;
|
||||
@@ -3137,8 +3134,9 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
|
||||
zCmd, azArg[i]);
|
||||
}
|
||||
(void)system(zCmd);
|
||||
x = system(zCmd);
|
||||
sqlite3_free(zCmd);
|
||||
if( x ) fprintf(stderr, "System command returns %d\n", x);
|
||||
}else
|
||||
|
||||
if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
|
||||
|
||||
@@ -264,7 +264,7 @@ typedef sqlite_uint64 sqlite3_uint64;
|
||||
**
|
||||
** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
|
||||
** for the [sqlite3] object.
|
||||
** ^Calls to sqlite3_close() and sqlite3_close_v2() return SQLITE_OK if
|
||||
** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if
|
||||
** the [sqlite3] object is successfully destroyed and all associated
|
||||
** resources are deallocated.
|
||||
**
|
||||
@@ -272,7 +272,7 @@ typedef sqlite_uint64 sqlite3_uint64;
|
||||
** statements or unfinished sqlite3_backup objects then sqlite3_close()
|
||||
** will leave the database connection open and return [SQLITE_BUSY].
|
||||
** ^If sqlite3_close_v2() is called with unfinalized prepared statements
|
||||
** and unfinished sqlite3_backups, then the database connection becomes
|
||||
** and/or unfinished sqlite3_backups, then the database connection becomes
|
||||
** an unusable "zombie" which will automatically be deallocated when the
|
||||
** last prepared statement is finalized or the last sqlite3_backup is
|
||||
** finished. The sqlite3_close_v2() interface is intended for use with
|
||||
@@ -285,7 +285,7 @@ typedef sqlite_uint64 sqlite3_uint64;
|
||||
** with the [sqlite3] object prior to attempting to close the object. ^If
|
||||
** sqlite3_close_v2() is called on a [database connection] that still has
|
||||
** outstanding [prepared statements], [BLOB handles], and/or
|
||||
** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation
|
||||
** [sqlite3_backup] objects then it returns [SQLITE_OK] and the deallocation
|
||||
** of resources is deferred until all [prepared statements], [BLOB handles],
|
||||
** and [sqlite3_backup] objects are also destroyed.
|
||||
**
|
||||
@@ -381,16 +381,14 @@ int sqlite3_exec(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Result Codes
|
||||
** KEYWORDS: SQLITE_OK {error code} {error codes}
|
||||
** KEYWORDS: {result code} {result codes}
|
||||
** KEYWORDS: {result code definitions}
|
||||
**
|
||||
** Many SQLite functions return an integer result code from the set shown
|
||||
** here in order to indicate success or failure.
|
||||
**
|
||||
** New error codes may be added in future versions of SQLite.
|
||||
**
|
||||
** See also: [SQLITE_IOERR_READ | extended result codes],
|
||||
** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes].
|
||||
** See also: [extended result code definitions]
|
||||
*/
|
||||
#define SQLITE_OK 0 /* Successful result */
|
||||
/* beginning-of-error-codes */
|
||||
@@ -428,26 +426,19 @@ int sqlite3_exec(
|
||||
|
||||
/*
|
||||
** CAPI3REF: Extended Result Codes
|
||||
** KEYWORDS: {extended error code} {extended error codes}
|
||||
** KEYWORDS: {extended result code} {extended result codes}
|
||||
** KEYWORDS: {extended result code definitions}
|
||||
**
|
||||
** In its default configuration, SQLite API routines return one of 26 integer
|
||||
** [SQLITE_OK | result codes]. However, experience has shown that many of
|
||||
** In its default configuration, SQLite API routines return one of 30 integer
|
||||
** [result codes]. However, experience has shown that many of
|
||||
** these result codes are too coarse-grained. They do not provide as
|
||||
** much information about problems as programmers might like. In an effort to
|
||||
** address this, newer versions of SQLite (version 3.3.8 and later) include
|
||||
** support for additional result codes that provide more detailed information
|
||||
** about errors. The extended result codes are enabled or disabled
|
||||
** about errors. These [extended result codes] are enabled or disabled
|
||||
** on a per database connection basis using the
|
||||
** [sqlite3_extended_result_codes()] API.
|
||||
**
|
||||
** Some of the available extended result codes are listed here.
|
||||
** One may expect the number of extended result codes will increase
|
||||
** over time. Software that uses extended result codes should expect
|
||||
** to see new result codes in future releases of SQLite.
|
||||
**
|
||||
** The SQLITE_OK result code will never be extended. It will always
|
||||
** be exactly zero.
|
||||
** [sqlite3_extended_result_codes()] API. Or, the extended code for
|
||||
** the most recent error can be obtained using
|
||||
** [sqlite3_extended_errcode()].
|
||||
*/
|
||||
#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
|
||||
#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
|
||||
@@ -680,7 +671,7 @@ struct sqlite3_file {
|
||||
** locking strategy (for example to use dot-file locks), to inquire
|
||||
** about the status of a lock, or to break stale locks. The SQLite
|
||||
** core reserves all opcodes less than 100 for its own use.
|
||||
** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available.
|
||||
** A [file control opcodes | list of opcodes] less than 100 is available.
|
||||
** Applications that define a custom xFileControl method should use opcodes
|
||||
** greater than 100 to avoid conflicts. VFS implementations should
|
||||
** return [SQLITE_NOTFOUND] for file control opcodes that they do not
|
||||
@@ -753,6 +744,7 @@ struct sqlite3_io_methods {
|
||||
|
||||
/*
|
||||
** CAPI3REF: Standard File Control Opcodes
|
||||
** KEYWORDS: {file control opcodes} {file control opcode}
|
||||
**
|
||||
** These integer constants are opcodes for the xFileControl method
|
||||
** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
|
||||
@@ -2040,7 +2032,7 @@ int sqlite3_complete16(const void *sql);
|
||||
** The sqlite3_busy_handler() interface is used to implement
|
||||
** [sqlite3_busy_timeout()] and [PRAGMA busy_timeout].
|
||||
**
|
||||
** ^If the busy callback is NULL, then [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]
|
||||
** ^If the busy callback is NULL, then [SQLITE_BUSY]
|
||||
** is returned immediately upon encountering the lock. ^If the busy callback
|
||||
** is not NULL, then the callback might be invoked with two arguments.
|
||||
**
|
||||
@@ -2049,7 +2041,7 @@ int sqlite3_complete16(const void *sql);
|
||||
** the busy handler callback is the number of times that the busy handler has
|
||||
** been invoked for the same locking event. ^If the
|
||||
** busy callback returns 0, then no additional attempts are made to
|
||||
** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned
|
||||
** access the database and [SQLITE_BUSY] is returned
|
||||
** to the application.
|
||||
** ^If the callback returns non-zero, then another attempt
|
||||
** is made to access the database and the cycle repeats.
|
||||
@@ -2057,7 +2049,7 @@ int sqlite3_complete16(const void *sql);
|
||||
** 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 go ahead and return [SQLITE_BUSY]
|
||||
** or [SQLITE_IOERR_BLOCKED] to the application instead of invoking the
|
||||
** to the application instead of invoking the
|
||||
** busy handler.
|
||||
** Consider a scenario where one process is holding a read lock that
|
||||
** it is trying to promote to a reserved lock and
|
||||
@@ -2072,21 +2064,6 @@ int sqlite3_complete16(const void *sql);
|
||||
**
|
||||
** ^The default busy callback is NULL.
|
||||
**
|
||||
** ^The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED]
|
||||
** when SQLite is in the middle of a large transaction where all the
|
||||
** changes will not fit into the in-memory cache. SQLite will
|
||||
** already hold a RESERVED lock on the database file, but it needs
|
||||
** to promote this lock to EXCLUSIVE so that it can spill cache
|
||||
** pages into the database file without harm to concurrent
|
||||
** readers. ^If it is unable to promote the lock, then the in-memory
|
||||
** cache will be left in an inconsistent state and so the error
|
||||
** code is promoted from the relatively benign [SQLITE_BUSY] to
|
||||
** the more severe [SQLITE_IOERR_BLOCKED]. ^This error code promotion
|
||||
** forces an automatic rollback of the changes. See the
|
||||
** <a href="/cvstrac/wiki?p=CorruptionFollowingBusyError">
|
||||
** CorruptionFollowingBusyError</a> wiki page for a discussion of why
|
||||
** this is important.
|
||||
**
|
||||
** ^(There can only be a single busy handler defined for each
|
||||
** [database connection]. Setting a new busy handler clears any
|
||||
** previously set handler.)^ ^Note that calling [sqlite3_busy_timeout()]
|
||||
@@ -2111,7 +2088,7 @@ int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
|
||||
** will sleep multiple times until at least "ms" milliseconds of sleeping
|
||||
** have accumulated. ^After at least "ms" milliseconds of sleeping,
|
||||
** the handler returns 0 which causes [sqlite3_step()] to return
|
||||
** [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED].
|
||||
** [SQLITE_BUSY].
|
||||
**
|
||||
** ^Calling this routine with an argument less than or equal to zero
|
||||
** turns off all busy handlers.
|
||||
@@ -2523,8 +2500,8 @@ int sqlite3_set_authorizer(
|
||||
** [sqlite3_set_authorizer | authorizer documentation] for additional
|
||||
** information.
|
||||
**
|
||||
** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code]
|
||||
** from the [sqlite3_vtab_on_conflict()] interface.
|
||||
** Note that SQLITE_IGNORE is also used as a [conflict resolution mode]
|
||||
** returned from the [sqlite3_vtab_on_conflict()] interface.
|
||||
*/
|
||||
#define SQLITE_DENY 1 /* Abort the SQL statement with an error */
|
||||
#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
|
||||
@@ -7364,6 +7341,7 @@ int sqlite3_vtab_on_conflict(sqlite3 *);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Conflict resolution modes
|
||||
** KEYWORDS: {conflict resolution mode}
|
||||
**
|
||||
** These constants are returned by [sqlite3_vtab_on_conflict()] to
|
||||
** inform a [virtual table] implementation what the [ON CONFLICT] mode
|
||||
|
||||
@@ -3276,7 +3276,7 @@ case OP_ReopenIdx: {
|
||||
assert( pOp->p5==0 );
|
||||
assert( pOp->p4type==P4_KEYINFO );
|
||||
pCur = p->apCsr[pOp->p1];
|
||||
if( pCur && pCur->pgnoRoot==pOp->p2 ){
|
||||
if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){
|
||||
assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -85,18 +85,35 @@ void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
|
||||
}
|
||||
|
||||
/*
|
||||
** Resize the Vdbe.aOp array so that it is at least one op larger than
|
||||
** it was.
|
||||
** Resize the Vdbe.aOp array so that it is at least nOp elements larger
|
||||
** than its current size. nOp is guaranteed to be less than or equal
|
||||
** to 1024/sizeof(Op).
|
||||
**
|
||||
** If an out-of-memory error occurs while resizing the array, return
|
||||
** SQLITE_NOMEM. In this case Vdbe.aOp and Vdbe.nOpAlloc remain
|
||||
** SQLITE_NOMEM. In this case Vdbe.aOp and Parse.nOpAlloc remain
|
||||
** unchanged (this is so that any opcodes already allocated can be
|
||||
** correctly deallocated along with the rest of the Vdbe).
|
||||
*/
|
||||
static int growOpArray(Vdbe *v){
|
||||
static int growOpArray(Vdbe *v, int nOp){
|
||||
VdbeOp *pNew;
|
||||
Parse *p = v->pParse;
|
||||
|
||||
/* The SQLITE_TEST_REALLOC_STRESS compile-time option is designed to force
|
||||
** more frequent reallocs and hence provide more opportunities for
|
||||
** simulated OOM faults. SQLITE_TEST_REALLOC_STRESS is generally used
|
||||
** during testing only. With SQLITE_TEST_REALLOC_STRESS grow the op array
|
||||
** by the minimum* amount required until the size reaches 512. Normal
|
||||
** operation (without SQLITE_TEST_REALLOC_STRESS) is to double the current
|
||||
** size of the op array or add 1KB of space, whichever is smaller. */
|
||||
#ifdef SQLITE_TEST_REALLOC_STRESS
|
||||
int nNew = (p->nOpAlloc>=512 ? p->nOpAlloc*2 : p->nOpAlloc+nOp);
|
||||
#else
|
||||
int nNew = (p->nOpAlloc ? p->nOpAlloc*2 : (int)(1024/sizeof(Op)));
|
||||
UNUSED_PARAMETER(nOp);
|
||||
#endif
|
||||
|
||||
assert( nOp<=(1024/sizeof(Op)) );
|
||||
assert( nNew>=(p->nOpAlloc+nOp) );
|
||||
pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op));
|
||||
if( pNew ){
|
||||
p->nOpAlloc = sqlite3DbMallocSize(p->db, pNew)/sizeof(Op);
|
||||
@@ -140,7 +157,7 @@ int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
|
||||
assert( p->magic==VDBE_MAGIC_INIT );
|
||||
assert( op>0 && op<0xff );
|
||||
if( p->pParse->nOpAlloc<=i ){
|
||||
if( growOpArray(p) ){
|
||||
if( growOpArray(p, 1) ){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -542,7 +559,7 @@ VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){
|
||||
int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp, int iLineno){
|
||||
int addr;
|
||||
assert( p->magic==VDBE_MAGIC_INIT );
|
||||
if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p) ){
|
||||
if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p, nOp) ){
|
||||
return 0;
|
||||
}
|
||||
addr = p->nOp;
|
||||
@@ -727,7 +744,7 @@ void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){
|
||||
** Change the opcode at addr into OP_Noop
|
||||
*/
|
||||
void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
|
||||
if( p->aOp ){
|
||||
if( addr<p->nOp ){
|
||||
VdbeOp *pOp = &p->aOp[addr];
|
||||
sqlite3 *db = p->db;
|
||||
freeP4(db, pOp->p4type, pOp->p4.p);
|
||||
@@ -2302,7 +2319,6 @@ int sqlite3VdbeHalt(Vdbe *p){
|
||||
|
||||
/* Check for one of the special errors */
|
||||
mrc = p->rc & 0xff;
|
||||
assert( p->rc!=SQLITE_IOERR_BLOCKED ); /* This error no longer exists */
|
||||
isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR
|
||||
|| mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL;
|
||||
if( isSpecialError ){
|
||||
|
||||
197
src/where.c
197
src/where.c
@@ -5400,6 +5400,45 @@ static const char *wherePathName(WherePath *pPath, int nLoop, WhereLoop *pLast){
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Return the cost of sorting nRow rows, assuming that the keys have
|
||||
** nOrderby columns and that the first nSorted columns are already in
|
||||
** order.
|
||||
*/
|
||||
static LogEst whereSortingCost(
|
||||
WhereInfo *pWInfo,
|
||||
LogEst nRow,
|
||||
int nOrderBy,
|
||||
int nSorted
|
||||
){
|
||||
/* TUNING: Estimated cost of a full external sort, where N is
|
||||
** the number of rows to sort is:
|
||||
**
|
||||
** cost = (3.0 * N * log(N)).
|
||||
**
|
||||
** Or, if the order-by clause has X terms but only the last Y
|
||||
** terms are out of order, then block-sorting will reduce the
|
||||
** sorting cost to:
|
||||
**
|
||||
** cost = (3.0 * N * log(N)) * (Y/X)
|
||||
**
|
||||
** The (Y/X) term is implemented using stack variable rScale
|
||||
** below. */
|
||||
LogEst rScale, rSortCost;
|
||||
assert( nOrderBy>0 && 66==sqlite3LogEst(100) );
|
||||
rScale = sqlite3LogEst((nOrderBy-nSorted)*100/nOrderBy) - 66;
|
||||
rSortCost = nRow + estLog(nRow) + rScale + 16;
|
||||
|
||||
/* TUNING: The cost of implementing DISTINCT using a B-TREE is
|
||||
** similar but with a larger constant of proportionality.
|
||||
** Multiply by an additional factor of 3.0. */
|
||||
if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){
|
||||
rSortCost += 16;
|
||||
}
|
||||
|
||||
return rSortCost;
|
||||
}
|
||||
|
||||
/*
|
||||
** Given the list of WhereLoop objects at pWInfo->pLoops, this routine
|
||||
** attempts to find the lowest cost path that visits each WhereLoop
|
||||
@@ -5421,9 +5460,8 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
int ii, jj; /* Loop counters */
|
||||
int mxI = 0; /* Index of next entry to replace */
|
||||
int nOrderBy; /* Number of ORDER BY clause terms */
|
||||
LogEst rCost; /* Cost of a path */
|
||||
LogEst nOut; /* Number of outputs */
|
||||
LogEst mxCost = 0; /* Maximum cost of a set of paths */
|
||||
LogEst mxUnsorted = 0; /* Maximum unsorted cost of a set of path */
|
||||
int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */
|
||||
WherePath *aFrom; /* All nFrom paths at the previous level */
|
||||
WherePath *aTo; /* The nTo best paths at the current level */
|
||||
@@ -5431,7 +5469,9 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
WherePath *pTo; /* An element of aTo[] that we are working on */
|
||||
WhereLoop *pWLoop; /* One of the WhereLoop objects */
|
||||
WhereLoop **pX; /* Used to divy up the pSpace memory */
|
||||
LogEst *aSortCost = 0; /* Sorting and partial sorting costs */
|
||||
char *pSpace; /* Temporary memory used by this routine */
|
||||
int nSpace; /* Bytes of space allocated at pSpace */
|
||||
|
||||
pParse = pWInfo->pParse;
|
||||
db = pParse->db;
|
||||
@@ -5441,11 +5481,23 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
** For joins of 3 or more tables, track the 10 best paths */
|
||||
mxChoice = (nLoop<=1) ? 1 : (nLoop==2 ? 5 : 10);
|
||||
assert( nLoop<=pWInfo->pTabList->nSrc );
|
||||
WHERETRACE(0x002, ("---- begin solver\n"));
|
||||
WHERETRACE(0x002, ("---- begin solver. (nRowEst=%d)\n", nRowEst));
|
||||
|
||||
/* Allocate and initialize space for aTo and aFrom */
|
||||
ii = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2;
|
||||
pSpace = sqlite3DbMallocRaw(db, ii);
|
||||
/* If nRowEst is zero and there is an ORDER BY clause, ignore it. In this
|
||||
** case the purpose of this call is to estimate the number of rows returned
|
||||
** by the overall query. Once this estimate has been obtained, the caller
|
||||
** will invoke this function a second time, passing the estimate as the
|
||||
** nRowEst parameter. */
|
||||
if( pWInfo->pOrderBy==0 || nRowEst==0 ){
|
||||
nOrderBy = 0;
|
||||
}else{
|
||||
nOrderBy = pWInfo->pOrderBy->nExpr;
|
||||
}
|
||||
|
||||
/* Allocate and initialize space for aTo, aFrom and aSortCost[] */
|
||||
nSpace = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2;
|
||||
nSpace += sizeof(LogEst) * nOrderBy;
|
||||
pSpace = sqlite3DbMallocRaw(db, nSpace);
|
||||
if( pSpace==0 ) return SQLITE_NOMEM;
|
||||
aTo = (WherePath*)pSpace;
|
||||
aFrom = aTo+mxChoice;
|
||||
@@ -5454,6 +5506,18 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
for(ii=mxChoice*2, pFrom=aTo; ii>0; ii--, pFrom++, pX += nLoop){
|
||||
pFrom->aLoop = pX;
|
||||
}
|
||||
if( nOrderBy ){
|
||||
/* If there is an ORDER BY clause and it is not being ignored, set up
|
||||
** space for the aSortCost[] array. Each element of the aSortCost array
|
||||
** is either zero - meaning it has not yet been initialized - or the
|
||||
** cost of sorting nRowEst rows of data where the first X terms of
|
||||
** the ORDER BY clause are already in order, where X is the array
|
||||
** index. */
|
||||
aSortCost = (LogEst*)pX;
|
||||
memset(aSortCost, 0, sizeof(LogEst) * nOrderBy);
|
||||
}
|
||||
assert( aSortCost==0 || &pSpace[nSpace]==(char*)&aSortCost[nOrderBy] );
|
||||
assert( aSortCost!=0 || &pSpace[nSpace]==(char*)pX );
|
||||
|
||||
/* Seed the search with a single WherePath containing zero WhereLoops.
|
||||
**
|
||||
@@ -5462,15 +5526,15 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
** rows, then do not use the automatic index. */
|
||||
aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==sqlite3LogEst(25) );
|
||||
nFrom = 1;
|
||||
|
||||
/* Precompute the cost of sorting the final result set, if the caller
|
||||
** to sqlite3WhereBegin() was concerned about sorting */
|
||||
if( pWInfo->pOrderBy==0 || nRowEst==0 ){
|
||||
aFrom[0].isOrdered = 0;
|
||||
nOrderBy = 0;
|
||||
}else{
|
||||
aFrom[0].isOrdered = nLoop>0 ? -1 : 1;
|
||||
nOrderBy = pWInfo->pOrderBy->nExpr;
|
||||
assert( aFrom[0].isOrdered==0 );
|
||||
if( nOrderBy ){
|
||||
/* If nLoop is zero, then there are no FROM terms in the query. Since
|
||||
** in this case the query may return a maximum of one row, the results
|
||||
** are already in the requested order. Set isOrdered to nOrderBy to
|
||||
** indicate this. Or, if nLoop is greater than zero, set isOrdered to
|
||||
** -1, indicating that the result set may or may not be ordered,
|
||||
** depending on the loops added to the current plan. */
|
||||
aFrom[0].isOrdered = nLoop>0 ? -1 : nOrderBy;
|
||||
}
|
||||
|
||||
/* Compute successively longer WherePaths using the previous generation
|
||||
@@ -5480,66 +5544,71 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
nTo = 0;
|
||||
for(ii=0, pFrom=aFrom; ii<nFrom; ii++, pFrom++){
|
||||
for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
|
||||
Bitmask maskNew;
|
||||
Bitmask revMask = 0;
|
||||
i8 isOrdered = pFrom->isOrdered;
|
||||
LogEst nOut; /* Rows visited by (pFrom+pWLoop) */
|
||||
LogEst rCost; /* Cost of path (pFrom+pWLoop) */
|
||||
LogEst rUnsorted; /* Unsorted cost of (pFrom+pWLoop) */
|
||||
i8 isOrdered = pFrom->isOrdered; /* isOrdered for (pFrom+pWLoop) */
|
||||
Bitmask maskNew; /* Mask of src visited by (..) */
|
||||
Bitmask revMask = 0; /* Mask of rev-order loops for (..) */
|
||||
|
||||
if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue;
|
||||
if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
|
||||
/* At this point, pWLoop is a candidate to be the next loop.
|
||||
** Compute its cost */
|
||||
rCost = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
|
||||
rCost = sqlite3LogEstAdd(rCost, pFrom->rCost);
|
||||
rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
|
||||
rUnsorted = sqlite3LogEstAdd(rUnsorted, pFrom->rUnsorted);
|
||||
nOut = pFrom->nRow + pWLoop->nOut;
|
||||
maskNew = pFrom->maskLoop | pWLoop->maskSelf;
|
||||
if( isOrdered<0 ){
|
||||
isOrdered = wherePathSatisfiesOrderBy(pWInfo,
|
||||
pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags,
|
||||
iLoop, pWLoop, &revMask);
|
||||
if( isOrdered>=0 && isOrdered<nOrderBy ){
|
||||
/* TUNING: Estimated cost of a full external sort, where N is
|
||||
** the number of rows to sort is:
|
||||
**
|
||||
** cost = (3.0 * N * log(N)).
|
||||
**
|
||||
** Or, if the order-by clause has X terms but only the last Y
|
||||
** terms are out of order, then block-sorting will reduce the
|
||||
** sorting cost to:
|
||||
**
|
||||
** cost = (3.0 * N * log(N)) * (Y/X)
|
||||
**
|
||||
** The (Y/X) term is implemented using stack variable rScale
|
||||
** below. */
|
||||
LogEst rScale, rSortCost;
|
||||
assert( nOrderBy>0 && 66==sqlite3LogEst(100) );
|
||||
rScale = sqlite3LogEst((nOrderBy-isOrdered)*100/nOrderBy) - 66;
|
||||
rSortCost = nRowEst + estLog(nRowEst) + rScale + 16;
|
||||
|
||||
/* TUNING: The cost of implementing DISTINCT using a B-TREE is
|
||||
** similar but with a larger constant of proportionality.
|
||||
** Multiply by an additional factor of 3.0. */
|
||||
if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){
|
||||
rSortCost += 16;
|
||||
}
|
||||
WHERETRACE(0x002,
|
||||
("---- sort cost=%-3d (%d/%d) increases cost %3d to %-3d\n",
|
||||
rSortCost, (nOrderBy-isOrdered), nOrderBy, rCost,
|
||||
sqlite3LogEstAdd(rCost,rSortCost)));
|
||||
rCost = sqlite3LogEstAdd(rCost, rSortCost);
|
||||
}
|
||||
}else{
|
||||
revMask = pFrom->revLoop;
|
||||
}
|
||||
/* Check to see if pWLoop should be added to the mxChoice best so far */
|
||||
if( isOrdered>=0 && isOrdered<nOrderBy ){
|
||||
if( aSortCost[isOrdered]==0 ){
|
||||
aSortCost[isOrdered] = whereSortingCost(
|
||||
pWInfo, nRowEst, nOrderBy, isOrdered
|
||||
);
|
||||
}
|
||||
rCost = sqlite3LogEstAdd(rUnsorted, aSortCost[isOrdered]);
|
||||
|
||||
WHERETRACE(0x002,
|
||||
("---- sort cost=%-3d (%d/%d) increases cost %3d to %-3d\n",
|
||||
aSortCost[isOrdered], (nOrderBy-isOrdered), nOrderBy,
|
||||
rUnsorted, rCost));
|
||||
}else{
|
||||
rCost = rUnsorted;
|
||||
}
|
||||
|
||||
/* Check to see if pWLoop should be added to the set of
|
||||
** mxChoice best-so-far paths.
|
||||
**
|
||||
** First look for an existing path among best-so-far paths
|
||||
** that covers the same set of loops and has the same isOrdered
|
||||
** setting as the current path candidate.
|
||||
**
|
||||
** The term "((pTo->isOrdered^isOrdered)&0x80)==0" is equivalent
|
||||
** to (pTo->isOrdered==(-1))==(isOrdered==(-1))" for the range
|
||||
** of legal values for isOrdered, -1..64.
|
||||
*/
|
||||
for(jj=0, pTo=aTo; jj<nTo; jj++, pTo++){
|
||||
if( pTo->maskLoop==maskNew
|
||||
&& ((pTo->isOrdered^isOrdered)&80)==0
|
||||
&& ((pTo->isOrdered^isOrdered)&0x80)==0
|
||||
){
|
||||
testcase( jj==nTo-1 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( jj>=nTo ){
|
||||
if( nTo>=mxChoice && rCost>=mxCost ){
|
||||
/* None of the existing best-so-far paths match the candidate. */
|
||||
if( nTo>=mxChoice
|
||||
&& (rCost>mxCost || (rCost==mxCost && rUnsorted>=mxUnsorted))
|
||||
){
|
||||
/* The current candidate is no better than any of the mxChoice
|
||||
** paths currently in the best-so-far buffer. So discard
|
||||
** this candidate as not viable. */
|
||||
#ifdef WHERETRACE_ENABLED /* 0x4 */
|
||||
if( sqlite3WhereTrace&0x4 ){
|
||||
sqlite3DebugPrintf("Skip %s cost=%-3d,%3d order=%c\n",
|
||||
@@ -5549,7 +5618,8 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
/* Add a new Path to the aTo[] set */
|
||||
/* If we reach this points it means that the new candidate path
|
||||
** needs to be added to the set of best-so-far paths. */
|
||||
if( nTo<mxChoice ){
|
||||
/* Increase the size of the aTo set by one */
|
||||
jj = nTo++;
|
||||
@@ -5566,7 +5636,11 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
}
|
||||
#endif
|
||||
}else{
|
||||
if( pTo->rCost<=rCost ){
|
||||
/* Control reaches here if best-so-far path pTo=aTo[jj] covers the
|
||||
** same set of loops and has the sam isOrdered setting as the
|
||||
** candidate path. Check to see if the candidate should replace
|
||||
** pTo or if the candidate should be skipped */
|
||||
if( pTo->rCost<rCost || (pTo->rCost==rCost && pTo->nRow<=nOut) ){
|
||||
#ifdef WHERETRACE_ENABLED /* 0x4 */
|
||||
if( sqlite3WhereTrace&0x4 ){
|
||||
sqlite3DebugPrintf(
|
||||
@@ -5578,11 +5652,13 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
|
||||
}
|
||||
#endif
|
||||
/* Discard the candidate path from further consideration */
|
||||
testcase( pTo->rCost==rCost );
|
||||
continue;
|
||||
}
|
||||
testcase( pTo->rCost==rCost+1 );
|
||||
/* A new and better score for a previously created equivalent path */
|
||||
/* Control reaches here if the candidate path is better than the
|
||||
** pTo path. Replace pTo with the candidate. */
|
||||
#ifdef WHERETRACE_ENABLED /* 0x4 */
|
||||
if( sqlite3WhereTrace&0x4 ){
|
||||
sqlite3DebugPrintf(
|
||||
@@ -5600,15 +5676,20 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
pTo->revLoop = revMask;
|
||||
pTo->nRow = nOut;
|
||||
pTo->rCost = rCost;
|
||||
pTo->rUnsorted = rUnsorted;
|
||||
pTo->isOrdered = isOrdered;
|
||||
memcpy(pTo->aLoop, pFrom->aLoop, sizeof(WhereLoop*)*iLoop);
|
||||
pTo->aLoop[iLoop] = pWLoop;
|
||||
if( nTo>=mxChoice ){
|
||||
mxI = 0;
|
||||
mxCost = aTo[0].rCost;
|
||||
mxUnsorted = aTo[0].nRow;
|
||||
for(jj=1, pTo=&aTo[1]; jj<mxChoice; jj++, pTo++){
|
||||
if( pTo->rCost>mxCost ){
|
||||
if( pTo->rCost>mxCost
|
||||
|| (pTo->rCost==mxCost && pTo->rUnsorted>mxUnsorted)
|
||||
){
|
||||
mxCost = pTo->rCost;
|
||||
mxUnsorted = pTo->rUnsorted;
|
||||
mxI = jj;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,6 +183,7 @@ struct WherePath {
|
||||
Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */
|
||||
LogEst nRow; /* Estimated number of rows generated by this path */
|
||||
LogEst rCost; /* Total cost of this path */
|
||||
LogEst rUnsorted; /* Total cost of this path ignoring sorting costs */
|
||||
i8 isOrdered; /* No. of ORDER BY terms satisfied. -1 for unknown */
|
||||
WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user