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

feat(query): Procedure support drop if exists and create or replace #16500

Merged
merged 5 commits into from
Sep 26, 2024

Conversation

TCeason
Copy link
Collaborator

@TCeason TCeason commented Sep 23, 2024

I hereby agree to the terms of the CLA available at: https://docs.databend.com/dev/policies/cla/

Summary

  • support drop procedure if exists
  • support create or replace procedure

Part of #16501

Tests

  • Unit Test
  • Logic Test
  • Benchmark Test
  • No Test - Explain why

Type of change

  • Bug Fix (non-breaking change which fixes an issue)
  • New Feature (non-breaking change which adds functionality)
  • Breaking Change (fix or feature that could cause existing functionality not to work as expected)
  • Documentation Update
  • Refactoring
  • Performance Improvement
  • Other (please describe):

This change is Reviewable

@dosubot dosubot bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Sep 23, 2024
@github-actions github-actions bot added the pr-feature this PR introduces a new feature to the codebase label Sep 23, 2024
@dosubot dosubot bot added the A-query Area: databend query label Sep 23, 2024
@BohuTANG
Copy link
Member

Also need the syntax CREATE [ OR REPLACE ] PROCEDURE <name> ...

@TCeason
Copy link
Collaborator Author

TCeason commented Sep 23, 2024

Also need the syntax CREATE [ OR REPLACE ] PROCEDURE <name> ...

Yes create or replace already in plan. #16501

@TCeason TCeason changed the title feat(query): support drop procedure if exists feat(query): Procedure support drop if exists and create or replace Sep 24, 2024
@dosubot dosubot bot added the lgtm This PR has been approved by a maintainer label Sep 24, 2024
@TCeason TCeason force-pushed the drop_procedure branch 2 times, most recently from 5c099b9 to f4b3ec6 Compare September 24, 2024 14:36
Copy link
Member

@drmingdrmer drmingdrmer left a comment

Choose a reason for hiding this comment

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

Reviewed 5 of 7 files at r1, 2 of 2 files at r2, 1 of 1 files at r3, all commit messages.
Reviewable status: all files reviewed, 3 unresolved discussions (waiting on @sundy-li and @TCeason)


src/query/management/src/procedure/procedure_mgr.rs line 94 at r2 (raw file):

                    } else {
                        Err(AppError::from(name_ident.unknown_error(func_name!())).into())
                    }

IMHO, CreateOrReplace does not expect an unknown error. If there is no such record, it should just create one.

The above create_id_value() should be already enough. I do not get why this update_id_value is requried.

Code quote:

                    let res = self
                        .kv_api
                        .update_id_value(name_ident, meta.clone())
                        .await?;

                    if let Some((id, _meta)) = res {
                        Ok(CreateProcedureReply { procedure_id: *id })
                    } else {
                        Err(AppError::from(name_ident.unknown_error(func_name!())).into())
                    }

src/query/management/src/procedure/procedure_mgr.rs line 120 at r2 (raw file):

                return Err(AppError::from(name_ident.unknown_error("drop procedure")).into());
            }
        }

The if_exists flag only affects the response to the client; it does not influence operations on the meta-service.

This if_exists check should be moved up the call stack to the point where an Error response is actually required, either in the immediate caller or a higher-level caller.

Adn DropProcedureReq does not need if_exists at all.

Code quote:

        if dropped.is_none() {
            if req.if_exists {
                // Ok
            } else {
                return Err(AppError::from(name_ident.unknown_error("drop procedure")).into());
            }
        }

@dosubot dosubot bot removed the lgtm This PR has been approved by a maintainer label Sep 24, 2024
@TCeason
Copy link
Collaborator Author

TCeason commented Sep 24, 2024

Reviewed 5 of 7 files at r1, 2 of 2 files at r2, 1 of 1 files at r3, all commit messages.
Reviewable status: all files reviewed, 3 unresolved discussions (waiting on @sundy-li and @TCeason)

src/query/management/src/procedure/procedure_mgr.rs line 94 at r2 (raw file):

                    } else {
                        Err(AppError::from(name_ident.unknown_error(func_name!())).into())
                    }

IMHO, CreateOrReplace does not expect an unknown error. If there is no such record, it should just create one.

The above create_id_value() should be already enough. I do not get why this update_id_value is requried.

Code quote:

                    let res = self
                        .kv_api
                        .update_id_value(name_ident, meta.clone())
                        .await?;

                    if let Some((id, _meta)) = res {
                        Ok(CreateProcedureReply { procedure_id: *id })
                    } else {
                        Err(AppError::from(name_ident.unknown_error(func_name!())).into())
                    }

src/query/management/src/procedure/procedure_mgr.rs line 120 at r2 (raw file):

                return Err(AppError::from(name_ident.unknown_error("drop procedure")).into());
            }
        }

The if_exists flag only affects the response to the client; it does not influence operations on the meta-service.

This if_exists check should be moved up the call stack to the point where an Error response is actually required, either in the immediate caller or a higher-level caller.

Adn DropProcedureReq does not need if_exists at all.

Code quote:

        if dropped.is_none() {
            if req.if_exists {
                // Ok
            } else {
                return Err(AppError::from(name_ident.unknown_error("drop procedure")).into());
            }
        }

Ok, we can refactor these two function. e.g. add update_procedure API. If is replace , call update.

