fix(pgsql): handle nullability/type/default drift on existing columns
Existing databases that already ran an old migration kept stale NOT NULL constraints and mismatched column types/defaults, because the schema writer only emitted idempotent ADD COLUMN IF NOT EXISTS guards and never altered columns that already existed. - Emit guarded ALTER COLUMN ... SET/DROP NOT NULL when a column's nullability differs from the model. - Emit guarded ALTER COLUMN ... TYPE, falling back to renaming the old column and adding a fresh one when the in-place conversion fails. - Emit guarded ALTER COLUMN ... SET/DROP DEFAULT for default drift. - Collapse the previously duplicated plain/guarded templates so WriteSchema (full-schema, live-state-checking) and WriteMigration (diff-based) share the same guarded SQL templates and Go helpers instead of maintaining the logic twice.
This commit is contained in:
@@ -1,7 +0,0 @@
|
||||
{{- if .SetDefault -}}
|
||||
ALTER TABLE {{qual_table .SchemaName .TableName}}
|
||||
ALTER COLUMN {{quote_ident .ColumnName}} SET DEFAULT {{.DefaultValue}};
|
||||
{{- else -}}
|
||||
ALTER TABLE {{qual_table .SchemaName .TableName}}
|
||||
ALTER COLUMN {{quote_ident .ColumnName}} DROP DEFAULT;
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,29 @@
|
||||
DO $$
|
||||
DECLARE
|
||||
current_default text;
|
||||
BEGIN
|
||||
SELECT pg_catalog.pg_get_expr(d.adbin, d.adrelid)
|
||||
INTO current_default
|
||||
FROM pg_attribute a
|
||||
JOIN pg_class t ON t.oid = a.attrelid
|
||||
JOIN pg_namespace n ON n.oid = t.relnamespace
|
||||
LEFT JOIN pg_attrdef d ON d.adrelid = a.attrelid AND d.adnum = a.attnum
|
||||
WHERE n.nspname = '{{.SchemaName}}'
|
||||
AND t.relname = '{{.TableName}}'
|
||||
AND a.attname = '{{.ColumnName}}'
|
||||
AND a.attnum > 0
|
||||
AND NOT a.attisdropped;
|
||||
|
||||
{{- if .SetDefault }}
|
||||
IF current_default IS DISTINCT FROM {{quote .DefaultValue}} THEN
|
||||
ALTER TABLE {{qual_table .SchemaName .TableName}}
|
||||
ALTER COLUMN {{quote_ident .ColumnName}} SET DEFAULT {{.DefaultValue}};
|
||||
END IF;
|
||||
{{- else }}
|
||||
IF current_default IS NOT NULL THEN
|
||||
ALTER TABLE {{qual_table .SchemaName .TableName}}
|
||||
ALTER COLUMN {{quote_ident .ColumnName}} DROP DEFAULT;
|
||||
END IF;
|
||||
{{- end }}
|
||||
END;
|
||||
$$;
|
||||
@@ -1,7 +0,0 @@
|
||||
{{- if .NotNull -}}
|
||||
ALTER TABLE {{qual_table .SchemaName .TableName}}
|
||||
ALTER COLUMN {{quote_ident .ColumnName}} SET NOT NULL;
|
||||
{{- else -}}
|
||||
ALTER TABLE {{qual_table .SchemaName .TableName}}
|
||||
ALTER COLUMN {{quote_ident .ColumnName}} DROP NOT NULL;
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,26 @@
|
||||
DO $$
|
||||
DECLARE
|
||||
current_not_null boolean;
|
||||
BEGIN
|
||||
SELECT a.attnotnull
|
||||
INTO current_not_null
|
||||
FROM pg_attribute a
|
||||
JOIN pg_class t ON t.oid = a.attrelid
|
||||
JOIN pg_namespace n ON n.oid = t.relnamespace
|
||||
WHERE n.nspname = '{{.SchemaName}}'
|
||||
AND t.relname = '{{.TableName}}'
|
||||
AND a.attname = '{{.ColumnName}}'
|
||||
AND a.attnum > 0
|
||||
AND NOT a.attisdropped;
|
||||
|
||||
IF current_not_null IS NOT NULL AND current_not_null IS DISTINCT FROM {{.NotNull}} THEN
|
||||
{{- if .NotNull }}
|
||||
ALTER TABLE {{qual_table .SchemaName .TableName}}
|
||||
ALTER COLUMN {{quote_ident .ColumnName}} SET NOT NULL;
|
||||
{{- else }}
|
||||
ALTER TABLE {{qual_table .SchemaName .TableName}}
|
||||
ALTER COLUMN {{quote_ident .ColumnName}} DROP NOT NULL;
|
||||
{{- end }}
|
||||
END IF;
|
||||
END;
|
||||
$$;
|
||||
@@ -1,2 +0,0 @@
|
||||
ALTER TABLE {{qual_table .SchemaName .TableName}}
|
||||
ALTER COLUMN {{quote_ident .ColumnName}} TYPE {{.NewType}}{{if .UsingExpr}} USING {{.UsingExpr}}{{end}};
|
||||
@@ -1,13 +0,0 @@
|
||||
DO $$
|
||||
BEGIN
|
||||
BEGIN
|
||||
ALTER TABLE {{qual_table .SchemaName .TableName}}
|
||||
ALTER COLUMN {{quote_ident .ColumnName}} TYPE {{.NewType}}{{if .UsingExpr}} USING {{.UsingExpr}}{{end}};
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
ALTER TABLE {{qual_table .SchemaName .TableName}}
|
||||
RENAME COLUMN {{quote_ident .ColumnName}} TO {{quote_ident .OldColumnName}};
|
||||
ALTER TABLE {{qual_table .SchemaName .TableName}}
|
||||
ADD COLUMN {{quote_ident .ColumnName}} {{.NewType}};
|
||||
END;
|
||||
END;
|
||||
$$;
|
||||
Reference in New Issue
Block a user