Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -48,32 +48,61 @@ struct identifier_processor
return process_bound(bound_seq[0]);
}

static xtypes::TypeIdentifier resolve_type(
const xtypes::TypeIdentifier& ti,
const position& pos)
{
if (xtypes::EK_COMPLETE != ti._d())
{
return ti;
}

std::shared_ptr<xtypes::TypeObject> type_object = std::make_shared<xtypes::TypeObject>();
if (RETCODE_OK == DomainParticipantFactory::get_instance()->type_object_registry().get_type_object(
ti, *type_object) && xtypes::EK_COMPLETE == type_object->_d())
{
if (xtypes::TK_ALIAS == type_object->complete()._d())
{
const xtypes::TypeIdentifier& aliased_id =
type_object->complete().alias_type().body().common().related_type();
return resolve_type(aliased_id, pos);
}
return ti;
}
throw parse_error("could not find type object definition", pos);
}

static bool type_should_be_indexed(
const xtypes::TypeIdentifier& ti,
std::shared_ptr<xtypes::TypeIdentifier>& out_type,
size_t& max_size)
size_t& max_size,
const position& pos)
{
max_size = 0;

switch (ti._d())
{
case xtypes::TI_PLAIN_ARRAY_SMALL:
out_type = std::make_shared<xtypes::TypeIdentifier>(*ti.array_sdefn().element_identifier());
out_type = std::make_shared<xtypes::TypeIdentifier>(
resolve_type(*ti.array_sdefn().element_identifier(), pos));
max_size = process_bounds(ti.array_sdefn().array_bound_seq());
return true;

case xtypes::TI_PLAIN_ARRAY_LARGE:
out_type = std::make_shared<xtypes::TypeIdentifier>(*ti.array_ldefn().element_identifier());
out_type = std::make_shared<xtypes::TypeIdentifier>(
resolve_type(*ti.array_ldefn().element_identifier(), pos));
max_size = process_bounds(ti.array_ldefn().array_bound_seq());
return true;

case xtypes::TI_PLAIN_SEQUENCE_SMALL:
out_type = std::make_shared<xtypes::TypeIdentifier>(*ti.seq_sdefn().element_identifier());
out_type = std::make_shared<xtypes::TypeIdentifier>(
resolve_type(*ti.seq_sdefn().element_identifier(), pos));
max_size = process_bound(ti.seq_sdefn().bound());
return true;

case xtypes::TI_PLAIN_SEQUENCE_LARGE:
out_type = std::make_shared<xtypes::TypeIdentifier>(*ti.seq_ldefn().element_identifier());
out_type = std::make_shared<xtypes::TypeIdentifier>(
resolve_type(*ti.seq_ldefn().element_identifier(), pos));
max_size = process_bound(ti.seq_ldefn().bound());
return true;

Expand Down Expand Up @@ -111,11 +140,12 @@ struct identifier_processor
throw parse_error("field not found", name_node.begin());
}

const xtypes::TypeIdentifier& ti = members[member_index].common().member_type_id();
const xtypes::TypeIdentifier& ti =
resolve_type(members[member_index].common().member_type_id(), name_node.begin());
bool has_index = n->children.size() > 1;
size_t max_size = 0;
size_t array_index = std::numeric_limits<size_t>::max();
if (type_should_be_indexed(ti, identifier_state.current_type, max_size))
if (type_should_be_indexed(ti, identifier_state.current_type, max_size, name_node.begin()))
{
if (!has_index)
{
Expand Down Expand Up @@ -184,16 +214,11 @@ struct identifier_processor
if (RETCODE_OK == DomainParticipantFactory::get_instance()->type_object_registry().get_type_object(
ti, *type_object) && xtypes::EK_COMPLETE == type_object->_d())
{
assert(xtypes::TK_ALIAS != type_object->complete()._d()); // should be resolved already at this point
if (xtypes::TK_ENUM == type_object->complete()._d())
{
return DDSFilterValue::ValueKind::ENUM;
}
if (xtypes::TK_ALIAS == type_object->complete()._d())
{
const xtypes::TypeIdentifier& aliasedId =
type_object->complete().alias_type().body().common().related_type();
return get_value_kind(aliasedId, pos);
}
}
}
break;
Expand All @@ -210,6 +235,11 @@ struct identifier_processor
{
if (n->is<fieldname>())
{
if (!state.current_type)
{
throw parse_error("undefined type identifier", n->begin());
}

// Set data for fieldname node
n->field_kind = get_value_kind(*state.current_type, n->end());
n->field_access_path = state.access_path;
Expand All @@ -223,6 +253,10 @@ struct identifier_processor
{
if (!state.current_type)
{
if (!state.type_object)
{
throw parse_error("undefined type object", n->begin());
}
add_member_access(n, state, state.type_object->complete());
}
else
Expand Down
3 changes: 2 additions & 1 deletion src/cpp/fastdds/topic/DDSSQLFilter/DDSFilterField.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,11 +212,12 @@ bool DDSFilterField::set_value_using_member_id(

case eprosima::fastdds::dds::xtypes::EK_COMPLETE:
{
// WARNING: this assumes EK_COMPLETE is always an enumeration, aliases should be resolved when parsing
int32_t valueenum {0};
ret = RETCODE_OK == data->get_int32_value(valueenum, member_id);
signed_integer_value = valueenum;
break;
}
break;

default:
break;
Expand Down
151 changes: 136 additions & 15 deletions test/unittest/dds/topic/DDSSQLFilter/DDSSQLFilterTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,22 @@ namespace dds {
// Name of all the primitive fields used along the tests
static const std::vector<std::pair<std::string, std::string>> primitive_fields
{
{"char_field", "CHAR"},
{"uint8_field", "INT"},
{"int16_field", "INT"},
{"uint16_field", "INT"},
{"int32_field", "INT"},
{"uint32_field", "INT"},
{"int64_field", "INT"},
{"uint64_field", "INT"},
{"float_field", "FLOAT"},
{"double_field", "FLOAT"},
{"long_double_field", "FLOAT"},
{"bool_field", "BOOL"},
{"string_field", "STRING"},
{"enum_field", "ENUM"},
{"enum2_field", "ENUM2"}
{"char_field", "CHAR"},
{"uint8_field", "INT"},
{"int16_field", "INT"},
{"uint16_field", "INT"},
{"int32_field", "INT"},
{"uint32_field", "INT"},
{"int64_field", "INT"},
{"uint64_field", "INT"},
{"float_field", "FLOAT"},
{"double_field", "FLOAT"},
{"long_double_field", "FLOAT"},
{"bool_field", "BOOL"},
{"string_field", "STRING"},
{"alias_string_field", "STRING"},
{"enum_field", "ENUM"},
{"enum2_field", "ENUM2"}
};

static const std::map<std::string, std::set<std::string>> type_compatibility_matrix
Expand Down Expand Up @@ -961,13 +962,21 @@ class DDSSQLFilterValueGlobalData
for (size_t i = 0; i < values.size(); ++i)
{
data[i].string_field(values[i]);
data[i].alias_string_field(values[i]);
data[i].struct_field().string_field(values[i]);
data[i].struct_field().alias_string_field(values[i]);
data[i].array_struct_field()[0].string_field(values[i]);
data[i].array_struct_field()[0].alias_string_field(values[i]);
data[i].bounded_sequence_struct_field()[0].string_field(values[i]);
data[i].bounded_sequence_struct_field()[0].alias_string_field(values[i]);
data[i].unbounded_sequence_struct_field()[0].string_field(values[i]);
data[i].unbounded_sequence_struct_field()[0].alias_string_field(values[i]);
data[i].array_string_field()[0] = values[i];
data[i].array_alias_string_field()[0] = values[i];
data[i].bounded_sequence_string_field().push_back(values[i]);
data[i].bounded_sequence_alias_string_field().push_back(values[i]);
data[i].unbounded_sequence_string_field().push_back(values[i]);
data[i].unbounded_sequence_alias_string_field().push_back(values[i]);
}
}

Expand Down Expand Up @@ -1504,6 +1513,112 @@ static std::vector<DDSSQLFilterValueParams> get_test_filtered_value_string_input
return inputs;
}

static std::vector<DDSSQLFilterValueParams> get_test_filtered_value_alias_string_inputs()
{
static const std::array<std::pair<std::string, std::string>, 5> values =
{
std::pair<std::string, std::string>{"''", "minus_2"},
std::pair<std::string, std::string>{"' '", "minus_1"},
std::pair<std::string, std::string>{"' AA'", "0"},
std::pair<std::string, std::string>{"' AZ'", "plus_1"},
std::pair<std::string, std::string>{"'ZZZ'", "plus_2"}
};

// Adding standard tests
std::vector<DDSSQLFilterValueParams> inputs;
inputs = get_test_filtered_value_inputs_given_values_and_results("alias_string_field", values);

// Adding tests for LIKE operator
DDSSQLFilterValueParams input;
input.test_case_name = "like_any_percent";
input.expression = "alias_string_field LIKE '%'";
input.samples_filtered.assign(5, true);
inputs.push_back(input);

input.test_case_name = "like_any_star";
input.expression = "alias_string_field LIKE '*'";
input.samples_filtered.assign(5, true);
inputs.push_back(input);

input.test_case_name = "like_space_percent";
input.expression = "alias_string_field LIKE ' %'";
input.samples_filtered.assign({ false, true, true, true, false });
inputs.push_back(input);

input.test_case_name = "like_space_star";
input.expression = "alias_string_field LIKE ' *'";
input.samples_filtered.assign({ false, true, true, true, false });
inputs.push_back(input);

input.test_case_name = "like_A_question";
input.expression = "alias_string_field LIKE '?A?'";
input.samples_filtered.assign({ false, false, true, true, false });
inputs.push_back(input);

input.test_case_name = "like_A_underscore";
input.expression = "alias_string_field LIKE '_A_'";
input.samples_filtered.assign({ false, false, true, true, false });
inputs.push_back(input);

input.test_case_name = "like_exact_empty";
input.expression = "alias_string_field LIKE ''";
input.samples_filtered.assign({ true, false, false, false, false });
inputs.push_back(input);

input.test_case_name = "like_exact_ZZZ";
input.expression = "alias_string_field LIKE 'ZZZ'";
input.samples_filtered.assign({ false, false, false, false, true });
inputs.push_back(input);

input.test_case_name = "like_exact_none";
input.expression = "alias_string_field LIKE 'BBB'";
input.samples_filtered.assign({ false, false, false, false, false });
inputs.push_back(input);

// Adding tests for MATCH operator
input.test_case_name = "match_any";
input.expression = "alias_string_field match '.*'";
input.samples_filtered.assign(5, true);
inputs.push_back(input);

input.test_case_name = "match_space";
input.expression = "alias_string_field match ' .*'";
input.samples_filtered.assign({ false, true, true, true, false });
inputs.push_back(input);

input.test_case_name = "match_A";
input.expression = "alias_string_field match '.A.'";
input.samples_filtered.assign({ false, false, true, true, false });
inputs.push_back(input);

input.test_case_name = "match_exact_empty";
input.expression = "alias_string_field match ''";
input.samples_filtered.assign({ true, false, false, false, false });
inputs.push_back(input);

input.test_case_name = "match_exact_ZZZ";
input.expression = "alias_string_field match 'ZZZ'";
input.samples_filtered.assign({ false, false, false, false, true });
inputs.push_back(input);

input.test_case_name = "match_exact_none";
input.expression = "alias_string_field match 'BBB'";
input.samples_filtered.assign({ false, false, false, false, false });
inputs.push_back(input);

input.test_case_name = "match_range";
input.expression = "alias_string_field match '([A-Z])+'";
input.samples_filtered.assign({ false, false, false, false, true });
inputs.push_back(input);

input.test_case_name = "match_space_and_range";
input.expression = "alias_string_field match ' ([A-Z])+'";
input.samples_filtered.assign({ false, false, true, true, false });
inputs.push_back(input);

return inputs;
}

static std::vector<DDSSQLFilterValueParams> get_test_filtered_value_boolean_inputs()
{
static const std::array<std::pair<std::string, std::string>, 5> values =
Expand Down Expand Up @@ -2062,6 +2177,12 @@ INSTANTIATE_TEST_SUITE_P(
::testing::ValuesIn(get_test_filtered_value_string_inputs()),
DDSSQLFilterValueTests::PrintToStringParamName());

INSTANTIATE_TEST_SUITE_P(
DDSSQLFilterValueTestsAliasString,
DDSSQLFilterValueTests,
::testing::ValuesIn(get_test_filtered_value_alias_string_inputs()),
DDSSQLFilterValueTests::PrintToStringParamName());

INSTANTIATE_TEST_SUITE_P(
DDSSQLFilterValueTestsBool,
DDSSQLFilterValueTests,
Expand Down
Loading
Loading