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

refactor(optimizer): type-safe plan base with compile-time convention check #13000

Merged
merged 15 commits into from
Oct 26, 2023

Conversation

BugenZhao
Copy link
Member

@BugenZhao BugenZhao commented Oct 23, 2023

Signed-off-by: Bugen Zhao [email protected]
I hereby agree to the terms of the RisingWave Labs, Inc. Contributor License Agreement.

What's changed and what's your intention?

Reviewing the following files should be sufficient:


Follow-up of #12980. This PR further makes PlanBase over a generic ConventionMarker.

pub struct PlanBase<C: ConventionMarker> {

As the result, the base field in the plan node struct will specify the corresponding ConventionMarker.

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct StreamHashAgg {
pub base: PlanBase<Stream>,

Any attempts to access fields with a mismatched convention (like logical_agg.emit_on_window_close() or stream_hash_agg.plan_base().order()) will be a compile error.

Accessing the PlanBase through PlanNodeMeta trait will now also get a type with specific convention, which makes the trait not object-safe anymore.

/// The trait for accessing the meta data and [`PlanBase`] for plan nodes.
pub trait PlanNodeMeta {
type Convention: ConventionMarker;
const NODE_TYPE: PlanNodeType;
/// Get the reference to the [`PlanBase`] with corresponding convention.
fn plan_base(&self) -> &PlanBase<Self::Convention>;

However, there're still a lot of places where PlanRef are directly worked on. To still allow erasing the type of a plan node, the original PlanNodeMeta turns into AnyPlanNodeMeta and is automatically implemented.

/// The object-safe version of [`PlanNodeMeta`], used as a super trait of [`PlanNode`].
///
/// Check [`PlanNodeMeta`] for more details.
pub trait AnyPlanNodeMeta {
fn node_type(&self) -> PlanNodeType;
fn plan_base(&self) -> PlanBaseRef<'_>;
fn convention(&self) -> Convention;
}
/// Implement [`AnyPlanNodeMeta`] for all [`PlanNodeMeta`].
impl<P> AnyPlanNodeMeta for P
where
P: PlanNodeMeta,
{
fn node_type(&self) -> PlanNodeType {
P::NODE_TYPE
}
fn plan_base(&self) -> PlanBaseRef<'_> {
PlanNodeMeta::plan_base_ref(self)
}
fn convention(&self) -> Convention {
P::Convention::value()
}
}

Future work may further explore reducing the usage of type-erased PlanRef. For example, we can at least constrain the convention for it.

Checklist

  • I have written necessary rustdoc comments
  • I have added necessary unit tests and integration tests
  • All checks passed in ./risedev check (or alias, ./risedev c)

Documentation

  • My PR needs documentation updates. (Please use the Release note section below to summarize the impact on users)

Release note

If this PR includes changes that directly affect users or other significant modifications relevant to the community, kindly draft a release note to provide a concise summary of these changes. Please prioritize highlighting the impact these changes will have on users.

Signed-off-by: Bugen Zhao

Base automatically changed from bz/immutable-plan-base to main October 24, 2023 06:31
@BugenZhao BugenZhao force-pushed the bz/type-safer-optimizer branch from c374187 to 93185e8 Compare October 24, 2023 06:32
Signed-off-by: Bugen Zhao <[email protected]>
Signed-off-by: Bugen Zhao <[email protected]>
Signed-off-by: Bugen Zhao <[email protected]>
Signed-off-by: Bugen Zhao <[email protected]>
Signed-off-by: Bugen Zhao <[email protected]>
Signed-off-by: Bugen Zhao <[email protected]>
Signed-off-by: Bugen Zhao <[email protected]>
Signed-off-by: Bugen Zhao <[email protected]>
@BugenZhao BugenZhao force-pushed the bz/type-safer-optimizer branch from 93185e8 to e6c55fe Compare October 24, 2023 06:36
Signed-off-by: Bugen Zhao <[email protected]>
Signed-off-by: Bugen Zhao <[email protected]>
@BugenZhao BugenZhao changed the title refactor(optimizer): type-safe plan base refactor(optimizer): type-safe plan base with compile-time convention check Oct 24, 2023
@BugenZhao BugenZhao marked this pull request as ready for review October 24, 2023 08:35
@BugenZhao BugenZhao requested a review from a team as a code owner October 24, 2023 08:35
Copy link
Contributor

@TennyZhuang TennyZhuang left a comment

Choose a reason for hiding this comment

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

LGTM!

Copy link
Member

@stdrc stdrc left a comment

Choose a reason for hiding this comment

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

LGTM

use super::utils::impl_distill_by_unit;
use super::{
generic, ExprRewritable, PlanBase, PlanRef, PlanTreeNodeUnary, ToBatchPb, ToDistributedBatch,
};
use crate::optimizer::plan_node::generic::PhysicalPlanRef;
Copy link
Member

Choose a reason for hiding this comment

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

Redundant import

Copy link
Contributor

@chenzl25 chenzl25 left a comment

Choose a reason for hiding this comment

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

Will take a look later. Compile error rather than runtime panic sounds pretty cool!

Copy link
Contributor

@chenzl25 chenzl25 left a comment

Choose a reason for hiding this comment

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

Rest LGTM!

Comment on lines +125 to 141
impl<P> AnyPlanNodeMeta for P
where
P: PlanNodeMeta,
{
fn node_type(&self) -> PlanNodeType {
P::NODE_TYPE
}

fn plan_base(&self) -> PlanBaseRef<'_> {
PlanNodeMeta::plan_base_ref(self)
}

fn convention(&self) -> Convention {
P::Convention::value()
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I am wondering whether we can expose a different property fetching interface for PlanRef to let developers know which (logical, batch or stream) properties they want to access explicitly. For example, plan_ref.batch_property().unwrap() to access the batch property with an explicit unwrap.

Copy link
Contributor

Choose a reason for hiding this comment

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

Because accessing a property in PlanRef could panic underlying potentially might require a very high code coverage rate to ensure them work well. Exposing an Option or Result can help developers realize what are they doing right now and the potential result. At least we can throw an Error instead of panicking the whole system.

Copy link
Member Author

Choose a reason for hiding this comment

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

let developers know which (logical, batch or stream) properties they want to access explicitly

Yeah, this is a good point. Several reasons for not doing this now:

  • I want to make the changes minimal in this PR.
  • We may first further explore if it's possible to constrain PlanRef to something like PlanRef<Convention>, to reduce the usages of accessing on the convention-erased plan.

Because accessing a property in PlanRef could panic underlying potentially might require a very high code coverage rate to ensure them work well.

Agree.

At least we can throw an Error instead of panicking the whole system.

That's not a big problem. We always catch the panic when handling a SQL statement, so panicking will not affect other active sessions.

@gitguardian
Copy link

gitguardian bot commented Oct 26, 2023

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secret in your pull request
GitGuardian id Secret Commit Filename
7648795 Generic CLI Secret b57e395 integration_tests/iceberg-cdc/run_test.sh View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

Our GitHub checks need improvements? Share your feedbacks!

@BugenZhao BugenZhao enabled auto-merge October 26, 2023 06:23
@BugenZhao BugenZhao added this pull request to the merge queue Oct 26, 2023
@codecov
Copy link

codecov bot commented Oct 26, 2023

Codecov Report

Merging #13000 (b57e395) into main (942e99d) will decrease coverage by 0.03%.
Report is 2 commits behind head on main.
The diff coverage is 87.24%.

@@            Coverage Diff             @@
##             main   #13000      +/-   ##
==========================================
- Coverage   68.33%   68.31%   -0.03%     
==========================================
  Files        1496     1498       +2     
  Lines      252058   252102      +44     
==========================================
- Hits       172253   172217      -36     
- Misses      79805    79885      +80     
Flag Coverage Δ
rust 68.31% <87.24%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files Coverage Δ
src/frontend/src/handler/explain.rs 79.19% <ø> (ø)
src/frontend/src/optimizer/mod.rs 92.21% <ø> (ø)
...c/frontend/src/optimizer/plan_node/batch_delete.rs 75.00% <100.00%> (ø)
...frontend/src/optimizer/plan_node/batch_exchange.rs 69.56% <ø> (ø)
...c/frontend/src/optimizer/plan_node/batch_expand.rs 46.34% <ø> (ø)
...c/frontend/src/optimizer/plan_node/batch_filter.rs 97.61% <ø> (ø)
...ontend/src/optimizer/plan_node/batch_group_topn.rs 58.97% <ø> (ø)
...frontend/src/optimizer/plan_node/batch_hash_agg.rs 96.84% <ø> (ø)
...rontend/src/optimizer/plan_node/batch_hash_join.rs 90.54% <ø> (ø)
...ontend/src/optimizer/plan_node/batch_hop_window.rs 75.49% <ø> (ø)
... and 84 more

... and 5 files with indirect coverage changes

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

Merged via the queue into main with commit efdf3c9 Oct 26, 2023
8 of 9 checks passed
@BugenZhao BugenZhao deleted the bz/type-safer-optimizer branch October 26, 2023 07:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants