From 1e6242c1b986424246777ad93d7012ceb4d3450b Mon Sep 17 00:00:00 2001 From: morikuni Date: Thu, 6 Feb 2025 09:30:25 +0900 Subject: [PATCH 1/3] Extract dependency on table or view from view --- definition.go | 32 +++++++++++++++++++++++++++++--- spannerdiff_test.go | 10 ++++++++++ util.go | 16 ++++++++++++++++ 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/definition.go b/definition.go index 7e3a681..c1fcf01 100755 --- a/definition.go +++ b/definition.go @@ -863,11 +863,37 @@ func (v *view) alter(tgt definition, m *migration) { } func (v *view) dependsOn() []identifier { - // TODO: process query to find dependencies - return nil + var ids []identifier + paths, idents := tablesOrViewsInQueryExpr(v.node.Query) + // Can't distinguish between tables and views, so add both. + for _, ident := range idents { + ids = append(ids, + newTableIDFromIdent(ident), + newViewIDFromIdent(ident), + ) + } + for _, path := range paths { + ids = append(ids, + newTableIDFromPath(path), + newViewIDFromPath(path), + ) + } + // TODO: Add dependencies on columns. + // But it's difficult to extract column names from the query! + return ids } -func (v *view) onDependencyChange(me, dependency migrationState, m *migration) {} +func (v *view) onDependencyChange(me, dependency migrationState, m *migration) { + switch dep := dependency.definition().(type) { + case *column, *table, *view: + switch dependency.kind { + case migrationKindDropAndAdd: + m.updateState(me.updateKind(migrationKindDropAndAdd)) + } + default: + panic(fmt.Sprintf("unexpected dependOn type on view: %T", dep)) + } +} type changeStream struct { node *ast.CreateChangeStream diff --git a/spannerdiff_test.go b/spannerdiff_test.go index a12c227..3b053b7 100644 --- a/spannerdiff_test.go +++ b/spannerdiff_test.go @@ -772,6 +772,16 @@ func TestDiff(t *testing.T) { ALTER DATABASE D1 SET OPTIONS (version_retention_period = '2d');`, false, }, + "issue #35": { + ``, + ` + CREATE OR REPLACE VIEW V2 SQL SECURITY INVOKER AS SELECT * FROM T1; + CREATE OR REPLACE VIEW V1 SQL SECURITY INVOKER AS SELECT * FROM V2;`, + ` + CREATE OR REPLACE VIEW V2 SQL SECURITY INVOKER AS SELECT * FROM T1; + CREATE OR REPLACE VIEW V1 SQL SECURITY INVOKER AS SELECT * FROM V2;`, + false, + }, } { t.Run(name, func(t *testing.T) { var buf bytes.Buffer diff --git a/util.go b/util.go index 398697f..77cca59 100644 --- a/util.go +++ b/util.go @@ -156,3 +156,19 @@ func uniqueIdent(is []*ast.Ident) []*ast.Ident { return i.Name }) } + +func tablesOrViewsInQueryExpr(expr ast.QueryExpr) ([]*ast.Path, []*ast.Ident) { + var idents []*ast.Ident + var paths []*ast.Path + + ast.Inspect(expr, func(n ast.Node) bool { + switch t := n.(type) { + case *ast.TableName: + idents = append(idents, t.Table) + case *ast.PathTableExpr: + paths = append(paths, t.Path) + } + return true + }) + return paths, idents +} From 8f0f5b43645dfb7bc99dfd9b3377ad88ab10e869 Mon Sep 17 00:00:00 2001 From: morikuni Date: Thu, 6 Feb 2025 09:45:37 +0900 Subject: [PATCH 2/3] Add test case for drop and create view --- spannerdiff_test.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/spannerdiff_test.go b/spannerdiff_test.go index 3b053b7..7837149 100644 --- a/spannerdiff_test.go +++ b/spannerdiff_test.go @@ -530,6 +530,26 @@ func TestDiff(t *testing.T) { CREATE OR REPLACE VIEW V1 SQL SECURITY DEFINER AS SELECT * FROM T1 WHERE T1_I1 > 0;`, false, }, + "drop and create view": { + ` + CREATE TABLE T1 ( + T1_I1 INT64 NOT NULL, + ) PRIMARY KEY(T1_I1); + CREATE VIEW V1 SQL SECURITY DEFINER AS SELECT * FROM T1;`, + ` + CREATE TABLE T1 ( + T1_S1 STRING(MAX) NOT NULL, + ) PRIMARY KEY(T1_S1); + CREATE VIEW V1 SQL SECURITY DEFINER AS SELECT * FROM T1;`, + ` + DROP VIEW V1; + DROP TABLE T1; + CREATE TABLE T1 ( + T1_S1 STRING(MAX) NOT NULL, + ) PRIMARY KEY(T1_S1); + CREATE VIEW V1 SQL SECURITY DEFINER AS SELECT * FROM T1;`, + false, + }, "add change stream": { ``, ` From 9f64b857a02e43b016fa915a9590e0450379deb3 Mon Sep 17 00:00:00 2001 From: morikuni Date: Thu, 6 Feb 2025 09:48:27 +0900 Subject: [PATCH 3/3] Add known issue section --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 255a4c3..66166bb 100644 --- a/README.md +++ b/README.md @@ -76,3 +76,7 @@ CREATE INDEX Test_Name_CreatedAt ON Test(Name, CreatedAt DESC); $ gcloud spanner databases ddl update test --ddl-file=tmp.sql Schema updating...done. ``` + +## Known Issues & Limitations + +- View DDL generation may be incorrect or out of order due to unresolved column names in the view query.