diff --git a/src/realm/parser/driver.cpp b/src/realm/parser/driver.cpp index fa79f826168..645069b53e9 100644 --- a/src/realm/parser/driver.cpp +++ b/src/realm/parser/driver.cpp @@ -162,6 +162,16 @@ inline T string_to(const std::string& s) return value; } +template <> +inline Decimal128 string_to(const std::string& s) +{ + Decimal128 value(s); + if (value.is_nan()) { + throw InvalidQueryArgError(util::format("Cannot convert '%1' to a %2", s, get_type_name())); + } + return value; +} + class MixedArguments : public query_parser::Arguments { public: using Arg = mpark::variant>; @@ -261,12 +271,12 @@ class MixedArguments : public query_parser::Arguments { static_assert(std::is_same_v, std::vector>); return m_args[n].index() == 1; } - DataType type_for_argument(size_t n) + DataType type_for_argument(size_t n) final { return mixed_for_argument(n).get_type(); } - Mixed mixed_for_argument(size_t n) override + Mixed mixed_for_argument(size_t n) final { Arguments::verify_ndx(n); if (is_argument_list(n)) { @@ -1196,14 +1206,14 @@ void ConstantNode::decode_b64() { const size_t encoded_size = text.size() - 5; size_t buffer_size = util::base64_decoded_size(encoded_size); - decode_buffer.resize(buffer_size); + m_decode_buffer.resize(buffer_size); StringData window(text.c_str() + 4, encoded_size); - util::Optional decoded_size = util::base64_decode(window, decode_buffer.data(), buffer_size); + util::Optional decoded_size = util::base64_decode(window, m_decode_buffer.data(), buffer_size); if (!decoded_size) { throw SyntaxError("Invalid base64 value"); } REALM_ASSERT_DEBUG_EX(*decoded_size <= encoded_size, *decoded_size, encoded_size); - decode_buffer.resize(*decoded_size); // truncate + m_decode_buffer.resize(*decoded_size); // truncate } Mixed ConstantNode::get_value() @@ -1227,7 +1237,7 @@ Mixed ConstantNode::get_value() return StringData(text.data() + 1, text.size() - 2); case Type::STRING_BASE64: decode_b64(); - return StringData(decode_buffer.data(), decode_buffer.size()); + return StringData(m_decode_buffer.data(), m_decode_buffer.size()); case Type::TIMESTAMP: { auto s = text; int64_t seconds; @@ -1293,7 +1303,7 @@ Mixed ConstantNode::get_value() } case BINARY_BASE64: decode_b64(); - return BinaryData(decode_buffer.data(), decode_buffer.size()); + return BinaryData(m_decode_buffer.data(), m_decode_buffer.size()); } return {}; } @@ -1329,8 +1339,12 @@ std::unique_ptr ConstantNode::visit(ParserDriver* drv, DataType hint) print_pretty_objlink(value.get(), drv->m_base_table->get_parent_group())); } else { - explain_value_message = util::format("argument %1 of type '%2'", explain_value_message, - get_data_type_name(value.get_type())); + explain_value_message = util::format("argument %1 with value '%2'", explain_value_message, value); + if (!(m_target_table || Mixed::data_types_are_comparable(value.get_type(), hint) || + Mixed::is_numeric(hint) || (value.is_type(type_String) && hint == type_TypeOfValue))) { + throw InvalidQueryArgError( + util::format("Cannot compare %1 to a %2", explain_value_message, get_data_type_name(hint))); + } } } } @@ -1338,17 +1352,17 @@ std::unique_ptr ConstantNode::visit(ParserDriver* drv, DataType hint) value = get_value(); } - if (target_table.length()) { + if (m_target_table) { // There is a table name set. This must be an ObjLink const Group* g = drv->m_base_table->get_parent_group(); - auto table = g->get_table(target_table); + auto table = g->get_table(m_target_table); if (!table) { // Perhaps class prefix is missing Group::TableNameBuffer buffer; - table = g->get_table(Group::class_name_to_table_name(target_table, buffer)); + table = g->get_table(Group::class_name_to_table_name(m_target_table, buffer)); } if (!table) { - throw InvalidQueryError(util::format("Unknown object type '%1'", target_table)); + throw InvalidQueryError(util::format("Unknown object type '%1'", m_target_table)); } auto obj_key = table->find_primary_key(value); value = ObjLink(table->get_key(), ObjKey(obj_key)); @@ -1385,26 +1399,29 @@ std::unique_ptr ConstantNode::visit(ParserDriver* drv, DataType hint) break; case type_Double: { auto double_val = value.get_double(); - - if (hint == type_Int) { - int64_t int_val = int64_t(double_val); - // Only return an integer if it precisely represents val - if (double(int_val) == double_val) - ret = std::make_unique>(int_val); - } - else if (hint == type_Float) { - ret = std::make_unique>(double_val); - } - else if (hint == type_Decimal) { - ret = std::make_unique>(Decimal128(text)); + if (std::isinf(double_val) && (!Mixed::is_numeric(hint) || hint == type_Int)) { + throw InvalidQueryError(util::format("Infinity not supported for %1", get_data_type_name(hint))); } - if (!ret) { - constexpr auto inf = std::numeric_limits::infinity(); - bool is_infinity = (double_val == inf || double_val == -inf); - if (is_infinity && hint != type_Double) { - throw InvalidQueryError(util::format("Infinity not supported for %1", get_data_type_name(hint))); + + switch (hint) { + case type_Float: + ret = std::make_unique>(double_val); + break; + case type_Decimal: + ret = std::make_unique>(Decimal128(text)); + break; + case type_Int: { + int64_t int_val = int64_t(double_val); + // Only return an integer if it precisely represents val + if (double(int_val) == double_val) { + ret = std::make_unique>(int_val); + break; + } + [[fallthrough]]; } - ret = std::make_unique>(double_val); + default: + ret = std::make_unique>(double_val); + break; } break; } @@ -1421,7 +1438,7 @@ std::unique_ptr ConstantNode::visit(ParserDriver* drv, DataType hint) ret = std::make_unique>(string_to(str)); break; case type_Decimal: - ret = std::make_unique>(Decimal128(str)); + ret = std::make_unique>(string_to(str)); break; default: if (hint == type_TypeOfValue) { diff --git a/src/realm/parser/driver.hpp b/src/realm/parser/driver.hpp index 6ce9baebe7a..e255b45bc67 100644 --- a/src/realm/parser/driver.hpp +++ b/src/realm/parser/driver.hpp @@ -191,18 +191,17 @@ class ConstantNode : public ValueNode { } void add_table(std::string table_name) { - target_table = table_name.substr(1, table_name.size() - 2); + m_target_table = table_name.substr(1, table_name.size() - 2); } std::unique_ptr copy_list_of_args(std::vector&); - std::unique_ptr copy_arg(ParserDriver*, DataType, size_t, DataType, std::string&); std::unique_ptr visit(ParserDriver*, DataType) override; Mixed get_value(); - util::Optional m_comp_type; - std::string target_table; private: - std::string decode_buffer; + std::string m_decode_buffer; + std::optional m_comp_type; + std::optional m_target_table; void decode_b64(); }; diff --git a/src/realm/parser/generated/query_bison.cpp b/src/realm/parser/generated/query_bison.cpp index fdacc34a75a..d7af8ba1245 100644 --- a/src/realm/parser/generated/query_bison.cpp +++ b/src/realm/parser/generated/query_bison.cpp @@ -1929,15 +1929,11 @@ namespace yy { { yylhs.value.as < ConstantNode* > () = drv.m_parse_nodes.create(ConstantNode::NULL_VAL, ""); } break; - case 77: // constant: "argument" - { yylhs.value.as < ConstantNode* > () = drv.m_parse_nodes.create(ConstantNode::ARG, yystack_[0].value.as < std::string > ()); } - break; - - case 78: // constant: comp_type "argument" + case 77: // constant: comp_type "argument" { yylhs.value.as < ConstantNode* > () = drv.m_parse_nodes.create(ExpressionComparisonType(yystack_[1].value.as < int > ()), yystack_[0].value.as < std::string > ()); } break; - case 79: // constant: "obj" '(' "string" ',' primary_key ')' + case 78: // constant: "obj" '(' "string" ',' primary_key ')' { auto tmp = yystack_[1].value.as < ConstantNode* > (); tmp->add_table(yystack_[3].value.as < std::string > ()); @@ -1945,34 +1941,38 @@ namespace yy { } break; - case 80: // constant: "binary" '(' "string" ')' + case 79: // constant: "binary" '(' "string" ')' { yylhs.value.as < ConstantNode* > () = drv.m_parse_nodes.create(ConstantNode::BINARY_STR, yystack_[1].value.as < std::string > ()); } break; - case 81: // constant: "binary" '(' "base64" ')' + case 80: // constant: "binary" '(' "base64" ')' { yylhs.value.as < ConstantNode* > () = drv.m_parse_nodes.create(ConstantNode::BINARY_BASE64, yystack_[1].value.as < std::string > ()); } break; - case 82: // primary_key: "natural0" + case 81: // primary_key: "natural0" { yylhs.value.as < ConstantNode* > () = drv.m_parse_nodes.create(ConstantNode::NUMBER, yystack_[0].value.as < std::string > ()); } break; - case 83: // primary_key: "number" + case 82: // primary_key: "number" { yylhs.value.as < ConstantNode* > () = drv.m_parse_nodes.create(ConstantNode::NUMBER, yystack_[0].value.as < std::string > ()); } break; - case 84: // primary_key: "string" + case 83: // primary_key: "string" { yylhs.value.as < ConstantNode* > () = drv.m_parse_nodes.create(ConstantNode::STRING, yystack_[0].value.as < std::string > ()); } break; - case 85: // primary_key: "UUID" + case 84: // primary_key: "UUID" { yylhs.value.as < ConstantNode* > () = drv.m_parse_nodes.create(ConstantNode::UUID_T, yystack_[0].value.as < std::string > ()); } break; - case 86: // primary_key: "ObjectId" + case 85: // primary_key: "ObjectId" { yylhs.value.as < ConstantNode* > () = drv.m_parse_nodes.create(ConstantNode::OID, yystack_[0].value.as < std::string > ()); } break; + case 86: // primary_key: "argument" + { yylhs.value.as < ConstantNode* > () = drv.m_parse_nodes.create(ConstantNode::ARG, yystack_[0].value.as < std::string > ()); } + break; + case 87: // boolexpr: "truepredicate" { yylhs.value.as < TrueOrFalseNode* > () = drv.m_parse_nodes.create(true); } break; @@ -2541,50 +2541,50 @@ namespace yy { -160, -160, -160, -160, -160, -160, -160, -160, -160, -160, -160, -160, -160, -38, -160, -160, -160, 37, -160, -160, -160, -160, -160, -160, -160, 123, 438, 87, 26, -160, - 17, 166, 45, -160, -160, -160, -160, -160, -160, 453, - -58, -160, 546, -160, 86, 29, -5, 11, 37, -66, - -160, 82, -160, 123, 123, 79, -160, -160, -160, -160, + 17, 164, 45, -160, -160, -160, -160, -160, -160, 453, + -58, -160, 546, -160, 88, 29, -5, 11, 37, -66, + -160, 81, -160, 123, 123, 79, -160, -160, -160, -160, -160, -160, -160, 250, 250, 250, 250, 189, 250, -160, -160, -160, 377, -160, 22, 316, 73, -160, -160, 438, - -3, 501, 83, -160, 49, 101, 64, 112, 66, 75, - -160, -160, 438, -160, -160, 163, 121, 132, 138, -160, + -3, 501, 83, -160, 52, 64, 47, 101, 75, 114, + -160, -160, 438, -160, -160, 163, 121, 132, 170, -160, -160, -160, 250, 34, -160, -160, 34, -160, -160, 250, - 194, 194, -160, -160, 140, 377, -160, 147, 170, 181, + 148, 148, -160, -160, 175, 377, -160, 182, 190, 191, -160, -160, -40, 523, -160, -160, -160, -160, -160, -160, - -160, -160, 177, 201, 226, 237, 238, 242, 244, 568, - 568, 568, -25, 84, -160, -160, -160, 546, 546, 230, - 203, 194, -160, 204, 249, 204, -160, -160, -160, -160, - -160, -160, -160, -160, -160, 254, 206, 76, 36, 119, - 64, 257, 167, 256, 204, -160, 202, 262, 123, -160, + -160, -160, 187, 188, 198, 200, 201, 202, 226, 568, + 568, 568, -25, 497, -160, -160, -160, 546, 546, 230, + 203, 148, -160, 204, 236, 204, -160, -160, -160, -160, + -160, -160, -160, -160, -160, 240, 245, 65, 36, 76, + 47, 246, 80, 252, 204, -160, 119, 254, 123, -160, -160, 546, -160, -160, -160, -160, 546, -160, -160, -160, - -160, 263, 204, -160, -29, -160, 249, 167, 18, 36, - 64, 167, 259, 204, -160, -160, 266, 267, -160, 243, - -160, -160, -160, 276, 304, -160, -160, 268, -160 + -160, 255, 204, -160, -29, -160, 236, 80, 18, 36, + 47, 80, 247, 204, -160, -160, 248, 257, -160, 128, + -160, -160, -160, 268, 299, -160, -160, 261, -160 }; const unsigned char parser::yydefact_[] = { 0, 87, 88, 0, 74, 75, 76, 89, 90, 91, - 0, 120, 84, 69, 67, 68, 82, 83, 70, 71, - 85, 86, 72, 73, 77, 112, 122, 123, 124, 134, + 0, 120, 83, 69, 67, 68, 81, 82, 70, 71, + 84, 85, 72, 73, 86, 112, 122, 123, 124, 134, 125, 126, 133, 0, 128, 129, 130, 135, 131, 132, 136, 137, 138, 127, 121, 0, 64, 0, 48, 3, 0, 18, 25, 27, 28, 26, 24, 66, 8, 0, 92, 111, 0, 6, 0, 0, 0, 0, 0, 0, 63, 0, 1, 0, 0, 2, 100, 101, 103, 105, 106, 104, 102, 0, 0, 0, 0, 0, 0, 107, - 108, 109, 0, 110, 0, 0, 0, 78, 135, 64, + 108, 109, 0, 110, 0, 0, 0, 77, 135, 64, 92, 0, 0, 29, 32, 0, 33, 0, 0, 0, 7, 19, 0, 61, 5, 4, 0, 0, 0, 50, 49, 51, 0, 22, 18, 25, 23, 20, 21, 0, 9, 11, 13, 15, 0, 0, 12, 0, 0, 0, 17, 16, 0, 0, 30, 96, 97, 98, 99, 93, 95, 113, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 80, 81, 65, 0, 0, 0, + 0, 0, 0, 0, 79, 80, 65, 0, 0, 0, 0, 10, 14, 0, 0, 0, 62, 118, 114, 119, 115, 116, 94, 117, 31, 0, 0, 0, 0, 0, - 53, 0, 0, 0, 0, 43, 0, 0, 0, 79, + 53, 0, 0, 0, 0, 43, 0, 0, 0, 78, 55, 0, 59, 60, 56, 52, 0, 58, 36, 35, 37, 0, 0, 40, 0, 47, 0, 0, 0, 0, 54, 0, 0, 0, 42, 44, 0, 0, 57, 0, @@ -2595,8 +2595,8 @@ namespace yy { parser::yypgoto_[] = { -160, -160, -9, -160, -32, 0, 2, -160, -160, -160, - -159, -103, -160, 125, -160, -160, -160, -160, -160, -160, - -160, -160, 148, 248, 245, -42, 215, -160, -31, 279, + -159, -103, -160, 122, -160, -160, -160, -160, -160, -160, + -160, -160, 118, 249, 241, -42, 176, -160, -31, 242, -160, -160, -160, -160, -56, -55 }; @@ -2623,33 +2623,33 @@ namespace yy { 86, 71, 111, 83, 84, 85, 86, 72, 151, 227, 170, 213, 132, 202, 203, 136, 96, 171, 46, 137, 138, 139, 85, 86, 184, 185, 151, 65, 161, 222, - 162, 188, 190, 152, 12, 140, 107, 153, 16, 17, - 231, 159, 20, 21, 97, 154, 1, 2, 3, 4, - 5, 6, 116, 117, 118, 172, 161, 164, 162, 7, - 8, 9, 155, 156, 157, 219, 165, 200, 10, 201, + 162, 188, 190, 152, 208, 140, 209, 153, 107, 161, + 231, 162, 210, 97, 159, 154, 1, 2, 3, 4, + 5, 6, 116, 117, 118, 172, 200, 160, 201, 7, + 8, 9, 155, 156, 157, 219, 164, 205, 10, 206, 220, 158, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32, 160, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 163, 73, 43, 44, 218, - 205, 167, 206, 45, 3, 4, 5, 6, 51, 46, - 52, 208, 168, 209, 129, 7, 8, 9, 169, 210, - 89, 90, 91, 92, 93, 94, 99, 173, 11, 12, + 29, 30, 31, 32, 163, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 165, 73, 43, 44, 218, + 215, 167, 216, 45, 3, 4, 5, 6, 51, 46, + 52, 234, 168, 235, 129, 7, 8, 9, 89, 90, + 91, 92, 93, 94, 83, 84, 85, 86, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 174, 33, 34, 35, 36, 37, 38, 39, 40, 41, - 42, 175, 177, 43, 44, 3, 4, 5, 6, 122, - 83, 84, 85, 86, 191, 46, 7, 8, 9, 83, - 84, 85, 86, 215, 111, 216, 178, 199, 192, 11, + 169, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 42, 99, 173, 43, 44, 3, 4, 5, 6, 122, + 174, 175, 177, 178, 191, 46, 7, 8, 9, 83, + 84, 85, 86, 179, 111, 180, 181, 182, 192, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 179, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 180, 181, 43, 44, 234, 182, 235, 183, - 122, 3, 4, 5, 6, 194, 46, 198, 207, 212, - 230, 135, 7, 8, 9, 217, 221, 232, 236, 233, - 237, 225, 133, 238, 142, 11, 12, 13, 14, 15, + 32, 183, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 194, 198, 43, 44, 199, 207, 230, 232, + 122, 3, 4, 5, 6, 212, 46, 217, 221, 233, + 236, 135, 7, 8, 9, 237, 238, 228, 225, 186, + 142, 0, 144, 133, 0, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 228, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 186, 144, + 26, 27, 28, 29, 30, 31, 32, 0, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 0, 0, 43, 44, 3, 4, 5, 6, 0, 0, 0, 0, 0, 0, 46, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 12, 13, 14, @@ -2664,8 +2664,8 @@ namespace yy { 33, 0, 0, 0, 68, 97, 25, 26, 27, 28, 29, 30, 31, 32, 0, 0, 34, 35, 36, 98, 38, 39, 40, 41, 42, 0, 0, 43, 44, 0, - 145, 146, 147, 148, 0, 0, 0, 0, 0, 99, - 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 145, 146, 147, 148, 0, 0, 0, 12, 0, 99, + 11, 16, 17, 0, 0, 20, 21, 0, 0, 24, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 11, 0, 34, 35, 36, 98, 38, 39, 40, 41, 42, 149, 150, 43, 44, 26, 27, 28, @@ -2692,33 +2692,33 @@ namespace yy { 69, 112, 71, 66, 67, 68, 69, 0, 143, 71, 122, 194, 92, 57, 58, 95, 51, 129, 76, 26, 27, 28, 68, 69, 159, 160, 161, 70, 72, 212, - 74, 167, 168, 30, 30, 42, 30, 34, 34, 35, - 223, 72, 38, 39, 42, 42, 3, 4, 5, 6, - 7, 8, 53, 54, 55, 135, 72, 71, 74, 16, + 74, 167, 168, 30, 34, 42, 36, 34, 30, 72, + 223, 74, 42, 42, 72, 42, 3, 4, 5, 6, + 7, 8, 53, 54, 55, 135, 71, 73, 73, 16, 17, 18, 59, 60, 61, 201, 71, 71, 25, 73, 206, 68, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 73, 52, 53, 54, 55, 56, - 57, 58, 59, 60, 61, 73, 23, 64, 65, 198, + 57, 58, 59, 60, 61, 71, 23, 64, 65, 198, 71, 70, 73, 70, 5, 6, 7, 8, 198, 76, - 198, 34, 70, 36, 15, 16, 17, 18, 70, 42, - 44, 45, 46, 47, 48, 49, 76, 70, 29, 30, + 198, 73, 70, 75, 15, 16, 17, 18, 44, 45, + 46, 47, 48, 49, 66, 67, 68, 69, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 70, 52, 53, 54, 55, 56, 57, 58, 59, 60, - 61, 70, 75, 64, 65, 5, 6, 7, 8, 70, - 66, 67, 68, 69, 34, 76, 16, 17, 18, 66, - 67, 68, 69, 71, 71, 73, 75, 71, 74, 29, + 61, 76, 70, 64, 65, 5, 6, 7, 8, 70, + 70, 70, 75, 75, 34, 76, 16, 17, 18, 66, + 67, 68, 69, 75, 71, 75, 75, 75, 74, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 75, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 75, 75, 64, 65, 73, 75, 75, 75, - 70, 5, 6, 7, 8, 76, 76, 73, 71, 73, - 71, 15, 16, 17, 18, 73, 73, 71, 62, 72, - 36, 216, 94, 75, 99, 29, 30, 31, 32, 33, + 60, 61, 76, 73, 64, 65, 71, 71, 71, 71, + 70, 5, 6, 7, 8, 73, 76, 73, 73, 72, + 62, 15, 16, 17, 18, 36, 75, 219, 216, 163, + 99, -1, 100, 94, -1, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 219, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 163, 100, + 44, 45, 46, 47, 48, 49, 50, -1, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, 76, 16, 17, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 29, 30, 31, 32, @@ -2733,8 +2733,8 @@ namespace yy { 52, -1, -1, -1, 56, 42, 43, 44, 45, 46, 47, 48, 49, 50, -1, -1, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, -1, - 19, 20, 21, 22, -1, -1, -1, -1, -1, 76, - 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 19, 20, 21, 22, -1, -1, -1, 30, -1, 76, + 29, 34, 35, -1, -1, 38, 39, -1, -1, 42, -1, -1, -1, -1, -1, 44, 45, 46, 47, 48, 49, 50, 29, -1, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 44, 45, 46, @@ -2787,7 +2787,7 @@ namespace yy { 94, 94, 95, 96, 96, 97, 98, 98, 99, 100, 100, 101, 101, 102, 102, 102, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, - 103, 103, 104, 104, 104, 104, 104, 105, 105, 106, + 103, 104, 104, 104, 104, 104, 104, 105, 105, 106, 106, 106, 107, 107, 107, 107, 108, 108, 108, 108, 109, 109, 109, 110, 110, 110, 110, 111, 111, 111, 111, 112, 112, 112, 112, 112, 112, 112, 112, 112, @@ -2805,8 +2805,8 @@ namespace yy { 1, 3, 3, 1, 3, 6, 6, 4, 0, 2, 2, 2, 4, 1, 3, 4, 2, 4, 4, 1, 1, 3, 4, 1, 0, 3, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 2, 6, - 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 6, 4, + 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 4, 4, 4, 4, 4, 4, @@ -2857,8 +2857,8 @@ namespace yy { 257, 258, 260, 263, 264, 267, 268, 269, 272, 273, 274, 275, 277, 280, 281, 283, 286, 287, 289, 292, 293, 295, 296, 299, 300, 301, 304, 305, 306, 307, - 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, - 323, 324, 327, 328, 329, 330, 331, 334, 335, 338, + 308, 309, 310, 311, 312, 313, 314, 315, 316, 322, + 323, 326, 327, 328, 329, 330, 331, 334, 335, 338, 339, 340, 343, 344, 345, 346, 349, 350, 351, 352, 355, 356, 357, 360, 361, 362, 363, 366, 367, 368, 369, 372, 373, 374, 375, 376, 377, 378, 379, 380, diff --git a/src/realm/parser/query_bison.yy b/src/realm/parser/query_bison.yy index 37b33331b5a..1ca81214829 100644 --- a/src/realm/parser/query_bison.yy +++ b/src/realm/parser/query_bison.yy @@ -312,7 +312,6 @@ constant | TRUE { $$ = drv.m_parse_nodes.create(ConstantNode::TRUE, ""); } | FALSE { $$ = drv.m_parse_nodes.create(ConstantNode::FALSE, ""); } | NULL_VAL { $$ = drv.m_parse_nodes.create(ConstantNode::NULL_VAL, ""); } - | ARG { $$ = drv.m_parse_nodes.create(ConstantNode::ARG, $1); } | comp_type ARG { $$ = drv.m_parse_nodes.create(ExpressionComparisonType($1), $2); } | OBJ '(' STRING ',' primary_key ')' { @@ -329,6 +328,7 @@ primary_key | STRING { $$ = drv.m_parse_nodes.create(ConstantNode::STRING, $1); } | UUID { $$ = drv.m_parse_nodes.create(ConstantNode::UUID_T, $1); } | OID { $$ = drv.m_parse_nodes.create(ConstantNode::OID, $1); } + | ARG { $$ = drv.m_parse_nodes.create(ConstantNode::ARG, $1); } boolexpr : "truepredicate" { $$ = drv.m_parse_nodes.create(true); } diff --git a/test/object-store/c_api/c_api.cpp b/test/object-store/c_api/c_api.cpp index f4810335892..935769aa507 100644 --- a/test/object-store/c_api/c_api.cpp +++ b/test/object-store/c_api/c_api.cpp @@ -4713,27 +4713,27 @@ TEST_CASE("C API - queries", "[c_api]") { SECTION("type mismatch") { CHECK(!realm_query_parse(realm, class_foo.key, "int == $2", num_args, arg_list)); - CHECK_ERR(RLM_ERR_INVALID_QUERY); + CHECK_ERR(RLM_ERR_INVALID_QUERY_ARG); CHECK(!realm_query_parse(realm, class_foo.key, "bool == $2", num_args, arg_list)); - CHECK_ERR(RLM_ERR_INVALID_QUERY); + CHECK_ERR(RLM_ERR_INVALID_QUERY_ARG); CHECK(!realm_query_parse(realm, class_foo.key, "string == $7", num_args, arg_list)); - CHECK_ERR(RLM_ERR_INVALID_QUERY); + CHECK_ERR(RLM_ERR_INVALID_QUERY_ARG); CHECK(!realm_query_parse(realm, class_foo.key, "timestamp == $2", num_args, arg_list)); - CHECK_ERR(RLM_ERR_INVALID_QUERY); + CHECK_ERR(RLM_ERR_INVALID_QUERY_ARG); CHECK(!realm_query_parse(realm, class_foo.key, "double == $2", num_args, arg_list)); - CHECK_ERR(RLM_ERR_INVALID_QUERY); + CHECK_ERR(RLM_ERR_INVALID_QUERY_ARG); CHECK(!realm_query_parse(realm, class_foo.key, "float == $2", num_args, arg_list)); - CHECK_ERR(RLM_ERR_INVALID_QUERY); + CHECK_ERR(RLM_ERR_INVALID_QUERY_ARG); CHECK(!realm_query_parse(realm, class_foo.key, "binary == $0", num_args, arg_list)); - CHECK_ERR(RLM_ERR_INVALID_QUERY); + CHECK_ERR(RLM_ERR_INVALID_QUERY_ARG); CHECK(!realm_query_parse(realm, class_foo.key, "decimal == $2", num_args, arg_list)); - CHECK_ERR(RLM_ERR_INVALID_QUERY); + CHECK_ERR(RLM_ERR_INVALID_QUERY_ARG); CHECK(!realm_query_parse(realm, class_foo.key, "object_id == $2", num_args, arg_list)); - CHECK_ERR(RLM_ERR_INVALID_QUERY); + CHECK_ERR(RLM_ERR_INVALID_QUERY_ARG); CHECK(!realm_query_parse(realm, class_foo.key, "uuid == $2", num_args, arg_list)); - CHECK_ERR(RLM_ERR_INVALID_QUERY); + CHECK_ERR(RLM_ERR_INVALID_QUERY_ARG); CHECK(!realm_query_parse(realm, class_foo.key, "link == $2", num_args, arg_list)); - CHECK_ERR(RLM_ERR_INVALID_QUERY); + CHECK_ERR(RLM_ERR_INVALID_QUERY_ARG); } } diff --git a/test/test_parser.cpp b/test/test_parser.cpp index 0b97c66d862..7eedca62d79 100644 --- a/test/test_parser.cpp +++ b/test/test_parser.cpp @@ -5114,8 +5114,13 @@ TEST(Parser_DictionaryObjects) q = persons->link(col_friend).link(col_dict).column(col_age) > 4; CHECK_EQUAL(q.count(), 1); + + std::any args[] = {StringData("pluto")}; + size_t num_args = 1; + verify_query(test_context, persons, "pets.@values.age > 4", 2); verify_query(test_context, persons, "pets.@values == obj('dog', 'pluto')", 2); + verify_query_sub(test_context, persons, "pets.@values == obj('dog', $0)", args, num_args, 2); verify_query(test_context, persons, "pets.@values != obj('dog', 'pluto')", 2); verify_query(test_context, persons, "pets.@values == ANY { obj('dog', 'lady'), obj('dog', 'astro') }", 2); verify_query(test_context, persons, "pets.@values == ANY { obj('dog', 'astro'), NULL }", 2);