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:
18
manifest
18
manifest
@@ -1,5 +1,5 @@
|
||||
C Improved\sanalysis\sand\susage\sof\sindexed\sexpressions\sin\sthe\squery\splanner.
|
||||
D 2015-08-31T15:58:06.350
|
||||
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-31T17:34:41.308
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in f85066ce844a28b671aaeeff320921cd0ce36239
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@@ -286,7 +286,7 @@ F src/build.c e0902658fc86dbd60a5c6772ca45429c69ee81fe
|
||||
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
|
||||
F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f
|
||||
F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b
|
||||
F src/date.c 8ec787fed4929d8ccdf6b1bc360fccc3e1d2ca58
|
||||
F src/date.c fb1c99172017dcc8e237339132c91a21a0788584
|
||||
F src/dbstat.c f402e77e25089c6003d0c60b3233b9b3947d599a
|
||||
F src/delete.c 224e5c9a0eae7fbdd3b461ca971465c992851354
|
||||
F src/expr.c cf0c5ef6467d3eb65e3ff5c88eb2f602ba3b5163
|
||||
@@ -335,14 +335,14 @@ F src/pragma.h 631a91c8b0e6ca8f051a1d8a4a0da4150e04620a
|
||||
F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1
|
||||
F src/printf.c 2bc439ff20a4aad0e0ad50a37a67b5eae7d20edc
|
||||
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
|
||||
F src/resolve.c e6dc5a5490cf93afc1cc2cb58280c98da56acb3c
|
||||
F src/resolve.c 3ec6456a534bcbf0f3fc11ad83c6208301db60a2
|
||||
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
|
||||
F src/select.c b52c80f2b1bdb62491f9ce40eea0c5f80c78d105
|
||||
F src/shell.c 6332ef06db1390ef812cfdff1fc97b4fd76cdd42
|
||||
F src/sqlite.h.in 378bebc8fe6a88bade25e5f23b7e6123fdc64b00
|
||||
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
||||
F src/sqlite3ext.h f700e6a9dd1fdcccc9951ab022b366fb66b9e413
|
||||
F src/sqliteInt.h 340fc115a707838ad365b52057f126b143f6aa60
|
||||
F src/sqliteInt.h 332ae4f753d91c92421a2c4227c195298d5b154c
|
||||
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
|
||||
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
|
||||
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
|
||||
@@ -780,7 +780,7 @@ F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7
|
||||
F test/index6.test 7102ec371414c42dfb1d5ca37eb4519aa9edc23a
|
||||
F test/index7.test 9c6765a74fc3fcde7aebc5b3bd40d98df14a527c
|
||||
F test/indexedby.test 5f527a78bae74c61b8046ae3037f9dfb0bf0c353
|
||||
F test/indexexpr1.test 36b7aab1fdb03710b99ee876ff764b92c7b96e3e
|
||||
F test/indexexpr1.test 1e57b4bb93b65a451803e7547a51f685af1c35db
|
||||
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
|
||||
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
|
||||
F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371
|
||||
@@ -1381,7 +1381,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 7bde6d4d8cf05e1beb9bdf20b85760dc3e7a76c9
|
||||
R b7744e5a00368fcccd1913a83a0521e8
|
||||
P f8893696387cba9d293a05a68dc38228077b3dc5
|
||||
R 73b6719fd207957d3d30c3e1b6c218bc
|
||||
U drh
|
||||
Z 32945199df036dc2360847bdab3537ac
|
||||
Z fe2263cb4a747333f78b4cc6eb661f66
|
||||
|
@@ -1 +1 @@
|
||||
f8893696387cba9d293a05a68dc38228077b3dc5
|
||||
c77554b5c42327106a7b90334e9cc3c07b007c76
|
16
src/date.c
16
src/date.c
@@ -1115,14 +1115,14 @@ static void currentTimeFunc(
|
||||
void sqlite3RegisterDateTimeFunctions(void){
|
||||
static SQLITE_WSD FuncDef aDateTimeFuncs[] = {
|
||||
#ifndef SQLITE_OMIT_DATETIME_FUNCS
|
||||
FUNCTION(julianday, -1, 0, 0, juliandayFunc ),
|
||||
FUNCTION(date, -1, 0, 0, dateFunc ),
|
||||
FUNCTION(time, -1, 0, 0, timeFunc ),
|
||||
FUNCTION(datetime, -1, 0, 0, datetimeFunc ),
|
||||
FUNCTION(strftime, -1, 0, 0, strftimeFunc ),
|
||||
FUNCTION(current_time, 0, 0, 0, ctimeFunc ),
|
||||
FUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
|
||||
FUNCTION(current_date, 0, 0, 0, cdateFunc ),
|
||||
DFUNCTION(julianday, -1, 0, 0, juliandayFunc ),
|
||||
DFUNCTION(date, -1, 0, 0, dateFunc ),
|
||||
DFUNCTION(time, -1, 0, 0, timeFunc ),
|
||||
DFUNCTION(datetime, -1, 0, 0, datetimeFunc ),
|
||||
DFUNCTION(strftime, -1, 0, 0, strftimeFunc ),
|
||||
DFUNCTION(current_time, 0, 0, 0, ctimeFunc ),
|
||||
DFUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
|
||||
DFUNCTION(current_date, 0, 0, 0, cdateFunc ),
|
||||
#else
|
||||
STR_FUNCTION(current_time, 0, "%H:%M:%S", 0, currentTimeFunc),
|
||||
STR_FUNCTION(current_date, 0, "%Y-%m-%d", 0, currentTimeFunc),
|
||||
|
@@ -732,9 +732,15 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
return WRC_Prune;
|
||||
}
|
||||
#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);
|
||||
}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);
|
||||
}
|
||||
}
|
||||
|
@@ -1384,18 +1384,19 @@ struct FuncDestructor {
|
||||
** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. There
|
||||
** are assert() statements in the code to verify this.
|
||||
*/
|
||||
#define SQLITE_FUNC_ENCMASK 0x003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
|
||||
#define SQLITE_FUNC_LIKE 0x004 /* Candidate for the LIKE optimization */
|
||||
#define SQLITE_FUNC_CASE 0x008 /* Case-sensitive LIKE-type function */
|
||||
#define SQLITE_FUNC_EPHEM 0x010 /* Ephemeral. Delete with VDBE */
|
||||
#define SQLITE_FUNC_NEEDCOLL 0x020 /* sqlite3GetFuncCollSeq() might be called */
|
||||
#define SQLITE_FUNC_LENGTH 0x040 /* Built-in length() function */
|
||||
#define SQLITE_FUNC_TYPEOF 0x080 /* Built-in typeof() function */
|
||||
#define SQLITE_FUNC_COUNT 0x100 /* Built-in count(*) aggregate */
|
||||
#define SQLITE_FUNC_COALESCE 0x200 /* Built-in coalesce() or ifnull() */
|
||||
#define SQLITE_FUNC_UNLIKELY 0x400 /* Built-in unlikely() function */
|
||||
#define SQLITE_FUNC_CONSTANT 0x800 /* Constant inputs give a constant output */
|
||||
#define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */
|
||||
#define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
|
||||
#define SQLITE_FUNC_LIKE 0x0004 /* Candidate for the LIKE optimization */
|
||||
#define SQLITE_FUNC_CASE 0x0008 /* Case-sensitive LIKE-type function */
|
||||
#define SQLITE_FUNC_EPHEM 0x0010 /* Ephemeral. Delete with VDBE */
|
||||
#define SQLITE_FUNC_NEEDCOLL 0x0020 /* sqlite3GetFuncCollSeq() might be called*/
|
||||
#define SQLITE_FUNC_LENGTH 0x0040 /* Built-in length() function */
|
||||
#define SQLITE_FUNC_TYPEOF 0x0080 /* Built-in typeof() function */
|
||||
#define SQLITE_FUNC_COUNT 0x0100 /* Built-in count(*) aggregate */
|
||||
#define SQLITE_FUNC_COALESCE 0x0200 /* Built-in coalesce() or ifnull() */
|
||||
#define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */
|
||||
#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_DATETIME 0x2000 /* Function returns a date and/or time */
|
||||
|
||||
/*
|
||||
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
|
||||
@@ -1411,6 +1412,10 @@ struct FuncDestructor {
|
||||
** VFUNCTION(zName, nArg, iArg, bNC, xFunc)
|
||||
** 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)
|
||||
** Used to create an aggregate function definition implemented by
|
||||
** the C functions xStep and xFinal. The first four parameters
|
||||
@@ -1431,6 +1436,9 @@ struct FuncDestructor {
|
||||
#define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \
|
||||
{nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
|
||||
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) \
|
||||
{nArg,SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\
|
||||
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_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */
|
||||
#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_Subquery 0x200000 /* Tree contains a TK_SELECT operator */
|
||||
|
||||
|
@@ -18,28 +18,131 @@ source $testdir/tester.tcl
|
||||
do_execsql_test indexexpr1-100 {
|
||||
CREATE TABLE t1(a,b,c);
|
||||
INSERT INTO t1(a,b,c)
|
||||
VALUES('In the beginning was the Word',1,1),
|
||||
('and the Word was with God',1,2),
|
||||
('and the Word was God',1,3),
|
||||
('The same was in the beginning with God',2,1),
|
||||
('All things were made by him',3,1),
|
||||
('and without him was not any thing made that was made',3,2);
|
||||
VALUES('In_the_beginning_was_the_Word',1,1),
|
||||
('and_the_Word_was_with_God',1,2),
|
||||
('and_the_Word_was_God',1,3),
|
||||
('The_same_was_in_the_beginning_with_God',2,1),
|
||||
('All_things_were_made_by_him',3,1),
|
||||
('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-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 |}
|
||||
do_execsql_test indexexpr1-110eqp {
|
||||
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/}
|
||||
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 |}
|
||||
do_execsql_test indexexpr1-120eqp {
|
||||
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/}
|
||||
|
||||
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
|
||||
|
Reference in New Issue
Block a user