Skip to content

Commit d88b3f3

Browse files
committed
1 parent f79f615 commit d88b3f3

File tree

3 files changed

+132
-74
lines changed

3 files changed

+132
-74
lines changed

deps/rabbit/src/rabbit_amqp_filter_sql.erl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,9 +355,9 @@ transform_ast(Ast0, SQL) ->
355355
end, Ast0) of
356356
Ast ->
357357
{ok, Ast}
358-
catch {unsupported_field, Name} ->
358+
catch {unsupported_field_name, Name} ->
359359
rabbit_log:warning(
360-
"identifier ~ts in SQL expression ~tp is unsupported",
360+
"field name ~ts in SQL expression ~tp is unsupported",
361361
[Name, SQL]),
362362
error;
363363
{invalid_pattern, Reason} ->

deps/rabbit/src/rabbit_amqp_util.erl

Lines changed: 53 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,26 +20,60 @@
2020
-type field_name() :: header_field_name() | properties_field_name().
2121
-export_type([field_name/0]).
2222

23+
%% [Filter-Expressions-v1.0] § 6.4.4.4
24+
%% https://docs.oasis-open.org/amqp/filtex/v1.0/csd01/filtex-v1.0-csd01.html#_Toc67929312
2325
-spec section_field_name_to_atom(binary()) -> field_name() | binary().
24-
section_field_name_to_atom(<<"header.priority">>) -> priority;
25-
%% ttl, first-acquirer, and delivery-count are unsupported
26-
%% because setting a JMS message selector on these fields is invalid.
27-
section_field_name_to_atom(<<"header.", _/binary>> = Bin) -> throw({unsupported_field, Bin});
28-
section_field_name_to_atom(<<"properties.message-id">>) -> message_id;
29-
section_field_name_to_atom(<<"properties.user-id">>) -> user_id;
30-
section_field_name_to_atom(<<"properties.to">>) -> to;
31-
section_field_name_to_atom(<<"properties.subject">>) -> subject;
32-
section_field_name_to_atom(<<"properties.reply-to">>) -> reply_to;
33-
section_field_name_to_atom(<<"properties.correlation-id">>) -> correlation_id;
34-
section_field_name_to_atom(<<"properties.content-type">>) -> content_type;
35-
section_field_name_to_atom(<<"properties.content-encoding">>) -> content_encoding;
36-
section_field_name_to_atom(<<"properties.absolute-expiry-time">>) -> absolute_expiry_time;
37-
section_field_name_to_atom(<<"properties.creation-time">>) -> creation_time;
38-
section_field_name_to_atom(<<"properties.group-id">>) -> group_id;
39-
section_field_name_to_atom(<<"properties.group-sequence">>) -> group_sequence;
40-
section_field_name_to_atom(<<"properties.reply-to-group-id">>) -> reply_to_group_id;
41-
section_field_name_to_atom(<<"properties.", _/binary>> = Bin) -> throw({unsupported_field, Bin});
42-
section_field_name_to_atom(Other) -> Other.
26+
section_field_name_to_atom(<<"header.", FieldName/binary>>) ->
27+
header_field_name_to_atom(FieldName);
28+
section_field_name_to_atom(<<"h.", FieldName/binary>>) ->
29+
header_field_name_to_atom(FieldName);
30+
section_field_name_to_atom(<<"delivery-annotations.", FieldName/binary>>) ->
31+
unsupported_field_name(FieldName);
32+
section_field_name_to_atom(<<"d.", FieldName/binary>>) ->
33+
unsupported_field_name(FieldName);
34+
section_field_name_to_atom(<<"message-annotations.", FieldName/binary>>) ->
35+
unsupported_field_name(FieldName);
36+
section_field_name_to_atom(<<"m.", FieldName/binary>>) ->
37+
unsupported_field_name(FieldName);
38+
section_field_name_to_atom(<<"properties.", FieldName/binary>>) ->
39+
properties_field_name_to_atom(FieldName);
40+
section_field_name_to_atom(<<"p.", FieldName/binary>>) ->
41+
properties_field_name_to_atom(FieldName);
42+
section_field_name_to_atom(<<"application-properties.", FieldName/binary>>) ->
43+
FieldName;
44+
section_field_name_to_atom(<<"a.", FieldName/binary>>) ->
45+
FieldName;
46+
section_field_name_to_atom(<<"footer.", FieldName/binary>>) ->
47+
unsupported_field_name(FieldName);
48+
section_field_name_to_atom(<<"f.", FieldName/binary>>) ->
49+
unsupported_field_name(FieldName);
50+
section_field_name_to_atom(ApplicationPropertiesFieldName) ->
51+
%% "When the section is omitted, the assumed section is ‘application-properties’."
52+
ApplicationPropertiesFieldName.
53+
54+
header_field_name_to_atom(<<"priority">>) ->
55+
priority;
56+
header_field_name_to_atom(Other) ->
57+
unsupported_field_name(Other).
58+
59+
properties_field_name_to_atom(<<"message-id">>) -> message_id;
60+
properties_field_name_to_atom(<<"user-id">>) -> user_id;
61+
properties_field_name_to_atom(<<"to">>) -> to;
62+
properties_field_name_to_atom(<<"subject">>) -> subject;
63+
properties_field_name_to_atom(<<"reply-to">>) -> reply_to;
64+
properties_field_name_to_atom(<<"correlation-id">>) -> correlation_id;
65+
properties_field_name_to_atom(<<"content-type">>) -> content_type;
66+
properties_field_name_to_atom(<<"content-encoding">>) -> content_encoding;
67+
properties_field_name_to_atom(<<"absolute-expiry-time">>) -> absolute_expiry_time;
68+
properties_field_name_to_atom(<<"creation-time">>) -> creation_time;
69+
properties_field_name_to_atom(<<"group-id">>) -> group_id;
70+
properties_field_name_to_atom(<<"group-sequence">>) -> group_sequence;
71+
properties_field_name_to_atom(<<"reply-to-group-id">>) -> reply_to_group_id;
72+
properties_field_name_to_atom(Other) -> unsupported_field_name(Other).
73+
74+
-spec unsupported_field_name(binary()) -> no_return().
75+
unsupported_field_name(Name) ->
76+
throw({unsupported_field_name, Name}).
4377

