From ff84d397a44128d8266ee1d463a6d78019947d8c Mon Sep 17 00:00:00 2001 From: Max Hoffman Date: Fri, 8 Mar 2024 12:41:40 -0800 Subject: [PATCH] [memory] force mutating the accEditor AutoInc because tableEditor is unreliable --- enginetest/queries/script_queries.go | 34 ++++++++++++++++++++++++++++ memory/table.go | 1 + memory/table_editor.go | 24 +++++++++++++++----- 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/enginetest/queries/script_queries.go b/enginetest/queries/script_queries.go index 32d5021912..20c487c9a1 100644 --- a/enginetest/queries/script_queries.go +++ b/enginetest/queries/script_queries.go @@ -121,6 +121,40 @@ var ScriptTests = []ScriptTest{ }, }, }, + { + Name: "GMS issue 2369", + SetUpScript: []string{ + `CREATE TABLE table1 ( + id int NOT NULL AUTO_INCREMENT, + name text, + parentId int DEFAULT NULL, + PRIMARY KEY (id), + CONSTRAINT myConstraint FOREIGN KEY (parentId) REFERENCES table1 (id) ON DELETE CASCADE +)`, + }, + Assertions: []ScriptTestAssertion{ + { + Query: "INSERT INTO table1 (name, parentId) VALUES ('tbl1 row 1', NULL);", + Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 1}}}, + }, + { + Query: "INSERT INTO table1 (name, parentId) VALUES ('tbl1 row 2', 1);", + Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 2}}}, + }, + { + Query: "INSERT INTO table1 (name, parentId) VALUES ('tbl1 row 3', NULL);", + Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 3}}}, + }, + { + Query: "select * from table1", + Expected: []sql.Row{ + {1, "tbl1 row 1", nil}, + {2, "tbl1 row 2", 1}, + {3, "tbl1 row 3", nil}, + }, + }, + }, + }, { Name: "GMS issue 2349", SetUpScript: []string{ diff --git a/memory/table.go b/memory/table.go index 5d4686d628..4034dc2fb4 100644 --- a/memory/table.go +++ b/memory/table.go @@ -971,6 +971,7 @@ func (t *Table) tableEditorForRewrite(ctx *sql.Context, oldSchema, newSchema sql tableData := tableUnderEdit.data.truncate(normalizeSchemaForRewrite(newSchema)) tableUnderEdit.data = tableData + // TODO: |editedTableAnd| and |ea| should have the same tableData reference uniqIdxCols, prefixLengths := tableData.indexColsForTableEditor() var editor sql.TableEditor = &tableEditor{ editedTable: tableUnderEdit, diff --git a/memory/table_editor.go b/memory/table_editor.go index efa8018d53..81492b4fc3 100644 --- a/memory/table_editor.go +++ b/memory/table_editor.go @@ -178,10 +178,11 @@ func (t *tableEditor) Insert(ctx *sql.Context, row sql.Row) error { return err } - idx := t.editedTable.data.autoColIdx + // todo could peek into internals, not use editedTable t.ea.(*pkTableEditAccumulator).tableData + idx := t.ea.TableData().autoColIdx if idx >= 0 { - autoCol := t.editedTable.data.schema.Schema[idx] - cmp, err := autoCol.Type.Compare(row[idx], t.editedTable.data.autoIncVal) + autoCol := t.ea.TableData().schema.Schema[idx] + cmp, err := autoCol.Type.Compare(row[idx], t.ea.TableData().autoIncVal) if err != nil { return err } @@ -191,11 +192,11 @@ func (t *tableEditor) Insert(ctx *sql.Context, row sql.Row) error { if err != nil { return err } - t.editedTable.data.autoIncVal = v.(uint64) - t.editedTable.data.autoIncVal++ // Move onto next autoIncVal + t.ea.TableData().autoIncVal = v.(uint64) + t.ea.TableData().autoIncVal++ // Move onto next autoIncVal } else if cmp == 0 { // Provided value equal to autoIncVal - t.editedTable.data.autoIncVal++ // Move onto next autoIncVal + t.ea.TableData().autoIncVal++ // Move onto next autoIncVal } } @@ -372,6 +373,9 @@ type tableEditAccumulator interface { GetByCols(value sql.Row, cols []int, prefixLengths []uint16) (sql.Row, bool, error) // Clear wipes all of the stored inserts and deletes that may or may not have been applied. Clear() + // TableData exposes the session table data for this accumulator. Currently used for mutating + // autoincrement in a way that will track row changes. + TableData() *TableData } // newTableEditAccumulator returns a tableEditAccumulator based on the schema. @@ -400,6 +404,10 @@ type pkTableEditAccumulator struct { var _ tableEditAccumulator = (*pkTableEditAccumulator)(nil) +func (pke *pkTableEditAccumulator) TableData() *TableData { + return pke.tableData +} + // Insert implements the tableEditAccumulator interface. func (pke *pkTableEditAccumulator) Insert(value sql.Row) error { rowKey := pke.getRowKey(value) @@ -650,6 +658,10 @@ type keylessTableEditAccumulator struct { var _ tableEditAccumulator = (*keylessTableEditAccumulator)(nil) +func (k *keylessTableEditAccumulator) TableData() *TableData { + return k.tableData +} + // Insert implements the tableEditAccumulator interface. func (k *keylessTableEditAccumulator) Insert(value sql.Row) error { for i, row := range k.deletes {