Skip to content

Commit b7e0f08

Browse files
Fix CTE detection in empty-subquery wrap when leading comments are present (#621).
sqlserver__get_empty_subquery_sql wraps non-CTE select_sql in `select * from (...) dbt_sbq_tmp where 1 = 0` for contract-driven column introspection. The CTE short-circuit only fired when select_sql literally began with `with`, so a model with a leading -- or /* */ comment had its CTE wrapped in a subquery and failed with `Incorrect syntax near the keyword 'WITH'`. Strip line and block comments before the startswith check; the original select_sql is still what gets emitted. Adds a functional regression test covering three variants: line-comment + CTE, block-comment + CTE, and comment + non-CTE (to ensure the non-CTE wrap path still works).
1 parent 4b295d9 commit b7e0f08

2 files changed

Lines changed: 65 additions & 1 deletion

File tree

dbt/include/sqlserver/macros/adapters/columns.sql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{% macro sqlserver__get_empty_subquery_sql(select_sql, select_sql_header=none) %}
2-
{% if select_sql.strip().lower().startswith('with') %}
2+
{%- set select_sql_stripped = modules.re.sub('(?s)/\\*.*?\\*/|--[^\n]*\n', '', select_sql) -%}
3+
{% if select_sql_stripped.strip().lower().startswith('with') %}
34
{{ select_sql }}
45
{% else -%}
56
select * from (
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import pytest
2+
3+
from dbt.tests.util import run_dbt
4+
5+
model_with_line_comment_sql = """
6+
-- This is a comment before the WITH clause
7+
WITH input as (SELECT 1 as id)
8+
SELECT * FROM input
9+
"""
10+
11+
model_with_block_comment_sql = """
12+
/* This is a block comment before the WITH clause */
13+
WITH input as (SELECT 1 as id)
14+
SELECT * FROM input
15+
"""
16+
17+
model_without_cte_sql = """
18+
-- This is a comment before a non-CTE query
19+
SELECT 1 as id
20+
"""
21+
22+
model_yml = """
23+
version: 2
24+
models:
25+
- name: model_with_line_comment
26+
config:
27+
contract:
28+
enforced: true
29+
columns:
30+
- name: id
31+
data_type: int
32+
- name: model_with_block_comment
33+
config:
34+
contract:
35+
enforced: true
36+
columns:
37+
- name: id
38+
data_type: int
39+
- name: model_without_cte
40+
config:
41+
contract:
42+
enforced: true
43+
columns:
44+
- name: id
45+
data_type: int
46+
"""
47+
48+
49+
class TestLeadingComments:
50+
@pytest.fixture(scope="class")
51+
def models(self):
52+
return {
53+
"model_with_line_comment.sql": model_with_line_comment_sql,
54+
"model_with_block_comment.sql": model_with_block_comment_sql,
55+
"model_without_cte.sql": model_without_cte_sql,
56+
"schema.yml": model_yml,
57+
}
58+
59+
def test_comments_before_cte(self, project):
60+
results = run_dbt(["run"])
61+
assert len(results) == 3
62+
for result in results:
63+
assert result.status == "success", f"{result.node.name} failed"

0 commit comments

Comments
 (0)