From 6def78365ddf3875e3b9b7ade4deed18ad248b36 Mon Sep 17 00:00:00 2001 From: Dirkjan Bussink Date: Wed, 5 Jun 2024 11:08:22 +0200 Subject: [PATCH] Handle single sharded keyspaces for analysis (#16068) Signed-off-by: Dirkjan Bussink --- go/vt/schemadiff/schema_diff_test.go | 12 +++++++++++- go/vt/vtgate/semantics/analyzer.go | 13 ++++++++----- go/vt/vtgate/semantics/check_invalid.go | 6 ++++-- go/vt/vtgate/semantics/semantic_state.go | 2 +- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/go/vt/schemadiff/schema_diff_test.go b/go/vt/schemadiff/schema_diff_test.go index 270449841d9..3dc1ab291fd 100644 --- a/go/vt/schemadiff/schema_diff_test.go +++ b/go/vt/schemadiff/schema_diff_test.go @@ -414,6 +414,16 @@ func TestSchemaDiff(t *testing.T) { entityOrder: []string{"v2"}, instantCapability: InstantDDLCapabilityIrrelevant, }, + { + name: "add view with over", + toQueries: append( + createQueries, + "create view v2 as SELECT *, ROW_NUMBER() OVER(PARTITION BY info) AS row_num1, ROW_NUMBER() OVER(PARTITION BY info ORDER BY id) AS row_num2 FROM t1;\n", + ), + expectDiffs: 1, + entityOrder: []string{"v2"}, + instantCapability: InstantDDLCapabilityIrrelevant, + }, { name: "add view, alter table", toQueries: []string{ @@ -1050,7 +1060,7 @@ func TestSchemaDiff(t *testing.T) { return } if tc.conflictingDiffs > 0 { - assert.Error(t, err) + require.Error(t, err) impossibleOrderErr, ok := err.(*ImpossibleApplyDiffOrderError) assert.True(t, ok) conflictingDiffsStatements := []string{} diff --git a/go/vt/vtgate/semantics/analyzer.go b/go/vt/vtgate/semantics/analyzer.go index b872a1dde04..c771e541923 100644 --- a/go/vt/vtgate/semantics/analyzer.go +++ b/go/vt/vtgate/semantics/analyzer.go @@ -46,6 +46,7 @@ type analyzer struct { projErr error unshardedErr error warning string + canShortcut bool singleUnshardedKeyspace bool fullAnalysis bool } @@ -135,7 +136,7 @@ func (a *analyzer) newSemTable( comments = commentedStmt.GetParsedComments() } - if a.singleUnshardedKeyspace { + if a.canShortcut { return &SemTable{ Tables: a.earlyTables.Tables, Comments: comments, @@ -386,16 +387,18 @@ func (a *analyzer) reAnalyze(statement sqlparser.SQLNode) error { // canShortCut checks if we are dealing with a single unsharded keyspace and no tables that have managed foreign keys // if so, we can stop the analyzer early func (a *analyzer) canShortCut(statement sqlparser.Statement) (canShortCut bool) { - if a.fullAnalysis { + ks, _ := singleUnshardedKeyspace(a.earlyTables.Tables) + a.singleUnshardedKeyspace = ks != nil + if !a.singleUnshardedKeyspace { return false } - ks, _ := singleUnshardedKeyspace(a.earlyTables.Tables) - if ks == nil { + + if a.fullAnalysis { return false } defer func() { - a.singleUnshardedKeyspace = canShortCut + a.canShortcut = canShortCut }() if !sqlparser.IsDMLStatement(statement) { diff --git a/go/vt/vtgate/semantics/check_invalid.go b/go/vt/vtgate/semantics/check_invalid.go index 2cf16aa0417..272bea9d9d0 100644 --- a/go/vt/vtgate/semantics/check_invalid.go +++ b/go/vt/vtgate/semantics/check_invalid.go @@ -49,11 +49,13 @@ func (a *analyzer) checkForInvalidConstructs(cursor *sqlparser.Cursor) error { return vterrors.VT12001("recursive common table expression") } case *sqlparser.Insert: - if node.Action == sqlparser.ReplaceAct { + if !a.singleUnshardedKeyspace && node.Action == sqlparser.ReplaceAct { return ShardedError{Inner: &UnsupportedConstruct{errString: "REPLACE INTO with sharded keyspace"}} } case *sqlparser.OverClause: - return ShardedError{Inner: &UnsupportedConstruct{errString: "OVER CLAUSE with sharded keyspace"}} + if !a.singleUnshardedKeyspace { + return ShardedError{Inner: &UnsupportedConstruct{errString: "OVER CLAUSE with sharded keyspace"}} + } } return nil diff --git a/go/vt/vtgate/semantics/semantic_state.go b/go/vt/vtgate/semantics/semantic_state.go index f6f62a3eba5..c81442a6c5b 100644 --- a/go/vt/vtgate/semantics/semantic_state.go +++ b/go/vt/vtgate/semantics/semantic_state.go @@ -821,7 +821,7 @@ func singleUnshardedKeyspace(tableInfos []TableInfo) (ks *vindexes.Keyspace, tab return ks, tables } -// SingleUnshardedKeyspace returns the single keyspace if all tables in the query are in the same keyspace +// SingleKeyspace returns the single keyspace if all tables in the query are in the same keyspace func (st *SemTable) SingleKeyspace() (ks *vindexes.Keyspace) { validKS := func(this *vindexes.Keyspace) bool { if this == nil {