Skip to content

fix: more sql prepared statements and quoting#8431

Merged
mscolnick merged 5 commits intomainfrom
ms/sql-statments
Feb 23, 2026
Merged

fix: more sql prepared statements and quoting#8431
mscolnick merged 5 commits intomainfrom
ms/sql-statments

Conversation

@mscolnick
Copy link
Contributor

@mscolnick mscolnick commented Feb 23, 2026

  • Fix unsafe SQL identifier construction across ClickHouse, Redshift, Ibis, and DuckDB engines by replacing raw string interpolation with parameterized queries and proper identifier quoting
  • Add shared sql_quoting module with dialect-aware identifier quoting (double-quote for DuckDB/Redshift/Postgres, backtick for ClickHouse/MySQL) and a parser for quoted fully-qualified table names
  • Add execute_duckdb_sql helper that supports parameterized queries ($1, $2, ...) while preserving the kernel globals context that wrapped_sql provides

@vercel
Copy link

vercel bot commented Feb 23, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
marimo-docs Ready Ready Preview, Comment Feb 23, 2026 5:25pm

Request Review

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR hardens SQL execution across multiple engines by centralizing identifier quoting and replacing unsafe string interpolation with parameterized queries where supported.

Changes:

  • Added a shared marimo._sql.sql_quoting module for dialect-aware identifier quoting and parsing of fully-qualified table names.
  • Introduced execute_duckdb_sql to run parameterized DuckDB queries while preserving kernel globals context.
  • Updated Redshift, ClickHouse, Ibis, and SQL summaries code paths to use quoting and/or parameters instead of raw interpolation.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/_sql/test_sql_quoting.py New unit tests covering identifier/qualified-name quoting and FQN parsing.
marimo/_sql/utils.py Adds execute_duckdb_sql helper for parameterized DuckDB execution in kernel context.
marimo/_sql/sql_quoting.py New module implementing identifier quoting, qualified-name quoting, and FQN parsing.
marimo/_sql/engines/redshift.py Uses quote_qualified_name when querying row counts and columns.
marimo/_sql/engines/ibis.py Replaces interpolated information_schema query with parameterized execution.
marimo/_sql/engines/clickhouse.py Quotes database/table identifiers and switches system table lookup to parameters.
marimo/_data/sql_summaries.py Uses the new FQN parser + parameterized DuckDB queries for column type lookup.
marimo/_data/get_datasets.py Reuses shared DuckDB identifier quoting helper instead of local implementation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 139 to 144
# First, get the column info and data type
if "." in fully_qualified_table_name:
# Fully qualified table name
db_name, schema_name, table_name = _parse_fully_qualified_table_name(
db_name, schema_name, table_name = parse_fully_qualified_table_name(
fully_qualified_table_name
)
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

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

get_column_type decides “fully-qualified” vs “simple” table name using a raw "." in fully_qualified_table_name check. That means a single quoted identifier that legitimately contains dots (e.g. "my.table") will be treated as a 3-part name and then rejected by parse_fully_qualified_table_name. Consider trying to parse as FQN in a try/except and falling back to the simple-table path if parsing fails.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is maybe an existing bug that we can fix in a followup

Comment on lines +26 to +29
else:
# Default to double-quote (ANSI SQL standard)
escaped = identifier.replace('"', '""')
return f'"{escaped}"'
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think maybe we don't want to quote by default. It can fail/treated as literals for certain databasess

# Double-quote style: escape embedded " as ""
escaped = identifier.replace('"', '""')
return f'"{escaped}"'
elif dialect in ("clickhouse", "mysql"):
Copy link
Collaborator

Choose a reason for hiding this comment

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

should be able to include bigquery: https://docs.cloud.google.com/bigquery/docs/reference/standard-sql/lexical
quote with backticks

@mscolnick mscolnick merged commit 547e64e into main Feb 23, 2026
36 of 43 checks passed
@mscolnick mscolnick deleted the ms/sql-statments branch February 23, 2026 20:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants