1#include "duckdb/optimizer/statistics_propagator.hpp"
2#include "duckdb/planner/expression/bound_cast_expression.hpp"
3
4namespace duckdb {
5
6static unique_ptr<BaseStatistics> StatisticsOperationsNumericNumericCast(const BaseStatistics &input,
7 const LogicalType &target) {
8 if (!NumericStats::HasMinMax(stats: input)) {
9 return nullptr;
10 }
11 Value min = NumericStats::Min(stats: input);
12 Value max = NumericStats::Max(stats: input);
13 if (!min.DefaultTryCastAs(target_type: target) || !max.DefaultTryCastAs(target_type: target)) {
14 // overflow in cast: bailout
15 return nullptr;
16 }
17 auto result = NumericStats::CreateEmpty(type: target);
18 result.CopyBase(orig: input);
19 NumericStats::SetMin(stats&: result, val: min);
20 NumericStats::SetMax(stats&: result, val: max);
21 return result.ToUnique();
22}
23
24static unique_ptr<BaseStatistics> StatisticsNumericCastSwitch(const BaseStatistics &input, const LogicalType &target) {
25 switch (target.InternalType()) {
26 case PhysicalType::INT8:
27 case PhysicalType::INT16:
28 case PhysicalType::INT32:
29 case PhysicalType::INT64:
30 case PhysicalType::INT128:
31 case PhysicalType::FLOAT:
32 case PhysicalType::DOUBLE:
33 return StatisticsOperationsNumericNumericCast(input, target);
34 default:
35 return nullptr;
36 }
37}
38
39unique_ptr<BaseStatistics> StatisticsPropagator::PropagateExpression(BoundCastExpression &cast,
40 unique_ptr<Expression> *expr_ptr) {
41 auto child_stats = PropagateExpression(expr&: cast.child);
42 if (!child_stats) {
43 return nullptr;
44 }
45 unique_ptr<BaseStatistics> result_stats;
46 switch (cast.child->return_type.InternalType()) {
47 case PhysicalType::INT8:
48 case PhysicalType::INT16:
49 case PhysicalType::INT32:
50 case PhysicalType::INT64:
51 case PhysicalType::INT128:
52 case PhysicalType::FLOAT:
53 case PhysicalType::DOUBLE:
54 result_stats = StatisticsNumericCastSwitch(input: *child_stats, target: cast.return_type);
55 break;
56 default:
57 return nullptr;
58 }
59 if (cast.try_cast && result_stats) {
60 result_stats->Set(StatsInfo::CAN_HAVE_NULL_VALUES);
61 }
62 return result_stats;
63}
64
65} // namespace duckdb
66