Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 1 addition & 35 deletions pkg/sql/plan/bind_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,34 +135,7 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext)
validIndexes, _ := getValidIndexes(tableDef)
tableDef.Indexes = validIndexes

var pkAndUkCols = make(map[string]bool)

if tableDef.Name == catalog.MO_PUBS || tableDef.Name == catalog.MO_SUBS {
for _, colName := range tableDef.Pkey.Names {
pkAndUkCols[colName] = true
}
}

for _, idxDef := range tableDef.Indexes {
if !idxDef.Unique {
continue
}

if tableDef.Name == catalog.MO_PUBS || tableDef.Name == catalog.MO_SUBS {
for _, colName := range idxDef.Parts {
pkAndUkCols[catalog.ResolveAlias(colName)] = true
}
}
}

for colName, updateExpr := range dmlCtx.updateCol2Expr[i] {
if pkAndUkCols[colName] {
return 0, newLegacyUpdatePlannerRouteError(
updateRouteReasonPubSubKey,
moerr.NewUnsupportedDML(builder.compCtx.GetContext(), "update pk/uk on pub/sub table"),
)
}

// Check: cannot update a generated column (unless SET gen_col = DEFAULT)
isGenCol := false
for _, colDef := range tableDef.Cols {
Expand All @@ -189,13 +162,6 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext)
for _, colDef := range tableDef.Cols {
if colDef.Name == colName {
if isEnumOrSetPlanType(&colDef.Typ) {
if colDef.Typ.AutoIncr {
return 0, newLegacyUpdatePlannerRouteError(
updateRouteReasonAutoIncrement,
moerr.NewUnsupportedDML(builder.compCtx.GetContext(), "auto_increment default value"),
)
}

updateExpr, err = wrapAstExprForMySQLSpecialType(builder.GetContext(), colDef.Typ, updateExpr)
if err != nil {
return 0, err
Expand Down Expand Up @@ -414,7 +380,7 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext)
if updateAutoIncrCols[i] &&
len(affectedUpdateChildFks(tableDef, dmlCtx.aliases[i], newColName2Idx)) > 0 {
return 0, newLegacyUpdatePlannerRouteError(
updateRouteReasonAutoIncrement,
updateRouteReasonAutoIncrementFK,
moerr.NewUnsupportedDML(
builder.compCtx.GetContext(),
"auto_increment foreign key update",
Expand Down
23 changes: 11 additions & 12 deletions pkg/sql/plan/update_planner_route.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,17 @@ const (
type updatePlannerRouteReason string

const (
updateRouteReasonNone updatePlannerRouteReason = "none"
updateRouteReasonMultiTarget updatePlannerRouteReason = "multi_target"
updateRouteReasonForeignKey updatePlannerRouteReason = "foreign_key"
updateRouteReasonIrregularIndex updatePlannerRouteReason = "irregular_index"
updateRouteReasonPubSubKey updatePlannerRouteReason = "pub_sub_key"
updateRouteReasonAutoIncrement updatePlannerRouteReason = "enum_set_auto_increment"
updateRouteReasonIceberg updatePlannerRouteReason = "iceberg"
updateRouteReasonExternalTable updatePlannerRouteReason = "external_table"
updateRouteReasonTableForm updatePlannerRouteReason = "unsupported_table_form"
updateRouteReasonEmptyTableName updatePlannerRouteReason = "empty_table_name"
updateRouteReasonBinderError updatePlannerRouteReason = "binder_error"
updateRouteReasonUnknown updatePlannerRouteReason = "unknown"
updateRouteReasonNone updatePlannerRouteReason = "none"
updateRouteReasonMultiTarget updatePlannerRouteReason = "multi_target"
updateRouteReasonForeignKey updatePlannerRouteReason = "foreign_key"
updateRouteReasonIrregularIndex updatePlannerRouteReason = "irregular_index"
updateRouteReasonAutoIncrementFK updatePlannerRouteReason = "auto_increment_foreign_key"
updateRouteReasonIceberg updatePlannerRouteReason = "iceberg"
updateRouteReasonExternalTable updatePlannerRouteReason = "external_table"
updateRouteReasonTableForm updatePlannerRouteReason = "unsupported_table_form"
updateRouteReasonEmptyTableName updatePlannerRouteReason = "empty_table_name"
updateRouteReasonBinderError updatePlannerRouteReason = "binder_error"
updateRouteReasonUnknown updatePlannerRouteReason = "unknown"
)

type updatePlannerRouteError struct {
Expand Down
53 changes: 47 additions & 6 deletions pkg/sql/plan/update_planner_route_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,13 +195,28 @@ func TestBindUpdateProducesTypedPlannerRoutes(t *testing.T) {
wantReason: updateRouteReasonNone,
},
{
name: "pub sub key",
name: "pub primary key",
sql: "UPDATE nation SET n_nationkey = 2",
prepare: func(mock *MockOptimizer) {
mock.ctxt.tables["nation"].Name = catalog.MO_PUBS
},
wantRoute: updatePlannerLegacy,
wantReason: updateRouteReasonPubSubKey,
wantRoute: updatePlannerModern,
wantReason: updateRouteReasonNone,
},
{
name: "sub unique key",
sql: "UPDATE nation SET n_name = 'x'",
prepare: func(mock *MockOptimizer) {
tableDef := mock.ctxt.tables["nation"]
tableDef.Name = catalog.MO_SUBS
tableDef.Indexes = []*planpb.IndexDef{{
IndexName: "uk_name",
Unique: true,
Parts: []string{"n_name"},
}}
},
wantRoute: updatePlannerModern,
wantReason: updateRouteReasonNone,
},
{
name: "set auto increment",
Expand All @@ -212,8 +227,8 @@ func TestBindUpdateProducesTypedPlannerRoutes(t *testing.T) {
col.Typ.Enumvalues = "one,two"
col.Typ.AutoIncr = true
},
wantRoute: updatePlannerLegacy,
wantReason: updateRouteReasonAutoIncrement,
wantRoute: updatePlannerModern,
wantReason: updateRouteReasonNone,
},
}

Expand Down Expand Up @@ -249,6 +264,32 @@ func TestBindUpdateProducesTypedPlannerRoutes(t *testing.T) {
}
}

func TestRemainingUpdateSpecialCasesUseModernPlan(t *testing.T) {
t.Run("pub primary key uses multi update", func(t *testing.T) {
mock := NewMockOptimizer(true)
mock.ctxt.tables["nation"].Name = catalog.MO_PUBS

logicPlan, err := runOneStmt(mock, t, "UPDATE nation SET n_nationkey = 2")
require.NoError(t, err)
require.Equal(t, 1, countUpdateFkPlanNodes(logicPlan.GetQuery(), planpb.Node_MULTI_UPDATE))
})

t.Run("set auto increment keeps type conversion and pre insert", func(t *testing.T) {
mock := NewMockOptimizer(true)
col := mock.ctxt.tables["nation"].Cols[0]
col.Typ.Id = int32(types.T_uint64)
col.Typ.Enumvalues = "one,two"
col.Typ.AutoIncr = true

logicPlan, err := runOneStmt(mock, t, "UPDATE nation SET n_nationkey = 'two'")
require.NoError(t, err)
query := logicPlan.GetQuery()
require.Equal(t, 1, countUpdateFkPlanNodes(query, planpb.Node_MULTI_UPDATE))
require.Equal(t, 1, countUpdateFkPlanNodes(query, planpb.Node_PRE_INSERT))
require.True(t, updateFkPlanContainsFunc(query, moSetCastValueToIndexFun))
})
}

func TestBindUpdateForeignKeyRoutingByAffectedColumns(t *testing.T) {
prepareEmpDept := func(mock *MockOptimizer) {
emp := mock.ctxt.tables["emp"]
Expand Down Expand Up @@ -376,7 +417,7 @@ func TestBindUpdateForeignKeyRoutingByAffectedColumns(t *testing.T) {
require.Error(t, err)
route, reason, _ := classifyUpdatePlannerError(err)
require.Equal(t, updatePlannerLegacy, route)
require.Equal(t, updateRouteReasonAutoIncrement, reason)
require.Equal(t, updateRouteReasonAutoIncrementFK, reason)
})

t.Run("disabled checks keep auto increment child key on modern route", func(t *testing.T) {
Expand Down
Loading
Loading