Uh oh!
There was an error while loading. Please reload this page.
fix: replace escapeSqlString with parameterized query binds in finops/schema - #277
Conversation
8fa79e5 to
2637b18Compare| const options: Record<string, unknown> = { query } | ||
| if (binds?.length) options.params = binds |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
2637b18 to
a56e670Compare| const stmtOptions: Record<string, any> = {} | ||
| if (binds?.length) { | ||
| stmtOptions.positionParameters = binds.map((v) => ({ value: v === null ? null : String(v) })) | ||
| } | ||
| const operation = await session.executeStatement(query, stmtOptions) |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
a56e670 to
c63ab04Compare| const options: Record<string, unknown> = { query } | ||
| if (isSelectLike && effectiveLimit && !/\bLIMIT\b/i.test(sql)) { | ||
| options.maxResults = effectiveLimit + 1 | ||
| } | ||
| if (binds?.length) options.params = binds | ||
| if (config.dataset) { |
There was a problem hiding this comment.
Bug: BigQuery queries will fail because LIMIT ? is not supported. The logic for detecting truncated results is also bypassed because the LIMIT keyword is now present in the SQL string.
Severity: CRITICAL
Suggested Fix
Remove the LIMIT ? placeholder from the BigQuery SQL templates. Instead, rely on the driver's existing mechanism which appends LIMIT and sets maxResults correctly. This will ensure the queries are valid and that truncation detection works as intended.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.
Location: packages/drivers/src/bigquery.ts#L37-L42
Potential issue: The BigQuery driver's `execute` method checks if a `LIMIT` clause is
present in the SQL to decide whether to set `options.maxResults` for truncation
detection. However, recent changes introduced SQL templates with a parameterized `LIMIT
?` clause. According to BigQuery documentation, using a parameter for the `LIMIT` clause
is not supported, which will cause all BigQuery finops queries (credit analysis,
expensive queries, query history) to fail at runtime. Additionally, because the SQL now
contains a `LIMIT` keyword, the driver's logic to detect truncated results by fetching
one extra row (`maxResults = effectiveLimit + 1`) is bypassed. This means that even if
the query were valid, the `truncated` flag would always be `false`.
c63ab04 to
2ea0e49Compare…/schema
Add `binds?: any[]` to `Connector.execute()` and implement parameterized
query support in Snowflake, DuckDB, BigQuery, and Databricks drivers.
Refactor all finops and schema builder functions to return `{ sql, binds }`
instead of interpolating user values directly into SQL strings. Remove
`sql-escape.ts` which is no longer used.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>…r SQL fixes, finops e2e tests
- snowflake.ts: normalize column names to lowercase at driver level
(rawColumns for value lookup, columns.map(toLowerCase) for keys)
- warehouse-advisor: remove warehouse_size from SNOWFLAKE_LOAD_SQL and
SNOWFLAKE_SIZING_SQL; source size via SHOW WAREHOUSES with silent fallback;
run load+sizing queries in parallel via Promise.all
- unused-resources: convert {days}/{limit} string interpolation to
parameterized binds (?, ?) for all Snowflake/BigQuery/Databricks queries
- tags.ts: remove non-existent 'comment' column from TAGS query
- drivers-snowflake-e2e.test.ts: update column assertions to lowercase
- Add finops-databricks-e2e.test.ts and finops-snowflake-e2e.test.ts
(12/12 and 17/17 pass respectively)
- schema-finops-dbt.test.ts: add regression tests for issue #203
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>2ea0e49 to
95942d4CompareUh oh!
There was an error while loading. Please reload this page.
…ery binds
Replace all remaining .replace("{placeholder}", ...) patterns with
parameterized ? placeholders and binds arrays across finops and schema
modules. Also migrates warehouse-advisor.ts which was missed in AltimateAI#277.
Updates tests to verify binds are passed correctly.
FixesAltimateAI#290…binds
Replaces `{days}` string interpolation in warehouse-advisor SQL
templates with `?` positional binds across Snowflake, BigQuery, and
Databricks warehouse-load and warehouse-sizing queries. `buildLoadSql`
and `buildSizingSql` now return `{ sql, binds }` and the call sites
in `adviseWarehouse` pass binds through to `connector.execute()`.
Postgres `{limit}` in query-history is kept as a rendered value with
`Math.floor(Number(limit))` because the Postgres connector's
execute() does not yet forward the `_binds` parameter. Filter
placeholder interpolations elsewhere in finops/schema are left as-is
per review feedback — tracked separately.
- `warehouse-advisor.ts`: 6× `{days}` → `?`, return types updated
- `query-history.ts`: comment clarifies why Postgres stays inline
- `schema-finops-dbt.test.ts`: updated for new `{ sql, binds }` shape
Continues the migration started in AltimateAI#277.…binds
Replaces `{days}` string interpolation in warehouse-advisor SQL
templates with `?` positional binds across Snowflake, BigQuery, and
Databricks warehouse-load and warehouse-sizing queries. `buildLoadSql`
and `buildSizingSql` now return `{ sql, binds }` and the call sites
in `adviseWarehouse` pass binds through to `connector.execute()`.
Postgres `{limit}` in query-history is kept as a rendered value with
`Math.floor(Number(limit))` because the Postgres connector's
execute() does not yet forward the `_binds` parameter. Filter
placeholder interpolations elsewhere in finops/schema are left as-is
per review feedback — tracked separately.
- `warehouse-advisor.ts`: 6× `{days}` → `?`, return types updated
- `query-history.ts`: comment clarifies why Postgres stays inline
- `schema-finops-dbt.test.ts`: updated for new `{ sql, binds }` shape
Continues the migration started in AltimateAI#277.…binds
Replaces `{days}` string interpolation in warehouse-advisor SQL
templates with `?` positional binds across Snowflake, BigQuery, and
Databricks warehouse-load and warehouse-sizing queries. `buildLoadSql`
and `buildSizingSql` now return `{ sql, binds }` and the call sites
in `adviseWarehouse` pass binds through to `connector.execute()`.
Postgres `{limit}` in query-history is kept as a rendered value with
`Math.floor(Number(limit))` because the Postgres connector's
execute() does not yet forward the `_binds` parameter. Filter
placeholder interpolations elsewhere in finops/schema are left as-is
per review feedback — tracked separately.
- `warehouse-advisor.ts`: 6× `{days}` → `?`, return types updated
- `query-history.ts`: comment clarifies why Postgres stays inline
- `schema-finops-dbt.test.ts`: updated for new `{ sql, binds }` shape
Continues the migration started in AltimateAI#277.
Add
binds?: any[]toConnector.execute()and implement parameterized query support in Snowflake, DuckDB, BigQuery, and Databricks drivers. Refactor all finops and schema builder functions to return{ sql, binds }instead of interpolating user values directly into SQL strings. Removesql-escape.tswhich is no longer used.Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com
Summary
What changed and why?
Test Plan
How was this tested?
Checklist