1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Make the distinction between truly deterministic functions and date/time

functions which only return the same answer for a single query.  Only truly
deterministic functions are allowed in indexes.  Add new expression index
test cases.

FossilOrigin-Name: c77554b5c42327106a7b90334e9cc3c07b007c76
This commit is contained in:
drh
2015-08-31 17:34:41 +00:00
parent 47991425cb
commit 1d85e405e6
6 changed files with 160 additions and 43 deletions

View File

@@ -1,5 +1,5 @@
C Improved\sanalysis\sand\susage\sof\sindexed\sexpressions\sin\sthe\squery\splanner. C Make\sthe\sdistinction\sbetween\struly\sdeterministic\sfunctions\sand\sdate/time\nfunctions\swhich\sonly\sreturn\sthe\ssame\sanswer\sfor\sa\ssingle\squery.\s\sOnly\struly\ndeterministic\sfunctions\sare\sallowed\sin\sindexes.\s\sAdd\snew\sexpression\sindex\ntest\scases.
D 2015-08-31T15:58:06.350 D 2015-08-31T17:34:41.308
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in f85066ce844a28b671aaeeff320921cd0ce36239 F Makefile.in f85066ce844a28b671aaeeff320921cd0ce36239
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -286,7 +286,7 @@ F src/build.c e0902658fc86dbd60a5c6772ca45429c69ee81fe
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0 F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f
F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b
F src/date.c 8ec787fed4929d8ccdf6b1bc360fccc3e1d2ca58 F src/date.c fb1c99172017dcc8e237339132c91a21a0788584
F src/dbstat.c f402e77e25089c6003d0c60b3233b9b3947d599a F src/dbstat.c f402e77e25089c6003d0c60b3233b9b3947d599a
F src/delete.c 224e5c9a0eae7fbdd3b461ca971465c992851354 F src/delete.c 224e5c9a0eae7fbdd3b461ca971465c992851354
F src/expr.c cf0c5ef6467d3eb65e3ff5c88eb2f602ba3b5163 F src/expr.c cf0c5ef6467d3eb65e3ff5c88eb2f602ba3b5163
@@ -335,14 +335,14 @@ F src/pragma.h 631a91c8b0e6ca8f051a1d8a4a0da4150e04620a
F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1 F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1
F src/printf.c 2bc439ff20a4aad0e0ad50a37a67b5eae7d20edc F src/printf.c 2bc439ff20a4aad0e0ad50a37a67b5eae7d20edc
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
F src/resolve.c e6dc5a5490cf93afc1cc2cb58280c98da56acb3c F src/resolve.c 3ec6456a534bcbf0f3fc11ad83c6208301db60a2
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
F src/select.c b52c80f2b1bdb62491f9ce40eea0c5f80c78d105 F src/select.c b52c80f2b1bdb62491f9ce40eea0c5f80c78d105
F src/shell.c 6332ef06db1390ef812cfdff1fc97b4fd76cdd42 F src/shell.c 6332ef06db1390ef812cfdff1fc97b4fd76cdd42
F src/sqlite.h.in 378bebc8fe6a88bade25e5f23b7e6123fdc64b00 F src/sqlite.h.in 378bebc8fe6a88bade25e5f23b7e6123fdc64b00
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h f700e6a9dd1fdcccc9951ab022b366fb66b9e413 F src/sqlite3ext.h f700e6a9dd1fdcccc9951ab022b366fb66b9e413
F src/sqliteInt.h 340fc115a707838ad365b52057f126b143f6aa60 F src/sqliteInt.h 332ae4f753d91c92421a2c4227c195298d5b154c
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179 F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
@@ -780,7 +780,7 @@ F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7
F test/index6.test 7102ec371414c42dfb1d5ca37eb4519aa9edc23a F test/index6.test 7102ec371414c42dfb1d5ca37eb4519aa9edc23a
F test/index7.test 9c6765a74fc3fcde7aebc5b3bd40d98df14a527c F test/index7.test 9c6765a74fc3fcde7aebc5b3bd40d98df14a527c
F test/indexedby.test 5f527a78bae74c61b8046ae3037f9dfb0bf0c353 F test/indexedby.test 5f527a78bae74c61b8046ae3037f9dfb0bf0c353
F test/indexexpr1.test 36b7aab1fdb03710b99ee876ff764b92c7b96e3e F test/indexexpr1.test 1e57b4bb93b65a451803e7547a51f685af1c35db
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7 F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371 F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371
@@ -1381,7 +1381,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 7bde6d4d8cf05e1beb9bdf20b85760dc3e7a76c9 P f8893696387cba9d293a05a68dc38228077b3dc5
R b7744e5a00368fcccd1913a83a0521e8 R 73b6719fd207957d3d30c3e1b6c218bc
U drh U drh
Z 32945199df036dc2360847bdab3537ac Z fe2263cb4a747333f78b4cc6eb661f66

