-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
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
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
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
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
-f8893696387cba9d293a05a68dc38228077b3dc5
\ No newline at end of file
+c77554b5c42327106a7b90334e9cc3c07b007c76
\ No newline at end of file
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),
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);
}
}
** 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
** 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
#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}
#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 */
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