Add support to list views (#358)

Signed-off-by: Alexis Rico <sferadev@gmail.com>
This commit is contained in:
Alexis Rico 2024-06-19 16:30:17 +02:00 committed by GitHub
parent fca5abdfe2
commit f994a42192
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 87 additions and 4 deletions

View File

@ -26,6 +26,8 @@ type Schema struct {
Name string `json:"name"`
// Tables is a map of virtual table name -> table mapping
Tables map[string]Table `json:"tables"`
// Views is a map of virtual view name -> view mapping
Views map[string]View `json:"views"`
}
type Table struct {
@ -57,6 +59,23 @@ type Table struct {
UniqueConstraints map[string]UniqueConstraint `json:"uniqueConstraints"`
}
type View struct {
// OID for the view
OID string `json:"oid"`
// Name is the actual name in postgres
Name string `json:"name"`
// Optional comment for the view
Comment string `json:"comment"`
// Definition is the SQL definition of the view
Definition string `json:"definition"`
// Columns is a map of virtual column name -> column mapping
Columns map[string]Column `json:"columns"`
}
type Column struct {
// Name is the actual name in postgres
Name string `json:"name"`

View File

@ -94,7 +94,7 @@ STABLE;
CREATE OR REPLACE FUNCTION %[1]s.read_schema(schemaname text) RETURNS jsonb
LANGUAGE plpgsql AS $$
DECLARE
tables jsonb;
result jsonb;
BEGIN
SELECT json_build_object(
'name', schemaname,
@ -255,11 +255,43 @@ BEGIN
WHERE
ns.nspname = schemaname
AND t.relkind IN ('r', 'p') -- tables only (ignores views, materialized views & foreign tables)
),
'views', (
SELECT COALESCE(json_object_agg(v.relname, jsonb_build_object(
'name', v.relname,
'oid', v.oid,
'comment', descr.description,
'definition', pg_get_viewdef(v.oid, true),
'columns', (
SELECT COALESCE(json_object_agg(name, c), '{}'::json) FROM (
SELECT
attr.attname AS name,
format_type(attr.atttypid, attr.atttypmod) AS type,
descr.description AS comment
FROM
pg_attribute AS attr
LEFT JOIN pg_description AS descr ON attr.attrelid = descr.objoid
AND attr.attnum = descr.objsubid
WHERE
attr.attnum > 0
AND NOT attr.attisdropped
AND attr.attrelid = v.oid
ORDER BY
attr.attnum
) c
)
)), '{}'::json) FROM pg_class AS v
INNER JOIN pg_namespace AS ns ON v.relnamespace = ns.oid
LEFT JOIN pg_description AS descr ON v.oid = descr.objoid
AND descr.objsubid = 0
WHERE
ns.nspname = schemaname
AND v.relkind = 'v' -- views only
)
)
INTO tables;
INTO result;
RETURN tables;
RETURN result;
END;
$$;

View File

@ -311,6 +311,7 @@ func TestReadSchema(t *testing.T) {
wantSchema: &schema.Schema{
Name: "public",
Tables: map[string]schema.Table{},
Views: map[string]schema.View{},
},
},
{
@ -329,6 +330,27 @@ func TestReadSchema(t *testing.T) {
ForeignKeys: map[string]schema.ForeignKey{},
},
},
Views: map[string]schema.View{},
},
},
{
name: "one view without columns",
createStmt: "CREATE VIEW public.view1 AS SELECT 1 AS foo",
wantSchema: &schema.Schema{
Name: "public",
Tables: map[string]schema.Table{},
Views: map[string]schema.View{
"view1": {
Name: "view1",
Definition: " SELECT 1 AS foo;",
Columns: map[string]schema.Column{
"foo": {
Name: "foo",
Type: "integer",
},
},
},
},
},
},
{
@ -353,6 +375,7 @@ func TestReadSchema(t *testing.T) {
ForeignKeys: map[string]schema.ForeignKey{},
},
},
Views: map[string]schema.View{},
},
},
{
@ -389,6 +412,7 @@ func TestReadSchema(t *testing.T) {
ForeignKeys: map[string]schema.ForeignKey{},
},
},
Views: map[string]schema.View{},
},
},
{
@ -424,6 +448,7 @@ func TestReadSchema(t *testing.T) {
ForeignKeys: map[string]schema.ForeignKey{},
},
},
Views: map[string]schema.View{},
},
},
{
@ -478,6 +503,7 @@ func TestReadSchema(t *testing.T) {
UniqueConstraints: map[string]schema.UniqueConstraint{},
},
},
Views: map[string]schema.View{},
},
},
{
@ -532,6 +558,7 @@ func TestReadSchema(t *testing.T) {
UniqueConstraints: map[string]schema.UniqueConstraint{},
},
},
Views: map[string]schema.View{},
},
},
{
@ -574,6 +601,7 @@ func TestReadSchema(t *testing.T) {
UniqueConstraints: map[string]schema.UniqueConstraint{},
},
},
Views: map[string]schema.View{},
},
},
{
@ -621,6 +649,7 @@ func TestReadSchema(t *testing.T) {
},
},
},
Views: map[string]schema.View{},
},
},
{
@ -668,6 +697,7 @@ func TestReadSchema(t *testing.T) {
},
},
},
Views: map[string]schema.View{},
},
},
{
@ -703,6 +733,7 @@ func TestReadSchema(t *testing.T) {
UniqueConstraints: map[string]schema.UniqueConstraint{},
},
},
Views: map[string]schema.View{},
},
},
{
@ -727,6 +758,7 @@ func TestReadSchema(t *testing.T) {
UniqueConstraints: map[string]schema.UniqueConstraint{},
},
},
Views: map[string]schema.View{},
},
},
}
@ -745,7 +777,7 @@ func TestReadSchema(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(tt.wantSchema, gotSchema, cmpopts.IgnoreFields(schema.Table{}, "OID")); diff != "" {
if diff := cmp.Diff(tt.wantSchema, gotSchema, cmpopts.IgnoreFields(schema.Table{}, "OID"), cmpopts.IgnoreFields(schema.View{}, "OID")); diff != "" {
t.Errorf("expected schema mismatch (-want +got):\n%s", diff)
}
})