From c7e0544b4691022a18b40e11f167d9df8888f288 Mon Sep 17 00:00:00 2001 From: Nick Tobey Date: Thu, 16 Jan 2025 10:33:14 -0800 Subject: [PATCH] Don't force a table rewrite when appending extra values to the end of an enum. --- enginetest/queries/script_queries.go | 14 ++++++++++++++ sql/rowexec/ddl_iters.go | 2 +- sql/type.go | 3 +++ sql/types/enum.go | 13 +++++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/enginetest/queries/script_queries.go b/enginetest/queries/script_queries.go index 97ddefeb94..29a56d8499 100644 --- a/enginetest/queries/script_queries.go +++ b/enginetest/queries/script_queries.go @@ -7620,6 +7620,20 @@ where {3, "c", float64(4)}, }, }, + { + Query: "alter table t modify column e enum('asdf', 'a', 'b', 'c', 'd');", + Expected: []sql.Row{ + {types.NewOkResult(0)}, + }, + }, + { + Query: "select i, e, e + 0 from t;", + Expected: []sql.Row{ + {1, "a", float64(2)}, + {2, "b", float64(3)}, + {3, "c", float64(4)}, + }, + }, { Query: "alter table t modify column e enum('abc');", ExpectedErr: types.ErrConvertingToEnum, diff --git a/sql/rowexec/ddl_iters.go b/sql/rowexec/ddl_iters.go index dc21ab3518..c39e55dc8f 100644 --- a/sql/rowexec/ddl_iters.go +++ b/sql/rowexec/ddl_iters.go @@ -525,7 +525,7 @@ func (i *modifyColumnIter) rewriteTable(ctx *sql.Context, rwt sql.RewritableTabl oldEnum, isOldEnum := oldCol.Type.(sql.EnumType) newEnum, isNewEnum := newCol.Type.(sql.EnumType) - if isOldEnum && isNewEnum && !oldEnum.Equals(newEnum) { + if isOldEnum && isNewEnum && !oldEnum.IsSubsetOf(newEnum) { rewriteRequired = true } diff --git a/sql/type.go b/sql/type.go index c5ab25e50e..07a02f5fba 100644 --- a/sql/type.go +++ b/sql/type.go @@ -186,6 +186,9 @@ type EnumType interface { Collation() CollationID // IndexOf returns the index of the given string. If the string was not found, then this returns -1. IndexOf(v string) int + // IsSubsetOf returns whether every element in this is also in |otherType|, with the same indexes. + // |otherType| may contain additional elements not in this. + IsSubsetOf(otherType EnumType) bool // NumberOfElements returns the number of enumerations. NumberOfElements() uint16 // Values returns the elements, in order, of every enumeration. diff --git a/sql/types/enum.go b/sql/types/enum.go index 62fdc07585..ebcc426982 100644 --- a/sql/types/enum.go +++ b/sql/types/enum.go @@ -335,6 +335,19 @@ func (t EnumType) IndexOf(v string) int { return -1 } +// IsSubsetOf implements the sql.EnumType interface. +func (t EnumType) IsSubsetOf(otherType sql.EnumType) bool { + if ot, ok := otherType.(EnumType); ok && t.collation.Equals(ot.collation) && len(t.idxToVal) <= len(ot.idxToVal) { + for i, val := range t.idxToVal { + if ot.idxToVal[i] != val { + return false + } + } + return true + } + return false +} + // NumberOfElements implements EnumType interface. func (t EnumType) NumberOfElements() uint16 { return uint16(len(t.idxToVal))