From 9586b448f3501572d2d6044c3e22784c4c10ebee Mon Sep 17 00:00:00 2001 From: Alexis Rico Date: Mon, 5 Feb 2024 16:35:22 +0100 Subject: [PATCH] Update `state` command to avoid returning nulls (#274) --- pkg/state/state.go | 24 +++++++++--------- pkg/state/state_test.go | 55 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 13 deletions(-) diff --git a/pkg/state/state.go b/pkg/state/state.go index 16d927dc..7d207bbc 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -99,12 +99,12 @@ BEGIN SELECT json_build_object( 'name', schemaname, 'tables', ( - SELECT json_object_agg(t.relname, jsonb_build_object( + SELECT COALESCE(json_object_agg(t.relname, jsonb_build_object( 'name', t.relname, 'oid', t.oid, 'comment', descr.description, 'columns', ( - SELECT json_object_agg(name, c) FROM ( + SELECT COALESCE(json_object_agg(name, c), '{}'::json) FROM ( SELECT attr.attname AS name, pg_get_expr(def.adbin, def.adrelid) AS default, @@ -157,7 +157,7 @@ BEGIN ) c ), 'primaryKey', ( - SELECT json_agg(pg_attribute.attname) AS primary_key_columns + SELECT COALESCE(json_agg(pg_attribute.attname), '[]'::json) AS primary_key_columns FROM pg_index, pg_attribute WHERE indrelid = t.oid AND @@ -167,11 +167,11 @@ BEGIN AND indisprimary ), 'indexes', ( - SELECT json_object_agg(ix_details.indexrelid::regclass, json_build_object( + SELECT COALESCE(json_object_agg(ix_details.indexrelid::regclass, json_build_object( 'name', ix_details.indexrelid::regclass, 'unique', ix_details.indisunique, 'columns', ix_details.columns - )) + )), '{}'::json) FROM ( SELECT pi.indexrelid, @@ -184,11 +184,11 @@ BEGIN ) as ix_details ), 'checkConstraints', ( - SELECT json_object_agg(cc_details.conname, json_build_object( + SELECT COALESCE(json_object_agg(cc_details.conname, json_build_object( 'name', cc_details.conname, 'columns', cc_details.columns, 'definition', cc_details.definition - )) + )), '{}'::json) FROM ( SELECT cc_constraint.conname, @@ -202,10 +202,10 @@ BEGIN ) AS cc_details ), 'uniqueConstraints', ( - SELECT json_object_agg(uc_details.conname, json_build_object( + SELECT COALESCE(json_object_agg(uc_details.conname, json_build_object( 'name', uc_details.conname, 'columns', uc_details.columns - )) + )), '{}'::json) FROM ( SELECT uc_constraint.conname, @@ -219,12 +219,12 @@ BEGIN ) AS uc_details ), 'foreignKeys', ( - SELECT json_object_agg(fk_details.conname, json_build_object( + SELECT COALESCE(json_object_agg(fk_details.conname, json_build_object( 'name', fk_details.conname, 'columns', fk_details.columns, 'referencedTable', fk_details.referencedTable, 'referencedColumns', fk_details.referencedColumns - )) + )), '{}'::json) FROM ( SELECT fk_constraint.conname, @@ -240,7 +240,7 @@ BEGIN GROUP BY fk_constraint.conname, fk_cl.relname ) AS fk_details ) - )) FROM pg_class AS t + )), '{}'::json) FROM pg_class AS t INNER JOIN pg_namespace AS ns ON t.relnamespace = ns.oid LEFT JOIN pg_description AS descr ON t.oid = descr.objoid AND descr.objsubid = 0 diff --git a/pkg/state/state_test.go b/pkg/state/state_test.go index 70fb6d8a..574835c4 100644 --- a/pkg/state/state_test.go +++ b/pkg/state/state_test.go @@ -126,7 +126,33 @@ func TestReadSchema(t *testing.T) { wantSchema *schema.Schema }{ { - name: "one table", + name: "empty schema", + createStmt: "", + wantSchema: &schema.Schema{ + Name: "public", + Tables: map[string]schema.Table{}, + }, + }, + { + name: "one table without columns", + createStmt: "CREATE TABLE public.table1 ()", + wantSchema: &schema.Schema{ + Name: "public", + Tables: map[string]schema.Table{ + "table1": { + Name: "table1", + Columns: map[string]schema.Column{}, + PrimaryKey: []string{}, + Indexes: map[string]schema.Index{}, + CheckConstraints: map[string]schema.CheckConstraint{}, + UniqueConstraints: map[string]schema.UniqueConstraint{}, + ForeignKeys: map[string]schema.ForeignKey{}, + }, + }, + }, + }, + { + name: "one table with columns", createStmt: "CREATE TABLE public.table1 (id int)", wantSchema: &schema.Schema{ Name: "public", @@ -140,6 +166,11 @@ func TestReadSchema(t *testing.T) { Nullable: true, }, }, + PrimaryKey: []string{}, + Indexes: map[string]schema.Index{}, + CheckConstraints: map[string]schema.CheckConstraint{}, + UniqueConstraints: map[string]schema.UniqueConstraint{}, + ForeignKeys: map[string]schema.ForeignKey{}, }, }, }, @@ -160,6 +191,7 @@ func TestReadSchema(t *testing.T) { Unique: true, }, }, + PrimaryKey: []string{}, Indexes: map[string]schema.Index{ "id_unique": { Name: "id_unique", @@ -167,12 +199,14 @@ func TestReadSchema(t *testing.T) { Columns: []string{"id"}, }, }, + CheckConstraints: map[string]schema.CheckConstraint{}, UniqueConstraints: map[string]schema.UniqueConstraint{ "id_unique": { Name: "id_unique", Columns: []string{"id"}, }, }, + ForeignKeys: map[string]schema.ForeignKey{}, }, }, }, @@ -197,6 +231,7 @@ func TestReadSchema(t *testing.T) { Nullable: true, }, }, + PrimaryKey: []string{}, Indexes: map[string]schema.Index{ "idx_name": { Name: "idx_name", @@ -204,6 +239,9 @@ func TestReadSchema(t *testing.T) { Columns: []string{"name"}, }, }, + CheckConstraints: map[string]schema.CheckConstraint{}, + UniqueConstraints: map[string]schema.UniqueConstraint{}, + ForeignKeys: map[string]schema.ForeignKey{}, }, }, }, @@ -232,6 +270,9 @@ func TestReadSchema(t *testing.T) { Columns: []string{"id"}, }, }, + CheckConstraints: map[string]schema.CheckConstraint{}, + UniqueConstraints: map[string]schema.UniqueConstraint{}, + ForeignKeys: map[string]schema.ForeignKey{}, }, "table2": { Name: "table2", @@ -242,6 +283,8 @@ func TestReadSchema(t *testing.T) { Nullable: false, }, }, + PrimaryKey: []string{}, + Indexes: map[string]schema.Index{}, ForeignKeys: map[string]schema.ForeignKey{ "fk_fkey": { Name: "fk_fkey", @@ -250,6 +293,8 @@ func TestReadSchema(t *testing.T) { ReferencedColumns: []string{"id"}, }, }, + CheckConstraints: map[string]schema.CheckConstraint{}, + UniqueConstraints: map[string]schema.UniqueConstraint{}, }, }, }, @@ -283,6 +328,7 @@ func TestReadSchema(t *testing.T) { Columns: []string{"id"}, }, }, + ForeignKeys: map[string]schema.ForeignKey{}, CheckConstraints: map[string]schema.CheckConstraint{ "age_check": { Name: "age_check", @@ -290,6 +336,7 @@ func TestReadSchema(t *testing.T) { Definition: "CHECK ((age > 18))", }, }, + UniqueConstraints: map[string]schema.UniqueConstraint{}, }, }, }, @@ -329,6 +376,8 @@ func TestReadSchema(t *testing.T) { Columns: []string{"name"}, }, }, + ForeignKeys: map[string]schema.ForeignKey{}, + CheckConstraints: map[string]schema.CheckConstraint{}, UniqueConstraints: map[string]schema.UniqueConstraint{ "name_unique": { Name: "name_unique", @@ -359,6 +408,7 @@ func TestReadSchema(t *testing.T) { Nullable: true, }, }, + PrimaryKey: []string{}, Indexes: map[string]schema.Index{ "idx_ab": { Name: "idx_ab", @@ -366,6 +416,9 @@ func TestReadSchema(t *testing.T) { Columns: []string{"a", "b"}, }, }, + ForeignKeys: map[string]schema.ForeignKey{}, + CheckConstraints: map[string]schema.CheckConstraint{}, + UniqueConstraints: map[string]schema.UniqueConstraint{}, }, }, },