Skip to content
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

Support table functions with pushdown to connector #11336

Merged
merged 9 commits into from
May 10, 2022

Conversation

kasiafi
Copy link
Member

@kasiafi kasiafi commented Mar 4, 2022

#1839

This PR introduces partial support for Table Functions (including Polymorphic Table Functions).

Temporarily, only constant scalar arguments are supported (no Table or Descriptor arguments).
The supported execution path for a Table Function is to be pushed down into connector, and replaced with a TableHandle.

Later, Descriptor and Table arguments will be supported, and operator-based execution will be enabled for Table Functions.

@kasiafi
Copy link
Member Author

kasiafi commented Mar 14, 2022

Sadly, not all jdbc-based connectors want to cooperate. Testing all to see what they need.

@kasiafi kasiafi changed the title Support table functions in grammar and AST Support table functions with pushdown to connector Mar 14, 2022
append(indent, "");
}
Node value = argument.getValue();
if (value instanceof TableArgument) {
Copy link
Member

Choose a reason for hiding this comment

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

Ideally, the formatting of each argument should be done by a recursive call to format each element, instead of switching on the specific concrete classes here.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done for all except Expression arguments. I order to be processed recursively, they would require wrapping in another AST node, which I considered too much overhead.

Comment on lines 1827 to 1831
if (context.qualifiedName() != null) {
table = new Table(getLocation(context.TABLE()), getQualifiedName(context.qualifiedName()));
}
else {
table = new TableSubquery(getLocation(context.TABLE()), (Query) visit(context.query()));
Copy link
Member

Choose a reason for hiding this comment

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

It'd be better to model these as sub-rules so that the construction occurs naturally by the recursive tree traversal instead of switching on whether qualifiedName is present or not

Copy link
Member Author

Choose a reason for hiding this comment

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

done

@kasiafi kasiafi requested a review from martint March 16, 2022 10:02
@kasiafi kasiafi force-pushed the 308PTF branch 3 times, most recently from 8c3cdc9 to a05ddd6 Compare March 18, 2022 11:15
@kasiafi kasiafi force-pushed the 308PTF branch 3 times, most recently from 149971a to b8aa8f0 Compare April 12, 2022 12:40
@kasiafi kasiafi mentioned this pull request Apr 13, 2022
54 tasks
@kasiafi kasiafi force-pushed the 308PTF branch 2 times, most recently from 34b3d71 to 907158e Compare April 26, 2022 12:33
catalogTableFunctions.remove(catalogName);
}

public TableFunction resolve(List<CatalogSchemaRoutineName> names)
Copy link
Member

Choose a reason for hiding this comment

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

Why is the argument a list of names?

Copy link
Member Author

Choose a reason for hiding this comment

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

Refactored so that the list is implementation detail in table function resolution.

for (Argument argument : arguments) {
ArgumentDeclaration declaration = declarationsByName.remove(argument.getName().get().getCanonicalValue());
if (declaration == null) {
throw semanticException(INVALID_FUNCTION_ARGUMENT, argument, "Unexpected argument name: ", argument.getName().get().getCanonicalValue());
Copy link
Member

Choose a reason for hiding this comment

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

There should be explicit validation to make sure the arguments provided to the function are not duplicated. This will catch that condition, but with an unclear error message.

@Override
public Result apply(TableFunctionNode tableFunctionNode, Captures captures, Context context)
{
Optional<TableHandle> result = plannerContext.getMetadata().applyTableFunction(context.getSession(), tableFunctionNode.getName(), tableFunctionNode.getHandle());
Copy link
Member

Choose a reason for hiding this comment

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

applyFunction should return a TableHandle and a list of ColumnHandle for that TH corresponding to the columns coming out of the original table function. This optimizer should not have to derive that from the table metadata, which may not actually exist for a "virtual" table.

public class TableFunctionNode
extends PlanNode
{
private final QualifiedObjectName name;
Copy link
Member

Choose a reason for hiding this comment

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

Why does this hold a name?

Copy link
Member Author

Choose a reason for hiding this comment

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

Refactored. Now the TableFunctionHandle holds the catalog name.

@kasiafi kasiafi force-pushed the 308PTF branch 2 times, most recently from 3325323 to 0acafc1 Compare May 1, 2022 07:58
@kasiafi
Copy link
Member Author

kasiafi commented May 1, 2022

@martint Applied comments

@kasiafi kasiafi requested a review from martint May 1, 2022 08:12
}
}

static String checkNotNullOrEmpty(String value, String name)
Copy link
Member

Choose a reason for hiding this comment

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

As a follow up - can we extract it to a common util method ?

@kasiafi kasiafi force-pushed the 308PTF branch 2 times, most recently from eec1b22 to a2139f7 Compare May 6, 2022 07:05
Copy link
Member

@martint martint left a comment

Choose a reason for hiding this comment

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

Great job. Let's merge everything in except for the functions added to the jdbc and elasticsearch connectors. We need to come up with a good name for them and make sure they have reasonable semantics -- I haven't had a chance to review them yet.

@kasiafi kasiafi merged commit 287e869 into trinodb:master May 10, 2022
@findepi findepi mentioned this pull request May 10, 2022
59 tasks
@github-actions github-actions bot added this to the 381 milestone May 10, 2022
@wendigo
Copy link
Contributor

wendigo commented May 10, 2022

Woah, nice job @kasiafi!

@mosabua
Copy link
Member

mosabua commented May 11, 2022

I am going to assume this needs to release notes entry or docs at this stage. Going forward can you maybe use the PR template to indicate that @kasiafi .. thanks

@kasiafi
Copy link
Member Author

kasiafi commented May 11, 2022

I am going to assume this needs to release notes entry or docs at this stage.

@mosabua this does need a release notes entry and docs. I'll add the proposed release notes entry in the relnotes issue. I'm currently working on the documentation -- it's likely we'll have to wait for it until the next release.

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

Successfully merging this pull request may close these issues.

5 participants