diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ea8db2d870..b07f86adcb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### Under the hood - Added 3 more adapter methods that the new dbt-adapter-test suite can use for testing. ([#2492](https://github.com/fishtown-analytics/dbt/issues/2492), [#2721](https://github.com/fishtown-analytics/dbt/pull/2721)) +- Check for Postgres relation names longer than 63 and throw exception. ([#2197](https://github.com/fishtown-analytics/dbt/issues/2197)) ## dbt 0.18.0rc1 (August 19, 2020) diff --git a/plugins/postgres/dbt/adapters/postgres/__init__.py b/plugins/postgres/dbt/adapters/postgres/__init__.py index 7a3b1bd48ed..04f0e8cda53 100644 --- a/plugins/postgres/dbt/adapters/postgres/__init__.py +++ b/plugins/postgres/dbt/adapters/postgres/__init__.py @@ -2,6 +2,7 @@ from dbt.adapters.postgres.connections import PostgresConnectionManager # noqa from dbt.adapters.postgres.connections import PostgresCredentials from dbt.adapters.postgres.relation import PostgresColumn # noqa +from dbt.adapters.postgres.relation import PostgresRelation # noqa: F401 from dbt.adapters.postgres.impl import PostgresAdapter from dbt.adapters.base import AdapterPlugin diff --git a/plugins/postgres/dbt/adapters/postgres/impl.py b/plugins/postgres/dbt/adapters/postgres/impl.py index fc22f78e452..c03dafefe14 100644 --- a/plugins/postgres/dbt/adapters/postgres/impl.py +++ b/plugins/postgres/dbt/adapters/postgres/impl.py @@ -5,6 +5,7 @@ from dbt.adapters.sql import SQLAdapter from dbt.adapters.postgres import PostgresConnectionManager from dbt.adapters.postgres import PostgresColumn +from dbt.adapters.postgres import PostgresRelation import dbt.exceptions @@ -18,6 +19,7 @@ class PostgresConfig(AdapterConfig): class PostgresAdapter(SQLAdapter): + Relation = PostgresRelation ConnectionManager = PostgresConnectionManager Column = PostgresColumn diff --git a/plugins/postgres/dbt/adapters/postgres/relation.py b/plugins/postgres/dbt/adapters/postgres/relation.py index 3b864ce440f..2040337ac48 100644 --- a/plugins/postgres/dbt/adapters/postgres/relation.py +++ b/plugins/postgres/dbt/adapters/postgres/relation.py @@ -1,4 +1,23 @@ from dbt.adapters.base import Column +from dataclasses import dataclass +from dbt.adapters.base.relation import BaseRelation +from dbt.exceptions import RuntimeException + + +@dataclass(frozen=True, eq=False, repr=False) +class PostgresRelation(BaseRelation): + def __post_init__(self): + # Check for length of Postgres table/view names. + # Check self.type to exclude test relation identifiers + if (self.identifier is not None and self.type is not None and + len(self.identifier) > self.relation_max_name_length()): + raise RuntimeException( + f"Relation name '{self.identifier}' " + f"is longer than {self.relation_max_name_length()} characters" + ) + + def relation_max_name_length(self): + return 63 class PostgresColumn(Column): diff --git a/plugins/redshift/dbt/adapters/redshift/__init__.py b/plugins/redshift/dbt/adapters/redshift/__init__.py index 003c3ba9a9d..f8059e1168b 100644 --- a/plugins/redshift/dbt/adapters/redshift/__init__.py +++ b/plugins/redshift/dbt/adapters/redshift/__init__.py @@ -1,6 +1,7 @@ from dbt.adapters.redshift.connections import RedshiftConnectionManager # noqa from dbt.adapters.redshift.connections import RedshiftCredentials from dbt.adapters.redshift.relation import RedshiftColumn # noqa +from dbt.adapters.redshift.relation import RedshiftRelation # noqa: F401 from dbt.adapters.redshift.impl import RedshiftAdapter diff --git a/plugins/redshift/dbt/adapters/redshift/impl.py b/plugins/redshift/dbt/adapters/redshift/impl.py index da8588df3f2..65ea6bbeda6 100644 --- a/plugins/redshift/dbt/adapters/redshift/impl.py +++ b/plugins/redshift/dbt/adapters/redshift/impl.py @@ -4,6 +4,7 @@ from dbt.adapters.postgres import PostgresAdapter from dbt.adapters.redshift import RedshiftConnectionManager from dbt.adapters.redshift import RedshiftColumn +from dbt.adapters.redshift import RedshiftRelation from dbt.logger import GLOBAL_LOGGER as logger # noqa @@ -16,6 +17,7 @@ class RedshiftConfig(AdapterConfig): class RedshiftAdapter(PostgresAdapter): + Relation = RedshiftRelation ConnectionManager = RedshiftConnectionManager Column = RedshiftColumn diff --git a/plugins/redshift/dbt/adapters/redshift/relation.py b/plugins/redshift/dbt/adapters/redshift/relation.py index 4d48746a650..ac3ecdb9534 100644 --- a/plugins/redshift/dbt/adapters/redshift/relation.py +++ b/plugins/redshift/dbt/adapters/redshift/relation.py @@ -1,4 +1,14 @@ from dbt.adapters.base import Column +from dataclasses import dataclass +from dbt.adapters.postgres.relation import PostgresRelation + + +@dataclass(frozen=True, eq=False, repr=False) +class RedshiftRelation(PostgresRelation): + # Override the method in the Postgres Relation + # because Redshift allows longer names + def relation_max_name_length(self): + return 127 class RedshiftColumn(Column): diff --git a/test/integration/063_relation_name_tests/data/seed.csv b/test/integration/063_relation_name_tests/data/seed.csv new file mode 100644 index 00000000000..d4a1e26eed2 --- /dev/null +++ b/test/integration/063_relation_name_tests/data/seed.csv @@ -0,0 +1,4 @@ +col_A,col_B +1,2 +3,4 +5,6 diff --git a/test/integration/063_relation_name_tests/models/long_table_name_with_enough_characters_to_fail_when_tmp_name.sql b/test/integration/063_relation_name_tests/models/long_table_name_with_enough_characters_to_fail_when_tmp_name.sql new file mode 100644 index 00000000000..31dc91a8d51 --- /dev/null +++ b/test/integration/063_relation_name_tests/models/long_table_name_with_enough_characters_to_fail_when_tmp_name.sql @@ -0,0 +1,2 @@ + +select * from {{ this.schema }}.seed diff --git a/test/integration/063_relation_name_tests/test_relation_name.py b/test/integration/063_relation_name_tests/test_relation_name.py new file mode 100644 index 00000000000..39513f12b3e --- /dev/null +++ b/test/integration/063_relation_name_tests/test_relation_name.py @@ -0,0 +1,34 @@ +from test.integration.base import DBTIntegrationTest, use_profile +import dbt.exceptions + +class TestAdapterDDL(DBTIntegrationTest): + + def setUp(self): + DBTIntegrationTest.setUp(self) + self.run_dbt(['seed']) + + @property + def schema(self): + return "adapter_ddl_063" + + @property + def models(self): + return "models" + + @property + def project_config(self): + return { + 'config-version': 2, + 'seeds': { + 'quote_columns': False, + }, + } + + @use_profile('postgres') + def test_postgres_long_name_fails(self): + self.run_dbt(['run'],expect_pass=False) + + @use_profile('redshift') + def test_redshift_long_name_succeeds(self): + self.run_dbt(['run'],expect_pass=True) +