7272import com .starrocks .sql .optimizer .Optimizer ;
7373import com .starrocks .sql .optimizer .OptimizerConfig ;
7474import com .starrocks .sql .optimizer .OptimizerContext ;
75+ import com .starrocks .sql .optimizer .OptimizerTraceUtil ;
7576import com .starrocks .sql .optimizer .QueryMaterializationContext ;
7677import com .starrocks .sql .optimizer .Utils ;
7778import com .starrocks .sql .optimizer .base .ColumnRefFactory ;
@@ -1180,11 +1181,17 @@ public static OptExpression replaceLogicalViewScanOperator(OptExpression queryEx
11801181 // add a LogicalTreeAnchorOperator to replace the tree easier
11811182 OptExpression anchorExpr = OptExpression .create (new LogicalTreeAnchorOperator (), queryExpression );
11821183 doReplaceLogicalViewScanOperator (anchorExpr , 0 , queryExpression );
1184+
1185+ // check if there is any view scan operator in the tree
11831186 List <Operator > viewScanOperators = Lists .newArrayList ();
11841187 MvUtils .collectViewScanOperator (anchorExpr , viewScanOperators );
11851188 if (!viewScanOperators .isEmpty ()) {
1189+ OptimizerTraceUtil .logMVRewriteRule ("VIEW_BASED_MV_REWRITE" ,
1190+ "After replacing logical view scan operator but found view scan operator in the tree, "
1191+ + "so cannot rewrite the query expression: " + queryExpression );
11861192 return null ;
11871193 }
1194+
11881195 OptExpression newQuery = anchorExpr .inputAt (0 );
11891196 deriveLogicalProperty (newQuery );
11901197 return newQuery ;
@@ -1196,29 +1203,48 @@ private static void doReplaceLogicalViewScanOperator(OptExpression parent,
11961203 LogicalOperator op = queryExpression .getOp ().cast ();
11971204 if (op instanceof LogicalViewScanOperator ) {
11981205 LogicalViewScanOperator viewScanOperator = op .cast ();
1199- OptExpression viewPlan = viewScanOperator .getOriginalPlanEvaluator ();
1206+ OptExpression inlineViewPlan = viewScanOperator .getOriginalPlanEvaluator ();
12001207 if (viewScanOperator .getPredicate () != null ) {
1201- // If viewScanOperator contains predicate, we need to rewrite them,
1202- // otherwise predicate will be lost.
1203- Map <ColumnRefOperator , ScalarOperator > reverseColumnRefMap =
1204- viewScanOperator .getProjection ().getColumnRefMap ().entrySet ().stream ()
1205- .collect (Collectors .toMap (e -> (ColumnRefOperator ) e .getValue (), e -> e .getKey ()));
1206- ReplaceColumnRefRewriter rewriter = new ReplaceColumnRefRewriter (reverseColumnRefMap );
1207- Operator .Builder builder = OperatorBuilderFactory .build (viewPlan .getOp ());
1208- builder .withOperator (viewPlan .getOp ());
1209- // rewrite predicate
1210- builder .setPredicate (rewriter .rewrite (viewScanOperator .getPredicate ()));
1211- // rewrite projection
1212- Map <ColumnRefOperator , ScalarOperator > newColumnRefMap = viewScanOperator .getProjection ().getColumnRefMap ()
1208+ // original map records inlined view's column ref to non-inlined view's column ref mapping,
1209+ // now we need to rewrite non-inlined view's column ref to inlined view's column ref,
1210+ // so we need to reverse the mapping.
1211+ Map <ColumnRefOperator , ScalarOperator > originalColumnRefToInlinedColumnRefMap =
1212+ Maps .newHashMap (viewScanOperator .getOriginalColumnRefToInlinedColumnRefMap ());
1213+ // add new added column ref mapping
1214+ if (viewScanOperator .getProjection () != null ) {
1215+ viewScanOperator .getProjection ().getColumnRefMap ()
1216+ .entrySet ()
1217+ .stream ()
1218+ .forEach (e -> originalColumnRefToInlinedColumnRefMap .put (e .getKey (), e .getValue ()));
1219+ }
1220+ Map <ColumnRefOperator , ScalarOperator > reverseColumnRefMap = originalColumnRefToInlinedColumnRefMap
12131221 .entrySet ()
12141222 .stream ()
1215- .map (e -> Maps .immutableEntry (e .getKey (), rewriter .rewrite (e .getValue ())))
1216- .collect (Collectors .toMap (Map .Entry ::getKey , Map .Entry ::getValue ));
1217- builder .setProjection (new Projection (newColumnRefMap ));
1218- Operator newViewPlanOp = builder .build ();
1219- parent .setChild (index , OptExpression .create (newViewPlanOp , viewPlan .getInputs ()));
1223+ .collect (Collectors .toMap (e -> (ColumnRefOperator ) e .getValue (), e -> e .getKey ()));
1224+
1225+ // If viewScanOperator contains predicate, we need to rewrite them, otherwise predicate will be lost.
1226+ ReplaceColumnRefRewriter rewriter = new ReplaceColumnRefRewriter (reverseColumnRefMap );
1227+ Operator .Builder builder = OperatorBuilderFactory .build (inlineViewPlan .getOp ());
1228+ builder .withOperator (inlineViewPlan .getOp ());
1229+ if (viewScanOperator .getPredicate () != null ) {
1230+ // rewrite predicate
1231+ ScalarOperator rewrittenPredicate = rewriter .rewrite (viewScanOperator .getPredicate ());
1232+ builder .setPredicate (rewrittenPredicate );
1233+ }
1234+ // rewrite projection
1235+ if (viewScanOperator .getPredicate () != null ) {
1236+ Map <ColumnRefOperator , ScalarOperator > newColumnRefMap = viewScanOperator
1237+ .getProjection ().getColumnRefMap ()
1238+ .entrySet ()
1239+ .stream ()
1240+ .map (e -> Maps .immutableEntry (e .getKey (), rewriter .rewrite (e .getValue ())))
1241+ .collect (Collectors .toMap (Map .Entry ::getKey , Map .Entry ::getValue ));
1242+ builder .setProjection (new Projection (newColumnRefMap ));
1243+ }
1244+ Operator newInlineViewPlanOp = builder .build ();
1245+ parent .setChild (index , OptExpression .create (newInlineViewPlanOp , inlineViewPlan .getInputs ()));
12201246 } else {
1221- parent .setChild (index , viewPlan );
1247+ parent .setChild (index , inlineViewPlan );
12221248 }
12231249 return ;
12241250 }
0 commit comments