MCPcopy Create free account
hub / github.com/apache/arrow / SimplifyIsIn

Method SimplifyIsIn

cpp/src/arrow/compute/expression.cc:1257–1320  ·  view source on GitHub ↗

Simplify an `is_in` call against an inequality guarantee. We avoid the complexity of fully simplifying EQUAL comparisons to true literals (e.g., 'x is_in [1, 2, 3]' given the guarantee 'x = 2') due to potential complications with null matching behavior. This is ok for the predicate pushdown use case because the overall aim is to simplify to an unsatisfiable expression. \pre `is_in_call` is a cal

Source from the content-addressed store, hash-verified

1255 /// \pre `is_in_call` is a call to the `is_in` function
1256 /// \return a simplified expression, or nullopt if no simplification occurred
1257 static Result<std::optional<Expression>> SimplifyIsIn(
1258 const Inequality& guarantee, const Expression::Call* is_in_call) {
1259 DCHECK_EQ(is_in_call->function_name, "is_in");
1260
1261 auto options = checked_pointer_cast<SetLookupOptions>(is_in_call->options);
1262
1263 // The maximum number of values in the is_in expression set of values
1264 // in order to use the simplification.
1265 // If the set is large there are performance implications, see:
1266 // https://github.com/apache/arrow/issues/46777
1267 constexpr int16_t kIsInSimplificationMaxValueSet = 50;
1268 if (options->value_set.length() > kIsInSimplificationMaxValueSet) {
1269 return std::nullopt;
1270 }
1271
1272 const auto& lhs = Comparison::StripOrderPreservingCasts(is_in_call->arguments[0]);
1273 if (!lhs.field_ref()) return std::nullopt;
1274 if (*lhs.field_ref() != guarantee.target) return std::nullopt;
1275
1276 FilterOptions::NullSelectionBehavior null_selection{};
1277 switch (options->null_matching_behavior) {
1278 case SetLookupOptions::MATCH:
1279 null_selection =
1280 guarantee.nullable ? FilterOptions::EMIT_NULL : FilterOptions::DROP;
1281 break;
1282 case SetLookupOptions::SKIP:
1283 null_selection = FilterOptions::DROP;
1284 break;
1285 case SetLookupOptions::EMIT_NULL:
1286 if (guarantee.nullable) return std::nullopt;
1287 null_selection = FilterOptions::DROP;
1288 break;
1289 case SetLookupOptions::INCONCLUSIVE:
1290 if (guarantee.nullable) return std::nullopt;
1291 ARROW_ASSIGN_OR_RAISE(Datum is_null, IsNull(options->value_set));
1292 ARROW_ASSIGN_OR_RAISE(Datum any_null, Any(is_null));
1293 if (any_null.scalar_as<BooleanScalar>().value) return std::nullopt;
1294 null_selection = FilterOptions::DROP;
1295 break;
1296 }
1297
1298 std::string func_name = Comparison::GetName(guarantee.cmp);
1299 DCHECK_NE(func_name, "na");
1300 std::vector<Datum> args{options->value_set, guarantee.bound};
1301 ARROW_ASSIGN_OR_RAISE(Datum filter_mask, CallFunction(func_name, args));
1302 FilterOptions filter_options(null_selection);
1303 ARROW_ASSIGN_OR_RAISE(Datum simplified_value_set,
1304 Filter(options->value_set, filter_mask, filter_options));
1305
1306 if (simplified_value_set.length() == 0) return literal(false);
1307 if (simplified_value_set.length() == options->value_set.length()) return std::nullopt;
1308
1309 ExecContext exec_context;
1310 Expression::Call simplified_call;
1311 simplified_call.function_name = "is_in";
1312 simplified_call.arguments = is_in_call->arguments;
1313 simplified_call.options = std::make_shared<SetLookupOptions>(
1314 simplified_value_set, options->null_matching_behavior);

Callers

nothing calls this directly

Calls 6

field_refMethod · 0.80
IsNullFunction · 0.70
AnyFunction · 0.70
literalFunction · 0.70
ARROW_ASSIGN_OR_RAISEFunction · 0.50
lengthMethod · 0.45

Tested by

no test coverage detected