4478
-spec capabilities([binary()]) ->
4579
undefined | {array, symbol, [{symbol, binary()}]}.

deps/rabbit/test/amqp_filter_sql_unit_SUITE.erl

Lines changed: 77 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ groups() ->
4343
header_section,
4444
properties_section,
4545
multiple_sections,
46+
section_qualifier,
4647
parse_errors
4748
]
4849
}].
@@ -693,13 +694,13 @@ header_section(_Config) ->
693694
Hdr = #'v1_0.header'{priority = {ubyte, 7}},
694695
Ps = #'v1_0.properties'{},
695696
APs = [],
696-
true = match("header.priority > 5", Hdr, Ps, APs),
697-
true = match("header.priority = 7", Hdr, Ps, APs),
698-
false = match("header.priority < 7", Hdr, Ps, APs),
697+
true = match("h.priority > 5", Hdr, Ps, APs),
698+
true = match("h.priority = 7", Hdr, Ps, APs),
699+
false = match("h.priority < 7", Hdr, Ps, APs),
699700

700701
%% Since the default priority is 4, we expect the following expression to evaluate
701702
%% to true if matched against a message without an explicit priority level set.
702-
true = match("header.priority = 4", []).
703+
true = match("h.priority = 4", []).
703704

704705
properties_section(_Config) ->
705706
Ps = #'v1_0.properties'{
@@ -718,69 +719,69 @@ properties_section(_Config) ->
718719
reply_to_group_id = {utf8, <<"other group ID">>}},
719720
APs = [],
720721

721-
true = match("properties.message-id = 'id-123'", Ps, APs),
722-
false = match("'id-123' <> properties.message-id", Ps, APs),
723-
true = match("properties.message-id LIKE 'id-%'", Ps, APs),
724-
true = match("properties.message-id IN ('id-123', 'id-456')", Ps, APs),
722+
true = match("p.message-id = 'id-123'", Ps, APs),
723+
false = match("'id-123' <> p.message-id", Ps, APs),
724+
true = match("p.message-id LIKE 'id-%'", Ps, APs),
725+
true = match("p.message-id IN ('id-123', 'id-456')", Ps, APs),
725726

726-
true = match("properties.user-id = 'some user ID'", Ps, APs),
727-
true = match("properties.user-id LIKE '%user%'", Ps, APs),
728-
false = match("properties.user-id = 'other user ID'", Ps, APs),
727+
true = match("p.user-id = 'some user ID'", Ps, APs),
728+
true = match("p.user-id LIKE '%user%'", Ps, APs),
729+
false = match("p.user-id = 'other user ID'", Ps, APs),
729730

