\brief Simplify the given expression given this inequality as a guarantee.
| 1321 | |
| 1322 | /// \brief Simplify the given expression given this inequality as a guarantee. |
| 1323 | Result<Expression> Simplify(Expression expr) { |
| 1324 | const auto& guarantee = *this; |
| 1325 | |
| 1326 | auto call = expr.call(); |
| 1327 | if (!call) return expr; |
| 1328 | |
| 1329 | if (call->function_name == "is_valid" || call->function_name == "is_null") { |
| 1330 | if (guarantee.nullable) return expr; |
| 1331 | const auto& lhs = Comparison::StripOrderPreservingCasts(call->arguments[0]); |
| 1332 | if (!lhs.field_ref()) return expr; |
| 1333 | if (*lhs.field_ref() != guarantee.target) return expr; |
| 1334 | |
| 1335 | return call->function_name == "is_valid" ? literal(true) : literal(false); |
| 1336 | } |
| 1337 | |
| 1338 | if (call->function_name == "is_in") { |
| 1339 | ARROW_ASSIGN_OR_RAISE(std::optional<Expression> result, |
| 1340 | SimplifyIsIn(guarantee, call)); |
| 1341 | return result.value_or(expr); |
| 1342 | } |
| 1343 | |
| 1344 | auto cmp = Comparison::Get(expr); |
| 1345 | if (!cmp) return expr; |
| 1346 | |
| 1347 | auto rhs = call->arguments[1].literal(); |
| 1348 | if (!rhs) return expr; |
| 1349 | if (!rhs->is_scalar()) return expr; |
| 1350 | |
| 1351 | const auto& lhs = Comparison::StripOrderPreservingCasts(call->arguments[0]); |
| 1352 | if (!lhs.field_ref()) return expr; |
| 1353 | if (*lhs.field_ref() != guarantee.target) return expr; |
| 1354 | |
| 1355 | // Whether the RHS of the expression is EQUAL, LESS, or GREATER than the |
| 1356 | // RHS of the guarantee. N.B. Comparison::type is a bitmask |
| 1357 | ARROW_ASSIGN_OR_RAISE(const Comparison::type cmp_rhs_bound, |
| 1358 | Comparison::Execute(*rhs, guarantee.bound)); |
| 1359 | DCHECK_NE(cmp_rhs_bound, Comparison::NA); |
| 1360 | |
| 1361 | if (cmp_rhs_bound == Comparison::EQUAL) { |
| 1362 | // RHS of filter is equal to RHS of guarantee |
| 1363 | |
| 1364 | if ((*cmp & guarantee.cmp) == guarantee.cmp) { |
| 1365 | // guarantee is a subset of filter, so all data will be included |
| 1366 | // x > 1, x >= 1, x != 1 guaranteed by x > 1 |
| 1367 | return simplified_to(lhs, true); |
| 1368 | } |
| 1369 | |
| 1370 | if ((*cmp & guarantee.cmp) == 0) { |
| 1371 | // guarantee disjoint with filter, so all data will be excluded |
| 1372 | // x > 1, x >= 1 unsatisfiable if x == 1 |
| 1373 | return simplified_to(lhs, false); |
| 1374 | } |
| 1375 | |
| 1376 | return expr; |
| 1377 | } |
| 1378 | |
| 1379 | if (guarantee.cmp & cmp_rhs_bound) { |
| 1380 | // We guarantee (x (?) N) and are trying to simplify (x (?) M). We know |