Skip to content

GH-49792: [Format][FlightSQL][C++] Add dialect-related SqlInfo codes - #49796

Open
tokoko wants to merge 3 commits into
apache:mainfrom
tokoko:flight-sql-flags
Open

tokoko wants to merge 3 commits into
apache:mainfrom
tokoko:flight-sql-flags

Conversation

@tokoko

@tokoko tokoko commented Apr 18, 2026 •

Copy link
Copy Markdown

Rationale for this change

Fills gaps in SqlInfo dialect metadata for axes that clients need when compiling SQL per-backend. Motivation and use case in #49792.

What changes are included in this PR?

  • format/FlightSql.proto — four new int32_bitmask SqlInfo codes (577–580):
    • SQL_SUPPORTED_LIMIT_OFFSET (577) — row-limit and offset grammars: LIMIT n, LIMIT n OFFSET m, FETCH FIRST n ROWS ONLY, OFFSET m ROWS FETCH NEXT n ROWS ONLY, TOP n, plus a bit for whether the FETCH grammars are accepted without ORDER BY.
    • SQL_SUPPORTED_NULLS_ORDERING (578) — whether explicit NULLS FIRST / NULLS LAST is accepted.
    • SQL_SUPPORTED_LIKE_ESCAPE (579) — how % and _ are escaped in a LIKE pattern: ESCAPE clause and/or implicit backslash.
    • SQL_SUPPORTED_PARAMETER_MARKER (580) — parameter marker spellings in a prepared statement: ?, $1, :1, @p1.
  • cpp/src/arrow/flight/sql/types.h — the same codes and enums.
  • Bitmask, not scalar enum - Dialects often accept multiple forms (e.g. PostgreSQL accepts both LIMIT/OFFSET and OFFSET/FETCH). Follows the existing SQL_SUPPORTED_GROUP_BY / SupportedSqlGrammar convention — enum values are bit positions;
  • Enums are admittedly non-exhaustive. They are just enough to cover current use cases and leave room for other behavior.
  • SQL_SUPPORTED_NULLS_ORDERING (578) is intentionally distinct from the pre-existing SQL_NULL_ORDERING (507) — the latter reports the server's default null ordering; the new flag reports whether the explicit NULLS FIRST / NULLS LAST clause is accepted.
  • SQL_SUPPORTED_LIKE_ESCAPE (579) supersedes the pre-existing SQL_SUPPORTS_LIKE_ESCAPE_CLAUSE (523), which cannot describe a server that escapes without an ESCAPE clause.
  • SQL_SUPPORTED_BOOLEAN_LITERAL and SQL_SUPPORTED_DATETIME_LITERAL from the first revision are removed.

Are these changes tested?

No behavior change.

Are there any user-facing changes?

New SqlInfo codes and supporting enums available to clients and servers. Fully backwards-compatible; no existing codes or types change.

@tokoko
tokoko requested a review from lidavidm as a code owner April 18, 2026 21:02
@github-actions

Copy link
Copy Markdown

⚠️ GitHub issue #49792 has been automatically assigned in GitHub to PR creator.

@lidavidm lidavidm left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Seems reasonable to me. Do you want to start a discussion on the mailing list?

@lidavidm

lidavidm commented Jun 4, 2026

Copy link
Copy Markdown
Member

@CurtHagenlocher I think we talked about adding more dialect flags to ADBC before to help applications that have to generate SQL; is this the kind of thing you were envisioning?

@CurtHagenlocher

Copy link
Copy Markdown
Contributor

@CurtHagenlocher I think we talked about adding more dialect flags to ADBC before to help applications that have to generate SQL; is this the kind of thing you were envisioning?

My feelings are colored by the fact that the majority of my experience has been with ODBC where the flags are woefully inadequate (and often wrong). It's put me off of the "flags" approach entirely. I have the vague understanding that the JDBC flags are more extensive (and have been updated more recently) but I don't have the kind of personal experience with them which would convince me that it's a workable approach.

The Flight SQL flags don't have enough information to correctly encode a CHAR literal. I mention this not because I think it should be added but as an example of something fairly basic that's missing and which is suggestive of additional gaps.

@tokoko

tokoko commented Jun 6, 2026

Copy link
Copy Markdown
Author

@CurtHagenlocher I do get the sentiment, but I still think it's worth giving a shot. ADBC is still fresh enough that we should be able to cover most of the basic functionality in most drivers to create some value. We also might be able to create some sort of an ecosystem pressure I'm hoping. if spark, pbi, duckdb UX improves by providing enough of the sql metadata, there should be an incentive.

The way I'm looking at it, the only alternatives are:

  • substrait which would be ideal, but even bigger ask at this point for both applications to produce and drivers to consume. if the use case is entire query generation, I think substrait is probably the only way to go, but I think it's impractical to make even "simpler" pushdown sql generation dependent on substrait support.
  • every adbc consumer maintaining their own dialect definitions, essentially the same as flags approach that's not owned by drivers.

tokoko added a commit to tokoko/spark-adbc that referenced this pull request Sep 24, 2026
Align Q1-Q6 with the Spark SPIP template: plain-language Q1, non-goals
in Q2, merged problem statement into Q3, short Q4 with design detail
moved to Appendix B. Write path now points to partitioned bulk ingest
(apache/arrow-adbc#4317) and dialect handling to driver-reported
SqlInfo codes (apache/arrow#49796). Drop Q7/Q8 for now.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@tokoko
tokoko requested a review from pitrou as a code owner October 11, 2026 08:01
@tokoko

tokoko commented Oct 11, 2026

Copy link
Copy Markdown
Author

@ianmcook As you suggested I expanded the test suite quite of bit both in terms of drivers and use cases (different data types mainly) over in spark-adbc. I included all "proper" sql adbc drivers from dbc (plus gizmodata's oracle driver). There were additional gaps as @CurtHagenlocher predicted, mainly around literal building. To render literals correctly I would have needed all of these and maybe more:

Flag Why
Boolean literal TRUE/FALSE vs 1/0 (already in the PR)
Date/time literal DATE '...' vs bare string (already in the PR), and it has to hold for every such type and for fractional seconds
Timestamp with time zone literal Three spellings, none accepted everywhere. Some engines parse a spelling and silently drop the offset, and two have no working form at all
String literal escape Backslash is an escape character on MySQL, ClickHouse, SingleStore and Spark, so a literal backslash has to be doubled there and nowhere else
Non-ASCII string literal SQL Server needs N'...' or the characters are lost
Binary literal Seven spellings across the engines: X'..', 0x.., two different '\x..' string forms, HEXTORAW, UNHEX, FROM_HEX

So I've changed direction. Instead of describing literals, the PR now reports how to write a parameter marker (SQL_SUPPORTED_PARAMETER_MARKER: ?, $1, :1, @p1), so values are bound as Arrow data and the driver or server owns the conversion. That replaces all six flags above with one, and it doesn't grow when a new type or quirk shows up.

What remains is syntax that binding can't replace: limit/offset grammar, NULLS FIRST/LAST, and LIKE escaping.
Binding is not uniform in today's drivers:

  • In my tests it worked for every type on 9 of the 14 engines; the rest were driver bugs with specific types, which I think is a better kind of problem to have than missing flags. I'll go hunt those down in respective repos.
  • Spark driver doesn't support bind parameters at all, but that should be easily fixable.
  • ClickHouse only supports typed markers ({name:Type}), which a generic client can't write without knowing ClickHouse's type names. I opened Binding from a generic ADBC client ClickHouse/adbc_clickhouse#81 to ask about that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants