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.
- dbt/adapters/__about__.py +1 -0
- dbt/adapters/__init__.py +8 -0
- dbt/adapters/base/README.md +13 -0
- dbt/adapters/base/__init__.py +16 -0
- dbt/adapters/base/column.py +173 -0
- dbt/adapters/base/connections.py +429 -0
- dbt/adapters/base/impl.py +2036 -0
- dbt/adapters/base/meta.py +150 -0
- dbt/adapters/base/plugin.py +32 -0
- dbt/adapters/base/query_headers.py +106 -0
- dbt/adapters/base/relation.py +648 -0
- dbt/adapters/cache.py +521 -0
- dbt/adapters/capability.py +63 -0
- dbt/adapters/catalogs/__init__.py +14 -0
- dbt/adapters/catalogs/_client.py +54 -0
- dbt/adapters/catalogs/_constants.py +1 -0
- dbt/adapters/catalogs/_exceptions.py +39 -0
- dbt/adapters/catalogs/_integration.py +113 -0
- dbt/adapters/clients/__init__.py +0 -0
- dbt/adapters/clients/jinja.py +24 -0
- dbt/adapters/contracts/__init__.py +0 -0
- dbt/adapters/contracts/connection.py +229 -0
- dbt/adapters/contracts/macros.py +11 -0
- dbt/adapters/contracts/relation.py +160 -0
- dbt/adapters/events/README.md +51 -0
- dbt/adapters/events/__init__.py +0 -0
- dbt/adapters/events/adapter_types_pb2.py +2 -0
- dbt/adapters/events/base_types.py +36 -0
- dbt/adapters/events/logging.py +83 -0
- dbt/adapters/events/types.py +436 -0
- dbt/adapters/exceptions/__init__.py +40 -0
- dbt/adapters/exceptions/alias.py +24 -0
- dbt/adapters/exceptions/cache.py +68 -0
- dbt/adapters/exceptions/compilation.py +269 -0
- dbt/adapters/exceptions/connection.py +16 -0
- dbt/adapters/exceptions/database.py +51 -0
- dbt/adapters/factory.py +264 -0
- dbt/adapters/protocol.py +150 -0
- dbt/adapters/py.typed +0 -0
- dbt/adapters/record/__init__.py +2 -0
- dbt/adapters/record/base.py +291 -0
- dbt/adapters/record/cursor/cursor.py +69 -0
- dbt/adapters/record/cursor/description.py +37 -0
- dbt/adapters/record/cursor/execute.py +39 -0
- dbt/adapters/record/cursor/fetchall.py +69 -0
- dbt/adapters/record/cursor/fetchmany.py +23 -0
- dbt/adapters/record/cursor/fetchone.py +23 -0
- dbt/adapters/record/cursor/rowcount.py +23 -0
- dbt/adapters/record/handle.py +55 -0
- dbt/adapters/record/serialization.py +115 -0
- dbt/adapters/reference_keys.py +39 -0
- dbt/adapters/relation_configs/README.md +25 -0
- dbt/adapters/relation_configs/__init__.py +12 -0
- dbt/adapters/relation_configs/config_base.py +46 -0
- dbt/adapters/relation_configs/config_change.py +26 -0
- dbt/adapters/relation_configs/config_validation.py +57 -0
- dbt/adapters/sql/__init__.py +2 -0
- dbt/adapters/sql/connections.py +263 -0
- dbt/adapters/sql/impl.py +286 -0
- dbt/adapters/utils.py +69 -0
- dbt/include/__init__.py +3 -0
- dbt/include/global_project/__init__.py +4 -0
- dbt/include/global_project/dbt_project.yml +7 -0
- dbt/include/global_project/docs/overview.md +43 -0
- dbt/include/global_project/macros/adapters/apply_grants.sql +167 -0
- dbt/include/global_project/macros/adapters/columns.sql +144 -0
- dbt/include/global_project/macros/adapters/freshness.sql +32 -0
- dbt/include/global_project/macros/adapters/indexes.sql +41 -0
- dbt/include/global_project/macros/adapters/metadata.sql +105 -0
- dbt/include/global_project/macros/adapters/persist_docs.sql +33 -0
- dbt/include/global_project/macros/adapters/relation.sql +84 -0
- dbt/include/global_project/macros/adapters/schema.sql +20 -0
- dbt/include/global_project/macros/adapters/show.sql +26 -0
- dbt/include/global_project/macros/adapters/timestamps.sql +52 -0
- dbt/include/global_project/macros/adapters/validate_sql.sql +10 -0
- dbt/include/global_project/macros/etc/datetime.sql +62 -0
- dbt/include/global_project/macros/etc/statement.sql +52 -0
- dbt/include/global_project/macros/generic_test_sql/accepted_values.sql +27 -0
- dbt/include/global_project/macros/generic_test_sql/not_null.sql +9 -0
- dbt/include/global_project/macros/generic_test_sql/relationships.sql +23 -0
- dbt/include/global_project/macros/generic_test_sql/unique.sql +12 -0
- dbt/include/global_project/macros/get_custom_name/get_custom_alias.sql +36 -0
- dbt/include/global_project/macros/get_custom_name/get_custom_database.sql +32 -0
- dbt/include/global_project/macros/get_custom_name/get_custom_schema.sql +60 -0
- dbt/include/global_project/macros/materializations/configs.sql +21 -0
- dbt/include/global_project/macros/materializations/functions/aggregate.sql +65 -0
- dbt/include/global_project/macros/materializations/functions/function.sql +20 -0
- dbt/include/global_project/macros/materializations/functions/helpers.sql +20 -0
- dbt/include/global_project/macros/materializations/functions/scalar.sql +69 -0
- dbt/include/global_project/macros/materializations/hooks.sql +35 -0
- dbt/include/global_project/macros/materializations/models/clone/can_clone_table.sql +7 -0
- dbt/include/global_project/macros/materializations/models/clone/clone.sql +67 -0
- dbt/include/global_project/macros/materializations/models/clone/create_or_replace_clone.sql +7 -0
- dbt/include/global_project/macros/materializations/models/incremental/column_helpers.sql +80 -0
- dbt/include/global_project/macros/materializations/models/incremental/incremental.sql +99 -0
- dbt/include/global_project/macros/materializations/models/incremental/is_incremental.sql +13 -0
- dbt/include/global_project/macros/materializations/models/incremental/merge.sql +120 -0
- dbt/include/global_project/macros/materializations/models/incremental/on_schema_change.sql +159 -0
- dbt/include/global_project/macros/materializations/models/incremental/strategies.sql +92 -0
- dbt/include/global_project/macros/materializations/models/materialized_view.sql +121 -0
- dbt/include/global_project/macros/materializations/models/table.sql +64 -0
- dbt/include/global_project/macros/materializations/models/view.sql +72 -0
- dbt/include/global_project/macros/materializations/seeds/helpers.sql +128 -0
- dbt/include/global_project/macros/materializations/seeds/seed.sql +60 -0
- dbt/include/global_project/macros/materializations/snapshots/helpers.sql +345 -0
- dbt/include/global_project/macros/materializations/snapshots/snapshot.sql +109 -0
- dbt/include/global_project/macros/materializations/snapshots/snapshot_merge.sql +34 -0
- dbt/include/global_project/macros/materializations/snapshots/strategies.sql +184 -0
- dbt/include/global_project/macros/materializations/tests/helpers.sql +44 -0
- dbt/include/global_project/macros/materializations/tests/test.sql +66 -0
- dbt/include/global_project/macros/materializations/tests/unit.sql +40 -0
- dbt/include/global_project/macros/materializations/tests/where_subquery.sql +15 -0
- dbt/include/global_project/macros/python_model/python.sql +114 -0
- dbt/include/global_project/macros/relations/column/columns_spec_ddl.sql +89 -0
- dbt/include/global_project/macros/relations/create.sql +23 -0
- dbt/include/global_project/macros/relations/create_backup.sql +17 -0
- dbt/include/global_project/macros/relations/create_intermediate.sql +17 -0
- dbt/include/global_project/macros/relations/drop.sql +41 -0
- dbt/include/global_project/macros/relations/drop_backup.sql +14 -0
- dbt/include/global_project/macros/relations/materialized_view/alter.sql +55 -0
- dbt/include/global_project/macros/relations/materialized_view/create.sql +10 -0
- dbt/include/global_project/macros/relations/materialized_view/drop.sql +14 -0
- dbt/include/global_project/macros/relations/materialized_view/refresh.sql +9 -0
- dbt/include/global_project/macros/relations/materialized_view/rename.sql +10 -0
- dbt/include/global_project/macros/relations/materialized_view/replace.sql +10 -0
- dbt/include/global_project/macros/relations/rename.sql +35 -0
- dbt/include/global_project/macros/relations/rename_intermediate.sql +14 -0
- dbt/include/global_project/macros/relations/replace.sql +50 -0
- dbt/include/global_project/macros/relations/schema.sql +8 -0
- dbt/include/global_project/macros/relations/table/create.sql +60 -0
- dbt/include/global_project/macros/relations/table/drop.sql +14 -0
- dbt/include/global_project/macros/relations/table/rename.sql +10 -0
- dbt/include/global_project/macros/relations/table/replace.sql +10 -0
- dbt/include/global_project/macros/relations/view/create.sql +27 -0
- dbt/include/global_project/macros/relations/view/drop.sql +14 -0
- dbt/include/global_project/macros/relations/view/rename.sql +10 -0
- dbt/include/global_project/macros/relations/view/replace.sql +66 -0
- dbt/include/global_project/macros/unit_test_sql/get_fixture_sql.sql +107 -0
- dbt/include/global_project/macros/utils/any_value.sql +9 -0
- dbt/include/global_project/macros/utils/array_append.sql +8 -0
- dbt/include/global_project/macros/utils/array_concat.sql +7 -0
- dbt/include/global_project/macros/utils/array_construct.sql +12 -0
- dbt/include/global_project/macros/utils/bool_or.sql +9 -0
- dbt/include/global_project/macros/utils/cast.sql +7 -0
- dbt/include/global_project/macros/utils/cast_bool_to_text.sql +7 -0
- dbt/include/global_project/macros/utils/concat.sql +7 -0
- dbt/include/global_project/macros/utils/data_types.sql +129 -0
- dbt/include/global_project/macros/utils/date.sql +10 -0
- dbt/include/global_project/macros/utils/date_spine.sql +75 -0
- dbt/include/global_project/macros/utils/date_trunc.sql +7 -0
- dbt/include/global_project/macros/utils/dateadd.sql +14 -0
- dbt/include/global_project/macros/utils/datediff.sql +14 -0
- dbt/include/global_project/macros/utils/equals.sql +14 -0
- dbt/include/global_project/macros/utils/escape_single_quotes.sql +8 -0
- dbt/include/global_project/macros/utils/except.sql +9 -0
- dbt/include/global_project/macros/utils/generate_series.sql +53 -0
- dbt/include/global_project/macros/utils/hash.sql +7 -0
- dbt/include/global_project/macros/utils/intersect.sql +9 -0
- dbt/include/global_project/macros/utils/last_day.sql +15 -0
- dbt/include/global_project/macros/utils/length.sql +11 -0
- dbt/include/global_project/macros/utils/listagg.sql +30 -0
- dbt/include/global_project/macros/utils/literal.sql +7 -0
- dbt/include/global_project/macros/utils/position.sql +11 -0
- dbt/include/global_project/macros/utils/replace.sql +14 -0
- dbt/include/global_project/macros/utils/right.sql +12 -0
- dbt/include/global_project/macros/utils/safe_cast.sql +9 -0
- dbt/include/global_project/macros/utils/split_part.sql +26 -0
- dbt/include/global_project/tests/generic/builtin.sql +30 -0
- dbt/include/py.typed +0 -0
- dbt_adapters-1.22.2.dist-info/METADATA +124 -0
- dbt_adapters-1.22.2.dist-info/RECORD +173 -0
- dbt_adapters-1.22.2.dist-info/WHEEL +4 -0
- dbt_adapters-1.22.2.dist-info/licenses/LICENSE +201 -0
dbt/adapters/protocol.py
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import (
|
|
3
|
+
Any,
|
|
4
|
+
ContextManager,
|
|
5
|
+
Dict,
|
|
6
|
+
Generic,
|
|
7
|
+
Hashable,
|
|
8
|
+
List,
|
|
9
|
+
Optional,
|
|
10
|
+
Type,
|
|
11
|
+
TypeVar,
|
|
12
|
+
Tuple,
|
|
13
|
+
TYPE_CHECKING,
|
|
14
|
+
)
|
|
15
|
+
from typing_extensions import Protocol
|
|
16
|
+
|
|
17
|
+
from dbt_common.clients.jinja import MacroProtocol
|
|
18
|
+
from dbt_common.contracts.config.base import BaseConfig
|
|
19
|
+
|
|
20
|
+
from dbt.adapters.contracts.connection import (
|
|
21
|
+
AdapterRequiredConfig,
|
|
22
|
+
AdapterResponse,
|
|
23
|
+
Connection,
|
|
24
|
+
)
|
|
25
|
+
from dbt.adapters.contracts.macros import MacroResolverProtocol
|
|
26
|
+
from dbt.adapters.contracts.relation import HasQuoting, Policy, RelationConfig
|
|
27
|
+
|
|
28
|
+
if TYPE_CHECKING:
|
|
29
|
+
import agate
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass
|
|
33
|
+
class AdapterConfig(BaseConfig):
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class ConnectionManagerProtocol(Protocol):
|
|
38
|
+
TYPE: str
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class ColumnProtocol(Protocol):
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
Self = TypeVar("Self", bound="RelationProtocol")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class RelationProtocol(Protocol):
|
|
49
|
+
@classmethod
|
|
50
|
+
def get_default_quote_policy(cls) -> Policy: ...
|
|
51
|
+
|
|
52
|
+
@classmethod
|
|
53
|
+
def create_from(
|
|
54
|
+
cls: Type[Self],
|
|
55
|
+
quoting: HasQuoting,
|
|
56
|
+
relation_config: RelationConfig,
|
|
57
|
+
**kwargs: Any,
|
|
58
|
+
) -> Self: ...
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
AdapterConfig_T = TypeVar("AdapterConfig_T", bound=AdapterConfig)
|
|
62
|
+
ConnectionManager_T = TypeVar("ConnectionManager_T", bound=ConnectionManagerProtocol)
|
|
63
|
+
Relation_T = TypeVar("Relation_T", bound=RelationProtocol)
|
|
64
|
+
Column_T = TypeVar("Column_T", bound=ColumnProtocol)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class MacroContextGeneratorCallable(Protocol):
|
|
68
|
+
def __call__(
|
|
69
|
+
self,
|
|
70
|
+
macro_protocol: MacroProtocol,
|
|
71
|
+
config: AdapterRequiredConfig,
|
|
72
|
+
macro_resolver: MacroResolverProtocol,
|
|
73
|
+
package_name: Optional[str],
|
|
74
|
+
) -> Dict[str, Any]: ...
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# TODO CT-211
|
|
78
|
+
class AdapterProtocol(
|
|
79
|
+
Protocol,
|
|
80
|
+
Generic[
|
|
81
|
+
AdapterConfig_T,
|
|
82
|
+
ConnectionManager_T,
|
|
83
|
+
Relation_T,
|
|
84
|
+
Column_T,
|
|
85
|
+
],
|
|
86
|
+
):
|
|
87
|
+
# N.B. Technically these are ClassVars, but mypy doesn't support putting type vars in a
|
|
88
|
+
# ClassVar due to the restrictiveness of PEP-526
|
|
89
|
+
# See: https://github.com/python/mypy/issues/5144
|
|
90
|
+
AdapterSpecificConfigs: Type[AdapterConfig_T]
|
|
91
|
+
Column: Type[Column_T]
|
|
92
|
+
Relation: Type[Relation_T]
|
|
93
|
+
ConnectionManager: Type[ConnectionManager_T]
|
|
94
|
+
connections: ConnectionManager_T
|
|
95
|
+
|
|
96
|
+
def __init__(self, config: AdapterRequiredConfig) -> None: ...
|
|
97
|
+
|
|
98
|
+
def set_macro_resolver(self, macro_resolver: MacroResolverProtocol) -> None: ...
|
|
99
|
+
|
|
100
|
+
def get_macro_resolver(self) -> Optional[MacroResolverProtocol]: ...
|
|
101
|
+
|
|
102
|
+
def clear_macro_resolver(self) -> None: ...
|
|
103
|
+
|
|
104
|
+
def set_macro_context_generator(
|
|
105
|
+
self,
|
|
106
|
+
macro_context_generator: MacroContextGeneratorCallable,
|
|
107
|
+
) -> None: ...
|
|
108
|
+
|
|
109
|
+
@classmethod
|
|
110
|
+
def type(cls) -> str:
|
|
111
|
+
pass
|
|
112
|
+
|
|
113
|
+
def set_query_header(self, query_header_context: Dict[str, Any]) -> None: ...
|
|
114
|
+
|
|
115
|
+
@staticmethod
|
|
116
|
+
def get_thread_identifier() -> Hashable: ...
|
|
117
|
+
|
|
118
|
+
def get_thread_connection(self) -> Connection: ...
|
|
119
|
+
|
|
120
|
+
def set_thread_connection(self, conn: Connection) -> None: ...
|
|
121
|
+
|
|
122
|
+
def get_if_exists(self) -> Optional[Connection]: ...
|
|
123
|
+
|
|
124
|
+
def clear_thread_connection(self) -> None: ...
|
|
125
|
+
|
|
126
|
+
def clear_transaction(self) -> None: ...
|
|
127
|
+
|
|
128
|
+
def exception_handler(self, sql: str) -> ContextManager: ...
|
|
129
|
+
|
|
130
|
+
def set_connection_name(self, name: Optional[str] = None) -> Connection: ...
|
|
131
|
+
|
|
132
|
+
def cancel_open(self) -> Optional[List[str]]: ...
|
|
133
|
+
|
|
134
|
+
def open(cls, connection: Connection) -> Connection: ...
|
|
135
|
+
|
|
136
|
+
def release(self) -> None: ...
|
|
137
|
+
|
|
138
|
+
def cleanup_all(self) -> None: ...
|
|
139
|
+
|
|
140
|
+
def begin(self) -> None: ...
|
|
141
|
+
|
|
142
|
+
def commit(self) -> None: ...
|
|
143
|
+
|
|
144
|
+
def close(cls, connection: Connection) -> Connection: ...
|
|
145
|
+
|
|
146
|
+
def commit_if_has_connection(self) -> None: ...
|
|
147
|
+
|
|
148
|
+
def execute(
|
|
149
|
+
self, sql: str, auto_begin: bool = False, fetch: bool = False
|
|
150
|
+
) -> Tuple[AdapterResponse, "agate.Table"]: ...
|
dbt/adapters/py.typed
ADDED
|
File without changes
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
"""Implementations of record/replay classes for the base adapter implementation."""
|
|
2
|
+
|
|
3
|
+
import dataclasses
|
|
4
|
+
|
|
5
|
+
from typing import Optional, Tuple, Dict, Any, TYPE_CHECKING, List
|
|
6
|
+
|
|
7
|
+
from dbt.adapters.contracts.connection import AdapterResponse
|
|
8
|
+
from dbt.adapters.record.serialization import serialize_agate_table, serialize_bindings
|
|
9
|
+
from dbt_common.record import Record, Recorder
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from agate import Table
|
|
13
|
+
from dbt.adapters.base.relation import BaseRelation
|
|
14
|
+
from dbt.adapters.base.column import Column as BaseColumn
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclasses.dataclass
|
|
18
|
+
class AdapterExecuteParams:
|
|
19
|
+
thread_id: str
|
|
20
|
+
sql: str
|
|
21
|
+
auto_begin: bool = False
|
|
22
|
+
fetch: bool = False
|
|
23
|
+
limit: Optional[int] = None
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclasses.dataclass
|
|
27
|
+
class AdapterExecuteResult:
|
|
28
|
+
return_val: Tuple[AdapterResponse, "Table"]
|
|
29
|
+
|
|
30
|
+
def _to_dict(self):
|
|
31
|
+
adapter_response = self.return_val[0]
|
|
32
|
+
table = self.return_val[1]
|
|
33
|
+
return {
|
|
34
|
+
"return_val": {
|
|
35
|
+
"adapter_response": adapter_response.to_dict(),
|
|
36
|
+
"table": serialize_agate_table(table),
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
def _from_dict(self, data: Dict[str, Any]):
|
|
41
|
+
# We will need this for replay, but it is not a priority at time of writing.
|
|
42
|
+
raise NotImplementedError()
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@Recorder.register_record_type
|
|
46
|
+
class AdapterExecuteRecord(Record):
|
|
47
|
+
"""Implements record/replay support for the BaseAdapter.execute() method."""
|
|
48
|
+
|
|
49
|
+
params_cls = AdapterExecuteParams
|
|
50
|
+
result_cls = AdapterExecuteResult
|
|
51
|
+
group = "Available"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@dataclasses.dataclass
|
|
55
|
+
class AdapterTestSqlResult:
|
|
56
|
+
return_val: str
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@dataclasses.dataclass
|
|
60
|
+
class AdapterTestSqlParams:
|
|
61
|
+
thread_id: str
|
|
62
|
+
sql: str
|
|
63
|
+
fetch: str
|
|
64
|
+
conn: Any
|
|
65
|
+
|
|
66
|
+
def _to_dict(self):
|
|
67
|
+
return {
|
|
68
|
+
"thread_id": self.thread_id,
|
|
69
|
+
"sql": self.sql,
|
|
70
|
+
"fetch": self.fetch,
|
|
71
|
+
"conn": "conn",
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@Recorder.register_record_type
|
|
76
|
+
class AdapterTestSqlRecord(Record):
|
|
77
|
+
"""Implements record/replay support for the BaseAdapter.execute() method."""
|
|
78
|
+
|
|
79
|
+
params_cls = AdapterTestSqlParams
|
|
80
|
+
result_cls = AdapterTestSqlResult
|
|
81
|
+
group = "Available"
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@dataclasses.dataclass
|
|
85
|
+
class AdapterGetPartitionsMetadataParams:
|
|
86
|
+
thread_id: str
|
|
87
|
+
table: str
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@dataclasses.dataclass
|
|
91
|
+
class AdapterGetPartitionsMetadataResult:
|
|
92
|
+
return_val: tuple["Table"]
|
|
93
|
+
|
|
94
|
+
def _to_dict(self):
|
|
95
|
+
return list(map(serialize_agate_table, self.return_val))
|
|
96
|
+
|
|
97
|
+
def _from_dict(self, data: Dict[str, Any]):
|
|
98
|
+
# We will need this for replay, but it is not a priority at time of writing.
|
|
99
|
+
raise NotImplementedError()
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@Recorder.register_record_type
|
|
103
|
+
class AdapterGetPartitionsMetadataRecord(Record):
|
|
104
|
+
"""Implements record/replay support for the BaseAdapter.get_partitions_metadata() method."""
|
|
105
|
+
|
|
106
|
+
params_cls = AdapterGetPartitionsMetadataParams
|
|
107
|
+
result_cls = AdapterGetPartitionsMetadataResult
|
|
108
|
+
group = "Available"
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
@dataclasses.dataclass
|
|
112
|
+
class AdapterConvertTypeParams:
|
|
113
|
+
thread_id: str
|
|
114
|
+
table: "Table"
|
|
115
|
+
col_idx: int
|
|
116
|
+
|
|
117
|
+
def _to_dict(self):
|
|
118
|
+
return {
|
|
119
|
+
"thread_id": self.thread_id,
|
|
120
|
+
"table": serialize_agate_table(self.table),
|
|
121
|
+
"col_idx": self.col_idx,
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
def _from_dict(self, data: Dict[str, Any]):
|
|
125
|
+
# We will need this for replay, but it is not a priority at time of writing.
|
|
126
|
+
raise NotImplementedError()
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
@dataclasses.dataclass
|
|
130
|
+
class AdapterConvertTypeResult:
|
|
131
|
+
return_val: Optional[str]
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
@Recorder.register_record_type
|
|
135
|
+
class AdapterConvertTypeRecord(Record):
|
|
136
|
+
"""Implements record/replay support for the BaseAdapter.convert_type() method."""
|
|
137
|
+
|
|
138
|
+
params_cls = AdapterConvertTypeParams
|
|
139
|
+
result_cls = AdapterConvertTypeResult
|
|
140
|
+
group = "Available"
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
@dataclasses.dataclass
|
|
144
|
+
class AdapterStandardizeGrantsDictParams:
|
|
145
|
+
thread_id: str
|
|
146
|
+
table: "Table"
|
|
147
|
+
|
|
148
|
+
def _to_dict(self):
|
|
149
|
+
return {"thread_id": self.thread_id, "table": serialize_agate_table(self.table)}
|
|
150
|
+
|
|
151
|
+
def _from_dict(self, data: Dict[str, Any]):
|
|
152
|
+
# We will need this for replay, but it is not a priority at time of writing.
|
|
153
|
+
raise NotImplementedError()
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
@dataclasses.dataclass
|
|
157
|
+
class AdapterStandardizeGrantsDictResult:
|
|
158
|
+
return_val: dict
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
@Recorder.register_record_type
|
|
162
|
+
class AdapterStandardizeGrantsDictRecord(Record):
|
|
163
|
+
params_cls = AdapterStandardizeGrantsDictParams
|
|
164
|
+
result_cls = AdapterStandardizeGrantsDictResult
|
|
165
|
+
group = "Available"
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
@dataclasses.dataclass
|
|
169
|
+
class AdapterAddQueryParams:
|
|
170
|
+
thread_id: str
|
|
171
|
+
sql: str
|
|
172
|
+
auto_begin: bool = True
|
|
173
|
+
bindings: Optional[Any] = None
|
|
174
|
+
abridge_sql_log: bool = False
|
|
175
|
+
|
|
176
|
+
def _to_dict(self):
|
|
177
|
+
return {
|
|
178
|
+
"thread_id": self.thread_id,
|
|
179
|
+
"sql": self.sql,
|
|
180
|
+
"auto_begin": self.auto_begin,
|
|
181
|
+
"bindings": serialize_bindings(self.bindings),
|
|
182
|
+
"abridge_sql_log": self.abridge_sql_log,
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
@dataclasses.dataclass
|
|
187
|
+
class AdapterAddQueryResult:
|
|
188
|
+
return_val: Tuple[str, str]
|
|
189
|
+
|
|
190
|
+
def _to_dict(self):
|
|
191
|
+
return {
|
|
192
|
+
"return_val": {
|
|
193
|
+
"conn": "conn",
|
|
194
|
+
"cursor": "cursor",
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
@Recorder.register_record_type
|
|
200
|
+
class AdapterAddQueryRecord(Record):
|
|
201
|
+
params_cls = AdapterAddQueryParams
|
|
202
|
+
result_cls = AdapterAddQueryResult
|
|
203
|
+
group = "Available"
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
@dataclasses.dataclass
|
|
207
|
+
class AdapterListRelationsWithoutCachingParams:
|
|
208
|
+
thread_id: str
|
|
209
|
+
schema_relation: "BaseRelation"
|
|
210
|
+
|
|
211
|
+
def _to_dict(self):
|
|
212
|
+
from dbt.adapters.record.serialization import serialize_base_relation
|
|
213
|
+
|
|
214
|
+
return {
|
|
215
|
+
"thread_id": self.thread_id,
|
|
216
|
+
"schema_relation": serialize_base_relation(self.schema_relation),
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
def _from_dict(self, data: Dict[str, Any]):
|
|
220
|
+
from dbt.adapters.record.serialization import deserialize_base_relation
|
|
221
|
+
|
|
222
|
+
self.thread_id = data["thread_id"]
|
|
223
|
+
self.schema_relation = deserialize_base_relation(data["schema_relation"])
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
@dataclasses.dataclass
|
|
227
|
+
class AdapterListRelationsWithoutCachingResult:
|
|
228
|
+
return_val: List["BaseRelation"]
|
|
229
|
+
|
|
230
|
+
def _to_dict(self):
|
|
231
|
+
from dbt.adapters.record.serialization import serialize_base_relation_list
|
|
232
|
+
|
|
233
|
+
return {"return_val": serialize_base_relation_list(self.return_val)}
|
|
234
|
+
|
|
235
|
+
def _from_dict(self, data: Dict[str, Any]):
|
|
236
|
+
from dbt.adapters.record.serialization import deserialize_base_relation_list
|
|
237
|
+
|
|
238
|
+
self.return_val = deserialize_base_relation_list(data["return_val"])
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
@Recorder.register_record_type
|
|
242
|
+
class AdapterListRelationsWithoutCachingRecord(Record):
|
|
243
|
+
"""Implements record/replay support for the BaseAdapter.list_relations_without_caching() method."""
|
|
244
|
+
|
|
245
|
+
params_cls = AdapterListRelationsWithoutCachingParams
|
|
246
|
+
result_cls = AdapterListRelationsWithoutCachingResult
|
|
247
|
+
group = "Available"
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
@dataclasses.dataclass
|
|
251
|
+
class AdapterGetColumnsInRelationParams:
|
|
252
|
+
thread_id: str
|
|
253
|
+
relation: "BaseRelation"
|
|
254
|
+
|
|
255
|
+
def _to_dict(self):
|
|
256
|
+
from dbt.adapters.record.serialization import serialize_base_relation
|
|
257
|
+
|
|
258
|
+
return {
|
|
259
|
+
"thread_id": self.thread_id,
|
|
260
|
+
"relation": serialize_base_relation(self.relation),
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
def _from_dict(self, data: Dict[str, Any]):
|
|
264
|
+
from dbt.adapters.record.serialization import deserialize_base_relation
|
|
265
|
+
|
|
266
|
+
self.thread_id = data["thread_id"]
|
|
267
|
+
self.relation = deserialize_base_relation(data["relation"])
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
@dataclasses.dataclass
|
|
271
|
+
class AdapterGetColumnsInRelationResult:
|
|
272
|
+
return_val: List["BaseColumn"]
|
|
273
|
+
|
|
274
|
+
def _to_dict(self):
|
|
275
|
+
from dbt.adapters.record.serialization import serialize_base_column_list
|
|
276
|
+
|
|
277
|
+
return {"return_val": serialize_base_column_list(self.return_val)}
|
|
278
|
+
|
|
279
|
+
def _from_dict(self, data: Dict[str, Any]):
|
|
280
|
+
from dbt.adapters.record.serialization import deserialize_base_column_list
|
|
281
|
+
|
|
282
|
+
self.return_val = deserialize_base_column_list(data["return_val"])
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
@Recorder.register_record_type
|
|
286
|
+
class AdapterGetColumnsInRelationRecord(Record):
|
|
287
|
+
"""Implements record/replay support for the BaseAdapter.get_columns_in_relation() method."""
|
|
288
|
+
|
|
289
|
+
params_cls = AdapterGetColumnsInRelationParams
|
|
290
|
+
result_cls = AdapterGetColumnsInRelationResult
|
|
291
|
+
group = "Available"
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from typing import Any, Optional
|
|
2
|
+
|
|
3
|
+
from dbt_common.events.base_types import BaseEvent
|
|
4
|
+
from dbt_common.events.functions import fire_event
|
|
5
|
+
from dbt_common.events.types import RecordReplayIssue
|
|
6
|
+
from dbt_common.record import record_function
|
|
7
|
+
|
|
8
|
+
from dbt.adapters.contracts.connection import Connection
|
|
9
|
+
from dbt.adapters.record.cursor.description import CursorGetDescriptionRecord
|
|
10
|
+
from dbt.adapters.record.cursor.execute import CursorExecuteRecord
|
|
11
|
+
from dbt.adapters.record.cursor.fetchone import CursorFetchOneRecord
|
|
12
|
+
from dbt.adapters.record.cursor.fetchmany import CursorFetchManyRecord
|
|
13
|
+
from dbt.adapters.record.cursor.fetchall import CursorFetchAllRecord
|
|
14
|
+
from dbt.adapters.record.cursor.rowcount import CursorGetRowCountRecord
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class RecordReplayCursor:
|
|
18
|
+
"""A proxy object used to wrap native database cursors under record/replay
|
|
19
|
+
modes. In record mode, this proxy notes the parameters and return values
|
|
20
|
+
of the methods and properties it implements, which closely match the Python
|
|
21
|
+
DB API 2.0 cursor methods used by many dbt adapters to interact with the
|
|
22
|
+
database or DWH. In replay mode, it mocks out those calls using previously
|
|
23
|
+
recorded calls, so that no interaction with a database actually occurs."""
|
|
24
|
+
|
|
25
|
+
def __init__(self, native_cursor: Any, connection: Connection) -> None:
|
|
26
|
+
self.native_cursor = native_cursor
|
|
27
|
+
self.connection = connection
|
|
28
|
+
|
|
29
|
+
@record_function(CursorExecuteRecord, method=True, id_field_name="connection_name")
|
|
30
|
+
def execute(self, operation, parameters=None) -> None:
|
|
31
|
+
self.native_cursor.execute(operation, parameters)
|
|
32
|
+
|
|
33
|
+
@record_function(CursorFetchOneRecord, method=True, id_field_name="connection_name")
|
|
34
|
+
def fetchone(self) -> Any:
|
|
35
|
+
return self.native_cursor.fetchone()
|
|
36
|
+
|
|
37
|
+
@record_function(CursorFetchManyRecord, method=True, id_field_name="connection_name")
|
|
38
|
+
def fetchmany(self, size: int) -> Any:
|
|
39
|
+
return self.native_cursor.fetchmany(size)
|
|
40
|
+
|
|
41
|
+
@record_function(CursorFetchAllRecord, method=True, id_field_name="connection_name")
|
|
42
|
+
def fetchall(self) -> Any:
|
|
43
|
+
return self.native_cursor.fetchall()
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
def connection_name(self) -> Optional[str]:
|
|
47
|
+
return self.connection.name
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
@record_function(CursorGetRowCountRecord, method=True, id_field_name="connection_name")
|
|
51
|
+
def rowcount(self) -> int:
|
|
52
|
+
return self.native_cursor.rowcount
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
@record_function(CursorGetDescriptionRecord, method=True, id_field_name="connection_name")
|
|
56
|
+
def description(self) -> str:
|
|
57
|
+
return self.native_cursor.description
|
|
58
|
+
|
|
59
|
+
def _fire_event(self, evt: BaseEvent) -> None:
|
|
60
|
+
"""Wraps fire_event for easier test mocking."""
|
|
61
|
+
fire_event(evt)
|
|
62
|
+
|
|
63
|
+
def __getattr__(self, name: str) -> Any:
|
|
64
|
+
self._fire_event(
|
|
65
|
+
RecordReplayIssue(
|
|
66
|
+
msg=f"Unexpected attribute '{name}' accessed on {self.__class__.__name__}"
|
|
67
|
+
)
|
|
68
|
+
)
|
|
69
|
+
return getattr(self.native_cursor, name)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import dataclasses
|
|
2
|
+
from typing import Any, Iterable, Mapping
|
|
3
|
+
|
|
4
|
+
from dbt_common.record import Record, Recorder
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclasses.dataclass
|
|
8
|
+
class CursorGetDescriptionParams:
|
|
9
|
+
connection_name: str
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclasses.dataclass
|
|
13
|
+
class CursorGetDescriptionResult:
|
|
14
|
+
columns: Iterable[Any]
|
|
15
|
+
|
|
16
|
+
def _to_dict(self) -> Any:
|
|
17
|
+
column_dicts = []
|
|
18
|
+
for c in self.columns:
|
|
19
|
+
# This captures the mandatory column information, but we might need
|
|
20
|
+
# more for some adapters.
|
|
21
|
+
# See https://peps.python.org/pep-0249/#description
|
|
22
|
+
column_dicts.append((c[0], c[1]))
|
|
23
|
+
|
|
24
|
+
return {"columns": column_dicts}
|
|
25
|
+
|
|
26
|
+
@classmethod
|
|
27
|
+
def _from_dict(cls, dct: Mapping) -> "CursorGetDescriptionResult":
|
|
28
|
+
return CursorGetDescriptionResult(columns=dct["columns"])
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@Recorder.register_record_type
|
|
32
|
+
class CursorGetDescriptionRecord(Record):
|
|
33
|
+
"""Implements record/replay support for the cursor.description property."""
|
|
34
|
+
|
|
35
|
+
params_cls = CursorGetDescriptionParams
|
|
36
|
+
result_cls = CursorGetDescriptionResult
|
|
37
|
+
group = "Database"
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import dataclasses
|
|
2
|
+
from typing import Any, Iterable, Union, Mapping, Optional
|
|
3
|
+
|
|
4
|
+
from dbt.adapters.record.cursor.fetchall import CursorFetchAllResult
|
|
5
|
+
from dbt_common.record import Record, Recorder
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclasses.dataclass
|
|
9
|
+
class CursorExecuteParams:
|
|
10
|
+
connection_name: str
|
|
11
|
+
operation: str
|
|
12
|
+
parameters: Optional[Union[Iterable[Any], Mapping[str, Any]]] = None
|
|
13
|
+
|
|
14
|
+
def _to_dict(self):
|
|
15
|
+
p = self.parameters
|
|
16
|
+
if isinstance(self.parameters, dict):
|
|
17
|
+
p = {(k, CursorFetchAllResult._process_value(v)) for k, v in self.parameters.items()}
|
|
18
|
+
elif isinstance(self.parameters, list) or isinstance(self.parameters, tuple):
|
|
19
|
+
p = [CursorFetchAllResult._process_value(v) for v in self.parameters]
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
"connection_name": self.connection_name,
|
|
23
|
+
"operation": self.operation,
|
|
24
|
+
"parameters": p,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
def _from_dict(cls, data):
|
|
28
|
+
# NOTE: This will be needed for replay, but is not needed at time
|
|
29
|
+
# of writing.
|
|
30
|
+
raise NotImplementedError()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@Recorder.register_record_type
|
|
34
|
+
class CursorExecuteRecord(Record):
|
|
35
|
+
"""Implements record/replay support for the cursor.execute() method."""
|
|
36
|
+
|
|
37
|
+
params_cls = CursorExecuteParams
|
|
38
|
+
result_cls = None
|
|
39
|
+
group = "Database"
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import dataclasses
|
|
2
|
+
import datetime
|
|
3
|
+
import decimal
|
|
4
|
+
from typing import Any, Dict, List, Mapping
|
|
5
|
+
|
|
6
|
+
from dbt_common.record import Record, Recorder
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclasses.dataclass
|
|
10
|
+
class CursorFetchAllParams:
|
|
11
|
+
connection_name: str
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclasses.dataclass
|
|
15
|
+
class CursorFetchAllResult:
|
|
16
|
+
results: List[Any]
|
|
17
|
+
|
|
18
|
+
def _to_dict(self) -> Dict[str, Any]:
|
|
19
|
+
processed_results = []
|
|
20
|
+
for result in self.results:
|
|
21
|
+
result = tuple(map(self._process_value, result))
|
|
22
|
+
processed_results.append(result)
|
|
23
|
+
|
|
24
|
+
return {"results": processed_results}
|
|
25
|
+
|
|
26
|
+
@classmethod
|
|
27
|
+
def _from_dict(cls, dct: Mapping) -> "CursorFetchAllResult":
|
|
28
|
+
unprocessed_results = []
|
|
29
|
+
for result in dct["results"]:
|
|
30
|
+
result = tuple(map(cls._unprocess_value, result))
|
|
31
|
+
unprocessed_results.append(result)
|
|
32
|
+
|
|
33
|
+
return CursorFetchAllResult(unprocessed_results)
|
|
34
|
+
|
|
35
|
+
@classmethod
|
|
36
|
+
def _process_value(cls, value: Any) -> Any:
|
|
37
|
+
if type(value) is datetime.date:
|
|
38
|
+
return {"type": "date", "value": value.isoformat()}
|
|
39
|
+
elif type(value) is datetime.datetime:
|
|
40
|
+
return {"type": "datetime", "value": value.isoformat()}
|
|
41
|
+
elif type(value) is decimal.Decimal:
|
|
42
|
+
return float(value)
|
|
43
|
+
else:
|
|
44
|
+
return value
|
|
45
|
+
|
|
46
|
+
@classmethod
|
|
47
|
+
def _unprocess_value(cls, value: Any) -> Any:
|
|
48
|
+
if type(value) is dict:
|
|
49
|
+
value_type = value.get("type")
|
|
50
|
+
if value_type == "date":
|
|
51
|
+
date_string = value.get("value")
|
|
52
|
+
assert isinstance(date_string, str)
|
|
53
|
+
return datetime.date.fromisoformat(date_string)
|
|
54
|
+
elif value_type == "datetime":
|
|
55
|
+
date_string = value.get("value")
|
|
56
|
+
assert isinstance(date_string, str)
|
|
57
|
+
return datetime.datetime.fromisoformat(date_string)
|
|
58
|
+
return value
|
|
59
|
+
else:
|
|
60
|
+
return value
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@Recorder.register_record_type
|
|
64
|
+
class CursorFetchAllRecord(Record):
|
|
65
|
+
"""Implements record/replay support for the cursor.fetchall() method."""
|
|
66
|
+
|
|
67
|
+
params_cls = CursorFetchAllParams
|
|
68
|
+
result_cls = CursorFetchAllResult
|
|
69
|
+
group = "Database"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import dataclasses
|
|
2
|
+
from typing import Any, List
|
|
3
|
+
|
|
4
|
+
from dbt_common.record import Record, Recorder
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclasses.dataclass
|
|
8
|
+
class CursorFetchManyParams:
|
|
9
|
+
connection_name: str
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclasses.dataclass
|
|
13
|
+
class CursorFetchManyResult:
|
|
14
|
+
results: List[Any]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@Recorder.register_record_type
|
|
18
|
+
class CursorFetchManyRecord(Record):
|
|
19
|
+
"""Implements record/replay support for the cursor.fetchmany() method."""
|
|
20
|
+
|
|
21
|
+
params_cls = CursorFetchManyParams
|
|
22
|
+
result_cls = CursorFetchManyResult
|
|
23
|
+
group = "Database"
|