1
1
#include " to_substrait.hpp"
2
2
3
+ #include " duckdb/catalog/catalog_entry/duck_table_entry.hpp"
3
4
#include " duckdb/common/constants.hpp"
4
5
#include " duckdb/common/enums/expression_type.hpp"
5
6
#include " duckdb/common/types/value.hpp"
7
+ #include " duckdb/execution/index/art/art_key.hpp"
6
8
#include " duckdb/function/table/table_scan.hpp"
9
+ #include " duckdb/parser/constraints/not_null_constraint.hpp"
7
10
#include " duckdb/planner/expression/list.hpp"
8
11
#include " duckdb/planner/filter/conjunction_filter.hpp"
9
12
#include " duckdb/planner/filter/constant_filter.hpp"
13
+ #include " duckdb/planner/filter/expression_filter.hpp"
14
+ #include " duckdb/planner/filter/in_filter.hpp"
15
+ #include " duckdb/planner/filter/dynamic_filter.hpp"
16
+ #include " duckdb/planner/filter/struct_filter.hpp"
10
17
#include " duckdb/planner/joinside.hpp"
11
18
#include " duckdb/planner/operator/list.hpp"
19
+ #include " duckdb/planner/operator/logical_set_operation.hpp"
12
20
#include " duckdb/planner/table_filter.hpp"
13
21
#include " duckdb/storage/statistics/base_statistics.hpp"
14
- #include " duckdb/catalog/catalog_entry/duck_table_entry.hpp"
15
- #include " duckdb/planner/operator/logical_set_operation.hpp"
16
22
#include " google/protobuf/util/json_util.h"
17
23
#include " substrait/algebra.pb.h"
18
24
#include " substrait/plan.pb.h"
19
- #include " duckdb/parser/constraints/not_null_constraint.hpp"
20
- #include " duckdb/execution/index/art/art_key.hpp"
21
25
22
26
namespace duckdb {
23
27
const std::unordered_map<std::string, std::string> DuckDBToSubstrait::function_names_remap = {
@@ -668,7 +672,7 @@ void DuckDBToSubstrait::DepthFirstNamesRecurse(vector<string> &names, const Logi
668
672
}
669
673
670
674
substrait::Expression *DuckDBToSubstrait::TransformIsNotNullFilter (uint64_t col_idx, const LogicalType &column_type,
671
- TableFilter &dfilter,
675
+ const TableFilter &dfilter,
672
676
const LogicalType &return_type) {
673
677
auto s_expr = new substrait::Expression ();
674
678
auto scalar_fun = s_expr->mutable_scalar_function ();
@@ -683,17 +687,58 @@ substrait::Expression *DuckDBToSubstrait::TransformIsNotNullFilter(uint64_t col_
683
687
return s_expr;
684
688
}
685
689
686
- substrait::Expression *DuckDBToSubstrait::TransformConjuctionAndFilter (uint64_t col_idx, LogicalType &column_type,
687
- TableFilter &dfilter, LogicalType &return_type) {
690
+ substrait::Expression *DuckDBToSubstrait::TransformIsNullFilter (uint64_t col_idx, const LogicalType &column_type,
691
+ const TableFilter &dfilter,
692
+ const LogicalType &return_type) {
693
+ auto s_expr = new substrait::Expression ();
694
+ auto scalar_fun = s_expr->mutable_scalar_function ();
695
+ vector<substrait::Type> args_types;
696
+
697
+ args_types.emplace_back (DuckToSubstraitType (column_type));
698
+
699
+ scalar_fun->set_function_reference (RegisterFunction (" is_null" , args_types));
700
+ auto s_arg = scalar_fun->add_arguments ();
701
+ CreateFieldRef (s_arg->mutable_value (), col_idx);
702
+ *scalar_fun->mutable_output_type () = DuckToSubstraitType (return_type);
703
+ return s_expr;
704
+ }
705
+
706
+ substrait::Expression *DuckDBToSubstrait::TransformStructExtractFilter (uint64_t col_idx, const LogicalType &column_type, const TableFilter &dfilter, const LogicalType &return_type) {
707
+ auto &struct_filter = dfilter.Cast <StructFilter>();
708
+
709
+ // Create a field reference to the child_idx within the struct
710
+ auto s_field_ref = new substrait::Expression ();
711
+ auto selection = new substrait::Expression_FieldReference ();
712
+ selection->mutable_direct_reference ()->mutable_struct_field ()->set_field (static_cast <int32_t >(struct_filter.child_idx ));
713
+ auto root_reference = new substrait::Expression_FieldReference_RootReference ();
714
+ selection->set_allocated_root_reference (root_reference);
715
+ s_field_ref->set_allocated_selection (selection);
716
+
717
+ // Now, apply the child filter to this new field reference
718
+ // The col_idx for the recursive call should be 0 because s_field_ref is now the "root" of the expression for the child filter
719
+ return TransformFilter (0 , StructType::GetChildType (column_type, struct_filter.child_idx ),
720
+ *struct_filter.child_filter , return_type);
721
+ }
722
+
723
+ substrait::Expression *DuckDBToSubstrait::TransformConjunctionAndFilter (uint64_t col_idx, const LogicalType &column_type,
724
+ const TableFilter &dfilter, const LogicalType &return_type) {
688
725
auto &conjunction_filter = dfilter.Cast <ConjunctionAndFilter>();
689
726
return CreateConjunction (conjunction_filter.child_filters , [&](const unique_ptr<TableFilter> &in) {
690
727
return TransformFilter (col_idx, column_type, *in, return_type);
691
728
});
692
729
}
693
730
731
+ substrait::Expression *DuckDBToSubstrait::TransformConjunctionOrFilter (uint64_t col_idx, const LogicalType &column_type,
732
+ const TableFilter &dfilter, const LogicalType &return_type) {
733
+ auto &conjunction_filter = dfilter.Cast <ConjunctionOrFilter>();
734
+ return CreateConjunction (conjunction_filter.child_filters , [&](const unique_ptr<TableFilter> &in) {
735
+ return TransformFilter (col_idx, column_type, *in, return_type);
736
+ }, " or" );
737
+ }
738
+
694
739
substrait::Expression *DuckDBToSubstrait::TransformConstantComparisonFilter (uint64_t col_idx,
695
740
const LogicalType &column_type,
696
- TableFilter &dfilter,
741
+ const TableFilter &dfilter,
697
742
const LogicalType &return_type) {
698
743
auto s_expr = new substrait::Expression ();
699
744
auto s_scalar = s_expr->mutable_scalar_function ();
@@ -737,19 +782,71 @@ substrait::Expression *DuckDBToSubstrait::TransformConstantComparisonFilter(uint
737
782
return s_expr;
738
783
}
739
784
740
- substrait::Expression *DuckDBToSubstrait::TransformFilter (uint64_t col_idx, LogicalType &column_type,
741
- TableFilter &dfilter, LogicalType &return_type) {
785
+ substrait::Expression *DuckDBToSubstrait::TransformInFilter (uint64_t col_idx, const LogicalType &column_type,
786
+ const TableFilter &dfilter, const LogicalType &return_type) {
787
+ auto s_expr = new substrait::Expression ();
788
+ auto &in_filter = dfilter.Cast <InFilter>();
789
+ auto singular_or_list = s_expr->mutable_singular_or_list ();
790
+
791
+ // Set the input expression (the column being filtered)
792
+ CreateFieldRef (singular_or_list->mutable_value (), col_idx);
793
+
794
+ // Add the options (the values in the IN list)
795
+ for (auto &constant_value : in_filter.values ) {
796
+ TransformConstant (constant_value, *singular_or_list->add_options ());
797
+ }
798
+
799
+ return s_expr;
800
+ }
801
+
802
+ substrait::Expression *DuckDBToSubstrait::TransformDynamicFilter (uint64_t col_idx, const LogicalType &column_type, const TableFilter &dfilter, const LogicalType &return_type) {
803
+ auto &dynamic_filter = dfilter.Cast <DynamicFilter>();
804
+ if (!dynamic_filter.filter_data || !dynamic_filter.filter_data ->filter ) {
805
+ throw InternalException (" Dynamic filter data or inner filter is null" );
806
+ }
807
+ // Dynamic filter wraps a ConstantFilter, so we transform the inner filter
808
+ return TransformConstantComparisonFilter (col_idx, column_type, *dynamic_filter.filter_data ->filter , return_type);
809
+ }
810
+
811
+ substrait::Expression *DuckDBToSubstrait::TransformExpressionFilter (uint64_t col_idx, const LogicalType &column_type, const TableFilter &dfilter, const LogicalType &return_type) {
812
+ auto s_expr = new substrait::Expression ();
813
+ auto &expr_filter = dfilter.Cast <ExpressionFilter>();
814
+
815
+ // Create a proper column reference for the ToExpression method
816
+ auto column_ref = make_uniq<BoundReferenceExpression>(column_type, col_idx);
817
+ auto bound_expr = expr_filter.ToExpression (*column_ref);
818
+
819
+ // Transform the properly bound expression
820
+ TransformExpr (*bound_expr, *s_expr);
821
+ return s_expr;
822
+ }
823
+
824
+ substrait::Expression *DuckDBToSubstrait::TransformFilter (uint64_t col_idx, const LogicalType &column_type,
825
+ const TableFilter &dfilter, const LogicalType &return_type) {
742
826
switch (dfilter.filter_type ) {
743
- case TableFilterType::IS_NOT_NULL:
744
- return TransformIsNotNullFilter (col_idx, column_type, dfilter, return_type);
745
827
case TableFilterType::CONJUNCTION_AND:
746
- return TransformConjuctionAndFilter (col_idx, column_type, dfilter, return_type);
828
+ return TransformConjunctionAndFilter (col_idx, column_type, dfilter, return_type);
829
+ case TableFilterType::CONJUNCTION_OR:
830
+ return TransformConjunctionOrFilter (col_idx, column_type, dfilter, return_type);
747
831
case TableFilterType::CONSTANT_COMPARISON:
748
832
return TransformConstantComparisonFilter (col_idx, column_type, dfilter, return_type);
833
+ case TableFilterType::DYNAMIC_FILTER:
834
+ return TransformDynamicFilter (col_idx, column_type, dfilter, return_type);
835
+ case TableFilterType::EXPRESSION_FILTER:
836
+ return TransformExpressionFilter (col_idx, column_type, dfilter, return_type);
837
+ case TableFilterType::IN_FILTER:
838
+ return TransformInFilter (col_idx, column_type, dfilter, return_type);
839
+ case TableFilterType::IS_NOT_NULL:
840
+ return TransformIsNotNullFilter (col_idx, column_type, dfilter, return_type);
841
+ case TableFilterType::IS_NULL:
842
+ return TransformIsNullFilter (col_idx, column_type, dfilter, return_type);
749
843
case TableFilterType::OPTIONAL_FILTER:
750
844
return nullptr ;
751
- default :
752
- throw InternalException (" Unsupported table filter type" );
845
+ case TableFilterType::STRUCT_EXTRACT:
846
+ return TransformStructExtractFilter (col_idx, column_type, dfilter, return_type);
847
+ default :
848
+ throw NotImplementedException (" Unsupported table filter type: %s" ,
849
+ EnumUtil::ToString (dfilter.filter_type ));
753
850
}
754
851
}
755
852
0 commit comments