Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/dbt_core_interface/dbt_templater/templater.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ def dbt_version(self) -> str:
"""Gets the dbt version."""
return self._dbt_version.to_version_string()

def _apply_dbt_builtins(self, config: FluffConfig | None) -> bool:
"""DbtTemplater uses actual dbt compilation, not FunctionWrapper placeholders.

Returning False prevents SQLFluff from adding FunctionWrapper objects
(which lack .get() method) to the Jinja environment during slice_file analysis.
"""
return False

@large_file_check
def process( # pyright: ignore[reportIncompatibleMethodOverride]
self,
Expand Down
6 changes: 5 additions & 1 deletion src/dbt_core_interface/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import functools
import gc
import json
import re
import logging
import os
import shlex
Expand Down Expand Up @@ -76,7 +77,7 @@ def _set_invocation_context() -> None:
_set_invocation_context()

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logger.setLevel(getattr(logging, os.getenv("LOG_LEVEL", "INFO").upper(), logging.INFO))
logger.addHandler(rich.logging.RichHandler())

add_logger_to_manager(
Expand Down Expand Up @@ -674,6 +675,9 @@ def _create_temp_node(
self, sql: str, node_id: str | None = None
) -> tuple[ManifestNode, t.Callable[[], None]]:
"""Create a temporary node for SQL execution/compilation."""
# Remove only the opening and closing snapshot tags, keep the body
sql = re.sub(r'{%\s*snapshot\b.*?%}', '', sql, flags=re.DOTALL)
sql = re.sub(r'{%\s*endsnapshot\s*%}', '', sql, flags=re.DOTALL)
node_id = node_id or f"temp_node_{uuid.uuid4().hex[:8]}"
sql_node = self.sql_parser.parse_remote(sql, node_id)
process_node(self.runtime_config, self.manifest, sql_node)
Expand Down
42 changes: 31 additions & 11 deletions src/dbt_core_interface/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import json
import logging
import os
import re
import time
import typing as t
import uuid
Expand Down Expand Up @@ -284,17 +285,31 @@ def run_sql(
comp_res = runner.compile_sql(raw_sql)
try:
model_context = runner.generate_runtime_model_context(comp_res.node)
query = runner.adapter.execute_macro(
macro_name="get_show_sql",
macro_resolver=runner.manifest,
context_override=model_context,
kwargs={
"compiled_code": model_context["compiled_code"],
"sql_header": model_context["config"].get("sql_header"),
"limit": limit,
},
)
original_code = model_context["compiled_code"]
sql_header = model_context["config"].get("sql_header") or ""

# Check if query already has a LIMIT clause at the end - if so, execute as-is
query: str
has_limit = bool(re.search(r"\slimit\s+\d+(\s+offset\s+\d+)?\s*;?\s*$", original_code, re.IGNORECASE))

if has_limit:
query = f"{sql_header}\n{original_code}" if sql_header else original_code

else:
# Wrap in subquery to safely apply limit
compiled_code = f"select * from ({original_code}) as __server_query"
query = runner.adapter.execute_macro(
macro_name="get_show_sql",
macro_resolver=runner.manifest,
context_override=model_context,
kwargs={
"compiled_code": compiled_code,
"sql_header": sql_header,
"limit": limit,
},
)
exec_res = runner.execute_sql(t.cast(str, query), compile=False) # pyright: ignore[reportInvalidCast]

except Exception as e:
response.status_code = 500
return ServerErrorContainer(
Expand Down Expand Up @@ -469,9 +484,14 @@ def parse_project(


@app.get("/health") # legacy extension support
def health() -> dict[str, t.Any]:
"""Health check for vscode-sqlfluff extension. Always returns ready if server is running."""
return {"result": {"status": "ready"}}


@app.get("/api/v1/status")
def status(runner: DbtProject = Depends(_get_runner)) -> dict[str, t.Any]:
"""Health check endpoint to verify server status."""
"""Status endpoint with project details."""
return {
"result": {
"status": "ready",
Expand Down