@@ -73,58 +73,58 @@ llvm::Value* CodeGenerator::codegenCast(llvm::Value* operand_lv,
73
73
return cgen_state_->ir_builder_ .CreatePointerCast (operand_lv,
74
74
byte_array_type->getPointerTo ());
75
75
}
76
- if (operand_lv->getType ()->isIntegerTy ()) {
77
- if (operand_type->isString () || operand_type->isExtDictionary ()) {
78
- return codegenCastFromString (
79
- operand_lv, operand_type, type, operand_is_const, is_dict_intersection, co);
80
- }
81
- CHECK (operand_type->isInteger () || operand_type->isDecimal () ||
82
- operand_type->isDateTime () || operand_type->isBoolean ());
83
- if (operand_type->isBoolean ()) {
84
- // cast boolean to int8
85
- CHECK (operand_lv->getType ()->isIntegerTy (1 ) ||
86
- operand_lv->getType ()->isIntegerTy (8 ));
87
- if (operand_lv->getType ()->isIntegerTy (1 )) {
88
- operand_lv = cgen_state_->castToTypeIn (operand_lv, 8 );
89
- }
90
- if (type->isBoolean ()) {
91
- return operand_lv;
92
- }
93
- }
94
- if (operand_type->isInteger () && operand_lv->getType ()->isIntegerTy (8 ) &&
95
- type->isBoolean ()) {
96
- // cast int8 to boolean
97
- return codegenCastBetweenIntTypes (operand_lv, operand_type, type);
98
- }
99
- if (operand_type->isTimestamp () && type->isDate ()) {
100
- // Maybe we should instead generate DateTruncExpr directly from RelAlgTranslator
101
- // for this pattern. However, DateTruncExpr is supposed to return a timestamp,
102
- // whereas this cast returns a date. The underlying type for both is still the same,
103
- // but it still doesn't look like a good idea to misuse DateTruncExpr.
104
- // Date will have default precision of day, but TIMESTAMP dimension would
105
- // matter but while converting date through seconds
106
- return codegenCastTimestampToDate (
107
- operand_lv,
108
- operand_type->as <hdk::ir::TimestampType>()->unit (),
109
- type->nullable ());
76
+ if (!operand_lv->getType ()->isIntegerTy ()) {
77
+ return codegenCastFromFp (operand_lv, operand_type, type);
78
+ }
79
+
80
+ if (operand_type->isString () || operand_type->isExtDictionary ()) {
81
+ return codegenCastFromString (
82
+ operand_lv, operand_type, type, operand_is_const, is_dict_intersection, co);
83
+ }
84
+ CHECK (operand_type->isInteger () || operand_type->isDecimal () ||
85
+ operand_type->isDateTime () || operand_type->isBoolean ());
86
+ if (operand_type->isBoolean ()) {
87
+ // cast boolean to int8
88
+ CHECK (operand_lv->getType ()->isIntegerTy (1 ) || operand_lv->getType ()->isIntegerTy (8 ));
89
+ if (operand_lv->getType ()->isIntegerTy (1 )) {
90
+ operand_lv = cgen_state_->castToTypeIn (operand_lv, 8 );
110
91
}
111
- if ((operand_type->isTimestamp () || operand_type->isDate ()) && type->isTimestamp ()) {
112
- const auto operand_unit = (operand_type->isTimestamp ())
113
- ? operand_type->as <hdk::ir::TimestampType>()->unit ()
114
- : hdk::ir::TimeUnit::kSecond ;
115
- if (operand_unit != type->as <hdk::ir::TimestampType>()->unit ()) {
116
- return codegenCastBetweenTimestamps (
117
- operand_lv, operand_type, type, type->nullable ());
118
- }
92
+ if (type->isBoolean ()) {
93
+ return operand_lv;
119
94
}
120
- if (type->isInteger () || type->isDecimal () || type->isDateTime ()) {
121
- return codegenCastBetweenIntTypes (operand_lv, operand_type, type);
122
- } else {
123
- return codegenCastToFp (operand_lv, operand_type, type);
95
+ }
96
+ if (operand_type->isInteger () && operand_lv->getType ()->isIntegerTy (8 ) &&
97
+ type->isBoolean ()) {
98
+ // cast int8 to boolean
99
+ return codegenCastBetweenIntTypes (operand_lv, operand_type, type);
100
+ }
101
+ if (operand_type->isTimestamp () && type->isDate ()) {
102
+ // Maybe we should instead generate DateTruncExpr directly from RelAlgTranslator
103
+ // for this pattern. However, DateTruncExpr is supposed to return a timestamp,
104
+ // whereas this cast returns a date. The underlying type for both is still the same,
105
+ // but it still doesn't look like a good idea to misuse DateTruncExpr.
106
+ // Date will have default precision of day, but TIMESTAMP dimension would
107
+ // matter but while converting date through seconds
108
+ return codegenCastTimestampToDate (
109
+ operand_lv, operand_type->as <hdk::ir::TimestampType>()->unit (), type->nullable ());
110
+ }
111
+ if (operand_type->isTimestamp () && type->isTime ()) {
112
+ return codegenCastTimestampToTime (operand_lv, operand_type, type);
113
+ }
114
+ if ((operand_type->isTimestamp () || operand_type->isDate ()) && type->isTimestamp ()) {
115
+ const auto operand_unit = (operand_type->isTimestamp ())
116
+ ? operand_type->as <hdk::ir::TimestampType>()->unit ()
117
+ : hdk::ir::TimeUnit::kSecond ;
118
+ if (operand_unit != type->as <hdk::ir::TimestampType>()->unit ()) {
119
+ return codegenCastBetweenTimestamps (operand_lv, operand_type, type);
124
120
}
121
+ }
122
+ if (type->isInteger () || type->isDecimal () || type->isDateTime ()) {
123
+ return codegenCastBetweenIntTypes (operand_lv, operand_type, type);
125
124
} else {
126
- return codegenCastFromFp (operand_lv, operand_type, type);
125
+ return codegenCastToFp (operand_lv, operand_type, type);
127
126
}
127
+
128
128
CHECK (false );
129
129
return nullptr ;
130
130
}
@@ -159,11 +159,53 @@ llvm::Value* CodeGenerator::codegenCastTimestampToDate(llvm::Value* ts_lv,
159
159
return ret;
160
160
}
161
161
162
+ llvm::Value* CodeGenerator::codegenCastTimestampToTime (llvm::Value* ts_lv,
163
+ const hdk::ir::Type* operand_type,
164
+ const hdk::ir::Type* target_type) {
165
+ AUTOMATIC_IR_METADATA (cgen_state_);
166
+ const auto operand_unit = operand_type->as <hdk::ir::TimestampType>()->unit ();
167
+ const auto target_unit = target_type->as <hdk::ir::TimeType>()->unit ();
168
+
169
+ CHECK (ts_lv->getType ()->isIntegerTy (64 ));
170
+ if (operand_unit < target_unit) {
171
+ const auto target_sec_scale = hdk::ir::unitsPerSecond (target_unit);
172
+ const auto scale =
173
+ hdk::ir::unitsPerSecond (target_unit) / hdk::ir::unitsPerSecond (operand_unit);
174
+ if (!operand_type->nullable ()) {
175
+ return cgen_state_->emitCall (
176
+ " TimestampToTimeUpscale" ,
177
+ {{ts_lv, cgen_state_->llInt (scale), cgen_state_->llInt (target_sec_scale)}});
178
+ }
179
+ // Timestamp, Time32. Time64 have int64 inline int value, but logically corect to pass
180
+ // target and source null values.
181
+ return cgen_state_->emitCall (" TimestampToTimeUpscaleNullable" ,
182
+ {{ts_lv,
183
+ cgen_state_->llInt (scale),
184
+ cgen_state_->llInt (target_sec_scale),
185
+ cgen_state_->inlineIntNull (operand_type),
186
+ cgen_state_->inlineIntNull (target_type)}});
187
+ }
188
+ // On downscale we at first cut of date part, than cut of unused unit precision
189
+ const auto operand_sec_scale = hdk::ir::unitsPerSecond (operand_unit);
190
+ const auto scale =
191
+ hdk::ir::unitsPerSecond (operand_unit) / hdk::ir::unitsPerSecond (target_unit);
192
+ if (!operand_type->nullable ()) {
193
+ return cgen_state_->emitCall (
194
+ " TimestampToTimeDownscale" ,
195
+ {{ts_lv, cgen_state_->llInt (scale), cgen_state_->llInt (operand_sec_scale)}});
196
+ }
197
+ return cgen_state_->emitCall (" TimestampToTimeDownscaleNullable" ,
198
+ {{ts_lv,
199
+ cgen_state_->llInt (scale),
200
+ cgen_state_->llInt (operand_sec_scale),
201
+ cgen_state_->inlineIntNull (operand_type),
202
+ cgen_state_->inlineIntNull (target_type)}});
203
+ }
204
+
162
205
llvm::Value* CodeGenerator::codegenCastBetweenTimestamps (
163
206
llvm::Value* ts_lv,
164
207
const hdk::ir::Type* operand_type,
165
- const hdk::ir::Type* target_type,
166
- const bool nullable) {
208
+ const hdk::ir::Type* target_type) {
167
209
AUTOMATIC_IR_METADATA (cgen_state_);
168
210
const auto operand_unit = operand_type->isTimestamp ()
169
211
? operand_type->as <hdk::ir::TimestampType>()->unit ()
@@ -179,7 +221,7 @@ llvm::Value* CodeGenerator::codegenCastBetweenTimestamps(
179
221
const auto scale =
180
222
hdk::ir::unitsPerSecond (target_unit) / hdk::ir::unitsPerSecond (operand_unit);
181
223
codegenCastBetweenIntTypesOverflowChecks (ts_lv, operand_type, target_type, scale);
182
- return nullable
224
+ return target_type-> nullable ()
183
225
? cgen_state_->emitCall (" mul_int64_t_nullable_lhs" ,
184
226
{ts_lv,
185
227
cgen_state_->llInt (static_cast <int64_t >(scale)),
@@ -189,7 +231,7 @@ llvm::Value* CodeGenerator::codegenCastBetweenTimestamps(
189
231
}
190
232
const auto scale =
191
233
hdk::ir::unitsPerSecond (operand_unit) / hdk::ir::unitsPerSecond (target_unit);
192
- return nullable
234
+ return target_type-> nullable ()
193
235
? cgen_state_->emitCall (" floor_div_nullable_lhs" ,
194
236
{ts_lv,
195
237
cgen_state_->llInt (static_cast <int64_t >(scale)),
0 commit comments