github.com/jdgcs/sqlite3@v1.12.1-0.20210908114423-bc5f96e4dd51/testdata/tcl/without_rowid1.test (about)

     1  # 2013-10-30
     2  #
     3  # The author disclaims copyright to this source code.  In place of
     4  # a legal notice, here is a blessing:
     5  #
     6  #    May you do good and not evil.
     7  #    May you find forgiveness for yourself and forgive others.
     8  #    May you share freely, never taking more than you give.
     9  #
    10  #***********************************************************************
    11  #
    12  # This file implements regression tests for SQLite library.  The
    13  # focus of this file is testing WITHOUT ROWID tables.
    14  #
    15  
    16  set testdir [file dirname $argv0]
    17  source $testdir/tester.tcl
    18  set testprefix without_rowid1
    19  
    20  proc do_execsql_test_if_vtab {tn sql {res {}}} {
    21    ifcapable vtab { uplevel [list do_execsql_test $tn $sql $res] }
    22  }
    23  
    24  # Create and query a WITHOUT ROWID table.
    25  #
    26  do_execsql_test without_rowid1-1.0 {
    27    CREATE TABLE t1(a,b,c,d, PRIMARY KEY(c,a)) WITHOUT ROWID;
    28    CREATE INDEX t1bd ON t1(b, d);
    29    INSERT INTO t1 VALUES('journal','sherman','ammonia','helena');
    30    INSERT INTO t1 VALUES('dynamic','juliet','flipper','command');
    31    INSERT INTO t1 VALUES('journal','sherman','gamma','patriot');
    32    INSERT INTO t1 VALUES('arctic','sleep','ammonia','helena');
    33    SELECT *, '|' FROM t1 ORDER BY c, a;
    34  } {arctic sleep ammonia helena | journal sherman ammonia helena | dynamic juliet flipper command | journal sherman gamma patriot |}
    35  
    36  integrity_check without_rowid1-1.0ic
    37  
    38  do_execsql_test_if_vtab without_rowid1-1.0ixi {
    39    SELECT name, key FROM pragma_index_xinfo('t1');
    40  } {c 1 a 1 b 0 d 0}
    41  
    42  do_execsql_test without_rowid1-1.1 {
    43    SELECT *, '|' FROM t1 ORDER BY +c, a;
    44  } {arctic sleep ammonia helena | journal sherman ammonia helena | dynamic juliet flipper command | journal sherman gamma patriot |}
    45  
    46  do_execsql_test without_rowid1-1.2 {
    47    SELECT *, '|' FROM t1 ORDER BY c DESC, a DESC;
    48  } {journal sherman gamma patriot | dynamic juliet flipper command | journal sherman ammonia helena | arctic sleep ammonia helena |}
    49  
    50  do_execsql_test without_rowid1-1.11 {
    51    SELECT *, '|' FROM t1 ORDER BY b, d;
    52  } {dynamic juliet flipper command | journal sherman ammonia helena | journal sherman gamma patriot | arctic sleep ammonia helena |}
    53  
    54  do_execsql_test without_rowid1-1.12 {
    55    SELECT *, '|' FROM t1 ORDER BY +b, d;
    56  } {dynamic juliet flipper command | journal sherman ammonia helena | journal sherman gamma patriot | arctic sleep ammonia helena |}
    57  
    58  # Trying to insert a duplicate PRIMARY KEY fails.
    59  #
    60  do_test without_rowid1-1.21 {
    61    catchsql {
    62      INSERT INTO t1 VALUES('dynamic','phone','flipper','harvard');
    63    }
    64  } {1 {UNIQUE constraint failed: t1.c, t1.a}}
    65  
    66  # REPLACE INTO works, however.
    67  #
    68  do_execsql_test without_rowid1-1.22 {
    69    REPLACE INTO t1 VALUES('dynamic','phone','flipper','harvard');
    70    SELECT *, '|' FROM t1 ORDER BY c, a;
    71  } {arctic sleep ammonia helena | journal sherman ammonia helena | dynamic phone flipper harvard | journal sherman gamma patriot |}
    72  
    73  do_execsql_test without_rowid1-1.23 {
    74    SELECT *, '|' FROM t1 ORDER BY b, d;
    75  } {dynamic phone flipper harvard | journal sherman ammonia helena | journal sherman gamma patriot | arctic sleep ammonia helena |}
    76  
    77  # UPDATE statements.
    78  #
    79  do_execsql_test without_rowid1-1.31 {
    80    UPDATE t1 SET d=3.1415926 WHERE a='journal';
    81    SELECT *, '|' FROM t1 ORDER BY c, a;
    82  } {arctic sleep ammonia helena | journal sherman ammonia 3.1415926 | dynamic phone flipper harvard | journal sherman gamma 3.1415926 |}
    83  do_execsql_test without_rowid1-1.32 {
    84    SELECT *, '|' FROM t1 ORDER BY b, d;
    85  } {dynamic phone flipper harvard | journal sherman ammonia 3.1415926 | journal sherman gamma 3.1415926 | arctic sleep ammonia helena |}
    86  
    87  do_execsql_test without_rowid1-1.35 {
    88    UPDATE t1 SET a=1250 WHERE b='phone';
    89    SELECT *, '|' FROM t1 ORDER BY c, a;
    90  } {arctic sleep ammonia helena | journal sherman ammonia 3.1415926 | 1250 phone flipper harvard | journal sherman gamma 3.1415926 |}
    91  integrity_check without_rowid1-1.36
    92  
    93  do_execsql_test without_rowid1-1.37 {
    94    SELECT *, '|' FROM t1 ORDER BY b, d;
    95  } {1250 phone flipper harvard | journal sherman ammonia 3.1415926 | journal sherman gamma 3.1415926 | arctic sleep ammonia helena |}
    96  
    97  do_execsql_test without_rowid1-1.40 {
    98    VACUUM;
    99    SELECT *, '|' FROM t1 ORDER BY b, d;
   100  } {1250 phone flipper harvard | journal sherman ammonia 3.1415926 | journal sherman gamma 3.1415926 | arctic sleep ammonia helena |}
   101  integrity_check without_rowid1-1.41
   102  
   103  # Verify that ANALYZE works
   104  #
   105  do_execsql_test without_rowid1-1.50 {
   106    ANALYZE;
   107    SELECT * FROM sqlite_stat1 ORDER BY idx;
   108  } {t1 t1 {4 2 1} t1 t1bd {4 2 2}}
   109  ifcapable stat4 {
   110    do_execsql_test without_rowid1-1.52 {
   111      SELECT DISTINCT tbl, idx FROM sqlite_stat4 ORDER BY idx;
   112    } {t1 t1 t1 t1bd}
   113  }
   114  
   115  #----------
   116  
   117  do_execsql_test 2.1.1 {
   118    CREATE TABLE t4 (a COLLATE nocase PRIMARY KEY, b) WITHOUT ROWID;
   119    INSERT INTO t4 VALUES('abc', 'def');
   120    SELECT * FROM t4;
   121  } {abc def}
   122  do_execsql_test 2.1.2 {
   123    UPDATE t4 SET a = 'ABC';
   124    SELECT * FROM t4;
   125  } {ABC def}
   126  do_execsql_test_if_vtab 2.1.3 {
   127    SELECT name, coll, key FROM pragma_index_xinfo('t4');
   128  } {a nocase 1 b BINARY 0}
   129  
   130  do_execsql_test 2.2.1 {
   131    DROP TABLE t4;
   132    CREATE TABLE t4 (b, a COLLATE nocase PRIMARY KEY) WITHOUT ROWID;
   133    INSERT INTO t4(a, b) VALUES('abc', 'def');
   134    SELECT * FROM t4;
   135  } {def abc}
   136  
   137  do_execsql_test 2.2.2 {
   138    UPDATE t4 SET a = 'ABC', b = 'xyz';
   139    SELECT * FROM t4;
   140  } {xyz ABC}
   141  
   142  do_execsql_test_if_vtab 2.2.3 {
   143    SELECT name, coll, key FROM pragma_index_xinfo('t4');
   144  } {a nocase 1 b BINARY 0}
   145  
   146  
   147  do_execsql_test 2.3.1 {
   148    CREATE TABLE t5 (a, b, PRIMARY KEY(b, a)) WITHOUT ROWID;
   149    INSERT INTO t5(a, b) VALUES('abc', 'def');
   150    UPDATE t5 SET a='abc', b='def';
   151  } {}
   152  
   153  do_execsql_test_if_vtab 2.3.2 {
   154    SELECT name, coll, key FROM pragma_index_xinfo('t5');
   155  } {b BINARY 1 a BINARY 1}
   156  
   157  
   158  do_execsql_test 2.4.1 {
   159    CREATE TABLE t6 (
   160      a COLLATE nocase, b, c UNIQUE, PRIMARY KEY(b, a)
   161    ) WITHOUT ROWID;
   162  
   163    INSERT INTO t6(a, b, c) VALUES('abc', 'def', 'ghi');
   164    UPDATE t6 SET a='ABC', c='ghi';
   165  } {}
   166  
   167  do_execsql_test 2.4.2 {
   168    SELECT * FROM t6 ORDER BY b, a;
   169    SELECT * FROM t6 ORDER BY c;
   170  } {ABC def ghi ABC def ghi}
   171  
   172  do_execsql_test_if_vtab 2.4.3 {
   173    SELECT name, coll, key FROM pragma_index_xinfo('t6');
   174  } {b BINARY 1 a nocase 1 c BINARY 0}
   175  
   176  
   177  #-------------------------------------------------------------------------
   178  # Unless the destination table is completely empty, the xfer optimization 
   179  # is disabled for WITHOUT ROWID tables. The following tests check for
   180  # some problems that might occur if this were not the case.
   181  #
   182  reset_db
   183  do_execsql_test 3.1.1 {
   184    CREATE TABLE t1(a, b, PRIMARY KEY(a)) WITHOUT ROWID;
   185    CREATE UNIQUE INDEX i1 ON t1(b);
   186  
   187    CREATE TABLE t2(a, b, PRIMARY KEY(a)) WITHOUT ROWID;
   188    CREATE UNIQUE INDEX i2 ON t2(b);
   189  
   190    INSERT INTO t1 VALUES('one', 'two');
   191    INSERT INTO t2 VALUES('three', 'two');
   192  }
   193  
   194  do_execsql_test 3.1.2 {
   195    INSERT OR REPLACE INTO t1 SELECT * FROM t2;
   196    SELECT * FROM t1;
   197  } {three two}
   198  
   199  do_execsql_test 3.1.3 {
   200    DELETE FROM t1;
   201    INSERT INTO t1 SELECT * FROM t2;
   202    SELECT * FROM t1;
   203  } {three two}
   204  
   205  do_catchsql_test 3.1.4 {
   206    INSERT INTO t2 VALUES('four', 'four');
   207    INSERT INTO t2 VALUES('six', 'two');
   208    INSERT INTO t1 SELECT * FROM t2;
   209  } {1 {UNIQUE constraint failed: t2.b}}
   210  
   211  do_execsql_test 3.1.5 {
   212    CREATE TABLE t3(a PRIMARY KEY);
   213    CREATE TABLE t4(a PRIMARY KEY);
   214  
   215    INSERT INTO t4 VALUES('i');
   216    INSERT INTO t4 VALUES('ii');
   217    INSERT INTO t4 VALUES('iii');
   218  
   219    INSERT INTO t3 SELECT * FROM t4;
   220    SELECT * FROM t3;
   221  } {i ii iii}
   222  
   223  ############################################################################
   224  # Ticket [c34d0557f740c450709d6e33df72d4f3f651a3cc]
   225  # Name resolution issue with WITHOUT ROWID
   226  #
   227  do_execsql_test 4.1 {
   228    CREATE TABLE t41(a PRIMARY KEY) WITHOUT ROWID;
   229    INSERT INTO t41 VALUES('abc');
   230    CREATE TABLE t42(x);
   231    INSERT INTO t42 VALUES('xyz');
   232    SELECT t42.rowid FROM t41, t42;
   233  } {1}
   234  do_execsql_test 4.2 {
   235    SELECT t42.rowid FROM t42, t41;
   236  } {1}
   237  
   238  
   239  #--------------------------------------------------------------------------
   240  # The following tests verify that the trailing PK fields added to each
   241  # entry in an index on a WITHOUT ROWID table are used correctly.
   242  #
   243  do_execsql_test 5.0 {
   244    CREATE TABLE t45(a PRIMARY KEY, b, c) WITHOUT ROWID;
   245    CREATE INDEX i45 ON t45(b);
   246  
   247    INSERT INTO t45 VALUES(2, 'one', 'x');
   248    INSERT INTO t45 VALUES(4, 'one', 'x');
   249    INSERT INTO t45 VALUES(6, 'one', 'x');
   250    INSERT INTO t45 VALUES(8, 'one', 'x');
   251    INSERT INTO t45 VALUES(10, 'one', 'x');
   252  
   253    INSERT INTO t45 VALUES(1, 'two', 'x');
   254    INSERT INTO t45 VALUES(3, 'two', 'x');
   255    INSERT INTO t45 VALUES(5, 'two', 'x');
   256    INSERT INTO t45 VALUES(7, 'two', 'x');
   257    INSERT INTO t45 VALUES(9, 'two', 'x');
   258  }
   259  
   260  do_eqp_test 5.1 {
   261    SELECT * FROM t45 WHERE b=? AND a>?
   262  } {USING INDEX i45 (b=? AND a>?)}
   263  
   264  do_execsql_test 5.2 {
   265    SELECT * FROM t45 WHERE b='two' AND a>4
   266  } {5 two x 7 two x 9 two x}
   267  
   268  do_execsql_test 5.3 {
   269    SELECT * FROM t45 WHERE b='one' AND a<8
   270  } { 2 one x 4 one x 6 one x }
   271  
   272  do_execsql_test 5.4 {
   273    CREATE TABLE t46(a, b, c, d, PRIMARY KEY(a, b)) WITHOUT ROWID;
   274    WITH r(x) AS (
   275      SELECT 1 UNION ALL SELECT x+1 FROM r WHERE x<100
   276    )
   277    INSERT INTO t46 SELECT x / 20, x % 20, x % 10, x FROM r;
   278  }
   279  
   280  set queries {
   281    1    2    "c = 5 AND a = 1"          {i46 (c=? AND a=?)}
   282    2    6    "c = 4 AND a < 3"          {i46 (c=? AND a<?)}
   283    3    4    "c = 2 AND a >= 3"         {i46 (c=? AND a>?)}
   284    4    1    "c = 2 AND a = 1 AND b<10" {i46 (c=? AND a=? AND b<?)}
   285    5    1    "c = 0 AND a = 0 AND b>5"  {i46 (c=? AND a=? AND b>?)}
   286  }
   287  
   288  foreach {tn cnt where eqp} $queries {
   289    do_execsql_test 5.5.$tn.1 "SELECT count(*) FROM t46 WHERE $where" $cnt
   290  }
   291  
   292  do_execsql_test 5.6 {
   293    CREATE INDEX i46 ON t46(c);
   294  }
   295  
   296  foreach {tn cnt where eqp} $queries {
   297    do_execsql_test 5.7.$tn.1 "SELECT count(*) FROM t46 WHERE $where" $cnt
   298    do_eqp_test 5.7.$tn.2  "SELECT count(*) FROM t46 WHERE $where" $eqp
   299  }
   300  
   301  #-------------------------------------------------------------------------
   302  # Check that redundant UNIQUE constraints do not cause a problem.
   303  #
   304  do_execsql_test 6.0 {
   305    CREATE TABLE t47(a, b UNIQUE PRIMARY KEY) WITHOUT ROWID;
   306    CREATE INDEX i47 ON t47(a);
   307    INSERT INTO t47 VALUES(1, 2);
   308    INSERT INTO t47 VALUES(2, 4);
   309    INSERT INTO t47 VALUES(3, 6);
   310    INSERT INTO t47 VALUES(4, 8);
   311  
   312    VACUUM;
   313    PRAGMA integrity_check;
   314    SELECT name FROM sqlite_master WHERE tbl_name = 't47';
   315  } {ok t47 i47}
   316  
   317  do_execsql_test 6.1 {
   318    CREATE TABLE t48(
   319      a UNIQUE UNIQUE, 
   320      b UNIQUE, 
   321      PRIMARY KEY(a), 
   322      UNIQUE(a)
   323    ) WITHOUT ROWID;
   324    INSERT INTO t48 VALUES('a', 'b'), ('c', 'd'), ('e', 'f');
   325    VACUUM;
   326    PRAGMA integrity_check;
   327    SELECT name FROM sqlite_master WHERE tbl_name = 't48';
   328  } {
   329    ok  t48   sqlite_autoindex_t48_2
   330  }
   331  
   332  # 2015-05-28: CHECK constraints can refer to the rowid in a
   333  # rowid table, but not in a WITHOUT ROWID table.
   334  #
   335  do_execsql_test 7.1 {
   336    CREATE TABLE t70a(
   337       a INT CHECK( rowid!=33 ),
   338       b TEXT PRIMARY KEY
   339    );
   340    INSERT INTO t70a(a,b) VALUES(99,'hello');
   341  } {}
   342  do_catchsql_test 7.2 {
   343    INSERT INTO t70a(rowid,a,b) VALUES(33,99,'xyzzy');
   344  } {1 {CHECK constraint failed: rowid!=33}}
   345  do_catchsql_test 7.3 {
   346    CREATE TABLE t70b(
   347       a INT CHECK( rowid!=33 ),
   348       b TEXT PRIMARY KEY
   349    ) WITHOUT ROWID;
   350  } {1 {no such column: rowid}}
   351  
   352  # 2017-07-30: OSSFuzz discovered that an extra entry was being
   353  # added in the sqlite_master table for an "INTEGER PRIMARY KEY UNIQUE"
   354  # WITHOUT ROWID table.  Make sure this has now been fixed.
   355  #
   356  db close
   357  sqlite3 db :memory:
   358  do_execsql_test 8.1 {
   359    CREATE TABLE t1(x INTEGER PRIMARY KEY UNIQUE, b) WITHOUT ROWID;
   360    CREATE INDEX t1x ON t1(x);
   361    INSERT INTO t1(x,b) VALUES('funny','buffalo');
   362    SELECT type, name, '|' FROM sqlite_master;
   363  } {table t1 | index t1x |}
   364  
   365  # 2018-04-05: OSSFuzz found that the following was accessing an 
   366  # unintialized memory cell. Which was not actually causing a 
   367  # malfunction, but does cause an assert() to fail.
   368  #
   369  do_execsql_test 9.0 {
   370    CREATE TABLE t2(b, c, PRIMARY KEY(b,c)) WITHOUT ROWID;
   371    CREATE UNIQUE INDEX t2b ON t2(b);
   372    UPDATE t2 SET b=1 WHERE b='';
   373  }
   374  
   375  do_execsql_test 10.1 {
   376    DELETE FROM t2 WHERE b=1
   377  }
   378  
   379  #-------------------------------------------------------------------------
   380  # UNIQUE constraint violation in an UPDATE with a multi-column PK.
   381  #
   382  reset_db
   383  do_execsql_test 10.0 {
   384    CREATE TABLE t1(a, b, c UNIQUE, PRIMARY KEY(a, b)) WITHOUT ROWID;
   385    INSERT INTO t1 VALUES('a', 'a', 1);
   386    INSERT INTO t1 VALUES('a', 'b', 2);
   387    INSERT INTO t1 VALUES('b', 'a', 3);
   388    INSERT INTO t1 VALUES('b', 'b', 4);
   389  }
   390  
   391  do_catchsql_test 10.1 {
   392    UPDATE t1 SET c=1 WHERE (a, b) = ('a', 'a');
   393  } {0 {}}
   394  do_catchsql_test 10.2 {
   395    UPDATE t1 SET c=1 WHERE (a, b) = ('a', 'b');
   396  } {1 {UNIQUE constraint failed: t1.c}}
   397  do_catchsql_test 10.3 {
   398    UPDATE t1 SET c=1 WHERE (a, b) = ('b', 'a');
   399  } {1 {UNIQUE constraint failed: t1.c}}
   400  do_catchsql_test 10.4 {
   401    UPDATE t1 SET c=1 WHERE (a, b) = ('b', 'b');
   402  } {1 {UNIQUE constraint failed: t1.c}}
   403  do_catchsql_test 10.5 {
   404    UPDATE t1 SET c=1 WHERE (a, b) = ('c', 'c');
   405  } {0 {}}
   406  
   407  do_execsql_test 10.6 {
   408    CREATE TRIGGER t1_tr BEFORE UPDATE ON t1 BEGIN
   409      DELETE FROM t1 WHERE a = new.a;
   410    END;
   411    UPDATE t1 SET c = c+1 WHERE a = 'a';
   412    SELECT * FROM t1;
   413  } {b a 3  b b 4}
   414  
   415  # 2019-04-29 ticket https://www.sqlite.org/src/info/3182d3879020ef3
   416  do_execsql_test 11.1 {
   417    CREATE TABLE t11(a TEXT PRIMARY KEY, b INT) WITHOUT ROWID;
   418    CREATE INDEX t11a ON t11(a COLLATE NOCASE);
   419    INSERT INTO t11(a,b) VALUES ('A',1),('a',2);
   420    PRAGMA integrity_check;
   421    SELECT a FROM t11 ORDER BY a COLLATE binary;
   422  } {ok A a}
   423  
   424  # 2019-05-13 ticket https://www.sqlite.org/src/info/bba7b69f9849b5b
   425  do_execsql_test 12.1 {
   426    DROP TABLE IF EXISTS t0;
   427    CREATE TABLE t0 (c0 INTEGER PRIMARY KEY DESC, c1 UNIQUE DEFAULT NULL) WITHOUT ROWID;
   428    INSERT INTO t0(c0) VALUES (1), (2), (3), (4), (5);
   429    REINDEX;
   430    PRAGMA integrity_check;
   431  } {ok}
   432  
   433  # 2019-11-07 ticket https://www.sqlite.org/src/info/302027baf1374498
   434  # The xferCompatibleIndex() function confuses a PRIMARY KEY index
   435  # with a UNIQUE index.
   436  #
   437  do_execsql_test 13.10 {
   438    DROP TABLE IF EXISTS t0;
   439    DROP TABLE IF EXISTS t1;
   440    CREATE TABLE t0(
   441      c0,
   442      c1 UNIQUE,
   443      PRIMARY KEY(c1, c1)
   444    ) WITHOUT ROWID;
   445    INSERT INTO t0(c0,c1) VALUES('abc','xyz');
   446    CREATE TABLE t1(
   447      c0,
   448      c1 UNIQUE,
   449      PRIMARY KEY(c1, c1)
   450    ) WITHOUT ROWID;
   451    INSERT INTO t1 SELECT * FROM t0;
   452    PRAGMA integrity_check;
   453    SELECT * FROM t0, t1;
   454  } {ok abc xyz abc xyz}
   455  
   456  # 2021-05-13 https://sqlite.org/forum/forumpost/6c8960f545
   457  reset_db
   458  do_execsql_test 14.1 {
   459    CREATE TABLE t1(a INT PRIMARY KEY) WITHOUT ROWID;
   460    INSERT INTO t1(a) VALUES(10);
   461    ALTER TABLE t1 ADD COLUMN b INT;
   462    SELECT * FROM t1 WHERE a=20 OR (a=10 AND b=10);
   463  } {}
   464  do_execsql_test 14.2 {
   465    CREATE TABLE dual AS SELECT 'X' AS dummy;
   466    EXPLAIN QUERY PLAN SELECT * FROM dual, t1 WHERE a=10 AND b=10;
   467  } {~/b=/}
   468    
   469  finish_test