730-
true = match("properties.to = 'to some queue'", Ps, APs),
731-
true = match("properties.to LIKE 'to some%'", Ps, APs),
732-
true = match("properties.to NOT LIKE '%topic'", Ps, APs),
731+
true = match("p.to = 'to some queue'", Ps, APs),
732+
true = match("p.to LIKE 'to some%'", Ps, APs),
733+
true = match("p.to NOT LIKE '%topic'", Ps, APs),
733734

734-
true = match("properties.subject = 'some subject'", Ps, APs),
735-
true = match("properties.subject LIKE '%subject'", Ps, APs),
736-
true = match("properties.subject IN ('some subject', 'other subject')", Ps, APs),
735+
true = match("p.subject = 'some subject'", Ps, APs),
736+
true = match("p.subject LIKE '%subject'", Ps, APs),
737+
true = match("p.subject IN ('some subject', 'other subject')", Ps, APs),
737738

738-
true = match("properties.reply-to = 'reply to some topic'", Ps, APs),
739-
true = match("properties.reply-to LIKE 'reply%topic'", Ps, APs),
740-
false = match("properties.reply-to LIKE 'reply%queue'", Ps, APs),
739+
true = match("p.reply-to = 'reply to some topic'", Ps, APs),
740+
true = match("p.reply-to LIKE 'reply%topic'", Ps, APs),
741+
false = match("p.reply-to LIKE 'reply%queue'", Ps, APs),
741742

742-
true = match("properties.correlation-id = 789", Ps, APs),
743-
true = match("500 < properties.correlation-id", Ps, APs),
744-
true = match("properties.correlation-id BETWEEN 700 AND 800", Ps, APs),
745-
false = match("properties.correlation-id < 700", Ps, APs),
743+
true = match("p.correlation-id = 789", Ps, APs),
744+
true = match("500 < p.correlation-id", Ps, APs),
745+
true = match("p.correlation-id BETWEEN 700 AND 800", Ps, APs),
746+
false = match("p.correlation-id < 700", Ps, APs),
746747

747-
true = match("properties.content-type = 'text/plain'", Ps, APs),
748-
true = match("properties.content-type LIKE 'text/%'", Ps, APs),
749-
true = match("properties.content-type IN ('text/plain', 'text/html')", Ps, APs),
748+
true = match("p.content-type = 'text/plain'", Ps, APs),
749+
true = match("p.content-type LIKE 'text/%'", Ps, APs),
750+
true = match("p.content-type IN ('text/plain', 'text/html')", Ps, APs),
750751

751-
true = match("'deflate' = properties.content-encoding", Ps, APs),
752-
false = match("properties.content-encoding = 'gzip'", Ps, APs),
753-
true = match("properties.content-encoding NOT IN ('gzip', 'compress')", Ps, APs),
752+
true = match("'deflate' = p.content-encoding", Ps, APs),
753+
false = match("p.content-encoding = 'gzip'", Ps, APs),
754+
true = match("p.content-encoding NOT IN ('gzip', 'compress')", Ps, APs),
754755

755-
true = match("properties.absolute-expiry-time = 1311999988888", Ps, APs),
756-
true = match("properties.absolute-expiry-time > 1311999988000", Ps, APs),
757-
true = match("properties.absolute-expiry-time BETWEEN 1311999988000 AND 1311999989000", Ps, APs),
756+
true = match("p.absolute-expiry-time = 1311999988888", Ps, APs),
757+
true = match("p.absolute-expiry-time > 1311999988000", Ps, APs),
758+
true = match("p.absolute-expiry-time BETWEEN 1311999988000 AND 1311999989000", Ps, APs),
758759

759-
true = match("properties.creation-time = 1311704463521", Ps, APs),
760-
true = match("properties.creation-time < 1311999988888", Ps, APs),
761-
true = match("properties.creation-time NOT BETWEEN 1311999988000 AND 1311999989000", Ps, APs),
760+
true = match("p.creation-time = 1311704463521", Ps, APs),
761+
true = match("p.creation-time < 1311999988888", Ps, APs),
762+
true = match("p.creation-time NOT BETWEEN 1311999988000 AND 1311999989000", Ps, APs),
762763

763-
true = match("properties.group-id = 'some group ID'", Ps, APs),
764-
true = match("properties.group-id LIKE 'some%ID'", Ps, APs),
765-
false = match("properties.group-id = 'other group ID'", Ps, APs),
764+
true = match("p.group-id = 'some group ID'", Ps, APs),
765+
true = match("p.group-id LIKE 'some%ID'", Ps, APs),
766+
false = match("p.group-id = 'other group ID'", Ps, APs),
766767

