-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Initial version of extension to allow creating operators outside of duckdb core lib #5144
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initial version of extension to allow creating operators outside of duckdb core lib #5144
Conversation
src/planner/binder.cpp
Outdated
default: // LCOV_EXCL_START | ||
auto &config = DBConfig::GetConfig(context); | ||
|
||
for (auto &extension_op : config.operator_extensions) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the reason to throw here, then catch it and perform the exact same code that resulted in the throw again?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The NotImplementedException
is not of type StandardException
so it should not be caught.
Sorry for the lack of description when posting this PR. Create an accompanying document which I will add shortly. Primarily the PR was opened as a discussion aid for a meeting later today.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR! Looks good. Some comments:
src/planner/binder.cpp
Outdated
StatementTypeToString(statement.type)); | ||
} // LCOV_EXCL_STOP | ||
} catch (const StandardException &e) { | ||
auto &config = DBConfig::GetConfig(context); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We generally try to avoid try/catch
everywhere outside of at the "root" of query execution. Can this be removed? The extension should only throw an exception if there is an unrecoverable error (i.e. it failed to bind its own custom node) - in which case we want to propagate the exception upwards anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The primary reason for adding the try-catch block was to call the extension's bind functions when duckdb Binding fails. Realize on second glance that using the existing exception block in
duckdb/src/planner/planner.cpp
Line 49 in c0a4ab9
if (ex.what() != string("Parameter Not Resolved Error: Parameter types could not be resolved")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps I'm misunderstanding but what is the use case for wanting to call the extensions' bind function when DuckDB's bind function fails? Isn't that what the call to the extensions' bind in the switch statement is for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will remove the call insight the switch as it is confusing and I don't have a good case for it. The call in the switch is only triggered by unhandled statement types. I can see this being useful if the flow of the parser extension changes, so that it returns a SQLStatement that is parsed by DuckDB. However, as it stands there should not be unhandled statement types.
With the try/catch I intend to capture catalog misses & other bind exceptions (StandardException - that fail a query, but don't kill a transaction). So
insert into remote_foo values(1,2)
will trigger the call inside the catch if remote_foo is not a member of DuckDB's catalog.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aha, that makes sense. I'm fine with that at least as a temporary solution - but I think a cleaner solution would be implementing the extensible catalog & pluggable storage systems (although clearly a lot more work). Are there other use cases you have for this - or is it limited to only emulating a pluggable catalog for now?
public: | ||
//! Creates a plan for a new logical operator injected into duckdb via the OperatorExtension's bind function or | ||
// the optimizer extension | ||
create_plan_function_t CreatePlan; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this perhaps be implemented as virtual methods on the LogicalOperator
that are only used for the extension operators? It seems a bit tricky to know which extension knows how to handle which logical operator otherwise.
@rj-atw could you still have a look at fixing the tidy check issue and mark this as ready for review? |
ca7b019
to
89c7a79
Compare
@Mytherin Updated PR please take another look and merge if acceptable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me - happy to merge it, but one question remains from my side:
this->names = bound_statement.names; | ||
this->types = bound_statement.types; | ||
this->plan = move(bound_statement.plan); | ||
break; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Won't this still throw the exception - as this break only breaks out of the loop and into the throw
statement?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for taking close look at my PR. Indeed I staged my commit incorrectly and forgot the guard check. Doing another round of testing and will push the update.
…logical operator itself
817b405
to
cc2eff0
Compare
Thanks for the updates! |
* Use an inequality for the cardinality test to defend against zero LHS cardinalities fixes: duckdblabs/duckdb-internal#5144
* Use an inequality for the cardinality test to defend against zero LHS cardinalities fixes: duckdblabs/duckdb-internal#5144
* Use an inequality for the cardinality test to defend against zero LHS cardinalities fixes: duckdblabs/duckdb-internal#5144
* Use an inequality for the cardinality test to defend against zero LHS cardinalities fixes: duckdblabs/duckdb-internal#5144
Issue duckdb/duckdb#5144: AsOf Join Threshold (duckdb/duckdb#17978)
Issue duckdb/duckdb#5144: AsOf Join Threshold (duckdb/duckdb#17978) Co-authored-by: krlmlr <krlmlr@users.noreply.github.com>
Issue duckdb/duckdb#5144: AsOf Join Threshold (duckdb/duckdb#17979) [CI] Skip some workflows when updating out of tree extensions SHA (duckdb/duckdb#17949)
Issue duckdb/duckdb#5144: AsOf Join Threshold (duckdb/duckdb#17979) [CI] Skip some workflows when updating out of tree extensions SHA (duckdb/duckdb#17949) Co-authored-by: krlmlr <krlmlr@users.noreply.github.com>
Sorry for the lack of description when posting this draft PR. Create an accompanying document which I will add shortly. Primarily the PR was opened as a discussion aid for a meeting later today.