View File

@@ -1 +1 @@
f8893696387cba9d293a05a68dc38228077b3dc5 c77554b5c42327106a7b90334e9cc3c07b007c76

View File

@@ -1115,14 +1115,14 @@ static void currentTimeFunc(
void sqlite3RegisterDateTimeFunctions(void){ void sqlite3RegisterDateTimeFunctions(void){
static SQLITE_WSD FuncDef aDateTimeFuncs[] = { static SQLITE_WSD FuncDef aDateTimeFuncs[] = {
#ifndef SQLITE_OMIT_DATETIME_FUNCS #ifndef SQLITE_OMIT_DATETIME_FUNCS
FUNCTION(julianday, -1, 0, 0, juliandayFunc ), DFUNCTION(julianday, -1, 0, 0, juliandayFunc ),
FUNCTION(date, -1, 0, 0, dateFunc ), DFUNCTION(date, -1, 0, 0, dateFunc ),
FUNCTION(time, -1, 0, 0, timeFunc ), DFUNCTION(time, -1, 0, 0, timeFunc ),
FUNCTION(datetime, -1, 0, 0, datetimeFunc ), DFUNCTION(datetime, -1, 0, 0, datetimeFunc ),
FUNCTION(strftime, -1, 0, 0, strftimeFunc ), DFUNCTION(strftime, -1, 0, 0, strftimeFunc ),
FUNCTION(current_time, 0, 0, 0, ctimeFunc ), DFUNCTION(current_time, 0, 0, 0, ctimeFunc ),
FUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc), DFUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
FUNCTION(current_date, 0, 0, 0, cdateFunc ), DFUNCTION(current_date, 0, 0, 0, cdateFunc ),
#else #else
STR_FUNCTION(current_time, 0, "%H:%M:%S", 0, currentTimeFunc), STR_FUNCTION(current_time, 0, "%H:%M:%S", 0, currentTimeFunc),
STR_FUNCTION(current_date, 0, "%Y-%m-%d", 0, currentTimeFunc), STR_FUNCTION(current_date, 0, "%Y-%m-%d", 0, currentTimeFunc),

View File

@@ -732,9 +732,15 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
return WRC_Prune; return WRC_Prune;
} }
#endif #endif
if( pDef->funcFlags & SQLITE_FUNC_CONSTANT ){ if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_DATETIME) ){
/* For the purposes of the EP_ConstFunc flag, date and time
** functions are considered constant because the the time does
** not change for the duration of a query. */
ExprSetProperty(pExpr,EP_ConstFunc); ExprSetProperty(pExpr,EP_ConstFunc);
}else{ }
if( (pDef->funcFlags & SQLITE_FUNC_CONSTANT)==0 ){
/* DATETIME functions are considered non-deterministic because of
** the 'now' capability */
notValid(pParse, pNC, "non-deterministic functions", NC_IdxExpr, 0); notValid(pParse, pNC, "non-deterministic functions", NC_IdxExpr, 0);
} }
} }

View File

