|
50 | 50 | import org.apache.doris.nereids.trees.expressions.functions.scalar.StructElement; |
51 | 51 | import org.apache.doris.nereids.trees.expressions.literal.Literal; |
52 | 52 | import org.apache.doris.nereids.trees.expressions.visitor.DefaultExpressionVisitor; |
| 53 | +import org.apache.doris.nereids.types.ArrayType; |
53 | 54 | import org.apache.doris.nereids.types.DataType; |
| 55 | +import org.apache.doris.nereids.types.MapType; |
54 | 56 | import org.apache.doris.nereids.types.NestedColumnPrunable; |
55 | 57 | import org.apache.doris.nereids.types.StructField; |
56 | 58 | import org.apache.doris.nereids.types.StructType; |
|
65 | 67 | import java.util.LinkedList; |
66 | 68 | import java.util.List; |
67 | 69 | import java.util.Map; |
| 70 | +import java.util.Map.Entry; |
68 | 71 | import java.util.Objects; |
69 | 72 | import java.util.Stack; |
70 | 73 |
|
@@ -135,7 +138,8 @@ public Void visitAlias(Alias alias, CollectorContext context) { |
135 | 138 | public Void visitCast(Cast cast, CollectorContext context) { |
136 | 139 | if (!context.accessPathBuilder.isEmpty() |
137 | 140 | && cast.getDataType() instanceof NestedColumnPrunable |
138 | | - && cast.child().getDataType() instanceof NestedColumnPrunable) { |
| 141 | + && cast.child().getDataType() instanceof NestedColumnPrunable |
| 142 | + && !mapTypeIsChanged(cast.child().getDataType(), cast.getDataType(), false)) { |
139 | 143 |
|
140 | 144 | DataTypeAccessTree castTree = DataTypeAccessTree.of(cast.getDataType(), TAccessPathType.DATA); |
141 | 145 | DataTypeAccessTree originTree = DataTypeAccessTree.of(cast.child().getDataType(), TAccessPathType.DATA); |
@@ -509,4 +513,46 @@ public int hashCode() { |
509 | 513 | return path.hashCode(); |
510 | 514 | } |
511 | 515 | } |
| 516 | + |
| 517 | + // if the map type is changed, we can not prune the type, because the map type need distinct the keys, |
| 518 | + // e.g. select map_values(cast(map(3.0, 1, 3.1, 2) as map<int, int>)); |
| 519 | + // the result is [2] because the keys: 3.0 and 3.1 will cast to 3 and the second entry remained. |
| 520 | + // backend will throw exception because it can not only access the values without the cast keys, |
| 521 | + // so we should check whether the map type is changed, if not changed, we can prune the type. |
| 522 | + private static boolean mapTypeIsChanged(DataType originType, DataType castType, boolean inMap) { |
| 523 | + if (originType.isMapType()) { |
| 524 | + MapType originMapType = (MapType) originType; |
| 525 | + MapType castMapType = (MapType) castType; |
| 526 | + if (mapTypeIsChanged(originMapType.getKeyType(), castMapType.getKeyType(), true) |
| 527 | + || mapTypeIsChanged(originMapType.getValueType(), castMapType.getValueType(), true)) { |
| 528 | + return true; |
| 529 | + } |
| 530 | + return false; |
| 531 | + } else if (originType.isStructType()) { |
| 532 | + StructType originStructType = (StructType) originType; |
| 533 | + StructType castStructType = (StructType) castType; |
| 534 | + List<Entry<String, StructField>> originFields |
| 535 | + = new ArrayList<>(originStructType.getNameToFields().entrySet()); |
| 536 | + List<Entry<String, StructField>> castFields |
| 537 | + = new ArrayList<>(castStructType.getNameToFields().entrySet()); |
| 538 | + |
| 539 | + for (int i = 0; i < originFields.size(); i++) { |
| 540 | + DataType originFieldType = originFields.get(i).getValue().getDataType(); |
| 541 | + DataType castFieldType = castFields.get(i).getValue().getDataType(); |
| 542 | + if (mapTypeIsChanged(originFieldType, castFieldType, inMap)) { |
| 543 | + return true; |
| 544 | + } |
| 545 | + } |
| 546 | + return false; |
| 547 | + } else if (originType.isArrayType()) { |
| 548 | + ArrayType originArrayType = (ArrayType) originType; |
| 549 | + ArrayType castArrayType = (ArrayType) castType; |
| 550 | + return mapTypeIsChanged(originArrayType.getItemType(), castArrayType.getItemType(), inMap); |
| 551 | + } else if (inMap) { |
| 552 | + return !originType.equals(castType); |
| 553 | + } else { |
| 554 | + // other type changed which not in map will not affect the map |
| 555 | + return false; |
| 556 | + } |
| 557 | + } |
512 | 558 | } |
0 commit comments