/ Check-in [8e79a0c2]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fixes for OMIT_SUBQUERY builds: Disable where clause OR->IN optimization. Include EXISTS keyword (for new CREATE TABLE syntax). Test file fixes. (CVS 2943)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:8e79a0c24a03ccf960d6ccfb7c6b9b0f7c614e9b
User & Date: danielk1977 2006-01-14 08:02:28
Context
2006-01-15
00:13
Documentation updates. Fix to date.c. But most importantly: database connections are now allowed to change threads as long as they are not holding a lock. (CVS 2944) check-in: 03c422ec user: drh tags: trunk
2006-01-14
08:02
Fixes for OMIT_SUBQUERY builds: Disable where clause OR->IN optimization. Include EXISTS keyword (for new CREATE TABLE syntax). Test file fixes. (CVS 2943) check-in: 8e79a0c2 user: danielk1977 tags: trunk
2006-01-13
18:06
Account for multi-byte characters in ALTER TABLE code. Fix for #1609. (CVS 2942) check-in: d634f8b2 user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/where.c.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654



655
656
657
658
659
660
661
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  This module is reponsible for
** generating the code that loops through a table looking for applicable
** rows.  Indices are selected and used to speed the search when doing
** so is applicable.  Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
** $Id: where.c,v 1.197 2006/01/13 15:58:43 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** The number of bits in a Bitmask.  "BMS" means "BitMask Size".
*/
#define BMS  (sizeof(Bitmask)*8)
................................................................................
      pTerm = &pWC->a[idxTerm];
      pWC->a[idxNew].iParent = idxTerm;
    }
    pTerm->nChild = 2;
  }
#endif /* SQLITE_OMIT_BETWEEN_OPTIMIZATION */

#ifndef SQLITE_OMIT_OR_OPTIMIZATION
  /* Attempt to convert OR-connected terms into an IN operator so that
  ** they can make use of indices.  Example:
  **
  **      x = expr1  OR  expr2 = x  OR  x = expr3
  **
  ** is converted into
  **
  **      x IN (expr1,expr2,expr3)



  */
  else if( pExpr->op==TK_OR ){
    int ok;
    int i, j;
    int iColumn, iCursor;
    WhereClause sOr;
    WhereTerm *pOrTerm;







|







 







|








>
>
>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  This module is reponsible for
** generating the code that loops through a table looking for applicable
** rows.  Indices are selected and used to speed the search when doing
** so is applicable.  Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
** $Id: where.c,v 1.198 2006/01/14 08:02:28 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** The number of bits in a Bitmask.  "BMS" means "BitMask Size".
*/
#define BMS  (sizeof(Bitmask)*8)
................................................................................
      pTerm = &pWC->a[idxTerm];
      pWC->a[idxNew].iParent = idxTerm;
    }
    pTerm->nChild = 2;
  }
#endif /* SQLITE_OMIT_BETWEEN_OPTIMIZATION */

#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY)
  /* Attempt to convert OR-connected terms into an IN operator so that
  ** they can make use of indices.  Example:
  **
  **      x = expr1  OR  expr2 = x  OR  x = expr3
  **
  ** is converted into
  **
  **      x IN (expr1,expr2,expr3)
  **
  ** This optimization must be omitted if OMIT_SUBQUERY is defined because
  ** the compiler for the the IN operator is part of sub-queries.
  */
  else if( pExpr->op==TK_OR ){
    int ok;
    int i, j;
    int iColumn, iCursor;
    WhereClause sOr;
    WhereTerm *pOrTerm;

Changes to test/alter.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
556
557
558
559
560
561
562

563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
#    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 script is testing the ALTER TABLE statement.
#
# $Id: alter.test,v 1.13 2006/01/13 18:06:40 danielk1977 Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
................................................................................
do_test alter-5.1 {
  string length $::tbl_name
} {7}
do_test alter-5.2 {
  execsql "
    CREATE TABLE ${tbl_name}(a, b, c);
  "

  execsql {
    SELECT sql FROM sqlite_master 
        WHERE oid = (SELECT max(oid) FROM sqlite_master);
  }
} "{CREATE TABLE ${::tbl_name}(a, b, c)}"
set ::tbl_name2 "abcXdef"
do_test alter-5.2 {
  execsql "
    ALTER TABLE $::tbl_name RENAME TO $::tbl_name2 
  "
  execsql {
    SELECT sql FROM sqlite_master 
        WHERE oid = (SELECT max(oid) FROM sqlite_master);
  }
} "{CREATE TABLE '${::tbl_name2}'(a, b, c)}"
do_test alter-5.3 {
  execsql "
    ALTER TABLE $::tbl_name2 RENAME TO $::tbl_name
  "
  execsql {
    SELECT sql FROM sqlite_master 
        WHERE oid = (SELECT max(oid) FROM sqlite_master);
  }
} "{CREATE TABLE '${::tbl_name}'(a, b, c)}"
set ::col_name ghi\1234\jkl
do_test alter-5.4 {
  execsql "
    ALTER TABLE $::tbl_name ADD COLUMN $::col_name VARCHAR
  "
  execsql {
    SELECT sql FROM sqlite_master 
        WHERE oid = (SELECT max(oid) FROM sqlite_master);
  }
} "{CREATE TABLE '${::tbl_name}'(a, b, c, $::col_name VARCHAR)}"
set ::col_name2 B\3421\A
do_test alter-5.5 {
  db close
  sqlite3 db test.db
  execsql "
    ALTER TABLE $::tbl_name ADD COLUMN $::col_name2
  "
  execsql {
    SELECT sql FROM sqlite_master 
        WHERE oid = (SELECT max(oid) FROM sqlite_master);
  }
} "{CREATE TABLE '${::tbl_name}'(a, b, c, $::col_name VARCHAR, $::col_name2)}"
do_test alter-5.6 {
  execsql "
    INSERT INTO ${::tbl_name} VALUES(1, 2, 3, 4, 5);
    SELECT $::col_name, $::col_name2 FROM $::tbl_name;
  "
} {4 5}

finish_test








|







 







>

|
<








|
<







|
<








|
<










|
<











7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
556
557
558
559
560
561
562
563
564
565

566
567
568
569
570
571
572
573
574

575
576
577
578
579
580
581
582

583
584
585
586
587
588
589
590
591

592
593
594
595
596
597
598
599
600
601
602

603
604
605
606
607
608
609
610
611
612
613
#    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 script is testing the ALTER TABLE statement.
#
# $Id: alter.test,v 1.14 2006/01/14 08:02:28 danielk1977 Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
................................................................................
do_test alter-5.1 {
  string length $::tbl_name
} {7}
do_test alter-5.2 {
  execsql "
    CREATE TABLE ${tbl_name}(a, b, c);
  "
  set ::oid [execsql {SELECT max(oid) FROM sqlite_master}]
  execsql {
    SELECT sql FROM sqlite_master WHERE oid = $::oid;

  }
} "{CREATE TABLE ${::tbl_name}(a, b, c)}"
set ::tbl_name2 "abcXdef"
do_test alter-5.2 {
  execsql "
    ALTER TABLE $::tbl_name RENAME TO $::tbl_name2 
  "
  execsql {
    SELECT sql FROM sqlite_master WHERE oid = $::oid;

  }
} "{CREATE TABLE '${::tbl_name2}'(a, b, c)}"
do_test alter-5.3 {
  execsql "
    ALTER TABLE $::tbl_name2 RENAME TO $::tbl_name
  "
  execsql {
    SELECT sql FROM sqlite_master WHERE oid = $::oid;

  }
} "{CREATE TABLE '${::tbl_name}'(a, b, c)}"
set ::col_name ghi\1234\jkl
do_test alter-5.4 {
  execsql "
    ALTER TABLE $::tbl_name ADD COLUMN $::col_name VARCHAR
  "
  execsql {
    SELECT sql FROM sqlite_master WHERE oid = $::oid;

  }
} "{CREATE TABLE '${::tbl_name}'(a, b, c, $::col_name VARCHAR)}"
set ::col_name2 B\3421\A
do_test alter-5.5 {
  db close
  sqlite3 db test.db
  execsql "
    ALTER TABLE $::tbl_name ADD COLUMN $::col_name2
  "
  execsql {
    SELECT sql FROM sqlite_master WHERE oid = $::oid;

  }
} "{CREATE TABLE '${::tbl_name}'(a, b, c, $::col_name VARCHAR, $::col_name2)}"
do_test alter-5.6 {
  execsql "
    INSERT INTO ${::tbl_name} VALUES(1, 2, 3, 4, 5);
    SELECT $::col_name, $::col_name2 FROM $::tbl_name;
  "
} {4 5}

finish_test

Changes to test/check.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
147
148
149
150
151
152
153

154
155
156
157
158
159
160
161


162
163
164
165
166
167
168
#    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 testing CHECK constraints
#
# $Id: check.test,v 1.6 2005/11/14 22:29:06 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Only run these tests if the build includes support for CHECK constraints
ifcapable !check {
  finish_test
................................................................................
} {1 {constraint failed}}
do_test check-2.6 {
  catchsql {
    INSERT INTO t2 VALUES(NULL, NULL, 3.14159);
  }
} {1 {constraint failed}}


do_test check-3.1 {
  catchsql {
    CREATE TABLE t3(
      x, y, z,
      CHECK( x<(SELECT min(x) FROM t1) )
    );
  }
} {1 {subqueries prohibited in CHECK constraints}}


do_test check-3.2 {
  execsql {
    SELECT name FROM sqlite_master ORDER BY name
  }
} {t1 t2}
do_test check-3.3 {
  catchsql {







|







 







>
|
|
|
|
|
|
|
|
>
>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#    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 testing CHECK constraints
#
# $Id: check.test,v 1.7 2006/01/14 08:02:28 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Only run these tests if the build includes support for CHECK constraints
ifcapable !check {
  finish_test
................................................................................
} {1 {constraint failed}}
do_test check-2.6 {
  catchsql {
    INSERT INTO t2 VALUES(NULL, NULL, 3.14159);
  }
} {1 {constraint failed}}

ifcapable subquery {
  do_test check-3.1 {
    catchsql {
      CREATE TABLE t3(
        x, y, z,
        CHECK( x<(SELECT min(x) FROM t1) )
      );
    }
  } {1 {subqueries prohibited in CHECK constraints}}
}

do_test check-3.2 {
  execsql {
    SELECT name FROM sqlite_master ORDER BY name
  }
} {t1 t2}
do_test check-3.3 {
  catchsql {

Changes to test/descidx3.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
118
119
120
121
122
123
124




125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

144
#    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 script is descending indices.
#
# $Id: descidx3.test,v 1.1 2006/01/02 18:24:40 drh Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# This procedure sets the value of the file-format in file 'test.db'
# to $newval. Also, the schema cookie is incremented.
................................................................................
} {5 2 4 3 8 6 7 9}
do_test descidx3-3.5 {
  execsql {
    SELECT i FROM t1 WHERE b>-9999 AND b<x'ffffffff'
  }
} {9 7 6 8 3 4 2 5}





do_test descidx3-4.1 {
  execsql {
    UPDATE t1 SET a=2 WHERE i<6;
    SELECT i FROM t1 WHERE a IN (1,2) AND b>0 AND b<'zzz';
  }
} {8 6 2 4 3}
do_test descidx3-4.2 {
  execsql {
    UPDATE t1 SET a=1;
    SELECT i FROM t1 WHERE a IN (1,2) AND b>0 AND b<'zzz';
  }
} {2 4 3 8 6}
do_test descidx3-4.3 {
  execsql {
    UPDATE t1 SET b=2;
    SELECT i FROM t1 WHERE a IN (1,2) AND b>0 AND b<'zzz';
  }
} {9 7 6 8 3 4 2 5 1}


finish_test







|







 







>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#    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 script is descending indices.
#
# $Id: descidx3.test,v 1.2 2006/01/14 08:02:28 danielk1977 Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# This procedure sets the value of the file-format in file 'test.db'
# to $newval. Also, the schema cookie is incremented.
................................................................................
} {5 2 4 3 8 6 7 9}
do_test descidx3-3.5 {
  execsql {
    SELECT i FROM t1 WHERE b>-9999 AND b<x'ffffffff'
  }
} {9 7 6 8 3 4 2 5}

ifcapable subquery {
  # If the subquery capability is not compiled in to the binary, then
  # the IN(...) operator is not available. Hence these tests cannot be 
  # run.
  do_test descidx3-4.1 {
    execsql {
      UPDATE t1 SET a=2 WHERE i<6;
      SELECT i FROM t1 WHERE a IN (1,2) AND b>0 AND b<'zzz';
    }
  } {8 6 2 4 3}
  do_test descidx3-4.2 {
    execsql {
      UPDATE t1 SET a=1;
      SELECT i FROM t1 WHERE a IN (1,2) AND b>0 AND b<'zzz';
    }
  } {2 4 3 8 6}
  do_test descidx3-4.3 {
    execsql {
      UPDATE t1 SET b=2;
      SELECT i FROM t1 WHERE a IN (1,2) AND b>0 AND b<'zzz';
    }
  } {9 7 6 8 3 4 2 5 1}
}

finish_test

Changes to test/misc2.test.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
253
254
255
256
257
258
259

260
261
262
263
264
265
266
267
268
269

270
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for miscellanous features that were
# left out of other test files.
#
# $Id: misc2.test,v 1.22 2005/04/29 02:10:00 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable {trigger} {
# Test for ticket #360
#
................................................................................
# Ticket #1229.  Sometimes when a "NEW.X" appears in a SELECT without
# a FROM clause deep within a trigger, the code generator is unable to
# trace the NEW.X back to an original table and thus figure out its
# declared datatype.
#
# The SQL code below was causing a segfault.
#

do_test misc2-10.1 {
  execsql {
    CREATE TABLE t1229(x);
    CREATE TRIGGER r1229 BEFORE INSERT ON t1229 BEGIN
      INSERT INTO t1229 SELECT y FROM (SELECT new.x y);
    END;
    INSERT INTO t1229 VALUES(1);
  }
} {}


finish_test







|







 







>
|
|
|
|
|
|
|
|
|
|
>

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for miscellanous features that were
# left out of other test files.
#
# $Id: misc2.test,v 1.23 2006/01/14 08:02:28 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable {trigger} {
# Test for ticket #360
#
................................................................................
# Ticket #1229.  Sometimes when a "NEW.X" appears in a SELECT without
# a FROM clause deep within a trigger, the code generator is unable to
# trace the NEW.X back to an original table and thus figure out its
# declared datatype.
#
# The SQL code below was causing a segfault.
#
ifcapable subquery {
  do_test misc2-10.1 {
    execsql {
      CREATE TABLE t1229(x);
      CREATE TRIGGER r1229 BEFORE INSERT ON t1229 BEGIN
        INSERT INTO t1229 SELECT y FROM (SELECT new.x y);
      END;
      INSERT INTO t1229 VALUES(1);
    }
  } {}
}

finish_test

Changes to test/misc5.test.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
435
436
437
438
439
440
441

442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473

474
475
476
477
478
479
480
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for miscellanous features that were
# left out of other test files.
#
# $Id: misc5.test,v 1.8 2006/01/05 14:22:34 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Build records using the MakeRecord opcode such that the size of the 
# header is at the transition point in the size of a varint.
#
................................................................................
4611686018427387903\
4611686018427387904\
4611686018427387905"

# Ticket #1210.  Do proper reference counting of Table structures
# so that deeply nested SELECT statements can be flattened correctly.
#

do_test misc5-3.1 {
  execsql {
    CREATE TABLE songs(songid, artist, timesplayed);
    INSERT INTO songs VALUES(1,'one',1);
    INSERT INTO songs VALUES(2,'one',2);
    INSERT INTO songs VALUES(3,'two',3);
    INSERT INTO songs VALUES(4,'three',5);
    INSERT INTO songs VALUES(5,'one',7);
    INSERT INTO songs VALUES(6,'two',11);
    SELECT DISTINCT artist 
    FROM (    
     SELECT DISTINCT artist    
     FROM songs      
     WHERE songid IN (    
      SELECT songid    
      FROM songs    
      WHERE LOWER(artist) = (    
        SELECT DISTINCT LOWER(artist)    
        FROM (      
          SELECT DISTINCT artist,sum(timesplayed) AS total      
          FROM songs      
          GROUP BY LOWER(artist)      
          ORDER BY total DESC      
          LIMIT 10    
        )    
        WHERE artist <> '' 
      )  
     )       
    )  
    ORDER BY LOWER(artist) ASC;
  }
} {two}


# Ticket #1370.  Do not overwrite small files (less than 1024 bytes)
# when trying to open them as a database.
#
do_test misc5-4.1 {
  db close
  file delete -force test.db







|







 







>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for miscellanous features that were
# left out of other test files.
#
# $Id: misc5.test,v 1.9 2006/01/14 08:02:28 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Build records using the MakeRecord opcode such that the size of the 
# header is at the transition point in the size of a varint.
#
................................................................................
4611686018427387903\
4611686018427387904\
4611686018427387905"

# Ticket #1210.  Do proper reference counting of Table structures
# so that deeply nested SELECT statements can be flattened correctly.
#
ifcapable subquery {
  do_test misc5-3.1 {
    execsql {
      CREATE TABLE songs(songid, artist, timesplayed);
      INSERT INTO songs VALUES(1,'one',1);
      INSERT INTO songs VALUES(2,'one',2);
      INSERT INTO songs VALUES(3,'two',3);
      INSERT INTO songs VALUES(4,'three',5);
      INSERT INTO songs VALUES(5,'one',7);
      INSERT INTO songs VALUES(6,'two',11);
      SELECT DISTINCT artist 
      FROM (    
       SELECT DISTINCT artist    
       FROM songs      
       WHERE songid IN (    
        SELECT songid    
        FROM songs    
        WHERE LOWER(artist) = (    
          SELECT DISTINCT LOWER(artist)    
          FROM (      
            SELECT DISTINCT artist,sum(timesplayed) AS total      
            FROM songs      
            GROUP BY LOWER(artist)      
            ORDER BY total DESC      
            LIMIT 10    
          )    
          WHERE artist <> '' 
        )  
       )       
      )  
      ORDER BY LOWER(artist) ASC;
    }
  } {two}
}

# Ticket #1370.  Do not overwrite small files (less than 1024 bytes)
# when trying to open them as a database.
#
do_test misc5-4.1 {
  db close
  file delete -force test.db

Changes to test/select1.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
799
800
801
802
803
804
805

806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826

827
828
829
#    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 testing the SELECT statement.
#
# $Id: select1.test,v 1.46 2006/01/13 13:01:20 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Try to select on a non-existant table.
#
do_test select1-1.1 {
................................................................................
    }
  } {x 1 x 3}
} ;# ifcapable compound


# Check for a VDBE stack growth problem that existed at one point.
#

do_test select1-13.1 {
  execsql {
    BEGIN;
    create TABLE abc(a, b, c, PRIMARY KEY(a, b));
    INSERT INTO abc VALUES(1, 1, 1);
  }
  for {set i 0} {$i<10} {incr i} {
    execsql {
      INSERT INTO abc SELECT a+(select max(a) FROM abc), 
          b+(select max(a) FROM abc), c+(select max(a) FROM abc) FROM abc;
    }
  }
  execsql {COMMIT}

  # This used to seg-fault when the problem existed.
  execsql {
    SELECT count(
      (SELECT a FROM abc WHERE a = NULL AND b >= upper.c) 
    ) FROM abc AS upper;
  }
} {0}


finish_test








|







 







>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
#    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 testing the SELECT statement.
#
# $Id: select1.test,v 1.47 2006/01/14 08:02:28 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Try to select on a non-existant table.
#
do_test select1-1.1 {
................................................................................
    }
  } {x 1 x 3}
} ;# ifcapable compound


# Check for a VDBE stack growth problem that existed at one point.
#
ifcapable subquery {
  do_test select1-13.1 {
    execsql {
      BEGIN;
      create TABLE abc(a, b, c, PRIMARY KEY(a, b));
      INSERT INTO abc VALUES(1, 1, 1);
    }
    for {set i 0} {$i<10} {incr i} {
      execsql {
        INSERT INTO abc SELECT a+(select max(a) FROM abc), 
            b+(select max(a) FROM abc), c+(select max(a) FROM abc) FROM abc;
      }
    }
    execsql {COMMIT}
  
    # This used to seg-fault when the problem existed.
    execsql {
      SELECT count(
        (SELECT a FROM abc WHERE a = NULL AND b >= upper.c) 
      ) FROM abc AS upper;
    }
  } {0}
}

finish_test

Changes to test/shared.test.

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
187
188
189
190
191
192
193
194

195
196
197
198
199
200
201
202
#
#    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.
#
#***********************************************************************
#
# $Id: shared.test,v 1.11 2006/01/11 14:09:32 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
db close

ifcapable !shared_cache {
  finish_test
................................................................................
  "
  execsql {SELECT * FROM sqlite_master} db2
  execsql {PRAGMA read_uncommitted = 1} db2

  set ret [list]
  db2 eval {SELECT i FROM seq} {
    if {$i < 4} {
      execsql {

        INSERT INTO seq SELECT i + (SELECT max(i) FROM seq), x FROM seq;
      }
    }
    lappend ret $i
  }
  set ret
} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16}
do_test shared-3.1.2 {







|







 







|
>
|







5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
#
#    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.
#
#***********************************************************************
#
# $Id: shared.test,v 1.12 2006/01/14 08:02:29 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
db close

ifcapable !shared_cache {
  finish_test
................................................................................
  "
  execsql {SELECT * FROM sqlite_master} db2
  execsql {PRAGMA read_uncommitted = 1} db2

  set ret [list]
  db2 eval {SELECT i FROM seq} {
    if {$i < 4} {
      set max [execsql {SELECT max(i) FROM seq}]
      db eval {
        INSERT INTO seq SELECT i + $max, x FROM seq;
      }
    }
    lappend ret $i
  }
  set ret
} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16}
do_test shared-3.1.2 {

Changes to test/tkt1443.test.

30
31
32
33
34
35
36
37
38
39
40
41




42
43
44
45
46
47
48
#
# NOTE:  Yes, in spite of the name of this file (tkt1443.test) this
# test is for ticket #1433 not #1443.  I mistyped the name when I was
# creating the file and I had already checked in the file by the wrong
# name be the time I noticed the error.  With CVS it is a really hassle
# to change filenames, so I'll just leave it as is.  No harm done.
#
# $Id: tkt1443.test,v 1.2 2005/09/17 13:29:24 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl






# Construct the sample database.
#
do_test tkt1443-1.0 {
  sqlite3 db :memory:
  execsql {
    CREATE TABLE Items(







|




>
>
>
>







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#
# NOTE:  Yes, in spite of the name of this file (tkt1443.test) this
# test is for ticket #1433 not #1443.  I mistyped the name when I was
# creating the file and I had already checked in the file by the wrong
# name be the time I noticed the error.  With CVS it is a really hassle
# to change filenames, so I'll just leave it as is.  No harm done.
#
# $Id: tkt1443.test,v 1.3 2006/01/14 08:02:29 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !subquery {
  finish_test
  return
}

# Construct the sample database.
#
do_test tkt1443-1.0 {
  sqlite3 db :memory:
  execsql {
    CREATE TABLE Items(

Changes to test/tkt1449.test.

12
13
14
15
16
17
18







19
20
21
22
23
24
25
#
# This file implements tests to verify that ticket #1449 has been
# fixed.  
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl








# The following schema generated problems in ticket #1449.  We've retained
# the original schema here because it is some unbelievably complex, it seemed
# like a good test case for SQLite.
#
do_test tkt1449-1.1 {
  execsql {







>
>
>
>
>
>
>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#
# This file implements tests to verify that ticket #1449 has been
# fixed.  
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Somewhere in tkt1449-1.1 is a VIEW definition that uses a subquery.
# So we cannot run this file if subqueries are not available.
ifcapable !subquery {
  finish_test
  return
}

# The following schema generated problems in ticket #1449.  We've retained
# the original schema here because it is some unbelievably complex, it seemed
# like a good test case for SQLite.
#
do_test tkt1449-1.1 {
  execsql {

Changes to test/tkt1473.test.

62
63
64
65
66
67
68







69
70
71
72
73
74
75
  }
} {}
do_test tkt1473-1.9 {
  execsql {
    SELECT 1 FROM t1 WHERE a=0 UNION SELECT 2 FROM t1 WHERE b=0
  }
} {}








do_test tkt1473-2.2 {
  execsql {
    SELECT (SELECT 1 FROM t1 WHERE a=1 UNION ALL SELECT 2 FROM t1 WHERE b=0)
  }
} {1}
do_test tkt1473-2.3 {







>
>
>
>
>
>
>







62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
  }
} {}
do_test tkt1473-1.9 {
  execsql {
    SELECT 1 FROM t1 WHERE a=0 UNION SELECT 2 FROM t1 WHERE b=0
  }
} {}

# Everything from this point on depends on sub-queries. So skip it
# if sub-queries are not available.
ifcapable !subquery {
  finish_test
  return
}

do_test tkt1473-2.2 {
  execsql {
    SELECT (SELECT 1 FROM t1 WHERE a=1 UNION ALL SELECT 2 FROM t1 WHERE b=0)
  }
} {1}
do_test tkt1473-2.3 {

Changes to test/tkt1537.test.

34
35
36
37
38
39
40

41
42
43
44
45
46
47
48
49
50

51
52
53
54
55
56
57
58
59
60
61
62
63


64
65
66
67
68
69
70
71
72
73

74
75
76
77
78
79
80
  }
} {1 {} {} {} {} 2 1 3 3 1}
do_test tkt1537-1.3 {
  execsql {
    SELECT * FROM t2 LEFT JOIN t1 ON a1=b OR a2=b;
  }
} {3 1 2 1 3 4 {} {} {} {}}

do_test tkt1537-1.4 {
  execsql {
    SELECT * FROM t1 LEFT JOIN t2 ON b IN (a1,a2);
  }
} {1 {} {} {} {} 2 1 3 3 1}
do_test tkt1537-1.5 {
  execsql {
    SELECT * FROM t2 LEFT JOIN t1 ON b IN (a2,a1);
  }
} {3 1 2 1 3 4 {} {} {} {}}

do_test tkt1537-1.6 {
  execsql {
    CREATE INDEX t1a1 ON t1(a1);
    CREATE INDEX t1a2 ON t1(a2);
    CREATE INDEX t2b ON t2(b);
    SELECT * FROM t1 LEFT JOIN t2 ON a1=b OR a2=b;
  }
} {1 {} {} {} {} 2 1 3 3 1}
do_test tkt1537-1.7 {
  execsql {
    SELECT * FROM t2 LEFT JOIN t1 ON a1=b OR a2=b;
  }
} {3 1 2 1 3 4 {} {} {} {}}


do_test tkt1537-1.8 {
  execsql {
    SELECT * FROM t1 LEFT JOIN t2 ON b IN (a1,a2);
  }
} {1 {} {} {} {} 2 1 3 3 1}
do_test tkt1537-1.9 {
  execsql {
    SELECT * FROM t2 LEFT JOIN t1 ON b IN (a2,a1);
  }
} {3 1 2 1 3 4 {} {} {} {}}


execsql {
  DROP INDEX t1a1;
  DROP INDEX t1a2;
  DROP INDEX t2b;
}








>
|
|
|
|
|
|
|
|
|
|
>













>
>
|
|
|
|
|
|
|
|
|
|
>







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
  }
} {1 {} {} {} {} 2 1 3 3 1}
do_test tkt1537-1.3 {
  execsql {
    SELECT * FROM t2 LEFT JOIN t1 ON a1=b OR a2=b;
  }
} {3 1 2 1 3 4 {} {} {} {}}
ifcapable subquery {
  do_test tkt1537-1.4 {
    execsql {
      SELECT * FROM t1 LEFT JOIN t2 ON b IN (a1,a2);
    }
  } {1 {} {} {} {} 2 1 3 3 1}
  do_test tkt1537-1.5 {
    execsql {
      SELECT * FROM t2 LEFT JOIN t1 ON b IN (a2,a1);
    }
  } {3 1 2 1 3 4 {} {} {} {}}
}
do_test tkt1537-1.6 {
  execsql {
    CREATE INDEX t1a1 ON t1(a1);
    CREATE INDEX t1a2 ON t1(a2);
    CREATE INDEX t2b ON t2(b);
    SELECT * FROM t1 LEFT JOIN t2 ON a1=b OR a2=b;
  }
} {1 {} {} {} {} 2 1 3 3 1}
do_test tkt1537-1.7 {
  execsql {
    SELECT * FROM t2 LEFT JOIN t1 ON a1=b OR a2=b;
  }
} {3 1 2 1 3 4 {} {} {} {}}

ifcapable subquery {
  do_test tkt1537-1.8 {
    execsql {
      SELECT * FROM t1 LEFT JOIN t2 ON b IN (a1,a2);
    }
  } {1 {} {} {} {} 2 1 3 3 1}
  do_test tkt1537-1.9 {
    execsql {
      SELECT * FROM t2 LEFT JOIN t1 ON b IN (a2,a1);
    }
  } {3 1 2 1 3 4 {} {} {} {}}
}

execsql {
  DROP INDEX t1a1;
  DROP INDEX t1a2;
  DROP INDEX t2b;
}

Changes to test/view.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
424
425
426
427
428
429
430

431
432
433
434
435

436
437
438
439
440
441
442
#    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 testing VIEW statements.
#
# $Id: view.test,v 1.27 2005/08/20 03:03:04 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Omit this entire file if the library is not configured with views enabled.
ifcapable !view {
  finish_test
  return
................................................................................
    CREATE TABLE t4(a COLLATE NOCASE);
    INSERT INTO t4 VALUES('This');
    INSERT INTO t4 VALUES('this');
    INSERT INTO t4 VALUES('THIS');
    SELECT * FROM t4 WHERE a = 'THIS';
  }
} {This this THIS}

do_test view-11.2 {
  execsql {
    SELECT * FROM (SELECT * FROM t4) WHERE a = 'THIS';
  }
} {This this THIS}

do_test view-11.3 {
  execsql {
    CREATE VIEW v11 AS SELECT * FROM t4;
    SELECT * FROM v11 WHERE a = 'THIS';
  }
} {This this THIS}








|







 







>
|
|
|
|
|
>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
#    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 testing VIEW statements.
#
# $Id: view.test,v 1.28 2006/01/14 08:02:29 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Omit this entire file if the library is not configured with views enabled.
ifcapable !view {
  finish_test
  return
................................................................................
    CREATE TABLE t4(a COLLATE NOCASE);
    INSERT INTO t4 VALUES('This');
    INSERT INTO t4 VALUES('this');
    INSERT INTO t4 VALUES('THIS');
    SELECT * FROM t4 WHERE a = 'THIS';
  }
} {This this THIS}
ifcapable subquery {
  do_test view-11.2 {
    execsql {
      SELECT * FROM (SELECT * FROM t4) WHERE a = 'THIS';
    }
  } {This this THIS}
}
do_test view-11.3 {
  execsql {
    CREATE VIEW v11 AS SELECT * FROM t4;
    SELECT * FROM v11 WHERE a = 'THIS';
  }
} {This this THIS}

Changes to test/where2.test.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
120
121
122
123
124
125
126

127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189


190
191
192
193
194
195
196
197


198
199
200
201
202

203
204
205


206
207
208
209
210
211
212
213
214
215

216
217
218
219
220
221
222
223
224
225



226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the use of indices in WHERE clauses
# based on recent changes to the optimizer.
#
# $Id: where2.test,v 1.5 2005/08/13 16:13:06 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Build some test data
#
do_test where2-1.0 {
................................................................................
  queryplan {
    SELECT * FROM t1 ORDER BY rowid DESC LIMIT 2
  }
} {100 6 10201 10207 99 6 10000 10006 nosort t1 *}

# The IN operator can be used by indices at multiple layers
#

do_test where2-4.1 {
  queryplan {
    SELECT * FROM t1 WHERE z IN (10207,10006) AND y IN (10000,10201)
                     AND x>0 AND x<10
    ORDER BY w
  }
} {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}
do_test where2-4.2 {
  queryplan {
    SELECT * FROM t1 WHERE z IN (10207,10006) AND y=10000
                     AND x>0 AND x<10
    ORDER BY w
  }
} {99 6 10000 10006 sort t1 i1zyx}
do_test where2-4.3 {
  queryplan {
    SELECT * FROM t1 WHERE z=10006 AND y IN (10000,10201)
                     AND x>0 AND x<10
    ORDER BY w
  }
} {99 6 10000 10006 sort t1 i1zyx}
do_test where2-4.4 {
  queryplan {
    SELECT * FROM t1 WHERE z IN (SELECT 10207 UNION SELECT 10006)
                     AND y IN (10000,10201)
                     AND x>0 AND x<10
    ORDER BY w
  }
} {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}
do_test where2-4.5 {
  queryplan {
    SELECT * FROM t1 WHERE z IN (SELECT 10207 UNION SELECT 10006)
                     AND y IN (SELECT 10000 UNION SELECT 10201)
                     AND x>0 AND x<10
    ORDER BY w
  }
} {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}
do_test where2-4.6 {
  queryplan {
    SELECT * FROM t1
     WHERE x IN (1,2,3,4,5,6,7,8)
       AND y IN (10000,10001,10002,10003,10004,10005)
     ORDER BY 2
  }
} {99 6 10000 10006 sort t1 i1xy}

# Duplicate entires on the RHS of an IN operator do not cause duplicate
# output rows.
#
do_test where2-4.6 {
  queryplan {
    SELECT * FROM t1 WHERE z IN (10207,10006,10006,10207)
    ORDER BY w
  }
} {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}
do_test where2-4.7 {
  queryplan {
    SELECT * FROM t1 WHERE z IN (
       SELECT 10207 UNION ALL SELECT 10006
       UNION ALL SELECT 10006 UNION ALL SELECT 10207)
    ORDER BY w
  }
} {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}



# The use of an IN operator disables the index as a sorter.
#
do_test where2-5.1 {
  queryplan {
    SELECT * FROM t1 WHERE w=99 ORDER BY w
  }
} {99 6 10000 10006 nosort t1 i1w}


do_test where2-5.2 {
  queryplan {
    SELECT * FROM t1 WHERE w IN (99) ORDER BY w
  }
} {99 6 10000 10006 sort t1 i1w}


# Verify that OR clauses get translated into IN operators.
#


do_test where2-6.1 {
  queryplan {
    SELECT * FROM t1 WHERE w=99 OR w=100 ORDER BY +w
  }
} {99 6 10000 10006 100 6 10201 10207 sort t1 i1w}
do_test where2-6.2 {
  queryplan {
    SELECT * FROM t1 WHERE w=99 OR w=100 OR 6=w ORDER BY +w
  }
} {6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 i1w}

do_test where2-6.3 {
  queryplan {
    SELECT * FROM t1 WHERE w=99 OR w=100 OR 6=+w ORDER BY +w
  }
} {6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 {}}
do_test where2-6.4 {
  queryplan {
    SELECT * FROM t1 WHERE w=99 OR +w=100 OR 6=w ORDER BY +w
  }
} {6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 {}}



do_test where2-6.5 {
  queryplan {
    SELECT b.* FROM t1 a, t1 b
     WHERE a.w=1 AND (a.y=b.z OR b.z=10)
     ORDER BY +b.w
  }
} {1 0 4 4 2 1 9 10 sort a i1w b i1zyx}
do_test where2-6.6 {
  queryplan {
    SELECT b.* FROM t1 a, t1 b
     WHERE a.w=1 AND (b.z=10 OR a.y=b.z OR b.z=10)
     ORDER BY +b.w
  }
} {1 0 4 4 2 1 9 10 sort a i1w b i1zyx}

# Unique queries (queries that are guaranteed to return only a single
# row of result) do not call the sorter.  But all tables must give
# a unique result.  If any one table in the join does not give a unique
# result then sorting is necessary.
#
do_test where2-7.1 {







|







 







>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>








>
>
|
|
|
|
|
>



>
>




|




|
>










>
>
>






|






|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the use of indices in WHERE clauses
# based on recent changes to the optimizer.
#
# $Id: where2.test,v 1.6 2006/01/14 08:02:29 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Build some test data
#
do_test where2-1.0 {
................................................................................
  queryplan {
    SELECT * FROM t1 ORDER BY rowid DESC LIMIT 2
  }
} {100 6 10201 10207 99 6 10000 10006 nosort t1 *}

# The IN operator can be used by indices at multiple layers
#
ifcapable subquery {
  do_test where2-4.1 {
    queryplan {
      SELECT * FROM t1 WHERE z IN (10207,10006) AND y IN (10000,10201)
                       AND x>0 AND x<10
      ORDER BY w
    }
  } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}
  do_test where2-4.2 {
    queryplan {
      SELECT * FROM t1 WHERE z IN (10207,10006) AND y=10000
                       AND x>0 AND x<10
      ORDER BY w
    }
  } {99 6 10000 10006 sort t1 i1zyx}
  do_test where2-4.3 {
    queryplan {
      SELECT * FROM t1 WHERE z=10006 AND y IN (10000,10201)
                       AND x>0 AND x<10
      ORDER BY w
    }
  } {99 6 10000 10006 sort t1 i1zyx}
  do_test where2-4.4 {
    queryplan {
      SELECT * FROM t1 WHERE z IN (SELECT 10207 UNION SELECT 10006)
                       AND y IN (10000,10201)
                       AND x>0 AND x<10
      ORDER BY w
    }
  } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}
  do_test where2-4.5 {
    queryplan {
      SELECT * FROM t1 WHERE z IN (SELECT 10207 UNION SELECT 10006)
                       AND y IN (SELECT 10000 UNION SELECT 10201)
                       AND x>0 AND x<10
      ORDER BY w
    }
  } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}
  do_test where2-4.6 {
    queryplan {
      SELECT * FROM t1
       WHERE x IN (1,2,3,4,5,6,7,8)
         AND y IN (10000,10001,10002,10003,10004,10005)
       ORDER BY 2
    }
  } {99 6 10000 10006 sort t1 i1xy}

  # Duplicate entires on the RHS of an IN operator do not cause duplicate
  # output rows.
  #
  do_test where2-4.6 {
    queryplan {
      SELECT * FROM t1 WHERE z IN (10207,10006,10006,10207)
      ORDER BY w
    }
  } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}
  do_test where2-4.7 {
    queryplan {
      SELECT * FROM t1 WHERE z IN (
         SELECT 10207 UNION ALL SELECT 10006
         UNION ALL SELECT 10006 UNION ALL SELECT 10207)
      ORDER BY w
    }
  } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}

} ;# ifcapable subquery

