You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Expose schema-aware semantic analysis through the C API
Summary
add C ABI entry points for column qualification, scope analysis, and requested output-column lineage;
accept the existing JSON AST plus an ordered schema transport matching MappingSchema's table paths;
parse schema type strings with the SQL parser rather than maintaining a second type grammar;
return explicit JSON views of the Rust semantic result types;
cover qualification, CTE scopes, and output lineage through the public FFI.
Motivation
Language bindings currently expose parsing, generation, and transpilation, but cannot use the schema-aware optimizer APIs already implemented by sql-glot-rust. Consumers consequently need to maintain a second native extension to call MappingSchema, qualify_columns, build_scope, and lineage.
These entry points keep the same JSON boundary used by the existing parse and generate functions. They expose the existing Rust concepts directly rather than adding a consumer-specific combined analyzer. Python sqlglot also supports requesting every top-level output lineage in one call; the Rust API currently builds lineage for one requested output column, and this C ABI keeps that single-result contract.
Schema JSON uses explicit identifier paths and ordered columns:
Paths are arrays so quoted identifiers containing dots are not confused with catalog or schema separators. Columns are arrays so wildcard expansion retains schema definition order. Type strings use the parser's data-type grammar, including lengths, precision, scale, timezone modifiers, arrays, and dialect-specific types.
The parser entry point is also exposed as parse_data_type(sql, dialect) -> Result<DataType>, analogous to Python sqlglot's DataType.from_str, so other Rust callers do not need to embed a type inside a synthetic statement.
The scope transport uses stable lowercase scope_type and tagged source objects ({"kind":"table", ...} / {"kind":"scope", ...}) instead of serializing Debug output.
sqlglot_lineage requires a non-NULL output column and returns one lineage graph. An all-output lineage operation would require a separate Rust API and C entry point so this function's input and result shapes remain stable.
All successful calls return heap-allocated JSON and use the existing sqlglot_free ownership contract. Invalid input or semantic errors return NULL, matching the existing C API.
Verification
cargo fmt --check is clean, and the full test suite and doctests pass with cargo test --features cli.
This is a great addition — exposing the schema-aware semantic APIs (qualify_columns, build_scope, lineage) plus a standalone parse_data_type through the C ABI closes a real gap for language bindings that previously had to maintain a second native extension. I especially appreciated the careful design: reusing the parser's data-type grammar instead of a second type grammar, the path-array schema transport so quoted identifiers with dots aren't split, stable tagged source objects instead of Debug output, and keeping the existing sqlglot_free ownership contract with NULL on invalid input.
Verified locally before merging:
Full test suite green with cargo test --features cli (all bins + doctests, 0 failures), including your new FFI coverage for qualification, CTE scopes, and output lineage — no regressions.
cargo fmt --check clean; no new clippy diagnostics in the added code.
Thanks again for the thorough PR and clear write-up! 🚀
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Expose schema-aware semantic analysis through the C API
Summary
MappingSchema's table paths;Motivation
Language bindings currently expose parsing, generation, and transpilation, but cannot use the schema-aware optimizer APIs already implemented by
sql-glot-rust. Consumers consequently need to maintain a second native extension to callMappingSchema,qualify_columns,build_scope, andlineage.These entry points keep the same JSON boundary used by the existing parse and generate functions. They expose the existing Rust concepts directly rather than adding a consumer-specific combined analyzer. Python sqlglot also supports requesting every top-level output lineage in one call; the Rust API currently builds lineage for one requested output column, and this C ABI keeps that single-result contract.
Schema JSON uses explicit identifier paths and ordered columns:
{ "tables": [ { "path": ["catalog", "schema", "cards"], "columns": [ {"name": "id", "data_type": "BIGINT"}, {"name": "amount", "data_type": "DECIMAL(18, 4)"} ] } ] }Paths are arrays so quoted identifiers containing dots are not confused with catalog or schema separators. Columns are arrays so wildcard expansion retains schema definition order. Type strings use the parser's data-type grammar, including lengths, precision, scale, timezone modifiers, arrays, and dialect-specific types.
The parser entry point is also exposed as
parse_data_type(sql, dialect) -> Result<DataType>, analogous to Python sqlglot'sDataType.from_str, so other Rust callers do not need to embed a type inside a synthetic statement.The scope transport uses stable lowercase
scope_typeand tagged source objects ({"kind":"table", ...}/{"kind":"scope", ...}) instead of serializingDebugoutput.API
sqlglot_lineagerequires a non-NULL output column and returns one lineage graph. An all-output lineage operation would require a separate Rust API and C entry point so this function's input and result shapes remain stable.All successful calls return heap-allocated JSON and use the existing
sqlglot_freeownership contract. Invalid input or semantic errors returnNULL, matching the existing C API.Verification
cargo fmt --checkis clean, and the full test suite and doctests pass withcargo test --features cli.