This is an automated email from the ASF dual-hosted git repository.

lgbo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-gluten.git


The following commit(s) were added to refs/heads/main by this push:
     new 8ebd283434 simplify subtrait parsing (#8976)
8ebd283434 is described below

commit 8ebd283434810b08c6cc110b10703cbb75216997
Author: lgbo <[email protected]>
AuthorDate: Thu Mar 13 11:41:01 2025 +0800

    simplify subtrait parsing (#8976)
---
 .../local-engine/Builder/SerializedPlanBuilder.cpp |  8 -----
 cpp-ch/local-engine/Parser/ExpressionParser.cpp    | 11 +++---
 cpp-ch/local-engine/Parser/FunctionExecutor.cpp    |  6 ++--
 .../Parser/RelParsers/AggregateRelParser.cpp       |  8 +++--
 .../Parser/RelParsers/ExpandRelParser.cpp          | 14 ++++----
 .../Parser/RelParsers/GroupLimitRelParser.cpp      |  9 ++---
 .../Parser/RelParsers/JoinRelParser.cpp            | 42 ++++++++--------------
 .../Parser/RelParsers/MergeTreeRelParser.cpp       |  8 +++--
 .../Parser/RelParsers/SortParsingUtils.cpp         | 22 ++++++------
 .../local-engine/Parser/SerializedPlanParser.cpp   |  5 ++-
 .../local-engine/Parser/SubstraitParserUtils.cpp   | 41 +++++++++++++++++++++
 cpp-ch/local-engine/Parser/SubstraitParserUtils.h  |  9 +++++
 12 files changed, 110 insertions(+), 73 deletions(-)

diff --git a/cpp-ch/local-engine/Builder/SerializedPlanBuilder.cpp 
b/cpp-ch/local-engine/Builder/SerializedPlanBuilder.cpp
index be5a9ca4b0..f90bd12176 100644
--- a/cpp-ch/local-engine/Builder/SerializedPlanBuilder.cpp
+++ b/cpp-ch/local-engine/Builder/SerializedPlanBuilder.cpp
@@ -312,14 +312,6 @@ void SerializedPlanBuilder::buildType(const 
DB::DataTypePtr & ch_type, String &
     substrait_type = pb->SerializeAsString();
 }
 
-
-substrait::Expression * selection(int32_t field_id)
-{
-    substrait::Expression * rel = new substrait::Expression();
-    auto * selection = rel->mutable_selection();
-    
selection->mutable_direct_reference()->mutable_struct_field()->set_field(field_id);
-    return rel;
-}
 substrait::Expression * scalarFunction(int32_t id, ExpressionList args)
 {
     substrait::Expression * rel = new substrait::Expression();
diff --git a/cpp-ch/local-engine/Parser/ExpressionParser.cpp 
b/cpp-ch/local-engine/Parser/ExpressionParser.cpp
index 99bc5b3ff4..fb78066e8d 100644
--- a/cpp-ch/local-engine/Parser/ExpressionParser.cpp
+++ b/cpp-ch/local-engine/Parser/ExpressionParser.cpp
@@ -35,6 +35,7 @@
 #include <Parser/FunctionParser.h>
 #include <Parser/ParserContext.h>
 #include <Parser/SerializedPlanParser.h>
+#include <Parser/SubstraitParserUtils.h>
 #include <Parser/TypeParser.h>
 #include <Poco/Logger.h>
 #include <Common/BlockTypeUtils.h>
@@ -293,10 +294,11 @@ ExpressionParser::NodeRawConstPtr 
ExpressionParser::parseExpression(ActionsDAG &
         }
 
         case substrait::Expression::RexTypeCase::kSelection: {
-            if (!rel.selection().has_direct_reference() || 
!rel.selection().direct_reference().has_struct_field())
+            auto field_index = SubstraitParserUtils::getStructFieldIndex(rel);
+            if (!field_index)
                 throw DB::Exception(DB::ErrorCodes::BAD_ARGUMENTS, "Can only 
have direct struct references in selections");
 
-            const auto * field = 
actions_dag.getInputs()[rel.selection().direct_reference().struct_field().field()];
+            const auto * field = actions_dag.getInputs()[*field_index];
             return field;
         }
 
@@ -521,10 +523,9 @@ ExpressionParser::expressionsToActionsDAG(const 
std::vector<substrait::Expressio
 
     for (const auto & expr : expressions)
     {
-        if (expr.has_selection())
+        if (auto field_index = SubstraitParserUtils::getStructFieldIndex(expr))
         {
-            auto position = 
expr.selection().direct_reference().struct_field().field();
-            auto col_name = header.getByPosition(position).name;
+            auto col_name = header.getByPosition(*field_index).name;
             const DB::ActionsDAG::Node * field = 
actions_dag.tryFindInOutputs(col_name);
             if (!field)
                 throw DB::Exception(DB::ErrorCodes::LOGICAL_ERROR, "Not found 
{} in actions dag's output", col_name);
diff --git a/cpp-ch/local-engine/Parser/FunctionExecutor.cpp 
b/cpp-ch/local-engine/Parser/FunctionExecutor.cpp
index 2cef922ba4..93f30d55d5 100644
--- a/cpp-ch/local-engine/Parser/FunctionExecutor.cpp
+++ b/cpp-ch/local-engine/Parser/FunctionExecutor.cpp
@@ -19,6 +19,7 @@
 #include <Builder/SerializedPlanBuilder.h>
 #include <Core/ColumnWithTypeAndName.h>
 #include <Common/BlockTypeUtils.h>
+#include <Parser/SubstraitParserUtils.h>
 
 namespace DB
 {
@@ -57,10 +58,7 @@ void FunctionExecutor::buildExpression()
       [&](const auto & ) {
           substrait::FunctionArgument argument;
           auto * value = argument.mutable_value();
-          auto * selection = value->mutable_selection();
-          auto * direct_reference = selection->mutable_direct_reference();
-          auto * struct_field = direct_reference->mutable_struct_field();
-          struct_field->set_field(field++);
+          
value->CopyFrom(SubstraitParserUtils::buildStructFieldExpression(field++));
 
           arguments->Add(std::move(argument));
     });
diff --git a/cpp-ch/local-engine/Parser/RelParsers/AggregateRelParser.cpp 
b/cpp-ch/local-engine/Parser/RelParsers/AggregateRelParser.cpp
index ef98bba618..1cdf03091b 100644
--- a/cpp-ch/local-engine/Parser/RelParsers/AggregateRelParser.cpp
+++ b/cpp-ch/local-engine/Parser/RelParsers/AggregateRelParser.cpp
@@ -28,6 +28,7 @@
 #include <Operator/StreamingAggregatingStep.h>
 #include <Parser/AdvancedParametersParseUtil.h>
 #include <Parser/AggregateFunctionParser.h>
+#include <Parser/SubstraitParserUtils.h>
 #include <Processors/QueryPlan/AggregatingStep.h>
 #include <Processors/QueryPlan/ExpressionStep.h>
 #include <Processors/QueryPlan/MergingAggregatedStep.h>
@@ -186,10 +187,13 @@ void AggregateRelParser::setup(DB::QueryPlanPtr 
query_plan, const substrait::Rel
     if (aggregate_rel->groupings_size() == 1)
     {
         for (const auto & expr : 
aggregate_rel->groupings(0).grouping_expressions())
-            if (expr.has_selection() && 
expr.selection().has_direct_reference())
-                
grouping_keys.push_back(input_header.getByPosition(expr.selection().direct_reference().struct_field().field()).name);
+        {
+            auto field_index = SubstraitParserUtils::getStructFieldIndex(expr);
+            if (field_index)
+                
grouping_keys.push_back(input_header.getByPosition(*field_index).name);
             else
                 throw Exception(ErrorCodes::BAD_ARGUMENTS, "unsupported group 
expression: {}", expr.DebugString());
+        }
     }
     else if (aggregate_rel->groupings_size() != 0)
     {
diff --git a/cpp-ch/local-engine/Parser/RelParsers/ExpandRelParser.cpp 
b/cpp-ch/local-engine/Parser/RelParsers/ExpandRelParser.cpp
index 7d31fcf2bc..d261bc5dd6 100644
--- a/cpp-ch/local-engine/Parser/RelParsers/ExpandRelParser.cpp
+++ b/cpp-ch/local-engine/Parser/RelParsers/ExpandRelParser.cpp
@@ -23,6 +23,7 @@
 #include <Operator/AdvancedExpandStep.h>
 #include <Operator/ExpandStep.h>
 #include <Parser/RelParsers/RelParser.h>
+#include <Parser/SubstraitParserUtils.h>
 #include <Processors/QueryPlan/QueryPlan.h>
 #include <Common/logger_useful.h>
 
@@ -83,18 +84,17 @@ ExpandField ExpandRelParser::buildExpandField(const 
DB::Block & header, const su
         for (int i = 0; i < expand_col_size; ++i)
         {
             const auto & project_expr = 
projections.switching_field().duplicates(i);
-            if (project_expr.has_selection())
+            if (auto field_index = 
SubstraitParserUtils::getStructFieldIndex(project_expr))
             {
-                auto field = 
project_expr.selection().direct_reference().struct_field().field();
                 kinds.push_back(ExpandFieldKind::EXPAND_FIELD_KIND_SELECTION);
-                fields.push_back(field);
-                if (field >= header.columns())
+                fields.push_back(*field_index);
+                if (*field_index >= header.columns())
                 {
                     throw DB::Exception(
-                        DB::ErrorCodes::LOGICAL_ERROR, "Field index out of 
range: {}, header: {}", field, header.dumpStructure());
+                        DB::ErrorCodes::LOGICAL_ERROR, "Field index out of 
range: {}, header: {}", *field_index, header.dumpStructure());
                 }
-                updateType(types[i], header.getByPosition(field).type);
-                const auto & name = header.getByPosition(field).name;
+                updateType(types[i], header.getByPosition(*field_index).type);
+                const auto & name = header.getByPosition(*field_index).name;
                 if (names[i].empty())
                 {
                     if (distinct_names.contains(name))
diff --git a/cpp-ch/local-engine/Parser/RelParsers/GroupLimitRelParser.cpp 
b/cpp-ch/local-engine/Parser/RelParsers/GroupLimitRelParser.cpp
index 6359959ebc..597d90adaa 100644
--- a/cpp-ch/local-engine/Parser/RelParsers/GroupLimitRelParser.cpp
+++ b/cpp-ch/local-engine/Parser/RelParsers/GroupLimitRelParser.cpp
@@ -36,6 +36,7 @@
 #include <Parser/AdvancedParametersParseUtil.h>
 #include <Parser/RelParsers/SortParsingUtils.h>
 #include <Parser/RelParsers/SortRelParser.h>
+#include <Parser/SubstraitParserUtils.h>
 #include <Processors/QueryPlan/ExpressionStep.h>
 #include <Processors/QueryPlan/FilterStep.h>
 #include <Processors/QueryPlan/QueryPlan.h>
@@ -100,8 +101,8 @@ static std::vector<size_t> parsePartitionFields(const 
google::protobuf::Repeated
 {
     std::vector<size_t> fields;
     for (const auto & expr : expressions)
-        if (expr.has_selection())
-            
fields.push_back(static_cast<size_t>(expr.selection().direct_reference().struct_field().field()));
+        if (auto field_index = SubstraitParserUtils::getStructFieldIndex(expr))
+            fields.push_back(*field_index);
         else if (expr.has_literal())
             continue;
         else
@@ -115,8 +116,8 @@ std::vector<size_t> parseSortFields(const 
google::protobuf::RepeatedPtrField<sub
     for (const auto sort_field : sort_fields)
         if (sort_field.expr().has_literal())
             continue;
-        else if (sort_field.expr().has_selection())
-            
fields.push_back(static_cast<size_t>(sort_field.expr().selection().direct_reference().struct_field().field()));
+        else if (auto field_index = 
SubstraitParserUtils::getStructFieldIndex(sort_field.expr()))
+            fields.push_back(*field_index);
         else
             throw DB::Exception(DB::ErrorCodes::BAD_ARGUMENTS, "Unknown 
expression: {}", sort_field.expr().DebugString());
     return fields;
diff --git a/cpp-ch/local-engine/Parser/RelParsers/JoinRelParser.cpp 
b/cpp-ch/local-engine/Parser/RelParsers/JoinRelParser.cpp
index 1842e8e107..9355777b44 100644
--- a/cpp-ch/local-engine/Parser/RelParsers/JoinRelParser.cpp
+++ b/cpp-ch/local-engine/Parser/RelParsers/JoinRelParser.cpp
@@ -31,6 +31,7 @@
 #include <Parser/AdvancedParametersParseUtil.h>
 #include <Parser/ExpressionParser.h>
 #include <Parsers/ASTIdentifier.h>
+#include <Parser/SubstraitParserUtils.h>
 #include <Processors/QueryPlan/ExpressionStep.h>
 #include <Processors/QueryPlan/FilterStep.h>
 #include <Processors/QueryPlan/JoinStep.h>
@@ -114,10 +115,9 @@ std::unordered_set<DB::JoinTableSide> 
JoinRelParser::extractTableSidesFromExpres
             table_sides.insert(table_sides_from_arg.begin(), 
table_sides_from_arg.end());
         }
     }
-    else if (expr.has_selection() && expr.selection().has_direct_reference() 
&& expr.selection().direct_reference().has_struct_field())
+    else if (auto field = SubstraitParserUtils::getStructFieldIndex(expr))
     {
-        auto pos = expr.selection().direct_reference().struct_field().field();
-        if (pos < left_header.columns())
+        if (*field < left_header.columns())
             table_sides.insert(DB::JoinTableSide::Left);
         else
             table_sides.insert(DB::JoinTableSide::Right);
@@ -272,15 +272,10 @@ DB::QueryPlanPtr JoinRelParser::parseJoin(const 
substrait::JoinRel & join, DB::Q
                 auto input_header = left->getCurrentHeader();
                 DB::ActionsDAG 
filter_is_not_null_dag{input_header.getColumnsWithTypeAndName()};
                 // when is_null_aware_anti_join is true, there is only one 
join key
-                const auto * key_field = 
filter_is_not_null_dag.getInputs()[join.expression()
-                                                                               
 .scalar_function()
-                                                                               
 .arguments()
-                                                                               
 .at(0)
-                                                                               
 .value()
-                                                                               
 .selection()
-                                                                               
 .direct_reference()
-                                                                               
 .struct_field()
-                                                                               
 .field()];
+                auto field_index = 
SubstraitParserUtils::getStructFieldIndex(join.expression().scalar_function().arguments(0).value());
+                if (!field_index)
+                    throw DB::Exception(DB::ErrorCodes::LOGICAL_ERROR, "The 
join key is not found in the expression.");
+                const auto * key_field = 
filter_is_not_null_dag.getInputs()[*field_index];
 
                 auto result_node = 
filter_is_not_null_dag.tryFindInOutputs(key_field->result_name);
                 // add a function isNotNull to filter the null key on the left 
side
@@ -480,12 +475,12 @@ void JoinRelParser::collectJoinKeys(
             size_t left_pos = 0, right_pos = 0;
             for (const auto & arg : 
current_expr->scalar_function().arguments())
             {
-                if (!arg.value().has_selection() || 
!arg.value().selection().has_direct_reference()
-                    || 
!arg.value().selection().direct_reference().has_struct_field())
+                auto field_index = 
SubstraitParserUtils::getStructFieldIndex(arg.value());
+                if (!field_index)
                 {
                     throw DB::Exception(DB::ErrorCodes::LOGICAL_ERROR, "A 
column reference is expected");
                 }
-                auto col_pos_ref = 
arg.value().selection().direct_reference().struct_field().field();
+                auto col_pos_ref = *field_index;
                 if (col_pos_ref < left_header.columns())
                 {
                     left_pos = col_pos_ref;
@@ -550,8 +545,7 @@ bool JoinRelParser::applyJoinFilter(
         std::vector<substrait::Expression> exprs;
         for (size_t i = 0; i < header.columns(); ++i)
         {
-            substrait::Expression expr;
-            
expr.mutable_selection()->mutable_direct_reference()->mutable_struct_field()->set_field(i);
+            substrait::Expression expr = 
SubstraitParserUtils::buildStructFieldExpression(i);
             exprs.emplace_back(expr);
         }
         return exprs;
@@ -680,23 +674,17 @@ bool JoinRelParser::couldRewriteToMultiJoinOnClauses(
         dfs_visit_and_expr(and_exprs, args[1].value());
     };
 
-    auto get_field_ref = [](const substrait::Expression & e) -> 
std::optional<Int32>
-    {
-        if (e.has_selection() && e.selection().has_direct_reference() && 
e.selection().direct_reference().has_struct_field())
-            return 
std::optional<Int32>(e.selection().direct_reference().struct_field().field());
-        return {};
-    };
     auto visit_equal_expr = [&](const substrait::Expression & e) -> 
std::optional<std::pair<String, String>>
     {
         if (!check_function("equals", e))
             return {};
         const auto & args = e.scalar_function().arguments();
-        auto l_field_ref = get_field_ref(args[0].value());
-        auto r_field_ref = get_field_ref(args[1].value());
+        auto l_field_ref = 
SubstraitParserUtils::getStructFieldIndex(args[0].value());
+        auto r_field_ref = 
SubstraitParserUtils::getStructFieldIndex(args[1].value());
         if (!l_field_ref.has_value() || !r_field_ref.has_value())
             return {};
-        size_t l_pos = static_cast<size_t>(*l_field_ref);
-        size_t r_pos = static_cast<size_t>(*r_field_ref);
+        size_t l_pos = *l_field_ref;
+        size_t r_pos = *r_field_ref;
         size_t l_cols = left_header.columns();
         size_t total_cols = l_cols + right_header.columns();
 
diff --git a/cpp-ch/local-engine/Parser/RelParsers/MergeTreeRelParser.cpp 
b/cpp-ch/local-engine/Parser/RelParsers/MergeTreeRelParser.cpp
index 7483627d29..4c8c59fe21 100644
--- a/cpp-ch/local-engine/Parser/RelParsers/MergeTreeRelParser.cpp
+++ b/cpp-ch/local-engine/Parser/RelParsers/MergeTreeRelParser.cpp
@@ -317,9 +317,11 @@ void MergeTreeRelParser::collectColumns(const 
substrait::Expression & rel, NameS
         }
 
         case substrait::Expression::RexTypeCase::kSelection: {
-            const size_t idx = 
rel.selection().direct_reference().struct_field().field();
-            if (const Names names = block.getNames(); names.size() > idx)
-                columns.insert(names[idx]);
+            auto idx = SubstraitParserUtils::getStructFieldIndex(rel);
+            if (!idx)
+                throw DB::Exception(DB::ErrorCodes::LOGICAL_ERROR, "Selection 
node must have direct reference.");
+            if (const Names names = block.getNames(); names.size() > *idx)
+                columns.insert(names[*idx]);
 
             return;
         }
diff --git a/cpp-ch/local-engine/Parser/RelParsers/SortParsingUtils.cpp 
b/cpp-ch/local-engine/Parser/RelParsers/SortParsingUtils.cpp
index 70cacf0633..c45849d972 100644
--- a/cpp-ch/local-engine/Parser/RelParsers/SortParsingUtils.cpp
+++ b/cpp-ch/local-engine/Parser/RelParsers/SortParsingUtils.cpp
@@ -20,6 +20,7 @@
 #include <Poco/Logger.h>
 #include <Common/Exception.h>
 #include <Common/logger_useful.h>
+#include <Parser/SubstraitParserUtils.h>
 
 namespace DB::ErrorCodes
 {
@@ -33,16 +34,18 @@ DB::SortDescription parseSortFields(const DB::Block & 
header, const google::prot
 {
     DB::SortDescription description;
     for (const auto & expr : expressions)
-        if (expr.has_selection())
+    {
+        auto field_index = SubstraitParserUtils::getStructFieldIndex(expr);
+        if (field_index)
         {
-            auto pos = 
expr.selection().direct_reference().struct_field().field();
-            const auto & col_name = header.getByPosition(pos).name;
+            const auto & col_name = header.getByPosition(*field_index).name;
             description.push_back(DB::SortColumnDescription(col_name, 1, -1));
         }
         else if (expr.has_literal())
             continue;
         else
             throw DB::Exception(DB::ErrorCodes::BAD_ARGUMENTS, "Unknow 
expression as sort field: {}", expr.DebugString());
+    }
     return description;
 }
 
@@ -58,17 +61,16 @@ DB::SortDescription parseSortFields(const DB::Block & 
header, const google::prot
         if (sort_field.expr().has_literal())
             continue;
 
-        if (!sort_field.expr().has_selection() || 
!sort_field.expr().selection().has_direct_reference()
-            || 
!sort_field.expr().selection().direct_reference().has_struct_field())
+        auto field_index = 
SubstraitParserUtils::getStructFieldIndex(sort_field.expr());
+        if(!field_index)
         {
             throw DB::Exception(DB::ErrorCodes::LOGICAL_ERROR, "Unsupport sort 
field");
         }
-        auto field_pos = 
sort_field.expr().selection().direct_reference().struct_field().field();
 
         auto direction_iter = direction_map.find(sort_field.direction());
         if (direction_iter == direction_map.end())
             throw DB::Exception(DB::ErrorCodes::LOGICAL_ERROR, "Unsuppor sort 
direction: {}", sort_field.direction());
-        const auto & col_name = header.getByPosition(field_pos).name;
+        const auto & col_name = header.getByPosition(*field_index).name;
         sort_descr.emplace_back(col_name, direction_iter->second.first, 
direction_iter->second.second);
     }
     return sort_descr;
@@ -86,13 +88,13 @@ buildSQLLikeSortDescription(const DB::Block & header, const 
google::protobuf::Re
         auto it = order_directions.find(sort_field.direction());
         if (it == order_directions.end())
             throw DB::Exception(DB::ErrorCodes::BAD_ARGUMENTS, "Unknow sort 
direction: {}", sort_field.direction());
-        if (!sort_field.expr().has_selection())
+        auto field_index = 
SubstraitParserUtils::getStructFieldIndex(sort_field.expr());
+        if (!field_index)
         {
             throw DB::Exception(
                 DB::ErrorCodes::BAD_ARGUMENTS, "Sort field must be a column 
reference. but got {}", sort_field.DebugString());
         }
-        auto ref = 
sort_field.expr().selection().direct_reference().struct_field().field();
-        const auto & col_name = header.getByPosition(ref).name;
+        const auto & col_name = header.getByPosition(*field_index).name;
         if (n)
             ostr << String(",");
         // the col_name may contain '#' which can may ch fail to parse.
diff --git a/cpp-ch/local-engine/Parser/SerializedPlanParser.cpp 
b/cpp-ch/local-engine/Parser/SerializedPlanParser.cpp
index 4fbe710eeb..cbe0e5089e 100644
--- a/cpp-ch/local-engine/Parser/SerializedPlanParser.cpp
+++ b/cpp-ch/local-engine/Parser/SerializedPlanParser.cpp
@@ -416,10 +416,9 @@ void NonNullableColumnsResolver::visitNonNullable(const 
substrait::Expression &
             visitNonNullable(scalar_function.arguments(1).value());
         }
     }
-    else if (expr.has_selection())
+    else if (auto field_index = 
SubstraitParserUtils::getStructFieldIndex(expr))
     {
-        const auto & selection = expr.selection();
-        auto column_pos = selection.direct_reference().struct_field().field();
+        const auto & column_pos = *field_index;
         auto column_name = header.getByPosition(column_pos).name;
         collected_columns.insert(column_name);
     }
diff --git a/cpp-ch/local-engine/Parser/SubstraitParserUtils.cpp 
b/cpp-ch/local-engine/Parser/SubstraitParserUtils.cpp
new file mode 100644
index 0000000000..055ec856c1
--- /dev/null
+++ b/cpp-ch/local-engine/Parser/SubstraitParserUtils.cpp
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <Parser/SubstraitParserUtils.h>
+#include "substrait/algebra.pb.h"
+namespace local_engine::SubstraitParserUtils
+{
+std::optional<size_t> getStructFieldIndex(const substrait::Expression & e)
+{
+    if (!e.has_selection())
+        return {};
+    const auto & select = e.selection();
+    if (!select.has_direct_reference())
+        return {};
+    const auto & ref = select.direct_reference();
+    if (!ref.has_struct_field())
+        return {};
+    return ref.struct_field().field();
+}
+
+substrait::Expression buildStructFieldExpression(size_t index)
+{
+    substrait::Expression e;
+    
e.mutable_selection()->mutable_direct_reference()->mutable_struct_field()->set_field(index);
+    return e;
+}
+
+}
diff --git a/cpp-ch/local-engine/Parser/SubstraitParserUtils.h 
b/cpp-ch/local-engine/Parser/SubstraitParserUtils.h
index c020d96d8e..a9e21ba579 100644
--- a/cpp-ch/local-engine/Parser/SubstraitParserUtils.h
+++ b/cpp-ch/local-engine/Parser/SubstraitParserUtils.h
@@ -17,9 +17,12 @@
 #pragma once
 
 #include <string>
+#include <optional>
 #include <google/protobuf/util/json_util.h>
 #include <google/protobuf/wrappers.pb.h>
+#include <substrait/plan.pb.h>
 #include <Common/Exception.h>
+#include "substrait/algebra.pb.h"
 
 namespace DB::ErrorCodes
 {
@@ -74,4 +77,10 @@ inline std::string toString(const google::protobuf::Any & 
any)
     sv.ParseFromString(any.value());
     return sv.value();
 }
+
+namespace SubstraitParserUtils
+{
+    std::optional<size_t> getStructFieldIndex(const substrait::Expression & e);
+    substrait::Expression buildStructFieldExpression(size_t index);
+}
 } // namespace local_engine


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to