@dosubot dosubot bot added size:L This PR changes 100-499 lines, ignoring generated files. and removed size:M This PR changes 30-99 lines, ignoring generated files. labels Sep 25, 2024
@TCeason TCeason force-pushed the drop_procedure branch 2 times, most recently from 19834b5 to 7a9f382 Compare September 25, 2024 01:44
@TCeason TCeason requested a review from drmingdrmer September 25, 2024 03:24
Copy link
Member

@drmingdrmer drmingdrmer left a comment

Choose a reason for hiding this comment

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

Reviewed 4 of 6 files at r6, all commit messages.
Reviewable status: 10 of 12 files reviewed, 4 unresolved discussions (waiting on @sundy-li and @TCeason)


src/query/service/src/interpreters/interpreter_procedure_create.rs line 62 at r6 (raw file):

        let _ = UserApiProvider::instance()
            .add_procedure(&tenant, create_procedure_req, overriding)
            .await?;

The returned result should be consumed: with CreateOption::CreateIfNotExists, no error should be returned.

Code quote:

        let overriding = self.plan.create_option.is_overriding();

        let _ = UserApiProvider::instance()
            .add_procedure(&tenant, create_procedure_req, overriding)
            .await?;

Copy link
Member

@drmingdrmer drmingdrmer left a comment

Choose a reason for hiding this comment

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

The logic looks good to me. And I'd suggest avoiding using ErrorCode if possible.

Reviewed 11 of 11 files at r8, all commit messages.
Reviewable status: all files reviewed, 5 unresolved discussions (waiting on @sundy-li and @TCeason)


src/query/service/src/interpreters/interpreter_procedure_create.rs line 71 at r8 (raw file):

                return Err(e);
            }
        }

I'd suggest avoid using ErrorCode if possible. ErrorCode includes all kind of errors that makes it difficult to distinguish(by enumerate every of them) RPC error or logic error like PROCEDURE_ALREADY_EXISTS.

If add_procedure() returns KVAppError or Result<Result<..>>, the error handling like this would be easier.

Such as with Result<Result<T, LogicError>, MetaError>, a simple ? will filter out meta service errors that are not interested.

Code quote:

        if let Err(e) = UserApiProvider::instance()
            .add_procedure(&tenant, create_procedure_req, overriding)
            .await
        {
            if !(self.plan.create_option == CreateOption::CreateIfNotExists
                && e.code() == ErrorCode::PROCEDURE_ALREADY_EXISTS)
            {
                return Err(e);
            }
        }

@dosubot dosubot bot added the lgtm This PR has been approved by a maintainer label Sep 25, 2024
@TCeason
Copy link
Collaborator Author

TCeason commented Sep 26, 2024

The logic looks good to me. And I'd suggest avoiding using ErrorCode if possible.

Reviewed 11 of 11 files at r8, all commit messages.
Reviewable status: all files reviewed, 5 unresolved discussions (waiting on @sundy-li and @TCeason)

src/query/service/src/interpreters/interpreter_procedure_create.rs line 71 at r8 (raw file):

                return Err(e);
            }
        }

I'd suggest avoid using ErrorCode if possible. ErrorCode includes all kind of errors that makes it difficult to distinguish(by enumerate every of them) RPC error or logic error like PROCEDURE_ALREADY_EXISTS.

If add_procedure() returns KVAppError or Result<Result<..>>, the error handling like this would be easier.

Such as with Result<Result<T, LogicError>, MetaError>, a simple ? will filter out meta service errors that are not interested.

Code quote:

        if let Err(e) = UserApiProvider::instance()
            .add_procedure(&tenant, create_procedure_req, overriding)
            .await
        {
            if !(self.plan.create_option == CreateOption::CreateIfNotExists
                && e.code() == ErrorCode::PROCEDURE_ALREADY_EXISTS)
            {
                return Err(e);
            }
        }

Like this: 7213781?

Maybe we can refactor all procedure API in next pr that support alter procedure name?

@drmingdrmer
Copy link
Member

Like this: 7213781?

Maybe we can refactor all procedure API in next pr that support alter procedure name?

Yes, It would be alright with another PR:)

In the code snippet above, the outer Result should be a std::result::Result with MetaError as its error type. The current ErrorCode Result combines both logical errors and RPC errors, which can lead to confusion for the caller. Separating these error types will provide clearer error handling and improve the API's usability.

@TCeason
Copy link
Collaborator Author

TCeason commented Sep 26, 2024

Also need the syntax CREATE [ OR REPLACE ] PROCEDURE <name> ...

I think we can merge this pr now. cc @BohuTANG

Copy link
Member

@drmingdrmer drmingdrmer left a comment

Choose a reason for hiding this comment

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

Reviewed 2 of 2 files at r9, all commit messages.
Reviewable status: all files reviewed, 4 unresolved discussions (waiting on @sundy-li and @TCeason)

@sundy-li sundy-li added this pull request to the merge queue Sep 26, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Sep 26, 2024
@sundy-li sundy-li added this pull request to the merge queue Sep 26, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Sep 26, 2024
@BohuTANG BohuTANG merged commit 7e14ac0 into databendlabs:main Sep 26, 2024
71 of 72 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-query Area: databend query lgtm This PR has been approved by a maintainer pr-feature this PR introduces a new feature to the codebase size:L This PR changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants