-
Notifications
You must be signed in to change notification settings - Fork 30
fix: default column value function order #175
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
Changes from all commits
003fad9
1a55e50
ebc43f7
b786725
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -65,9 +65,9 @@ func normalizeTable(table *Table) { | |||||
| return | ||||||
| } | ||||||
|
|
||||||
| // Normalize columns | ||||||
| // Normalize columns (pass table schema for context) | ||||||
| for _, column := range table.Columns { | ||||||
| normalizeColumn(column) | ||||||
| normalizeColumn(column, table.Schema) | ||||||
| } | ||||||
|
|
||||||
| // Normalize policies | ||||||
|
|
@@ -92,17 +92,19 @@ func normalizeTable(table *Table) { | |||||
| } | ||||||
|
|
||||||
| // normalizeColumn normalizes column default values | ||||||
| func normalizeColumn(column *Column) { | ||||||
| // tableSchema is used to strip same-schema qualifiers from function calls | ||||||
| func normalizeColumn(column *Column, tableSchema string) { | ||||||
| if column == nil || column.DefaultValue == nil { | ||||||
| return | ||||||
| } | ||||||
|
|
||||||
| normalized := normalizeDefaultValue(*column.DefaultValue) | ||||||
| normalized := normalizeDefaultValue(*column.DefaultValue, tableSchema) | ||||||
| column.DefaultValue = &normalized | ||||||
| } | ||||||
|
|
||||||
| // normalizeDefaultValue normalizes default values for semantic comparison | ||||||
| func normalizeDefaultValue(value string) string { | ||||||
| // tableSchema is used to strip same-schema qualifiers from function calls | ||||||
| func normalizeDefaultValue(value string, tableSchema string) string { | ||||||
| // Remove unnecessary whitespace | ||||||
| value = strings.TrimSpace(value) | ||||||
|
|
||||||
|
|
@@ -118,6 +120,18 @@ func normalizeDefaultValue(value string) string { | |||||
| return value | ||||||
| } | ||||||
|
|
||||||
| // Normalize function calls - remove schema qualifiers for functions in the same schema | ||||||
| // This matches PostgreSQL's pg_get_expr() behavior which strips same-schema qualifiers | ||||||
| // Example: public.get_status() -> get_status() (when tableSchema is "public") | ||||||
| // other_schema.get_status() -> other_schema.get_status() (preserved) | ||||||
| if tableSchema != "" && strings.Contains(value, tableSchema+".") { | ||||||
| // Pattern: schema.function_name( | ||||||
| // Replace "tableSchema." with "" when followed by identifier and ( | ||||||
| prefix := tableSchema + "." | ||||||
| pattern := regexp.MustCompile(regexp.QuoteMeta(prefix) + `([a-zA-Z_][a-zA-Z0-9_]*)\(`) | ||||||
|
||||||
| pattern := regexp.MustCompile(regexp.QuoteMeta(prefix) + `([a-zA-Z_][a-zA-Z0-9_]*)\(`) | |
| pattern := regexp.MustCompile(regexp.QuoteMeta(prefix) + `([a-zA-Z_][a-zA-Z0-9_$]*)\(`) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| CREATE OR REPLACE FUNCTION get_default_status() | ||
| RETURNS text | ||
| LANGUAGE plpgsql | ||
| SECURITY INVOKER | ||
| VOLATILE | ||
| AS $$ | ||
| BEGIN | ||
| RETURN 'active'; | ||
| END; | ||
| $$; | ||
|
|
||
| CREATE TABLE IF NOT EXISTS users ( | ||
| id SERIAL, | ||
| name text NOT NULL, | ||
| status text DEFAULT get_default_status(), | ||
| CONSTRAINT users_pkey PRIMARY KEY (id) | ||
| ); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| -- Simple function that returns a default value | ||
| CREATE OR REPLACE FUNCTION public.get_default_status() | ||
| RETURNS text | ||
| LANGUAGE plpgsql | ||
| AS $$ | ||
| BEGIN | ||
| RETURN 'active'; | ||
| END; | ||
| $$; | ||
|
|
||
| -- Table with column default that uses the function | ||
| CREATE TABLE public.users ( | ||
| id serial PRIMARY KEY, | ||
| name text NOT NULL, | ||
| status text DEFAULT get_default_status() | ||
| ); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| -- Empty schema (no objects) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| { | ||
| "version": "1.0.0", | ||
| "pgschema_version": "1.4.3", | ||
| "created_at": "1970-01-01T00:00:00Z", | ||
| "source_fingerprint": { | ||
| "hash": "965b1131737c955e24c7f827c55bd78e4cb49a75adfd04229e0ba297376f5085" | ||
| }, | ||
| "groups": [ | ||
| { | ||
| "steps": [ | ||
| { | ||
| "sql": "CREATE OR REPLACE FUNCTION get_default_status()\nRETURNS text\nLANGUAGE plpgsql\nSECURITY INVOKER\nVOLATILE\nAS $$\nBEGIN\n RETURN 'active';\nEND;\n$$;", | ||
| "type": "function", | ||
| "operation": "create", | ||
| "path": "public.get_default_status" | ||
| }, | ||
| { | ||
| "sql": "CREATE TABLE IF NOT EXISTS users (\n id SERIAL,\n name text NOT NULL,\n status text DEFAULT get_default_status(),\n CONSTRAINT users_pkey PRIMARY KEY (id)\n);", | ||
| "type": "table", | ||
| "operation": "create", | ||
| "path": "public.users" | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| CREATE OR REPLACE FUNCTION get_default_status() | ||
| RETURNS text | ||
| LANGUAGE plpgsql | ||
| SECURITY INVOKER | ||
| VOLATILE | ||
| AS $$ | ||
| BEGIN | ||
| RETURN 'active'; | ||
| END; | ||
| $$; | ||
|
|
||
| CREATE TABLE IF NOT EXISTS users ( | ||
| id SERIAL, | ||
| name text NOT NULL, | ||
| status text DEFAULT get_default_status(), | ||
| CONSTRAINT users_pkey PRIMARY KEY (id) | ||
| ); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| Plan: 2 to add. | ||
|
|
||
| Summary by type: | ||
| functions: 1 to add | ||
| tables: 1 to add | ||
|
|
||
| Functions: | ||
| + get_default_status | ||
|
|
||
| Tables: | ||
| + users | ||
|
|
||
| DDL to be executed: | ||
| -------------------------------------------------- | ||
|
|
||
| CREATE OR REPLACE FUNCTION get_default_status() | ||
| RETURNS text | ||
| LANGUAGE plpgsql | ||
| SECURITY INVOKER | ||
| VOLATILE | ||
| AS $$ | ||
| BEGIN | ||
| RETURN 'active'; | ||
| END; | ||
| $$; | ||
|
|
||
| CREATE TABLE IF NOT EXISTS users ( | ||
| id SERIAL, | ||
| name text NOT NULL, | ||
| status text DEFAULT get_default_status(), | ||
| CONSTRAINT users_pkey PRIMARY KEY (id) | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment states "We need to create triggers for ALL tables, not just the original d.addedTables", but the code on line 985 still only passes
d.addedTables. Either the comment is misleading or the code needs to be updated. If triggers should be created for all newly added tables (including bothtablesWithoutFunctionDepsandtablesWithFunctionDeps), the code is already correct sinced.addedTablescontains all of them. Consider clarifying the comment or removing it if it's not accurate.