2020
2121#include < memory>
2222#include < string>
23+ #include < utility>
2324#include < vector>
2425
2526#include " arrow/api.h"
2627#include " paimon/common/predicate/compound_function.h"
2728#include " paimon/common/predicate/leaf_function.h"
2829#include " paimon/common/predicate/literal_converter.h"
30+ #include " paimon/common/predicate/literal_set.h"
2931#include " paimon/common/predicate/predicate_filter.h"
3032#include " paimon/common/utils/checked_cast.h"
3133#include " paimon/predicate/leaf_predicate.h"
@@ -35,7 +37,8 @@ class LeafPredicateImpl : public LeafPredicate, public PredicateFilter {
3537 LeafPredicateImpl (const LeafFunction& leaf_function, int32_t field_index,
3638 const std::string& field_name, const FieldType& field_type,
3739 const std::vector<Literal>& literals)
38- : LeafPredicate(leaf_function, field_index, field_name, field_type, literals) {}
40+ : LeafPredicateImpl(leaf_function, field_index, field_name, field_type, literals,
41+ BuildLiteralSet (leaf_function, field_type, literals)) {}
3942
4043 const LeafFunction& GetLeafFunction () const {
4144 return leaf_function_;
@@ -49,6 +52,11 @@ class LeafPredicateImpl : public LeafPredicate, public PredicateFilter {
4952 struct_array.fields ().size ()));
5053 }
5154 const auto & field_array = struct_array.field (field_index_);
55+ if (literal_set_ && literal_set_->MatchesArrowType (*field_array)) {
56+ std::vector<char > is_valid (field_array->length (), 0 );
57+ PAIMON_RETURN_NOT_OK (literal_set_->TestArray (*field_array, negate_in_, &is_valid));
58+ return is_valid;
59+ }
5260 return leaf_function_.Test (*field_array, literals_);
5361 }
5462
@@ -60,6 +68,9 @@ class LeafPredicateImpl : public LeafPredicate, public PredicateFilter {
6068 }
6169 PAIMON_ASSIGN_OR_RAISE (Literal value, LiteralConverter::ConvertLiteralsFromRow (
6270 schema, row, field_index_, field_type_));
71+ if (literal_set_ && value.GetType () == field_type_) {
72+ return literal_set_->TestValue (value, negate_in_);
73+ }
6374 return leaf_function_.Test (value, literals_);
6475 }
6576
@@ -86,14 +97,41 @@ class LeafPredicateImpl : public LeafPredicate, public PredicateFilter {
8697 return leaf_function_.Test (row_count, min_value, max_value, null_count, literals_);
8798 }
8899
100+ // Rebinding to another schema keeps the literals untouched, so the lookup structure is shared
101+ // instead of rebuilt for every reader.
89102 std::shared_ptr<LeafPredicateImpl> NewLeafPredicate (int32_t new_field_index) const {
90- return std::make_shared <LeafPredicateImpl>(leaf_function_, new_field_index, field_name_,
91- field_type_, literals_);
103+ return std::shared_ptr <LeafPredicateImpl>(new LeafPredicateImpl (
104+ leaf_function_, new_field_index, field_name_, field_type_, literals_, literal_set_) );
92105 }
93106
94107 std::shared_ptr<LeafPredicateImpl> NewLeafPredicate (const std::string& new_field_name) const {
95- return std::make_shared <LeafPredicateImpl>(leaf_function_, field_index_, new_field_name,
96- field_type_, literals_);
108+ return std::shared_ptr <LeafPredicateImpl>(new LeafPredicateImpl (
109+ leaf_function_, field_index_, new_field_name, field_type_, literals_, literal_set_) );
97110 }
111+
112+ private:
113+ LeafPredicateImpl (const LeafFunction& leaf_function, int32_t field_index,
114+ const std::string& field_name, const FieldType& field_type,
115+ const std::vector<Literal>& literals,
116+ std::shared_ptr<const LiteralSet> literal_set)
117+ : LeafPredicate(leaf_function, field_index, field_name, field_type, literals),
118+ literal_set_(std::move(literal_set)),
119+ negate_in_(leaf_function.GetType() == Function::Type::NOT_IN) {}
120+
121+ static std::shared_ptr<const LiteralSet> BuildLiteralSet (const LeafFunction& leaf_function,
122+ const FieldType& field_type,
123+ const std::vector<Literal>& literals) {
124+ Function::Type type = leaf_function.GetType ();
125+ if (type != Function::Type::IN && type != Function::Type::NOT_IN ) {
126+ return nullptr ;
127+ }
128+ return LiteralSet::CreateOrNull (field_type, literals);
129+ }
130+
131+ // Built once at construction time and never mutated afterwards, so concurrent `Test` calls on
132+ // the same predicate stay safe. Null when the type or the literals are not supported, in which
133+ // case every path falls back to `leaf_function_`.
134+ std::shared_ptr<const LiteralSet> literal_set_;
135+ bool negate_in_;
98136};
99137} // namespace paimon
0 commit comments