]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix a problem causing an infinite loop or other malfunction in some UPDATE
authordan <dan@noemail.net>
Tue, 16 Jan 2018 13:37:43 +0000 (13:37 +0000)
committerdan <dan@noemail.net>
Tue, 16 Jan 2018 13:37:43 +0000 (13:37 +0000)
statements with an OR term in the WHERE clause.

FossilOrigin-Name: feb2c2b6f66b0f45490beb1642d99cdb89fa220e299a8c118929df557c814189

manifest
manifest.uuid
src/where.c
test/update2.test

index fe093445380d3c6e4765ad0f013b42195e95d62a..31ecdf30e1807783c75798a1c088275a04d4c6c3 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Disable\sthe\s".archive"\scommand\stests\sin\sshell8.test\sif\sthe\sCLI\sis\scompiled\swithout\nZLIB\ssupport.
-D 2018-01-16T02:38:35.189
+C Fix\sa\sproblem\scausing\san\sinfinite\sloop\sor\sother\smalfunction\sin\ssome\sUPDATE\nstatements\swith\san\sOR\sterm\sin\sthe\sWHERE\sclause.
+D 2018-01-16T13:37:43.188
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F Makefile.in 38f84f301cbef443b2d269f67a74b8cc536469831f70df7c3e912acc04932cc2
@@ -568,7 +568,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
 F src/wal.c 5a3f464edd64596f601683ed321d12e6fd93c5fb9afdfb3653d6ffd0fee9c48f
 F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a
 F src/walker.c da987a20d40145c0a03c07d8fefcb2ed363becc7680d0500d9c79915591f5b1f
-F src/where.c 36b92103f726609cc3dbe07c619426bd6886bede455de56ccff54c8e567f5582
+F src/where.c caf0b6c9d31f22f0b2c91aba723858de52b5d665aaa89034099015aaf9bb8219
 F src/whereInt.h 82c04c5075308abbac59180c8bad5ecb45b07453981f60a53f3c7dee21e1e971
 F src/wherecode.c af1e79154aaa88cd802d6f2e5b945f67eaca7c958d1525fbf8ee19d5bd7b9020
 F src/whereexpr.c 427ea8e96ec24f2a7814c67b8024ad664a9c7656264c4566c34743cb23186e46
@@ -1490,7 +1490,7 @@ F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2
 F test/unixexcl.test d936ba2b06794018e136418addd59a2354eeae97
 F test/unordered.test ca7adce0419e4ca0c50f039885e76ed2c531eda8
 F test/update.test 6c68446b8a0a33d522a7c72b320934596a2d7d32
-F test/update2.test fffc92e72ae568fe048588762e650cd8ccbd8c8b6e4fe9099231766bfe4b51de
+F test/update2.test 5e67667e1c54017d964e626db765cf8bedcf87483c184f4c575bdb8c1dd2313e
 F test/uri.test 3481026f00ade6dfe8adb7acb6e1e47b04369568
 F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7
 F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9
@@ -1699,7 +1699,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P b0b7d0363acf38c2178e2d3041d8ce2a0de061a51caa64670dbf539ee6d4356b
-R 7e32bbd83b21ce648e53afd2544cab2d
-U drh
-Z 4c459e37e4b5a5b61d3c298abef31f05
+P ce8bfe6c2b87090a2de1e04bc88fcb878597fe1f4ecd5df6d9d588a65601c901
+R 1aa7995509c0f191863de5587ae93f47
+U dan
+Z 2e5fd108f2c4172f1f8c00e9ff432235
index 82ff37d4dad671f43b675691ebe8e97b2cc33f96..239a9bce672215cf3c7d62a4fb0400f5c2e94572 100644 (file)
@@ -1 +1 @@
-ce8bfe6c2b87090a2de1e04bc88fcb878597fe1f4ecd5df6d9d588a65601c901
\ No newline at end of file
+feb2c2b6f66b0f45490beb1642d99cdb89fa220e299a8c118929df557c814189
\ No newline at end of file
index ec53527943f35fe748422258704894c587dc23dc..3152c8e9aa49b60a7d51b406689b9c21d8f01bab 100644 (file)
@@ -4801,15 +4801,32 @@ WhereInfo *sqlite3WhereBegin(
 
   /* If the caller is an UPDATE or DELETE statement that is requesting
   ** to use a one-pass algorithm, determine if this is appropriate.
+  **
+  ** A one-pass approach can be used if the caller has requested one
+  ** and either (a) the scan visits at most one row or (b) each
+  ** of the following are true:
+  **
+  **   * the caller has indicated that a one-pass approach can be used
+  **     with multiple rows (by setting WHERE_ONEPASS_MULTIROW), and
+  **   * the table is not a virtual table, and
+  **   * either the scan does not use the OR optimization or the caller
+  **     is a DELETE operation (WHERE_DUPLICATES_OK is only specified
+  **     for DELETE).
+  **
+  ** The last qualification is because an UPDATE statement uses
+  ** WhereInfo.aiCurOnePass[1] to determine whether or not it really can
+  ** use a one-pass approach, and this is not set accurately for scans
+  ** that use the OR optimization.
   */
   assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 );
   if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 ){
     int wsFlags = pWInfo->a[0].pWLoop->wsFlags;
     int bOnerow = (wsFlags & WHERE_ONEROW)!=0;
-    if( bOnerow
-     || ((wctrlFlags & WHERE_ONEPASS_MULTIROW)!=0
-           && 0==(wsFlags & WHERE_VIRTUALTABLE))
-    ){
+    if( bOnerow || (
+        0!=(wctrlFlags & WHERE_ONEPASS_MULTIROW)
+     && 0==(wsFlags & WHERE_VIRTUALTABLE)
+     && (0==(wsFlags & WHERE_MULTI_OR) || (wctrlFlags & WHERE_DUPLICATES_OK))
+    )){
       pWInfo->eOnePass = bOnerow ? ONEPASS_SINGLE : ONEPASS_MULTI;
       if( HasRowid(pTabList->a[0].pTab) && (wsFlags & WHERE_IDX_ONLY) ){
         if( wctrlFlags & WHERE_ONEPASS_MULTIROW ){
index af4ce96e7feb461c9bc8c3228717563f8e7e2200..a6c31134000dbf1831cac6417613a54ef02e88a6 100644 (file)
@@ -200,5 +200,20 @@ do_test 5.2 {
   set A(NotExists)
 } {1}
 
+#-------------------------------------------------------------------------
+do_execsql_test 6.0 {
+  CREATE TABLE d1(a,b);
+  CREATE INDEX d1b ON d1(a);
+  CREATE INDEX d1c ON d1(b);
+  INSERT INTO d1 VALUES(1,2);
+}
+
+do_execsql_test 6.1 {
+  UPDATE d1 SET a = a+2 WHERE a>0 OR b>0;
+}
+
+do_execsql_test 6.2 {
+  SELECT * FROM d1;
+} {3 2}
 
 finish_test