| | @@ -222,11 +222,11 @@ |
| 222 | 222 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 223 | 223 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 224 | 224 | */ |
| 225 | 225 | #define SQLITE_VERSION "3.8.5" |
| 226 | 226 | #define SQLITE_VERSION_NUMBER 3008005 |
| 227 | | -#define SQLITE_SOURCE_ID "2014-04-18 22:20:31 9a5d38c79d2482a23bcfbc3ff35ca4fa269c768d" |
| 227 | +#define SQLITE_SOURCE_ID "2014-05-28 20:22:28 d018a34a05cec6adda61ed225d084c587343f2a6" |
| 228 | 228 | |
| 229 | 229 | /* |
| 230 | 230 | ** CAPI3REF: Run-Time Library Version Numbers |
| 231 | 231 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 232 | 232 | ** |
| | @@ -673,11 +673,14 @@ |
| 673 | 673 | ** to xWrite(). The SQLITE_IOCAP_POWERSAFE_OVERWRITE property means that |
| 674 | 674 | ** after reboot following a crash or power loss, the only bytes in a |
| 675 | 675 | ** file that were written at the application level might have changed |
| 676 | 676 | ** and that adjacent bytes, even bytes within the same sector are |
| 677 | 677 | ** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN |
| 678 | | -** flag indicate that a file cannot be deleted when open. |
| 678 | +** flag indicate that a file cannot be deleted when open. The |
| 679 | +** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on |
| 680 | +** read-only media and cannot be changed even by processes with |
| 681 | +** elevated privileges. |
| 679 | 682 | */ |
| 680 | 683 | #define SQLITE_IOCAP_ATOMIC 0x00000001 |
| 681 | 684 | #define SQLITE_IOCAP_ATOMIC512 0x00000002 |
| 682 | 685 | #define SQLITE_IOCAP_ATOMIC1K 0x00000004 |
| 683 | 686 | #define SQLITE_IOCAP_ATOMIC2K 0x00000008 |
| | @@ -688,10 +691,11 @@ |
| 688 | 691 | #define SQLITE_IOCAP_ATOMIC64K 0x00000100 |
| 689 | 692 | #define SQLITE_IOCAP_SAFE_APPEND 0x00000200 |
| 690 | 693 | #define SQLITE_IOCAP_SEQUENTIAL 0x00000400 |
| 691 | 694 | #define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800 |
| 692 | 695 | #define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000 |
| 696 | +#define SQLITE_IOCAP_IMMUTABLE 0x00002000 |
| 693 | 697 | |
| 694 | 698 | /* |
| 695 | 699 | ** CAPI3REF: File Locking Levels |
| 696 | 700 | ** |
| 697 | 701 | ** SQLite uses one of these integer values as the second |
| | @@ -2892,10 +2896,34 @@ |
| 2892 | 2896 | ** sqlite3_open_v2(). ^Setting the cache parameter to "private" is |
| 2893 | 2897 | ** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit. |
| 2894 | 2898 | ** ^If sqlite3_open_v2() is used and the "cache" parameter is present in |
| 2895 | 2899 | ** a URI filename, its value overrides any behavior requested by setting |
| 2896 | 2900 | ** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag. |
| 2901 | +** |
| 2902 | +** <li> <b>psow</b>: ^The psow parameter may be "true" (or "on" or "yes" or |
| 2903 | +** "1") or "false" (or "off" or "no" or "0") to indicate that the |
| 2904 | +** [powersafe overwrite] property does or does not apply to the |
| 2905 | +** storage media on which the database file resides. ^The psow query |
| 2906 | +** parameter only works for the built-in unix and Windows VFSes. |
| 2907 | +** |
| 2908 | +** <li> <b>nolock</b>: ^The nolock parameter is a boolean query parameter |
| 2909 | +** which if set disables file locking in rollback journal modes. This |
| 2910 | +** is useful for accessing a database on a filesystem that does not |
| 2911 | +** support locking. Caution: Database corruption might result if two |
| 2912 | +** or more processes write to the same database and any one of those |
| 2913 | +** processes uses nolock=1. |
| 2914 | +** |
| 2915 | +** <li> <b>immutable</b>: ^The immutable parameter is a boolean query |
| 2916 | +** parameter that indicates that the database file is stored on |
| 2917 | +** read-only media. ^When immutable is set, SQLite assumes that the |
| 2918 | +** database file cannot be changed, even by a process with higher |
| 2919 | +** privilege, and so the database is opened read-only and all locking |
| 2920 | +** and change detection is disabled. Caution: Setting the immutable |
| 2921 | +** property on a database file that does in fact change can result |
| 2922 | +** in incorrect query results and/or [SQLITE_CORRUPT] errors. |
| 2923 | +** See also: [SQLITE_IOCAP_IMMUTABLE]. |
| 2924 | +** |
| 2897 | 2925 | ** </ul> |
| 2898 | 2926 | ** |
| 2899 | 2927 | ** ^Specifying an unknown parameter in the query component of a URI is not an |
| 2900 | 2928 | ** error. Future versions of SQLite might understand additional query |
| 2901 | 2929 | ** parameters. See "[query parameters with special meaning to SQLite]" for |
| | @@ -2921,12 +2949,13 @@ |
| 2921 | 2949 | ** in URI filenames. |
| 2922 | 2950 | ** <tr><td> file:data.db?mode=ro&cache=private <td> |
| 2923 | 2951 | ** Open file "data.db" in the current directory for read-only access. |
| 2924 | 2952 | ** Regardless of whether or not shared-cache mode is enabled by |
| 2925 | 2953 | ** default, use a private cache. |
| 2926 | | -** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td> |
| 2927 | | -** Open file "/home/fred/data.db". Use the special VFS "unix-nolock". |
| 2954 | +** <tr><td> file:/home/fred/data.db?vfs=unix-dotfile <td> |
| 2955 | +** Open file "/home/fred/data.db". Use the special VFS "unix-dotfile" |
| 2956 | +** that uses dot-files in place of posix advisory locking. |
| 2928 | 2957 | ** <tr><td> file:data.db?mode=readonly <td> |
| 2929 | 2958 | ** An error. "readonly" is not a valid option for the "mode" parameter. |
| 2930 | 2959 | ** </table> |
| 2931 | 2960 | ** |
| 2932 | 2961 | ** ^URI hexadecimal escape sequences (%HH) are supported within the path and |
| | @@ -7460,10 +7489,20 @@ |
| 7460 | 7489 | #if 0 |
| 7461 | 7490 | extern "C" { |
| 7462 | 7491 | #endif |
| 7463 | 7492 | |
| 7464 | 7493 | typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry; |
| 7494 | +typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info; |
| 7495 | + |
| 7496 | +/* The double-precision datatype used by RTree depends on the |
| 7497 | +** SQLITE_RTREE_INT_ONLY compile-time option. |
| 7498 | +*/ |
| 7499 | +#ifdef SQLITE_RTREE_INT_ONLY |
| 7500 | + typedef sqlite3_int64 sqlite3_rtree_dbl; |
| 7501 | +#else |
| 7502 | + typedef double sqlite3_rtree_dbl; |
| 7503 | +#endif |
| 7465 | 7504 | |
| 7466 | 7505 | /* |
| 7467 | 7506 | ** Register a geometry callback named zGeom that can be used as part of an |
| 7468 | 7507 | ** R-Tree geometry query as follows: |
| 7469 | 7508 | ** |
| | @@ -7470,15 +7509,11 @@ |
| 7470 | 7509 | ** SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zGeom(... params ...) |
| 7471 | 7510 | */ |
| 7472 | 7511 | SQLITE_API int sqlite3_rtree_geometry_callback( |
| 7473 | 7512 | sqlite3 *db, |
| 7474 | 7513 | const char *zGeom, |
| 7475 | | -#ifdef SQLITE_RTREE_INT_ONLY |
| 7476 | | - int (*xGeom)(sqlite3_rtree_geometry*, int n, sqlite3_int64 *a, int *pRes), |
| 7477 | | -#else |
| 7478 | | - int (*xGeom)(sqlite3_rtree_geometry*, int n, double *a, int *pRes), |
| 7479 | | -#endif |
| 7514 | + int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*), |
| 7480 | 7515 | void *pContext |
| 7481 | 7516 | ); |
| 7482 | 7517 | |
| 7483 | 7518 | |
| 7484 | 7519 | /* |
| | @@ -7486,15 +7521,64 @@ |
| 7486 | 7521 | ** argument to callbacks registered using rtree_geometry_callback(). |
| 7487 | 7522 | */ |
| 7488 | 7523 | struct sqlite3_rtree_geometry { |
| 7489 | 7524 | void *pContext; /* Copy of pContext passed to s_r_g_c() */ |
| 7490 | 7525 | int nParam; /* Size of array aParam[] */ |
| 7491 | | - double *aParam; /* Parameters passed to SQL geom function */ |
| 7526 | + sqlite3_rtree_dbl *aParam; /* Parameters passed to SQL geom function */ |
| 7492 | 7527 | void *pUser; /* Callback implementation user data */ |
| 7493 | 7528 | void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */ |
| 7494 | 7529 | }; |
| 7495 | 7530 | |
| 7531 | +/* |
| 7532 | +** Register a 2nd-generation geometry callback named zScore that can be |
| 7533 | +** used as part of an R-Tree geometry query as follows: |
| 7534 | +** |
| 7535 | +** SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zQueryFunc(... params ...) |
| 7536 | +*/ |
| 7537 | +SQLITE_API int sqlite3_rtree_query_callback( |
| 7538 | + sqlite3 *db, |
| 7539 | + const char *zQueryFunc, |
| 7540 | + int (*xQueryFunc)(sqlite3_rtree_query_info*), |
| 7541 | + void *pContext, |
| 7542 | + void (*xDestructor)(void*) |
| 7543 | +); |
| 7544 | + |
| 7545 | + |
| 7546 | +/* |
| 7547 | +** A pointer to a structure of the following type is passed as the |
| 7548 | +** argument to scored geometry callback registered using |
| 7549 | +** sqlite3_rtree_query_callback(). |
| 7550 | +** |
| 7551 | +** Note that the first 5 fields of this structure are identical to |
| 7552 | +** sqlite3_rtree_geometry. This structure is a subclass of |
| 7553 | +** sqlite3_rtree_geometry. |
| 7554 | +*/ |
| 7555 | +struct sqlite3_rtree_query_info { |
| 7556 | + void *pContext; /* pContext from when function registered */ |
| 7557 | + int nParam; /* Number of function parameters */ |
| 7558 | + sqlite3_rtree_dbl *aParam; /* value of function parameters */ |
| 7559 | + void *pUser; /* callback can use this, if desired */ |
| 7560 | + void (*xDelUser)(void*); /* function to free pUser */ |
| 7561 | + sqlite3_rtree_dbl *aCoord; /* Coordinates of node or entry to check */ |
| 7562 | + unsigned int *anQueue; /* Number of pending entries in the queue */ |
| 7563 | + int nCoord; /* Number of coordinates */ |
| 7564 | + int iLevel; /* Level of current node or entry */ |
| 7565 | + int mxLevel; /* The largest iLevel value in the tree */ |
| 7566 | + sqlite3_int64 iRowid; /* Rowid for current entry */ |
| 7567 | + sqlite3_rtree_dbl rParentScore; /* Score of parent node */ |
| 7568 | + int eParentWithin; /* Visibility of parent node */ |
| 7569 | + int eWithin; /* OUT: Visiblity */ |
| 7570 | + sqlite3_rtree_dbl rScore; /* OUT: Write the score here */ |
| 7571 | +}; |
| 7572 | + |
| 7573 | +/* |
| 7574 | +** Allowed values for sqlite3_rtree_query.eWithin and .eParentWithin. |
| 7575 | +*/ |
| 7576 | +#define NOT_WITHIN 0 /* Object completely outside of query region */ |
| 7577 | +#define PARTLY_WITHIN 1 /* Object partially overlaps query region */ |
| 7578 | +#define FULLY_WITHIN 2 /* Object fully contained within query region */ |
| 7579 | + |
| 7496 | 7580 | |
| 7497 | 7581 | #if 0 |
| 7498 | 7582 | } /* end of the 'extern "C"' block */ |
| 7499 | 7583 | #endif |
| 7500 | 7584 | |
| | @@ -8417,14 +8501,14 @@ |
| 8417 | 8501 | ** Estimated quantities used for query planning are stored as 16-bit |
| 8418 | 8502 | ** logarithms. For quantity X, the value stored is 10*log2(X). This |
| 8419 | 8503 | ** gives a possible range of values of approximately 1.0e986 to 1e-986. |
| 8420 | 8504 | ** But the allowed values are "grainy". Not every value is representable. |
| 8421 | 8505 | ** For example, quantities 16 and 17 are both represented by a LogEst |
| 8422 | | -** of 40. However, since LogEst quantatites are suppose to be estimates, |
| 8506 | +** of 40. However, since LogEst quantaties are suppose to be estimates, |
| 8423 | 8507 | ** not exact values, this imprecision is not a problem. |
| 8424 | 8508 | ** |
| 8425 | | -** "LogEst" is short for "Logarithimic Estimate". |
| 8509 | +** "LogEst" is short for "Logarithmic Estimate". |
| 8426 | 8510 | ** |
| 8427 | 8511 | ** Examples: |
| 8428 | 8512 | ** 1 -> 0 20 -> 43 10000 -> 132 |
| 8429 | 8513 | ** 2 -> 10 25 -> 46 25000 -> 146 |
| 8430 | 8514 | ** 3 -> 16 100 -> 66 1000000 -> 199 |
| | @@ -8916,10 +9000,11 @@ |
| 8916 | 9000 | SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); |
| 8917 | 9001 | SQLITE_PRIVATE void sqlite3BtreeIncrblobCursor(BtCursor *); |
| 8918 | 9002 | SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *); |
| 8919 | 9003 | SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBt, int iVersion); |
| 8920 | 9004 | SQLITE_PRIVATE void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask); |
| 9005 | +SQLITE_PRIVATE int sqlite3BtreeIsReadonly(Btree *pBt); |
| 8921 | 9006 | |
| 8922 | 9007 | #ifndef NDEBUG |
| 8923 | 9008 | SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*); |
| 8924 | 9009 | #endif |
| 8925 | 9010 | |
| | @@ -9870,87 +9955,75 @@ |
| 9870 | 9955 | */ |
| 9871 | 9956 | #ifndef _SQLITE_OS_H_ |
| 9872 | 9957 | #define _SQLITE_OS_H_ |
| 9873 | 9958 | |
| 9874 | 9959 | /* |
| 9875 | | -** Figure out if we are dealing with Unix, Windows, or some other |
| 9876 | | -** operating system. After the following block of preprocess macros, |
| 9877 | | -** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, and SQLITE_OS_OTHER |
| 9878 | | -** will defined to either 1 or 0. One of the four will be 1. The other |
| 9879 | | -** three will be 0. |
| 9960 | +** Attempt to automatically detect the operating system and setup the |
| 9961 | +** necessary pre-processor macros for it. |
| 9962 | +*/ |
| 9963 | +/************** Include os_setup.h in the middle of os.h *********************/ |
| 9964 | +/************** Begin file os_setup.h ****************************************/ |
| 9965 | +/* |
| 9966 | +** 2013 November 25 |
| 9967 | +** |
| 9968 | +** The author disclaims copyright to this source code. In place of |
| 9969 | +** a legal notice, here is a blessing: |
| 9970 | +** |
| 9971 | +** May you do good and not evil. |
| 9972 | +** May you find forgiveness for yourself and forgive others. |
| 9973 | +** May you share freely, never taking more than you give. |
| 9974 | +** |
| 9975 | +****************************************************************************** |
| 9976 | +** |
| 9977 | +** This file contains pre-processor directives related to operating system |
| 9978 | +** detection and/or setup. |
| 9979 | +*/ |
| 9980 | +#ifndef _OS_SETUP_H_ |
| 9981 | +#define _OS_SETUP_H_ |
| 9982 | + |
| 9983 | +/* |
| 9984 | +** Figure out if we are dealing with Unix, Windows, or some other operating |
| 9985 | +** system. |
| 9986 | +** |
| 9987 | +** After the following block of preprocess macros, all of SQLITE_OS_UNIX, |
| 9988 | +** SQLITE_OS_WIN, and SQLITE_OS_OTHER will defined to either 1 or 0. One of |
| 9989 | +** the three will be 1. The other two will be 0. |
| 9880 | 9990 | */ |
| 9881 | 9991 | #if defined(SQLITE_OS_OTHER) |
| 9882 | | -# if SQLITE_OS_OTHER==1 |
| 9883 | | -# undef SQLITE_OS_UNIX |
| 9884 | | -# define SQLITE_OS_UNIX 0 |
| 9885 | | -# undef SQLITE_OS_WIN |
| 9886 | | -# define SQLITE_OS_WIN 0 |
| 9887 | | -# else |
| 9888 | | -# undef SQLITE_OS_OTHER |
| 9889 | | -# endif |
| 9992 | +# if SQLITE_OS_OTHER==1 |
| 9993 | +# undef SQLITE_OS_UNIX |
| 9994 | +# define SQLITE_OS_UNIX 0 |
| 9995 | +# undef SQLITE_OS_WIN |
| 9996 | +# define SQLITE_OS_WIN 0 |
| 9997 | +# else |
| 9998 | +# undef SQLITE_OS_OTHER |
| 9999 | +# endif |
| 9890 | 10000 | #endif |
| 9891 | 10001 | #if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER) |
| 9892 | | -# define SQLITE_OS_OTHER 0 |
| 9893 | | -# ifndef SQLITE_OS_WIN |
| 9894 | | -# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__) |
| 9895 | | -# define SQLITE_OS_WIN 1 |
| 9896 | | -# define SQLITE_OS_UNIX 0 |
| 9897 | | -# else |
| 9898 | | -# define SQLITE_OS_WIN 0 |
| 9899 | | -# define SQLITE_OS_UNIX 1 |
| 10002 | +# define SQLITE_OS_OTHER 0 |
| 10003 | +# ifndef SQLITE_OS_WIN |
| 10004 | +# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \ |
| 10005 | + defined(__MINGW32__) || defined(__BORLANDC__) |
| 10006 | +# define SQLITE_OS_WIN 1 |
| 10007 | +# define SQLITE_OS_UNIX 0 |
| 10008 | +# else |
| 10009 | +# define SQLITE_OS_WIN 0 |
| 10010 | +# define SQLITE_OS_UNIX 1 |
| 10011 | +# endif |
| 10012 | +# else |
| 10013 | +# define SQLITE_OS_UNIX 0 |
| 10014 | +# endif |
| 10015 | +#else |
| 10016 | +# ifndef SQLITE_OS_WIN |
| 10017 | +# define SQLITE_OS_WIN 0 |
| 9900 | 10018 | # endif |
| 9901 | | -# else |
| 9902 | | -# define SQLITE_OS_UNIX 0 |
| 9903 | | -# endif |
| 9904 | | -#else |
| 9905 | | -# ifndef SQLITE_OS_WIN |
| 9906 | | -# define SQLITE_OS_WIN 0 |
| 9907 | | -# endif |
| 9908 | | -#endif |
| 9909 | | - |
| 9910 | | -#if SQLITE_OS_WIN |
| 9911 | | -# include <windows.h> |
| 9912 | | -#endif |
| 9913 | | - |
| 9914 | | -/* |
| 9915 | | -** Determine if we are dealing with Windows NT. |
| 9916 | | -** |
| 9917 | | -** We ought to be able to determine if we are compiling for win98 or winNT |
| 9918 | | -** using the _WIN32_WINNT macro as follows: |
| 9919 | | -** |
| 9920 | | -** #if defined(_WIN32_WINNT) |
| 9921 | | -** # define SQLITE_OS_WINNT 1 |
| 9922 | | -** #else |
| 9923 | | -** # define SQLITE_OS_WINNT 0 |
| 9924 | | -** #endif |
| 9925 | | -** |
| 9926 | | -** However, vs2005 does not set _WIN32_WINNT by default, as it ought to, |
| 9927 | | -** so the above test does not work. We'll just assume that everything is |
| 9928 | | -** winNT unless the programmer explicitly says otherwise by setting |
| 9929 | | -** SQLITE_OS_WINNT to 0. |
| 9930 | | -*/ |
| 9931 | | -#if SQLITE_OS_WIN && !defined(SQLITE_OS_WINNT) |
| 9932 | | -# define SQLITE_OS_WINNT 1 |
| 9933 | | -#endif |
| 9934 | | - |
| 9935 | | -/* |
| 9936 | | -** Determine if we are dealing with WindowsCE - which has a much |
| 9937 | | -** reduced API. |
| 9938 | | -*/ |
| 9939 | | -#if defined(_WIN32_WCE) |
| 9940 | | -# define SQLITE_OS_WINCE 1 |
| 9941 | | -#else |
| 9942 | | -# define SQLITE_OS_WINCE 0 |
| 9943 | | -#endif |
| 9944 | | - |
| 9945 | | -/* |
| 9946 | | -** Determine if we are dealing with WinRT, which provides only a subset of |
| 9947 | | -** the full Win32 API. |
| 9948 | | -*/ |
| 9949 | | -#if !defined(SQLITE_OS_WINRT) |
| 9950 | | -# define SQLITE_OS_WINRT 0 |
| 9951 | | -#endif |
| 10019 | +#endif |
| 10020 | + |
| 10021 | +#endif /* _OS_SETUP_H_ */ |
| 10022 | + |
| 10023 | +/************** End of os_setup.h ********************************************/ |
| 10024 | +/************** Continuing where we left off in os.h *************************/ |
| 9952 | 10025 | |
| 9953 | 10026 | /* If the SET_FULLSYNC macro is not defined above, then make it |
| 9954 | 10027 | ** a no-op |
| 9955 | 10028 | */ |
| 9956 | 10029 | #ifndef SET_FULLSYNC |
| | @@ -10845,11 +10918,11 @@ |
| 10845 | 10918 | FKey *pFKey; /* Linked list of all foreign keys in this table */ |
| 10846 | 10919 | char *zColAff; /* String defining the affinity of each column */ |
| 10847 | 10920 | #ifndef SQLITE_OMIT_CHECK |
| 10848 | 10921 | ExprList *pCheck; /* All CHECK constraints */ |
| 10849 | 10922 | #endif |
| 10850 | | - tRowcnt nRowEst; /* Estimated rows in table - from sqlite_stat1 table */ |
| 10923 | + LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */ |
| 10851 | 10924 | int tnum; /* Root BTree node for this table (see note above) */ |
| 10852 | 10925 | i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */ |
| 10853 | 10926 | i16 nCol; /* Number of columns in this table */ |
| 10854 | 10927 | u16 nRef; /* Number of pointers to this Table */ |
| 10855 | 10928 | LogEst szTabRow; /* Estimated size of each table row in bytes */ |
| | @@ -11054,11 +11127,11 @@ |
| 11054 | 11127 | ** element. |
| 11055 | 11128 | */ |
| 11056 | 11129 | struct Index { |
| 11057 | 11130 | char *zName; /* Name of this index */ |
| 11058 | 11131 | i16 *aiColumn; /* Which columns are used by this index. 1st is 0 */ |
| 11059 | | - tRowcnt *aiRowEst; /* From ANALYZE: Est. rows selected by each column */ |
| 11132 | + LogEst *aiRowLogEst; /* From ANALYZE: Est. rows selected by each column */ |
| 11060 | 11133 | Table *pTable; /* The SQL table being indexed */ |
| 11061 | 11134 | char *zColAff; /* String defining the affinity of each column */ |
| 11062 | 11135 | Index *pNext; /* The next index associated with the same table */ |
| 11063 | 11136 | Schema *pSchema; /* Schema containing this index */ |
| 11064 | 11137 | u8 *aSortOrder; /* for each column: True==DESC, False==ASC */ |
| | @@ -11068,11 +11141,11 @@ |
| 11068 | 11141 | int tnum; /* DB Page containing root of this index */ |
| 11069 | 11142 | LogEst szIdxRow; /* Estimated average row size in bytes */ |
| 11070 | 11143 | u16 nKeyCol; /* Number of columns forming the key */ |
| 11071 | 11144 | u16 nColumn; /* Number of columns stored in the index */ |
| 11072 | 11145 | u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ |
| 11073 | | - unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */ |
| 11146 | + unsigned idxType:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */ |
| 11074 | 11147 | unsigned bUnordered:1; /* Use this index for == or IN queries only */ |
| 11075 | 11148 | unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */ |
| 11076 | 11149 | unsigned isResized:1; /* True if resizeIndexObject() has been called */ |
| 11077 | 11150 | unsigned isCovering:1; /* True if this is a covering index */ |
| 11078 | 11151 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| | @@ -11081,10 +11154,20 @@ |
| 11081 | 11154 | tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */ |
| 11082 | 11155 | IndexSample *aSample; /* Samples of the left-most key */ |
| 11083 | 11156 | #endif |
| 11084 | 11157 | }; |
| 11085 | 11158 | |
| 11159 | +/* |
| 11160 | +** Allowed values for Index.idxType |
| 11161 | +*/ |
| 11162 | +#define SQLITE_IDXTYPE_APPDEF 0 /* Created using CREATE INDEX */ |
| 11163 | +#define SQLITE_IDXTYPE_UNIQUE 1 /* Implements a UNIQUE constraint */ |
| 11164 | +#define SQLITE_IDXTYPE_PRIMARYKEY 2 /* Is the PRIMARY KEY for the table */ |
| 11165 | + |
| 11166 | +/* Return true if index X is a PRIMARY KEY index */ |
| 11167 | +#define IsPrimaryKeyIndex(X) ((X)->idxType==SQLITE_IDXTYPE_PRIMARYKEY) |
| 11168 | + |
| 11086 | 11169 | /* |
| 11087 | 11170 | ** Each sample stored in the sqlite_stat3 table is represented in memory |
| 11088 | 11171 | ** using a structure of this type. See documentation at the top of the |
| 11089 | 11172 | ** analyze.c source file for additional information. |
| 11090 | 11173 | */ |
| | @@ -11499,10 +11582,11 @@ |
| 11499 | 11582 | #define WHERE_ONETABLE_ONLY 0x0040 /* Only code the 1st table in pTabList */ |
| 11500 | 11583 | #define WHERE_AND_ONLY 0x0080 /* Don't use indices for OR terms */ |
| 11501 | 11584 | #define WHERE_GROUPBY 0x0100 /* pOrderBy is really a GROUP BY */ |
| 11502 | 11585 | #define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */ |
| 11503 | 11586 | #define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */ |
| 11587 | +#define WHERE_SORTBYGROUP 0x0800 /* Support sqlite3WhereIsSorted() */ |
| 11504 | 11588 | |
| 11505 | 11589 | /* Allowed return values from sqlite3WhereIsDistinct() |
| 11506 | 11590 | */ |
| 11507 | 11591 | #define WHERE_DISTINCT_NOOP 0 /* DISTINCT keyword not used */ |
| 11508 | 11592 | #define WHERE_DISTINCT_UNIQUE 1 /* No duplicates */ |
| | @@ -12082,15 +12166,14 @@ |
| 12082 | 12166 | int isInit; /* True after initialization has finished */ |
| 12083 | 12167 | int inProgress; /* True while initialization in progress */ |
| 12084 | 12168 | int isMutexInit; /* True after mutexes are initialized */ |
| 12085 | 12169 | int isMallocInit; /* True after malloc is initialized */ |
| 12086 | 12170 | int isPCacheInit; /* True after malloc is initialized */ |
| 12087 | | - sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */ |
| 12088 | 12171 | int nRefInitMutex; /* Number of users of pInitMutex */ |
| 12172 | + sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */ |
| 12089 | 12173 | void (*xLog)(void*,int,const char*); /* Function for logging */ |
| 12090 | 12174 | void *pLogArg; /* First argument to xLog() */ |
| 12091 | | - int bLocaltimeFault; /* True to fail localtime() calls */ |
| 12092 | 12175 | #ifdef SQLITE_ENABLE_SQLLOG |
| 12093 | 12176 | void(*xSqllog)(void*,sqlite3*,const char*, int); |
| 12094 | 12177 | void *pSqllogArg; |
| 12095 | 12178 | #endif |
| 12096 | 12179 | #ifdef SQLITE_VDBE_COVERAGE |
| | @@ -12098,10 +12181,14 @@ |
| 12098 | 12181 | ** operation. Set the callback using SQLITE_TESTCTRL_VDBE_COVERAGE. |
| 12099 | 12182 | */ |
| 12100 | 12183 | void (*xVdbeBranch)(void*,int iSrcLine,u8 eThis,u8 eMx); /* Callback */ |
| 12101 | 12184 | void *pVdbeBranchArg; /* 1st argument */ |
| 12102 | 12185 | #endif |
| 12186 | +#ifndef SQLITE_OMIT_BUILTIN_TEST |
| 12187 | + int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */ |
| 12188 | +#endif |
| 12189 | + int bLocaltimeFault; /* True to fail localtime() calls */ |
| 12103 | 12190 | }; |
| 12104 | 12191 | |
| 12105 | 12192 | /* |
| 12106 | 12193 | ** This macro is used inside of assert() statements to indicate that |
| 12107 | 12194 | ** the assert is only valid on a well-formed database. Instead of: |
| | @@ -12398,10 +12485,16 @@ |
| 12398 | 12485 | SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*); |
| 12399 | 12486 | SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*, |
| 12400 | 12487 | sqlite3_vfs**,char**,char **); |
| 12401 | 12488 | SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3*,const char*); |
| 12402 | 12489 | SQLITE_PRIVATE int sqlite3CodeOnce(Parse *); |
| 12490 | + |
| 12491 | +#ifdef SQLITE_OMIT_BUILTIN_TEST |
| 12492 | +# define sqlite3FaultSim(X) SQLITE_OK |
| 12493 | +#else |
| 12494 | +SQLITE_PRIVATE int sqlite3FaultSim(int); |
| 12495 | +#endif |
| 12403 | 12496 | |
| 12404 | 12497 | SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32); |
| 12405 | 12498 | SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec*, u32); |
| 12406 | 12499 | SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec*, u32); |
| 12407 | 12500 | SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec*, u32, void*); |
| | @@ -12466,10 +12559,11 @@ |
| 12466 | 12559 | SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int); |
| 12467 | 12560 | SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*); |
| 12468 | 12561 | SQLITE_PRIVATE u64 sqlite3WhereOutputRowCount(WhereInfo*); |
| 12469 | 12562 | SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo*); |
| 12470 | 12563 | SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo*); |
| 12564 | +SQLITE_PRIVATE int sqlite3WhereIsSorted(WhereInfo*); |
| 12471 | 12565 | SQLITE_PRIVATE int sqlite3WhereContinueLabel(WhereInfo*); |
| 12472 | 12566 | SQLITE_PRIVATE int sqlite3WhereBreakLabel(WhereInfo*); |
| 12473 | 12567 | SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo*, int*); |
| 12474 | 12568 | SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8); |
| 12475 | 12569 | SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int); |
| | @@ -13203,19 +13297,26 @@ |
| 13203 | 13297 | 0, /* isInit */ |
| 13204 | 13298 | 0, /* inProgress */ |
| 13205 | 13299 | 0, /* isMutexInit */ |
| 13206 | 13300 | 0, /* isMallocInit */ |
| 13207 | 13301 | 0, /* isPCacheInit */ |
| 13208 | | - 0, /* pInitMutex */ |
| 13209 | 13302 | 0, /* nRefInitMutex */ |
| 13303 | + 0, /* pInitMutex */ |
| 13210 | 13304 | 0, /* xLog */ |
| 13211 | 13305 | 0, /* pLogArg */ |
| 13212 | | - 0, /* bLocaltimeFault */ |
| 13213 | 13306 | #ifdef SQLITE_ENABLE_SQLLOG |
| 13214 | 13307 | 0, /* xSqllog */ |
| 13215 | | - 0 /* pSqllogArg */ |
| 13308 | + 0, /* pSqllogArg */ |
| 13216 | 13309 | #endif |
| 13310 | +#ifdef SQLITE_VDBE_COVERAGE |
| 13311 | + 0, /* xVdbeBranch */ |
| 13312 | + 0, /* pVbeBranchArg */ |
| 13313 | +#endif |
| 13314 | +#ifndef SQLITE_OMIT_BUILTIN_TEST |
| 13315 | + 0, /* xTestCallback */ |
| 13316 | +#endif |
| 13317 | + 0 /* bLocaltimeFault */ |
| 13217 | 13318 | }; |
| 13218 | 13319 | |
| 13219 | 13320 | /* |
| 13220 | 13321 | ** Hash table for global functions - functions common to all |
| 13221 | 13322 | ** database connections. After initialization, this table is |
| | @@ -18934,10 +19035,88 @@ |
| 18934 | 19035 | ** |
| 18935 | 19036 | ************************************************************************* |
| 18936 | 19037 | ** This file contains the C functions that implement mutexes for win32 |
| 18937 | 19038 | */ |
| 18938 | 19039 | |
| 19040 | +#if SQLITE_OS_WIN |
| 19041 | +/* |
| 19042 | +** Include the header file for the Windows VFS. |
| 19043 | +*/ |
| 19044 | +/************** Include os_win.h in the middle of mutex_w32.c ****************/ |
| 19045 | +/************** Begin file os_win.h ******************************************/ |
| 19046 | +/* |
| 19047 | +** 2013 November 25 |
| 19048 | +** |
| 19049 | +** The author disclaims copyright to this source code. In place of |
| 19050 | +** a legal notice, here is a blessing: |
| 19051 | +** |
| 19052 | +** May you do good and not evil. |
| 19053 | +** May you find forgiveness for yourself and forgive others. |
| 19054 | +** May you share freely, never taking more than you give. |
| 19055 | +** |
| 19056 | +****************************************************************************** |
| 19057 | +** |
| 19058 | +** This file contains code that is specific to Windows. |
| 19059 | +*/ |
| 19060 | +#ifndef _OS_WIN_H_ |
| 19061 | +#define _OS_WIN_H_ |
| 19062 | + |
| 19063 | +/* |
| 19064 | +** Include the primary Windows SDK header file. |
| 19065 | +*/ |
| 19066 | +#include "windows.h" |
| 19067 | + |
| 19068 | +#ifdef __CYGWIN__ |
| 19069 | +# include <sys/cygwin.h> |
| 19070 | +# include <errno.h> /* amalgamator: dontcache */ |
| 19071 | +#endif |
| 19072 | + |
| 19073 | +/* |
| 19074 | +** Determine if we are dealing with Windows NT. |
| 19075 | +** |
| 19076 | +** We ought to be able to determine if we are compiling for Windows 9x or |
| 19077 | +** Windows NT using the _WIN32_WINNT macro as follows: |
| 19078 | +** |
| 19079 | +** #if defined(_WIN32_WINNT) |
| 19080 | +** # define SQLITE_OS_WINNT 1 |
| 19081 | +** #else |
| 19082 | +** # define SQLITE_OS_WINNT 0 |
| 19083 | +** #endif |
| 19084 | +** |
| 19085 | +** However, Visual Studio 2005 does not set _WIN32_WINNT by default, as |
| 19086 | +** it ought to, so the above test does not work. We'll just assume that |
| 19087 | +** everything is Windows NT unless the programmer explicitly says otherwise |
| 19088 | +** by setting SQLITE_OS_WINNT to 0. |
| 19089 | +*/ |
| 19090 | +#if SQLITE_OS_WIN && !defined(SQLITE_OS_WINNT) |
| 19091 | +# define SQLITE_OS_WINNT 1 |
| 19092 | +#endif |
| 19093 | + |
| 19094 | +/* |
| 19095 | +** Determine if we are dealing with Windows CE - which has a much reduced |
| 19096 | +** API. |
| 19097 | +*/ |
| 19098 | +#if defined(_WIN32_WCE) |
| 19099 | +# define SQLITE_OS_WINCE 1 |
| 19100 | +#else |
| 19101 | +# define SQLITE_OS_WINCE 0 |
| 19102 | +#endif |
| 19103 | + |
| 19104 | +/* |
| 19105 | +** Determine if we are dealing with WinRT, which provides only a subset of |
| 19106 | +** the full Win32 API. |
| 19107 | +*/ |
| 19108 | +#if !defined(SQLITE_OS_WINRT) |
| 19109 | +# define SQLITE_OS_WINRT 0 |
| 19110 | +#endif |
| 19111 | + |
| 19112 | +#endif /* _OS_WIN_H_ */ |
| 19113 | + |
| 19114 | +/************** End of os_win.h **********************************************/ |
| 19115 | +/************** Continuing where we left off in mutex_w32.c ******************/ |
| 19116 | +#endif |
| 19117 | + |
| 18939 | 19118 | /* |
| 18940 | 19119 | ** The code in this file is only used if we are compiling multithreaded |
| 18941 | 19120 | ** on a win32 system. |
| 18942 | 19121 | */ |
| 18943 | 19122 | #ifdef SQLITE_MUTEX_W32 |
| | @@ -21789,10 +21968,28 @@ |
| 21789 | 21968 | static unsigned dummy = 0; |
| 21790 | 21969 | dummy += (unsigned)x; |
| 21791 | 21970 | } |
| 21792 | 21971 | #endif |
| 21793 | 21972 | |
| 21973 | +/* |
| 21974 | +** Give a callback to the test harness that can be used to simulate faults |
| 21975 | +** in places where it is difficult or expensive to do so purely by means |
| 21976 | +** of inputs. |
| 21977 | +** |
| 21978 | +** The intent of the integer argument is to let the fault simulator know |
| 21979 | +** which of multiple sqlite3FaultSim() calls has been hit. |
| 21980 | +** |
| 21981 | +** Return whatever integer value the test callback returns, or return |
| 21982 | +** SQLITE_OK if no test callback is installed. |
| 21983 | +*/ |
| 21984 | +#ifndef SQLITE_OMIT_BUILTIN_TEST |
| 21985 | +SQLITE_PRIVATE int sqlite3FaultSim(int iTest){ |
| 21986 | + int (*xCallback)(int) = sqlite3GlobalConfig.xTestCallback; |
| 21987 | + return xCallback ? xCallback(iTest) : SQLITE_OK; |
| 21988 | +} |
| 21989 | +#endif |
| 21990 | + |
| 21794 | 21991 | #ifndef SQLITE_OMIT_FLOATING_POINT |
| 21795 | 21992 | /* |
| 21796 | 21993 | ** Return true if the floating point value is Not a Number (NaN). |
| 21797 | 21994 | ** |
| 21798 | 21995 | ** Use the math library isnan() function if compiled with SQLITE_HAVE_ISNAN. |
| | @@ -23004,12 +23201,12 @@ |
| 23004 | 23201 | return b+x[b-a]; |
| 23005 | 23202 | } |
| 23006 | 23203 | } |
| 23007 | 23204 | |
| 23008 | 23205 | /* |
| 23009 | | -** Convert an integer into a LogEst. In other words, compute a |
| 23010 | | -** good approximatation for 10*log2(x). |
| 23206 | +** Convert an integer into a LogEst. In other words, compute an |
| 23207 | +** approximation for 10*log2(x). |
| 23011 | 23208 | */ |
| 23012 | 23209 | SQLITE_PRIVATE LogEst sqlite3LogEst(u64 x){ |
| 23013 | 23210 | static LogEst a[] = { 0, 2, 3, 5, 6, 7, 8, 9 }; |
| 23014 | 23211 | LogEst y = 40; |
| 23015 | 23212 | if( x<8 ){ |
| | @@ -31226,15 +31423,10 @@ |
| 31226 | 31423 | ** |
| 31227 | 31424 | ** This file contains code that is specific to Windows. |
| 31228 | 31425 | */ |
| 31229 | 31426 | #if SQLITE_OS_WIN /* This file is used for Windows only */ |
| 31230 | 31427 | |
| 31231 | | -#ifdef __CYGWIN__ |
| 31232 | | -# include <sys/cygwin.h> |
| 31233 | | -# include <errno.h> /* amalgamator: keep */ |
| 31234 | | -#endif |
| 31235 | | - |
| 31236 | 31428 | /* |
| 31237 | 31429 | ** Include code that is common to all os_*.c files |
| 31238 | 31430 | */ |
| 31239 | 31431 | /************** Include os_common.h in the middle of os_win.c ****************/ |
| 31240 | 31432 | /************** Begin file os_common.h ***************************************/ |
| | @@ -31443,10 +31635,14 @@ |
| 31443 | 31635 | |
| 31444 | 31636 | #endif /* !defined(_OS_COMMON_H_) */ |
| 31445 | 31637 | |
| 31446 | 31638 | /************** End of os_common.h *******************************************/ |
| 31447 | 31639 | /************** Continuing where we left off in os_win.c *********************/ |
| 31640 | + |
| 31641 | +/* |
| 31642 | +** Include the header file for the Windows VFS. |
| 31643 | +*/ |
| 31448 | 31644 | |
| 31449 | 31645 | /* |
| 31450 | 31646 | ** Compiling and using WAL mode requires several APIs that are only |
| 31451 | 31647 | ** available in Windows platforms based on the NT kernel. |
| 31452 | 31648 | */ |
| | @@ -33255,10 +33451,36 @@ |
| 33255 | 33451 | # define SQLITE_WIN32_IOERR_RETRY_DELAY 25 |
| 33256 | 33452 | #endif |
| 33257 | 33453 | static int winIoerrRetry = SQLITE_WIN32_IOERR_RETRY; |
| 33258 | 33454 | static int winIoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY; |
| 33259 | 33455 | |
| 33456 | +/* |
| 33457 | +** The "winIoerrCanRetry1" macro is used to determine if a particular I/O |
| 33458 | +** error code obtained via GetLastError() is eligible to be retried. It |
| 33459 | +** must accept the error code DWORD as its only argument and should return |
| 33460 | +** non-zero if the error code is transient in nature and the operation |
| 33461 | +** responsible for generating the original error might succeed upon being |
| 33462 | +** retried. The argument to this macro should be a variable. |
| 33463 | +** |
| 33464 | +** Additionally, a macro named "winIoerrCanRetry2" may be defined. If it |
| 33465 | +** is defined, it will be consulted only when the macro "winIoerrCanRetry1" |
| 33466 | +** returns zero. The "winIoerrCanRetry2" macro is completely optional and |
| 33467 | +** may be used to include additional error codes in the set that should |
| 33468 | +** result in the failing I/O operation being retried by the caller. If |
| 33469 | +** defined, the "winIoerrCanRetry2" macro must exhibit external semantics |
| 33470 | +** identical to those of the "winIoerrCanRetry1" macro. |
| 33471 | +*/ |
| 33472 | +#if !defined(winIoerrCanRetry1) |
| 33473 | +#define winIoerrCanRetry1(a) (((a)==ERROR_ACCESS_DENIED) || \ |
| 33474 | + ((a)==ERROR_SHARING_VIOLATION) || \ |
| 33475 | + ((a)==ERROR_LOCK_VIOLATION) || \ |
| 33476 | + ((a)==ERROR_DEV_NOT_EXIST) || \ |
| 33477 | + ((a)==ERROR_NETNAME_DELETED) || \ |
| 33478 | + ((a)==ERROR_SEM_TIMEOUT) || \ |
| 33479 | + ((a)==ERROR_NETWORK_UNREACHABLE)) |
| 33480 | +#endif |
| 33481 | + |
| 33260 | 33482 | /* |
| 33261 | 33483 | ** If a ReadFile() or WriteFile() error occurs, invoke this routine |
| 33262 | 33484 | ** to see if it should be retried. Return TRUE to retry. Return FALSE |
| 33263 | 33485 | ** to give up with an error. |
| 33264 | 33486 | */ |
| | @@ -33268,17 +33490,22 @@ |
| 33268 | 33490 | if( pError ){ |
| 33269 | 33491 | *pError = e; |
| 33270 | 33492 | } |
| 33271 | 33493 | return 0; |
| 33272 | 33494 | } |
| 33273 | | - if( e==ERROR_ACCESS_DENIED || |
| 33274 | | - e==ERROR_LOCK_VIOLATION || |
| 33275 | | - e==ERROR_SHARING_VIOLATION ){ |
| 33495 | + if( winIoerrCanRetry1(e) ){ |
| 33496 | + sqlite3_win32_sleep(winIoerrRetryDelay*(1+*pnRetry)); |
| 33497 | + ++*pnRetry; |
| 33498 | + return 1; |
| 33499 | + } |
| 33500 | +#if defined(winIoerrCanRetry2) |
| 33501 | + else if( winIoerrCanRetry2(e) ){ |
| 33276 | 33502 | sqlite3_win32_sleep(winIoerrRetryDelay*(1+*pnRetry)); |
| 33277 | 33503 | ++*pnRetry; |
| 33278 | 33504 | return 1; |
| 33279 | 33505 | } |
| 33506 | +#endif |
| 33280 | 33507 | if( pError ){ |
| 33281 | 33508 | *pError = e; |
| 33282 | 33509 | } |
| 33283 | 33510 | return 0; |
| 33284 | 33511 | } |
| | @@ -34213,11 +34440,11 @@ |
| 34213 | 34440 | #endif |
| 34214 | 34441 | if( res == 0 ){ |
| 34215 | 34442 | pFile->lastErrno = osGetLastError(); |
| 34216 | 34443 | /* No need to log a failure to lock */ |
| 34217 | 34444 | } |
| 34218 | | - OSTRACE(("READ-LOCK file=%p, rc=%s\n", pFile->h, sqlite3ErrName(res))); |
| 34445 | + OSTRACE(("READ-LOCK file=%p, result=%d\n", pFile->h, res)); |
| 34219 | 34446 | return res; |
| 34220 | 34447 | } |
| 34221 | 34448 | |
| 34222 | 34449 | /* |
| 34223 | 34450 | ** Undo a readlock |
| | @@ -34237,11 +34464,11 @@ |
| 34237 | 34464 | if( res==0 && ((lastErrno = osGetLastError())!=ERROR_NOT_LOCKED) ){ |
| 34238 | 34465 | pFile->lastErrno = lastErrno; |
| 34239 | 34466 | winLogError(SQLITE_IOERR_UNLOCK, pFile->lastErrno, |
| 34240 | 34467 | "winUnlockReadLock", pFile->zPath); |
| 34241 | 34468 | } |
| 34242 | | - OSTRACE(("READ-UNLOCK file=%p, rc=%s\n", pFile->h, sqlite3ErrName(res))); |
| 34469 | + OSTRACE(("READ-UNLOCK file=%p, result=%d\n", pFile->h, res)); |
| 34243 | 34470 | return res; |
| 34244 | 34471 | } |
| 34245 | 34472 | |
| 34246 | 34473 | /* |
| 34247 | 34474 | ** Lock the file with the lock specified by parameter locktype - one |
| | @@ -34312,12 +34539,12 @@ |
| 34312 | 34539 | ** around problems caused by indexing and/or anti-virus software on |
| 34313 | 34540 | ** Windows systems. |
| 34314 | 34541 | ** If you are using this code as a model for alternative VFSes, do not |
| 34315 | 34542 | ** copy this retry logic. It is a hack intended for Windows only. |
| 34316 | 34543 | */ |
| 34317 | | - OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, rc=%s\n", |
| 34318 | | - pFile->h, cnt, sqlite3ErrName(res))); |
| 34544 | + OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, result=%d\n", |
| 34545 | + pFile->h, cnt, res)); |
| 34319 | 34546 | if( cnt ) sqlite3_win32_sleep(1); |
| 34320 | 34547 | } |
| 34321 | 34548 | gotPendingLock = res; |
| 34322 | 34549 | if( !res ){ |
| 34323 | 34550 | lastErrno = osGetLastError(); |
| | @@ -34398,29 +34625,29 @@ |
| 34398 | 34625 | ** This routine checks if there is a RESERVED lock held on the specified |
| 34399 | 34626 | ** file by this or any other process. If such a lock is held, return |
| 34400 | 34627 | ** non-zero, otherwise zero. |
| 34401 | 34628 | */ |
| 34402 | 34629 | static int winCheckReservedLock(sqlite3_file *id, int *pResOut){ |
| 34403 | | - int rc; |
| 34630 | + int res; |
| 34404 | 34631 | winFile *pFile = (winFile*)id; |
| 34405 | 34632 | |
| 34406 | 34633 | SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); |
| 34407 | 34634 | OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p\n", pFile->h, pResOut)); |
| 34408 | 34635 | |
| 34409 | 34636 | assert( id!=0 ); |
| 34410 | 34637 | if( pFile->locktype>=RESERVED_LOCK ){ |
| 34411 | | - rc = 1; |
| 34412 | | - OSTRACE(("TEST-WR-LOCK file=%p, rc=%d (local)\n", pFile->h, rc)); |
| 34638 | + res = 1; |
| 34639 | + OSTRACE(("TEST-WR-LOCK file=%p, result=%d (local)\n", pFile->h, res)); |
| 34413 | 34640 | }else{ |
| 34414 | | - rc = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE, 0, 1, 0); |
| 34415 | | - if( rc ){ |
| 34641 | + res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE, 0, 1, 0); |
| 34642 | + if( res ){ |
| 34416 | 34643 | winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0); |
| 34417 | 34644 | } |
| 34418 | | - rc = !rc; |
| 34419 | | - OSTRACE(("TEST-WR-LOCK file=%p, rc=%d (remote)\n", pFile->h, rc)); |
| 34645 | + res = !res; |
| 34646 | + OSTRACE(("TEST-WR-LOCK file=%p, result=%d (remote)\n", pFile->h, res)); |
| 34420 | 34647 | } |
| 34421 | | - *pResOut = rc; |
| 34648 | + *pResOut = res; |
| 34422 | 34649 | OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n", |
| 34423 | 34650 | pFile->h, pResOut, *pResOut)); |
| 34424 | 34651 | return SQLITE_OK; |
| 34425 | 34652 | } |
| 34426 | 34653 | |
| | @@ -40231,11 +40458,12 @@ |
| 40231 | 40458 | u8 noSync; /* Do not sync the journal if true */ |
| 40232 | 40459 | u8 fullSync; /* Do extra syncs of the journal for robustness */ |
| 40233 | 40460 | u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */ |
| 40234 | 40461 | u8 walSyncFlags; /* SYNC_NORMAL or SYNC_FULL for wal writes */ |
| 40235 | 40462 | u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */ |
| 40236 | | - u8 tempFile; /* zFilename is a temporary file */ |
| 40463 | + u8 tempFile; /* zFilename is a temporary or immutable file */ |
| 40464 | + u8 noLock; /* Do not lock (except in WAL mode) */ |
| 40237 | 40465 | u8 readOnly; /* True for a read-only database */ |
| 40238 | 40466 | u8 memDb; /* True to inhibit all file I/O */ |
| 40239 | 40467 | |
| 40240 | 40468 | /************************************************************************** |
| 40241 | 40469 | ** The following block contains those class members that change during |
| | @@ -40696,11 +40924,11 @@ |
| 40696 | 40924 | assert( !pPager->exclusiveMode || pPager->eLock==eLock ); |
| 40697 | 40925 | assert( eLock==NO_LOCK || eLock==SHARED_LOCK ); |
| 40698 | 40926 | assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 ); |
| 40699 | 40927 | if( isOpen(pPager->fd) ){ |
| 40700 | 40928 | assert( pPager->eLock>=eLock ); |
| 40701 | | - rc = sqlite3OsUnlock(pPager->fd, eLock); |
| 40929 | + rc = pPager->noLock ? SQLITE_OK : sqlite3OsUnlock(pPager->fd, eLock); |
| 40702 | 40930 | if( pPager->eLock!=UNKNOWN_LOCK ){ |
| 40703 | 40931 | pPager->eLock = (u8)eLock; |
| 40704 | 40932 | } |
| 40705 | 40933 | IOTRACE(("UNLOCK %p %d\n", pPager, eLock)) |
| 40706 | 40934 | } |
| | @@ -40720,11 +40948,11 @@ |
| 40720 | 40948 | static int pagerLockDb(Pager *pPager, int eLock){ |
| 40721 | 40949 | int rc = SQLITE_OK; |
| 40722 | 40950 | |
| 40723 | 40951 | assert( eLock==SHARED_LOCK || eLock==RESERVED_LOCK || eLock==EXCLUSIVE_LOCK ); |
| 40724 | 40952 | if( pPager->eLock<eLock || pPager->eLock==UNKNOWN_LOCK ){ |
| 40725 | | - rc = sqlite3OsLock(pPager->fd, eLock); |
| 40953 | + rc = pPager->noLock ? SQLITE_OK : sqlite3OsLock(pPager->fd, eLock); |
| 40726 | 40954 | if( rc==SQLITE_OK && (pPager->eLock!=UNKNOWN_LOCK||eLock==EXCLUSIVE_LOCK) ){ |
| 40727 | 40955 | pPager->eLock = (u8)eLock; |
| 40728 | 40956 | IOTRACE(("LOCK %p %d\n", pPager, eLock)) |
| 40729 | 40957 | } |
| 40730 | 40958 | } |
| | @@ -44279,47 +44507,59 @@ |
| 44279 | 44507 | ** |
| 44280 | 44508 | ** + SQLITE_DEFAULT_PAGE_SIZE, |
| 44281 | 44509 | ** + The value returned by sqlite3OsSectorSize() |
| 44282 | 44510 | ** + The largest page size that can be written atomically. |
| 44283 | 44511 | */ |
| 44284 | | - if( rc==SQLITE_OK && !readOnly ){ |
| 44285 | | - setSectorSize(pPager); |
| 44286 | | - assert(SQLITE_DEFAULT_PAGE_SIZE<=SQLITE_MAX_DEFAULT_PAGE_SIZE); |
| 44287 | | - if( szPageDflt<pPager->sectorSize ){ |
| 44288 | | - if( pPager->sectorSize>SQLITE_MAX_DEFAULT_PAGE_SIZE ){ |
| 44289 | | - szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE; |
| 44290 | | - }else{ |
| 44291 | | - szPageDflt = (u32)pPager->sectorSize; |
| 44292 | | - } |
| 44293 | | - } |
| 44512 | + if( rc==SQLITE_OK ){ |
| 44513 | + int iDc = sqlite3OsDeviceCharacteristics(pPager->fd); |
| 44514 | + if( !readOnly ){ |
| 44515 | + setSectorSize(pPager); |
| 44516 | + assert(SQLITE_DEFAULT_PAGE_SIZE<=SQLITE_MAX_DEFAULT_PAGE_SIZE); |
| 44517 | + if( szPageDflt<pPager->sectorSize ){ |
| 44518 | + if( pPager->sectorSize>SQLITE_MAX_DEFAULT_PAGE_SIZE ){ |
| 44519 | + szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE; |
| 44520 | + }else{ |
| 44521 | + szPageDflt = (u32)pPager->sectorSize; |
| 44522 | + } |
| 44523 | + } |
| 44294 | 44524 | #ifdef SQLITE_ENABLE_ATOMIC_WRITE |
| 44295 | | - { |
| 44296 | | - int iDc = sqlite3OsDeviceCharacteristics(pPager->fd); |
| 44297 | | - int ii; |
| 44298 | | - assert(SQLITE_IOCAP_ATOMIC512==(512>>8)); |
| 44299 | | - assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8)); |
| 44300 | | - assert(SQLITE_MAX_DEFAULT_PAGE_SIZE<=65536); |
| 44301 | | - for(ii=szPageDflt; ii<=SQLITE_MAX_DEFAULT_PAGE_SIZE; ii=ii*2){ |
| 44302 | | - if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ){ |
| 44303 | | - szPageDflt = ii; |
| 44525 | + { |
| 44526 | + int ii; |
| 44527 | + assert(SQLITE_IOCAP_ATOMIC512==(512>>8)); |
| 44528 | + assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8)); |
| 44529 | + assert(SQLITE_MAX_DEFAULT_PAGE_SIZE<=65536); |
| 44530 | + for(ii=szPageDflt; ii<=SQLITE_MAX_DEFAULT_PAGE_SIZE; ii=ii*2){ |
| 44531 | + if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ){ |
| 44532 | + szPageDflt = ii; |
| 44533 | + } |
| 44304 | 44534 | } |
| 44305 | 44535 | } |
| 44536 | +#endif |
| 44306 | 44537 | } |
| 44307 | | -#endif |
| 44538 | + pPager->noLock = sqlite3_uri_boolean(zFilename, "nolock", 0); |
| 44539 | + if( (iDc & SQLITE_IOCAP_IMMUTABLE)!=0 |
| 44540 | + || sqlite3_uri_boolean(zFilename, "immutable", 0) ){ |
| 44541 | + vfsFlags |= SQLITE_OPEN_READONLY; |
| 44542 | + goto act_like_temp_file; |
| 44543 | + } |
| 44308 | 44544 | } |
| 44309 | 44545 | }else{ |
| 44310 | 44546 | /* If a temporary file is requested, it is not opened immediately. |
| 44311 | 44547 | ** In this case we accept the default page size and delay actually |
| 44312 | 44548 | ** opening the file until the first call to OsWrite(). |
| 44313 | 44549 | ** |
| 44314 | 44550 | ** This branch is also run for an in-memory database. An in-memory |
| 44315 | 44551 | ** database is the same as a temp-file that is never written out to |
| 44316 | 44552 | ** disk and uses an in-memory rollback journal. |
| 44553 | + ** |
| 44554 | + ** This branch also runs for files marked as immutable. |
| 44317 | 44555 | */ |
| 44556 | +act_like_temp_file: |
| 44318 | 44557 | tempFile = 1; |
| 44319 | | - pPager->eState = PAGER_READER; |
| 44320 | | - pPager->eLock = EXCLUSIVE_LOCK; |
| 44558 | + pPager->eState = PAGER_READER; /* Pretend we already have a lock */ |
| 44559 | + pPager->eLock = EXCLUSIVE_LOCK; /* Pretend we are in EXCLUSIVE locking mode */ |
| 44560 | + pPager->noLock = 1; /* Do no locking */ |
| 44321 | 44561 | readOnly = (vfsFlags&SQLITE_OPEN_READONLY); |
| 44322 | 44562 | } |
| 44323 | 44563 | |
| 44324 | 44564 | /* The following call to PagerSetPagesize() serves to set the value of |
| 44325 | 44565 | ** Pager.pageSize and to allocate the Pager.pTmpSpace buffer. |
| | @@ -44356,13 +44596,10 @@ |
| 44356 | 44596 | /* pPager->stmtSize = 0; */ |
| 44357 | 44597 | /* pPager->stmtJSize = 0; */ |
| 44358 | 44598 | /* pPager->nPage = 0; */ |
| 44359 | 44599 | pPager->mxPgno = SQLITE_MAX_PAGE_COUNT; |
| 44360 | 44600 | /* pPager->state = PAGER_UNLOCK; */ |
| 44361 | | -#if 0 |
| 44362 | | - assert( pPager->state == (tempFile ? PAGER_EXCLUSIVE : PAGER_UNLOCK) ); |
| 44363 | | -#endif |
| 44364 | 44601 | /* pPager->errMask = 0; */ |
| 44365 | 44602 | pPager->tempFile = (u8)tempFile; |
| 44366 | 44603 | assert( tempFile==PAGER_LOCKINGMODE_NORMAL |
| 44367 | 44604 | || tempFile==PAGER_LOCKINGMODE_EXCLUSIVE ); |
| 44368 | 44605 | assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 ); |
| | @@ -55106,16 +55343,10 @@ |
| 55106 | 55343 | assert( pCur->eState==CURSOR_VALID ); |
| 55107 | 55344 | assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); |
| 55108 | 55345 | assert( cursorHoldsMutex(pCur) ); |
| 55109 | 55346 | assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell ); |
| 55110 | 55347 | assert( pCur->info.nSize>0 ); |
| 55111 | | -#if 0 |
| 55112 | | - if( pCur->info.nSize==0 ){ |
| 55113 | | - btreeParseCell(pCur->apPage[pCur->iPage], pCur->aiIdx[pCur->iPage], |
| 55114 | | - &pCur->info); |
| 55115 | | - } |
| 55116 | | -#endif |
| 55117 | 55348 | *pAmt = pCur->info.nLocal; |
| 55118 | 55349 | return (void*)(pCur->info.pCell + pCur->info.nHeader); |
| 55119 | 55350 | } |
| 55120 | 55351 | |
| 55121 | 55352 | |
| | @@ -59414,10 +59645,17 @@ |
| 59414 | 59645 | */ |
| 59415 | 59646 | SQLITE_PRIVATE void sqlite3BtreeCursorHints(BtCursor *pCsr, unsigned int mask){ |
| 59416 | 59647 | assert( mask==BTREE_BULKLOAD || mask==0 ); |
| 59417 | 59648 | pCsr->hints = mask; |
| 59418 | 59649 | } |
| 59650 | + |
| 59651 | +/* |
| 59652 | +** Return true if the given Btree is read-only. |
| 59653 | +*/ |
| 59654 | +SQLITE_PRIVATE int sqlite3BtreeIsReadonly(Btree *p){ |
| 59655 | + return (p->pBt->btsFlags & BTS_READ_ONLY)!=0; |
| 59656 | +} |
| 59419 | 59657 | |
| 59420 | 59658 | /************** End of btree.c ***********************************************/ |
| 59421 | 59659 | /************** Begin file backup.c ******************************************/ |
| 59422 | 59660 | /* |
| 59423 | 59661 | ** 2009 January 28 |
| | @@ -70686,11 +70924,11 @@ |
| 70686 | 70924 | ** |
| 70687 | 70925 | ** Reposition cursor P1 so that it points to the smallest entry that |
| 70688 | 70926 | ** is greater than or equal to the key value. If there are no records |
| 70689 | 70927 | ** greater than or equal to the key and P2 is not zero, then jump to P2. |
| 70690 | 70928 | ** |
| 70691 | | -** See also: Found, NotFound, Distinct, SeekLt, SeekGt, SeekLe |
| 70929 | +** See also: Found, NotFound, SeekLt, SeekGt, SeekLe |
| 70692 | 70930 | */ |
| 70693 | 70931 | /* Opcode: SeekGt P1 P2 P3 P4 * |
| 70694 | 70932 | ** Synopsis: key=r[P3@P4] |
| 70695 | 70933 | ** |
| 70696 | 70934 | ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), |
| | @@ -70700,11 +70938,11 @@ |
| 70700 | 70938 | ** |
| 70701 | 70939 | ** Reposition cursor P1 so that it points to the smallest entry that |
| 70702 | 70940 | ** is greater than the key value. If there are no records greater than |
| 70703 | 70941 | ** the key and P2 is not zero, then jump to P2. |
| 70704 | 70942 | ** |
| 70705 | | -** See also: Found, NotFound, Distinct, SeekLt, SeekGe, SeekLe |
| 70943 | +** See also: Found, NotFound, SeekLt, SeekGe, SeekLe |
| 70706 | 70944 | */ |
| 70707 | 70945 | /* Opcode: SeekLt P1 P2 P3 P4 * |
| 70708 | 70946 | ** Synopsis: key=r[P3@P4] |
| 70709 | 70947 | ** |
| 70710 | 70948 | ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), |
| | @@ -70714,11 +70952,11 @@ |
| 70714 | 70952 | ** |
| 70715 | 70953 | ** Reposition cursor P1 so that it points to the largest entry that |
| 70716 | 70954 | ** is less than the key value. If there are no records less than |
| 70717 | 70955 | ** the key and P2 is not zero, then jump to P2. |
| 70718 | 70956 | ** |
| 70719 | | -** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLe |
| 70957 | +** See also: Found, NotFound, SeekGt, SeekGe, SeekLe |
| 70720 | 70958 | */ |
| 70721 | 70959 | /* Opcode: SeekLe P1 P2 P3 P4 * |
| 70722 | 70960 | ** Synopsis: key=r[P3@P4] |
| 70723 | 70961 | ** |
| 70724 | 70962 | ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), |
| | @@ -70728,11 +70966,11 @@ |
| 70728 | 70966 | ** |
| 70729 | 70967 | ** Reposition cursor P1 so that it points to the largest entry that |
| 70730 | 70968 | ** is less than or equal to the key value. If there are no records |
| 70731 | 70969 | ** less than or equal to the key and P2 is not zero, then jump to P2. |
| 70732 | 70970 | ** |
| 70733 | | -** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLt |
| 70971 | +** See also: Found, NotFound, SeekGt, SeekGe, SeekLt |
| 70734 | 70972 | */ |
| 70735 | 70973 | case OP_SeekLT: /* jump, in3 */ |
| 70736 | 70974 | case OP_SeekLE: /* jump, in3 */ |
| 70737 | 70975 | case OP_SeekGE: /* jump, in3 */ |
| 70738 | 70976 | case OP_SeekGT: { /* jump, in3 */ |
| | @@ -71454,10 +71692,11 @@ |
| 71454 | 71692 | |
| 71455 | 71693 | pOut = &aMem[pOp->p2]; |
| 71456 | 71694 | pC = p->apCsr[pOp->p1]; |
| 71457 | 71695 | assert( isSorter(pC) ); |
| 71458 | 71696 | rc = sqlite3VdbeSorterRowkey(pC, pOut); |
| 71697 | + assert( rc!=SQLITE_OK || (pOut->flags & MEM_Blob) ); |
| 71459 | 71698 | break; |
| 71460 | 71699 | } |
| 71461 | 71700 | |
| 71462 | 71701 | /* Opcode: RowData P1 P2 * * * |
| 71463 | 71702 | ** Synopsis: r[P2]=data |
| | @@ -73502,11 +73741,11 @@ |
| 73502 | 73741 | #ifdef SQLITE_USE_FCNTL_TRACE |
| 73503 | 73742 | zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql); |
| 73504 | 73743 | if( zTrace ){ |
| 73505 | 73744 | int i; |
| 73506 | 73745 | for(i=0; i<db->nDb; i++){ |
| 73507 | | - if( MASKBIT(i) & p->btreeMask)==0 ) continue; |
| 73746 | + if( (MASKBIT(i) & p->btreeMask)==0 ) continue; |
| 73508 | 73747 | sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace); |
| 73509 | 73748 | } |
| 73510 | 73749 | } |
| 73511 | 73750 | #endif /* SQLITE_USE_FCNTL_TRACE */ |
| 73512 | 73751 | #ifdef SQLITE_DEBUG |
| | @@ -73545,12 +73784,12 @@ |
| 73545 | 73784 | *****************************************************************************/ |
| 73546 | 73785 | } |
| 73547 | 73786 | |
| 73548 | 73787 | #ifdef VDBE_PROFILE |
| 73549 | 73788 | { |
| 73550 | | - u64 elapsed = sqlite3Hwtime() - start; |
| 73551 | | - pOp->cycles += elapsed; |
| 73789 | + u64 endTime = sqlite3Hwtime(); |
| 73790 | + if( endTime>start ) pOp->cycles += endTime - start; |
| 73552 | 73791 | pOp->cnt++; |
| 73553 | 73792 | } |
| 73554 | 73793 | #endif |
| 73555 | 73794 | |
| 73556 | 73795 | /* The following code adds nothing to the actual functionality |
| | @@ -74457,11 +74696,10 @@ |
| 74457 | 74696 | nRead = (int)(pSorter->iWriteOff - iStart); |
| 74458 | 74697 | } |
| 74459 | 74698 | rc = sqlite3OsRead( |
| 74460 | 74699 | pSorter->pTemp1, &pIter->aBuffer[iBuf], nRead, iStart |
| 74461 | 74700 | ); |
| 74462 | | - assert( rc!=SQLITE_IOERR_SHORT_READ ); |
| 74463 | 74701 | } |
| 74464 | 74702 | |
| 74465 | 74703 | if( rc==SQLITE_OK ){ |
| 74466 | 74704 | u64 nByte; /* Size of PMA in bytes */ |
| 74467 | 74705 | pIter->iEof = pSorter->iWriteOff; |
| | @@ -83420,11 +83658,11 @@ |
| 83420 | 83658 | nCol = pIdx->nKeyCol; |
| 83421 | 83659 | aGotoChng = sqlite3DbMallocRaw(db, sizeof(int)*(nCol+1)); |
| 83422 | 83660 | if( aGotoChng==0 ) continue; |
| 83423 | 83661 | |
| 83424 | 83662 | /* Populate the register containing the index name. */ |
| 83425 | | - if( pIdx->autoIndex==2 && !HasRowid(pTab) ){ |
| 83663 | + if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ |
| 83426 | 83664 | zIdxName = pTab->zName; |
| 83427 | 83665 | }else{ |
| 83428 | 83666 | zIdxName = pIdx->zName; |
| 83429 | 83667 | } |
| 83430 | 83668 | sqlite3VdbeAddOp4(v, OP_String8, 0, regIdxname, 0, zIdxName, 0); |
| | @@ -83789,10 +84027,11 @@ |
| 83789 | 84027 | */ |
| 83790 | 84028 | static void decodeIntArray( |
| 83791 | 84029 | char *zIntArray, /* String containing int array to decode */ |
| 83792 | 84030 | int nOut, /* Number of slots in aOut[] */ |
| 83793 | 84031 | tRowcnt *aOut, /* Store integers here */ |
| 84032 | + LogEst *aLog, /* Or, if aOut==0, here */ |
| 83794 | 84033 | Index *pIndex /* Handle extra flags for this index, if not NULL */ |
| 83795 | 84034 | ){ |
| 83796 | 84035 | char *z = zIntArray; |
| 83797 | 84036 | int c; |
| 83798 | 84037 | int i; |
| | @@ -83807,11 +84046,21 @@ |
| 83807 | 84046 | v = 0; |
| 83808 | 84047 | while( (c=z[0])>='0' && c<='9' ){ |
| 83809 | 84048 | v = v*10 + c - '0'; |
| 83810 | 84049 | z++; |
| 83811 | 84050 | } |
| 83812 | | - aOut[i] = v; |
| 84051 | +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 84052 | + if( aOut ){ |
| 84053 | + aOut[i] = v; |
| 84054 | + }else |
| 84055 | +#else |
| 84056 | + assert( aOut==0 ); |
| 84057 | + UNUSED_PARAMETER(aOut); |
| 84058 | +#endif |
| 84059 | + { |
| 84060 | + aLog[i] = sqlite3LogEst(v); |
| 84061 | + } |
| 83813 | 84062 | if( *z==' ' ) z++; |
| 83814 | 84063 | } |
| 83815 | 84064 | #ifndef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 83816 | 84065 | assert( pIndex!=0 ); |
| 83817 | 84066 | #else |
| | @@ -83863,16 +84112,16 @@ |
| 83863 | 84112 | pIndex = sqlite3FindIndex(pInfo->db, argv[1], pInfo->zDatabase); |
| 83864 | 84113 | } |
| 83865 | 84114 | z = argv[2]; |
| 83866 | 84115 | |
| 83867 | 84116 | if( pIndex ){ |
| 83868 | | - decodeIntArray((char*)z, pIndex->nKeyCol+1, pIndex->aiRowEst, pIndex); |
| 83869 | | - if( pIndex->pPartIdxWhere==0 ) pTable->nRowEst = pIndex->aiRowEst[0]; |
| 84117 | + decodeIntArray((char*)z, pIndex->nKeyCol+1, 0, pIndex->aiRowLogEst, pIndex); |
| 84118 | + if( pIndex->pPartIdxWhere==0 ) pTable->nRowLogEst = pIndex->aiRowLogEst[0]; |
| 83870 | 84119 | }else{ |
| 83871 | 84120 | Index fakeIdx; |
| 83872 | 84121 | fakeIdx.szIdxRow = pTable->szTabRow; |
| 83873 | | - decodeIntArray((char*)z, 1, &pTable->nRowEst, &fakeIdx); |
| 84122 | + decodeIntArray((char*)z, 1, 0, &pTable->nRowLogEst, &fakeIdx); |
| 83874 | 84123 | pTable->szTabRow = fakeIdx.szIdxRow; |
| 83875 | 84124 | } |
| 83876 | 84125 | |
| 83877 | 84126 | return 0; |
| 83878 | 84127 | } |
| | @@ -84060,13 +84309,13 @@ |
| 84060 | 84309 | if( pIdx!=pPrevIdx ){ |
| 84061 | 84310 | initAvgEq(pPrevIdx); |
| 84062 | 84311 | pPrevIdx = pIdx; |
| 84063 | 84312 | } |
| 84064 | 84313 | pSample = &pIdx->aSample[pIdx->nSample]; |
| 84065 | | - decodeIntArray((char*)sqlite3_column_text(pStmt,1), nCol, pSample->anEq, 0); |
| 84066 | | - decodeIntArray((char*)sqlite3_column_text(pStmt,2), nCol, pSample->anLt, 0); |
| 84067 | | - decodeIntArray((char*)sqlite3_column_text(pStmt,3), nCol, pSample->anDLt,0); |
| 84314 | + decodeIntArray((char*)sqlite3_column_text(pStmt,1),nCol,pSample->anEq,0,0); |
| 84315 | + decodeIntArray((char*)sqlite3_column_text(pStmt,2),nCol,pSample->anLt,0,0); |
| 84316 | + decodeIntArray((char*)sqlite3_column_text(pStmt,3),nCol,pSample->anDLt,0,0); |
| 84068 | 84317 | |
| 84069 | 84318 | /* Take a copy of the sample. Add two 0x00 bytes the end of the buffer. |
| 84070 | 84319 | ** This is in case the sample record is corrupted. In that case, the |
| 84071 | 84320 | ** sqlite3VdbeRecordCompare() may read up to two varints past the |
| 84072 | 84321 | ** end of the allocated buffer before it realizes it is dealing with |
| | @@ -85776,11 +86025,11 @@ |
| 85776 | 86025 | /* |
| 85777 | 86026 | ** Return the PRIMARY KEY index of a table |
| 85778 | 86027 | */ |
| 85779 | 86028 | SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table *pTab){ |
| 85780 | 86029 | Index *p; |
| 85781 | | - for(p=pTab->pIndex; p && p->autoIndex!=2; p=p->pNext){} |
| 86030 | + for(p=pTab->pIndex; p && !IsPrimaryKeyIndex(p); p=p->pNext){} |
| 85782 | 86031 | return p; |
| 85783 | 86032 | } |
| 85784 | 86033 | |
| 85785 | 86034 | /* |
| 85786 | 86035 | ** Return the column of index pIdx that corresponds to table |
| | @@ -85924,11 +86173,11 @@ |
| 85924 | 86173 | } |
| 85925 | 86174 | pTable->zName = zName; |
| 85926 | 86175 | pTable->iPKey = -1; |
| 85927 | 86176 | pTable->pSchema = db->aDb[iDb].pSchema; |
| 85928 | 86177 | pTable->nRef = 1; |
| 85929 | | - pTable->nRowEst = 1048576; |
| 86178 | + pTable->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); |
| 85930 | 86179 | assert( pParse->pNewTable==0 ); |
| 85931 | 86180 | pParse->pNewTable = pTable; |
| 85932 | 86181 | |
| 85933 | 86182 | /* If this is the magic sqlite_sequence table used by autoincrement, |
| 85934 | 86183 | ** then record a pointer to this table in the main database structure |
| | @@ -86305,11 +86554,11 @@ |
| 86305 | 86554 | Index *p; |
| 86306 | 86555 | if( v ) pParse->addrSkipPK = sqlite3VdbeAddOp0(v, OP_Noop); |
| 86307 | 86556 | p = sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, |
| 86308 | 86557 | 0, sortOrder, 0); |
| 86309 | 86558 | if( p ){ |
| 86310 | | - p->autoIndex = 2; |
| 86559 | + p->idxType = SQLITE_IDXTYPE_PRIMARYKEY; |
| 86311 | 86560 | if( v ) sqlite3VdbeJumpHere(v, pParse->addrSkipPK); |
| 86312 | 86561 | } |
| 86313 | 86562 | pList = 0; |
| 86314 | 86563 | } |
| 86315 | 86564 | |
| | @@ -86325,11 +86574,14 @@ |
| 86325 | 86574 | Parse *pParse, /* Parsing context */ |
| 86326 | 86575 | Expr *pCheckExpr /* The check expression */ |
| 86327 | 86576 | ){ |
| 86328 | 86577 | #ifndef SQLITE_OMIT_CHECK |
| 86329 | 86578 | Table *pTab = pParse->pNewTable; |
| 86330 | | - if( pTab && !IN_DECLARE_VTAB ){ |
| 86579 | + sqlite3 *db = pParse->db; |
| 86580 | + if( pTab && !IN_DECLARE_VTAB |
| 86581 | + && !sqlite3BtreeIsReadonly(db->aDb[db->init.iDb].pBt) |
| 86582 | + ){ |
| 86331 | 86583 | pTab->pCheck = sqlite3ExprListAppend(pParse, pTab->pCheck, pCheckExpr); |
| 86332 | 86584 | if( pParse->constraintName.n ){ |
| 86333 | 86585 | sqlite3ExprListSetName(pParse, pTab->pCheck, &pParse->constraintName, 1); |
| 86334 | 86586 | } |
| 86335 | 86587 | }else |
| | @@ -86677,11 +86929,11 @@ |
| 86677 | 86929 | pTab->aCol[pTab->iPKey].zName); |
| 86678 | 86930 | pList->a[0].sortOrder = pParse->iPkSortOrder; |
| 86679 | 86931 | assert( pParse->pNewTable==pTab ); |
| 86680 | 86932 | pPk = sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0); |
| 86681 | 86933 | if( pPk==0 ) return; |
| 86682 | | - pPk->autoIndex = 2; |
| 86934 | + pPk->idxType = SQLITE_IDXTYPE_PRIMARYKEY; |
| 86683 | 86935 | pTab->iPKey = -1; |
| 86684 | 86936 | }else{ |
| 86685 | 86937 | pPk = sqlite3PrimaryKeyIndex(pTab); |
| 86686 | 86938 | } |
| 86687 | 86939 | pPk->isCovering = 1; |
| | @@ -86700,11 +86952,11 @@ |
| 86700 | 86952 | /* Update the in-memory representation of all UNIQUE indices by converting |
| 86701 | 86953 | ** the final rowid column into one or more columns of the PRIMARY KEY. |
| 86702 | 86954 | */ |
| 86703 | 86955 | for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
| 86704 | 86956 | int n; |
| 86705 | | - if( pIdx->autoIndex==2 ) continue; |
| 86957 | + if( IsPrimaryKeyIndex(pIdx) ) continue; |
| 86706 | 86958 | for(i=n=0; i<nPk; i++){ |
| 86707 | 86959 | if( !hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) ) n++; |
| 86708 | 86960 | } |
| 86709 | 86961 | if( n==0 ){ |
| 86710 | 86962 | /* This index is a superset of the primary key */ |
| | @@ -87749,19 +88001,19 @@ |
| 87749 | 88001 | Index *p; /* Allocated index object */ |
| 87750 | 88002 | int nByte; /* Bytes of space for Index object + arrays */ |
| 87751 | 88003 | |
| 87752 | 88004 | nByte = ROUND8(sizeof(Index)) + /* Index structure */ |
| 87753 | 88005 | ROUND8(sizeof(char*)*nCol) + /* Index.azColl */ |
| 87754 | | - ROUND8(sizeof(tRowcnt)*(nCol+1) + /* Index.aiRowEst */ |
| 88006 | + ROUND8(sizeof(LogEst)*(nCol+1) + /* Index.aiRowLogEst */ |
| 87755 | 88007 | sizeof(i16)*nCol + /* Index.aiColumn */ |
| 87756 | 88008 | sizeof(u8)*nCol); /* Index.aSortOrder */ |
| 87757 | 88009 | p = sqlite3DbMallocZero(db, nByte + nExtra); |
| 87758 | 88010 | if( p ){ |
| 87759 | 88011 | char *pExtra = ((char*)p)+ROUND8(sizeof(Index)); |
| 87760 | | - p->azColl = (char**)pExtra; pExtra += ROUND8(sizeof(char*)*nCol); |
| 87761 | | - p->aiRowEst = (tRowcnt*)pExtra; pExtra += sizeof(tRowcnt)*(nCol+1); |
| 87762 | | - p->aiColumn = (i16*)pExtra; pExtra += sizeof(i16)*nCol; |
| 88012 | + p->azColl = (char**)pExtra; pExtra += ROUND8(sizeof(char*)*nCol); |
| 88013 | + p->aiRowLogEst = (LogEst*)pExtra; pExtra += sizeof(LogEst)*(nCol+1); |
| 88014 | + p->aiColumn = (i16*)pExtra; pExtra += sizeof(i16)*nCol; |
| 87763 | 88015 | p->aSortOrder = (u8*)pExtra; |
| 87764 | 88016 | p->nColumn = nCol; |
| 87765 | 88017 | p->nKeyCol = nCol - 1; |
| 87766 | 88018 | *ppExtra = ((char*)p) + nByte; |
| 87767 | 88019 | } |
| | @@ -87780,11 +88032,11 @@ |
| 87780 | 88032 | ** is a primary key or unique-constraint on the most recent column added |
| 87781 | 88033 | ** to the table currently under construction. |
| 87782 | 88034 | ** |
| 87783 | 88035 | ** If the index is created successfully, return a pointer to the new Index |
| 87784 | 88036 | ** structure. This is used by sqlite3AddPrimaryKey() to mark the index |
| 87785 | | -** as the tables primary key (Index.autoIndex==2). |
| 88037 | +** as the tables primary key (Index.idxType==SQLITE_IDXTYPE_PRIMARYKEY) |
| 87786 | 88038 | */ |
| 87787 | 88039 | SQLITE_PRIVATE Index *sqlite3CreateIndex( |
| 87788 | 88040 | Parse *pParse, /* All information about this parse */ |
| 87789 | 88041 | Token *pName1, /* First part of index name. May be NULL */ |
| 87790 | 88042 | Token *pName2, /* Second part of index name. May be NULL */ |
| | @@ -87987,19 +88239,19 @@ |
| 87987 | 88239 | pIndex = sqlite3AllocateIndexObject(db, pList->nExpr + nExtraCol, |
| 87988 | 88240 | nName + nExtra + 1, &zExtra); |
| 87989 | 88241 | if( db->mallocFailed ){ |
| 87990 | 88242 | goto exit_create_index; |
| 87991 | 88243 | } |
| 87992 | | - assert( EIGHT_BYTE_ALIGNMENT(pIndex->aiRowEst) ); |
| 88244 | + assert( EIGHT_BYTE_ALIGNMENT(pIndex->aiRowLogEst) ); |
| 87993 | 88245 | assert( EIGHT_BYTE_ALIGNMENT(pIndex->azColl) ); |
| 87994 | 88246 | pIndex->zName = zExtra; |
| 87995 | 88247 | zExtra += nName + 1; |
| 87996 | 88248 | memcpy(pIndex->zName, zName, nName+1); |
| 87997 | 88249 | pIndex->pTable = pTab; |
| 87998 | 88250 | pIndex->onError = (u8)onError; |
| 87999 | 88251 | pIndex->uniqNotNull = onError!=OE_None; |
| 88000 | | - pIndex->autoIndex = (u8)(pName==0); |
| 88252 | + pIndex->idxType = pName ? SQLITE_IDXTYPE_APPDEF : SQLITE_IDXTYPE_UNIQUE; |
| 88001 | 88253 | pIndex->pSchema = db->aDb[iDb].pSchema; |
| 88002 | 88254 | pIndex->nKeyCol = pList->nExpr; |
| 88003 | 88255 | if( pPIWhere ){ |
| 88004 | 88256 | sqlite3ResolveSelfReference(pParse, pTab, NC_PartIdx, pPIWhere, 0); |
| 88005 | 88257 | pIndex->pPartIdxWhere = pPIWhere; |
| | @@ -88107,11 +88359,11 @@ |
| 88107 | 88359 | */ |
| 88108 | 88360 | Index *pIdx; |
| 88109 | 88361 | for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
| 88110 | 88362 | int k; |
| 88111 | 88363 | assert( pIdx->onError!=OE_None ); |
| 88112 | | - assert( pIdx->autoIndex ); |
| 88364 | + assert( pIdx->idxType!=SQLITE_IDXTYPE_APPDEF ); |
| 88113 | 88365 | assert( pIndex->onError!=OE_None ); |
| 88114 | 88366 | |
| 88115 | 88367 | if( pIdx->nKeyCol!=pIndex->nKeyCol ) continue; |
| 88116 | 88368 | for(k=0; k<pIdx->nKeyCol; k++){ |
| 88117 | 88369 | const char *z1; |
| | @@ -88268,11 +88520,11 @@ |
| 88268 | 88520 | ** |
| 88269 | 88521 | ** aiRowEst[0] is suppose to contain the number of elements in the index. |
| 88270 | 88522 | ** Since we do not know, guess 1 million. aiRowEst[1] is an estimate of the |
| 88271 | 88523 | ** number of rows in the table that match any particular value of the |
| 88272 | 88524 | ** first column of the index. aiRowEst[2] is an estimate of the number |
| 88273 | | -** of rows that match any particular combiniation of the first 2 columns |
| 88525 | +** of rows that match any particular combination of the first 2 columns |
| 88274 | 88526 | ** of the index. And so forth. It must always be the case that |
| 88275 | 88527 | * |
| 88276 | 88528 | ** aiRowEst[N]<=aiRowEst[N-1] |
| 88277 | 88529 | ** aiRowEst[N]>=1 |
| 88278 | 88530 | ** |
| | @@ -88279,24 +88531,31 @@ |
| 88279 | 88531 | ** Apart from that, we have little to go on besides intuition as to |
| 88280 | 88532 | ** how aiRowEst[] should be initialized. The numbers generated here |
| 88281 | 88533 | ** are based on typical values found in actual indices. |
| 88282 | 88534 | */ |
| 88283 | 88535 | SQLITE_PRIVATE void sqlite3DefaultRowEst(Index *pIdx){ |
| 88284 | | - tRowcnt *a = pIdx->aiRowEst; |
| 88536 | + /* 10, 9, 8, 7, 6 */ |
| 88537 | + LogEst aVal[] = { 33, 32, 30, 28, 26 }; |
| 88538 | + LogEst *a = pIdx->aiRowLogEst; |
| 88539 | + int nCopy = MIN(ArraySize(aVal), pIdx->nKeyCol); |
| 88285 | 88540 | int i; |
| 88286 | | - tRowcnt n; |
| 88287 | | - assert( a!=0 ); |
| 88288 | | - a[0] = pIdx->pTable->nRowEst; |
| 88289 | | - if( a[0]<10 ) a[0] = 10; |
| 88290 | | - n = 10; |
| 88291 | | - for(i=1; i<=pIdx->nKeyCol; i++){ |
| 88292 | | - a[i] = n; |
| 88293 | | - if( n>5 ) n--; |
| 88294 | | - } |
| 88295 | | - if( pIdx->onError!=OE_None ){ |
| 88296 | | - a[pIdx->nKeyCol] = 1; |
| 88297 | | - } |
| 88541 | + |
| 88542 | + /* Set the first entry (number of rows in the index) to the estimated |
| 88543 | + ** number of rows in the table. Or 10, if the estimated number of rows |
| 88544 | + ** in the table is less than that. */ |
| 88545 | + a[0] = pIdx->pTable->nRowLogEst; |
| 88546 | + if( a[0]<33 ) a[0] = 33; assert( 33==sqlite3LogEst(10) ); |
| 88547 | + |
| 88548 | + /* Estimate that a[1] is 10, a[2] is 9, a[3] is 8, a[4] is 7, a[5] is |
| 88549 | + ** 6 and each subsequent value (if any) is 5. */ |
| 88550 | + memcpy(&a[1], aVal, nCopy*sizeof(LogEst)); |
| 88551 | + for(i=nCopy+1; i<=pIdx->nKeyCol; i++){ |
| 88552 | + a[i] = 23; assert( 23==sqlite3LogEst(5) ); |
| 88553 | + } |
| 88554 | + |
| 88555 | + assert( 0==sqlite3LogEst(1) ); |
| 88556 | + if( pIdx->onError!=OE_None ) a[pIdx->nKeyCol] = 0; |
| 88298 | 88557 | } |
| 88299 | 88558 | |
| 88300 | 88559 | /* |
| 88301 | 88560 | ** This routine will drop an existing named index. This routine |
| 88302 | 88561 | ** implements the DROP INDEX statement. |
| | @@ -88323,11 +88582,11 @@ |
| 88323 | 88582 | sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase); |
| 88324 | 88583 | } |
| 88325 | 88584 | pParse->checkSchema = 1; |
| 88326 | 88585 | goto exit_drop_index; |
| 88327 | 88586 | } |
| 88328 | | - if( pIndex->autoIndex ){ |
| 88587 | + if( pIndex->idxType!=SQLITE_IDXTYPE_APPDEF ){ |
| 88329 | 88588 | sqlite3ErrorMsg(pParse, "index associated with UNIQUE " |
| 88330 | 88589 | "or PRIMARY KEY constraint cannot be dropped", 0); |
| 88331 | 88590 | goto exit_drop_index; |
| 88332 | 88591 | } |
| 88333 | 88592 | iDb = sqlite3SchemaToIndex(db, pIndex->pSchema); |
| | @@ -88982,11 +89241,12 @@ |
| 88982 | 89241 | sqlite3StrAccumAppend(&errMsg, ".", 1); |
| 88983 | 89242 | sqlite3StrAccumAppendAll(&errMsg, zCol); |
| 88984 | 89243 | } |
| 88985 | 89244 | zErr = sqlite3StrAccumFinish(&errMsg); |
| 88986 | 89245 | sqlite3HaltConstraint(pParse, |
| 88987 | | - (pIdx->autoIndex==2)?SQLITE_CONSTRAINT_PRIMARYKEY:SQLITE_CONSTRAINT_UNIQUE, |
| 89246 | + IsPrimaryKeyIndex(pIdx) ? SQLITE_CONSTRAINT_PRIMARYKEY |
| 89247 | + : SQLITE_CONSTRAINT_UNIQUE, |
| 88988 | 89248 | onError, zErr, P4_DYNAMIC, P5_ConstraintUnique); |
| 88989 | 89249 | } |
| 88990 | 89250 | |
| 88991 | 89251 | |
| 88992 | 89252 | /* |
| | @@ -92116,11 +92376,11 @@ |
| 92116 | 92376 | } |
| 92117 | 92377 | if( nSep ) sqlite3StrAccumAppend(pAccum, zSep, nSep); |
| 92118 | 92378 | } |
| 92119 | 92379 | zVal = (char*)sqlite3_value_text(argv[0]); |
| 92120 | 92380 | nVal = sqlite3_value_bytes(argv[0]); |
| 92121 | | - if( nVal ) sqlite3StrAccumAppend(pAccum, zVal, nVal); |
| 92381 | + if( zVal ) sqlite3StrAccumAppend(pAccum, zVal, nVal); |
| 92122 | 92382 | } |
| 92123 | 92383 | } |
| 92124 | 92384 | static void groupConcatFinalize(sqlite3_context *context){ |
| 92125 | 92385 | StrAccum *pAccum; |
| 92126 | 92386 | pAccum = sqlite3_aggregate_context(context, 0); |
| | @@ -92560,12 +92820,12 @@ |
| 92560 | 92820 | ** column of pFKey, then this index is a winner. */ |
| 92561 | 92821 | |
| 92562 | 92822 | if( zKey==0 ){ |
| 92563 | 92823 | /* If zKey is NULL, then this foreign key is implicitly mapped to |
| 92564 | 92824 | ** the PRIMARY KEY of table pParent. The PRIMARY KEY index may be |
| 92565 | | - ** identified by the test (Index.autoIndex==2). */ |
| 92566 | | - if( pIdx->autoIndex==2 ){ |
| 92825 | + ** identified by the test. */ |
| 92826 | + if( IsPrimaryKeyIndex(pIdx) ){ |
| 92567 | 92827 | if( aiCol ){ |
| 92568 | 92828 | int i; |
| 92569 | 92829 | for(i=0; i<nCol; i++) aiCol[i] = pFKey->aCol[i].iFrom; |
| 92570 | 92830 | } |
| 92571 | 92831 | break; |
| | @@ -94306,10 +94566,11 @@ |
| 94306 | 94566 | } |
| 94307 | 94567 | } |
| 94308 | 94568 | if( j>=pTab->nCol ){ |
| 94309 | 94569 | if( sqlite3IsRowid(pColumn->a[i].zName) && !withoutRowid ){ |
| 94310 | 94570 | ipkColumn = i; |
| 94571 | + bIdListInOrder = 0; |
| 94311 | 94572 | }else{ |
| 94312 | 94573 | sqlite3ErrorMsg(pParse, "table %S has no column named %s", |
| 94313 | 94574 | pTabList, 0, pColumn->a[i].zName); |
| 94314 | 94575 | pParse->checkSchema = 1; |
| 94315 | 94576 | goto insert_cleanup; |
| | @@ -95154,11 +95415,11 @@ |
| 95154 | 95415 | ** For a UNIQUE index, only conflict if the PRIMARY KEY values |
| 95155 | 95416 | ** of the matched index row are different from the original PRIMARY |
| 95156 | 95417 | ** KEY values of this row before the update. */ |
| 95157 | 95418 | int addrJump = sqlite3VdbeCurrentAddr(v)+pPk->nKeyCol; |
| 95158 | 95419 | int op = OP_Ne; |
| 95159 | | - int regCmp = (pIdx->autoIndex==2 ? regIdx : regR); |
| 95420 | + int regCmp = (IsPrimaryKeyIndex(pIdx) ? regIdx : regR); |
| 95160 | 95421 | |
| 95161 | 95422 | for(i=0; i<pPk->nKeyCol; i++){ |
| 95162 | 95423 | char *p4 = (char*)sqlite3LocateCollSeq(pParse, pPk->azColl[i]); |
| 95163 | 95424 | x = pPk->aiColumn[i]; |
| 95164 | 95425 | if( i==(pPk->nKeyCol-1) ){ |
| | @@ -95255,11 +95516,11 @@ |
| 95255 | 95516 | VdbeCoverage(v); |
| 95256 | 95517 | } |
| 95257 | 95518 | sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i]); |
| 95258 | 95519 | pik_flags = 0; |
| 95259 | 95520 | if( useSeekResult ) pik_flags = OPFLAG_USESEEKRESULT; |
| 95260 | | - if( pIdx->autoIndex==2 && !HasRowid(pTab) ){ |
| 95521 | + if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ |
| 95261 | 95522 | assert( pParse->nested==0 ); |
| 95262 | 95523 | pik_flags |= OPFLAG_NCHANGE; |
| 95263 | 95524 | } |
| 95264 | 95525 | if( pik_flags ) sqlite3VdbeChangeP5(v, pik_flags); |
| 95265 | 95526 | } |
| | @@ -95341,11 +95602,11 @@ |
| 95341 | 95602 | } |
| 95342 | 95603 | if( piIdxCur ) *piIdxCur = iBase; |
| 95343 | 95604 | for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ |
| 95344 | 95605 | int iIdxCur = iBase++; |
| 95345 | 95606 | assert( pIdx->pSchema==pTab->pSchema ); |
| 95346 | | - if( pIdx->autoIndex==2 && !HasRowid(pTab) && piDataCur ){ |
| 95607 | + if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) && piDataCur ){ |
| 95347 | 95608 | *piDataCur = iIdxCur; |
| 95348 | 95609 | } |
| 95349 | 95610 | if( aToOpen==0 || aToOpen[i+1] ){ |
| 95350 | 95611 | sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb); |
| 95351 | 95612 | sqlite3VdbeSetP4KeyInfo(pParse, pIdx); |
| | @@ -95557,18 +95818,27 @@ |
| 95557 | 95818 | } |
| 95558 | 95819 | if( pDest->iPKey!=pSrc->iPKey ){ |
| 95559 | 95820 | return 0; /* Both tables must have the same INTEGER PRIMARY KEY */ |
| 95560 | 95821 | } |
| 95561 | 95822 | for(i=0; i<pDest->nCol; i++){ |
| 95562 | | - if( pDest->aCol[i].affinity!=pSrc->aCol[i].affinity ){ |
| 95823 | + Column *pDestCol = &pDest->aCol[i]; |
| 95824 | + Column *pSrcCol = &pSrc->aCol[i]; |
| 95825 | + if( pDestCol->affinity!=pSrcCol->affinity ){ |
| 95563 | 95826 | return 0; /* Affinity must be the same on all columns */ |
| 95564 | 95827 | } |
| 95565 | | - if( !xferCompatibleCollation(pDest->aCol[i].zColl, pSrc->aCol[i].zColl) ){ |
| 95828 | + if( !xferCompatibleCollation(pDestCol->zColl, pSrcCol->zColl) ){ |
| 95566 | 95829 | return 0; /* Collating sequence must be the same on all columns */ |
| 95567 | 95830 | } |
| 95568 | | - if( pDest->aCol[i].notNull && !pSrc->aCol[i].notNull ){ |
| 95831 | + if( pDestCol->notNull && !pSrcCol->notNull ){ |
| 95569 | 95832 | return 0; /* tab2 must be NOT NULL if tab1 is */ |
| 95833 | + } |
| 95834 | + /* Default values for second and subsequent columns need to match. */ |
| 95835 | + if( i>0 |
| 95836 | + && ((pDestCol->zDflt==0)!=(pSrcCol->zDflt==0) |
| 95837 | + || (pDestCol->zDflt && strcmp(pDestCol->zDflt, pSrcCol->zDflt)!=0)) |
| 95838 | + ){ |
| 95839 | + return 0; /* Default values must be the same for all columns */ |
| 95570 | 95840 | } |
| 95571 | 95841 | } |
| 95572 | 95842 | for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ |
| 95573 | 95843 | if( pDestIdx->onError!=OE_None ){ |
| 95574 | 95844 | destHasUniqueIdx = 1; |
| | @@ -98583,17 +98853,19 @@ |
| 98583 | 98853 | Table *pTab = sqliteHashData(i); |
| 98584 | 98854 | sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, pTab->zName, 0); |
| 98585 | 98855 | sqlite3VdbeAddOp2(v, OP_Null, 0, 2); |
| 98586 | 98856 | sqlite3VdbeAddOp2(v, OP_Integer, |
| 98587 | 98857 | (int)sqlite3LogEstToInt(pTab->szTabRow), 3); |
| 98588 | | - sqlite3VdbeAddOp2(v, OP_Integer, (int)pTab->nRowEst, 4); |
| 98858 | + sqlite3VdbeAddOp2(v, OP_Integer, |
| 98859 | + (int)sqlite3LogEstToInt(pTab->nRowLogEst), 4); |
| 98589 | 98860 | sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); |
| 98590 | 98861 | for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
| 98591 | 98862 | sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0); |
| 98592 | 98863 | sqlite3VdbeAddOp2(v, OP_Integer, |
| 98593 | 98864 | (int)sqlite3LogEstToInt(pIdx->szIdxRow), 3); |
| 98594 | | - sqlite3VdbeAddOp2(v, OP_Integer, (int)pIdx->aiRowEst[0], 4); |
| 98865 | + sqlite3VdbeAddOp2(v, OP_Integer, |
| 98866 | + (int)sqlite3LogEstToInt(pIdx->aiRowLogEst[0]), 4); |
| 98595 | 98867 | sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); |
| 98596 | 98868 | } |
| 98597 | 98869 | } |
| 98598 | 98870 | } |
| 98599 | 98871 | break; |
| | @@ -100760,19 +101032,21 @@ |
| 100760 | 101032 | Select *pSelect, /* The whole SELECT statement */ |
| 100761 | 101033 | int regData /* Register holding data to be sorted */ |
| 100762 | 101034 | ){ |
| 100763 | 101035 | Vdbe *v = pParse->pVdbe; |
| 100764 | 101036 | int nExpr = pSort->pOrderBy->nExpr; |
| 100765 | | - int regBase = sqlite3GetTempRange(pParse, nExpr+2); |
| 100766 | | - int regRecord = sqlite3GetTempReg(pParse); |
| 101037 | + int regRecord = ++pParse->nMem; |
| 101038 | + int regBase = pParse->nMem+1; |
| 100767 | 101039 | int nOBSat = pSort->nOBSat; |
| 100768 | 101040 | int op; |
| 101041 | + |
| 101042 | + pParse->nMem += nExpr+2; /* nExpr+2 registers allocated at regBase */ |
| 100769 | 101043 | sqlite3ExprCacheClear(pParse); |
| 100770 | 101044 | sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, 0); |
| 100771 | 101045 | sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr); |
| 100772 | 101046 | sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1, 1); |
| 100773 | | - sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nExpr+2-nOBSat, regRecord); |
| 101047 | + sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nExpr+2-nOBSat,regRecord); |
| 100774 | 101048 | if( nOBSat>0 ){ |
| 100775 | 101049 | int regPrevKey; /* The first nOBSat columns of the previous row */ |
| 100776 | 101050 | int addrFirst; /* Address of the OP_IfNot opcode */ |
| 100777 | 101051 | int addrJmp; /* Address of the OP_Jump opcode */ |
| 100778 | 101052 | VdbeOp *pOp; /* Opcode that opens the sorter */ |
| | @@ -100805,14 +101079,10 @@ |
| 100805 | 101079 | op = OP_SorterInsert; |
| 100806 | 101080 | }else{ |
| 100807 | 101081 | op = OP_IdxInsert; |
| 100808 | 101082 | } |
| 100809 | 101083 | sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord); |
| 100810 | | - if( nOBSat==0 ){ |
| 100811 | | - sqlite3ReleaseTempReg(pParse, regRecord); |
| 100812 | | - sqlite3ReleaseTempRange(pParse, regBase, nExpr+2); |
| 100813 | | - } |
| 100814 | 101084 | if( pSelect->iLimit ){ |
| 100815 | 101085 | int addr1, addr2; |
| 100816 | 101086 | int iLimit; |
| 100817 | 101087 | if( pSelect->iOffset ){ |
| 100818 | 101088 | iLimit = pSelect->iOffset+1; |
| | @@ -101984,11 +102254,11 @@ |
| 101984 | 102254 | /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside |
| 101985 | 102255 | ** is disabled */ |
| 101986 | 102256 | assert( db->lookaside.bEnabled==0 ); |
| 101987 | 102257 | pTab->nRef = 1; |
| 101988 | 102258 | pTab->zName = 0; |
| 101989 | | - pTab->nRowEst = 1048576; |
| 102259 | + pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); |
| 101990 | 102260 | selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); |
| 101991 | 102261 | selectAddColumnTypeAndCollation(pParse, pTab, pSelect); |
| 101992 | 102262 | pTab->iPKey = -1; |
| 101993 | 102263 | if( db->mallocFailed ){ |
| 101994 | 102264 | sqlite3DeleteTable(db, pTab); |
| | @@ -104123,11 +104393,11 @@ |
| 104123 | 104393 | pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); |
| 104124 | 104394 | if( pTab==0 ) return WRC_Abort; |
| 104125 | 104395 | pTab->nRef = 1; |
| 104126 | 104396 | pTab->zName = sqlite3DbStrDup(db, pCte->zName); |
| 104127 | 104397 | pTab->iPKey = -1; |
| 104128 | | - pTab->nRowEst = 1048576; |
| 104398 | + pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); |
| 104129 | 104399 | pTab->tabFlags |= TF_Ephemeral; |
| 104130 | 104400 | pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0); |
| 104131 | 104401 | if( db->mallocFailed ) return SQLITE_NOMEM; |
| 104132 | 104402 | assert( pFrom->pSelect ); |
| 104133 | 104403 | |
| | @@ -104299,11 +104569,11 @@ |
| 104299 | 104569 | pTab->nRef = 1; |
| 104300 | 104570 | pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab); |
| 104301 | 104571 | while( pSel->pPrior ){ pSel = pSel->pPrior; } |
| 104302 | 104572 | selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol); |
| 104303 | 104573 | pTab->iPKey = -1; |
| 104304 | | - pTab->nRowEst = 1048576; |
| 104574 | + pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); |
| 104305 | 104575 | pTab->tabFlags |= TF_Ephemeral; |
| 104306 | 104576 | #endif |
| 104307 | 104577 | }else{ |
| 104308 | 104578 | /* An ordinary table or view name in the FROM clause */ |
| 104309 | 104579 | assert( pFrom->pTab==0 ); |
| | @@ -104794,14 +105064,15 @@ |
| 104794 | 105064 | Parse *pParse, /* Parse context */ |
| 104795 | 105065 | Table *pTab, /* Table being queried */ |
| 104796 | 105066 | Index *pIdx /* Index used to optimize scan, or NULL */ |
| 104797 | 105067 | ){ |
| 104798 | 105068 | if( pParse->explain==2 ){ |
| 105069 | + int bCover = (pIdx!=0 && (HasRowid(pTab) || !IsPrimaryKeyIndex(pIdx))); |
| 104799 | 105070 | char *zEqp = sqlite3MPrintf(pParse->db, "SCAN TABLE %s%s%s", |
| 104800 | | - pTab->zName, |
| 104801 | | - pIdx ? " USING COVERING INDEX " : "", |
| 104802 | | - pIdx ? pIdx->zName : "" |
| 105071 | + pTab->zName, |
| 105072 | + bCover ? " USING COVERING INDEX " : "", |
| 105073 | + bCover ? pIdx->zName : "" |
| 104803 | 105074 | ); |
| 104804 | 105075 | sqlite3VdbeAddOp4( |
| 104805 | 105076 | pParse->pVdbe, OP_Explain, pParse->iSelectId, 0, 0, zEqp, P4_DYNAMIC |
| 104806 | 105077 | ); |
| 104807 | 105078 | } |
| | @@ -104949,11 +105220,11 @@ |
| 104949 | 105220 | VdbeComment((v, "%s", pItem->pTab->zName)); |
| 104950 | 105221 | pItem->addrFillSub = addrTop; |
| 104951 | 105222 | sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn); |
| 104952 | 105223 | explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); |
| 104953 | 105224 | sqlite3Select(pParse, pSub, &dest); |
| 104954 | | - pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow; |
| 105225 | + pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow); |
| 104955 | 105226 | pItem->viaCoroutine = 1; |
| 104956 | 105227 | pItem->regResult = dest.iSdst; |
| 104957 | 105228 | sqlite3VdbeAddOp1(v, OP_EndCoroutine, pItem->regReturn); |
| 104958 | 105229 | sqlite3VdbeJumpHere(v, addrTop-1); |
| 104959 | 105230 | sqlite3ClearTempRegCache(pParse); |
| | @@ -104980,11 +105251,11 @@ |
| 104980 | 105251 | VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName)); |
| 104981 | 105252 | } |
| 104982 | 105253 | sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); |
| 104983 | 105254 | explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); |
| 104984 | 105255 | sqlite3Select(pParse, pSub, &dest); |
| 104985 | | - pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow; |
| 105256 | + pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow); |
| 104986 | 105257 | if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr); |
| 104987 | 105258 | retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn); |
| 104988 | 105259 | VdbeComment((v, "end %s", pItem->pTab->zName)); |
| 104989 | 105260 | sqlite3VdbeChangeP1(v, topAddr, retAddr); |
| 104990 | 105261 | sqlite3ClearTempRegCache(pParse); |
| | @@ -105013,22 +105284,10 @@ |
| 105013 | 105284 | explainSetInteger(pParse->iSelectId, iRestoreSelectId); |
| 105014 | 105285 | return rc; |
| 105015 | 105286 | } |
| 105016 | 105287 | #endif |
| 105017 | 105288 | |
| 105018 | | - /* If there is both a GROUP BY and an ORDER BY clause and they are |
| 105019 | | - ** identical, then disable the ORDER BY clause since the GROUP BY |
| 105020 | | - ** will cause elements to come out in the correct order. This is |
| 105021 | | - ** an optimization - the correct answer should result regardless. |
| 105022 | | - ** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER |
| 105023 | | - ** to disable this optimization for testing purposes. |
| 105024 | | - */ |
| 105025 | | - if( sqlite3ExprListCompare(p->pGroupBy, sSort.pOrderBy, -1)==0 |
| 105026 | | - && OptimizationEnabled(db, SQLITE_GroupByOrder) ){ |
| 105027 | | - sSort.pOrderBy = 0; |
| 105028 | | - } |
| 105029 | | - |
| 105030 | 105289 | /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and |
| 105031 | 105290 | ** if the select-list is the same as the ORDER BY list, then this query |
| 105032 | 105291 | ** can be rewritten as a GROUP BY. In other words, this: |
| 105033 | 105292 | ** |
| 105034 | 105293 | ** SELECT DISTINCT xyz FROM ... ORDER BY xyz |
| | @@ -105153,10 +105412,11 @@ |
| 105153 | 105412 | int iAbortFlag; /* Mem address which causes query abort if positive */ |
| 105154 | 105413 | int groupBySort; /* Rows come from source in GROUP BY order */ |
| 105155 | 105414 | int addrEnd; /* End of processing for this SELECT */ |
| 105156 | 105415 | int sortPTab = 0; /* Pseudotable used to decode sorting results */ |
| 105157 | 105416 | int sortOut = 0; /* Output register from the sorter */ |
| 105417 | + int orderByGrp = 0; /* True if the GROUP BY and ORDER BY are the same */ |
| 105158 | 105418 | |
| 105159 | 105419 | /* Remove any and all aliases between the result set and the |
| 105160 | 105420 | ** GROUP BY clause. |
| 105161 | 105421 | */ |
| 105162 | 105422 | if( pGroupBy ){ |
| | @@ -105172,10 +105432,22 @@ |
| 105172 | 105432 | if( p->nSelectRow>100 ) p->nSelectRow = 100; |
| 105173 | 105433 | }else{ |
| 105174 | 105434 | p->nSelectRow = 1; |
| 105175 | 105435 | } |
| 105176 | 105436 | |
| 105437 | + |
| 105438 | + /* If there is both a GROUP BY and an ORDER BY clause and they are |
| 105439 | + ** identical, then it may be possible to disable the ORDER BY clause |
| 105440 | + ** on the grounds that the GROUP BY will cause elements to come out |
| 105441 | + ** in the correct order. It also may not - the GROUP BY may use a |
| 105442 | + ** database index that causes rows to be grouped together as required |
| 105443 | + ** but not actually sorted. Either way, record the fact that the |
| 105444 | + ** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp |
| 105445 | + ** variable. */ |
| 105446 | + if( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){ |
| 105447 | + orderByGrp = 1; |
| 105448 | + } |
| 105177 | 105449 | |
| 105178 | 105450 | /* Create a label to jump to when we want to abort the query */ |
| 105179 | 105451 | addrEnd = sqlite3VdbeMakeLabel(v); |
| 105180 | 105452 | |
| 105181 | 105453 | /* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in |
| | @@ -105252,11 +105524,12 @@ |
| 105252 | 105524 | ** it might be a single loop that uses an index to extract information |
| 105253 | 105525 | ** in the right order to begin with. |
| 105254 | 105526 | */ |
| 105255 | 105527 | sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); |
| 105256 | 105528 | pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0, |
| 105257 | | - WHERE_GROUPBY, 0); |
| 105529 | + WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0), 0 |
| 105530 | + ); |
| 105258 | 105531 | if( pWInfo==0 ) goto select_end; |
| 105259 | 105532 | if( sqlite3WhereIsOrdered(pWInfo)==pGroupBy->nExpr ){ |
| 105260 | 105533 | /* The optimizer is able to deliver rows in group by order so |
| 105261 | 105534 | ** we do not have to sort. The OP_OpenEphemeral table will be |
| 105262 | 105535 | ** cancelled later because we still need to use the pKeyInfo |
| | @@ -105317,10 +105590,25 @@ |
| 105317 | 105590 | sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol); |
| 105318 | 105591 | sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd); |
| 105319 | 105592 | VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v); |
| 105320 | 105593 | sAggInfo.useSortingIdx = 1; |
| 105321 | 105594 | sqlite3ExprCacheClear(pParse); |
| 105595 | + |
| 105596 | + } |
| 105597 | + |
| 105598 | + /* If the index or temporary table used by the GROUP BY sort |
| 105599 | + ** will naturally deliver rows in the order required by the ORDER BY |
| 105600 | + ** clause, cancel the ephemeral table open coded earlier. |
| 105601 | + ** |
| 105602 | + ** This is an optimization - the correct answer should result regardless. |
| 105603 | + ** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER to |
| 105604 | + ** disable this optimization for testing purposes. */ |
| 105605 | + if( orderByGrp && OptimizationEnabled(db, SQLITE_GroupByOrder) |
| 105606 | + && (groupBySort || sqlite3WhereIsSorted(pWInfo)) |
| 105607 | + ){ |
| 105608 | + sSort.pOrderBy = 0; |
| 105609 | + sqlite3VdbeChangeToNoop(v, sSort.addrSortIndex); |
| 105322 | 105610 | } |
| 105323 | 105611 | |
| 105324 | 105612 | /* Evaluate the current GROUP BY terms and store in b0, b1, b2... |
| 105325 | 105613 | ** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth) |
| 105326 | 105614 | ** Then compare the current GROUP BY terms against the GROUP BY terms |
| | @@ -107204,11 +107492,11 @@ |
| 107204 | 107492 | */ |
| 107205 | 107493 | pTabList->a[0].iCursor = iBaseCur = iDataCur = pParse->nTab++; |
| 107206 | 107494 | iIdxCur = iDataCur+1; |
| 107207 | 107495 | pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); |
| 107208 | 107496 | for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ |
| 107209 | | - if( pIdx->autoIndex==2 && pPk!=0 ){ |
| 107497 | + if( IsPrimaryKeyIndex(pIdx) && pPk!=0 ){ |
| 107210 | 107498 | iDataCur = pParse->nTab; |
| 107211 | 107499 | pTabList->a[0].iCursor = iDataCur; |
| 107212 | 107500 | } |
| 107213 | 107501 | pParse->nTab++; |
| 107214 | 107502 | } |
| | @@ -109680,10 +109968,11 @@ |
| 109680 | 109968 | WhereLoop *pLoops; /* List of all WhereLoop objects */ |
| 109681 | 109969 | Bitmask revMask; /* Mask of ORDER BY terms that need reversing */ |
| 109682 | 109970 | LogEst nRowOut; /* Estimated number of output rows */ |
| 109683 | 109971 | u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */ |
| 109684 | 109972 | i8 nOBSat; /* Number of ORDER BY terms satisfied by indices */ |
| 109973 | + u8 sorted; /* True if really sorted (not just grouped) */ |
| 109685 | 109974 | u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */ |
| 109686 | 109975 | u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */ |
| 109687 | 109976 | u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */ |
| 109688 | 109977 | u8 nLevel; /* Number of nested loop */ |
| 109689 | 109978 | int iTop; /* The very beginning of the WHERE loop */ |
| | @@ -109739,10 +110028,11 @@ |
| 109739 | 110028 | #define WHERE_ONEROW 0x00001000 /* Selects no more than one row */ |
| 109740 | 110029 | #define WHERE_MULTI_OR 0x00002000 /* OR using multiple indices */ |
| 109741 | 110030 | #define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */ |
| 109742 | 110031 | #define WHERE_SKIPSCAN 0x00008000 /* Uses the skip-scan algorithm */ |
| 109743 | 110032 | #define WHERE_UNQ_WANTED 0x00010000 /* WHERE_ONEROW would have been helpful*/ |
| 110033 | +#define WHERE_LIKELIHOOD 0x00020000 /* A likelihood() is affecting nOut */ |
| 109744 | 110034 | |
| 109745 | 110035 | /************** End of whereInt.h ********************************************/ |
| 109746 | 110036 | /************** Continuing where we left off in where.c **********************/ |
| 109747 | 110037 | |
| 109748 | 110038 | /* |
| | @@ -109951,11 +110241,11 @@ |
| 109951 | 110241 | } |
| 109952 | 110242 | pTerm = &pWC->a[idx = pWC->nTerm++]; |
| 109953 | 110243 | if( p && ExprHasProperty(p, EP_Unlikely) ){ |
| 109954 | 110244 | pTerm->truthProb = sqlite3LogEst(p->iTable) - 99; |
| 109955 | 110245 | }else{ |
| 109956 | | - pTerm->truthProb = -1; |
| 110246 | + pTerm->truthProb = 1; |
| 109957 | 110247 | } |
| 109958 | 110248 | pTerm->pExpr = sqlite3ExprSkipCollate(p); |
| 109959 | 110249 | pTerm->wtFlags = wtFlags; |
| 109960 | 110250 | pTerm->pWC = pWC; |
| 109961 | 110251 | pTerm->iParent = -1; |
| | @@ -111680,11 +111970,12 @@ |
| 111680 | 111970 | tRowcnt iLower, iUpper, iGap; |
| 111681 | 111971 | if( i==0 ){ |
| 111682 | 111972 | iLower = 0; |
| 111683 | 111973 | iUpper = aSample[0].anLt[iCol]; |
| 111684 | 111974 | }else{ |
| 111685 | | - iUpper = i>=pIdx->nSample ? pIdx->aiRowEst[0] : aSample[i].anLt[iCol]; |
| 111975 | + i64 nRow0 = sqlite3LogEstToInt(pIdx->aiRowLogEst[0]); |
| 111976 | + iUpper = i>=pIdx->nSample ? nRow0 : aSample[i].anLt[iCol]; |
| 111686 | 111977 | iLower = aSample[i-1].anEq[iCol] + aSample[i-1].anLt[iCol]; |
| 111687 | 111978 | } |
| 111688 | 111979 | aStat[1] = (pIdx->nKeyCol>iCol ? pIdx->aAvgEq[iCol] : 1); |
| 111689 | 111980 | if( iLower>=iUpper ){ |
| 111690 | 111981 | iGap = 0; |
| | @@ -111698,10 +111989,33 @@ |
| 111698 | 111989 | } |
| 111699 | 111990 | aStat[0] = iLower + iGap; |
| 111700 | 111991 | } |
| 111701 | 111992 | } |
| 111702 | 111993 | #endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ |
| 111994 | + |
| 111995 | +/* |
| 111996 | +** If it is not NULL, pTerm is a term that provides an upper or lower |
| 111997 | +** bound on a range scan. Without considering pTerm, it is estimated |
| 111998 | +** that the scan will visit nNew rows. This function returns the number |
| 111999 | +** estimated to be visited after taking pTerm into account. |
| 112000 | +** |
| 112001 | +** If the user explicitly specified a likelihood() value for this term, |
| 112002 | +** then the return value is the likelihood multiplied by the number of |
| 112003 | +** input rows. Otherwise, this function assumes that an "IS NOT NULL" term |
| 112004 | +** has a likelihood of 0.50, and any other term a likelihood of 0.25. |
| 112005 | +*/ |
| 112006 | +static LogEst whereRangeAdjust(WhereTerm *pTerm, LogEst nNew){ |
| 112007 | + LogEst nRet = nNew; |
| 112008 | + if( pTerm ){ |
| 112009 | + if( pTerm->truthProb<=0 ){ |
| 112010 | + nRet += pTerm->truthProb; |
| 112011 | + }else if( (pTerm->wtFlags & TERM_VNULL)==0 ){ |
| 112012 | + nRet -= 20; assert( 20==sqlite3LogEst(4) ); |
| 112013 | + } |
| 112014 | + } |
| 112015 | + return nRet; |
| 112016 | +} |
| 111703 | 112017 | |
| 111704 | 112018 | /* |
| 111705 | 112019 | ** This function is used to estimate the number of rows that will be visited |
| 111706 | 112020 | ** by scanning an index for a range of values. The range may have an upper |
| 111707 | 112021 | ** bound, a lower bound, or both. The WHERE clause terms that set the upper |
| | @@ -111791,11 +112105,11 @@ |
| 111791 | 112105 | aff = p->pTable->aCol[p->aiColumn[nEq]].affinity; |
| 111792 | 112106 | } |
| 111793 | 112107 | /* Determine iLower and iUpper using ($P) only. */ |
| 111794 | 112108 | if( nEq==0 ){ |
| 111795 | 112109 | iLower = 0; |
| 111796 | | - iUpper = p->aiRowEst[0]; |
| 112110 | + iUpper = sqlite3LogEstToInt(p->aiRowLogEst[0]); |
| 111797 | 112111 | }else{ |
| 111798 | 112112 | /* Note: this call could be optimized away - since the same values must |
| 111799 | 112113 | ** have been requested when testing key $P in whereEqualScanEst(). */ |
| 111800 | 112114 | whereKeyStats(pParse, p, pRec, 0, a); |
| 111801 | 112115 | iLower = a[0]; |
| | @@ -111851,21 +112165,22 @@ |
| 111851 | 112165 | #else |
| 111852 | 112166 | UNUSED_PARAMETER(pParse); |
| 111853 | 112167 | UNUSED_PARAMETER(pBuilder); |
| 111854 | 112168 | #endif |
| 111855 | 112169 | assert( pLower || pUpper ); |
| 111856 | | - /* TUNING: Each inequality constraint reduces the search space 4-fold. |
| 111857 | | - ** A BETWEEN operator, therefore, reduces the search space 16-fold */ |
| 111858 | | - nNew = nOut; |
| 111859 | | - if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ){ |
| 111860 | | - nNew -= 20; assert( 20==sqlite3LogEst(4) ); |
| 111861 | | - nOut--; |
| 111862 | | - } |
| 111863 | | - if( pUpper ){ |
| 111864 | | - nNew -= 20; assert( 20==sqlite3LogEst(4) ); |
| 111865 | | - nOut--; |
| 111866 | | - } |
| 112170 | + assert( pUpper==0 || (pUpper->wtFlags & TERM_VNULL)==0 ); |
| 112171 | + nNew = whereRangeAdjust(pLower, nOut); |
| 112172 | + nNew = whereRangeAdjust(pUpper, nNew); |
| 112173 | + |
| 112174 | + /* TUNING: If there is both an upper and lower limit, assume the range is |
| 112175 | + ** reduced by an additional 75%. This means that, by default, an open-ended |
| 112176 | + ** range query (e.g. col > ?) is assumed to match 1/4 of the rows in the |
| 112177 | + ** index. While a closed range (e.g. col BETWEEN ? AND ?) is estimated to |
| 112178 | + ** match 1/64 of the index. */ |
| 112179 | + if( pLower && pUpper ) nNew -= 20; |
| 112180 | + |
| 112181 | + nOut -= (pLower!=0) + (pUpper!=0); |
| 111867 | 112182 | if( nNew<10 ) nNew = 10; |
| 111868 | 112183 | if( nNew<nOut ) nOut = nNew; |
| 111869 | 112184 | pLoop->nOut = (LogEst)nOut; |
| 111870 | 112185 | return rc; |
| 111871 | 112186 | } |
| | @@ -111958,26 +112273,27 @@ |
| 111958 | 112273 | WhereLoopBuilder *pBuilder, |
| 111959 | 112274 | ExprList *pList, /* The value list on the RHS of "x IN (v1,v2,v3,...)" */ |
| 111960 | 112275 | tRowcnt *pnRow /* Write the revised row estimate here */ |
| 111961 | 112276 | ){ |
| 111962 | 112277 | Index *p = pBuilder->pNew->u.btree.pIndex; |
| 112278 | + i64 nRow0 = sqlite3LogEstToInt(p->aiRowLogEst[0]); |
| 111963 | 112279 | int nRecValid = pBuilder->nRecValid; |
| 111964 | 112280 | int rc = SQLITE_OK; /* Subfunction return code */ |
| 111965 | 112281 | tRowcnt nEst; /* Number of rows for a single term */ |
| 111966 | 112282 | tRowcnt nRowEst = 0; /* New estimate of the number of rows */ |
| 111967 | 112283 | int i; /* Loop counter */ |
| 111968 | 112284 | |
| 111969 | 112285 | assert( p->aSample!=0 ); |
| 111970 | 112286 | for(i=0; rc==SQLITE_OK && i<pList->nExpr; i++){ |
| 111971 | | - nEst = p->aiRowEst[0]; |
| 112287 | + nEst = nRow0; |
| 111972 | 112288 | rc = whereEqualScanEst(pParse, pBuilder, pList->a[i].pExpr, &nEst); |
| 111973 | 112289 | nRowEst += nEst; |
| 111974 | 112290 | pBuilder->nRecValid = nRecValid; |
| 111975 | 112291 | } |
| 111976 | 112292 | |
| 111977 | 112293 | if( rc==SQLITE_OK ){ |
| 111978 | | - if( nRowEst > p->aiRowEst[0] ) nRowEst = p->aiRowEst[0]; |
| 112294 | + if( nRowEst > nRow0 ) nRowEst = nRow0; |
| 111979 | 112295 | *pnRow = nRowEst; |
| 111980 | 112296 | WHERETRACE(0x10,("IN row estimate: est=%g\n", nRowEst)); |
| 111981 | 112297 | } |
| 111982 | 112298 | assert( pBuilder->nRecValid==nRecValid ); |
| 111983 | 112299 | return rc; |
| | @@ -112416,17 +112732,24 @@ |
| 112416 | 112732 | zMsg = sqlite3MAppendf(db, zMsg, "%s AS %s", zMsg, pItem->zAlias); |
| 112417 | 112733 | } |
| 112418 | 112734 | if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 |
| 112419 | 112735 | && ALWAYS(pLoop->u.btree.pIndex!=0) |
| 112420 | 112736 | ){ |
| 112737 | + const char *zFmt; |
| 112738 | + Index *pIdx = pLoop->u.btree.pIndex; |
| 112421 | 112739 | char *zWhere = explainIndexRange(db, pLoop, pItem->pTab); |
| 112422 | | - zMsg = sqlite3MAppendf(db, zMsg, |
| 112423 | | - ((flags & WHERE_AUTO_INDEX) ? |
| 112424 | | - "%s USING AUTOMATIC %sINDEX%.0s%s" : |
| 112425 | | - "%s USING %sINDEX %s%s"), |
| 112426 | | - zMsg, ((flags & WHERE_IDX_ONLY) ? "COVERING " : ""), |
| 112427 | | - pLoop->u.btree.pIndex->zName, zWhere); |
| 112740 | + assert( !(flags&WHERE_AUTO_INDEX) || (flags&WHERE_IDX_ONLY) ); |
| 112741 | + if( !HasRowid(pItem->pTab) && IsPrimaryKeyIndex(pIdx) ){ |
| 112742 | + zFmt = zWhere ? "%s USING PRIMARY KEY%.0s%s" : "%s%.0s%s"; |
| 112743 | + }else if( flags & WHERE_AUTO_INDEX ){ |
| 112744 | + zFmt = "%s USING AUTOMATIC COVERING INDEX%.0s%s"; |
| 112745 | + }else if( flags & WHERE_IDX_ONLY ){ |
| 112746 | + zFmt = "%s USING COVERING INDEX %s%s"; |
| 112747 | + }else{ |
| 112748 | + zFmt = "%s USING INDEX %s%s"; |
| 112749 | + } |
| 112750 | + zMsg = sqlite3MAppendf(db, zMsg, zFmt, zMsg, pIdx->zName, zWhere); |
| 112428 | 112751 | sqlite3DbFree(db, zWhere); |
| 112429 | 112752 | }else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){ |
| 112430 | 112753 | zMsg = sqlite3MAppendf(db, zMsg, "%s USING INTEGER PRIMARY KEY", zMsg); |
| 112431 | 112754 | |
| 112432 | 112755 | if( flags&(WHERE_COLUMN_EQ|WHERE_COLUMN_IN) ){ |
| | @@ -112914,11 +113237,11 @@ |
| 112914 | 113237 | }else if( HasRowid(pIdx->pTable) ){ |
| 112915 | 113238 | iRowidReg = ++pParse->nMem; |
| 112916 | 113239 | sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg); |
| 112917 | 113240 | sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); |
| 112918 | 113241 | sqlite3VdbeAddOp2(v, OP_Seek, iCur, iRowidReg); /* Deferred seek */ |
| 112919 | | - }else{ |
| 113242 | + }else if( iCur!=iIdxCur ){ |
| 112920 | 113243 | Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable); |
| 112921 | 113244 | iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol); |
| 112922 | 113245 | for(j=0; j<pPk->nKeyCol; j++){ |
| 112923 | 113246 | k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]); |
| 112924 | 113247 | sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, iRowidReg+j); |
| | @@ -112984,10 +113307,14 @@ |
| 112984 | 113307 | ** |
| 112985 | 113308 | ** Return 2 # Jump back to the Gosub |
| 112986 | 113309 | ** |
| 112987 | 113310 | ** B: <after the loop> |
| 112988 | 113311 | ** |
| 113312 | + ** Added 2014-05-26: If the table is a WITHOUT ROWID table, then |
| 113313 | + ** use an ephermeral index instead of a RowSet to record the primary |
| 113314 | + ** keys of the rows we have already seen. |
| 113315 | + ** |
| 112989 | 113316 | */ |
| 112990 | 113317 | WhereClause *pOrWc; /* The OR-clause broken out into subterms */ |
| 112991 | 113318 | SrcList *pOrTab; /* Shortened table list or OR-clause generation */ |
| 112992 | 113319 | Index *pCov = 0; /* Potential covering index (or NULL) */ |
| 112993 | 113320 | int iCovCur = pParse->nTab++; /* Cursor used for index scans (if any) */ |
| | @@ -112998,10 +113325,11 @@ |
| 112998 | 113325 | int iLoopBody = sqlite3VdbeMakeLabel(v); /* Start of loop body */ |
| 112999 | 113326 | int iRetInit; /* Address of regReturn init */ |
| 113000 | 113327 | int untestedTerms = 0; /* Some terms not completely tested */ |
| 113001 | 113328 | int ii; /* Loop counter */ |
| 113002 | 113329 | Expr *pAndExpr = 0; /* An ".. AND (...)" expression */ |
| 113330 | + Table *pTab = pTabItem->pTab; |
| 113003 | 113331 | |
| 113004 | 113332 | pTerm = pLoop->aLTerm[0]; |
| 113005 | 113333 | assert( pTerm!=0 ); |
| 113006 | 113334 | assert( pTerm->eOperator & WO_OR ); |
| 113007 | 113335 | assert( (pTerm->wtFlags & TERM_ORINFO)!=0 ); |
| | @@ -113030,11 +113358,12 @@ |
| 113030 | 113358 | }else{ |
| 113031 | 113359 | pOrTab = pWInfo->pTabList; |
| 113032 | 113360 | } |
| 113033 | 113361 | |
| 113034 | 113362 | /* Initialize the rowset register to contain NULL. An SQL NULL is |
| 113035 | | - ** equivalent to an empty rowset. |
| 113363 | + ** equivalent to an empty rowset. Or, create an ephermeral index |
| 113364 | + ** capable of holding primary keys in the case of a WITHOUT ROWID. |
| 113036 | 113365 | ** |
| 113037 | 113366 | ** Also initialize regReturn to contain the address of the instruction |
| 113038 | 113367 | ** immediately following the OP_Return at the bottom of the loop. This |
| 113039 | 113368 | ** is required in a few obscure LEFT JOIN cases where control jumps |
| 113040 | 113369 | ** over the top of the loop into the body of it. In this case the |
| | @@ -113041,13 +113370,20 @@ |
| 113041 | 113370 | ** correct response for the end-of-loop code (the OP_Return) is to |
| 113042 | 113371 | ** fall through to the next instruction, just as an OP_Next does if |
| 113043 | 113372 | ** called on an uninitialized cursor. |
| 113044 | 113373 | */ |
| 113045 | 113374 | if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){ |
| 113046 | | - regRowset = ++pParse->nMem; |
| 113375 | + if( HasRowid(pTab) ){ |
| 113376 | + regRowset = ++pParse->nMem; |
| 113377 | + sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset); |
| 113378 | + }else{ |
| 113379 | + Index *pPk = sqlite3PrimaryKeyIndex(pTab); |
| 113380 | + regRowset = pParse->nTab++; |
| 113381 | + sqlite3VdbeAddOp2(v, OP_OpenEphemeral, regRowset, pPk->nKeyCol); |
| 113382 | + sqlite3VdbeSetP4KeyInfo(pParse, pPk); |
| 113383 | + } |
| 113047 | 113384 | regRowid = ++pParse->nMem; |
| 113048 | | - sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset); |
| 113049 | 113385 | } |
| 113050 | 113386 | iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn); |
| 113051 | 113387 | |
| 113052 | 113388 | /* If the original WHERE clause is z of the form: (x1 OR x2 OR ...) AND y |
| 113053 | 113389 | ** Then for every term xN, evaluate as the subexpression: xN AND z |
| | @@ -113079,15 +113415,20 @@ |
| 113079 | 113415 | if( pAndExpr ){ |
| 113080 | 113416 | pAndExpr = sqlite3PExpr(pParse, TK_AND, 0, pAndExpr, 0); |
| 113081 | 113417 | } |
| 113082 | 113418 | } |
| 113083 | 113419 | |
| 113420 | + /* Run a separate WHERE clause for each term of the OR clause. After |
| 113421 | + ** eliminating duplicates from other WHERE clauses, the action for each |
| 113422 | + ** sub-WHERE clause is to to invoke the main loop body as a subroutine. |
| 113423 | + */ |
| 113084 | 113424 | for(ii=0; ii<pOrWc->nTerm; ii++){ |
| 113085 | 113425 | WhereTerm *pOrTerm = &pOrWc->a[ii]; |
| 113086 | 113426 | if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){ |
| 113087 | | - WhereInfo *pSubWInfo; /* Info for single OR-term scan */ |
| 113088 | | - Expr *pOrExpr = pOrTerm->pExpr; |
| 113427 | + WhereInfo *pSubWInfo; /* Info for single OR-term scan */ |
| 113428 | + Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */ |
| 113429 | + int j1 = 0; /* Address of jump operation */ |
| 113089 | 113430 | if( pAndExpr && !ExprHasProperty(pOrExpr, EP_FromJoin) ){ |
| 113090 | 113431 | pAndExpr->pLeft = pOrExpr; |
| 113091 | 113432 | pOrExpr = pAndExpr; |
| 113092 | 113433 | } |
| 113093 | 113434 | /* Loop through table entries that match term pOrTerm. */ |
| | @@ -113098,20 +113439,66 @@ |
| 113098 | 113439 | if( pSubWInfo ){ |
| 113099 | 113440 | WhereLoop *pSubLoop; |
| 113100 | 113441 | explainOneScan( |
| 113101 | 113442 | pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0 |
| 113102 | 113443 | ); |
| 113444 | + /* This is the sub-WHERE clause body. First skip over |
| 113445 | + ** duplicate rows from prior sub-WHERE clauses, and record the |
| 113446 | + ** rowid (or PRIMARY KEY) for the current row so that the same |
| 113447 | + ** row will be skipped in subsequent sub-WHERE clauses. |
| 113448 | + */ |
| 113103 | 113449 | if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){ |
| 113104 | | - int iSet = ((ii==pOrWc->nTerm-1)?-1:ii); |
| 113105 | 113450 | int r; |
| 113106 | | - r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur, |
| 113107 | | - regRowid, 0); |
| 113108 | | - sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, |
| 113109 | | - sqlite3VdbeCurrentAddr(v)+2, r, iSet); |
| 113110 | | - VdbeCoverage(v); |
| 113451 | + int iSet = ((ii==pOrWc->nTerm-1)?-1:ii); |
| 113452 | + if( HasRowid(pTab) ){ |
| 113453 | + r = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, regRowid, 0); |
| 113454 | + j1 = sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, 0, r,iSet); |
| 113455 | + VdbeCoverage(v); |
| 113456 | + }else{ |
| 113457 | + Index *pPk = sqlite3PrimaryKeyIndex(pTab); |
| 113458 | + int nPk = pPk->nKeyCol; |
| 113459 | + int iPk; |
| 113460 | + |
| 113461 | + /* Read the PK into an array of temp registers. */ |
| 113462 | + r = sqlite3GetTempRange(pParse, nPk); |
| 113463 | + for(iPk=0; iPk<nPk; iPk++){ |
| 113464 | + int iCol = pPk->aiColumn[iPk]; |
| 113465 | + sqlite3ExprCodeGetColumn(pParse, pTab, iCol, iCur, r+iPk, 0); |
| 113466 | + } |
| 113467 | + |
| 113468 | + /* Check if the temp table already contains this key. If so, |
| 113469 | + ** the row has already been included in the result set and |
| 113470 | + ** can be ignored (by jumping past the Gosub below). Otherwise, |
| 113471 | + ** insert the key into the temp table and proceed with processing |
| 113472 | + ** the row. |
| 113473 | + ** |
| 113474 | + ** Use some of the same optimizations as OP_RowSetTest: If iSet |
| 113475 | + ** is zero, assume that the key cannot already be present in |
| 113476 | + ** the temp table. And if iSet is -1, assume that there is no |
| 113477 | + ** need to insert the key into the temp table, as it will never |
| 113478 | + ** be tested for. */ |
| 113479 | + if( iSet ){ |
| 113480 | + j1 = sqlite3VdbeAddOp4Int(v, OP_Found, regRowset, 0, r, nPk); |
| 113481 | + VdbeCoverage(v); |
| 113482 | + } |
| 113483 | + if( iSet>=0 ){ |
| 113484 | + sqlite3VdbeAddOp3(v, OP_MakeRecord, r, nPk, regRowid); |
| 113485 | + sqlite3VdbeAddOp3(v, OP_IdxInsert, regRowset, regRowid, 0); |
| 113486 | + if( iSet ) sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); |
| 113487 | + } |
| 113488 | + |
| 113489 | + /* Release the array of temp registers */ |
| 113490 | + sqlite3ReleaseTempRange(pParse, r, nPk); |
| 113491 | + } |
| 113111 | 113492 | } |
| 113493 | + |
| 113494 | + /* Invoke the main loop body as a subroutine */ |
| 113112 | 113495 | sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody); |
| 113496 | + |
| 113497 | + /* Jump here (skipping the main loop body subroutine) if the |
| 113498 | + ** current sub-WHERE row is a duplicate from prior sub-WHEREs. */ |
| 113499 | + if( j1 ) sqlite3VdbeJumpHere(v, j1); |
| 113113 | 113500 | |
| 113114 | 113501 | /* The pSubWInfo->untestedTerms flag means that this OR term |
| 113115 | 113502 | ** contained one or more AND term from a notReady table. The |
| 113116 | 113503 | ** terms from the notReady table could not be tested and will |
| 113117 | 113504 | ** need to be tested later. |
| | @@ -113132,10 +113519,11 @@ |
| 113132 | 113519 | */ |
| 113133 | 113520 | pSubLoop = pSubWInfo->a[0].pWLoop; |
| 113134 | 113521 | assert( (pSubLoop->wsFlags & WHERE_AUTO_INDEX)==0 ); |
| 113135 | 113522 | if( (pSubLoop->wsFlags & WHERE_INDEXED)!=0 |
| 113136 | 113523 | && (ii==0 || pSubLoop->u.btree.pIndex==pCov) |
| 113524 | + && (HasRowid(pTab) || !IsPrimaryKeyIndex(pSubLoop->u.btree.pIndex)) |
| 113137 | 113525 | ){ |
| 113138 | 113526 | assert( pSubWInfo->a[0].iIdxCur==iCovCur ); |
| 113139 | 113527 | pCov = pSubLoop->u.btree.pIndex; |
| 113140 | 113528 | }else{ |
| 113141 | 113529 | pCov = 0; |
| | @@ -113459,11 +113847,11 @@ |
| 113459 | 113847 | if( pX->nLTerm >= pY->nLTerm ) return 0; /* X is not a subset of Y */ |
| 113460 | 113848 | if( pX->rRun >= pY->rRun ){ |
| 113461 | 113849 | if( pX->rRun > pY->rRun ) return 0; /* X costs more than Y */ |
| 113462 | 113850 | if( pX->nOut > pY->nOut ) return 0; /* X costs more than Y */ |
| 113463 | 113851 | } |
| 113464 | | - for(j=0, i=pX->nLTerm-1; i>=0; i--){ |
| 113852 | + for(i=pX->nLTerm-1; i>=0; i--){ |
| 113465 | 113853 | for(j=pY->nLTerm-1; j>=0; j--){ |
| 113466 | 113854 | if( pY->aLTerm[j]==pX->aLTerm[i] ) break; |
| 113467 | 113855 | } |
| 113468 | 113856 | if( j<0 ) return 0; /* X not a subset of Y since term X[i] not used by Y */ |
| 113469 | 113857 | } |
| | @@ -113481,16 +113869,29 @@ |
| 113481 | 113869 | ** is a proper subset. |
| 113482 | 113870 | ** |
| 113483 | 113871 | ** To say "WhereLoop X is a proper subset of Y" means that X uses fewer |
| 113484 | 113872 | ** WHERE clause terms than Y and that every WHERE clause term used by X is |
| 113485 | 113873 | ** also used by Y. |
| 113874 | +** |
| 113875 | +** This adjustment is omitted for SKIPSCAN loops. In a SKIPSCAN loop, the |
| 113876 | +** WhereLoop.nLTerm field is not an accurate measure of the number of WHERE |
| 113877 | +** clause terms covered, since some of the first nLTerm entries in aLTerm[] |
| 113878 | +** will be NULL (because they are skipped). That makes it more difficult |
| 113879 | +** to compare the loops. We could add extra code to do the comparison, and |
| 113880 | +** perhaps we will someday. But SKIPSCAN is sufficiently uncommon, and this |
| 113881 | +** adjustment is sufficient minor, that it is very difficult to construct |
| 113882 | +** a test case where the extra code would improve the query plan. Better |
| 113883 | +** to avoid the added complexity and just omit cost adjustments to SKIPSCAN |
| 113884 | +** loops. |
| 113486 | 113885 | */ |
| 113487 | 113886 | static void whereLoopAdjustCost(const WhereLoop *p, WhereLoop *pTemplate){ |
| 113488 | 113887 | if( (pTemplate->wsFlags & WHERE_INDEXED)==0 ) return; |
| 113888 | + if( (pTemplate->wsFlags & WHERE_SKIPSCAN)!=0 ) return; |
| 113489 | 113889 | for(; p; p=p->pNextLoop){ |
| 113490 | 113890 | if( p->iTab!=pTemplate->iTab ) continue; |
| 113491 | 113891 | if( (p->wsFlags & WHERE_INDEXED)==0 ) continue; |
| 113892 | + if( (p->wsFlags & WHERE_SKIPSCAN)!=0 ) continue; |
| 113492 | 113893 | if( whereLoopCheaperProperSubset(p, pTemplate) ){ |
| 113493 | 113894 | /* Adjust pTemplate cost downward so that it is cheaper than its |
| 113494 | 113895 | ** subset p */ |
| 113495 | 113896 | pTemplate->rRun = p->rRun; |
| 113496 | 113897 | pTemplate->nOut = p->nOut - 1; |
| | @@ -113711,17 +114112,24 @@ |
| 113711 | 114112 | pX = pLoop->aLTerm[j]; |
| 113712 | 114113 | if( pX==0 ) continue; |
| 113713 | 114114 | if( pX==pTerm ) break; |
| 113714 | 114115 | if( pX->iParent>=0 && (&pWC->a[pX->iParent])==pTerm ) break; |
| 113715 | 114116 | } |
| 113716 | | - if( j<0 ) pLoop->nOut += pTerm->truthProb; |
| 114117 | + if( j<0 ){ |
| 114118 | + pLoop->nOut += (pTerm->truthProb<=0 ? pTerm->truthProb : -1); |
| 114119 | + } |
| 113717 | 114120 | } |
| 113718 | 114121 | } |
| 113719 | 114122 | |
| 113720 | 114123 | /* |
| 113721 | | -** We have so far matched pBuilder->pNew->u.btree.nEq terms of the index pIndex. |
| 113722 | | -** Try to match one more. |
| 114124 | +** We have so far matched pBuilder->pNew->u.btree.nEq terms of the |
| 114125 | +** index pIndex. Try to match one more. |
| 114126 | +** |
| 114127 | +** When this function is called, pBuilder->pNew->nOut contains the |
| 114128 | +** number of rows expected to be visited by filtering using the nEq |
| 114129 | +** terms only. If it is modified, this value is restored before this |
| 114130 | +** function returns. |
| 113723 | 114131 | ** |
| 113724 | 114132 | ** If pProbe->tnum==0, that means pIndex is a fake index used for the |
| 113725 | 114133 | ** INTEGER PRIMARY KEY. |
| 113726 | 114134 | */ |
| 113727 | 114135 | static int whereLoopAddBtreeIndex( |
| | @@ -113743,11 +114151,10 @@ |
| 113743 | 114151 | u16 saved_nSkip; /* Original value of pNew->u.btree.nSkip */ |
| 113744 | 114152 | u32 saved_wsFlags; /* Original value of pNew->wsFlags */ |
| 113745 | 114153 | LogEst saved_nOut; /* Original value of pNew->nOut */ |
| 113746 | 114154 | int iCol; /* Index of the column in the table */ |
| 113747 | 114155 | int rc = SQLITE_OK; /* Return code */ |
| 113748 | | - LogEst nRowEst; /* Estimated index selectivity */ |
| 113749 | 114156 | LogEst rLogSize; /* Logarithm of table size */ |
| 113750 | 114157 | WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */ |
| 113751 | 114158 | |
| 113752 | 114159 | pNew = pBuilder->pNew; |
| 113753 | 114160 | if( db->mallocFailed ) return SQLITE_NOMEM; |
| | @@ -113764,15 +114171,12 @@ |
| 113764 | 114171 | if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE); |
| 113765 | 114172 | |
| 113766 | 114173 | assert( pNew->u.btree.nEq<=pProbe->nKeyCol ); |
| 113767 | 114174 | if( pNew->u.btree.nEq < pProbe->nKeyCol ){ |
| 113768 | 114175 | iCol = pProbe->aiColumn[pNew->u.btree.nEq]; |
| 113769 | | - nRowEst = sqlite3LogEst(pProbe->aiRowEst[pNew->u.btree.nEq+1]); |
| 113770 | | - if( nRowEst==0 && pProbe->onError==OE_None ) nRowEst = 1; |
| 113771 | 114176 | }else{ |
| 113772 | 114177 | iCol = -1; |
| 113773 | | - nRowEst = 0; |
| 113774 | 114178 | } |
| 113775 | 114179 | pTerm = whereScanInit(&scan, pBuilder->pWC, pSrc->iCursor, iCol, |
| 113776 | 114180 | opMask, pProbe); |
| 113777 | 114181 | saved_nEq = pNew->u.btree.nEq; |
| 113778 | 114182 | saved_nSkip = pNew->u.btree.nSkip; |
| | @@ -113779,57 +114183,68 @@ |
| 113779 | 114183 | saved_nLTerm = pNew->nLTerm; |
| 113780 | 114184 | saved_wsFlags = pNew->wsFlags; |
| 113781 | 114185 | saved_prereq = pNew->prereq; |
| 113782 | 114186 | saved_nOut = pNew->nOut; |
| 113783 | 114187 | pNew->rSetup = 0; |
| 113784 | | - rLogSize = estLog(sqlite3LogEst(pProbe->aiRowEst[0])); |
| 114188 | + rLogSize = estLog(pProbe->aiRowLogEst[0]); |
| 113785 | 114189 | |
| 113786 | 114190 | /* Consider using a skip-scan if there are no WHERE clause constraints |
| 113787 | 114191 | ** available for the left-most terms of the index, and if the average |
| 113788 | | - ** number of repeats in the left-most terms is at least 18. The magic |
| 113789 | | - ** number 18 was found by experimentation to be the payoff point where |
| 113790 | | - ** skip-scan become faster than a full-scan. |
| 113791 | | - */ |
| 114192 | + ** number of repeats in the left-most terms is at least 18. |
| 114193 | + ** |
| 114194 | + ** The magic number 18 is selected on the basis that scanning 17 rows |
| 114195 | + ** is almost always quicker than an index seek (even though if the index |
| 114196 | + ** contains fewer than 2^17 rows we assume otherwise in other parts of |
| 114197 | + ** the code). And, even if it is not, it should not be too much slower. |
| 114198 | + ** On the other hand, the extra seeks could end up being significantly |
| 114199 | + ** more expensive. */ |
| 114200 | + assert( 42==sqlite3LogEst(18) ); |
| 113792 | 114201 | if( pTerm==0 |
| 113793 | 114202 | && saved_nEq==saved_nSkip |
| 113794 | 114203 | && saved_nEq+1<pProbe->nKeyCol |
| 113795 | | - && pProbe->aiRowEst[saved_nEq+1]>=18 /* TUNING: Minimum for skip-scan */ |
| 114204 | + && pProbe->aiRowLogEst[saved_nEq+1]>=42 /* TUNING: Minimum for skip-scan */ |
| 113796 | 114205 | && (rc = whereLoopResize(db, pNew, pNew->nLTerm+1))==SQLITE_OK |
| 113797 | 114206 | ){ |
| 113798 | 114207 | LogEst nIter; |
| 113799 | 114208 | pNew->u.btree.nEq++; |
| 113800 | 114209 | pNew->u.btree.nSkip++; |
| 113801 | 114210 | pNew->aLTerm[pNew->nLTerm++] = 0; |
| 113802 | 114211 | pNew->wsFlags |= WHERE_SKIPSCAN; |
| 113803 | | - nIter = sqlite3LogEst(pProbe->aiRowEst[0]/pProbe->aiRowEst[saved_nEq+1]); |
| 113804 | | - pNew->rRun = rLogSize + nIter; |
| 113805 | | - pNew->nOut += nIter; |
| 113806 | | - whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nIter); |
| 114212 | + nIter = pProbe->aiRowLogEst[saved_nEq] - pProbe->aiRowLogEst[saved_nEq+1]; |
| 114213 | + pNew->nOut -= nIter; |
| 114214 | + whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nIter + nInMul); |
| 113807 | 114215 | pNew->nOut = saved_nOut; |
| 113808 | 114216 | } |
| 113809 | 114217 | for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){ |
| 114218 | + u16 eOp = pTerm->eOperator; /* Shorthand for pTerm->eOperator */ |
| 114219 | + LogEst rCostIdx; |
| 114220 | + LogEst nOutUnadjusted; /* nOut before IN() and WHERE adjustments */ |
| 113810 | 114221 | int nIn = 0; |
| 113811 | 114222 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 113812 | 114223 | int nRecValid = pBuilder->nRecValid; |
| 113813 | 114224 | #endif |
| 113814 | | - if( (pTerm->eOperator==WO_ISNULL || (pTerm->wtFlags&TERM_VNULL)!=0) |
| 114225 | + if( (eOp==WO_ISNULL || (pTerm->wtFlags&TERM_VNULL)!=0) |
| 113815 | 114226 | && (iCol<0 || pSrc->pTab->aCol[iCol].notNull) |
| 113816 | 114227 | ){ |
| 113817 | 114228 | continue; /* ignore IS [NOT] NULL constraints on NOT NULL columns */ |
| 113818 | 114229 | } |
| 113819 | 114230 | if( pTerm->prereqRight & pNew->maskSelf ) continue; |
| 113820 | 114231 | |
| 113821 | | - assert( pNew->nOut==saved_nOut ); |
| 113822 | | - |
| 113823 | 114232 | pNew->wsFlags = saved_wsFlags; |
| 113824 | 114233 | pNew->u.btree.nEq = saved_nEq; |
| 113825 | 114234 | pNew->nLTerm = saved_nLTerm; |
| 113826 | 114235 | if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */ |
| 113827 | 114236 | pNew->aLTerm[pNew->nLTerm++] = pTerm; |
| 113828 | 114237 | pNew->prereq = (saved_prereq | pTerm->prereqRight) & ~pNew->maskSelf; |
| 113829 | | - pNew->rRun = rLogSize; /* Baseline cost is log2(N). Adjustments below */ |
| 113830 | | - if( pTerm->eOperator & WO_IN ){ |
| 114238 | + |
| 114239 | + assert( nInMul==0 |
| 114240 | + || (pNew->wsFlags & WHERE_COLUMN_NULL)!=0 |
| 114241 | + || (pNew->wsFlags & WHERE_COLUMN_IN)!=0 |
| 114242 | + || (pNew->wsFlags & WHERE_SKIPSCAN)!=0 |
| 114243 | + ); |
| 114244 | + |
| 114245 | + if( eOp & WO_IN ){ |
| 113831 | 114246 | Expr *pExpr = pTerm->pExpr; |
| 113832 | 114247 | pNew->wsFlags |= WHERE_COLUMN_IN; |
| 113833 | 114248 | if( ExprHasProperty(pExpr, EP_xIsSelect) ){ |
| 113834 | 114249 | /* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */ |
| 113835 | 114250 | nIn = 46; assert( 46==sqlite3LogEst(25) ); |
| | @@ -113837,87 +114252,122 @@ |
| 113837 | 114252 | /* "x IN (value, value, ...)" */ |
| 113838 | 114253 | nIn = sqlite3LogEst(pExpr->x.pList->nExpr); |
| 113839 | 114254 | } |
| 113840 | 114255 | assert( nIn>0 ); /* RHS always has 2 or more terms... The parser |
| 113841 | 114256 | ** changes "x IN (?)" into "x=?". */ |
| 113842 | | - pNew->rRun += nIn; |
| 113843 | | - pNew->u.btree.nEq++; |
| 113844 | | - pNew->nOut = nRowEst + nInMul + nIn; |
| 113845 | | - }else if( pTerm->eOperator & (WO_EQ) ){ |
| 113846 | | - assert( |
| 113847 | | - (pNew->wsFlags & (WHERE_COLUMN_NULL|WHERE_COLUMN_IN|WHERE_SKIPSCAN))!=0 |
| 113848 | | - || nInMul==0 |
| 113849 | | - ); |
| 114257 | + |
| 114258 | + }else if( eOp & (WO_EQ) ){ |
| 113850 | 114259 | pNew->wsFlags |= WHERE_COLUMN_EQ; |
| 113851 | | - if( iCol<0 || (nInMul==0 && pNew->u.btree.nEq==pProbe->nKeyCol-1)){ |
| 113852 | | - assert( (pNew->wsFlags & WHERE_COLUMN_IN)==0 || iCol<0 ); |
| 114260 | + if( iCol<0 || (nInMul==0 && pNew->u.btree.nEq==pProbe->nKeyCol-1) ){ |
| 113853 | 114261 | if( iCol>=0 && pProbe->onError==OE_None ){ |
| 113854 | 114262 | pNew->wsFlags |= WHERE_UNQ_WANTED; |
| 113855 | 114263 | }else{ |
| 113856 | 114264 | pNew->wsFlags |= WHERE_ONEROW; |
| 113857 | 114265 | } |
| 113858 | 114266 | } |
| 113859 | | - pNew->u.btree.nEq++; |
| 113860 | | - pNew->nOut = nRowEst + nInMul; |
| 113861 | | - }else if( pTerm->eOperator & (WO_ISNULL) ){ |
| 114267 | + }else if( eOp & WO_ISNULL ){ |
| 113862 | 114268 | pNew->wsFlags |= WHERE_COLUMN_NULL; |
| 113863 | | - pNew->u.btree.nEq++; |
| 113864 | | - /* TUNING: IS NULL selects 2 rows */ |
| 113865 | | - nIn = 10; assert( 10==sqlite3LogEst(2) ); |
| 113866 | | - pNew->nOut = nRowEst + nInMul + nIn; |
| 113867 | | - }else if( pTerm->eOperator & (WO_GT|WO_GE) ){ |
| 113868 | | - testcase( pTerm->eOperator & WO_GT ); |
| 113869 | | - testcase( pTerm->eOperator & WO_GE ); |
| 114269 | + }else if( eOp & (WO_GT|WO_GE) ){ |
| 114270 | + testcase( eOp & WO_GT ); |
| 114271 | + testcase( eOp & WO_GE ); |
| 113870 | 114272 | pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT; |
| 113871 | 114273 | pBtm = pTerm; |
| 113872 | 114274 | pTop = 0; |
| 113873 | 114275 | }else{ |
| 113874 | | - assert( pTerm->eOperator & (WO_LT|WO_LE) ); |
| 113875 | | - testcase( pTerm->eOperator & WO_LT ); |
| 113876 | | - testcase( pTerm->eOperator & WO_LE ); |
| 114276 | + assert( eOp & (WO_LT|WO_LE) ); |
| 114277 | + testcase( eOp & WO_LT ); |
| 114278 | + testcase( eOp & WO_LE ); |
| 113877 | 114279 | pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT; |
| 113878 | 114280 | pTop = pTerm; |
| 113879 | 114281 | pBtm = (pNew->wsFlags & WHERE_BTM_LIMIT)!=0 ? |
| 113880 | 114282 | pNew->aLTerm[pNew->nLTerm-2] : 0; |
| 113881 | 114283 | } |
| 114284 | + |
| 114285 | + /* At this point pNew->nOut is set to the number of rows expected to |
| 114286 | + ** be visited by the index scan before considering term pTerm, or the |
| 114287 | + ** values of nIn and nInMul. In other words, assuming that all |
| 114288 | + ** "x IN(...)" terms are replaced with "x = ?". This block updates |
| 114289 | + ** the value of pNew->nOut to account for pTerm (but not nIn/nInMul). */ |
| 114290 | + assert( pNew->nOut==saved_nOut ); |
| 113882 | 114291 | if( pNew->wsFlags & WHERE_COLUMN_RANGE ){ |
| 113883 | | - /* Adjust nOut and rRun for STAT3 range values */ |
| 113884 | | - assert( pNew->nOut==saved_nOut ); |
| 114292 | + /* Adjust nOut using stat3/stat4 data. Or, if there is no stat3/stat4 |
| 114293 | + ** data, using some other estimate. */ |
| 113885 | 114294 | whereRangeScanEst(pParse, pBuilder, pBtm, pTop, pNew); |
| 113886 | | - } |
| 114295 | + }else{ |
| 114296 | + int nEq = ++pNew->u.btree.nEq; |
| 114297 | + assert( eOp & (WO_ISNULL|WO_EQ|WO_IN) ); |
| 114298 | + |
| 114299 | + assert( pNew->nOut==saved_nOut ); |
| 114300 | + if( pTerm->truthProb<=0 && iCol>=0 ){ |
| 114301 | + assert( (eOp & WO_IN) || nIn==0 ); |
| 114302 | + testcase( eOp & WO_IN ); |
| 114303 | + pNew->nOut += pTerm->truthProb; |
| 114304 | + pNew->nOut -= nIn; |
| 114305 | + pNew->wsFlags |= WHERE_LIKELIHOOD; |
| 114306 | + }else{ |
| 113887 | 114307 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 113888 | | - if( nInMul==0 |
| 113889 | | - && pProbe->nSample |
| 113890 | | - && pNew->u.btree.nEq<=pProbe->nSampleCol |
| 113891 | | - && OptimizationEnabled(db, SQLITE_Stat3) |
| 113892 | | - ){ |
| 113893 | | - Expr *pExpr = pTerm->pExpr; |
| 113894 | | - tRowcnt nOut = 0; |
| 113895 | | - if( (pTerm->eOperator & (WO_EQ|WO_ISNULL))!=0 ){ |
| 113896 | | - testcase( pTerm->eOperator & WO_EQ ); |
| 113897 | | - testcase( pTerm->eOperator & WO_ISNULL ); |
| 113898 | | - rc = whereEqualScanEst(pParse, pBuilder, pExpr->pRight, &nOut); |
| 113899 | | - }else if( (pTerm->eOperator & WO_IN) |
| 113900 | | - && !ExprHasProperty(pExpr, EP_xIsSelect) ){ |
| 113901 | | - rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut); |
| 113902 | | - } |
| 113903 | | - assert( nOut==0 || rc==SQLITE_OK ); |
| 113904 | | - if( nOut ){ |
| 113905 | | - pNew->nOut = sqlite3LogEst(nOut); |
| 113906 | | - if( pNew->nOut>saved_nOut ) pNew->nOut = saved_nOut; |
| 113907 | | - } |
| 113908 | | - } |
| 113909 | | -#endif |
| 114308 | + tRowcnt nOut = 0; |
| 114309 | + if( nInMul==0 |
| 114310 | + && pProbe->nSample |
| 114311 | + && pNew->u.btree.nEq<=pProbe->nSampleCol |
| 114312 | + && OptimizationEnabled(db, SQLITE_Stat3) |
| 114313 | + && ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect)) |
| 114314 | + && (pNew->wsFlags & WHERE_LIKELIHOOD)==0 |
| 114315 | + ){ |
| 114316 | + Expr *pExpr = pTerm->pExpr; |
| 114317 | + if( (eOp & (WO_EQ|WO_ISNULL))!=0 ){ |
| 114318 | + testcase( eOp & WO_EQ ); |
| 114319 | + testcase( eOp & WO_ISNULL ); |
| 114320 | + rc = whereEqualScanEst(pParse, pBuilder, pExpr->pRight, &nOut); |
| 114321 | + }else{ |
| 114322 | + rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut); |
| 114323 | + } |
| 114324 | + assert( rc!=SQLITE_OK || nOut>0 ); |
| 114325 | + if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; |
| 114326 | + if( rc!=SQLITE_OK ) break; /* Jump out of the pTerm loop */ |
| 114327 | + if( nOut ){ |
| 114328 | + pNew->nOut = sqlite3LogEst(nOut); |
| 114329 | + if( pNew->nOut>saved_nOut ) pNew->nOut = saved_nOut; |
| 114330 | + pNew->nOut -= nIn; |
| 114331 | + } |
| 114332 | + } |
| 114333 | + if( nOut==0 ) |
| 114334 | +#endif |
| 114335 | + { |
| 114336 | + pNew->nOut += (pProbe->aiRowLogEst[nEq] - pProbe->aiRowLogEst[nEq-1]); |
| 114337 | + if( eOp & WO_ISNULL ){ |
| 114338 | + /* TUNING: If there is no likelihood() value, assume that a |
| 114339 | + ** "col IS NULL" expression matches twice as many rows |
| 114340 | + ** as (col=?). */ |
| 114341 | + pNew->nOut += 10; |
| 114342 | + } |
| 114343 | + } |
| 114344 | + } |
| 114345 | + } |
| 114346 | + |
| 114347 | + /* Set rCostIdx to the cost of visiting selected rows in index. Add |
| 114348 | + ** it to pNew->rRun, which is currently set to the cost of the index |
| 114349 | + ** seek only. Then, if this is a non-covering index, add the cost of |
| 114350 | + ** visiting the rows in the main table. */ |
| 114351 | + rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow; |
| 114352 | + pNew->rRun = sqlite3LogEstAdd(rLogSize, rCostIdx); |
| 113910 | 114353 | if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){ |
| 113911 | | - /* Each row involves a step of the index, then a binary search of |
| 113912 | | - ** the main table */ |
| 113913 | | - pNew->rRun = sqlite3LogEstAdd(pNew->rRun,rLogSize>27 ? rLogSize-17 : 10); |
| 114354 | + pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut + 16); |
| 113914 | 114355 | } |
| 113915 | | - /* Step cost for each output row */ |
| 113916 | | - pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut); |
| 114356 | + |
| 114357 | + nOutUnadjusted = pNew->nOut; |
| 114358 | + pNew->rRun += nInMul + nIn; |
| 114359 | + pNew->nOut += nInMul + nIn; |
| 113917 | 114360 | whereLoopOutputAdjust(pBuilder->pWC, pNew); |
| 113918 | 114361 | rc = whereLoopInsert(pBuilder, pNew); |
| 114362 | + |
| 114363 | + if( pNew->wsFlags & WHERE_COLUMN_RANGE ){ |
| 114364 | + pNew->nOut = saved_nOut; |
| 114365 | + }else{ |
| 114366 | + pNew->nOut = nOutUnadjusted; |
| 114367 | + } |
| 114368 | + |
| 113919 | 114369 | if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 |
| 113920 | 114370 | && pNew->u.btree.nEq<(pProbe->nKeyCol + (pProbe->zName!=0)) |
| 113921 | 114371 | ){ |
| 113922 | 114372 | whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn); |
| 113923 | 114373 | } |
| | @@ -113997,19 +114447,42 @@ |
| 113997 | 114447 | |
| 113998 | 114448 | /* |
| 113999 | 114449 | ** Add all WhereLoop objects for a single table of the join where the table |
| 114000 | 114450 | ** is idenfied by pBuilder->pNew->iTab. That table is guaranteed to be |
| 114001 | 114451 | ** a b-tree table, not a virtual table. |
| 114452 | +** |
| 114453 | +** The costs (WhereLoop.rRun) of the b-tree loops added by this function |
| 114454 | +** are calculated as follows: |
| 114455 | +** |
| 114456 | +** For a full scan, assuming the table (or index) contains nRow rows: |
| 114457 | +** |
| 114458 | +** cost = nRow * 3.0 // full-table scan |
| 114459 | +** cost = nRow * K // scan of covering index |
| 114460 | +** cost = nRow * (K+3.0) // scan of non-covering index |
| 114461 | +** |
| 114462 | +** where K is a value between 1.1 and 3.0 set based on the relative |
| 114463 | +** estimated average size of the index and table records. |
| 114464 | +** |
| 114465 | +** For an index scan, where nVisit is the number of index rows visited |
| 114466 | +** by the scan, and nSeek is the number of seek operations required on |
| 114467 | +** the index b-tree: |
| 114468 | +** |
| 114469 | +** cost = nSeek * (log(nRow) + K * nVisit) // covering index |
| 114470 | +** cost = nSeek * (log(nRow) + (K+3.0) * nVisit) // non-covering index |
| 114471 | +** |
| 114472 | +** Normally, nSeek is 1. nSeek values greater than 1 come about if the |
| 114473 | +** WHERE clause includes "x IN (....)" terms used in place of "x=?". Or when |
| 114474 | +** implicit "x IN (SELECT x FROM tbl)" terms are added for skip-scans. |
| 114002 | 114475 | */ |
| 114003 | 114476 | static int whereLoopAddBtree( |
| 114004 | 114477 | WhereLoopBuilder *pBuilder, /* WHERE clause information */ |
| 114005 | 114478 | Bitmask mExtra /* Extra prerequesites for using this table */ |
| 114006 | 114479 | ){ |
| 114007 | 114480 | WhereInfo *pWInfo; /* WHERE analysis context */ |
| 114008 | 114481 | Index *pProbe; /* An index we are evaluating */ |
| 114009 | 114482 | Index sPk; /* A fake index object for the primary key */ |
| 114010 | | - tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */ |
| 114483 | + LogEst aiRowEstPk[2]; /* The aiRowLogEst[] value for the sPk index */ |
| 114011 | 114484 | i16 aiColumnPk = -1; /* The aColumn[] value for the sPk index */ |
| 114012 | 114485 | SrcList *pTabList; /* The FROM clause */ |
| 114013 | 114486 | struct SrcList_item *pSrc; /* The FROM clause btree term to add */ |
| 114014 | 114487 | WhereLoop *pNew; /* Template WhereLoop object */ |
| 114015 | 114488 | int rc = SQLITE_OK; /* Return code */ |
| | @@ -114040,24 +114513,25 @@ |
| 114040 | 114513 | ** indices to follow */ |
| 114041 | 114514 | Index *pFirst; /* First of real indices on the table */ |
| 114042 | 114515 | memset(&sPk, 0, sizeof(Index)); |
| 114043 | 114516 | sPk.nKeyCol = 1; |
| 114044 | 114517 | sPk.aiColumn = &aiColumnPk; |
| 114045 | | - sPk.aiRowEst = aiRowEstPk; |
| 114518 | + sPk.aiRowLogEst = aiRowEstPk; |
| 114046 | 114519 | sPk.onError = OE_Replace; |
| 114047 | 114520 | sPk.pTable = pTab; |
| 114048 | | - aiRowEstPk[0] = pTab->nRowEst; |
| 114049 | | - aiRowEstPk[1] = 1; |
| 114521 | + sPk.szIdxRow = pTab->szTabRow; |
| 114522 | + aiRowEstPk[0] = pTab->nRowLogEst; |
| 114523 | + aiRowEstPk[1] = 0; |
| 114050 | 114524 | pFirst = pSrc->pTab->pIndex; |
| 114051 | 114525 | if( pSrc->notIndexed==0 ){ |
| 114052 | 114526 | /* The real indices of the table are only considered if the |
| 114053 | 114527 | ** NOT INDEXED qualifier is omitted from the FROM clause */ |
| 114054 | 114528 | sPk.pNext = pFirst; |
| 114055 | 114529 | } |
| 114056 | 114530 | pProbe = &sPk; |
| 114057 | 114531 | } |
| 114058 | | - rSize = sqlite3LogEst(pTab->nRowEst); |
| 114532 | + rSize = pTab->nRowLogEst; |
| 114059 | 114533 | rLogSize = estLog(rSize); |
| 114060 | 114534 | |
| 114061 | 114535 | #ifndef SQLITE_OMIT_AUTOMATIC_INDEX |
| 114062 | 114536 | /* Automatic indexes */ |
| 114063 | 114537 | if( !pBuilder->pOrSet |
| | @@ -114103,10 +114577,11 @@ |
| 114103 | 114577 | for(; rc==SQLITE_OK && pProbe; pProbe=pProbe->pNext, iSortIdx++){ |
| 114104 | 114578 | if( pProbe->pPartIdxWhere!=0 |
| 114105 | 114579 | && !whereUsablePartialIndex(pNew->iTab, pWC, pProbe->pPartIdxWhere) ){ |
| 114106 | 114580 | continue; /* Partial index inappropriate for this query */ |
| 114107 | 114581 | } |
| 114582 | + rSize = pProbe->aiRowLogEst[0]; |
| 114108 | 114583 | pNew->u.btree.nEq = 0; |
| 114109 | 114584 | pNew->u.btree.nSkip = 0; |
| 114110 | 114585 | pNew->nLTerm = 0; |
| 114111 | 114586 | pNew->iSortIdx = 0; |
| 114112 | 114587 | pNew->rSetup = 0; |
| | @@ -114120,14 +114595,12 @@ |
| 114120 | 114595 | /* Integer primary key index */ |
| 114121 | 114596 | pNew->wsFlags = WHERE_IPK; |
| 114122 | 114597 | |
| 114123 | 114598 | /* Full table scan */ |
| 114124 | 114599 | pNew->iSortIdx = b ? iSortIdx : 0; |
| 114125 | | - /* TUNING: Cost of full table scan is 3*(N + log2(N)). |
| 114126 | | - ** + The extra 3 factor is to encourage the use of indexed lookups |
| 114127 | | - ** over full scans. FIXME */ |
| 114128 | | - pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 16; |
| 114600 | + /* TUNING: Cost of full table scan is (N*3.0). */ |
| 114601 | + pNew->rRun = rSize + 16; |
| 114129 | 114602 | whereLoopOutputAdjust(pWC, pNew); |
| 114130 | 114603 | rc = whereLoopInsert(pBuilder, pNew); |
| 114131 | 114604 | pNew->nOut = rSize; |
| 114132 | 114605 | if( rc ) break; |
| 114133 | 114606 | }else{ |
| | @@ -114150,39 +114623,20 @@ |
| 114150 | 114623 | && sqlite3GlobalConfig.bUseCis |
| 114151 | 114624 | && OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan) |
| 114152 | 114625 | ) |
| 114153 | 114626 | ){ |
| 114154 | 114627 | pNew->iSortIdx = b ? iSortIdx : 0; |
| 114155 | | - /* TUNING: The base cost of an index scan is N + log2(N). |
| 114156 | | - ** The log2(N) is for the initial seek to the beginning and the N |
| 114157 | | - ** is for the scan itself. */ |
| 114158 | | - pNew->rRun = sqlite3LogEstAdd(rSize, rLogSize); |
| 114159 | | - if( m==0 ){ |
| 114160 | | - /* TUNING: Cost of a covering index scan is K*(N + log2(N)). |
| 114161 | | - ** + The extra factor K of between 1.1 and 3.0 that depends |
| 114162 | | - ** on the relative sizes of the table and the index. K |
| 114163 | | - ** is smaller for smaller indices, thus favoring them. |
| 114164 | | - ** The upper bound on K (3.0) matches the penalty factor |
| 114165 | | - ** on a full table scan that tries to encourage the use of |
| 114166 | | - ** indexed lookups over full scans. |
| 114167 | | - */ |
| 114168 | | - pNew->rRun += 1 + (15*pProbe->szIdxRow)/pTab->szTabRow; |
| 114169 | | - }else{ |
| 114170 | | - /* TUNING: The cost of scanning a non-covering index is multiplied |
| 114171 | | - ** by log2(N) to account for the binary search of the main table |
| 114172 | | - ** that must happen for each row of the index. |
| 114173 | | - ** TODO: Should there be a multiplier here, analogous to the 3x |
| 114174 | | - ** multiplier for a fulltable scan or covering index scan, to |
| 114175 | | - ** further discourage the use of an index scan? Or is the log2(N) |
| 114176 | | - ** term sufficient discouragement? |
| 114177 | | - ** TODO: What if some or all of the WHERE clause terms can be |
| 114178 | | - ** computed without reference to the original table. Then the |
| 114179 | | - ** penality should reduce to logK where K is the number of output |
| 114180 | | - ** rows. |
| 114181 | | - */ |
| 114182 | | - pNew->rRun += rLogSize; |
| 114183 | | - } |
| 114628 | + |
| 114629 | + /* The cost of visiting the index rows is N*K, where K is |
| 114630 | + ** between 1.1 and 3.0, depending on the relative sizes of the |
| 114631 | + ** index and table rows. If this is a non-covering index scan, |
| 114632 | + ** also add the cost of visiting table rows (N*3.0). */ |
| 114633 | + pNew->rRun = rSize + 1 + (15*pProbe->szIdxRow)/pTab->szTabRow; |
| 114634 | + if( m!=0 ){ |
| 114635 | + pNew->rRun = sqlite3LogEstAdd(pNew->rRun, rSize+16); |
| 114636 | + } |
| 114637 | + |
| 114184 | 114638 | whereLoopOutputAdjust(pWC, pNew); |
| 114185 | 114639 | rc = whereLoopInsert(pBuilder, pNew); |
| 114186 | 114640 | pNew->nOut = rSize; |
| 114187 | 114641 | if( rc ) break; |
| 114188 | 114642 | } |
| | @@ -114382,20 +114836,19 @@ |
| 114382 | 114836 | WhereTerm *pTerm, *pWCEnd; |
| 114383 | 114837 | int rc = SQLITE_OK; |
| 114384 | 114838 | int iCur; |
| 114385 | 114839 | WhereClause tempWC; |
| 114386 | 114840 | WhereLoopBuilder sSubBuild; |
| 114387 | | - WhereOrSet sSum, sCur, sPrev; |
| 114841 | + WhereOrSet sSum, sCur; |
| 114388 | 114842 | struct SrcList_item *pItem; |
| 114389 | 114843 | |
| 114390 | 114844 | pWC = pBuilder->pWC; |
| 114391 | 114845 | if( pWInfo->wctrlFlags & WHERE_AND_ONLY ) return SQLITE_OK; |
| 114392 | 114846 | pWCEnd = pWC->a + pWC->nTerm; |
| 114393 | 114847 | pNew = pBuilder->pNew; |
| 114394 | 114848 | memset(&sSum, 0, sizeof(sSum)); |
| 114395 | 114849 | pItem = pWInfo->pTabList->a + pNew->iTab; |
| 114396 | | - if( !HasRowid(pItem->pTab) ) return SQLITE_OK; |
| 114397 | 114850 | iCur = pItem->iCursor; |
| 114398 | 114851 | |
| 114399 | 114852 | for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){ |
| 114400 | 114853 | if( (pTerm->eOperator & WO_OR)!=0 |
| 114401 | 114854 | && (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0 |
| | @@ -114438,10 +114891,11 @@ |
| 114438 | 114891 | break; |
| 114439 | 114892 | }else if( once ){ |
| 114440 | 114893 | whereOrMove(&sSum, &sCur); |
| 114441 | 114894 | once = 0; |
| 114442 | 114895 | }else{ |
| 114896 | + WhereOrSet sPrev; |
| 114443 | 114897 | whereOrMove(&sPrev, &sSum); |
| 114444 | 114898 | sSum.n = 0; |
| 114445 | 114899 | for(i=0; i<sPrev.n; i++){ |
| 114446 | 114900 | for(j=0; j<sCur.n; j++){ |
| 114447 | 114901 | whereOrInsert(&sSum, sPrev.a[i].prereq | sCur.a[j].prereq, |
| | @@ -114456,12 +114910,23 @@ |
| 114456 | 114910 | pNew->wsFlags = WHERE_MULTI_OR; |
| 114457 | 114911 | pNew->rSetup = 0; |
| 114458 | 114912 | pNew->iSortIdx = 0; |
| 114459 | 114913 | memset(&pNew->u, 0, sizeof(pNew->u)); |
| 114460 | 114914 | for(i=0; rc==SQLITE_OK && i<sSum.n; i++){ |
| 114461 | | - /* TUNING: Multiple by 3.5 for the secondary table lookup */ |
| 114462 | | - pNew->rRun = sSum.a[i].rRun + 18; |
| 114915 | + /* TUNING: Currently sSum.a[i].rRun is set to the sum of the costs |
| 114916 | + ** of all sub-scans required by the OR-scan. However, due to rounding |
| 114917 | + ** errors, it may be that the cost of the OR-scan is equal to its |
| 114918 | + ** most expensive sub-scan. Add the smallest possible penalty |
| 114919 | + ** (equivalent to multiplying the cost by 1.07) to ensure that |
| 114920 | + ** this does not happen. Otherwise, for WHERE clauses such as the |
| 114921 | + ** following where there is an index on "y": |
| 114922 | + ** |
| 114923 | + ** WHERE likelihood(x=?, 0.99) OR y=? |
| 114924 | + ** |
| 114925 | + ** the planner may elect to "OR" together a full-table scan and an |
| 114926 | + ** index lookup. And other similarly odd results. */ |
| 114927 | + pNew->rRun = sSum.a[i].rRun + 1; |
| 114463 | 114928 | pNew->nOut = sSum.a[i].nOut; |
| 114464 | 114929 | pNew->prereq = sSum.a[i].prereq; |
| 114465 | 114930 | rc = whereLoopInsert(pBuilder, pNew); |
| 114466 | 114931 | } |
| 114467 | 114932 | } |
| | @@ -114520,11 +114985,11 @@ |
| 114520 | 114985 | ** N<0: Unknown yet how many terms of ORDER BY might be satisfied. |
| 114521 | 114986 | ** |
| 114522 | 114987 | ** Note that processing for WHERE_GROUPBY and WHERE_DISTINCTBY is not as |
| 114523 | 114988 | ** strict. With GROUP BY and DISTINCT the only requirement is that |
| 114524 | 114989 | ** equivalent rows appear immediately adjacent to one another. GROUP BY |
| 114525 | | -** and DISTINT do not require rows to appear in any particular order as long |
| 114990 | +** and DISTINCT do not require rows to appear in any particular order as long |
| 114526 | 114991 | ** as equivelent rows are grouped together. Thus for GROUP BY and DISTINCT |
| 114527 | 114992 | ** the pOrderBy terms can be matched in any order. With ORDER BY, the |
| 114528 | 114993 | ** pOrderBy terms must be matched in strict left-to-right order. |
| 114529 | 114994 | */ |
| 114530 | 114995 | static i8 wherePathSatisfiesOrderBy( |
| | @@ -114581,18 +115046,10 @@ |
| 114581 | 115046 | ** rowid appears in the ORDER BY clause, the corresponding WhereLoop is |
| 114582 | 115047 | ** automatically order-distinct. |
| 114583 | 115048 | */ |
| 114584 | 115049 | |
| 114585 | 115050 | assert( pOrderBy!=0 ); |
| 114586 | | - |
| 114587 | | - /* Sortability of virtual tables is determined by the xBestIndex method |
| 114588 | | - ** of the virtual table itself */ |
| 114589 | | - if( pLast->wsFlags & WHERE_VIRTUALTABLE ){ |
| 114590 | | - testcase( nLoop>0 ); /* True when outer loops are one-row and match |
| 114591 | | - ** no ORDER BY terms */ |
| 114592 | | - return pLast->u.vtab.isOrdered; |
| 114593 | | - } |
| 114594 | 115051 | if( nLoop && OptimizationDisabled(db, SQLITE_OrderByIdxJoin) ) return 0; |
| 114595 | 115052 | |
| 114596 | 115053 | nOrderBy = pOrderBy->nExpr; |
| 114597 | 115054 | testcase( nOrderBy==BMS-1 ); |
| 114598 | 115055 | if( nOrderBy>BMS-1 ) return 0; /* Cannot optimize overly large ORDER BYs */ |
| | @@ -114601,11 +115058,14 @@ |
| 114601 | 115058 | orderDistinctMask = 0; |
| 114602 | 115059 | ready = 0; |
| 114603 | 115060 | for(iLoop=0; isOrderDistinct && obSat<obDone && iLoop<=nLoop; iLoop++){ |
| 114604 | 115061 | if( iLoop>0 ) ready |= pLoop->maskSelf; |
| 114605 | 115062 | pLoop = iLoop<nLoop ? pPath->aLoop[iLoop] : pLast; |
| 114606 | | - assert( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ); |
| 115063 | + if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){ |
| 115064 | + if( pLoop->u.vtab.isOrdered ) obSat = obDone; |
| 115065 | + break; |
| 115066 | + } |
| 114607 | 115067 | iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor; |
| 114608 | 115068 | |
| 114609 | 115069 | /* Mark off any ORDER BY term X that is a column in the table of |
| 114610 | 115070 | ** the current loop for which there is term in the WHERE |
| 114611 | 115071 | ** clause of the form X IS NULL or X=? that reference only outer |
| | @@ -114689,11 +115149,11 @@ |
| 114689 | 115149 | ){ |
| 114690 | 115150 | isOrderDistinct = 0; |
| 114691 | 115151 | } |
| 114692 | 115152 | |
| 114693 | 115153 | /* Find the ORDER BY term that corresponds to the j-th column |
| 114694 | | - ** of the index and and mark that ORDER BY term off |
| 115154 | + ** of the index and mark that ORDER BY term off |
| 114695 | 115155 | */ |
| 114696 | 115156 | bOnce = 1; |
| 114697 | 115157 | isMatch = 0; |
| 114698 | 115158 | for(i=0; bOnce && i<nOrderBy; i++){ |
| 114699 | 115159 | if( MASKBIT(i) & obSat ) continue; |
| | @@ -114769,10 +115229,40 @@ |
| 114769 | 115229 | return 0; |
| 114770 | 115230 | } |
| 114771 | 115231 | return -1; |
| 114772 | 115232 | } |
| 114773 | 115233 | |
| 115234 | + |
| 115235 | +/* |
| 115236 | +** If the WHERE_GROUPBY flag is set in the mask passed to sqlite3WhereBegin(), |
| 115237 | +** the planner assumes that the specified pOrderBy list is actually a GROUP |
| 115238 | +** BY clause - and so any order that groups rows as required satisfies the |
| 115239 | +** request. |
| 115240 | +** |
| 115241 | +** Normally, in this case it is not possible for the caller to determine |
| 115242 | +** whether or not the rows are really being delivered in sorted order, or |
| 115243 | +** just in some other order that provides the required grouping. However, |
| 115244 | +** if the WHERE_SORTBYGROUP flag is also passed to sqlite3WhereBegin(), then |
| 115245 | +** this function may be called on the returned WhereInfo object. It returns |
| 115246 | +** true if the rows really will be sorted in the specified order, or false |
| 115247 | +** otherwise. |
| 115248 | +** |
| 115249 | +** For example, assuming: |
| 115250 | +** |
| 115251 | +** CREATE INDEX i1 ON t1(x, Y); |
| 115252 | +** |
| 115253 | +** then |
| 115254 | +** |
| 115255 | +** SELECT * FROM t1 GROUP BY x,y ORDER BY x,y; -- IsSorted()==1 |
| 115256 | +** SELECT * FROM t1 GROUP BY y,x ORDER BY y,x; -- IsSorted()==0 |
| 115257 | +*/ |
| 115258 | +SQLITE_PRIVATE int sqlite3WhereIsSorted(WhereInfo *pWInfo){ |
| 115259 | + assert( pWInfo->wctrlFlags & WHERE_GROUPBY ); |
| 115260 | + assert( pWInfo->wctrlFlags & WHERE_SORTBYGROUP ); |
| 115261 | + return pWInfo->sorted; |
| 115262 | +} |
| 115263 | + |
| 114774 | 115264 | #ifdef WHERETRACE_ENABLED |
| 114775 | 115265 | /* For debugging use only: */ |
| 114776 | 115266 | static const char *wherePathName(WherePath *pPath, int nLoop, WhereLoop *pLast){ |
| 114777 | 115267 | static char zName[65]; |
| 114778 | 115268 | int i; |
| | @@ -114780,11 +115270,10 @@ |
| 114780 | 115270 | if( pLast ) zName[i++] = pLast->cId; |
| 114781 | 115271 | zName[i] = 0; |
| 114782 | 115272 | return zName; |
| 114783 | 115273 | } |
| 114784 | 115274 | #endif |
| 114785 | | - |
| 114786 | 115275 | |
| 114787 | 115276 | /* |
| 114788 | 115277 | ** Given the list of WhereLoop objects at pWInfo->pLoops, this routine |
| 114789 | 115278 | ** attempts to find the lowest cost path that visits each WhereLoop |
| 114790 | 115279 | ** once. This path is then loaded into the pWInfo->a[].pWLoop fields. |
| | @@ -114879,26 +115368,31 @@ |
| 114879 | 115368 | if( isOrdered<0 ){ |
| 114880 | 115369 | isOrdered = wherePathSatisfiesOrderBy(pWInfo, |
| 114881 | 115370 | pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags, |
| 114882 | 115371 | iLoop, pWLoop, &revMask); |
| 114883 | 115372 | if( isOrdered>=0 && isOrdered<nOrderBy ){ |
| 114884 | | - /* TUNING: Estimated cost of sorting is N*log(N). |
| 114885 | | - ** If the order-by clause has X terms but only the last Y terms |
| 114886 | | - ** are out of order, then block-sorting will reduce the sorting |
| 114887 | | - ** cost to N*log(N)*log(Y/X). The log(Y/X) term is computed |
| 114888 | | - ** by rScale. |
| 114889 | | - ** TODO: Should the sorting cost get a small multiplier to help |
| 114890 | | - ** discourage the use of sorting and encourage the use of index |
| 114891 | | - ** scans instead? |
| 114892 | | - */ |
| 115373 | + /* TUNING: Estimated cost of a full external sort, where N is |
| 115374 | + ** the number of rows to sort is: |
| 115375 | + ** |
| 115376 | + ** cost = (3.0 * N * log(N)). |
| 115377 | + ** |
| 115378 | + ** Or, if the order-by clause has X terms but only the last Y |
| 115379 | + ** terms are out of order, then block-sorting will reduce the |
| 115380 | + ** sorting cost to: |
| 115381 | + ** |
| 115382 | + ** cost = (3.0 * N * log(N)) * (Y/X) |
| 115383 | + ** |
| 115384 | + ** The (Y/X) term is implemented using stack variable rScale |
| 115385 | + ** below. */ |
| 114893 | 115386 | LogEst rScale, rSortCost; |
| 114894 | | - assert( nOrderBy>0 ); |
| 115387 | + assert( nOrderBy>0 && 66==sqlite3LogEst(100) ); |
| 114895 | 115388 | rScale = sqlite3LogEst((nOrderBy-isOrdered)*100/nOrderBy) - 66; |
| 114896 | | - rSortCost = nRowEst + estLog(nRowEst) + rScale; |
| 115389 | + rSortCost = nRowEst + estLog(nRowEst) + rScale + 16; |
| 115390 | + |
| 114897 | 115391 | /* TUNING: The cost of implementing DISTINCT using a B-TREE is |
| 114898 | | - ** also N*log(N) but it has a larger constant of proportionality. |
| 114899 | | - ** Multiply by 3.0. */ |
| 115392 | + ** similar but with a larger constant of proportionality. |
| 115393 | + ** Multiply by an additional factor of 3.0. */ |
| 114900 | 115394 | if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){ |
| 114901 | 115395 | rSortCost += 16; |
| 114902 | 115396 | } |
| 114903 | 115397 | WHERETRACE(0x002, |
| 114904 | 115398 | ("---- sort cost=%-3d (%d/%d) increases cost %3d to %-3d\n", |
| | @@ -115062,11 +115556,23 @@ |
| 115062 | 115556 | }else{ |
| 115063 | 115557 | pWInfo->nOBSat = pFrom->isOrdered; |
| 115064 | 115558 | if( pWInfo->nOBSat<0 ) pWInfo->nOBSat = 0; |
| 115065 | 115559 | pWInfo->revMask = pFrom->revLoop; |
| 115066 | 115560 | } |
| 115561 | + if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP) |
| 115562 | + && pWInfo->nOBSat==pWInfo->pOrderBy->nExpr |
| 115563 | + ){ |
| 115564 | + Bitmask notUsed = 0; |
| 115565 | + int nOrder = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, |
| 115566 | + pFrom, 0, nLoop-1, pFrom->aLoop[nLoop-1], ¬Used |
| 115567 | + ); |
| 115568 | + assert( pWInfo->sorted==0 ); |
| 115569 | + pWInfo->sorted = (nOrder==pWInfo->pOrderBy->nExpr); |
| 115570 | + } |
| 115067 | 115571 | } |
| 115572 | + |
| 115573 | + |
| 115068 | 115574 | pWInfo->nRowOut = pFrom->nRow; |
| 115069 | 115575 | |
| 115070 | 115576 | /* Free temporary memory and return success */ |
| 115071 | 115577 | sqlite3DbFree(db, pSpace); |
| 115072 | 115578 | return SQLITE_OK; |
| | @@ -115587,11 +116093,18 @@ |
| 115587 | 116093 | Index *pIx = pLoop->u.btree.pIndex; |
| 115588 | 116094 | int iIndexCur; |
| 115589 | 116095 | int op = OP_OpenRead; |
| 115590 | 116096 | /* iIdxCur is always set if to a positive value if ONEPASS is possible */ |
| 115591 | 116097 | assert( iIdxCur!=0 || (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 ); |
| 115592 | | - if( pWInfo->okOnePass ){ |
| 116098 | + if( !HasRowid(pTab) && IsPrimaryKeyIndex(pIx) |
| 116099 | + && (wctrlFlags & WHERE_ONETABLE_ONLY)!=0 |
| 116100 | + ){ |
| 116101 | + /* This is one term of an OR-optimization using the PRIMARY KEY of a |
| 116102 | + ** WITHOUT ROWID table. No need for a separate index */ |
| 116103 | + iIndexCur = pLevel->iTabCur; |
| 116104 | + op = 0; |
| 116105 | + }else if( pWInfo->okOnePass ){ |
| 115593 | 116106 | Index *pJ = pTabItem->pTab->pIndex; |
| 115594 | 116107 | iIndexCur = iIdxCur; |
| 115595 | 116108 | assert( wctrlFlags & WHERE_ONEPASS_DESIRED ); |
| 115596 | 116109 | while( ALWAYS(pJ) && pJ!=pIx ){ |
| 115597 | 116110 | iIndexCur++; |
| | @@ -115605,13 +116118,15 @@ |
| 115605 | 116118 | iIndexCur = pParse->nTab++; |
| 115606 | 116119 | } |
| 115607 | 116120 | pLevel->iIdxCur = iIndexCur; |
| 115608 | 116121 | assert( pIx->pSchema==pTab->pSchema ); |
| 115609 | 116122 | assert( iIndexCur>=0 ); |
| 115610 | | - sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb); |
| 115611 | | - sqlite3VdbeSetP4KeyInfo(pParse, pIx); |
| 115612 | | - VdbeComment((v, "%s", pIx->zName)); |
| 116123 | + if( op ){ |
| 116124 | + sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb); |
| 116125 | + sqlite3VdbeSetP4KeyInfo(pParse, pIx); |
| 116126 | + VdbeComment((v, "%s", pIx->zName)); |
| 116127 | + } |
| 115613 | 116128 | } |
| 115614 | 116129 | if( iDb>=0 ) sqlite3CodeVerifySchema(pParse, iDb); |
| 115615 | 116130 | notReady &= ~getMask(&pWInfo->sMaskSet, pTabItem->iCursor); |
| 115616 | 116131 | } |
| 115617 | 116132 | pWInfo->iTop = sqlite3VdbeCurrentAddr(v); |
| | @@ -123654,10 +124169,32 @@ |
| 123654 | 124169 | int sz = va_arg(ap, int); |
| 123655 | 124170 | int *aProg = va_arg(ap, int*); |
| 123656 | 124171 | rc = sqlite3BitvecBuiltinTest(sz, aProg); |
| 123657 | 124172 | break; |
| 123658 | 124173 | } |
| 124174 | + |
| 124175 | + /* |
| 124176 | + ** sqlite3_test_control(FAULT_INSTALL, xCallback) |
| 124177 | + ** |
| 124178 | + ** Arrange to invoke xCallback() whenever sqlite3FaultSim() is called, |
| 124179 | + ** if xCallback is not NULL. |
| 124180 | + ** |
| 124181 | + ** As a test of the fault simulator mechanism itself, sqlite3FaultSim(0) |
| 124182 | + ** is called immediately after installing the new callback and the return |
| 124183 | + ** value from sqlite3FaultSim(0) becomes the return from |
| 124184 | + ** sqlite3_test_control(). |
| 124185 | + */ |
| 124186 | + case SQLITE_TESTCTRL_FAULT_INSTALL: { |
| 124187 | + /* MSVC is picky about pulling func ptrs from va lists. |
| 124188 | + ** http://support.microsoft.com/kb/47961 |
| 124189 | + ** sqlite3Config.xTestCallback = va_arg(ap, int(*)(int)); |
| 124190 | + */ |
| 124191 | + typedef int(*TESTCALLBACKFUNC_t)(int); |
| 124192 | + sqlite3Config.xTestCallback = va_arg(ap, TESTCALLBACKFUNC_t); |
| 124193 | + rc = sqlite3FaultSim(0); |
| 124194 | + break; |
| 124195 | + } |
| 123659 | 124196 | |
| 123660 | 124197 | /* |
| 123661 | 124198 | ** sqlite3_test_control(BENIGN_MALLOC_HOOKS, xBegin, xEnd) |
| 123662 | 124199 | ** |
| 123663 | 124200 | ** Register hooks to call to indicate which malloc() failures |
| | @@ -123964,11 +124501,11 @@ |
| 123964 | 124501 | ** Return 1 if database is read-only or 0 if read/write. Return -1 if |
| 123965 | 124502 | ** no such database exists. |
| 123966 | 124503 | */ |
| 123967 | 124504 | SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){ |
| 123968 | 124505 | Btree *pBt = sqlite3DbNameToBtree(db, zDbName); |
| 123969 | | - return pBt ? sqlite3PagerIsreadonly(sqlite3BtreePager(pBt)) : -1; |
| 124506 | + return pBt ? sqlite3BtreeIsReadonly(pBt) : -1; |
| 123970 | 124507 | } |
| 123971 | 124508 | |
| 123972 | 124509 | /************** End of main.c ************************************************/ |
| 123973 | 124510 | /************** Begin file notify.c ******************************************/ |
| 123974 | 124511 | /* |
| | @@ -125084,17 +125621,17 @@ |
| 125084 | 125621 | char **azColumn; /* column names. malloced */ |
| 125085 | 125622 | u8 *abNotindexed; /* True for 'notindexed' columns */ |
| 125086 | 125623 | sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */ |
| 125087 | 125624 | char *zContentTbl; /* content=xxx option, or NULL */ |
| 125088 | 125625 | char *zLanguageid; /* languageid=xxx option, or NULL */ |
| 125089 | | - u8 bAutoincrmerge; /* True if automerge=1 */ |
| 125626 | + int nAutoincrmerge; /* Value configured by 'automerge' */ |
| 125090 | 125627 | u32 nLeafAdd; /* Number of leaf blocks added this trans */ |
| 125091 | 125628 | |
| 125092 | 125629 | /* Precompiled statements used by the implementation. Each of these |
| 125093 | 125630 | ** statements is run and reset within a single virtual table API call. |
| 125094 | 125631 | */ |
| 125095 | | - sqlite3_stmt *aStmt[37]; |
| 125632 | + sqlite3_stmt *aStmt[40]; |
| 125096 | 125633 | |
| 125097 | 125634 | char *zReadExprlist; |
| 125098 | 125635 | char *zWriteExprlist; |
| 125099 | 125636 | |
| 125100 | 125637 | int nNodeSize; /* Soft limit for node size */ |
| | @@ -126512,11 +127049,11 @@ |
| 126512 | 127049 | p->nMaxPendingData = FTS3_MAX_PENDING_DATA; |
| 126513 | 127050 | p->bHasDocsize = (isFts4 && bNoDocsize==0); |
| 126514 | 127051 | p->bHasStat = isFts4; |
| 126515 | 127052 | p->bFts4 = isFts4; |
| 126516 | 127053 | p->bDescIdx = bDescIdx; |
| 126517 | | - p->bAutoincrmerge = 0xff; /* 0xff means setting unknown */ |
| 127054 | + p->nAutoincrmerge = 0xff; /* 0xff means setting unknown */ |
| 126518 | 127055 | p->zContentTbl = zContent; |
| 126519 | 127056 | p->zLanguageid = zLanguageid; |
| 126520 | 127057 | zContent = 0; |
| 126521 | 127058 | zLanguageid = 0; |
| 126522 | 127059 | TESTONLY( p->inTransaction = -1 ); |
| | @@ -126555,11 +127092,13 @@ |
| 126555 | 127092 | /* Fill in the abNotindexed array */ |
| 126556 | 127093 | for(iCol=0; iCol<nCol; iCol++){ |
| 126557 | 127094 | int n = (int)strlen(p->azColumn[iCol]); |
| 126558 | 127095 | for(i=0; i<nNotindexed; i++){ |
| 126559 | 127096 | char *zNot = azNotindexed[i]; |
| 126560 | | - if( zNot && 0==sqlite3_strnicmp(p->azColumn[iCol], zNot, n) ){ |
| 127097 | + if( zNot && n==(int)strlen(zNot) |
| 127098 | + && 0==sqlite3_strnicmp(p->azColumn[iCol], zNot, n) |
| 127099 | + ){ |
| 126561 | 127100 | p->abNotindexed[iCol] = 1; |
| 126562 | 127101 | sqlite3_free(zNot); |
| 126563 | 127102 | azNotindexed[i] = 0; |
| 126564 | 127103 | } |
| 126565 | 127104 | } |
| | @@ -128481,19 +129020,22 @@ |
| 128481 | 129020 | const u32 nMinMerge = 64; /* Minimum amount of incr-merge work to do */ |
| 128482 | 129021 | |
| 128483 | 129022 | Fts3Table *p = (Fts3Table*)pVtab; |
| 128484 | 129023 | int rc = sqlite3Fts3PendingTermsFlush(p); |
| 128485 | 129024 | |
| 128486 | | - if( rc==SQLITE_OK && p->bAutoincrmerge==1 && p->nLeafAdd>(nMinMerge/16) ){ |
| 129025 | + if( rc==SQLITE_OK |
| 129026 | + && p->nLeafAdd>(nMinMerge/16) |
| 129027 | + && p->nAutoincrmerge && p->nAutoincrmerge!=0xff |
| 129028 | + ){ |
| 128487 | 129029 | int mxLevel = 0; /* Maximum relative level value in db */ |
| 128488 | 129030 | int A; /* Incr-merge parameter A */ |
| 128489 | 129031 | |
| 128490 | 129032 | rc = sqlite3Fts3MaxLevel(p, &mxLevel); |
| 128491 | 129033 | assert( rc==SQLITE_OK || mxLevel==0 ); |
| 128492 | 129034 | A = p->nLeafAdd * mxLevel; |
| 128493 | 129035 | A += (A/2); |
| 128494 | | - if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, 8); |
| 129036 | + if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, p->nAutoincrmerge); |
| 128495 | 129037 | } |
| 128496 | 129038 | sqlite3Fts3SegmentsClose(p); |
| 128497 | 129039 | return rc; |
| 128498 | 129040 | } |
| 128499 | 129041 | |
| | @@ -131712,44 +132254,27 @@ |
| 131712 | 132254 | sqlite3_tokenizer *pTokenizer = pParse->pTokenizer; |
| 131713 | 132255 | sqlite3_tokenizer_module const *pModule = pTokenizer->pModule; |
| 131714 | 132256 | int rc; |
| 131715 | 132257 | sqlite3_tokenizer_cursor *pCursor; |
| 131716 | 132258 | Fts3Expr *pRet = 0; |
| 131717 | | - int nConsumed = 0; |
| 132259 | + int i = 0; |
| 131718 | 132260 | |
| 131719 | | - rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor); |
| 132261 | + /* Set variable i to the maximum number of bytes of input to tokenize. */ |
| 132262 | + for(i=0; i<n; i++){ |
| 132263 | + if( sqlite3_fts3_enable_parentheses && (z[i]=='(' || z[i]==')') ) break; |
| 132264 | + if( z[i]=='*' || z[i]=='"' ) break; |
| 132265 | + } |
| 132266 | + |
| 132267 | + *pnConsumed = i; |
| 132268 | + rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, i, &pCursor); |
| 131720 | 132269 | if( rc==SQLITE_OK ){ |
| 131721 | 132270 | const char *zToken; |
| 131722 | 132271 | int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0; |
| 131723 | 132272 | int nByte; /* total space to allocate */ |
| 131724 | 132273 | |
| 131725 | 132274 | rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition); |
| 131726 | | - |
| 131727 | | - if( (rc==SQLITE_OK || rc==SQLITE_DONE) && sqlite3_fts3_enable_parentheses ){ |
| 131728 | | - int i; |
| 131729 | | - if( rc==SQLITE_DONE ) iStart = n; |
| 131730 | | - for(i=0; i<iStart; i++){ |
| 131731 | | - if( z[i]=='(' ){ |
| 131732 | | - pParse->nNest++; |
| 131733 | | - rc = fts3ExprParse(pParse, &z[i+1], n-i-1, &pRet, &nConsumed); |
| 131734 | | - if( rc==SQLITE_OK && !pRet ){ |
| 131735 | | - rc = SQLITE_DONE; |
| 131736 | | - } |
| 131737 | | - nConsumed = (int)(i + 1 + nConsumed); |
| 131738 | | - break; |
| 131739 | | - } |
| 131740 | | - |
| 131741 | | - if( z[i]==')' ){ |
| 131742 | | - rc = SQLITE_DONE; |
| 131743 | | - pParse->nNest--; |
| 131744 | | - nConsumed = i+1; |
| 131745 | | - break; |
| 131746 | | - } |
| 131747 | | - } |
| 131748 | | - } |
| 131749 | | - |
| 131750 | | - if( nConsumed==0 && rc==SQLITE_OK ){ |
| 132275 | + if( rc==SQLITE_OK ){ |
| 131751 | 132276 | nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken; |
| 131752 | 132277 | pRet = (Fts3Expr *)fts3MallocZero(nByte); |
| 131753 | 132278 | if( !pRet ){ |
| 131754 | 132279 | rc = SQLITE_NOMEM; |
| 131755 | 132280 | }else{ |
| | @@ -131779,17 +132304,18 @@ |
| 131779 | 132304 | break; |
| 131780 | 132305 | } |
| 131781 | 132306 | } |
| 131782 | 132307 | |
| 131783 | 132308 | } |
| 131784 | | - nConsumed = iEnd; |
| 132309 | + *pnConsumed = iEnd; |
| 132310 | + }else if( i && rc==SQLITE_DONE ){ |
| 132311 | + rc = SQLITE_OK; |
| 131785 | 132312 | } |
| 131786 | 132313 | |
| 131787 | 132314 | pModule->xClose(pCursor); |
| 131788 | 132315 | } |
| 131789 | 132316 | |
| 131790 | | - *pnConsumed = nConsumed; |
| 131791 | 132317 | *ppExpr = pRet; |
| 131792 | 132318 | return rc; |
| 131793 | 132319 | } |
| 131794 | 132320 | |
| 131795 | 132321 | |
| | @@ -132035,10 +132561,25 @@ |
| 132035 | 132561 | return SQLITE_ERROR; |
| 132036 | 132562 | } |
| 132037 | 132563 | return getNextString(pParse, &zInput[1], ii-1, ppExpr); |
| 132038 | 132564 | } |
| 132039 | 132565 | |
| 132566 | + if( sqlite3_fts3_enable_parentheses ){ |
| 132567 | + if( *zInput=='(' ){ |
| 132568 | + int nConsumed = 0; |
| 132569 | + pParse->nNest++; |
| 132570 | + rc = fts3ExprParse(pParse, zInput+1, nInput-1, ppExpr, &nConsumed); |
| 132571 | + if( rc==SQLITE_OK && !*ppExpr ){ rc = SQLITE_DONE; } |
| 132572 | + *pnConsumed = (int)(zInput - z) + 1 + nConsumed; |
| 132573 | + return rc; |
| 132574 | + }else if( *zInput==')' ){ |
| 132575 | + pParse->nNest--; |
| 132576 | + *pnConsumed = (int)((zInput - z) + 1); |
| 132577 | + *ppExpr = 0; |
| 132578 | + return SQLITE_DONE; |
| 132579 | + } |
| 132580 | + } |
| 132040 | 132581 | |
| 132041 | 132582 | /* If control flows to this point, this must be a regular token, or |
| 132042 | 132583 | ** the end of the input. Read a regular token using the sqlite3_tokenizer |
| 132043 | 132584 | ** interface. Before doing so, figure out if there is an explicit |
| 132044 | 132585 | ** column specifier for the token. |
| | @@ -132153,100 +132694,104 @@ |
| 132153 | 132694 | int isRequirePhrase = 1; |
| 132154 | 132695 | |
| 132155 | 132696 | while( rc==SQLITE_OK ){ |
| 132156 | 132697 | Fts3Expr *p = 0; |
| 132157 | 132698 | int nByte = 0; |
| 132158 | | - rc = getNextNode(pParse, zIn, nIn, &p, &nByte); |
| 132159 | | - if( rc==SQLITE_OK ){ |
| 132160 | | - int isPhrase; |
| 132161 | | - |
| 132162 | | - if( !sqlite3_fts3_enable_parentheses |
| 132163 | | - && p->eType==FTSQUERY_PHRASE && pParse->isNot |
| 132164 | | - ){ |
| 132165 | | - /* Create an implicit NOT operator. */ |
| 132166 | | - Fts3Expr *pNot = fts3MallocZero(sizeof(Fts3Expr)); |
| 132167 | | - if( !pNot ){ |
| 132168 | | - sqlite3Fts3ExprFree(p); |
| 132169 | | - rc = SQLITE_NOMEM; |
| 132170 | | - goto exprparse_out; |
| 132171 | | - } |
| 132172 | | - pNot->eType = FTSQUERY_NOT; |
| 132173 | | - pNot->pRight = p; |
| 132174 | | - p->pParent = pNot; |
| 132175 | | - if( pNotBranch ){ |
| 132176 | | - pNot->pLeft = pNotBranch; |
| 132177 | | - pNotBranch->pParent = pNot; |
| 132178 | | - } |
| 132179 | | - pNotBranch = pNot; |
| 132180 | | - p = pPrev; |
| 132181 | | - }else{ |
| 132182 | | - int eType = p->eType; |
| 132183 | | - isPhrase = (eType==FTSQUERY_PHRASE || p->pLeft); |
| 132184 | | - |
| 132185 | | - /* The isRequirePhrase variable is set to true if a phrase or |
| 132186 | | - ** an expression contained in parenthesis is required. If a |
| 132187 | | - ** binary operator (AND, OR, NOT or NEAR) is encounted when |
| 132188 | | - ** isRequirePhrase is set, this is a syntax error. |
| 132189 | | - */ |
| 132190 | | - if( !isPhrase && isRequirePhrase ){ |
| 132191 | | - sqlite3Fts3ExprFree(p); |
| 132192 | | - rc = SQLITE_ERROR; |
| 132193 | | - goto exprparse_out; |
| 132194 | | - } |
| 132195 | | - |
| 132196 | | - if( isPhrase && !isRequirePhrase ){ |
| 132197 | | - /* Insert an implicit AND operator. */ |
| 132198 | | - Fts3Expr *pAnd; |
| 132199 | | - assert( pRet && pPrev ); |
| 132200 | | - pAnd = fts3MallocZero(sizeof(Fts3Expr)); |
| 132201 | | - if( !pAnd ){ |
| 132202 | | - sqlite3Fts3ExprFree(p); |
| 132203 | | - rc = SQLITE_NOMEM; |
| 132204 | | - goto exprparse_out; |
| 132205 | | - } |
| 132206 | | - pAnd->eType = FTSQUERY_AND; |
| 132207 | | - insertBinaryOperator(&pRet, pPrev, pAnd); |
| 132208 | | - pPrev = pAnd; |
| 132209 | | - } |
| 132210 | | - |
| 132211 | | - /* This test catches attempts to make either operand of a NEAR |
| 132212 | | - ** operator something other than a phrase. For example, either of |
| 132213 | | - ** the following: |
| 132214 | | - ** |
| 132215 | | - ** (bracketed expression) NEAR phrase |
| 132216 | | - ** phrase NEAR (bracketed expression) |
| 132217 | | - ** |
| 132218 | | - ** Return an error in either case. |
| 132219 | | - */ |
| 132220 | | - if( pPrev && ( |
| 132221 | | - (eType==FTSQUERY_NEAR && !isPhrase && pPrev->eType!=FTSQUERY_PHRASE) |
| 132222 | | - || (eType!=FTSQUERY_PHRASE && isPhrase && pPrev->eType==FTSQUERY_NEAR) |
| 132223 | | - )){ |
| 132224 | | - sqlite3Fts3ExprFree(p); |
| 132225 | | - rc = SQLITE_ERROR; |
| 132226 | | - goto exprparse_out; |
| 132227 | | - } |
| 132228 | | - |
| 132229 | | - if( isPhrase ){ |
| 132230 | | - if( pRet ){ |
| 132231 | | - assert( pPrev && pPrev->pLeft && pPrev->pRight==0 ); |
| 132232 | | - pPrev->pRight = p; |
| 132233 | | - p->pParent = pPrev; |
| 132234 | | - }else{ |
| 132235 | | - pRet = p; |
| 132236 | | - } |
| 132237 | | - }else{ |
| 132238 | | - insertBinaryOperator(&pRet, pPrev, p); |
| 132239 | | - } |
| 132240 | | - isRequirePhrase = !isPhrase; |
| 132699 | + |
| 132700 | + rc = getNextNode(pParse, zIn, nIn, &p, &nByte); |
| 132701 | + assert( nByte>0 || (rc!=SQLITE_OK && p==0) ); |
| 132702 | + if( rc==SQLITE_OK ){ |
| 132703 | + if( p ){ |
| 132704 | + int isPhrase; |
| 132705 | + |
| 132706 | + if( !sqlite3_fts3_enable_parentheses |
| 132707 | + && p->eType==FTSQUERY_PHRASE && pParse->isNot |
| 132708 | + ){ |
| 132709 | + /* Create an implicit NOT operator. */ |
| 132710 | + Fts3Expr *pNot = fts3MallocZero(sizeof(Fts3Expr)); |
| 132711 | + if( !pNot ){ |
| 132712 | + sqlite3Fts3ExprFree(p); |
| 132713 | + rc = SQLITE_NOMEM; |
| 132714 | + goto exprparse_out; |
| 132715 | + } |
| 132716 | + pNot->eType = FTSQUERY_NOT; |
| 132717 | + pNot->pRight = p; |
| 132718 | + p->pParent = pNot; |
| 132719 | + if( pNotBranch ){ |
| 132720 | + pNot->pLeft = pNotBranch; |
| 132721 | + pNotBranch->pParent = pNot; |
| 132722 | + } |
| 132723 | + pNotBranch = pNot; |
| 132724 | + p = pPrev; |
| 132725 | + }else{ |
| 132726 | + int eType = p->eType; |
| 132727 | + isPhrase = (eType==FTSQUERY_PHRASE || p->pLeft); |
| 132728 | + |
| 132729 | + /* The isRequirePhrase variable is set to true if a phrase or |
| 132730 | + ** an expression contained in parenthesis is required. If a |
| 132731 | + ** binary operator (AND, OR, NOT or NEAR) is encounted when |
| 132732 | + ** isRequirePhrase is set, this is a syntax error. |
| 132733 | + */ |
| 132734 | + if( !isPhrase && isRequirePhrase ){ |
| 132735 | + sqlite3Fts3ExprFree(p); |
| 132736 | + rc = SQLITE_ERROR; |
| 132737 | + goto exprparse_out; |
| 132738 | + } |
| 132739 | + |
| 132740 | + if( isPhrase && !isRequirePhrase ){ |
| 132741 | + /* Insert an implicit AND operator. */ |
| 132742 | + Fts3Expr *pAnd; |
| 132743 | + assert( pRet && pPrev ); |
| 132744 | + pAnd = fts3MallocZero(sizeof(Fts3Expr)); |
| 132745 | + if( !pAnd ){ |
| 132746 | + sqlite3Fts3ExprFree(p); |
| 132747 | + rc = SQLITE_NOMEM; |
| 132748 | + goto exprparse_out; |
| 132749 | + } |
| 132750 | + pAnd->eType = FTSQUERY_AND; |
| 132751 | + insertBinaryOperator(&pRet, pPrev, pAnd); |
| 132752 | + pPrev = pAnd; |
| 132753 | + } |
| 132754 | + |
| 132755 | + /* This test catches attempts to make either operand of a NEAR |
| 132756 | + ** operator something other than a phrase. For example, either of |
| 132757 | + ** the following: |
| 132758 | + ** |
| 132759 | + ** (bracketed expression) NEAR phrase |
| 132760 | + ** phrase NEAR (bracketed expression) |
| 132761 | + ** |
| 132762 | + ** Return an error in either case. |
| 132763 | + */ |
| 132764 | + if( pPrev && ( |
| 132765 | + (eType==FTSQUERY_NEAR && !isPhrase && pPrev->eType!=FTSQUERY_PHRASE) |
| 132766 | + || (eType!=FTSQUERY_PHRASE && isPhrase && pPrev->eType==FTSQUERY_NEAR) |
| 132767 | + )){ |
| 132768 | + sqlite3Fts3ExprFree(p); |
| 132769 | + rc = SQLITE_ERROR; |
| 132770 | + goto exprparse_out; |
| 132771 | + } |
| 132772 | + |
| 132773 | + if( isPhrase ){ |
| 132774 | + if( pRet ){ |
| 132775 | + assert( pPrev && pPrev->pLeft && pPrev->pRight==0 ); |
| 132776 | + pPrev->pRight = p; |
| 132777 | + p->pParent = pPrev; |
| 132778 | + }else{ |
| 132779 | + pRet = p; |
| 132780 | + } |
| 132781 | + }else{ |
| 132782 | + insertBinaryOperator(&pRet, pPrev, p); |
| 132783 | + } |
| 132784 | + isRequirePhrase = !isPhrase; |
| 132785 | + } |
| 132786 | + pPrev = p; |
| 132241 | 132787 | } |
| 132242 | 132788 | assert( nByte>0 ); |
| 132243 | 132789 | } |
| 132244 | 132790 | assert( rc!=SQLITE_OK || (nByte>0 && nByte<=nIn) ); |
| 132245 | 132791 | nIn -= nByte; |
| 132246 | 132792 | zIn += nByte; |
| 132247 | | - pPrev = p; |
| 132248 | 132793 | } |
| 132249 | 132794 | |
| 132250 | 132795 | if( rc==SQLITE_DONE && pRet && isRequirePhrase ){ |
| 132251 | 132796 | rc = SQLITE_ERROR; |
| 132252 | 132797 | } |
| | @@ -135230,10 +135775,11 @@ |
| 135230 | 135775 | int nMalloc; /* Size of malloc'd buffer at zMalloc */ |
| 135231 | 135776 | char *zMalloc; /* Malloc'd space (possibly) used for zTerm */ |
| 135232 | 135777 | int nSize; /* Size of allocation at aData */ |
| 135233 | 135778 | int nData; /* Bytes of data in aData */ |
| 135234 | 135779 | char *aData; /* Pointer to block from malloc() */ |
| 135780 | + i64 nLeafData; /* Number of bytes of leaf data written */ |
| 135235 | 135781 | }; |
| 135236 | 135782 | |
| 135237 | 135783 | /* |
| 135238 | 135784 | ** Type SegmentNode is used by the following three functions to create |
| 135239 | 135785 | ** the interior part of the segment b+-tree structures (everything except |
| | @@ -135304,10 +135850,14 @@ |
| 135304 | 135850 | #define SQL_SELECT_SEGDIR 32 |
| 135305 | 135851 | #define SQL_CHOMP_SEGDIR 33 |
| 135306 | 135852 | #define SQL_SEGMENT_IS_APPENDABLE 34 |
| 135307 | 135853 | #define SQL_SELECT_INDEXES 35 |
| 135308 | 135854 | #define SQL_SELECT_MXLEVEL 36 |
| 135855 | + |
| 135856 | +#define SQL_SELECT_LEVEL_RANGE2 37 |
| 135857 | +#define SQL_UPDATE_LEVEL_IDX 38 |
| 135858 | +#define SQL_UPDATE_LEVEL 39 |
| 135309 | 135859 | |
| 135310 | 135860 | /* |
| 135311 | 135861 | ** This function is used to obtain an SQLite prepared statement handle |
| 135312 | 135862 | ** for the statement identified by the second argument. If successful, |
| 135313 | 135863 | ** *pp is set to the requested statement handle and SQLITE_OK returned. |
| | @@ -135406,11 +135956,22 @@ |
| 135406 | 135956 | ** Return the list of valid segment indexes for absolute level ? */ |
| 135407 | 135957 | /* 35 */ "SELECT idx FROM %Q.'%q_segdir' WHERE level=? ORDER BY 1 ASC", |
| 135408 | 135958 | |
| 135409 | 135959 | /* SQL_SELECT_MXLEVEL |
| 135410 | 135960 | ** Return the largest relative level in the FTS index or indexes. */ |
| 135411 | | -/* 36 */ "SELECT max( level %% 1024 ) FROM %Q.'%q_segdir'" |
| 135961 | +/* 36 */ "SELECT max( level %% 1024 ) FROM %Q.'%q_segdir'", |
| 135962 | + |
| 135963 | + /* Return segments in order from oldest to newest.*/ |
| 135964 | +/* 37 */ "SELECT level, idx, end_block " |
| 135965 | + "FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ? " |
| 135966 | + "ORDER BY level DESC, idx ASC", |
| 135967 | + |
| 135968 | + /* Update statements used while promoting segments */ |
| 135969 | +/* 38 */ "UPDATE OR FAIL %Q.'%q_segdir' SET level=-1,idx=? " |
| 135970 | + "WHERE level=? AND idx=?", |
| 135971 | +/* 39 */ "UPDATE OR FAIL %Q.'%q_segdir' SET level=? WHERE level=-1" |
| 135972 | + |
| 135412 | 135973 | }; |
| 135413 | 135974 | int rc = SQLITE_OK; |
| 135414 | 135975 | sqlite3_stmt *pStmt; |
| 135415 | 135976 | |
| 135416 | 135977 | assert( SizeofArray(azSql)==SizeofArray(p->aStmt) ); |
| | @@ -136947,10 +137508,11 @@ |
| 136947 | 137508 | sqlite3_int64 iLevel, /* Value for "level" field (absolute level) */ |
| 136948 | 137509 | int iIdx, /* Value for "idx" field */ |
| 136949 | 137510 | sqlite3_int64 iStartBlock, /* Value for "start_block" field */ |
| 136950 | 137511 | sqlite3_int64 iLeafEndBlock, /* Value for "leaves_end_block" field */ |
| 136951 | 137512 | sqlite3_int64 iEndBlock, /* Value for "end_block" field */ |
| 137513 | + sqlite3_int64 nLeafData, /* Bytes of leaf data in segment */ |
| 136952 | 137514 | char *zRoot, /* Blob value for "root" field */ |
| 136953 | 137515 | int nRoot /* Number of bytes in buffer zRoot */ |
| 136954 | 137516 | ){ |
| 136955 | 137517 | sqlite3_stmt *pStmt; |
| 136956 | 137518 | int rc = fts3SqlStmt(p, SQL_INSERT_SEGDIR, &pStmt, 0); |
| | @@ -136957,11 +137519,17 @@ |
| 136957 | 137519 | if( rc==SQLITE_OK ){ |
| 136958 | 137520 | sqlite3_bind_int64(pStmt, 1, iLevel); |
| 136959 | 137521 | sqlite3_bind_int(pStmt, 2, iIdx); |
| 136960 | 137522 | sqlite3_bind_int64(pStmt, 3, iStartBlock); |
| 136961 | 137523 | sqlite3_bind_int64(pStmt, 4, iLeafEndBlock); |
| 136962 | | - sqlite3_bind_int64(pStmt, 5, iEndBlock); |
| 137524 | + if( nLeafData==0 ){ |
| 137525 | + sqlite3_bind_int64(pStmt, 5, iEndBlock); |
| 137526 | + }else{ |
| 137527 | + char *zEnd = sqlite3_mprintf("%lld %lld", iEndBlock, nLeafData); |
| 137528 | + if( !zEnd ) return SQLITE_NOMEM; |
| 137529 | + sqlite3_bind_text(pStmt, 5, zEnd, -1, sqlite3_free); |
| 137530 | + } |
| 136963 | 137531 | sqlite3_bind_blob(pStmt, 6, zRoot, nRoot, SQLITE_STATIC); |
| 136964 | 137532 | sqlite3_step(pStmt); |
| 136965 | 137533 | rc = sqlite3_reset(pStmt); |
| 136966 | 137534 | } |
| 136967 | 137535 | return rc; |
| | @@ -137282,10 +137850,13 @@ |
| 137282 | 137850 | sqlite3Fts3VarintLen(nTerm) + /* varint containing suffix size */ |
| 137283 | 137851 | nTerm + /* Term suffix */ |
| 137284 | 137852 | sqlite3Fts3VarintLen(nDoclist) + /* Size of doclist */ |
| 137285 | 137853 | nDoclist; /* Doclist data */ |
| 137286 | 137854 | } |
| 137855 | + |
| 137856 | + /* Increase the total number of bytes written to account for the new entry. */ |
| 137857 | + pWriter->nLeafData += nReq; |
| 137287 | 137858 | |
| 137288 | 137859 | /* If the buffer currently allocated is too small for this entry, realloc |
| 137289 | 137860 | ** the buffer to make it large enough. |
| 137290 | 137861 | */ |
| 137291 | 137862 | if( nReq>pWriter->nSize ){ |
| | @@ -137354,17 +137925,17 @@ |
| 137354 | 137925 | if( rc==SQLITE_OK ){ |
| 137355 | 137926 | rc = fts3NodeWrite(p, pWriter->pTree, 1, |
| 137356 | 137927 | pWriter->iFirst, pWriter->iFree, &iLast, &zRoot, &nRoot); |
| 137357 | 137928 | } |
| 137358 | 137929 | if( rc==SQLITE_OK ){ |
| 137359 | | - rc = fts3WriteSegdir( |
| 137360 | | - p, iLevel, iIdx, pWriter->iFirst, iLastLeaf, iLast, zRoot, nRoot); |
| 137930 | + rc = fts3WriteSegdir(p, iLevel, iIdx, |
| 137931 | + pWriter->iFirst, iLastLeaf, iLast, pWriter->nLeafData, zRoot, nRoot); |
| 137361 | 137932 | } |
| 137362 | 137933 | }else{ |
| 137363 | 137934 | /* The entire tree fits on the root node. Write it to the segdir table. */ |
| 137364 | | - rc = fts3WriteSegdir( |
| 137365 | | - p, iLevel, iIdx, 0, 0, 0, pWriter->aData, pWriter->nData); |
| 137935 | + rc = fts3WriteSegdir(p, iLevel, iIdx, |
| 137936 | + 0, 0, 0, pWriter->nLeafData, pWriter->aData, pWriter->nData); |
| 137366 | 137937 | } |
| 137367 | 137938 | p->nLeafAdd++; |
| 137368 | 137939 | return rc; |
| 137369 | 137940 | } |
| 137370 | 137941 | |
| | @@ -137443,10 +138014,41 @@ |
| 137443 | 138014 | if( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 137444 | 138015 | *pnMax = sqlite3_column_int64(pStmt, 0); |
| 137445 | 138016 | } |
| 137446 | 138017 | return sqlite3_reset(pStmt); |
| 137447 | 138018 | } |
| 138019 | + |
| 138020 | +/* |
| 138021 | +** iAbsLevel is an absolute level that may be assumed to exist within |
| 138022 | +** the database. This function checks if it is the largest level number |
| 138023 | +** within its index. Assuming no error occurs, *pbMax is set to 1 if |
| 138024 | +** iAbsLevel is indeed the largest level, or 0 otherwise, and SQLITE_OK |
| 138025 | +** is returned. If an error occurs, an error code is returned and the |
| 138026 | +** final value of *pbMax is undefined. |
| 138027 | +*/ |
| 138028 | +static int fts3SegmentIsMaxLevel(Fts3Table *p, i64 iAbsLevel, int *pbMax){ |
| 138029 | + |
| 138030 | + /* Set pStmt to the compiled version of: |
| 138031 | + ** |
| 138032 | + ** SELECT max(level) FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ? |
| 138033 | + ** |
| 138034 | + ** (1024 is actually the value of macro FTS3_SEGDIR_PREFIXLEVEL_STR). |
| 138035 | + */ |
| 138036 | + sqlite3_stmt *pStmt; |
| 138037 | + int rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0); |
| 138038 | + if( rc!=SQLITE_OK ) return rc; |
| 138039 | + sqlite3_bind_int64(pStmt, 1, iAbsLevel+1); |
| 138040 | + sqlite3_bind_int64(pStmt, 2, |
| 138041 | + ((iAbsLevel/FTS3_SEGDIR_MAXLEVEL)+1) * FTS3_SEGDIR_MAXLEVEL |
| 138042 | + ); |
| 138043 | + |
| 138044 | + *pbMax = 0; |
| 138045 | + if( SQLITE_ROW==sqlite3_step(pStmt) ){ |
| 138046 | + *pbMax = sqlite3_column_type(pStmt, 0)==SQLITE_NULL; |
| 138047 | + } |
| 138048 | + return sqlite3_reset(pStmt); |
| 138049 | +} |
| 137448 | 138050 | |
| 137449 | 138051 | /* |
| 137450 | 138052 | ** Delete all entries in the %_segments table associated with the segment |
| 137451 | 138053 | ** opened with seg-reader pSeg. This function does not affect the contents |
| 137452 | 138054 | ** of the %_segdir table. |
| | @@ -137978,10 +138580,144 @@ |
| 137978 | 138580 | pCsr->nSegment = 0; |
| 137979 | 138581 | pCsr->apSegment = 0; |
| 137980 | 138582 | pCsr->aBuffer = 0; |
| 137981 | 138583 | } |
| 137982 | 138584 | } |
| 138585 | + |
| 138586 | +/* |
| 138587 | +** Decode the "end_block" field, selected by column iCol of the SELECT |
| 138588 | +** statement passed as the first argument. |
| 138589 | +** |
| 138590 | +** The "end_block" field may contain either an integer, or a text field |
| 138591 | +** containing the text representation of two non-negative integers separated |
| 138592 | +** by one or more space (0x20) characters. In the first case, set *piEndBlock |
| 138593 | +** to the integer value and *pnByte to zero before returning. In the second, |
| 138594 | +** set *piEndBlock to the first value and *pnByte to the second. |
| 138595 | +*/ |
| 138596 | +static void fts3ReadEndBlockField( |
| 138597 | + sqlite3_stmt *pStmt, |
| 138598 | + int iCol, |
| 138599 | + i64 *piEndBlock, |
| 138600 | + i64 *pnByte |
| 138601 | +){ |
| 138602 | + const unsigned char *zText = sqlite3_column_text(pStmt, iCol); |
| 138603 | + if( zText ){ |
| 138604 | + int i; |
| 138605 | + int iMul = 1; |
| 138606 | + i64 iVal = 0; |
| 138607 | + for(i=0; zText[i]>='0' && zText[i]<='9'; i++){ |
| 138608 | + iVal = iVal*10 + (zText[i] - '0'); |
| 138609 | + } |
| 138610 | + *piEndBlock = iVal; |
| 138611 | + while( zText[i]==' ' ) i++; |
| 138612 | + iVal = 0; |
| 138613 | + if( zText[i]=='-' ){ |
| 138614 | + i++; |
| 138615 | + iMul = -1; |
| 138616 | + } |
| 138617 | + for(/* no-op */; zText[i]>='0' && zText[i]<='9'; i++){ |
| 138618 | + iVal = iVal*10 + (zText[i] - '0'); |
| 138619 | + } |
| 138620 | + *pnByte = (iVal * (i64)iMul); |
| 138621 | + } |
| 138622 | +} |
| 138623 | + |
| 138624 | + |
| 138625 | +/* |
| 138626 | +** A segment of size nByte bytes has just been written to absolute level |
| 138627 | +** iAbsLevel. Promote any segments that should be promoted as a result. |
| 138628 | +*/ |
| 138629 | +static int fts3PromoteSegments( |
| 138630 | + Fts3Table *p, /* FTS table handle */ |
| 138631 | + sqlite3_int64 iAbsLevel, /* Absolute level just updated */ |
| 138632 | + sqlite3_int64 nByte /* Size of new segment at iAbsLevel */ |
| 138633 | +){ |
| 138634 | + int rc = SQLITE_OK; |
| 138635 | + sqlite3_stmt *pRange; |
| 138636 | + |
| 138637 | + rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE2, &pRange, 0); |
| 138638 | + |
| 138639 | + if( rc==SQLITE_OK ){ |
| 138640 | + int bOk = 0; |
| 138641 | + i64 iLast = (iAbsLevel/FTS3_SEGDIR_MAXLEVEL + 1) * FTS3_SEGDIR_MAXLEVEL - 1; |
| 138642 | + i64 nLimit = (nByte*3)/2; |
| 138643 | + |
| 138644 | + /* Loop through all entries in the %_segdir table corresponding to |
| 138645 | + ** segments in this index on levels greater than iAbsLevel. If there is |
| 138646 | + ** at least one such segment, and it is possible to determine that all |
| 138647 | + ** such segments are smaller than nLimit bytes in size, they will be |
| 138648 | + ** promoted to level iAbsLevel. */ |
| 138649 | + sqlite3_bind_int64(pRange, 1, iAbsLevel+1); |
| 138650 | + sqlite3_bind_int64(pRange, 2, iLast); |
| 138651 | + while( SQLITE_ROW==sqlite3_step(pRange) ){ |
| 138652 | + i64 nSize = 0, dummy; |
| 138653 | + fts3ReadEndBlockField(pRange, 2, &dummy, &nSize); |
| 138654 | + if( nSize<=0 || nSize>nLimit ){ |
| 138655 | + /* If nSize==0, then the %_segdir.end_block field does not not |
| 138656 | + ** contain a size value. This happens if it was written by an |
| 138657 | + ** old version of FTS. In this case it is not possible to determine |
| 138658 | + ** the size of the segment, and so segment promotion does not |
| 138659 | + ** take place. */ |
| 138660 | + bOk = 0; |
| 138661 | + break; |
| 138662 | + } |
| 138663 | + bOk = 1; |
| 138664 | + } |
| 138665 | + rc = sqlite3_reset(pRange); |
| 138666 | + |
| 138667 | + if( bOk ){ |
| 138668 | + int iIdx = 0; |
| 138669 | + sqlite3_stmt *pUpdate1; |
| 138670 | + sqlite3_stmt *pUpdate2; |
| 138671 | + |
| 138672 | + if( rc==SQLITE_OK ){ |
| 138673 | + rc = fts3SqlStmt(p, SQL_UPDATE_LEVEL_IDX, &pUpdate1, 0); |
| 138674 | + } |
| 138675 | + if( rc==SQLITE_OK ){ |
| 138676 | + rc = fts3SqlStmt(p, SQL_UPDATE_LEVEL, &pUpdate2, 0); |
| 138677 | + } |
| 138678 | + |
| 138679 | + if( rc==SQLITE_OK ){ |
| 138680 | + |
| 138681 | + /* Loop through all %_segdir entries for segments in this index with |
| 138682 | + ** levels equal to or greater than iAbsLevel. As each entry is visited, |
| 138683 | + ** updated it to set (level = -1) and (idx = N), where N is 0 for the |
| 138684 | + ** oldest segment in the range, 1 for the next oldest, and so on. |
| 138685 | + ** |
| 138686 | + ** In other words, move all segments being promoted to level -1, |
| 138687 | + ** setting the "idx" fields as appropriate to keep them in the same |
| 138688 | + ** order. The contents of level -1 (which is never used, except |
| 138689 | + ** transiently here), will be moved back to level iAbsLevel below. */ |
| 138690 | + sqlite3_bind_int64(pRange, 1, iAbsLevel); |
| 138691 | + while( SQLITE_ROW==sqlite3_step(pRange) ){ |
| 138692 | + sqlite3_bind_int(pUpdate1, 1, iIdx++); |
| 138693 | + sqlite3_bind_int(pUpdate1, 2, sqlite3_column_int(pRange, 0)); |
| 138694 | + sqlite3_bind_int(pUpdate1, 3, sqlite3_column_int(pRange, 1)); |
| 138695 | + sqlite3_step(pUpdate1); |
| 138696 | + rc = sqlite3_reset(pUpdate1); |
| 138697 | + if( rc!=SQLITE_OK ){ |
| 138698 | + sqlite3_reset(pRange); |
| 138699 | + break; |
| 138700 | + } |
| 138701 | + } |
| 138702 | + } |
| 138703 | + if( rc==SQLITE_OK ){ |
| 138704 | + rc = sqlite3_reset(pRange); |
| 138705 | + } |
| 138706 | + |
| 138707 | + /* Move level -1 to level iAbsLevel */ |
| 138708 | + if( rc==SQLITE_OK ){ |
| 138709 | + sqlite3_bind_int64(pUpdate2, 1, iAbsLevel); |
| 138710 | + sqlite3_step(pUpdate2); |
| 138711 | + rc = sqlite3_reset(pUpdate2); |
| 138712 | + } |
| 138713 | + } |
| 138714 | + } |
| 138715 | + |
| 138716 | + |
| 138717 | + return rc; |
| 138718 | +} |
| 137983 | 138719 | |
| 137984 | 138720 | /* |
| 137985 | 138721 | ** Merge all level iLevel segments in the database into a single |
| 137986 | 138722 | ** iLevel+1 segment. Or, if iLevel<0, merge all segments into a |
| 137987 | 138723 | ** single segment with a level equal to the numerically largest level |
| | @@ -138003,10 +138739,11 @@ |
| 138003 | 138739 | sqlite3_int64 iNewLevel = 0; /* Level/index to create new segment at */ |
| 138004 | 138740 | SegmentWriter *pWriter = 0; /* Used to write the new, merged, segment */ |
| 138005 | 138741 | Fts3SegFilter filter; /* Segment term filter condition */ |
| 138006 | 138742 | Fts3MultiSegReader csr; /* Cursor to iterate through level(s) */ |
| 138007 | 138743 | int bIgnoreEmpty = 0; /* True to ignore empty segments */ |
| 138744 | + i64 iMaxLevel = 0; /* Max level number for this index/langid */ |
| 138008 | 138745 | |
| 138009 | 138746 | assert( iLevel==FTS3_SEGCURSOR_ALL |
| 138010 | 138747 | || iLevel==FTS3_SEGCURSOR_PENDING |
| 138011 | 138748 | || iLevel>=0 |
| 138012 | 138749 | ); |
| | @@ -138013,10 +138750,15 @@ |
| 138013 | 138750 | assert( iLevel<FTS3_SEGDIR_MAXLEVEL ); |
| 138014 | 138751 | assert( iIndex>=0 && iIndex<p->nIndex ); |
| 138015 | 138752 | |
| 138016 | 138753 | rc = sqlite3Fts3SegReaderCursor(p, iLangid, iIndex, iLevel, 0, 0, 1, 0, &csr); |
| 138017 | 138754 | if( rc!=SQLITE_OK || csr.nSegment==0 ) goto finished; |
| 138755 | + |
| 138756 | + if( iLevel!=FTS3_SEGCURSOR_PENDING ){ |
| 138757 | + rc = fts3SegmentMaxLevel(p, iLangid, iIndex, &iMaxLevel); |
| 138758 | + if( rc!=SQLITE_OK ) goto finished; |
| 138759 | + } |
| 138018 | 138760 | |
| 138019 | 138761 | if( iLevel==FTS3_SEGCURSOR_ALL ){ |
| 138020 | 138762 | /* This call is to merge all segments in the database to a single |
| 138021 | 138763 | ** segment. The level of the new segment is equal to the numerically |
| 138022 | 138764 | ** greatest segment level currently present in the database for this |
| | @@ -138023,25 +138765,25 @@ |
| 138023 | 138765 | ** index. The idx of the new segment is always 0. */ |
| 138024 | 138766 | if( csr.nSegment==1 ){ |
| 138025 | 138767 | rc = SQLITE_DONE; |
| 138026 | 138768 | goto finished; |
| 138027 | 138769 | } |
| 138028 | | - rc = fts3SegmentMaxLevel(p, iLangid, iIndex, &iNewLevel); |
| 138770 | + iNewLevel = iMaxLevel; |
| 138029 | 138771 | bIgnoreEmpty = 1; |
| 138030 | 138772 | |
| 138031 | | - }else if( iLevel==FTS3_SEGCURSOR_PENDING ){ |
| 138032 | | - iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, 0); |
| 138033 | | - rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, 0, &iIdx); |
| 138034 | 138773 | }else{ |
| 138035 | 138774 | /* This call is to merge all segments at level iLevel. find the next |
| 138036 | 138775 | ** available segment index at level iLevel+1. The call to |
| 138037 | 138776 | ** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to |
| 138038 | 138777 | ** a single iLevel+2 segment if necessary. */ |
| 138039 | | - rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, iLevel+1, &iIdx); |
| 138778 | + assert( FTS3_SEGCURSOR_PENDING==-1 ); |
| 138040 | 138779 | iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, iLevel+1); |
| 138780 | + rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, iLevel+1, &iIdx); |
| 138781 | + bIgnoreEmpty = (iLevel!=FTS3_SEGCURSOR_PENDING) && (iNewLevel>iMaxLevel); |
| 138041 | 138782 | } |
| 138042 | 138783 | if( rc!=SQLITE_OK ) goto finished; |
| 138784 | + |
| 138043 | 138785 | assert( csr.nSegment>0 ); |
| 138044 | 138786 | assert( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) ); |
| 138045 | 138787 | assert( iNewLevel<getAbsoluteLevel(p, iLangid, iIndex,FTS3_SEGDIR_MAXLEVEL) ); |
| 138046 | 138788 | |
| 138047 | 138789 | memset(&filter, 0, sizeof(Fts3SegFilter)); |
| | @@ -138054,29 +138796,36 @@ |
| 138054 | 138796 | if( rc!=SQLITE_ROW ) break; |
| 138055 | 138797 | rc = fts3SegWriterAdd(p, &pWriter, 1, |
| 138056 | 138798 | csr.zTerm, csr.nTerm, csr.aDoclist, csr.nDoclist); |
| 138057 | 138799 | } |
| 138058 | 138800 | if( rc!=SQLITE_OK ) goto finished; |
| 138059 | | - assert( pWriter ); |
| 138801 | + assert( pWriter || bIgnoreEmpty ); |
| 138060 | 138802 | |
| 138061 | 138803 | if( iLevel!=FTS3_SEGCURSOR_PENDING ){ |
| 138062 | 138804 | rc = fts3DeleteSegdir( |
| 138063 | 138805 | p, iLangid, iIndex, iLevel, csr.apSegment, csr.nSegment |
| 138064 | 138806 | ); |
| 138065 | 138807 | if( rc!=SQLITE_OK ) goto finished; |
| 138066 | 138808 | } |
| 138067 | | - rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx); |
| 138809 | + if( pWriter ){ |
| 138810 | + rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx); |
| 138811 | + if( rc==SQLITE_OK ){ |
| 138812 | + if( iLevel==FTS3_SEGCURSOR_PENDING || iNewLevel<iMaxLevel ){ |
| 138813 | + rc = fts3PromoteSegments(p, iNewLevel, pWriter->nLeafData); |
| 138814 | + } |
| 138815 | + } |
| 138816 | + } |
| 138068 | 138817 | |
| 138069 | 138818 | finished: |
| 138070 | 138819 | fts3SegWriterFree(pWriter); |
| 138071 | 138820 | sqlite3Fts3SegReaderFinish(&csr); |
| 138072 | 138821 | return rc; |
| 138073 | 138822 | } |
| 138074 | 138823 | |
| 138075 | 138824 | |
| 138076 | 138825 | /* |
| 138077 | | -** Flush the contents of pendingTerms to level 0 segments. |
| 138826 | +** Flush the contents of pendingTerms to level 0 segments. |
| 138078 | 138827 | */ |
| 138079 | 138828 | SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *p){ |
| 138080 | 138829 | int rc = SQLITE_OK; |
| 138081 | 138830 | int i; |
| 138082 | 138831 | |
| | @@ -138088,18 +138837,23 @@ |
| 138088 | 138837 | |
| 138089 | 138838 | /* Determine the auto-incr-merge setting if unknown. If enabled, |
| 138090 | 138839 | ** estimate the number of leaf blocks of content to be written |
| 138091 | 138840 | */ |
| 138092 | 138841 | if( rc==SQLITE_OK && p->bHasStat |
| 138093 | | - && p->bAutoincrmerge==0xff && p->nLeafAdd>0 |
| 138842 | + && p->nAutoincrmerge==0xff && p->nLeafAdd>0 |
| 138094 | 138843 | ){ |
| 138095 | 138844 | sqlite3_stmt *pStmt = 0; |
| 138096 | 138845 | rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pStmt, 0); |
| 138097 | 138846 | if( rc==SQLITE_OK ){ |
| 138098 | 138847 | sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE); |
| 138099 | 138848 | rc = sqlite3_step(pStmt); |
| 138100 | | - p->bAutoincrmerge = (rc==SQLITE_ROW && sqlite3_column_int(pStmt, 0)); |
| 138849 | + if( rc==SQLITE_ROW ){ |
| 138850 | + p->nAutoincrmerge = sqlite3_column_int(pStmt, 0); |
| 138851 | + if( p->nAutoincrmerge==1 ) p->nAutoincrmerge = 8; |
| 138852 | + }else if( rc==SQLITE_DONE ){ |
| 138853 | + p->nAutoincrmerge = 0; |
| 138854 | + } |
| 138101 | 138855 | rc = sqlite3_reset(pStmt); |
| 138102 | 138856 | } |
| 138103 | 138857 | } |
| 138104 | 138858 | return rc; |
| 138105 | 138859 | } |
| | @@ -138463,10 +139217,12 @@ |
| 138463 | 139217 | int nWork; /* Number of leaf pages flushed */ |
| 138464 | 139218 | sqlite3_int64 iAbsLevel; /* Absolute level of input segments */ |
| 138465 | 139219 | int iIdx; /* Index of *output* segment in iAbsLevel+1 */ |
| 138466 | 139220 | sqlite3_int64 iStart; /* Block number of first allocated block */ |
| 138467 | 139221 | sqlite3_int64 iEnd; /* Block number of last allocated block */ |
| 139222 | + sqlite3_int64 nLeafData; /* Bytes of leaf page data so far */ |
| 139223 | + u8 bNoLeafData; /* If true, store 0 for segment size */ |
| 138468 | 139224 | NodeWriter aNodeWriter[FTS_MAX_APPENDABLE_HEIGHT]; |
| 138469 | 139225 | }; |
| 138470 | 139226 | |
| 138471 | 139227 | /* |
| 138472 | 139228 | ** An object of the following type is used to read data from a single |
| | @@ -138801,12 +139557,12 @@ |
| 138801 | 139557 | nSpace = 1; |
| 138802 | 139558 | nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix; |
| 138803 | 139559 | nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist; |
| 138804 | 139560 | } |
| 138805 | 139561 | |
| 139562 | + pWriter->nLeafData += nSpace; |
| 138806 | 139563 | blobGrowBuffer(&pLeaf->block, pLeaf->block.n + nSpace, &rc); |
| 138807 | | - |
| 138808 | 139564 | if( rc==SQLITE_OK ){ |
| 138809 | 139565 | if( pLeaf->block.n==0 ){ |
| 138810 | 139566 | pLeaf->block.n = 1; |
| 138811 | 139567 | pLeaf->block.a[0] = '\0'; |
| 138812 | 139568 | } |
| | @@ -138901,10 +139657,11 @@ |
| 138901 | 139657 | pWriter->iAbsLevel+1, /* level */ |
| 138902 | 139658 | pWriter->iIdx, /* idx */ |
| 138903 | 139659 | pWriter->iStart, /* start_block */ |
| 138904 | 139660 | pWriter->aNodeWriter[0].iBlock, /* leaves_end_block */ |
| 138905 | 139661 | pWriter->iEnd, /* end_block */ |
| 139662 | + (pWriter->bNoLeafData==0 ? pWriter->nLeafData : 0), /* end_block */ |
| 138906 | 139663 | pRoot->block.a, pRoot->block.n /* root */ |
| 138907 | 139664 | ); |
| 138908 | 139665 | } |
| 138909 | 139666 | sqlite3_free(pRoot->block.a); |
| 138910 | 139667 | sqlite3_free(pRoot->key.a); |
| | @@ -139002,11 +139759,15 @@ |
| 139002 | 139759 | sqlite3_bind_int64(pSelect, 1, iAbsLevel+1); |
| 139003 | 139760 | sqlite3_bind_int(pSelect, 2, iIdx); |
| 139004 | 139761 | if( sqlite3_step(pSelect)==SQLITE_ROW ){ |
| 139005 | 139762 | iStart = sqlite3_column_int64(pSelect, 1); |
| 139006 | 139763 | iLeafEnd = sqlite3_column_int64(pSelect, 2); |
| 139007 | | - iEnd = sqlite3_column_int64(pSelect, 3); |
| 139764 | + fts3ReadEndBlockField(pSelect, 3, &iEnd, &pWriter->nLeafData); |
| 139765 | + if( pWriter->nLeafData<0 ){ |
| 139766 | + pWriter->nLeafData = pWriter->nLeafData * -1; |
| 139767 | + } |
| 139768 | + pWriter->bNoLeafData = (pWriter->nLeafData==0); |
| 139008 | 139769 | nRoot = sqlite3_column_bytes(pSelect, 4); |
| 139009 | 139770 | aRoot = sqlite3_column_blob(pSelect, 4); |
| 139010 | 139771 | }else{ |
| 139011 | 139772 | return sqlite3_reset(pSelect); |
| 139012 | 139773 | } |
| | @@ -139603,15 +140364,15 @@ |
| 139603 | 140364 | |
| 139604 | 140365 | |
| 139605 | 140366 | /* |
| 139606 | 140367 | ** Attempt an incremental merge that writes nMerge leaf blocks. |
| 139607 | 140368 | ** |
| 139608 | | -** Incremental merges happen nMin segments at a time. The two |
| 139609 | | -** segments to be merged are the nMin oldest segments (the ones with |
| 139610 | | -** the smallest indexes) in the highest level that contains at least |
| 139611 | | -** nMin segments. Multiple merges might occur in an attempt to write the |
| 139612 | | -** quota of nMerge leaf blocks. |
| 140369 | +** Incremental merges happen nMin segments at a time. The segments |
| 140370 | +** to be merged are the nMin oldest segments (the ones with the smallest |
| 140371 | +** values for the _segdir.idx field) in the highest level that contains |
| 140372 | +** at least nMin segments. Multiple merges might occur in an attempt to |
| 140373 | +** write the quota of nMerge leaf blocks. |
| 139613 | 140374 | */ |
| 139614 | 140375 | SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){ |
| 139615 | 140376 | int rc; /* Return code */ |
| 139616 | 140377 | int nRem = nMerge; /* Number of leaf pages yet to be written */ |
| 139617 | 140378 | Fts3MultiSegReader *pCsr; /* Cursor used to read input data */ |
| | @@ -139632,10 +140393,11 @@ |
| 139632 | 140393 | rc = fts3IncrmergeHintLoad(p, &hint); |
| 139633 | 140394 | while( rc==SQLITE_OK && nRem>0 ){ |
| 139634 | 140395 | const i64 nMod = FTS3_SEGDIR_MAXLEVEL * p->nIndex; |
| 139635 | 140396 | sqlite3_stmt *pFindLevel = 0; /* SQL used to determine iAbsLevel */ |
| 139636 | 140397 | int bUseHint = 0; /* True if attempting to append */ |
| 140398 | + int iIdx = 0; /* Largest idx in level (iAbsLevel+1) */ |
| 139637 | 140399 | |
| 139638 | 140400 | /* Search the %_segdir table for the absolute level with the smallest |
| 139639 | 140401 | ** relative level number that contains at least nMin segments, if any. |
| 139640 | 140402 | ** If one is found, set iAbsLevel to the absolute level number and |
| 139641 | 140403 | ** nSeg to nMin. If no level with at least nMin segments can be found, |
| | @@ -139685,27 +140447,36 @@ |
| 139685 | 140447 | ** segments available in level iAbsLevel. In this case, no work is |
| 139686 | 140448 | ** done on iAbsLevel - fall through to the next iteration of the loop |
| 139687 | 140449 | ** to start work on some other level. */ |
| 139688 | 140450 | memset(pWriter, 0, nAlloc); |
| 139689 | 140451 | pFilter->flags = FTS3_SEGMENT_REQUIRE_POS; |
| 140452 | + |
| 140453 | + if( rc==SQLITE_OK ){ |
| 140454 | + rc = fts3IncrmergeOutputIdx(p, iAbsLevel, &iIdx); |
| 140455 | + assert( bUseHint==1 || bUseHint==0 ); |
| 140456 | + if( iIdx==0 || (bUseHint && iIdx==1) ){ |
| 140457 | + int bIgnore = 0; |
| 140458 | + rc = fts3SegmentIsMaxLevel(p, iAbsLevel+1, &bIgnore); |
| 140459 | + if( bIgnore ){ |
| 140460 | + pFilter->flags |= FTS3_SEGMENT_IGNORE_EMPTY; |
| 140461 | + } |
| 140462 | + } |
| 140463 | + } |
| 140464 | + |
| 139690 | 140465 | if( rc==SQLITE_OK ){ |
| 139691 | 140466 | rc = fts3IncrmergeCsr(p, iAbsLevel, nSeg, pCsr); |
| 139692 | 140467 | } |
| 139693 | 140468 | if( SQLITE_OK==rc && pCsr->nSegment==nSeg |
| 139694 | 140469 | && SQLITE_OK==(rc = sqlite3Fts3SegReaderStart(p, pCsr, pFilter)) |
| 139695 | 140470 | && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pCsr)) |
| 139696 | 140471 | ){ |
| 139697 | | - int iIdx = 0; /* Largest idx in level (iAbsLevel+1) */ |
| 139698 | | - rc = fts3IncrmergeOutputIdx(p, iAbsLevel, &iIdx); |
| 139699 | | - if( rc==SQLITE_OK ){ |
| 139700 | | - if( bUseHint && iIdx>0 ){ |
| 139701 | | - const char *zKey = pCsr->zTerm; |
| 139702 | | - int nKey = pCsr->nTerm; |
| 139703 | | - rc = fts3IncrmergeLoad(p, iAbsLevel, iIdx-1, zKey, nKey, pWriter); |
| 139704 | | - }else{ |
| 139705 | | - rc = fts3IncrmergeWriter(p, iAbsLevel, iIdx, pCsr, pWriter); |
| 139706 | | - } |
| 140472 | + if( bUseHint && iIdx>0 ){ |
| 140473 | + const char *zKey = pCsr->zTerm; |
| 140474 | + int nKey = pCsr->nTerm; |
| 140475 | + rc = fts3IncrmergeLoad(p, iAbsLevel, iIdx-1, zKey, nKey, pWriter); |
| 140476 | + }else{ |
| 140477 | + rc = fts3IncrmergeWriter(p, iAbsLevel, iIdx, pCsr, pWriter); |
| 139707 | 140478 | } |
| 139708 | 140479 | |
| 139709 | 140480 | if( rc==SQLITE_OK && pWriter->nLeafEst ){ |
| 139710 | 140481 | fts3LogMerge(nSeg, iAbsLevel); |
| 139711 | 140482 | do { |
| | @@ -139723,11 +140494,17 @@ |
| 139723 | 140494 | fts3IncrmergeHintPush(&hint, iAbsLevel, nSeg, &rc); |
| 139724 | 140495 | } |
| 139725 | 140496 | } |
| 139726 | 140497 | } |
| 139727 | 140498 | |
| 140499 | + if( nSeg!=0 ){ |
| 140500 | + pWriter->nLeafData = pWriter->nLeafData * -1; |
| 140501 | + } |
| 139728 | 140502 | fts3IncrmergeRelease(p, pWriter, &rc); |
| 140503 | + if( nSeg==0 && pWriter->bNoLeafData==0 ){ |
| 140504 | + fts3PromoteSegments(p, iAbsLevel+1, pWriter->nLeafData); |
| 140505 | + } |
| 139729 | 140506 | } |
| 139730 | 140507 | |
| 139731 | 140508 | sqlite3Fts3SegReaderFinish(pCsr); |
| 139732 | 140509 | } |
| 139733 | 140510 | |
| | @@ -139810,20 +140587,23 @@ |
| 139810 | 140587 | Fts3Table *p, /* FTS3 table handle */ |
| 139811 | 140588 | const char *zParam /* Nul-terminated string containing boolean */ |
| 139812 | 140589 | ){ |
| 139813 | 140590 | int rc = SQLITE_OK; |
| 139814 | 140591 | sqlite3_stmt *pStmt = 0; |
| 139815 | | - p->bAutoincrmerge = fts3Getint(&zParam)!=0; |
| 140592 | + p->nAutoincrmerge = fts3Getint(&zParam); |
| 140593 | + if( p->nAutoincrmerge==1 || p->nAutoincrmerge>FTS3_MERGE_COUNT ){ |
| 140594 | + p->nAutoincrmerge = 8; |
| 140595 | + } |
| 139816 | 140596 | if( !p->bHasStat ){ |
| 139817 | 140597 | assert( p->bFts4==0 ); |
| 139818 | 140598 | sqlite3Fts3CreateStatTable(&rc, p); |
| 139819 | 140599 | if( rc ) return rc; |
| 139820 | 140600 | } |
| 139821 | 140601 | rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0); |
| 139822 | 140602 | if( rc ) return rc; |
| 139823 | 140603 | sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE); |
| 139824 | | - sqlite3_bind_int(pStmt, 2, p->bAutoincrmerge); |
| 140604 | + sqlite3_bind_int(pStmt, 2, p->nAutoincrmerge); |
| 139825 | 140605 | sqlite3_step(pStmt); |
| 139826 | 140606 | rc = sqlite3_reset(pStmt); |
| 139827 | 140607 | return rc; |
| 139828 | 140608 | } |
| 139829 | 140609 | |
| | @@ -142802,64 +143582,24 @@ |
| 142802 | 143582 | ** child page. |
| 142803 | 143583 | */ |
| 142804 | 143584 | |
| 142805 | 143585 | #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RTREE) |
| 142806 | 143586 | |
| 142807 | | -/* |
| 142808 | | -** This file contains an implementation of a couple of different variants |
| 142809 | | -** of the r-tree algorithm. See the README file for further details. The |
| 142810 | | -** same data-structure is used for all, but the algorithms for insert and |
| 142811 | | -** delete operations vary. The variants used are selected at compile time |
| 142812 | | -** by defining the following symbols: |
| 142813 | | -*/ |
| 142814 | | - |
| 142815 | | -/* Either, both or none of the following may be set to activate |
| 142816 | | -** r*tree variant algorithms. |
| 142817 | | -*/ |
| 142818 | | -#define VARIANT_RSTARTREE_CHOOSESUBTREE 0 |
| 142819 | | -#define VARIANT_RSTARTREE_REINSERT 1 |
| 142820 | | - |
| 142821 | | -/* |
| 142822 | | -** Exactly one of the following must be set to 1. |
| 142823 | | -*/ |
| 142824 | | -#define VARIANT_GUTTMAN_QUADRATIC_SPLIT 0 |
| 142825 | | -#define VARIANT_GUTTMAN_LINEAR_SPLIT 0 |
| 142826 | | -#define VARIANT_RSTARTREE_SPLIT 1 |
| 142827 | | - |
| 142828 | | -#define VARIANT_GUTTMAN_SPLIT \ |
| 142829 | | - (VARIANT_GUTTMAN_LINEAR_SPLIT||VARIANT_GUTTMAN_QUADRATIC_SPLIT) |
| 142830 | | - |
| 142831 | | -#if VARIANT_GUTTMAN_QUADRATIC_SPLIT |
| 142832 | | - #define PickNext QuadraticPickNext |
| 142833 | | - #define PickSeeds QuadraticPickSeeds |
| 142834 | | - #define AssignCells splitNodeGuttman |
| 142835 | | -#endif |
| 142836 | | -#if VARIANT_GUTTMAN_LINEAR_SPLIT |
| 142837 | | - #define PickNext LinearPickNext |
| 142838 | | - #define PickSeeds LinearPickSeeds |
| 142839 | | - #define AssignCells splitNodeGuttman |
| 142840 | | -#endif |
| 142841 | | -#if VARIANT_RSTARTREE_SPLIT |
| 142842 | | - #define AssignCells splitNodeStartree |
| 142843 | | -#endif |
| 142844 | | - |
| 142845 | | -#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) |
| 142846 | | -# define NDEBUG 1 |
| 142847 | | -#endif |
| 142848 | | - |
| 142849 | 143587 | #ifndef SQLITE_CORE |
| 142850 | 143588 | SQLITE_EXTENSION_INIT1 |
| 142851 | 143589 | #else |
| 142852 | 143590 | #endif |
| 142853 | 143591 | |
| 142854 | 143592 | /* #include <string.h> */ |
| 142855 | 143593 | /* #include <assert.h> */ |
| 143594 | +/* #include <stdio.h> */ |
| 142856 | 143595 | |
| 142857 | 143596 | #ifndef SQLITE_AMALGAMATION |
| 142858 | 143597 | #include "sqlite3rtree.h" |
| 142859 | 143598 | typedef sqlite3_int64 i64; |
| 142860 | 143599 | typedef unsigned char u8; |
| 143600 | +typedef unsigned short u16; |
| 142861 | 143601 | typedef unsigned int u32; |
| 142862 | 143602 | #endif |
| 142863 | 143603 | |
| 142864 | 143604 | /* The following macro is used to suppress compiler warnings. |
| 142865 | 143605 | */ |
| | @@ -142873,19 +143613,20 @@ |
| 142873 | 143613 | typedef struct RtreeCell RtreeCell; |
| 142874 | 143614 | typedef struct RtreeConstraint RtreeConstraint; |
| 142875 | 143615 | typedef struct RtreeMatchArg RtreeMatchArg; |
| 142876 | 143616 | typedef struct RtreeGeomCallback RtreeGeomCallback; |
| 142877 | 143617 | typedef union RtreeCoord RtreeCoord; |
| 143618 | +typedef struct RtreeSearchPoint RtreeSearchPoint; |
| 142878 | 143619 | |
| 142879 | 143620 | /* The rtree may have between 1 and RTREE_MAX_DIMENSIONS dimensions. */ |
| 142880 | 143621 | #define RTREE_MAX_DIMENSIONS 5 |
| 142881 | 143622 | |
| 142882 | 143623 | /* Size of hash table Rtree.aHash. This hash table is not expected to |
| 142883 | 143624 | ** ever contain very many entries, so a fixed number of buckets is |
| 142884 | 143625 | ** used. |
| 142885 | 143626 | */ |
| 142886 | | -#define HASHSIZE 128 |
| 143627 | +#define HASHSIZE 97 |
| 142887 | 143628 | |
| 142888 | 143629 | /* The xBestIndex method of this virtual table requires an estimate of |
| 142889 | 143630 | ** the number of rows in the virtual table to calculate the costs of |
| 142890 | 143631 | ** various strategies. If possible, this estimate is loaded from the |
| 142891 | 143632 | ** sqlite_stat1 table (with RTREE_MIN_ROWEST as a hard-coded minimum). |
| | @@ -142897,19 +143638,19 @@ |
| 142897 | 143638 | |
| 142898 | 143639 | /* |
| 142899 | 143640 | ** An rtree virtual-table object. |
| 142900 | 143641 | */ |
| 142901 | 143642 | struct Rtree { |
| 142902 | | - sqlite3_vtab base; |
| 143643 | + sqlite3_vtab base; /* Base class. Must be first */ |
| 142903 | 143644 | sqlite3 *db; /* Host database connection */ |
| 142904 | 143645 | int iNodeSize; /* Size in bytes of each node in the node table */ |
| 142905 | | - int nDim; /* Number of dimensions */ |
| 142906 | | - int nBytesPerCell; /* Bytes consumed per cell */ |
| 143646 | + u8 nDim; /* Number of dimensions */ |
| 143647 | + u8 eCoordType; /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */ |
| 143648 | + u8 nBytesPerCell; /* Bytes consumed per cell */ |
| 142907 | 143649 | int iDepth; /* Current depth of the r-tree structure */ |
| 142908 | 143650 | char *zDb; /* Name of database containing r-tree table */ |
| 142909 | 143651 | char *zName; /* Name of r-tree table */ |
| 142910 | | - RtreeNode *aHash[HASHSIZE]; /* Hash table of in-memory nodes. */ |
| 142911 | 143652 | int nBusy; /* Current number of users of this structure */ |
| 142912 | 143653 | i64 nRowEst; /* Estimated number of rows in this table */ |
| 142913 | 143654 | |
| 142914 | 143655 | /* List of nodes removed during a CondenseTree operation. List is |
| 142915 | 143656 | ** linked together via the pointer normally used for hash chains - |
| | @@ -142932,14 +143673,14 @@ |
| 142932 | 143673 | /* Statements to read/write/delete a record from xxx_parent */ |
| 142933 | 143674 | sqlite3_stmt *pReadParent; |
| 142934 | 143675 | sqlite3_stmt *pWriteParent; |
| 142935 | 143676 | sqlite3_stmt *pDeleteParent; |
| 142936 | 143677 | |
| 142937 | | - int eCoordType; |
| 143678 | + RtreeNode *aHash[HASHSIZE]; /* Hash table of in-memory nodes. */ |
| 142938 | 143679 | }; |
| 142939 | 143680 | |
| 142940 | | -/* Possible values for eCoordType: */ |
| 143681 | +/* Possible values for Rtree.eCoordType: */ |
| 142941 | 143682 | #define RTREE_COORD_REAL32 0 |
| 142942 | 143683 | #define RTREE_COORD_INT32 1 |
| 142943 | 143684 | |
| 142944 | 143685 | /* |
| 142945 | 143686 | ** If SQLITE_RTREE_INT_ONLY is defined, then this virtual table will |
| | @@ -142947,14 +143688,33 @@ |
| 142947 | 143688 | ** will be done. |
| 142948 | 143689 | */ |
| 142949 | 143690 | #ifdef SQLITE_RTREE_INT_ONLY |
| 142950 | 143691 | typedef sqlite3_int64 RtreeDValue; /* High accuracy coordinate */ |
| 142951 | 143692 | typedef int RtreeValue; /* Low accuracy coordinate */ |
| 143693 | +# define RTREE_ZERO 0 |
| 142952 | 143694 | #else |
| 142953 | 143695 | typedef double RtreeDValue; /* High accuracy coordinate */ |
| 142954 | 143696 | typedef float RtreeValue; /* Low accuracy coordinate */ |
| 143697 | +# define RTREE_ZERO 0.0 |
| 142955 | 143698 | #endif |
| 143699 | + |
| 143700 | +/* |
| 143701 | +** When doing a search of an r-tree, instances of the following structure |
| 143702 | +** record intermediate results from the tree walk. |
| 143703 | +** |
| 143704 | +** The id is always a node-id. For iLevel>=1 the id is the node-id of |
| 143705 | +** the node that the RtreeSearchPoint represents. When iLevel==0, however, |
| 143706 | +** the id is of the parent node and the cell that RtreeSearchPoint |
| 143707 | +** represents is the iCell-th entry in the parent node. |
| 143708 | +*/ |
| 143709 | +struct RtreeSearchPoint { |
| 143710 | + RtreeDValue rScore; /* The score for this node. Smallest goes first. */ |
| 143711 | + sqlite3_int64 id; /* Node ID */ |
| 143712 | + u8 iLevel; /* 0=entries. 1=leaf node. 2+ for higher */ |
| 143713 | + u8 eWithin; /* PARTLY_WITHIN or FULLY_WITHIN */ |
| 143714 | + u8 iCell; /* Cell index within the node */ |
| 143715 | +}; |
| 142956 | 143716 | |
| 142957 | 143717 | /* |
| 142958 | 143718 | ** The minimum number of cells allowed for a node is a third of the |
| 142959 | 143719 | ** maximum. In Gutman's notation: |
| 142960 | 143720 | ** |
| | @@ -142974,25 +143734,48 @@ |
| 142974 | 143734 | ** 2^40 is greater than 2^64, an r-tree structure always has a depth of |
| 142975 | 143735 | ** 40 or less. |
| 142976 | 143736 | */ |
| 142977 | 143737 | #define RTREE_MAX_DEPTH 40 |
| 142978 | 143738 | |
| 143739 | + |
| 143740 | +/* |
| 143741 | +** Number of entries in the cursor RtreeNode cache. The first entry is |
| 143742 | +** used to cache the RtreeNode for RtreeCursor.sPoint. The remaining |
| 143743 | +** entries cache the RtreeNode for the first elements of the priority queue. |
| 143744 | +*/ |
| 143745 | +#define RTREE_CACHE_SZ 5 |
| 143746 | + |
| 142979 | 143747 | /* |
| 142980 | 143748 | ** An rtree cursor object. |
| 142981 | 143749 | */ |
| 142982 | 143750 | struct RtreeCursor { |
| 142983 | | - sqlite3_vtab_cursor base; |
| 142984 | | - RtreeNode *pNode; /* Node cursor is currently pointing at */ |
| 142985 | | - int iCell; /* Index of current cell in pNode */ |
| 143751 | + sqlite3_vtab_cursor base; /* Base class. Must be first */ |
| 143752 | + u8 atEOF; /* True if at end of search */ |
| 143753 | + u8 bPoint; /* True if sPoint is valid */ |
| 142986 | 143754 | int iStrategy; /* Copy of idxNum search parameter */ |
| 142987 | 143755 | int nConstraint; /* Number of entries in aConstraint */ |
| 142988 | 143756 | RtreeConstraint *aConstraint; /* Search constraints. */ |
| 143757 | + int nPointAlloc; /* Number of slots allocated for aPoint[] */ |
| 143758 | + int nPoint; /* Number of slots used in aPoint[] */ |
| 143759 | + int mxLevel; /* iLevel value for root of the tree */ |
| 143760 | + RtreeSearchPoint *aPoint; /* Priority queue for search points */ |
| 143761 | + RtreeSearchPoint sPoint; /* Cached next search point */ |
| 143762 | + RtreeNode *aNode[RTREE_CACHE_SZ]; /* Rtree node cache */ |
| 143763 | + u32 anQueue[RTREE_MAX_DEPTH+1]; /* Number of queued entries by iLevel */ |
| 142989 | 143764 | }; |
| 142990 | 143765 | |
| 143766 | +/* Return the Rtree of a RtreeCursor */ |
| 143767 | +#define RTREE_OF_CURSOR(X) ((Rtree*)((X)->base.pVtab)) |
| 143768 | + |
| 143769 | +/* |
| 143770 | +** A coordinate can be either a floating point number or a integer. All |
| 143771 | +** coordinates within a single R-Tree are always of the same time. |
| 143772 | +*/ |
| 142991 | 143773 | union RtreeCoord { |
| 142992 | | - RtreeValue f; |
| 142993 | | - int i; |
| 143774 | + RtreeValue f; /* Floating point value */ |
| 143775 | + int i; /* Integer value */ |
| 143776 | + u32 u; /* Unsigned for byte-order conversions */ |
| 142994 | 143777 | }; |
| 142995 | 143778 | |
| 142996 | 143779 | /* |
| 142997 | 143780 | ** The argument is an RtreeCoord. Return the value stored within the RtreeCoord |
| 142998 | 143781 | ** formatted as a RtreeDValue (double or int64). This macro assumes that local |
| | @@ -143013,42 +143796,71 @@ |
| 143013 | 143796 | ** A search constraint. |
| 143014 | 143797 | */ |
| 143015 | 143798 | struct RtreeConstraint { |
| 143016 | 143799 | int iCoord; /* Index of constrained coordinate */ |
| 143017 | 143800 | int op; /* Constraining operation */ |
| 143018 | | - RtreeDValue rValue; /* Constraint value. */ |
| 143019 | | - int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*); |
| 143020 | | - sqlite3_rtree_geometry *pGeom; /* Constraint callback argument for a MATCH */ |
| 143801 | + union { |
| 143802 | + RtreeDValue rValue; /* Constraint value. */ |
| 143803 | + int (*xGeom)(sqlite3_rtree_geometry*,int,RtreeDValue*,int*); |
| 143804 | + int (*xQueryFunc)(sqlite3_rtree_query_info*); |
| 143805 | + } u; |
| 143806 | + sqlite3_rtree_query_info *pInfo; /* xGeom and xQueryFunc argument */ |
| 143021 | 143807 | }; |
| 143022 | 143808 | |
| 143023 | 143809 | /* Possible values for RtreeConstraint.op */ |
| 143024 | | -#define RTREE_EQ 0x41 |
| 143025 | | -#define RTREE_LE 0x42 |
| 143026 | | -#define RTREE_LT 0x43 |
| 143027 | | -#define RTREE_GE 0x44 |
| 143028 | | -#define RTREE_GT 0x45 |
| 143029 | | -#define RTREE_MATCH 0x46 |
| 143810 | +#define RTREE_EQ 0x41 /* A */ |
| 143811 | +#define RTREE_LE 0x42 /* B */ |
| 143812 | +#define RTREE_LT 0x43 /* C */ |
| 143813 | +#define RTREE_GE 0x44 /* D */ |
| 143814 | +#define RTREE_GT 0x45 /* E */ |
| 143815 | +#define RTREE_MATCH 0x46 /* F: Old-style sqlite3_rtree_geometry_callback() */ |
| 143816 | +#define RTREE_QUERY 0x47 /* G: New-style sqlite3_rtree_query_callback() */ |
| 143817 | + |
| 143030 | 143818 | |
| 143031 | 143819 | /* |
| 143032 | 143820 | ** An rtree structure node. |
| 143033 | 143821 | */ |
| 143034 | 143822 | struct RtreeNode { |
| 143035 | | - RtreeNode *pParent; /* Parent node */ |
| 143036 | | - i64 iNode; |
| 143037 | | - int nRef; |
| 143038 | | - int isDirty; |
| 143039 | | - u8 *zData; |
| 143040 | | - RtreeNode *pNext; /* Next node in this hash chain */ |
| 143823 | + RtreeNode *pParent; /* Parent node */ |
| 143824 | + i64 iNode; /* The node number */ |
| 143825 | + int nRef; /* Number of references to this node */ |
| 143826 | + int isDirty; /* True if the node needs to be written to disk */ |
| 143827 | + u8 *zData; /* Content of the node, as should be on disk */ |
| 143828 | + RtreeNode *pNext; /* Next node in this hash collision chain */ |
| 143041 | 143829 | }; |
| 143830 | + |
| 143831 | +/* Return the number of cells in a node */ |
| 143042 | 143832 | #define NCELL(pNode) readInt16(&(pNode)->zData[2]) |
| 143043 | 143833 | |
| 143044 | 143834 | /* |
| 143045 | | -** Structure to store a deserialized rtree record. |
| 143835 | +** A single cell from a node, deserialized |
| 143046 | 143836 | */ |
| 143047 | 143837 | struct RtreeCell { |
| 143048 | | - i64 iRowid; |
| 143049 | | - RtreeCoord aCoord[RTREE_MAX_DIMENSIONS*2]; |
| 143838 | + i64 iRowid; /* Node or entry ID */ |
| 143839 | + RtreeCoord aCoord[RTREE_MAX_DIMENSIONS*2]; /* Bounding box coordinates */ |
| 143840 | +}; |
| 143841 | + |
| 143842 | + |
| 143843 | +/* |
| 143844 | +** This object becomes the sqlite3_user_data() for the SQL functions |
| 143845 | +** that are created by sqlite3_rtree_geometry_callback() and |
| 143846 | +** sqlite3_rtree_query_callback() and which appear on the right of MATCH |
| 143847 | +** operators in order to constrain a search. |
| 143848 | +** |
| 143849 | +** xGeom and xQueryFunc are the callback functions. Exactly one of |
| 143850 | +** xGeom and xQueryFunc fields is non-NULL, depending on whether the |
| 143851 | +** SQL function was created using sqlite3_rtree_geometry_callback() or |
| 143852 | +** sqlite3_rtree_query_callback(). |
| 143853 | +** |
| 143854 | +** This object is deleted automatically by the destructor mechanism in |
| 143855 | +** sqlite3_create_function_v2(). |
| 143856 | +*/ |
| 143857 | +struct RtreeGeomCallback { |
| 143858 | + int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*); |
| 143859 | + int (*xQueryFunc)(sqlite3_rtree_query_info*); |
| 143860 | + void (*xDestructor)(void*); |
| 143861 | + void *pContext; |
| 143050 | 143862 | }; |
| 143051 | 143863 | |
| 143052 | 143864 | |
| 143053 | 143865 | /* |
| 143054 | 143866 | ** Value for the first field of every RtreeMatchArg object. The MATCH |
| | @@ -143056,33 +143868,20 @@ |
| 143056 | 143868 | ** value to avoid operating on invalid blobs (which could cause a segfault). |
| 143057 | 143869 | */ |
| 143058 | 143870 | #define RTREE_GEOMETRY_MAGIC 0x891245AB |
| 143059 | 143871 | |
| 143060 | 143872 | /* |
| 143061 | | -** An instance of this structure must be supplied as a blob argument to |
| 143062 | | -** the right-hand-side of an SQL MATCH operator used to constrain an |
| 143063 | | -** r-tree query. |
| 143873 | +** An instance of this structure (in the form of a BLOB) is returned by |
| 143874 | +** the SQL functions that sqlite3_rtree_geometry_callback() and |
| 143875 | +** sqlite3_rtree_query_callback() create, and is read as the right-hand |
| 143876 | +** operand to the MATCH operator of an R-Tree. |
| 143064 | 143877 | */ |
| 143065 | 143878 | struct RtreeMatchArg { |
| 143066 | | - u32 magic; /* Always RTREE_GEOMETRY_MAGIC */ |
| 143067 | | - int (*xGeom)(sqlite3_rtree_geometry *, int, RtreeDValue*, int *); |
| 143068 | | - void *pContext; |
| 143069 | | - int nParam; |
| 143070 | | - RtreeDValue aParam[1]; |
| 143071 | | -}; |
| 143072 | | - |
| 143073 | | -/* |
| 143074 | | -** When a geometry callback is created (see sqlite3_rtree_geometry_callback), |
| 143075 | | -** a single instance of the following structure is allocated. It is used |
| 143076 | | -** as the context for the user-function created by by s_r_g_c(). The object |
| 143077 | | -** is eventually deleted by the destructor mechanism provided by |
| 143078 | | -** sqlite3_create_function_v2() (which is called by s_r_g_c() to create |
| 143079 | | -** the geometry callback function). |
| 143080 | | -*/ |
| 143081 | | -struct RtreeGeomCallback { |
| 143082 | | - int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*); |
| 143083 | | - void *pContext; |
| 143879 | + u32 magic; /* Always RTREE_GEOMETRY_MAGIC */ |
| 143880 | + RtreeGeomCallback cb; /* Info about the callback functions */ |
| 143881 | + int nParam; /* Number of parameters to the SQL function */ |
| 143882 | + RtreeDValue aParam[1]; /* Values for parameters to the SQL function */ |
| 143084 | 143883 | }; |
| 143085 | 143884 | |
| 143086 | 143885 | #ifndef MAX |
| 143087 | 143886 | # define MAX(x,y) ((x) < (y) ? (y) : (x)) |
| 143088 | 143887 | #endif |
| | @@ -143172,14 +143971,11 @@ |
| 143172 | 143971 | /* |
| 143173 | 143972 | ** Given a node number iNode, return the corresponding key to use |
| 143174 | 143973 | ** in the Rtree.aHash table. |
| 143175 | 143974 | */ |
| 143176 | 143975 | static int nodeHash(i64 iNode){ |
| 143177 | | - return ( |
| 143178 | | - (iNode>>56) ^ (iNode>>48) ^ (iNode>>40) ^ (iNode>>32) ^ |
| 143179 | | - (iNode>>24) ^ (iNode>>16) ^ (iNode>> 8) ^ (iNode>> 0) |
| 143180 | | - ) % HASHSIZE; |
| 143976 | + return iNode % HASHSIZE; |
| 143181 | 143977 | } |
| 143182 | 143978 | |
| 143183 | 143979 | /* |
| 143184 | 143980 | ** Search the node hash table for node iNode. If found, return a pointer |
| 143185 | 143981 | ** to it. Otherwise, return 0. |
| | @@ -143235,12 +144031,11 @@ |
| 143235 | 144031 | } |
| 143236 | 144032 | |
| 143237 | 144033 | /* |
| 143238 | 144034 | ** Obtain a reference to an r-tree node. |
| 143239 | 144035 | */ |
| 143240 | | -static int |
| 143241 | | -nodeAcquire( |
| 144036 | +static int nodeAcquire( |
| 143242 | 144037 | Rtree *pRtree, /* R-tree structure */ |
| 143243 | 144038 | i64 iNode, /* Node number to load */ |
| 143244 | 144039 | RtreeNode *pParent, /* Either the parent node or NULL */ |
| 143245 | 144040 | RtreeNode **ppNode /* OUT: Acquired node */ |
| 143246 | 144041 | ){ |
| | @@ -143325,14 +144120,14 @@ |
| 143325 | 144120 | |
| 143326 | 144121 | /* |
| 143327 | 144122 | ** Overwrite cell iCell of node pNode with the contents of pCell. |
| 143328 | 144123 | */ |
| 143329 | 144124 | static void nodeOverwriteCell( |
| 143330 | | - Rtree *pRtree, |
| 143331 | | - RtreeNode *pNode, |
| 143332 | | - RtreeCell *pCell, |
| 143333 | | - int iCell |
| 144125 | + Rtree *pRtree, /* The overall R-Tree */ |
| 144126 | + RtreeNode *pNode, /* The node into which the cell is to be written */ |
| 144127 | + RtreeCell *pCell, /* The cell to write */ |
| 144128 | + int iCell /* Index into pNode into which pCell is written */ |
| 143334 | 144129 | ){ |
| 143335 | 144130 | int ii; |
| 143336 | 144131 | u8 *p = &pNode->zData[4 + pRtree->nBytesPerCell*iCell]; |
| 143337 | 144132 | p += writeInt64(p, pCell->iRowid); |
| 143338 | 144133 | for(ii=0; ii<(pRtree->nDim*2); ii++){ |
| | @@ -143340,11 +144135,11 @@ |
| 143340 | 144135 | } |
| 143341 | 144136 | pNode->isDirty = 1; |
| 143342 | 144137 | } |
| 143343 | 144138 | |
| 143344 | 144139 | /* |
| 143345 | | -** Remove cell the cell with index iCell from node pNode. |
| 144140 | +** Remove the cell with index iCell from node pNode. |
| 143346 | 144141 | */ |
| 143347 | 144142 | static void nodeDeleteCell(Rtree *pRtree, RtreeNode *pNode, int iCell){ |
| 143348 | 144143 | u8 *pDst = &pNode->zData[4 + pRtree->nBytesPerCell*iCell]; |
| 143349 | 144144 | u8 *pSrc = &pDst[pRtree->nBytesPerCell]; |
| 143350 | 144145 | int nByte = (NCELL(pNode) - iCell - 1) * pRtree->nBytesPerCell; |
| | @@ -143357,15 +144152,14 @@ |
| 143357 | 144152 | ** Insert the contents of cell pCell into node pNode. If the insert |
| 143358 | 144153 | ** is successful, return SQLITE_OK. |
| 143359 | 144154 | ** |
| 143360 | 144155 | ** If there is not enough free space in pNode, return SQLITE_FULL. |
| 143361 | 144156 | */ |
| 143362 | | -static int |
| 143363 | | -nodeInsertCell( |
| 143364 | | - Rtree *pRtree, |
| 143365 | | - RtreeNode *pNode, |
| 143366 | | - RtreeCell *pCell |
| 144157 | +static int nodeInsertCell( |
| 144158 | + Rtree *pRtree, /* The overall R-Tree */ |
| 144159 | + RtreeNode *pNode, /* Write new cell into this node */ |
| 144160 | + RtreeCell *pCell /* The cell to be inserted */ |
| 143367 | 144161 | ){ |
| 143368 | 144162 | int nCell; /* Current number of cells in pNode */ |
| 143369 | 144163 | int nMaxCell; /* Maximum number of cells for pNode */ |
| 143370 | 144164 | |
| 143371 | 144165 | nMaxCell = (pRtree->iNodeSize-4)/pRtree->nBytesPerCell; |
| | @@ -143382,12 +144176,11 @@ |
| 143382 | 144176 | } |
| 143383 | 144177 | |
| 143384 | 144178 | /* |
| 143385 | 144179 | ** If the node is dirty, write it out to the database. |
| 143386 | 144180 | */ |
| 143387 | | -static int |
| 143388 | | -nodeWrite(Rtree *pRtree, RtreeNode *pNode){ |
| 144181 | +static int nodeWrite(Rtree *pRtree, RtreeNode *pNode){ |
| 143389 | 144182 | int rc = SQLITE_OK; |
| 143390 | 144183 | if( pNode->isDirty ){ |
| 143391 | 144184 | sqlite3_stmt *p = pRtree->pWriteNode; |
| 143392 | 144185 | if( pNode->iNode ){ |
| 143393 | 144186 | sqlite3_bind_int64(p, 1, pNode->iNode); |
| | @@ -143408,12 +144201,11 @@ |
| 143408 | 144201 | |
| 143409 | 144202 | /* |
| 143410 | 144203 | ** Release a reference to a node. If the node is dirty and the reference |
| 143411 | 144204 | ** count drops to zero, the node data is written to the database. |
| 143412 | 144205 | */ |
| 143413 | | -static int |
| 143414 | | -nodeRelease(Rtree *pRtree, RtreeNode *pNode){ |
| 144206 | +static int nodeRelease(Rtree *pRtree, RtreeNode *pNode){ |
| 143415 | 144207 | int rc = SQLITE_OK; |
| 143416 | 144208 | if( pNode ){ |
| 143417 | 144209 | assert( pNode->nRef>0 ); |
| 143418 | 144210 | pNode->nRef--; |
| 143419 | 144211 | if( pNode->nRef==0 ){ |
| | @@ -143437,45 +144229,50 @@ |
| 143437 | 144229 | ** Return the 64-bit integer value associated with cell iCell of |
| 143438 | 144230 | ** node pNode. If pNode is a leaf node, this is a rowid. If it is |
| 143439 | 144231 | ** an internal node, then the 64-bit integer is a child page number. |
| 143440 | 144232 | */ |
| 143441 | 144233 | static i64 nodeGetRowid( |
| 143442 | | - Rtree *pRtree, |
| 143443 | | - RtreeNode *pNode, |
| 143444 | | - int iCell |
| 144234 | + Rtree *pRtree, /* The overall R-Tree */ |
| 144235 | + RtreeNode *pNode, /* The node from which to extract the ID */ |
| 144236 | + int iCell /* The cell index from which to extract the ID */ |
| 143445 | 144237 | ){ |
| 143446 | 144238 | assert( iCell<NCELL(pNode) ); |
| 143447 | 144239 | return readInt64(&pNode->zData[4 + pRtree->nBytesPerCell*iCell]); |
| 143448 | 144240 | } |
| 143449 | 144241 | |
| 143450 | 144242 | /* |
| 143451 | 144243 | ** Return coordinate iCoord from cell iCell in node pNode. |
| 143452 | 144244 | */ |
| 143453 | 144245 | static void nodeGetCoord( |
| 143454 | | - Rtree *pRtree, |
| 143455 | | - RtreeNode *pNode, |
| 143456 | | - int iCell, |
| 143457 | | - int iCoord, |
| 143458 | | - RtreeCoord *pCoord /* Space to write result to */ |
| 144246 | + Rtree *pRtree, /* The overall R-Tree */ |
| 144247 | + RtreeNode *pNode, /* The node from which to extract a coordinate */ |
| 144248 | + int iCell, /* The index of the cell within the node */ |
| 144249 | + int iCoord, /* Which coordinate to extract */ |
| 144250 | + RtreeCoord *pCoord /* OUT: Space to write result to */ |
| 143459 | 144251 | ){ |
| 143460 | 144252 | readCoord(&pNode->zData[12 + pRtree->nBytesPerCell*iCell + 4*iCoord], pCoord); |
| 143461 | 144253 | } |
| 143462 | 144254 | |
| 143463 | 144255 | /* |
| 143464 | 144256 | ** Deserialize cell iCell of node pNode. Populate the structure pointed |
| 143465 | 144257 | ** to by pCell with the results. |
| 143466 | 144258 | */ |
| 143467 | 144259 | static void nodeGetCell( |
| 143468 | | - Rtree *pRtree, |
| 143469 | | - RtreeNode *pNode, |
| 143470 | | - int iCell, |
| 143471 | | - RtreeCell *pCell |
| 144260 | + Rtree *pRtree, /* The overall R-Tree */ |
| 144261 | + RtreeNode *pNode, /* The node containing the cell to be read */ |
| 144262 | + int iCell, /* Index of the cell within the node */ |
| 144263 | + RtreeCell *pCell /* OUT: Write the cell contents here */ |
| 143472 | 144264 | ){ |
| 143473 | | - int ii; |
| 144265 | + u8 *pData; |
| 144266 | + u8 *pEnd; |
| 144267 | + RtreeCoord *pCoord; |
| 143474 | 144268 | pCell->iRowid = nodeGetRowid(pRtree, pNode, iCell); |
| 143475 | | - for(ii=0; ii<pRtree->nDim*2; ii++){ |
| 143476 | | - nodeGetCoord(pRtree, pNode, iCell, ii, &pCell->aCoord[ii]); |
| 144269 | + pData = pNode->zData + (12 + pRtree->nBytesPerCell*iCell); |
| 144270 | + pEnd = pData + pRtree->nDim*8; |
| 144271 | + pCoord = pCell->aCoord; |
| 144272 | + for(; pData<pEnd; pData+=4, pCoord++){ |
| 144273 | + readCoord(pData, pCoord); |
| 143477 | 144274 | } |
| 143478 | 144275 | } |
| 143479 | 144276 | |
| 143480 | 144277 | |
| 143481 | 144278 | /* Forward declaration for the function that does the work of |
| | @@ -143597,14 +144394,14 @@ |
| 143597 | 144394 | */ |
| 143598 | 144395 | static void freeCursorConstraints(RtreeCursor *pCsr){ |
| 143599 | 144396 | if( pCsr->aConstraint ){ |
| 143600 | 144397 | int i; /* Used to iterate through constraint array */ |
| 143601 | 144398 | for(i=0; i<pCsr->nConstraint; i++){ |
| 143602 | | - sqlite3_rtree_geometry *pGeom = pCsr->aConstraint[i].pGeom; |
| 143603 | | - if( pGeom ){ |
| 143604 | | - if( pGeom->xDelUser ) pGeom->xDelUser(pGeom->pUser); |
| 143605 | | - sqlite3_free(pGeom); |
| 144399 | + sqlite3_rtree_query_info *pInfo = pCsr->aConstraint[i].pInfo; |
| 144400 | + if( pInfo ){ |
| 144401 | + if( pInfo->xDelUser ) pInfo->xDelUser(pInfo->pUser); |
| 144402 | + sqlite3_free(pInfo); |
| 143606 | 144403 | } |
| 143607 | 144404 | } |
| 143608 | 144405 | sqlite3_free(pCsr->aConstraint); |
| 143609 | 144406 | pCsr->aConstraint = 0; |
| 143610 | 144407 | } |
| | @@ -143613,16 +144410,17 @@ |
| 143613 | 144410 | /* |
| 143614 | 144411 | ** Rtree virtual table module xClose method. |
| 143615 | 144412 | */ |
| 143616 | 144413 | static int rtreeClose(sqlite3_vtab_cursor *cur){ |
| 143617 | 144414 | Rtree *pRtree = (Rtree *)(cur->pVtab); |
| 143618 | | - int rc; |
| 144415 | + int ii; |
| 143619 | 144416 | RtreeCursor *pCsr = (RtreeCursor *)cur; |
| 143620 | 144417 | freeCursorConstraints(pCsr); |
| 143621 | | - rc = nodeRelease(pRtree, pCsr->pNode); |
| 144418 | + sqlite3_free(pCsr->aPoint); |
| 144419 | + for(ii=0; ii<RTREE_CACHE_SZ; ii++) nodeRelease(pRtree, pCsr->aNode[ii]); |
| 143622 | 144420 | sqlite3_free(pCsr); |
| 143623 | | - return rc; |
| 144421 | + return SQLITE_OK; |
| 143624 | 144422 | } |
| 143625 | 144423 | |
| 143626 | 144424 | /* |
| 143627 | 144425 | ** Rtree virtual table module xEof method. |
| 143628 | 144426 | ** |
| | @@ -143629,198 +144427,168 @@ |
| 143629 | 144427 | ** Return non-zero if the cursor does not currently point to a valid |
| 143630 | 144428 | ** record (i.e if the scan has finished), or zero otherwise. |
| 143631 | 144429 | */ |
| 143632 | 144430 | static int rtreeEof(sqlite3_vtab_cursor *cur){ |
| 143633 | 144431 | RtreeCursor *pCsr = (RtreeCursor *)cur; |
| 143634 | | - return (pCsr->pNode==0); |
| 143635 | | -} |
| 143636 | | - |
| 143637 | | -/* |
| 143638 | | -** The r-tree constraint passed as the second argument to this function is |
| 143639 | | -** guaranteed to be a MATCH constraint. |
| 143640 | | -*/ |
| 143641 | | -static int testRtreeGeom( |
| 143642 | | - Rtree *pRtree, /* R-Tree object */ |
| 143643 | | - RtreeConstraint *pConstraint, /* MATCH constraint to test */ |
| 143644 | | - RtreeCell *pCell, /* Cell to test */ |
| 143645 | | - int *pbRes /* OUT: Test result */ |
| 143646 | | -){ |
| 143647 | | - int i; |
| 143648 | | - RtreeDValue aCoord[RTREE_MAX_DIMENSIONS*2]; |
| 143649 | | - int nCoord = pRtree->nDim*2; |
| 143650 | | - |
| 143651 | | - assert( pConstraint->op==RTREE_MATCH ); |
| 143652 | | - assert( pConstraint->pGeom ); |
| 143653 | | - |
| 143654 | | - for(i=0; i<nCoord; i++){ |
| 143655 | | - aCoord[i] = DCOORD(pCell->aCoord[i]); |
| 143656 | | - } |
| 143657 | | - return pConstraint->xGeom(pConstraint->pGeom, nCoord, aCoord, pbRes); |
| 143658 | | -} |
| 143659 | | - |
| 143660 | | -/* |
| 143661 | | -** Cursor pCursor currently points to a cell in a non-leaf page. |
| 143662 | | -** Set *pbEof to true if the sub-tree headed by the cell is filtered |
| 143663 | | -** (excluded) by the constraints in the pCursor->aConstraint[] |
| 143664 | | -** array, or false otherwise. |
| 143665 | | -** |
| 143666 | | -** Return SQLITE_OK if successful or an SQLite error code if an error |
| 143667 | | -** occurs within a geometry callback. |
| 143668 | | -*/ |
| 143669 | | -static int testRtreeCell(Rtree *pRtree, RtreeCursor *pCursor, int *pbEof){ |
| 143670 | | - RtreeCell cell; |
| 143671 | | - int ii; |
| 143672 | | - int bRes = 0; |
| 143673 | | - int rc = SQLITE_OK; |
| 143674 | | - |
| 143675 | | - nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell); |
| 143676 | | - for(ii=0; bRes==0 && ii<pCursor->nConstraint; ii++){ |
| 143677 | | - RtreeConstraint *p = &pCursor->aConstraint[ii]; |
| 143678 | | - RtreeDValue cell_min = DCOORD(cell.aCoord[(p->iCoord>>1)*2]); |
| 143679 | | - RtreeDValue cell_max = DCOORD(cell.aCoord[(p->iCoord>>1)*2+1]); |
| 143680 | | - |
| 143681 | | - assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE |
| 143682 | | - || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH |
| 143683 | | - ); |
| 143684 | | - |
| 143685 | | - switch( p->op ){ |
| 143686 | | - case RTREE_LE: case RTREE_LT: |
| 143687 | | - bRes = p->rValue<cell_min; |
| 143688 | | - break; |
| 143689 | | - |
| 143690 | | - case RTREE_GE: case RTREE_GT: |
| 143691 | | - bRes = p->rValue>cell_max; |
| 143692 | | - break; |
| 143693 | | - |
| 143694 | | - case RTREE_EQ: |
| 143695 | | - bRes = (p->rValue>cell_max || p->rValue<cell_min); |
| 143696 | | - break; |
| 143697 | | - |
| 143698 | | - default: { |
| 143699 | | - assert( p->op==RTREE_MATCH ); |
| 143700 | | - rc = testRtreeGeom(pRtree, p, &cell, &bRes); |
| 143701 | | - bRes = !bRes; |
| 143702 | | - break; |
| 143703 | | - } |
| 143704 | | - } |
| 143705 | | - } |
| 143706 | | - |
| 143707 | | - *pbEof = bRes; |
| 143708 | | - return rc; |
| 143709 | | -} |
| 143710 | | - |
| 143711 | | -/* |
| 143712 | | -** Test if the cell that cursor pCursor currently points to |
| 143713 | | -** would be filtered (excluded) by the constraints in the |
| 143714 | | -** pCursor->aConstraint[] array. If so, set *pbEof to true before |
| 143715 | | -** returning. If the cell is not filtered (excluded) by the constraints, |
| 143716 | | -** set pbEof to zero. |
| 143717 | | -** |
| 143718 | | -** Return SQLITE_OK if successful or an SQLite error code if an error |
| 143719 | | -** occurs within a geometry callback. |
| 143720 | | -** |
| 143721 | | -** This function assumes that the cell is part of a leaf node. |
| 143722 | | -*/ |
| 143723 | | -static int testRtreeEntry(Rtree *pRtree, RtreeCursor *pCursor, int *pbEof){ |
| 143724 | | - RtreeCell cell; |
| 143725 | | - int ii; |
| 143726 | | - *pbEof = 0; |
| 143727 | | - |
| 143728 | | - nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell); |
| 143729 | | - for(ii=0; ii<pCursor->nConstraint; ii++){ |
| 143730 | | - RtreeConstraint *p = &pCursor->aConstraint[ii]; |
| 143731 | | - RtreeDValue coord = DCOORD(cell.aCoord[p->iCoord]); |
| 143732 | | - int res; |
| 143733 | | - assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE |
| 143734 | | - || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH |
| 143735 | | - ); |
| 143736 | | - switch( p->op ){ |
| 143737 | | - case RTREE_LE: res = (coord<=p->rValue); break; |
| 143738 | | - case RTREE_LT: res = (coord<p->rValue); break; |
| 143739 | | - case RTREE_GE: res = (coord>=p->rValue); break; |
| 143740 | | - case RTREE_GT: res = (coord>p->rValue); break; |
| 143741 | | - case RTREE_EQ: res = (coord==p->rValue); break; |
| 143742 | | - default: { |
| 143743 | | - int rc; |
| 143744 | | - assert( p->op==RTREE_MATCH ); |
| 143745 | | - rc = testRtreeGeom(pRtree, p, &cell, &res); |
| 143746 | | - if( rc!=SQLITE_OK ){ |
| 143747 | | - return rc; |
| 143748 | | - } |
| 143749 | | - break; |
| 143750 | | - } |
| 143751 | | - } |
| 143752 | | - |
| 143753 | | - if( !res ){ |
| 143754 | | - *pbEof = 1; |
| 143755 | | - return SQLITE_OK; |
| 143756 | | - } |
| 143757 | | - } |
| 143758 | | - |
| 143759 | | - return SQLITE_OK; |
| 143760 | | -} |
| 143761 | | - |
| 143762 | | -/* |
| 143763 | | -** Cursor pCursor currently points at a node that heads a sub-tree of |
| 143764 | | -** height iHeight (if iHeight==0, then the node is a leaf). Descend |
| 143765 | | -** to point to the left-most cell of the sub-tree that matches the |
| 143766 | | -** configured constraints. |
| 143767 | | -*/ |
| 143768 | | -static int descendToCell( |
| 143769 | | - Rtree *pRtree, |
| 143770 | | - RtreeCursor *pCursor, |
| 143771 | | - int iHeight, |
| 143772 | | - int *pEof /* OUT: Set to true if cannot descend */ |
| 143773 | | -){ |
| 143774 | | - int isEof; |
| 143775 | | - int rc; |
| 143776 | | - int ii; |
| 143777 | | - RtreeNode *pChild; |
| 143778 | | - sqlite3_int64 iRowid; |
| 143779 | | - |
| 143780 | | - RtreeNode *pSavedNode = pCursor->pNode; |
| 143781 | | - int iSavedCell = pCursor->iCell; |
| 143782 | | - |
| 143783 | | - assert( iHeight>=0 ); |
| 143784 | | - |
| 143785 | | - if( iHeight==0 ){ |
| 143786 | | - rc = testRtreeEntry(pRtree, pCursor, &isEof); |
| 143787 | | - }else{ |
| 143788 | | - rc = testRtreeCell(pRtree, pCursor, &isEof); |
| 143789 | | - } |
| 143790 | | - if( rc!=SQLITE_OK || isEof || iHeight==0 ){ |
| 143791 | | - goto descend_to_cell_out; |
| 143792 | | - } |
| 143793 | | - |
| 143794 | | - iRowid = nodeGetRowid(pRtree, pCursor->pNode, pCursor->iCell); |
| 143795 | | - rc = nodeAcquire(pRtree, iRowid, pCursor->pNode, &pChild); |
| 143796 | | - if( rc!=SQLITE_OK ){ |
| 143797 | | - goto descend_to_cell_out; |
| 143798 | | - } |
| 143799 | | - |
| 143800 | | - nodeRelease(pRtree, pCursor->pNode); |
| 143801 | | - pCursor->pNode = pChild; |
| 143802 | | - isEof = 1; |
| 143803 | | - for(ii=0; isEof && ii<NCELL(pChild); ii++){ |
| 143804 | | - pCursor->iCell = ii; |
| 143805 | | - rc = descendToCell(pRtree, pCursor, iHeight-1, &isEof); |
| 143806 | | - if( rc!=SQLITE_OK ){ |
| 143807 | | - goto descend_to_cell_out; |
| 143808 | | - } |
| 143809 | | - } |
| 143810 | | - |
| 143811 | | - if( isEof ){ |
| 143812 | | - assert( pCursor->pNode==pChild ); |
| 143813 | | - nodeReference(pSavedNode); |
| 143814 | | - nodeRelease(pRtree, pChild); |
| 143815 | | - pCursor->pNode = pSavedNode; |
| 143816 | | - pCursor->iCell = iSavedCell; |
| 143817 | | - } |
| 143818 | | - |
| 143819 | | -descend_to_cell_out: |
| 143820 | | - *pEof = isEof; |
| 143821 | | - return rc; |
| 144432 | + return pCsr->atEOF; |
| 144433 | +} |
| 144434 | + |
| 144435 | +/* |
| 144436 | +** Convert raw bits from the on-disk RTree record into a coordinate value. |
| 144437 | +** The on-disk format is big-endian and needs to be converted for little- |
| 144438 | +** endian platforms. The on-disk record stores integer coordinates if |
| 144439 | +** eInt is true and it stores 32-bit floating point records if eInt is |
| 144440 | +** false. a[] is the four bytes of the on-disk record to be decoded. |
| 144441 | +** Store the results in "r". |
| 144442 | +** |
| 144443 | +** There are three versions of this macro, one each for little-endian and |
| 144444 | +** big-endian processors and a third generic implementation. The endian- |
| 144445 | +** specific implementations are much faster and are preferred if the |
| 144446 | +** processor endianness is known at compile-time. The SQLITE_BYTEORDER |
| 144447 | +** macro is part of sqliteInt.h and hence the endian-specific |
| 144448 | +** implementation will only be used if this module is compiled as part |
| 144449 | +** of the amalgamation. |
| 144450 | +*/ |
| 144451 | +#if defined(SQLITE_BYTEORDER) && SQLITE_BYTEORDER==1234 |
| 144452 | +#define RTREE_DECODE_COORD(eInt, a, r) { \ |
| 144453 | + RtreeCoord c; /* Coordinate decoded */ \ |
| 144454 | + memcpy(&c.u,a,4); \ |
| 144455 | + c.u = ((c.u>>24)&0xff)|((c.u>>8)&0xff00)| \ |
| 144456 | + ((c.u&0xff)<<24)|((c.u&0xff00)<<8); \ |
| 144457 | + r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \ |
| 144458 | +} |
| 144459 | +#elif defined(SQLITE_BYTEORDER) && SQLITE_BYTEORDER==4321 |
| 144460 | +#define RTREE_DECODE_COORD(eInt, a, r) { \ |
| 144461 | + RtreeCoord c; /* Coordinate decoded */ \ |
| 144462 | + memcpy(&c.u,a,4); \ |
| 144463 | + r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \ |
| 144464 | +} |
| 144465 | +#else |
| 144466 | +#define RTREE_DECODE_COORD(eInt, a, r) { \ |
| 144467 | + RtreeCoord c; /* Coordinate decoded */ \ |
| 144468 | + c.u = ((u32)a[0]<<24) + ((u32)a[1]<<16) \ |
| 144469 | + +((u32)a[2]<<8) + a[3]; \ |
| 144470 | + r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \ |
| 144471 | +} |
| 144472 | +#endif |
| 144473 | + |
| 144474 | +/* |
| 144475 | +** Check the RTree node or entry given by pCellData and p against the MATCH |
| 144476 | +** constraint pConstraint. |
| 144477 | +*/ |
| 144478 | +static int rtreeCallbackConstraint( |
| 144479 | + RtreeConstraint *pConstraint, /* The constraint to test */ |
| 144480 | + int eInt, /* True if RTree holding integer coordinates */ |
| 144481 | + u8 *pCellData, /* Raw cell content */ |
| 144482 | + RtreeSearchPoint *pSearch, /* Container of this cell */ |
| 144483 | + sqlite3_rtree_dbl *prScore, /* OUT: score for the cell */ |
| 144484 | + int *peWithin /* OUT: visibility of the cell */ |
| 144485 | +){ |
| 144486 | + int i; /* Loop counter */ |
| 144487 | + sqlite3_rtree_query_info *pInfo = pConstraint->pInfo; /* Callback info */ |
| 144488 | + int nCoord = pInfo->nCoord; /* No. of coordinates */ |
| 144489 | + int rc; /* Callback return code */ |
| 144490 | + sqlite3_rtree_dbl aCoord[RTREE_MAX_DIMENSIONS*2]; /* Decoded coordinates */ |
| 144491 | + |
| 144492 | + assert( pConstraint->op==RTREE_MATCH || pConstraint->op==RTREE_QUERY ); |
| 144493 | + assert( nCoord==2 || nCoord==4 || nCoord==6 || nCoord==8 || nCoord==10 ); |
| 144494 | + |
| 144495 | + if( pConstraint->op==RTREE_QUERY && pSearch->iLevel==1 ){ |
| 144496 | + pInfo->iRowid = readInt64(pCellData); |
| 144497 | + } |
| 144498 | + pCellData += 8; |
| 144499 | + for(i=0; i<nCoord; i++, pCellData += 4){ |
| 144500 | + RTREE_DECODE_COORD(eInt, pCellData, aCoord[i]); |
| 144501 | + } |
| 144502 | + if( pConstraint->op==RTREE_MATCH ){ |
| 144503 | + rc = pConstraint->u.xGeom((sqlite3_rtree_geometry*)pInfo, |
| 144504 | + nCoord, aCoord, &i); |
| 144505 | + if( i==0 ) *peWithin = NOT_WITHIN; |
| 144506 | + *prScore = RTREE_ZERO; |
| 144507 | + }else{ |
| 144508 | + pInfo->aCoord = aCoord; |
| 144509 | + pInfo->iLevel = pSearch->iLevel - 1; |
| 144510 | + pInfo->rScore = pInfo->rParentScore = pSearch->rScore; |
| 144511 | + pInfo->eWithin = pInfo->eParentWithin = pSearch->eWithin; |
| 144512 | + rc = pConstraint->u.xQueryFunc(pInfo); |
| 144513 | + if( pInfo->eWithin<*peWithin ) *peWithin = pInfo->eWithin; |
| 144514 | + if( pInfo->rScore<*prScore || *prScore<RTREE_ZERO ){ |
| 144515 | + *prScore = pInfo->rScore; |
| 144516 | + } |
| 144517 | + } |
| 144518 | + return rc; |
| 144519 | +} |
| 144520 | + |
| 144521 | +/* |
| 144522 | +** Check the internal RTree node given by pCellData against constraint p. |
| 144523 | +** If this constraint cannot be satisfied by any child within the node, |
| 144524 | +** set *peWithin to NOT_WITHIN. |
| 144525 | +*/ |
| 144526 | +static void rtreeNonleafConstraint( |
| 144527 | + RtreeConstraint *p, /* The constraint to test */ |
| 144528 | + int eInt, /* True if RTree holds integer coordinates */ |
| 144529 | + u8 *pCellData, /* Raw cell content as appears on disk */ |
| 144530 | + int *peWithin /* Adjust downward, as appropriate */ |
| 144531 | +){ |
| 144532 | + sqlite3_rtree_dbl val; /* Coordinate value convert to a double */ |
| 144533 | + |
| 144534 | + /* p->iCoord might point to either a lower or upper bound coordinate |
| 144535 | + ** in a coordinate pair. But make pCellData point to the lower bound. |
| 144536 | + */ |
| 144537 | + pCellData += 8 + 4*(p->iCoord&0xfe); |
| 144538 | + |
| 144539 | + assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE |
| 144540 | + || p->op==RTREE_GT || p->op==RTREE_EQ ); |
| 144541 | + switch( p->op ){ |
| 144542 | + case RTREE_LE: |
| 144543 | + case RTREE_LT: |
| 144544 | + case RTREE_EQ: |
| 144545 | + RTREE_DECODE_COORD(eInt, pCellData, val); |
| 144546 | + /* val now holds the lower bound of the coordinate pair */ |
| 144547 | + if( p->u.rValue>=val ) return; |
| 144548 | + if( p->op!=RTREE_EQ ) break; /* RTREE_LE and RTREE_LT end here */ |
| 144549 | + /* Fall through for the RTREE_EQ case */ |
| 144550 | + |
| 144551 | + default: /* RTREE_GT or RTREE_GE, or fallthrough of RTREE_EQ */ |
| 144552 | + pCellData += 4; |
| 144553 | + RTREE_DECODE_COORD(eInt, pCellData, val); |
| 144554 | + /* val now holds the upper bound of the coordinate pair */ |
| 144555 | + if( p->u.rValue<=val ) return; |
| 144556 | + } |
| 144557 | + *peWithin = NOT_WITHIN; |
| 144558 | +} |
| 144559 | + |
| 144560 | +/* |
| 144561 | +** Check the leaf RTree cell given by pCellData against constraint p. |
| 144562 | +** If this constraint is not satisfied, set *peWithin to NOT_WITHIN. |
| 144563 | +** If the constraint is satisfied, leave *peWithin unchanged. |
| 144564 | +** |
| 144565 | +** The constraint is of the form: xN op $val |
| 144566 | +** |
| 144567 | +** The op is given by p->op. The xN is p->iCoord-th coordinate in |
| 144568 | +** pCellData. $val is given by p->u.rValue. |
| 144569 | +*/ |
| 144570 | +static void rtreeLeafConstraint( |
| 144571 | + RtreeConstraint *p, /* The constraint to test */ |
| 144572 | + int eInt, /* True if RTree holds integer coordinates */ |
| 144573 | + u8 *pCellData, /* Raw cell content as appears on disk */ |
| 144574 | + int *peWithin /* Adjust downward, as appropriate */ |
| 144575 | +){ |
| 144576 | + RtreeDValue xN; /* Coordinate value converted to a double */ |
| 144577 | + |
| 144578 | + assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE |
| 144579 | + || p->op==RTREE_GT || p->op==RTREE_EQ ); |
| 144580 | + pCellData += 8 + p->iCoord*4; |
| 144581 | + RTREE_DECODE_COORD(eInt, pCellData, xN); |
| 144582 | + switch( p->op ){ |
| 144583 | + case RTREE_LE: if( xN <= p->u.rValue ) return; break; |
| 144584 | + case RTREE_LT: if( xN < p->u.rValue ) return; break; |
| 144585 | + case RTREE_GE: if( xN >= p->u.rValue ) return; break; |
| 144586 | + case RTREE_GT: if( xN > p->u.rValue ) return; break; |
| 144587 | + default: if( xN == p->u.rValue ) return; break; |
| 144588 | + } |
| 144589 | + *peWithin = NOT_WITHIN; |
| 143822 | 144590 | } |
| 143823 | 144591 | |
| 143824 | 144592 | /* |
| 143825 | 144593 | ** One of the cells in node pNode is guaranteed to have a 64-bit |
| 143826 | 144594 | ** integer value equal to iRowid. Return the index of this cell. |
| | @@ -143831,10 +144599,11 @@ |
| 143831 | 144599 | i64 iRowid, |
| 143832 | 144600 | int *piIndex |
| 143833 | 144601 | ){ |
| 143834 | 144602 | int ii; |
| 143835 | 144603 | int nCell = NCELL(pNode); |
| 144604 | + assert( nCell<200 ); |
| 143836 | 144605 | for(ii=0; ii<nCell; ii++){ |
| 143837 | 144606 | if( nodeGetRowid(pRtree, pNode, ii)==iRowid ){ |
| 143838 | 144607 | *piIndex = ii; |
| 143839 | 144608 | return SQLITE_OK; |
| 143840 | 144609 | } |
| | @@ -143852,82 +144621,342 @@ |
| 143852 | 144621 | return nodeRowidIndex(pRtree, pParent, pNode->iNode, piIndex); |
| 143853 | 144622 | } |
| 143854 | 144623 | *piIndex = -1; |
| 143855 | 144624 | return SQLITE_OK; |
| 143856 | 144625 | } |
| 144626 | + |
| 144627 | +/* |
| 144628 | +** Compare two search points. Return negative, zero, or positive if the first |
| 144629 | +** is less than, equal to, or greater than the second. |
| 144630 | +** |
| 144631 | +** The rScore is the primary key. Smaller rScore values come first. |
| 144632 | +** If the rScore is a tie, then use iLevel as the tie breaker with smaller |
| 144633 | +** iLevel values coming first. In this way, if rScore is the same for all |
| 144634 | +** SearchPoints, then iLevel becomes the deciding factor and the result |
| 144635 | +** is a depth-first search, which is the desired default behavior. |
| 144636 | +*/ |
| 144637 | +static int rtreeSearchPointCompare( |
| 144638 | + const RtreeSearchPoint *pA, |
| 144639 | + const RtreeSearchPoint *pB |
| 144640 | +){ |
| 144641 | + if( pA->rScore<pB->rScore ) return -1; |
| 144642 | + if( pA->rScore>pB->rScore ) return +1; |
| 144643 | + if( pA->iLevel<pB->iLevel ) return -1; |
| 144644 | + if( pA->iLevel>pB->iLevel ) return +1; |
| 144645 | + return 0; |
| 144646 | +} |
| 144647 | + |
| 144648 | +/* |
| 144649 | +** Interchange to search points in a cursor. |
| 144650 | +*/ |
| 144651 | +static void rtreeSearchPointSwap(RtreeCursor *p, int i, int j){ |
| 144652 | + RtreeSearchPoint t = p->aPoint[i]; |
| 144653 | + assert( i<j ); |
| 144654 | + p->aPoint[i] = p->aPoint[j]; |
| 144655 | + p->aPoint[j] = t; |
| 144656 | + i++; j++; |
| 144657 | + if( i<RTREE_CACHE_SZ ){ |
| 144658 | + if( j>=RTREE_CACHE_SZ ){ |
| 144659 | + nodeRelease(RTREE_OF_CURSOR(p), p->aNode[i]); |
| 144660 | + p->aNode[i] = 0; |
| 144661 | + }else{ |
| 144662 | + RtreeNode *pTemp = p->aNode[i]; |
| 144663 | + p->aNode[i] = p->aNode[j]; |
| 144664 | + p->aNode[j] = pTemp; |
| 144665 | + } |
| 144666 | + } |
| 144667 | +} |
| 144668 | + |
| 144669 | +/* |
| 144670 | +** Return the search point with the lowest current score. |
| 144671 | +*/ |
| 144672 | +static RtreeSearchPoint *rtreeSearchPointFirst(RtreeCursor *pCur){ |
| 144673 | + return pCur->bPoint ? &pCur->sPoint : pCur->nPoint ? pCur->aPoint : 0; |
| 144674 | +} |
| 144675 | + |
| 144676 | +/* |
| 144677 | +** Get the RtreeNode for the search point with the lowest score. |
| 144678 | +*/ |
| 144679 | +static RtreeNode *rtreeNodeOfFirstSearchPoint(RtreeCursor *pCur, int *pRC){ |
| 144680 | + sqlite3_int64 id; |
| 144681 | + int ii = 1 - pCur->bPoint; |
| 144682 | + assert( ii==0 || ii==1 ); |
| 144683 | + assert( pCur->bPoint || pCur->nPoint ); |
| 144684 | + if( pCur->aNode[ii]==0 ){ |
| 144685 | + assert( pRC!=0 ); |
| 144686 | + id = ii ? pCur->aPoint[0].id : pCur->sPoint.id; |
| 144687 | + *pRC = nodeAcquire(RTREE_OF_CURSOR(pCur), id, 0, &pCur->aNode[ii]); |
| 144688 | + } |
| 144689 | + return pCur->aNode[ii]; |
| 144690 | +} |
| 144691 | + |
| 144692 | +/* |
| 144693 | +** Push a new element onto the priority queue |
| 144694 | +*/ |
| 144695 | +static RtreeSearchPoint *rtreeEnqueue( |
| 144696 | + RtreeCursor *pCur, /* The cursor */ |
| 144697 | + RtreeDValue rScore, /* Score for the new search point */ |
| 144698 | + u8 iLevel /* Level for the new search point */ |
| 144699 | +){ |
| 144700 | + int i, j; |
| 144701 | + RtreeSearchPoint *pNew; |
| 144702 | + if( pCur->nPoint>=pCur->nPointAlloc ){ |
| 144703 | + int nNew = pCur->nPointAlloc*2 + 8; |
| 144704 | + pNew = sqlite3_realloc(pCur->aPoint, nNew*sizeof(pCur->aPoint[0])); |
| 144705 | + if( pNew==0 ) return 0; |
| 144706 | + pCur->aPoint = pNew; |
| 144707 | + pCur->nPointAlloc = nNew; |
| 144708 | + } |
| 144709 | + i = pCur->nPoint++; |
| 144710 | + pNew = pCur->aPoint + i; |
| 144711 | + pNew->rScore = rScore; |
| 144712 | + pNew->iLevel = iLevel; |
| 144713 | + assert( iLevel>=0 && iLevel<=RTREE_MAX_DEPTH ); |
| 144714 | + while( i>0 ){ |
| 144715 | + RtreeSearchPoint *pParent; |
| 144716 | + j = (i-1)/2; |
| 144717 | + pParent = pCur->aPoint + j; |
| 144718 | + if( rtreeSearchPointCompare(pNew, pParent)>=0 ) break; |
| 144719 | + rtreeSearchPointSwap(pCur, j, i); |
| 144720 | + i = j; |
| 144721 | + pNew = pParent; |
| 144722 | + } |
| 144723 | + return pNew; |
| 144724 | +} |
| 144725 | + |
| 144726 | +/* |
| 144727 | +** Allocate a new RtreeSearchPoint and return a pointer to it. Return |
| 144728 | +** NULL if malloc fails. |
| 144729 | +*/ |
| 144730 | +static RtreeSearchPoint *rtreeSearchPointNew( |
| 144731 | + RtreeCursor *pCur, /* The cursor */ |
| 144732 | + RtreeDValue rScore, /* Score for the new search point */ |
| 144733 | + u8 iLevel /* Level for the new search point */ |
| 144734 | +){ |
| 144735 | + RtreeSearchPoint *pNew, *pFirst; |
| 144736 | + pFirst = rtreeSearchPointFirst(pCur); |
| 144737 | + pCur->anQueue[iLevel]++; |
| 144738 | + if( pFirst==0 |
| 144739 | + || pFirst->rScore>rScore |
| 144740 | + || (pFirst->rScore==rScore && pFirst->iLevel>iLevel) |
| 144741 | + ){ |
| 144742 | + if( pCur->bPoint ){ |
| 144743 | + int ii; |
| 144744 | + pNew = rtreeEnqueue(pCur, rScore, iLevel); |
| 144745 | + if( pNew==0 ) return 0; |
| 144746 | + ii = (int)(pNew - pCur->aPoint) + 1; |
| 144747 | + if( ii<RTREE_CACHE_SZ ){ |
| 144748 | + assert( pCur->aNode[ii]==0 ); |
| 144749 | + pCur->aNode[ii] = pCur->aNode[0]; |
| 144750 | + }else{ |
| 144751 | + nodeRelease(RTREE_OF_CURSOR(pCur), pCur->aNode[0]); |
| 144752 | + } |
| 144753 | + pCur->aNode[0] = 0; |
| 144754 | + *pNew = pCur->sPoint; |
| 144755 | + } |
| 144756 | + pCur->sPoint.rScore = rScore; |
| 144757 | + pCur->sPoint.iLevel = iLevel; |
| 144758 | + pCur->bPoint = 1; |
| 144759 | + return &pCur->sPoint; |
| 144760 | + }else{ |
| 144761 | + return rtreeEnqueue(pCur, rScore, iLevel); |
| 144762 | + } |
| 144763 | +} |
| 144764 | + |
| 144765 | +#if 0 |
| 144766 | +/* Tracing routines for the RtreeSearchPoint queue */ |
| 144767 | +static void tracePoint(RtreeSearchPoint *p, int idx, RtreeCursor *pCur){ |
| 144768 | + if( idx<0 ){ printf(" s"); }else{ printf("%2d", idx); } |
| 144769 | + printf(" %d.%05lld.%02d %g %d", |
| 144770 | + p->iLevel, p->id, p->iCell, p->rScore, p->eWithin |
| 144771 | + ); |
| 144772 | + idx++; |
| 144773 | + if( idx<RTREE_CACHE_SZ ){ |
| 144774 | + printf(" %p\n", pCur->aNode[idx]); |
| 144775 | + }else{ |
| 144776 | + printf("\n"); |
| 144777 | + } |
| 144778 | +} |
| 144779 | +static void traceQueue(RtreeCursor *pCur, const char *zPrefix){ |
| 144780 | + int ii; |
| 144781 | + printf("=== %9s ", zPrefix); |
| 144782 | + if( pCur->bPoint ){ |
| 144783 | + tracePoint(&pCur->sPoint, -1, pCur); |
| 144784 | + } |
| 144785 | + for(ii=0; ii<pCur->nPoint; ii++){ |
| 144786 | + if( ii>0 || pCur->bPoint ) printf(" "); |
| 144787 | + tracePoint(&pCur->aPoint[ii], ii, pCur); |
| 144788 | + } |
| 144789 | +} |
| 144790 | +# define RTREE_QUEUE_TRACE(A,B) traceQueue(A,B) |
| 144791 | +#else |
| 144792 | +# define RTREE_QUEUE_TRACE(A,B) /* no-op */ |
| 144793 | +#endif |
| 144794 | + |
| 144795 | +/* Remove the search point with the lowest current score. |
| 144796 | +*/ |
| 144797 | +static void rtreeSearchPointPop(RtreeCursor *p){ |
| 144798 | + int i, j, k, n; |
| 144799 | + i = 1 - p->bPoint; |
| 144800 | + assert( i==0 || i==1 ); |
| 144801 | + if( p->aNode[i] ){ |
| 144802 | + nodeRelease(RTREE_OF_CURSOR(p), p->aNode[i]); |
| 144803 | + p->aNode[i] = 0; |
| 144804 | + } |
| 144805 | + if( p->bPoint ){ |
| 144806 | + p->anQueue[p->sPoint.iLevel]--; |
| 144807 | + p->bPoint = 0; |
| 144808 | + }else if( p->nPoint ){ |
| 144809 | + p->anQueue[p->aPoint[0].iLevel]--; |
| 144810 | + n = --p->nPoint; |
| 144811 | + p->aPoint[0] = p->aPoint[n]; |
| 144812 | + if( n<RTREE_CACHE_SZ-1 ){ |
| 144813 | + p->aNode[1] = p->aNode[n+1]; |
| 144814 | + p->aNode[n+1] = 0; |
| 144815 | + } |
| 144816 | + i = 0; |
| 144817 | + while( (j = i*2+1)<n ){ |
| 144818 | + k = j+1; |
| 144819 | + if( k<n && rtreeSearchPointCompare(&p->aPoint[k], &p->aPoint[j])<0 ){ |
| 144820 | + if( rtreeSearchPointCompare(&p->aPoint[k], &p->aPoint[i])<0 ){ |
| 144821 | + rtreeSearchPointSwap(p, i, k); |
| 144822 | + i = k; |
| 144823 | + }else{ |
| 144824 | + break; |
| 144825 | + } |
| 144826 | + }else{ |
| 144827 | + if( rtreeSearchPointCompare(&p->aPoint[j], &p->aPoint[i])<0 ){ |
| 144828 | + rtreeSearchPointSwap(p, i, j); |
| 144829 | + i = j; |
| 144830 | + }else{ |
| 144831 | + break; |
| 144832 | + } |
| 144833 | + } |
| 144834 | + } |
| 144835 | + } |
| 144836 | +} |
| 144837 | + |
| 144838 | + |
| 144839 | +/* |
| 144840 | +** Continue the search on cursor pCur until the front of the queue |
| 144841 | +** contains an entry suitable for returning as a result-set row, |
| 144842 | +** or until the RtreeSearchPoint queue is empty, indicating that the |
| 144843 | +** query has completed. |
| 144844 | +*/ |
| 144845 | +static int rtreeStepToLeaf(RtreeCursor *pCur){ |
| 144846 | + RtreeSearchPoint *p; |
| 144847 | + Rtree *pRtree = RTREE_OF_CURSOR(pCur); |
| 144848 | + RtreeNode *pNode; |
| 144849 | + int eWithin; |
| 144850 | + int rc = SQLITE_OK; |
| 144851 | + int nCell; |
| 144852 | + int nConstraint = pCur->nConstraint; |
| 144853 | + int ii; |
| 144854 | + int eInt; |
| 144855 | + RtreeSearchPoint x; |
| 144856 | + |
| 144857 | + eInt = pRtree->eCoordType==RTREE_COORD_INT32; |
| 144858 | + while( (p = rtreeSearchPointFirst(pCur))!=0 && p->iLevel>0 ){ |
| 144859 | + pNode = rtreeNodeOfFirstSearchPoint(pCur, &rc); |
| 144860 | + if( rc ) return rc; |
| 144861 | + nCell = NCELL(pNode); |
| 144862 | + assert( nCell<200 ); |
| 144863 | + while( p->iCell<nCell ){ |
| 144864 | + sqlite3_rtree_dbl rScore = (sqlite3_rtree_dbl)-1; |
| 144865 | + u8 *pCellData = pNode->zData + (4+pRtree->nBytesPerCell*p->iCell); |
| 144866 | + eWithin = FULLY_WITHIN; |
| 144867 | + for(ii=0; ii<nConstraint; ii++){ |
| 144868 | + RtreeConstraint *pConstraint = pCur->aConstraint + ii; |
| 144869 | + if( pConstraint->op>=RTREE_MATCH ){ |
| 144870 | + rc = rtreeCallbackConstraint(pConstraint, eInt, pCellData, p, |
| 144871 | + &rScore, &eWithin); |
| 144872 | + if( rc ) return rc; |
| 144873 | + }else if( p->iLevel==1 ){ |
| 144874 | + rtreeLeafConstraint(pConstraint, eInt, pCellData, &eWithin); |
| 144875 | + }else{ |
| 144876 | + rtreeNonleafConstraint(pConstraint, eInt, pCellData, &eWithin); |
| 144877 | + } |
| 144878 | + if( eWithin==NOT_WITHIN ) break; |
| 144879 | + } |
| 144880 | + p->iCell++; |
| 144881 | + if( eWithin==NOT_WITHIN ) continue; |
| 144882 | + x.iLevel = p->iLevel - 1; |
| 144883 | + if( x.iLevel ){ |
| 144884 | + x.id = readInt64(pCellData); |
| 144885 | + x.iCell = 0; |
| 144886 | + }else{ |
| 144887 | + x.id = p->id; |
| 144888 | + x.iCell = p->iCell - 1; |
| 144889 | + } |
| 144890 | + if( p->iCell>=nCell ){ |
| 144891 | + RTREE_QUEUE_TRACE(pCur, "POP-S:"); |
| 144892 | + rtreeSearchPointPop(pCur); |
| 144893 | + } |
| 144894 | + if( rScore<RTREE_ZERO ) rScore = RTREE_ZERO; |
| 144895 | + p = rtreeSearchPointNew(pCur, rScore, x.iLevel); |
| 144896 | + if( p==0 ) return SQLITE_NOMEM; |
| 144897 | + p->eWithin = eWithin; |
| 144898 | + p->id = x.id; |
| 144899 | + p->iCell = x.iCell; |
| 144900 | + RTREE_QUEUE_TRACE(pCur, "PUSH-S:"); |
| 144901 | + break; |
| 144902 | + } |
| 144903 | + if( p->iCell>=nCell ){ |
| 144904 | + RTREE_QUEUE_TRACE(pCur, "POP-Se:"); |
| 144905 | + rtreeSearchPointPop(pCur); |
| 144906 | + } |
| 144907 | + } |
| 144908 | + pCur->atEOF = p==0; |
| 144909 | + return SQLITE_OK; |
| 144910 | +} |
| 143857 | 144911 | |
| 143858 | 144912 | /* |
| 143859 | 144913 | ** Rtree virtual table module xNext method. |
| 143860 | 144914 | */ |
| 143861 | 144915 | static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){ |
| 143862 | | - Rtree *pRtree = (Rtree *)(pVtabCursor->pVtab); |
| 143863 | 144916 | RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; |
| 143864 | 144917 | int rc = SQLITE_OK; |
| 143865 | 144918 | |
| 143866 | | - /* RtreeCursor.pNode must not be NULL. If is is NULL, then this cursor is |
| 143867 | | - ** already at EOF. It is against the rules to call the xNext() method of |
| 143868 | | - ** a cursor that has already reached EOF. |
| 143869 | | - */ |
| 143870 | | - assert( pCsr->pNode ); |
| 143871 | | - |
| 143872 | | - if( pCsr->iStrategy==1 ){ |
| 143873 | | - /* This "scan" is a direct lookup by rowid. There is no next entry. */ |
| 143874 | | - nodeRelease(pRtree, pCsr->pNode); |
| 143875 | | - pCsr->pNode = 0; |
| 143876 | | - }else{ |
| 143877 | | - /* Move to the next entry that matches the configured constraints. */ |
| 143878 | | - int iHeight = 0; |
| 143879 | | - while( pCsr->pNode ){ |
| 143880 | | - RtreeNode *pNode = pCsr->pNode; |
| 143881 | | - int nCell = NCELL(pNode); |
| 143882 | | - for(pCsr->iCell++; pCsr->iCell<nCell; pCsr->iCell++){ |
| 143883 | | - int isEof; |
| 143884 | | - rc = descendToCell(pRtree, pCsr, iHeight, &isEof); |
| 143885 | | - if( rc!=SQLITE_OK || !isEof ){ |
| 143886 | | - return rc; |
| 143887 | | - } |
| 143888 | | - } |
| 143889 | | - pCsr->pNode = pNode->pParent; |
| 143890 | | - rc = nodeParentIndex(pRtree, pNode, &pCsr->iCell); |
| 143891 | | - if( rc!=SQLITE_OK ){ |
| 143892 | | - return rc; |
| 143893 | | - } |
| 143894 | | - nodeReference(pCsr->pNode); |
| 143895 | | - nodeRelease(pRtree, pNode); |
| 143896 | | - iHeight++; |
| 143897 | | - } |
| 143898 | | - } |
| 143899 | | - |
| 144919 | + /* Move to the next entry that matches the configured constraints. */ |
| 144920 | + RTREE_QUEUE_TRACE(pCsr, "POP-Nx:"); |
| 144921 | + rtreeSearchPointPop(pCsr); |
| 144922 | + rc = rtreeStepToLeaf(pCsr); |
| 143900 | 144923 | return rc; |
| 143901 | 144924 | } |
| 143902 | 144925 | |
| 143903 | 144926 | /* |
| 143904 | 144927 | ** Rtree virtual table module xRowid method. |
| 143905 | 144928 | */ |
| 143906 | 144929 | static int rtreeRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){ |
| 143907 | | - Rtree *pRtree = (Rtree *)pVtabCursor->pVtab; |
| 143908 | 144930 | RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; |
| 143909 | | - |
| 143910 | | - assert(pCsr->pNode); |
| 143911 | | - *pRowid = nodeGetRowid(pRtree, pCsr->pNode, pCsr->iCell); |
| 143912 | | - |
| 143913 | | - return SQLITE_OK; |
| 144931 | + RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr); |
| 144932 | + int rc = SQLITE_OK; |
| 144933 | + RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc); |
| 144934 | + if( rc==SQLITE_OK && p ){ |
| 144935 | + *pRowid = nodeGetRowid(RTREE_OF_CURSOR(pCsr), pNode, p->iCell); |
| 144936 | + } |
| 144937 | + return rc; |
| 143914 | 144938 | } |
| 143915 | 144939 | |
| 143916 | 144940 | /* |
| 143917 | 144941 | ** Rtree virtual table module xColumn method. |
| 143918 | 144942 | */ |
| 143919 | 144943 | static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ |
| 143920 | 144944 | Rtree *pRtree = (Rtree *)cur->pVtab; |
| 143921 | 144945 | RtreeCursor *pCsr = (RtreeCursor *)cur; |
| 144946 | + RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr); |
| 144947 | + RtreeCoord c; |
| 144948 | + int rc = SQLITE_OK; |
| 144949 | + RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc); |
| 143922 | 144950 | |
| 144951 | + if( rc ) return rc; |
| 144952 | + if( p==0 ) return SQLITE_OK; |
| 143923 | 144953 | if( i==0 ){ |
| 143924 | | - i64 iRowid = nodeGetRowid(pRtree, pCsr->pNode, pCsr->iCell); |
| 143925 | | - sqlite3_result_int64(ctx, iRowid); |
| 144954 | + sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell)); |
| 143926 | 144955 | }else{ |
| 143927 | | - RtreeCoord c; |
| 143928 | | - nodeGetCoord(pRtree, pCsr->pNode, pCsr->iCell, i-1, &c); |
| 144956 | + if( rc ) return rc; |
| 144957 | + nodeGetCoord(pRtree, pNode, p->iCell, i-1, &c); |
| 143929 | 144958 | #ifndef SQLITE_RTREE_INT_ONLY |
| 143930 | 144959 | if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ |
| 143931 | 144960 | sqlite3_result_double(ctx, c.f); |
| 143932 | 144961 | }else |
| 143933 | 144962 | #endif |
| | @@ -143934,11 +144963,10 @@ |
| 143934 | 144963 | { |
| 143935 | 144964 | assert( pRtree->eCoordType==RTREE_COORD_INT32 ); |
| 143936 | 144965 | sqlite3_result_int(ctx, c.i); |
| 143937 | 144966 | } |
| 143938 | 144967 | } |
| 143939 | | - |
| 143940 | 144968 | return SQLITE_OK; |
| 143941 | 144969 | } |
| 143942 | 144970 | |
| 143943 | 144971 | /* |
| 143944 | 144972 | ** Use nodeAcquire() to obtain the leaf node containing the record with |
| | @@ -143945,16 +144973,22 @@ |
| 143945 | 144973 | ** rowid iRowid. If successful, set *ppLeaf to point to the node and |
| 143946 | 144974 | ** return SQLITE_OK. If there is no such record in the table, set |
| 143947 | 144975 | ** *ppLeaf to 0 and return SQLITE_OK. If an error occurs, set *ppLeaf |
| 143948 | 144976 | ** to zero and return an SQLite error code. |
| 143949 | 144977 | */ |
| 143950 | | -static int findLeafNode(Rtree *pRtree, i64 iRowid, RtreeNode **ppLeaf){ |
| 144978 | +static int findLeafNode( |
| 144979 | + Rtree *pRtree, /* RTree to search */ |
| 144980 | + i64 iRowid, /* The rowid searching for */ |
| 144981 | + RtreeNode **ppLeaf, /* Write the node here */ |
| 144982 | + sqlite3_int64 *piNode /* Write the node-id here */ |
| 144983 | +){ |
| 143951 | 144984 | int rc; |
| 143952 | 144985 | *ppLeaf = 0; |
| 143953 | 144986 | sqlite3_bind_int64(pRtree->pReadRowid, 1, iRowid); |
| 143954 | 144987 | if( sqlite3_step(pRtree->pReadRowid)==SQLITE_ROW ){ |
| 143955 | 144988 | i64 iNode = sqlite3_column_int64(pRtree->pReadRowid, 0); |
| 144989 | + if( piNode ) *piNode = iNode; |
| 143956 | 144990 | rc = nodeAcquire(pRtree, iNode, 0, ppLeaf); |
| 143957 | 144991 | sqlite3_reset(pRtree->pReadRowid); |
| 143958 | 144992 | }else{ |
| 143959 | 144993 | rc = sqlite3_reset(pRtree->pReadRowid); |
| 143960 | 144994 | } |
| | @@ -143966,13 +145000,14 @@ |
| 143966 | 145000 | ** as the second argument for a MATCH constraint. The value passed as the |
| 143967 | 145001 | ** first argument to this function is the right-hand operand to the MATCH |
| 143968 | 145002 | ** operator. |
| 143969 | 145003 | */ |
| 143970 | 145004 | static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){ |
| 143971 | | - RtreeMatchArg *p; |
| 143972 | | - sqlite3_rtree_geometry *pGeom; |
| 143973 | | - int nBlob; |
| 145005 | + RtreeMatchArg *pBlob; /* BLOB returned by geometry function */ |
| 145006 | + sqlite3_rtree_query_info *pInfo; /* Callback information */ |
| 145007 | + int nBlob; /* Size of the geometry function blob */ |
| 145008 | + int nExpected; /* Expected size of the BLOB */ |
| 143974 | 145009 | |
| 143975 | 145010 | /* Check that value is actually a blob. */ |
| 143976 | 145011 | if( sqlite3_value_type(pValue)!=SQLITE_BLOB ) return SQLITE_ERROR; |
| 143977 | 145012 | |
| 143978 | 145013 | /* Check that the blob is roughly the right size. */ |
| | @@ -143981,31 +145016,33 @@ |
| 143981 | 145016 | || ((nBlob-sizeof(RtreeMatchArg))%sizeof(RtreeDValue))!=0 |
| 143982 | 145017 | ){ |
| 143983 | 145018 | return SQLITE_ERROR; |
| 143984 | 145019 | } |
| 143985 | 145020 | |
| 143986 | | - pGeom = (sqlite3_rtree_geometry *)sqlite3_malloc( |
| 143987 | | - sizeof(sqlite3_rtree_geometry) + nBlob |
| 143988 | | - ); |
| 143989 | | - if( !pGeom ) return SQLITE_NOMEM; |
| 143990 | | - memset(pGeom, 0, sizeof(sqlite3_rtree_geometry)); |
| 143991 | | - p = (RtreeMatchArg *)&pGeom[1]; |
| 143992 | | - |
| 143993 | | - memcpy(p, sqlite3_value_blob(pValue), nBlob); |
| 143994 | | - if( p->magic!=RTREE_GEOMETRY_MAGIC |
| 143995 | | - || nBlob!=(int)(sizeof(RtreeMatchArg) + (p->nParam-1)*sizeof(RtreeDValue)) |
| 143996 | | - ){ |
| 143997 | | - sqlite3_free(pGeom); |
| 145021 | + pInfo = (sqlite3_rtree_query_info*)sqlite3_malloc( sizeof(*pInfo)+nBlob ); |
| 145022 | + if( !pInfo ) return SQLITE_NOMEM; |
| 145023 | + memset(pInfo, 0, sizeof(*pInfo)); |
| 145024 | + pBlob = (RtreeMatchArg*)&pInfo[1]; |
| 145025 | + |
| 145026 | + memcpy(pBlob, sqlite3_value_blob(pValue), nBlob); |
| 145027 | + nExpected = (int)(sizeof(RtreeMatchArg) + |
| 145028 | + (pBlob->nParam-1)*sizeof(RtreeDValue)); |
| 145029 | + if( pBlob->magic!=RTREE_GEOMETRY_MAGIC || nBlob!=nExpected ){ |
| 145030 | + sqlite3_free(pInfo); |
| 143998 | 145031 | return SQLITE_ERROR; |
| 143999 | 145032 | } |
| 145033 | + pInfo->pContext = pBlob->cb.pContext; |
| 145034 | + pInfo->nParam = pBlob->nParam; |
| 145035 | + pInfo->aParam = pBlob->aParam; |
| 144000 | 145036 | |
| 144001 | | - pGeom->pContext = p->pContext; |
| 144002 | | - pGeom->nParam = p->nParam; |
| 144003 | | - pGeom->aParam = p->aParam; |
| 144004 | | - |
| 144005 | | - pCons->xGeom = p->xGeom; |
| 144006 | | - pCons->pGeom = pGeom; |
| 145037 | + if( pBlob->cb.xGeom ){ |
| 145038 | + pCons->u.xGeom = pBlob->cb.xGeom; |
| 145039 | + }else{ |
| 145040 | + pCons->op = RTREE_QUERY; |
| 145041 | + pCons->u.xQueryFunc = pBlob->cb.xQueryFunc; |
| 145042 | + } |
| 145043 | + pCons->pInfo = pInfo; |
| 144007 | 145044 | return SQLITE_OK; |
| 144008 | 145045 | } |
| 144009 | 145046 | |
| 144010 | 145047 | /* |
| 144011 | 145048 | ** Rtree virtual table module xFilter method. |
| | @@ -144015,91 +145052,96 @@ |
| 144015 | 145052 | int idxNum, const char *idxStr, |
| 144016 | 145053 | int argc, sqlite3_value **argv |
| 144017 | 145054 | ){ |
| 144018 | 145055 | Rtree *pRtree = (Rtree *)pVtabCursor->pVtab; |
| 144019 | 145056 | RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; |
| 144020 | | - |
| 144021 | 145057 | RtreeNode *pRoot = 0; |
| 144022 | 145058 | int ii; |
| 144023 | 145059 | int rc = SQLITE_OK; |
| 145060 | + int iCell = 0; |
| 144024 | 145061 | |
| 144025 | 145062 | rtreeReference(pRtree); |
| 144026 | 145063 | |
| 144027 | 145064 | freeCursorConstraints(pCsr); |
| 144028 | 145065 | pCsr->iStrategy = idxNum; |
| 144029 | 145066 | |
| 144030 | 145067 | if( idxNum==1 ){ |
| 144031 | 145068 | /* Special case - lookup by rowid. */ |
| 144032 | 145069 | RtreeNode *pLeaf; /* Leaf on which the required cell resides */ |
| 145070 | + RtreeSearchPoint *p; /* Search point for the the leaf */ |
| 144033 | 145071 | i64 iRowid = sqlite3_value_int64(argv[0]); |
| 144034 | | - rc = findLeafNode(pRtree, iRowid, &pLeaf); |
| 144035 | | - pCsr->pNode = pLeaf; |
| 144036 | | - if( pLeaf ){ |
| 144037 | | - assert( rc==SQLITE_OK ); |
| 144038 | | - rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &pCsr->iCell); |
| 145072 | + i64 iNode = 0; |
| 145073 | + rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode); |
| 145074 | + if( rc==SQLITE_OK && pLeaf!=0 ){ |
| 145075 | + p = rtreeSearchPointNew(pCsr, RTREE_ZERO, 0); |
| 145076 | + assert( p!=0 ); /* Always returns pCsr->sPoint */ |
| 145077 | + pCsr->aNode[0] = pLeaf; |
| 145078 | + p->id = iNode; |
| 145079 | + p->eWithin = PARTLY_WITHIN; |
| 145080 | + rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &iCell); |
| 145081 | + p->iCell = iCell; |
| 145082 | + RTREE_QUEUE_TRACE(pCsr, "PUSH-F1:"); |
| 145083 | + }else{ |
| 145084 | + pCsr->atEOF = 1; |
| 144039 | 145085 | } |
| 144040 | 145086 | }else{ |
| 144041 | 145087 | /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array |
| 144042 | 145088 | ** with the configured constraints. |
| 144043 | 145089 | */ |
| 144044 | | - if( argc>0 ){ |
| 145090 | + rc = nodeAcquire(pRtree, 1, 0, &pRoot); |
| 145091 | + if( rc==SQLITE_OK && argc>0 ){ |
| 144045 | 145092 | pCsr->aConstraint = sqlite3_malloc(sizeof(RtreeConstraint)*argc); |
| 144046 | 145093 | pCsr->nConstraint = argc; |
| 144047 | 145094 | if( !pCsr->aConstraint ){ |
| 144048 | 145095 | rc = SQLITE_NOMEM; |
| 144049 | 145096 | }else{ |
| 144050 | 145097 | memset(pCsr->aConstraint, 0, sizeof(RtreeConstraint)*argc); |
| 145098 | + memset(pCsr->anQueue, 0, sizeof(u32)*(pRtree->iDepth + 1)); |
| 144051 | 145099 | assert( (idxStr==0 && argc==0) |
| 144052 | 145100 | || (idxStr && (int)strlen(idxStr)==argc*2) ); |
| 144053 | 145101 | for(ii=0; ii<argc; ii++){ |
| 144054 | 145102 | RtreeConstraint *p = &pCsr->aConstraint[ii]; |
| 144055 | 145103 | p->op = idxStr[ii*2]; |
| 144056 | | - p->iCoord = idxStr[ii*2+1]-'a'; |
| 144057 | | - if( p->op==RTREE_MATCH ){ |
| 145104 | + p->iCoord = idxStr[ii*2+1]-'0'; |
| 145105 | + if( p->op>=RTREE_MATCH ){ |
| 144058 | 145106 | /* A MATCH operator. The right-hand-side must be a blob that |
| 144059 | 145107 | ** can be cast into an RtreeMatchArg object. One created using |
| 144060 | 145108 | ** an sqlite3_rtree_geometry_callback() SQL user function. |
| 144061 | 145109 | */ |
| 144062 | 145110 | rc = deserializeGeometry(argv[ii], p); |
| 144063 | 145111 | if( rc!=SQLITE_OK ){ |
| 144064 | 145112 | break; |
| 144065 | 145113 | } |
| 145114 | + p->pInfo->nCoord = pRtree->nDim*2; |
| 145115 | + p->pInfo->anQueue = pCsr->anQueue; |
| 145116 | + p->pInfo->mxLevel = pRtree->iDepth + 1; |
| 144066 | 145117 | }else{ |
| 144067 | 145118 | #ifdef SQLITE_RTREE_INT_ONLY |
| 144068 | | - p->rValue = sqlite3_value_int64(argv[ii]); |
| 145119 | + p->u.rValue = sqlite3_value_int64(argv[ii]); |
| 144069 | 145120 | #else |
| 144070 | | - p->rValue = sqlite3_value_double(argv[ii]); |
| 145121 | + p->u.rValue = sqlite3_value_double(argv[ii]); |
| 144071 | 145122 | #endif |
| 144072 | 145123 | } |
| 144073 | 145124 | } |
| 144074 | 145125 | } |
| 144075 | 145126 | } |
| 144076 | | - |
| 144077 | | - if( rc==SQLITE_OK ){ |
| 144078 | | - pCsr->pNode = 0; |
| 144079 | | - rc = nodeAcquire(pRtree, 1, 0, &pRoot); |
| 144080 | | - } |
| 144081 | | - if( rc==SQLITE_OK ){ |
| 144082 | | - int isEof = 1; |
| 144083 | | - int nCell = NCELL(pRoot); |
| 144084 | | - pCsr->pNode = pRoot; |
| 144085 | | - for(pCsr->iCell=0; rc==SQLITE_OK && pCsr->iCell<nCell; pCsr->iCell++){ |
| 144086 | | - assert( pCsr->pNode==pRoot ); |
| 144087 | | - rc = descendToCell(pRtree, pCsr, pRtree->iDepth, &isEof); |
| 144088 | | - if( !isEof ){ |
| 144089 | | - break; |
| 144090 | | - } |
| 144091 | | - } |
| 144092 | | - if( rc==SQLITE_OK && isEof ){ |
| 144093 | | - assert( pCsr->pNode==pRoot ); |
| 144094 | | - nodeRelease(pRtree, pRoot); |
| 144095 | | - pCsr->pNode = 0; |
| 144096 | | - } |
| 144097 | | - assert( rc!=SQLITE_OK || !pCsr->pNode || pCsr->iCell<NCELL(pCsr->pNode) ); |
| 144098 | | - } |
| 144099 | | - } |
| 144100 | | - |
| 145127 | + if( rc==SQLITE_OK ){ |
| 145128 | + RtreeSearchPoint *pNew; |
| 145129 | + pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, pRtree->iDepth+1); |
| 145130 | + if( pNew==0 ) return SQLITE_NOMEM; |
| 145131 | + pNew->id = 1; |
| 145132 | + pNew->iCell = 0; |
| 145133 | + pNew->eWithin = PARTLY_WITHIN; |
| 145134 | + assert( pCsr->bPoint==1 ); |
| 145135 | + pCsr->aNode[0] = pRoot; |
| 145136 | + pRoot = 0; |
| 145137 | + RTREE_QUEUE_TRACE(pCsr, "PUSH-Fm:"); |
| 145138 | + rc = rtreeStepToLeaf(pCsr); |
| 145139 | + } |
| 145140 | + } |
| 145141 | + |
| 145142 | + nodeRelease(pRtree, pRoot); |
| 144101 | 145143 | rtreeRelease(pRtree); |
| 144102 | 145144 | return rc; |
| 144103 | 145145 | } |
| 144104 | 145146 | |
| 144105 | 145147 | /* |
| | @@ -144197,11 +145239,11 @@ |
| 144197 | 145239 | assert( p->op==SQLITE_INDEX_CONSTRAINT_MATCH ); |
| 144198 | 145240 | op = RTREE_MATCH; |
| 144199 | 145241 | break; |
| 144200 | 145242 | } |
| 144201 | 145243 | zIdxStr[iIdx++] = op; |
| 144202 | | - zIdxStr[iIdx++] = p->iColumn - 1 + 'a'; |
| 145244 | + zIdxStr[iIdx++] = p->iColumn - 1 + '0'; |
| 144203 | 145245 | pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2); |
| 144204 | 145246 | pIdxInfo->aConstraintUsage[ii].omit = 1; |
| 144205 | 145247 | } |
| 144206 | 145248 | } |
| 144207 | 145249 | |
| | @@ -144290,66 +145332,36 @@ |
| 144290 | 145332 | area = cellArea(pRtree, &cell); |
| 144291 | 145333 | cellUnion(pRtree, &cell, pCell); |
| 144292 | 145334 | return (cellArea(pRtree, &cell)-area); |
| 144293 | 145335 | } |
| 144294 | 145336 | |
| 144295 | | -#if VARIANT_RSTARTREE_CHOOSESUBTREE || VARIANT_RSTARTREE_SPLIT |
| 144296 | 145337 | static RtreeDValue cellOverlap( |
| 144297 | 145338 | Rtree *pRtree, |
| 144298 | 145339 | RtreeCell *p, |
| 144299 | 145340 | RtreeCell *aCell, |
| 144300 | | - int nCell, |
| 144301 | | - int iExclude |
| 145341 | + int nCell |
| 144302 | 145342 | ){ |
| 144303 | 145343 | int ii; |
| 144304 | | - RtreeDValue overlap = 0.0; |
| 145344 | + RtreeDValue overlap = RTREE_ZERO; |
| 144305 | 145345 | for(ii=0; ii<nCell; ii++){ |
| 144306 | | -#if VARIANT_RSTARTREE_CHOOSESUBTREE |
| 144307 | | - if( ii!=iExclude ) |
| 144308 | | -#else |
| 144309 | | - assert( iExclude==-1 ); |
| 144310 | | - UNUSED_PARAMETER(iExclude); |
| 144311 | | -#endif |
| 144312 | | - { |
| 144313 | | - int jj; |
| 144314 | | - RtreeDValue o = (RtreeDValue)1; |
| 144315 | | - for(jj=0; jj<(pRtree->nDim*2); jj+=2){ |
| 144316 | | - RtreeDValue x1, x2; |
| 144317 | | - |
| 144318 | | - x1 = MAX(DCOORD(p->aCoord[jj]), DCOORD(aCell[ii].aCoord[jj])); |
| 144319 | | - x2 = MIN(DCOORD(p->aCoord[jj+1]), DCOORD(aCell[ii].aCoord[jj+1])); |
| 144320 | | - |
| 144321 | | - if( x2<x1 ){ |
| 144322 | | - o = 0.0; |
| 144323 | | - break; |
| 144324 | | - }else{ |
| 144325 | | - o = o * (x2-x1); |
| 144326 | | - } |
| 144327 | | - } |
| 144328 | | - overlap += o; |
| 144329 | | - } |
| 145346 | + int jj; |
| 145347 | + RtreeDValue o = (RtreeDValue)1; |
| 145348 | + for(jj=0; jj<(pRtree->nDim*2); jj+=2){ |
| 145349 | + RtreeDValue x1, x2; |
| 145350 | + x1 = MAX(DCOORD(p->aCoord[jj]), DCOORD(aCell[ii].aCoord[jj])); |
| 145351 | + x2 = MIN(DCOORD(p->aCoord[jj+1]), DCOORD(aCell[ii].aCoord[jj+1])); |
| 145352 | + if( x2<x1 ){ |
| 145353 | + o = (RtreeDValue)0; |
| 145354 | + break; |
| 145355 | + }else{ |
| 145356 | + o = o * (x2-x1); |
| 145357 | + } |
| 145358 | + } |
| 145359 | + overlap += o; |
| 144330 | 145360 | } |
| 144331 | 145361 | return overlap; |
| 144332 | 145362 | } |
| 144333 | | -#endif |
| 144334 | | - |
| 144335 | | -#if VARIANT_RSTARTREE_CHOOSESUBTREE |
| 144336 | | -static RtreeDValue cellOverlapEnlargement( |
| 144337 | | - Rtree *pRtree, |
| 144338 | | - RtreeCell *p, |
| 144339 | | - RtreeCell *pInsert, |
| 144340 | | - RtreeCell *aCell, |
| 144341 | | - int nCell, |
| 144342 | | - int iExclude |
| 144343 | | -){ |
| 144344 | | - RtreeDValue before, after; |
| 144345 | | - before = cellOverlap(pRtree, p, aCell, nCell, iExclude); |
| 144346 | | - cellUnion(pRtree, p, pInsert); |
| 144347 | | - after = cellOverlap(pRtree, p, aCell, nCell, iExclude); |
| 144348 | | - return (after-before); |
| 144349 | | -} |
| 144350 | | -#endif |
| 144351 | 145363 | |
| 144352 | 145364 | |
| 144353 | 145365 | /* |
| 144354 | 145366 | ** This function implements the ChooseLeaf algorithm from Gutman[84]. |
| 144355 | 145367 | ** ChooseSubTree in r*tree terminology. |
| | @@ -144367,39 +145379,19 @@ |
| 144367 | 145379 | |
| 144368 | 145380 | for(ii=0; rc==SQLITE_OK && ii<(pRtree->iDepth-iHeight); ii++){ |
| 144369 | 145381 | int iCell; |
| 144370 | 145382 | sqlite3_int64 iBest = 0; |
| 144371 | 145383 | |
| 144372 | | - RtreeDValue fMinGrowth = 0.0; |
| 144373 | | - RtreeDValue fMinArea = 0.0; |
| 144374 | | -#if VARIANT_RSTARTREE_CHOOSESUBTREE |
| 144375 | | - RtreeDValue fMinOverlap = 0.0; |
| 144376 | | - RtreeDValue overlap; |
| 144377 | | -#endif |
| 145384 | + RtreeDValue fMinGrowth = RTREE_ZERO; |
| 145385 | + RtreeDValue fMinArea = RTREE_ZERO; |
| 144378 | 145386 | |
| 144379 | 145387 | int nCell = NCELL(pNode); |
| 144380 | 145388 | RtreeCell cell; |
| 144381 | 145389 | RtreeNode *pChild; |
| 144382 | 145390 | |
| 144383 | 145391 | RtreeCell *aCell = 0; |
| 144384 | 145392 | |
| 144385 | | -#if VARIANT_RSTARTREE_CHOOSESUBTREE |
| 144386 | | - if( ii==(pRtree->iDepth-1) ){ |
| 144387 | | - int jj; |
| 144388 | | - aCell = sqlite3_malloc(sizeof(RtreeCell)*nCell); |
| 144389 | | - if( !aCell ){ |
| 144390 | | - rc = SQLITE_NOMEM; |
| 144391 | | - nodeRelease(pRtree, pNode); |
| 144392 | | - pNode = 0; |
| 144393 | | - continue; |
| 144394 | | - } |
| 144395 | | - for(jj=0; jj<nCell; jj++){ |
| 144396 | | - nodeGetCell(pRtree, pNode, jj, &aCell[jj]); |
| 144397 | | - } |
| 144398 | | - } |
| 144399 | | -#endif |
| 144400 | | - |
| 144401 | 145393 | /* Select the child node which will be enlarged the least if pCell |
| 144402 | 145394 | ** is inserted into it. Resolve ties by choosing the entry with |
| 144403 | 145395 | ** the smallest area. |
| 144404 | 145396 | */ |
| 144405 | 145397 | for(iCell=0; iCell<nCell; iCell++){ |
| | @@ -144407,30 +145399,13 @@ |
| 144407 | 145399 | RtreeDValue growth; |
| 144408 | 145400 | RtreeDValue area; |
| 144409 | 145401 | nodeGetCell(pRtree, pNode, iCell, &cell); |
| 144410 | 145402 | growth = cellGrowth(pRtree, &cell, pCell); |
| 144411 | 145403 | area = cellArea(pRtree, &cell); |
| 144412 | | - |
| 144413 | | -#if VARIANT_RSTARTREE_CHOOSESUBTREE |
| 144414 | | - if( ii==(pRtree->iDepth-1) ){ |
| 144415 | | - overlap = cellOverlapEnlargement(pRtree,&cell,pCell,aCell,nCell,iCell); |
| 144416 | | - }else{ |
| 144417 | | - overlap = 0.0; |
| 144418 | | - } |
| 144419 | | - if( (iCell==0) |
| 144420 | | - || (overlap<fMinOverlap) |
| 144421 | | - || (overlap==fMinOverlap && growth<fMinGrowth) |
| 144422 | | - || (overlap==fMinOverlap && growth==fMinGrowth && area<fMinArea) |
| 144423 | | - ){ |
| 144424 | | - bBest = 1; |
| 144425 | | - fMinOverlap = overlap; |
| 144426 | | - } |
| 144427 | | -#else |
| 144428 | 145404 | if( iCell==0||growth<fMinGrowth||(growth==fMinGrowth && area<fMinArea) ){ |
| 144429 | 145405 | bBest = 1; |
| 144430 | 145406 | } |
| 144431 | | -#endif |
| 144432 | 145407 | if( bBest ){ |
| 144433 | 145408 | fMinGrowth = growth; |
| 144434 | 145409 | fMinArea = area; |
| 144435 | 145410 | iBest = cell.iRowid; |
| 144436 | 145411 | } |
| | @@ -144497,159 +145472,10 @@ |
| 144497 | 145472 | return sqlite3_reset(pRtree->pWriteParent); |
| 144498 | 145473 | } |
| 144499 | 145474 | |
| 144500 | 145475 | static int rtreeInsertCell(Rtree *, RtreeNode *, RtreeCell *, int); |
| 144501 | 145476 | |
| 144502 | | -#if VARIANT_GUTTMAN_LINEAR_SPLIT |
| 144503 | | -/* |
| 144504 | | -** Implementation of the linear variant of the PickNext() function from |
| 144505 | | -** Guttman[84]. |
| 144506 | | -*/ |
| 144507 | | -static RtreeCell *LinearPickNext( |
| 144508 | | - Rtree *pRtree, |
| 144509 | | - RtreeCell *aCell, |
| 144510 | | - int nCell, |
| 144511 | | - RtreeCell *pLeftBox, |
| 144512 | | - RtreeCell *pRightBox, |
| 144513 | | - int *aiUsed |
| 144514 | | -){ |
| 144515 | | - int ii; |
| 144516 | | - for(ii=0; aiUsed[ii]; ii++); |
| 144517 | | - aiUsed[ii] = 1; |
| 144518 | | - return &aCell[ii]; |
| 144519 | | -} |
| 144520 | | - |
| 144521 | | -/* |
| 144522 | | -** Implementation of the linear variant of the PickSeeds() function from |
| 144523 | | -** Guttman[84]. |
| 144524 | | -*/ |
| 144525 | | -static void LinearPickSeeds( |
| 144526 | | - Rtree *pRtree, |
| 144527 | | - RtreeCell *aCell, |
| 144528 | | - int nCell, |
| 144529 | | - int *piLeftSeed, |
| 144530 | | - int *piRightSeed |
| 144531 | | -){ |
| 144532 | | - int i; |
| 144533 | | - int iLeftSeed = 0; |
| 144534 | | - int iRightSeed = 1; |
| 144535 | | - RtreeDValue maxNormalInnerWidth = (RtreeDValue)0; |
| 144536 | | - |
| 144537 | | - /* Pick two "seed" cells from the array of cells. The algorithm used |
| 144538 | | - ** here is the LinearPickSeeds algorithm from Gutman[1984]. The |
| 144539 | | - ** indices of the two seed cells in the array are stored in local |
| 144540 | | - ** variables iLeftSeek and iRightSeed. |
| 144541 | | - */ |
| 144542 | | - for(i=0; i<pRtree->nDim; i++){ |
| 144543 | | - RtreeDValue x1 = DCOORD(aCell[0].aCoord[i*2]); |
| 144544 | | - RtreeDValue x2 = DCOORD(aCell[0].aCoord[i*2+1]); |
| 144545 | | - RtreeDValue x3 = x1; |
| 144546 | | - RtreeDValue x4 = x2; |
| 144547 | | - int jj; |
| 144548 | | - |
| 144549 | | - int iCellLeft = 0; |
| 144550 | | - int iCellRight = 0; |
| 144551 | | - |
| 144552 | | - for(jj=1; jj<nCell; jj++){ |
| 144553 | | - RtreeDValue left = DCOORD(aCell[jj].aCoord[i*2]); |
| 144554 | | - RtreeDValue right = DCOORD(aCell[jj].aCoord[i*2+1]); |
| 144555 | | - |
| 144556 | | - if( left<x1 ) x1 = left; |
| 144557 | | - if( right>x4 ) x4 = right; |
| 144558 | | - if( left>x3 ){ |
| 144559 | | - x3 = left; |
| 144560 | | - iCellRight = jj; |
| 144561 | | - } |
| 144562 | | - if( right<x2 ){ |
| 144563 | | - x2 = right; |
| 144564 | | - iCellLeft = jj; |
| 144565 | | - } |
| 144566 | | - } |
| 144567 | | - |
| 144568 | | - if( x4!=x1 ){ |
| 144569 | | - RtreeDValue normalwidth = (x3 - x2) / (x4 - x1); |
| 144570 | | - if( normalwidth>maxNormalInnerWidth ){ |
| 144571 | | - iLeftSeed = iCellLeft; |
| 144572 | | - iRightSeed = iCellRight; |
| 144573 | | - } |
| 144574 | | - } |
| 144575 | | - } |
| 144576 | | - |
| 144577 | | - *piLeftSeed = iLeftSeed; |
| 144578 | | - *piRightSeed = iRightSeed; |
| 144579 | | -} |
| 144580 | | -#endif /* VARIANT_GUTTMAN_LINEAR_SPLIT */ |
| 144581 | | - |
| 144582 | | -#if VARIANT_GUTTMAN_QUADRATIC_SPLIT |
| 144583 | | -/* |
| 144584 | | -** Implementation of the quadratic variant of the PickNext() function from |
| 144585 | | -** Guttman[84]. |
| 144586 | | -*/ |
| 144587 | | -static RtreeCell *QuadraticPickNext( |
| 144588 | | - Rtree *pRtree, |
| 144589 | | - RtreeCell *aCell, |
| 144590 | | - int nCell, |
| 144591 | | - RtreeCell *pLeftBox, |
| 144592 | | - RtreeCell *pRightBox, |
| 144593 | | - int *aiUsed |
| 144594 | | -){ |
| 144595 | | - #define FABS(a) ((a)<0.0?-1.0*(a):(a)) |
| 144596 | | - |
| 144597 | | - int iSelect = -1; |
| 144598 | | - RtreeDValue fDiff; |
| 144599 | | - int ii; |
| 144600 | | - for(ii=0; ii<nCell; ii++){ |
| 144601 | | - if( aiUsed[ii]==0 ){ |
| 144602 | | - RtreeDValue left = cellGrowth(pRtree, pLeftBox, &aCell[ii]); |
| 144603 | | - RtreeDValue right = cellGrowth(pRtree, pLeftBox, &aCell[ii]); |
| 144604 | | - RtreeDValue diff = FABS(right-left); |
| 144605 | | - if( iSelect<0 || diff>fDiff ){ |
| 144606 | | - fDiff = diff; |
| 144607 | | - iSelect = ii; |
| 144608 | | - } |
| 144609 | | - } |
| 144610 | | - } |
| 144611 | | - aiUsed[iSelect] = 1; |
| 144612 | | - return &aCell[iSelect]; |
| 144613 | | -} |
| 144614 | | - |
| 144615 | | -/* |
| 144616 | | -** Implementation of the quadratic variant of the PickSeeds() function from |
| 144617 | | -** Guttman[84]. |
| 144618 | | -*/ |
| 144619 | | -static void QuadraticPickSeeds( |
| 144620 | | - Rtree *pRtree, |
| 144621 | | - RtreeCell *aCell, |
| 144622 | | - int nCell, |
| 144623 | | - int *piLeftSeed, |
| 144624 | | - int *piRightSeed |
| 144625 | | -){ |
| 144626 | | - int ii; |
| 144627 | | - int jj; |
| 144628 | | - |
| 144629 | | - int iLeftSeed = 0; |
| 144630 | | - int iRightSeed = 1; |
| 144631 | | - RtreeDValue fWaste = 0.0; |
| 144632 | | - |
| 144633 | | - for(ii=0; ii<nCell; ii++){ |
| 144634 | | - for(jj=ii+1; jj<nCell; jj++){ |
| 144635 | | - RtreeDValue right = cellArea(pRtree, &aCell[jj]); |
| 144636 | | - RtreeDValue growth = cellGrowth(pRtree, &aCell[ii], &aCell[jj]); |
| 144637 | | - RtreeDValue waste = growth - right; |
| 144638 | | - |
| 144639 | | - if( waste>fWaste ){ |
| 144640 | | - iLeftSeed = ii; |
| 144641 | | - iRightSeed = jj; |
| 144642 | | - fWaste = waste; |
| 144643 | | - } |
| 144644 | | - } |
| 144645 | | - } |
| 144646 | | - |
| 144647 | | - *piLeftSeed = iLeftSeed; |
| 144648 | | - *piRightSeed = iRightSeed; |
| 144649 | | -} |
| 144650 | | -#endif /* VARIANT_GUTTMAN_QUADRATIC_SPLIT */ |
| 144651 | 145477 | |
| 144652 | 145478 | /* |
| 144653 | 145479 | ** Arguments aIdx, aDistance and aSpare all point to arrays of size |
| 144654 | 145480 | ** nIdx. The aIdx array contains the set of integers from 0 to |
| 144655 | 145481 | ** (nIdx-1) in no particular order. This function sorts the values |
| | @@ -144786,11 +145612,10 @@ |
| 144786 | 145612 | } |
| 144787 | 145613 | #endif |
| 144788 | 145614 | } |
| 144789 | 145615 | } |
| 144790 | 145616 | |
| 144791 | | -#if VARIANT_RSTARTREE_SPLIT |
| 144792 | 145617 | /* |
| 144793 | 145618 | ** Implementation of the R*-tree variant of SplitNode from Beckman[1990]. |
| 144794 | 145619 | */ |
| 144795 | 145620 | static int splitNodeStartree( |
| 144796 | 145621 | Rtree *pRtree, |
| | @@ -144805,11 +145630,11 @@ |
| 144805 | 145630 | int *aSpare; |
| 144806 | 145631 | int ii; |
| 144807 | 145632 | |
| 144808 | 145633 | int iBestDim = 0; |
| 144809 | 145634 | int iBestSplit = 0; |
| 144810 | | - RtreeDValue fBestMargin = 0.0; |
| 145635 | + RtreeDValue fBestMargin = RTREE_ZERO; |
| 144811 | 145636 | |
| 144812 | 145637 | int nByte = (pRtree->nDim+1)*(sizeof(int*)+nCell*sizeof(int)); |
| 144813 | 145638 | |
| 144814 | 145639 | aaSorted = (int **)sqlite3_malloc(nByte); |
| 144815 | 145640 | if( !aaSorted ){ |
| | @@ -144826,13 +145651,13 @@ |
| 144826 | 145651 | } |
| 144827 | 145652 | SortByDimension(pRtree, aaSorted[ii], nCell, ii, aCell, aSpare); |
| 144828 | 145653 | } |
| 144829 | 145654 | |
| 144830 | 145655 | for(ii=0; ii<pRtree->nDim; ii++){ |
| 144831 | | - RtreeDValue margin = 0.0; |
| 144832 | | - RtreeDValue fBestOverlap = 0.0; |
| 144833 | | - RtreeDValue fBestArea = 0.0; |
| 145656 | + RtreeDValue margin = RTREE_ZERO; |
| 145657 | + RtreeDValue fBestOverlap = RTREE_ZERO; |
| 145658 | + RtreeDValue fBestArea = RTREE_ZERO; |
| 144834 | 145659 | int iBestLeft = 0; |
| 144835 | 145660 | int nLeft; |
| 144836 | 145661 | |
| 144837 | 145662 | for( |
| 144838 | 145663 | nLeft=RTREE_MINCELLS(pRtree); |
| | @@ -144854,11 +145679,11 @@ |
| 144854 | 145679 | cellUnion(pRtree, &right, &aCell[aaSorted[ii][kk]]); |
| 144855 | 145680 | } |
| 144856 | 145681 | } |
| 144857 | 145682 | margin += cellMargin(pRtree, &left); |
| 144858 | 145683 | margin += cellMargin(pRtree, &right); |
| 144859 | | - overlap = cellOverlap(pRtree, &left, &right, 1, -1); |
| 145684 | + overlap = cellOverlap(pRtree, &left, &right, 1); |
| 144860 | 145685 | area = cellArea(pRtree, &left) + cellArea(pRtree, &right); |
| 144861 | 145686 | if( (nLeft==RTREE_MINCELLS(pRtree)) |
| 144862 | 145687 | || (overlap<fBestOverlap) |
| 144863 | 145688 | || (overlap==fBestOverlap && area<fBestArea) |
| 144864 | 145689 | ){ |
| | @@ -144886,67 +145711,11 @@ |
| 144886 | 145711 | } |
| 144887 | 145712 | |
| 144888 | 145713 | sqlite3_free(aaSorted); |
| 144889 | 145714 | return SQLITE_OK; |
| 144890 | 145715 | } |
| 144891 | | -#endif |
| 144892 | | - |
| 144893 | | -#if VARIANT_GUTTMAN_SPLIT |
| 144894 | | -/* |
| 144895 | | -** Implementation of the regular R-tree SplitNode from Guttman[1984]. |
| 144896 | | -*/ |
| 144897 | | -static int splitNodeGuttman( |
| 144898 | | - Rtree *pRtree, |
| 144899 | | - RtreeCell *aCell, |
| 144900 | | - int nCell, |
| 144901 | | - RtreeNode *pLeft, |
| 144902 | | - RtreeNode *pRight, |
| 144903 | | - RtreeCell *pBboxLeft, |
| 144904 | | - RtreeCell *pBboxRight |
| 144905 | | -){ |
| 144906 | | - int iLeftSeed = 0; |
| 144907 | | - int iRightSeed = 1; |
| 144908 | | - int *aiUsed; |
| 144909 | | - int i; |
| 144910 | | - |
| 144911 | | - aiUsed = sqlite3_malloc(sizeof(int)*nCell); |
| 144912 | | - if( !aiUsed ){ |
| 144913 | | - return SQLITE_NOMEM; |
| 144914 | | - } |
| 144915 | | - memset(aiUsed, 0, sizeof(int)*nCell); |
| 144916 | | - |
| 144917 | | - PickSeeds(pRtree, aCell, nCell, &iLeftSeed, &iRightSeed); |
| 144918 | | - |
| 144919 | | - memcpy(pBboxLeft, &aCell[iLeftSeed], sizeof(RtreeCell)); |
| 144920 | | - memcpy(pBboxRight, &aCell[iRightSeed], sizeof(RtreeCell)); |
| 144921 | | - nodeInsertCell(pRtree, pLeft, &aCell[iLeftSeed]); |
| 144922 | | - nodeInsertCell(pRtree, pRight, &aCell[iRightSeed]); |
| 144923 | | - aiUsed[iLeftSeed] = 1; |
| 144924 | | - aiUsed[iRightSeed] = 1; |
| 144925 | | - |
| 144926 | | - for(i=nCell-2; i>0; i--){ |
| 144927 | | - RtreeCell *pNext; |
| 144928 | | - pNext = PickNext(pRtree, aCell, nCell, pBboxLeft, pBboxRight, aiUsed); |
| 144929 | | - RtreeDValue diff = |
| 144930 | | - cellGrowth(pRtree, pBboxLeft, pNext) - |
| 144931 | | - cellGrowth(pRtree, pBboxRight, pNext) |
| 144932 | | - ; |
| 144933 | | - if( (RTREE_MINCELLS(pRtree)-NCELL(pRight)==i) |
| 144934 | | - || (diff>0.0 && (RTREE_MINCELLS(pRtree)-NCELL(pLeft)!=i)) |
| 144935 | | - ){ |
| 144936 | | - nodeInsertCell(pRtree, pRight, pNext); |
| 144937 | | - cellUnion(pRtree, pBboxRight, pNext); |
| 144938 | | - }else{ |
| 144939 | | - nodeInsertCell(pRtree, pLeft, pNext); |
| 144940 | | - cellUnion(pRtree, pBboxLeft, pNext); |
| 144941 | | - } |
| 144942 | | - } |
| 144943 | | - |
| 144944 | | - sqlite3_free(aiUsed); |
| 144945 | | - return SQLITE_OK; |
| 144946 | | -} |
| 144947 | | -#endif |
| 145716 | + |
| 144948 | 145717 | |
| 144949 | 145718 | static int updateMapping( |
| 144950 | 145719 | Rtree *pRtree, |
| 144951 | 145720 | i64 iRowid, |
| 144952 | 145721 | RtreeNode *pNode, |
| | @@ -145020,11 +145789,12 @@ |
| 145020 | 145789 | } |
| 145021 | 145790 | |
| 145022 | 145791 | memset(pLeft->zData, 0, pRtree->iNodeSize); |
| 145023 | 145792 | memset(pRight->zData, 0, pRtree->iNodeSize); |
| 145024 | 145793 | |
| 145025 | | - rc = AssignCells(pRtree, aCell, nCell, pLeft, pRight, &leftbbox, &rightbbox); |
| 145794 | + rc = splitNodeStartree(pRtree, aCell, nCell, pLeft, pRight, |
| 145795 | + &leftbbox, &rightbbox); |
| 145026 | 145796 | if( rc!=SQLITE_OK ){ |
| 145027 | 145797 | goto splitnode_out; |
| 145028 | 145798 | } |
| 145029 | 145799 | |
| 145030 | 145800 | /* Ensure both child nodes have node numbers assigned to them by calling |
| | @@ -145303,11 +146073,11 @@ |
| 145303 | 146073 | for(iDim=0; iDim<pRtree->nDim; iDim++){ |
| 145304 | 146074 | aCenterCoord[iDim] = (aCenterCoord[iDim]/(nCell*(RtreeDValue)2)); |
| 145305 | 146075 | } |
| 145306 | 146076 | |
| 145307 | 146077 | for(ii=0; ii<nCell; ii++){ |
| 145308 | | - aDistance[ii] = 0.0; |
| 146078 | + aDistance[ii] = RTREE_ZERO; |
| 145309 | 146079 | for(iDim=0; iDim<pRtree->nDim; iDim++){ |
| 145310 | 146080 | RtreeDValue coord = (DCOORD(aCell[ii].aCoord[iDim*2+1]) - |
| 145311 | 146081 | DCOORD(aCell[ii].aCoord[iDim*2])); |
| 145312 | 146082 | aDistance[ii] += (coord-aCenterCoord[iDim])*(coord-aCenterCoord[iDim]); |
| 145313 | 146083 | } |
| | @@ -145369,20 +146139,16 @@ |
| 145369 | 146139 | nodeReference(pNode); |
| 145370 | 146140 | pChild->pParent = pNode; |
| 145371 | 146141 | } |
| 145372 | 146142 | } |
| 145373 | 146143 | if( nodeInsertCell(pRtree, pNode, pCell) ){ |
| 145374 | | -#if VARIANT_RSTARTREE_REINSERT |
| 145375 | 146144 | if( iHeight<=pRtree->iReinsertHeight || pNode->iNode==1){ |
| 145376 | 146145 | rc = SplitNode(pRtree, pNode, pCell, iHeight); |
| 145377 | 146146 | }else{ |
| 145378 | 146147 | pRtree->iReinsertHeight = iHeight; |
| 145379 | 146148 | rc = Reinsert(pRtree, pNode, pCell, iHeight); |
| 145380 | 146149 | } |
| 145381 | | -#else |
| 145382 | | - rc = SplitNode(pRtree, pNode, pCell, iHeight); |
| 145383 | | -#endif |
| 145384 | 146150 | }else{ |
| 145385 | 146151 | rc = AdjustTree(pRtree, pNode, pCell); |
| 145386 | 146152 | if( rc==SQLITE_OK ){ |
| 145387 | 146153 | if( iHeight==0 ){ |
| 145388 | 146154 | rc = rowidWrite(pRtree, pCell->iRowid, pNode->iNode); |
| | @@ -145448,11 +146214,11 @@ |
| 145448 | 146214 | |
| 145449 | 146215 | /* Obtain a reference to the leaf node that contains the entry |
| 145450 | 146216 | ** about to be deleted. |
| 145451 | 146217 | */ |
| 145452 | 146218 | if( rc==SQLITE_OK ){ |
| 145453 | | - rc = findLeafNode(pRtree, iDelete, &pLeaf); |
| 146219 | + rc = findLeafNode(pRtree, iDelete, &pLeaf, 0); |
| 145454 | 146220 | } |
| 145455 | 146221 | |
| 145456 | 146222 | /* Delete the cell in question from the leaf node. */ |
| 145457 | 146223 | if( rc==SQLITE_OK ){ |
| 145458 | 146224 | int rc2; |
| | @@ -145785,11 +146551,12 @@ |
| 145785 | 146551 | |
| 145786 | 146552 | if( isCreate ){ |
| 145787 | 146553 | char *zCreate = sqlite3_mprintf( |
| 145788 | 146554 | "CREATE TABLE \"%w\".\"%w_node\"(nodeno INTEGER PRIMARY KEY, data BLOB);" |
| 145789 | 146555 | "CREATE TABLE \"%w\".\"%w_rowid\"(rowid INTEGER PRIMARY KEY, nodeno INTEGER);" |
| 145790 | | -"CREATE TABLE \"%w\".\"%w_parent\"(nodeno INTEGER PRIMARY KEY, parentnode INTEGER);" |
| 146556 | +"CREATE TABLE \"%w\".\"%w_parent\"(nodeno INTEGER PRIMARY KEY," |
| 146557 | + " parentnode INTEGER);" |
| 145791 | 146558 | "INSERT INTO '%q'.'%q_node' VALUES(1, zeroblob(%d))", |
| 145792 | 146559 | zDb, zPrefix, zDb, zPrefix, zDb, zPrefix, zDb, zPrefix, pRtree->iNodeSize |
| 145793 | 146560 | ); |
| 145794 | 146561 | if( !zCreate ){ |
| 145795 | 146562 | return SQLITE_NOMEM; |
| | @@ -145999,14 +146766,14 @@ |
| 145999 | 146766 | |
| 146000 | 146767 | /* |
| 146001 | 146768 | ** Implementation of a scalar function that decodes r-tree nodes to |
| 146002 | 146769 | ** human readable strings. This can be used for debugging and analysis. |
| 146003 | 146770 | ** |
| 146004 | | -** The scalar function takes two arguments, a blob of data containing |
| 146005 | | -** an r-tree node, and the number of dimensions the r-tree indexes. |
| 146006 | | -** For a two-dimensional r-tree structure called "rt", to deserialize |
| 146007 | | -** all nodes, a statement like: |
| 146771 | +** The scalar function takes two arguments: (1) the number of dimensions |
| 146772 | +** to the rtree (between 1 and 5, inclusive) and (2) a blob of data containing |
| 146773 | +** an r-tree node. For a two-dimensional r-tree structure called "rt", to |
| 146774 | +** deserialize all nodes, a statement like: |
| 146008 | 146775 | ** |
| 146009 | 146776 | ** SELECT rtreenode(2, data) FROM rt_node; |
| 146010 | 146777 | ** |
| 146011 | 146778 | ** The human readable string takes the form of a Tcl list with one |
| 146012 | 146779 | ** entry for each cell in the r-tree node. Each entry is itself a |
| | @@ -146035,11 +146802,11 @@ |
| 146035 | 146802 | nodeGetCell(&tree, &node, ii, &cell); |
| 146036 | 146803 | sqlite3_snprintf(512-nCell,&zCell[nCell],"%lld", cell.iRowid); |
| 146037 | 146804 | nCell = (int)strlen(zCell); |
| 146038 | 146805 | for(jj=0; jj<tree.nDim*2; jj++){ |
| 146039 | 146806 | #ifndef SQLITE_RTREE_INT_ONLY |
| 146040 | | - sqlite3_snprintf(512-nCell,&zCell[nCell], " %f", |
| 146807 | + sqlite3_snprintf(512-nCell,&zCell[nCell], " %g", |
| 146041 | 146808 | (double)cell.aCoord[jj].f); |
| 146042 | 146809 | #else |
| 146043 | 146810 | sqlite3_snprintf(512-nCell,&zCell[nCell], " %d", |
| 146044 | 146811 | cell.aCoord[jj].i); |
| 146045 | 146812 | #endif |
| | @@ -146056,10 +146823,19 @@ |
| 146056 | 146823 | } |
| 146057 | 146824 | |
| 146058 | 146825 | sqlite3_result_text(ctx, zText, -1, sqlite3_free); |
| 146059 | 146826 | } |
| 146060 | 146827 | |
| 146828 | +/* This routine implements an SQL function that returns the "depth" parameter |
| 146829 | +** from the front of a blob that is an r-tree node. For example: |
| 146830 | +** |
| 146831 | +** SELECT rtreedepth(data) FROM rt_node WHERE nodeno=1; |
| 146832 | +** |
| 146833 | +** The depth value is 0 for all nodes other than the root node, and the root |
| 146834 | +** node always has nodeno=1, so the example above is the primary use for this |
| 146835 | +** routine. This routine is intended for testing and analysis only. |
| 146836 | +*/ |
| 146061 | 146837 | static void rtreedepth(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){ |
| 146062 | 146838 | UNUSED_PARAMETER(nArg); |
| 146063 | 146839 | if( sqlite3_value_type(apArg[0])!=SQLITE_BLOB |
| 146064 | 146840 | || sqlite3_value_bytes(apArg[0])<2 |
| 146065 | 146841 | ){ |
| | @@ -146098,26 +146874,35 @@ |
| 146098 | 146874 | |
| 146099 | 146875 | return rc; |
| 146100 | 146876 | } |
| 146101 | 146877 | |
| 146102 | 146878 | /* |
| 146103 | | -** A version of sqlite3_free() that can be used as a callback. This is used |
| 146104 | | -** in two places - as the destructor for the blob value returned by the |
| 146105 | | -** invocation of a geometry function, and as the destructor for the geometry |
| 146106 | | -** functions themselves. |
| 146879 | +** This routine deletes the RtreeGeomCallback object that was attached |
| 146880 | +** one of the SQL functions create by sqlite3_rtree_geometry_callback() |
| 146881 | +** or sqlite3_rtree_query_callback(). In other words, this routine is the |
| 146882 | +** destructor for an RtreeGeomCallback objecct. This routine is called when |
| 146883 | +** the corresponding SQL function is deleted. |
| 146107 | 146884 | */ |
| 146108 | | -static void doSqlite3Free(void *p){ |
| 146885 | +static void rtreeFreeCallback(void *p){ |
| 146886 | + RtreeGeomCallback *pInfo = (RtreeGeomCallback*)p; |
| 146887 | + if( pInfo->xDestructor ) pInfo->xDestructor(pInfo->pContext); |
| 146109 | 146888 | sqlite3_free(p); |
| 146110 | 146889 | } |
| 146111 | 146890 | |
| 146112 | 146891 | /* |
| 146113 | | -** Each call to sqlite3_rtree_geometry_callback() creates an ordinary SQLite |
| 146114 | | -** scalar user function. This C function is the callback used for all such |
| 146115 | | -** registered SQL functions. |
| 146892 | +** Each call to sqlite3_rtree_geometry_callback() or |
| 146893 | +** sqlite3_rtree_query_callback() creates an ordinary SQLite |
| 146894 | +** scalar function that is implemented by this routine. |
| 146895 | +** |
| 146896 | +** All this function does is construct an RtreeMatchArg object that |
| 146897 | +** contains the geometry-checking callback routines and a list of |
| 146898 | +** parameters to this function, then return that RtreeMatchArg object |
| 146899 | +** as a BLOB. |
| 146116 | 146900 | ** |
| 146117 | | -** The scalar user functions return a blob that is interpreted by r-tree |
| 146118 | | -** table MATCH operators. |
| 146901 | +** The R-Tree MATCH operator will read the returned BLOB, deserialize |
| 146902 | +** the RtreeMatchArg object, and use the RtreeMatchArg object to figure |
| 146903 | +** out which elements of the R-Tree should be returned by the query. |
| 146119 | 146904 | */ |
| 146120 | 146905 | static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ |
| 146121 | 146906 | RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx); |
| 146122 | 146907 | RtreeMatchArg *pBlob; |
| 146123 | 146908 | int nBlob; |
| | @@ -146127,45 +146912,68 @@ |
| 146127 | 146912 | if( !pBlob ){ |
| 146128 | 146913 | sqlite3_result_error_nomem(ctx); |
| 146129 | 146914 | }else{ |
| 146130 | 146915 | int i; |
| 146131 | 146916 | pBlob->magic = RTREE_GEOMETRY_MAGIC; |
| 146132 | | - pBlob->xGeom = pGeomCtx->xGeom; |
| 146133 | | - pBlob->pContext = pGeomCtx->pContext; |
| 146917 | + pBlob->cb = pGeomCtx[0]; |
| 146134 | 146918 | pBlob->nParam = nArg; |
| 146135 | 146919 | for(i=0; i<nArg; i++){ |
| 146136 | 146920 | #ifdef SQLITE_RTREE_INT_ONLY |
| 146137 | 146921 | pBlob->aParam[i] = sqlite3_value_int64(aArg[i]); |
| 146138 | 146922 | #else |
| 146139 | 146923 | pBlob->aParam[i] = sqlite3_value_double(aArg[i]); |
| 146140 | 146924 | #endif |
| 146141 | 146925 | } |
| 146142 | | - sqlite3_result_blob(ctx, pBlob, nBlob, doSqlite3Free); |
| 146926 | + sqlite3_result_blob(ctx, pBlob, nBlob, sqlite3_free); |
| 146143 | 146927 | } |
| 146144 | 146928 | } |
| 146145 | 146929 | |
| 146146 | 146930 | /* |
| 146147 | 146931 | ** Register a new geometry function for use with the r-tree MATCH operator. |
| 146148 | 146932 | */ |
| 146149 | 146933 | SQLITE_API int sqlite3_rtree_geometry_callback( |
| 146150 | | - sqlite3 *db, |
| 146151 | | - const char *zGeom, |
| 146152 | | - int (*xGeom)(sqlite3_rtree_geometry *, int, RtreeDValue *, int *), |
| 146153 | | - void *pContext |
| 146934 | + sqlite3 *db, /* Register SQL function on this connection */ |
| 146935 | + const char *zGeom, /* Name of the new SQL function */ |
| 146936 | + int (*xGeom)(sqlite3_rtree_geometry*,int,RtreeDValue*,int*), /* Callback */ |
| 146937 | + void *pContext /* Extra data associated with the callback */ |
| 146154 | 146938 | ){ |
| 146155 | 146939 | RtreeGeomCallback *pGeomCtx; /* Context object for new user-function */ |
| 146156 | 146940 | |
| 146157 | 146941 | /* Allocate and populate the context object. */ |
| 146158 | 146942 | pGeomCtx = (RtreeGeomCallback *)sqlite3_malloc(sizeof(RtreeGeomCallback)); |
| 146159 | 146943 | if( !pGeomCtx ) return SQLITE_NOMEM; |
| 146160 | 146944 | pGeomCtx->xGeom = xGeom; |
| 146945 | + pGeomCtx->xQueryFunc = 0; |
| 146946 | + pGeomCtx->xDestructor = 0; |
| 146161 | 146947 | pGeomCtx->pContext = pContext; |
| 146162 | | - |
| 146163 | | - /* Create the new user-function. Register a destructor function to delete |
| 146164 | | - ** the context object when it is no longer required. */ |
| 146165 | 146948 | return sqlite3_create_function_v2(db, zGeom, -1, SQLITE_ANY, |
| 146166 | | - (void *)pGeomCtx, geomCallback, 0, 0, doSqlite3Free |
| 146949 | + (void *)pGeomCtx, geomCallback, 0, 0, rtreeFreeCallback |
| 146950 | + ); |
| 146951 | +} |
| 146952 | + |
| 146953 | +/* |
| 146954 | +** Register a new 2nd-generation geometry function for use with the |
| 146955 | +** r-tree MATCH operator. |
| 146956 | +*/ |
| 146957 | +SQLITE_API int sqlite3_rtree_query_callback( |
| 146958 | + sqlite3 *db, /* Register SQL function on this connection */ |
| 146959 | + const char *zQueryFunc, /* Name of new SQL function */ |
| 146960 | + int (*xQueryFunc)(sqlite3_rtree_query_info*), /* Callback */ |
| 146961 | + void *pContext, /* Extra data passed into the callback */ |
| 146962 | + void (*xDestructor)(void*) /* Destructor for the extra data */ |
| 146963 | +){ |
| 146964 | + RtreeGeomCallback *pGeomCtx; /* Context object for new user-function */ |
| 146965 | + |
| 146966 | + /* Allocate and populate the context object. */ |
| 146967 | + pGeomCtx = (RtreeGeomCallback *)sqlite3_malloc(sizeof(RtreeGeomCallback)); |
| 146968 | + if( !pGeomCtx ) return SQLITE_NOMEM; |
| 146969 | + pGeomCtx->xGeom = 0; |
| 146970 | + pGeomCtx->xQueryFunc = xQueryFunc; |
| 146971 | + pGeomCtx->xDestructor = xDestructor; |
| 146972 | + pGeomCtx->pContext = pContext; |
| 146973 | + return sqlite3_create_function_v2(db, zQueryFunc, -1, SQLITE_ANY, |
| 146974 | + (void *)pGeomCtx, geomCallback, 0, 0, rtreeFreeCallback |
| 146167 | 146975 | ); |
| 146168 | 146976 | } |
| 146169 | 146977 | |
| 146170 | 146978 | #if !SQLITE_CORE |
| 146171 | 146979 | #ifdef _WIN32 |
| 146172 | 146980 | |