| | @@ -135,11 +135,11 @@ |
| 135 | 135 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 136 | 136 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 137 | 137 | */ |
| 138 | 138 | #define SQLITE_VERSION "3.8.1" |
| 139 | 139 | #define SQLITE_VERSION_NUMBER 3008001 |
| 140 | | -#define SQLITE_SOURCE_ID "2013-10-11 13:27:26 03593817ab5abdd4bbaa5e47e2e4745eef025af9" |
| 140 | +#define SQLITE_SOURCE_ID "2013-10-17 12:57:35 c78be6d786c19073b3a6730dfe3fb1be54f5657a" |
| 141 | 141 | |
| 142 | 142 | /* |
| 143 | 143 | ** CAPI3REF: Run-Time Library Version Numbers |
| 144 | 144 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 145 | 145 | ** |
| | @@ -1643,31 +1643,31 @@ |
| 1643 | 1643 | ** supplied by the application must not invoke any SQLite interface. |
| 1644 | 1644 | ** In a multi-threaded application, the application-defined logger |
| 1645 | 1645 | ** function must be threadsafe. </dd> |
| 1646 | 1646 | ** |
| 1647 | 1647 | ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI |
| 1648 | | -** <dd> This option takes a single argument of type int. If non-zero, then |
| 1648 | +** <dd>^(This option takes a single argument of type int. If non-zero, then |
| 1649 | 1649 | ** URI handling is globally enabled. If the parameter is zero, then URI handling |
| 1650 | | -** is globally disabled. If URI handling is globally enabled, all filenames |
| 1650 | +** is globally disabled.)^ ^If URI handling is globally enabled, all filenames |
| 1651 | 1651 | ** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or |
| 1652 | 1652 | ** specified as part of [ATTACH] commands are interpreted as URIs, regardless |
| 1653 | 1653 | ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database |
| 1654 | | -** connection is opened. If it is globally disabled, filenames are |
| 1654 | +** connection is opened. ^If it is globally disabled, filenames are |
| 1655 | 1655 | ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the |
| 1656 | | -** database connection is opened. By default, URI handling is globally |
| 1656 | +** database connection is opened. ^(By default, URI handling is globally |
| 1657 | 1657 | ** disabled. The default value may be changed by compiling with the |
| 1658 | | -** [SQLITE_USE_URI] symbol defined. |
| 1658 | +** [SQLITE_USE_URI] symbol defined.)^ |
| 1659 | 1659 | ** |
| 1660 | 1660 | ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN |
| 1661 | | -** <dd> This option takes a single integer argument which is interpreted as |
| 1661 | +** <dd>^This option takes a single integer argument which is interpreted as |
| 1662 | 1662 | ** a boolean in order to enable or disable the use of covering indices for |
| 1663 | | -** full table scans in the query optimizer. The default setting is determined |
| 1663 | +** full table scans in the query optimizer. ^The default setting is determined |
| 1664 | 1664 | ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" |
| 1665 | 1665 | ** if that compile-time option is omitted. |
| 1666 | 1666 | ** The ability to disable the use of covering indices for full table scans |
| 1667 | 1667 | ** is because some incorrectly coded legacy applications might malfunction |
| 1668 | | -** malfunction when the optimization is enabled. Providing the ability to |
| 1668 | +** when the optimization is enabled. Providing the ability to |
| 1669 | 1669 | ** disable the optimization allows the older, buggy application code to work |
| 1670 | 1670 | ** without change even with newer versions of SQLite. |
| 1671 | 1671 | ** |
| 1672 | 1672 | ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] |
| 1673 | 1673 | ** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE |
| | @@ -1692,20 +1692,20 @@ |
| 1692 | 1692 | ** configuration option can be seen in the "test_sqllog.c" source file in |
| 1693 | 1693 | ** the canonical SQLite source tree.</dd> |
| 1694 | 1694 | ** |
| 1695 | 1695 | ** [[SQLITE_CONFIG_MMAP_SIZE]] |
| 1696 | 1696 | ** <dt>SQLITE_CONFIG_MMAP_SIZE |
| 1697 | | -** <dd>SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values |
| 1697 | +** <dd>^SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values |
| 1698 | 1698 | ** that are the default mmap size limit (the default setting for |
| 1699 | 1699 | ** [PRAGMA mmap_size]) and the maximum allowed mmap size limit. |
| 1700 | | -** The default setting can be overridden by each database connection using |
| 1700 | +** ^The default setting can be overridden by each database connection using |
| 1701 | 1701 | ** either the [PRAGMA mmap_size] command, or by using the |
| 1702 | | -** [SQLITE_FCNTL_MMAP_SIZE] file control. The maximum allowed mmap size |
| 1702 | +** [SQLITE_FCNTL_MMAP_SIZE] file control. ^(The maximum allowed mmap size |
| 1703 | 1703 | ** cannot be changed at run-time. Nor may the maximum allowed mmap size |
| 1704 | 1704 | ** exceed the compile-time maximum mmap size set by the |
| 1705 | | -** [SQLITE_MAX_MMAP_SIZE] compile-time option. |
| 1706 | | -** If either argument to this option is negative, then that argument is |
| 1705 | +** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^ |
| 1706 | +** ^If either argument to this option is negative, then that argument is |
| 1707 | 1707 | ** changed to its compile-time default. |
| 1708 | 1708 | ** </dl> |
| 1709 | 1709 | */ |
| 1710 | 1710 | #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ |
| 1711 | 1711 | #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ |
| | @@ -12468,14 +12468,14 @@ |
| 12468 | 12468 | SQLITE_PRIVATE int sqlite3FkRequired(Parse*, Table*, int*, int); |
| 12469 | 12469 | SQLITE_PRIVATE u32 sqlite3FkOldmask(Parse*, Table*); |
| 12470 | 12470 | SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *); |
| 12471 | 12471 | #else |
| 12472 | 12472 | #define sqlite3FkActions(a,b,c,d,e,f) |
| 12473 | | - #define sqlite3FkCheck(a,b,c,d) |
| 12473 | + #define sqlite3FkCheck(a,b,c,d,e,f) |
| 12474 | 12474 | #define sqlite3FkDropTable(a,b,c) |
| 12475 | | - #define sqlite3FkOldmask(a,b) 0 |
| 12476 | | - #define sqlite3FkRequired(a,b,c,d,e,f) 0 |
| 12475 | + #define sqlite3FkOldmask(a,b) 0 |
| 12476 | + #define sqlite3FkRequired(a,b,c,d) 0 |
| 12477 | 12477 | #endif |
| 12478 | 12478 | #ifndef SQLITE_OMIT_FOREIGN_KEY |
| 12479 | 12479 | SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*); |
| 12480 | 12480 | SQLITE_PRIVATE int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**); |
| 12481 | 12481 | #else |
| | @@ -14430,10 +14430,14 @@ |
| 14430 | 14430 | ** is available. This routine returns 0 on success and |
| 14431 | 14431 | ** non-zero on any kind of error. |
| 14432 | 14432 | ** |
| 14433 | 14433 | ** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this |
| 14434 | 14434 | ** routine will always fail. |
| 14435 | +** |
| 14436 | +** EVIDENCE-OF: R-62172-00036 In this implementation, the standard C |
| 14437 | +** library function localtime_r() is used to assist in the calculation of |
| 14438 | +** local time. |
| 14435 | 14439 | */ |
| 14436 | 14440 | static int osLocaltime(time_t *t, struct tm *pTm){ |
| 14437 | 14441 | int rc; |
| 14438 | 14442 | #if (!defined(HAVE_LOCALTIME_R) || !HAVE_LOCALTIME_R) \ |
| 14439 | 14443 | && (!defined(HAVE_LOCALTIME_S) || !HAVE_LOCALTIME_S) |
| | @@ -14486,10 +14490,15 @@ |
| 14486 | 14490 | memset(&sLocal, 0, sizeof(sLocal)); |
| 14487 | 14491 | |
| 14488 | 14492 | x = *p; |
| 14489 | 14493 | computeYMD_HMS(&x); |
| 14490 | 14494 | if( x.Y<1971 || x.Y>=2038 ){ |
| 14495 | + /* EVIDENCE-OF: R-55269-29598 The localtime_r() C function normally only |
| 14496 | + ** works for years between 1970 and 2037. For dates outside this range, |
| 14497 | + ** SQLite attempts to map the year into an equivalent year within this |
| 14498 | + ** range, do the calculation, then map the year back. |
| 14499 | + */ |
| 14491 | 14500 | x.Y = 2000; |
| 14492 | 14501 | x.M = 1; |
| 14493 | 14502 | x.D = 1; |
| 14494 | 14503 | x.h = 0; |
| 14495 | 14504 | x.m = 0; |
| | @@ -33006,12 +33015,11 @@ |
| 33006 | 33015 | #endif |
| 33007 | 33016 | assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE ); |
| 33008 | 33017 | OSTRACE(("CLOSE file=%p\n", pFile->h)); |
| 33009 | 33018 | |
| 33010 | 33019 | #if SQLITE_MAX_MMAP_SIZE>0 |
| 33011 | | - rc = winUnmapfile(pFile); |
| 33012 | | - if( rc!=SQLITE_OK ) return rc; |
| 33020 | + winUnmapfile(pFile); |
| 33013 | 33021 | #endif |
| 33014 | 33022 | |
| 33015 | 33023 | do{ |
| 33016 | 33024 | rc = osCloseHandle(pFile->h); |
| 33017 | 33025 | /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */ |
| | @@ -33813,11 +33821,11 @@ |
| 33813 | 33821 | } |
| 33814 | 33822 | *(i64*)pArg = pFile->mmapSizeMax; |
| 33815 | 33823 | if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){ |
| 33816 | 33824 | pFile->mmapSizeMax = newLimit; |
| 33817 | 33825 | if( pFile->mmapSize>0 ){ |
| 33818 | | - (void)winUnmapfile(pFile); |
| 33826 | + winUnmapfile(pFile); |
| 33819 | 33827 | rc = winMapfile(pFile, -1); |
| 33820 | 33828 | } |
| 33821 | 33829 | } |
| 33822 | 33830 | OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc))); |
| 33823 | 33831 | return rc; |
| | @@ -34030,11 +34038,11 @@ |
| 34030 | 34038 | osGetCurrentProcessId(), deleteFlag)); |
| 34031 | 34039 | pp = &winShmNodeList; |
| 34032 | 34040 | while( (p = *pp)!=0 ){ |
| 34033 | 34041 | if( p->nRef==0 ){ |
| 34034 | 34042 | int i; |
| 34035 | | - if( p->mutex ) sqlite3_mutex_free(p->mutex); |
| 34043 | + if( p->mutex ){ sqlite3_mutex_free(p->mutex); } |
| 34036 | 34044 | for(i=0; i<p->nRegion; i++){ |
| 34037 | 34045 | BOOL bRc = osUnmapViewOfFile(p->aRegion[i].pMap); |
| 34038 | 34046 | OSTRACE(("SHM-PURGE-UNMAP pid=%lu, region=%d, rc=%s\n", |
| 34039 | 34047 | osGetCurrentProcessId(), i, bRc ? "ok" : "failed")); |
| 34040 | 34048 | UNUSED_VARIABLE_VALUE(bRc); |
| | @@ -34883,10 +34891,11 @@ |
| 34883 | 34891 | ** API prior to using it. |
| 34884 | 34892 | */ |
| 34885 | 34893 | if( winIsDriveLetterAndColon(zDir) ){ |
| 34886 | 34894 | zConverted = winConvertFromUtf8Filename(zDir); |
| 34887 | 34895 | if( !zConverted ){ |
| 34896 | + sqlite3_free(zBuf); |
| 34888 | 34897 | OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); |
| 34889 | 34898 | return SQLITE_IOERR_NOMEM; |
| 34890 | 34899 | } |
| 34891 | 34900 | if( winIsDir(zConverted) ){ |
| 34892 | 34901 | sqlite3_snprintf(nBuf-30, zBuf, "%s", zDir); |
| | @@ -34895,17 +34904,19 @@ |
| 34895 | 34904 | } |
| 34896 | 34905 | sqlite3_free(zConverted); |
| 34897 | 34906 | }else{ |
| 34898 | 34907 | zConverted = sqlite3MallocZero( nBuf+1 ); |
| 34899 | 34908 | if( !zConverted ){ |
| 34909 | + sqlite3_free(zBuf); |
| 34900 | 34910 | OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); |
| 34901 | 34911 | return SQLITE_IOERR_NOMEM; |
| 34902 | 34912 | } |
| 34903 | 34913 | if( cygwin_conv_path( |
| 34904 | 34914 | osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A, zDir, |
| 34905 | 34915 | zConverted, nBuf+1)<0 ){ |
| 34906 | 34916 | sqlite3_free(zConverted); |
| 34917 | + sqlite3_free(zBuf); |
| 34907 | 34918 | OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_CONVPATH\n")); |
| 34908 | 34919 | return winLogError(SQLITE_IOERR_CONVPATH, (DWORD)errno, |
| 34909 | 34920 | "winGetTempname1", zDir); |
| 34910 | 34921 | } |
| 34911 | 34922 | if( winIsDir(zConverted) ){ |
| | @@ -34915,10 +34926,11 @@ |
| 34915 | 34926 | */ |
| 34916 | 34927 | if( osIsNT() ){ |
| 34917 | 34928 | char *zUtf8 = winUnicodeToUtf8(zConverted); |
| 34918 | 34929 | if( !zUtf8 ){ |
| 34919 | 34930 | sqlite3_free(zConverted); |
| 34931 | + sqlite3_free(zBuf); |
| 34920 | 34932 | OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); |
| 34921 | 34933 | return SQLITE_IOERR_NOMEM; |
| 34922 | 34934 | } |
| 34923 | 34935 | sqlite3_snprintf(nBuf-30, zBuf, "%s", zUtf8); |
| 34924 | 34936 | sqlite3_free(zUtf8); |
| | @@ -34930,11 +34942,10 @@ |
| 34930 | 34942 | break; |
| 34931 | 34943 | } |
| 34932 | 34944 | } |
| 34933 | 34945 | sqlite3_free(zConverted); |
| 34934 | 34946 | } |
| 34935 | | - break; |
| 34936 | 34947 | } |
| 34937 | 34948 | } |
| 34938 | 34949 | #elif !SQLITE_OS_WINRT && !defined(__CYGWIN__) |
| 34939 | 34950 | else if( osIsNT() ){ |
| 34940 | 34951 | char *zMulti; |
| | @@ -35300,13 +35311,13 @@ |
| 35300 | 35311 | pFile->zDeleteOnClose = zConverted; |
| 35301 | 35312 | }else |
| 35302 | 35313 | #endif |
| 35303 | 35314 | { |
| 35304 | 35315 | sqlite3_free(zConverted); |
| 35305 | | - sqlite3_free(zTmpname); |
| 35306 | 35316 | } |
| 35307 | 35317 | |
| 35318 | + sqlite3_free(zTmpname); |
| 35308 | 35319 | pFile->pMethod = &winIoMethod; |
| 35309 | 35320 | pFile->pVfs = pVfs; |
| 35310 | 35321 | pFile->h = h; |
| 35311 | 35322 | if( isReadonly ){ |
| 35312 | 35323 | pFile->ctrlFlags |= WINFILE_RDONLY; |
| | @@ -52033,10 +52044,22 @@ |
| 52033 | 52044 | ** MX_CELL_SIZE(pBt) bytes. |
| 52034 | 52045 | */ |
| 52035 | 52046 | static void allocateTempSpace(BtShared *pBt){ |
| 52036 | 52047 | if( !pBt->pTmpSpace ){ |
| 52037 | 52048 | pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize ); |
| 52049 | + |
| 52050 | + /* One of the uses of pBt->pTmpSpace is to format cells before |
| 52051 | + ** inserting them into a leaf page (function fillInCell()). If |
| 52052 | + ** a cell is less than 4 bytes in size, it is rounded up to 4 bytes |
| 52053 | + ** by the various routines that manipulate binary cells. Which |
| 52054 | + ** can mean that fillInCell() only initializes the first 2 or 3 |
| 52055 | + ** bytes of pTmpSpace, but that the first 4 bytes are copied from |
| 52056 | + ** it into a database page. This is not actually a problem, but it |
| 52057 | + ** does cause a valgrind error when the 1 or 2 bytes of unitialized |
| 52058 | + ** data is passed to system call write(). So to avoid this error, |
| 52059 | + ** zero the first 4 bytes of temp space here. */ |
| 52060 | + if( pBt->pTmpSpace ) memset(pBt->pTmpSpace, 0, 4); |
| 52038 | 52061 | } |
| 52039 | 52062 | } |
| 52040 | 52063 | |
| 52041 | 52064 | /* |
| 52042 | 52065 | ** Free the pBt->pTmpSpace allocation |
| | @@ -60299,11 +60322,13 @@ |
| 60299 | 60322 | } |
| 60300 | 60323 | |
| 60301 | 60324 | pRec->nField = p->iVal+1; |
| 60302 | 60325 | return &pRec->aMem[p->iVal]; |
| 60303 | 60326 | } |
| 60304 | | -#endif |
| 60327 | +#else |
| 60328 | + UNUSED_PARAMETER(p); |
| 60329 | +#endif /* defined(SQLITE_ENABLE_STAT3_OR_STAT4) */ |
| 60305 | 60330 | return sqlite3ValueNew(db); |
| 60306 | 60331 | } |
| 60307 | 60332 | |
| 60308 | 60333 | /* |
| 60309 | 60334 | ** Extract a value from the supplied expression in the manner described |
| | @@ -60313,11 +60338,11 @@ |
| 60313 | 60338 | ** If pCtx is NULL and an error occurs after the sqlite3_value object |
| 60314 | 60339 | ** has been allocated, it is freed before returning. Or, if pCtx is not |
| 60315 | 60340 | ** NULL, it is assumed that the caller will free any allocated object |
| 60316 | 60341 | ** in all cases. |
| 60317 | 60342 | */ |
| 60318 | | -int valueFromExpr( |
| 60343 | +static int valueFromExpr( |
| 60319 | 60344 | sqlite3 *db, /* The database connection */ |
| 60320 | 60345 | Expr *pExpr, /* The expression to evaluate */ |
| 60321 | 60346 | u8 enc, /* Encoding to use */ |
| 60322 | 60347 | u8 affinity, /* Affinity to use */ |
| 60323 | 60348 | sqlite3_value **ppVal, /* Write the new value here */ |
| | @@ -60470,10 +60495,11 @@ |
| 60470 | 60495 | int nVal; /* Bytes of space required for argv[0] */ |
| 60471 | 60496 | int nRet; |
| 60472 | 60497 | sqlite3 *db; |
| 60473 | 60498 | u8 *aRet; |
| 60474 | 60499 | |
| 60500 | + UNUSED_PARAMETER( argc ); |
| 60475 | 60501 | iSerial = sqlite3VdbeSerialType(argv[0], file_format); |
| 60476 | 60502 | nSerial = sqlite3VarintLen(iSerial); |
| 60477 | 60503 | nVal = sqlite3VdbeSerialTypeLen(iSerial); |
| 60478 | 60504 | db = sqlite3_context_db_handle(context); |
| 60479 | 60505 | |
| | @@ -75410,10 +75436,14 @@ |
| 75410 | 75436 | sqlite3ErrorMsg(pParse, "second argument to likelihood() must be a " |
| 75411 | 75437 | "constant between 0.0 and 1.0"); |
| 75412 | 75438 | pNC->nErr++; |
| 75413 | 75439 | } |
| 75414 | 75440 | }else{ |
| 75441 | + /* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is equivalent to |
| 75442 | + ** likelihood(X, 0.0625). |
| 75443 | + ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is short-hand for |
| 75444 | + ** likelihood(X,0.0625). */ |
| 75415 | 75445 | pExpr->iTable = 62; /* TUNING: Default 2nd arg to unlikely() is 0.0625 */ |
| 75416 | 75446 | } |
| 75417 | 75447 | } |
| 75418 | 75448 | } |
| 75419 | 75449 | #ifndef SQLITE_OMIT_AUTHORIZATION |
| | @@ -81284,11 +81314,11 @@ |
| 81284 | 81314 | ** The sqlite_stat2 table is superseded by sqlite_stat3, which is only |
| 81285 | 81315 | ** created and used by SQLite versions 3.7.9 and later and with |
| 81286 | 81316 | ** SQLITE_ENABLE_STAT3 defined. The functionality of sqlite_stat3 |
| 81287 | 81317 | ** is a superset of sqlite_stat2. The sqlite_stat4 is an enhanced |
| 81288 | 81318 | ** version of sqlite_stat3 and is only available when compiled with |
| 81289 | | -** SQLITE_ENABLE_STAT4 and in SQLite versions 3.8.0 and later. It is |
| 81319 | +** SQLITE_ENABLE_STAT4 and in SQLite versions 3.8.1 and later. It is |
| 81290 | 81320 | ** not possible to enable both STAT3 and STAT4 at the same time. If they |
| 81291 | 81321 | ** are both enabled, then STAT4 takes precedence. |
| 81292 | 81322 | ** |
| 81293 | 81323 | ** For most applications, sqlite_stat1 provides all the statisics required |
| 81294 | 81324 | ** for the query planner to make good choices. |
| | @@ -81360,16 +81390,16 @@ |
| 81360 | 81390 | ** |
| 81361 | 81391 | ** The sqlite_stat4 table contains multiple entries for each index. |
| 81362 | 81392 | ** The idx column names the index and the tbl column is the table of the |
| 81363 | 81393 | ** index. If the idx and tbl columns are the same, then the sample is |
| 81364 | 81394 | ** of the INTEGER PRIMARY KEY. The sample column is a blob which is the |
| 81365 | | -** binary encoding of a key from the index, with the trailing rowid |
| 81366 | | -** omitted. The nEq column is a list of integers. The first integer |
| 81367 | | -** is the approximate number of entries in the index whose left-most |
| 81368 | | -** column exactly matches the left-most column of the sample. The second |
| 81369 | | -** integer in nEq is the approximate number of entries in the index where |
| 81370 | | -** the first two columns match the first two columns of the sample. |
| 81395 | +** binary encoding of a key from the index. The nEq column is a |
| 81396 | +** list of integers. The first integer is the approximate number |
| 81397 | +** of entries in the index whose left-most column exactly matches |
| 81398 | +** the left-most column of the sample. The second integer in nEq |
| 81399 | +** is the approximate number of entries in the index where the |
| 81400 | +** first two columns match the first two columns of the sample. |
| 81371 | 81401 | ** And so forth. nLt is another list of integers that show the approximate |
| 81372 | 81402 | ** number of entries that are strictly less than the sample. The first |
| 81373 | 81403 | ** integer in nLt contains the number of entries in the index where the |
| 81374 | 81404 | ** left-most column is less than the left-most column of the sample. |
| 81375 | 81405 | ** The K-th integer in the nLt entry is the number of index entries |
| | @@ -81696,11 +81726,11 @@ |
| 81696 | 81726 | } |
| 81697 | 81727 | |
| 81698 | 81728 | /* |
| 81699 | 81729 | ** Copy the contents of object (*pFrom) into (*pTo). |
| 81700 | 81730 | */ |
| 81701 | | -void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){ |
| 81731 | +static void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){ |
| 81702 | 81732 | pTo->iRowid = pFrom->iRowid; |
| 81703 | 81733 | pTo->isPSample = pFrom->isPSample; |
| 81704 | 81734 | pTo->iCol = pFrom->iCol; |
| 81705 | 81735 | pTo->iHash = pFrom->iHash; |
| 81706 | 81736 | memcpy(pTo->anEq, pFrom->anEq, sizeof(tRowcnt)*p->nCol); |
| | @@ -81841,10 +81871,15 @@ |
| 81841 | 81871 | ){ |
| 81842 | 81872 | sampleInsert(p, &p->current, 0); |
| 81843 | 81873 | } |
| 81844 | 81874 | } |
| 81845 | 81875 | #endif |
| 81876 | + |
| 81877 | +#ifndef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 81878 | + UNUSED_PARAMETER( p ); |
| 81879 | + UNUSED_PARAMETER( iChng ); |
| 81880 | +#endif |
| 81846 | 81881 | } |
| 81847 | 81882 | |
| 81848 | 81883 | /* |
| 81849 | 81884 | ** Implementation of the stat_push SQL function: stat_push(P,R,C) |
| 81850 | 81885 | ** Arguments: |
| | @@ -81866,10 +81901,12 @@ |
| 81866 | 81901 | |
| 81867 | 81902 | /* The three function arguments */ |
| 81868 | 81903 | Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]); |
| 81869 | 81904 | int iChng = sqlite3_value_int(argv[1]); |
| 81870 | 81905 | |
| 81906 | + UNUSED_PARAMETER( argc ); |
| 81907 | + UNUSED_PARAMETER( context ); |
| 81871 | 81908 | assert( p->nCol>1 ); /* Includes rowid field */ |
| 81872 | 81909 | assert( iChng<p->nCol ); |
| 81873 | 81910 | |
| 81874 | 81911 | if( p->nRow==0 ){ |
| 81875 | 81912 | /* This is the first call to this function. Do initialization. */ |
| | @@ -82051,10 +82088,13 @@ |
| 82051 | 82088 | sqlite3_result_text(context, zRet, -1, sqlite3_free); |
| 82052 | 82089 | } |
| 82053 | 82090 | } |
| 82054 | 82091 | } |
| 82055 | 82092 | #endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ |
| 82093 | +#ifndef SQLITE_DEBUG |
| 82094 | + UNUSED_PARAMETER( argc ); |
| 82095 | +#endif |
| 82056 | 82096 | } |
| 82057 | 82097 | static const FuncDef statGetFuncdef = { |
| 82058 | 82098 | 1+IsStat34, /* nArg */ |
| 82059 | 82099 | SQLITE_UTF8, /* funcFlags */ |
| 82060 | 82100 | 0, /* pUserData */ |
| | @@ -82069,12 +82109,14 @@ |
| 82069 | 82109 | |
| 82070 | 82110 | static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){ |
| 82071 | 82111 | assert( regOut!=regStat4 && regOut!=regStat4+1 ); |
| 82072 | 82112 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 82073 | 82113 | sqlite3VdbeAddOp2(v, OP_Integer, iParam, regStat4+1); |
| 82074 | | -#else |
| 82114 | +#elif SQLITE_DEBUG |
| 82075 | 82115 | assert( iParam==STAT_GET_STAT1 ); |
| 82116 | +#else |
| 82117 | + UNUSED_PARAMETER( iParam ); |
| 82076 | 82118 | #endif |
| 82077 | 82119 | sqlite3VdbeAddOp3(v, OP_Function, 0, regStat4, regOut); |
| 82078 | 82120 | sqlite3VdbeChangeP4(v, -1, (char*)&statGetFuncdef, P4_FUNCDEF); |
| 82079 | 82121 | sqlite3VdbeChangeP5(v, 1 + IsStat34); |
| 82080 | 82122 | } |
| | @@ -84833,11 +84875,11 @@ |
| 84833 | 84875 | *pszEst = 1; /* default size is approx 4 bytes */ |
| 84834 | 84876 | if( aff<=SQLITE_AFF_NONE ){ |
| 84835 | 84877 | if( zChar ){ |
| 84836 | 84878 | while( zChar[0] ){ |
| 84837 | 84879 | if( sqlite3Isdigit(zChar[0]) ){ |
| 84838 | | - int v; |
| 84880 | + int v = 0; |
| 84839 | 84881 | sqlite3GetInt32(zChar, &v); |
| 84840 | 84882 | v = v/4 + 1; |
| 84841 | 84883 | if( v>255 ) v = 255; |
| 84842 | 84884 | *pszEst = v; /* BLOB(k), VARCHAR(k), CHAR(k) -> r=(k/4+1) */ |
| 84843 | 84885 | break; |
| | @@ -91144,11 +91186,11 @@ |
| 91144 | 91186 | ** generating any VDBE code. If one can be found, then jump over |
| 91145 | 91187 | ** the entire DELETE if there are no outstanding deferred constraints |
| 91146 | 91188 | ** when this statement is run. */ |
| 91147 | 91189 | FKey *p; |
| 91148 | 91190 | for(p=pTab->pFKey; p; p=p->pNextFrom){ |
| 91149 | | - if( p->isDeferred ) break; |
| 91191 | + if( p->isDeferred || (db->flags & SQLITE_DeferFKs) ) break; |
| 91150 | 91192 | } |
| 91151 | 91193 | if( !p ) return; |
| 91152 | 91194 | iSkip = sqlite3VdbeMakeLabel(v); |
| 91153 | 91195 | sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip); |
| 91154 | 91196 | } |
| | @@ -91158,15 +91200,22 @@ |
| 91158 | 91200 | pParse->disableTriggers = 0; |
| 91159 | 91201 | |
| 91160 | 91202 | /* If the DELETE has generated immediate foreign key constraint |
| 91161 | 91203 | ** violations, halt the VDBE and return an error at this point, before |
| 91162 | 91204 | ** any modifications to the schema are made. This is because statement |
| 91163 | | - ** transactions are not able to rollback schema changes. */ |
| 91164 | | - sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2); |
| 91165 | | - sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY, |
| 91166 | | - OE_Abort, "foreign key constraint failed", P4_STATIC |
| 91167 | | - ); |
| 91205 | + ** transactions are not able to rollback schema changes. |
| 91206 | + ** |
| 91207 | + ** If the SQLITE_DeferFKs flag is set, then this is not required, as |
| 91208 | + ** the statement transaction will not be rolled back even if FK |
| 91209 | + ** constraints are violated. |
| 91210 | + */ |
| 91211 | + if( (db->flags & SQLITE_DeferFKs)==0 ){ |
| 91212 | + sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2); |
| 91213 | + sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY, |
| 91214 | + OE_Abort, "foreign key constraint failed", P4_STATIC |
| 91215 | + ); |
| 91216 | + } |
| 91168 | 91217 | |
| 91169 | 91218 | if( iSkip ){ |
| 91170 | 91219 | sqlite3VdbeResolveLabel(v, iSkip); |
| 91171 | 91220 | } |
| 91172 | 91221 | } |
| | @@ -95164,22 +95213,23 @@ |
| 95164 | 95213 | #define PragTyp_MMAP_SIZE 23 |
| 95165 | 95214 | #define PragTyp_PAGE_SIZE 24 |
| 95166 | 95215 | #define PragTyp_SECURE_DELETE 25 |
| 95167 | 95216 | #define PragTyp_SHRINK_MEMORY 26 |
| 95168 | 95217 | #define PragTyp_SOFT_HEAP_LIMIT 27 |
| 95169 | | -#define PragTyp_SYNCHRONOUS 28 |
| 95170 | | -#define PragTyp_TABLE_INFO 29 |
| 95171 | | -#define PragTyp_TEMP_STORE 30 |
| 95172 | | -#define PragTyp_TEMP_STORE_DIRECTORY 31 |
| 95173 | | -#define PragTyp_WAL_AUTOCHECKPOINT 32 |
| 95174 | | -#define PragTyp_WAL_CHECKPOINT 33 |
| 95175 | | -#define PragTyp_ACTIVATE_EXTENSIONS 34 |
| 95176 | | -#define PragTyp_HEXKEY 35 |
| 95177 | | -#define PragTyp_KEY 36 |
| 95178 | | -#define PragTyp_REKEY 37 |
| 95179 | | -#define PragTyp_LOCK_STATUS 38 |
| 95180 | | -#define PragTyp_PARSER_TRACE 39 |
| 95218 | +#define PragTyp_STATS 28 |
| 95219 | +#define PragTyp_SYNCHRONOUS 29 |
| 95220 | +#define PragTyp_TABLE_INFO 30 |
| 95221 | +#define PragTyp_TEMP_STORE 31 |
| 95222 | +#define PragTyp_TEMP_STORE_DIRECTORY 32 |
| 95223 | +#define PragTyp_WAL_AUTOCHECKPOINT 33 |
| 95224 | +#define PragTyp_WAL_CHECKPOINT 34 |
| 95225 | +#define PragTyp_ACTIVATE_EXTENSIONS 35 |
| 95226 | +#define PragTyp_HEXKEY 36 |
| 95227 | +#define PragTyp_KEY 37 |
| 95228 | +#define PragTyp_REKEY 38 |
| 95229 | +#define PragTyp_LOCK_STATUS 39 |
| 95230 | +#define PragTyp_PARSER_TRACE 40 |
| 95181 | 95231 | #define PragFlag_NeedSchema 0x01 |
| 95182 | 95232 | static const struct sPragmaNames { |
| 95183 | 95233 | const char *const zName; /* Name of pragma */ |
| 95184 | 95234 | u8 ePragTyp; /* PragTyp_XXX value */ |
| 95185 | 95235 | u8 mPragFlag; /* Zero or more PragFlag_XXX values */ |
| | @@ -95466,10 +95516,16 @@ |
| 95466 | 95516 | #if defined(SQLITE_DEBUG) |
| 95467 | 95517 | { /* zName: */ "sql_trace", |
| 95468 | 95518 | /* ePragTyp: */ PragTyp_FLAG, |
| 95469 | 95519 | /* ePragFlag: */ 0, |
| 95470 | 95520 | /* iArg: */ SQLITE_SqlTrace }, |
| 95521 | +#endif |
| 95522 | +#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
| 95523 | + { /* zName: */ "stats", |
| 95524 | + /* ePragTyp: */ PragTyp_STATS, |
| 95525 | + /* ePragFlag: */ PragFlag_NeedSchema, |
| 95526 | + /* iArg: */ 0 }, |
| 95471 | 95527 | #endif |
| 95472 | 95528 | #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
| 95473 | 95529 | { /* zName: */ "synchronous", |
| 95474 | 95530 | /* ePragTyp: */ PragTyp_SYNCHRONOUS, |
| 95475 | 95531 | /* ePragFlag: */ PragFlag_NeedSchema, |
| | @@ -95528,11 +95584,11 @@ |
| 95528 | 95584 | { /* zName: */ "writable_schema", |
| 95529 | 95585 | /* ePragTyp: */ PragTyp_FLAG, |
| 95530 | 95586 | /* ePragFlag: */ 0, |
| 95531 | 95587 | /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, |
| 95532 | 95588 | }; |
| 95533 | | -/* Number of pragmas: 55 on by default, 67 total. */ |
| 95589 | +/* Number of pragmas: 56 on by default, 68 total. */ |
| 95534 | 95590 | /* End of the automatically generated pragma table. |
| 95535 | 95591 | ***************************************************************************/ |
| 95536 | 95592 | |
| 95537 | 95593 | /* |
| 95538 | 95594 | ** Interpret the given string as a safety level. Return 0 for OFF, |
| | @@ -96532,10 +96588,40 @@ |
| 96532 | 96588 | sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); |
| 96533 | 96589 | } |
| 96534 | 96590 | } |
| 96535 | 96591 | } |
| 96536 | 96592 | break; |
| 96593 | + |
| 96594 | + case PragTyp_STATS: { |
| 96595 | + Index *pIdx; |
| 96596 | + HashElem *i; |
| 96597 | + v = sqlite3GetVdbe(pParse); |
| 96598 | + sqlite3VdbeSetNumCols(v, 4); |
| 96599 | + pParse->nMem = 4; |
| 96600 | + sqlite3CodeVerifySchema(pParse, iDb); |
| 96601 | + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC); |
| 96602 | + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "index", SQLITE_STATIC); |
| 96603 | + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "width", SQLITE_STATIC); |
| 96604 | + sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "height", SQLITE_STATIC); |
| 96605 | + for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){ |
| 96606 | + Table *pTab = sqliteHashData(i); |
| 96607 | + sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, pTab->zName, 0); |
| 96608 | + sqlite3VdbeAddOp2(v, OP_Null, 0, 2); |
| 96609 | + sqlite3VdbeAddOp2(v, OP_Integer, |
| 96610 | + (int)sqlite3LogEstToInt(pTab->szTabRow), 3); |
| 96611 | + sqlite3VdbeAddOp2(v, OP_Integer, (int)pTab->nRowEst, 4); |
| 96612 | + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); |
| 96613 | + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
| 96614 | + sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0); |
| 96615 | + sqlite3VdbeAddOp2(v, OP_Integer, |
| 96616 | + (int)sqlite3LogEstToInt(pIdx->szIdxRow), 3); |
| 96617 | + sqlite3VdbeAddOp2(v, OP_Integer, (int)pIdx->aiRowEst[0], 4); |
| 96618 | + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); |
| 96619 | + } |
| 96620 | + } |
| 96621 | + } |
| 96622 | + break; |
| 96537 | 96623 | |
| 96538 | 96624 | case PragTyp_INDEX_INFO: if( zRight ){ |
| 96539 | 96625 | Index *pIdx; |
| 96540 | 96626 | Table *pTab; |
| 96541 | 96627 | pIdx = sqlite3FindIndex(db, zRight, zDb); |
| | @@ -96565,30 +96651,21 @@ |
| 96565 | 96651 | Table *pTab; |
| 96566 | 96652 | int i; |
| 96567 | 96653 | pTab = sqlite3FindTable(db, zRight, zDb); |
| 96568 | 96654 | if( pTab ){ |
| 96569 | 96655 | v = sqlite3GetVdbe(pParse); |
| 96570 | | - sqlite3VdbeSetNumCols(v, 4); |
| 96571 | | - pParse->nMem = 4; |
| 96656 | + sqlite3VdbeSetNumCols(v, 3); |
| 96657 | + pParse->nMem = 3; |
| 96572 | 96658 | sqlite3CodeVerifySchema(pParse, iDb); |
| 96573 | 96659 | sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC); |
| 96574 | 96660 | sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); |
| 96575 | 96661 | sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC); |
| 96576 | | - sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "avgrowsize", SQLITE_STATIC); |
| 96577 | | - sqlite3VdbeAddOp2(v, OP_Integer, 0, 1); |
| 96578 | | - sqlite3VdbeAddOp2(v, OP_Null, 0, 2); |
| 96579 | | - sqlite3VdbeAddOp2(v, OP_Integer, 1, 3); |
| 96580 | | - sqlite3VdbeAddOp2(v, OP_Integer, |
| 96581 | | - (int)sqlite3LogEstToInt(pTab->szTabRow), 4); |
| 96582 | | - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); |
| 96583 | | - for(pIdx=pTab->pIndex, i=1; pIdx; pIdx=pIdx->pNext, i++){ |
| 96662 | + for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){ |
| 96584 | 96663 | sqlite3VdbeAddOp2(v, OP_Integer, i, 1); |
| 96585 | 96664 | sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0); |
| 96586 | 96665 | sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3); |
| 96587 | | - sqlite3VdbeAddOp2(v, OP_Integer, |
| 96588 | | - (int)sqlite3LogEstToInt(pIdx->szIdxRow), 4); |
| 96589 | | - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); |
| 96666 | + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); |
| 96590 | 96667 | } |
| 96591 | 96668 | } |
| 96592 | 96669 | } |
| 96593 | 96670 | break; |
| 96594 | 96671 | |
| | @@ -96718,12 +96795,12 @@ |
| 96718 | 96795 | if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow; |
| 96719 | 96796 | sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead); |
| 96720 | 96797 | sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName, |
| 96721 | 96798 | P4_TRANSIENT); |
| 96722 | 96799 | for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ |
| 96723 | | - pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb); |
| 96724 | | - if( pParent==0 ) break; |
| 96800 | + pParent = sqlite3FindTable(db, pFK->zTo, zDb); |
| 96801 | + if( pParent==0 ) continue; |
| 96725 | 96802 | pIdx = 0; |
| 96726 | 96803 | sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName); |
| 96727 | 96804 | x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0); |
| 96728 | 96805 | if( x==0 ){ |
| 96729 | 96806 | if( pIdx==0 ){ |
| | @@ -96736,22 +96813,24 @@ |
| 96736 | 96813 | }else{ |
| 96737 | 96814 | k = 0; |
| 96738 | 96815 | break; |
| 96739 | 96816 | } |
| 96740 | 96817 | } |
| 96818 | + assert( pParse->nErr>0 || pFK==0 ); |
| 96741 | 96819 | if( pFK ) break; |
| 96742 | 96820 | if( pParse->nTab<i ) pParse->nTab = i; |
| 96743 | 96821 | addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); |
| 96744 | 96822 | for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ |
| 96745 | | - pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb); |
| 96746 | | - assert( pParent!=0 ); |
| 96823 | + pParent = sqlite3FindTable(db, pFK->zTo, zDb); |
| 96747 | 96824 | pIdx = 0; |
| 96748 | 96825 | aiCols = 0; |
| 96749 | | - x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols); |
| 96750 | | - assert( x==0 ); |
| 96826 | + if( pParent ){ |
| 96827 | + x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols); |
| 96828 | + assert( x==0 ); |
| 96829 | + } |
| 96751 | 96830 | addrOk = sqlite3VdbeMakeLabel(v); |
| 96752 | | - if( pIdx==0 ){ |
| 96831 | + if( pParent && pIdx==0 ){ |
| 96753 | 96832 | int iKey = pFK->aCol[0].iFrom; |
| 96754 | 96833 | assert( iKey>=0 && iKey<pTab->nCol ); |
| 96755 | 96834 | if( iKey!=pTab->iPKey ){ |
| 96756 | 96835 | sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow); |
| 96757 | 96836 | sqlite3ColumnDefault(v, pTab, iKey, regRow); |
| | @@ -96765,17 +96844,19 @@ |
| 96765 | 96844 | sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk); |
| 96766 | 96845 | sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); |
| 96767 | 96846 | }else{ |
| 96768 | 96847 | for(j=0; j<pFK->nCol; j++){ |
| 96769 | 96848 | sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, |
| 96770 | | - aiCols ? aiCols[j] : pFK->aCol[0].iFrom, regRow+j); |
| 96849 | + aiCols ? aiCols[j] : pFK->aCol[j].iFrom, regRow+j); |
| 96771 | 96850 | sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); |
| 96772 | 96851 | } |
| 96773 | | - sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey); |
| 96774 | | - sqlite3VdbeChangeP4(v, -1, |
| 96775 | | - sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT); |
| 96776 | | - sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0); |
| 96852 | + if( pParent ){ |
| 96853 | + sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey); |
| 96854 | + sqlite3VdbeChangeP4(v, -1, |
| 96855 | + sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT); |
| 96856 | + sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0); |
| 96857 | + } |
| 96777 | 96858 | } |
| 96778 | 96859 | sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1); |
| 96779 | 96860 | sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0, |
| 96780 | 96861 | pFK->zTo, P4_TRANSIENT); |
| 96781 | 96862 | sqlite3VdbeAddOp2(v, OP_Integer, i-1, regResult+3); |
| | @@ -108909,10 +108990,13 @@ |
| 108909 | 108990 | int iMin = 0; /* Smallest sample not yet tested */ |
| 108910 | 108991 | int i = pIdx->nSample; /* Smallest sample larger than or equal to pRec */ |
| 108911 | 108992 | int iTest; /* Next sample to test */ |
| 108912 | 108993 | int res; /* Result of comparison operation */ |
| 108913 | 108994 | |
| 108995 | +#ifndef SQLITE_DEBUG |
| 108996 | + UNUSED_PARAMETER( pParse ); |
| 108997 | +#endif |
| 108914 | 108998 | assert( pRec!=0 || pParse->db->mallocFailed ); |
| 108915 | 108999 | if( pRec==0 ) return; |
| 108916 | 109000 | iCol = pRec->nField - 1; |
| 108917 | 109001 | assert( pIdx->nSample>0 ); |
| 108918 | 109002 | assert( pRec->nField>0 && iCol<pIdx->nSampleCol ); |
| | @@ -109026,15 +109110,15 @@ |
| 109026 | 109110 | WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */ |
| 109027 | 109111 | WhereLoop *pLoop /* Modify the .nOut and maybe .rRun fields */ |
| 109028 | 109112 | ){ |
| 109029 | 109113 | int rc = SQLITE_OK; |
| 109030 | 109114 | int nOut = pLoop->nOut; |
| 109031 | | - int nEq = pLoop->u.btree.nEq; |
| 109032 | 109115 | LogEst nNew; |
| 109033 | 109116 | |
| 109034 | 109117 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 109035 | 109118 | Index *p = pLoop->u.btree.pIndex; |
| 109119 | + int nEq = pLoop->u.btree.nEq; |
| 109036 | 109120 | |
| 109037 | 109121 | if( p->nSample>0 |
| 109038 | 109122 | && nEq==pBuilder->nRecValid |
| 109039 | 109123 | && nEq<p->nSampleCol |
| 109040 | 109124 | && OptimizationEnabled(pParse->db, SQLITE_Stat3) |
| | @@ -110754,11 +110838,11 @@ |
| 110754 | 110838 | ** |
| 110755 | 110839 | ** In the current implementation, the first extra WHERE clause term reduces |
| 110756 | 110840 | ** the number of output rows by a factor of 10 and each additional term |
| 110757 | 110841 | ** reduces the number of output rows by sqrt(2). |
| 110758 | 110842 | */ |
| 110759 | | -static void whereLoopOutputAdjust(WhereClause *pWC, WhereLoop *pLoop, int iCur){ |
| 110843 | +static void whereLoopOutputAdjust(WhereClause *pWC, WhereLoop *pLoop){ |
| 110760 | 110844 | WhereTerm *pTerm, *pX; |
| 110761 | 110845 | Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf); |
| 110762 | 110846 | int i, j; |
| 110763 | 110847 | |
| 110764 | 110848 | if( !OptimizationEnabled(pWC->pWInfo->pParse->db, SQLITE_AdjustOutEst) ){ |
| | @@ -110929,12 +111013,12 @@ |
| 110929 | 111013 | && !ExprHasProperty(pExpr, EP_xIsSelect) ){ |
| 110930 | 111014 | rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut); |
| 110931 | 111015 | } |
| 110932 | 111016 | assert( nOut==0 || rc==SQLITE_OK ); |
| 110933 | 111017 | if( nOut ){ |
| 110934 | | - nOut = sqlite3LogEst(nOut); |
| 110935 | | - pNew->nOut = MIN(nOut, saved_nOut); |
| 111018 | + pNew->nOut = sqlite3LogEst(nOut); |
| 111019 | + if( pNew->nOut>saved_nOut ) pNew->nOut = saved_nOut; |
| 110936 | 111020 | } |
| 110937 | 111021 | } |
| 110938 | 111022 | #endif |
| 110939 | 111023 | if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){ |
| 110940 | 111024 | /* Each row involves a step of the index, then a binary search of |
| | @@ -110941,11 +111025,11 @@ |
| 110941 | 111025 | ** the main table */ |
| 110942 | 111026 | pNew->rRun = sqlite3LogEstAdd(pNew->rRun,rLogSize>27 ? rLogSize-17 : 10); |
| 110943 | 111027 | } |
| 110944 | 111028 | /* Step cost for each output row */ |
| 110945 | 111029 | pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut); |
| 110946 | | - whereLoopOutputAdjust(pBuilder->pWC, pNew, pSrc->iCursor); |
| 111030 | + whereLoopOutputAdjust(pBuilder->pWC, pNew); |
| 110947 | 111031 | rc = whereLoopInsert(pBuilder, pNew); |
| 110948 | 111032 | if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 |
| 110949 | 111033 | && pNew->u.btree.nEq<(pProbe->nColumn + (pProbe->zName!=0)) |
| 110950 | 111034 | ){ |
| 110951 | 111035 | whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn); |
| | @@ -111145,11 +111229,11 @@ |
| 111145 | 111229 | pNew->iSortIdx = b ? iSortIdx : 0; |
| 111146 | 111230 | /* TUNING: Cost of full table scan is 3*(N + log2(N)). |
| 111147 | 111231 | ** + The extra 3 factor is to encourage the use of indexed lookups |
| 111148 | 111232 | ** over full scans. FIXME */ |
| 111149 | 111233 | pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 16; |
| 111150 | | - whereLoopOutputAdjust(pWC, pNew, pSrc->iCursor); |
| 111234 | + whereLoopOutputAdjust(pWC, pNew); |
| 111151 | 111235 | rc = whereLoopInsert(pBuilder, pNew); |
| 111152 | 111236 | pNew->nOut = rSize; |
| 111153 | 111237 | if( rc ) break; |
| 111154 | 111238 | }else{ |
| 111155 | 111239 | Bitmask m = pSrc->colUsed & ~columnsInIndex(pProbe); |
| | @@ -111178,11 +111262,11 @@ |
| 111178 | 111262 | assert( b!=0 ); |
| 111179 | 111263 | /* TUNING: Cost of scanning a non-covering index is (N+1)*log2(N) |
| 111180 | 111264 | ** which we will simplify to just N*log2(N) */ |
| 111181 | 111265 | pNew->rRun = rSize + rLogSize; |
| 111182 | 111266 | } |
| 111183 | | - whereLoopOutputAdjust(pWC, pNew, pSrc->iCursor); |
| 111267 | + whereLoopOutputAdjust(pWC, pNew); |
| 111184 | 111268 | rc = whereLoopInsert(pBuilder, pNew); |
| 111185 | 111269 | pNew->nOut = rSize; |
| 111186 | 111270 | if( rc ) break; |
| 111187 | 111271 | } |
| 111188 | 111272 | } |
| | @@ -126258,15 +126342,15 @@ |
| 126258 | 126342 | assert( p->nToken<=MAX_INCR_PHRASE_TOKENS ); |
| 126259 | 126343 | assert( p->iDoclistToken<MAX_INCR_PHRASE_TOKENS ); |
| 126260 | 126344 | |
| 126261 | 126345 | while( bEof==0 ){ |
| 126262 | 126346 | int bMaxSet = 0; |
| 126263 | | - sqlite3_int64 iMax; /* Largest docid for all iterators */ |
| 126347 | + sqlite3_int64 iMax = 0; /* Largest docid for all iterators */ |
| 126264 | 126348 | int i; /* Used to iterate through tokens */ |
| 126265 | 126349 | |
| 126266 | 126350 | /* Advance the iterator for each token in the phrase once. */ |
| 126267 | | - for(i=0; rc==SQLITE_OK && i<p->nToken; i++){ |
| 126351 | + for(i=0; rc==SQLITE_OK && i<p->nToken && bEof==0; i++){ |
| 126268 | 126352 | rc = incrPhraseTokenNext(pTab, p, i, &a[i], &bEof); |
| 126269 | 126353 | if( a[i].bIgnore==0 && (bMaxSet==0 || DOCID_CMP(iMax, a[i].iDocid)<0) ){ |
| 126270 | 126354 | iMax = a[i].iDocid; |
| 126271 | 126355 | bMaxSet = 1; |
| 126272 | 126356 | } |
| | @@ -126301,11 +126385,11 @@ |
| 126301 | 126385 | char *pR = aDoclist; |
| 126302 | 126386 | char *pOut = aDoclist; |
| 126303 | 126387 | int nDist = p->nToken-1-i; |
| 126304 | 126388 | int res = fts3PoslistPhraseMerge(&pOut, nDist, 0, 1, &pL, &pR); |
| 126305 | 126389 | if( res==0 ) break; |
| 126306 | | - nList = (pOut - aDoclist); |
| 126390 | + nList = (int)(pOut - aDoclist); |
| 126307 | 126391 | } |
| 126308 | 126392 | } |
| 126309 | 126393 | if( i==(p->nToken-1) ){ |
| 126310 | 126394 | pDL->iDocid = iMax; |
| 126311 | 126395 | pDL->pList = aDoclist; |
| | @@ -127675,10 +127759,11 @@ |
| 127675 | 127759 | sqlite3_vtab_cursor base; /* Base class used by SQLite core */ |
| 127676 | 127760 | Fts3MultiSegReader csr; /* Must be right after "base" */ |
| 127677 | 127761 | Fts3SegFilter filter; |
| 127678 | 127762 | char *zStop; |
| 127679 | 127763 | int nStop; /* Byte-length of string zStop */ |
| 127764 | + int iLangid; /* Language id to query */ |
| 127680 | 127765 | int isEof; /* True if cursor is at EOF */ |
| 127681 | 127766 | sqlite3_int64 iRowid; /* Current rowid */ |
| 127682 | 127767 | |
| 127683 | 127768 | int iCol; /* Current value of 'col' column */ |
| 127684 | 127769 | int nStat; /* Size of aStat[] array */ |
| | @@ -127689,11 +127774,12 @@ |
| 127689 | 127774 | }; |
| 127690 | 127775 | |
| 127691 | 127776 | /* |
| 127692 | 127777 | ** Schema of the terms table. |
| 127693 | 127778 | */ |
| 127694 | | -#define FTS3_TERMS_SCHEMA "CREATE TABLE x(term, col, documents, occurrences)" |
| 127779 | +#define FTS3_AUX_SCHEMA \ |
| 127780 | + "CREATE TABLE x(term, col, documents, occurrences, languageid HIDDEN)" |
| 127695 | 127781 | |
| 127696 | 127782 | /* |
| 127697 | 127783 | ** This function does all the work for both the xConnect and xCreate methods. |
| 127698 | 127784 | ** These tables have no persistent representation of their own, so xConnect |
| 127699 | 127785 | ** and xCreate are identical operations. |
| | @@ -127736,11 +127822,11 @@ |
| 127736 | 127822 | }else{ |
| 127737 | 127823 | zFts3 = argv[3]; |
| 127738 | 127824 | } |
| 127739 | 127825 | nFts3 = (int)strlen(zFts3); |
| 127740 | 127826 | |
| 127741 | | - rc = sqlite3_declare_vtab(db, FTS3_TERMS_SCHEMA); |
| 127827 | + rc = sqlite3_declare_vtab(db, FTS3_AUX_SCHEMA); |
| 127742 | 127828 | if( rc!=SQLITE_OK ) return rc; |
| 127743 | 127829 | |
| 127744 | 127830 | nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2; |
| 127745 | 127831 | p = (Fts3auxTable *)sqlite3_malloc(nByte); |
| 127746 | 127832 | if( !p ) return SQLITE_NOMEM; |
| | @@ -127796,10 +127882,12 @@ |
| 127796 | 127882 | ){ |
| 127797 | 127883 | int i; |
| 127798 | 127884 | int iEq = -1; |
| 127799 | 127885 | int iGe = -1; |
| 127800 | 127886 | int iLe = -1; |
| 127887 | + int iLangid = -1; |
| 127888 | + int iNext = 1; /* Next free argvIndex value */ |
| 127801 | 127889 | |
| 127802 | 127890 | UNUSED_PARAMETER(pVTab); |
| 127803 | 127891 | |
| 127804 | 127892 | /* This vtab delivers always results in "ORDER BY term ASC" order. */ |
| 127805 | 127893 | if( pInfo->nOrderBy==1 |
| | @@ -127807,40 +127895,52 @@ |
| 127807 | 127895 | && pInfo->aOrderBy[0].desc==0 |
| 127808 | 127896 | ){ |
| 127809 | 127897 | pInfo->orderByConsumed = 1; |
| 127810 | 127898 | } |
| 127811 | 127899 | |
| 127812 | | - /* Search for equality and range constraints on the "term" column. */ |
| 127900 | + /* Search for equality and range constraints on the "term" column. |
| 127901 | + ** And equality constraints on the hidden "languageid" column. */ |
| 127813 | 127902 | for(i=0; i<pInfo->nConstraint; i++){ |
| 127814 | | - if( pInfo->aConstraint[i].usable && pInfo->aConstraint[i].iColumn==0 ){ |
| 127903 | + if( pInfo->aConstraint[i].usable ){ |
| 127815 | 127904 | int op = pInfo->aConstraint[i].op; |
| 127816 | | - if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iEq = i; |
| 127817 | | - if( op==SQLITE_INDEX_CONSTRAINT_LT ) iLe = i; |
| 127818 | | - if( op==SQLITE_INDEX_CONSTRAINT_LE ) iLe = i; |
| 127819 | | - if( op==SQLITE_INDEX_CONSTRAINT_GT ) iGe = i; |
| 127820 | | - if( op==SQLITE_INDEX_CONSTRAINT_GE ) iGe = i; |
| 127905 | + int iCol = pInfo->aConstraint[i].iColumn; |
| 127906 | + |
| 127907 | + if( iCol==0 ){ |
| 127908 | + if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iEq = i; |
| 127909 | + if( op==SQLITE_INDEX_CONSTRAINT_LT ) iLe = i; |
| 127910 | + if( op==SQLITE_INDEX_CONSTRAINT_LE ) iLe = i; |
| 127911 | + if( op==SQLITE_INDEX_CONSTRAINT_GT ) iGe = i; |
| 127912 | + if( op==SQLITE_INDEX_CONSTRAINT_GE ) iGe = i; |
| 127913 | + } |
| 127914 | + if( iCol==4 ){ |
| 127915 | + if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iLangid = i; |
| 127916 | + } |
| 127821 | 127917 | } |
| 127822 | 127918 | } |
| 127823 | 127919 | |
| 127824 | 127920 | if( iEq>=0 ){ |
| 127825 | 127921 | pInfo->idxNum = FTS4AUX_EQ_CONSTRAINT; |
| 127826 | | - pInfo->aConstraintUsage[iEq].argvIndex = 1; |
| 127922 | + pInfo->aConstraintUsage[iEq].argvIndex = iNext++; |
| 127827 | 127923 | pInfo->estimatedCost = 5; |
| 127828 | 127924 | }else{ |
| 127829 | 127925 | pInfo->idxNum = 0; |
| 127830 | 127926 | pInfo->estimatedCost = 20000; |
| 127831 | 127927 | if( iGe>=0 ){ |
| 127832 | 127928 | pInfo->idxNum += FTS4AUX_GE_CONSTRAINT; |
| 127833 | | - pInfo->aConstraintUsage[iGe].argvIndex = 1; |
| 127929 | + pInfo->aConstraintUsage[iGe].argvIndex = iNext++; |
| 127834 | 127930 | pInfo->estimatedCost /= 2; |
| 127835 | 127931 | } |
| 127836 | 127932 | if( iLe>=0 ){ |
| 127837 | 127933 | pInfo->idxNum += FTS4AUX_LE_CONSTRAINT; |
| 127838 | | - pInfo->aConstraintUsage[iLe].argvIndex = 1 + (iGe>=0); |
| 127934 | + pInfo->aConstraintUsage[iLe].argvIndex = iNext++; |
| 127839 | 127935 | pInfo->estimatedCost /= 2; |
| 127840 | 127936 | } |
| 127841 | 127937 | } |
| 127938 | + if( iLangid>=0 ){ |
| 127939 | + pInfo->aConstraintUsage[iLangid].argvIndex = iNext++; |
| 127940 | + pInfo->estimatedCost--; |
| 127941 | + } |
| 127842 | 127942 | |
| 127843 | 127943 | return SQLITE_OK; |
| 127844 | 127944 | } |
| 127845 | 127945 | |
| 127846 | 127946 | /* |
| | @@ -127996,21 +128096,42 @@ |
| 127996 | 128096 | sqlite3_value **apVal /* Arguments for the indexing scheme */ |
| 127997 | 128097 | ){ |
| 127998 | 128098 | Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor; |
| 127999 | 128099 | Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab; |
| 128000 | 128100 | int rc; |
| 128001 | | - int isScan; |
| 128101 | + int isScan = 0; |
| 128102 | + int iLangVal = 0; /* Language id to query */ |
| 128103 | + |
| 128104 | + int iEq = -1; /* Index of term=? value in apVal */ |
| 128105 | + int iGe = -1; /* Index of term>=? value in apVal */ |
| 128106 | + int iLe = -1; /* Index of term<=? value in apVal */ |
| 128107 | + int iLangid = -1; /* Index of languageid=? value in apVal */ |
| 128108 | + int iNext = 0; |
| 128002 | 128109 | |
| 128003 | 128110 | UNUSED_PARAMETER(nVal); |
| 128004 | 128111 | UNUSED_PARAMETER(idxStr); |
| 128005 | 128112 | |
| 128006 | 128113 | assert( idxStr==0 ); |
| 128007 | 128114 | assert( idxNum==FTS4AUX_EQ_CONSTRAINT || idxNum==0 |
| 128008 | 128115 | || idxNum==FTS4AUX_LE_CONSTRAINT || idxNum==FTS4AUX_GE_CONSTRAINT |
| 128009 | 128116 | || idxNum==(FTS4AUX_LE_CONSTRAINT|FTS4AUX_GE_CONSTRAINT) |
| 128010 | 128117 | ); |
| 128011 | | - isScan = (idxNum!=FTS4AUX_EQ_CONSTRAINT); |
| 128118 | + |
| 128119 | + if( idxNum==FTS4AUX_EQ_CONSTRAINT ){ |
| 128120 | + iEq = iNext++; |
| 128121 | + }else{ |
| 128122 | + isScan = 1; |
| 128123 | + if( idxNum & FTS4AUX_GE_CONSTRAINT ){ |
| 128124 | + iGe = iNext++; |
| 128125 | + } |
| 128126 | + if( idxNum & FTS4AUX_LE_CONSTRAINT ){ |
| 128127 | + iLe = iNext++; |
| 128128 | + } |
| 128129 | + } |
| 128130 | + if( iNext<nVal ){ |
| 128131 | + iLangid = iNext++; |
| 128132 | + } |
| 128012 | 128133 | |
| 128013 | 128134 | /* In case this cursor is being reused, close and zero it. */ |
| 128014 | 128135 | testcase(pCsr->filter.zTerm); |
| 128015 | 128136 | sqlite3Fts3SegReaderFinish(&pCsr->csr); |
| 128016 | 128137 | sqlite3_free((void *)pCsr->filter.zTerm); |
| | @@ -128018,26 +128139,39 @@ |
| 128018 | 128139 | memset(&pCsr->csr, 0, ((u8*)&pCsr[1]) - (u8*)&pCsr->csr); |
| 128019 | 128140 | |
| 128020 | 128141 | pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY; |
| 128021 | 128142 | if( isScan ) pCsr->filter.flags |= FTS3_SEGMENT_SCAN; |
| 128022 | 128143 | |
| 128023 | | - if( idxNum&(FTS4AUX_EQ_CONSTRAINT|FTS4AUX_GE_CONSTRAINT) ){ |
| 128144 | + if( iEq>=0 || iGe>=0 ){ |
| 128024 | 128145 | const unsigned char *zStr = sqlite3_value_text(apVal[0]); |
| 128146 | + assert( (iEq==0 && iGe==-1) || (iEq==-1 && iGe==0) ); |
| 128025 | 128147 | if( zStr ){ |
| 128026 | 128148 | pCsr->filter.zTerm = sqlite3_mprintf("%s", zStr); |
| 128027 | 128149 | pCsr->filter.nTerm = sqlite3_value_bytes(apVal[0]); |
| 128028 | 128150 | if( pCsr->filter.zTerm==0 ) return SQLITE_NOMEM; |
| 128029 | 128151 | } |
| 128030 | 128152 | } |
| 128031 | | - if( idxNum&FTS4AUX_LE_CONSTRAINT ){ |
| 128032 | | - int iIdx = (idxNum&FTS4AUX_GE_CONSTRAINT) ? 1 : 0; |
| 128033 | | - pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iIdx])); |
| 128034 | | - pCsr->nStop = sqlite3_value_bytes(apVal[iIdx]); |
| 128153 | + |
| 128154 | + if( iLe>=0 ){ |
| 128155 | + pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iLe])); |
| 128156 | + pCsr->nStop = sqlite3_value_bytes(apVal[iLe]); |
| 128035 | 128157 | if( pCsr->zStop==0 ) return SQLITE_NOMEM; |
| 128036 | 128158 | } |
| 128159 | + |
| 128160 | + if( iLangid>=0 ){ |
| 128161 | + iLangVal = sqlite3_value_int(apVal[iLangid]); |
| 128037 | 128162 | |
| 128038 | | - rc = sqlite3Fts3SegReaderCursor(pFts3, 0, 0, FTS3_SEGCURSOR_ALL, |
| 128163 | + /* If the user specified a negative value for the languageid, use zero |
| 128164 | + ** instead. This works, as the "languageid=?" constraint will also |
| 128165 | + ** be tested by the VDBE layer. The test will always be false (since |
| 128166 | + ** this module will not return a row with a negative languageid), and |
| 128167 | + ** so the overall query will return zero rows. */ |
| 128168 | + if( iLangVal<0 ) iLangVal = 0; |
| 128169 | + } |
| 128170 | + pCsr->iLangid = iLangVal; |
| 128171 | + |
| 128172 | + rc = sqlite3Fts3SegReaderCursor(pFts3, iLangVal, 0, FTS3_SEGCURSOR_ALL, |
| 128039 | 128173 | pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr |
| 128040 | 128174 | ); |
| 128041 | 128175 | if( rc==SQLITE_OK ){ |
| 128042 | 128176 | rc = sqlite3Fts3SegReaderStart(pFts3, &pCsr->csr, &pCsr->filter); |
| 128043 | 128177 | } |
| | @@ -128057,28 +128191,41 @@ |
| 128057 | 128191 | /* |
| 128058 | 128192 | ** xColumn - Return a column value. |
| 128059 | 128193 | */ |
| 128060 | 128194 | static int fts3auxColumnMethod( |
| 128061 | 128195 | sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ |
| 128062 | | - sqlite3_context *pContext, /* Context for sqlite3_result_xxx() calls */ |
| 128196 | + sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */ |
| 128063 | 128197 | int iCol /* Index of column to read value from */ |
| 128064 | 128198 | ){ |
| 128065 | 128199 | Fts3auxCursor *p = (Fts3auxCursor *)pCursor; |
| 128066 | 128200 | |
| 128067 | 128201 | assert( p->isEof==0 ); |
| 128068 | | - if( iCol==0 ){ /* Column "term" */ |
| 128069 | | - sqlite3_result_text(pContext, p->csr.zTerm, p->csr.nTerm, SQLITE_TRANSIENT); |
| 128070 | | - }else if( iCol==1 ){ /* Column "col" */ |
| 128071 | | - if( p->iCol ){ |
| 128072 | | - sqlite3_result_int(pContext, p->iCol-1); |
| 128073 | | - }else{ |
| 128074 | | - sqlite3_result_text(pContext, "*", -1, SQLITE_STATIC); |
| 128075 | | - } |
| 128076 | | - }else if( iCol==2 ){ /* Column "documents" */ |
| 128077 | | - sqlite3_result_int64(pContext, p->aStat[p->iCol].nDoc); |
| 128078 | | - }else{ /* Column "occurrences" */ |
| 128079 | | - sqlite3_result_int64(pContext, p->aStat[p->iCol].nOcc); |
| 128202 | + switch( iCol ){ |
| 128203 | + case 0: /* term */ |
| 128204 | + sqlite3_result_text(pCtx, p->csr.zTerm, p->csr.nTerm, SQLITE_TRANSIENT); |
| 128205 | + break; |
| 128206 | + |
| 128207 | + case 1: /* col */ |
| 128208 | + if( p->iCol ){ |
| 128209 | + sqlite3_result_int(pCtx, p->iCol-1); |
| 128210 | + }else{ |
| 128211 | + sqlite3_result_text(pCtx, "*", -1, SQLITE_STATIC); |
| 128212 | + } |
| 128213 | + break; |
| 128214 | + |
| 128215 | + case 2: /* documents */ |
| 128216 | + sqlite3_result_int64(pCtx, p->aStat[p->iCol].nDoc); |
| 128217 | + break; |
| 128218 | + |
| 128219 | + case 3: /* occurrences */ |
| 128220 | + sqlite3_result_int64(pCtx, p->aStat[p->iCol].nOcc); |
| 128221 | + break; |
| 128222 | + |
| 128223 | + default: /* languageid */ |
| 128224 | + assert( iCol==4 ); |
| 128225 | + sqlite3_result_int(pCtx, p->iLangid); |
| 128226 | + break; |
| 128080 | 128227 | } |
| 128081 | 128228 | |
| 128082 | 128229 | return SQLITE_OK; |
| 128083 | 128230 | } |
| 128084 | 128231 | |
| 128085 | 128232 | |