@@ -1384,18 +1384,19 @@ struct FuncDestructor {
** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. There ** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. There
** are assert() statements in the code to verify this. ** are assert() statements in the code to verify this.
*/ */
#define SQLITE_FUNC_ENCMASK 0x003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */ #define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
#define SQLITE_FUNC_LIKE 0x004 /* Candidate for the LIKE optimization */ #define SQLITE_FUNC_LIKE 0x0004 /* Candidate for the LIKE optimization */
#define SQLITE_FUNC_CASE 0x008 /* Case-sensitive LIKE-type function */ #define SQLITE_FUNC_CASE 0x0008 /* Case-sensitive LIKE-type function */
#define SQLITE_FUNC_EPHEM 0x010 /* Ephemeral. Delete with VDBE */ #define SQLITE_FUNC_EPHEM 0x0010 /* Ephemeral. Delete with VDBE */
#define SQLITE_FUNC_NEEDCOLL 0x020 /* sqlite3GetFuncCollSeq() might be called */ #define SQLITE_FUNC_NEEDCOLL 0x0020 /* sqlite3GetFuncCollSeq() might be called*/
#define SQLITE_FUNC_LENGTH 0x040 /* Built-in length() function */ #define SQLITE_FUNC_LENGTH 0x0040 /* Built-in length() function */
#define SQLITE_FUNC_TYPEOF 0x080 /* Built-in typeof() function */ #define SQLITE_FUNC_TYPEOF 0x0080 /* Built-in typeof() function */
#define SQLITE_FUNC_COUNT 0x100 /* Built-in count(*) aggregate */ #define SQLITE_FUNC_COUNT 0x0100 /* Built-in count(*) aggregate */
#define SQLITE_FUNC_COALESCE 0x200 /* Built-in coalesce() or ifnull() */ #define SQLITE_FUNC_COALESCE 0x0200 /* Built-in coalesce() or ifnull() */
#define SQLITE_FUNC_UNLIKELY 0x400 /* Built-in unlikely() function */ #define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */
#define SQLITE_FUNC_CONSTANT 0x800 /* Constant inputs give a constant output */ #define SQLITE_FUNC_CONSTANT 0x0800 /* Constant inputs give a constant output */
#define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */ #define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */
#define SQLITE_FUNC_DATETIME 0x2000 /* Function returns a date and/or time */
/* /*
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
@@ -1411,6 +1412,10 @@ struct FuncDestructor {
** VFUNCTION(zName, nArg, iArg, bNC, xFunc) ** VFUNCTION(zName, nArg, iArg, bNC, xFunc)
** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag. ** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag.
** **
** DFUNCTION(zName, nArg, iArg, bNC, xFunc)
** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag and
** adds the SQLITE_FUNC_DATETIME flag. Used for date & time functions.
**
** AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal) ** AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal)
** Used to create an aggregate function definition implemented by ** Used to create an aggregate function definition implemented by
** the C functions xStep and xFinal. The first four parameters ** the C functions xStep and xFinal. The first four parameters
@@ -1431,6 +1436,9 @@ struct FuncDestructor {
#define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \ #define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ {nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0} SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0}
#define DFUNCTION(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_FUNC_DATETIME|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0}
#define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \ #define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \
{nArg,SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\ {nArg,SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0} SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0}
@@ -2121,7 +2129,7 @@ struct Expr {
#define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */ #define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */
#define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */ #define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */
#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */ #define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */
#define EP_ConstFunc 0x080000 /* Node is a SQLITE_FUNC_CONSTANT function */ #define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _DATETIME function */
#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */ #define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */
#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */ #define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */

View File

@@ -18,28 +18,131 @@ source $testdir/tester.tcl
do_execsql_test indexexpr1-100 { do_execsql_test indexexpr1-100 {
CREATE TABLE t1(a,b,c); CREATE TABLE t1(a,b,c);
INSERT INTO t1(a,b,c) INSERT INTO t1(a,b,c)
VALUES('In the beginning was the Word',1,1), VALUES('In_the_beginning_was_the_Word',1,1),
('and the Word was with God',1,2), ('and_the_Word_was_with_God',1,2),
('and the Word was God',1,3), ('and_the_Word_was_God',1,3),
('The same was in the beginning with God',2,1), ('The_same_was_in_the_beginning_with_God',2,1),
('All things were made by him',3,1), ('All_things_were_made_by_him',3,1),
('and without him was not any thing made that was made',3,2); ('and_without_him_was_not_any_thing_made_that_was_made',3,2);
CREATE INDEX t1a1 ON t1(substr(a,1,12)); CREATE INDEX t1a1 ON t1(substr(a,1,12));
} {} } {}
do_execsql_test indexexpr1-110 { do_execsql_test indexexpr1-110 {
SELECT b, c, '|' FROM t1 WHERE substr(a,1,12)=='and the Word' ORDER BY b, c; SELECT b, c, '|' FROM t1 WHERE substr(a,1,12)=='and_the_Word' ORDER BY b, c;
} {1 2 | 1 3 |} } {1 2 | 1 3 |}
do_execsql_test indexexpr1-110eqp { do_execsql_test indexexpr1-110eqp {
EXPLAIN QUERY PLAN EXPLAIN QUERY PLAN
SELECT b, c, '|' FROM t1 WHERE substr(a,1,12)=='and the Word' ORDER BY b, c; SELECT b, c, '|' FROM t1 WHERE substr(a,1,12)=='and_the_Word' ORDER BY b, c;
} {/USING INDEX t1a1/} } {/USING INDEX t1a1/}
do_execsql_test indexexpr1-120 { do_execsql_test indexexpr1-120 {
SELECT b, c, '|' FROM t1 WHERE 'and the Word'==substr(a,1,12) ORDER BY b, c; SELECT b, c, '|' FROM t1 WHERE 'and_the_Word'==substr(a,1,12) ORDER BY b, c;
} {1 2 | 1 3 |} } {1 2 | 1 3 |}
do_execsql_test indexexpr1-120eqp { do_execsql_test indexexpr1-120eqp {
EXPLAIN QUERY PLAN EXPLAIN QUERY PLAN
SELECT b, c, '|' FROM t1 WHERE 'and the Word'==substr(a,1,12) ORDER BY b, c; SELECT b, c, '|' FROM t1 WHERE 'and_the_Word'==substr(a,1,12) ORDER BY b, c;
} {/USING INDEX t1a1/} } {/USING INDEX t1a1/}
do_execsql_test indexexpr1-130 {
CREATE INDEX t1ba ON t1(b,substr(a,2,3),c);
SELECT c FROM t1 WHERE b=1 AND substr(a,2,3)='nd_' ORDER BY c;
} {2 3}
do_execsql_test indexexpr1-130eqp {
EXPLAIN QUERY PLAN
SELECT c FROM t1 WHERE b=1 AND substr(a,2,3)='nd_' ORDER BY c;
} {/USING INDEX t1ba/}
do_execsql_test indexexpr1-140 {
SELECT rowid, substr(a,b,3), '|' FROM t1 ORDER BY 2;
} {1 In_ | 2 and | 3 and | 6 d_w | 4 he_ | 5 l_t |}
do_execsql_test indexexpr1-141 {
CREATE INDEX t1abx ON t1(substr(a,b,3));
SELECT rowid FROM t1 WHERE substr(a,b,3)<='and' ORDER BY +rowid;
} {1 2 3}
do_execsql_test indexexpr1-141eqp {
EXPLAIN QUERY PLAN
SELECT rowid FROM t1 WHERE substr(a,b,3)<='and' ORDER BY +rowid;
} {/USING INDEX t1abx/}
do_execsql_test indexexpr1-142 {
SELECT rowid FROM t1 WHERE +substr(a,b,3)<='and' ORDER BY +rowid;
} {1 2 3}
do_execsql_test indexexpr1-150 {
SELECT rowid FROM t1 WHERE substr(a,b,3) IN ('and','l_t','xyz')
ORDER BY +rowid;
} {2 3 5}
do_execsql_test indexexpr1-150eqp {
EXPLAIN QUERY PLAN
SELECT rowid FROM t1 WHERE substr(a,b,3) IN ('and','l_t','xyz')
ORDER BY +rowid;
} {/USING INDEX t1abx/}
do_execsql_test indexexpr1-200 {
DROP TABLE t1;
CREATE TABLE t1(id ANY PRIMARY KEY, a,b,c) WITHOUT ROWID;
INSERT INTO t1(id,a,b,c)
VALUES(1,'In_the_beginning_was_the_Word',1,1),
(2,'and_the_Word_was_with_God',1,2),
(3,'and_the_Word_was_God',1,3),
(4,'The_same_was_in_the_beginning_with_God',2,1),
(5,'All_things_were_made_by_him',3,1),
(6,'and_without_him_was_not_any_thing_made_that_was_made',3,2);
CREATE INDEX t1a1 ON t1(substr(a,1,12));
} {}
do_execsql_test indexexpr1-210 {
SELECT b, c, '|' FROM t1 WHERE substr(a,1,12)=='and_the_Word' ORDER BY b, c;
} {1 2 | 1 3 |}
do_execsql_test indexexpr1-210eqp {
EXPLAIN QUERY PLAN
SELECT b, c, '|' FROM t1 WHERE substr(a,1,12)=='and_the_Word' ORDER BY b, c;
} {/USING INDEX t1a1/}
do_execsql_test indexexpr1-220 {
SELECT b, c, '|' FROM t1 WHERE 'and_the_Word'==substr(a,1,12) ORDER BY b, c;
} {1 2 | 1 3 |}
do_execsql_test indexexpr1-220eqp {
EXPLAIN QUERY PLAN
SELECT b, c, '|' FROM t1 WHERE 'and_the_Word'==substr(a,1,12) ORDER BY b, c;
} {/USING INDEX t1a1/}
do_execsql_test indexexpr1-230 {
CREATE INDEX t1ba ON t1(b,substr(a,2,3),c);
SELECT c FROM t1 WHERE b=1 AND substr(a,2,3)='nd_' ORDER BY c;
} {2 3}
do_execsql_test indexexpr1-230eqp {
EXPLAIN QUERY PLAN
SELECT c FROM t1 WHERE b=1 AND substr(a,2,3)='nd_' ORDER BY c;
} {/USING INDEX t1ba/}
do_execsql_test indexexpr1-240 {
SELECT id, substr(a,b,3), '|' FROM t1 ORDER BY 2;
} {1 In_ | 2 and | 3 and | 6 d_w | 4 he_ | 5 l_t |}
do_execsql_test indexexpr1-241 {
CREATE INDEX t1abx ON t1(substr(a,b,3));
SELECT id FROM t1 WHERE substr(a,b,3)<='and' ORDER BY +id;
} {1 2 3}
do_execsql_test indexexpr1-241eqp {
EXPLAIN QUERY PLAN
SELECT id FROM t1 WHERE substr(a,b,3)<='and' ORDER BY +id;
} {/USING INDEX t1abx/}
do_execsql_test indexexpr1-242 {
SELECT id FROM t1 WHERE +substr(a,b,3)<='and' ORDER BY +id;
} {1 2 3}
do_execsql_test indexexpr1-250 {
SELECT id FROM t1 WHERE substr(a,b,3) IN ('and','l_t','xyz')
ORDER BY +id;
} {2 3 5}
do_execsql_test indexexpr1-250eqp {
EXPLAIN QUERY PLAN
SELECT id FROM t1 WHERE substr(a,b,3) IN ('and','l_t','xyz')
ORDER BY +id;
} {/USING INDEX t1abx/}
do_catchsql_test indexexpr1-300 {
CREATE TABLE t2(a,b,c);
CREATE INDEX t2x1 ON t2(a,b+random());
} {1 {non-deterministic functions prohibited in index expressions}}
do_catchsql_test indexexpr1-301 {
CREATE INDEX t2x1 ON t2(a+julianday('now'));
} {1 {non-deterministic functions prohibited in index expressions}}
do_catchsql_test indexexpr1-310 {
CREATE INDEX t2x2 ON t2(a,b+(SELECT 15));
} {1 {subqueries prohibited in index expressions}}
finish_test finish_test