Repository navigation
Move Relational API to BindStatement - #697
Merged
Merged
Conversation
evertlammerts
force-pushed
the
relational-sql
branch
from
October 20, 2026 06:47
7a72333 to
cc48861
Compare
evertlammerts
force-pushed
the
relational-sql
branch
from
October 20, 2026 08:03
cc48861 to
c0507ff
Compare
evertlammerts
enabled auto-merge
October 20, 2026 08:18
evertlammerts
disabled auto-merge
October 20, 2026 09:09
1 task
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Core is replacing its C++ Relation classes with one primitive,
ClientContext::BindStatement. The Python relational API was built on those classes, bound eagerly through them, and could not express a lazy parameterised relation. This PR replaces that layer. It's a port that also changes behavior.A relation is now a value in Python: a step record, its inputs, a schema bound once when the step is built, its parameters, and handles on the Python objects it reads. It runs nothing until a terminal. Every step renders into one SELECT while SQL clause order allows, otherwise it closes that SELECT as a common table expression;
sql_query()is the text that runs. Names and types are whatever the engine's binder says. User SQL fragments are validated by the engine's parser and spliced as written.What changes for users:
col("s") == "x"compares with the text). A warning for one release when it matches a column name.sql()is lazy and binds its values on every read.distinct().project()does what it says; a filter after a limit applies after the limit.rel.query(name, sql)leaves no temporary view behind.nextval) runs at the call.materialize(),values()) is refused; userel.create()orcon.register().with_columns,drop,rename,unnest,unpivot,pivot,sample,head,offset,union_by_name,group_by().agg(),join(suffix=).Deleted:
DuckDBPyRelationand the expression classes in C++, every include of the engine's relation headers.Notes:
BEHAVIOR.mdon the branch.Next PRs: