From b210714ccf211e112e6272531806c026af95534f Mon Sep 17 00:00:00 2001 From: Axell Padilla <68310020+axellpadilla@users.noreply.github.com> Date: Thu, 6 Aug 2026 17:55:20 -0600 Subject: [PATCH] fix: quote openquery's server name through adapter.quote() instead of hand-formatted brackets sqlserver__openquery emitted OPENQUERY([{{ server_name }}], ...), a hand- formatted bracket identifier that bypasses adapter.quote() and breaks the one-quoting-style guard from #785 (test_macros_do_not_hand_format_identifiers). Route it through adapter.quote() like every other macro-built identifier; SQL Server accepts a double-quoted linked-server name under QUOTED_IDENTIFIER ON (the adapter's default). Updates the functional test's compiled-SQL assertions to match the new quoting. --- dbt/include/sqlserver/macros/utils/openquery.sql | 2 +- tests/functional/adapter/mssql/test_openquery.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dbt/include/sqlserver/macros/utils/openquery.sql b/dbt/include/sqlserver/macros/utils/openquery.sql index 04b0f11b..461ad7a5 100644 --- a/dbt/include/sqlserver/macros/utils/openquery.sql +++ b/dbt/include/sqlserver/macros/utils/openquery.sql @@ -17,5 +17,5 @@ {{ exceptions.raise_compiler_error("openquery: query exceeds SQL Server OPENQUERY 8 KB limit (got " ~ (cleaned_sql | length) ~ " characters after escaping, max 8000). Use EXEC('...') AT or a remote view/OPENROWSET for longer queries.") }} {%- endif -%} {%- endif -%} - OPENQUERY([{{ server_name }}], '{{ cleaned_sql }}') + OPENQUERY({{ adapter.quote(server_name) }}, '{{ cleaned_sql }}') {%- endmacro %} diff --git a/tests/functional/adapter/mssql/test_openquery.py b/tests/functional/adapter/mssql/test_openquery.py index e959bfab..488d9ba7 100644 --- a/tests/functional/adapter/mssql/test_openquery.py +++ b/tests/functional/adapter/mssql/test_openquery.py @@ -203,9 +203,9 @@ def _run_all(self, project, _linked_server): return results def test_emits_openquery_and_returns_rows(self, project, _run_all): - """Happy path: bracketed server name, literal remote SQL, real rows.""" + """Happy path: quoted server name, literal remote SQL, real rows.""" sql = _find_compiled_sql(project, "basic_model.sql") - assert "OPENQUERY([LOCALLOOP], 'SELECT 1 AS id" in sql + assert 'OPENQUERY("LOCALLOOP", \'SELECT 1 AS id' in sql rows = project.run_sql( f"SELECT id, name FROM {project.test_schema}.basic_model ORDER BY id", fetch="all", @@ -216,21 +216,21 @@ def test_single_quotes_are_doubled_and_survive(self, project, _run_all): """Quotes are doubled in the emitted SQL, and the remote literal round-trips to the value it's.""" sql = _find_compiled_sql(project, "quotes_model.sql") - assert "OPENQUERY([LOCALLOOP], 'SELECT ''it''''s'' AS msg')" in sql + assert "OPENQUERY(\"LOCALLOOP\", 'SELECT ''it''''s'' AS msg')" in sql rows = project.run_sql(f"SELECT msg FROM {project.test_schema}.quotes_model", fetch="all") assert [row[0] for row in rows] == ["it's"] def test_carriage_returns_are_stripped_and_query_runs(self, project, _run_all): sql = _find_compiled_sql(project, "cr_model.sql") assert "\r" not in sql - assert "OPENQUERY([LOCALLOOP], 'SELECT 1" in sql + assert 'OPENQUERY("LOCALLOOP", \'SELECT 1' in sql rows = project.run_sql(f"SELECT id FROM {project.test_schema}.cr_model", fetch="all") assert [row[0] for row in rows] == [1] def test_max_length_boundary_compiles(self, project, _run_all): """Exactly 8000 escaped characters is allowed.""" sql = _find_compiled_sql(project, "max_length_model.sql") - assert "OPENQUERY([LOCALLOOP], 'SELECT " in sql + assert 'OPENQUERY("LOCALLOOP", \'SELECT ' in sql @pytest.mark.parametrize( "model_name,expected",