Skip to content

Comments

fix: default column value function order#175

Merged
tianzhou merged 4 commits intomainfrom
chore_fix_order
Nov 27, 2025
Merged

fix: default column value function order#175
tianzhou merged 4 commits intomainfrom
chore_fix_order

Conversation

@tianzhou
Copy link
Contributor

Fix #174

tianzhou and others added 4 commits November 27, 2025 09:08
Column default expressions with function calls were generating schema-qualified
names (e.g., "public.get_status()") even when PostgreSQL's pg_get_expr() returns
unqualified names for functions in the same schema. This caused drift detection
where the second plan/apply would attempt to re-apply the same default.

Changes:
- Add normalizeDefaultExpr() helper in internal/diff/table.go to strip
  same-schema qualifiers from function calls in default expressions
- Apply normalization in buildColumnClauses() for CREATE TABLE and ADD COLUMN
- Apply normalization in column.go generateColumnSQL() for ALTER COLUMN SET DEFAULT
- Update columnsEqual() to compare normalized default values
- Update test expectations in testdata/diff/dependency/function_to_table/

This matches PostgreSQL's behavior where pg_get_expr() returns unqualified
function names for functions in the same schema as the table, ensuring
idempotent plan generation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Moved schema qualifier normalization from diff generation to IR normalization
for better separation of concerns and architectural consistency.

Changes:
- Extended ir.normalizeDefaultValue() to strip same-schema function qualifiers
- Updated normalizeColumn() to pass table schema context
- Updated normalizeFunction/Procedure() to pass schema for parameter defaults
- Removed normalizeDefaultExpr() from internal/diff/table.go
- Simplified buildColumnClauses() to use already-normalized values
- Simplified generateColumnSQL() in column.go to use normalized values
- Simplified columnsEqual() - no longer needs schema parameter

Benefits:
- Single normalization point in IR layer (follows existing pattern)
- Diff code is simpler - just compares normalized values
- More maintainable - normalization logic lives with other IR normalizations
- Consistent with how other IR attributes are normalized

All 77 diff tests and full integration test suite pass.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings November 27, 2025 17:49
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes dependency ordering issues when creating tables with column defaults that reference functions (issue #174). The fix ensures functions are created before tables that use them in column defaults, CHECK constraints, or generated columns.

Key Changes:

  • Extended normalization to strip same-schema qualifiers from function calls in column defaults, matching PostgreSQL's behavior
  • Split table creation into two batches: tables without function dependencies first, then tables with function dependencies after functions are created
  • Added logic to detect when tables reference newly added functions in defaults, generated expressions, and CHECK constraints

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
ir/normalize.go Added schema parameter to normalizeColumn and normalizeDefaultValue to strip same-schema function qualifiers; updated function and procedure parameter normalization to pass schema context
internal/diff/diff.go Implemented two-phase table creation to handle function dependencies; added tableReferencesNewFunction to detect tables that reference new functions
internal/diff/table.go Removed duplicate schema-agnostic logic for default values, now handled by normalization; added comment noting normalization is done in IR layer
internal/diff/column.go Added comments noting default values are already normalized
testdata/diff/dependency/function_to_table/* Added test data demonstrating correct dependency ordering for function-to-table references

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

generateCreatePoliciesSQL(allDeferredPolicies, targetSchema, collector)

// Create triggers (triggers may depend on functions/procedures)
// Note: We need to create triggers for ALL tables, not just the original d.addedTables
Copy link

Copilot AI Nov 27, 2025

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 both tablesWithoutFunctionDeps and tablesWithFunctionDeps), the code is already correct since d.addedTables contains all of them. Consider clarifying the comment or removing it if it's not accurate.

Suggested change
// Note: We need to create triggers for ALL tables, not just the original d.addedTables

Copilot uses AI. Check for mistakes.
// 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_]*)\(`)
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The regex pattern for matching function names should include $ in the character class to match PostgreSQL's identifier rules. PostgreSQL allows $ in identifiers, and the functionCallRegex in internal/diff/diff.go (line 1197) correctly includes it: [a-z0-9_$].

Update the pattern to:

pattern := regexp.MustCompile(regexp.QuoteMeta(prefix) + `([a-zA-Z_][a-zA-Z0-9_$]*)\(`)

This ensures consistent handling of function names that contain $ characters (e.g., public.my$function()).

Suggested change
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_$]*)\(`)

Copilot uses AI. Check for mistakes.
@tianzhou tianzhou merged commit 7f0cc8c into main Nov 27, 2025
8 checks passed
@tianzhou tianzhou deleted the chore_fix_order branch December 5, 2025 15:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wrong order when using function for default value

1 participant