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

Supports prepare and execute statement #769

Closed
killme2008 opened this issue Dec 20, 2022 · 6 comments · Fixed by #4125
Closed

Supports prepare and execute statement #769

killme2008 opened this issue Dec 20, 2022 · 6 comments · Fixed by #4125
Assignees
Labels
C-feature Category Features good first issue Good for newcomers help wanted Extra attention is needed

Comments

@killme2008
Copy link
Contributor

killme2008 commented Dec 20, 2022

What problem does the new feature solve?

For example:

PREPARE v1 AS SELECT 'Test' LIMIT ?
EXECUTE v1(1)

May depend on #470

What does the feature do?

Supports prepare and execute statements.

Implementation challenges

No response

@killme2008 killme2008 added the C-feature Category Features label Dec 20, 2022
@killme2008 killme2008 mentioned this issue Dec 27, 2022
2 tasks
@MichaelScofield MichaelScofield self-assigned this Feb 15, 2023
@MichaelScofield MichaelScofield added good first issue Good for newcomers help wanted Extra attention is needed labels Feb 26, 2024
@MichaelScofield MichaelScofield removed their assignment Feb 26, 2024
@MichaelScofield
Copy link
Collaborator

Note that the "prepare" and "execute" statement in datafusion only support postgresql style. We can follow the postgresql's document for implementing this feature: https://www.postgresql.org/docs/current/sql-prepare.html

@MichaelScofield
Copy link
Collaborator

All other necessary features like plan cache and parameter type parsing and binding are implemented now, so I think this issue is relatively simple to Implement. Release to "good first issue".

@CookiePieWw
Copy link
Collaborator

Is this still active? If so, I'd like to take it :)

All stmts through client are treated as COM_QUERY so I wonder if it's appropriate to filter the prepare and execute out in the on_query here and fall back to on_prepare and on_execute:

async fn on_query<'a>(

@MichaelScofield
Copy link
Collaborator

@CookiePieWw On first thought, it's a viable option. Thanks for your interest, assigned.

@CookiePieWw
Copy link
Collaborator

@MichaelScofield I created a draft PR for this. Now I get stuck in 2 problems here:

  1. To execute a statement like EXECUTE stmt, we need to construct a map from the identifier of the statement to the stmt_id of the prepared one. I tried to add a field prepared_statements into QueryContext for that but it does not work actually. It seems I need to use the configuration_variables in Session for that? It's used in the SET variables stmt which may be similar.
  2. I'm struggling in parsing the parameters from the string EXECUTE stmt USING param1, ... into &[ScalarValue] which is used by LogicalPlan.replace_params_with_values. I'd like to assume there're some existing tools for it? A compromising plan is to use pure strings and fall back to do_query like it in on_execute.
    None => {
    let query = replace_params(params, sql_plan.query);
    debug!("Mysql execute replaced query: {}", query);
    self.do_query(&query, query_ctx.clone()).await
    }

Would you like to give me some advice? Thanks! :)

@MichaelScofield
Copy link
Collaborator

@MichaelScofield I created a draft PR for this. Now I get stuck in 2 problems here:

  1. To execute a statement like EXECUTE stmt, we need to construct a map from the identifier of the statement to the stmt_id of the prepared one. I tried to add a field prepared_statements into QueryContext for that but it does not work actually. It seems I need to use the configuration_variables in Session for that? It's used in the SET variables stmt which may be similar.
  2. I'm struggling in parsing the parameters from the string EXECUTE stmt USING param1, ... into &[ScalarValue] which is used by LogicalPlan.replace_params_with_values. I'd like to assume there're some existing tools for it? A compromising plan is to use pure strings and fall back to do_query like it in on_execute.
    None => {
    let query = replace_params(params, sql_plan.query);
    debug!("Mysql execute replaced query: {}", query);
    self.do_query(&query, query_ctx.clone()).await
    }

Would you like to give me some advice? Thanks! :)

@CookiePieWw :

  1. Better not touch the Session. What's feature of mysql stays in the crate of mysql. There's already a prepared_stmts: Arc<RwLock<HashMap<u32, SqlPlan>>> field in struct MysqlInstanceShim for similar purpose, we can reuse it. The prepared_stmts then serves storing two types of prepared stmt ids, one for the original implicit generated, the other for your explicit name in PREPARE. You can create an enum StmtKey for them. Just one caution: don't let the explicit stmt name clash with the implicit stmt id.
  2. We can treat all parameters in USING as strings, create ScalarValue::Utf8s from them, then cast them to the actual datatypes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-feature Category Features good first issue Good for newcomers help wanted Extra attention is needed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants