From fb38799c5a7ee204da10773d6358da38f8e369ef Mon Sep 17 00:00:00 2001 From: Jason Fulghum Date: Mon, 10 Mar 2025 15:47:38 -0700 Subject: [PATCH] Bug fixes for primary and foreign key naming --- .../convert_drop_primary_key_constraint.go | 54 ++++++++++ server/analyzer/generate_fk_name.go | 102 ++++++++++++++++++ server/analyzer/init.go | 41 +++---- server/ast/table_def.go | 29 +++++ server/tables/pgcatalog/pg_constraint.go | 4 +- testing/go/create_table_test.go | 28 +++++ testing/go/foreign_keys_test.go | 79 +++++++++++++- testing/go/functions_test.go | 9 +- testing/go/pgcatalog_test.go | 15 +-- .../node/workbenchTests/diffs.js | 8 +- .../node/workbenchTests/table.js | 2 +- 11 files changed, 328 insertions(+), 43 deletions(-) create mode 100644 server/analyzer/convert_drop_primary_key_constraint.go create mode 100644 server/analyzer/generate_fk_name.go diff --git a/server/analyzer/convert_drop_primary_key_constraint.go b/server/analyzer/convert_drop_primary_key_constraint.go new file mode 100644 index 0000000000..1ac8360aba --- /dev/null +++ b/server/analyzer/convert_drop_primary_key_constraint.go @@ -0,0 +1,54 @@ +// Copyright 2025 Dolthub, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package analyzer + +import ( + "github.com/dolthub/go-mysql-server/sql" + "github.com/dolthub/go-mysql-server/sql/analyzer" + "github.com/dolthub/go-mysql-server/sql/plan" + "github.com/dolthub/go-mysql-server/sql/transform" +) + +// convertDropPrimaryKeyConstraint converts a DropConstraint node dropping a primary key constraint into +// an AlterPK node that GMS can process to remove the primary key. +func convertDropPrimaryKeyConstraint(ctx *sql.Context, _ *analyzer.Analyzer, n sql.Node, _ *plan.Scope, _ analyzer.RuleSelector, _ *sql.QueryFlags) (sql.Node, transform.TreeIdentity, error) { + return transform.Node(n, func(n sql.Node) (sql.Node, transform.TreeIdentity, error) { + dropConstraint, ok := n.(*plan.DropConstraint) + if !ok { + return n, transform.SameTree, nil + } + + rt, ok := dropConstraint.Child.(*plan.ResolvedTable) + if !ok { + return nil, transform.SameTree, analyzer.ErrInAnalysis.New( + "Expected a TableNode for ALTER TABLE DROP CONSTRAINT statement") + } + + table := rt.Table + if it, ok := table.(sql.IndexAddressableTable); ok { + indexes, err := it.GetIndexes(ctx) + if err != nil { + return nil, transform.SameTree, err + } + for _, index := range indexes { + if index.ID() == "PRIMARY" && dropConstraint.Name == rt.Name()+"_pkey" { + return plan.NewAlterDropPk(rt.Database(), rt), transform.NewTree, nil + } + } + } + + return n, transform.SameTree, nil + }) +} diff --git a/server/analyzer/generate_fk_name.go b/server/analyzer/generate_fk_name.go new file mode 100644 index 0000000000..2d94337fd1 --- /dev/null +++ b/server/analyzer/generate_fk_name.go @@ -0,0 +1,102 @@ +// Copyright 2025 Dolthub, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package analyzer + +import ( + "fmt" + "strings" + + "github.com/dolthub/go-mysql-server/sql" + "github.com/dolthub/go-mysql-server/sql/analyzer" + "github.com/dolthub/go-mysql-server/sql/plan" + "github.com/dolthub/go-mysql-server/sql/transform" +) + +// generateForeignKeyName populates a generated foreign key name, in the Postgres default foreign key name format, +// when a foreign key is created without an explicit name specified. +func generateForeignKeyName(_ *sql.Context, _ *analyzer.Analyzer, n sql.Node, _ *plan.Scope, _ analyzer.RuleSelector, _ *sql.QueryFlags) (sql.Node, transform.TreeIdentity, error) { + return transform.Node(n, func(n sql.Node) (sql.Node, transform.TreeIdentity, error) { + switch n := n.(type) { + case *plan.CreateTable: + copiedForeignKeys := make([]*sql.ForeignKeyConstraint, len(n.ForeignKeys())) + for i := range n.ForeignKeys() { + fk := *n.ForeignKeys()[i] + copiedForeignKeys[i] = &fk + } + + changedForeignKey := false + for _, fk := range copiedForeignKeys { + if fk.Name == "" { + generatedName, err := generateFkName(n.Name(), fk, nil) + if err != nil { + return nil, transform.SameTree, err + } + changedForeignKey = true + fk.Name = generatedName + } + } + if changedForeignKey { + newCreateTable := plan.NewCreateTable(n.Db, n.Name(), n.IfNotExists(), n.Temporary(), &plan.TableSpec{ + Schema: n.PkSchema(), + FkDefs: copiedForeignKeys, + ChDefs: n.Checks(), + IdxDefs: n.Indexes(), + Collation: n.Collation, + TableOpts: n.TableOpts, + }) + return newCreateTable, transform.NewTree, nil + } else { + return n, transform.SameTree, nil + } + + case *plan.CreateForeignKey: + if n.FkDef.Name == "" { + copiedFk := *n.FkDef + generatedName, err := generateFkName(copiedFk.Table, &copiedFk, nil) + if err != nil { + return nil, transform.SameTree, err + } + copiedFk.Name = generatedName + return &plan.CreateForeignKey{ + DbProvider: n.DbProvider, + FkDef: &copiedFk, + }, transform.NewTree, nil + } else { + return n, transform.SameTree, nil + } + + default: + return n, transform.SameTree, nil + } + }) +} + +// generateFkName creates a default foreign key name, according to Postgres naming rules (i.e. "___fkey"). +// |existingFks| is used to check that the generated name doesn't conflict with an existing foreign key name. If a +// conflicting name is generated, this function returns an error. +func generateFkName(tableName string, newFk *sql.ForeignKeyConstraint, existingFks []sql.ForeignKeyConstraint) (string, error) { + columnNames := strings.Join(newFk.Columns, "_") + generatedFkName := fmt.Sprintf("%s_%s_fkey", tableName, columnNames) + + for _, existingFk := range existingFks { + if existingFk.Name == generatedFkName { + // TODO: Instead of returning an error, we should follow Postgres' behavior for disambiguating the name. + return "", fmt.Errorf("unable to create foreign key %s: "+ + "a foreign key constraint already exists with this name", generatedFkName) + } + } + + return generatedFkName, nil +} diff --git a/server/analyzer/init.go b/server/analyzer/init.go index 2e1d605c8d..7086aadf94 100644 --- a/server/analyzer/init.go +++ b/server/analyzer/init.go @@ -22,22 +22,24 @@ import ( // Comments are to match the Stringer formatting rules in the original rule definition file, but we can't generate // human-readable strings for these extended types because they are in another package. const ( - ruleId_TypeSanitizer analyzer.RuleId = iota + 1000 // typeSanitizer - ruleId_AddDomainConstraints // addDomainConstraints - ruleId_AddDomainConstraintsToCasts // addDomainConstraintsToCasts - ruleId_AssignInsertCasts // assignInsertCasts - ruleId_AssignUpdateCasts // assignUpdateCasts - ruleId_ReplaceIndexedTables // replaceIndexedTables - ruleId_ReplaceNode // replaceNode - ruleId_ReplaceSerial // replaceSerial - ruleId_AddImplicitPrefixLengths // addImplicitPrefixLengths - ruleId_InsertContextRootFinalizer // insertContextRootFinalizer - ruleId_ResolveType // resolveType - ruleId_ReplaceArithmeticExpressions // replaceArithmeticExpressions - ruleId_OptimizeFunctions // optimizeFunctions - ruleId_ValidateColumnDefaults // validateColumnDefaults - ruleId_ValidateCreateTable // validateCreateTable - rulesId_ResolveAlterColumn // resolveAlterColumn + ruleId_TypeSanitizer analyzer.RuleId = iota + 1000 // typeSanitizer + ruleId_AddDomainConstraints // addDomainConstraints + ruleId_AddDomainConstraintsToCasts // addDomainConstraintsToCasts + ruleId_AssignInsertCasts // assignInsertCasts + ruleId_AssignUpdateCasts // assignUpdateCasts + ruleId_ConvertDropPrimaryKeyConstraint // convertDropPrimaryKeyConstraint + ruleId_GenerateForeignKeyName // generateForeignKeyName + ruleId_ReplaceIndexedTables // replaceIndexedTables + ruleId_ReplaceNode // replaceNode + ruleId_ReplaceSerial // replaceSerial + ruleId_AddImplicitPrefixLengths // addImplicitPrefixLengths + ruleId_InsertContextRootFinalizer // insertContextRootFinalizer + ruleId_ResolveType // resolveType + ruleId_ReplaceArithmeticExpressions // replaceArithmeticExpressions + ruleId_OptimizeFunctions // optimizeFunctions + ruleId_ValidateColumnDefaults // validateColumnDefaults + ruleId_ValidateCreateTable // validateCreateTable + ruleId_ResolveAlterColumn // resolveAlterColumn ) // Init adds additional rules to the analyzer to handle Doltgres-specific functionality. @@ -45,6 +47,7 @@ func Init() { analyzer.AlwaysBeforeDefault = append(analyzer.AlwaysBeforeDefault, analyzer.Rule{Id: ruleId_ResolveType, Apply: ResolveType}, analyzer.Rule{Id: ruleId_TypeSanitizer, Apply: TypeSanitizer}, + analyzer.Rule{Id: ruleId_GenerateForeignKeyName, Apply: generateForeignKeyName}, analyzer.Rule{Id: ruleId_AddDomainConstraints, Apply: AddDomainConstraints}, analyzer.Rule{Id: ruleId_ValidateColumnDefaults, Apply: ValidateColumnDefaults}, analyzer.Rule{Id: ruleId_AssignInsertCasts, Apply: AssignInsertCasts}, @@ -54,14 +57,16 @@ func Init() { // PostgreSQL doesn't have the concept of prefix lengths, so we add a rule to implicitly add them // TODO: this should be replaced by implementing automatic toast semantics for blob types - analyzer.OnceBeforeDefault = append([]analyzer.Rule{{Id: ruleId_AddImplicitPrefixLengths, Apply: AddImplicitPrefixLengths}}, + analyzer.OnceBeforeDefault = append([]analyzer.Rule{ + {Id: ruleId_AddImplicitPrefixLengths, Apply: AddImplicitPrefixLengths}, + {Id: ruleId_ConvertDropPrimaryKeyConstraint, Apply: convertDropPrimaryKeyConstraint}}, analyzer.OnceBeforeDefault...) // We remove several validation rules and substitute our own analyzer.OnceBeforeDefault = insertAnalyzerRules(analyzer.OnceBeforeDefault, analyzer.ValidateCreateTableId, true, analyzer.Rule{Id: ruleId_ValidateCreateTable, Apply: validateCreateTable}) analyzer.OnceBeforeDefault = insertAnalyzerRules(analyzer.OnceBeforeDefault, analyzer.ResolveAlterColumnId, true, - analyzer.Rule{Id: rulesId_ResolveAlterColumn, Apply: resolveAlterColumn}) + analyzer.Rule{Id: ruleId_ResolveAlterColumn, Apply: resolveAlterColumn}) analyzer.OnceBeforeDefault = removeAnalyzerRules( analyzer.OnceBeforeDefault, diff --git a/server/ast/table_def.go b/server/ast/table_def.go index 1c4abfc9c8..28e6510951 100644 --- a/server/ast/table_def.go +++ b/server/ast/table_def.go @@ -55,6 +55,15 @@ func assignTableDef(ctx *Context, node tree.TableDef, target *vitess.DDL) error return err } target.TableSpec.AddColumn(columnDef) + if node.References.Table != nil { + fkDef, err := nodeForeignKeyDefinitionFromColumnTableDef(ctx, node.Name, node) + if err != nil { + return err + } + target.TableSpec.Constraints = append(target.TableSpec.Constraints, &vitess.ConstraintDefinition{ + Details: fkDef, + }) + } return nil case *tree.ForeignKeyConstraintTableDef: if target.TableSpec == nil { @@ -122,6 +131,26 @@ func assignTableDef(ctx *Context, node tree.TableDef, target *vitess.DDL) error } } +// nodeForeignKeyDefinitionFromColumnTableDef returns a vitess ForeignKeyDefinition from the specified column +// definition |node|. +func nodeForeignKeyDefinitionFromColumnTableDef(ctx *Context, fromColumn tree.Name, node *tree.ColumnTableDef) (*vitess.ForeignKeyDefinition, error) { + if node == nil { + return nil, nil + } + + references := node.References + fkConstraintTableDef := &tree.ForeignKeyConstraintTableDef{ + Name: references.ConstraintName, + FromCols: []tree.Name{fromColumn}, + Table: *references.Table, + ToCols: []tree.Name{references.Col}, + Actions: references.Actions, + Match: references.Match, + } + + return nodeForeignKeyConstraintTableDef(ctx, fkConstraintTableDef) +} + // assignTableDefs handles tree.TableDefs nodes for *vitess.DDL targets. This also sorts table defs by whether they're // dependent on other table defs evaluating first. Some table defs, such as indexes, affect other defs, such as columns, // and they're therefore dependent on columns being handled first. diff --git a/server/tables/pgcatalog/pg_constraint.go b/server/tables/pgcatalog/pg_constraint.go index bfb0e05ce9..d7b613237c 100644 --- a/server/tables/pgcatalog/pg_constraint.go +++ b/server/tables/pgcatalog/pg_constraint.go @@ -134,7 +134,9 @@ func (p PgConstraintHandler) RowIter(ctx *sql.Context) (sql.RowIter, error) { if index.Item.IsUnique() { conType = "u" } else { - conType = "f" + // If this isn't a primary key or a unique index, then it's a regular index, and not + // a constraint, so we don't need to report it in the pg_constraint table. + return true, nil } } diff --git a/testing/go/create_table_test.go b/testing/go/create_table_test.go index 2e5d1c399f..6eb43de3f1 100755 --- a/testing/go/create_table_test.go +++ b/testing/go/create_table_test.go @@ -18,6 +18,7 @@ import ( "testing" "github.com/dolthub/go-mysql-server/sql" + "github.com/dolthub/go-mysql-server/sql/types" ) func TestCreateTable(t *testing.T) { @@ -43,6 +44,33 @@ func TestCreateTable(t *testing.T) { {1, "Doe", "John"}, }, }, + { + // Test that the PK constraint shows up in the information schema + Query: "SELECT conname FROM pg_constraint WHERE conrelid = 'employees'::regclass AND contype = 'p';", + Expected: []sql.Row{{"employees_pkey"}}, + }, + { + Query: "ALTER TABLE employees DROP CONSTRAINT employees_pkey;", + Expected: []sql.Row{}, + }, + }, + }, + { + // TODO: We don't currently support storing a custom name for a primary key constraint. + Skip: true, + Name: "create table with primary key, using custom constraint name", + SetUpScript: []string{ + "CREATE TABLE users (id SERIAL, name TEXT, CONSTRAINT users_primary_key PRIMARY KEY (id));", + }, + Assertions: []ScriptTestAssertion{ + { + Query: "SELECT conname FROM pg_constraint WHERE conrelid = 'users'::regclass AND contype = 'p';", + Expected: []sql.Row{{"users_primary_key"}}, + }, + { + Query: "ALTER TABLE users DROP CONSTRAINT users_primary_key;", + Expected: []sql.Row{{types.NewOkResult(0)}}, + }, }, }, { diff --git a/testing/go/foreign_keys_test.go b/testing/go/foreign_keys_test.go index aee7ca707a..a1b8694070 100755 --- a/testing/go/foreign_keys_test.go +++ b/testing/go/foreign_keys_test.go @@ -410,7 +410,7 @@ func TestForeignKeys(t *testing.T) { ExpectedErr: "Foreign key violation", }, { - Query: "alter table child DROP constraint child_ibfk_1", + Query: "alter table child DROP constraint child_test_pk_fkey;", SkipResultsCheck: true, }, { @@ -450,6 +450,83 @@ func TestForeignKeys(t *testing.T) { }, }, }, + { + Name: "foreign key default naming", + SetUpScript: []string{ + "CREATE TABLE webhooks (id varchar not null, id2 int8, primary key (id));", + "CREATE UNIQUE INDEX idx1 on webhooks(id, id2);", + "CREATE TABLE t33 (id varchar not null, webhook_id_fk varchar not null, webhook_id2_fk int8, foreign key (webhook_id_fk) references webhooks(id), foreign key (webhook_id_fk, webhook_id2_fk) references webhooks(id, id2), primary key (id));", + }, + Assertions: []ScriptTestAssertion{ + { + Query: "SELECT conname AS constraint_name FROM pg_constraint WHERE conrelid = 't33'::regclass AND contype = 'f';", + Expected: []sql.Row{ + {"t33_webhook_id_fk_fkey"}, + {"t33_webhook_id_fk_webhook_id2_fk_fkey"}, + }, + }, + { + Query: "ALTER TABLE t33 DROP CONSTRAINT t33_webhook_id_fk_fkey;", + Expected: []sql.Row{}, + }, + }, + }, + { + Name: "foreign key default naming, in column definition", + SetUpScript: []string{ + "CREATE TABLE webhooks (id varchar not null, primary key (id));", + "CREATE TABLE t33 (id varchar not null, webhook_id_fk varchar not null references webhooks(id), primary key (id));", + }, + Assertions: []ScriptTestAssertion{ + { + Query: "SELECT conname AS constraint_name FROM pg_constraint WHERE conrelid = 't33'::regclass AND contype = 'f';", + Expected: []sql.Row{ + {"t33_webhook_id_fk_fkey"}, + }, + }, + { + Query: "ALTER TABLE t33 DROP CONSTRAINT t33_webhook_id_fk_fkey;", + Expected: []sql.Row{}, + }, + }, + }, + { + Name: "foreign key custom naming", + SetUpScript: []string{ + "CREATE TABLE webhooks (id VARCHAR NOT NULL, PRIMARY KEY (id));", + "CREATE TABLE t33 (id VARCHAR NOT NULL, webhook_id_fk VARCHAR NOT NULL, CONSTRAINT foo1 FOREIGN KEY (webhook_id_fk) REFERENCES webhooks(id), PRIMARY KEY (id));", + }, + Assertions: []ScriptTestAssertion{ + { + Query: "SELECT conname AS constraint_name FROM pg_constraint WHERE conrelid = 't33'::regclass AND contype = 'f';", + Expected: []sql.Row{{"foo1"}}, + }, + { + Query: "ALTER TABLE t33 DROP CONSTRAINT foo1;", + Expected: []sql.Row{}, + }, + }, + }, + { + Name: "foreign key default naming, added through alter table", + SetUpScript: []string{ + "CREATE TABLE webhooks (id varchar not null, primary key (id));", + "CREATE TABLE t33 (id varchar not null, webhook_id_fk varchar not null, primary key (id));", + "ALTER TABLE t33 ADD FOREIGN KEY (webhook_id_fk) REFERENCES webhooks(id);", + }, + Assertions: []ScriptTestAssertion{ + { + Query: "SELECT conname AS constraint_name FROM pg_constraint WHERE conrelid = 't33'::regclass AND contype = 'f';", + Expected: []sql.Row{ + {"t33_webhook_id_fk_fkey"}, + }, + }, + { + Query: "ALTER TABLE t33 DROP CONSTRAINT t33_webhook_id_fk_fkey;", + Expected: []sql.Row{}, + }, + }, + }, }, ) } diff --git a/testing/go/functions_test.go b/testing/go/functions_test.go index 49599a5f35..ef0ba4bcea 100644 --- a/testing/go/functions_test.go +++ b/testing/go/functions_test.go @@ -848,17 +848,10 @@ func TestSystemInformationFunctions(t *testing.T) { }, }, { - Query: `SELECT pg_get_constraintdef(oid) FROM pg_catalog.pg_constraint WHERE conrelid='testing2'::regclass LIMIT 1;`, - Expected: []sql.Row{ - {"PRIMARY KEY (pk)"}, - }, - }, - { - Skip: true, // TODO: Foreign keys don't work Query: `SELECT pg_get_constraintdef(oid) FROM pg_catalog.pg_constraint WHERE conrelid='testing2'::regclass;`, Expected: []sql.Row{ + {"FOREIGN KEY testing2_pktesting_fkey (pktesting) REFERENCES testing (pk)"}, {"PRIMARY KEY (pk)"}, - {"FOREIGN KEY (pktesting) REFERENCES testing(pk)"}, }, }, { diff --git a/testing/go/pgcatalog_test.go b/testing/go/pgcatalog_test.go index ac1b4f39c7..a73052d2ca 100644 --- a/testing/go/pgcatalog_test.go +++ b/testing/go/pgcatalog_test.go @@ -629,21 +629,14 @@ func TestPgConstraint(t *testing.T) { }, Assertions: []ScriptTestAssertion{ { - Query: `SELECT * FROM "pg_catalog"."pg_constraint" LIMIT 3;`, - Expected: []sql.Row{ - {3757635986, "testing_pkey", 2200, "p", "f", "f", "t", 2147906242, 0, 3757635986, 0, 0, "", "", "", "t", 0, "t", "{1}", nil, nil, nil, nil, nil, nil, nil}, - {3050361446, "v1", 2200, "u", "f", "f", "t", 2147906242, 0, 3050361446, 0, 0, "", "", "", "t", 0, "t", "{2}", nil, nil, nil, nil, nil, nil, nil}, - {2068729390, "testing2_pkey", 2200, "p", "f", "f", "t", 2694106299, 0, 2068729390, 0, 0, "", "", "", "t", 0, "t", "{1}", nil, nil, nil, nil, nil, nil, nil}, - }, - }, - { - Skip: true, // TODO: Foreign keys don't work Query: `SELECT * FROM "pg_catalog"."pg_constraint" WHERE conrelid='testing2'::regclass OR conrelid='testing'::regclass;`, Expected: []sql.Row{ {3757635986, "testing_pkey", 2200, "p", "f", "f", "t", 2147906242, 0, 3757635986, 0, 0, "", "", "", "t", 0, "t", "{1}", nil, nil, nil, nil, nil, nil, nil}, + // TODO: postgres names this index testing_v1_key {3050361446, "v1", 2200, "u", "f", "f", "t", 2147906242, 0, 3050361446, 0, 0, "", "", "", "t", 0, "t", "{2}", nil, nil, nil, nil, nil, nil, nil}, + {1719906648, "testing2_pktesting_fkey", 2200, "f", "f", "f", "t", 2694106299, 0, 1719906648, 0, 2147906242, "a", "a", "s", "t", 0, "t", "{0}", "{1}", nil, nil, nil, nil, nil, nil}, {2068729390, "testing2_pkey", 2200, "p", "f", "f", "t", 2694106299, 0, 2068729390, 0, 0, "", "", "", "t", 0, "t", "{1}", nil, nil, nil, nil, nil, nil, nil}, - {2068729390, "testing2_pktesting_fkey", 2200, "f", "f", "t", 2694106299, 0, 2068729390, 0, 0, "", "", "", "t", 0, "t", "{2}", "{1}", nil, nil, nil, nil, nil, nil}}, + }, }, { // Different cases and quoted, so it fails Query: `SELECT * FROM "PG_catalog"."pg_constraint";`, @@ -657,6 +650,7 @@ func TestPgConstraint(t *testing.T) { Query: "SELECT conname FROM PG_catalog.pg_CONSTRAINT ORDER BY conname;", Expected: []sql.Row{ {"testing2_pkey"}, + {"testing2_pktesting_fkey"}, {"testing_pkey"}, {"v1"}, }, @@ -665,6 +659,7 @@ func TestPgConstraint(t *testing.T) { Query: "SELECT co.oid, co.conname, co.conrelid, cl.relname FROM pg_catalog.pg_constraint co JOIN pg_catalog.pg_class cl ON co.conrelid = cl.oid WHERE cl.relname = 'testing2';", Expected: []sql.Row{ {2068729390, "testing2_pkey", 2694106299, "testing2"}, + {1719906648, "testing2_pktesting_fkey", 2694106299, "testing2"}, }, }, }, diff --git a/testing/postgres-client-tests/node/workbenchTests/diffs.js b/testing/postgres-client-tests/node/workbenchTests/diffs.js index 88080dbd2e..f8a0a979a7 100644 --- a/testing/postgres-client-tests/node/workbenchTests/diffs.js +++ b/testing/postgres-client-tests/node/workbenchTests/diffs.js @@ -463,8 +463,8 @@ export const diffTests = [ " `info` varchar(255),\n" + " `test_pk` integer,\n" + " PRIMARY KEY (`id`),\n" + - " KEY `test_pk` (`test_pk`),\n" + - " CONSTRAINT `test_info_ibfk_1` FOREIGN KEY (`test_pk`) REFERENCES `test` (`pk`) ON DELETE NO ACTION ON UPDATE NO ACTION\n" + + " KEY `test_info_test_pk_fkey` (`test_pk`),\n" + + " CONSTRAINT `test_info_test_pk_fkey` FOREIGN KEY (`test_pk`) REFERENCES `test` (`pk`) ON DELETE NO ACTION ON UPDATE NO ACTION\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;", to_create_statement: "", }, @@ -513,8 +513,8 @@ export const diffTests = [ " `info` varchar(255),\n" + " `test_pk` integer,\n" + " PRIMARY KEY (`id`),\n" + - " KEY `test_pk` (`test_pk`),\n" + - " CONSTRAINT `test_info_ibfk_1` FOREIGN KEY (`test_pk`) REFERENCES `test` (`pk`) ON DELETE NO ACTION ON UPDATE NO ACTION\n" + + " KEY `test_info_test_pk_fkey` (`test_pk`),\n" + + " CONSTRAINT `test_info_test_pk_fkey` FOREIGN KEY (`test_pk`) REFERENCES `test` (`pk`) ON DELETE NO ACTION ON UPDATE NO ACTION\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;", to_create_statement: "", }, diff --git a/testing/postgres-client-tests/node/workbenchTests/table.js b/testing/postgres-client-tests/node/workbenchTests/table.js index 0422e30dab..31929fe3d8 100644 --- a/testing/postgres-client-tests/node/workbenchTests/table.js +++ b/testing/postgres-client-tests/node/workbenchTests/table.js @@ -251,7 +251,7 @@ export const tableTests = [ { CONSTRAINT_CATALOG: `${dbName}/main`, CONSTRAINT_SCHEMA: "public", - CONSTRAINT_NAME: "test_info_ibfk_1", + CONSTRAINT_NAME: "test_info_test_pk_fkey", TABLE_CATALOG: `${dbName}/main`, TABLE_SCHEMA: "public", TABLE_NAME: "test_info",