Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add enum support #120

Merged
merged 1 commit into from
Mar 29, 2024
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
131 changes: 131 additions & 0 deletions internal/migration_acceptance_tests/enum_cases_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package migration_acceptance_tests

import "github.com/stripe/pg-schema-diff/pkg/diff"

var enumAcceptanceTestCases = []acceptanceTestCase{
{
name: "no-op",
oldSchemaDDL: []string{
`
CREATE TYPE color AS ENUM ('red', 'green', 'blue');
CREATE TABLE foo(
color color DEFAULT 'green'
);
`,
},
newSchemaDDL: []string{
`
CREATE TYPE color AS ENUM ('red', 'green', 'blue');
CREATE TABLE foo(
color color DEFAULT 'green'
);
`,
},

vanillaExpectations: expectations{
empty: true,
},
dataPackingExpectations: expectations{
empty: true,
},
},
{
name: "create enum",
oldSchemaDDL: []string{
`
CREATE TABLE foo();
`,
},
newSchemaDDL: []string{
`
CREATE SCHEMA schema_1;
CREATE TYPE schema_1.color AS ENUM ('red', 'green', 'blue');
CREATE TABLE foo(
color schema_1.color DEFAULT 'green'
);
`,
},
},
{
name: "drop enum",
oldSchemaDDL: []string{
`
CREATE SCHEMA schema_1;
CREATE TYPE schema_1.color AS ENUM ('red', 'green', 'blue');
CREATE TABLE foo(
color schema_1.color DEFAULT 'green'
);
`,
},
newSchemaDDL: []string{
`
CREATE SCHEMA schema_1;
CREATE TABLE foo(
color VARCHAR(255) DEFAULT 'green'
);
`,
},
expectedHazardTypes: []diff.MigrationHazardType{
diff.MigrationHazardTypeAcquiresAccessExclusiveLock,
diff.MigrationHazardTypeImpactsDatabasePerformance,
},
},
{
name: "add values",
oldSchemaDDL: []string{
`
CREATE TYPE some_enum_1 AS ENUM ('1', '2', '3');
CREATE TABLE foo(
val some_enum_1
);
`},
newSchemaDDL: []string{
`
CREATE TYPE some_enum_1 AS ENUM ('0', '1', '1.5', '2', '2.5', '3', '4');
CREATE TABLE foo(
val some_enum_1 DEFAULT '1.5'
);
`},
},
{
name: "delete value and add value (enum not used)",
oldSchemaDDL: []string{
`
CREATE TYPE some_enum_1 AS ENUM ('1', '2', '3');
`},
newSchemaDDL: []string{
`
CREATE TYPE some_enum_1 AS ENUM ('0', '1', '3');
`},
},
{
name: "delete value and add value (enum used)",
oldSchemaDDL: []string{
`
CREATE TYPE some_enum_1 AS ENUM ('1', '2', '3');
CREATE TABLE foo(
val some_enum_1
);
`},
newSchemaDDL: []string{
`
CREATE TYPE some_enum_1 AS ENUM ('0', '1', '3');
CREATE TABLE foo(
val some_enum_1
);
`},

// Removing a value from an enum in-use is impossible in Postgres. pg-schema-diff will currently identify this
// as a validation error. In the future, we can identify this in the actual plan generation stage.
vanillaExpectations: expectations{
planErrorContains: errValidatingPlan.Error(),
},
dataPackingExpectations: expectations{
planErrorContains: errValidatingPlan.Error(),
},
},
}

