limbo/testing/update.test
AdrianAcala 7ca902979d Fix: Correctly update indexes when INTEGER PRIMARY KEY (rowid alias) changes (Issue #1897)
When an `UPDATE` statement modifies a table's `INTEGER PRIMARY KEY` (which acts as a `rowid` alias) alongside other indexed columns, the index entries were incorrectly retaining the old `rowid`. This led to stale index references, causing subsequent queries to return incorrect results.

This change ensures that when the `rowid` alias is part of the `SET` clause in an `UPDATE` statement, the new `rowid` value is used for generating and updating index records. This guarantees that all index entries correctly point to the updated row, resolving the data inconsistency.
2025-07-01 16:03:27 +00:00

272 lines
No EOL
9.4 KiB
Tcl
Executable file

#!/usr/bin/env tclsh
set testdir [file dirname $argv0]
source $testdir/tester.tcl
do_execsql_test_on_specific_db {:memory:} basic-update {
create table temp (t1 integer);
insert into temp values (1);
update temp set t1 = 2;
select * from temp;
} {2}
do_execsql_test_on_specific_db {:memory:} update-mul {
create table temp (t1 integer);
insert into temp values (1),(2.0),('3'),('4.0');
update temp set t1 = 2;
select * from temp;
} {2
2
2
2}
do_execsql_test_on_specific_db {:memory:} update-where {
create table temp (a,b,c);
insert into temp values (1,2,33);
insert into temp values (1,22,33);
insert into temp values (1,22,33);
update temp set a = 6 where b = 2;
select * from temp;
} {6|2|33
1|22|33
1|22|33}
do_execsql_test_on_specific_db {:memory:} update-where-2 {
create table temp (a,b,c);
insert into temp values (1,22,33);
insert into temp values (1,22,33);
insert into temp values (1,22,33);
insert into temp values (6,22,33);
insert into temp values (1,22,33);
insert into temp values (1,22,33);
update temp set b = 100000 where a = 6;
select b from temp where a = 6;
} {100000}
do_execsql_test_on_specific_db {:memory:} update-all-many {
create table temp (a,b,c);
insert into temp values (1,22,33),(1,22,33),(1,22,33),(1,22,33),(1,22,33),(1,22,33),(1,22,33),(1,22,33);
update temp set a = 1234234234234234;
select COUNT(*) from temp where a = 1234234234234234;
} {8}
do_execsql_test_on_specific_db {:memory:} update-large-small {
create table temp (a,b,c);
insert into temp values (randomblob(1024), 1, 2);
update temp set a = 'a';
select * from temp;
} {a|1|2}
do_execsql_test_on_specific_db {:memory:} update-null {
create table temp (a,b,c);
insert into temp values (NULL, 1, 2);
insert into temp values (3, 4, 5);
update temp set a = 10 where a IS NULL;
select * from temp;
} {10|1|2
3|4|5}
do_execsql_test_on_specific_db {:memory:} update-not-null-1 {
create table temp (a,b not null,c);
insert into temp values (1, 2, 3);
update temp set b = 999;
select * from temp;
} {1|999|3}
do_execsql_test_in_memory_any_error update-not-null-2 {
create table temp (a,b not null,c);
insert into temp values (1, 2, 3);
update temp set b = NULL;
}
do_execsql_test_on_specific_db {:memory:} update-not-null-3 {
create table temp (a not null, b not null, c not null);
update temp set a = null, b = null, c = null;
select * from temp;
} {}
do_execsql_test_on_specific_db {:memory:} update-mixed-types {
create table temp (a);
insert into temp values (1);
insert into temp values ('2');
insert into temp values (3.0);
insert into temp values (X'01');
update temp set a = 'updated';
select * from temp;
} {updated
updated
updated
updated}
do_execsql_test_on_specific_db {:memory:} update-with-expression {
create table temp (a, b);
insert into temp values (1, 10);
insert into temp values (2, 20);
insert into temp values (3, 30);
update temp set a = b * 3 / 2;
select * from temp;
} {15|10
30|20
45|30}
do_execsql_test_on_specific_db {:memory:} update-self-reference {
create table temp (a, b);
insert into temp values (1, 10);
insert into temp values (2, 20);
update temp set a = b where a = 1;
select * from temp;
} {10|10
2|20}
do_execsql_test_on_specific_db {:memory:} update-self-ref-all {
create table temp (a, b, c);
insert into temp values (1, 2, 3);
insert into temp values (4, 5, 6);
update temp set a = b;
select * from temp;
} {2|2|3
5|5|6}
do_execsql_test_on_specific_db {:memory:} update-large-text {
create table temp (a);
insert into temp values ('short');
update temp set a = 'this is a very large text field that exceeds the default cell size and should trigger overflow handling in the btree implementation';
select * from temp;
} {{this is a very large text field that exceeds the default cell size and should trigger overflow handling in the btree implementation}}
do_execsql_test_on_specific_db {:memory:} update-with-null-condition {
create table temp (a, b);
insert into temp values (NULL, 1);
insert into temp values (2, NULL);
insert into temp values (3, 4);
update temp set a = 99 where b IS NULL;
select * from temp;
} {|1
99|
3|4}
do_execsql_test_on_specific_db {:memory:} update-to-null {
create table temp (a, b);
insert into temp values (1, 10);
insert into temp values (2, 20);
update temp set a = NULL where b = 10;
select * from temp;
} {|10
2|20}
do_execsql_test_on_specific_db {:memory:} update-with-randomblob {
create table temp (a, b);
insert into temp values (randomblob(100), 1);
update temp set a = randomblob(200);
select length(a) from temp;
} {200}
do_execsql_test_on_specific_db {:memory:} update-multiple-columns {
create table temp (a, b, c);
insert into temp values (1, 2, 3);
insert into temp values (4, 5, 6);
update temp set a = 10, b = 20, c = 30;
select * from temp;
} {10|20|30
10|20|30}
do_execsql_test_on_specific_db {:memory:} update-true-expr {
create table temp (a, b, c);
insert into temp values (1, 2, 3);
insert into temp values (4, 5, 6);
update temp set a = 10, b = 20, c = 30 where 1;
select * from temp;
} {10|20|30
10|20|30}
# https://github.com/tursodatabase/turso/issues/1625
do_execsql_test_on_specific_db {:memory:} update_cache_full_regression_test_#1625 {
CREATE TABLE t(x);
INSERT INTO t VALUES (randomblob(4096));
UPDATE t SET x = randomblob(4096) WHERE rowid = 1;
SELECT count(*) FROM t;
} {1}
if {[info exists ::env(SQLITE_EXEC)] && ($::env(SQLITE_EXEC) eq "scripts/limbo-sqlite3-index-experimental" || $::env(SQLITE_EXEC) eq "sqlite3")} {
do_execsql_test_on_specific_db {:memory:} update_index_regression_test {
CREATE TABLE t(x, y);
CREATE INDEX tx ON t (x);
CREATE UNIQUE INDEX tyu ON t (y);
INSERT INTO t VALUES (1, 1);
SELECT x FROM t; -- uses tx index
SELECT y FROM t; -- uses ty index
UPDATE t SET x=2, y=2;
SELECT x FROM t; -- uses tx index
SELECT y FROM t; -- uses ty index
} {1
1
2
2}
do_execsql_test_on_specific_db {:memory:} update_rowid_alias_index_regression_test {
CREATE TABLE t(a INTEGER PRIMARY KEY, b);
CREATE INDEX idx_b ON t (b);
INSERT INTO t VALUES (1, 'foo');
SELECT a FROM t WHERE b = 'foo';
UPDATE t SET a = 2, b = 'bar';
SELECT a FROM t WHERE b = 'bar';
} {1
2}
}
do_execsql_test_on_specific_db {:memory:} update_where_or_regression_test {
CREATE TABLE t (a INTEGER);
INSERT INTO t VALUES (1), ('hi');
UPDATE t SET a = X'6C6F76656C795F7265766F6C74' WHERE ~ 'gorgeous_thropy' OR NOT -3830873834.233324;
SELECT * from t;
} {lovely_revolt
lovely_revolt}
do_execsql_test_in_memory_any_error update_primary_key_constraint_error {
CREATE TABLE eye (study REAL, spring BLOB, save TEXT, thank REAL, election INTEGER, PRIMARY KEY (election));
INSERT INTO eye VALUES (183559032.521585, x'6625d092', 'Trial six should.', 2606132742.43174, 2817);
INSERT INTO eye VALUES (78255586.9204539, x'651061e8', 'World perhaps.', -5815764.49018679, 1917);
UPDATE eye SET election = 6150;
}
do_execsql_test_in_memory_any_error update_primary_key_constraint_error_2 {
CREATE TABLE eye (study REAL, spring BLOB, save TEXT, thank REAL, election INTEGER, PRIMARY KEY (election));
INSERT INTO eye VALUES (183559032.521585, x'6625d092', 'Trial six should.', 2606132742.43174, 2817);
INSERT INTO eye VALUES (78255586.9204539, x'651061e8', 'World perhaps.', -5815764.49018679, 1917);
INSERT INTO eye VALUES (53.3274327094467, x'f574c507', 'Senior wish degree.', -423.432750526747, 2650);
INSERT INTO eye VALUES (-908148213048.983, x'6d812051', 'Possible able.', 101.171781837336, 4100);
INSERT INTO eye VALUES (-572332773760.924, x'd7a4d9fb', 'Money catch expect.', -271065488.756746, 4667);
UPDATE eye SET election = 6150 WHERE election != 1917;
}
do_execsql_test_in_memory_any_error update_primary_key_constraint_error_3 {
CREATE TABLE eye (study REAL, spring BLOB, save TEXT, thank REAL, election INTEGER, PRIMARY KEY (election));
INSERT INTO eye VALUES (183559032.521585, x'6625d092', 'Trial six should.', 2606132742.43174, 2817);
INSERT INTO eye VALUES (78255586.9204539, x'651061e8', 'World perhaps.', -5815764.49018679, 1917);
INSERT INTO eye VALUES (53.3274327094467, x'f574c507', 'Senior wish degree.', -423.432750526747, 2650);
INSERT INTO eye VALUES (-908148213048.983, x'6d812051', 'Possible able.', 101.171781837336, 4100);
INSERT INTO eye VALUES (-572332773760.924, x'd7a4d9fb', 'Money catch expect.', -271065488.756746, 4667);
UPDATE eye SET election = 6150 WHERE election > 1000 AND study > 1;
}
do_execsql_test_in_memory_any_error update_primary_key_constraint_error_4 {
CREATE TABLE t(a PRIMARY KEY INTEGER, b UNIQUE);
INSERT INTO t(b) VALUES (100), (200), (300);
UPDATE t SET a = 1;
}
do_execsql_test_in_memory_any_error update_primary_key_unique_constraint_error {
CREATE TABLE t(a PRIMARY KEY INTEGER, b UNIQUE);
INSERT INTO t(b) VALUES (100), (200), (300);
UPDATE t SET b = 2;
}
do_execsql_test_on_specific_db {:memory:} update-single-rowid {
CREATE TABLE t(x INTEGER PRIMARY KEY);
INSERT INTO t VALUES (1);
UPDATE t SET x = 2 WHERE x = 1;
SELECT * FROM t;
} {2}