{"record":{"id":"2dd8c1fd8b3237ba","repo":"risingwavelabs/risingwave","slug":"call-predicate-pushdown-of-the-planref-instead-of","errorCode":null,"errorMessage":"call predicate_pushdown of the PlanRef instead of calling directly on LogicalShare","messagePattern":"call predicate_pushdown of the PlanRef instead of calling directly on LogicalShare","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/frontend/src/optimizer/plan_node/logical_share.rs","lineNumber":147,"sourceCode":"}\n\nimpl ColPrunable for LogicalShare {\n    fn prune_col(&self, _required_cols: &[usize], _ctx: &mut ColumnPruningContext) -> PlanRef {\n        unimplemented!(\"call prune_col of the PlanRef instead of calling directly on LogicalShare\")\n    }\n}\n\nimpl ExprRewritable<Logical> for LogicalShare {}\n\nimpl ExprVisitable for LogicalShare {}\n\nimpl PredicatePushdown for LogicalShare {\n    fn predicate_pushdown(\n        &self,\n        _predicate: Condition,\n        _ctx: &mut PredicatePushdownContext,\n    ) -> PlanRef {\n        unimplemented!(\n            \"call predicate_pushdown of the PlanRef instead of calling directly on LogicalShare\"\n        )\n    }\n}\n\nimpl ToBatch for LogicalShare {\n    fn to_batch(&self) -> Result<crate::optimizer::plan_node::BatchPlanRef> {\n        bail_not_implemented!(\"batch query doesn't support share operator for now\");\n    }\n}\n\nimpl ToStream for LogicalShare {\n    fn to_stream(\n        &self,\n        ctx: &mut ToStreamContext,\n    ) -> Result<crate::optimizer::plan_node::StreamPlanRef> {\n        match ctx.get_to_stream_result(self.share_id()) {\n            None => {","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/frontend/src/optimizer/plan_node/logical_share.rs#L129-L165","documentation":"`LogicalShare::predicate_pushdown` is deliberately `unimplemented!()`. Predicate pushdown into a shared subplan must be routed through `PlanRef::predicate_pushdown`, which special-cases LogicalShare so predicates are duplicated/filtered above the share rather than pushed incorrectly into it. Calling the trait method directly breaks the API contract.","triggerScenarios":"Calling `predicate_pushdown(cond, ctx)` directly on a `LogicalShare` value instead of on a `PlanRef` wrapping it.","commonSituations":"Encountered by developers extending the predicate pushdown rules who downcast to LogicalShare and invoke the trait method, bypassing the share-aware dispatch.","solutions":["Call `PlanRef::from(share.clone()).predicate_pushdown(cond, ctx)` so the share-aware implementation runs.","Keep predicate-pushdown code generic over `PlanRef` and avoid downcasting to LogicalShare before pushing predicates.","If a built-in rule triggers this, file a RisingWave optimizer bug."],"exampleFix":"// before\nlet pushed = logical_share.predicate_pushdown(cond, ctx);\n// after\nlet pushed = PlanRef::from(logical_share.clone()).predicate_pushdown(cond, ctx);\n","handlingStrategy":"type-guard","validationCode":"if node.as_logical_share().is_some() {\n    let node = PlanRef::from(node.clone());\n    // call node.predicate_pushdown(cond, ctx)\n}","typeGuard":"fn pushable_ref(plan: PlanRef) -> PlanRef {\n    assert!(plan.as_logical_share().is_none(), \"predicate_pushdown via PlanRef only\");\n    plan\n}","tryCatchPattern":null,"preventionTips":["Always push predicates through `PlanRef::predicate_pushdown`.","Avoid `as_logical_share()` downcasts inside pushdown rules.","Cover shared-subplan cases in rule tests.","Follow the existing share-aware code path in predicate_pushdown for LogicalPlanRef."],"tags":["rust","optimizer","unimplemented","predicate-pushdown","logical-share"],"backgroundTag":"method-not-implemented","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}