dbt-sqlserver 1.11.2rc1__tar.gz → 1.11.2rc2__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.
Files changed (82) hide show
  1. {dbt_sqlserver-1.11.2rc1/dbt_sqlserver.egg-info → dbt_sqlserver-1.11.2rc2}/PKG-INFO +7 -8
  2. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/README.md +6 -7
  3. dbt_sqlserver-1.11.2rc2/dbt/adapters/sqlserver/__version__.py +1 -0
  4. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/adapters/sqlserver/sqlserver_adapter.py +48 -30
  5. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/adapters/metadata.sql +49 -0
  6. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/adapters/schema.sql +34 -9
  7. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/materializations/models/view/view.sql +8 -15
  8. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/materializations/tests.sql +3 -6
  9. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/materializations/unit_tests.sql +2 -5
  10. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/relations/table/create.sql +22 -8
  11. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2/dbt_sqlserver.egg-info}/PKG-INFO +7 -8
  12. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/pyproject.toml +27 -0
  13. dbt_sqlserver-1.11.2rc1/dbt/adapters/sqlserver/__version__.py +0 -1
  14. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/LICENSE +0 -0
  15. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/__init__.py +0 -0
  16. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/adapters/sqlserver/__init__.py +0 -0
  17. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/adapters/sqlserver/py.typed +0 -0
  18. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/adapters/sqlserver/relation_configs/__init__.py +0 -0
  19. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/adapters/sqlserver/relation_configs/index.py +0 -0
  20. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/adapters/sqlserver/relation_configs/policies.py +0 -0
  21. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/adapters/sqlserver/sqlserver_auth.py +0 -0
  22. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/adapters/sqlserver/sqlserver_backend.py +0 -0
  23. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/adapters/sqlserver/sqlserver_column.py +0 -0
  24. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/adapters/sqlserver/sqlserver_configs.py +0 -0
  25. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/adapters/sqlserver/sqlserver_connections.py +0 -0
  26. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/adapters/sqlserver/sqlserver_constants.py +0 -0
  27. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/adapters/sqlserver/sqlserver_credentials.py +0 -0
  28. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/adapters/sqlserver/sqlserver_helpers.py +0 -0
  29. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/adapters/sqlserver/sqlserver_mask.py +0 -0
  30. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/adapters/sqlserver/sqlserver_relation.py +0 -0
  31. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/adapters/sqlserver/sqlserver_runtime.py +0 -0
  32. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/__init__.py +0 -0
  33. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/dbt_project.yml +0 -0
  34. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/adapters/apply_grants.sql +0 -0
  35. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/adapters/apply_masks.sql +0 -0
  36. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/adapters/catalog.sql +0 -0
  37. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/adapters/columns.sql +0 -0
  38. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/adapters/indexes.sql +0 -0
  39. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/adapters/persist_docs.sql +0 -0
  40. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/adapters/relation.sql +0 -0
  41. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/adapters/show.sql +0 -0
  42. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/adapters/validate_sql.sql +0 -0
  43. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/materializations/functions/helpers.sql +0 -0
  44. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/materializations/functions/scalar.sql +0 -0
  45. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/materializations/hooks.sql +0 -0
  46. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/materializations/models/incremental/incremental.sql +0 -0
  47. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/materializations/models/incremental/incremental_strategies.sql +0 -0
  48. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/materializations/models/incremental/merge.sql +0 -0
  49. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/materializations/models/table/columns_spec_ddl.sql +0 -0
  50. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/materializations/models/table/table.sql +0 -0
  51. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/materializations/models/table/table_dml_refresh.sql +0 -0
  52. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/materializations/models/unit_test/get_fixture_sql.sql +0 -0
  53. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/materializations/models/unit_test/unit_test_create_table_as.sql +0 -0
  54. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/materializations/models/view/create_view_as.sql +0 -0
  55. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/materializations/snapshots/helpers.sql +0 -0
  56. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/materializations/snapshots/snapshot.sql +0 -0
  57. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/materializations/snapshots/snapshot_merge.sql +0 -0
  58. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/materializations/snapshots/strategies.sql +0 -0
  59. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/relations/seeds/helpers.sql +0 -0
  60. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/relations/table/clone.sql +0 -0
  61. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/relations/views/create.sql +0 -0
  62. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/utils/any_value.sql +0 -0
  63. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/utils/array_construct.sql +0 -0
  64. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/utils/cast_bool_to_text.sql +0 -0
  65. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/utils/concat.sql +0 -0
  66. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/utils/date_trunc.sql +0 -0
  67. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/utils/dateadd.sql +0 -0
  68. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/utils/get_tables_by_pattern.sql +0 -0
  69. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/utils/hash.sql +0 -0
  70. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/utils/last_day.sql +0 -0
  71. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/utils/length.sql +0 -0
  72. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/utils/listagg.sql +0 -0
  73. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/utils/position.sql +0 -0
  74. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/utils/safe_cast.sql +0 -0
  75. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/utils/split_part.sql +0 -0
  76. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/macros/utils/timestamps.sql +0 -0
  77. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt/include/sqlserver/profile_template.yml +0 -0
  78. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt_sqlserver.egg-info/SOURCES.txt +0 -0
  79. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt_sqlserver.egg-info/dependency_links.txt +0 -0
  80. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt_sqlserver.egg-info/requires.txt +0 -0
  81. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/dbt_sqlserver.egg-info/top_level.txt +0 -0
  82. {dbt_sqlserver-1.11.2rc1 → dbt_sqlserver-1.11.2rc2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dbt-sqlserver
3
- Version: 1.11.2rc1
3
+ Version: 1.11.2rc2
4
4
  Summary: A Microsoft SQL Server adapter plugin for dbt
5
5
  Author: Mikael Ene, Anders Swanson, Sam Debruyn, Cor Zuurmond, Cody Scott
6
6
  License: MIT
@@ -157,7 +157,7 @@ your_profile:
157
157
 
158
158
  ## Changelog
159
159
 
160
- See [the changelog](CHANGELOG.md)
160
+ See [the changelog](https://github.com/dbt-msft/dbt-sqlserver/blob/release/v1.11/CHANGELOG.md)
161
161
 
162
162
  ## Configuration
163
163
 
@@ -204,7 +204,7 @@ Safe expansions are further gated by `column_type_expansion_max_rows` (default 1
204
204
 
205
205
  ### `dbt_sqlserver_use_dbt_transactions`
206
206
 
207
- _(default: `false`)_ When enabled, makes dbt's transaction hooks real at the SQL Server level by emitting `BEGIN TRANSACTION` / `COMMIT TRANSACTION` through the adapter's `add_begin_query` and `add_commit_query` methods.
207
+ _(default: `false`)_ When enabled, makes dbt's transaction hooks real at the SQL Server level by emitting `BEGIN TRANSACTION` / `COMMIT TRANSACTION` through the adapter's `add_begin_query` and `add_commit_query` methods.
208
208
 
209
209
  The default is `false`, preserving existing behavior where `begin`/`commit` hooks are logical no-ops and the ODBC driver auto-commits each statement. When `dbt_sqlserver_use_dbt_transactions: true`, the adapter emits real T-SQL transaction statements, and rollback uses `IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION`.
210
210
 
@@ -212,10 +212,11 @@ The driver connection remains in autocommit mode (`autocommit=true`) in both mod
212
212
 
213
213
  This mode is opt-in and should be tested carefully with project-specific materializations and hooks.
214
214
 
215
+ **Compatibility notes:** Enabling `dbt_sqlserver_use_dbt_transactions: true` may expose transaction-state assumptions hidden by autocommit-only mode. Explicit transaction macros may interact with dbt-managed transactions, and cleanup after failed DDL/DML may differ. Review pre/post hooks for in-transaction vs out-of-transaction semantics.
216
+
215
217
  ```yaml
216
218
  # dbt_project.yml
217
219
  flags:
218
- dbt_sqlserver_enable_safe_type_expansion: true
219
220
  dbt_sqlserver_use_dbt_transactions: true # <-- opt-in; default is false
220
221
  ```
221
222
 
@@ -258,8 +259,6 @@ your_profile:
258
259
  prefer_single_alter_column=true) }}
