@@ -70,36 +70,38 @@ VariantData ExpressionNode::compute(ProcessingUnit& seg) const {
70
70
}
71
71
}
72
72
73
- std::optional<DataType> ExpressionNode::compute (const ExpressionContext& expression_context,
74
- const ankerl::unordered_dense::map<std::string, DataType>& column_types) const {
75
- std::optional<DataType> res;
76
- std::optional<DataType> left_type = util::variant_match (
73
+ std::variant<BitSetTag, DataType> ExpressionNode::compute (
74
+ const ExpressionContext& expression_context,
75
+ const ankerl::unordered_dense::map<std::string, DataType>& column_types) const {
76
+ // Default to BitSetTag
77
+ std::variant<BitSetTag, DataType> res;
78
+ std::variant<BitSetTag, DataType> left_type = util::variant_match (
77
79
left_,
78
- [&column_types] (const ColumnName& column_name) -> std::optional< DataType> {
80
+ [&column_types] (const ColumnName& column_name) -> std::variant<BitSetTag, DataType> {
79
81
auto it = column_types.find (column_name.value );
80
82
schema::check<ErrorCode::E_COLUMN_DOESNT_EXIST>(it != column_types.end (),
81
83
" ProjectClause requires column '{}' to exist in input data"
82
84
,column_name.value );
83
85
return it->second ;
84
86
},
85
- [&expression_context] (const ValueName& value_name) -> std::optional< DataType> {
87
+ [&expression_context] (const ValueName& value_name) -> std::variant<BitSetTag, DataType> {
86
88
return expression_context.values_ .get_value (value_name.value )->data_type_ ;
87
89
},
88
- [&expression_context, &column_types] (const ExpressionName& expression_name) -> std::optional< DataType> {
90
+ [&expression_context, &column_types] (const ExpressionName& expression_name) -> std::variant<BitSetTag, DataType> {
89
91
auto expr = expression_context.expression_nodes_ .get_value (expression_name.value );
90
92
return expr->compute (expression_context, column_types);
91
93
},
92
- [] (auto &&) -> std::optional< DataType> {
94
+ [] (auto &&) -> std::variant<BitSetTag, DataType> {
93
95
internal::raise <ErrorCode::E_ASSERTION_FAILURE>(" Unexpected expression argument type" );
94
- return std::nullopt ;
96
+ return {} ;
95
97
}
96
98
);
97
99
if (is_unary_operation (operation_type_)) {
98
100
switch (operation_type_) {
99
101
case OperationType::ABS:
100
102
case OperationType::NEG:
101
- user_input::check<ErrorCode::E_INVALID_USER_ARGUMENT>(left_type. has_value ( ), " Unexpected bitset input to unary arithmetic operation" );
102
- details::visit_type (* left_type, [this , &res](auto tag) {
103
+ user_input::check<ErrorCode::E_INVALID_USER_ARGUMENT>(std::holds_alternative<DataType>(left_type ), " Unexpected bitset input to unary arithmetic operation" );
104
+ details::visit_type (std::get<DataType>( left_type) , [this , &res](auto tag) {
103
105
using type_info = ScalarTypeInfo<decltype (tag)>;
104
106
if constexpr (is_numeric_type (type_info::data_type)) {
105
107
if (operation_type_ == OperationType::ABS) {
@@ -119,60 +121,58 @@ std::optional<DataType> ExpressionNode::compute(const ExpressionContext& express
119
121
case OperationType::ISNULL:
120
122
case OperationType::NOTNULL:
121
123
user_input::check<ErrorCode::E_INVALID_USER_ARGUMENT>(
122
- left_type.has_value () && (is_floating_point_type (*left_type) || is_sequence_type (*left_type) ||
123
- is_time_type (*left_type)),
124
- " Unexpected data type input to unary comparison operation {}" ,
125
- left_type.has_value () ? *left_type : DataType::UNKNOWN);
124
+ std::holds_alternative<DataType>(left_type) && (is_floating_point_type (std::get<DataType>(left_type)) || is_sequence_type (std::get<DataType>(left_type)) ||
125
+ is_time_type (std::get<DataType>(left_type))),
126
+ " Unexpected data type input to unary comparison operation" );
126
127
break ;
127
128
case OperationType::IDENTITY:
128
129
case OperationType::NOT:
129
- user_input::check<ErrorCode::E_INVALID_USER_ARGUMENT>(!left_type.has_value () || *left_type == DataType::BOOL8,
130
- " Unexpected data type input to unary boolean operation {}" ,
131
- left_type.has_value () ? *left_type : DataType::UNKNOWN);
130
+ user_input::check<ErrorCode::E_INVALID_USER_ARGUMENT>(!std::holds_alternative<DataType>(left_type) || std::get<DataType>(left_type) == DataType::BOOL8,
131
+ " Unexpected data type input to unary boolean operation" );
132
132
break ;
133
133
default :
134
134
internal::raise <ErrorCode::E_ASSERTION_FAILURE>(" Unexpected unary operator" );
135
135
}
136
136
} else {
137
137
// Binary operation
138
- std::optional< DataType> right_type;
138
+ std::variant<BitSetTag, DataType> right_type;
139
139
std::optional<bool > empty_value_set;
140
140
right_type = util::variant_match (
141
141
right_,
142
- [&column_types] (const ColumnName& column_name) -> std::optional< DataType> {
142
+ [&column_types] (const ColumnName& column_name) -> std::variant<BitSetTag, DataType> {
143
143
auto it = column_types.find (column_name.value );
144
144
schema::check<ErrorCode::E_COLUMN_DOESNT_EXIST>(it != column_types.end (),
145
145
" ProjectClause requires column '{}' to exist in input data"
146
146
,column_name.value );
147
147
return it->second ;
148
148
},
149
- [&expression_context] (const ValueName& value_name) -> std::optional< DataType> {
149
+ [&expression_context] (const ValueName& value_name) -> std::variant<BitSetTag, DataType> {
150
150
return expression_context.values_ .get_value (value_name.value )->data_type_ ;
151
151
},
152
- [&expression_context, &empty_value_set] (const ValueSetName& value_set_name) -> std::optional< DataType> {
152
+ [&expression_context, &empty_value_set] (const ValueSetName& value_set_name) -> std::variant<BitSetTag, DataType> {
153
153
auto value_set = expression_context.value_sets_ .get_value (value_set_name.value );
154
154
empty_value_set = value_set->empty ();
155
155
return value_set->base_type ().data_type ();
156
156
},
157
- [&expression_context, &column_types] (const ExpressionName& expression_name) -> std::optional< DataType> {
157
+ [&expression_context, &column_types] (const ExpressionName& expression_name) -> std::variant<BitSetTag, DataType> {
158
158
auto expr = expression_context.expression_nodes_ .get_value (expression_name.value );
159
159
return expr->compute (expression_context, column_types);
160
160
},
161
- [] (auto &&) -> std::optional< DataType> {
161
+ [] (auto &&) -> std::variant<BitSetTag, DataType> {
162
162
internal::raise <ErrorCode::E_ASSERTION_FAILURE>(" Unexpected expression argument type" );
163
- return std::nullopt ;
163
+ return {} ;
164
164
}
165
165
);
166
166
switch (operation_type_) {
167
167
case OperationType::ADD:
168
168
case OperationType::SUB:
169
169
case OperationType::MUL:
170
170
case OperationType::DIV:
171
- user_input::check<ErrorCode::E_INVALID_USER_ARGUMENT>(left_type. has_value ( ), " Unexpected bitset input to binary arithmetic operator" );
172
- user_input::check<ErrorCode::E_INVALID_USER_ARGUMENT>(right_type. has_value ( ) && !empty_value_set.has_value (), " Unexpected input to binary arithmetic operator" );
173
- details::visit_type (* left_type, [this , &res, right_type](auto left_tag) {
171
+ user_input::check<ErrorCode::E_INVALID_USER_ARGUMENT>(std::holds_alternative<DataType>(left_type ), " Unexpected bitset input to binary arithmetic operator" );
172
+ user_input::check<ErrorCode::E_INVALID_USER_ARGUMENT>(std::holds_alternative<DataType>(right_type ) && !empty_value_set.has_value (), " Unexpected input to binary arithmetic operator" );
173
+ details::visit_type (std::get<DataType>( left_type) , [this , &res, right_type](auto left_tag) {
174
174
using left_type_info = ScalarTypeInfo<decltype (left_tag)>;
175
- details::visit_type (* right_type, [this , &res](auto right_tag) {
175
+ details::visit_type (std::get<DataType>( right_type) , [this , &res](auto right_tag) {
176
176
using right_type_info = ScalarTypeInfo<decltype (right_tag)>;
177
177
if constexpr (is_numeric_type (left_type_info::data_type) && is_numeric_type (right_type_info::data_type)) {
178
178
switch (operation_type_) {
@@ -212,34 +212,32 @@ std::optional<DataType> ExpressionNode::compute(const ExpressionContext& express
212
212
case OperationType::LE:
213
213
case OperationType::GT:
214
214
case OperationType::GE:
215
- user_input::check<ErrorCode::E_INVALID_USER_ARGUMENT>(left_type. has_value ( ), " Unexpected bitset input to binary comparison operator" );
216
- user_input::check<ErrorCode::E_INVALID_USER_ARGUMENT>(right_type. has_value ( ) && !empty_value_set.has_value (), " Unexpected input to binary comparison operator" );
215
+ user_input::check<ErrorCode::E_INVALID_USER_ARGUMENT>(std::holds_alternative<DataType>(left_type ), " Unexpected bitset input to binary comparison operator" );
216
+ user_input::check<ErrorCode::E_INVALID_USER_ARGUMENT>(std::holds_alternative<DataType>(right_type ) && !empty_value_set.has_value (), " Unexpected input to binary comparison operator" );
217
217
user_input::check<ErrorCode::E_INVALID_USER_ARGUMENT>(
218
- (is_numeric_type (* left_type) && is_numeric_type (* right_type)) ||
219
- (is_bool_type (* left_type) && is_bool_type (* right_type)) ||
220
- (is_sequence_type (* left_type) && is_sequence_type (* right_type) && (operation_type_ == OperationType::EQ || operation_type_ == OperationType::NE)),
218
+ (is_numeric_type (std::get<DataType>( left_type)) && is_numeric_type (std::get<DataType>( right_type) )) ||
219
+ (is_bool_type (std::get<DataType>( left_type)) && is_bool_type (std::get<DataType>( right_type) )) ||
220
+ (is_sequence_type (std::get<DataType>( left_type)) && is_sequence_type (std::get<DataType>( right_type) ) && (operation_type_ == OperationType::EQ || operation_type_ == OperationType::NE)),
221
221
" Incompatible data types provided in binary comparison {}, {}" ,
222
- * left_type, * right_type);
222
+ std::get<DataType>( left_type), std::get<DataType>( right_type) );
223
223
break ;
224
224
case OperationType::ISIN:
225
225
case OperationType::ISNOTIN:
226
- user_input::check<ErrorCode::E_INVALID_USER_ARGUMENT>(left_type. has_value ( ), " Unexpected bitset input to binary comparison operator" );
227
- user_input::check<ErrorCode::E_INVALID_USER_ARGUMENT>(right_type. has_value ( ) && empty_value_set.has_value (), " Unexpected input to binary comparison operator" );
226
+ user_input::check<ErrorCode::E_INVALID_USER_ARGUMENT>(std::holds_alternative<DataType>(left_type ), " Unexpected bitset input to binary comparison operator" );
227
+ user_input::check<ErrorCode::E_INVALID_USER_ARGUMENT>(std::holds_alternative<DataType>(right_type ) && empty_value_set.has_value (), " Unexpected input to binary comparison operator" );
228
228
if (!*empty_value_set) {
229
229
user_input::check<ErrorCode::E_INVALID_USER_ARGUMENT>(
230
- (is_sequence_type (* left_type) && is_sequence_type (* right_type)) || (is_numeric_type (* left_type) && is_numeric_type (* right_type)),
230
+ (is_sequence_type (std::get<DataType>( left_type)) && is_sequence_type (std::get<DataType>( right_type))) || (is_numeric_type (std::get<DataType>( left_type)) && is_numeric_type (std::get<DataType>( right_type) )),
231
231
" Incompatible data types provided in set membership operator {}, {}" ,
232
- * left_type, * right_type);
232
+ std::get<DataType>( left_type), std::get<DataType>( right_type) );
233
233
} // else - Empty value set compatible with all data types
234
234
break ;
235
235
case OperationType::AND:
236
236
case OperationType::OR:
237
237
case OperationType::XOR:
238
238
user_input::check<ErrorCode::E_INVALID_USER_ARGUMENT>(
239
- (!left_type.has_value () || *left_type == DataType::BOOL8) && (!right_type.has_value () || *right_type == DataType::BOOL8),
240
- " Unexpected data types input to binary boolean operation {} {}" ,
241
- left_type.has_value () ? *left_type : DataType::UNKNOWN,
242
- right_type.has_value () ? *right_type : DataType::UNKNOWN);
239
+ (!std::holds_alternative<DataType>(left_type) || std::get<DataType>(left_type) == DataType::BOOL8) && (!std::holds_alternative<DataType>(right_type) || std::get<DataType>(right_type) == DataType::BOOL8),
240
+ " Unexpected data types input to binary boolean operation" );
243
241
break ;
244
242
default :
245
243
internal::raise <ErrorCode::E_ASSERTION_FAILURE>(" Unexpected binary operator" );
0 commit comments