-C Merge\srecent\schanges\sfrom\strunk.\s\sAlso\sremove\sunused\svariables\sto\spermit\ncompiling\swith\s-Werror.
-D 2015-12-11T13:59:45.914
+C Add\sfurther\stests\sfor\sthe\schanges\son\sthis\sbranch.\sAlso\sfix\sa\smemory-leak\sthat\scould\sfollow\sa\smalloc\sfailure.
+D 2015-12-12T17:31:40.728
F Makefile.in 28bcd6149e050dff35d4dcfd97e890cd387a499d
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc e8fdca1cb89a1b58b5f4d3a130ea9a3d28cb314d
F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198
F src/date.c fb1c99172017dcc8e237339132c91a21a0788584
F src/dbstat.c ffd63fc8ba7541476ced189b95e95d7f2bc63f78
-F src/delete.c 93f68145ac74fd8f7849175e09db4fd70e96b03d
+F src/delete.c a7ada4d4ca96daa71508d73128ffe5f1710f6c33
F src/expr.c ccb93d7b7e1ac5d187c9b153bae145933f93ee5c
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 31900763094a3736a5fc887469202eb579fef2d0
F src/sqlite.h.in 7d87d71b9a4689c51fa092f48f16590ff71558e3
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d
-F src/sqliteInt.h e93e14407ef5ad4b8eabd7b9a765cfb190722ffb
+F src/sqliteInt.h dd30e0e695e56795ce6cd0694499bb64af48cc16
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
F src/wal.c cb709aa42fc11b1ea92a00c8c7e6214de0995fa3
F src/wal.h 907943dfdef10b583e81906679a347e0ec6f1b1b
F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba
-F src/where.c b3b70c8e0f02a4f5f0722322615d93e3f9fb337b
+F src/where.c b7462d37a9819071d252bf167d5e951a2a9c5c1e
F src/whereInt.h e20801d89e34de1912bb6a3babb30c390da27add
F src/wherecode.c dfbfe198e418b01f208b489e088edd230c91a4e7
F src/whereexpr.c eebba8340c90de73b3d3bbe8c43b84559b8e6e2c
F test/delete.test e1bcdf8926234e27aac24b346ad83d3329ec8b6f
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab
-F test/delete4.test fb95a3f0640789cb95ca19f5f9b28731611a6295
+F test/delete4.test dbd922693b52332e5e1f1b748513f11d28414bbc
+F test/delete_fault.test bb4a1ab823f77df32db237ad4e96562d1b06795a
F test/descidx1.test 6d03b44c8538fe0eb4924e19fba10cdd8f3c9240
F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d
F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2
F test/fkey7.test 72e915890ee4a005daaf3002cb208e8fe973ac13
F test/fkey8.test 8f08203458321e6c19a263829de4cfc936274ab0
F test/fkey_malloc.test 594a7ea1fbab553c036c70813cd8bd9407d63749
-F test/fordelete.test 3648283f90ab7a8e046d9b0c54e497a80ff7b2a2
+F test/fordelete.test 2b8b9a2d8f430ceacb314b06b020116d3d136931
F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c
F test/fts1a.test 46090311f85da51bb33bd5ce84f7948359c6d8d7
F test/syscall.test 2aa9e111b79fb385681ff8940124def6f8faab87
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
F test/tabfunc01.test cc33684f9480fcf1fd5ce287ac28d22971cad1cc
-F test/table.test f85f8694f94ac1275cee81f84bdea66cdcc494c5
+F test/table.test 9ed9aed4a81a0369531b697186ce3a611e57295d
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
F test/tclsqlite.test 7fb866443c7deceed22b63948ccd6f76b52ad054
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 571b64b923c82060f34bf6baa21d72d2a9797e6f e998513e442ce1206b12dc28bdc996d7b5f9f94d
-R 7e34dbe155ea9f60691f4ae03f3a719a
-U drh
-Z abb81097f04b710d8fe83482078029c5
+P 57b700baa690f73894cd53b8e87839760fe4019b
+R 86649e829c9bcb9dbf4e0f992deac233
+U dan
+Z ef334e7566d0d33e4ad81a28a6f57921
-57b700baa690f73894cd53b8e87839760fe4019b
\ No newline at end of file
+21526012c274e709d672dbafb9e16158c0749341
\ No newline at end of file
*/
static void deleteSetColUsed(Parse *pParse, SrcList *pSrc, Expr *pExpr){
Walker w;
+ assert( pSrc->nSrc==1 );
memset(&w, 0, sizeof(w));
w.pParse = pParse;
w.u.pSrcList = pSrc;
/* This loop iterates once for each OR-connected term in the WHERE clause */
for(i=0; rc==SQLITE_OK && (pExpr=sqlite3WhereSplitExpr(pWInfo, i)); i++){
- if( db->mallocFailed ) break;
- deleteSetColUsed(pParse, pTabList, pExpr);
- rc = deleteFrom(pParse, pTabList, pExpr, 0, 0, 0, memCnt, nIdx);
+ if( db->mallocFailed==0 ){
+ deleteSetColUsed(pParse, pTabList, pExpr);
+ rc = deleteFrom(pParse, pTabList, pExpr, 0, 0, 0, memCnt, nIdx);
+ }
sqlite3ExprDelete(db, pExpr);
}
sqlite3WhereInfoFree(db, pWInfo);
#define ONEPASS_OFF 0 /* Use of ONEPASS not allowed */
#define ONEPASS_SINGLE 1 /* ONEPASS valid for a single row update */
#define ONEPASS_MULTI 2 /* ONEPASS is valid for multiple rows */
-#define ONEPASS_SPLIT_DELETE 3
+#define ONEPASS_SPLIT_DELETE 3 /* DELETE should be split into multiple ops */
void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int);
int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
void sqlite3ExprCodeGetColumnToReg(Parse*, Table*, int, int, int);
** sub-expression iExpr is returned. The caller is responsible for eventually
** deleting this object using sqlite3ExprDelete().
**
-** If an OOM error occurs, NULL is returned. In this case the mallocFailed
-** field of the database handle (pWInfo->pParse->db->mallocFailed) is set
-** to record the error.
+** If an OOM error occurs, the mallocFailed field of the database handle
+** (pWInfo->pParse->db->mallocFailed) is set to record the error. Even
+** if an OOM error occurs, this function may return a non-NULL pointer. In
+** this case the caller is still responsible for deleting the returned
+** object, even though it is not safe to use.
*/
Expr *sqlite3WhereSplitExpr(WhereInfo *pWInfo, int iExpr){
sqlite3 *db = pWInfo->pParse->db;
&& 0==(wsFlags & WHERE_VIRTUALTABLE)
)){
if( (wsFlags & WHERE_MULTI_OR) && (wctrlFlags & WHERE_ONEPASS_MULTIROW) ){
+ /* This call is being made as part of a DELETE program and the
+ ** optimizer has indicated that the OR-optimization is the best
+ ** approach. In this case it is better to let the caller generate
+ ** a separate loop for each OR'd term than to actually go ahead
+ ** and code the OR-optimized loop. Set the value returned by
+ ** sqlite3WhereOkOnePass() to ONEPASS_SPLIT_DELETE to communicate
+ ** this to the caller and return early. */
pWInfo->eOnePass = ONEPASS_SPLIT_DELETE;
return pWInfo;
}
}
}
+#-------------------------------------------------------------------------
+# Test that nested OR optimizations work.
+#
+do_execsql_test 6.0 {
+ CREATE TABLE t6(a, b, c, d);
+ CREATE INDEX t6a ON t6(a);
+ CREATE INDEX t6b ON t6(b);
+ CREATE INDEX t6c ON t6(c);
+ WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<1000 )
+ INSERT INTO t6 SELECT i, i*2, i*3, i%2 FROM s;
+}
+
+proc do_61_test {tn sql lDel} {
+ uplevel [list do_execsql_test $tn "
+ BEGIN;
+ $sql;
+ WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<1000 )
+ SELECT i FROM s EXCEPT SELECT a FROM t6 ORDER BY 1;
+ ROLLBACK;
+ " $lDel]
+}
+
+do_61_test 6.1 {
+ DELETE FROM t6 WHERE a=22 OR b=90 OR (d=0 AND (b=400 OR c=303));
+} {22 45 200}
+
+do_61_test 6.2 {
+ DELETE FROM t6 WHERE a=22 OR b=90 OR (d=1 AND (b=400 OR c=303));
+} {22 45 101}
+
+do_61_test 6.3 {
+ DELETE FROM t6 WHERE (d=0 AND (a=100 OR b=150)) OR (d=1 AND (b=50 OR c=603));
+} {25 100 201}
+
finish_test
--- /dev/null
+# 2015 December 10
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library. The focus
+# of this file is fault-injection into DELETE statements.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix delete_fault
+
+do_execsql_test 1.0 {
+ CREATE TABLE t6(a, b, c, d);
+ CREATE INDEX t6a ON t6(a);
+ CREATE INDEX t6b ON t6(b);
+ CREATE INDEX t6c ON t6(c);
+ WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<1000 )
+ INSERT INTO t6 SELECT i, i*2, i*3, i%2 FROM s;
+}
+faultsim_save_and_close
+
+proc deleted_t6_rows {} {
+ db eval {
+ WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<1000 )
+ SELECT i FROM s EXCEPT SELECT a FROM t6 ORDER BY 1;
+ }
+}
+
+do_faultsim_test 1 -faults oom-t* -prep {
+ faultsim_restore_and_reopen
+} -body {
+ execsql {
+ DELETE FROM t6 WHERE (d=0 AND (a=100 OR b=150)) OR (d=1 AND (b=50 OR c=603))
+ }
+} -test {
+ faultsim_test_result {0 {}}
+ if {$testrc==0} {
+ set lDel [deleted_t6_rows]
+ if {$lDel != "25 100 201"} { error "lDel is $lDel" }
+ }
+}
+
+finish_test
do_adp_test 2.3.$tn "DELETE FROM t3 WHERE $where" $res
}
+do_execsql_test 2.4.0 {
+ CREATE TABLE t6(a, b, c, d);
+ CREATE INDEX t6a ON t6(a);
+ CREATE INDEX t6b ON t6(b);
+ CREATE INDEX t6c ON t6(c);
+}
+
+do_adp_test 2.4.1 {
+ DELETE FROM t6 WHERE a=22 OR b=90 OR (d=0 AND (b=400 OR c=303));
+} [lsort {
+ t6* t6a t6b* t6c*
+ t6* t6a* t6b t6c*
+ t6 t6a* t6b t6c*
+ t6 t6a* t6b* t6c
+}]
+
+do_adp_test 2.4.2 {
+ DELETE FROM t6 WHERE a=22 OR b=90 OR (d=1 AND (b=400 OR c=303));
+} [lsort {
+ t6* t6a t6b* t6c*
+ t6* t6a* t6b t6c*
+ t6 t6a* t6b t6c*
+ t6 t6a* t6b* t6c
+}]
+
+do_adp_test 2.4.3 {
+ DELETE FROM t6 WHERE (d=0 AND (a=100 OR b=150)) OR (d=1 AND (b=50 OR c=603));
+} [lsort {
+ t6 t6a t6b* t6c*
+ t6 t6a* t6b t6c*
+ t6 t6a* t6b t6c*
+ t6 t6a* t6b* t6c
+}]
+
#-------------------------------------------------------------------------
# Test that a record that consists of the bytes:
#
# At one point the DROP TABLE in the following was causing problems on an
# experimental branch.
#
-do_execsql_test 20.0 {
+reset_db
+do_execsql_test table-20.0 {
CREATE TABLE t20(a PRIMARY KEY, b, c);
CREATE TRIGGER tr6 AFTER INSERT ON t20 BEGIN SELECT 1+1+1; END;
ANALYZE;