#!/usr/bin/env tclsh set testdir [file dirname $argv0] source $testdir/tester.tcl # Test: Create an AUTOINCREMENT table and verify sqlite_sequence is also created. do_execsql_test_on_specific_db {:memory:} autoinc-create-sequence-table { CREATE TABLE t1(x INTEGER PRIMARY KEY AUTOINCREMENT, y); SELECT name FROM sqlite_master WHERE type='table' ORDER BY name; } {sqlite_sequence t1} # Test: The sqlite_sequence table is initially empty after table creation. do_execsql_test_on_specific_db {:memory:} autoinc-sequence-table-is-initially-empty { CREATE TABLE t1(x INTEGER PRIMARY KEY AUTOINCREMENT, y); SELECT * FROM sqlite_sequence; } {} # Test: You cannot drop the sqlite_sequence table. do_execsql_test_in_memory_any_error autoinc-fail-drop-sequence-table { CREATE TABLE t1(x INTEGER PRIMARY KEY AUTOINCREMENT, y); DROP TABLE sqlite_sequence; } # Test: You cannot create an index on the sqlite_sequence table. do_execsql_test_in_memory_any_error autoinc-fail-index-sequence-table { CREATE TABLE t1(x INTEGER PRIMARY KEY AUTOINCREMENT, y); CREATE INDEX seqidx ON sqlite_sequence(name); } # Test: First insert populates sqlite_sequence. do_execsql_test_on_specific_db {:memory:} autoinc-first-insert-populates-sequence { CREATE TABLE t1(x INTEGER PRIMARY KEY AUTOINCREMENT, y); INSERT INTO t1 VALUES(12,34); SELECT * FROM sqlite_sequence; } {t1|12} # Test: Inserting a value larger than the current sequence updates the sequence. do_execsql_test_on_specific_db {:memory:} autoinc-larger-insert-updates-sequence { CREATE TABLE t1(x INTEGER PRIMARY KEY AUTOINCREMENT, y); INSERT INTO t1 VALUES(12,34); INSERT INTO t1 VALUES(123,456); SELECT * FROM sqlite_sequence; } {t1|123} # Test: Inserting NULL generates a key one greater than the max. do_execsql_test_on_specific_db {:memory:} autoinc-null-insert-increments-sequence { CREATE TABLE t1(x INTEGER PRIMARY KEY AUTOINCREMENT, y); INSERT INTO t1 VALUES(123,456); INSERT INTO t1 VALUES(NULL,567); SELECT * FROM sqlite_sequence; } {t1|124} # Test: Sequence value is not decreased after a DELETE. do_execsql_test_on_specific_db {:memory:} autoinc-sequence-not-decremented-by-delete { CREATE TABLE t1(x INTEGER PRIMARY KEY AUTOINCREMENT, y); INSERT INTO t1 VALUES(123,456); INSERT INTO t1 VALUES(NULL,567); DELETE FROM t1 WHERE y=567; SELECT * FROM sqlite_sequence; } {t1|124} # Test: A NULL insert after a DELETE continues from the previous high-water mark. do_execsql_test_on_specific_db {:memory:} autoinc-insert-after-delete-uses-high-water-mark { CREATE TABLE t1(x INTEGER PRIMARY KEY AUTOINCREMENT, y); INSERT INTO t1 VALUES(125, 1); DELETE FROM t1; INSERT INTO t1 VALUES(NULL, 2); SELECT x FROM t1; } {126} # Test: Clearing a table does not reset the sequence. do_execsql_test_on_specific_db {:memory:} autoinc-delete-all-does-not-reset-sequence { CREATE TABLE t1(x INTEGER PRIMARY KEY AUTOINCREMENT, y); INSERT INTO t1 VALUES(125, 456); DELETE FROM t1; SELECT * FROM sqlite_sequence; } {t1|125} # Test: Manually updating the sequence table affects the next generated key. do_execsql_test_on_specific_db {:memory:} autoinc-manual-update-to-sequence-table { CREATE TABLE t1(x INTEGER PRIMARY KEY AUTOINCREMENT, y); INSERT INTO t1 VALUES(1, 1); UPDATE sqlite_sequence SET seq=1234 WHERE name='t1'; INSERT INTO t1 VALUES(NULL, 2); SELECT * FROM t1 ORDER BY x; } {1|1 1235|2} # Test: AUTOINCREMENT works for multiple tables independently. do_execsql_test_on_specific_db {:memory:} autoinc-multiple-tables { CREATE TABLE t1(x INTEGER PRIMARY KEY AUTOINCREMENT, y); CREATE TABLE t2(d, e INTEGER PRIMARY KEY AUTOINCREMENT, f); CREATE TABLE t3(g INTEGER PRIMARY KEY AUTOINCREMENT, h); INSERT INTO t1(y) VALUES('a'); INSERT INTO t2(d) VALUES('b'); INSERT INTO t2(d) VALUES('c'); INSERT INTO t3(h) VALUES('d'); INSERT INTO t1(x) VALUES(100); SELECT name, seq FROM sqlite_sequence ORDER BY name; } {t1|100 t2|2 t3|1} # Test: Dropping an AUTOINCREMENT table removes its entry from sqlite_sequence. do_execsql_test_on_specific_db {:memory:} autoinc-drop-table-removes-sequence-entry { CREATE TABLE t1(x INTEGER PRIMARY KEY AUTOINCREMENT, y); CREATE TABLE t2(d, e INTEGER PRIMARY KEY AUTOINCREMENT, f); INSERT INTO t1(y) VALUES('a'); INSERT INTO t2(d) VALUES('b'); DROP TABLE t1; SELECT name FROM sqlite_sequence; } {t2} # Test: When the last AUTOINCREMENT table is dropped, the sequence table remains but is empty. do_execsql_test_on_specific_db {:memory:} autoinc-drop-last-table-empties-sequence { CREATE TABLE t1(x INTEGER PRIMARY KEY AUTOINCREMENT, y); DROP TABLE t1; SELECT * FROM sqlite_sequence; } {} # Test: AUTOINCREMENT fails if the maximum rowid is reached. (Assumes 64-bit rowid) do_execsql_test_in_memory_any_error autoinc-fail-on-max-rowid { CREATE TABLE t6(v INTEGER PRIMARY KEY AUTOINCREMENT, w); INSERT INTO t6 VALUES(9223372036854775807, 1); INSERT INTO t6 VALUES(NULL, 2); } # Test: AUTOINCREMENT keyword is allowed in a separate PRIMARY KEY clause. do_execsql_test_on_specific_db {:memory:} autoinc-keyword-in-pk-clause { CREATE TABLE t7(x INTEGER, y REAL, PRIMARY KEY(x AUTOINCREMENT)); INSERT INTO t7(y) VALUES(123); INSERT INTO t7(y) VALUES(234); DELETE FROM t7; INSERT INTO t7(y) VALUES(345); SELECT * FROM t7; } {3|345.0} # Test: AUTOINCREMENT fails if the primary key is not an INTEGER. do_execsql_test_in_memory_any_error autoinc-fail-on-non-integer-pk { CREATE TABLE t8(x TEXT PRIMARY KEY AUTOINCREMENT); } # Test: An empty INSERT...SELECT does not damage the sequence table. (Ticket #3148) do_execsql_test_on_specific_db {:memory:} autoinc-empty-insert-select-is-safe { CREATE TABLE t2(x INTEGER PRIMARY KEY AUTOINCREMENT, y); INSERT INTO t2 VALUES(NULL, 1); CREATE TABLE t3(a INTEGER PRIMARY KEY AUTOINCREMENT, b); INSERT INTO t3 SELECT * FROM t2 WHERE y > 1; SELECT * FROM sqlite_sequence WHERE name='t3'; } {t3|0} # Test: AUTOINCREMENT with the xfer optimization. (Ticket 7b3328086a5c1) do_execsql_test_on_specific_db {:memory:} autoinc-with-xfer-optimization { CREATE TABLE t10a(a INTEGER PRIMARY KEY AUTOINCREMENT, b UNIQUE); INSERT INTO t10a VALUES(888,9999); CREATE TABLE t10b(x INTEGER PRIMARY KEY AUTOINCREMENT, y UNIQUE); INSERT INTO t10b SELECT * FROM t10a; SELECT * FROM sqlite_sequence ORDER BY name; } {t10a|888 t10b|888} # Test: AUTOINCREMENT works correctly with UPSERT. do_execsql_test_on_specific_db {:memory:} autoinc-with-upsert { CREATE TABLE t11(a INTEGER PRIMARY KEY AUTOINCREMENT, b UNIQUE); INSERT INTO t11(a,b) VALUES(2,3),(5,6),(4,3),(1,2) ON CONFLICT(b) DO UPDATE SET a=a+1000; SELECT seq FROM sqlite_sequence WHERE name='t11'; } {5} # refer https://github.com/tursodatabase/turso/pull/2983#issuecomment-3322404270 was discovered while adding autoincr to fuzz tests do_execsql_test_on_specific_db {:memory:} autoinc-conflict-on-nothing { CREATE TABLE t (id INTEGER PRIMARY KEY AUTOINCREMENT, k TEXT); CREATE UNIQUE INDEX idx_k_partial ON t(k) WHERE id > 1; INSERT INTO t (k) VALUES ('a'); INSERT INTO t (k) VALUES ('a'); INSERT INTO t (k) VALUES ('a') ON CONFLICT DO NOTHING; INSERT INTO t (k) VALUES ('b'); SELECT * FROM t ORDER BY id; } {1|a 2|a 4|b} # https://github.com/tursodatabase/turso/issues/3664 do_execsql_test_on_specific_db {:memory:} autoinc-skips-manually-updated-pk { CREATE TABLE t(a INTEGER PRIMARY KEY AUTOINCREMENT); INSERT INTO t DEFAULT VALUES; select * from sqlite_sequence; UPDATE t SET a = a + 1; SELECT * FROM sqlite_sequence; INSERT INTO t DEFAULT VALUES; SELECT * FROM sqlite_sequence; } {t|1 t|1 t|3}