dbt-sqlserver 1.9.0__tar.gz → 1.9.1rc1__tar.gz
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-sqlserver-1.9.0 → dbt_sqlserver-1.9.1rc1}/PKG-INFO +43 -7
- dbt-sqlserver-1.9.0/dbt_sqlserver.egg-info/PKG-INFO → dbt_sqlserver-1.9.1rc1/README.md +27 -28
- {dbt-sqlserver-1.9.0 → dbt_sqlserver-1.9.1rc1}/dbt/adapters/sqlserver/__init__.py +1 -1
- dbt_sqlserver-1.9.1rc1/dbt/adapters/sqlserver/__version__.py +1 -0
- dbt_sqlserver-1.9.1rc1/dbt/adapters/sqlserver/sqlserver_adapter.py +290 -0
- dbt_sqlserver-1.9.1rc1/dbt/adapters/sqlserver/sqlserver_column.py +98 -0
- dbt_sqlserver-1.9.1rc1/dbt/adapters/sqlserver/sqlserver_configs.py +9 -0
- dbt_sqlserver-1.9.1rc1/dbt/adapters/sqlserver/sqlserver_connections.py +673 -0
- dbt_sqlserver-1.9.1rc1/dbt/adapters/sqlserver/sqlserver_credentials.py +74 -0
- {dbt-sqlserver-1.9.0 → dbt_sqlserver-1.9.1rc1}/dbt/adapters/sqlserver/sqlserver_relation.py +2 -2
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/adapters/apply_grants.sql +71 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/adapters/columns.sql +101 -0
- {dbt-sqlserver-1.9.0/dbt/include/sqlserver/macros/adapter → dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/adapters}/indexes.sql +68 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/adapters/metadata.sql +112 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/adapters/relation.sql +55 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/adapters/schema.sql +70 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/adapters/show.sql +12 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/materializations/models/incremental/incremental_strategies.sql +11 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/materializations/models/incremental/merge.sql +85 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/materializations/models/table/clone.sql +4 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/materializations/models/table/columns_spec_ddl.sql +30 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/materializations/models/unit_test/unit_test_create_table_as.sql +58 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/materializations/models/view/create_view_as.sql +12 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/materializations/snapshots/helpers.sql +189 -0
- {dbt-sqlserver-1.9.0/dbt/include/sqlserver/macros/materializations/snapshot → dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/materializations/snapshots}/snapshot.sql +33 -34
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/materializations/snapshots/snapshot_merge.sql +30 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/materializations/snapshots/strategies.sql +5 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/materializations/unit_tests.sql +47 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/utils/any_value.sql +5 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/utils/array_construct.sql +3 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/utils/cast_bool_to_text.sql +7 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/utils/concat.sql +7 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/utils/date_trunc.sql +3 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/utils/dateadd.sql +9 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/utils/get_tables_by_pattern.sql +12 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/utils/hash.sql +3 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/utils/last_day.sql +13 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/utils/length.sql +5 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/utils/listagg.sql +8 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/utils/position.sql +8 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/utils/safe_cast.sql +3 -0
- dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/utils/timestamps.sql +8 -0
- dbt-sqlserver-1.9.0/README.md → dbt_sqlserver-1.9.1rc1/dbt_sqlserver.egg-info/PKG-INFO +64 -0
- dbt_sqlserver-1.9.1rc1/dbt_sqlserver.egg-info/SOURCES.txt +65 -0
- {dbt-sqlserver-1.9.0 → dbt_sqlserver-1.9.1rc1}/dbt_sqlserver.egg-info/requires.txt +0 -1
- {dbt-sqlserver-1.9.0 → dbt_sqlserver-1.9.1rc1}/setup.py +1 -3
- dbt-sqlserver-1.9.0/dbt/adapters/sqlserver/__version__.py +0 -1
- dbt-sqlserver-1.9.0/dbt/adapters/sqlserver/sqlserver_adapter.py +0 -67
- dbt-sqlserver-1.9.0/dbt/adapters/sqlserver/sqlserver_column.py +0 -22
- dbt-sqlserver-1.9.0/dbt/adapters/sqlserver/sqlserver_configs.py +0 -8
- dbt-sqlserver-1.9.0/dbt/adapters/sqlserver/sqlserver_connections.py +0 -160
- dbt-sqlserver-1.9.0/dbt/adapters/sqlserver/sqlserver_credentials.py +0 -22
- dbt-sqlserver-1.9.0/dbt/include/sqlserver/macros/adapter/columns.sql +0 -50
- dbt-sqlserver-1.9.0/dbt/include/sqlserver/macros/adapter/metadata.sql +0 -8
- dbt-sqlserver-1.9.0/dbt/include/sqlserver/macros/adapter/relation.sql +0 -5
- dbt-sqlserver-1.9.0/dbt/include/sqlserver/macros/adapter/schemas.sql +0 -5
- dbt-sqlserver-1.9.0/dbt/include/sqlserver/macros/materializations/models/incremental/merge.sql +0 -31
- dbt-sqlserver-1.9.0/dbt/include/sqlserver/macros/materializations/snapshot/helpers.sql +0 -35
- dbt-sqlserver-1.9.0/dbt/include/sqlserver/macros/materializations/snapshot/snapshot_merge.sql +0 -19
- dbt-sqlserver-1.9.0/dbt/include/sqlserver/macros/materializations/unit_tests.sql +0 -47
- dbt-sqlserver-1.9.0/dbt/include/sqlserver/macros/readme.md +0 -54
- dbt-sqlserver-1.9.0/dbt_sqlserver.egg-info/SOURCES.txt +0 -44
- {dbt-sqlserver-1.9.0 → dbt_sqlserver-1.9.1rc1}/LICENSE +0 -0
- {dbt-sqlserver-1.9.0 → dbt_sqlserver-1.9.1rc1}/MANIFEST.in +0 -0
- {dbt-sqlserver-1.9.0 → dbt_sqlserver-1.9.1rc1}/dbt/adapters/sqlserver/relation_configs/__init__.py +0 -0
- {dbt-sqlserver-1.9.0 → dbt_sqlserver-1.9.1rc1}/dbt/adapters/sqlserver/relation_configs/policies.py +0 -0
- {dbt-sqlserver-1.9.0 → dbt_sqlserver-1.9.1rc1}/dbt/include/sqlserver/__init__.py +0 -0
- {dbt-sqlserver-1.9.0 → dbt_sqlserver-1.9.1rc1}/dbt/include/sqlserver/dbt_project.yml +0 -0
- {dbt-sqlserver-1.9.0/dbt/include/sqlserver/macros/adapter → dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/adapters}/catalog.sql +0 -0
- {dbt-sqlserver-1.9.0/dbt/include/sqlserver/macros/adapter → dbt_sqlserver-1.9.1rc1/dbt/include/sqlserver/macros/adapters}/validate_sql.sql +0 -0
- {dbt-sqlserver-1.9.0 → dbt_sqlserver-1.9.1rc1}/dbt/include/sqlserver/macros/materializations/models/incremental/incremental.sql +0 -0
- {dbt-sqlserver-1.9.0 → dbt_sqlserver-1.9.1rc1}/dbt/include/sqlserver/macros/materializations/models/table/table.sql +0 -0
- {dbt-sqlserver-1.9.0 → dbt_sqlserver-1.9.1rc1}/dbt/include/sqlserver/macros/materializations/models/view/view.sql +0 -0
- {dbt-sqlserver-1.9.0 → dbt_sqlserver-1.9.1rc1}/dbt/include/sqlserver/macros/materializations/tests.sql +0 -0
- {dbt-sqlserver-1.9.0 → dbt_sqlserver-1.9.1rc1}/dbt/include/sqlserver/macros/relations/seeds/helpers.sql +0 -0
- {dbt-sqlserver-1.9.0 → dbt_sqlserver-1.9.1rc1}/dbt/include/sqlserver/macros/relations/table/clone.sql +0 -0
- {dbt-sqlserver-1.9.0 → dbt_sqlserver-1.9.1rc1}/dbt/include/sqlserver/macros/relations/table/create.sql +0 -0
- {dbt-sqlserver-1.9.0 → dbt_sqlserver-1.9.1rc1}/dbt/include/sqlserver/macros/relations/views/create.sql +0 -0
- {dbt-sqlserver-1.9.0 → dbt_sqlserver-1.9.1rc1}/dbt/include/sqlserver/macros/utils/split_part.sql +0 -0
- {dbt-sqlserver-1.9.0 → dbt_sqlserver-1.9.1rc1}/dbt/include/sqlserver/profile_template.yml +0 -0
- {dbt-sqlserver-1.9.0 → dbt_sqlserver-1.9.1rc1}/dbt_sqlserver.egg-info/dependency_links.txt +0 -0
- {dbt-sqlserver-1.9.0 → dbt_sqlserver-1.9.1rc1}/dbt_sqlserver.egg-info/top_level.txt +0 -0
- {dbt-sqlserver-1.9.0 → dbt_sqlserver-1.9.1rc1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: dbt-sqlserver
|
|
3
|
-
Version: 1.9.
|
|
3
|
+
Version: 1.9.1rc1
|
|
4
4
|
Summary: A Microsoft SQL Server adapter plugin for dbt
|
|
5
5
|
Home-page: https://github.com/dbt-msft/dbt-sqlserver
|
|
6
6
|
Author: Mikael Ene, Anders Swanson, Sam Debruyn, Cor Zuurmond, Cody Scott
|
|
@@ -9,20 +9,31 @@ Project-URL: Setup & configuration, https://docs.getdbt.com/reference/warehouse-
|
|
|
9
9
|
Project-URL: Documentation & usage, https://docs.getdbt.com/reference/resource-configs/mssql-configs
|
|
10
10
|
Project-URL: Changelog, https://github.com/dbt-msft/dbt-sqlserver/blob/master/CHANGELOG.md
|
|
11
11
|
Project-URL: Issue Tracker, https://github.com/dbt-msft/dbt-sqlserver/issues
|
|
12
|
-
Platform: UNKNOWN
|
|
13
12
|
Classifier: Development Status :: 5 - Production/Stable
|
|
14
13
|
Classifier: License :: OSI Approved :: MIT License
|
|
15
14
|
Classifier: Operating System :: Microsoft :: Windows
|
|
16
15
|
Classifier: Operating System :: MacOS :: MacOS X
|
|
17
16
|
Classifier: Operating System :: POSIX :: Linux
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
20
17
|
Classifier: Programming Language :: Python :: 3.9
|
|
21
18
|
Classifier: Programming Language :: Python :: 3.10
|
|
22
19
|
Classifier: Programming Language :: Python :: 3.11
|
|
23
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
22
|
Description-Content-Type: text/markdown
|
|
25
23
|
License-File: LICENSE
|
|
24
|
+
Requires-Dist: dbt-core<2.0,>=1.9.0
|
|
25
|
+
Requires-Dist: dbt-common<2.0,>=1.0
|
|
26
|
+
Requires-Dist: dbt-adapters<2.0,>=1.11.0
|
|
27
|
+
Dynamic: author
|
|
28
|
+
Dynamic: classifier
|
|
29
|
+
Dynamic: description
|
|
30
|
+
Dynamic: description-content-type
|
|
31
|
+
Dynamic: home-page
|
|
32
|
+
Dynamic: license
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
Dynamic: project-url
|
|
35
|
+
Dynamic: requires-dist
|
|
36
|
+
Dynamic: summary
|
|
26
37
|
|
|
27
38
|
# dbt-sqlserver
|
|
28
39
|
|
|
@@ -75,6 +86,33 @@ pip install -U --pre dbt-sqlserver
|
|
|
75
86
|
|
|
76
87
|
See [the changelog](CHANGELOG.md)
|
|
77
88
|
|
|
89
|
+
## Configuration
|
|
90
|
+
|
|
91
|
+
### Flags
|
|
92
|
+
|
|
93
|
+
- `dbt_sqlserver_use_default_schema_concat`: *(default: `false`)* Controls schema name generation when a [custom schema](https://docs.getdbt.com/docs/build/custom-schemas) is set on a model.
|
|
94
|
+
|
|
95
|
+
| Flag value | `custom_schema_name` | Result |
|
|
96
|
+
|---|---|---|
|
|
97
|
+
| `false` (default, legacy) | *(none)* | `target.schema` |
|
|
98
|
+
| `false` (default, legacy) | `"reporting"` | `reporting` |
|
|
99
|
+
| `true` (dbt-core standard) | *(none)* | `target.schema` |
|
|
100
|
+
| `true` (dbt-core standard) | `"reporting"` | `target.schema_reporting` |
|
|
101
|
+
|
|
102
|
+
When `false` (the default), the adapter uses its legacy behaviour: `custom_schema_name` is used **as-is** without being prefixed by `target.schema`.
|
|
103
|
+
When `true`, the adapter delegates to dbt-core's `default__generate_schema_name`, which concatenates `target.schema` + `_` + `custom_schema_name`.
|
|
104
|
+
|
|
105
|
+
**Example usage in `dbt_project.yml`:**
|
|
106
|
+
|
|
107
|
+
```yaml
|
|
108
|
+
vars:
|
|
109
|
+
dbt_sqlserver_use_default_schema_concat: true # Enable standard schema concatenation
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
> **Note:** If you want to permanently customise schema generation and avoid any future deprecation of this flag, override the `sqlserver__generate_schema_name` macro directly in your project.
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|
|
78
116
|
## Contributing
|
|
79
117
|
|
|
80
118
|
[](https://github.com/dbt-msft/dbt-sqlserver/actions/workflows/unit-tests.yml)
|
|
@@ -92,5 +130,3 @@ If you're unsure how to get started, check out our [contributing guide](CONTRIBU
|
|
|
92
130
|
## Code of Conduct
|
|
93
131
|
|
|
94
132
|
This project and everyone involved is expected to follow the [dbt Code of Conduct](https://community.getdbt.com/code-of-conduct).
|
|
95
|
-
|
|
96
|
-
|
|
@@ -1,29 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: dbt-sqlserver
|
|
3
|
-
Version: 1.9.0
|
|
4
|
-
Summary: A Microsoft SQL Server adapter plugin for dbt
|
|
5
|
-
Home-page: https://github.com/dbt-msft/dbt-sqlserver
|
|
6
|
-
Author: Mikael Ene, Anders Swanson, Sam Debruyn, Cor Zuurmond, Cody Scott
|
|
7
|
-
License: MIT
|
|
8
|
-
Project-URL: Setup & configuration, https://docs.getdbt.com/reference/warehouse-profiles/mssql-profile
|
|
9
|
-
Project-URL: Documentation & usage, https://docs.getdbt.com/reference/resource-configs/mssql-configs
|
|
10
|
-
Project-URL: Changelog, https://github.com/dbt-msft/dbt-sqlserver/blob/master/CHANGELOG.md
|
|
11
|
-
Project-URL: Issue Tracker, https://github.com/dbt-msft/dbt-sqlserver/issues
|
|
12
|
-
Platform: UNKNOWN
|
|
13
|
-
Classifier: Development Status :: 5 - Production/Stable
|
|
14
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
-
Classifier: Operating System :: Microsoft :: Windows
|
|
16
|
-
Classifier: Operating System :: MacOS :: MacOS X
|
|
17
|
-
Classifier: Operating System :: POSIX :: Linux
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
21
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
-
Description-Content-Type: text/markdown
|
|
25
|
-
License-File: LICENSE
|
|
26
|
-
|
|
27
1
|
# dbt-sqlserver
|
|
28
2
|
|
|
29
3
|
[dbt](https://www.getdbt.com) adapter for Microsoft SQL Server and Azure SQL services.
|
|
@@ -75,6 +49,33 @@ pip install -U --pre dbt-sqlserver
|
|
|
75
49
|
|
|
76
50
|
See [the changelog](CHANGELOG.md)
|
|
77
51
|
|
|
52
|
+
## Configuration
|
|
53
|
+
|
|
54
|
+
### Flags
|
|
55
|
+
|
|
56
|
+
- `dbt_sqlserver_use_default_schema_concat`: *(default: `false`)* Controls schema name generation when a [custom schema](https://docs.getdbt.com/docs/build/custom-schemas) is set on a model.
|
|
57
|
+
|
|
58
|
+
| Flag value | `custom_schema_name` | Result |
|
|
59
|
+
|---|---|---|
|
|
60
|
+
| `false` (default, legacy) | *(none)* | `target.schema` |
|
|
61
|
+
| `false` (default, legacy) | `"reporting"` | `reporting` |
|
|
62
|
+
| `true` (dbt-core standard) | *(none)* | `target.schema` |
|
|
63
|
+
| `true` (dbt-core standard) | `"reporting"` | `target.schema_reporting` |
|
|
64
|
+
|
|
65
|
+
When `false` (the default), the adapter uses its legacy behaviour: `custom_schema_name` is used **as-is** without being prefixed by `target.schema`.
|
|
66
|
+
When `true`, the adapter delegates to dbt-core's `default__generate_schema_name`, which concatenates `target.schema` + `_` + `custom_schema_name`.
|
|
67
|
+
|
|
68
|
+
**Example usage in `dbt_project.yml`:**
|
|
69
|
+
|
|
70
|
+
```yaml
|
|
71
|
+
vars:
|
|
72
|
+
dbt_sqlserver_use_default_schema_concat: true # Enable standard schema concatenation
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
> **Note:** If you want to permanently customise schema generation and avoid any future deprecation of this flag, override the `sqlserver__generate_schema_name` macro directly in your project.
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
78
79
|
## Contributing
|
|
79
80
|
|
|
80
81
|
[](https://github.com/dbt-msft/dbt-sqlserver/actions/workflows/unit-tests.yml)
|
|
@@ -92,5 +93,3 @@ If you're unsure how to get started, check out our [contributing guide](CONTRIBU
|
|
|
92
93
|
## Code of Conduct
|
|
93
94
|
|
|
94
95
|
This project and everyone involved is expected to follow the [dbt Code of Conduct](https://community.getdbt.com/code-of-conduct).
|
|
95
|
-
|
|
96
|
-
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
version = "1.9.1rc1"
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
from typing import List, Optional
|
|
2
|
+
|
|
3
|
+
import agate
|
|
4
|
+
import dbt_common.exceptions
|
|
5
|
+
from dbt.adapters.base.column import Column as BaseColumn
|
|
6
|
+
from dbt.adapters.base.impl import ConstraintSupport
|
|
7
|
+
from dbt.adapters.base.meta import available
|
|
8
|
+
from dbt.adapters.base.relation import BaseRelation
|
|
9
|
+
from dbt.adapters.capability import Capability, CapabilityDict, CapabilitySupport, Support
|
|
10
|
+
from dbt.adapters.events.types import SchemaCreation
|
|
11
|
+
from dbt.adapters.reference_keys import _make_ref_key_dict
|
|
12
|
+
from dbt.adapters.sql.impl import CREATE_SCHEMA_MACRO_NAME, SQLAdapter
|
|
13
|
+
from dbt_common.behavior_flags import BehaviorFlag
|
|
14
|
+
from dbt_common.contracts.constraints import (
|
|
15
|
+
ColumnLevelConstraint,
|
|
16
|
+
ConstraintType,
|
|
17
|
+
ModelLevelConstraint,
|
|
18
|
+
)
|
|
19
|
+
from dbt_common.events.functions import fire_event
|
|
20
|
+
|
|
21
|
+
from dbt.adapters.sqlserver.sqlserver_column import SQLServerColumn
|
|
22
|
+
from dbt.adapters.sqlserver.sqlserver_configs import SQLServerConfigs
|
|
23
|
+
from dbt.adapters.sqlserver.sqlserver_connections import SQLServerConnectionManager
|
|
24
|
+
from dbt.adapters.sqlserver.sqlserver_relation import SQLServerRelation
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class SQLServerAdapter(SQLAdapter):
|
|
28
|
+
"""
|
|
29
|
+
Controls actual implmentation of adapter, and ability to override certain methods.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
ConnectionManager = SQLServerConnectionManager
|
|
33
|
+
Column = SQLServerColumn
|
|
34
|
+
AdapterSpecificConfigs = SQLServerConfigs
|
|
35
|
+
Relation = SQLServerRelation
|
|
36
|
+
|
|
37
|
+
_capabilities: CapabilityDict = CapabilityDict(
|
|
38
|
+
{
|
|
39
|
+
Capability.SchemaMetadataByRelations: CapabilitySupport(support=Support.Full),
|
|
40
|
+
Capability.TableLastModifiedMetadata: CapabilitySupport(support=Support.Full),
|
|
41
|
+
}
|
|
42
|
+
)
|
|
43
|
+
CONSTRAINT_SUPPORT = {
|
|
44
|
+
ConstraintType.check: ConstraintSupport.ENFORCED,
|
|
45
|
+
ConstraintType.not_null: ConstraintSupport.ENFORCED,
|
|
46
|
+
ConstraintType.unique: ConstraintSupport.ENFORCED,
|
|
47
|
+
ConstraintType.primary_key: ConstraintSupport.ENFORCED,
|
|
48
|
+
ConstraintType.foreign_key: ConstraintSupport.ENFORCED,
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def _behavior_flags(self) -> List[BehaviorFlag]:
|
|
53
|
+
return [
|
|
54
|
+
{
|
|
55
|
+
"name": "empty",
|
|
56
|
+
"default": False,
|
|
57
|
+
"description": (
|
|
58
|
+
"When enabled, table and view materializations will be created as empty "
|
|
59
|
+
"structures (no data)."
|
|
60
|
+
),
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"name": "dbt_sqlserver_use_default_schema_concat",
|
|
64
|
+
"default": False,
|
|
65
|
+
"description": (
|
|
66
|
+
"When True, uses dbt-core's standard schema concatenation "
|
|
67
|
+
"(`target.schema` + `_` + `custom_schema_name`). "
|
|
68
|
+
"When False (default), uses legacy adapter behaviour: "
|
|
69
|
+
"`custom_schema_name` is used directly without prefixing `target.schema`. "
|
|
70
|
+
"For a permanent solution, override the `sqlserver__generate_schema_name` "
|
|
71
|
+
"macro in your project instead."
|
|
72
|
+
),
|
|
73
|
+
},
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
@available.parse(lambda *a, **k: [])
|
|
77
|
+
def get_column_schema_from_query(self, sql: str) -> List[BaseColumn]:
|
|
78
|
+
"""Get a list of the Columns with names and data types from the given sql."""
|
|
79
|
+
_, cursor = self.connections.add_select_query(sql)
|
|
80
|
+
|
|
81
|
+
columns = [
|
|
82
|
+
self.Column.create(
|
|
83
|
+
column_name, self.connections.data_type_code_to_name(column_type_code)
|
|
84
|
+
)
|
|
85
|
+
# https://peps.python.org/pep-0249/#description
|
|
86
|
+
for column_name, column_type_code, *_ in cursor.description
|
|
87
|
+
]
|
|
88
|
+
return columns
|
|
89
|
+
|
|
90
|
+
@classmethod
|
|
91
|
+
def convert_boolean_type(cls, agate_table, col_idx):
|
|
92
|
+
return "bit"
|
|
93
|
+
|
|
94
|
+
@classmethod
|
|
95
|
+
def convert_datetime_type(cls, agate_table, col_idx):
|
|
96
|
+
return "datetime2(6)"
|
|
97
|
+
|
|
98
|
+
@classmethod
|
|
99
|
+
def convert_number_type(cls, agate_table, col_idx):
|
|
100
|
+
decimals = agate_table.aggregate(agate.MaxPrecision(col_idx))
|
|
101
|
+
return "float" if decimals else "int"
|
|
102
|
+
|
|
103
|
+
def create_schema(self, relation: BaseRelation) -> None:
|
|
104
|
+
relation = relation.without_identifier()
|
|
105
|
+
fire_event(SchemaCreation(relation=_make_ref_key_dict(relation)))
|
|
106
|
+
macro_name = CREATE_SCHEMA_MACRO_NAME
|
|
107
|
+
kwargs = {
|
|
108
|
+
"relation": relation,
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if self.config.credentials.schema_authorization:
|
|
112
|
+
kwargs["schema_authorization"] = self.config.credentials.schema_authorization
|
|
113
|
+
macro_name = "sqlserver__create_schema_with_authorization"
|
|
114
|
+
|
|
115
|
+
self.execute_macro(macro_name, kwargs=kwargs)
|
|
116
|
+
self.commit_if_has_connection()
|
|
117
|
+
|
|
118
|
+
@classmethod
|
|
119
|
+
def convert_text_type(cls, agate_table, col_idx):
|
|
120
|
+
column = agate_table.columns[col_idx]
|
|
121
|
+
# see https://github.com/fishtown-analytics/dbt/pull/2255
|
|
122
|
+
lens = [len(d.encode("utf-8")) for d in column.values_without_nulls()]
|
|
123
|
+
max_len = max(lens) if lens else 64
|
|
124
|
+
length = max_len if max_len > 16 else 16
|
|
125
|
+
return "varchar({})".format(length)
|
|
126
|
+
|
|
127
|
+
@classmethod
|
|
128
|
+
def convert_time_type(cls, agate_table, col_idx):
|
|
129
|
+
return "time(6)"
|
|
130
|
+
|
|
131
|
+
@classmethod
|
|
132
|
+
def date_function(cls):
|
|
133
|
+
return "getdate()"
|
|
134
|
+
|
|
135
|
+
# Methods used in adapter tests
|
|
136
|
+
def timestamp_add_sql(self, add_to: str, number: int = 1, interval: str = "hour") -> str:
|
|
137
|
+
# note: 'interval' is not supported for T-SQL
|
|
138
|
+
# for backwards compatibility, we're compelled to set some sort of
|
|
139
|
+
# default. A lot of searching has lead me to believe that the
|
|
140
|
+
# '+ interval' syntax used in postgres/redshift is relatively common
|
|
141
|
+
# and might even be the SQL standard's intention.
|
|
142
|
+
return f"DATEADD({interval},{number},{add_to})"
|
|
143
|
+
|
|
144
|
+
def string_add_sql(
|
|
145
|
+
self,
|
|
146
|
+
add_to: str,
|
|
147
|
+
value: str,
|
|
148
|
+
location="append",
|
|
149
|
+
) -> str:
|
|
150
|
+
"""
|
|
151
|
+
`+` is T-SQL's string concatenation operator
|
|
152
|
+
"""
|
|
153
|
+
if location == "append":
|
|
154
|
+
return f"{add_to} + '{value}'"
|
|
155
|
+
elif location == "prepend":
|
|
156
|
+
return f"'{value}' + {add_to}"
|
|
157
|
+
else:
|
|
158
|
+
raise ValueError(f'Got an unexpected location value of "{location}"')
|
|
159
|
+
|
|
160
|
+
def get_rows_different_sql(
|
|
161
|
+
self,
|
|
162
|
+
relation_a: BaseRelation,
|
|
163
|
+
relation_b: BaseRelation,
|
|
164
|
+
column_names: Optional[List[str]] = None,
|
|
165
|
+
except_operator: str = "EXCEPT",
|
|
166
|
+
) -> str:
|
|
167
|
+
"""
|
|
168
|
+
note: using is not supported on Synapse so COLUMNS_EQUAL_SQL is adjsuted
|
|
169
|
+
Generate SQL for a query that returns a single row with a two
|
|
170
|
+
columns: the number of rows that are different between the two
|
|
171
|
+
relations and the number of mismatched rows.
|
|
172
|
+
"""
|
|
173
|
+
# This method only really exists for test reasons.
|
|
174
|
+
names: List[str]
|
|
175
|
+
if column_names is None:
|
|
176
|
+
columns = self.get_columns_in_relation(relation_a)
|
|
177
|
+
names = sorted((self.quote(c.name) for c in columns))
|
|
178
|
+
else:
|
|
179
|
+
names = sorted((self.quote(n) for n in column_names))
|
|
180
|
+
columns_csv = ", ".join(names)
|
|
181
|
+
|
|
182
|
+
if columns_csv == "":
|
|
183
|
+
columns_csv = "*"
|
|
184
|
+
|
|
185
|
+
sql = COLUMNS_EQUAL_SQL.format(
|
|
186
|
+
columns=columns_csv,
|
|
187
|
+
relation_a=str(relation_a),
|
|
188
|
+
relation_b=str(relation_b),
|
|
189
|
+
except_op=except_operator,
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
return sql
|
|
193
|
+
|
|
194
|
+
def valid_incremental_strategies(self):
|
|
195
|
+
"""The set of standard builtin strategies which this adapter supports out-of-the-box.
|
|
196
|
+
Not used to validate custom strategies defined by end users.
|
|
197
|
+
"""
|
|
198
|
+
return ["append", "delete+insert", "merge", "microbatch"]
|
|
199
|
+
|
|
200
|
+
# This is for use in the test suite
|
|
201
|
+
def run_sql_for_tests(self, sql, fetch, conn):
|
|
202
|
+
cursor = conn.handle.cursor()
|
|
203
|
+
try:
|
|
204
|
+
cursor.execute(sql)
|
|
205
|
+
if not fetch:
|
|
206
|
+
conn.handle.commit()
|
|
207
|
+
if fetch == "one":
|
|
208
|
+
return cursor.fetchone()
|
|
209
|
+
elif fetch == "all":
|
|
210
|
+
return cursor.fetchall()
|
|
211
|
+
else:
|
|
212
|
+
return
|
|
213
|
+
except BaseException:
|
|
214
|
+
if conn.handle and not getattr(conn.handle, "closed", True):
|
|
215
|
+
conn.handle.rollback()
|
|
216
|
+
raise
|
|
217
|
+
finally:
|
|
218
|
+
conn.transaction_open = False
|
|
219
|
+
|
|
220
|
+
@available
|
|
221
|
+
@classmethod
|
|
222
|
+
def render_column_constraint(cls, constraint: ColumnLevelConstraint) -> Optional[str]:
|
|
223
|
+
rendered_column_constraint = None
|
|
224
|
+
if constraint.type == ConstraintType.not_null:
|
|
225
|
+
rendered_column_constraint = "not null "
|
|
226
|
+
else:
|
|
227
|
+
rendered_column_constraint = ""
|
|
228
|
+
|
|
229
|
+
if rendered_column_constraint:
|
|
230
|
+
rendered_column_constraint = rendered_column_constraint.strip()
|
|
231
|
+
|
|
232
|
+
return rendered_column_constraint
|
|
233
|
+
|
|
234
|
+
@classmethod
|
|
235
|
+
def render_model_constraint(cls, constraint: ModelLevelConstraint) -> Optional[str]:
|
|
236
|
+
constraint_prefix = "add constraint "
|
|
237
|
+
column_list = ", ".join(constraint.columns)
|
|
238
|
+
|
|
239
|
+
if constraint.name is None:
|
|
240
|
+
raise dbt_common.exceptions.DbtDatabaseError(
|
|
241
|
+
"Constraint name cannot be empty. Provide constraint name - column "
|
|
242
|
+
+ column_list
|
|
243
|
+
+ " and run the project again."
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
if constraint.type == ConstraintType.unique:
|
|
247
|
+
return constraint_prefix + f"{constraint.name} unique nonclustered({column_list})"
|
|
248
|
+
elif constraint.type == ConstraintType.primary_key:
|
|
249
|
+
return constraint_prefix + f"{constraint.name} primary key nonclustered({column_list})"
|
|
250
|
+
elif constraint.type == ConstraintType.foreign_key and constraint.expression:
|
|
251
|
+
return (
|
|
252
|
+
constraint_prefix
|
|
253
|
+
+ f"{constraint.name} foreign key({column_list}) references "
|
|
254
|
+
+ constraint.expression
|
|
255
|
+
)
|
|
256
|
+
elif constraint.type == ConstraintType.check and constraint.expression:
|
|
257
|
+
return f"{constraint_prefix} {constraint.name} check ({constraint.expression})"
|
|
258
|
+
elif constraint.type == ConstraintType.custom and constraint.expression:
|
|
259
|
+
return f"{constraint_prefix} {constraint.name} {constraint.expression}"
|
|
260
|
+
else:
|
|
261
|
+
return None
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
COLUMNS_EQUAL_SQL = """
|
|
265
|
+
with diff_count as (
|
|
266
|
+
SELECT
|
|
267
|
+
1 as id,
|
|
268
|
+
COUNT(*) as num_missing FROM (
|
|
269
|
+
(SELECT {columns} FROM {relation_a} {except_op}
|
|
270
|
+
SELECT {columns} FROM {relation_b})
|
|
271
|
+
UNION ALL
|
|
272
|
+
(SELECT {columns} FROM {relation_b} {except_op}
|
|
273
|
+
SELECT {columns} FROM {relation_a})
|
|
274
|
+
) as a
|
|
275
|
+
), table_a as (
|
|
276
|
+
SELECT COUNT(*) as num_rows FROM {relation_a}
|
|
277
|
+
), table_b as (
|
|
278
|
+
SELECT COUNT(*) as num_rows FROM {relation_b}
|
|
279
|
+
), row_count_diff as (
|
|
280
|
+
select
|
|
281
|
+
1 as id,
|
|
282
|
+
table_a.num_rows - table_b.num_rows as difference
|
|
283
|
+
from table_a, table_b
|
|
284
|
+
)
|
|
285
|
+
select
|
|
286
|
+
row_count_diff.difference as row_count_difference,
|
|
287
|
+
diff_count.num_missing as num_mismatched
|
|
288
|
+
from row_count_diff
|
|
289
|
+
join diff_count on row_count_diff.id = diff_count.id
|
|
290
|
+
""".strip()
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
from typing import Any, ClassVar, Dict
|
|
2
|
+
|
|
3
|
+
from dbt.adapters.base.column import Column
|
|
4
|
+
from dbt_common.exceptions import DbtRuntimeError
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class SQLServerColumn(Column):
|
|
8
|
+
TYPE_LABELS: ClassVar[Dict[str, str]] = {
|
|
9
|
+
"STRING": "VARCHAR(8000)",
|
|
10
|
+
"VARCHAR": "VARCHAR(8000)",
|
|
11
|
+
"CHAR": "CHAR(1)",
|
|
12
|
+
"NCHAR": "CHAR(1)",
|
|
13
|
+
"NVARCHAR": "VARCHAR(8000)",
|
|
14
|
+
"TIMESTAMP": "DATETIME2(6)",
|
|
15
|
+
"DATETIME2": "DATETIME2(6)",
|
|
16
|
+
"DATETIME2(6)": "DATETIME2(6)",
|
|
17
|
+
"DATE": "DATE",
|
|
18
|
+
"TIME": "TIME(6)",
|
|
19
|
+
"FLOAT": "FLOAT",
|
|
20
|
+
"REAL": "REAL",
|
|
21
|
+
"INT": "INT",
|
|
22
|
+
"INTEGER": "INT",
|
|
23
|
+
"BIGINT": "BIGINT",
|
|
24
|
+
"SMALLINT": "SMALLINT",
|
|
25
|
+
"TINYINT": "SMALLINT",
|
|
26
|
+
"BIT": "BIT",
|
|
27
|
+
"BOOLEAN": "BIT",
|
|
28
|
+
"DECIMAL": "DECIMAL",
|
|
29
|
+
"NUMERIC": "NUMERIC",
|
|
30
|
+
"MONEY": "DECIMAL",
|
|
31
|
+
"SMALLMONEY": "DECIMAL",
|
|
32
|
+
"UNIQUEIDENTIFIER": "UNIQUEIDENTIFIER",
|
|
33
|
+
"VARBINARY": "VARBINARY(MAX)",
|
|
34
|
+
"BINARY": "BINARY(1)",
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@classmethod
|
|
38
|
+
def string_type(cls, size: int) -> str:
|
|
39
|
+
return f"varchar({size if size > 0 else '8000'})"
|
|
40
|
+
|
|
41
|
+
def literal(self, value: Any) -> str:
|
|
42
|
+
return "cast('{}' as {})".format(value, self.data_type)
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def data_type(self) -> str:
|
|
46
|
+
# Always enforce datetime2 precision
|
|
47
|
+
if self.dtype.lower() == "datetime2":
|
|
48
|
+
return "datetime2(6)"
|
|
49
|
+
if self.is_string():
|
|
50
|
+
return self.string_type(self.string_size())
|
|
51
|
+
elif self.is_numeric():
|
|
52
|
+
return self.numeric_type(self.dtype, self.numeric_precision, self.numeric_scale)
|
|
53
|
+
else:
|
|
54
|
+
return self.dtype
|
|
55
|
+
|
|
56
|
+
def is_string(self) -> bool:
|
|
57
|
+
return self.dtype.lower() in ["varchar", "char"]
|
|
58
|
+
|
|
59
|
+
def is_number(self):
|
|
60
|
+
return any([self.is_integer(), self.is_numeric(), self.is_float()])
|
|
61
|
+
|
|
62
|
+
def is_float(self):
|
|
63
|
+
return self.dtype.lower() in ["float", "real"]
|
|
64
|
+
|
|
65
|
+
def is_integer(self) -> bool:
|
|
66
|
+
return self.dtype.lower() in [
|
|
67
|
+
# real types
|
|
68
|
+
"smallint",
|
|
69
|
+
"integer",
|
|
70
|
+
"bigint",
|
|
71
|
+
"smallserial",
|
|
72
|
+
"serial",
|
|
73
|
+
"bigserial",
|
|
74
|
+
# aliases
|
|
75
|
+
"int2",
|
|
76
|
+
"int4",
|
|
77
|
+
"int8",
|
|
78
|
+
"serial2",
|
|
79
|
+
"serial4",
|
|
80
|
+
"serial8",
|
|
81
|
+
"int",
|
|
82
|
+
]
|
|
83
|
+
|
|
84
|
+
def is_numeric(self) -> bool:
|
|
85
|
+
return self.dtype.lower() in ["numeric", "decimal", "money", "smallmoney"]
|
|
86
|
+
|
|
87
|
+
def string_size(self) -> int:
|
|
88
|
+
if not self.is_string():
|
|
89
|
+
raise DbtRuntimeError("Called string_size() on non-string field!")
|
|
90
|
+
if self.char_size is None:
|
|
91
|
+
return 8000
|
|
92
|
+
else:
|
|
93
|
+
return int(self.char_size)
|
|
94
|
+
|
|
95
|
+
def can_expand_to(self, other_column: "SQLServerColumn") -> bool:
|
|
96
|
+
if not self.is_string() or not other_column.is_string():
|
|
97
|
+
return False
|
|
98
|
+
return other_column.string_size() > self.string_size()
|