@@ -265,6 +265,25 @@ class FlatbuffersExpressionEvaluator {
265
265
266
266
case tuix::ExprUnion_Literal:
267
267
{
268
+ auto * literal = static_cast <const tuix::Literal *>(expr->expr ());
269
+ const tuix::Field *value = literal->value ();
270
+
271
+ // If type is CalendarInterval, manually return a calendar interval field.
272
+ // Otherwise 'days' disappears in conversion.
273
+ if (value->value_type () == tuix::FieldUnion_CalendarIntervalField) {
274
+
275
+ auto *interval = value->value_as_CalendarIntervalField ();
276
+ uint32_t months = interval->months ();
277
+ uint32_t days = interval->days ();
278
+ uint64_t ms = interval->microseconds ();
279
+
280
+ return tuix::CreateField (
281
+ builder,
282
+ tuix::FieldUnion_CalendarIntervalField,
283
+ tuix::CreateCalendarIntervalField (builder, months, days, ms).Union (),
284
+ false );
285
+ }
286
+
268
287
return flatbuffers_copy<tuix::Field>(
269
288
static_cast <const tuix::Literal *>(expr->expr ())->value (), builder);
270
289
}
@@ -403,6 +422,7 @@ class FlatbuffersExpressionEvaluator {
403
422
auto add = static_cast <const tuix::Add *>(expr->expr ());
404
423
auto left_offset = eval_helper (row, add->left ());
405
424
auto right_offset = eval_helper (row, add->right ());
425
+
406
426
return eval_binary_arithmetic_op<tuix::Add, std::plus>(
407
427
builder,
408
428
flatbuffers::GetTemporaryPointer (builder, left_offset),
@@ -1041,6 +1061,102 @@ class FlatbuffersExpressionEvaluator {
1041
1061
false );
1042
1062
}
1043
1063
1064
+ // Time expressions
1065
+ case tuix::ExprUnion_DateAdd:
1066
+ {
1067
+ auto c = static_cast <const tuix::DateAdd *>(expr->expr ());
1068
+ auto left_offset = eval_helper (row, c->left ());
1069
+ auto right_offset = eval_helper (row, c->right ());
1070
+
1071
+ // Note: These temporary pointers will be invalidated when we next write to builder
1072
+ const tuix::Field *left = flatbuffers::GetTemporaryPointer (builder, left_offset);
1073
+ const tuix::Field *right = flatbuffers::GetTemporaryPointer (builder, right_offset);
1074
+
1075
+ if (left->value_type () != tuix::FieldUnion_DateField
1076
+ || right->value_type () != tuix::FieldUnion_IntegerField) {
1077
+ throw std::runtime_error (
1078
+ std::string (" tuix::DateAdd requires date Date, increment Integer, not " )
1079
+ + std::string (" date " )
1080
+ + std::string (tuix::EnumNameFieldUnion (left->value_type ()))
1081
+ + std::string (" , increment " )
1082
+ + std::string (tuix::EnumNameFieldUnion (right->value_type ())));
1083
+ }
1084
+
1085
+ bool result_is_null = left->is_null () || right->is_null ();
1086
+
1087
+ if (!result_is_null) {
1088
+ auto left_field = static_cast <const tuix::DateField *>(left->value ());
1089
+ auto right_field = static_cast <const tuix::IntegerField *>(right->value ());
1090
+
1091
+ uint32_t result = left_field->value () + right_field->value ();
1092
+
1093
+ return tuix::CreateField (
1094
+ builder,
1095
+ tuix::FieldUnion_DateField,
1096
+ tuix::CreateDateField (builder, result).Union (),
1097
+ result_is_null);
1098
+ } else {
1099
+ uint32_t result = 0 ;
1100
+ return tuix::CreateField (
1101
+ builder,
1102
+ tuix::FieldUnion_DateField,
1103
+ tuix::CreateDateField (builder, result).Union (),
1104
+ result_is_null);
1105
+ }
1106
+ }
1107
+
1108
+ case tuix::ExprUnion_DateAddInterval:
1109
+ {
1110
+ auto c = static_cast <const tuix::DateAddInterval *>(expr->expr ());
1111
+ auto left_offset = eval_helper (row, c->left ());
1112
+ auto right_offset = eval_helper (row, c->right ());
1113
+
1114
+ // Note: These temporary pointers will be invalidated when we next write to builder
1115
+ const tuix::Field *left = flatbuffers::GetTemporaryPointer (builder, left_offset);
1116
+ const tuix::Field *right = flatbuffers::GetTemporaryPointer (builder, right_offset);
1117
+
1118
+ if (left->value_type () != tuix::FieldUnion_DateField
1119
+ || right->value_type () != tuix::FieldUnion_CalendarIntervalField) {
1120
+ throw std::runtime_error (
1121
+ std::string (" tuix::DateAddInterval requires date Date, interval CalendarIntervalField, not " )
1122
+ + std::string (" date " )
1123
+ + std::string (tuix::EnumNameFieldUnion (left->value_type ()))
1124
+ + std::string (" , interval " )
1125
+ + std::string (tuix::EnumNameFieldUnion (right->value_type ())));
1126
+ }
1127
+
1128
+ bool result_is_null = left->is_null () || right->is_null ();
1129
+ uint32_t result = 0 ;
1130
+
1131
+ if (!result_is_null) {
1132
+
1133
+ auto left_field = static_cast <const tuix::DateField *>(left->value ());
1134
+ auto right_field = static_cast <const tuix::CalendarIntervalField *>(right->value ());
1135
+
1136
+ // This is an approximation
1137
+ // TODO take into account leap seconds
1138
+ uint64_t date = 86400L *left_field->value ();
1139
+ struct tm tm ;
1140
+ secs_to_tm (date, &tm );
1141
+ tm .tm_mon += right_field->months ();
1142
+ tm .tm_mday += right_field->days ();
1143
+ time_t time = std::mktime (&tm );
1144
+ uint32_t result = (time + (right_field->microseconds () / 1000 )) / 86400L ;
1145
+
1146
+ return tuix::CreateField (
1147
+ builder,
1148
+ tuix::FieldUnion_DateField,
1149
+ tuix::CreateDateField (builder, result).Union (),
1150
+ result_is_null);
1151
+ } else {
1152
+ return tuix::CreateField (
1153
+ builder,
1154
+ tuix::FieldUnion_DateField,
1155
+ tuix::CreateDateField (builder, result).Union (),
1156
+ result_is_null);
1157
+ }
1158
+ }
1159
+
1044
1160
case tuix::ExprUnion_Year:
1045
1161
{
1046
1162
auto e = static_cast <const tuix::Year *>(expr->expr ());
0 commit comments