259
260
  ```
260
261
 
261
- **Compatibility notes:** Enabling `dbt_sqlserver_use_dbt_transactions: true` may expose transaction-state assumptions hidden by autocommit-only mode. Explicit transaction macros may interact with dbt-managed transactions, and cleanup after failed DDL/DML may differ. Review pre/post hooks for in-transaction vs out-of-transaction semantics.
262
-
263
262
  ### `as_columnstore`
264
263
 
265
264
  *(default: `true`)* When building a table, the adapter creates a [clustered columnstore index](https://learn.microsoft.com/en-us/sql/relational-databases/indexes/columnstore-indexes-overview) (CCI) on it. Set `as_columnstore: false` to build a plain rowstore table instead.
@@ -297,7 +296,7 @@ A *model-level* constraint carrying `name:` is applied by `ALTER TABLE … ADD C
297
296
 
298
297
  Name a constraint when you want it stable across environments (schema-comparison tools report the generated names as differences) or need to reference it later. A `name:` on a *column-level* constraint is ignored with a warning — declare it under the model's `constraints:` key instead.
299
298
 
300
- The full set of rules, with the test that verifies each, is in [docs/constraints.md](docs/constraints.md).
299
+ The full set of rules, with the test that verifies each, is in [docs/constraints.md](https://github.com/dbt-msft/dbt-sqlserver/blob/release/v1.11/docs/constraints.md).
301
300
 
302
301
  ```yaml
303
302
  models:
@@ -439,7 +438,7 @@ Behaviour:
439
438
 
440
439
  This adapter is community-maintained.
441
440
  You are welcome to contribute by creating issues, opening or reviewing pull requests, or helping other users in the Slack channel.
442
- If you're unsure how to get started, check out our [contributing guide](CONTRIBUTING.md).
441
+ If you're unsure how to get started, check out our [contributing guide](https://github.com/dbt-msft/dbt-sqlserver/blob/release/v1.11/CONTRIBUTING.md).
443
442
 
444
443
  ## License
445
444
 
@@ -120,7 +120,7 @@ your_profile:
120
120
 
121
121
  ## Changelog
122
122
 
123
- See [the changelog](CHANGELOG.md)
123
+ See [the changelog](https://github.com/dbt-msft/dbt-sqlserver/blob/release/v1.11/CHANGELOG.md)
124
124
 
125
125
  ## Configuration
126
126
 
@@ -167,7 +167,7 @@ Safe expansions are further gated by `column_type_expansion_max_rows` (default 1
167
167
 
168
168
  ### `dbt_sqlserver_use_dbt_transactions`
169
169
 
170
- _(default: `false`)_ When enabled, makes dbt's transaction hooks real at the SQL Server level by emitting `BEGIN TRANSACTION` / `COMMIT TRANSACTION` through the adapter's `add_begin_query` and `add_commit_query` methods.
170
+ _(default: `false`)_ When enabled, makes dbt's transaction hooks real at the SQL Server level by emitting `BEGIN TRANSACTION` / `COMMIT TRANSACTION` through the adapter's `add_begin_query` and `add_commit_query` methods.
171
171
 
172
172
  The default is `false`, preserving existing behavior where `begin`/`commit` hooks are logical no-ops and the ODBC driver auto-commits each statement. When `dbt_sqlserver_use_dbt_transactions: true`, the adapter emits real T-SQL transaction statements, and rollback uses `IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION`.
173
173
 
@@ -175,10 +175,11 @@ The driver connection remains in autocommit mode (`autocommit=true`) in both mod
175
175
 
176
176
  This mode is opt-in and should be tested carefully with project-specific materializations and hooks.
177
177
 
178
+ **Compatibility notes:** Enabling `dbt_sqlserver_use_dbt_transactions: true` may expose transaction-state assumptions hidden by autocommit-only mode. Explicit transaction macros may interact with dbt-managed transactions, and cleanup after failed DDL/DML may differ. Review pre/post hooks for in-transaction vs out-of-transaction semantics.
179
+
178
180
  ```yaml
179
181
  # dbt_project.yml
180
182
  flags:
181
- dbt_sqlserver_enable_safe_type_expansion: true
182
183
  dbt_sqlserver_use_dbt_transactions: true # <-- opt-in; default is false
183
184
  ```
184
185
 
@@ -221,8 +222,6 @@ your_profile:
221
222
  prefer_single_alter_column=true) }}
222
223
  ```
223
224
 
224
- **Compatibility notes:** Enabling `dbt_sqlserver_use_dbt_transactions: true` may expose transaction-state assumptions hidden by autocommit-only mode. Explicit transaction macros may interact with dbt-managed transactions, and cleanup after failed DDL/DML may differ. Review pre/post hooks for in-transaction vs out-of-transaction semantics.
225
-
226
225
  ### `as_columnstore`
227
226
 
228
227
  *(default: `true`)* When building a table, the adapter creates a [clustered columnstore index](https://learn.microsoft.com/en-us/sql/relational-databases/indexes/columnstore-indexes-overview) (CCI) on it. Set `as_columnstore: false` to build a plain rowstore table instead.
@@ -260,7 +259,7 @@ A *model-level* constraint carrying `name:` is applied by `ALTER TABLE … ADD C
260
259
 
261
260
  Name a constraint when you want it stable across environments (schema-comparison tools report the generated names as differences) or need to reference it later. A `name:` on a *column-level* constraint is ignored with a warning — declare it under the model's `constraints:` key instead.
262
261
 
263
- The full set of rules, with the test that verifies each, is in [docs/constraints.md](docs/constraints.md).
262
+ The full set of rules, with the test that verifies each, is in [docs/constraints.md](https://github.com/dbt-msft/dbt-sqlserver/blob/release/v1.11/docs/constraints.md).
264
263
 
265
264
  ```yaml
266
265
  models:
@@ -402,7 +401,7 @@ Behaviour:
402
401
 
403
402
  This adapter is community-maintained.
404
403
  You are welcome to contribute by creating issues, opening or reviewing pull requests, or helping other users in the Slack channel.
405
- If you're unsure how to get started, check out our [contributing guide](CONTRIBUTING.md).
404
+ If you're unsure how to get started, check out our [contributing guide](https://github.com/dbt-msft/dbt-sqlserver/blob/release/v1.11/CONTRIBUTING.md).
406
405
 
407
406
  ## License
408
407
 
@@ -0,0 +1 @@
1
+ version = "1.11.2rc2"
@@ -56,7 +56,7 @@ _KEYED_CONSTRAINTS = frozenset(
56
56
  # full just to read its column names.
57
57
  _SQL_COMMENT = re.compile(r"(?s)/\*.*?\*/|--[^\n]*\n")
58
58
 
59
- # sp_describe_first_result_set reports true SQL Server types; reading
59
+ # The describe reports true SQL Server types; reading
60
60
  # ``cursor.description`` reports Python classes, which collapse whole families
61
61
  # (every integer width arrives as ``int``, every string type as ``varchar``).
62
62
  # Contract comparison comes through this method either way, so the describe
@@ -184,6 +184,13 @@ class SQLServerAdapter(SQLAdapter):
184
184
  SQLServerConnectionManager._dbt_sqlserver_use_dbt_transactions = use_dbt_transactions
185
185
  self.connections._dbt_sqlserver_use_dbt_transactions = use_dbt_transactions
186
186
 
187
+ @SQLAdapter.behavior.setter
188
+ def behavior(self, flags: List[BehaviorFlag]) -> None:
189
+ # The base setter extends `flags` in place, and it is passed the module-level
190
+ # DEFAULT_BASE_BEHAVIOR_FLAGS, which then grows on every adapter init (#855).
191
+ # Drop once dbt-adapters stops mutating it.
192
+ SQLAdapter.behavior.fset(self, list(flags))
193
+
187
194
  @property
188
195
  def _behavior_flags(self) -> List[BehaviorFlag]:
189
196
  return [
@@ -282,34 +289,42 @@ class SQLServerAdapter(SQLAdapter):
282
289
  def _describe_result_set(self, sql: str) -> Optional[List[BaseColumn]]:
283
290
  """Read a query's column shape without running it, or None to fall back.
284
291
 
285
- ``sp_describe_first_result_set`` compiles the query and reports its
286
- result shape, which is all this method ever wanted. It is already how
287
- ``sqlserver__get_columns_in_query`` handles CTEs (#698).
292
+ ``sys.dm_exec_describe_first_result_set`` compiles the query and
293
+ reports its result shape, which is all this method ever wanted. It is
294
+ the table-valued form of the ``sp_describe_first_result_set`` that
295
+ ``sqlserver__get_columns_in_query`` uses for CTEs (#698).
288
296
 
289
297
  Returns None -- deliberately, rather than raising -- whenever the
290
298
  describe cannot be trusted to match what executing would have reported:
291
- a query it refuses to describe (it cannot see through ``#temp`` tables,
292
- where executing works), or a type this backend's driver has no known
293
- executed name for. The caller then executes as before, which is
299
+ a query the describe fails on, or a type this backend's driver has no
300
+ known executed name for. The caller then executes as before, which is
294
301
  slower but never disagrees with itself.
302
+
303
+ A query that fails to compile is no exception: executing it fails at
304
+ compile too, costing nothing, and raises the query's own error --
305
+ Msg 207 naming the missing column -- through the normal path.
295
306
  """
296
307
  credentials = self.connections.profile.credentials
297
308
 
309
+ # The function rather than ``exec sp_describe_first_result_set``: the
310
+ # procedure raises whatever stops it describing, and handling a raised
311
+ # error closes the connection, so the fallback executed on a closed
312
+ # handle and reported that instead. The function hands the same
313
+ # failures back as rows with an error_number, which leaves the
314
+ # connection alone and needs no parsing of driver message text (which
315
+ # mssql-python strips of the error number anyway).
316
+ #
298
317
  # Inline rather than bound: mssql-python binds str as varchar and the
299
- # procedure demands nvarchar(max). columns.sql:24 escapes it the same
318
+ # function demands nvarchar(max). columns.sql:24 escapes it the same
300
319
  # way for the same reason.
301
- describe_sql = "exec sp_describe_first_result_set @tsql = N'{}'".format(
302
- sql.replace("'", "''")
303
- )
320
+ describe_sql = (
321
+ "select is_hidden, name, system_type_name, error_number, error_message"
322
+ " from sys.dm_exec_describe_first_result_set(N'{}', null, 0)"
323
+ " order by column_ordinal"
324
+ ).format(sql.replace("'", "''"))
304
325
 
326
+ _, cursor = self.connections.add_select_query(describe_sql)
305
327
  try:
306
- _, cursor = self.connections.add_select_query(describe_sql)
307
- except Exception as e:
308
- logger.debug(f"Could not describe a CTE query, falling back to executing it: {e}")
309
- return None
310
-
311
- try:
312
- fields = [description[0].lower() for description in cursor.description]
313
328
  rows = cursor.fetchall()
314
329
  except Exception as e:
315
330
  logger.debug(f"Could not read a described result set, executing the query: {e}")
@@ -317,32 +332,35 @@ class SQLServerAdapter(SQLAdapter):
317
332
  finally:
318
333
  _discard_pending_results(cursor)
319
334
 
320
- try:
321
- hidden, name, type_name = (
322
- fields.index("is_hidden"),
323
- fields.index("name"),
324
- fields.index("system_type_name"),
335
+ errors = [
336
+ f"Msg {error_number}: {message}" for *_, error_number, message in rows if error_number
337
+ ]
338
+ if errors:
339
+ # Nothing to tell apart here. A query the describe declines -- one
340
+ # under SET STATISTICS XML, say -- executes fine; one that does
341
+ # not compile fails executing too, with its own message.
342
+ logger.debug(
343
+ f"Could not describe a CTE query, executing it instead: {'; '.join(errors)}"
325
344
  )
326
- except ValueError: # pragma: no cover - shape is fixed by SQL Server
327
345
  return None
328
346
 
329
347
  columns = []
330
- for row in rows:
331
- if row[hidden]:
348
+ for hidden, name, type_name, *_ in rows:
349
+ if hidden:
332
350
  continue
333
351
  # "varchar(10)" / "decimal(10,2)" -> "varchar" / "decimal"
334
- base_type = str(row[type_name]).split("(")[0].strip().lower()
352
+ base_type = str(type_name).split("(")[0].strip().lower()
335
353
  executed_name = _executed_name_for_system_type(base_type, credentials.backend)
336
- if executed_name is None or row[name] is None:
354
+ if executed_name is None or name is None:
337
355
  logger.debug(
338
356
  f"Describing a CTE query reported {base_type!r}, which has no "
339
357
  "equivalent in the executed path; executing it instead"
340
358
  )
341
359
  return None
342
- columns.append(self.Column.create(row[name], executed_name))
360
+ columns.append(self.Column.create(name, executed_name))
343
361
 
344
362
  # Every select has at least one column, so nothing described means
345
- # sp_describe_first_result_set could not work the shape out. Returning
363
+ # the describe could not work the shape out. Returning
346
364
  # an empty list would read as "this query has no columns" and surface
347
365
  # as a baffling contract mismatch; execute instead.
348
366
  return columns or None
@@ -187,6 +187,55 @@
187
187
  where object_id({{ object_name }}, 'V') is not null
188
188
  {% endmacro %}
189
189
 
190
+ {% macro get_view_skip_check_sql(relation, compiled_sql) %}
191
+ {{ return(adapter.dispatch('get_view_skip_check_sql')(relation, compiled_sql)) }}
192
+ {% endmacro %}
193
+
194
+ {#- `definition` for the skip decision, and `needs_refresh` when the cached column
195
+ metadata no longer matches what the body resolves to. Refreshing unconditionally
196
+ would advance modify_date on every unchanged view.
197
+ - dm_exec_describe_first_result_set is referenced once: each reference compiles the body.
198
+ - Its error row is kept, so a body it cannot describe is refreshed.
199
+ - COLLATE DATABASE_DEFAULT, or the join fails where catalog and database collations differ.
200
+ - The body is inlined: the function needs nvarchar and mssql-python binds str as varchar. -#}
201
+ {% macro sqlserver__get_view_skip_check_sql(relation, compiled_sql) -%}
202
+ {%- set object_name = "quotename('" ~ relation.schema ~ "') + '.' + quotename('" ~ relation.identifier ~ "')" -%}
203
+ {{ get_use_database_sql(relation.database) }}
204
+ declare @dbt_sqlserver_skip_check_body nvarchar(max) = N'{{ escape_single_quotes(compiled_sql) }}';
205
+ select
206
+ object_definition(object_id({{ object_name }}, 'V')) as definition,
207
+ case when exists (
208
+ select 1
209
+ from (
210
+ select column_ordinal, name, system_type_id, user_type_id,
211
+ max_length, precision, scale, collation_name
212
+ from sys.dm_exec_describe_first_result_set(
213
+ @dbt_sqlserver_skip_check_body, null, 0)
214
+ where is_hidden = 0 or error_number is not null
215
+ ) as described
216
+ full outer join (
217
+ select row_number() over (order by column_id) as column_ordinal,
218
+ name, system_type_id, user_type_id,
219
+ max_length, precision, scale, collation_name
220
+ from sys.columns {{ information_schema_hints() }}
221
+ where object_id = object_id({{ object_name }}, 'V')
222
+ ) as cached
223
+ on described.column_ordinal = cached.column_ordinal
224
+ where described.column_ordinal is null
225
+ or cached.column_ordinal is null
226
+ or described.name collate database_default
227
+ <> cached.name collate database_default
228
+ or described.system_type_id <> cached.system_type_id
229
+ or described.user_type_id <> cached.user_type_id
230
+ or described.max_length <> cached.max_length
231
+ or described.precision <> cached.precision
232
+ or described.scale <> cached.scale
233
+ or isnull(described.collation_name, '') collate database_default
234
+ <> isnull(cached.collation_name, '') collate database_default
235
+ ) then 1 else 0 end as needs_refresh
236
+ where object_id({{ object_name }}, 'V') is not null
237
+ {% endmacro %}
238
+
190
239
  {% macro sqlserver__get_relation_last_modified(information_schema, relations) -%}
191
240
  {%- call statement('last_modified', fetch_result=True) -%}
192
241
  select
@@ -1,20 +1,45 @@
1
- {% macro sqlserver__create_schema(relation) -%}
2
- {% call statement('create_schema') -%}
3
- USE [{{ relation.database }}];
4
- IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = '{{ relation.schema }}')
1
+ {#
2
+ SQL Server has no `CREATE SCHEMA IF NOT EXISTS`, and check-then-act races under
3
+ concurrency (Msg 2714), so an applock serializes the check and the create.
4
+ The lock is session-scoped: a transaction-scoped one would be held until dbt
5
+ commits, after the test query in `get_test_sql`. `XACT_ABORT` skips a trailing
6
+ release when the create fails, so the `CATCH` releases and rethrows. A timed-out
7
+ request falls through to the bare check.
8
+ #}
9
+ {% macro create_schema_if_not_exists(schema, authorization=none) -%}
10
+ {%- set lock_resource = 'dbt_create_schema_' ~ schema -%}
11
+ DECLARE @dbt_schema_lock int;
12
+ EXEC @dbt_schema_lock = sp_getapplock
13
+ @Resource = '{{ escape_single_quotes(lock_resource) }}',
14
+ @LockMode = 'Exclusive',
15
+ @LockOwner = 'Session',
16
+ @LockTimeout = 30000;
17
+ BEGIN TRY
18
+ IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = '{{ escape_single_quotes(schema) }}')
5
19
  BEGIN
6
- EXEC('CREATE SCHEMA [{{ relation.schema }}]')
20
+ EXEC('CREATE SCHEMA {{ escape_single_quotes(adapter.quote(schema)) }}{% if authorization is not none %} AUTHORIZATION {{ escape_single_quotes(adapter.quote(authorization)) }}{% endif %}')
7
21
  END
22
+ END TRY
23
+ BEGIN CATCH
24
+ IF @dbt_schema_lock >= 0
25
+ EXEC sp_releaseapplock @Resource = '{{ escape_single_quotes(lock_resource) }}', @LockOwner = 'Session';
26
+ THROW;
27
+ END CATCH
28
+ IF @dbt_schema_lock >= 0
29
+ EXEC sp_releaseapplock @Resource = '{{ escape_single_quotes(lock_resource) }}', @LockOwner = 'Session';
30
+ {%- endmacro %}
31
+
32
+ {% macro sqlserver__create_schema(relation) -%}
33
+ {% call statement('create_schema') -%}
34
+ {{ get_use_database_sql(relation.database) }}
35
+ {{ create_schema_if_not_exists(relation.schema) }}
8
36
  {% endcall %}
9
37
  {% endmacro %}
10
38
 
11
39
  {% macro sqlserver__create_schema_with_authorization(relation, schema_authorization) -%}
12
40
  {% call statement('create_schema') -%}
13
41
  {{ get_use_database_sql(relation.database) }}
14
- IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = '{{ relation.schema }}')
15
- BEGIN
16
- EXEC('CREATE SCHEMA [{{ relation.schema }}] AUTHORIZATION [{{ schema_authorization }}]')
17
- END
42
+ {{ create_schema_if_not_exists(relation.schema, schema_authorization) }}
18
43
  {% endcall %}
19
44
  {% endmacro %}
20
45
 
@@ -41,7 +41,8 @@
41
41
  {% endfor %}
42
42
  {% set build_sql = get_create_view_as_sql(intermediate_relation, sql) %}
43
43
  {% elif existing_relation is not none and existing_relation.type == 'view' %}
44
- {% set current_view_definition_table = run_query(get_view_definition_sql(existing_relation)) %}
44
+ {% set current_view_definition_table = run_query(get_view_skip_check_sql(existing_relation, sql)) %}
45
+ {% set view_metadata_is_stale = false %}
45
46
  {% if current_view_definition_table is not none and current_view_definition_table.rows | length > 0 %}
46
47
  {#- Compare the view *body* exactly, not by suffix. The stored definition is
47
48
  the whole statement (CREATE [OR ALTER] VIEW <name> AS <body>); the model is
@@ -67,23 +68,15 @@
67
68
  {% set model_body = (model_body[:-1] if model_body.endswith(';') else model_body) | trim %}
68
69
  {% set should_skip_view_update = stored_body == model_body %}
69
70
  {% endif %}
71
+ {% set view_metadata_is_stale = current_view_definition_table.rows[0][1] == 1 %}
70
72
  {% endif %}
71
- {% if should_skip_view_update %}
72
- {#- The view's SQL text is unchanged, so the CREATE/ALTER is skipped -
73
- but a *referenced* table can still have changed shape (columns
74
- added, dropped, or reordered) since this view was last built. SQL
75
- Server resolves an unqualified `select *` at CREATE/ALTER time and
76
- caches the result; skipping that statement here means the cached
77
- column list silently goes stale relative to the underlying table,
78
- even though this view's own definition never changed. sp_refreshview
79
- re-derives that cached metadata from the table's current shape
80
- without re-running the CREATE, so a skip stays a skip (no DDL, no
81
- grant/deny churn) while the view keeps reporting the right columns. -#}
82
- {#- sp_refreshview resolves its argument in the *current* database, so this needs
83
- the same USE prefix every other name-resolving statement here carries -
84
- without it a cross-database view model would refresh nothing and error. -#}
73
+ {% if should_skip_view_update and view_metadata_is_stale %}
74
+ {#- A source changed shape under an unchanged body (e.g. a `select *` expansion).
75
+ sp_refreshview resolves its argument in the current database, hence the USE. -#}
85
76
  {% set object_name = "quotename('" ~ target_relation.schema ~ "') + '.' + quotename('" ~ target_relation.identifier ~ "')" %}
86
77
  {% set build_sql = get_use_database_sql(target_relation.database) ~ " declare @dbt_sqlserver_refresh_target nvarchar(max) = " ~ object_name ~ "; exec sp_refreshview @dbt_sqlserver_refresh_target;" %}
78
+ {% elif should_skip_view_update %}
79
+ {% set build_sql = 'declare @dbt_sqlserver_noop int;' %}
87
80
  {% else %}
88
81
  {% set build_sql = get_create_view_as_sql(target_relation, sql) %}
89
82
  {% endif %}
@@ -1,11 +1,8 @@
1
1
  {% macro sqlserver__get_test_sql(main_sql, fail_calc, warn_if, error_if, limit) -%}
2
2
 
3
- -- Create target schema if it does not
4
- USE [{{ target.database }}];
5
- IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = '{{ target.schema }}')
6
- BEGIN
7
- EXEC('CREATE SCHEMA [{{ target.schema }}]')
8
- END
3
+ -- Create target schema if it does not exist
4
+ {{ get_use_database_sql(target.database) }}
5
+ {{ create_schema_if_not_exists(target.schema) }}
9
6
 
10
7
  {% set testview %}
11
8
  [{{ target.schema }}].[testview_{{ local_md5(main_sql) }}_{{ range(1300, 19000) | random }}]
@@ -1,10 +1,7 @@
1
1
  {% macro sqlserver__get_unit_test_sql(main_sql, expected_fixture_sql, expected_column_names) -%}
2
2
 
3
- USE [{{ target.database }}];
4
- IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = '{{ target.schema }}')
5
- BEGIN
6
- EXEC('CREATE SCHEMA [{{ target.schema }}]')
7
- END
3
+ {{ get_use_database_sql(target.database) }}
4
+ {{ create_schema_if_not_exists(target.schema) }}
8
5
 
9
6
  {% set test_view %}
10
7
  [{{ target.schema }}].[testview_{{ local_md5(main_sql) }}_{{ range(1300, 19000) | random }}]
@@ -209,13 +209,21 @@
209
209
  {#- mark a table as having a full refresh in flight; the marker rides the
210
210
  object, so a successful swap (old table dropped) or in-place rebuild
211
211
  (table dropped) clears it naturally -#}
212
+ {#- USE persists for the session, so without it both halves resolve
213
+ against wherever the last statement left the connection - and there
214
+ they disagree: OBJECT_ID returns NULL, so the guard runs the EXEC even
215
+ when the marker is present, and the proc rejects the same name as
216
+ absent (Msg 15135). -#}
212
217
  {% do run_query(
213
- "if not exists (select 1 from sys.extended_properties where major_id = OBJECT_ID('"
214
- ~ relation.schema ~ "." ~ relation.identifier
215
- ~ "') and name = 'dbt_full_refresh_incomplete')"
218
+ get_use_database_sql(relation.database)
219
+ ~ " if not exists (select 1 from sys.extended_properties"
220
+ ~ " where class = 1 and minor_id = 0"
221
+ ~ " and name = 'dbt_full_refresh_incomplete' and major_id = OBJECT_ID('"
222
+ ~ escape_single_quotes(relation.include(database=False))
223
+ ~ "'))"
216
224
  ~ " EXEC sp_addextendedproperty @name = N'dbt_full_refresh_incomplete', @value = '1',"
217
- ~ " @level0type = N'SCHEMA', @level0name = N'" ~ relation.schema ~ "',"
218
- ~ " @level1type = N'TABLE', @level1name = N'" ~ relation.identifier ~ "'"
225
+ ~ " @level0type = N'SCHEMA', @level0name = N'" ~ escape_single_quotes(relation.schema) ~ "',"
226
+ ~ " @level1type = N'TABLE', @level1name = N'" ~ escape_single_quotes(relation.identifier) ~ "'"
219
227
  ) %}
220
228
  {#- This marker exists to survive a failed rebuild, so it must not ride on
221
229
  the same transaction as the rebuild it's guarding: if a prior
@@ -234,10 +242,16 @@
234
242
 
235
243
 
236
244
  {% macro sqlserver__assert_no_incomplete_full_refresh(relation) -%}
245
+ {#- Needs the USE more than the marker does: off-database this returns 0
246
+ rather than erroring, which reads as "no marker" and lets the append
247
+ through. -#}
237
248
  {%- set marker = run_query(
238
- "select count(*) as marker_count from sys.extended_properties where major_id = OBJECT_ID('"
239
- ~ relation.schema ~ "." ~ relation.identifier
240
- ~ "') and name = 'dbt_full_refresh_incomplete'"
249
+ get_use_database_sql(relation.database)
250
+ ~ " select count(*) as marker_count from sys.extended_properties"
251
+ ~ " where class = 1 and minor_id = 0"
252
+ ~ " and name = 'dbt_full_refresh_incomplete' and major_id = OBJECT_ID('"
253
+ ~ escape_single_quotes(relation.include(database=False))
254
+ ~ "')"
241
255
  ) -%}
242
256
  {%- if marker.rows[0][0] > 0 -%}
243
257
  {{ exceptions.raise_compiler_error(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dbt-sqlserver
3
- Version: 1.11.2rc1
3
+ Version: 1.11.2rc2
4
4
  Summary: A Microsoft SQL Server adapter plugin for dbt
5
5
  Author: Mikael Ene, Anders Swanson, Sam Debruyn, Cor Zuurmond, Cody Scott
6
6
  License: MIT
@@ -157,7 +157,7 @@ your_profile:
157
157
 
158
158
  ## Changelog
159
159
 
160
- See [the changelog](CHANGELOG.md)
160
+ See [the changelog](https://github.com/dbt-msft/dbt-sqlserver/blob/release/v1.11/CHANGELOG.md)
161
161
 
162
162
  ## Configuration
163
163
 
@@ -204,7 +204,7 @@ Safe expansions are further gated by `column_type_expansion_max_rows` (default 1
204
204
 
205
205
  ### `dbt_sqlserver_use_dbt_transactions`
206
206
 
207
- _(default: `false`)_ When enabled, makes dbt's transaction hooks real at the SQL Server level by emitting `BEGIN TRANSACTION` / `COMMIT TRANSACTION` through the adapter's `add_begin_query` and `add_commit_query` methods.
207
+ _(default: `false`)_ When enabled, makes dbt's transaction hooks real at the SQL Server level by emitting `BEGIN TRANSACTION` / `COMMIT TRANSACTION` through the adapter's `add_begin_query` and `add_commit_query` methods.
208
208
 
209
209
  The default is `false`, preserving existing behavior where `begin`/`commit` hooks are logical no-ops and the ODBC driver auto-commits each statement. When `dbt_sqlserver_use_dbt_transactions: true`, the adapter emits real T-SQL transaction statements, and rollback uses `IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION`.
210
210
 
@@ -212,10 +212,11 @@ The driver connection remains in autocommit mode (`autocommit=true`) in both mod
212
212
 
213
213
  This mode is opt-in and should be tested carefully with project-specific materializations and hooks.
214
214
 
215
+ **Compatibility notes:** Enabling `dbt_sqlserver_use_dbt_transactions: true` may expose transaction-state assumptions hidden by autocommit-only mode. Explicit transaction macros may interact with dbt-managed transactions, and cleanup after failed DDL/DML may differ. Review pre/post hooks for in-transaction vs out-of-transaction semantics.
216
+
215
217
  ```yaml
216
218
  # dbt_project.yml
217
219
  flags:
218
- dbt_sqlserver_enable_safe_type_expansion: true
219
220
  dbt_sqlserver_use_dbt_transactions: true # <-- opt-in; default is false
220
221
  ```
221
222
 
@@ -258,8 +259,6 @@ your_profile:
258
259
  prefer_single_alter_column=true) }}
259
260
  ```
260
261
 
261
- **Compatibility notes:** Enabling `dbt_sqlserver_use_dbt_transactions: true` may expose transaction-state assumptions hidden by autocommit-only mode. Explicit transaction macros may interact with dbt-managed transactions, and cleanup after failed DDL/DML may differ. Review pre/post hooks for in-transaction vs out-of-transaction semantics.
262
-
263
262
  ### `as_columnstore`
264
263
 
265
264
  *(default: `true`)* When building a table, the adapter creates a [clustered columnstore index](https://learn.microsoft.com/en-us/sql/relational-databases/indexes/columnstore-indexes-overview) (CCI) on it. Set `as_columnstore: false` to build a plain rowstore table instead.
@@ -297,7 +296,7 @@ A *model-level* constraint carrying `name:` is applied by `ALTER TABLE … ADD C
297
296
 
298
297
  Name a constraint when you want it stable across environments (schema-comparison tools report the generated names as differences) or need to reference it later. A `name:` on a *column-level* constraint is ignored with a warning — declare it under the model's `constraints:` key instead.
299
298
 
300
- The full set of rules, with the test that verifies each, is in [docs/constraints.md](docs/constraints.md).
299
+ The full set of rules, with the test that verifies each, is in [docs/constraints.md](https://github.com/dbt-msft/dbt-sqlserver/blob/release/v1.11/docs/constraints.md).
301
300
 
302
301
  ```yaml
303
302
  models:
@@ -439,7 +438,7 @@ Behaviour:
439
438
 
440
439
  This adapter is community-maintained.
441
440
  You are welcome to contribute by creating issues, opening or reviewing pull requests, or helping other users in the Slack channel.
442
- If you're unsure how to get started, check out our [contributing guide](CONTRIBUTING.md).
441
+ If you're unsure how to get started, check out our [contributing guide](https://github.com/dbt-msft/dbt-sqlserver/blob/release/v1.11/CONTRIBUTING.md).
443
442
 
444
443
  ## License
445
444
 
@@ -68,6 +68,7 @@ dev = [
68
68
  "pytz",
69
69
  "ruff",
70
70
  "tox>=3.13",
71
+ "towncrier>=26.9.0",
71
72
  "twine",
72
73
  ]
73
74
 
@@ -94,6 +95,32 @@ link-mode = "copy"
94
95
  environments = "python_version >= '3.11'"
95
96
  override-dependencies = ["pathspec>=0.9,<1.1"] # Remove on dbt-core v1.12 or migration to ty by astral
96
97
 
98
+ [tool.towncrier]
99
+ directory = "changes"
100
+ filename = "CHANGELOG.md"
101
+ title_format = "### v{version}"
102
+ issue_format = "[#{issue}](https://github.com/dbt-msft/dbt-sqlserver/issues/{issue})"
103
+
104
+ [[tool.towncrier.type]]
105
+ directory = "behavior"
106
+ name = "Behavior changes"
107
+ showcontent = true
108
+
109
+ [[tool.towncrier.type]]
110
+ directory = "feature"
111
+ name = "Features"
112
+ showcontent = true
113
+
114
+ [[tool.towncrier.type]]
115
+ directory = "bugfix"
116
+ name = "Bugfixes"
117
+ showcontent = true
118
+
119
+ [[tool.towncrier.type]]
120
+ directory = "misc"
121
+ name = "Under the hood"
122
+ showcontent = true
123
+
97
124
  [tool.ruff]
98
125
  line-length = 99
99
126
  target-version = "py311"
@@ -1 +0,0 @@
1
- version = "1.11.2rc1"