func (s *acceptanceTestSuite) TestEnumTestCases() {
s.runTestCases(enumAcceptanceTestCases)
}
14 changes: 13 additions & 1 deletion internal/migration_acceptance_tests/schema_cases_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ var schemaAcceptanceTests = []acceptanceTestCase{
CREATE TABLE fizz(
);

CREATE TYPE schema_1.color AS ENUM ('red', 'green', 'blue');

CREATE SEQUENCE schema_1.foobar_sequence
AS BIGINT
INCREMENT BY 2
Expand Down Expand Up @@ -46,6 +48,7 @@ var schemaAcceptanceTests = []acceptanceTestCase{
foo VARCHAR(255) DEFAULT 'some default' NOT NULL CHECK (LENGTH(foo) > 0),
bar SERIAL NOT NULL,
fizz TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
color schema_1.color DEFAULT 'green',
PRIMARY KEY (foo, id),
UNIQUE (foo, bar)
) PARTITION BY LIST(foo);
Expand Down Expand Up @@ -83,6 +86,8 @@ var schemaAcceptanceTests = []acceptanceTestCase{
CREATE TABLE fizz(
);

CREATE TYPE schema_1.color AS ENUM ('red', 'green', 'blue');

CREATE SEQUENCE schema_1.foobar_sequence
AS BIGINT
INCREMENT BY 2
Expand Down Expand Up @@ -113,6 +118,7 @@ var schemaAcceptanceTests = []acceptanceTestCase{
foo VARCHAR(255) DEFAULT 'some default' NOT NULL CHECK (LENGTH(foo) > 0),
bar SERIAL NOT NULL,
fizz TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
color schema_1.color DEFAULT 'green',
PRIMARY KEY (foo, id),
UNIQUE (foo, bar)
) PARTITION BY LIST(foo);
Expand Down Expand Up @@ -150,7 +156,7 @@ var schemaAcceptanceTests = []acceptanceTestCase{
},
},
{
name: "Add schema, drop schema, Drop table, Add Table, Drop Seq, Add Seq, Drop Funcs, Add Funcs, Drop Triggers, Add Triggers, Create Extension, Drop Extension, Create Index Using Extension",
name: "Add schema, drop schema, Add enum, Drop enum, Drop table, Add Table, Drop Seq, Add Seq, Drop Funcs, Add Funcs, Drop Triggers, Add Triggers, Create Extension, Drop Extension, Create Index Using Extension",
oldSchemaDDL: []string{
`
CREATE SCHEMA schema_1;
Expand All @@ -161,6 +167,8 @@ var schemaAcceptanceTests = []acceptanceTestCase{
CREATE TABLE fizz(
);

CREATE TYPE schema_1.color AS ENUM ('red', 'green', 'blue');

CREATE SEQUENCE schema_2.foobar_sequence
AS BIGINT
INCREMENT BY 2
Expand Down Expand Up @@ -198,6 +206,7 @@ var schemaAcceptanceTests = []acceptanceTestCase{
bar SERIAL NOT NULL,
foo VARCHAR(255) DEFAULT 'some default' NOT NULL,
fizz TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
color schema_1.color DEFAULT 'green',
UNIQUE (foo, bar)
);
CREATE INDEX foobar_normal_idx ON foobar USING hash (fizz);
Expand Down Expand Up @@ -233,6 +242,8 @@ var schemaAcceptanceTests = []acceptanceTestCase{
CREATE TABLE fizz(
);

CREATE TYPE new_color AS ENUM ('yellow', 'orange', 'cyan');

CREATE SEQUENCE schema_3.new_foobar_sequence
AS SMALLINT
INCREMENT BY 4
Expand Down Expand Up @@ -269,6 +280,7 @@ var schemaAcceptanceTests = []acceptanceTestCase{
new_fizz TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
id INT PRIMARY KEY,
version INT NOT NULL DEFAULT 0,
new_color new_color DEFAULT 'cyan',
new_bar SMALLSERIAL NOT NULL,
new_foo VARCHAR(255) DEFAULT '' NOT NULL CHECK ( new_foo IS NOT NULL),
UNIQUE (new_foo, new_bar)
Expand Down
30 changes: 29 additions & 1 deletion internal/queries/queries.sql
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ LEFT JOIN
WHERE
seq_ns.nspname NOT IN ('pg_catalog', 'information_schema')
AND seq_ns.nspname !~ '^pg_toast'
-- It doesn't belong to an extension
-- Exclude sequences belonging to extensions
AND NOT EXISTS (
SELECT ext_depend.objid
FROM pg_catalog.pg_depend AS ext_depend
Expand All @@ -305,3 +305,31 @@ INNER JOIN
WHERE
extension_namespace.nspname NOT IN ('pg_catalog', 'information_schema')
AND extension_namespace.nspname !~ '^pg_toast';


-- name: GetEnums :many
SELECT
pg_type.typname::TEXT AS enum_name,
type_namespace.nspname::TEXT AS enum_schema_name,
(
SELECT ARRAY_AGG(pg_enum.enumlabel ORDER BY pg_enum.enumsortorder)
FROM pg_catalog.pg_enum
WHERE pg_enum.enumtypid = pg_type.oid
)::TEXT [] AS enum_labels
FROM pg_catalog.pg_type AS pg_type
INNER JOIN
pg_catalog.pg_namespace AS type_namespace
ON type_namespace.oid = pg_type.typnamespace
WHERE
pg_type.typtype = 'e'
AND type_namespace.nspname NOT IN ('pg_catalog', 'information_schema')
AND type_namespace.nspname !~ '^pg_toast'
-- Exclude enums belonging to extensions
AND NOT EXISTS (
SELECT ext_depend.objid
FROM pg_catalog.pg_depend AS ext_depend
WHERE
ext_depend.classid = 'pg_class'::REGCLASS
AND ext_depend.objid = pg_type.oid
AND ext_depend.deptype = 'e'
);
59 changes: 58 additions & 1 deletion internal/queries/queries.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading