dbt-adapters 1.22.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. dbt/adapters/__about__.py +1 -0
  2. dbt/adapters/__init__.py +8 -0
  3. dbt/adapters/base/README.md +13 -0
  4. dbt/adapters/base/__init__.py +16 -0
  5. dbt/adapters/base/column.py +173 -0
  6. dbt/adapters/base/connections.py +429 -0
  7. dbt/adapters/base/impl.py +2036 -0
  8. dbt/adapters/base/meta.py +150 -0
  9. dbt/adapters/base/plugin.py +32 -0
  10. dbt/adapters/base/query_headers.py +106 -0
  11. dbt/adapters/base/relation.py +648 -0
  12. dbt/adapters/cache.py +521 -0
  13. dbt/adapters/capability.py +63 -0
  14. dbt/adapters/catalogs/__init__.py +14 -0
  15. dbt/adapters/catalogs/_client.py +54 -0
  16. dbt/adapters/catalogs/_constants.py +1 -0
  17. dbt/adapters/catalogs/_exceptions.py +39 -0
  18. dbt/adapters/catalogs/_integration.py +113 -0
  19. dbt/adapters/clients/__init__.py +0 -0
  20. dbt/adapters/clients/jinja.py +24 -0
  21. dbt/adapters/contracts/__init__.py +0 -0
  22. dbt/adapters/contracts/connection.py +229 -0
  23. dbt/adapters/contracts/macros.py +11 -0
  24. dbt/adapters/contracts/relation.py +160 -0
  25. dbt/adapters/events/README.md +51 -0
  26. dbt/adapters/events/__init__.py +0 -0
  27. dbt/adapters/events/adapter_types_pb2.py +2 -0
  28. dbt/adapters/events/base_types.py +36 -0
  29. dbt/adapters/events/logging.py +83 -0
  30. dbt/adapters/events/types.py +436 -0
  31. dbt/adapters/exceptions/__init__.py +40 -0
  32. dbt/adapters/exceptions/alias.py +24 -0
  33. dbt/adapters/exceptions/cache.py +68 -0
  34. dbt/adapters/exceptions/compilation.py +269 -0
  35. dbt/adapters/exceptions/connection.py +16 -0
  36. dbt/adapters/exceptions/database.py +51 -0
  37. dbt/adapters/factory.py +264 -0
  38. dbt/adapters/protocol.py +150 -0
  39. dbt/adapters/py.typed +0 -0
  40. dbt/adapters/record/__init__.py +2 -0
  41. dbt/adapters/record/base.py +291 -0
  42. dbt/adapters/record/cursor/cursor.py +69 -0
  43. dbt/adapters/record/cursor/description.py +37 -0
  44. dbt/adapters/record/cursor/execute.py +39 -0
  45. dbt/adapters/record/cursor/fetchall.py +69 -0
  46. dbt/adapters/record/cursor/fetchmany.py +23 -0
  47. dbt/adapters/record/cursor/fetchone.py +23 -0
  48. dbt/adapters/record/cursor/rowcount.py +23 -0
  49. dbt/adapters/record/handle.py +55 -0
  50. dbt/adapters/record/serialization.py +115 -0
  51. dbt/adapters/reference_keys.py +39 -0
  52. dbt/adapters/relation_configs/README.md +25 -0
  53. dbt/adapters/relation_configs/__init__.py +12 -0
  54. dbt/adapters/relation_configs/config_base.py +46 -0
  55. dbt/adapters/relation_configs/config_change.py +26 -0
  56. dbt/adapters/relation_configs/config_validation.py +57 -0
  57. dbt/adapters/sql/__init__.py +2 -0
  58. dbt/adapters/sql/connections.py +263 -0
  59. dbt/adapters/sql/impl.py +286 -0
  60. dbt/adapters/utils.py +69 -0
  61. dbt/include/__init__.py +3 -0
  62. dbt/include/global_project/__init__.py +4 -0
  63. dbt/include/global_project/dbt_project.yml +7 -0
  64. dbt/include/global_project/docs/overview.md +43 -0
  65. dbt/include/global_project/macros/adapters/apply_grants.sql +167 -0
  66. dbt/include/global_project/macros/adapters/columns.sql +144 -0
  67. dbt/include/global_project/macros/adapters/freshness.sql +32 -0
  68. dbt/include/global_project/macros/adapters/indexes.sql +41 -0
  69. dbt/include/global_project/macros/adapters/metadata.sql +105 -0
  70. dbt/include/global_project/macros/adapters/persist_docs.sql +33 -0
  71. dbt/include/global_project/macros/adapters/relation.sql +84 -0
  72. dbt/include/global_project/macros/adapters/schema.sql +20 -0
  73. dbt/include/global_project/macros/adapters/show.sql +26 -0
  74. dbt/include/global_project/macros/adapters/timestamps.sql +52 -0
  75. dbt/include/global_project/macros/adapters/validate_sql.sql +10 -0
  76. dbt/include/global_project/macros/etc/datetime.sql +62 -0
  77. dbt/include/global_project/macros/etc/statement.sql +52 -0
  78. dbt/include/global_project/macros/generic_test_sql/accepted_values.sql +27 -0
  79. dbt/include/global_project/macros/generic_test_sql/not_null.sql +9 -0
  80. dbt/include/global_project/macros/generic_test_sql/relationships.sql +23 -0
  81. dbt/include/global_project/macros/generic_test_sql/unique.sql +12 -0
  82. dbt/include/global_project/macros/get_custom_name/get_custom_alias.sql +36 -0
  83. dbt/include/global_project/macros/get_custom_name/get_custom_database.sql +32 -0
  84. dbt/include/global_project/macros/get_custom_name/get_custom_schema.sql +60 -0
  85. dbt/include/global_project/macros/materializations/configs.sql +21 -0
  86. dbt/include/global_project/macros/materializations/functions/aggregate.sql +65 -0
  87. dbt/include/global_project/macros/materializations/functions/function.sql +20 -0
  88. dbt/include/global_project/macros/materializations/functions/helpers.sql +20 -0
  89. dbt/include/global_project/macros/materializations/functions/scalar.sql +69 -0
  90. dbt/include/global_project/macros/materializations/hooks.sql +35 -0
  91. dbt/include/global_project/macros/materializations/models/clone/can_clone_table.sql +7 -0
  92. dbt/include/global_project/macros/materializations/models/clone/clone.sql +67 -0
  93. dbt/include/global_project/macros/materializations/models/clone/create_or_replace_clone.sql +7 -0
  94. dbt/include/global_project/macros/materializations/models/incremental/column_helpers.sql +80 -0
  95. dbt/include/global_project/macros/materializations/models/incremental/incremental.sql +99 -0
  96. dbt/include/global_project/macros/materializations/models/incremental/is_incremental.sql +13 -0
  97. dbt/include/global_project/macros/materializations/models/incremental/merge.sql +120 -0
  98. dbt/include/global_project/macros/materializations/models/incremental/on_schema_change.sql +159 -0
  99. dbt/include/global_project/macros/materializations/models/incremental/strategies.sql +92 -0
  100. dbt/include/global_project/macros/materializations/models/materialized_view.sql +121 -0
  101. dbt/include/global_project/macros/materializations/models/table.sql +64 -0
  102. dbt/include/global_project/macros/materializations/models/view.sql +72 -0
  103. dbt/include/global_project/macros/materializations/seeds/helpers.sql +128 -0
  104. dbt/include/global_project/macros/materializations/seeds/seed.sql +60 -0
  105. dbt/include/global_project/macros/materializations/snapshots/helpers.sql +345 -0
  106. dbt/include/global_project/macros/materializations/snapshots/snapshot.sql +109 -0
  107. dbt/include/global_project/macros/materializations/snapshots/snapshot_merge.sql +34 -0
  108. dbt/include/global_project/macros/materializations/snapshots/strategies.sql +184 -0
  109. dbt/include/global_project/macros/materializations/tests/helpers.sql +44 -0
  110. dbt/include/global_project/macros/materializations/tests/test.sql +66 -0
  111. dbt/include/global_project/macros/materializations/tests/unit.sql +40 -0
  112. dbt/include/global_project/macros/materializations/tests/where_subquery.sql +15 -0
  113. dbt/include/global_project/macros/python_model/python.sql +114 -0
  114. dbt/include/global_project/macros/relations/column/columns_spec_ddl.sql +89 -0
  115. dbt/include/global_project/macros/relations/create.sql +23 -0
  116. dbt/include/global_project/macros/relations/create_backup.sql +17 -0
  117. dbt/include/global_project/macros/relations/create_intermediate.sql +17 -0
  118. dbt/include/global_project/macros/relations/drop.sql +41 -0
  119. dbt/include/global_project/macros/relations/drop_backup.sql +14 -0
  120. dbt/include/global_project/macros/relations/materialized_view/alter.sql +55 -0
  121. dbt/include/global_project/macros/relations/materialized_view/create.sql +10 -0
  122. dbt/include/global_project/macros/relations/materialized_view/drop.sql +14 -0
  123. dbt/include/global_project/macros/relations/materialized_view/refresh.sql +9 -0
  124. dbt/include/global_project/macros/relations/materialized_view/rename.sql +10 -0
  125. dbt/include/global_project/macros/relations/materialized_view/replace.sql +10 -0
  126. dbt/include/global_project/macros/relations/rename.sql +35 -0
  127. dbt/include/global_project/macros/relations/rename_intermediate.sql +14 -0
  128. dbt/include/global_project/macros/relations/replace.sql +50 -0
  129. dbt/include/global_project/macros/relations/schema.sql +8 -0
  130. dbt/include/global_project/macros/relations/table/create.sql +60 -0
  131. dbt/include/global_project/macros/relations/table/drop.sql +14 -0
  132. dbt/include/global_project/macros/relations/table/rename.sql +10 -0
  133. dbt/include/global_project/macros/relations/table/replace.sql +10 -0
  134. dbt/include/global_project/macros/relations/view/create.sql +27 -0
  135. dbt/include/global_project/macros/relations/view/drop.sql +14 -0
  136. dbt/include/global_project/macros/relations/view/rename.sql +10 -0
  137. dbt/include/global_project/macros/relations/view/replace.sql +66 -0
  138. dbt/include/global_project/macros/unit_test_sql/get_fixture_sql.sql +107 -0
  139. dbt/include/global_project/macros/utils/any_value.sql +9 -0
  140. dbt/include/global_project/macros/utils/array_append.sql +8 -0
  141. dbt/include/global_project/macros/utils/array_concat.sql +7 -0
  142. dbt/include/global_project/macros/utils/array_construct.sql +12 -0
  143. dbt/include/global_project/macros/utils/bool_or.sql +9 -0
  144. dbt/include/global_project/macros/utils/cast.sql +7 -0
  145. dbt/include/global_project/macros/utils/cast_bool_to_text.sql +7 -0
  146. dbt/include/global_project/macros/utils/concat.sql +7 -0
  147. dbt/include/global_project/macros/utils/data_types.sql +129 -0
  148. dbt/include/global_project/macros/utils/date.sql +10 -0
  149. dbt/include/global_project/macros/utils/date_spine.sql +75 -0
  150. dbt/include/global_project/macros/utils/date_trunc.sql +7 -0
  151. dbt/include/global_project/macros/utils/dateadd.sql +14 -0
  152. dbt/include/global_project/macros/utils/datediff.sql +14 -0
  153. dbt/include/global_project/macros/utils/equals.sql +14 -0
  154. dbt/include/global_project/macros/utils/escape_single_quotes.sql +8 -0
  155. dbt/include/global_project/macros/utils/except.sql +9 -0
  156. dbt/include/global_project/macros/utils/generate_series.sql +53 -0
  157. dbt/include/global_project/macros/utils/hash.sql +7 -0
  158. dbt/include/global_project/macros/utils/intersect.sql +9 -0
  159. dbt/include/global_project/macros/utils/last_day.sql +15 -0
  160. dbt/include/global_project/macros/utils/length.sql +11 -0
  161. dbt/include/global_project/macros/utils/listagg.sql +30 -0
  162. dbt/include/global_project/macros/utils/literal.sql +7 -0
  163. dbt/include/global_project/macros/utils/position.sql +11 -0
  164. dbt/include/global_project/macros/utils/replace.sql +14 -0
  165. dbt/include/global_project/macros/utils/right.sql +12 -0
  166. dbt/include/global_project/macros/utils/safe_cast.sql +9 -0
  167. dbt/include/global_project/macros/utils/split_part.sql +26 -0
  168. dbt/include/global_project/tests/generic/builtin.sql +30 -0
  169. dbt/include/py.typed +0 -0
  170. dbt_adapters-1.22.2.dist-info/METADATA +124 -0
  171. dbt_adapters-1.22.2.dist-info/RECORD +173 -0
  172. dbt_adapters-1.22.2.dist-info/WHEEL +4 -0
  173. dbt_adapters-1.22.2.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,269 @@