# The use of an IN operator disables the index as a sorter.
#
do_test where2-5.1 {
  queryplan {
    SELECT * FROM t1 WHERE w=99 ORDER BY w
  }
} {99 6 10000 10006 nosort t1 i1w}

ifcapable subquery {
  do_test where2-5.2 {
    queryplan {
      SELECT * FROM t1 WHERE w IN (99) ORDER BY w
    }
  } {99 6 10000 10006 sort t1 i1w}
}

# Verify that OR clauses get translated into IN operators.
#
set ::idx {}
ifcapable subquery {set ::idx i1w}
do_test where2-6.1 {
  queryplan {
    SELECT * FROM t1 WHERE w=99 OR w=100 ORDER BY +w
  }
} [list 99 6 10000 10006 100 6 10201 10207 sort t1 $::idx]
do_test where2-6.2 {
  queryplan {
    SELECT * FROM t1 WHERE w=99 OR w=100 OR 6=w ORDER BY +w
  }
} [list 6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 $::idx]

do_test where2-6.3 {
  queryplan {
    SELECT * FROM t1 WHERE w=99 OR w=100 OR 6=+w ORDER BY +w
  }
} {6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 {}}
do_test where2-6.4 {
  queryplan {
    SELECT * FROM t1 WHERE w=99 OR +w=100 OR 6=w ORDER BY +w
  }
} {6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 {}}

