| @@ -58,46 +58,7 @@ time_t ParseDateTimeLiteral(string time) · 57 unmodified lines |
| 58 | time.erase(time.size() - 1); | 58 | time.erase(time.size() - 1); |
| 59 | } | 59 | } |
| 60 | | 60 | |
| 61 | // Need a "generic" ParseTimestamp function... | 61 | return ParseTimestamp(time.c_str()); |
| 62 | // istringstream in { time }; | | |
| 63 | // sys_seconds timestamp; | | |
| 64 | // | | |
| 65 | // // Try parsing several date-time formats formatted timestamp string | | |
| 66 | // // using the Hinnant date library: https://github.com/HowardHinnant/date | | |
| 67 | // | | |
| 68 | // // Need to try several date/time format variations per: | | |
| 69 | // // https://howardhinnant.github.io/date/date.html#from_stream_formatting | | |
| 70 | // /* | | |
| 71 | // istringstream in { "2018-01-12 12:05:14" }; | | |
| 72 | // sys_seconds timestamp; | | |
| 73 | // | | |
| 74 | // in >> parse("%Y-%m-%dT%T%z", timestamp); | | |
| 75 | // | | |
| 76 | // if (bool(in)) | | |
| 77 | // { | | |
| 78 | // std::cout << "Parsed XML time: " << system_clock::to_time_t(timestamp) << "\n"; | | |
| 79 | // } | | |
| 80 | // else | | |
| 81 | // { | | |
| 82 | // in.clear(); | | |
| 83 | // in.str("2018-01-12 12:05:14"); | | |
| 84 | // in >> parse("%F%n %T", timestamp); | | |
| 85 | // | | |
| 86 | // if (bool(in)) | | |
| 87 | // { | | |
| 88 | // std::cout << "Parsed std time: " << system_clock::to_time_t(timestamp) << "\n"; | | |
| 89 | // } | | |
| 90 | // else | | |
| 91 | // { | | |
| 92 | // std::cout << "Failed to parse time...\n"; | | |
| 93 | // } | | |
| 94 | // } | | |
| 95 | // */ | | |
| 96 | // | | |
| 97 | // // Try XML format, e.g.: 2018-03-14T19:23:11.665-04:00: | | |
| 98 | // in >> parse("%Y-%m-%dT%T%z", timestamp); | | |
| 99 | | | |
| 100 | return ParseXMLTimestamp(time.c_str()); | | |
| 101 | } | 62 | } |
| 102 | | 63 | |
| 103 | FilterExpressionException::FilterExpressionException(string message) noexcept : | 64 | FilterExpressionException::FilterExpressionException(string message) noexcept : |
| @@ -253,14 +214,26 @@ void FilterExpressionParser::Evaluate() · 149 unmodified lines |
| 253 | ValueExpressionPtr result = expressionTree->Evaluate(row); | 214 | ValueExpressionPtr result = expressionTree->Evaluate(row); |
| 254 | | 215 | |
| 255 | // If final result is Null (due to Null propagation), treat result as False | 216 | // If final result is Null (due to Null propagation), treat result as False |
| 256 | if (result->DataType == ExpressionDataType::Null) | 217 | if (result->IsNullable) |
| 257 | result = ExpressionTree::False; | 218 | { |
| | 219 | NullableType value = Cast<NullableType>(result->Value); |
| | 220 | |
| | 221 | if (!value.HasValue()) |
| | 222 | result = ExpressionTree::False; |
| | 223 | } |
| 258 | | 224 | |
| 259 | // Final expression should have a boolean data type (it's part of a WHERE clause) | 225 | // Final expression should have a boolean data type (it's part of a WHERE clause) |
| 260 | if (result->DataType != ExpressionDataType::Boolean) | 226 | if (result->DataType != ExpressionDataType::Boolean) |
| 261 | throw FilterExpressionException("Final expression tree evaluation did not result in a boolean value, result data type is " + string(EnumName(result->DataType))); | 227 | throw FilterExpressionException("Final expression tree evaluation did not result in a boolean value, result data type is " + string(EnumName(result->DataType))); |
| 262 | | 228 | |
| 263 | if (Cast<bool>(CastSharedPtr<ValueExpression>(result)->Value)) | 229 | bool expressionValue; |
| | 230 | |
| | 231 | if (result->IsNullable) |
| | 232 | expressionValue = static_cast<bool>(Cast<Nullable<bool>>(result->Value).Value); |
| | 233 | else |
| | 234 | expressionValue = Cast<bool>(result->Value); |
| | 235 | |
| | 236 | if (expressionValue) |
| 264 | { | 237 | { |
| 265 | Nullable<guid> signalIDField = row->ValueAsGuid(signalIDColumnIndex); | 238 | Nullable<guid> signalIDField = row->ValueAsGuid(signalIDColumnIndex); |
| 266 | | 239 | |