Skip to content

Commit 6133f99

Browse files
committed
DELETE: Fix panic when using PRIMARY KEY
When an index lookup occurs as part of a DELETE, it was not stripping the qualified identifiers in the row necessary for storage to find the rows. This did not effect the equivilent UPDATE, but I have add an extra test for that anyway.
1 parent c1def77 commit 6133f99

File tree

4 files changed

+38
-1
lines changed

4 files changed

+38
-1
lines changed

tests/delete.sql

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,17 @@ DELETE FROM foo.bar;
3535
-- msg: CREATE SCHEMA 1
3636
-- msg: CREATE TABLE 1
3737
-- msg: DELETE 0
38+
39+
-- # https://github.com/elliotchance/vsql/issues/200
40+
CREATE TABLE PrimaryProduct (id INT NOT NULL, PRIMARY KEY(id));
41+
INSERT INTO PrimaryProduct (id) VALUES (1);
42+
INSERT INTO PrimaryProduct (id) VALUES (2);
43+
EXPLAIN DELETE FROM PrimaryProduct WHERE id = 1;
44+
DELETE FROM PrimaryProduct WHERE id = 1;
45+
SELECT * FROM PrimaryProduct;
46+
-- msg: CREATE TABLE 1
47+
-- msg: INSERT 1
48+
-- msg: INSERT 1
49+
-- EXPLAIN: PRIMARY KEY ":memory:".PUBLIC.PRIMARYPRODUCT (ID INTEGER NOT NULL) BETWEEN 1 AND 1
50+
-- msg: DELETE 1
51+
-- ID: 2

tests/update.sql

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,15 @@ SELECT * FROM foo;
108108
-- msg: INSERT 1
109109
-- error 22001: string data right truncation for CHARACTER VARYING(4)
110110
-- BAZ: abc
111+
112+
-- # https://github.com/elliotchance/vsql/issues/200
113+
CREATE TABLE PrimaryProduct (id INT NOT NULL, PRIMARY KEY(id));
114+
INSERT INTO PrimaryProduct (id) VALUES (1);
115+
EXPLAIN UPDATE PrimaryProduct SET id = 2 WHERE id = 1;
116+
UPDATE PrimaryProduct SET id = 2 WHERE id = 1;
117+
SELECT * FROM PrimaryProduct;
118+
-- msg: CREATE TABLE 1
119+
-- msg: INSERT 1
120+
-- EXPLAIN: PRIMARY KEY ":memory:".PUBLIC.PRIMARYPRODUCT (ID INTEGER NOT NULL) BETWEEN 1 AND 1
121+
-- msg: UPDATE 1
122+
-- ID: 2

vsql/std_14_9_delete_statement_searched.v

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ fn (stmt DeleteStatementSearched) execute(mut conn Connection, params map[string
3636
mut rows := plan.execute([]Row{})!
3737

3838
for mut row in rows {
39-
catalog.storage.delete_row(table_name.storage_id(), mut row)!
39+
// for_storage() here is important because it will strip the qualified
40+
// identifiers down to just their names used in storage.
41+
catalog.storage.delete_row(table_name.storage_id(), mut row.for_storage())!
4042
}
4143

4244
return new_result_msg('DELETE ${rows.len}', elapsed_parse, t.elapsed())

vsql/storage.v

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,15 @@ fn (mut f Storage) delete_row(table_name string, mut row Row) ! {
283283
}
284284

285285
page_number := f.btree.expire(row.object_key(f.tables[table_name])!, row.tid, f.transaction_id)!
286+
287+
// A negative page_number means the object didn't exist so there's nothing to
288+
// save. This should not be possible because the delete_row will only be
289+
// issued on a row that already exists, but I guess to be safe let's not let
290+
// it panic.
291+
if page_number < 0 {
292+
return error('DELETE: integrity issue, preventing panic')
293+
}
294+
286295
f.transaction_pages[page_number] = true
287296
}
288297

0 commit comments

Comments
 (0)