Skip to content

Proposal: Split SQL and parameters in query endpoint #759

@cliftonc

Description

@cliftonc

I have just come across this project (as a long time Snowflake buyer / user) and am super excited by the potential, and started to build out a library for it for my open source BI platform (see https://www.drizby.com/), via https://github.com/cliftonc/drizzle-databend.

However, I immediately ran into what I think is potentially a major issue ...

The /v1/query HTTP endpoint currently accepts only a sql string field. Parameter binding is handled entirely client-side by bendsql: the driver parses the SQL AST to find placeholders (?, $1, :name), calls Param::as_sql_string() on each value, and sends the fully-interpolated SQL string to the server.

This architecture has inherent limitations:

  1. Security — every client library must independently implement correct escaping. Any new language SDK will face the same problem. Given the prevalence of SQL injection attacks I think this really could be a problem (I think there are also separate issues in your Param::as_sql_string() functions related to escaping that should be addressed for SQL Injection).
  2. Performance — the server cannot cache query plans across different parameter values since every execution is a unique SQL string.
  3. Type fidelity — values are serialized to SQL text and re-parsed by the server.

Proposal

Add a params field to the /v1/query request body:

  {
    "sql": "SELECT * FROM users WHERE name = $1 AND age > $2",
    "params": ["O'Brien", 42]
  }

The server would bind parameters directly, eliminating client-side interpolation. This is how PostgreSQL ($1), MySQL (?), and most databases handle HTTP/wire protocol parameters.

Without this, ORM drivers (e.g., drizzle-databend) must pre-escape string values before passing them to bendsql, and convert numeric strings to actual numbers based on column type metadata — effectively reimplementing parts of what server-side binding would provide.

This would be non breaking - as you can just omit it and the sql would still be sql. I'd be happy to look at implementing via a PR, but not sure what your status re. external contributions is?

Related? databendlabs/databend#8802

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions