Skip to content

Commit

Permalink
Add CHECK constraints to pgroll's internal schema representation (#…
Browse files Browse the repository at this point in the history
…241)

Add knowledge of `CHECK` constraints defined on a table to `pgroll`'s
internal schema representation

Part of #105
  • Loading branch information
andrew-farries committed Jan 18, 2024
1 parent 7b5fafd commit 70a7c8e
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 0 deletions.
14 changes: 14 additions & 0 deletions pkg/schema/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ type Table struct {

// ForeignKeys is a map of all foreign keys defined on the table
ForeignKeys map[string]ForeignKey `json:"foreignKeys"`

// CheckConstraints is a map of all check constraints defined on the table
CheckConstraints map[string]CheckConstraint `json:"checkConstraints"`
}

type Column struct {
Expand Down Expand Up @@ -85,6 +88,17 @@ type ForeignKey struct {
ReferencedColumns []string `json:"referencedColumns"`
}

type CheckConstraint struct {
// Name is the name of the check constraint in postgres
Name string `json:"name"`

// The columns that the check constraint is defined on
Columns []string `json:"columns"`

// The definition of the check constraint
Definition string `json:"definition"`
}

func (s *Schema) GetTable(name string) *Table {
if s.Tables == nil {
return nil
Expand Down
18 changes: 18 additions & 0 deletions pkg/state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,24 @@ BEGIN
FROM pg_index pi
WHERE pi.indrelid = t.oid::regclass
),
'checkConstraints', (
SELECT json_object_agg(cc_details.conname, json_build_object(
'name', cc_details.conname,
'columns', cc_details.columns,
'definition', cc_details.definition
))
FROM (
SELECT
cc_constraint.conname,
array_agg(cc_attr.attname ORDER BY cc_constraint.conkey::int[]) AS columns,
pg_get_constraintdef(cc_constraint.oid) AS definition
FROM pg_constraint AS cc_constraint
INNER JOIN pg_attribute cc_attr ON cc_attr.attrelid = cc_constraint.conrelid AND cc_attr.attnum = ANY(cc_constraint.conkey)
WHERE cc_constraint.conrelid = t.oid
AND cc_constraint.contype = 'c'
GROUP BY cc_constraint.oid
) AS cc_details
),
'foreignKeys', (
SELECT json_object_agg(fk_details.conname, json_build_object(
'name', fk_details.conname,
Expand Down
38 changes: 38 additions & 0 deletions pkg/state/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,44 @@ func TestReadSchema(t *testing.T) {
},
},
},
{
name: "check constraint",
createStmt: "CREATE TABLE public.table1 (id int PRIMARY KEY, age INTEGER, CONSTRAINT age_check CHECK (age > 18));",
wantSchema: &schema.Schema{
Name: "public",
Tables: map[string]schema.Table{
"table1": {
Name: "table1",
Columns: map[string]schema.Column{
"id": {
Name: "id",
Type: "integer",
Nullable: false,
Unique: true,
},
"age": {
Name: "age",
Type: "integer",
Nullable: true,
},
},
PrimaryKey: []string{"id"},
Indexes: map[string]schema.Index{
"table1_pkey": {
Name: "table1_pkey",
},
},
CheckConstraints: map[string]schema.CheckConstraint{
"age_check": {
Name: "age_check",
Columns: []string{"age"},
Definition: "CHECK ((age > 18))",
},
},
},
},
},
},
}

// init the state
Expand Down

0 comments on commit 70a7c8e

Please sign in to comment.