18
18
from typing import Optional
19
19
20
20
import psycopg2
21
+ from psycopg2 .extensions import string_types
21
22
from psycopg2 .extras import register_uuid
22
23
23
24
import dbt .adapters .postgres .connections
31
32
32
33
logger = AdapterLogger ("Materialize" )
33
34
35
+ # NOTE(morsapaes): registering the UUID type produces nicer error messages when
36
+ # data contracts fail on a UUID type. See comment in the
37
+ # `data_type_code_to_name` method for details. We may be able to remove this
38
+ # when dbt-core#8900 lands.
39
+ register_uuid ()
40
+
34
41
# Override the psycopg2 connect function in order to inject Materialize-specific
35
42
# session parameter defaults.
36
43
#
@@ -50,10 +57,6 @@ def connect(**kwargs):
50
57
]
51
58
kwargs ["options" ] = " " .join (options )
52
59
53
- # NOTE(morsapaes): work around dbt-core #8353 while #8900 doesn't land to
54
- # unblock users using UUID types.
55
- register_uuid ()
56
-
57
60
return _connect (** kwargs )
58
61
59
62
@@ -135,6 +138,40 @@ def cancel(self, connection):
135
138
# probably bad, re-raise it
136
139
raise
137
140
141
+ # NOTE(benesch): this is a backport, with modifications, of dbt-core#8887.
142
+ # TODO(benesch): consider removing this when v1.8 ships with this code.
143
+ @classmethod
144
+ def data_type_code_to_name (cls , type_code : int ) -> str :
145
+ if type_code in string_types :
146
+ return string_types [type_code ].name
147
+ else :
148
+ # The type is unknown to psycopg2, so make up a unique name based on
149
+ # the type's OID. Here are the consequences for data contracts that
150
+ # reference unknown types:
151
+ #
152
+ # * Data contracts that are valid work flawlessly. Take the
153
+ # `mz_timestamp` type, for example, which is unknown to psycopg2
154
+ # because it is a special Materialize type. It has OID 16552. If
155
+ # the data contract specifies a column of type `mz_timestamp`
156
+ # and the model's column is actually of type `mz_timestamp`, the
157
+ # contract will validate successfully and the user will have no
158
+ # idea that under the hood dbt validated these two strings
159
+ # against one another:
160
+ #
161
+ # expected: `custom type unknown to dbt (OID 16552)`
162
+ # actual: `custom type unknown to dbt (OID 16552)`
163
+ #
164
+ # * Data contracts that are invalid produce an ugly error message.
165
+ # If the contract specifies the `timestamp` type but the model's
166
+ # column is actually of type `mz_timestamp`, dbt will complain
167
+ # with an error message like "expected type DATETIME, got custom
168
+ # type unknown to dbt (OID 16552)".
169
+ #
170
+ # Still, this is much better than the built-in behavior with dbt
171
+ # 1.7, which is to raise "Unhandled error while executing:
172
+ # 16552". See dbt-core#8353 for details.
173
+ return f"custom type unknown to dbt (OID { type_code } )"
174
+
138
175
# Disable transactions. Materialize transactions do not support arbitrary
139
176
# queries in transactions and therefore many of dbt's internal macros
140
177
# produce invalid transactions.
0 commit comments