Skip to content

Conversation

@timwaizenegger
Copy link
Collaborator

@timwaizenegger timwaizenegger commented Sep 17, 2025

Add pg_get_domain_ddl() function to reconstruct CREATE DOMAIN statements
This patch introduces a new system function pg_get_domain_ddl() that
reconstructs the CREATE DOMAIN statement for a given domain. The function
takes a regtype parameter and returns the complete DDL statement including
the domain name, base type, default value, and all associated constraints.

The function follows the same pattern as other DDL reconstruction functions
like pg_get_functiondef() and pg_get_constraintdef(), providing a
decompiled reconstruction rather than the original command text.

Key features:

  • Supports domains with default values
  • Includes all domain constraints (CHECK, NOT NULL)
  • Properly quotes identifiers and schema names
  • Handles complex constraint expressions

A new documentation section "Get Object DDL Functions" has been created
to group DDL reconstruction functions, starting with pg_get_domain_ddl().
This provides a foundation for future DDL functions for other object types.

Comprehensive regression tests are included covering various domain
configurations.

Reference: PG-151
Author: Florin Irion florin.irion@enterprisedb.com
Author: Tim Waizenegger tim.waizenegger@enterprisedb.com

@irionr irionr force-pushed the dev/PG-151 branch 2 times, most recently from 318042f to add4e62 Compare September 18, 2025 16:57
@irionr irionr marked this pull request as ready for review September 18, 2025 16:58
@irionr irionr changed the title create ddl for domain Add pg_get_domain_ddl() function to reconstruct CREATE DOMAIN statements Sep 18, 2025
# horology depends on date, time, timetz, timestamp, timestamptz, interval
# ----------
test: geometry horology tstypes regex type_sanity opr_sanity misc_sanity comments expressions unicode xid mvcc database stats_import
test: geometry horology tstypes regex type_sanity opr_sanity misc_sanity comments expressions unicode xid mvcc database stats_import object_ddl
Copy link
Owner

Choose a reason for hiding this comment

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

Not sure about this one...

* struct
*/
defaultDatum = SysCacheGetAttr(TYPEOID, typeTuple,
Anum_pg_type_typdefault, &defaultIsNull);

Choose a reason for hiding this comment

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

If I read the comments in pg_type.h right, the default value is in typdefaultbin, not in typdefault, so it looks like this shouldn't actually work. Maybe your test cases for defaults are all too simplistic, or maybe the comments in pg_type.h are wrong.

Copy link
Owner

Choose a reason for hiding this comment

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

  • typdefaultbin: stores the nodeToString representation of a default expression
  • typdefault: stores the human-readable version of the default expression represented by typdefaultbin

So for our case it's better to use the human-readable version. no?
I think the comments are correct but also our implementation, no?

here is an example:

# CREATE DOMAIN public.regress_seq_domain2 AS integer 
     DEFAULT nextval('regress_test_seq'::regclass) 
     CONSTRAINT "regress_Constraint B" CHECK (VALUE > 10) 
     CONSTRAINT "regress_ConstraintC" CHECK (VALUE <> 55);

# SELECT pg_get_domain_ddl('regress_seq_domain2');
                                                                                                pg_get_domain_ddl
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 CREATE DOMAIN public.regress_seq_domain2 AS integer DEFAULT nextval('regress_test_seq') CONSTRAINT "regress_Constraint B" CHECK (VALUE > 10) CONSTRAINT "regress_ConstraintC" CHECK (VALUE <> 55);
 
 
 # SELECT typdefaultbin, typdefault 
      FROM  pg_catalog.pg_type 
      WHERE typname ='regress_seq_domain2'  ;
-[ RECORD 1 ]-+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
typdefaultbin | {FUNCEXPR :funcid 480 :funcresulttype 23 :funcretset false :funcvariadic false :funcformat 2 :funccollid 0 :inputcollid 0 :args ({FUNCEXPR :funcid 1574 :funcresulttype 20 :funcretset false :funcvariadic false :funcformat 0 :funccollid 0 :inputcollid 0 :args ({CONST :consttype 2205 :consttypmod -1 :constcollid 0 :constlen 4 :constbyval true :constisnull false :location -1 :constvalue 4 [ 89 64 0 0 0 0 0 0 ]}) :location -1}) :location -1}
typdefault    | nextval('regress_test_seq'::regclass)

@alvherre Please explain a bit more if I didn't understand correctly.

Choose a reason for hiding this comment

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

yeah, you should be able to use get_rule_expr() to obtain a human-readable expression when given the typdefaultbin. My concern here is that it is possible that domains exist where the default is not stored in the human-readable form. I don't know how can that happen TBH. Maybe an example to try is to create a domain that defaults to a sequence, and later rename the sequence. I think the typdefault would continue to use the old name, which would be bogus.

Copy link
Owner

Choose a reason for hiding this comment

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

Indeed, it was not using the renamed sequence!
Thanks for catching it.
Adjusted.

@irionr irionr force-pushed the dev/PG-151 branch 3 times, most recently from 626a35c to 5c9941f Compare September 22, 2025 09:40
@irionr irionr requested a review from alvherre September 24, 2025 07:55
@irionr irionr force-pushed the dev/PG-151 branch 2 times, most recently from 9306094 to 63631fa Compare October 3, 2025 16:43
irionr pushed a commit that referenced this pull request Oct 14, 2025
truncate_useless_pathkeys() seems to have neglected to account for
PathKeys that might be useful for WindowClause evaluation.  Modify it so
that it properly accounts for that.

Making this work required adjusting two things:

1. Change from checking query_pathkeys to check sort_pathkeys instead.
2. Add explicit check for window_pathkeys

For #1, query_pathkeys gets set in standard_qp_callback() according to the
sort order requirements for the first operation to be applied after the
join planner is finished, so this changes depending on which upper
planner operations a particular query needs.  If the query has window
functions and no GROUP BY, then query_pathkeys gets set to
window_pathkeys.  Before this change, this meant PathKeys useful for the
ORDER BY were not accounted for in queries with window functions.

Because of #1, #2 is now required so that we explicitly check to ensure
we don't truncate away PathKeys useful for window functions.

Author: David Rowley <dgrowleyml@gmail.com>
Discussion: https://postgr.es/m/CAApHDvrj3HTKmXoLMbUjTO=_MNMxM=cnuCSyBKidAVibmYPnrg@mail.gmail.com
@irionr irionr force-pushed the dev/PG-151 branch 3 times, most recently from 8ce6547 to 592c5d6 Compare October 24, 2025 13:48
This patch introduces a new system function pg_get_domain_ddl() that
reconstructs the CREATE DOMAIN statement for a given domain. The function
takes a regtype parameter and returns the complete DDL statement including
the domain name, base type, default value, and all associated constraints.

The function follows the same pattern as other DDL reconstruction functions
like pg_get_functiondef() and pg_get_constraintdef(), providing a
decompiled reconstruction rather than the original command text.

Key features:
* Supports domains with default values
* Includes all domain constraints (CHECK, NOT NULL)
* NOT VALID constraint are handled with an extra ALTER command.
* Properly quotes identifiers and schema names
* Handles complex constraint expressions

A new documentation section "Get Object DDL Functions" has been created
to group DDL reconstruction functions, starting with pg_get_domain_ddl().
This provides a foundation for future DDL functions for other object types.

Comprehensive regression tests are included covering various domain
configurations.

Reference: PG-151
Author: Florin Irion <florin.irion@enterprisedb.com>
Author: Tim Waizenegger <tim.waizenegger@enterprisedb.com>
Reviewed-by: Álvaro Herrera alvherre@alvh.no-ip.org
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.

5 participants