Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Postgres: support materialized views #214

Merged
merged 5 commits into from
Apr 25, 2020
Merged

Postgres: support materialized views #214

merged 5 commits into from
Apr 25, 2020

Conversation

mjpieters
Copy link
Contributor

This is my proposed implementation for #212

I first refactored the way the postgres driver queries for table information. The original code relied mostly on information_schema (the SQL-92 standard system catalog) but added in joins against the Postgres-specific pg_catalog tables, my version uses just the pg_catalog system catalog. There isn't really much point in using information_schema unless you are trying to write standards-compliant SQL that is easily portable to other databases. Materialized view information is largely absent from the infromation_schema catalog and so not refactoring would have lead to quite convoluted joins or union queries.

This is mostly resulting in the exact same output, except for array types and domains. The information_schema view on attribute types is quite limited and make it quite hard to get proper type info out, but this is not the case when using the pg_attribute and pg_type tables in conjunction with the format_type() function.

For arrays, rather than array you now get the contained type and dimensions, so text[] (array of strings), double precision[][] (array of arrays of floating point values), etc. For domains (which are 'reusable constraints', attaching the constraint to a type rather than to a column or table), instead of the constrained type, you get the domain name. IIRC, for certain variable-length types you'll now get the table-specific length as well where that wasn't reflected before.

I've retained the preference for varchar(...) over character varying(...), however, applying that change at the query level.

Further changes in this refactor:

  • use tableOid everywhere to fetch information about the table, rather than the schema and table name strings.
  • fetch comments inline when fetching tables and columns.
  • use pq.Array() to fetch column names in constraints and indexes, avoiding potential parsing issues with column names containing the delimiter.

I've run the full test suite with this, as well as manually tested this agains AWS Redshift (see separate issue I found that's independent of this pull request, #213).

- only use pg_catalog tables and functions (faster, cleaner)
- fetch comments in-line with tables and columns
- use the oid to get related info (columns, indexes, etc.)
- use format_type() to produce the correct type name. This means arrays now show up as their contained type with `[]`, and custom domains are reflected correctly.

This is groundwork laid to enable other relationship types (e.g. MATERIALIZED VIEW)
@k1LoW k1LoW added the enhancement New feature or request label Apr 25, 2020
@k1LoW
Copy link
Owner

k1LoW commented Apr 25, 2020

@mjpieters THANK YOU FOR YOUR GREAT COMMIT !!! 🚀 🚀 🚀
I'll check it !!!

Copy link
Owner

@k1LoW k1LoW left a comment

Choose a reason for hiding this comment

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

I think I've learned a lot !!!!! Thank you !!!!

WHEN cls.relkind = 'f' THEN 'FOREIGN TABLE'
END AS table_type,
ns.nspname AS table_schema,
descr.description AS table_comment
Copy link
Owner

Choose a reason for hiding this comment

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

👍

@@ -146,12 +130,12 @@ AND table_schema = $3;
if err != nil {
return errors.WithStack(err)
}
table.Def = fmt.Sprintf("CREATE VIEW %s AS (\n%s\n)", tableName, strings.TrimRight(tableDef.String, ";"))
table.Def = fmt.Sprintf("CREATE %s %s AS (\n%s\n)", tableType, tableName, strings.TrimRight(tableDef.String, ";"))
Copy link
Owner

Choose a reason for hiding this comment

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

👍

pg_get_expr(def.adbin, def.adrelid) AS column_default,
NOT (attr.attnotnull OR tp.typtype = 'd' AND tp.typnotnull) AS is_nullable,
CASE
WHEN attr.atttypid::regtype = ANY(ARRAY['character varying'::regtype, 'character varying[]'::regtype]) THEN
Copy link
Owner

Choose a reason for hiding this comment

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

fmfm.

Copy link
Contributor Author

@mjpieters mjpieters Apr 25, 2020

Choose a reason for hiding this comment

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

Yeah, I’m not that happy with this part, it’ll fail for a multi-dimensional array. Looking over pg_type again this should really be a test for

    attr.atttypid::regtype = 'character varying'::regtype
OR (tp.typarray != 0 AND tp.typarray::regtype = 'character varying'::regtype)

Or, just drop the whole notion of transforming character varying to varchar altogether ;-)

@k1LoW k1LoW merged commit a18d041 into k1LoW:master Apr 25, 2020
@mjpieters mjpieters deleted the postgres_refactor branch April 25, 2020 10:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants