diff --git a/include/field.h b/include/field.h index 1dae7278..4a1a5e59 100644 --- a/include/field.h +++ b/include/field.h @@ -119,7 +119,11 @@ struct field { } bool is_dynamic() const { - return type == "string*" || (name != ".*" && name.find(".*") != std::string::npos); + return is_dynamic(name, type); + } + + static bool is_dynamic(const std::string& name, const std::string& type) { + return type == "string*" || (name != ".*" && name.find(".*") != std::string::npos); } bool has_numerical_index() const { @@ -231,6 +235,10 @@ struct field { } if(field.is_dynamic() && !field.optional) { + if(field_types::is_string_or_array(field.type)) { + return Option(400, "Field `" + field.name + "` must be an optional field."); + } + return Option(400, "Field `" + field.name + "` with wildcard name must be an optional field."); } @@ -368,10 +376,9 @@ struct field { field_json[fields::locale] = ""; } - bool is_dynamic = field_json[fields::name].get().find(".*") != std::string::npos; - if(field_json.count(fields::optional) == 0) { // dynamic fields are always optional + bool is_dynamic = field::is_dynamic(field_json[fields::name], field_json[fields::type]); field_json[fields::optional] = is_dynamic; } diff --git a/test/collection_all_fields_test.cpp b/test/collection_all_fields_test.cpp index 5ddc842f..e84b5ed2 100644 --- a/test/collection_all_fields_test.cpp +++ b/test/collection_all_fields_test.cpp @@ -552,6 +552,21 @@ TEST_F(CollectionAllFieldsTest, JsonFieldsToFieldsConversion) { ASSERT_EQ(".*", fields[0].name); ASSERT_EQ("string*", fields[0].type); + // non-wildcard string* field should be treated as optional by default + fields_json = nlohmann::json::array(); + nlohmann::json string_star_field; + string_star_field[fields::name] = "title"; + string_star_field[fields::type] = "string*"; + fields_json.emplace_back(string_star_field); + fields.clear(); + + parse_op = field::json_fields_to_fields(fields_json, fallback_field_type, fields); + ASSERT_TRUE(parse_op.ok()); + ASSERT_EQ(true, fields[0].optional); + + fields_json = nlohmann::json::array(); + fields_json.emplace_back(all_field); + // reject when you try to set geo property on * field fields_json[0][fields::geo_resolution] = 10; parse_op = field::json_fields_to_fields(fields_json, fallback_field_type, fields); @@ -782,6 +797,14 @@ TEST_F(CollectionAllFieldsTest, DynamicFieldsMustOnlyBeOptional) { ASSERT_FALSE(op.ok()); ASSERT_EQ("Field `.*_name` with wildcard name must be an optional field.", op.error()); + // string* fields should only be optional + std::vector bad_fields2 = {field("title", field_types::STRING, true), + field("name", "string*", true, false),}; + + op = collectionManager.create_collection("coll1", 1, bad_fields2, "", 0); + ASSERT_FALSE(op.ok()); + ASSERT_EQ("Field `name` must be an optional field.", op.error()); + std::vector fields = {field("title", field_types::STRING, true), field(".*_name", field_types::STRING, true, true),};