Skip to content

feat: prefer query API sql param while preserving legacy params#3640

Open
msmithstubbs wants to merge 2 commits into
Logflare:mainfrom
msmithstubbs:feat/deprecate-query-legacy-params
Open

feat: prefer query API sql param while preserving legacy params#3640
msmithstubbs wants to merge 2 commits into
Logflare:mainfrom
msmithstubbs:feat/deprecate-query-legacy-params

Conversation

@msmithstubbs

@msmithstubbs msmithstubbs commented Jun 24, 2026

Copy link
Copy Markdown
Contributor
  • /api/query prefers sql param over language specific ch_sql|bq_sql|pg_sql params
  • When query is passed with sql and backend_id SQL languages is determined by the backend.
  • Preserve existing behaviour with deprecated params:
    • ch_sql and pg_sql without a backend_id will query first backend of that type
    • sql without a backend_id is mapped to bq_sql and the default system backend (BigQuery or other).

Follow on from #3093 comment

@msmithstubbs
msmithstubbs marked this pull request as ready for review June 25, 2026 00:13

backend_id = backend.id

expect(ClickHouseAdaptor, :execute_query, fn %{id: ^backend_id},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

running against a clickhouse instance is preferred as the stub makes the test more brittle to refactors of execute_query

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@msmithstubbs
msmithstubbs force-pushed the feat/deprecate-query-legacy-params branch 2 times, most recently from 2ce4cd5 to 931122b Compare June 26, 2026 03:21
Comment thread lib/logflare/endpoints.ex
),
{:ok, declared_params} <- Sql.parameters(expanded_query) do
{:ok, declared_params} <-
Sql.parameters(expanded_query, dialect: Sql.to_dialect(language)) do

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Running tests against Clickhouse instance revealed the language was not being passed to Sql.parameters/1

@spec extract_query(map()) :: {:ok, atom(), String.t()} | {:error, String.t()}
@spec extract_query(map()) ::
{:ok, :infer | :bq_sql | :ch_sql | :pg_sql, String.t()} | {:error, String.t()}
defp extract_query(%{"sql" => sql}), do: {:ok, :infer, sql}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Severity: MEDIUM

When bq_sql/ch_sql/pg_sql deprecated params are combined with a mismatched backend_id, the query is validated using the wrong SQL dialect but executed on the target backend. For example, bq_sql with a ClickHouse backend_id uses BigQuery SQL validation but runs on ClickHouse, potentially bypassing ClickHouse-specific SQL restrictions (e.g., system.* table access).
Helpful? Add 👍 / 👎

💡 Fix Suggestion

Suggestion: The root cause is in resolve_language/2 at lines 149–152, not in extract_query/1. The second clause defp resolve_language(language, _backend), do: language blindly returns the deprecated param's dialect (:bq_sql, :ch_sql, :pg_sql) even when an explicit backend has been resolved. Fix this by changing the first clause to match on a concrete %Backend{} struct (i.e. any non-nil backend) instead of only on :infer, so that whenever an explicit backend is present the dialect is always derived from that backend's actual type:

# Before:
defp resolve_language(:infer, backend),
  do: EndpointQuery.map_backend_to_language(backend, SingleTenant.supabase_mode?())

defp resolve_language(language, _backend), do: language

# After:
defp resolve_language(_language, %Backend{} = backend),
  do: EndpointQuery.map_backend_to_language(backend, SingleTenant.supabase_mode?())

defp resolve_language(language, _backend), do: language

With this change, if a caller sends bq_sql=...&backend_id=<clickhouse_id>, the resolved ClickHouse backend struct matches the first clause and the dialect is correctly set to :ch_sql — the deprecated param's hint is ignored. When no backend_id is provided (fetch_backend returns nil), the second clause still applies and the legacy param's dialect (:ch_sql, :pg_sql, etc.) is preserved for backward compatibility with the 'first backend of that type' routing.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, but that is the legacy behaviour.

@msmithstubbs
msmithstubbs force-pushed the feat/deprecate-query-legacy-params branch from 931122b to e2add22 Compare July 19, 2026 23:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants