Add table function to execute stored procedure in MySQL & SQLServer#15813
Add table function to execute stored procedure in MySQL & SQLServer#15813Praveen2112 wants to merge 1 commit intotrinodb:masterfrom
Conversation
If you're not filling the PR template, please remove it from the PR description so that it's obvious to the reader there there isn't any information to look for. Thanks |
|
@findepi Sorry for the confusion. Have updated the description. |
| Optional.empty()); | ||
| } | ||
|
|
||
| private List<JdbcColumnHandle> getColumns(ConnectorSession session, Connection connection, ResultSetMetaData metadata) |
There was a problem hiding this comment.
Will extract it to a new commit.
skrzypo987
left a comment
There was a problem hiding this comment.
Skimmed thoroughly. Looks good
| } | ||
| } | ||
|
|
||
| private static final class TableHandlesByProcedureCacheKey |
| public Optional<TableFunctionApplicationResult<ConnectorTableHandle>> applyTableFunction(ConnectorSession session, ConnectorTableFunctionHandle handle) | ||
| { | ||
| if (!(handle instanceof QueryFunctionHandle)) { | ||
| if (!(handle instanceof QueryFunctionHandle || handle instanceof ProcedureFunctionHandle)) { |
There was a problem hiding this comment.
nit:
I think it would be clearer to do:
if (handle instanceof QueryFunctionHandle queryFunctionHandle) {
...
else if (handle instanceof ProcedureFunctionHandle procedureFunctionHandle) {
...
}
else{
return Optional.empty();
}
| .map(ColumnSchema::getName) | ||
| .map(columnHandlesByName::get) | ||
| .collect(toImmutableList()); | ||
|
|
plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/JdbcProcedureRelationHandle.java
Show resolved
Hide resolved
|
|
||
| import static java.util.Objects.requireNonNull; | ||
|
|
||
| public final class ProcedureQuery |
| super( | ||
| SCHEMA_NAME, | ||
| NAME, | ||
| List.of(ScalarArgumentSpecification.builder() |
| } | ||
| } | ||
|
|
||
| public static class ProcedureFunctionHandle |
| assertThat(e).hasMessageMatching("Column name must be shorter than or equal to '128' characters but got '129': '.*'"); | ||
| } | ||
|
|
||
| @Test |
There was a problem hiding this comment.
These tests look very similar to the ones in MySQL connector. Is it reasonable to put them in jdbc module as an abstract class?
There was a problem hiding this comment.
Our initial implementation was to add in BaseJdbcConnectorTest - but not all JDBC based source supports it directly (Only MySQL and SqlServer returns a ResultSet - some of them works only with output parameter and some returns ResultSet with no fields. Plus both MySQL and SQLServer has a different way of creating and executing these stored procedures - and it might be some sort of overkill to merges these tests now.
There was a problem hiding this comment.
If you believe this is too much of a hassle, I am fine with leaving that as it is.
|
Thank you for an informative PR description, @Praveen2112 !
We don't need a separate function for that. Within ¹) this can be done without overhead for the common case, where query can be wrapped. Simply, instead of analyzing the query results, we can first ask the connector to analyze results of |
findepi
left a comment
There was a problem hiding this comment.
When writing my earlier #15813 (comment) i was overly focused on the query wrapping problem, which is only part of the problem.
As explained offline, the other part of the problem is the necessity to use the prepareCallable. For that reason, I agree that we cannot use the existing query pass-through table function and we indeed need a new function. Thank you @Praveen2112 for taking time to explain this to me.
To implement such a function, we should not use the JdbcTableHandle though. I think the best way would be not to implement io.trino.plugin.jdbc.DefaultJdbcMetadata#applyTableFunction and go with normal table function execution path. It's code complete (#15575) and already proven by @homar to work well.
| throws SQLException | ||
| { | ||
| if (table.getRelationHandle() instanceof JdbcProcedureRelationHandle jdbcProcedureRelationHandle) { | ||
| return queryBuilder.callProcedure(this, session, connection, jdbcProcedureRelationHandle.getProcedureQuery()); |
There was a problem hiding this comment.
Does this ignore all the attributes that may be set on table?
| { | ||
| JdbcTableHandle handle = (JdbcTableHandle) table; | ||
| if (handle.isProcedure()) { | ||
| return Optional.empty(); |
There was a problem hiding this comment.
That means handle is not really a table handle / a relation handle.
|
Closing in favor of #15982 |
Description
A dedicated table function which allows us to run stored procedures in MySQL and SQLServer. We can't use existing query table function - as it wraps with inside a query like
SELECT * FROM (CALL my_procedure()) o- so we are handing them via a different function. All the pushdown are disabled forTableHandleresolved by thisTableFunction.Limitation
ResultSetonly for the first statement. (Test to be added)Example
Release notes
( ) This is not user-visible or docs only and no release notes are required.
( ) Release notes are required, please propose a release note for me.
( ) Release notes are required, with the following suggested text: