| | @@ -656,11 +656,11 @@ |
| 656 | 656 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 657 | 657 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 658 | 658 | */ |
| 659 | 659 | #define SQLITE_VERSION "3.8.1" |
| 660 | 660 | #define SQLITE_VERSION_NUMBER 3008001 |
| 661 | | -#define SQLITE_SOURCE_ID "2013-08-30 06:20:23 d9c018f8155ab48df8e0e02519bba50588fe49fc" |
| 661 | +#define SQLITE_SOURCE_ID "2013-09-04 04:04:08 8df95bb0b3f72222cf262174247a467c234f9939" |
| 662 | 662 | |
| 663 | 663 | /* |
| 664 | 664 | ** CAPI3REF: Run-Time Library Version Numbers |
| 665 | 665 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 666 | 666 | ** |
| | @@ -1026,16 +1026,18 @@ |
| 1026 | 1026 | #define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8)) |
| 1027 | 1027 | #define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8)) |
| 1028 | 1028 | #define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8)) |
| 1029 | 1029 | #define SQLITE_IOERR_MMAP (SQLITE_IOERR | (24<<8)) |
| 1030 | 1030 | #define SQLITE_IOERR_GETTEMPPATH (SQLITE_IOERR | (25<<8)) |
| 1031 | +#define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8)) |
| 1031 | 1032 | #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) |
| 1032 | 1033 | #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) |
| 1033 | 1034 | #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) |
| 1034 | 1035 | #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) |
| 1035 | 1036 | #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) |
| 1036 | 1037 | #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) |
| 1038 | +#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) |
| 1037 | 1039 | #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) |
| 1038 | 1040 | #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) |
| 1039 | 1041 | #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) |
| 1040 | 1042 | #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) |
| 1041 | 1043 | #define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) |
| | @@ -16259,11 +16261,11 @@ |
| 16259 | 16261 | assert( mem.disallow==0 ); |
| 16260 | 16262 | assert( (nByte & 7)==0 ); /* EV: R-46199-30249 */ |
| 16261 | 16263 | pOldHdr = sqlite3MemsysGetHeader(pPrior); |
| 16262 | 16264 | pNew = sqlite3MemMalloc(nByte); |
| 16263 | 16265 | if( pNew ){ |
| 16264 | | - memcpy(pNew, pPrior, nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize); |
| 16266 | + memcpy(pNew, pPrior, (int)(nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize)); |
| 16265 | 16267 | if( nByte>pOldHdr->iSize ){ |
| 16266 | 16268 | randomFill(&((char*)pNew)[pOldHdr->iSize], nByte - (int)pOldHdr->iSize); |
| 16267 | 16269 | } |
| 16268 | 16270 | sqlite3MemFree(pPrior); |
| 16269 | 16271 | } |
| | @@ -23594,10 +23596,19 @@ |
| 23594 | 23596 | if( aSyscall[i].pCurrent!=0 ) return aSyscall[i].zName; |
| 23595 | 23597 | } |
| 23596 | 23598 | return 0; |
| 23597 | 23599 | } |
| 23598 | 23600 | |
| 23601 | +/* |
| 23602 | +** Do not accept any file descriptor less than this value, in order to avoid |
| 23603 | +** opening database file using file descriptors that are commonly used for |
| 23604 | +** standard input, output, and error. |
| 23605 | +*/ |
| 23606 | +#ifndef SQLITE_MINIMUM_FILE_DESCRIPTOR |
| 23607 | +# define SQLITE_MINIMUM_FILE_DESCRIPTOR 3 |
| 23608 | +#endif |
| 23609 | + |
| 23599 | 23610 | /* |
| 23600 | 23611 | ** Invoke open(). Do so multiple times, until it either succeeds or |
| 23601 | 23612 | ** fails for some reason other than EINTR. |
| 23602 | 23613 | ** |
| 23603 | 23614 | ** If the file creation mode "m" is 0 then set it to the default for |
| | @@ -23624,11 +23635,11 @@ |
| 23624 | 23635 | #endif |
| 23625 | 23636 | if( fd<0 ){ |
| 23626 | 23637 | if( errno==EINTR ) continue; |
| 23627 | 23638 | break; |
| 23628 | 23639 | } |
| 23629 | | - if( fd>2 ) break; |
| 23640 | + if( fd>=SQLITE_MINIMUM_FILE_DESCRIPTOR ) break; |
| 23630 | 23641 | osClose(fd); |
| 23631 | 23642 | sqlite3_log(SQLITE_WARNING, |
| 23632 | 23643 | "attempt to open \"%s\" as file descriptor %d", z, fd); |
| 23633 | 23644 | fd = -1; |
| 23634 | 23645 | if( osOpen("/dev/null", f, m)<0 ) break; |
| | @@ -28373,10 +28384,11 @@ |
| 28373 | 28384 | ** If no suitable temporary file directory can be found, return NULL. |
| 28374 | 28385 | */ |
| 28375 | 28386 | static const char *unixTempFileDir(void){ |
| 28376 | 28387 | static const char *azDirs[] = { |
| 28377 | 28388 | 0, |
| 28389 | + 0, |
| 28378 | 28390 | 0, |
| 28379 | 28391 | "/var/tmp", |
| 28380 | 28392 | "/usr/tmp", |
| 28381 | 28393 | "/tmp", |
| 28382 | 28394 | 0 /* List terminator */ |
| | @@ -28384,11 +28396,12 @@ |
| 28384 | 28396 | unsigned int i; |
| 28385 | 28397 | struct stat buf; |
| 28386 | 28398 | const char *zDir = 0; |
| 28387 | 28399 | |
| 28388 | 28400 | azDirs[0] = sqlite3_temp_directory; |
| 28389 | | - if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR"); |
| 28401 | + if( !azDirs[1] ) azDirs[1] = getenv("SQLITE_TMPDIR"); |
| 28402 | + if( !azDirs[2] ) azDirs[2] = getenv("TMPDIR"); |
| 28390 | 28403 | for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); zDir=azDirs[i++]){ |
| 28391 | 28404 | if( zDir==0 ) continue; |
| 28392 | 28405 | if( osStat(zDir, &buf) ) continue; |
| 28393 | 28406 | if( !S_ISDIR(buf.st_mode) ) continue; |
| 28394 | 28407 | if( osAccess(zDir, 07) ) continue; |
| | @@ -30497,11 +30510,11 @@ |
| 30497 | 30510 | */ |
| 30498 | 30511 | #if SQLITE_OS_WIN /* This file is used for Windows only */ |
| 30499 | 30512 | |
| 30500 | 30513 | #ifdef __CYGWIN__ |
| 30501 | 30514 | # include <sys/cygwin.h> |
| 30502 | | -/* # include <errno.h> */ |
| 30515 | +# include <errno.h> /* amalgamator: keep */ |
| 30503 | 30516 | #endif |
| 30504 | 30517 | |
| 30505 | 30518 | /* |
| 30506 | 30519 | ** Include code that is common to all os_*.c files |
| 30507 | 30520 | */ |
| | @@ -30726,22 +30739,31 @@ |
| 30726 | 30739 | |
| 30727 | 30740 | /* |
| 30728 | 30741 | ** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions |
| 30729 | 30742 | ** based on the sub-platform)? |
| 30730 | 30743 | */ |
| 30731 | | -#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT |
| 30744 | +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(SQLITE_WIN32_NO_ANSI) |
| 30732 | 30745 | # define SQLITE_WIN32_HAS_ANSI |
| 30733 | 30746 | #endif |
| 30734 | 30747 | |
| 30735 | 30748 | /* |
| 30736 | 30749 | ** Are most of the Win32 Unicode APIs available (i.e. with certain exceptions |
| 30737 | 30750 | ** based on the sub-platform)? |
| 30738 | 30751 | */ |
| 30739 | | -#if SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT |
| 30752 | +#if (SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT) && \ |
| 30753 | + !defined(SQLITE_WIN32_NO_WIDE) |
| 30740 | 30754 | # define SQLITE_WIN32_HAS_WIDE |
| 30741 | 30755 | #endif |
| 30742 | 30756 | |
| 30757 | +/* |
| 30758 | +** Make sure at least one set of Win32 APIs is available. |
| 30759 | +*/ |
| 30760 | +#if !defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_WIN32_HAS_WIDE) |
| 30761 | +# error "At least one of SQLITE_WIN32_HAS_ANSI and SQLITE_WIN32_HAS_WIDE\ |
| 30762 | + must be defined." |
| 30763 | +#endif |
| 30764 | + |
| 30743 | 30765 | /* |
| 30744 | 30766 | ** Maximum pathname length (in chars) for Win32. This should normally be |
| 30745 | 30767 | ** MAX_PATH. |
| 30746 | 30768 | */ |
| 30747 | 30769 | #ifndef SQLITE_WIN32_MAX_PATH_CHARS |
| | @@ -30849,11 +30871,11 @@ |
| 30849 | 30871 | #ifndef FILE_ATTRIBUTE_MASK |
| 30850 | 30872 | # define FILE_ATTRIBUTE_MASK (0x0003FFF7) |
| 30851 | 30873 | #endif |
| 30852 | 30874 | |
| 30853 | 30875 | #ifndef SQLITE_OMIT_WAL |
| 30854 | | -/* Forward references */ |
| 30876 | +/* Forward references to structures used for WAL */ |
| 30855 | 30877 | typedef struct winShm winShm; /* A connection to shared-memory */ |
| 30856 | 30878 | typedef struct winShmNode winShmNode; /* A region of shared-memory */ |
| 30857 | 30879 | #endif |
| 30858 | 30880 | |
| 30859 | 30881 | /* |
| | @@ -31804,11 +31826,11 @@ |
| 31804 | 31826 | ** API as long as we don't call it when running Win95/98/ME. A call to |
| 31805 | 31827 | ** this routine is used to determine if the host is Win95/98/ME or |
| 31806 | 31828 | ** WinNT/2K/XP so that we will know whether or not we can safely call |
| 31807 | 31829 | ** the LockFileEx() API. |
| 31808 | 31830 | */ |
| 31809 | | -#if SQLITE_OS_WINCE || SQLITE_OS_WINRT |
| 31831 | +#if SQLITE_OS_WINCE || SQLITE_OS_WINRT || !defined(SQLITE_WIN32_HAS_ANSI) |
| 31810 | 31832 | # define osIsNT() (1) |
| 31811 | 31833 | #elif !defined(SQLITE_WIN32_HAS_WIDE) |
| 31812 | 31834 | # define osIsNT() (0) |
| 31813 | 31835 | #else |
| 31814 | 31836 | static int osIsNT(void){ |
| | @@ -32449,14 +32471,13 @@ |
| 32449 | 32471 | |
| 32450 | 32472 | /* Create/open the named mutex */ |
| 32451 | 32473 | pFile->hMutex = osCreateMutexW(NULL, FALSE, zName); |
| 32452 | 32474 | if (!pFile->hMutex){ |
| 32453 | 32475 | pFile->lastErrno = osGetLastError(); |
| 32454 | | - winLogError(SQLITE_IOERR, pFile->lastErrno, |
| 32455 | | - "winceCreateLock1", zFilename); |
| 32456 | 32476 | sqlite3_free(zName); |
| 32457 | | - return SQLITE_IOERR; |
| 32477 | + return winLogError(SQLITE_IOERR, pFile->lastErrno, |
| 32478 | + "winceCreateLock1", zFilename); |
| 32458 | 32479 | } |
| 32459 | 32480 | |
| 32460 | 32481 | /* Acquire the mutex before continuing */ |
| 32461 | 32482 | winceMutexAcquire(pFile->hMutex); |
| 32462 | 32483 | |
| | @@ -32788,11 +32809,11 @@ |
| 32788 | 32809 | |
| 32789 | 32810 | if( (dwRet==INVALID_SET_FILE_POINTER |
| 32790 | 32811 | && ((lastErrno = osGetLastError())!=NO_ERROR)) ){ |
| 32791 | 32812 | pFile->lastErrno = lastErrno; |
| 32792 | 32813 | winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno, |
| 32793 | | - "winSeekFile", pFile->zPath); |
| 32814 | + "winSeekFile", pFile->zPath); |
| 32794 | 32815 | OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h)); |
| 32795 | 32816 | return 1; |
| 32796 | 32817 | } |
| 32797 | 32818 | |
| 32798 | 32819 | OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h)); |
| | @@ -32809,11 +32830,11 @@ |
| 32809 | 32830 | bRet = osSetFilePointerEx(pFile->h, x, 0, FILE_BEGIN); |
| 32810 | 32831 | |
| 32811 | 32832 | if(!bRet){ |
| 32812 | 32833 | pFile->lastErrno = osGetLastError(); |
| 32813 | 32834 | winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno, |
| 32814 | | - "winSeekFile", pFile->zPath); |
| 32835 | + "winSeekFile", pFile->zPath); |
| 32815 | 32836 | OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h)); |
| 32816 | 32837 | return 1; |
| 32817 | 32838 | } |
| 32818 | 32839 | |
| 32819 | 32840 | OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h)); |
| | @@ -32820,11 +32841,12 @@ |
| 32820 | 32841 | return 0; |
| 32821 | 32842 | #endif |
| 32822 | 32843 | } |
| 32823 | 32844 | |
| 32824 | 32845 | #if SQLITE_MAX_MMAP_SIZE>0 |
| 32825 | | -/* Forward references to VFS methods */ |
| 32846 | +/* Forward references to VFS helper methods used for memory mapped files */ |
| 32847 | +static int winMapfile(winFile*, sqlite3_int64); |
| 32826 | 32848 | static int winUnmapfile(winFile*); |
| 32827 | 32849 | #endif |
| 32828 | 32850 | |
| 32829 | 32851 | /* |
| 32830 | 32852 | ** Close a file. |
| | @@ -32941,11 +32963,11 @@ |
| 32941 | 32963 | DWORD lastErrno; |
| 32942 | 32964 | if( winRetryIoerr(&nRetry, &lastErrno) ) continue; |
| 32943 | 32965 | pFile->lastErrno = lastErrno; |
| 32944 | 32966 | OSTRACE(("READ file=%p, rc=SQLITE_IOERR_READ\n", pFile->h)); |
| 32945 | 32967 | return winLogError(SQLITE_IOERR_READ, pFile->lastErrno, |
| 32946 | | - "winRead", pFile->zPath); |
| 32968 | + "winRead", pFile->zPath); |
| 32947 | 32969 | } |
| 32948 | 32970 | winLogIoerr(nRetry); |
| 32949 | 32971 | if( nRead<(DWORD)amt ){ |
| 32950 | 32972 | /* Unread parts of the buffer must be zero-filled */ |
| 32951 | 32973 | memset(&((char*)pBuf)[nRead], 0, amt-nRead); |
| | @@ -33047,15 +33069,16 @@ |
| 33047 | 33069 | |
| 33048 | 33070 | if( rc ){ |
| 33049 | 33071 | if( ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ) |
| 33050 | 33072 | || ( pFile->lastErrno==ERROR_DISK_FULL )){ |
| 33051 | 33073 | OSTRACE(("WRITE file=%p, rc=SQLITE_FULL\n", pFile->h)); |
| 33052 | | - return SQLITE_FULL; |
| 33074 | + return winLogError(SQLITE_FULL, pFile->lastErrno, |
| 33075 | + "winWrite1", pFile->zPath); |
| 33053 | 33076 | } |
| 33054 | 33077 | OSTRACE(("WRITE file=%p, rc=SQLITE_IOERR_WRITE\n", pFile->h)); |
| 33055 | 33078 | return winLogError(SQLITE_IOERR_WRITE, pFile->lastErrno, |
| 33056 | | - "winWrite", pFile->zPath); |
| 33079 | + "winWrite2", pFile->zPath); |
| 33057 | 33080 | }else{ |
| 33058 | 33081 | winLogIoerr(nRetry); |
| 33059 | 33082 | } |
| 33060 | 33083 | OSTRACE(("WRITE file=%p, rc=SQLITE_OK\n", pFile->h)); |
| 33061 | 33084 | return SQLITE_OK; |
| | @@ -33175,11 +33198,11 @@ |
| 33175 | 33198 | return SQLITE_OK; |
| 33176 | 33199 | }else{ |
| 33177 | 33200 | pFile->lastErrno = osGetLastError(); |
| 33178 | 33201 | OSTRACE(("SYNC file=%p, rc=SQLITE_IOERR_FSYNC\n", pFile->h)); |
| 33179 | 33202 | return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno, |
| 33180 | | - "winSync", pFile->zPath); |
| 33203 | + "winSync", pFile->zPath); |
| 33181 | 33204 | } |
| 33182 | 33205 | #endif |
| 33183 | 33206 | } |
| 33184 | 33207 | |
| 33185 | 33208 | /* |
| | @@ -33216,11 +33239,11 @@ |
| 33216 | 33239 | *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits; |
| 33217 | 33240 | if( (lowerBits == INVALID_FILE_SIZE) |
| 33218 | 33241 | && ((lastErrno = osGetLastError())!=NO_ERROR) ){ |
| 33219 | 33242 | pFile->lastErrno = lastErrno; |
| 33220 | 33243 | rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno, |
| 33221 | | - "winFileSize", pFile->zPath); |
| 33244 | + "winFileSize", pFile->zPath); |
| 33222 | 33245 | } |
| 33223 | 33246 | } |
| 33224 | 33247 | #endif |
| 33225 | 33248 | OSTRACE(("SIZE file=%p, pSize=%p, *pSize=%lld, rc=%s\n", |
| 33226 | 33249 | pFile->h, pSize, *pSize, sqlite3ErrName(rc))); |
| | @@ -33311,11 +33334,11 @@ |
| 33311 | 33334 | } |
| 33312 | 33335 | #endif |
| 33313 | 33336 | if( res==0 && ((lastErrno = osGetLastError())!=ERROR_NOT_LOCKED) ){ |
| 33314 | 33337 | pFile->lastErrno = lastErrno; |
| 33315 | 33338 | winLogError(SQLITE_IOERR_UNLOCK, pFile->lastErrno, |
| 33316 | | - "winUnlockReadLock", pFile->zPath); |
| 33339 | + "winUnlockReadLock", pFile->zPath); |
| 33317 | 33340 | } |
| 33318 | 33341 | OSTRACE(("READ-UNLOCK file=%p, rc=%s\n", pFile->h, sqlite3ErrName(res))); |
| 33319 | 33342 | return res; |
| 33320 | 33343 | } |
| 33321 | 33344 | |
| | @@ -33524,11 +33547,11 @@ |
| 33524 | 33547 | winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); |
| 33525 | 33548 | if( locktype==SHARED_LOCK && !winGetReadLock(pFile) ){ |
| 33526 | 33549 | /* This should never happen. We should always be able to |
| 33527 | 33550 | ** reacquire the read lock */ |
| 33528 | 33551 | rc = winLogError(SQLITE_IOERR_UNLOCK, osGetLastError(), |
| 33529 | | - "winUnlock", pFile->zPath); |
| 33552 | + "winUnlock", pFile->zPath); |
| 33530 | 33553 | } |
| 33531 | 33554 | } |
| 33532 | 33555 | if( type>=RESERVED_LOCK ){ |
| 33533 | 33556 | winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0); |
| 33534 | 33557 | } |
| | @@ -33558,15 +33581,14 @@ |
| 33558 | 33581 | }else{ |
| 33559 | 33582 | pFile->ctrlFlags |= mask; |
| 33560 | 33583 | } |
| 33561 | 33584 | } |
| 33562 | 33585 | |
| 33563 | | -/* Forward declaration */ |
| 33586 | +/* Forward references to VFS helper methods used for temporary files */ |
| 33564 | 33587 | static int winGetTempname(sqlite3_vfs *, char **); |
| 33565 | | -#if SQLITE_MAX_MMAP_SIZE>0 |
| 33566 | | -static int winMapfile(winFile*, sqlite3_int64); |
| 33567 | | -#endif |
| 33588 | +static int winIsDir(const void *); |
| 33589 | +static BOOL winIsDriveLetterAndColon(const char *); |
| 33568 | 33590 | |
| 33569 | 33591 | /* |
| 33570 | 33592 | ** Control and query of the open file handle. |
| 33571 | 33593 | */ |
| 33572 | 33594 | static int winFileControl(sqlite3_file *id, int op, void *pArg){ |
| | @@ -33640,11 +33662,11 @@ |
| 33640 | 33662 | char *zTFile = 0; |
| 33641 | 33663 | int rc = winGetTempname(pFile->pVfs, &zTFile); |
| 33642 | 33664 | if( rc==SQLITE_OK ){ |
| 33643 | 33665 | *(char**)pArg = zTFile; |
| 33644 | 33666 | } |
| 33645 | | - OSTRACE(("FCNTL file=%p, rc=%d\n", pFile->h, rc)); |
| 33667 | + OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc))); |
| 33646 | 33668 | return rc; |
| 33647 | 33669 | } |
| 33648 | 33670 | #if SQLITE_MAX_MMAP_SIZE>0 |
| 33649 | 33671 | case SQLITE_FCNTL_MMAP_SIZE: { |
| 33650 | 33672 | i64 newLimit = *(i64*)pArg; |
| | @@ -33658,11 +33680,11 @@ |
| 33658 | 33680 | if( pFile->mmapSize>0 ){ |
| 33659 | 33681 | (void)winUnmapfile(pFile); |
| 33660 | 33682 | rc = winMapfile(pFile, -1); |
| 33661 | 33683 | } |
| 33662 | 33684 | } |
| 33663 | | - OSTRACE(("FCNTL file=%p, rc=%d\n", pFile->h, rc)); |
| 33685 | + OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc))); |
| 33664 | 33686 | return rc; |
| 33665 | 33687 | } |
| 33666 | 33688 | #endif |
| 33667 | 33689 | } |
| 33668 | 33690 | OSTRACE(("FCNTL file=%p, rc=SQLITE_NOTFOUND\n", pFile->h)); |
| | @@ -33974,11 +33996,11 @@ |
| 33974 | 33996 | */ |
| 33975 | 33997 | if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){ |
| 33976 | 33998 | rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0); |
| 33977 | 33999 | if( rc!=SQLITE_OK ){ |
| 33978 | 34000 | rc = winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(), |
| 33979 | | - "winOpenShm", pDbFd->zPath); |
| 34001 | + "winOpenShm", pDbFd->zPath); |
| 33980 | 34002 | } |
| 33981 | 34003 | } |
| 33982 | 34004 | if( rc==SQLITE_OK ){ |
| 33983 | 34005 | winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1); |
| 33984 | 34006 | rc = winShmSystemLock(pShmNode, _SHM_RDLCK, WIN_SHM_DMS, 1); |
| | @@ -34234,11 +34256,11 @@ |
| 34234 | 34256 | ** large enough to contain the requested region). |
| 34235 | 34257 | */ |
| 34236 | 34258 | rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz); |
| 34237 | 34259 | if( rc!=SQLITE_OK ){ |
| 34238 | 34260 | rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(), |
| 34239 | | - "winShmMap1", pDbFd->zPath); |
| 34261 | + "winShmMap1", pDbFd->zPath); |
| 34240 | 34262 | goto shmpage_out; |
| 34241 | 34263 | } |
| 34242 | 34264 | |
| 34243 | 34265 | if( sz<nByte ){ |
| 34244 | 34266 | /* The requested memory region does not exist. If isWrite is set to |
| | @@ -34249,11 +34271,11 @@ |
| 34249 | 34271 | */ |
| 34250 | 34272 | if( !isWrite ) goto shmpage_out; |
| 34251 | 34273 | rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte); |
| 34252 | 34274 | if( rc!=SQLITE_OK ){ |
| 34253 | 34275 | rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(), |
| 34254 | | - "winShmMap2", pDbFd->zPath); |
| 34276 | + "winShmMap2", pDbFd->zPath); |
| 34255 | 34277 | goto shmpage_out; |
| 34256 | 34278 | } |
| 34257 | 34279 | } |
| 34258 | 34280 | |
| 34259 | 34281 | /* Map the requested memory region into this processes address space. */ |
| | @@ -34303,11 +34325,11 @@ |
| 34303 | 34325 | szRegion, pMap ? "ok" : "failed")); |
| 34304 | 34326 | } |
| 34305 | 34327 | if( !pMap ){ |
| 34306 | 34328 | pShmNode->lastErrno = osGetLastError(); |
| 34307 | 34329 | rc = winLogError(SQLITE_IOERR_SHMMAP, pShmNode->lastErrno, |
| 34308 | | - "winShmMap3", pDbFd->zPath); |
| 34330 | + "winShmMap3", pDbFd->zPath); |
| 34309 | 34331 | if( hMap ) osCloseHandle(hMap); |
| 34310 | 34332 | goto shmpage_out; |
| 34311 | 34333 | } |
| 34312 | 34334 | |
| 34313 | 34335 | pShmNode->aRegion[pShmNode->nRegion].pMap = pMap; |
| | @@ -34351,11 +34373,11 @@ |
| 34351 | 34373 | pFile->lastErrno = osGetLastError(); |
| 34352 | 34374 | OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, pMapRegion=%p, " |
| 34353 | 34375 | "rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(), pFile, |
| 34354 | 34376 | pFile->pMapRegion)); |
| 34355 | 34377 | return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno, |
| 34356 | | - "winUnmap1", pFile->zPath); |
| 34378 | + "winUnmapfile1", pFile->zPath); |
| 34357 | 34379 | } |
| 34358 | 34380 | pFile->pMapRegion = 0; |
| 34359 | 34381 | pFile->mmapSize = 0; |
| 34360 | 34382 | pFile->mmapSizeActual = 0; |
| 34361 | 34383 | } |
| | @@ -34363,11 +34385,11 @@ |
| 34363 | 34385 | if( !osCloseHandle(pFile->hMap) ){ |
| 34364 | 34386 | pFile->lastErrno = osGetLastError(); |
| 34365 | 34387 | OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, rc=SQLITE_IOERR_MMAP\n", |
| 34366 | 34388 | osGetCurrentProcessId(), pFile, pFile->hMap)); |
| 34367 | 34389 | return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno, |
| 34368 | | - "winUnmap2", pFile->zPath); |
| 34390 | + "winUnmapfile2", pFile->zPath); |
| 34369 | 34391 | } |
| 34370 | 34392 | pFile->hMap = NULL; |
| 34371 | 34393 | } |
| 34372 | 34394 | OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n", |
| 34373 | 34395 | osGetCurrentProcessId(), pFile)); |
| | @@ -34438,14 +34460,14 @@ |
| 34438 | 34460 | (DWORD)(nMap & 0xffffffff), NULL); |
| 34439 | 34461 | #endif |
| 34440 | 34462 | if( pFd->hMap==NULL ){ |
| 34441 | 34463 | pFd->lastErrno = osGetLastError(); |
| 34442 | 34464 | rc = winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno, |
| 34443 | | - "winMapfile", pFd->zPath); |
| 34465 | + "winMapfile1", pFd->zPath); |
| 34444 | 34466 | /* Log the error, but continue normal operation using xRead/xWrite */ |
| 34445 | | - OSTRACE(("MAP-FILE-CREATE pid=%lu, pFile=%p, rc=SQLITE_IOERR_MMAP\n", |
| 34446 | | - osGetCurrentProcessId(), pFd)); |
| 34467 | + OSTRACE(("MAP-FILE-CREATE pid=%lu, pFile=%p, rc=%s\n", |
| 34468 | + osGetCurrentProcessId(), pFd, sqlite3ErrName(rc))); |
| 34447 | 34469 | return SQLITE_OK; |
| 34448 | 34470 | } |
| 34449 | 34471 | assert( (nMap % winSysInfo.dwPageSize)==0 ); |
| 34450 | 34472 | assert( sizeof(SIZE_T)==sizeof(sqlite3_int64) || nMap<=0xffffffff ); |
| 34451 | 34473 | #if SQLITE_OS_WINRT |
| | @@ -34455,14 +34477,15 @@ |
| 34455 | 34477 | #endif |
| 34456 | 34478 | if( pNew==NULL ){ |
| 34457 | 34479 | osCloseHandle(pFd->hMap); |
| 34458 | 34480 | pFd->hMap = NULL; |
| 34459 | 34481 | pFd->lastErrno = osGetLastError(); |
| 34460 | | - winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno, |
| 34461 | | - "winMapfile", pFd->zPath); |
| 34462 | | - OSTRACE(("MAP-FILE-MAP pid=%lu, pFile=%p, rc=SQLITE_IOERR_MMAP\n", |
| 34463 | | - osGetCurrentProcessId(), pFd)); |
| 34482 | + rc = winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno, |
| 34483 | + "winMapfile2", pFd->zPath); |
| 34484 | + /* Log the error, but continue normal operation using xRead/xWrite */ |
| 34485 | + OSTRACE(("MAP-FILE-MAP pid=%lu, pFile=%p, rc=%s\n", |
| 34486 | + osGetCurrentProcessId(), pFd, sqlite3ErrName(rc))); |
| 34464 | 34487 | return SQLITE_OK; |
| 34465 | 34488 | } |
| 34466 | 34489 | pFd->pMapRegion = pNew; |
| 34467 | 34490 | pFd->mmapSize = nMap; |
| 34468 | 34491 | pFd->mmapSizeActual = nMap; |
| | @@ -34596,18 +34619,37 @@ |
| 34596 | 34619 | **************************** sqlite3_vfs methods **************************** |
| 34597 | 34620 | ** |
| 34598 | 34621 | ** This division contains the implementation of methods on the |
| 34599 | 34622 | ** sqlite3_vfs object. |
| 34600 | 34623 | */ |
| 34624 | + |
| 34625 | +/* |
| 34626 | +** Convert a filename from whatever the underlying operating system |
| 34627 | +** supports for filenames into UTF-8. Space to hold the result is |
| 34628 | +** obtained from malloc and must be freed by the calling function. |
| 34629 | +*/ |
| 34630 | +static char *winConvertToUtf8Filename(const void *zFilename){ |
| 34631 | + char *zConverted = 0; |
| 34632 | + if( osIsNT() ){ |
| 34633 | + zConverted = winUnicodeToUtf8(zFilename); |
| 34634 | + } |
| 34635 | +#ifdef SQLITE_WIN32_HAS_ANSI |
| 34636 | + else{ |
| 34637 | + zConverted = sqlite3_win32_mbcs_to_utf8(zFilename); |
| 34638 | + } |
| 34639 | +#endif |
| 34640 | + /* caller will handle out of memory */ |
| 34641 | + return zConverted; |
| 34642 | +} |
| 34601 | 34643 | |
| 34602 | 34644 | /* |
| 34603 | 34645 | ** Convert a UTF-8 filename into whatever form the underlying |
| 34604 | 34646 | ** operating system wants filenames in. Space to hold the result |
| 34605 | 34647 | ** is obtained from malloc and must be freed by the calling |
| 34606 | 34648 | ** function. |
| 34607 | 34649 | */ |
| 34608 | | -static void *winConvertUtf8Filename(const char *zFilename){ |
| 34650 | +static void *winConvertFromUtf8Filename(const char *zFilename){ |
| 34609 | 34651 | void *zConverted = 0; |
| 34610 | 34652 | if( osIsNT() ){ |
| 34611 | 34653 | zConverted = winUtf8ToUnicode(zFilename); |
| 34612 | 34654 | } |
| 34613 | 34655 | #ifdef SQLITE_WIN32_HAS_ANSI |
| | @@ -34668,11 +34710,94 @@ |
| 34668 | 34710 | if( sqlite3_temp_directory ){ |
| 34669 | 34711 | sqlite3_snprintf(nBuf-30, zBuf, "%s%s", sqlite3_temp_directory, |
| 34670 | 34712 | winEndsInDirSep(sqlite3_temp_directory) ? "" : |
| 34671 | 34713 | winGetDirDep()); |
| 34672 | 34714 | } |
| 34673 | | -#if !SQLITE_OS_WINRT |
| 34715 | +#if defined(__CYGWIN__) |
| 34716 | + else{ |
| 34717 | + static const char *azDirs[] = { |
| 34718 | + 0, /* getenv("SQLITE_TMPDIR") */ |
| 34719 | + 0, /* getenv("TMPDIR") */ |
| 34720 | + 0, /* getenv("TMP") */ |
| 34721 | + 0, /* getenv("TEMP") */ |
| 34722 | + 0, /* getenv("USERPROFILE") */ |
| 34723 | + "/var/tmp", |
| 34724 | + "/usr/tmp", |
| 34725 | + "/tmp", |
| 34726 | + ".", |
| 34727 | + 0 /* List terminator */ |
| 34728 | + }; |
| 34729 | + unsigned int i; |
| 34730 | + const char *zDir = 0; |
| 34731 | + |
| 34732 | + if( !azDirs[0] ) azDirs[0] = getenv("SQLITE_TMPDIR"); |
| 34733 | + if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR"); |
| 34734 | + if( !azDirs[2] ) azDirs[2] = getenv("TMP"); |
| 34735 | + if( !azDirs[3] ) azDirs[3] = getenv("TEMP"); |
| 34736 | + if( !azDirs[4] ) azDirs[4] = getenv("USERPROFILE"); |
| 34737 | + for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); zDir=azDirs[i++]){ |
| 34738 | + void *zConverted; |
| 34739 | + if( zDir==0 ) continue; |
| 34740 | + /* If the path starts with a drive letter followed by the colon |
| 34741 | + ** character, assume it is already a native Win32 path; otherwise, |
| 34742 | + ** it must be converted to a native Win32 path prior via the Cygwin |
| 34743 | + ** API prior to using it. |
| 34744 | + */ |
| 34745 | + if( winIsDriveLetterAndColon(zDir) ){ |
| 34746 | + zConverted = winConvertFromUtf8Filename(zDir); |
| 34747 | + if( !zConverted ){ |
| 34748 | + OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); |
| 34749 | + return SQLITE_IOERR_NOMEM; |
| 34750 | + } |
| 34751 | + if( winIsDir(zConverted) ){ |
| 34752 | + sqlite3_snprintf(nBuf-30, zBuf, "%s", zDir); |
| 34753 | + sqlite3_free(zConverted); |
| 34754 | + break; |
| 34755 | + } |
| 34756 | + sqlite3_free(zConverted); |
| 34757 | + }else{ |
| 34758 | + zConverted = sqlite3MallocZero( nBuf+1 ); |
| 34759 | + if( !zConverted ){ |
| 34760 | + OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); |
| 34761 | + return SQLITE_IOERR_NOMEM; |
| 34762 | + } |
| 34763 | + if( cygwin_conv_path( |
| 34764 | + osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A, zDir, |
| 34765 | + zConverted, nBuf+1)<0 ){ |
| 34766 | + sqlite3_free(zConverted); |
| 34767 | + OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_CONVPATH\n")); |
| 34768 | + return winLogError(SQLITE_IOERR_CONVPATH, (DWORD)errno, |
| 34769 | + "winGetTempname1", zDir); |
| 34770 | + } |
| 34771 | + if( winIsDir(zConverted) ){ |
| 34772 | + /* At this point, we know the candidate directory exists and should |
| 34773 | + ** be used. However, we may need to convert the string containing |
| 34774 | + ** its name into UTF-8 (i.e. if it is UTF-16 right now). |
| 34775 | + */ |
| 34776 | + if( osIsNT() ){ |
| 34777 | + char *zUtf8 = winUnicodeToUtf8(zConverted); |
| 34778 | + if( !zUtf8 ){ |
| 34779 | + sqlite3_free(zConverted); |
| 34780 | + OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); |
| 34781 | + return SQLITE_IOERR_NOMEM; |
| 34782 | + } |
| 34783 | + sqlite3_snprintf(nBuf-30, zBuf, "%s", zUtf8); |
| 34784 | + sqlite3_free(zUtf8); |
| 34785 | + sqlite3_free(zConverted); |
| 34786 | + break; |
| 34787 | + }else{ |
| 34788 | + sqlite3_snprintf(nBuf-30, zBuf, "%s", zConverted); |
| 34789 | + sqlite3_free(zConverted); |
| 34790 | + break; |
| 34791 | + } |
| 34792 | + } |
| 34793 | + sqlite3_free(zConverted); |
| 34794 | + } |
| 34795 | + break; |
| 34796 | + } |
| 34797 | + } |
| 34798 | +#elif !SQLITE_OS_WINRT && !defined(__CYGWIN__) |
| 34674 | 34799 | else if( osIsNT() ){ |
| 34675 | 34800 | char *zMulti; |
| 34676 | 34801 | LPWSTR zWidePath = sqlite3MallocZero( nBuf*sizeof(WCHAR) ); |
| 34677 | 34802 | if( !zWidePath ){ |
| 34678 | 34803 | sqlite3_free(zBuf); |
| | @@ -34681,11 +34806,12 @@ |
| 34681 | 34806 | } |
| 34682 | 34807 | if( osGetTempPathW(nBuf, zWidePath)==0 ){ |
| 34683 | 34808 | sqlite3_free(zWidePath); |
| 34684 | 34809 | sqlite3_free(zBuf); |
| 34685 | 34810 | OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_GETTEMPPATH\n")); |
| 34686 | | - return SQLITE_IOERR_GETTEMPPATH; |
| 34811 | + return winLogError(SQLITE_IOERR_GETTEMPPATH, osGetLastError(), |
| 34812 | + "winGetTempname1", 0); |
| 34687 | 34813 | } |
| 34688 | 34814 | zMulti = winUnicodeToUtf8(zWidePath); |
| 34689 | 34815 | if( zMulti ){ |
| 34690 | 34816 | sqlite3_snprintf(nBuf-30, zBuf, "%s", zMulti); |
| 34691 | 34817 | sqlite3_free(zMulti); |
| | @@ -34707,11 +34833,12 @@ |
| 34707 | 34833 | return SQLITE_IOERR_NOMEM; |
| 34708 | 34834 | } |
| 34709 | 34835 | if( osGetTempPathA(nBuf, zMbcsPath)==0 ){ |
| 34710 | 34836 | sqlite3_free(zBuf); |
| 34711 | 34837 | OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_GETTEMPPATH\n")); |
| 34712 | | - return SQLITE_IOERR_GETTEMPPATH; |
| 34838 | + return winLogError(SQLITE_IOERR_GETTEMPPATH, osGetLastError(), |
| 34839 | + "winGetTempname2", 0); |
| 34713 | 34840 | } |
| 34714 | 34841 | zUtf8 = sqlite3_win32_mbcs_to_utf8(zMbcsPath); |
| 34715 | 34842 | if( zUtf8 ){ |
| 34716 | 34843 | sqlite3_snprintf(nBuf-30, zBuf, "%s", zUtf8); |
| 34717 | 34844 | sqlite3_free(zUtf8); |
| | @@ -34730,11 +34857,11 @@ |
| 34730 | 34857 | nLen = sqlite3Strlen30(zBuf); |
| 34731 | 34858 | |
| 34732 | 34859 | if( (nLen + sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX) + 18) >= nBuf ){ |
| 34733 | 34860 | sqlite3_free(zBuf); |
| 34734 | 34861 | OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n")); |
| 34735 | | - return SQLITE_ERROR; |
| 34862 | + return winLogError(SQLITE_ERROR, 0, "winGetTempname3", 0); |
| 34736 | 34863 | } |
| 34737 | 34864 | |
| 34738 | 34865 | sqlite3_snprintf(nBuf-18-nLen, zBuf+nLen, SQLITE_TEMP_FILE_PREFIX); |
| 34739 | 34866 | |
| 34740 | 34867 | j = sqlite3Strlen30(zBuf); |
| | @@ -34886,11 +35013,11 @@ |
| 34886 | 35013 | */ |
| 34887 | 35014 | assert( (eType!=SQLITE_OPEN_MAIN_DB) || (flags & SQLITE_OPEN_URI) || |
| 34888 | 35015 | zUtf8Name[sqlite3Strlen30(zUtf8Name)+1]==0 ); |
| 34889 | 35016 | |
| 34890 | 35017 | /* Convert the filename to the system encoding. */ |
| 34891 | | - zConverted = winConvertUtf8Filename(zUtf8Name); |
| 35018 | + zConverted = winConvertFromUtf8Filename(zUtf8Name); |
| 34892 | 35019 | if( zConverted==0 ){ |
| 34893 | 35020 | sqlite3_free(zTmpname); |
| 34894 | 35021 | OSTRACE(("OPEN name=%s, rc=SQLITE_IOERR_NOMEM", zUtf8Name)); |
| 34895 | 35022 | return SQLITE_IOERR_NOMEM; |
| 34896 | 35023 | } |
| | @@ -35087,11 +35214,11 @@ |
| 35087 | 35214 | UNUSED_PARAMETER(syncDir); |
| 35088 | 35215 | |
| 35089 | 35216 | SimulateIOError(return SQLITE_IOERR_DELETE); |
| 35090 | 35217 | OSTRACE(("DELETE name=%s, syncDir=%d\n", zFilename, syncDir)); |
| 35091 | 35218 | |
| 35092 | | - zConverted = winConvertUtf8Filename(zFilename); |
| 35219 | + zConverted = winConvertFromUtf8Filename(zFilename); |
| 35093 | 35220 | if( zConverted==0 ){ |
| 35094 | 35221 | OSTRACE(("DELETE name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename)); |
| 35095 | 35222 | return SQLITE_IOERR_NOMEM; |
| 35096 | 35223 | } |
| 35097 | 35224 | if( osIsNT() ){ |
| | @@ -35167,12 +35294,11 @@ |
| 35167 | 35294 | } |
| 35168 | 35295 | } while(1); |
| 35169 | 35296 | } |
| 35170 | 35297 | #endif |
| 35171 | 35298 | if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){ |
| 35172 | | - rc = winLogError(SQLITE_IOERR_DELETE, lastErrno, |
| 35173 | | - "winDelete", zFilename); |
| 35299 | + rc = winLogError(SQLITE_IOERR_DELETE, lastErrno, "winDelete", zFilename); |
| 35174 | 35300 | }else{ |
| 35175 | 35301 | winLogIoerr(cnt); |
| 35176 | 35302 | } |
| 35177 | 35303 | sqlite3_free(zConverted); |
| 35178 | 35304 | OSTRACE(("DELETE name=%s, rc=%s\n", zFilename, sqlite3ErrName(rc))); |
| | @@ -35196,11 +35322,11 @@ |
| 35196 | 35322 | |
| 35197 | 35323 | SimulateIOError( return SQLITE_IOERR_ACCESS; ); |
| 35198 | 35324 | OSTRACE(("ACCESS name=%s, flags=%x, pResOut=%p\n", |
| 35199 | 35325 | zFilename, flags, pResOut)); |
| 35200 | 35326 | |
| 35201 | | - zConverted = winConvertUtf8Filename(zFilename); |
| 35327 | + zConverted = winConvertFromUtf8Filename(zFilename); |
| 35202 | 35328 | if( zConverted==0 ){ |
| 35203 | 35329 | OSTRACE(("ACCESS name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename)); |
| 35204 | 35330 | return SQLITE_IOERR_NOMEM; |
| 35205 | 35331 | } |
| 35206 | 35332 | if( osIsNT() ){ |
| | @@ -35222,13 +35348,13 @@ |
| 35222 | 35348 | attr = sAttrData.dwFileAttributes; |
| 35223 | 35349 | } |
| 35224 | 35350 | }else{ |
| 35225 | 35351 | winLogIoerr(cnt); |
| 35226 | 35352 | if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){ |
| 35227 | | - winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess", zFilename); |
| 35228 | 35353 | sqlite3_free(zConverted); |
| 35229 | | - return SQLITE_IOERR_ACCESS; |
| 35354 | + return winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess", |
| 35355 | + zFilename); |
| 35230 | 35356 | }else{ |
| 35231 | 35357 | attr = INVALID_FILE_ATTRIBUTES; |
| 35232 | 35358 | } |
| 35233 | 35359 | } |
| 35234 | 35360 | } |
| | @@ -35254,10 +35380,19 @@ |
| 35254 | 35380 | OSTRACE(("ACCESS name=%s, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n", |
| 35255 | 35381 | zFilename, pResOut, *pResOut)); |
| 35256 | 35382 | return SQLITE_OK; |
| 35257 | 35383 | } |
| 35258 | 35384 | |
| 35385 | +/* |
| 35386 | +** Returns non-zero if the specified path name starts with a drive letter |
| 35387 | +** followed by a colon character. |
| 35388 | +*/ |
| 35389 | +static BOOL winIsDriveLetterAndColon( |
| 35390 | + const char *zPathname |
| 35391 | +){ |
| 35392 | + return ( sqlite3Isalpha(zPathname[0]) && zPathname[1]==':' ); |
| 35393 | +} |
| 35259 | 35394 | |
| 35260 | 35395 | /* |
| 35261 | 35396 | ** Returns non-zero if the specified path name should be used verbatim. If |
| 35262 | 35397 | ** non-zero is returned from this function, the calling function must simply |
| 35263 | 35398 | ** use the provided path name verbatim -OR- resolve it into a full path name |
| | @@ -35281,11 +35416,11 @@ |
| 35281 | 35416 | ** If the path name starts with a letter and a colon it is either a volume |
| 35282 | 35417 | ** relative path or an absolute path. Callers of this function must not |
| 35283 | 35418 | ** attempt to treat it as a relative path name (i.e. they should simply use |
| 35284 | 35419 | ** it verbatim). |
| 35285 | 35420 | */ |
| 35286 | | - if ( sqlite3Isalpha(zPathname[0]) && zPathname[1]==':' ){ |
| 35421 | + if ( winIsDriveLetterAndColon(zPathname) ){ |
| 35287 | 35422 | return TRUE; |
| 35288 | 35423 | } |
| 35289 | 35424 | |
| 35290 | 35425 | /* |
| 35291 | 35426 | ** If we get to this point, the path name should almost certainly be a purely |
| | @@ -35317,28 +35452,25 @@ |
| 35317 | 35452 | ** for converting the relative path name to an absolute |
| 35318 | 35453 | ** one by prepending the data directory and a slash. |
| 35319 | 35454 | */ |
| 35320 | 35455 | char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 ); |
| 35321 | 35456 | if( !zOut ){ |
| 35322 | | - winLogError(SQLITE_IOERR_NOMEM, 0, "winFullPathname", zRelative); |
| 35323 | 35457 | return SQLITE_IOERR_NOMEM; |
| 35324 | 35458 | } |
| 35325 | 35459 | if( cygwin_conv_path(CCP_POSIX_TO_WIN_A|CCP_RELATIVE, zRelative, zOut, |
| 35326 | 35460 | pVfs->mxPathname+1)<0 ){ |
| 35327 | | - winLogError(SQLITE_CANTOPEN_FULLPATH, (DWORD)errno, "cygwin_conv_path", |
| 35328 | | - zRelative); |
| 35329 | 35461 | sqlite3_free(zOut); |
| 35330 | | - return SQLITE_CANTOPEN_FULLPATH; |
| 35462 | + return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno, |
| 35463 | + "winFullPathname1", zRelative); |
| 35331 | 35464 | } |
| 35332 | 35465 | sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%s%s", |
| 35333 | 35466 | sqlite3_data_directory, winGetDirDep(), zOut); |
| 35334 | 35467 | sqlite3_free(zOut); |
| 35335 | 35468 | }else{ |
| 35336 | 35469 | if( cygwin_conv_path(CCP_POSIX_TO_WIN_A, zRelative, zFull, nFull)<0 ){ |
| 35337 | | - winLogError(SQLITE_CANTOPEN_FULLPATH, (DWORD)errno, "cygwin_conv_path", |
| 35338 | | - zRelative); |
| 35339 | | - return SQLITE_CANTOPEN_FULLPATH; |
| 35470 | + return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno, |
| 35471 | + "winFullPathname2", zRelative); |
| 35340 | 35472 | } |
| 35341 | 35473 | } |
| 35342 | 35474 | return SQLITE_OK; |
| 35343 | 35475 | #endif |
| 35344 | 35476 | |
| | @@ -35367,11 +35499,11 @@ |
| 35367 | 35499 | char *zOut; |
| 35368 | 35500 | |
| 35369 | 35501 | /* If this path name begins with "/X:", where "X" is any alphabetic |
| 35370 | 35502 | ** character, discard the initial "/" from the pathname. |
| 35371 | 35503 | */ |
| 35372 | | - if( zRelative[0]=='/' && sqlite3Isalpha(zRelative[1]) && zRelative[2]==':' ){ |
| 35504 | + if( zRelative[0]=='/' && winIsDriveLetterAndColon(zRelative+1) ){ |
| 35373 | 35505 | zRelative++; |
| 35374 | 35506 | } |
| 35375 | 35507 | |
| 35376 | 35508 | /* It's odd to simulate an io-error here, but really this is just |
| 35377 | 35509 | ** using the io-error infrastructure to test that SQLite handles this |
| | @@ -35388,36 +35520,34 @@ |
| 35388 | 35520 | */ |
| 35389 | 35521 | sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%s%s", |
| 35390 | 35522 | sqlite3_data_directory, winGetDirDep(), zRelative); |
| 35391 | 35523 | return SQLITE_OK; |
| 35392 | 35524 | } |
| 35393 | | - zConverted = winConvertUtf8Filename(zRelative); |
| 35525 | + zConverted = winConvertFromUtf8Filename(zRelative); |
| 35394 | 35526 | if( zConverted==0 ){ |
| 35395 | 35527 | return SQLITE_IOERR_NOMEM; |
| 35396 | 35528 | } |
| 35397 | 35529 | if( osIsNT() ){ |
| 35398 | 35530 | LPWSTR zTemp; |
| 35399 | 35531 | nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0); |
| 35400 | 35532 | if( nByte==0 ){ |
| 35401 | | - winLogError(SQLITE_ERROR, osGetLastError(), |
| 35402 | | - "GetFullPathNameW1", zConverted); |
| 35403 | 35533 | sqlite3_free(zConverted); |
| 35404 | | - return SQLITE_CANTOPEN_FULLPATH; |
| 35534 | + return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(), |
| 35535 | + "winFullPathname1", zRelative); |
| 35405 | 35536 | } |
| 35406 | 35537 | nByte += 3; |
| 35407 | 35538 | zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) ); |
| 35408 | 35539 | if( zTemp==0 ){ |
| 35409 | 35540 | sqlite3_free(zConverted); |
| 35410 | 35541 | return SQLITE_IOERR_NOMEM; |
| 35411 | 35542 | } |
| 35412 | 35543 | nByte = osGetFullPathNameW((LPCWSTR)zConverted, nByte, zTemp, 0); |
| 35413 | 35544 | if( nByte==0 ){ |
| 35414 | | - winLogError(SQLITE_ERROR, osGetLastError(), |
| 35415 | | - "GetFullPathNameW2", zConverted); |
| 35416 | 35545 | sqlite3_free(zConverted); |
| 35417 | 35546 | sqlite3_free(zTemp); |
| 35418 | | - return SQLITE_CANTOPEN_FULLPATH; |
| 35547 | + return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(), |
| 35548 | + "winFullPathname2", zRelative); |
| 35419 | 35549 | } |
| 35420 | 35550 | sqlite3_free(zConverted); |
| 35421 | 35551 | zOut = winUnicodeToUtf8(zTemp); |
| 35422 | 35552 | sqlite3_free(zTemp); |
| 35423 | 35553 | } |
| | @@ -35424,28 +35554,26 @@ |
| 35424 | 35554 | #ifdef SQLITE_WIN32_HAS_ANSI |
| 35425 | 35555 | else{ |
| 35426 | 35556 | char *zTemp; |
| 35427 | 35557 | nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0); |
| 35428 | 35558 | if( nByte==0 ){ |
| 35429 | | - winLogError(SQLITE_ERROR, osGetLastError(), |
| 35430 | | - "GetFullPathNameA1", zConverted); |
| 35431 | 35559 | sqlite3_free(zConverted); |
| 35432 | | - return SQLITE_CANTOPEN_FULLPATH; |
| 35560 | + return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(), |
| 35561 | + "winFullPathname3", zRelative); |
| 35433 | 35562 | } |
| 35434 | 35563 | nByte += 3; |
| 35435 | 35564 | zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) ); |
| 35436 | 35565 | if( zTemp==0 ){ |
| 35437 | 35566 | sqlite3_free(zConverted); |
| 35438 | 35567 | return SQLITE_IOERR_NOMEM; |
| 35439 | 35568 | } |
| 35440 | 35569 | nByte = osGetFullPathNameA((char*)zConverted, nByte, zTemp, 0); |
| 35441 | 35570 | if( nByte==0 ){ |
| 35442 | | - winLogError(SQLITE_ERROR, osGetLastError(), |
| 35443 | | - "GetFullPathNameA2", zConverted); |
| 35444 | 35571 | sqlite3_free(zConverted); |
| 35445 | 35572 | sqlite3_free(zTemp); |
| 35446 | | - return SQLITE_CANTOPEN_FULLPATH; |
| 35573 | + return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(), |
| 35574 | + "winFullPathname4", zRelative); |
| 35447 | 35575 | } |
| 35448 | 35576 | sqlite3_free(zConverted); |
| 35449 | 35577 | zOut = sqlite3_win32_mbcs_to_utf8(zTemp); |
| 35450 | 35578 | sqlite3_free(zTemp); |
| 35451 | 35579 | } |
| | @@ -35469,11 +35597,11 @@ |
| 35469 | 35597 | ** Interfaces for opening a shared library, finding entry points |
| 35470 | 35598 | ** within the shared library, and closing the shared library. |
| 35471 | 35599 | */ |
| 35472 | 35600 | static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ |
| 35473 | 35601 | HANDLE h; |
| 35474 | | - void *zConverted = winConvertUtf8Filename(zFilename); |
| 35602 | + void *zConverted = winConvertFromUtf8Filename(zFilename); |
| 35475 | 35603 | UNUSED_PARAMETER(pVfs); |
| 35476 | 35604 | if( zConverted==0 ){ |
| 35477 | 35605 | return 0; |
| 35478 | 35606 | } |
| 35479 | 35607 | if( osIsNT() ){ |
| | @@ -60283,10 +60411,13 @@ |
| 60283 | 60411 | alloc.pParse = pParse; |
| 60284 | 60412 | alloc.pIdx = pIdx; |
| 60285 | 60413 | alloc.ppRec = ppRec; |
| 60286 | 60414 | alloc.iVal = iVal; |
| 60287 | 60415 | |
| 60416 | + /* Skip over any TK_COLLATE nodes */ |
| 60417 | + pExpr = sqlite3ExprSkipCollate(pExpr); |
| 60418 | + |
| 60288 | 60419 | if( !pExpr ){ |
| 60289 | 60420 | pVal = valueNew(pParse->db, &alloc); |
| 60290 | 60421 | if( pVal ){ |
| 60291 | 60422 | sqlite3VdbeMemSetNull((Mem*)pVal); |
| 60292 | 60423 | *pbOk = 1; |
| | @@ -80950,11 +81081,11 @@ |
| 80950 | 81081 | ** SQLITE_ENABLE_STAT3 defined. The functionality of sqlite_stat3 |
| 80951 | 81082 | ** is a superset of sqlite_stat2. The sqlite_stat4 is an enhanced |
| 80952 | 81083 | ** version of sqlite_stat3 and is only available when compiled with |
| 80953 | 81084 | ** SQLITE_ENABLE_STAT4 and in SQLite versions 3.8.0 and later. It is |
| 80954 | 81085 | ** not possible to enable both STAT3 and STAT4 at the same time. If they |
| 80955 | | -** are both enabled, then STAT4 is precedence. |
| 81086 | +** are both enabled, then STAT4 takes precedence. |
| 80956 | 81087 | ** |
| 80957 | 81088 | ** For most applications, sqlite_stat1 provides all the statisics required |
| 80958 | 81089 | ** for the query planner to make good choices. |
| 80959 | 81090 | ** |
| 80960 | 81091 | ** Format of sqlite_stat1: |
| | @@ -81261,11 +81392,11 @@ |
| 81261 | 81392 | u8 *pSpace; /* Allocated space not yet assigned */ |
| 81262 | 81393 | int i; /* Used to iterate through p->aSample[] */ |
| 81263 | 81394 | |
| 81264 | 81395 | p->iGet = -1; |
| 81265 | 81396 | p->mxSample = mxSample; |
| 81266 | | - p->nPSample = sqlite3_value_int64(argv[1])/(mxSample/3+1) + 1; |
| 81397 | + p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[1])/(mxSample/3+1) + 1); |
| 81267 | 81398 | p->current.anLt = &p->current.anEq[nColUp]; |
| 81268 | 81399 | sqlite3_randomness(sizeof(p->iPrn), &p->iPrn); |
| 81269 | 81400 | |
| 81270 | 81401 | /* Set up the Stat4Accum.a[] and aBest[] arrays */ |
| 81271 | 81402 | p->a = (struct Stat4Sample*)&p->current.anLt[nColUp]; |
| | @@ -81298,29 +81429,68 @@ |
| 81298 | 81429 | 0, /* xFinalize */ |
| 81299 | 81430 | "stat_init", /* zName */ |
| 81300 | 81431 | 0, /* pHash */ |
| 81301 | 81432 | 0 /* pDestructor */ |
| 81302 | 81433 | }; |
| 81434 | + |
| 81435 | +#ifdef SQLITE_ENABLE_STAT4 |
| 81436 | +/* |
| 81437 | +** pNew and pOld are both candidate non-periodic samples selected for |
| 81438 | +** the same column (pNew->iCol==pOld->iCol). Ignoring this column and |
| 81439 | +** considering only any trailing columns and the sample hash value, this |
| 81440 | +** function returns true if sample pNew is to be preferred over pOld. |
| 81441 | +** In other words, if we assume that the cardinalities of the selected |
| 81442 | +** column for pNew and pOld are equal, is pNew to be preferred over pOld. |
| 81443 | +** |
| 81444 | +** This function assumes that for each argument sample, the contents of |
| 81445 | +** the anEq[] array from pSample->anEq[pSample->iCol+1] onwards are valid. |
| 81446 | +*/ |
| 81447 | +static int sampleIsBetterPost( |
| 81448 | + Stat4Accum *pAccum, |
| 81449 | + Stat4Sample *pNew, |
| 81450 | + Stat4Sample *pOld |
| 81451 | +){ |
| 81452 | + int nCol = pAccum->nCol; |
| 81453 | + int i; |
| 81454 | + assert( pNew->iCol==pOld->iCol ); |
| 81455 | + for(i=pNew->iCol+1; i<nCol; i++){ |
| 81456 | + if( pNew->anEq[i]>pOld->anEq[i] ) return 1; |
| 81457 | + if( pNew->anEq[i]<pOld->anEq[i] ) return 0; |
| 81458 | + } |
| 81459 | + if( pNew->iHash>pOld->iHash ) return 1; |
| 81460 | + return 0; |
| 81461 | +} |
| 81462 | +#endif |
| 81303 | 81463 | |
| 81304 | 81464 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 81305 | 81465 | /* |
| 81306 | 81466 | ** Return true if pNew is to be preferred over pOld. |
| 81467 | +** |
| 81468 | +** This function assumes that for each argument sample, the contents of |
| 81469 | +** the anEq[] array from pSample->anEq[pSample->iCol] onwards are valid. |
| 81307 | 81470 | */ |
| 81308 | | -static int sampleIsBetter(Stat4Sample *pNew, Stat4Sample *pOld){ |
| 81471 | +static int sampleIsBetter( |
| 81472 | + Stat4Accum *pAccum, |
| 81473 | + Stat4Sample *pNew, |
| 81474 | + Stat4Sample *pOld |
| 81475 | +){ |
| 81309 | 81476 | tRowcnt nEqNew = pNew->anEq[pNew->iCol]; |
| 81310 | 81477 | tRowcnt nEqOld = pOld->anEq[pOld->iCol]; |
| 81311 | 81478 | |
| 81312 | 81479 | assert( pOld->isPSample==0 && pNew->isPSample==0 ); |
| 81313 | 81480 | assert( IsStat4 || (pNew->iCol==0 && pOld->iCol==0) ); |
| 81314 | 81481 | |
| 81315 | | - if( (nEqNew>nEqOld) |
| 81316 | | - || (nEqNew==nEqOld && pNew->iCol<pOld->iCol) |
| 81317 | | - || (nEqNew==nEqOld && pNew->iCol==pOld->iCol && pNew->iHash>pOld->iHash) |
| 81318 | | - ){ |
| 81319 | | - return 1; |
| 81482 | + if( (nEqNew>nEqOld) ) return 1; |
| 81483 | +#ifdef SQLITE_ENABLE_STAT4 |
| 81484 | + if( nEqNew==nEqOld ){ |
| 81485 | + if( pNew->iCol<pOld->iCol ) return 1; |
| 81486 | + return (pNew->iCol==pOld->iCol && sampleIsBetterPost(pAccum, pNew, pOld)); |
| 81320 | 81487 | } |
| 81321 | 81488 | return 0; |
| 81489 | +#else |
| 81490 | + return (nEqNew==nEqOld && pNew->iHash>pOld->iHash); |
| 81491 | +#endif |
| 81322 | 81492 | } |
| 81323 | 81493 | |
| 81324 | 81494 | /* |
| 81325 | 81495 | ** Copy the contents of object (*pFrom) into (*pTo). |
| 81326 | 81496 | */ |
| | @@ -81339,15 +81509,14 @@ |
| 81339 | 81509 | ** remove the least desirable sample from p->a[] to make room. |
| 81340 | 81510 | */ |
| 81341 | 81511 | static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){ |
| 81342 | 81512 | Stat4Sample *pSample; |
| 81343 | 81513 | int i; |
| 81344 | | - i64 iSeq; |
| 81345 | | - i64 iPos; |
| 81346 | 81514 | |
| 81347 | 81515 | assert( IsStat4 || nEqZero==0 ); |
| 81348 | 81516 | |
| 81517 | +#ifdef SQLITE_ENABLE_STAT4 |
| 81349 | 81518 | if( pNew->isPSample==0 ){ |
| 81350 | 81519 | Stat4Sample *pUpgrade = 0; |
| 81351 | 81520 | assert( pNew->anEq[pNew->iCol]>0 ); |
| 81352 | 81521 | |
| 81353 | 81522 | /* This sample is being added because the prefix that ends in column |
| | @@ -81357,12 +81526,13 @@ |
| 81357 | 81526 | ** existing sample that shares this prefix. */ |
| 81358 | 81527 | for(i=p->nSample-1; i>=0; i--){ |
| 81359 | 81528 | Stat4Sample *pOld = &p->a[i]; |
| 81360 | 81529 | if( pOld->anEq[pNew->iCol]==0 ){ |
| 81361 | 81530 | if( pOld->isPSample ) return; |
| 81362 | | - assert( sampleIsBetter(pNew, pOld) ); |
| 81363 | | - if( pUpgrade==0 || sampleIsBetter(pOld, pUpgrade) ){ |
| 81531 | + assert( pOld->iCol>pNew->iCol ); |
| 81532 | + assert( sampleIsBetter(p, pNew, pOld) ); |
| 81533 | + if( pUpgrade==0 || sampleIsBetter(p, pOld, pUpgrade) ){ |
| 81364 | 81534 | pUpgrade = pOld; |
| 81365 | 81535 | } |
| 81366 | 81536 | } |
| 81367 | 81537 | } |
| 81368 | 81538 | if( pUpgrade ){ |
| | @@ -81369,10 +81539,11 @@ |
| 81369 | 81539 | pUpgrade->iCol = pNew->iCol; |
| 81370 | 81540 | pUpgrade->anEq[pUpgrade->iCol] = pNew->anEq[pUpgrade->iCol]; |
| 81371 | 81541 | goto find_new_min; |
| 81372 | 81542 | } |
| 81373 | 81543 | } |
| 81544 | +#endif |
| 81374 | 81545 | |
| 81375 | 81546 | /* If necessary, remove sample iMin to make room for the new sample. */ |
| 81376 | 81547 | if( p->nSample>=p->mxSample ){ |
| 81377 | 81548 | Stat4Sample *pMin = &p->a[p->iMin]; |
| 81378 | 81549 | tRowcnt *anEq = pMin->anEq; |
| | @@ -81384,40 +81555,34 @@ |
| 81384 | 81555 | pSample->anDLt = anDLt; |
| 81385 | 81556 | pSample->anLt = anLt; |
| 81386 | 81557 | p->nSample = p->mxSample-1; |
| 81387 | 81558 | } |
| 81388 | 81559 | |
| 81389 | | - /* Figure out where in the a[] array the new sample should be inserted. */ |
| 81390 | | - iSeq = pNew->anLt[p->nCol-1]; |
| 81391 | | - for(iPos=p->nSample; iPos>0; iPos--){ |
| 81392 | | - if( iSeq>p->a[iPos-1].anLt[p->nCol-1] ) break; |
| 81393 | | - } |
| 81560 | + /* The "rows less-than" for the rowid column must be greater than that |
| 81561 | + ** for the last sample in the p->a[] array. Otherwise, the samples would |
| 81562 | + ** be out of order. */ |
| 81563 | +#ifdef SQLITE_ENABLE_STAT4 |
| 81564 | + assert( p->nSample==0 |
| 81565 | + || pNew->anLt[p->nCol-1] > p->a[p->nSample-1].anLt[p->nCol-1] ); |
| 81566 | +#endif |
| 81394 | 81567 | |
| 81395 | 81568 | /* Insert the new sample */ |
| 81396 | | - pSample = &p->a[iPos]; |
| 81397 | | - if( iPos!=p->nSample ){ |
| 81398 | | - Stat4Sample *pEnd = &p->a[p->nSample]; |
| 81399 | | - tRowcnt *anEq = pEnd->anEq; |
| 81400 | | - tRowcnt *anLt = pEnd->anLt; |
| 81401 | | - tRowcnt *anDLt = pEnd->anDLt; |
| 81402 | | - memmove(&p->a[iPos], &p->a[iPos+1], (p->nSample-iPos)*sizeof(p->a[0])); |
| 81403 | | - pSample->anEq = anEq; |
| 81404 | | - pSample->anDLt = anDLt; |
| 81405 | | - pSample->anLt = anLt; |
| 81406 | | - } |
| 81407 | | - p->nSample++; |
| 81569 | + pSample = &p->a[p->nSample]; |
| 81408 | 81570 | sampleCopy(p, pSample, pNew); |
| 81571 | + p->nSample++; |
| 81409 | 81572 | |
| 81410 | 81573 | /* Zero the first nEqZero entries in the anEq[] array. */ |
| 81411 | 81574 | memset(pSample->anEq, 0, sizeof(tRowcnt)*nEqZero); |
| 81412 | 81575 | |
| 81576 | +#ifdef SQLITE_ENABLE_STAT4 |
| 81413 | 81577 | find_new_min: |
| 81578 | +#endif |
| 81414 | 81579 | if( p->nSample>=p->mxSample ){ |
| 81415 | 81580 | int iMin = -1; |
| 81416 | 81581 | for(i=0; i<p->mxSample; i++){ |
| 81417 | 81582 | if( p->a[i].isPSample ) continue; |
| 81418 | | - if( iMin<0 || sampleIsBetter(&p->a[iMin], &p->a[i]) ){ |
| 81583 | + if( iMin<0 || sampleIsBetter(p, &p->a[iMin], &p->a[i]) ){ |
| 81419 | 81584 | iMin = i; |
| 81420 | 81585 | } |
| 81421 | 81586 | } |
| 81422 | 81587 | assert( iMin>=0 ); |
| 81423 | 81588 | p->iMin = iMin; |
| | @@ -81437,13 +81602,12 @@ |
| 81437 | 81602 | |
| 81438 | 81603 | /* Check if any samples from the aBest[] array should be pushed |
| 81439 | 81604 | ** into IndexSample.a[] at this point. */ |
| 81440 | 81605 | for(i=(p->nCol-2); i>=iChng; i--){ |
| 81441 | 81606 | Stat4Sample *pBest = &p->aBest[i]; |
| 81442 | | - if( p->nSample<p->mxSample |
| 81443 | | - || sampleIsBetter(pBest, &p->a[p->iMin]) |
| 81444 | | - ){ |
| 81607 | + pBest->anEq[i] = p->current.anEq[i]; |
| 81608 | + if( p->nSample<p->mxSample || sampleIsBetter(p, pBest, &p->a[p->iMin]) ){ |
| 81445 | 81609 | sampleInsert(p, pBest, i); |
| 81446 | 81610 | } |
| 81447 | 81611 | } |
| 81448 | 81612 | |
| 81449 | 81613 | /* Update the anEq[] fields of any samples already collected. */ |
| | @@ -81466,11 +81630,13 @@ |
| 81466 | 81630 | sampleInsert(p, &p->current, 0); |
| 81467 | 81631 | p->current.isPSample = 0; |
| 81468 | 81632 | }else |
| 81469 | 81633 | |
| 81470 | 81634 | /* Or if it is a non-periodic sample. Add it in this case too. */ |
| 81471 | | - if( p->nSample<p->mxSample || sampleIsBetter(&p->current, &p->a[p->iMin]) ){ |
| 81635 | + if( p->nSample<p->mxSample |
| 81636 | + || sampleIsBetter(p, &p->current, &p->a[p->iMin]) |
| 81637 | + ){ |
| 81472 | 81638 | sampleInsert(p, &p->current, 0); |
| 81473 | 81639 | } |
| 81474 | 81640 | } |
| 81475 | 81641 | #endif |
| 81476 | 81642 | } |
| | @@ -81500,12 +81666,11 @@ |
| 81500 | 81666 | |
| 81501 | 81667 | assert( p->nCol>1 ); /* Includes rowid field */ |
| 81502 | 81668 | assert( iChng<p->nCol ); |
| 81503 | 81669 | |
| 81504 | 81670 | if( p->nRow==0 ){ |
| 81505 | | - /* anEq[0] is only zero for the very first call to this function. Do |
| 81506 | | - ** appropriate initialization */ |
| 81671 | + /* This is the first call to this function. Do initialization. */ |
| 81507 | 81672 | for(i=0; i<p->nCol; i++) p->current.anEq[i] = 1; |
| 81508 | 81673 | }else{ |
| 81509 | 81674 | /* Second and subsequent calls get processed here */ |
| 81510 | 81675 | samplePushPrevious(p, iChng); |
| 81511 | 81676 | |
| | @@ -81541,11 +81706,11 @@ |
| 81541 | 81706 | } |
| 81542 | 81707 | |
| 81543 | 81708 | /* Update the aBest[] array. */ |
| 81544 | 81709 | for(i=0; i<(p->nCol-1); i++){ |
| 81545 | 81710 | p->current.iCol = i; |
| 81546 | | - if( i>=iChng || sampleIsBetter(&p->current, &p->aBest[i]) ){ |
| 81711 | + if( i>=iChng || sampleIsBetterPost(p, &p->current, &p->aBest[i]) ){ |
| 81547 | 81712 | sampleCopy(p, &p->aBest[i], &p->current); |
| 81548 | 81713 | } |
| 81549 | 81714 | } |
| 81550 | 81715 | } |
| 81551 | 81716 | #endif |
| | @@ -82249,11 +82414,11 @@ |
| 82249 | 82414 | IndexSample *pFinal = &aSample[pIdx->nSample-1]; |
| 82250 | 82415 | int iCol; |
| 82251 | 82416 | for(iCol=0; iCol<pIdx->nColumn; iCol++){ |
| 82252 | 82417 | int i; /* Used to iterate through samples */ |
| 82253 | 82418 | tRowcnt sumEq = 0; /* Sum of the nEq values */ |
| 82254 | | - int nSum = 0; /* Number of terms contributing to sumEq */ |
| 82419 | + tRowcnt nSum = 0; /* Number of terms contributing to sumEq */ |
| 82255 | 82420 | tRowcnt avgEq = 0; |
| 82256 | 82421 | tRowcnt nDLt = pFinal->anDLt[iCol]; |
| 82257 | 82422 | |
| 82258 | 82423 | /* Set nSum to the number of distinct (iCol+1) field prefixes that |
| 82259 | 82424 | ** occur in the stat4 table for this index before pFinal. Set |
| | @@ -105797,13 +105962,13 @@ |
| 105797 | 105962 | /* |
| 105798 | 105963 | ** Each instance of this object holds a sequence of WhereLoop objects |
| 105799 | 105964 | ** that implement some or all of a query plan. |
| 105800 | 105965 | ** |
| 105801 | 105966 | ** Think of each WhereLoop object as a node in a graph with arcs |
| 105802 | | -** showing dependences and costs for travelling between nodes. (That is |
| 105967 | +** showing dependencies and costs for travelling between nodes. (That is |
| 105803 | 105968 | ** not a completely accurate description because WhereLoop costs are a |
| 105804 | | -** vector, not a scalar, and because dependences are many-to-one, not |
| 105969 | +** vector, not a scalar, and because dependencies are many-to-one, not |
| 105805 | 105970 | ** one-to-one as are graph nodes. But it is a useful visualization aid.) |
| 105806 | 105971 | ** Then a WherePath object is a path through the graph that visits some |
| 105807 | 105972 | ** or all of the WhereLoop objects once. |
| 105808 | 105973 | ** |
| 105809 | 105974 | ** The "solver" works by creating the N best WherePath objects of length |
| | @@ -108033,16 +108198,19 @@ |
| 108033 | 108198 | UnpackedRecord *pRec, /* Vector of values to consider */ |
| 108034 | 108199 | int roundUp, /* Round up if true. Round down if false */ |
| 108035 | 108200 | tRowcnt *aStat /* OUT: stats written here */ |
| 108036 | 108201 | ){ |
| 108037 | 108202 | IndexSample *aSample = pIdx->aSample; |
| 108038 | | - int iCol = pRec->nField-1; /* Index of required stats in anEq[] etc. */ |
| 108203 | + int iCol; /* Index of required stats in anEq[] etc. */ |
| 108039 | 108204 | int iMin = 0; /* Smallest sample not yet tested */ |
| 108040 | 108205 | int i = pIdx->nSample; /* Smallest sample larger than or equal to pRec */ |
| 108041 | 108206 | int iTest; /* Next sample to test */ |
| 108042 | 108207 | int res; /* Result of comparison operation */ |
| 108043 | 108208 | |
| 108209 | + assert( pRec!=0 || pParse->db->mallocFailed ); |
| 108210 | + if( pRec==0 ) return; |
| 108211 | + iCol = pRec->nField - 1; |
| 108044 | 108212 | assert( pIdx->nSample>0 ); |
| 108045 | 108213 | assert( pRec->nField>0 && iCol<pIdx->nSampleCol ); |
| 108046 | 108214 | do{ |
| 108047 | 108215 | iTest = (iMin+i)/2; |
| 108048 | 108216 | res = sqlite3VdbeRecordCompare(aSample[iTest].n, aSample[iTest].p, pRec); |
| | @@ -108165,11 +108333,11 @@ |
| 108165 | 108333 | && p->nSample |
| 108166 | 108334 | && OptimizationEnabled(pParse->db, SQLITE_Stat3) |
| 108167 | 108335 | ){ |
| 108168 | 108336 | UnpackedRecord *pRec = pBuilder->pRec; |
| 108169 | 108337 | tRowcnt a[2]; |
| 108170 | | - u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity; |
| 108338 | + u8 aff; |
| 108171 | 108339 | |
| 108172 | 108340 | /* Variable iLower will be set to the estimate of the number of rows in |
| 108173 | 108341 | ** the index that are less than the lower bound of the range query. The |
| 108174 | 108342 | ** lower bound being the concatenation of $P and $L, where $P is the |
| 108175 | 108343 | ** key-prefix formed by the nEq values matched against the nEq left-most |
| | @@ -108187,10 +108355,15 @@ |
| 108187 | 108355 | ** of iUpper are requested of whereKeyStats() and the smaller used. |
| 108188 | 108356 | */ |
| 108189 | 108357 | tRowcnt iLower; |
| 108190 | 108358 | tRowcnt iUpper; |
| 108191 | 108359 | |
| 108360 | + if( nEq==p->nColumn ){ |
| 108361 | + aff = SQLITE_AFF_INTEGER; |
| 108362 | + }else{ |
| 108363 | + aff = p->pTable->aCol[p->aiColumn[nEq]].affinity; |
| 108364 | + } |
| 108192 | 108365 | /* Determine iLower and iUpper using ($P) only. */ |
| 108193 | 108366 | if( nEq==0 ){ |
| 108194 | 108367 | iLower = 0; |
| 108195 | 108368 | iUpper = p->aiRowEst[0]; |
| 108196 | 108369 | }else{ |
| | @@ -109781,19 +109954,21 @@ |
| 109781 | 109954 | assert( p->rSetup>=pTemplate->rSetup ); |
| 109782 | 109955 | |
| 109783 | 109956 | if( (p->prereq & pTemplate->prereq)==p->prereq |
| 109784 | 109957 | && p->rSetup<=pTemplate->rSetup |
| 109785 | 109958 | && p->rRun<=pTemplate->rRun |
| 109959 | + && p->nOut<=pTemplate->nOut |
| 109786 | 109960 | ){ |
| 109787 | 109961 | /* This branch taken when p is equal or better than pTemplate in |
| 109788 | | - ** all of (1) dependences (2) setup-cost, and (3) run-cost. */ |
| 109962 | + ** all of (1) dependencies (2) setup-cost, (3) run-cost, and |
| 109963 | + ** (4) number of output rows. */ |
| 109789 | 109964 | assert( p->rSetup==pTemplate->rSetup ); |
| 109790 | | - if( p->nLTerm<pTemplate->nLTerm |
| 109965 | + if( p->prereq==pTemplate->prereq |
| 109966 | + && p->nLTerm<pTemplate->nLTerm |
| 109791 | 109967 | && (p->wsFlags & WHERE_INDEXED)!=0 |
| 109792 | 109968 | && (pTemplate->wsFlags & WHERE_INDEXED)!=0 |
| 109793 | 109969 | && p->u.btree.pIndex==pTemplate->u.btree.pIndex |
| 109794 | | - && p->prereq==pTemplate->prereq |
| 109795 | 109970 | ){ |
| 109796 | 109971 | /* Overwrite an existing WhereLoop with an similar one that uses |
| 109797 | 109972 | ** more terms of the index */ |
| 109798 | 109973 | pNext = p->pNextLoop; |
| 109799 | 109974 | break; |
| | @@ -109803,15 +109978,17 @@ |
| 109803 | 109978 | goto whereLoopInsert_noop; |
| 109804 | 109979 | } |
| 109805 | 109980 | } |
| 109806 | 109981 | if( (p->prereq & pTemplate->prereq)==pTemplate->prereq |
| 109807 | 109982 | && p->rRun>=pTemplate->rRun |
| 109983 | + && p->nOut>=pTemplate->nOut |
| 109808 | 109984 | && ALWAYS(p->rSetup>=pTemplate->rSetup) /* See SETUP-INVARIANT above */ |
| 109809 | 109985 | ){ |
| 109810 | 109986 | /* Overwrite an existing WhereLoop with a better one: one that is |
| 109811 | | - ** better at one of (1) dependences, (2) setup-cost, or (3) run-cost |
| 109812 | | - ** and is no worse in any of those categories. */ |
| 109987 | + ** better at one of (1) dependencies, (2) setup-cost, (3) run-cost |
| 109988 | + ** or (4) number of output rows, and is no worse in any of those |
| 109989 | + ** categories. */ |
| 109813 | 109990 | pNext = p->pNextLoop; |
| 109814 | 109991 | break; |
| 109815 | 109992 | } |
| 109816 | 109993 | } |
| 109817 | 109994 | |
| | @@ -111512,11 +111689,11 @@ |
| 111512 | 111689 | if( pWInfo->nLevel>=2 |
| 111513 | 111690 | && pResultSet!=0 |
| 111514 | 111691 | && OptimizationEnabled(db, SQLITE_OmitNoopJoin) |
| 111515 | 111692 | ){ |
| 111516 | 111693 | Bitmask tabUsed = exprListTableUsage(pMaskSet, pResultSet); |
| 111517 | | - if( pOrderBy ) tabUsed |= exprListTableUsage(pMaskSet, pOrderBy); |
| 111694 | + if( sWLB.pOrderBy ) tabUsed |= exprListTableUsage(pMaskSet, sWLB.pOrderBy); |
| 111518 | 111695 | while( pWInfo->nLevel>=2 ){ |
| 111519 | 111696 | WhereTerm *pTerm, *pEnd; |
| 111520 | 111697 | pLoop = pWInfo->a[pWInfo->nLevel-1].pWLoop; |
| 111521 | 111698 | if( (pWInfo->pTabList->a[pLoop->iTab].jointype & JT_LEFT)==0 ) break; |
| 111522 | 111699 | if( (wctrlFlags & WHERE_WANT_DISTINCT)==0 |
| | @@ -117544,18 +117721,20 @@ |
| 117544 | 117721 | case SQLITE_IOERR_SHMMAP: zName = "SQLITE_IOERR_SHMMAP"; break; |
| 117545 | 117722 | case SQLITE_IOERR_SEEK: zName = "SQLITE_IOERR_SEEK"; break; |
| 117546 | 117723 | case SQLITE_IOERR_DELETE_NOENT: zName = "SQLITE_IOERR_DELETE_NOENT";break; |
| 117547 | 117724 | case SQLITE_IOERR_MMAP: zName = "SQLITE_IOERR_MMAP"; break; |
| 117548 | 117725 | case SQLITE_IOERR_GETTEMPPATH: zName = "SQLITE_IOERR_GETTEMPPATH"; break; |
| 117726 | + case SQLITE_IOERR_CONVPATH: zName = "SQLITE_IOERR_CONVPATH"; break; |
| 117549 | 117727 | case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break; |
| 117550 | 117728 | case SQLITE_CORRUPT_VTAB: zName = "SQLITE_CORRUPT_VTAB"; break; |
| 117551 | 117729 | case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break; |
| 117552 | 117730 | case SQLITE_FULL: zName = "SQLITE_FULL"; break; |
| 117553 | 117731 | case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break; |
| 117554 | 117732 | case SQLITE_CANTOPEN_NOTEMPDIR: zName = "SQLITE_CANTOPEN_NOTEMPDIR";break; |
| 117555 | 117733 | case SQLITE_CANTOPEN_ISDIR: zName = "SQLITE_CANTOPEN_ISDIR"; break; |
| 117556 | 117734 | case SQLITE_CANTOPEN_FULLPATH: zName = "SQLITE_CANTOPEN_FULLPATH"; break; |
| 117735 | + case SQLITE_CANTOPEN_CONVPATH: zName = "SQLITE_CANTOPEN_CONVPATH"; break; |
| 117557 | 117736 | case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break; |
| 117558 | 117737 | case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break; |
| 117559 | 117738 | case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break; |
| 117560 | 117739 | case SQLITE_TOOBIG: zName = "SQLITE_TOOBIG"; break; |
| 117561 | 117740 | case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break; |
| 117562 | 117741 | |