1
+ from typing import Any, List, Mapping
2
+
3
+ from dbt_common.exceptions import CompilationError, DbtDatabaseError
4
+ from dbt_common.ui import line_wrap_message
5
+
6
+
7
+ class MissingConfigError(CompilationError):
8
+ def __init__(self, unique_id: str, name: str):
9
+ self.unique_id = unique_id
10
+ self.name = name
11
+ msg = (
12
+ f"Model '{self.unique_id}' does not define a required config parameter '{self.name}'."
13
+ )
14
+ super().__init__(msg=msg)
15
+
16
+
17
+ class MultipleDatabasesNotAllowedError(CompilationError):
18
+ def __init__(self, databases):
19
+ self.databases = databases
20
+ super().__init__(msg=self.get_message())
21
+
22
+ def get_message(self) -> str:
23
+ msg = str(self.databases)
24
+ return msg
25
+
26
+
27
+ class ApproximateMatchError(CompilationError):
28
+ def __init__(self, target, relation):
29
+ self.target = target
30
+ self.relation = relation
31
+ super().__init__(msg=self.get_message())
32
+
33
+ def get_message(self) -> str:
34
+ msg = (
35
+ "When searching for a relation, dbt found an approximate match. "
36
+ "Instead of guessing \nwhich relation to use, dbt will move on. "
37
+ f"Please delete {self.relation}, or rename it to be less ambiguous."
38
+ f"\nSearched for: {self.target}\nFound: {self.relation}"
39
+ )
40
+
41
+ return msg
42
+
43
+
44
+ class SnapshotTargetIncompleteError(CompilationError):
45
+ def __init__(self, extra: List, missing: List):
46
+ self.extra = extra
47
+ self.missing = missing
48
+ super().__init__(msg=self.get_message())
49
+
50
+ def get_message(self) -> str:
51
+ msg = (
52
+ 'Snapshot target has ("{}") but not ("{}") - is it an '
53
+ "unmigrated previous version archive?".format(
54
+ '", "'.join(self.extra), '", "'.join(self.missing)
55
+ )
56
+ )
57
+ return msg
58
+
59
+
60
+ class DuplicateMacroInPackageError(CompilationError):
61
+ def __init__(self, macro, macro_mapping: Mapping):
62
+ self.macro = macro
63
+ self.macro_mapping = macro_mapping
64
+ super().__init__(msg=self.get_message())
65
+
66
+ def get_message(self) -> str:
67
+ other_path = self.macro_mapping[self.macro.unique_id].original_file_path
68
+ # subtract 2 for the "Compilation Error" indent
69
+ # note that the line wrap eats newlines, so if you want newlines,
70
+ # this is the result :(
71
+ msg = line_wrap_message(
72
+ f"""\
73
+ dbt found two macros named "{self.macro.name}" in the project
74
+ "{self.macro.package_name}".
75
+
76
+
77
+ To fix this error, rename or remove one of the following
78
+ macros:
79
+
80
+ - {self.macro.original_file_path}
81
+
82
+ - {other_path}
83
+ """,
84
+ subtract=2,
85
+ )
86
+ return msg
87
+
88
+
89
+ class DuplicateMaterializationNameError(CompilationError):
90
+ def __init__(self, macro, other_macro):
91
+ self.macro = macro
92
+ self.other_macro = other_macro
93
+ super().__init__(msg=self.get_message())
94
+
95
+ def get_message(self) -> str:
96
+ macro_name = self.macro.name
97
+ macro_package_name = self.macro.package_name
98
+ other_package_name = self.other_macro.macro.package_name
99
+
100
+ msg = (
101
+ f"Found two materializations with the name {macro_name} (packages "
102
+ f"{macro_package_name} and {other_package_name}). dbt cannot resolve "
103
+ "this ambiguity"
104
+ )
105
+ return msg
106
+
107
+
108
+ class ColumnTypeMissingError(CompilationError):
109
+ def __init__(self, column_names: List):
110
+ self.column_names = column_names
111
+ super().__init__(msg=self.get_message())
112
+
113
+ def get_message(self) -> str:
114
+ msg = (
115
+ "Contracted models require data_type to be defined for each column. "
116
+ "Please ensure that the column name and data_type are defined within "
117
+ f"the YAML configuration for the {self.column_names} column(s)."
118
+ )
119
+ return msg
120
+
121
+
122
+ class MacroNotFoundError(CompilationError):
123
+ def __init__(self, node, target_macro_id: str):
124
+ self.node = node
125
+ self.target_macro_id = target_macro_id
126
+ msg = f"'{self.node.unique_id}' references macro '{self.target_macro_id}' which is not defined!"
127
+
128
+ super().__init__(msg=msg)
129
+
130
+
131
+ class MissingMaterializationError(CompilationError):
132
+ def __init__(self, materialization, adapter_type):
133
+ self.materialization = materialization
134
+ self.adapter_type = adapter_type
135
+ super().__init__(msg=self.get_message())
136
+
137
+ def get_message(self) -> str:
138
+ valid_types = "'default'"
139
+
140
+ if self.adapter_type != "default":
141
+ valid_types = f"'default' and '{self.adapter_type}'"
142
+
143
+ msg = f"No materialization '{self.materialization}' was found for adapter {self.adapter_type}! (searched types {valid_types})"
144
+ return msg
145
+
146
+
147
+ class SnapshotTargetNotSnapshotTableError(CompilationError):
148
+ def __init__(self, missing: List):
149
+ self.missing = missing
150
+ super().__init__(msg=self.get_message())
151
+
152
+ def get_message(self) -> str:
153
+ missing = '", "'.join(self.missing)
154
+ msg = (
155
+ f'Snapshot target is missing configured columns (missing "{missing}"). '
156
+ "See https://docs.getdbt.com/docs/build/snapshots#snapshot-meta-fields for more information."
157
+ )
158
+ return msg
159
+
160
+
161
+ class NullRelationDropAttemptedError(CompilationError):
162
+ def __init__(self, name: str):
163
+ self.name = name
164
+ self.msg = f"Attempted to drop a null relation for {self.name}"
165
+ super().__init__(msg=self.msg)
166
+
167
+
168
+ class NullRelationCacheAttemptedError(CompilationError):
169
+ def __init__(self, name: str):
170
+ self.name = name
171
+ self.msg = f"Attempted to cache a null relation for {self.name}"
172
+ super().__init__(msg=self.msg)
173
+
174
+
175
+ class RelationTypeNullError(CompilationError):
176
+ def __init__(self, relation):
177
+ self.relation = relation
178
+ self.msg = f"Tried to drop relation {self.relation}, but its type is null."
179
+ super().__init__(msg=self.msg)
180
+
181
+
182
+ class MaterializationNotAvailableError(CompilationError):
183
+ def __init__(self, materialization, adapter_type: str):
184
+ self.materialization = materialization
185
+ self.adapter_type = adapter_type
186
+ super().__init__(msg=self.get_message())
187
+
188
+ def get_message(self) -> str:
189
+ msg = f"Materialization '{self.materialization}' is not available for {self.adapter_type}!"
190
+ return msg
191
+
192
+
193
+ class RelationReturnedMultipleResultsError(CompilationError):
194
+ def __init__(self, kwargs: Mapping[str, Any], matches: List):
195
+ self.kwargs = kwargs
196
+ self.matches = matches
197
+ super().__init__(msg=self.get_message())
198
+
199
+ def get_message(self) -> str:
200
+ msg = (
201
+ "get_relation returned more than one relation with the given args. "
202
+ "Please specify a database or schema to narrow down the result set."
203
+ f"\n{self.kwargs}\n\n{self.matches}"
204
+ )
205
+ return msg
206
+
207
+
208
+ class UnexpectedNonTimestampError(DbtDatabaseError):
209
+ def __init__(self, field_name: str, source, dt: Any):
210
+ self.field_name = field_name
211
+ self.source = source
212
+ self.type_name = type(dt).__name__
213
+ msg = (
214
+ f"Expected a timestamp value when querying field '{self.field_name}' of table "
215
+ f"{self.source} but received value of type '{self.type_name}' instead"
216
+ )
217
+ super().__init__(msg)
218
+
219
+
220
+ class RenameToNoneAttemptedError(CompilationError):
221
+ def __init__(self, src_name: str, dst_name: str, name: str):
222
+ self.src_name = src_name
223
+ self.dst_name = dst_name
224
+ self.name = name
225
+ self.msg = f"Attempted to rename {self.src_name} to {self.dst_name} for {self.name}"
226
+ super().__init__(msg=self.msg)
227
+
228
+
229
+ class QuoteConfigTypeError(CompilationError):
230
+ def __init__(self, quote_config: Any):
231
+ self.quote_config = quote_config
232
+ super().__init__(msg=self.get_message())
233
+
234
+ def get_message(self) -> str:
235
+ msg = (
236
+ 'The seed configuration value of "quote_columns" has an '
237
+ f"invalid type {type(self.quote_config)}"
238
+ )
239
+ return msg
240
+
241
+
242
+ class RelationWrongTypeError(CompilationError):
243
+ def __init__(self, relation, expected_type, model=None):
244
+ self.relation = relation
245
+ self.expected_type = expected_type
246
+ self.model = model
247
+ super().__init__(msg=self.get_message())
248
+
249
+ def get_message(self) -> str:
250
+ msg = (
251
+ f"Trying to create {self.expected_type} {self.relation}, "
252
+ f"but it currently exists as a {self.relation.type}. Either "
253
+ f"drop {self.relation} manually, or run dbt with "
254
+ "`--full-refresh` and dbt will drop it for you."
255
+ )
256
+
257
+ return msg
258
+
259
+
260
+ class InvalidRelationConfigError(CompilationError):
261
+ def __init__(self, relation, config, msg):
262
+ self.relation = relation
263
+ self.config = config
264
+ self.msg = msg
265
+ super().__init__(msg=self.get_message())
266
+
267
+ def get_message(self) -> str:
268
+ msg = f"Invalid relation config: {self.config}"
269
+ return msg
@@ -0,0 +1,16 @@
1
+ from typing import List
2
+
3
+ from dbt_common.exceptions import DbtDatabaseError, DbtRuntimeError
4
+
5
+
6
+ class InvalidConnectionError(DbtRuntimeError):
7
+ def __init__(self, thread_id, known: List) -> None:
8
+ self.thread_id = thread_id
9
+ self.known = known
10
+ super().__init__(
11
+ msg=f"connection never acquired for thread {self.thread_id}, have {self.known}"
12
+ )
13
+
14
+
15
+ class FailedToConnectError(DbtDatabaseError):
16
+ pass
@@ -0,0 +1,51 @@
1
+ from typing import Any
2
+
3
+ from dbt_common.exceptions import CompilationError, NotImplementedError
4
+
5
+
6
+ class UnexpectedDbReferenceError(NotImplementedError):
7
+ def __init__(self, adapter, database, expected):
8
+ self.adapter = adapter
9
+ self.database = database
10
+ self.expected = expected
11
+ super().__init__(msg=self.get_message())
12
+
13
+ def get_message(self) -> str:
14
+ msg = f"Cross-db references not allowed in {self.adapter} ({self.database} vs {self.expected})"
15
+ return msg
16
+
17
+
18
+ class CrossDbReferenceProhibitedError(CompilationError):
19
+ def __init__(self, adapter, exc_msg: str):
20
+ self.adapter = adapter
21
+ self.exc_msg = exc_msg
22
+ super().__init__(msg=self.get_message())
23
+
24
+ def get_message(self) -> str:
25
+ msg = f"Cross-db references not allowed in adapter {self.adapter}: Got {self.exc_msg}"
26
+ return msg
27
+
28
+
29
+ class IndexConfigNotDictError(CompilationError):
30
+ def __init__(self, raw_index: Any):
31
+ self.raw_index = raw_index
32
+ super().__init__(msg=self.get_message())
33
+
34
+ def get_message(self) -> str:
35
+ msg = (
36
+ f"Invalid index config:\n"
37
+ f" Got: {self.raw_index}\n"
38
+ f' Expected a dictionary with at minimum a "columns" key'
39
+ )
40
+ return msg
41
+
42
+
43
+ class IndexConfigError(CompilationError):
44
+ def __init__(self, exc: TypeError):
45
+ self.exc = exc
46
+ super().__init__(msg=self.get_message())
47
+
48
+ def get_message(self) -> str:
49
+ validator_msg = self.validator_error_message(self.exc)
50
+ msg = f"Could not parse index config: {validator_msg}"
51
+ return msg
@@ -0,0 +1,264 @@
1
+ from contextlib import contextmanager
2
+ from importlib import import_module
3
+ from multiprocessing.context import SpawnContext
4
+ from pathlib import Path
5
+ import threading
6
+ import traceback
7
+ from typing import Any, Dict, List, Optional, Set, Type
8
+
9
+ from dbt_common.events.functions import fire_event
10
+ from dbt_common.events.base_types import EventLevel
11
+ from dbt_common.exceptions import DbtInternalError, DbtRuntimeError
12
+ from dbt_common.semver import VersionSpecifier
13
+
14
+ from dbt.adapters.base.plugin import AdapterPlugin
15
+ from dbt.adapters.contracts.connection import AdapterRequiredConfig, Credentials
16
+ from dbt.adapters.events.types import (
17
+ AdapterImportError,
18
+ PluginLoadError,
19
+ AdapterRegistered,
20
+ )
21
+ from dbt.include.global_project import (
22
+ PACKAGE_PATH as GLOBAL_PROJECT_PATH,
23
+ PROJECT_NAME as GLOBAL_PROJECT_NAME,
24
+ )
25
+ from dbt.adapters.protocol import AdapterConfig, AdapterProtocol, RelationProtocol
26
+
27
+
28
+ Adapter = AdapterProtocol
29
+
30
+
31
+ class AdapterContainer:
32
+ def __init__(self) -> None:
33
+ self.lock = threading.Lock()
34
+ self.adapters: Dict[str, Adapter] = {}
35
+ self.plugins: Dict[str, AdapterPlugin] = {}
36
+ # map package names to their include paths
37
+ self.packages: Dict[str, Path] = {
38
+ GLOBAL_PROJECT_NAME: Path(GLOBAL_PROJECT_PATH),
39
+ }
40
+
41
+ def get_plugin_by_name(self, name: str) -> AdapterPlugin:
42
+ with self.lock:
43
+ if name in self.plugins:
44
+ return self.plugins[name]
45
+ names = ", ".join(self.plugins.keys())
46
+
47
+ message = f"Invalid adapter type {name}! Must be one of {names}"
48
+ raise DbtRuntimeError(message)
49
+
50
+ def get_adapter_class_by_name(self, name: str) -> Type[Adapter]:
51
+ plugin = self.get_plugin_by_name(name)
52
+ return plugin.adapter
53
+
54
+ def get_relation_class_by_name(self, name: str) -> Type[RelationProtocol]:
55
+ adapter = self.get_adapter_class_by_name(name)
56
+ return adapter.Relation
57
+
58
+ def get_config_class_by_name(self, name: str) -> Type[AdapterConfig]:
59
+ adapter = self.get_adapter_class_by_name(name)
60
+ return adapter.AdapterSpecificConfigs
61
+
62
+ def load_plugin(self, name: str) -> Type[Credentials]:
63
+ # this doesn't need a lock: in the worst case we'll overwrite packages
64
+ # and adapter_type entries with the same value, as they're all
65
+ # singletons
66
+ try:
67
+ # mypy doesn't think modules have any attributes.
68
+ mod: Any = import_module("." + name, "dbt.adapters")
69
+ except ModuleNotFoundError as exc:
70
+ # if we failed to import the target module in particular, inform
71
+ # the user about it via a runtime error
72
+ if exc.name == "dbt.adapters." + name:
73
+ fire_event(AdapterImportError(exc=str(exc)))
74
+ raise DbtRuntimeError(f"Could not find adapter type {name}!")
75
+ # otherwise, the error had to have come from some underlying
76
+ # library. Log the stack trace.
77
+
78
+ fire_event(PluginLoadError(exc_info=traceback.format_exc()))
79
+ raise
80
+ plugin: AdapterPlugin = mod.Plugin
81
+ plugin_type = plugin.adapter.type()
82
+
83
+ if plugin_type != name:
84
+ raise DbtRuntimeError(
85
+ f"Expected to find adapter with type named {name}, got "
86
+ f"adapter with type {plugin_type}"
87
+ )
88
+
89
+ with self.lock:
90
+ # things do hold the lock to iterate over it so we need it to add
91
+ self.plugins[name] = plugin
92
+
93
+ self.packages[plugin.project_name] = Path(plugin.include_path)
94
+
95
+ for dep in plugin.dependencies:
96
+ self.load_plugin(dep)
97
+
98
+ return plugin.credentials
99
+
100
+ def register_adapter(
101
+ self,
102
+ config: AdapterRequiredConfig,
103
+ mp_context: SpawnContext,
104
+ adapter_registered_log_level: Optional[EventLevel] = EventLevel.INFO,
105
+ ) -> None:
106
+ adapter_name = config.credentials.type
107
+ adapter_type = self.get_adapter_class_by_name(adapter_name)
108
+ adapter_version = self._adapter_version(adapter_name)
109
+ fire_event(
110
+ AdapterRegistered(adapter_name=adapter_name, adapter_version=adapter_version),
111
+ level=adapter_registered_log_level,
112
+ )
113
+ with self.lock:
114
+ if adapter_name in self.adapters:
115
+ # this shouldn't really happen...
116
+ return
117
+
118
+ adapter: Adapter = adapter_type(config, mp_context) # type: ignore
119
+ self.adapters[adapter_name] = adapter
120
+
121
+ def _adapter_version(self, adapter_name: str) -> str:
122
+ try:
123
+ raw_version = import_module(f".{adapter_name}.__about__", "dbt.adapters").version
124
+ except ModuleNotFoundError:
125
+ raw_version = import_module(f".{adapter_name}.__version__", "dbt.adapters").version
126
+ return self._validate_version(raw_version)
127
+
128
+ def _validate_version(self, raw_version: str) -> str:
129
+ return VersionSpecifier.from_version_string(raw_version).to_version_string()
130
+
131
+ def lookup_adapter(self, adapter_name: str) -> Adapter:
132
+ return self.adapters[adapter_name]
133
+
134
+ def reset_adapters(self):
135
+ """Clear the adapters. This is useful for tests, which change configs."""
136
+ with self.lock:
137
+ for adapter in self.adapters.values():
138
+ adapter.cleanup_connections()
139
+ self.adapters.clear()
140
+
141
+ def cleanup_connections(self):
142
+ """Only clean up the adapter connections list without resetting the
143
+ actual adapters.
144
+ """
145
+ with self.lock:
146
+ for adapter in self.adapters.values():
147
+ adapter.cleanup_connections()
148
+
149
+ def get_adapter_plugins(self, name: Optional[str]) -> List[AdapterPlugin]:
150
+ """Iterate over the known adapter plugins. If a name is provided,
151
+ iterate in dependency order over the named plugin and its dependencies.
152
+ """
153
+ if name is None:
154
+ return list(self.plugins.values())
155
+
156
+ plugins: List[AdapterPlugin] = []
157
+ seen: Set[str] = set()
158
+ plugin_names: List[str] = [name]
159
+ while plugin_names:
160
+ plugin_name = plugin_names[0]
161
+ plugin_names = plugin_names[1:]
162
+ try:
163
+ plugin = self.plugins[plugin_name]
164
+ except KeyError:
165
+ raise DbtInternalError(f"No plugin found for {plugin_name}") from None
166
+ plugins.append(plugin)
167
+ seen.add(plugin_name)
168
+ for dep in plugin.dependencies:
169
+ if dep not in seen:
170
+ plugin_names.append(dep)
171
+ return plugins
172
+
173
+ def get_adapter_package_names(self, name: Optional[str]) -> List[str]:
174
+ package_names: List[str] = [p.project_name for p in self.get_adapter_plugins(name)]
175
+ package_names.append(GLOBAL_PROJECT_NAME)
176
+ return package_names
177
+
178
+ def get_include_paths(self, name: Optional[str]) -> List[Path]:
179
+ paths = []
180
+ for package_name in self.get_adapter_package_names(name):
181
+ try:
182
+ path = self.packages[package_name]
183
+ except KeyError:
184
+ raise DbtInternalError(f"No internal package listing found for {package_name}")
185
+ paths.append(path)
186
+ return paths
187
+
188
+ def get_adapter_type_names(self, name: Optional[str]) -> List[str]:
189
+ return [p.adapter.type() for p in self.get_adapter_plugins(name)]
190
+
191
+ def get_adapter_constraint_support(self, name: Optional[str]) -> Dict[str, str]:
192
+ return self.lookup_adapter(name).CONSTRAINT_SUPPORT # type: ignore
193
+
194
+
195
+ FACTORY: AdapterContainer = AdapterContainer()
196
+
197
+
198
+ def register_adapter(
199
+ config: AdapterRequiredConfig,
200
+ mp_context: SpawnContext,
201
+ adapter_registered_log_level: Optional[EventLevel] = EventLevel.INFO,
202
+ ) -> None:
203
+ FACTORY.register_adapter(config, mp_context, adapter_registered_log_level)
204
+
205
+
206
+ def get_adapter(config: AdapterRequiredConfig):
207
+ return FACTORY.lookup_adapter(config.credentials.type)
208
+
209
+
210
+ def get_adapter_by_type(adapter_type):
211
+ return FACTORY.lookup_adapter(adapter_type)
212
+
213
+
214
+ def reset_adapters():
215
+ """Clear the adapters. This is useful for tests, which change configs."""
216
+ FACTORY.reset_adapters()
217
+
218
+
219
+ def cleanup_connections():
220
+ """Only clean up the adapter connections list without resetting the actual
221
+ adapters.
222
+ """
223
+ FACTORY.cleanup_connections()
224
+
225
+
226
+ def get_adapter_class_by_name(name: str) -> Type[AdapterProtocol]:
227
+ return FACTORY.get_adapter_class_by_name(name)
228
+
229
+
230
+ def get_config_class_by_name(name: str) -> Type[AdapterConfig]:
231
+ return FACTORY.get_config_class_by_name(name)
232
+
233
+
234
+ def get_relation_class_by_name(name: str) -> Type[RelationProtocol]:
235
+ return FACTORY.get_relation_class_by_name(name)
236
+
237
+
238
+ def load_plugin(name: str) -> Type[Credentials]:
239
+ return FACTORY.load_plugin(name)
240
+
241
+
242
+ def get_include_paths(name: Optional[str]) -> List[Path]:
243
+ return FACTORY.get_include_paths(name)
244
+
245
+
246
+ def get_adapter_package_names(name: Optional[str]) -> List[str]:
247
+ return FACTORY.get_adapter_package_names(name)
248
+
249
+
250
+ def get_adapter_type_names(name: Optional[str]) -> List[str]:
251
+ return FACTORY.get_adapter_type_names(name)
252
+
253
+
254
+ def get_adapter_constraint_support(name: Optional[str]) -> Dict[str, str]:
255
+ return FACTORY.get_adapter_constraint_support(name)
256
+
257
+
258
+ @contextmanager
259
+ def adapter_management():
260
+ reset_adapters()
261
+ try:
262
+ yield
263
+ finally:
264
+ cleanup_connections()