set ::idx {}
ifcapable subquery {set ::idx i1zyx}
do_test where2-6.5 {
  queryplan {
    SELECT b.* FROM t1 a, t1 b
     WHERE a.w=1 AND (a.y=b.z OR b.z=10)
     ORDER BY +b.w
  }
} [list 1 0 4 4 2 1 9 10 sort a i1w b $::idx]
do_test where2-6.6 {
  queryplan {
    SELECT b.* FROM t1 a, t1 b
     WHERE a.w=1 AND (b.z=10 OR a.y=b.z OR b.z=10)
     ORDER BY +b.w
  }
} [list 1 0 4 4 2 1 9 10 sort a i1w b $::idx]

# Unique queries (queries that are guaranteed to return only a single
# row of result) do not call the sorter.  But all tables must give
# a unique result.  If any one table in the join does not give a unique
# result then sorting is necessary.
#
do_test where2-7.1 {

Changes to tool/mkkeywordhash.c.

151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
  { "DROP",             "TK_DROP",         ALWAYS                 },
  { "END",              "TK_END",          ALWAYS                 },
  { "EACH",             "TK_EACH",         TRIGGER                },
  { "ELSE",             "TK_ELSE",         ALWAYS                 },
  { "ESCAPE",           "TK_ESCAPE",       ALWAYS                 },
  { "EXCEPT",           "TK_EXCEPT",       COMPOUND               },
  { "EXCLUSIVE",        "TK_EXCLUSIVE",    ALWAYS                 },
  { "EXISTS",           "TK_EXISTS",       SUBQUERY               },
  { "EXPLAIN",          "TK_EXPLAIN",      EXPLAIN                },
  { "FAIL",             "TK_FAIL",         CONFLICT|TRIGGER       },
  { "FOR",              "TK_FOR",          TRIGGER                },
  { "FOREIGN",          "TK_FOREIGN",      FKEY                   },
  { "FROM",             "TK_FROM",         ALWAYS                 },
  { "FULL",             "TK_JOIN_KW",      ALWAYS                 },
  { "GLOB",             "TK_LIKE_KW",      ALWAYS                 },







|







151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
  { "DROP",             "TK_DROP",         ALWAYS                 },
  { "END",              "TK_END",          ALWAYS                 },
  { "EACH",             "TK_EACH",         TRIGGER                },
  { "ELSE",             "TK_ELSE",         ALWAYS                 },
  { "ESCAPE",           "TK_ESCAPE",       ALWAYS                 },
  { "EXCEPT",           "TK_EXCEPT",       COMPOUND               },
  { "EXCLUSIVE",        "TK_EXCLUSIVE",    ALWAYS                 },
  { "EXISTS",           "TK_EXISTS",       ALWAYS                 },
  { "EXPLAIN",          "TK_EXPLAIN",      EXPLAIN                },
  { "FAIL",             "TK_FAIL",         CONFLICT|TRIGGER       },
  { "FOR",              "TK_FOR",          TRIGGER                },
  { "FOREIGN",          "TK_FOREIGN",      FKEY                   },
  { "FROM",             "TK_FROM",         ALWAYS                 },
  { "FULL",             "TK_JOIN_KW",      ALWAYS                 },
  { "GLOB",             "TK_LIKE_KW",      ALWAYS                 },