767-
true = match("properties.group-sequence = 999", Ps, APs),
768-
true = match("properties.group-sequence >= 999", Ps, APs),
769-
true = match("properties.group-sequence BETWEEN 900 AND 1000", Ps, APs),
770-
false = match("properties.group-sequence > 999", Ps, APs),
768+
true = match("p.group-sequence = 999", Ps, APs),
769+
true = match("p.group-sequence >= 999", Ps, APs),
770+
true = match("p.group-sequence BETWEEN 900 AND 1000", Ps, APs),
771+
false = match("p.group-sequence > 999", Ps, APs),
771772

772-
true = match("properties.reply-to-group-id = 'other group ID'", Ps, APs),
773-
true = match("properties.reply-to-group-id LIKE '%group ID'", Ps, APs),
774-
true = match("properties.reply-to-group-id <> 'some group ID'", Ps, APs),
775-
true = match("properties.reply-to-group-id IS NOT NULL", Ps, APs),
776-
false = match("properties.reply-to-group-id IS NULL", Ps, APs),
773+
true = match("p.reply-to-group-id = 'other group ID'", Ps, APs),
774+
true = match("p.reply-to-group-id LIKE '%group ID'", Ps, APs),
775+
true = match("p.reply-to-group-id <> 'some group ID'", Ps, APs),
776+
true = match("p.reply-to-group-id IS NOT NULL", Ps, APs),
777+
false = match("p.reply-to-group-id IS NULL", Ps, APs),
777778

778-
true = match("properties.message-id = 'id-123' and 'some subject' = properties.subject", Ps, APs),
779-
true = match("properties.group-sequence < 500 or properties.correlation-id > 700", Ps, APs),
780-
true = match("(properties.content-type LIKE 'text/%') AND properties.content-encoding = 'deflate'", Ps, APs),
779+
true = match("p.message-id = 'id-123' and 'some subject' = p.subject", Ps, APs),
780+
true = match("p.group-sequence < 500 or p.correlation-id > 700", Ps, APs),
781+
true = match("(p.content-type LIKE 'text/%') AND p.content-encoding = 'deflate'", Ps, APs),
781782

782-
true = match("properties.subject IS NULL", #'v1_0.properties'{}, APs),
783-
false = match("properties.subject IS NOT NULL", #'v1_0.properties'{}, APs).
783+
true = match("p.subject IS NULL", #'v1_0.properties'{}, APs),
784+
false = match("p.subject IS NOT NULL", #'v1_0.properties'{}, APs).
784785

785786
multiple_sections(_Config) ->
786787
Hdr = #'v1_0.header'{durable = true,
@@ -804,6 +805,29 @@ multiple_sections(_Config) ->
804805
true = match("-1.0 = key_1 AND 4 < header.priority AND properties.group-sequence > 90", Hdr, Ps, APs),
805806
false = match("-1.0 = key_1 AND 4 < header.priority AND properties.group-sequence < 90", Hdr, Ps, APs).
806807

808+
section_qualifier(_Config) ->
809+
Hdr = #'v1_0.header'{priority = {ubyte, 7}},
810+
Ps = #'v1_0.properties'{message_id = {utf8, <<"id-123">>}},
811+
APs = [{{utf8, <<"key_1">>}, {byte, -1}}],
812+
813+
%% supported section qualifiers
814+
true = match("header.priority = 7", Hdr, Ps, APs),
815+
true = match("h.priority = 7", Hdr, Ps, APs),
816+
true = match("properties.message-id = 'id-123'", Hdr, Ps, APs),
817+
true = match("p.message-id = 'id-123'", Hdr, Ps, APs),
818+
true = match("application-properties.key_1 = -1", Hdr, Ps, APs),
819+
true = match("a.key_1 = -1", Hdr, Ps, APs),
820+
true = match("key_1 = -1", Hdr, Ps, APs),
821+
822+
%% (currently) unsupported section qualifiers
823+
?assertEqual(error, parse("delivery-annotations.abc")),
824+
?assertEqual(error, parse("d.abc")),
825+
?assertEqual(error, parse("message-annotations.abc")),
826+
?assertEqual(error, parse("m.abc")),
827+
?assertEqual(error, parse("footer.abc")),
828+
?assertEqual(error, parse("f.abc")),
829+
ok.
830+
807831
parse_errors(_Config) ->
808832
%% Parsing a non-UTF-8 encoded message selector should fail.
809833
?assertEqual(error, parse([255])),

0 commit comments

Comments
 (0)